Design: Will there be a JS -> WASM compiler?

Created on 24 Jun 2015  ·  93Comments  ·  Source: WebAssembly/design

After scrutinizing the design docs, I was able to find a mention of a polyfill that would transpile WASM -> JS. I was also able to find mention of a C++ -> WASM compiler.

However, I was unable to find any mention of a JS -> WASM compiler.

The majority web developers are fluent in Javascript, and thus a JS -> WASM compiler would be ideal. Web developers will want to continue writing their websites using Javascript, instead of writing them using C++. Thus I am not sure what to make of the MVP, nor the post-MVP sections making no mention of a JS -> WASM compiler. What is happening here?

Most helpful comment

I just started experimenting with a toy programming language that might be relevant: https://github.com/evanw/thinscript. It uses TypeScript-style syntax and compiles to WebAssembly. I figured I should mention it because it might be an interesting case study. Also I was pleasantly surprised by how easy WebAssembly was to generate. Nice work everyone!

All 93 comments

Browsers will still have native JavaScript VM along-side wasm. There is no reason to compile JS to wasm because you would have to also include a whole javascript vm. The resulting code would be huge and slower than the JS VM natively provided.

There is a task post MVP for adding things like adding access to the GC from wasm code so that scripting languages can be implemented for wasm.

JS → wasm will only really make sense once wasm supports GC, and most likely JIT compilation too, which is still quite a while away. This would basically be equivalent to implementing the JS engine in wasm! I mentioned this recently and @BrendanEich accused me of having been taken over by horse_js.

To be clear, wasm's goal isn't to _replace_ JavaScript, it's to supplement it. It's therefore not really a goal at the moment to support JS → wasm, but the features we want to implement will make it possible. I'm not sure it'll be that useful from a developer's perspective, though. You may get some size reduction, but that's about it. From a browser's perspective it may be interesting to have the JS engine implemented in wasm from a pure security perspective.

@jfbastien I beat you by 2 seconds ;)

But your answer is better. I'm excited for GC and JIT in wasm. I love creating my own languages and running them on the web.

And how about supporting variants such as asm.js or TypeScript/ES7? These
flavours of Javascript promise some level of type guarantees.

I'd imagine the need for JIT would be less so, but GC still very much
needed for these languages. Would having a {typed flavour JS} -> WASM make
this any more feasible?

W: http://bguiz.com

On 24 June 2015 at 09:44, Tim Caswell [email protected] wrote:

@jfbastien https://github.com/jfbastien you beat me by 2 seconds :P


Reply to this email directly or view it on GitHub
https://github.com/WebAssembly/design/issues/219#issuecomment-114675456.

Yes, an asm.js -> wasm translator is a high priority, and Luke already did
work on a compressor that might serve as a good starting point.

On Wed, Jun 24, 2015 at 1:59 AM, Brendan Graetz [email protected]
wrote:

And how about supporting variants such as asm.js or TypeScript/ES7? These
flavours of Javascript promise some level of type guarantees.

I'd imagine the need for JIT would be less so, but GC still very much
needed for these languages. Would having a {typed flavour JS} -> WASM make
this any more feasible?

W: http://bguiz.com

On 24 June 2015 at 09:44, Tim Caswell [email protected] wrote:

@jfbastien https://github.com/jfbastien you beat me by 2 seconds :P


Reply to this email directly or view it on GitHub
<https://github.com/WebAssembly/design/issues/219#issuecomment-114675456
.


Reply to this email directly or view it on GitHub
https://github.com/WebAssembly/design/issues/219#issuecomment-114677789.

We have spoken with the TypeScript team about this possibility and they have shown interest, but it seems like progress there is currently gated on adding typed objects into JS.

