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

TextDecoder sometimes fails when used through an iframe #15217

Open
wffurr opened this issue Oct 4, 2021 · 5 comments · May be fixed by #16994
Open

TextDecoder sometimes fails when used through an iframe #15217

wffurr opened this issue Oct 4, 2021 · 5 comments · May be fixed by #16994

Comments

@wffurr
Copy link
Contributor

wffurr commented Oct 4, 2021

String types via embind sometimes fail with:

Failed to execute 'decode' on 'TextDecoder': The provided ArrayBufferView value must not be shared."

When the embind functions are called through an iframe. The instanceof check in TextDecoderWrapper fails when the object is from an iframe, which is a separate JavaScript realm.

This is a known problem with instanceof checks and iframes:

https://www.oreilly.com/library/view/speaking-javascript/9781449365028/ch17.html#cross-realm_instanceof
https://jakearchibald.com/2017/arrays-symbols-realms/#multiple-realms
https://esdiscuss.org/topic/cross-global-instanceof

For built-ins, the only real workaround is checking foo.constructor.name -> ArrayBuffer or Object.getPrototypeOf(foo).toString() -> [object ArrayBuffer].

This should work in all WebAssembly-supporting browsers.

@wffurr
Copy link
Contributor Author

wffurr commented Oct 4, 2021

Here's a short example of how this works.

In the iframe's code, e.g. iframe.js:

var emscriptenBinary = require('./my_emscripten_binary.js');
emscriptenBinary().then(instance => {
  window.foo = new (instance.Foo)();  // initialize some embind type
  window.parent.postMessage({type: 'ready'}, '*');
});

In the parent window's code, e.g. app.js:

window.addEventListener('message', messageEvent => {
  if (messageEvent.type === 'ready') {
    const result = window.frames[0].foo.frob();  // Call an embind function that returns a string.
  }
});

Note how the parent window calls into a function in an object on the iframe's window. All instanceof checks in that call will fail because they will be checking against the prototype objects in the parent window's realm, not the iframe's.

The other advice in the O'Reilly book on handling this is to just not make cross-realm calls. I think we can make Emscripten robust against this though.

@wffurr
Copy link
Contributor Author

wffurr commented Oct 4, 2021

Note this can be worked around at a performance hit (especially for large strings) with -s TEXTDECODER=0 compilation option.

@jiulongw
Copy link
Contributor

jiulongw commented May 20, 2022

I hit the same problem in a different context.

When pthread is enabled, and a tab is duplicated (Chrome, right click tab -> Duplicate), somehow the buffer sent from wasm (via embind) is actually a SAB but instanceof SharedArrayBuffer returns false. It causes a shared buffer being sent to TextDecoder and triggers this exact same exception.

@kripken
Copy link
Member

kripken commented May 20, 2022

@jiulongw Does "duplicate tab" not just open a new tab with the same URL? Or does it involve an iframe somehow?

If it does not involve an iframe then it sounds like a browser bug, and we should file a bug on Chrome. Also we can file a bug if we are not sure either way.

@jiulongw
Copy link
Contributor

I feel duplicating a tab is not simply a new tab with same URL. It carries some sort of state or context from the tab being duplicated.

I will try to repro it without involving Emscripten and open a bug to Chromium.

Either way, this patch might still be useful for people hitting this issue, given Symbol.toStringTag is supported by major browsers, and faster than instanceof.

IsaMorphic added a commit to IsaMorphic/runtime-wasmfix that referenced this issue May 23, 2023
…ffer from different JavaScript realm

When performing tasks such as allocating or marshalling large amounts of memory in multithreaded .NET land, inconsistent and frequent crashing behavior is exhibited. 

Related issues: 
emscripten-core/emscripten#15217
https://github.com/dotnet/aspnetcore/issues/48390
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants