Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

esm: --experimental-wasm-modules integration support #27659

Closed
wants to merge 1 commit into from

Conversation

@guybedford
Copy link
Contributor

commented May 12, 2019

This PR provides support for node --experimental-modules --experimental-wasm-modules to support the ES module integration of WebAssembly modules through eg import './module.wasm'.

The semantics match the proposed ES module integration semantics for Web Assembly as specified in https://github.com/webassembly/esm-integration.

At the previous modules group meeting we got consensus approval for upstreaming this feature under the --experimental-wasm-modules flag.

//cc @nodejs/modules

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • tests and/or benchmarks are included
  • documentation is changed or added
  • commit message follows commit guidelines
@nodejs-github-bot

This comment has been minimized.

@littledan
Copy link

left a comment

Note that this is slightly different than the standards track semantics, as it doesn't take a turn on the event loop during Instantiation. However, I don't expect this to affect most programs. I would also encourage you to write several more tests before landing.

const exports = WebAssembly.Module.exports(compiled).map(({ name }) => name);

return createDynamicModule(imports, exports, url, (reflect) => {
const { exports } = new WebAssembly.Instance(compiled, reflect.imports);

This comment has been minimized.

Copy link
@littledan

littledan May 12, 2019

In a cycle-closing edge, will reflect.imports usually be an empty object? If so, this will be basically the right semantics.

This comment has been minimized.

Copy link
@guybedford

guybedford May 12, 2019

Author Contributor

On the unexecuted cycle edge, reflect.imports would contain all the imported module namespaces, with their named exports, but all of those named exports would be undefined. Function exports would be supported in cycles here though just like ES modules.

This comment has been minimized.

Copy link
@guybedford

guybedford May 12, 2019

Author Contributor

Actually cycles would throw for any accesses to uninitialized let bindings on the namespaces, since these would be in TDZ.

This comment has been minimized.

Copy link
@guybedford

guybedford May 12, 2019

Author Contributor

To summarize:

  • Unexecuted cycle edge with function exports: fine - function is defined
  • Unexecuted cycle edge with let binding: throws - TDZ error

This comment has been minimized.

Copy link
@guybedford

guybedford May 12, 2019

Author Contributor

And specifically these errors are only thrown if the WASM module actually attempts to access the given binding.

This comment has been minimized.

Copy link
@littledan

littledan May 12, 2019

Right, so in particular, Wasm exports should always act like const bindings, and all imports are accessed during Instantiate (in the ESM evaluate phase). Does this implementation do that?

This comment has been minimized.

Copy link
@devsnek

devsnek May 12, 2019

Member

yep! reflect.imports is namespace objects so the imports are accessed directly.

@devsnek
Copy link
Member

left a comment

please upload a wat source for simple.wasm with a comment in the top with the command used to produce simple.wasm

example: https://github.com/nodejs/node/blob/master/test/fixtures/shared-memory.wat

@ljharb
Copy link
Contributor

left a comment

  • How might one have an entry point that's directly in wasm, without the need for an ESM wrapper?
  • how might one consume wasm modules in CJS?
@devsnek

This comment has been minimized.

Copy link
Member

commented May 12, 2019

@ljharb

How might one have an entry point that's directly in wasm, without the need for an ESM wrapper?

declare a wasm start function in your wasm module

this reminds me, @guybedford can you make a test which verifies that start functions run at the correct time?

how might one consume wasm modules in CJS?

at the moment, import()

@ljharb

This comment has been minimized.

Copy link
Contributor

commented May 12, 2019

@devsnek so node somethingWithStart.wasm will work?

I'll rephrase the question - how might one synchronously consume wasm modules in cjs?

@devsnek

This comment has been minimized.

Copy link
Member

commented May 12, 2019

@ljharb

so node somethingWithStart.wasm will work?

yes

how might one synchronously consume wasm modules in cjs

not possible atm. if require(esm) happens that would work i guess.

@guybedford guybedford requested a review from devsnek May 12, 2019

@targos

targos approved these changes May 12, 2019

Show resolved Hide resolved doc/api/esm.md Outdated
Show resolved Hide resolved src/node_options.cc
@devsnek
Copy link
Member

left a comment

actually... can you add a test that verifies that the wasm start function runs during the evaluate phase? in wat, you can specify it with (start $funcname)

@guybedford guybedford requested a review from devsnek May 12, 2019

@guybedford

This comment has been minimized.

Copy link
Contributor Author

commented May 12, 2019

Sure, I've added a start function test.

@MylesBorins
Copy link
Member

left a comment

LGTM

CommonJS loader. Additional formats such as _"wasm"_ or _"addon"_ can be
extended in future updates.
CommonJS loader. Additional formats such as _"addon"_ can be extended in future
updates.

This comment has been minimized.

Copy link
@Trott

Trott May 13, 2019

Member

There's one additional mention of the non-existent --entry-type CLI flag 7 lines below this one. Is this the right PR to remove or update that material?

@xtuc

xtuc approved these changes May 14, 2019

Copy link
Member

left a comment

Nice work @guybedford!

Show resolved Hide resolved doc/api/esm.md Outdated
Show resolved Hide resolved doc/api/esm.md Outdated

@guybedford guybedford force-pushed the guybedford:wasm-modules branch from 0353cbc to acbf59a May 16, 2019

@nodejs-github-bot

This comment has been minimized.

@guybedford

This comment has been minimized.

Copy link
Contributor Author

commented May 17, 2019

Landed in bbc254d.

@guybedford guybedford closed this May 17, 2019

guybedford added a commit that referenced this pull request May 17, 2019

esm: --experimental-wasm-modules integration support
PR-URL: #27659
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Myles Borins <myles.borins@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>

targos added a commit that referenced this pull request May 17, 2019

esm: --experimental-wasm-modules integration support
PR-URL: #27659
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Myles Borins <myles.borins@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>

@BridgeAR BridgeAR referenced this pull request May 21, 2019

Merged

v12.3.0 proposal #27799

4 of 4 tasks complete

@targos targos added the semver-minor label May 21, 2019

BridgeAR added a commit that referenced this pull request May 21, 2019

2019-05-21, Version 12.3.0 (Current)
Notable changes:

* esm:
  * Added the `--experimental-wasm-modules` flag to support
    WebAssembly modules (Myles Borins & Guy Bedford)
    #27659
* process:
  * Log errors using `util.inspect` in case of fatal exceptions
    (Ruben Bridgewater) #27243
* repl:
  * Add `process.on('uncaughtException')` support (Ruben Bridgewater)
    #27151
* stream:
  * Implemented `Readable.from` async iterator utility (Guy Bedford)
    #27660
* tls:
  * Expose built-in root certificates (Ben Noordhuis)
    #26415
  * Support `net.Server` options (Luigi Pinca)
    #27665
  * Expose `keylog` event on TLSSocket (Alba Mendez)
    #27654
* worker:
  * Added the ability to unshift messages from the `MessagePort`
    (Anna Henningsen) #27294

PR-URL: #27799

BridgeAR added a commit that referenced this pull request May 21, 2019

2019-05-21, Version 12.3.0 (Current)
Notable changes:

* esm:
  * Added the `--experimental-wasm-modules` flag to support
    WebAssembly modules (Myles Borins & Guy Bedford)
    #27659
* process:
  * Log errors using `util.inspect` in case of fatal exceptions
    (Ruben Bridgewater) #27243
* repl:
  * Add `process.on('uncaughtException')` support (Ruben Bridgewater)
    #27151
* stream:
  * Implemented `Readable.from` async iterator utility (Guy Bedford)
    #27660
* tls:
  * Expose built-in root certificates (Ben Noordhuis)
    #26415
  * Support `net.Server` options (Luigi Pinca)
    #27665
  * Expose `keylog` event on TLSSocket (Alba Mendez)
    #27654
* worker:
  * Added the ability to unshift messages from the `MessagePort`
    (Anna Henningsen) #27294

PR-URL: #27799
@vitaly-t

This comment has been minimized.

Copy link
Contributor

commented May 22, 2019

Ahem, very interesting! 😄

Any guidelines or examples on how to start playing with it in Node.js?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.