Show HN: Scratch.js – Interactive JavaScript Scratchpad
hole.dev
hole.dev
If the result is an Element (or perhaps Node) insert it into the document instead of for example "[object HTMLCanvasElement]"
A potentially more difficult one would be automagically hoisting functions defined in the document when you hit ctrl-enter.
function factorial(n) { ...the usual... }factorial(7);// [ctrl-enter] on just this line works
What would an MVP operating system like ctrl-C functionality look like for execution environments in the browser?
Browsers will complain against code running for too long without interruption though.
Wow, that seems hard to do. One would need to take a lot of things in account, including recursive calls, asynchronous functions / calls and, indeed, even long strings of instructions that are not necessarily part of a loop or recursive calls.
Would a transform that adds the check between every JS instructions where it is possible theoretically solve the problem? is there a solution that does not slow down the code too much and interrupts the code within an acceptable margin?
If you type while(true){} in a notebook only the iframe will break (and usually your browser will prompt you after a while to kill it). When you do only the iframe is no longer functional.
I don't think there's an elegant way to solve it any differently in the browser.
[0]: https://starboard.gg
What I'm getting at is that these browser notebooks try to get at the desire and feeling for rapid exploration and iteration. Losing context by having a crashing logic error is a massive blow to that ideal.
I'm not saying that your or anyone elses product is only for "rapid prototyping" but it's still true that larger projects could be bit by the same errors. When I crash my native code I C-c and I'm back in an instant. When I crash browser notebook code I lose a bit of time and unsaved code. I crash browsers often in creative coding where I write many loops and don't always do them right.
It may also be that my chrome and firefox experience on linus is worse than standard, I don't know. But I have crashed my entire browser in chrome when using observable, and I thought that wasn't supposed to be possible.
I work on an experimental Pyret [1] runtime that uses Stopify to instrument compiled Pyret code (plain old JS) so that we can run Pyret code on the main page thread without hanging it up. Main thread execution is important for quick/easy DOM access. In terms of performance cost, we haven't measured too extensively, but so far, on average, we're seeing a 2x slow down compared to un-Stopified programs.
(Disclaimer: paid contributor for Pyret).
Pyret used to use its own runtime system [0] but Stopify was created in part to replace it due to the maintenance burden and complexity of "vanilla" JS interoperability.
2 theoretical solutions ( with significant overhead ) are:
Run the code in a VM ( maybe quick.js compiled to WASM would work ) that suspends code execution periodically if it exceeds a certain duration. This has the advantage that long running code in general won't block rendering, not just loops.
Transform the AST to use async generator that yields once per loop. This would allow the loop to be suspended and resumed. But it would require a lot of modification to the AST, making effectively the entire call tree async.
Put a bit more simply, to work out if a problem is unsolvable (infinitly looping) you need to evaluate the problem... By trying to solve it. Checkout the halting problem for more details.
Well that can be achieved by executing the code in a background worker thread. Which doesn't affect the UI thread in browsers... no sure how it's managed but I think you could terminate it after a certain amount of time too
OS implementations dont solve the halting problem. I agree with the sibling comment.
Small issue: I find that the cursor can be hard to use sometimes. For example, if I clear and then execute the single line
"<style>body {background-color: #fdf6e3;}</style>"
I can no longer get an empty line at the bottom of the document. My cursor can only ever be within the outputted "<style>" tags, and hitting return from there creates a new pair of "<style>" tags.To temper this bug-report with a cool feature, I like that the output is (usually, with the exception of the above) plain text, which can itself be executed. I haven't found a use-case for this, but I'm sure there's some interesting meta-programming that could be done.
I considered supporting only plain-text, but I found the editable visible style tag very interesting. And I like the fact all the power of the browser is available, e.g canvas, 3d rendering, and simple stuff like headers and images. Of course, you can use only plaintext if you'd like.
`document.addEventListener('keydown', (e) => (e.metaKey && e.code === 'Enter' && evaluate() && e.preventDefault()));`
The metaKey[1] is only accessible for keydown.
[1] https://stackoverflow.com/questions/3902635/how-does-one-cap...
(()=>document.body.innerText.split('\n')[0])()1) What is your monetization strategy?
2) Will this be supported forever?
...
... /s
:) Nice project, useful.
EDIT: this was obviously satirical...
I'm also former Emacs user, and I like the lisp scratch buffer there, which is similar.
I'm also building a web-based literate programming environment called Starboard[1] that's probably a hundred times the amount of code (but then it has additional features such as top-level await, plugin, and Python support).
Consider supporting lit-html[2] literals instead of strings for HTML output, it works really well in notebook environments.
One more thing you can consider: a esm tagged literal that uses import(<data url of the code>), you can then use ES Module imports to dynamically load code. Here's a blog post about that approach [3]
[1]: https://starboard.gg [2]: https://lit-html.polymer-project.org/ [3]: https://2ality.com/2019/10/eval-via-import.html
My issue with these notebooks is they always get very cluttered with inline outputs after a couple 100 lines.
https://chrome.google.com/webstore/detail/markdown-new-tab/d...
Would be neat to see this integrated in somehow.
Felt a bit odd that "running" a line didn't drop the cursor down past the output, ready for the next line; but the current seems useful for editing and re-trying a line, also interesting!
data:text/html,<html contenteditable>