[HN Gopher] Show HN: Jaws - a JavaScript to WASM ahead-of-time c...
       ___________________________________________________________________
        
       Show HN: Jaws - a JavaScript to WASM ahead-of-time compiler
        
       I've open sourced a JavaScript to WASM compiler. It's an
       experimental tool, but given the semantics I already implemented,
       I'm fairly certain I am able to eventually cover 100% of JavaScript
       spec. Any ideas, questions or critique welcomed! If you are
       interested in WASM, especially with new proposals like WASM GC or
       exception handling, it might be a good source of seeing these
       features in action - the project has a few thousand lines of hand
       written WAT so far.
        
       Author : drogus
       Score  : 120 points
       Date   : 2024-11-09 18:14 UTC (4 hours ago)
        
 (HTM) web link (github.com)
 (TXT) w3m dump (github.com)
        
       | samuelstros wrote:
       | nice, "run JS without (browser) runtime" is coming. perforr,
       | jaws, or another project will eventually succeed.
        
         | jahewson wrote:
         | bun?
        
           | thrw42A8N wrote:
           | Bun is a runtime.. If you're referring to the fact it can
           | produce a single binary, Node.js can do that too.
        
             | drogus wrote:
             | Yeah, bun will still include V8 in the generated binary
        
               | thrw42A8N wrote:
               | Bun will include the Bun runtime with JavaScriptCore,
               | Node.js will include the Node.js runtime with V8.
        
               | drogus wrote:
               | Oh, thanks for the clarification, I somehow thought Bun
               | is also V8!
        
               | thrw42A8N wrote:
               | That would be Deno. It can also produce a single binary
               | using the same principle.
        
               | IggleSniggle wrote:
               | Bun uses JavaScriptCore as its runtime, not V8
        
         | codesnik wrote:
         | also https://docs.docker.com/desktop/features/wasm/
        
         | philipwhiuk wrote:
         | You mean like Node?
        
       | asabla wrote:
       | Title might need to include "Show HN".
       | 
       | Very cool and interesting project! How are build times? And how
       | big are the artifacts?
       | 
       | I'll for sure keep an eye on this, and add it to my ever
       | expanding list of tech to explore.
       | 
       | Thank you for sharing!
        
         | drogus wrote:
         | The binaries are a few KBs at the moment. I haven't measured
         | the build times, cause it's too early for it to mean much. The
         | amount of supported types and functions is very limited, so it
         | will change a lot over time as I add more stuff.
         | 
         | One interesting thing is that `eval()` support will require
         | custom WebAssembly host functions, cause you can't do custom
         | code generation in WASM. Thus by default the project will
         | assume "no eval" compilation. In this mode it will be possible
         | to do a lot of optimizations, like for example remove unused
         | parts of the language/types, do certain optimiztions knowing
         | exactly what types the script is dealing with etc. So a simple
         | script that doesn't use a lot of the builtins should eventually
         | result in a fairly small binary.
        
       | lagrange77 wrote:
       | Very cool!
       | 
       | Does it support ArrayBuffers?
        
         | drogus wrote:
         | Not yet, it's very early stage where I'm mostly implementing
         | full JavaScript semantics (and hopefully finding some
         | funding/support for the project), but as soon as I'm done with
         | async/await and a few simpler missing pieces, I will start
         | implementing JS builtin types
        
           | lagrange77 wrote:
           | Cool, thanks and all the best with the project.
        
       | OscarDC wrote:
       | I read the README.md of the project but I'm still not sure:
       | What's the expected usage of this? How does the outputed WASM
       | code then interacts with a runtime (and with which, is it
       | intended to be a tool compatible with browsers and other WASM
       | runtimes or is it only compatible with a runtime linked to the
       | project)?
       | 
       | Somewhat linked questions: How does it react if it encounters
       | e.g. web APIs inside the JavaScript code or other global
       | identifiers only defined in some environment (e.g. a recent
       | browser, Node.js etc.)? Or if it's not intended for those
       | environments, how are you supposed to do I/O when using this?
        
         | drogus wrote:
         | These are very good questions, I'll respond here, but I'll also
         | add more info to the README. This project is mainly targeting
         | WebAssembly usage on the server, cause I think it makes little
         | sense to run JavaScript in WebAssembly in JavaScript (although
         | time will tell, maybe it will be useful for sandboxing frontend
         | plugins?). Regardless if it's running in the browser or a
         | backend runtime like WasmTime or WasmEdge, at the moment
         | running JavaScript inside WebAssembly is not ideal. You either
         | have to compile a JS engine like V8 or SpiderMonkey to WASM and
         | then use it to run your script or you have to settle for an
         | "almost JavaScript" language like AssemblyScript. This is a
         | limiting factor for running server workloads. For example
         | Fastly uses SpiderMonkey for their WASM workers, but it means
         | that each instance uses 5-10MBs of memory even for a hello
         | world. Shopify, on the other hand, uses WASM for customizing
         | server side of their shops, and they decided they only allow
         | WASM binaries up to 250KBs, which is a no-go for embedding any
         | interpreter. Thus their "blessed" language is AssemblyScript.
         | They outline reasons for that here:
         | https://shopify.engineering/shopify-webassembly
         | 
         | This is all due to a fact that historically WASM was a very
         | simple runtime. It was relatively easy to compile C code to
         | WASM, just like you compile C code to machine code, but even
         | though a WebAssembly is a kind of interpreter by itself, it
         | wasn't easy to interpret higher level languages on top of it.
         | 
         | With new proposals being standardized, like garbage collection
         | support or exception handling support, WebAssembly becomes much
         | more powerful interpreter, with stuff like structs, arrays,
         | function references etc.
         | 
         | Jaws leverages that fact translating JS code to WASM code in a
         | way that WASM interprets the resulting code, without the need
         | of a JS engine like SpiderMonkey. In practice it mainly means
         | that a binary generated by Jaws will be probably under 50KBs vs
         | 10MBs when you compile SpiderMonkey to WASM and run your script
         | on top of that. Memory usage will be also significantly lower.
         | For companies like Fastly this would mean orders of magnitude
         | lower memory usage and thus server costs. For companies like
         | Shopify it would mean they could leverage JavaScript code
         | already available (think NPM packkages) and JavaScript
         | ecosystem for people writing plugins for Shopify's backend.
         | 
         | > is it intended to be a tool compatible with browsers and
         | other WASM runtimes or is it only compatible with a runtime
         | linked to the project
         | 
         | The only runtime the project uses is WebAssembly. The generated
         | code is mostly 3k lines of WAT code form this file:
         | https://github.com/drogus/jaws/blob/main/src/wat/template.wa...
         | and whatever your JS code is translated to. For example for a
         | very simple program like "console.log('foo')" the entire
         | "generated" part is this: https://gist.github.com/drogus/1c49c2
         | 5ed0b14804b2f27e10d2a79..., which more or less prepares an
         | argument (with new_static_string) and then calls console.log.
         | Right now I need a bit of glue code on the host, but eventually
         | it will be possible to execute such a binary with any runtime
         | that supports WASIp2, WASM GC and exception handling proposals.
         | 
         | > Somewhat linked questions: How does it react if it encounters
         | e.g. web APIs inside the JavaScript code or other global
         | identifiers only defined in some environment (e.g. a recent
         | browser, Node.js etc.)? Or if it's not intended for those
         | environments, how are you supposed to do I/O when using this?
         | 
         | None of this is implemented yet, but I can tell you how it will
         | work. I plan to support Node.js APIs through WASI. WASI is a
         | standard for communicating between WASM programs and the
         | outside world. For example WASI defines a standard set of
         | functions you can use to send an HTTP request, or write to
         | STDOUT, or read/write to a file. So when I get to APIs like
         | `fetch` or `fs`, it should work with any runtime that supports
         | WASI preview2. Browsers could also be supported with polyfills,
         | but in this case I/O support is more custom. Like, if you
         | decide you allow WASM programs to write or read files, you
         | would have to provide a mechanism to do that, for example save
         | files to localStorage or an SQLite database compiled to WASM
         | (or I guess even send them to S3 or something along the lines).
        
       | Aldipower wrote:
       | JAWS is a well-known screen reader for blind people with a more
       | then 30 years history.
        
         | refulgentis wrote:
         | Even worse, JAWS is a well-known movie with a _49 year_
         | history. I strongly believe the screen reader and the WASM
         | compiler both knew this at the time, quite damning.
        
           | drogus wrote:
           | I am painfully aware the project will never be the first hit
           | in Google by just typing it's name lol
           | 
           | Btw, I am very bad at naming, I chose the name cause it has
           | most of the letters that "JS-WASM" has (or all of them if you
           | consider W is just inverted M)
        
             | refulgentis wrote:
             | Don't even think about it :) I'm just teasing the person
             | I'm replying to, its a way of saying "yeah I don't think
             | that name collision is significant" that A) assumes they
             | desire conversation, so it's okay to reply B) engages
             | without asserting C) expresses disagreement in a jovial
             | matter, rather than confrontational
        
             | benmccann wrote:
             | JAWSM might be a more unique alternative if you're looking
             | for any.
             | 
             | Anyway, it's a cool project. Thanks for sharing!
        
             | chamomeal wrote:
             | I love the name!
        
           | Aldipower wrote:
           | Apples and peaches. Jaws the movie is another section, the
           | movie section. Jaws and JAWS are both in the software
           | section. There's the potential for conflicted naming. Sorry
           | to be emotionless here, but at least you could respect the
           | fact that there is a popular software with the same name,
           | without making jokes about it.
        
             | refulgentis wrote:
             | There is no "software section" anymore, alas :( RIP
             | Computer City.
             | 
             | FWIW, for the audience, both you and I know the game here
             | is "can we define a broad enough, yet narrow enough,
             | category that someone could confuse the screenreader with
             | the WASM compiler, such that it can be claimed to be
             | 'emotionless' to say there's a significant collision and
             | the WASM compiler needs a rename."
             | 
             | First, there's certainly room for conversation, emotionless
             | doesn't mean provably unambiguously correct and everyone
             | else needs to agree and not reply. :)
             | 
             | Second, it's clear you do have emotions, ex. see how you're
             | policing whether its okay to "joke", where "joke" is me
             | going to great lengths to indirectly indicate the
             | possibility this is less than 100% unambiguously correct in
             | as non-personal a way as possible. I did that because the
             | initial curt, policing, tone indicated strongly that you
             | would react poorly to any indication this was anything
             | other than unambiguous. And here we are.
        
         | drogus wrote:
         | I know about Jaws as a screen reader, but I don't think it is
         | much of a conflict. WebAssembly is a niche within a niche (like
         | a tool in a WebAssembly ecosystem within a programming
         | ecosystem), so it will probably never grow to a popularity
         | where it's higher in search results making life of people using
         | screen readers worse. But even now, when you enter Jaws into
         | google now, the whole first page is about Jaws, the movie. So
         | if anyone wants to find either of the projects by name they
         | have to specify it more anyway, just like you often have to do
         | with other projects (for example I always search for "phoenix
         | elixir" instead of just Phoenix). My take is that with the
         | amount of tools and programs there is no way to use simple
         | names and not have a conflict here or there.
        
         | IshKebab wrote:
         | Yes. Well done. This is a different Jaws though.
        
       | mmoskal wrote:
       | Back in the day I did an almost-Typescript (though much closer
       | than assembly script) to embedded ARM compiler. Some of the
       | techniques may be useful.
       | 
       | https://www.microsoft.com/en-us/research/uploads/prod/2019/0...
        
         | drogus wrote:
         | Nice! I'll definitely take a look!
        
       | kengoa wrote:
       | > I'm fairly certain I am able to eventually cover 100% of
       | JavaScript spec. Any ideas, questions or critique welcomed!
       | 
       | Do you have the results of test262_runner.rb? I came to know
       | about test262 at a talk by the porffor's author and something
       | like https://github.com/CanadaHonk/porffor?tab=readme-ov-
       | file#tes... in README would be great to show this progress. Great
       | project by the way!
        
         | drogus wrote:
         | Yeah, at the moment it's passing about 12% of tests, but there
         | is a lot of low hanging fruits to implement, especially
         | considering I started the project two weeks ago. This doesn't
         | mean I will hit 100% in linear time, unfortunately, cause there
         | is a long tail of builtin types and functions, but as I started
         | by implementing the "hard parts" I left some easy parts not
         | done. For example I implemented only enough syntax to allow
         | running conditionals and a while loop cause it was needed for
         | the test262 harness, but I left all the other loops (for, for
         | in, for of, do while) and conditional expressions (switch)
         | unimplemented. Implementing them will be more or less analogous
         | to existing implementations for if/else and while.
         | 
         | Once I finish implementing `await` and generators, which are
         | the last hard to implement semantic concepts, I will be
         | implementing those low hanging fruits. It's hard to say how
         | much coverage that will give me, but just to give an example:
         | currently 1200 tests fails, cause `object["foo"]` syntax is not
         | implemented. Ie. `object.foo` works, but `object["foo"]` does
         | not. It doesn't mean that those 1200 tests automatically will
         | pass, cause they might be testing other stuff, but there is a
         | lot of such relatively simple syntax ommissions that make
         | hundreds of tests fail.
         | 
         | And yes, I would love to have a nice graph like porffor has! :D
        
       | philipwhiuk wrote:
       | We're one step closer:
       | https://www.destroyallsoftware.com/talks/the-birth-and-death...
        
         | sedatk wrote:
         | Off-topic, but, why does he pronounce JavaScript "YavaScript"?
        
           | pvg wrote:
           | Why do we say 'wat' instead of hwaet? Same thing.
        
           | Kiro wrote:
           | How else would you pronounce it?
        
             | pvg wrote:
             | J as in Jacques, 'script' like 'esprit'. Zhavascree, stress
             | on final syllable.
        
           | noman-land wrote:
           | The joke is that he's speaking from the future where they
           | inexplicably pronounce javascript "yavascript". This is how
           | you know he's really from the future.
        
             | sedatk wrote:
             | Uh, okay, I must have missed that part :)
        
               | noman-land wrote:
               | He definitely never mentions it but the opening line of
               | the presentation is "This talk is a 40 year history
               | beginning in 1995 and going until 2035" and he speaks in
               | the past tense so he sorta just launches into it without
               | setting it up much.
        
       | teaearlgraycold wrote:
       | I get a build error where it can not find "prepend.js". Indeed it
       | appears to not be in the repo.
        
         | drogus wrote:
         | thanks for reporting and sorry about that! I was prepending
         | some JavaScript code to be compiled for test262 harness before,
         | but at the moment it was just an empty file, so I removed it
         | and pushed a fix. Please try again now and let me know if you
         | run into any issues!
        
       | andout_ wrote:
       | Really clever use of the new WASM GC proposal. All the JS -> WASM
       | compilers so far have basically just been shipping a whole JS
       | engine - this is the first one I've seen that actually tries to
       | map JS constructs directly to WASM primitives.
        
         | drogus wrote:
         | Thanks! Although, to be fair, it's a clever use mostly cause
         | I'm too dumb to write the full interpreter on top of WASM lol
        
       | tomcam wrote:
       | Or, as some of us call it, a compiler. Nice work btw!
        
         | drogus wrote:
         | Haha, I haven't even noticed it doesn't make too much sense
         | when I was writing the title :D
        
       | huijzer wrote:
       | Just when I was thinking: do we need more compilers or do they
       | all exist already?
       | 
       | Thank you for working on this! I think it's a great idea.
        
         | drogus wrote:
         | Just one more compiler, bro. Just one more, I promise. This is
         | the last one, just one more
        
       ___________________________________________________________________
       (page generated 2024-11-09 23:00 UTC)