@bguiz: JS engine is the wasm engine, and it will continue to support the evolving JS standard language. No worries there (I wasn't sure whether you thought that might go away. Not in any future that I can foresee). OTOH as others note, wasm needs time to evolve GC, JIT support, and other dynamic language features, to be a first-class target for JS. Even when it does evolve these things, I have doubts that JS/wasm engines will drop their JS syntax and built-ins in favor of downloaded JS-in-wasm VMs. We shall see!

/be

An asm.js-to-WebAssembly translator will also be something we're planning to add to Emscripten.

As for regular JS, I think others have answered the question above.

The whole point of JS is easy to code and can do amazing things : dhteumeuleu or codepen.io/ge1doot, but you can see the source and it's easy to hack.

"wasm" is only a way to sell more game and others apps for google, apple an co. The only "evolution" is that there'll be able to control you better with "no install", directly from the big brother server... I'm just surprised they are not afraid of eating each other yet...

It's possible with code analysis or code annotations to compile ECMAScript to WebAssembly. This doesn't sound like a priority for the WebAssembly team but it does sound like a great idea for an independent effort.

I just started experimenting with a toy programming language that might be relevant: https://github.com/evanw/thinscript. It uses TypeScript-style syntax and compiles to WebAssembly. I figured I should mention it because it might be an interesting case study. Also I was pleasantly surprised by how easy WebAssembly was to generate. Nice work everyone!

I would caution people about using very thin wrappers on top of wasm though, in general. As one example, thumbing through the thinscript code, I see there's a while statement which is lowered to loop { if (!condition) break; }, which will be less efficient than if (condition) loop { ...; br_if condition } on several wasm engines.

To me, the thing that makes wasm more than just a reheated JS is the possibility of a different philosophy: because wasm is a compiler target, compilers can perform optimizations before shipping the code to clients, so we can keep client-side VMs simpler and faster. However, if thin wrappers around wasm become popular, there's a risk that client-side implementations will eventually have to grow bulkier and more complex in order to do the optimizations that aren't being done.

Yes I agree. One of the things I like most about WebAssembly is its simplicity. I'm planning on adding compiler optimizations and doing benchmarks once the language is more complete. I expect inlining to be one of the bigger wins, for example, and I wouldn't expect WebAssembly to do that for me. I'm also planning on experimenting with a machine code target and I will be using the same optimizations for both targets.

Sounds very cool! I'll be interested to see where it leads.

I'm imagining JS->WASM being more appealing for servers than clients. As a very high-level overview of the architecture that I have in mind...

JavaScript -> WebAssembly -> Tracing Interpreter -> LLVM IR -> Machine Code

In this conception, a clear mapping from WASM to LLVM IR for garbage collection would be very desirable. Promotion from IEEE doubles to integers could be done as an LLVM pass. The notion of separate JITs for warm and hot code could be implemented in terms of LLVM pass managers.

Just some thoughts, please feel free to delete this if it's spurious!

Cross environment compatibility is a serious problem in JS ecosystem. Babel tries solves this problem by transpiling down to some more adopted version of ES and I guess we can all say that it is pretty successful.

There is still an issue here though. For example, if you are transpiling your ES 2016 code down to ES5 for compatibility and your code happens to run on an environment with (partial or complete) ES 2016 support, you will be missing out the benefits of having ES 2016 support in your environment.

If everyone is transpiling their code down to ES5, then what is the benefit of having ES 2016 support in an environment in the first place?

A new project called "babel-preset-env" tries to fight this issue by targeting environments by their versions. The idea behind it is that (1) you ask it to target specific versions or "latest X versions" of browsers, (2) it determines the lowest common denominator of features and (3) enables only necessary transpilations. This helps, but sadly can't solve the issue.

We still have the risk of a major vendor not behaving and causing the same issues Microsoft was causing with Internet Explorer for years. The whole ecosystem is in hands of a few vendors, who decide what to implement and when to implement. This is not free nor open.

The only solution is a new compile target for JavaScript which is performant and needs a lot less maintenance (hopefully none) than a JS engine. When environments (browsers, Node.js, etc.) starts supporting such a target, implementing new ES features should become the responsibility of compilers and not engine vendors.

JS -> WASM would be interesting to protect intellectual property by code obfuscation when it comes to on-premise installations of let's say Electron apps on customer servers. It's hard to believe but true, there are many small institutions in Germany with very little or no internet connection, which requires on-premise installations, but giving your entire code in plaintext to them can be scary for software companies.

@Simran-B Wasm has as a design principle to support a familiar text format. Notably it has a structured control flow design for quick analysis, and is optimized for single use definitions used in stack order so optimized for readable expressions. Thus it is not a 'code obfuscation' target, but developers can emit their own 'code obfuscation' on top of this but should understand that this is expected to have a cost in terms of decreased encoding efficiency and decreased performance.

Hi all, I just resently discovered WebAssembly, but thinking about the JS -> wasm compiler, I imagined something like Angular2's Ahead-of-Time compilation, jsut way more optimized (I'm thinking machinecode instead of javascript)... Will this ever be possible? Is it worth it?

EDIT
I'm also thinking, is will there ever be a possibility for the browser to send a flag to the client that it supports wasm, and then we can serve up a precompiled app instead of a javascript file?

Richard

@Richard87 you could think of webassembly as a platform independent instruction set with its own specialized encoding and calling conventions. There's nothing saying you can't describe a subset of javascript that'd be very easy to transpile to work in webassembly's world of those things, but enforcing that would probably be difficult. The featureset and implementation surface area are forever growing in javascript, and adapting existing libraries and frameworks to work in that subset would likely be difficult, especially given the current lack of garbage collection in webassembly, and you'd essentially lose the benefits of existing javascript code.

With the addition of garbage collection primitives in webassembly, the subset of javascript that would be feasible to transpile without writing a big ol' virtual machine would widen, but it still in my opinion wouldn't be optimal compared to just transpiling from a more suitable language, since your overheads in javascript would only be marginally smaller, the important overheads in web applications (the network!) would widen, and the benefits you'd want to reap from using javascript in the first place would still be out of reach, besides getting to say that it uses something that resembles "javascript" (this is actually a similar boat that Unity is in with UnityScript, except they adapted it somewhat to integrate better with their subsystems and calling conventions in general, besides other whims).

I think it is extremely important for some of us who are looking at Browser and Webgl to be faster for gaming. I intent to bring a commercial quality game in webgl but the current tech produces so much garbage that frames skip.
Browser gaming using JS game engines has almost failed and Unity took off. I think C++ => Wasm is an undue advantage for these big Unity like framework makers who could cross compile their code to WASM.
But what about people who write JS by hand using Three JS or Babylon.. Not having a JS/Asm.js => Wasm toolchain would mean large application in Js would be dead and people would use C++ and code generation backends to produce Wasm. More specifically in games and such.
Not having a JS => Wasm backend in unfair to JS Developers. Also EMCC allocates a Big heap when it runs and speeds are evident due to that, but Js Developers who write good js Code still couldnt achieve so much performance due to the complexity of writing such code. There should be some mechanism to reuse most stuff and ability to call gc earlier or at will. Frame skipping when the GC runs causes Webgl to skip frames is a big problem and needs to be resolved. There should be some mechanism to hand tune JS code better than Code generators. like hand written Assembly still produces much smaller and highly aligned code. That should be possible in web-assembly.

@metacritical C++ can compile to WASM because many people put a lot of work into the process. The same could happen for JavaScript, but as far as I know, no one is attempting this currently. There is little reason to do so: performance will be unchanged.

Your engine's problem is garbage collection. This problem doesn't go away if you build a garbage collection algorithm that uses linear memory and WASM code... eventually you have to stop the program to see which objects are still alive and delete the ones that are not. The solution is to not create garbage objects, preventing the need for the GC to ever run. You don't need WASM to achieve this, you need to rework your engine.

Ultra pristine Javascript that reuse Arrays and produce low garbage are extremely hard to write. Also i think Plain Js cannot be compiled to WASM. Asm.js or Typescript would be easier to compile to WASM due to availability of type annotations or types in them respectively.

@metacritical Difficult, but not impossible. Even in the C++ engines, much of the code is around object lifetime management. Although unconventional, there's no reason you can't do the same in JavaScript.

Plain JS _could_ be compiled to WASM but the compiler would have to add a lot of helper code to enable JavaScript's higher-level features like garbage collection, reflection, properties, and so on. Basically, all the stuff you get for free with the browser's built-in JS engine. TypeScript doesn't help much.

By comparison, ASM.JS would be easy to convert to WASM. The strict subset of JS features allowed by ASM.JS is also 100% covered by WASM. If there were a large volume of code written in ASM.JS, this would be a worthwhile effort, but as far as I know all the major ASM.JS files are produced from C++ source code, which can already directly target WASM.

By comparison, ASM.JS would be easy to convert to WASM.

Correct, and actually the main way we compile C++ to wasm today is to compile it to asm.js first, then compile that asm.js to wasm using Binaryen's asm2wasm.

@kripken Looking at the asm.js specs it seems easy to write handwritten asm.js, which means all is not lost for js programmers, we can still get WASM binaries using the above.

Wouldn't evolution of JS i.e. strictly typed language, could make it a good candidate for JS -> WASM?
I think TC39 has proposal for typed object. May be more other features could make it possible.

@aruns07 The fewer JavaScript features you allow people to use, the easier it would be to compile to WASM, and the more likely people will be unwilling to live with your restrictions due to incompatibility with their favorite libraries.

@Kardax @aruns07 People love the convenience of a Dynamic Language. We need strong types occasionally not all the time.

jfbastien commented on Jun 24, 2015
JS → wasm will only really make sense once wasm supports GC, and most likely JIT compilation too, which is still quite a while away. This would basically be equivalent to implementing the JS engine in wasm!

According to following link :
https://lists.w3.org/Archives/Public/public-webassembly/2017Feb/0002.html
WebAssembly consensus and end of Browser Preview

Now, 2 years after your first reply, WebAssembly is now supported by major web browsers today.
So it's not equivalent to implement JS engine in wasm.
The advantages of js -> wasm is not only GC support, but also smaller code size, and faster execution, specially in the field of Hybrid application development such as Ionic2 which usually produces a JS file around 10MB which cause application load time to exceed 5 seconds(each 2MB parse of JS = 1 second)

@jfbastien So please post your updated answer about JS -> wasm transpiler ?

As part of my master thesis, I'm trying to write a Transpiler from a subset of JavaScript to WebAssembly. At first, it will be limited to TypeScript, but other typed variants like Flow might be supported in the future.

However, the goal is not to implement the full JavaScript language as, in this case, I would face the same issues the JIT implementations face today, and therefore, no speedup can be expected (more certainly, my implementation would be 100 times slower!). It's going to be a subset like defined by SoundScript

My goal is more to allow specific parts of an application to be compiled to WebAssembly without the need that the developer leaves his familiar developing environment or uses another programming language. Therefore, it will be more intended to speed up performance crucial parts of an application and not as a general purpose transpiler that accepts any existing JavaScript application.

I'm quite curious what my findings are going to be as I see the pros and cons of such an approach. Let me know if you have any input.

@Mohsen7s my answer remains accurate: the MVP version of WebAssembly doesn't support GC and JIT capabilities which make it possible to implement a fast JavaScript virtual machine. An interpreter is entirely possible, with clever tricks it can be quite good, but not as much as what native implementations do.

This is inherent to our "Minimal Viable Product" approach: ship something that works for some usecases first, and then add feature to meet other usecases. Please see the following thread for a similar discussion on MVP and missing "future features": https://github.com/WebAssembly/design/issues/992#issuecomment-281735235

Leaving aside technical discussions as to what can and can't be implemented currently, I'm amazed that JS -> WASM isn't the number 1 goal both philosphically and from a marketing perspective - I fail to see how you'll ever get developer buy-in until this is the case. If all those front/back-end/full-stack developers out there with JS skills capable of working in any market vertical wanted to instead spend their time learning C++ which is used in a substantially smaller subset of industries, then they would already have done so - I know, I speak as one. I can't help but feel that this whole discussion is a bit of an echo chamber and that those defending the lack of a compiler would find their time would be better spent speaking to people on the coal-face asking them what they really want.

@BossLevel

Leaving aside technical discussions as to what can and can't be implemented currently, I'm amazed that JS -> WASM isn't the number 1 goal both philosphically and from a marketing perspective - I fail to see how you'll ever get developer buy-in until this is the case. If all those front/back-end/full-stack developers out there with JS skills capable of working in any market vertical wanted to instead spend their time learning C++ which is used in a substantially smaller subset of industries, then they would already have done so - I know, I speak as one.

Browsers can already run JavaScript efficiently. Browsers cannot run the intended use cases as efficiently. To top it off, WebAssembly has non-Web aspirations.

This discussion, as well as https://github.com/WebAssembly/design/issues/992#issuecomment-281735235, illustrate the variety of goals different people have. None are wrong! MVP simply needs to prioritize who gets served first.

I can't help but feel that this whole discussion is a bit of an echo chamber and that those defending the lack of a compiler would find their time would be better spent speaking to people on the coal-face asking them what they really want.

That was the entire point of forming a W3C Community Group. We think it's succeeded, as we've heard from many interested developers. Some aren't interested in MVP, but are interested in future features.

@jfbastien

Browsers can already run JavaScript efficiently.

Ha, I've been trying to write a massively multiplayer HTML5 game capable of running at a decent FPS on an average mobile phone since 2008 and I'm still not there! And given that when I go contracting to pay the bills, I am extremely well rewarded, I'm pretty certain that my lack of progress is not due to the quality of my code.

That was the entire point of forming a W3C Community Group

Ha again - how many real world devs do you know that join a Community Group? The devs that do are typically evangelists etc who are knowledgable yes, but have felt less of the pain of real-life dev.

And I'm sorry, I really don't want to belittle anyone on this page/involved/at W3C. As you say, this is a discussion, and this is my point of view from the front-lines.

Apologies for coming back to this like a dog worrying a bone but whilst away I thought of a better way of making my point. In your next newsletter/community event or whatever means you have of garnering feedback, put this question to web developers (your customers):

In order to take browser-based performance to the next level you will need to learn another language; would this be acceptable?

Because that is basically the question that has already (to my mind, deleteriously) been answered by some on this page.

And finally (I promise ;-) ) @jfbastien, if:

To top it off, WebAssembly has non-Web aspirations.

why's it called "WebAssembly"?

@BossLevel I think I see where you're coming from. I can't speak for people doing the evangelizing, but my understanding is that different evangelists have been in contact with traditional "native" developers who are interested in WebAssembly. From your point of view that may not be apparent, but at a minimum I can point at Unity's interest as a sign of "serious" developers. These folks also post to github, under their own names, but affiliations aren't always apparent. It is not my place to speak for them.

Ha, I've been trying to write a massively multiplayer HTML5 game capable of running at a decent FPS on an average mobile phone since 2008 and I'm still not there! And given that when I go contracting to pay the bills, I am extremely well rewarded, I'm pretty certain that my lack of progress is not due to the quality of my code.

I didn't mean to imply that writing fast JavaScript is easy. What I wanted to say is: WebAssembly doesn't make optimizing JavaScript any easier. Rather, it allows browsers to consume a format which is better suited at generating reliable performance. It also allows TC39 to focus on improving JavaScript itself, not just JavaScript as a compilation target.

Ha again - how many real world devs do you know that join a Community Group? The devs that do are typically evangelists etc who are knowledgable yes, but have felt less of the pain of real-life dev.

And I'm sorry, I really don't want to belittle anyone on this page/involved/at W3C. As you say, this is a discussion, and this is my point of view from the front-lines.

Your point of view is indeed valid, and I think it's clear that from where you stand I'm saying something that's hard to believe. We should communicate this better (or hey, maybe I'm wrong :wink:).

In order to take browser-based performance to the next level you will need to learn another language; would this be acceptable?

Because that is basically the question that has already (to my mind, deleteriously) been answered by some on this page.

I see your concern, but I hope it isn't one that will turn out to be true. Again, I may be wrong. The way I see it, WebAssembly brings new developers to this platform, developers who had bad experiences with the Web in the past or heard horror stories. In turn, it helps JavaScript developers who want to use "traditional" code (what some call "legacy") use that code: we want WebAssembly to be easily usable from JavaScript. To achieve this it needs to be as easy as using npm (which... isn't always easy!).

I'm somewhat confident this will turn out because of the feedback we've been seeing on Twitter, Hacker News, Reddit, and various conferences. Again, maybe I'm wrong and I'm listening to echo chambers. At a minimum, I've had very promising discussions at conferences with people with C++ as well as JavaScript backgrounds.

At the same time, TC39 is truly trying to improve JavaScript. I believe it has in recent years, especially with ES6.

But your point remains: maybe developers will want to be well-versed in JavaScript as well as more "WebAssembly-friendly" languages such as C++ or Rust. I don't know which way things will go.

why's it called "WebAssembly"?

Ha! That's a wonderful question. I have a talk entitled "WebAssembly: neither Web nor Assembly". I'll have to give it publicly so I can express how I feel about the name :grin:

So I'll keep you hanging on that one.

I'm reading two desires here:

  1. A binary representation of standard JavaScript for fast load times.
  2. Something to bridge the performance gap between natively-compiled C++ and standard JavaScript.

Item 2 is the subject of ongoing research and massive investments by many companies. If you look at performance measurements of JavaScript engines over the past 15 years, it's working too... the gap is getting smaller.

Item 1 is not being worked on by anyone, as far as I know. It's massively complicated, and getting harder as JavaScript continues to evolve at a rapid pace. WebAssembly is very strict and relatively uncomplicated, and it still took years to develop.

@jfbastien - many thanks for your considered and considerate response :)

So a couple of illustrative points, in no particular order:

1) A good example I see of this entire discussion and my view on the direction you should be heading, lies with NodeJS - a JS API/front-end to a C++ back-end - you get the ease of use/familiarity etc on the one hand and the speed on the other.
2) Sticking with Node, back in 2008 when I embarked on my own personal odyssey ;-) I originally looked at both PHP and Java for the back-end (I was coming back to development after a decade on the dark side of IT management and sales ;-) !) but quickly discounted them for the simple reason that I only wanted to have to learn one language, and to learn that one well! A personal tale I know, but I doubt I am the only developer who feels this way, particularly those working for themselves, not on a company dime whilst they learn the language.
3) I deliberately haven't googled the numbers before making my next point (indeed I am unsure if I even could) but I'll be willing to bet that take-up of ASM was low. I know I got very excited when I saw the initial demo but upon learning that there was no compiler I immediately dismissed it. To ask a web developer who's part of the largest dev community on the planet (JS) with a vast array of APIs, libraries, resources, tutorials, frameworks etc available online to step away from that, is to my mind asking too much, and by not providing them with a means to potentially make that first step (i.e. a compiler) is missing an obvious trick on your part. I'd even go so far as to wager that development in Shading langage (GLSL) has seen more growth than ASM now that you can a) write it directly into excellent frameworks like Pixi.js and Three.js and b) play with it directly on sites such as ShaderToy.
4) The games industry/gaming generally. I can speak from experience here as a) I've been writing (as yet unreleased!) games for the past 9 years and b) I served on the board of TIGA (the trade association for the UK's game developers) for 2 years. Trust me, I think the number of game developers who wanted to migrate to the web could probably be counted on one hand - game developers are already in the industry they love and even taking a pay-hit/working long hours despite that, so these should not be WA's target audience. Yes, their employers are always looking for new mediums to port their games to, but let's not kid ourselves, excluding mobile (where native code sadly wins hands-down and which is what I want WASM to fix), web is still very much the poor relation to PC/console both in terms of performance and monetisation.
5) Conversely, whilst the bedroom coder/indie scene is not at the zenith it was a few years ago, there are a vast number of web developers who fancy making a web game in their spare time. And whilst I don't want to veer overtly into politics and I am in no way knocking the Unity guys (I've had dealings with a number of them and it's a great product), personally I think you should be looking after the interests of the multiple little guys, not the one big-guy (it makes both philosphical and commercial sense).

I shall very much look forward to seeing your talk @jfbastien :)

@RyanLamansky - I think you make a reasonable distinction. With respect to:

Item 1 is not being worked on by anyone, as far as I know. It's massively complicated, and getting harder as JavaScript continues to evolve at a rapid pace.

On an entirely personal level, as someone who's been writing JS 8 hours a day since 2008, I'd very much like to see the evolution of JS just stop for a while and let everyone else catch up! I've always worked on a principle of developing for the lowest common denominator i.e. if it doesn't have 100% support it's not happening (IE6/7/8/9 aside ;-) ). And so we find ourselves in the ludicrous position of focusing on trendy ES6 patterns and supposed use-cases when we haven't even got 100% browser support for ES5 across desktop and mobile. The language clearly works as-is (despite it's admitted foibles) as demonstrated by it's market-share, so how about we, as a community of developers, spend the next few years learning to write efficient, optimal code with what we have rather than yet again re-inventing the wheel with new hipster code (sorry I'm getting into rant territory ;-) )?

I think it's probably time I got my coat ;-)

@RyanLamansky I have encountered the impression that WebAssembly will just be a new target for your bundle build process, and suddenly everything will be faster. Clearly that's not the case. WebAssembly has a very specific target use case, and likely won't have much to offer the typical web developer with a large JS code base full of business logic.

But as you note there are some gaps in the JS based development life cycle for more typical business oriented web applications:
1) Large JS bundles have a significant parsing overhead and typically provide insufficient obfuscation.
2) Standard JS code lacks the type annotations (and perhaps other hints) required to make JIT/Native code optimizations.

This suggest a possible solution is a properly typed and annotated version of JS that gives the developer more deterministic and transparent optimization paths, and a pre-parsed binary version of that version of the language.

The comments and the docs say WASM runs besides JS and uses the same JS engine of browsers (optimized). https://developer.mozilla.org/en-US/docs/WebAssembly

I dont understand this question really.

Sorry to be asking a stupid question and making a stupid comment: Does the question and the Webassembly team's comment mean that Webassembly is FASTER than Javascript? I do not see performance comparison for WebAssembly Code and similar Javascript Code? I see only subjective thoughts. Can someone explain this? If Webasembly is faster then Javascript then why not provide a transpiler? If Javascript is not possible then why not ES7/TS code? Why is there so much secrecy around this?

@ganeshkbhat The initial release of WASM is little more than a compact binary encoding of asm.js, which is a very strict subset of JavaScript. It does not run faster than asm.js unless 64-bit integers are used, as these have to be emulated in asm.js.

There are proposals to add features to WASM that would bring it closer to JavaScript in capability (garbage collection, DOM integration, threads), but there are no plans to add the full JavaScript feature set. So, it's likely a JS->WASM transpiler will never exist. Instead, new applications and libraries will be made that are designed to work within WASM's limitations. Today, that's C and C++, where the language restrictions align well with WASM and asm.js.

There is no secret nor any magic. Wasm is "faster than JavaScript" because it is a much simpler language that is much closer to hardware. JavaScript is a complicated language that has to do many expensive things during execution. It wouldn't magically get faster by compiling it to native code through Wasm instead of directly.

@ganeshkbhat currently, it is not possible to allocate objects inside asm.js / webassembly. In asm.js and webassembly, all JavaScript operations will use one big typedarray to store and load there values. Creating JavaScript objects (e.g. var obj = {a: 1, b: 'test'}) and arrays (e.g. var a = [];) is not possible inside webassembly since there is no object support yet. This is a design decision of the Minimal Viable Product made to get webassembly support in all major browsers as soon as possible.

In a future version, GC support is planned for webassembly. We (LeaningTech.com developers) are working on a proposal for object support in webassembly, but that will take some time to land as a specification and an implementation in all major browser. Until then, it is not possible to transpile JavaScript (and CoffeeScript, TypeScript, etc.) to webassembly. When the proposal is accepted, it should be possible to transpile a larger subset of JavaScript, but it will not support all features that are currently available.

Sure. Do look forward for better support for JS here. I definitely feel it can be supported. Writing a transpiler is what might be needed for type supporting languages.

From what I read about webassembly, it is targeting mainly web browsers and in that area it doesn't sound very appealing to have js -> webassembly compiler. But I can imagine running webassembly in non browser environments. This is not entirely true as in can also run in nodejs, but I see it's true potential in nodejs environments in something like vertx - polyglot allowing running modules written in any language, that can be compiled to webassembly. I can imagine, that it will extremely difficult to get something like this done. It will require many features like GC, maybe even some kind of VM to be implemented, but nothing is impossible. Remember that many people were skeptical about asm.js too and look at it today.

For all those, that are excited (as me) about compiling js -> webassembly, there might be indirect and very bumpy way through js -> c -> webassembly using project ts2c transpiler in the future.

@mauron85 Non-browser and non-JavaScript runtime environments are definitely a consideration of the design, it's just that only the JS API exists today.

For my part, I've been experimenting with a .NET JIT system and don't see any real barriers other than time, and I'm sure there are others looking to integrate WASM into their favorite platforms, too. I'm certain a few years from now there will be high-quality non-JavaScript runtimes for WebAssembly, the only open question is the degree to which they'll be formally endorsed by the WebAssembly team.

IMO one benefit of JavaScript -> WebAssembly compilation ability is that the developers/maintainers of the Javascript libraries and tools would probably be able to release their APIs in two formats:

  1. in JS (as is right now) which users can use for browsers & node
  2. WASM as the compiled library which might be more efficient.

And this is without having to ever rewrite their existing JS code in C/C++, if they want to unleash the performance benefits of WASM in their JS libraries.
So the library developers would still be able to develop and maintain in Javascript and produce two outputs for two different targets both in JS & WASM.

And using the compiled WASM version library would definitely be more efficient for the users as all they need to do is to use the exposed API from the library and they obviously won't care whether it's written in WASM or not. But the performance would certainly be improved.

WASM as the compiled library which might be more efficient

Why? Why would a blob of javascript transpiled web assembly (worst case scenario, including much of the runtime for a javascript engine in that binary; best case scenario, including a layer built on top of the future builtin wasm GC, which incurs its own overhead anyways) run faster than that javascript thrown at a jit dedicated to... running javascript?

Okay, you mean that would be even more slower with more overhead?

Perhaps there's something I haven't understood well. How is C/C++/Rust -> WebAssembly compiled stuff really efficient and even if there is a JS -> WASM support in the future that would cause overhead? Is that just because JS is a dynamic language and C, C++, & Rust aren't? Or is it because JS is by nature not a fully-compiled language but these other languages are?

I guess it is unlikely that JS to WASM compiling would boost sustained performance; however, it may improve code size and parsing time due to the binary encoding, which is still useful.

I think we can just define a binary encoding for JS, and ignore linear memory etc for now. This is simple and polyfillable.

@kabirbaidhya The main issue with JS -> WASM right now is that you can't build an efficient garbage collector inside of it as there is no way to analyze the stack to see which objects are alive. This means you'd have to place a copy of all object references in linear memory (the heap) and keep it synchronized, seriously degrading performance. It also lacks shared memory multi-threading, so background garbage collection is impossible. Future versions of WASM will be able to tap into the host browser's garbage collection engine, eliminating this problem.

The other major barrier to JS -> WASM is the fact that nearly all objects are fully dynamic. WASM intrinsically expects everything to be purely static, so complex mapping layers, emulation, and dynamic code generation would be needed to approach standard JS performance. Fortunately, TypeScript helps with this, so a strict subset of TypeScript may be able to target WASM to some degree. I know there's at least one person trying to build this.

C/C++ works well with the first release of WASM due to the fact that WASM's limitations are closely aligned with native hardware limitations, which C/C++ are designed to target.

FWIW there's a great slidedeck on how V8 handles JavaScript arithmetic: https://docs.google.com/presentation/d/1wZVIqJMODGFYggueQySdiA3tUYuHNMcyp_PndgXsO1Y/edit

tl;dr this is just _one_ example where the reality is much harder than it might seem and in practice isn't very meaningful since the native VM can (and likely will) do a better, faster job since it's truly native and has access to resources and APIs wasm never will--and (probably) most importantly, years of iteration.

That's not to say a _subset_ of JS/TypeScript couldn't proliferate successfully, like ThinScript, TurboScript, etc. They'll look very familiar to JS-programmers at first glance.

I still think these are good questions to ask, and continue asking. It's critical we all understand the use cases and future of WebAssembly--as well as non-goals.

On 6 April 2017 at 00:36, Ryan Lamansky notifications@github.com wrote:

The other major barrier to JS -> WASM is the fact that nearly all objects
are fully dynamic. WASM intrinsically expects everything to be purely
static, so complex mapping layers, emulation, and dynamic code generation
would be needed to approach standard JS performance. Fortunately,
TypeScript helps with this, so a strict subset of TypeScript may be able to
target WASM to some degree. I know there's at least one person trying to
build this.

Unfortunately, I doubt that TypeScript helps in this regard. To encompass
JS legacy, its type system is so deeply and fundamentally unsound that
there is no interesting "strict" subset. For example, such a subset would
need to exclude any of TS's notion of subtyping, which would make it pretty
much useless in its domain.

There have been nice research papers, like e.g. on SafeTypeScript, but not
only are they more restricted, they also require substantial amounts of
costly additional runtime bookkeeping and checks, defeating the purpose of
the discussion (and effectively being a different language than JS/TS).

Maybe I am not getting something, but one of the ideas of WebAssembly is to directly load the AST to avoid the parse time of js, right ?

So, if we have a tool that compiles js to this ast format and passes that to the browser, won't it benefit from avoiding the time to parse ?

@agnivade, it's an AST for a completely different, much more low-level language.

If you were to compile JS to Wasm offline, then yes, you wouldn't need to parse on the client side (just decode). At the same time, because JS is so complicated, code size would drastically increase, probably by a factor of 5 or more, which is a much higher cost. (And that isn't even take into account that you probably would also need to include an entire implementation of a JS VM runtime system in Wasm, which easily is megabytes of code.)

Moreover, without a representation of the sources you cannot implement most of the dynamic optimisations that are crucial for getting JS anywhere near fast. These optimisations rely on recompiling the original source code and specialising it based on profiling information. An already compiled Wasm AST doesn't enable that, you'd need an AST of the original source program.

@rossberg-chromium - Thanks a lot. That clears up a lot ! One doubt though -

And that isn't even take into account that you probably would also need to include an entire implementation of a JS VM runtime system in Wasm, which easily is megabytes of code

Why would you need the VM runtime system ? Isn't the browser itself the VM runtime ? I just want the code to be in the AST format so that the browser can readily start executing it. I get that the net size will increase because the language itself is complex, and we cannot implement dynamic optimisations. But why do we need to bundle the VM runtime itself, when we have the browser for that ?

@agnivade, without dynamic optimisations JavaScript will be slow, and I mean _really_ slow, like 100x slower, maybe worse.

By "runtime" I don't mean browser stuff like the DOM, but the bare JS language support, i.e., things like garbage collector, object representations, primitives and base libraries, etc. That is pretty huge for JavaScript, and you'd need a reimplementation of all of it inside Wasm.

And of course, you'd also need an interface layer to the DOM.

Ok I think I understand things a bit better now. I thought that the

garbage collector, object representations, primitives and base libraries, etc.

can be used from the browser itself. And I can just let the browser load the AST and do its usual job. But now I realize that everything needs to be packaged inside WASM itself.

A universal-ish scripting language bytecode would be interesting though! A compile target designed around efficiently transporting and executing programs written in dynamically typed, garbage collected languages, with all the bizarre edge cases of the popular ones (javascript, ruby, python, lua) covered in (some cases) special opcodes and structures etc

@distransient, so you want the combinatorial insanity of all the scripting languages? I'm optimistic that it would be possible for humanity to gather the engineering resources to specify and implement that efficiently by 2050. :)

Those who interested in compiling TypeScript to WebAssembly using LLVM. check out this reach project. https://github.com/MichaReiser/speedy.js
Looks like this discussion is never ending...

@rossberg-chromium I said it would be "interesting", not easy or pretty 😉

A universal-ish scripting language bytecode would be interesting...

While WASM is incrementally evolving to eventually support stuff like Python, we could have first-class support for developing scripting languages for the Web much sooner than WASM can provide it, if we approached the problem from the opposite end at the same time.

It should be relatively simple for JavaScript engines to expose their ability to execute JavaScript ASTs, and the ASTs they accepted could be standardised (even if they're immediately converted to a non-standard, intermediate format internally).

We could simply combine an AST format (like estree) and a serialisation format (like JSON) to create a new file format with a new extension. If browsers supported the format in script tags and so on, then languages like TypeScript and CoffeeScript would just compile to parse trees, and the browser would take it from there. Transpiled languages wouldn't need to do code generation, and source maps would no longer be needed either, as the lexical information would be based on the actual source.

Once the basic support was established, the standard could incrementally evolve to meet WASM in the middle, by basically just adding new node types. There are simple things to start with, like explicit add and concat nodes, or maybe adding new data types, like DEC64.

As WASM builds up to supporting scripting languages, by adding things like GC, AST execution would move downwards, extending JavaScript semantics to include features from other high level languages, so a broader set of scripting languages could compile to a kind of abstract JavaScript.

On 25 May 2017 at 02:57, Carl Smith notifications@github.com wrote:
>

There are some issues that would need addressing, but it would be
relatively simple for JavaScript engines to expose their internal support
for executing JavaScript ASTs, and the ASTs they accept should be
standardised (even if the AST is immediately converted to non-standard,
intermediate formats internally).

Only for a much broader definition of "relatively simple" than you probably
have in mind... ;)

Relative to WASM, it's simple.

@bguiz For example:

  • You cannot translate JS natively into ASM, because it has different architecture.
  • You cannot manipulate DOM from ASM, because you don't have access to it's resources at CPU ground level.

Google V8 engine already compiles the JavaScript directly to native machine code, by compiling the whole runtime task, before executing it.

So it would be totally unnecessary to have a alternative WASM pipeline from client side.

In the other hand, WASM was presented with a Mandelbrot demo, then it features Unity "Tanks" demo in the first place, but i doubt very much that drawing pixels with ASM->CPU (even with SSE double precision) could ever be faster than WebGL->GPU, because as this community says the GPU is not in the scope. So what?

@ivanherczeg Woah! Where does this community say GPU is not in spec?

@SephReed

We already have tensions due to bikeshed differences between arm and x86. I think that adding another set of hardware targets would create more tension: more operations would either have to be slow due to emulation costs to get uniform semantics on all targets, or more operations would have to have undefined behavior to allow everyone to run fast. I think that makes it unprofitable to consider the GPU at this time (or ever).

-Fil

https://github.com/WebAssembly/design/issues/273#issuecomment-123094583

C# runtime was ported to wasm and was fully functional prototype replacing JS completely. So this means in future you can expect runtimes emerging out to replace JS on browsers and write client side web apps in Java, C# or even C++ with a statement's saying "Code will run faster near native", "Compiled code are faster than VM" or anything without the aid of JavaScript.

Please watch this video of what i am trying to say.

WebASM was introduced to supplement JS not to take over completely , replacing the First class language.

Near future you can expect webpages delivered from server compiled natively

@Steakeye Very nice :) I shall have a play - many thanks for highlighting :)

you can compile JS to WebAssembly using NectarJS . Demo: http://nectar-lang.com/ choose from the dropdown WebAssembly

Interesting, the NectarJS demo uses emscripten, you can see that in the asm.js output. It appears it statically compiles JS into something - likely C or LLVM IR - and then runs that through emscripten.

The wasm output also uses emscripten (can be seen from inspecting the binary), but it seems to use an old version as it emits 0xd wasm binaries, which don't run in modern VMs. It also just sends you the wasm, not the JS, so it's not runnable anyhow. In any case, it's very possible it's just doing the same as for asm.js, just running emscripten with the flag for wasm output flipped on.

The demo has a 300 byte limit on the input, so it's hard to feed it a real-world program to get a feel for how powerful their analysis is, which is the real question with a static approach like this. In general, academic research on this topic suggests skepticism.

Their compiled demos for Windows simply crash for me 🤕

I agree with @kripken skepticism here. I believe arbitrary JS cannot be reasonably converted to WebAssembly. Any tool that claims to achieve this is probably working on some tractable subset of the JS language, or giving up execution performance.

JS is an extremely dynamic language. Unpredictable run-time operations can significantly and globally change the semantics of code. This means that an Ahead-Of-Time (or offline) compiler can only assume the worse and generate very inefficient generic code that can handle all the possible cases. For an example take the following JS code:

var a = {prop1: 1};
func(a);

could be converted (in pseudo-wasm) to this

i32.const 42
call $CreateJSValFromStrTable ;; Returns prop1
i32.const 1
call $CreateJSValFromInt
call $CreateJSObj1 ;; Consume a JS string and a JS value to make an object
call $_func

Now, this is a far call from what we can reasonably consider "compile" and it is more similar to unrolling an interpreter. It is of course also possible to run a JS interpreter compiled to Wasm, but that would hardly be a performance win.

JS engines such as V8 and Spidermonkey can run JS code as fast as they do by compiling it Just-In-Time. By doing JIT compilation they can observe what is the real intended semantics for a given piece of JS and generate fast code for that specific case, while of course being careful to detect any change in the environment that could invalidate the current assumptions.

Agreed. I wouldn't mind to use a JavaScript subset however. Or maybe a typed variant, which would probably reduce the dynamism and allow for more efficient code to be generated.

Are there any news on the "strong mode" front BTW?

@Simran-B, we have long abandoned strong mode, for the reasons summarised here. The takeaway is that it is pretty much impossible to tighten JavaScript semantics without losing interop with existing code.

For the same reason I also don't have much hope for the idea of designing a "statically compilable" dialect of JavaScript or TypeScript -- it would be a different language that can't run existing code, so not much point.

@Simran-B : "I wouldn't mind to use a JavaScript subset however. Or maybe a typed variant"

There is some very interesting work in that space, like AssemblyScript which is a strict subset of TypeScript that compiles to WebAssembly, https://github.com/AssemblyScript/assemblyscript

@rossberg : "I also don't have much hope for the idea of designing a "statically compilable" dialect of JavaScript or TypeScript -- it would be a different language that can't run existing code, so not much point."

I think the big potential with things like AssemblyScript is not about running existing code (I agree with you there, that won't be feasible in general), but that having a friendly and familiar language is a huge deal.

Right now if you are a TypeScript developer and you want to write WebAssembly then you need to use C++ or Rust. Both are good languages but also have downsides. For someone with that background, something like AssemblyScript could be the fastest path to productivity.

If AssemblyScript can compile to both JavaScript and Assembly, that would be pretty ideal. Looking forward to these updates.

Also, in the future, unless someone does it first, I'll probably try writing a TypeScript -> Assembly Script converter that goes through the files, asks the questions it needs to ask, and then makes the conversion. Hopefully it works out!

@SephReed Yes it can compile to JavaScript, because there is a WebAssembly -> asm.js compiler, which should work with all WebAssembly code.

See also the "Can WebAssembly be polyfilled?" section of the FAQ.

If you instead meant "is it possible for AssemblyScript to compile to idiomatic JavaScript code?", then I have to ask, why would you want to do that when WebAssembly / asm.js are so much faster than idiomatic JavaScript code?

Though I suppose you should be able to run the AssemblyScript code through the TypeScript compiler. However you will need to keep certain things in mind.

See also this section of the AssemblyScript documentation.

Gentlemen, please consider WALT, the JavaScript-like WebAssembly language.

UPD. Sorry for necroposting

I see a lot of people consider this "JS -> WASM" compiler a good idea.

For those who don't find it useful, like:

I'm not sure it'll be that useful from a developer's perspective, though. You may get some size reduction, but that's about it. From a browser's perspective it may be interesting to have the JS engine implemented in wasm from a pure security perspective.

Please, here's my concrete example of why it's important, and why it's useful, and not just you "get some size reduction, but that's about it". One of the features come with WebAssembly is:

<=XXX «SaNdBoXeD EnViRoNmEnT» XXX=>

WebAssembly isn't just about performance. You may see a good article about plugins from Figma team.

Making a plugin system is quite challenging. You need some good way to run custom code. You need a separate environment, a safe one.

WebAssembly gives you that, - a pure environment without mess like some global variables. AssemblyScript makes it convenient in a way, - you have almost the same TypeScript environment, as your main app's environment, which is quite cool.

But here's the problem, "almost same":

Can I use JS packages from NPM within my safe environment?

No.

Well, this WALT project is some kind of AssemblyScript alternative. It's barely JS-like, - it's typed js. It's more like TS-like. You can't compile/transpile existing js libraries with that.

Can I use TS packages from NPM within my safe environment?

No.

AssemblyScript is TS-like language too. It may compile something written in TS if it's fully covered with types. No exceptions. No any any's. But often people have their configs not strict enough or they have a few @ts-ignore, or even more often, - they write package in js and provide separate types in .d.ts files - in all these cases you won't be able to compile such a package to WASM.

@JerryGreen good points, but on the performance side of things, I actually believe it's a huge misconception that there aren't significant performance benefits beyond saving a few bytes. Folks, including benchmarks, are so obsessed with runtime performance. See how fast it runs 3D games?

Yet the real-world opportunity is actually in startup performance, which benefits virtually all websites. Few seem to talk about how WebAssembly is substantially faster in startup time (per byte), far beyond any runtime benefits. This is why for instance gzip on textual content, such as JavaScript, has little real-world impact on PLT -- it's the size of the compiled code that matters.

Ironically, the industry is obsessed about PLT (Page Load Times), and various visual complete markers, yet no one sees the correlation between WebAssembly and these vectors? JavaScript is responsible for over 30% time spent prior to these critical events, on most websites. In fact, size of pages and bandwidth have far less impact on PLT's compared to that of linear performance factors, namely JavaScript startup times and latency.

With that said, it isn't clear to me the feasibility of JS -> WebAssembly.

@JerryGreen Figma's approach is very specific case and I guess for most of projects iframes or realms are pretty enough for third-party javascript isolation. For special cases where isolation should be more controlled and performance, size and load time are not so important, you could always compile QuickJS or JavaScriptCore to WebAssembly.

You could also use Web Workers, and run code before your untrusted code that deletes any APIs you don’t want the untrusted code to have access to. No need for WASM in this case @JerryGreen!

Framerate Drops in Three js in a real thing, I am not sure if wasm could help but it sure seems so at least on the surface.

There is no reason to compile JS to wasm because you would have to also include a whole javascript vm. The resulting code would be huge and slower than the JS VM natively provided.

Couldn't we do all the monomorphisation etc that are done by JS VMs through Profile-Guided Optimization? We would pretty much just do the same thing as the JS VMs do at runtime, but ahead-of-time.

A PGO build consists of two passes: a first pass to build instrumented binaries, then a second pass to re-build optimized binaries using profile information gleaned from running the instrumented binaries.

The first run would provide us with all the type info (which functions get called with which typed-arguments etc), then we build an optimized binary with all variants a function is called with (+ generic one with dynamic args for non profiled code). We wouldn't need the whole JS VM.

PGO required great test's coverage of your program. It's not always possible. But you could trace some type information during execution in v8. See this doc: https://docs.google.com/document/d/1JY7pUCAk8gegyi6UkIdln6j_AeJqQucZg92advaMJY4/edit#heading=h.xgjl2srtytjt

We have spoken with the TypeScript team about this possibility and they have shown interest, but it seems like progress there is currently gated on adding typed objects into JS.

Don't need types

Can QuickJS really be compiled to WASM?

Yes, Figma use QuickJS for their plugin system for example

And it's used in http://numcalc.com/ too.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

dpw picture dpw  ·  3Comments

aaabbbcccddd00001111 picture aaabbbcccddd00001111  ·  3Comments

cretz picture cretz  ·  5Comments

konsoletyper picture konsoletyper  ·  6Comments

frehberg picture frehberg  ·  6Comments