
Hello wasm-pack - steveklabnik
https://hacks.mozilla.org/2018/04/hello-wasm-pack/
======
axefrog
Does anyone have a good sense of the current performance impact of crossing
the boundary between JS and WASM? I've often thought it'd be great to be able
to expose high-performance data structures (and other infrastructure-level
stuff) via WASM and then make use of them from JavaScript, but I seem to
recall that the interop performance cost is currently too high to make it
worth doing, which leaves WASM mainly only useful for long-running tasks, such
as game engines, expensive graph layout algorithms and so forth.

 __Edit: __[https://hacks.mozilla.org/2018/04/javascript-to-rust-and-
bac...](https://hacks.mozilla.org/2018/04/javascript-to-rust-and-back-again-a-
wasm-bindgen-tale/)

> "The wasm-bindgen code generation has been designed with the future host
> bindings proposal in mind from day 1. _As soon as that’s a feature available
> in WebAssembly_ , we’ll be able to directly invoke imported functions
> without any of wasm-bindgen‘s JS shims. Furthermore, this will allow JS
> engines to aggressively optimize WebAssembly manipulating the DOM as
> invocations are well-typed and no longer need the argument validation checks
> that calls from JS need. At that point wasm-bindgen will not only make it
> easy to work with richer types like strings, but it will also provide best-
> in-class DOM manipulation performance."

~~~
titzer
The cost is more than a JS->JS call, but not drastically so. Every argument
must be converted from a number to an int32/float32/float64, which for SMI
values is a single branch, for heap numbers a branch and a load. For other JS
values, a ValueOf() operation on the JS value.

V8 generates little wrappers for these, with inline conversions. It does not
currently inline the little wrapper functions, nor use ICs for the conversions
inside, since branches are generally enough to get the interesting fast cases.

The idea of a super-expensive call is therefore a bit of a myth. You can try
to measure the cost yourself, but be careful! Most microbenchmarks will end up
comparing the difference between an inlined JS call (as low as zero overhead)
versus a non-inlined WASM->JS or JS->WASM call. The proper comparison would be
instead with a non-inlined JS->JS call. Defeating inlining for JS->JS calls is
tricky. You can do it with cross-realm calls, or by trying manipulating
polymorphism. In either case, it's pretty tricky, so good luck.

~~~
girvo
For v8, doesn’t a try/catch block defeat inlining? It used to, but that was a
long time ago.

~~~
titzer
No, not with TurboFan (since Q2 2017).

------
mpolichette
I cant help but think of the post about stealing password credentials from the
site you build by surreptitiously inserting extra code into the published NPM
package. Except wasm packages seem like they'd be even harder to detect.

[https://hackernoon.com/im-harvesting-credit-card-numbers-
and...](https://hackernoon.com/im-harvesting-credit-card-numbers-and-
passwords-from-your-site-here-s-how-9a8cb347c5b5)

~~~
eridius
Since wasm (currently) requires js to interact with the DOM, you could still
read the js code to see if it's passing any sensitive data into wasm.

~~~
mattnewton
Js code is sufficiently dynamic where I wouldn’t be confident in anyone using
this defense, even with a debugger open.

~~~
eridius
The complaint here is that moving from js to wasm means you can't tell if a
package is maliciously exfiltrating your sensitive data. That presupposes that
you can read and understand the js code. If your argument here is that you
can't be confident in your ability to read and understand the js code, then
moving to wasm is no longer a problem.

~~~
mattnewton
That’s probably true, but I do think that the addition of wasm complicated
things. Imagine a js bridge that calls window objects by strings built in the
wasm blob, or does anytning using eval. Now the wasm code can call anything js
can through this bridge.

~~~
eridius
I suppose that's true, but you can also tell that the JS is trying to
obfuscate what it's doing and just generally distrust it at that point.

------
themihai
>> the goal of WebAssembly is not to replace JavaScript, but to be an awesome
tool to use with JavaScript.

Let's hope exactly the other way around will happen. I would rather like to
see better interop between different languages using wasm than wasm + js.

~~~
austincheney
I think that misses the point. Since WASM is a compile target you don't need
JS to achieve interop between different languages if they are all compiled to
WASM. The JS + WASM combo is to do things that WASM container cannot do on its
own.

~~~
fulafel
Also, JS is a more suitable target for most managed languages like clojure,
typescript, elm, etc.

~~~
themihai
Well... two of 3 of the languages you provided as example were designed to be
transpiled to javascript. I doubt JS is a more suitable target for other
languages than an IR like wasm which is being designed to be a compiler
target.

