Injected WASM Module is not an instance of "WebAssembly.Module"


Is there any reason why the injected module is not an instance of “WebAssembly.Module”, why module instanceof WebAssembly.Module returns false despite being a compiled module?

If this was the case, we wouldn’t have to edit the glue code generated by wasm-bindgen to validate this condition (here: (The module is instantiated without error when we replace path_or_module instanceof WebAssembly.Module by true).


The problem here is that it is an instance of WebAssembly.Module, but from a different JavaScript context.

You can see the same thing in a browser using iframes. If you have a page with an iframe whose URL is at the same origin, then the iframe and parent frame are allowed to reach into each other’s JavaScript contexts and exchange objects. But, each context has its own “copy” of all the builtins, including types. For example, the Element type in the iframe is not the same as the Element type in the parent frame. This bizarrely means, for example, that “iframe.contentDocument.body instanceof Element” returns false!

The same thing is happening here. The Workers runtime compiles the WebAsssembly module in a different context from the one that actually executes requests. The reason for this has to do with Cloudflare Apps: When the same app is installed on multiple web sites, we only want to compile the app (and any WebAssembly modules) once. But, we want to make sure the app can’t accidentally leak data between web sites. So, we run each web site in a different context, within the same V8 isolate.

Unfortunately, this means that we cannot make our WebAssembly modules be instanceof WebAssembly.Module, because we’d have to decide which context’s module it should be an instance of, and then it wouldn’t work in any of the other contexts.

Instead, to fix the problem, we need to fix wasm-bindgen to be more compatible with Workers.

The good news is there’s going to be a lot more movement on this soon, because: