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

Request: Add portable ESM build target #676

Closed
Jamesernator opened this issue Jul 12, 2019 · 4 comments
Closed

Request: Add portable ESM build target #676

Jamesernator opened this issue Jul 12, 2019 · 4 comments

Comments

@Jamesernator
Copy link

💡 Feature description

Currently there's 3 main build targets all that require different platforms, however there is no module target that is platform independent.

I'd like to propose adding a new target --target module that generates an ESM module similar to web but does not include any web specific things like fetch/Request/etc that make it unportable to Node (once it supports ESM) or other environments in future.

In order to be as environment independent as possible I would propose outputting a module that imports no other modules (so that it doesn't tie down to specifier dependency) and also only rely on ecma262 builtin functions + WebAssembly globals.

In order to do this I would propose that this target would output a file similar to the current --target web but would instead of fetching the module itself in init it could instead just be passed a WebAssembly.Module directly and then the init function could then use the WebAssembly.instantiate function to instantiate it.

💻 Basic example

Using such a module from the browser:

import init, { method1, method2 } from './file.js';

async function main() {
  const response = await fetch('./file_bg.wasm')
  await init(await WebAssembly.compileStreaming(response))

  method1('blah')
}

Or using such a module in Node (under experimental modules):

import init, { method1, method2 } from './file.js'

async function main() {
  const module = await WebAssembly.compile(await fs.promises.readFile('./file_bg.wasm'))
  await init(module)

  method1('blah')
}
@fitzgen
Copy link
Member

fitzgen commented Jul 12, 2019

Sort of related is the idea of --target all which would generate a package that is portable, but would generate a copy for each different target rather than a single js glue file that supports everything.

#313

@ibaryshnikov
Copy link
Member

I did some research, and found a surprising thing: it works almost as is with --target web
@Jamesernator everything as in your example, except you can't do import init from 'file.js' in node, you should use .mjs extension. Having both main.mjs and pkg/file.mjs, I ran

node --experimental-modules main.mjs

and got ReferenceError: Request is not defined
Ok, I went to file.mjs and changed

if (module instanceof URL || typeof module === 'string' || module instanceof Request) {

to

if (module instanceof URL || typeof module === 'string') {

and it worked!
I didn't even have to remove const response = fetch(module); from the file.mjs!

So we almost have this feature... almost, because of .mjs stuff

@Jamesernator
Copy link
Author

Jamesernator commented Aug 21, 2019

except you can't do import init from 'file.js' in node, you should use .mjs extension.

Actually importing .js in Node is supported via the new package.json "type" field: https://nodejs.org/api/esm.html#esm_code_package_json_code_code_type_code_field

Regardless a portable module doesn't even necessarily need to know anything about that, it just needs to have some source text with the right exports.


If module instanceof Request is the only thing preventing the output being portable then could the output just be changed to?:

if (typeof module === 'string'
/* Node supports URL but not all hosts necessarily will e.g. XS */
|| typeof URL !== 'undefined' && module instanceof URL
|| typeof Request !== 'undefined' && module instanceof Request) {

@alexcrichton
Copy link
Contributor

@Jamesernator I think that module instanceof Request is now expanded basically as you mentioned in the most recent version of wasm-bindgen

I think that means that this is actually fixed, so I'm going to close this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants