Skip to content

Fix loading wasm in electron by falling back to XHR #12921

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

Merged
merged 16 commits into from
Jan 6, 2021
Merged
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,7 @@ a license to everyone to use it as detailed in LICENSE.)
* Jean-Sébastien Nadeau <[email protected]> (copyright owned by Foundry Interactive Inc.)
* Wouter van Oortmerssen <[email protected]> (copyright owned by Google, LLC)
* Alexey Sokolov <[email protected]> (copyright owned by Google, LLC)
* Lukas Rieger <[email protected]>
* Ivan Romanovski <[email protected]>
* Max Brunsfeld <[email protected]>
* Basil Fierz <[email protected]>
Expand Down
39 changes: 27 additions & 12 deletions src/preamble.js
Original file line number Diff line number Diff line change
Expand Up @@ -767,23 +767,38 @@ function getBinary(file) {
}

function getBinaryPromise() {
// If we don't have the binary yet, and have the Fetch api, use that;
// in some environments, like Electron's render process, Fetch api may be present, but have a different context than expected, let's only use it on the Web
if (!wasmBinary && (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) && typeof fetch === 'function'
// If we don't have the binary yet, try to to load it asynchronously.
// Fetch has some additional restrictions over XHR, like it can't be used on a file:// url.
// See https://github.com/github/fetch/pull/92#issuecomment-140665932
// Cordova or Electron apps are typically loaded from a file:// url.
// So use fetch if it is available and the url is not a file, otherwise fall back to XHR.
if (!wasmBinary && (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER)) {
if (typeof fetch === 'function'
#if ENVIRONMENT_MAY_BE_WEBVIEW
// Let's not use fetch to get objects over file:// as it's most likely Cordova which doesn't support fetch for file://
&& !isFileURI(wasmBinaryFile)
#endif
) {
return fetch(wasmBinaryFile, { credentials: 'same-origin' }).then(function(response) {
if (!response['ok']) {
throw "failed to load wasm binary file at '" + wasmBinaryFile + "'";
) {
return fetch(wasmBinaryFile, { credentials: 'same-origin' }).then(function(response) {
if (!response['ok']) {
throw "failed to load wasm binary file at '" + wasmBinaryFile + "'";
}
return response['arrayBuffer']();
}).catch(function () {
return getBinary(wasmBinaryFile);
});
}
#if ENVIRONMENT_MAY_BE_WEBVIEW
else {
if (readAsync) {
// fetch is not available or url is file => try XHR (readAsync uses XHR internally)
return new Promise(function(resolve, reject) {
readAsync(wasmBinaryFile, function(response) { resolve(new Uint8Array(/** @type{!ArrayBuffer} */(response))) }, reject)
});
}
return response['arrayBuffer']();
}).catch(function () {
return getBinary(wasmBinaryFile);
});
}
#endif
}

// Otherwise, getBinary should be able to get it synchronously
return Promise.resolve().then(function() { return getBinary(wasmBinaryFile); });
}
Expand Down
8 changes: 4 additions & 4 deletions src/web_or_worker_shell_read.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* SPDX-License-Identifier: MIT
*/

read_ = function shell_read(url) {
read_ = function(url) {
#if SUPPORT_BASE64_EMBEDDING
try {
#endif
Expand All @@ -24,7 +24,7 @@
};

if (ENVIRONMENT_IS_WORKER) {
readBinary = function readBinary(url) {
readBinary = function(url) {
#if SUPPORT_BASE64_EMBEDDING
try {
#endif
Expand All @@ -45,11 +45,11 @@
};
}

readAsync = function readAsync(url, onload, onerror) {
readAsync = function(url, onload, onerror) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'arraybuffer';
xhr.onload = function xhr_onload() {
xhr.onload = function() {
if (xhr.status == 200 || (xhr.status == 0 && xhr.response)) { // file URLs can return 0
onload(xhr.response);
return;
Expand Down
2 changes: 1 addition & 1 deletion tests/test_other.py
Original file line number Diff line number Diff line change
Expand Up @@ -8780,7 +8780,7 @@ def test(args):
# Changing this option to [] should decrease code size.
self.assertLess(changed, normal)
# Check an absolute code size as well, with some slack.
self.assertLess(abs(changed - 5627), 150)
self.assertLess(abs(changed - 5872), 150)

def test_llvm_includes(self):
create_test_file('atomics.c', '#include <stdatomic.h>')
Expand Down