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

Adding Response based versions of validate, compile, and instantiate. #991

Merged
merged 1 commit into from
Feb 24, 2017

Conversation

flagxor
Copy link
Member

@flagxor flagxor commented Feb 17, 2017

This allows us to support streaming compilation and origin bound
sources for WebAssembly modules.

Proposes a mime type of application/wasm for WebAssembly modules.

@rossberg
Copy link
Member

rossberg commented Feb 17, 2017

Can we make these separate functions instead of overloading further? Moreover, I think we need to separate Web-specific extensions from the "general" JS API spec.

@flagxor
Copy link
Member Author

flagxor commented Feb 17, 2017

Agree on the overloads.
What do you and others think of:
downloadAndCompile
downloadAndValidate
downloadAndInstantiate

Should we separate into separate file (or clean up Web.md) or just a section in this one?

@rossberg
Copy link
Member

Names sound okay to me. Even though less convenient, I'd have a slight preference for a separate file, since technically, it is a separate spec (a supplement) -- I'm thinking of it in analogy to the DOM supplementing the ES lib on the web.

JS.md Outdated

```
Boolean validate(BufferSource bytes)

Boolean validate(Response source)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, since this is a synchronous method (it returns a Boolean), how can it take a Response? Should it instead create a Promise? In that case, I think it should not be an overload, but a separate function.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

validate is only useful for feature testing, so I'm not sure it's worth adding a whole Response overload and Promise type for this. I don't think anyone should be calling validate on a whole codebase. Furthermore, validation, unlike compilation, is crazy fast.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, hadn't thought of it until making the PR, will remove.

@titzer
Copy link

titzer commented Feb 17, 2017

Agree with @rossberg-chromium that these things are specific to a Web embedding and should probably move to their own .md file.

@lukewagner
Copy link
Member

Separate functions and files sound fine. Not to bikeshed, though, but "download" sounds a bit off. What about the more literal names compileResponse/instantiateResponse?

@lukewagner
Copy link
Member

Actually, could these go in Web.md?

@flagxor flagxor force-pushed the response branch 2 times, most recently from ef02af5 to 1816863 Compare February 17, 2017 17:52
@flagxor
Copy link
Member Author

flagxor commented Feb 17, 2017

Moved and renamed.
PTAL

Web.md Outdated
@@ -22,6 +22,82 @@ and retrieve compiled modules from offline storage, instantiate compiled modules
with JavaScript imports, call the exported functions of instantiated modules,
alias the exported memory of instantiated modules, etc.

In addition to the core JavaScript API, the Web embedding includes additional
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You have an "additional" "addition" in this sentence.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops, fixed.

Web.md Outdated

Promise<{module:WebAssembly.Module, instance:WebAssembly.Instance}>
instantiateResponse(Promise<Response> source [, importObject])
```
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does one use instantiateResponse with an importObject that contains a WebAssembly.Memory from another instantiateResponse? i.e. create multiple instances which share a memory, using the response APIs.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You'd need to Promise-chain them; but I think this is already the case with instantiate. To avoid the sequential dependency, one would want to instead create the memory/table up front (via their JS constructor) and pass them simultaneously into N instantiateResponse calls.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It'd like to see what the code looks like, and have folks such as @domenic and @slightlyoff chime in.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would think you'd either in this case want the memory to be external, or if you wanted it to originate from another module, you'd have to first instantiate that module (i.e. like a libc).
That does have the unfortunate property of serializing things.
The current instantiate method has this same issue, though or am I missing something?
I suppose we could also accept multiple modules bound to one internal memory, but at that point I wonder if we wouldn't be better off sorting out ES6 modules (as they should have a similar behavior).

Copy link
Member

@lukewagner lukewagner Feb 17, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sequential:

instantiateResponse(fetch(urlA)).then(resultsA =>
  instantiateResponse(fetch(urlB), resultsA.instance.exports).then(resultsB =>
    ...
  )
);

Parallel:

var imports = { libc: {
  mem: new WebAssembly.Memory(...),
  tbl: new WebAssembly.Table(...)
} };
Promise.all([
  instantiateResponse(fetch(urlA), imports),
  instantiateResponse(fetch(urlB), imports)
]).then(([resultsA, resultsB]) =>
  ...
);

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that only works if you don't need to import exports between A and B.
In that case you can build a web of promises that serialize things as little as possible, but you wouldn't be able to get maximum concurrency on the compiles.
If there's dependency chains like that, then you can do better if you use the two-step compile instantiate (as you can get all the compiles going in parallel, download already are).

That's no worse that with the non-response versions of these APIs.

We could try to fix that also, but as I said before its probably better to do that with ES6 modules.
If we did it for the one-step instantiate methods, it would probably end up requiring a declarative way to describe all the hookups (which seems to re-do a lot of the ideas from the ES6 modules space).

Copy link
Member

@lukewagner lukewagner Feb 17, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed.

If we did it for the one-step instantiate methods, it would probably end up requiring a declarative way to describe all the hookups (which seems to re-do a lot of the ideas from the ES6 modules space).

IIUC, there is a JS function to dynamically load an ES6 module proposed now (I forget the name). With wasm modules integrated with ES6 modules, that would basically give us this one-step capability.

Web.md Outdated

The `Response` or `Promise<Response>` is used as the source of the
bytes to compile.
WebAssembly `source` data is expected to have a mime type of `application/wasm`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/mime/MIME/ here and elsewhere.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

application/wasm sounds reasonable. In the current <script type="module"> pipeline, we have a restriction that the MIME type of the response should be one of JS MIME type. This is great since we can choose the different way to produce different modules (JS v.s. WASM modules) based on the MIME type of the given Response.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done
And good point.

@jfbastien
Copy link
Member

I think this comment contains an important design point:

How does one use instantiateResponse with an importObject that contains a WebAssembly.Memory from another instantiateResponse? i.e. create multiple instances which share a memory, using the response APIs.

I'm worried that the proposed API only allows us to use response for a single .wasm, but not to combine multiple .wasm that'll share a memory (or, later, more than just a memory).

Do you think that's an important usecase, and that this API should get it right from the beginning?

