
The security model of WebAssembly - jbaviat
https://webassembly.org/docs/security/
======
wyldfire
For some reason I assumed this might include specifics about spectre
mitigations.

Heading off on that tangent: the mitigation for browsers was to turn off the
time reference or to downsample the resolution, right? What if they do the
work to sync up with a remote reference clock? Including characterization of
the channel's jitter/RTT/all that cleverness? Could they have high enough
precision to deduce speculative execution? Or were there other mitigations
that I'm not recalling?

(apologies for the tangent, none of this post is wasm specific)

~~~
uluyol
Chrome is now using more processes to leverage OS-level spectre protections. I
think they will re-enable high precision timers.

Source: [https://security.googleblog.com/2018/07/mitigating-
spectre-w...](https://security.googleblog.com/2018/07/mitigating-spectre-with-
site-isolation.html)

------
sillysaurus3
One interesting aspect of webassembly is that it's feasible to do some
advanced program-specific architectures.

Consider a website whose img src references are not actually strings, but
instead are pointers to memory addresses. Your application works like this:
When you attempt to dereference the pointer, a page fault fires, which causes
the underlying system to load the image from the server. When the loading is
complete, your program resumes.

Big deal. But this opens up another interesting avenue: It's very easy to
return a _different_ image while you're waiting for the original to load.
Meaning there is no async/await -- no waiting at all. You just write code in
the natural, blocking way. No callback hell or promise chains.

There are other interesting applications of this too. When you dereference the
pointer to the image, you know the user's viewport size. Meaning you know how
large the image should be. Therefore the underlying system can automatically
request a perfectly-sized image from the server -- or have the server
construct it on the fly, then stream it to the client.

You never have to deal with any of this complexity yourself.

The most important area where this type of design is applicable is gaming. You
want to stream the exact texture miplevels you need, at an ~infinite level of
detail. If you approach a wall, you want to see lots of high resolution wall
textures. But when you move away from the wall, that texture data should be
freed. The above architecture handles this type of concern automatically.

~~~
sbjs
I really don’t see how any of this isn’t already possible in JS? It can be
done cleanly to. Take your first example:

    
    
        img.src = placeholderFor(viewport);
        loadRealImage().then(src => img.src = src);
        // carry on

~~~
sillysaurus3
Now, what do you do when you want to return from that function after
loadRealImage() finishes?

    
    
      function loadImage(src) {
        loadRealImage(src).then(img => /*... return img from loadImage ...?*/);
      }
    
    

"Just make it an async function." Well yes, but then the async nature
contaminates the rest of your code. You have to make sure to set up a toplevel
try-catch for every one of your async chains, for example.

What do you do when you want to have an async generator? That is, you want to
both await on something, and yield N values from the function. JS makes that
difficult.

There are all kinds of limitations like this, and everyone has their own
favorite hacks around them. But they're hacks, not unification. And yes, hacks
can be effective, but a unified framework can be tactical.

~~~
sbjs
So... to solve this... you want to use what's basically goto?

~~~
sillysaurus3
In this case, I'd like to write blocking-style code.

 _longjmp_ , however, is a crucial missing facility in JS. Emacs relies on it
heavily in its design -- it's how catch / throw work, and it's why you can do
things like

    
    
       (catch 'foo
        (map (fn (x)
               (if (= x 42) (throw 'foo x)))
          values))
    

Without longjmp, you can't do that. Just as you can't in JS.

So what? Well, that means you can't _write emacs_ , because you're limited to
what JS provides you. An entire class of software is beyond your ability to
write, because you cannot provide the same features that other runtimes give.

This gets me started on the lack of any kind of reasonable error definitions
in JS. In elisp, you define errors. Imagine you want to write some code that
parses some parens -- it turns "(a b (c))" into ["a", "b", ["c"]]. What do you
do when your program encounters "(a b" and then the end of the string? Throw a
scan error!

Not in JS. It's considered poor manners to throw errors to the people using
your library. Worse, it's a pain in the ass for users to catch and respond to
errors. If you use someone's library, you usually don't expect to have to wrap
it in a try-catch. And the code is massive:

try { operation } catch (e) { if (e instanceof ScanError) { do something else
} }

Contrast that with elisp:

    
    
      (condition-case nil
        operation
        (scan-error do something else))
    

There's no contest. It's way easier to write the latter than to use the tools
JS gives you. But it's a cultural difference, and culture is slow to change.

That's why webassembly at least gives an escape hatch.

~~~
millstone
> Well, that means you can't write emacs, because you're limited to what JS
> provides you

Well JS does provide this via exceptions.

Second it's totally crazy that emacs depends on longjmp, which is an insane
decades-old wart that ought to just quietly die.

Third...does web assembly even support longjmp? I'm pretty sure it does not.

> That's why webassembly at least gives an escape hatch.

Escape hatch from...writing five lines instead of three?

~~~
sillysaurus3

      function foo() {
        return doSomething();
      }
    
      async function doSomething() {
        ...
        throw ScanError();
      }
    

Spot the bug? That's an async function. Every JS programmer worth their salt
will tell you how many times they've been annoyed to discover a missing await,
and that the promise is failing mostly-silently (or worse, it works by
accident until it doesn't, since that code will work fine most of the time).

 _Well JS does provide this via exceptions._

 _Second it 's totally crazy that emacs depends on longjmp_

It's not crazy.

    
    
      function bar() {
        [1,2,3].forEach(x => {
          if (x == 2) /* return from bar...? */
        }
      }
    

Why can't you write this code? I mean you "can":

    
    
      function bar() {
        let tag = [];
        try {
          [1,2,3].forEach(x => {
            if (x == 2) { tag.value = x; throw tag; }
          }
        } catch (e) {
          if (e === tag) {
            return e.value;
          }
      }
    
    

But holy crap that's terrible. EDIT: I also forgot to rethrow the error,
showing just how easy it is to screw up.

Just write it as a for loop, then. Well sure, except for the hundreds of
libraries that don't support that style. What do you do when you want to
return prematurely from the iterator functions you pass to them? Now you can't
just make a for loop unless they provide Symbol.iterator. And 9 times out of
10 they give you a promise, meaning you're forced to convert your code to
async style.

It's a huge mess, and longjmp saves you a lot of headaches in disciplined
situations. Every tool has its place, and it's strange to argue that a
computer should be able to do _less_ , not more.

The goal is to save you time in the long run. And those 5 lines better be
exactly right, or you'll waste a lot.

~~~
gear54rus
just use one of myriad array methods available, like "find" for this case

"can't write some class of software" is just wrong, is all

