add side-by-side wasm support based on async modules

type: "webassembly/async-experimental"
remove i64 importing limitation since it will have BigInt integration eventually
update wasm example
This commit is contained in:
Tobias Koppers 2019-05-24 12:30:43 +02:00
parent a458479ef5
commit de61023616
62 changed files with 934 additions and 692 deletions

View File

@ -1,24 +1,24 @@
This very simple example shows usage of WebAssembly.
WebAssembly modules can be imported like other modules. Their download and compilation happens in parallel to the download and evaluation of the javascript chunk.
WebAssembly modules can be imported like other async modules.
Their download and compilation happens in parallel to the download and evaluation of the javascript chunk.
# example.js
```javascript
import("./add.wasm").then(addModule => {
console.log(addModule.add(22, 2200));
import("./math").then(math => {
console.log(math.add(10, 101));
console.log(math.factorial(15));
console.log(math.factorialJavascript(15));
console.log(math.fibonacci(15));
console.log(math.fibonacciJavascript(15));
timed("wasm factorial", () => math.factorial(1500));
timed("js factorial", () => math.factorialJavascript(1500));
timed("wasm fibonacci", () => math.fibonacci(22));
timed("js fibonacci", () => math.fibonacciJavascript(22));
});
});
import await { add } from "./add.wasm";
import await { add as mathAdd, factorial, factorialJavascript, fibonacci, fibonacciJavascript } from "./math";
console.log(add(22, 2200));
console.log(mathAdd(10, 101));
console.log(factorial(15));
console.log(factorialJavascript(15));
console.log(fibonacci(15));
console.log(fibonacciJavascript(15));
timed("wasm factorial", () => factorial(1500));
timed("js factorial", () => factorialJavascript(1500));
timed("wasm fibonacci", () => fibonacci(22));
timed("js fibonacci", () => fibonacciJavascript(22));
function timed(name, fn) {
if(!console.time || !console.timeEnd)
@ -36,9 +36,9 @@ function timed(name, fn) {
# math.js
```javascript
import { add } from "./add.wasm";
import { factorial } from "./factorial.wasm";
import { fibonacci } from "./fibonacci.wasm";
import await { add } from "./add.wasm";
import await { factorial } from "./factorial.wasm";
import await { fibonacci } from "./fibonacci.wasm";
export { add, factorial, fibonacci };
@ -88,11 +88,6 @@ export function fibonacciJavascript(i) {
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // the startup function
/******/ function startup() {
@ -116,24 +111,28 @@ export function fibonacciJavascript(i) {
/*!********************!*\
!*** ./example.js ***!
\********************/
/*! other exports [maybe provided (runtime-defined)] [no usage info] */
/*! runtime requirements: __webpack_require__.e__webpack_require__, */
/***/ (function(__unusedmodule, __unusedexports, __webpack_require__) {
/*! other exports [not provided] [no usage info] */
/*! runtime requirements: __webpack_require__.r, __webpack_exports__, module, __webpack_require__ */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
__webpack_require__.e(/*! import() */ 461).then(__webpack_require__.bind(null, /*! ./add.wasm */ 1)).then(addModule => {
console.log(addModule.add(22, 2200));
__webpack_require__.e(/*! import() */ 451).then(__webpack_require__.bind(null, /*! ./math */ 2)).then(math => {
console.log(math.add(10, 101));
console.log(math.factorial(15));
console.log(math.factorialJavascript(15));
console.log(math.fibonacci(15));
console.log(math.fibonacciJavascript(15));
timed("wasm factorial", () => math.factorial(1500));
timed("js factorial", () => math.factorialJavascript(1500));
timed("wasm fibonacci", () => math.fibonacci(22));
timed("js fibonacci", () => math.fibonacciJavascript(22));
});
});
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var _add_wasm__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./add.wasm */ 1);
/* harmony import */ var _math__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./math */ 2);
module.exports = Promise.all([_add_wasm__WEBPACK_IMPORTED_MODULE_0__, _math__WEBPACK_IMPORTED_MODULE_1__]).then(async function([_add_wasm__WEBPACK_IMPORTED_MODULE_0__, _math__WEBPACK_IMPORTED_MODULE_1__]) {
console.log(Object(_add_wasm__WEBPACK_IMPORTED_MODULE_0__["add"])(22, 2200));
console.log(Object(_math__WEBPACK_IMPORTED_MODULE_1__["add"])(10, 101));
console.log(Object(_math__WEBPACK_IMPORTED_MODULE_1__["factorial"])(15));
console.log(Object(_math__WEBPACK_IMPORTED_MODULE_1__["factorialJavascript"])(15));
console.log(Object(_math__WEBPACK_IMPORTED_MODULE_1__["fibonacci"])(15));
console.log(Object(_math__WEBPACK_IMPORTED_MODULE_1__["fibonacciJavascript"])(15));
timed("wasm factorial", () => Object(_math__WEBPACK_IMPORTED_MODULE_1__["factorial"])(1500));
timed("js factorial", () => Object(_math__WEBPACK_IMPORTED_MODULE_1__["factorialJavascript"])(1500));
timed("wasm fibonacci", () => Object(_math__WEBPACK_IMPORTED_MODULE_1__["fibonacci"])(22));
timed("js fibonacci", () => Object(_math__WEBPACK_IMPORTED_MODULE_1__["fibonacciJavascript"])(22));
function timed(name, fn) {
if(!console.time || !console.timeEnd)
@ -146,8 +145,90 @@ function timed(name, fn) {
fn();
console.timeEnd(name)
}
return __webpack_exports__;
});
/***/ }),
/* 1 */
/*!******************!*\
!*** ./add.wasm ***!
\******************/
/*! export add [provided] [no usage info] [missing usage info prevents renaming] */
/*! other exports [not provided] [no usage info] */
/*! runtime requirements: module, __webpack_require__.v, __webpack_require__ */
/***/ (function(module, __unusedexports, __webpack_require__) {
module.exports = __webpack_require__.v(module.i)
/***/ }),
/* 2 */
/*!*****************!*\
!*** ./math.js ***!
\*****************/
/*! export add [provided] [no usage info] [missing usage info prevents renaming] */
/*! export factorial [provided] [no usage info] [missing usage info prevents renaming] */
/*! export factorialJavascript [provided] [no usage info] [missing usage info prevents renaming] */
/*! export fibonacci [provided] [no usage info] [missing usage info prevents renaming] */
/*! export fibonacciJavascript [provided] [no usage info] [missing usage info prevents renaming] */
/*! other exports [not provided] [no usage info] */
/*! runtime requirements: __webpack_require__.r, __webpack_exports__, module, __webpack_require__, __webpack_require__.d */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var _add_wasm__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./add.wasm */ 1);
/* harmony import */ var _factorial_wasm__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./factorial.wasm */ 3);
/* harmony import */ var _fibonacci_wasm__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./fibonacci.wasm */ 4);
module.exports = Promise.all([_add_wasm__WEBPACK_IMPORTED_MODULE_0__, _factorial_wasm__WEBPACK_IMPORTED_MODULE_1__, _fibonacci_wasm__WEBPACK_IMPORTED_MODULE_2__]).then(async function([_add_wasm__WEBPACK_IMPORTED_MODULE_0__, _factorial_wasm__WEBPACK_IMPORTED_MODULE_1__, _fibonacci_wasm__WEBPACK_IMPORTED_MODULE_2__]) {
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "add", function() { return _add_wasm__WEBPACK_IMPORTED_MODULE_0__["add"]; });
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "factorial", function() { return _factorial_wasm__WEBPACK_IMPORTED_MODULE_1__["factorial"]; });
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "fibonacci", function() { return _fibonacci_wasm__WEBPACK_IMPORTED_MODULE_2__["fibonacci"]; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "factorialJavascript", function() { return factorialJavascript; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "fibonacciJavascript", function() { return fibonacciJavascript; });
function factorialJavascript(i) {
if(i < 1) return 1;
return i * factorialJavascript(i - 1);
}
function fibonacciJavascript(i) {
if(i < 2) return 1;
return fibonacciJavascript(i - 1) + fibonacciJavascript(i - 2);
}
return __webpack_exports__;
});
/***/ }),
/* 3 */
/*!************************!*\
!*** ./factorial.wasm ***!
\************************/
/*! export factorial [provided] [no usage info] [missing usage info prevents renaming] */
/*! other exports [not provided] [no usage info] */
/*! runtime requirements: module, __webpack_require__.v, __webpack_require__ */
/***/ (function(module, __unusedexports, __webpack_require__) {
module.exports = __webpack_require__.v(module.i)
/***/ }),
/* 4 */
/*!************************!*\
!*** ./fibonacci.wasm ***!
\************************/
/*! export fibonacci [provided] [no usage info] [missing usage info prevents renaming] */
/*! other exports [not provided] [no usage info] */
/*! runtime requirements: module, __webpack_require__.v, __webpack_require__ */
/***/ (function(module, __unusedexports, __webpack_require__) {
module.exports = __webpack_require__.v(module.i)
/***/ })
/******/ ],
```
@ -158,16 +239,6 @@ function timed(name, fn) {
/******/ function(__webpack_require__) { // webpackRuntimeModules
/******/ "use strict";
/******/
/******/ /* webpack/runtime/ensure chunk */
/******/ !function() {
/******/ __webpack_require__.f = {};
/******/ // This file contains only the entry chunk.
/******/ // The chunk loading function for additional chunks
/******/ __webpack_require__.e = function requireEnsure(chunkId) {
/******/ return Promise.all(Object.keys(__webpack_require__.f).reduce(function(promises, key) { __webpack_require__.f[key](chunkId, promises); return promises; }, []));
/******/ };
/******/ }();
/******/
/******/ /* webpack/runtime/make namespace object */
/******/ !function() {
/******/ // define __esModule on exports
@ -195,206 +266,18 @@ function timed(name, fn) {
/******/ __webpack_require__.p = "dist/";
/******/ }();
/******/
/******/ /* webpack/runtime/get javascript chunk filename */
/******/ !function() {
/******/ // This function allow to reference async chunks
/******/ __webpack_require__.u = function(chunkId) {
/******/ // return url for filenames based on template
/******/ return "" + chunkId + ".output.js";
/******/ };
/******/ }();
/******/
/******/ /* webpack/runtime/jsonp chunk loading */
/******/ !function() {
/******/
/******/
/******/ // object to store loaded and loading chunks
/******/ // undefined = chunk not loaded, null = chunk preloaded/prefetched
/******/ // Promise = chunk loading, 0 = chunk loaded
/******/ var installedChunks = {
/******/ 179: 0
/******/ };
/******/
/******/
/******/
/******/ __webpack_require__.f.j = function(chunkId, promises) {
/******/ // JSONP chunk loading for javascript
/******/ var installedChunkData = installedChunks[chunkId];
/******/ if(installedChunkData !== 0) { // 0 means "already installed".
/******/
/******/ // a Promise means "currently loading".
/******/ if(installedChunkData) {
/******/ promises.push(installedChunkData[2]);
/******/ } else {
/******/ // setup Promise in chunk cache
/******/ var promise = new Promise(function(resolve, reject) {
/******/ installedChunkData = installedChunks[chunkId] = [resolve, reject];
/******/ });
/******/ promises.push(installedChunkData[2] = promise);
/******/
/******/ // start chunk loading
/******/ var url = __webpack_require__.p + __webpack_require__.u(chunkId);
/******/ var loadingEnded = function() { if(installedChunks[chunkId]) return installedChunks[chunkId][1]; if(installedChunks[chunkId] !== 0) installedChunks[chunkId] = undefined; };
/******/ var script = document.createElement('script');
/******/ var onScriptComplete;
/******/
/******/ script.charset = 'utf-8';
/******/ script.timeout = 120;
/******/ if (__webpack_require__.nc) {
/******/ script.setAttribute("nonce", __webpack_require__.nc);
/******/ }
/******/ script.src = url;
/******/
/******/ onScriptComplete = function (event) {
/******/ // avoid mem leaks in IE.
/******/ script.onerror = script.onload = null;
/******/ clearTimeout(timeout);
/******/ var reportError = loadingEnded();
/******/ if(reportError) {
/******/ var errorType = event && (event.type === 'load' ? 'missing' : event.type);
/******/ var realSrc = event && event.target && event.target.src;
/******/ var error = new Error('Loading chunk ' + chunkId + ' failed.\n(' + errorType + ': ' + realSrc + ')');
/******/ error.type = errorType;
/******/ error.request = realSrc;
/******/ reportError(error);
/******/ }
/******/ };
/******/ var timeout = setTimeout(function(){
/******/ onScriptComplete({ type: 'timeout', target: script });
/******/ }, 120000);
/******/ script.onerror = script.onload = onScriptComplete;
/******/ document.head.appendChild(script);
/******/
/******/ // no HMR
/******/ }
/******/ }
/******/
/******/ // no chunk preloading needed
/******/ };
/******/
/******/ // no prefetching
/******/
/******/ // no HMR
/******/
/******/ // no HMR manifest
/******/
/******/ // no deferred startup
/******/
/******/ // install a JSONP callback for chunk loading
/******/ function webpackJsonpCallback(data) {
/******/ var chunkIds = data[0];
/******/ var moreModules = data[1];
/******/
/******/ var runtime = data[3];
/******/
/******/ // add "moreModules" to the modules object,
/******/ // then flag all "chunkIds" as loaded and fire callback
/******/ var moduleId, chunkId, i = 0, resolves = [];
/******/ for(;i < chunkIds.length; i++) {
/******/ chunkId = chunkIds[i];
/******/ if(installedChunks[chunkId]) {
/******/ resolves.push(installedChunks[chunkId][0]);
/******/ }
/******/ installedChunks[chunkId] = 0;
/******/ }
/******/ for(moduleId in moreModules) {
/******/ if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {
/******/ __webpack_require__.m[moduleId] = moreModules[moduleId];
/******/ }
/******/ }
/******/ if(runtime) runtime(__webpack_require__);
/******/ if(parentJsonpFunction) parentJsonpFunction(data);
/******/
/******/ while(resolves.length) {
/******/ resolves.shift()();
/******/ }
/******/
/******/ };
/******/
/******/ var jsonpArray = window["webpackJsonp"] = window["webpackJsonp"] || [];
/******/ var oldJsonpFunction = jsonpArray.push.bind(jsonpArray);
/******/ jsonpArray.push = webpackJsonpCallback;
/******/
/******/ var parentJsonpFunction = oldJsonpFunction;
/******/ }();
/******/
/******/ /* webpack/runtime/wasm chunk loading */
/******/ !function() {
/******/ // object to store loaded and loading wasm modules
/******/ var installedWasmModules = {};
/******/
/******/ function promiseResolve() { return Promise.resolve(); }
/******/
/******/
/******/ var wasmImportObjects = {
/******/ 1: function() {
/******/ return {
/******/
/******/ };
/******/ },
/******/ 3: function() {
/******/ return {
/******/
/******/ };
/******/ },
/******/ 4: function() {
/******/ return {
/******/
/******/ };
/******/ },
/******/ 1: function() {
/******/ return {
/******/
/******/ };
/******/ },
/******/ };
/******/
/******/ var wasmModuleMap = {
/******/ "451": [
/******/ 1,
/******/ 3,
/******/ 4
/******/ ],
/******/ "461": [
/******/ 1
/******/ ]
/******/ };
/******/
/******/ // object with all WebAssembly.instance exports
/******/ __webpack_require__.w = {};
/******/
/******/ // Fetch + compile chunk loading for webassembly
/******/ __webpack_require__.f.wasm = function(chunkId, promises) {
/******/
/******/ var wasmModules = wasmModuleMap[chunkId] || [];
/******/
/******/ wasmModules.forEach(function(wasmModuleId) {
/******/ var installedWasmModuleData = installedWasmModules[wasmModuleId];
/******/
/******/ // a Promise means "currently loading" or "already loaded".
/******/ if(installedWasmModuleData)
/******/ promises.push(installedWasmModuleData);
/******/ else {
/******/ var importObject = wasmImportObjects[wasmModuleId]();
/******/ var req = fetch(__webpack_require__.p + "" + {"1":"796ebb0fde2fd9366416","3":"f8c3f5244aa6dfa83d5d","4":"91af48c8382460c02425"}[wasmModuleId] + ".wasm");
/******/ var promise;
/******/ if(importObject instanceof Promise && typeof WebAssembly.compileStreaming === 'function') {
/******/ promise = Promise.all([WebAssembly.compileStreaming(req), importObject]).then(function(items) {
/******/ return WebAssembly.instantiate(items[0], items[1]);
/******/ });
/******/ } else if(typeof WebAssembly.instantiateStreaming === 'function') {
/******/ promise = WebAssembly.instantiateStreaming(req, importObject);
/******/ } else {
/******/ var bytesPromise = req.then(function(x) { return x.arrayBuffer(); });
/******/ promise = bytesPromise.then(function(bytes) {
/******/ return WebAssembly.instantiate(bytes, importObject);
/******/ });
/******/ }
/******/ promises.push(installedWasmModules[wasmModuleId] = promise.then(function(res) {
/******/ return __webpack_require__.w[wasmModuleId] = (res.instance || res).exports;
/******/ }));
/******/ }
/******/ });
/******/ __webpack_require__.v = function(wasmModuleId, importsObj) {
/******/ var req = fetch(__webpack_require__.p + "" + {"1":"216fd3b2e2c26ba17d6a","3":"ce408c5c3fbf4bafc915","4":"edf8dce07bda763a8ce8"}[wasmModuleId] + ".wasm");
/******/ if(typeof WebAssembly.instantiateStreaming === 'function') {
/******/ return WebAssembly.instantiateStreaming(req, importsObj)
/******/ .then(function(res) { return res.instance.exports; });
/******/ }
/******/ return req
/******/ .then(function(x) { return x.arrayBuffer(); })
/******/ .then(function(bytes) { return WebAssembly.instantiate(bytes, importsObj); })
/******/ .then(function(res) { return res.instance.exports; });
/******/ };
/******/ }();
/******/
@ -405,247 +288,100 @@ function timed(name, fn) {
</details>
# dist/451.output.js
```javascript
(window["webpackJsonp"] = window["webpackJsonp"] || []).push([[451],[
/* 0 */,
/* 1 */
/*!******************!*\
!*** ./add.wasm ***!
\******************/
/*! export add [provided] [no usage info] [missing usage info prevents renaming] */
/*! other exports [not provided] [no usage info] */
/*! runtime requirements: module__webpack_require__.w, __webpack_require__.r, __webpack_exports__, __webpack_require__, */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
// Instantiate WebAssembly module
var wasmExports = __webpack_require__.w[module.i];
__webpack_require__.r(exports);
// export exports from WebAssembly module
for(var name in wasmExports) if(name) exports[name] = wasmExports[name];
// exec imports from WebAssembly module (for esm order)
// exec wasm module
wasmExports[""]()
/***/ }),
/* 2 */
/*!*****************!*\
!*** ./math.js ***!
\*****************/
/*! export add [provided] [no usage info] [missing usage info prevents renaming] */
/*! export factorial [provided] [no usage info] [missing usage info prevents renaming] */
/*! export factorialJavascript [provided] [no usage info] [missing usage info prevents renaming] */
/*! export fibonacci [provided] [no usage info] [missing usage info prevents renaming] */
/*! export fibonacciJavascript [provided] [no usage info] [missing usage info prevents renaming] */
/*! other exports [not provided] [no usage info] */
/*! runtime requirements: __webpack_require__.r__webpack_exports__, __webpack_require__, __webpack_require__.d, */
/***/ (function(__unusedmodule, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "add", function() { return _add_wasm__WEBPACK_IMPORTED_MODULE_0__["add"]; });
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "factorial", function() { return _factorial_wasm__WEBPACK_IMPORTED_MODULE_1__["factorial"]; });
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "fibonacci", function() { return _fibonacci_wasm__WEBPACK_IMPORTED_MODULE_2__["fibonacci"]; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "factorialJavascript", function() { return factorialJavascript; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "fibonacciJavascript", function() { return fibonacciJavascript; });
/* harmony import */ var _add_wasm__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./add.wasm */ 1);
/* harmony import */ var _factorial_wasm__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./factorial.wasm */ 3);
/* harmony import */ var _fibonacci_wasm__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./fibonacci.wasm */ 4);
function factorialJavascript(i) {
if(i < 1) return 1;
return i * factorialJavascript(i - 1);
}
function fibonacciJavascript(i) {
if(i < 2) return 1;
return fibonacciJavascript(i - 1) + fibonacciJavascript(i - 2);
}
/***/ }),
/* 3 */
/*!************************!*\
!*** ./factorial.wasm ***!
\************************/
/*! export factorial [provided] [no usage info] [missing usage info prevents renaming] */
/*! other exports [not provided] [no usage info] */
/*! runtime requirements: module__webpack_require__.w, __webpack_require__.r, __webpack_exports__, __webpack_require__, */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
// Instantiate WebAssembly module
var wasmExports = __webpack_require__.w[module.i];
__webpack_require__.r(exports);
// export exports from WebAssembly module
for(var name in wasmExports) if(name) exports[name] = wasmExports[name];
// exec imports from WebAssembly module (for esm order)
// exec wasm module
wasmExports[""]()
/***/ }),
/* 4 */
/*!************************!*\
!*** ./fibonacci.wasm ***!
\************************/
/*! export fibonacci [provided] [no usage info] [missing usage info prevents renaming] */
/*! other exports [not provided] [no usage info] */
/*! runtime requirements: module__webpack_require__.w, __webpack_require__.r, __webpack_exports__, __webpack_require__, */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
// Instantiate WebAssembly module
var wasmExports = __webpack_require__.w[module.i];
__webpack_require__.r(exports);
// export exports from WebAssembly module
for(var name in wasmExports) if(name) exports[name] = wasmExports[name];
// exec imports from WebAssembly module (for esm order)
// exec wasm module
wasmExports[""]()
/***/ })
]]);
```
# dist/461.output.js
```javascript
(window["webpackJsonp"] = window["webpackJsonp"] || []).push([[461],[
/* 0 */,
/* 1 */
/*!******************!*\
!*** ./add.wasm ***!
\******************/
/*! export add [provided] [no usage info] [missing usage info prevents renaming] */
/*! other exports [not provided] [no usage info] */
/*! runtime requirements: module__webpack_require__.w, __webpack_require__.r, __webpack_exports__, __webpack_require__, */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
// Instantiate WebAssembly module
var wasmExports = __webpack_require__.w[module.i];
__webpack_require__.r(exports);
// export exports from WebAssembly module
for(var name in wasmExports) if(name) exports[name] = wasmExports[name];
// exec imports from WebAssembly module (for esm order)
// exec wasm module
wasmExports[""]()
/***/ })
]]);
```
# Info
## Unoptimized
```
Hash: 0a1b2c3d4e5f6a7b8c9d
Version: webpack 5.0.0-alpha.11
Asset Size Chunks Chunk Names
451.output.js 4.47 KiB {451} [emitted]
461.output.js 831 bytes {461} [emitted]
796ebb0fde2fd9366416.wasm 51 bytes {451}, {461} [emitted]
91af48c8382460c02425.wasm 77 bytes {451} [emitted]
f8c3f5244aa6dfa83d5d.wasm 72 bytes {451} [emitted]
output.js 11.9 KiB {179} [emitted] main
Entrypoint main = output.js
chunk {179} output.js (main) 762 bytes (javascript) 6.05 KiB (runtime) [entry] [rendered]
Version: webpack 5.0.0-alpha.14
Asset Size Chunks Chunk Names
216fd3b2e2c26ba17d6a.wasm 41 bytes {179} [emitted] main
ce408c5c3fbf4bafc915.wasm 62 bytes {179} [emitted] main
edf8dce07bda763a8ce8.wasm 67 bytes {179} [emitted] main
output.js 8.92 KiB {179} [emitted] main
Entrypoint main = output.js 216fd3b2e2c26ba17d6a.wasm ce408c5c3fbf4bafc915.wasm edf8dce07bda763a8ce8.wasm
chunk {179} output.js, 216fd3b2e2c26ba17d6a.wasm, ce408c5c3fbf4bafc915.wasm, edf8dce07bda763a8ce8.wasm (main) 1.3 KiB (javascript) 170 bytes (webassembly) 1.16 KiB (runtime) [entry] [rendered]
> ./example.js main
[0] ./example.js 762 bytes {179} [built]
[0] ./example.js 761 bytes {179} [built]
[no exports]
[used exports unknown]
entry ./example.js main
+ 7 hidden chunk modules
chunk {451} 451.output.js, 796ebb0fde2fd9366416.wasm, f8c3f5244aa6dfa83d5d.wasm, 91af48c8382460c02425.wasm 700 bytes (javascript) 170 bytes (webassembly) [rendered]
> ./math [0] ./example.js 3:1-17
[1] ./add.wasm 100 bytes (javascript) 41 bytes (webassembly) {451} {461} [built]
[1] ./add.wasm 50 bytes (javascript) 41 bytes (webassembly) {179} [built]
[exports: add]
[used exports unknown]
import() ./add.wasm [0] ./example.js 1:0-20
harmony side effect evaluation ./add.wasm [2] ./math.js 1:0-33
harmony side effect evaluation ./add.wasm [0] ./example.js 1:0-39
harmony import specifier ./add.wasm [0] ./example.js 4:12-15
harmony side effect evaluation ./add.wasm [2] ./math.js 1:0-39
harmony export imported specifier ./add.wasm [2] ./math.js 5:0-37
[2] ./math.js 400 bytes {451} [built]
[2] ./math.js 418 bytes {179} [built]
[exports: add, factorial, factorialJavascript, fibonacci, fibonacciJavascript]
[used exports unknown]
import() ./math [0] ./example.js 3:1-17
[3] ./factorial.wasm 100 bytes (javascript) 62 bytes (webassembly) {451} [built]
harmony side effect evaluation ./math [0] ./example.js 2:0-110
harmony import specifier ./math [0] ./example.js 5:12-19
harmony import specifier ./math [0] ./example.js 6:12-21
harmony import specifier ./math [0] ./example.js 7:12-31
harmony import specifier ./math [0] ./example.js 8:12-21
harmony import specifier ./math [0] ./example.js 9:12-31
harmony import specifier ./math [0] ./example.js 10:30-39
harmony import specifier ./math [0] ./example.js 11:28-47
harmony import specifier ./math [0] ./example.js 12:30-39
harmony import specifier ./math [0] ./example.js 13:28-47
[3] ./factorial.wasm 50 bytes (javascript) 62 bytes (webassembly) {179} [built]
[exports: factorial]
[used exports unknown]
harmony side effect evaluation ./factorial.wasm [2] ./math.js 2:0-45
harmony side effect evaluation ./factorial.wasm [2] ./math.js 2:0-51
harmony export imported specifier ./factorial.wasm [2] ./math.js 5:0-37
[4] ./fibonacci.wasm 100 bytes (javascript) 67 bytes (webassembly) {451} [built]
[4] ./fibonacci.wasm 50 bytes (javascript) 67 bytes (webassembly) {179} [built]
[exports: fibonacci]
[used exports unknown]
harmony side effect evaluation ./fibonacci.wasm [2] ./math.js 3:0-45
harmony side effect evaluation ./fibonacci.wasm [2] ./math.js 3:0-51
harmony export imported specifier ./fibonacci.wasm [2] ./math.js 5:0-37
chunk {461} 461.output.js, 796ebb0fde2fd9366416.wasm 100 bytes (javascript) 41 bytes (webassembly) [rendered]
> ./add.wasm [0] ./example.js 1:0-20
[1] ./add.wasm 100 bytes (javascript) 41 bytes (webassembly) {451} {461} [built]
[exports: add]
[used exports unknown]
import() ./add.wasm [0] ./example.js 1:0-20
harmony side effect evaluation ./add.wasm [2] ./math.js 1:0-33
harmony export imported specifier ./add.wasm [2] ./math.js 5:0-37
+ 4 hidden chunk modules
```
## Production mode
```
Hash: 0a1b2c3d4e5f6a7b8c9d
Version: webpack 5.0.0-alpha.11
Asset Size Chunks Chunk Names
0fdec8168d54770f0f62.wasm 51 bytes {451}, {461} [emitted]
451.output.js 668 bytes {451}, {461} [emitted]
461.output.js 156 bytes {461} [emitted]
5fc3e77f8ecdd320f3e0.wasm 69 bytes {451}, {461} [emitted]
81a4c3dd4ea06365035d.wasm 64 bytes {451}, {461} [emitted]
output.js 3.06 KiB {179} [emitted] main
Entrypoint main = output.js
chunk {179} output.js (main) 762 bytes (javascript) 6.07 KiB (runtime) [entry] [rendered]
Version: webpack 5.0.0-alpha.14
Asset Size Chunks Chunk Names
6d518704ecb4aa16ea4e.wasm 62 bytes {179} [emitted] main
9099c5b3bb53a85154d5.wasm 41 bytes {179} [emitted] main
b7e9245ccbc6eb4c52c9.wasm 67 bytes {179} [emitted] main
output.js 2.01 KiB {179} [emitted] main
Entrypoint main = output.js 6d518704ecb4aa16ea4e.wasm 9099c5b3bb53a85154d5.wasm b7e9245ccbc6eb4c52c9.wasm
chunk {179} output.js, 6d518704ecb4aa16ea4e.wasm, 9099c5b3bb53a85154d5.wasm, b7e9245ccbc6eb4c52c9.wasm (main) 1.3 KiB (javascript) 170 bytes (webassembly) 1.17 KiB (runtime) [entry] [rendered]
> ./example.js main
[144] ./example.js 762 bytes {179} [built]
entry ./example.js main
+ 7 hidden chunk modules
chunk {451} 451.output.js, 81a4c3dd4ea06365035d.wasm, 0fdec8168d54770f0f62.wasm, 5fc3e77f8ecdd320f3e0.wasm 700 bytes (javascript) 170 bytes (webassembly) [rendered]
> ./math [144] ./example.js 3:1-17
[78] ./factorial.wasm 100 bytes (javascript) 62 bytes (webassembly) {451} [built]
[78] ./factorial.wasm 50 bytes (javascript) 62 bytes (webassembly) {179} [built]
[exports: factorial]
[all exports used]
harmony side effect evaluation ./factorial.wasm [451] ./math.js 2:0-45
harmony side effect evaluation ./factorial.wasm [451] ./math.js 2:0-51
harmony export imported specifier ./factorial.wasm [451] ./math.js 5:0-37
[451] ./math.js 400 bytes {451} [built]
[144] ./example.js 761 bytes {179} [built]
[no exports]
entry ./example.js main
[451] ./math.js 418 bytes {179} [built]
[exports: add, factorial, factorialJavascript, fibonacci, fibonacciJavascript]
import() ./math [144] ./example.js 3:1-17
[461] ./add.wasm 100 bytes (javascript) 41 bytes (webassembly) {451} {461} [built]
[exports: add]
import() ./add.wasm [144] ./example.js 1:0-20
harmony side effect evaluation ./add.wasm [451] ./math.js 1:0-33
harmony export imported specifier ./add.wasm [451] ./math.js 5:0-37
[605] ./fibonacci.wasm 100 bytes (javascript) 67 bytes (webassembly) {451} [built]
[exports: fibonacci]
[all exports used]
harmony side effect evaluation ./fibonacci.wasm [451] ./math.js 3:0-45
harmony export imported specifier ./fibonacci.wasm [451] ./math.js 5:0-37
chunk {461} 461.output.js, 0fdec8168d54770f0f62.wasm 100 bytes (javascript) 41 bytes (webassembly) [rendered]
> ./add.wasm [144] ./example.js 1:0-20
[461] ./add.wasm 100 bytes (javascript) 41 bytes (webassembly) {451} {461} [built]
harmony side effect evaluation ./math [144] ./example.js 2:0-110
harmony import specifier ./math [144] ./example.js 5:12-19
harmony import specifier ./math [144] ./example.js 6:12-21
harmony import specifier ./math [144] ./example.js 7:12-31
harmony import specifier ./math [144] ./example.js 8:12-21
harmony import specifier ./math [144] ./example.js 9:12-31
harmony import specifier ./math [144] ./example.js 10:30-39
harmony import specifier ./math [144] ./example.js 11:28-47
harmony import specifier ./math [144] ./example.js 12:30-39
harmony import specifier ./math [144] ./example.js 13:28-47
[461] ./add.wasm 50 bytes (javascript) 41 bytes (webassembly) {179} [built]
[exports: add]
import() ./add.wasm [144] ./example.js 1:0-20
harmony side effect evaluation ./add.wasm [451] ./math.js 1:0-33
harmony side effect evaluation ./add.wasm [144] ./example.js 1:0-39
harmony import specifier ./add.wasm [144] ./example.js 4:12-15
harmony side effect evaluation ./add.wasm [451] ./math.js 1:0-39
harmony export imported specifier ./add.wasm [451] ./math.js 5:0-37
[605] ./fibonacci.wasm 50 bytes (javascript) 67 bytes (webassembly) {179} [built]
[exports: fibonacci]
harmony side effect evaluation ./fibonacci.wasm [451] ./math.js 3:0-51
harmony export imported specifier ./fibonacci.wasm [451] ./math.js 5:0-37
+ 4 hidden chunk modules
```

View File

@ -1,17 +1,16 @@
import("./add.wasm").then(addModule => {
console.log(addModule.add(22, 2200));
import("./math").then(math => {
console.log(math.add(10, 101));
console.log(math.factorial(15));
console.log(math.factorialJavascript(15));
console.log(math.fibonacci(15));
console.log(math.fibonacciJavascript(15));
timed("wasm factorial", () => math.factorial(1500));
timed("js factorial", () => math.factorialJavascript(1500));
timed("wasm fibonacci", () => math.fibonacci(22));
timed("js fibonacci", () => math.fibonacciJavascript(22));
});
});
import await { add } from "./add.wasm";
import await { add as mathAdd, factorial, factorialJavascript, fibonacci, fibonacciJavascript } from "./math";
console.log(add(22, 2200));
console.log(mathAdd(10, 101));
console.log(factorial(15));
console.log(factorialJavascript(15));
console.log(fibonacci(15));
console.log(fibonacciJavascript(15));
timed("wasm factorial", () => factorial(1500));
timed("js factorial", () => factorialJavascript(1500));
timed("wasm fibonacci", () => fibonacci(22));
timed("js fibonacci", () => fibonacciJavascript(22));
function timed(name, fn) {
if(!console.time || !console.timeEnd)

View File

@ -1,5 +1,5 @@
<html>
<body>
<script src="js/output.js"></script>
<script src="dist/output.js"></script>
</body>
</html>

View File

@ -1,6 +1,6 @@
import { add } from "./add.wasm";
import { factorial } from "./factorial.wasm";
import { fibonacci } from "./fibonacci.wasm";
import await { add } from "./add.wasm";
import await { factorial } from "./factorial.wasm";
import await { fibonacci } from "./fibonacci.wasm";
export { add, factorial, fibonacci };

View File

@ -1,6 +1,7 @@
This very simple example shows usage of WebAssembly.
WebAssembly modules can be imported like other modules. Their download and compilation happens in parallel to the download and evaluation of the javascript chunk.
WebAssembly modules can be imported like other async modules.
Their download and compilation happens in parallel to the download and evaluation of the javascript chunk.
# example.js
@ -20,18 +21,6 @@ _{{math.js}}_
_{{dist/output.js}}_
```
# dist/451.output.js
```javascript
_{{dist/451.output.js}}_
```
# dist/461.output.js
```javascript
_{{dist/461.output.js}}_
```
# Info
## Unoptimized

View File

@ -8,7 +8,7 @@ module.exports = {
rules: [
{
test: /\.wasm$/,
type: "webassembly/experimental"
type: "webassembly/async-experimental"
}
]
},

View File

@ -474,15 +474,16 @@ class ChunkGraph {
/**
* @param {Chunk} chunk the chunk
* @param {ModuleFilterPredicate} filterFn function used to filter modules
* @param {boolean} includeAllChunks all chunks or only async chunks
* @returns {ChunkModuleMaps} module map information
*/
getChunkModuleMaps(chunk, filterFn) {
getChunkModuleMaps(chunk, filterFn, includeAllChunks = false) {
/** @type {Record<string|number, (string|number)[]>} */
const chunkModuleIdMap = Object.create(null);
/** @type {Record<string|number, string>} */
const chunkModuleHashMap = Object.create(null);
for (const asyncChunk of chunk.getAllAsyncChunks()) {
for (const asyncChunk of includeAllChunks ? chunk.getAllReferencedChunks() : chunk.getAllAsyncChunks()) {
/** @type {(string|number)[]} */
let array;
for (const module of this.getOrderedChunkModulesIterable(

View File

@ -95,6 +95,11 @@ exports.getFullHash = "__webpack_require__.h";
*/
exports.wasmInstances = "__webpack_require__.w";
/**
* instantiate a wasm instance from url/filename and importsObject
*/
exports.instantiateWasm = "__webpack_require__.v";
/**
* the uncaught error handler for the webpack runtime
*/

View File

@ -42,7 +42,8 @@ const DEPENDENCIES = {
[RuntimeGlobals.publicPath]: [RuntimeGlobals.require],
[RuntimeGlobals.scriptNonce]: [RuntimeGlobals.require],
[RuntimeGlobals.uncaughtErrorHandler]: [RuntimeGlobals.require],
[RuntimeGlobals.wasmInstances]: [RuntimeGlobals.require]
[RuntimeGlobals.wasmInstances]: [RuntimeGlobals.require],
[RuntimeGlobals.instantiateWasm]: [RuntimeGlobals.require]
};
class RuntimePlugin {

View File

@ -9,6 +9,7 @@ const OptionsApply = require("./OptionsApply");
const JavascriptModulesPlugin = require("./JavascriptModulesPlugin");
const JsonModulesPlugin = require("./JsonModulesPlugin");
const AsyncWebAssemblyModulesPlugin = require("./wasm-async/AsyncWebAssemblyModulesPlugin");
const WebAssemblyModulesPlugin = require("./wasm/WebAssemblyModulesPlugin");
const EvalDevToolModulePlugin = require("./EvalDevToolModulePlugin");
@ -74,11 +75,13 @@ class WebpackOptionsApply extends OptionsApply {
case "web": {
const JsonpTemplatePlugin = require("./web/JsonpTemplatePlugin");
const FetchCompileWasmPlugin = require("./web/FetchCompileWasmPlugin");
const FetchCompileAsyncWasmPlugin = require("./web/FetchCompileAsyncWasmPlugin");
const NodeSourcePlugin = require("./node/NodeSourcePlugin");
new JsonpTemplatePlugin().apply(compiler);
new FetchCompileWasmPlugin({
mangleImports: options.optimization.mangleWasmImports
}).apply(compiler);
new FetchCompileAsyncWasmPlugin().apply(compiler);
new FunctionModulePlugin().apply(compiler);
new NodeSourcePlugin(options.node).apply(compiler);
new LoaderTargetPlugin(options.target).apply(compiler);
@ -87,12 +90,14 @@ class WebpackOptionsApply extends OptionsApply {
case "webworker": {
const WebWorkerTemplatePlugin = require("./webworker/WebWorkerTemplatePlugin");
const FetchCompileWasmPlugin = require("./web/FetchCompileWasmPlugin");
const FetchCompileAsyncWasmPlugin = require("./web/FetchCompileAsyncWasmPlugin");
const NodeSourcePlugin = require("./node/NodeSourcePlugin");
const StartupChunkDependenciesPlugin = require("./runtime/StartupChunkDependenciesPlugin");
new WebWorkerTemplatePlugin().apply(compiler);
new FetchCompileWasmPlugin({
mangleImports: options.optimization.mangleWasmImports
}).apply(compiler);
new FetchCompileAsyncWasmPlugin().apply(compiler);
new FunctionModulePlugin().apply(compiler);
new NodeSourcePlugin(options.node).apply(compiler);
new LoaderTargetPlugin(options.target).apply(compiler);
@ -105,6 +110,7 @@ class WebpackOptionsApply extends OptionsApply {
case "async-node": {
const NodeTemplatePlugin = require("./node/NodeTemplatePlugin");
const ReadFileCompileWasmPlugin = require("./node/ReadFileCompileWasmPlugin");
const ReadFileCompileAsyncWasmPlugin = require("./node/ReadFileCompileAsyncWasmPlugin");
const NodeTargetPlugin = require("./node/NodeTargetPlugin");
const StartupChunkDependenciesPlugin = require("./runtime/StartupChunkDependenciesPlugin");
new NodeTemplatePlugin({
@ -113,6 +119,7 @@ class WebpackOptionsApply extends OptionsApply {
new ReadFileCompileWasmPlugin({
mangleImports: options.optimization.mangleWasmImports
}).apply(compiler);
new ReadFileCompileAsyncWasmPlugin().apply(compiler);
new FunctionModulePlugin().apply(compiler);
new NodeTargetPlugin().apply(compiler);
new LoaderTargetPlugin("node").apply(compiler);
@ -180,6 +187,7 @@ class WebpackOptionsApply extends OptionsApply {
case "electron-renderer":
case "electron-preload": {
const FetchCompileWasmPlugin = require("./web/FetchCompileWasmPlugin");
const FetchCompileAsyncWasmPlugin = require("./web/FetchCompileAsyncWasmPlugin");
const NodeTargetPlugin = require("./node/NodeTargetPlugin");
const ExternalsPlugin = require("./ExternalsPlugin");
if (options.target === "electron-renderer") {
@ -194,6 +202,7 @@ class WebpackOptionsApply extends OptionsApply {
new FetchCompileWasmPlugin({
mangleImports: options.optimization.mangleWasmImports
}).apply(compiler);
new FetchCompileAsyncWasmPlugin().apply(compiler);
new FunctionModulePlugin().apply(compiler);
new NodeTargetPlugin().apply(compiler);
new ExternalsPlugin("commonjs", [
@ -302,6 +311,9 @@ class WebpackOptionsApply extends OptionsApply {
new WebAssemblyModulesPlugin({
mangleImports: options.optimization.mangleWasmImports
}).apply(compiler);
new AsyncWebAssemblyModulesPlugin({
mangleImports: options.optimization.mangleWasmImports
}).apply(compiler);
new EntryOptionPlugin().apply(compiler);
compiler.hooks.entryOption.call(options.context, options.entry);

View File

@ -137,7 +137,7 @@ class WebpackOptionsDefaulter extends OptionsDefaulter {
},
{
test: /\.wasm$/i,
type: "webassembly/experimental"
type: "webassembly/async-experimental"
}
].filter(Boolean)
);

View File

@ -6,35 +6,37 @@
"use strict";
const InitFragment = require("../InitFragment");
const RuntimeGlobals = require("../RuntimeGlobals");
const generateCode = promises => {
const generateCode = (moduleArgument, promises) => {
if (promises.length === 0) {
return `__webpack_module__.exports = (async function() {\n`;
return `${moduleArgument}.exports = (async function() {\n`;
}
return `__webpack_module__.exports = Promise.all([${promises.join(
return `${moduleArgument}.exports = Promise.all([${promises.join(
", "
)}]).then(async function([${promises.join(", ")}]) {\n`;
};
class AsyncModuleInitFragment extends InitFragment {
/**
* @param {string} moduleArgument the value of module.moduleArgument
* @param {string[]} promises the promises that should be awaited
*/
constructor(promises) {
constructor(moduleArgument, promises) {
super(
generateCode(promises),
generateCode(moduleArgument, promises),
InitFragment.STAGE_ASYNC_BOUNDARY,
0,
"async-boundary",
"return __webpack_exports__;\n" +
(promises.length === 0 ? "})();\n" : "});\n")
);
this.moduleArgument = moduleArgument;
this.promises = promises;
}
merge(other) {
return new AsyncModuleInitFragment(
this.moduleArgument,
Array.from(new Set(other.promises.concat(this.promises)))
);
}

View File

@ -318,6 +318,7 @@ const interceptAllParserHooks = (moduleFactory, tracer) => {
"javascript/dynamic",
"javascript/esm",
"json",
"webassembly/async-sexperimental",
"webassembly/experimental"
];

View File

@ -56,7 +56,9 @@ HarmonyCompatibilityDependency.Template = class HarmonyExportDependencyTemplate
}
if (module.buildMeta.exportsType === "async") {
runtimeRequirements.add(RuntimeGlobals.module);
initFragments.push(new AsyncModuleInitFragment([]));
initFragments.push(
new AsyncModuleInitFragment(module.moduleArgument, [])
);
}
}
};

View File

@ -48,9 +48,9 @@ module.exports = class HarmonyDetectionParserPlugin {
module.buildMeta.exportsType = isAsync ? "async" : "namespace";
module.buildInfo.strict = true;
module.buildInfo.exportsArgument = "__webpack_exports__";
module.buildInfo.moduleArgument = "__webpack_module__";
if (isStrictHarmony) {
module.buildMeta.strictHarmonyModule = true;
module.buildInfo.moduleArgument = "__webpack_module__";
}
}
});

View File

@ -157,7 +157,7 @@ HarmonyImportDependency.Template = class HarmonyImportDependencyTemplate extends
if (dep.await) {
templateContext.runtimeRequirements.add(RuntimeGlobals.module);
templateContext.initFragments.push(
new AsyncModuleInitFragment([
new AsyncModuleInitFragment(templateContext.module.moduleArgument, [
dep.getImportVar(templateContext.moduleGraph)
])
);

View File

@ -5,9 +5,9 @@
"use strict";
const WebpackError = require("../WebpackError");
const makeSerializable = require("../util/makeSerializable");
const HarmonyImportDependency = require("./HarmonyImportDependency");
const WebpackError = require("../WebpackError");
/** @typedef {import("webpack-sources").ReplaceSource} ReplaceSource */
/** @typedef {import("../Dependency")} Dependency */

View File

@ -80,8 +80,8 @@ ModuleDecoratorDependency.Template = class ModuleDecoratorDependencyTemplate ext
runtimeRequirements.add(dep.decorator);
initFragments.push(
new InitFragment(
`/* module decorator */ ${RuntimeGlobals.module} = ${dep.decorator}(${
RuntimeGlobals.module
`/* module decorator */ ${module.moduleArgument} = ${dep.decorator}(${
module.moduleArgument
});\n`,
InitFragment.STAGE_PROVIDES,
0,

View File

@ -0,0 +1,76 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const RuntimeGlobals = require("../RuntimeGlobals");
const Template = require("../Template");
const AsyncWasmChunkLoadingRuntimeModule = require("../wasm-async/AsyncWasmChunkLoadingRuntimeModule");
/** @typedef {import("../Compiler")} Compiler */
class ReadFileCompileAsyncWasmPlugin {
/**
* @param {Compiler} compiler the compiler instance
* @returns {void}
*/
apply(compiler) {
compiler.hooks.thisCompilation.tap(
"ReadFileCompileAsyncWasmPlugin",
compilation => {
const generateLoadBinaryCode = path =>
Template.asString([
"new Promise(function (resolve, reject) {",
Template.indent([
"var { readFile } = require('fs');",
"var { join } = require('path');",
"",
"try {",
Template.indent([
`readFile(join(__dirname, ${path}), function(err, buffer){`,
Template.indent([
"if (err) return reject(err);",
"",
"// Fake fetch response",
"resolve({",
Template.indent([
"arrayBuffer() { return Promise.resolve(buffer); }"
]),
"});"
]),
"});"
]),
"} catch (err) { reject(err); }"
]),
"})"
]);
compilation.hooks.runtimeRequirementInTree
.for(RuntimeGlobals.instantiateWasm)
.tap("ReadFileCompileAsyncWasmPlugin", (chunk, set) => {
const chunkGraph = compilation.chunkGraph;
if (
!chunkGraph.hasModuleInGraph(
chunk,
m => m.type === "webassembly/async-experimental"
)
) {
return;
}
set.add(RuntimeGlobals.publicPath);
compilation.addRuntimeModule(
chunk,
new AsyncWasmChunkLoadingRuntimeModule(chunk, compilation, {
generateLoadBinaryCode,
supportsStreaming: false
})
);
});
}
);
}
}
module.exports = ReadFileCompileAsyncWasmPlugin;

View File

@ -56,8 +56,9 @@ class ReadFileCompileWasmPlugin {
.tap("ReadFileCompileWasmPlugin", (chunk, set) => {
const chunkGraph = compilation.chunkGraph;
if (
!chunkGraph.hasModuleInGraph(chunk, m =>
m.type.startsWith("webassembly")
!chunkGraph.hasModuleInGraph(
chunk,
m => m.type === "webassembly/experimental"
)
) {
return;

View File

@ -7,40 +7,35 @@
const { tokTypes: tt } = require("acorn");
const empty = [];
/** @typedef {typeof import("acorn").Parser} Parser */
module.exports = Parser => {
return class extends Parser {
/**
* @param {Parser} P the acorn parser
* @returns {Parser} new acron parser
*/
module.exports = P => {
const Base = /** @type {any} */ (P);
const NewParser = /** @type {unknown} */ (class extends Base {
parseImport(node) {
this.next();
// import await '...'
if (this.type === tt.name) {
if (this.value === "await") {
node.await = true;
this.next();
} else {
this.unexpected();
}
if (this.type === tt.name && this.value === "await") {
node.await = true;
} else {
node.await = false;
this.pos = this.start;
}
this.pos = this.start;
return super.parseImport(node);
}
parseExport(node) {
this.next();
// import await '...'
if (this.type === tt.name) {
if (this.value === "await") {
node.await = true;
this.next();
} else {
this.unexpected();
}
// export await '...'
if (this.type === tt.name && this.value === "await") {
node.await = true;
} else {
node.await = false;
this.pos = this.start;
}
this.pos = this.start;
const result = super.parseExport(node);
if (node.await && !node.source) {
this.raiseRecoverable(
@ -50,5 +45,6 @@ module.exports = Parser => {
}
return result;
}
};
});
return /** @type {Parser} */ (NewParser);
};

View File

@ -0,0 +1,88 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const RuntimeGlobals = require("../RuntimeGlobals");
const RuntimeModule = require("../RuntimeModule");
const Template = require("../Template");
class AsyncWasmChunkLoadingRuntimeModule extends RuntimeModule {
constructor(
chunk,
compilation,
{ generateLoadBinaryCode, supportsStreaming }
) {
super("wasm chunk loading", 10);
this.chunk = chunk;
this.compilation = compilation;
this.generateLoadBinaryCode = generateLoadBinaryCode;
this.supportsStreaming = supportsStreaming;
}
/**
* @returns {string} runtime code
*/
generate() {
const { compilation, chunk } = this;
const { mainTemplate, outputOptions } = compilation;
const fn = RuntimeGlobals.instantiateWasm;
const chunkModuleMaps = this.compilation.chunkGraph.getChunkModuleMaps(
chunk,
m => m.type.startsWith("webassembly"),
true
);
const wasmModuleSrcPath = mainTemplate.getAssetPath(
JSON.stringify(outputOptions.webassemblyModuleFilename),
{
hash: `" + ${RuntimeGlobals.getFullHash}() + "`,
hashWithLength: length =>
`" + ${RuntimeGlobals.getFullHash}}().slice(0, ${length}) + "`,
module: {
id: '" + wasmModuleId + "',
hash: `" + ${JSON.stringify(chunkModuleMaps.hash)}[wasmModuleId] + "`,
hashWithLength(length) {
const shortChunkHashMap = Object.create(null);
for (const wasmModuleId of Object.keys(chunkModuleMaps.hash)) {
if (typeof chunkModuleMaps.hash[wasmModuleId] === "string") {
shortChunkHashMap[wasmModuleId] = chunkModuleMaps.hash[
wasmModuleId
].substr(0, length);
}
}
return `" + ${JSON.stringify(shortChunkHashMap)}[wasmModuleId] + "`;
}
}
}
);
return Template.asString([
`${fn} = function(wasmModuleId, importsObj) {`,
Template.indent([
`var req = ${this.generateLoadBinaryCode(wasmModuleSrcPath)};`,
this.supportsStreaming
? Template.asString([
"if(typeof WebAssembly.instantiateStreaming === 'function') {",
Template.indent([
"return WebAssembly.instantiateStreaming(req, importsObj)",
Template.indent([
".then(function(res) { return res.instance.exports; });"
])
]),
"}"
])
: "// no support for streaming compilation",
"return req",
Template.indent([
".then(function(x) { return x.arrayBuffer(); })",
".then(function(bytes) { return WebAssembly.instantiate(bytes, importsObj); })",
".then(function(res) { return res.instance.exports; });"
])
]),
"};"
]);
}
}
module.exports = AsyncWasmChunkLoadingRuntimeModule;

View File

@ -0,0 +1,51 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const Generator = require("../Generator");
/** @typedef {import("webpack-sources").Source} Source */
/** @typedef {import("../Generator").GenerateContext} GenerateContext */
/** @typedef {import("../NormalModule")} NormalModule */
const TYPES = new Set(["webassembly"]);
class AsyncWebAssemblyGenerator extends Generator {
constructor(options) {
super();
this.options = options;
}
/**
* @returns {Set<string>} available types (do not mutate)
*/
getTypes() {
return TYPES;
}
/**
* @param {NormalModule} module the module
* @param {string=} type source type
* @returns {number} estimate size of the module
*/
getSize(module, type) {
const originalSource = module.originalSource();
if (!originalSource) {
return 0;
}
return originalSource.size();
}
/**
* @param {NormalModule} module module for which the code should be generated
* @param {GenerateContext} generateContext context for generate
* @returns {Source} generated code
*/
generate(module, generateContext) {
return module.originalSource();
}
}
module.exports = AsyncWebAssemblyGenerator;

View File

@ -0,0 +1,159 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const { RawSource } = require("webpack-sources");
const Generator = require("../Generator");
const RuntimeGlobals = require("../RuntimeGlobals");
const Template = require("../Template");
const WebAssemblyImportDependency = require("../dependencies/WebAssemblyImportDependency");
/** @typedef {import("webpack-sources").Source} Source */
/** @typedef {import("../DependencyTemplates")} DependencyTemplates */
/** @typedef {import("../Generator").GenerateContext} GenerateContext */
/** @typedef {import("../Module")} Module */
/** @typedef {import("../NormalModule")} NormalModule */
/** @typedef {import("../RuntimeTemplate")} RuntimeTemplate */
const TYPES = new Set(["webassembly"]);
class AsyncWebAssemblyJavascriptGenerator extends Generator {
constructor(filenameTemplate) {
super();
this.filenameTemplate = filenameTemplate;
}
/**
* @returns {Set<string>} available types (do not mutate)
*/
getTypes() {
return TYPES;
}
/**
* @param {NormalModule} module the module
* @param {string=} type source type
* @returns {number} estimate size of the module
*/
getSize(module, type) {
return 40 + module.dependencies.length * 10;
}
/**
* @param {NormalModule} module module for which the code should be generated
* @param {GenerateContext} generateContext context for generate
* @returns {Source} generated code
*/
generate(
module,
{ runtimeTemplate, chunkGraph, moduleGraph, runtimeRequirements }
) {
runtimeRequirements.add(RuntimeGlobals.module);
runtimeRequirements.add(RuntimeGlobals.instantiateWasm);
/** @type {Map<Module, { request: string, importVar: string }>} */
const depModules = new Map();
/** @type {Map<string, WebAssemblyImportDependency[]>} */
const wasmDepsByRequest = new Map();
for (const dep of module.dependencies) {
if (dep instanceof WebAssemblyImportDependency) {
const module = moduleGraph.getModule(dep);
if (!depModules.has(module)) {
depModules.set(module, {
request: dep.request,
importVar: `WEBPACK_IMPORTED_MODULE_${depModules.size}`
});
}
let list = wasmDepsByRequest.get(dep.request);
if (list === undefined) {
list = [];
wasmDepsByRequest.set(dep.request, list);
}
list.push(dep);
}
}
const promises = [];
const importStatements = Array.from(
depModules,
([importedModule, { request, importVar }]) => {
if (
importedModule.buildMeta &&
importedModule.buildMeta.exportsType === "async"
) {
promises.push(importVar);
}
return runtimeTemplate.importStatement({
update: false,
module: importedModule,
chunkGraph,
request,
originModule: module,
importVar,
runtimeRequirements
});
}
);
const importObjRequestItems = Array.from(
wasmDepsByRequest,
([request, deps]) => {
const exportItems = deps.map(dep => {
const importedModule = moduleGraph.getModule(dep);
const importVar = depModules.get(importedModule).importVar;
return `${JSON.stringify(
dep.name
)}: ${runtimeTemplate.exportFromImport({
moduleGraph,
module: importedModule,
request,
exportName: dep.name,
originModule: module,
asiSafe: true,
isCall: false,
callContext: false,
importVar,
runtimeRequirements
})}`;
});
return Template.asString([
`${JSON.stringify(request)}: {`,
Template.indent(exportItems.join(",\n")),
"}"
]);
}
);
const importsObj =
importObjRequestItems.length > 0
? Template.asString([
"{",
Template.indent(importObjRequestItems.join(",\n")),
"}"
])
: undefined;
const instantiateCall = importsObj
? `${RuntimeGlobals.instantiateWasm}(${
module.moduleArgument
}.i, ${importsObj})`
: `${RuntimeGlobals.instantiateWasm}(${module.moduleArgument}.i)`;
return new RawSource(
Template.asString([
...importStatements,
promises.length > 0
? `${module.moduleArgument}.exports = Promise.all([${promises.join(
", "
)}]).then(function([${promises.join(
", "
)}]) { return ${instantiateCall}; })`
: `${module.moduleArgument}.exports = ${instantiateCall}`
])
);
}
}
module.exports = AsyncWebAssemblyJavascriptGenerator;

View File

@ -0,0 +1,110 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const Generator = require("../Generator");
const WebAssemblyImportDependency = require("../dependencies/WebAssemblyImportDependency");
const { compareModulesById } = require("../util/comparators");
const AsyncWebAssemblyGenerator = require("./AsyncWebAssemblyGenerator");
const AsyncWebAssemblyJavascriptGenerator = require("./AsyncWebAssemblyJavascriptGenerator");
const AsyncWebAssemblyParser = require("./AsyncWebAssemblyParser");
/** @typedef {import("../Compiler")} Compiler */
/** @typedef {import("../Template").RenderManifestOptions} RenderManifestOptions} */
/** @typedef {import("../Template").RenderManifestEntry} RenderManifestEntry} */
class AsyncWebAssemblyModulesPlugin {
constructor(options) {
this.options = options;
}
/**
* @param {Compiler} compiler compiler
* @returns {void}
*/
apply(compiler) {
compiler.hooks.compilation.tap(
"AsyncWebAssemblyModulesPlugin",
(compilation, { normalModuleFactory }) => {
compilation.dependencyFactories.set(
WebAssemblyImportDependency,
normalModuleFactory
);
normalModuleFactory.hooks.createParser
.for("webassembly/async-experimental")
.tap("AsyncWebAssemblyModulesPlugin", () => {
return new AsyncWebAssemblyParser();
});
normalModuleFactory.hooks.createGenerator
.for("webassembly/async-experimental")
.tap("AsyncWebAssemblyModulesPlugin", () => {
return Generator.byType({
javascript: new AsyncWebAssemblyJavascriptGenerator(
compilation.outputOptions.webassemblyModuleFilename
),
webassembly: new AsyncWebAssemblyGenerator(this.options)
});
});
/**
*
* @param {RenderManifestEntry[]} result render entries
* @param {RenderManifestOptions} options context options
* @returns {RenderManifestEntry[]} render entries
*/
const handler = (result, options) => {
const { moduleGraph, chunkGraph, runtimeTemplate } = compilation;
const chunk = options.chunk;
const outputOptions = options.outputOptions;
const moduleTemplates = options.moduleTemplates;
const dependencyTemplates = options.dependencyTemplates;
for (const module of chunkGraph.getOrderedChunkModulesIterable(
chunk,
compareModulesById(chunkGraph)
)) {
if (module.type === "webassembly/async-experimental") {
const filenameTemplate = outputOptions.webassemblyModuleFilename;
result.push({
render: () =>
moduleTemplates.webassembly.render(module, {
chunk,
dependencyTemplates,
runtimeTemplate,
moduleGraph,
chunkGraph
}),
filenameTemplate,
pathOptions: {
module,
chunkGraph
},
identifier: `webassemblyAsyncModule${chunkGraph.getModuleId(
module
)}`,
hash: chunkGraph.getModuleHash(module)
});
}
}
return result;
};
compilation.chunkTemplate.hooks.renderManifest.tap(
"WebAssemblyModulesPlugin",
handler
);
compilation.mainTemplate.hooks.renderManifest.tap(
"WebAssemblyModulesPlugin",
handler
);
}
);
}
}
module.exports = AsyncWebAssemblyModulesPlugin;

View File

@ -0,0 +1,60 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const t = require("@webassemblyjs/ast");
const { decode } = require("@webassemblyjs/wasm-parser");
const StaticExportsDependency = require("../dependencies/StaticExportsDependency");
const WebAssemblyImportDependency = require("../dependencies/WebAssemblyImportDependency");
const decoderOpts = {
ignoreCodeSection: true,
ignoreDataSection: true,
// this will avoid having to lookup with identifiers in the ModuleContext
ignoreCustomNameSection: true
};
class WebAssemblyParser {
constructor(options) {
this.hooks = Object.freeze({});
this.options = options;
}
parse(binary, state) {
// flag it as async module
state.module.buildMeta.exportsType = "async";
// parse it
const program = decode(binary, decoderOpts);
const module = program.body[0];
const exports = [];
t.traverse(module, {
ModuleExport({ node }) {
exports.push(node.name);
},
ModuleImport({ node }) {
const dep = new WebAssemblyImportDependency(
node.module,
node.name,
node.descr,
false
);
state.module.addDependency(dep);
}
});
state.module.addDependency(new StaticExportsDependency(exports, false));
return state;
}
}
module.exports = WebAssemblyParser;

View File

@ -71,7 +71,7 @@ class WebAssemblyModulesPlugin {
chunk,
compareModulesById(chunkGraph)
)) {
if (module.getSourceTypes().has("webassembly")) {
if (module.type === "webassembly/experimental") {
const filenameTemplate =
outputOptions.webassemblyModuleFilename;
@ -111,7 +111,7 @@ class WebAssemblyModulesPlugin {
for (const chunk of compilation.chunks) {
if (chunk.canBeInitial()) {
for (const module of chunkGraph.getChunkModulesIterable(chunk)) {
if (module.getSourceTypes().has("webassembly")) {
if (module.type === "webassembly/experimental") {
initialWasmModules.add(module);
}
}

View File

@ -0,0 +1,51 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const RuntimeGlobals = require("../RuntimeGlobals");
const AsyncWasmChunkLoadingRuntimeModule = require("../wasm-async/AsyncWasmChunkLoadingRuntimeModule");
/** @typedef {import("../Compiler")} Compiler */
class FetchCompileAsyncWasmPlugin {
/**
* @param {Compiler} compiler the compiler instance
* @returns {void}
*/
apply(compiler) {
compiler.hooks.thisCompilation.tap(
"FetchCompileAsyncWasmPlugin",
compilation => {
const generateLoadBinaryCode = path =>
`fetch(${RuntimeGlobals.publicPath} + ${path})`;
compilation.hooks.runtimeRequirementInTree
.for(RuntimeGlobals.instantiateWasm)
.tap("FetchCompileAsyncWasmPlugin", (chunk, set) => {
const chunkGraph = compilation.chunkGraph;
if (
!chunkGraph.hasModuleInGraph(
chunk,
m => m.type === "webassembly/async-experimental"
)
) {
return;
}
set.add(RuntimeGlobals.publicPath);
compilation.addRuntimeModule(
chunk,
new AsyncWasmChunkLoadingRuntimeModule(chunk, compilation, {
generateLoadBinaryCode,
supportsStreaming: true
})
);
});
}
);
}
}
module.exports = FetchCompileAsyncWasmPlugin;

View File

@ -31,8 +31,9 @@ class FetchCompileWasmPlugin {
.tap("FetchCompileWasmPlugin", (chunk, set) => {
const chunkGraph = compilation.chunkGraph;
if (
!chunkGraph.hasModuleInGraph(chunk, m =>
m.type.startsWith("webassembly")
!chunkGraph.hasModuleInGraph(
chunk,
m => m.type === "webassembly/experimental"
)
) {
return;

View File

@ -164,7 +164,7 @@ const describeCases = config => {
{
test: /\.wat$/i,
loader: "wast-loader",
type: "webassembly/experimental"
type: "webassembly/async-experimental"
}
]
},

View File

@ -3508,47 +3508,47 @@ WARNING in Terser Plugin: Dropping unused function someUnRemoteUsedFunction5 [./
`;
exports[`StatsTestCases should print correct stats for wasm-explorer-examples-sync 1`] = `
"Hash: 48cd6bb29a775ac0f234
"Hash: 7693034941eee0a43725
Time: Xms
Built at: Thu Jan 01 1970 00:00:00 GMT
Asset Size Chunks Chunk Names
10d1272d7cf8dafe2f3a.module.wasm 225 bytes {780} [emitted]
230.bundle.js 430 bytes {230} [emitted]
325.bundle.js 3.9 KiB {325} [emitted]
230.bundle.js 211 bytes {230} [emitted]
325.bundle.js 3.95 KiB {325} [emitted]
3622e435c31cc7731064.module.wasm 154 bytes {325} [emitted]
3e3d5fe8a21d1b31908d.module.wasm 531 bytes {99} [emitted]
526.bundle.js 329 bytes {526} [emitted]
780.bundle.js 842 bytes {780} [emitted]
7eee906d414e0947ebbf.module.wasm 132 bytes {780} [emitted]
94b864234c573663c221.module.wasm 94 bytes {325} [emitted]
99.bundle.js 428 bytes {99} [emitted]
a160192b41d0463ac226.module.wasm 131 bytes {230} [emitted]
bundle.js 13.5 KiB {520} [emitted] main-1df31ce3
d95036d90a8b92bc2692.module.wasm 510 bytes {99} [emitted]
ff9c5233b4dbdf834f6f.module.wasm 125 bytes {325} [emitted]
780.bundle.js 503 bytes {780} [emitted]
7aead7b7c43084efa07b.module.wasm 156 bytes {230} [emitted]
86f780f1d4b7ccf9001b.module.wasm 120 bytes {325} [emitted]
99.bundle.js 209 bytes {99} [emitted]
b2e68013411cb5aefaa9.module.wasm 154 bytes {780} [emitted]
bundle.js 10.8 KiB {520} [emitted] main-1df31ce3
de81fc7e751725498c48.module.wasm 290 bytes {780} [emitted]
Entrypoint main = bundle.js
chunk {99} 99.bundle.js, d95036d90a8b92bc2692.module.wasm 100 bytes (javascript) 531 bytes (webassembly) [rendered]
[99] ./duff.wasm 100 bytes (javascript) 531 bytes (webassembly) {99} [built]
chunk {230} 230.bundle.js, a160192b41d0463ac226.module.wasm 100 bytes (javascript) 156 bytes (webassembly) [rendered]
[230] ./Q_rsqrt.wasm 100 bytes (javascript) 156 bytes (webassembly) {230} [built]
chunk {325} 325.bundle.js, 94b864234c573663c221.module.wasm, ff9c5233b4dbdf834f6f.module.wasm 1.6 KiB (javascript) 274 bytes (webassembly) [rendered]
[287] ./popcnt.wasm 100 bytes (javascript) 120 bytes (webassembly) {325} [built]
[325] ./tests.js 1.4 KiB {325} [built]
[819] ./testFunction.wasm 100 bytes (javascript) 154 bytes (webassembly) {325} [built]
chunk {520} bundle.js (main-1df31ce3) 586 bytes (javascript) 6.75 KiB (runtime) [entry] [rendered]
chunk {99} 99.bundle.js, 3e3d5fe8a21d1b31908d.module.wasm 50 bytes (javascript) 531 bytes (webassembly) [rendered]
[99] ./duff.wasm 50 bytes (javascript) 531 bytes (webassembly) {99} [built]
chunk {230} 230.bundle.js, 7aead7b7c43084efa07b.module.wasm 50 bytes (javascript) 156 bytes (webassembly) [rendered]
[230] ./Q_rsqrt.wasm 50 bytes (javascript) 156 bytes (webassembly) {230} [built]
chunk {325} 325.bundle.js, 86f780f1d4b7ccf9001b.module.wasm, 3622e435c31cc7731064.module.wasm 1.54 KiB (javascript) 274 bytes (webassembly) [rendered]
[287] ./popcnt.wasm 50 bytes (javascript) 120 bytes (webassembly) {325} [built]
[325] ./tests.js 1.44 KiB {325} [built]
[819] ./testFunction.wasm 50 bytes (javascript) 154 bytes (webassembly) {325} [built]
chunk {520} bundle.js (main-1df31ce3) 586 bytes (javascript) 5.09 KiB (runtime) [entry] [rendered]
[10] ./index.js 586 bytes {520} [built]
+ 7 hidden chunk modules
chunk {526} 526.bundle.js 34 bytes [rendered] split chunk (cache group: defaultVendors)
[526] ./node_modules/env.js 34 bytes {526} [built]
chunk {780} 780.bundle.js, 7eee906d414e0947ebbf.module.wasm, 10d1272d7cf8dafe2f3a.module.wasm 205 bytes (javascript) 444 bytes (webassembly) [rendered]
[143] ./fact.wasm 100 bytes (javascript) 154 bytes (webassembly) {780} [built]
[151] ./fast-math.wasm 105 bytes (javascript) 290 bytes (webassembly) {780} [built]
chunk {780} 780.bundle.js, b2e68013411cb5aefaa9.module.wasm, de81fc7e751725498c48.module.wasm 110 bytes (javascript) 444 bytes (webassembly) [rendered]
[143] ./fact.wasm 50 bytes (javascript) 154 bytes (webassembly) {780} [built]
[151] ./fast-math.wasm 60 bytes (javascript) 290 bytes (webassembly) {780} [built]
[10] ./index.js 586 bytes {520} [built]
[99] ./duff.wasm 100 bytes (javascript) 531 bytes (webassembly) {99} [built]
[143] ./fact.wasm 100 bytes (javascript) 154 bytes (webassembly) {780} [built]
[151] ./fast-math.wasm 105 bytes (javascript) 290 bytes (webassembly) {780} [built]
[230] ./Q_rsqrt.wasm 100 bytes (javascript) 156 bytes (webassembly) {230} [built]
[287] ./popcnt.wasm 100 bytes (javascript) 120 bytes (webassembly) {325} [built]
[325] ./tests.js 1.4 KiB {325} [built]
[99] ./duff.wasm 50 bytes (javascript) 531 bytes (webassembly) {99} [built]
[143] ./fact.wasm 50 bytes (javascript) 154 bytes (webassembly) {780} [built]
[151] ./fast-math.wasm 60 bytes (javascript) 290 bytes (webassembly) {780} [built]
[230] ./Q_rsqrt.wasm 50 bytes (javascript) 156 bytes (webassembly) {230} [built]
[287] ./popcnt.wasm 50 bytes (javascript) 120 bytes (webassembly) {325} [built]
[325] ./tests.js 1.44 KiB {325} [built]
[526] ./node_modules/env.js 34 bytes {526} [built]
[819] ./testFunction.wasm 100 bytes (javascript) 154 bytes (webassembly) {325} [built]
[819] ./testFunction.wasm 50 bytes (javascript) 154 bytes (webassembly) {325} [built]
+ 7 hidden modules"
`;

View File

@ -1 +1 @@
export * from "./module.wat";
export await * from "./module.wat";

View File

@ -1 +1 @@
export * from "./module.wat";
export await * from "./module.wat";

View File

@ -1,5 +0,0 @@
it("should allow to run a WebAssembly module importing JS circular", function() {
return import("./module").then(function(mod) {
expect(mod.result).toBe(42);
});
});

View File

@ -1,7 +0,0 @@
import { addNumber } from "./wasm.wat";
export var result = addNumber(22);
export function getNumber() {
return 20;
}

View File

@ -1,5 +0,0 @@
var supportsWebAssembly = require("../../../helpers/supportsWebAssembly");
module.exports = function(config) {
return supportsWebAssembly();
};

View File

@ -1,9 +0,0 @@
(module
(type $t0 (func (result i32)))
(type $t1 (func (param i32) (result i32)))
(import "./module" "getNumber" (func $./module.getNumber (type $t0)))
(func $addNumber (export "addNumber") (type $t1) (param $p0 i32) (result i32)
(i32.add
(get_local $p0)
(call $./module.getNumber))))

View File

@ -1,5 +0,0 @@
it("should allow to run a WebAssembly module importing from multiple modules", function() {
return import("./module").then(function(mod) {
expect(mod.result).toBe(42);
});
});

View File

@ -1,7 +0,0 @@
import { getResult } from "./wasm.wasm";
export var result = getResult(1);
export function getNumber() {
return 20;
}

View File

@ -1,5 +0,0 @@
import { getNumber as getN } from "./wasm.wasm";
export function getNumber() {
return getN();
}

View File

@ -1,5 +0,0 @@
var supportsWebAssembly = require("../../../helpers/supportsWebAssembly");
module.exports = function(config) {
return supportsWebAssembly();
};

View File

@ -1 +0,0 @@
export const n = 1;

View File

@ -1,17 +0,0 @@
module.exports = [
[
{moduleName: /export-i64-param\.wat/},
/Export "a" with i64 as parameter can only be used for direct wasm to wasm dependencies/,
{moduleTrace: /export-i64-param\.js/}
],
[
{moduleName: /export-i64-result\.wat/},
/Export "a" with i64 as result can only be used for direct wasm to wasm dependencies/,
{moduleTrace: /export-i64-result\.js/}
],
[
{moduleName: /import-i64\.wat/},
/Import "n" from "\.\/env.js" with Non-JS-compatible Global Type \(i64\) can only be used for direct wasm to wasm dependencies/,
{moduleTrace: /index\.js/}
]
]

View File

@ -1 +0,0 @@
export { a } from "./export-i64-param.wat";

View File

@ -1,3 +0,0 @@
(module
(func (export "a") (param i64) (nop))
)

View File

@ -1 +0,0 @@
export { a } from "./export-i64-result.wat";

View File

@ -1,5 +0,0 @@
(module
(func (export "a") (result i64)
(i64.const 1)
)
)

View File

@ -1,3 +0,0 @@
(module
(import "./env.js" "n" (global i64))
)

View File

@ -1,17 +0,0 @@
const errorRegex = /wasm function signature contains illegal type|invalid type/;
it("should disallow exporting a func signature with result i64", function() {
return import("./export-i64-result").then(({a}) => {
expect(() => a()).toThrow(errorRegex);
});
});
it("should disallow exporting a func signature with param i64", function() {
return import("./export-i64-param").then(({a}) => {
expect(() => a()).toThrow(errorRegex);
});
});
it("should disallow importing a value type of i64", function() {
return expect(import("./import-i64.wat")).rejects.toThrow(errorRegex);
});

View File

@ -1,5 +0,0 @@
var supportsWebAssembly = require("../../../helpers/supportsWebAssembly");
module.exports = function(config) {
return supportsWebAssembly() && config.mode === "production";
};

View File

@ -1,5 +1,5 @@
import * as a1 from "./mem-access.wat?1";
import * as a2 from "./mem-access.wat?2";
import await * as a1 from "./mem-access.wat?1";
import await * as a2 from "./mem-access.wat?2";
a1.set(42);
export const x1 = a1.get();

View File

@ -1,6 +1,6 @@
import { trackA, results } from "./tracker";
import "./b.js";
import "./wasm.wat";
import await "./wasm.wat";
trackA();

View File

@ -1,7 +1,8 @@
it("should be evaluated in the correct order", () => {
return import("./a").then(({ default: results }) => {
return Promise.resolve().then(() => { // wait an extra tick to get the tick from the tracker
expect(results).toEqual(["b", "c", "wasm42", "a", "tick"]);
return Promise.resolve().then(() => {
// wait an extra tick to get the tick from the tracker
expect(results).toEqual(["b", "c", "tick", "wasm42", "a"]);
});
});
});

View File

@ -1,4 +1,4 @@
import { add, getNumber } from "./wasm.wat?1";
import await { add, getNumber } from "./wasm.wat?1";
export function run() {
return add(getNumber(), 2);

View File

@ -2,7 +2,8 @@ const stringifyRequest = require("loader-utils").stringifyRequest;
module.exports.pitch = function(remainingRequest) {
return `
import { getString as _getString, memory } from ${stringifyRequest(this,
import await { getString as _getString, memory } from ${stringifyRequest(
this,
`${this.resourcePath}.wat!=!${remainingRequest}`
)};

View File

@ -2,7 +2,7 @@ const stringifyRequest = require("loader-utils").stringifyRequest;
module.exports.pitch = function(remainingRequest) {
return `
import { getString as _getString, memory } from ${stringifyRequest(
import await { getString as _getString, memory } from ${stringifyRequest(
this,
`${this.resourcePath}.wasm!=!wast-loader!${remainingRequest}`
)};

View File

@ -1,4 +1,4 @@
import { getNumber } from "./wasm.wat";
import await { getNumber } from "./wasm.wat";
export function run() {
return getNumber();

View File

@ -1,9 +1,9 @@
import * as Q_rsqrt from "./Q_rsqrt.wasm";
import * as testFunction from "./testFunction.wasm";
import * as fact from "./fact.wasm";
import * as popcnt from "./popcnt.wasm";
import * as fastMath from "./fast-math.wasm";
import * as duff from "./duff.wasm";
import await * as Q_rsqrt from "./Q_rsqrt.wasm";
import await * as testFunction from "./testFunction.wasm";
import await * as fact from "./fact.wasm";
import await * as popcnt from "./popcnt.wasm";
import await * as fastMath from "./fast-math.wasm";
import await * as duff from "./duff.wasm";
export function run_Q_rsqrt() {
const result = Q_rsqrt._Z7Q_rsqrtf(1/1764);

View File

@ -1,5 +1,5 @@
import { getNumber } from "./wasm.wat?1";
import { getNumber as getNumber2 } from "./wasm.wat?2";
import await { getNumber } from "./wasm.wat?1";
import await { getNumber as getNumber2 } from "./wasm.wat?2";
export function run() {
return getNumber() + getNumber2();

View File

@ -8,7 +8,7 @@ module.exports = {
{
test: /\.wat$/,
loader: "wast-loader",
type: "webassembly/experimental"
type: "webassembly/async-experimental"
}
]
},

View File

@ -1,9 +1,9 @@
import * as Q_rsqrt from "./Q_rsqrt.wasm";
import * as testFunction from "./testFunction.wasm";
import * as fact from "./fact.wasm";
import * as popcnt from "./popcnt.wasm";
import * as fastMath from "./fast-math.wasm";
import * as duff from "./duff.wasm";
import await * as Q_rsqrt from "./Q_rsqrt.wasm";
import await * as testFunction from "./testFunction.wasm";
import await * as fact from "./fact.wasm";
import await * as popcnt from "./popcnt.wasm";
import await * as fastMath from "./fast-math.wasm";
import await * as duff from "./duff.wasm";
export function run_Q_rsqrt() {
const result = Q_rsqrt._Z7Q_rsqrtf(1/1764);