From 24ea1a940a6d38487936d3b8cc303b02ff0fe01e Mon Sep 17 00:00:00 2001 From: Derek Schuff Date: Thu, 28 Sep 2017 11:31:20 -0700 Subject: [PATCH] Use WebAssembly.compileStreaming API if available (#5606) This API is a post-MVP addition (http://webassembly.org/docs/web/#additional-web-embedding-api) that does streaming compilation (i.e compiles the wasm binary as it downloads), resulting in faster instantiation in the non-cached case. --- src/preamble.js | 32 +++++++++++++++++++++++++------- tests/runner.py | 2 ++ 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/src/preamble.js b/src/preamble.js index 72a6a2ef418f..afedbd99d73f 100644 --- a/src/preamble.js +++ b/src/preamble.js @@ -2318,19 +2318,37 @@ function integrateWasmJS() { // later), so we save Module and check it later. var trueModule = Module; #endif - getBinaryPromise().then(function(binary) { - return WebAssembly.instantiate(binary, info) - }).then(function(output) { + function receiveInstantiatedSource(output) { + // 'output' is a WebAssemblyInstantiatedSource object which has both the module and instance. // receiveInstance() will swap in the exports (to Module.asm) so they can be called #if ASSERTIONS assert(Module === trueModule, 'the Module object should not be replaced during async compilation - perhaps the order of HTML elements is wrong?'); trueModule = null; #endif receiveInstance(output['instance']); - }).catch(function(reason) { - Module['printErr']('failed to asynchronously prepare wasm: ' + reason); - abort(reason); - }); + } + function instantiateArrayBuffer(receiver) { + getBinaryPromise().then(function(binary) { + return WebAssembly.instantiate(binary, info); + }).then(receiver).catch(function(reason) { + Module['printErr']('failed to asynchronously prepare wasm: ' + reason); + abort(reason); + }); + } + // Prefer streaming instantiation if available. + if (!Module['wasmBinary'] && typeof WebAssembly.instantiateStreaming === 'function') { + WebAssembly.instantiateStreaming(fetch(wasmBinaryFile, { credentials: 'same-origin' }), info) + .then(receiveInstantiatedSource) + .catch(function(reason) { + // We expect the most common failure cause to be a bad MIME type for the binary, + // in which case falling back to ArrayBuffer instantiation should work. + Module['printErr']('wasm streaming compile failed: ' + reason); + Module['printErr']('falling back to ArrayBuffer instantiation'); + instantiateArrayBuffer(receiveInstantiatedSource); + }); + } else { + instantiateArrayBuffer(receiveInstantiatedSource); + } return {}; // no exports yet; we'll fill them in later #else var instance; diff --git a/tests/runner.py b/tests/runner.py index d0022df488bb..1400c0e130d8 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -746,6 +746,8 @@ def do_GET(self): def log_request(code=0, size=0): # don't log; too noisy pass + + SimpleHTTPServer.SimpleHTTPRequestHandler.extensions_map['.wasm'] = 'application/wasm' os.chdir(dir) httpd = BaseHTTPServer.HTTPServer(('localhost', 8888), TestServerHandler) httpd.serve_forever() # test runner will kill us