~~~
fulafel
I would be interested in hearing a more detailed argument on why ClojureScript
& Elm would be better if they targeted WebAssembly.

Even the WebAssembly authors seem to agree that it's not foremost a managed
language compile target - The Overview text from
[http://webassembly.org/](http://webassembly.org/) says "Wasm is designed as a
portable target for compilation of high-level languages like C/C++/Rust,
enabling deployment on the web for client and server applications."

~~~
themihai
Elm was designed to be transpiled into javascript just like CoffeScript so
let's put it aside for a moment. WASM is work in progress so I'm sure that if
people care enough they can find solutions for such specific issues(i.e. seems
that VM languages have their own set of issues). There is a GC proposal so
managed languages will benefit a lot(i.e. smaller runtime).

JS is a high level language. I don't see many people compiling to managed
languages outside of the browser. Wonder why is that? Few target JVM...but I
don't see many(if any) compiling to Java, C#, Ruby or Lua or PHP. I've never
seen anyone compiling JavaScript either unless they had to run it in a
browser. This should tell you how good JS is when it has to compete on merit
as compiler target.

~~~
fulafel
Elm semantics is very far from JS - it's a kind of Haskell-lite. The tooling
and diagnostics are very much custom and don't rely on JS developer tools or
source maps. (Also, "transpile" is just another word for "compile")

~~~
themihai
Do you mean that Elm was not designed considering JS as its compilation
target? Is Elm used anywhere else than the web browser? Why nobody compiles to
JS outside the web browser if it's such a good compilation target?

>> Also, "transpile" is just another word for "compile"

Well, I prefer to use the "transpile" term when the target is a high level
language.

JavaScript is a high level language. It seems some smart folks decided that a
new "language/IR" is needed (wasm) so that people can use other languages on
the web. Now let's make this new IR a first class citizen on the web.

~~~
fulafel
I'm sure Elm design considered JS, but I'm also sure that if WebAssembly had
been available when Elm was designed, it would still have targeted JS rather
than WebAssembly. Same goes for ClojureScript.

WebAssembly is a refinement of asm.js, which started as a mechnism to enable
C/C++ code to run in browsers. Other, managed languages aren't forced to go
the asm.js route because their semantics aren't tightly married to a byte
addressable, untyped program heap.

~~~
themihai
What exactly makes JavaScript a better target for languages such Elm (apart
from GC and DOM access which are supposed to be implemented sooner or later) ?
You realise that JavaScript itself is also compiled/transpiled by the browser
engine(i.e. v8) before it executes, right?

~~~
fulafel
Let me count the ways:

\- code size - a runtime for a managed language is much bigger if you have to
reimplement & ship the primitives you get from the JS platform.

\- implementation complexity: a LLVM-webassembly-toolchain along with your own
GC is much harder and more work than a JS backend, and would need to have a
rather good payoff to be worth investing in.

\- poor cross-browser development tooling support to have a good debugging
experience

\- GC implementation complexity and performance - firstly, there is no GC
support currently and no timeline about when/if something materalizes. The
current "future GC" support in webassembly[1] doesn't provide a GC
implemnetation, just hooks to peacefully coexist with JS GC.

\- JS interop

\- browser support

Now, it may be that some of these get solved eventually - but they would all
have to be solved, with high quality solutions, to beat JS as a managed
language compile target.

[1] [https://github.com/WebAssembly/reference-
types/blob/master/p...](https://github.com/WebAssembly/reference-
types/blob/master/proposals/reference-types/Overview.md)

~~~
themihai
>> \- implementation complexity: a LLVM-webassembly-toolchain along with your
own GC is much harder and more work than a JS backend, and would need to have
a rather good payoff to be worth investing in.

I strongly disagree. Wonder why no language(managed or unmanaged languages)
designer uses this gem named JavaScript as compile target?(web stuff excluded)

It seems your whole argument revolves around the fact that JS has better
support than WASM in browser. We already know this. WASM is a work in
progress. It's not ready yet for prime time. This year we will get some
managed languages compiled to WASM. Next year we might get GC. I believe in
some distant future javascript will be compiled to wasm either by the client
or by the browser itself(for backward compatibility). JavaScript is JIT-ed in
the browser anyway.

------
alex_duf
I'm dreaming of seeing a wasm DOM api that directly binds to the browser's
apis, without passing through javascript.

Is this even a possibility?

~~~
plurgid
when we can make web pages, and entire sites without once actually using
something a human can disassemble and reverse engineer ... this will be the
end of the open web.

truly the complete dead end of it.

Unless maybe I'm missing something. Is a disassembler for WASM a thing yet?

~~~
jchw
I've tried to read source code from YouTube and let me tell you:

If that kills it, it was already dead. Obfuscation and minification is already
as bad as bytecode. Honestly, wasm might be a little _better_ because there
are less insane hacks and more simple, if low level, code.

Also, if people are willing to implement DRM in it just because it's bytecode,
I'd rather they did that than implemented rootkits in all of the browsers.
Thanks for that one W3C.

------
m_st
It's great to see WASM taking off! In this context, see also Blazor, which
runs C#/.NET code on WASM.
[https://github.com/aspnet/blazor](https://github.com/aspnet/blazor)

~~~
steveklabnik
What’s the binary size like?

One interesting thing about wasm is the difference between libraries and apps;
Rust’s small binary size here can make it useful for this infrastructure work,
but for languages that need to bring along the runtime, it’s much more
complex. This is one reason why we’re pursuing stuff like wasm-pack.

I’m glad to see more and more languages compiling to wasm though! Exciting
times.

~~~
wvenable
The original Blazer was based on the DotNetAnywhere runtime and the binary
size was actually very reasonable.

Now that they're using the Mono runtime it's significantly larger and it seems
their main task now is finding ways to remove unused code from that runtime to
get it back to reasonable.

~~~
yougane
The original runtime was about 60kb in size, that's still unreasonable to add
to a library. Imagine a small library like Redux (2kb, including dependencies)
having to ship with a runtime that's 60kb (or more). Now imagine a project
that depends on multiple libraries of the same size or larger... This is why a
language that has no runtime (such as Rust) makes more sense for developing
wasm packages that can be used side-by-side with other languages.

~~~
Dayshine
>The original runtime was about 60kb in size, that's still unreasonable to add
to a library

What? What kind of bubble are you working in?

~~~
yougane
Web applications nowadays depend on hundreds of dependencies. If each one of
these dependencies were to have a size of 60kb or more that would be very bad.

------
gramstrong
This is great. Wasm really seems to be picking up steam. Any examples of a
Rust crate that has already been published to the npm registry?

~~~
steveklabnik
Ashley and I ran a workshop at BoosterConf a monthish ago using this tooling,
a bunch of people used it to publish demo packages. This is effectively a
release announcement, so we don’t have anything super real yet that I know of.
There’s some stuff in the works though.

(You can see those here: [https://www.npmjs.com/search?q=hello-
wasm](https://www.npmjs.com/search?q=hello-wasm))

------
ridiculous_fish
In its wasm-rewrite, the source-map module acquired a destructor that must be
manually invoked by its clients [1]. This makes the API much worse. Is this
typical of JS APIs that use wasm?

1: [https://github.com/mozilla/source-
map#sourcemapconsumerproto...](https://github.com/mozilla/source-
map#sourcemapconsumerprototypedestroy)

~~~
arcatek
Yes, the gc isn't exposed yet, so neither JS nor wasm are notified when an
object goes out of scope (which would allow to reclaim the memory on the wasm
side). It's on the roadmap, so it should eventually come.

------
K0nserv
It's been really exiciting to follow all the awesome work that Mozilla and the
Rust team are doing in this area. I'm looking forward to this bright new Rust
WASM future for sure!

------
ndarilek
Does any of this tooling (I.e. wasm-pack, wasm-bindgen) work with the
wasm32-unknown-emscripten target? All of the examples I see use
wasm32-unknown-unknown, which is (I think) of limited use to me since I'm
linking a fairly complex chain of native libraries against my current wasm
target.

It seems like cargo-web has lots of this ground covered already. I'm wondering
why build these other tools in that case? I don't have a dog in this fight,
I'm just working on a wasm-based app that I'm hoping will serve me for quite
some time, and seeing what appears to be duplicated effort at such an early
stage worries me a bit.

Either way, thanks for building this!

~~~
steveklabnik
We’re focusing on the unknown target for basically all future work; this stuff
_can_ work with the emacripten target, but it might take some PRs to configure
it, etc. We’d be open to people hacking on such a thing, but it’s not where
the team is putting in any effort.

~~~
ndarilek
Got it. I assume the unknown target will never be able to link against native
libraries beyond those provided by Rust's core itself? I assume the answer is
no, but a few years ago I assumed I wouldn't ever be able to do what wasm is
letting me now, so I don't want to hold too tightly to those assumptions. :)

~~~
steveklabnik
By “native libraries” you mean “C libraries”?

If so, then that’s correct, as rustc can’t compile C code. You need a C ->
wasm compiler, and that’s emscripten.

Hopefully we’ll have built the ecosystem enough that you won’t need to rely on
those libraries :)

~~~
mwcampbell
Unless I'm misunderstanding, this sounds like a mistake to me. On any other
platform, Rust interoperates smoothly with C libraries and does not demand
purity. There's lots of existing code written in C, and expecting all of it to
be replaced with pure Rust libraries is unrealistic.

Also, doesn't clang also have a wasm backend now? Emscripten isn't the only
option.

~~~
steveklabnik
It's because this is all a _little_ more complex than that.

Clang does have a wasm backend, same as the unknown target. It suffers the
same problems; that is, one of the things that emscripten does is provide a
runtime/support code that does things like "automatically translate opengl to
webgl". That is, one of emscripten's major goals is "get code that was never
assumed to be able to run on the web to run on the web with as little hassle
as possible." Outside of the web, those C libraries were very much intended to
work on the native platform. So there's extra complexity there.

We continue to support emscripten for when you need this use-case, but it
effectively only works if you're building an application, not a library, and
we want to support people writing libraries.

------
k__
Are there any benchmarks comparing WASM with Neon on Node.js?

~~~
steveklabnik
Generally should be faster, it we haven’t made benchmarks. Lots of wasm is
client side, Neon is server side. Wasm on the server is coming along too. It’s
probably something worth putting together!

~~~
k__
ah so it isnt in node yet?

~~~
steveklabnik
It is! It’s in the latest LTS even. But in my understanding, it hasn’t been a
focus of node, and so sometimes stuff breaks, etc. It’ll get there! Certainly
exciting as well.

------
jnordwick
I'm kind of curious how wasm is going to work out. It seems only logical that
wasm interpreters will be optimizing JITs. Wasm will essentially be an
intermediate language similar to JVM bytecode.

At that point why not just use the JVM stripped of the useless stuff as a base
and add the remaining small pieces that might be needed. Or Graal.

I guess I don't understand what Wasm is doing that is so much different that
couldn't be handled with other more advanced code bases.

~~~
Rusky
> It seems only logical that wasm interpreters will be optimizing JITs.

Webassembly was designed _not_ to do this, and I really hope it stays that way
forever. Optimizing JITs are useful for highly dynamic languages like
Javascript; Webassembly's fast startup times and predictable performance are a
much better solution for languages like Rust.

> I guess I don't understand what Wasm is doing that is so much different that
> couldn't be handled with other more advanced code bases.

On top of "the vast majority of the optimization is done ahead of time so
there's no need for a JIT," there's also the memory model. Webassembly exposes
memory as a big array of bytes for you to manage yourself, just like hardware.
The JVM enforces a particular object model with classes, inheritance, and
garbage collection.

So I guess what I'm saying is that "the JVM stripped of all the useless stuff"
is what Webassembly is already. And some of the stuff that got stripped is the
JIT and object model.

~~~
jashmatthews
> Webassembly was designed not to do this, and I really hope it stays that way
> forever. Optimizing JITs are useful for highly dynamic languages like
> Javascript; Webassembly's fast startup times and predictable performance are
> a much better solution for languages like Rust.

WebAssembly is a VM bytecode for a stack-based VM. Unless you want things to
run very, very slowly you still need a JIT to emit native code, rather than
loop dispatching each WebAssembly instruction in a bytecode interpreter.

WebKit, for example, has a two-tier JIT for WebAssembly just like JS, but
WebAssembly has already had all the high level language related optimizations
performed and looks a bit like an intermediate representation anyway so the
first pass is very fast.

~~~
jnordwick
So that means wasm has already been inlined and loops unrolled? How will this
all interact with vectorization or insurrection choice?

I think the VM is going to need to be just like every other VM (once inlining
is introduced, why even bother with trying to optimize wasm before the JIT).

If wasm is going to be so good, then you could retart java to it? I know a lot
of high performance java shops that would love to get rid of the GC in Java.
But Hotspot can be an optimizing beast.

~~~
Rusky
You can't get rid of GC in Java without essentially replacing Java.

------
chuckdries
Can you use JS packages as dependencies?

~~~
steveklabnik
From the article:

> The next large piece of development work on wasm-pack will focus on using
> custom segments in compiled WebAssembly to declare dependencies on local
> Javascript files or other npm packages.

> The preliminary work for this feature has already landed in wasm-bindgen, so
> the next step will be integrating it into wasm-pack.

------
jlebrech
"WebAssembly is not to replace JavaScript, but to be an awesome tool to use
with JavaScript."

NO, Replace Javascript, replace HTML, replace CSS.

------
digi_owl
So, yet another single purpose package manager. FFS...

~~~
steveklabnik
This isn’t a package manager. It’s tooling to create npm packages.

