Opened 8 months ago

Last modified 6 weeks ago

#7058 new change

Write WebAssembly module loader

Reported by: mjethani Assignee:
Priority: Unknown Milestone:
Module: Core Keywords:
Cc: sergz, sebastian, kzar, hfiguiere, greiner Blocked By:
Blocking: Platform: Unknown / Cross platform
Ready: no Confidential: no
Tester: Unknown Verified working: no
Review URL(s):

Description (last modified by mjethani)

Background

We would like to start moving some of our code to WebAssembly if and where possible as we run into our limits of what we can do with pure JavaScript (#7000). This would be somewhat in parallel to the Emscripten effort, but could also be seen as a way to gradually migrate to that implementation over time. In any case, the lessons learnt from the Emscripten effort would come in handy in this piecemeal migration.

The first step for doing this is to have a loader that can load a WebAssembly version of a module on platforms that support it and automatically fall back to a pure JavaScript implementation otherwise, based on a mapping somewhere. This mapping could be in the build script, for example, or it could be hardcoded into the source of the module.

These days it's easy to load a WebAssembly module using a few lines of JavaScript:

<script>
  function loadModule(path)
  {
    return fetch(`${path}.wasm`).then(response => response.arrayBuffer())
           .then(bytes => WebAssembly.instantiate(bytes))
           .then(object => object.instance.exports);
  }

  loadModule("simple").then(({add}) =>
  {
    console.log(add(1, 2)); // prints 3
  });
</script>

It would be easy to modify the above implementation to fall back to require'ing the pure JavaScript version of the module if the .wasm file is not found or if WebAssembly is not supported on the platform, while keeping it transparent to client code.

It is also trivial these days to write WebAssembly, even by hand:

;; simple.wat

(module
  (func (export "add") (param i32) (param i32) (result i32)
    get_local 0
    get_local 1
    i32.add
  )
)

This can be compiled to a WebAssembly binary using WABT:

wat2wasm -o simple.wasm simple.wat

There are higher-level languages and frameworks being built around this (e.g. Walt). The web is no longer so tightly coupled with JavaScript.

As a first step, we need a WebAssembly module loader that falls back to alternative pure JavaScript implementations based on certain criteria.

Compatibility

(What versions of Chrome, Firefox, and Edge is WebAssembly supported on? What are the details we need to know before we start work? To be filled out.)

What to change

To be determined.

Change History (16)

comment:1 Changed 8 months ago by mjethani

  • Description modified (diff)

comment:2 Changed 8 months ago by mjethani

  • Description modified (diff)

comment:3 Changed 8 months ago by mjethani

  • Cc sergz sebastian kzar hfiguiere added

comment:4 Changed 8 months ago by mjethani

  • Description modified (diff)

comment:5 Changed 8 months ago by hfiguiere

Issue #6312 is for the emscripten branch

comment:6 Changed 8 months ago by hfiguiere

Support matrix:
https://developer.mozilla.org/en-US/docs/WebAssembly

No IE, Edge 16, Chrome 57, Firefox 52

comment:7 Changed 8 months ago by mjethani

  • Blocking 7000 added

comment:8 Changed 8 months ago by hfiguiere

Also we don't need C++ to write wasm code. We can do it in Rust.

comment:9 follow-up: Changed 8 months ago by mjethani

Based on the little that I know about Rust, I would very much prefer it over C++.

comment:10 in reply to: ↑ 9 ; follow-up: Changed 8 months ago by mjethani

Replying to mjethani:

Based on the little that I know about Rust, I would very much prefer it over C++.

Seriously though, there are two things we would have to consider:

  1. Skills: Do we have the skills in the team? Anybody can write a "Hello world" program in Rust, but it takes a long time to master a language. In order to get the best out of it, one really must grok it. We have some very skilled C++ programmers on the team with lots of experience.
  2. Performance: If we're going to adopt WebAssembly as a target for performance reasons, we should try to get the best tradeoff between performance and maintainability. The question is whether Rust can be compiled to WebAssembly bytecode as optimally as C++.

comment:11 in reply to: ↑ 10 Changed 8 months ago by hfiguiere

Replying to mjethani:

The question is whether Rust can be compiled to WebAssembly bytecode as optimally as C++.

Yes.

comment:12 Changed 8 months ago by mjethani

This will actually have to be part of buildtools. We will need a custom webpack loader that loads the WebAssembly version of a given module if it's available and fall back on the JavaScript version otherwise. The WebAssembly binary would be included in the generated lib/adblockplus.js by the build script as a byte array.

We need to work out the details.

comment:13 Changed 8 months ago by hfiguiere

I think we could start by doing it for the emscripten branch, and then we can move that patch to the main branch when needed/wanted.

comment:14 Changed 8 months ago by mjethani

  • Blocking 7000 removed

comment:15 Changed 4 months ago by greiner

  • Cc greiner added

comment:16 Changed 6 weeks ago by Himanshu0709

Last edited 6 weeks ago by kzar (previous) (diff)
Note: See TracTickets for help on using tickets.