diff --git a/src/polyfill/fetch.js b/src/polyfill/fetch.js new file mode 100644 index 0000000000000..979335699a84e --- /dev/null +++ b/src/polyfill/fetch.js @@ -0,0 +1,80 @@ +// Fetch polyfill from https://github.com/developit/unfetch +// License: +//============================================================================== +// Copyright (c) 2017 Jason Miller +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +//============================================================================== + +#if !POLYFILL +#error "this file should never be included unless POLYFILL is set" +#endif + +if (typeof globalThis.fetch == 'undefined') { + globalThis.fetch = function (url, options) { + options = options || {}; + return new Promise((resolve, reject) => { + const request = new XMLHttpRequest(); + const keys = []; + const headers = {}; + + request.responseType = 'arraybuffer'; + + const response = () => ({ + ok: ((request.status / 100) | 0) == 2, // 200-299 + statusText: request.statusText, + status: request.status, + url: request.responseURL, + text: () => Promise.resolve(request.responseText), + json: () => Promise.resolve(request.responseText).then(JSON.parse), + blob: () => Promise.resolve(new Blob([request.response])), + arrayBuffer: () => Promise.resolve(request.response), + clone: response, + headers: { + keys: () => keys, + entries: () => keys.map((n) => [n, request.getResponseHeader(n)]), + get: (n) => request.getResponseHeader(n), + has: (n) => request.getResponseHeader(n) != null, + }, + }); + + request.open(options.method || "get", url, true); + + request.onload = () => { + request + .getAllResponseHeaders() + .toLowerCase() + .replace(/^(.+?):/gm, (m, key) => { + headers[key] || keys.push((headers[key] = key)); + }); + resolve(response()); + }; + + request.onerror = reject; + + request.withCredentials = options.credentials == "include"; + + for (const i in options.headers) { + request.setRequestHeader(i, options.headers[i]); + } + + request.send(options.body || null); + }); + } +} diff --git a/src/shell.js b/src/shell.js index add93992b4960..e0e99753c067c 100644 --- a/src/shell.js +++ b/src/shell.js @@ -61,6 +61,11 @@ var Module = typeof {{{ EXPORT_NAME }}} != 'undefined' ? {{{ EXPORT_NAME }}} : { // See https://caniuse.com/mdn-javascript_builtins_bigint64array #include "polyfill/bigint64array.js" #endif + +#if MIN_CHROME_VERSION < 40 || MIN_FIREFOX_VERSION < 39 || MIN_SAFARI_VERSION < 103000 +// See https://caniuse.com/fetch +#include "polyfill/fetch.js" +#endif #endif // POLYFILL #if MODULARIZE diff --git a/src/web_or_worker_shell_read.js b/src/web_or_worker_shell_read.js index 3ae5842e8f298..7bdf9868761cd 100644 --- a/src/web_or_worker_shell_read.js +++ b/src/web_or_worker_shell_read.js @@ -22,17 +22,12 @@ } readAsync = (url, onload, onerror) => { - var xhr = new XMLHttpRequest(); - xhr.open('GET', url, true); - xhr.responseType = 'arraybuffer'; - xhr.onload = () => { - if (xhr.status == 200 || (xhr.status == 0 && xhr.response)) { // file URLs can return 0 - onload(xhr.response); - return; + fetch(url) + .then(response => { + if(response.ok) { + return response.arrayBuffer(); } - onerror(); - }; - xhr.onerror = onerror; - xhr.send(null); - } - + return Promise.reject(new Error(response.statusText + ' : ' + response.url)); + }) + .then(onload, onerror) + }; diff --git a/test/common.py b/test/common.py index c19be77f01e00..a342524e42d30 100644 --- a/test/common.py +++ b/test/common.py @@ -2270,7 +2270,7 @@ def compile_btest(self, filename, args, reporting=Reporting.FULL): if reporting == Reporting.FULL: # If C reporting (i.e. the REPORT_RESULT macro) is required we # also include report_result.c and force-include report_result.h - self.run_process([EMCC, '-c', '-I' + TEST_ROOT, + self.run_process([EMCC, '-c', '-fPIC', '-I' + TEST_ROOT, '-DEMTEST_PORT_NUMBER=%d' % self.port, test_file('report_result.c')] + self.get_emcc_args(compile_only=True)) args += ['report_result.o', '-include', test_file('report_result.h')] diff --git a/test/other/test_unoptimized_code_size_no_asserts.js.size b/test/other/test_unoptimized_code_size_no_asserts.js.size index 587cc797c2641..6a0a9c8c4c3ff 100644 --- a/test/other/test_unoptimized_code_size_no_asserts.js.size +++ b/test/other/test_unoptimized_code_size_no_asserts.js.size @@ -1 +1 @@ -31420 +31418 diff --git a/test/test_browser.py b/test/test_browser.py index 957883dbe17cb..2164e15e821c9 100644 --- a/test/test_browser.py +++ b/test/test_browser.py @@ -699,7 +699,8 @@ def setup(assetLocalization):