Web.md Outdated
```
Promise<WebAssembly.Module> compileResponse(Response source)

Promise<WebAssembly.Module> compileResponse(Promise<Response> source)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How this works on the web is that the first step of the algorithm wraps whatever it gets in a promise, then unwraps the promise before continuing. I'm not sure how that translates to the notation you're using here (TypeScript??) but it should be noted in the algorithm. In Web IDL it's just Promise<Response> source as the argument, and then any incoming argument gets converted by the Web IDL bindings.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds better. Changed.

Web.md Outdated
Other mime types
[reject](http://tc39.github.io/ecma262/#sec-rejectpromise) the Promise with a
`WebAssembly.CompileError`.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should mention that the returned promise is rejected with a TypeError if the incoming value, after unwrapping, is not a Response.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@flagxor
Copy link
Member Author

flagxor commented Feb 17, 2017

PTAL

Web.md Outdated
`WebAssembly.CompileError`.

The `Promise<Response>` is used as the source of the bytes to compile.
WebAssembly `source` data is expected to have a MIME type of `application/wasm`.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather see this as application/webassembly for symmetry with JavaScript, which is application/javascript, not application/js.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, but never abbreviated.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have a strong opinion here except to note that many other mimetypes abbreviate: https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Complete_list_of_MIME_types

@ghost
Copy link

ghost commented Feb 18, 2017

@flagxor Thank you for exploring the space.

This allows us to support streaming compilation and origin bound sources for WebAssembly modules.

Great to see some effort to address this space of the design.

It is not clear (to me anyway) that this meets the needs of resource planning and caching. I understand that the web browser could cache the source data, but it is not clear if that caching will work well if there is a streaming translation stage?

The compiler might cache all the input stream, and use that as a key, but that seems a huge burden.

What would you think about having a build file, or Makefile of sorts, and that being the input:

Promise<{module:WebAssembly.Module, instance:WebAssembly.Instance}> build(makefile [, importDescriptor])

The makefile could be text or json, whatever suits people, and would describe the steps required to get the app running, and in a way that allows the web browser to schedule the fetches and to schedule linear memory allocation and to cache parts of the compilation work. Perhaps it could even launch multiple threads all using the same linear memory, and thus be able to optimize for that if that was a significant matter for the web browser. This could also include provision for a custom translation stage.

I believe that your proposal could be used to implement parts of such a build process, but that a web browser could do much better with the description than your proposal could ever do. Also, should the build file prove to be a dead end then it might be a small matter to create a polyfill for it.

Perhaps part of the problem with Responses is that they have no version or provenance. Can the compiler even trust that the stream is from a URL with a name and version without any modification?

For caching to be effective the web browser needs keys, and if it can use named sources with versions and data flow based on these as keys then it is a lot better off than having to use the data at each stage as a key.

@jfbastien
Copy link
Member

jfbastien commented Feb 18, 2017

Continuing on this comment, IIUC:

  • Sharing a WebAssembly.Memory seems OK as long as the WebAssembly.Memory is instantiated explicitly, not through the module's memory section.
  • This API doesn't allow us to instantiate two WebAssembly.Modules where one imports the other's functions, unless we serialize manually.
  • We'll get something based on ES6 modules that'll allow non-blocking instantiation where imports are shared (even cyclic?) and can even be WebAssembly ↔ JavaScript seamlessly.

Is the intent then to have:

  1. Blocking APIs for WebAssembly (already in).
  2. Non-blocking promise APIs for WebAssembly (already in).
  3. Non-blocking promise+response APIs for WebAssembly (this proposal).
  4. ES6 APIs for WebAssembly, shared with JavaScript (later).

?

@ghost
Copy link

ghost commented Feb 18, 2017

While looking at the potential of ES6 modules, I see references to a Loader, and find pages such as the following https://whatwg.github.io/loader/#request-translate and https://gist.github.com/dherman/7568080 which includes discussion of setting up a pipeline and includes a source-to-source translation stage. This all sounds much closer to what might be needed.

I also note that the ES6 Modules feature static definitions, but they appear to be just top level forms in a JS file, and ES6 Modules alone do not appear to have what we need, rather we already have imports and exports, and simply adding a require value might give us all that ES6 Modules offer and that does not seem enough to address the issues?

I also see a lot of uses of Promises, but Promises do not appear to be static descriptions (is that right?), so they do not seem to be the appropriate way to express the loader.

Perhaps we need a static description of the loader and need to extend the ideas to meet the specific needs of wasm, so to be able to define a binary-to-wasm translation stage (rather than source-to-source), and to work with the constraints imposed by the linear memory. Edit: and it needs to work well with caching so to support useful cache keys.

Would @dherman be willing and able to help on the state of the Loader?

@annevk
Copy link
Member

annevk commented Feb 18, 2017

I realize this is not the formal language, but I wanted to point out some things with respect to MIME types that would be good to have clarified for implementations and tests:

  1. It would be good to define extraction in terms of https://fetch.spec.whatwg.org/#concept-header-extract-mime-type.
  2. It would be good to state whether MIME type parameters need to be ignored or if their presence leads to failure.
  3. If you decide on failure, make sure to test application/wasm;, which would then technically have to fail if I remember correctly.

It would also be good to point out an opaque filtered response leads to failure as you don't explicitly define yet how you extract the data out of a response. (I.e., cross-origin without CORS won't work.)

@lukewagner
Copy link
Member

@jfbastien That matches my understanding. I found the proposal, currently Stage 3, for the dynamic import I mentioned above. So if we made application/wasm-MIME-typed modules loaded by the ES6 module loader Just Work, I think the cases you're talking about would ride along for free.

@jfbastien
Copy link
Member

@lukewagner

@jfbastien That matches my understanding. I found the proposal, currently Stage 3, for the dynamic import I mentioned above. So if we made application/wasm-MIME-typed modules loaded by the ES6 module loader Just Work, I think the cases you're talking about would ride along for free.

OK, so the ES6 module loader API will Just Work for WebAssembly, and be strictly more powerful than this proposal? What would its timing look like, compared to this proposal?

@domenic maybe?

@domenic
Copy link
Member

domenic commented Feb 20, 2017

I'm not sure what I'm supposed to be commenting on, exactly? It seems definitely false that a Response based version is less powerful than an import()-based one; for example, you can create synthetic streaming Responses easily, whereas without a service worker there is no such ability for import(). import() also has no ability to pass in a custom WebAssembly.Memory, or separate out instantiation and evaluation.

@jfbastien
Copy link
Member

@domenic

I'm not sure what I'm supposed to be commenting on, exactly? It seems definitely false that a Response based version is less powerful than an import()-based one; for example, you can create synthetic streaming Responses easily, whereas without a service worker there is no such ability for import(). import() also has no ability to pass in a custom WebAssembly.Memory, or separate out instantiation and evaluation.

Basically: I want to understand the four JavaScript APIs we're proposing for WebAssembly, and listed here. I want a list of features each offers.

From my summary it sounds like Response is missing features compared to import(), you're saying import() is also not offering all the features of Response. That's fine! My point is: we're designing APIs without a clear picture of what each offers. Let's make a little table, one row per feature and one column per JS API, and agree that's the table we want users to see on MDN.

@flagxor flagxor requested a review from kripken February 24, 2017 00:32
Copy link
Member

@kripken kripken left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bear in mind I don't know much about the Fetch API and Responses. But if I understand correctly, this adds new APIs with the ability to do a wasm compile/instantiate from a URL or a stream, etc.?

If so that sounds fine for Emscripten, we don't have any significant limitations on how the wasm is created (now that we support async compilation). We could pass the URL of the wasm to the proper API, etc., very easily.

@jfbastien
Copy link
Member

@kripken specifically: I'd like to understand whether Emscripten can use this Response API for dynamic linking of wasm modules, where one module imports another's exports.

@kripken
Copy link
Member

kripken commented Feb 24, 2017

@jfbastien I don't see anything specific to Emscripten or these Response versions here, so probably I'm missing something. But the constraint has to be that if module A imports module B's exports, then B must be fully loaded&compiled before A does so. Given these APIs, it seems we could either

  1. Fire off an instantiate for B and a compile for A. When both complete, we can use the exports from B and module from A to make an instance of A using B's exports.
  2. Fire off an instantiate for B. When that completes, fire off an instantiate for A using the exports from B.

Are you asking if 1 and/or 2 are possible with Emscripten? Both should be.

@jfbastien
Copy link
Member

@kripken yup that sounds right. I'd rather check because I was surprised last time with the promise API being more complex to use for Emscripten than I'd envisioned.

I'm not sure an importObect promise would make sense to break this sequencing (or importObject containing some promises which are checked after compilation). We can always add that as an overload later if it makes sense.

@annevk
Copy link
Member

annevk commented Feb 24, 2017

Final ping for #991 (comment).

@dschuff
Copy link
Member

dschuff commented Feb 24, 2017

As @kripken said, I think we could do dynamic linking with async using the same mechanisms we have now. Currently Emscripten also supports emulation of dlopen() which of course is synchronous, so there's probably no good way around that.

@jfbastien
Copy link
Member

As @kripken said, I think we could do dynamic linking with async using the same mechanisms we have now. Currently Emscripten also supports emulation of dlopen() which of course is synchronous, so there's probably no good way around that.

I agree it can be done. I'm asking if this is a good API for it, if Emscripten would use it, and if the API could be better suited to that purpose.

It sounds like a resounding "meh" so far. Given that the Response API is probably useful for non-Emscripten uses as well, I expect that Emscripten just isn't a good client. Maybe it would be one if the importObject could somehow be obtained asynchronously (promise or whatever stream combination mechanism). It's not clear that's necessary now, and IIUC it can be added as a simple overload later.

@annevk
Copy link
Member

annevk commented Feb 24, 2017

@jfbastien Response objects are a stream mechanism...

@dschuff
Copy link
Member

dschuff commented Feb 24, 2017

@annevk I think he's referring to a the importObject argument to instantiate, not the source argument. I do think a promise for an importObject or some other async way to get that might be useful, but I agree it doesn't have to be now.

@flagxor
Copy link
Member Author

flagxor commented Feb 24, 2017

@annevk Sorry missed your comment earlier. I've just added verbiage I believe addresses those points, please confirm. I figure strict seems better in this context, as there's a single format.

@flagxor
Copy link
Member Author

flagxor commented Feb 24, 2017

@jfbastien If I grok your concern correctly, you're pointing out that properly compiling and instantiating a collection of modules with complex dependencies while ensuring minimum latency and full asynchrony will require a very verbose pile of promise laden JS?

I think this is true. But such collections of modules will at this point be the product of something like Emscripten, which will no doubt have the plumbing to do it well. Such modules are also likely to have a complex internal contract between them anyhow. We might be able to make the set up less verbose by accepting promise in a few more places as Derek suggests, but I suspect it will only help some (as those promises won't have simple sources).

I think ultimately an asynchronous dynamic loader is a complex beast and making the API more ergonomic for this won't help as much as ensuring it has all the raw low-level rope.
There aren't likely to be a huge number of these. We'll probably end up with the one for C++ baked into Emscripten (I suppose it already is), maybe others for Rust etc, and then later a polyfill for wasm ES6 modules might.
The languages that need a more ELF like loader might all be able to share, but maybe not, as that also comes with other ABI issues.

I suppose it's a little sad that the recipe for C++ style dynamic loading won't be small, but then again even nacl's "simple" nmf manifests for dynamic loading required a bunch of tooling in practice to get right.

I'm hopeful that if we make wise choices for ES6 modules we'll get something super-pithy there, which seems like what you'd want if you're mixing in tiny wasm modules with JS code.

@annevk
Copy link
Member

annevk commented Feb 24, 2017

@flagxor thanks, that seems good enough for now.

@jfbastien
Copy link
Member

jfbastien commented Feb 24, 2017

@annevk as @dschuff said, I'm talking about APIs such as these:

Promise<{module:WebAssembly.Module, instance:WebAssembly.Instance}>
  instantiate(Response source [, importObject])

Promise<{module:WebAssembly.Module, instance:WebAssembly.Instance}>
  instantiate(Promise<Response> source [, importObject])

The optional importObect is very important to dynamic linking, and isn't a stream. Here's the most basic dynamic linking usecase:

  • Create an object of JavaScript "syscalls" which WebAssembly code calls to (draw to canvas, touch the DOM, etc) with syscalls = { log: console.log, draw: (x, y) => { /* something... */ }
  • Create mem = WebAssembly.Memory(...)
  • Instantiate a module with i0 = WebAssembly.instantiate(myResponse, { myImports: { memory: mem}, syscalls: syscalls })
  • Instantiate another module which will share the same memory, and be able to call functions exported by i0 with i1 = WebAssembly.instantiate(myOtherResponse, { myImports: { memory: mem }, importsFromI0: i0, syscalls: syscalls }).

This serializes the response handling. Compilation of i1 cannot start before that of i0 completes.

It seems weird to me to add a Response API, yet not handle this case up front, because the entire point is to handle streams and my example shows how it doesn't for what I think is a common usecase. We can add an overload later, it's not an MVP API so the overload may ship at the same time as this Response API.


@flagxor

@jfbastien If I grok your concern correctly, you're pointing out that properly compiling and instantiating a collection of modules with complex dependencies while ensuring minimum latency and full asynchrony will require a very verbose pile of promise laden JS?

No. My point isn't the amount of code. In my example above, there's a serialization which the API makes necessary but which doesn't need to exist for user code to work correctly. My concern is that we've designed a stream API which blocks for a (likely) common usecase, and it doesn't need to be that way.

I'm hopeful that if we make wise choices for ES6 modules we'll get something super-pithy there, which seems like what you'd want if you're mixing in tiny wasm modules with JS code.

Putting our hopes on ES6 modules seems fraught with peril given the comments in this thread. I'd love to, I've already implemented it that way in JSC, but I'm much less confident that's a foregone conclusion given this discussion.

@flagxor
Copy link
Member Author

flagxor commented Feb 24, 2017

@jfbastien
So it's true that a bare instantiate that takes a Response won't be able to handle these hook-ups (without serializing). You'd have to use the explicit compilation method to get maximum parallelism.

m0 = WebAssembly.compile(myResponse);
m1 = WebAssembly.compile(myOtherResponse);

(Then later promise chained in fun ways):
i0 = WebAssembly.instantiate(m0, { myImports: { memory: mem}, syscalls: syscalls });
i1 = WebAssembly.instantiate(m1, { myImports: { memory: mem }, importsFromI0: i0, syscalls: syscalls });

I suppose if you used the MIME type to aggressively hint the need to compile, you'd do nearly as well.

I don't think any simple change to importObjects will let you just use plain instantiate for complex dynamic linking cases, since you have to express all the ways you might extract an export from an instance.
My suspicion is that you either end up effectively duplicating our compile/instantiate split, or end up doing the same thing, but under a declarative veneer (and maybe missing cases you'd want to support).

I suppose this is somewhat at odds with instantiate(fetch(url)) being the "recommended" pattern.

Maybe I'm still not groking your core concern?

@jfbastien
Copy link
Member

jfbastien commented Feb 24, 2017

@flagxor that's correct. Because of this, I'm worried that we're back to advocating for the API that we had prior to #838. We'd really like WebAssembly.instantiate to be what people use because then our engines know at compilation time the amount of memory that'll be used, and which memory will be used.

If developers use something else than WebAssembly.instantiate then we have to use heuristics, or do gymnastics to try to peephole common usecases in the wild. It's not impossible, but has pitfalls and is kinda silly to force upon ourselves when we could avoid it.

This API is a much more minor case of #838. I think Emscripten could be careful at emitting code with this API, and then we'd be OK w.r.t. double-compilation. It's then only a question of tons of JS as you stated above. It seems silly to design this API with minimizing the risk of #838, and minimizing the amount of code Emscripten needs to emit (and what hand-coders need to write).

What I'd like is for folks familiar with Response / streams to help design a solution which addresses this as well (basically, an API which makes stream combination possible for WebAsembly). If they think this can be done on top of the currently proposed Response API then I'm good with it. I like the high-level bits of the Response API.

@lukewagner
Copy link
Member

lukewagner commented Feb 24, 2017

This is already a limitation of the existing WebAssembly.instantiate APIs. I think to allow these complex instantiation graphs (Response overload or not), we'd need to add a more powerful API that let you pass a map of modules to instantiate that could reference each other:

WebAssembly.instantiateGroup({a:fetch(urlA), b:fetch(urlB), otherImports:importObject})

With this, the module at urlA could import the foo export of the module at urlB by importing from "b" "foo". (Whether we allow cycles is an orthogonal question; we could limit to DAGs initially.)

(I actually had a TODO in JS.md (that I later removed) to add an API just like this to allow instantiating whole cyclic batches of modules at the same time.)

But, as I said, this is a more complicated API and thus it makes sense to have the simple version here for the simple case.

@jfbastien
Copy link
Member

jfbastien commented Feb 24, 2017

What @lukewagner says sounds good to me. As long as we go back to a multi-stream API for importObject akin to what he sketched, then I'm OK with this going in. Just file an issue and assign the right person to it.

Maybe we should start updating our github milestones, and find another marker than 🦄!

@flagxor
Copy link
Member Author

flagxor commented Feb 24, 2017

Agreed, API Luke suggests sounds close.
Opened this, which we should sort out soon:
#997

@jfbastien
Copy link
Member

jfbastien commented Feb 24, 2017

Great, thanks @flagxor . Can you mark this Response API as post-MVP (so developers don't get mislead, and know that they have to feature-test for it)? After that I'm good to go, commit this, iterate on #997.

This allows us to support streaming compilation and origin bound
sources for WebAssembly modules.

Proposes a mime type of application/wasm for WebAssembly modules.
@flagxor
Copy link
Member Author

flagxor commented Feb 24, 2017

Added, PTAL

@jfbastien
Copy link
Member

Update LGTM, let's merge this and continue in #997.

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

Successfully merging this pull request may close these issues.