Merge pull request #11267 from webpack/experiments/import-async

enable experiments.importAsync by default
This commit is contained in:
Tobias Koppers 2020-08-04 16:00:00 +02:00 committed by GitHub
commit 1273b9eb96
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
60 changed files with 397 additions and 578 deletions

View File

@ -882,14 +882,6 @@ export interface Experiments {
* Support WebAssembly as asynchronous EcmaScript Module.
*/
asyncWebAssembly?: boolean;
/**
* Allow 'import/export' syntax to import async modules.
*/
importAsync?: boolean;
/**
* Allow 'import/export await' syntax to import async modules.
*/
importAwait?: boolean;
/**
* Support .mjs files as way to define strict ESM file (node.js).
*/

View File

@ -25,30 +25,26 @@ export const close = () => {
But `db-connection.js` is no longer a normal module now.
It's an **async module** now.
Async modules have a different evaluation semantics.
While normal modules evaluate synchronously way, async modules evaluate asynchronously.
While normal modules evaluate synchronously, async modules evaluate asynchronously.
Async modules can't be imported with a normal `import`.
They need to be imported with `import await`.
Async modules can still be imported with a normal `import`.
But importing an async module makes the importing module also an async module.
The main reason for this is to make the using module aware of the different evaluation semantics.
The `import`s still hoist and are evaluated in parallel.
Using `import await` in a module also makes the module an async module.
You can see it as a form of top-level-await, but it's a bit different because imports hoist, so does `import await`.
All `import`s and `import await`s hoist and are evaluated in parallel.
`import await` doesn't affect tree shaking negatively.
Tree shaking still works as usual.
Here the `close` function is never used and will be removed from the output bundle in production mode.
# UserApi.js
```javascript
import await { dbCall } from "./db-connection.js";
import { dbCall } from "./db-connection.js";
export const createUser = async name => {
command = `CREATE USER ${name}`;
// This is a normal await, because it's in an async function
await dbCall({ command });
}
};
```
Now it looks like that this pattern will continue and will infect all using modules as async modules.
@ -60,7 +56,7 @@ But you as a developer don't want this.
You want to break the chain at a point in your module graph where it makes sense.
Luckily there is a nice way to break the chain.
You can use `import("./UserApi.js")` to import the module instead of `import await`.
You can use `import("./UserApi.js")` to import the module instead of `import`.
As this returns a Promise it can be awaited to wait for module evaluation (including top-level-awaits) and handle failures.
Handling failures is an important point here.
@ -99,8 +95,7 @@ export const AlternativeCreateUserAction = async name => {
// except in rare cases. It will import modules sequentially.
```
As `Actions.js` doesn't use any top-level-await nor `import await` it's not an async module.
It's a normal module and can be used via `import`.
As `Actions.js` doesn't use any top-level-await nor `import`s an async module directly so it's not an async module.
# example.js
@ -112,10 +107,6 @@ import { CreateUserAction } from "./Actions.js";
})();
```
Note that you may `import await` from a normal module too.
This is legal, but mostly not required.
`import await` may also be seen by developers as a hint that this dependency does some async actions and may delay evaluation.
As a guideline, you should prevent your application entry point to become an async module when compiling for web targets.
Doing async actions at application bootstrap will delay your application startup and may be negative for UX.
Use `import()` to do async action on-demand or in the background and use spinners or other indicators to inform the user about background actions.
@ -128,22 +119,41 @@ When compiling for other targets like node.js, electron or WebWorkers, it may be
/******/ (() => { // webpackBootstrap
/******/ "use strict";
/******/ var __webpack_modules__ = ([
/* 0 */,
/* 0 */
/*!********************!*\
!*** ./example.js ***!
\********************/
/*! namespace exports */
/*! exports [not provided] [no usage info] */
/*! runtime requirements: __webpack_require__, __webpack_require__.r, __webpack_exports__, __webpack_require__.* */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var _Actions_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Actions.js */ 1);
(async ()=> {
await (0,_Actions_js__WEBPACK_IMPORTED_MODULE_0__.CreateUserAction)("John");
})();
/***/ }),
/* 1 */
/*!********************!*\
!*** ./Actions.js ***!
\********************/
/*! namespace exports */
/*! export AlternativeCreateUserAction [provided] [unused] [could be renamed] */
/*! export CreateUserAction [provided] [used] [could be renamed] */
/*! other exports [not provided] [unused] */
/*! runtime requirements: __webpack_require__.e, __webpack_require__, __webpack_exports__, __webpack_require__.d, __webpack_require__.* */
/*! export AlternativeCreateUserAction [provided] [no usage info] [missing usage info prevents renaming] */
/*! export CreateUserAction [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__.e, __webpack_require__, __webpack_require__.d, __webpack_require__.* */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "CreateUserAction": () => /* binding */ CreateUserAction
/* harmony export */ "CreateUserAction": () => /* binding */ CreateUserAction,
/* harmony export */ "AlternativeCreateUserAction": () => /* binding */ AlternativeCreateUserAction
/* harmony export */ });
/* unused harmony export AlternativeCreateUserAction */
// import() doesn't care about whether a module is an async module or not
const UserApi = __webpack_require__.e(/*! import() */ 497).then(__webpack_require__.bind(__webpack_require__, /*! ./UserApi.js */ 2));
@ -247,6 +257,52 @@ const AlternativeCreateUserAction = async name => {
/******/ __webpack_require__.o = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop)
/******/ })();
/******/
/******/ /* webpack/runtime/load script */
/******/ (() => {
/******/ var inProgress = {};
/******/ // data-webpack is not used as build has no uniqueName
/******/ // loadScript function to load a script via script tag
/******/ __webpack_require__.l = (url, done, key) => {
/******/ if(inProgress[url]) { inProgress[url].push(done); return; }
/******/ var script, needAttach;
/******/ if(key !== undefined) {
/******/ var scripts = document.getElementsByTagName("script");
/******/ for(var i = 0; i < scripts.length; i++) {
/******/ var s = scripts[i];
/******/ if(s.getAttribute("src") == url) { script = s; break; }
/******/ }
/******/ }
/******/ if(!script) {
/******/ needAttach = true;
/******/ script = document.createElement('script');
/******/
/******/ script.charset = 'utf-8';
/******/ script.timeout = 120;
/******/ if (__webpack_require__.nc) {
/******/ script.setAttribute("nonce", __webpack_require__.nc);
/******/ }
/******/
/******/ script.src = url;
/******/ }
/******/ inProgress[url] = [done];
/******/ var onScriptComplete = (prev, event) => {
/******/ // avoid mem leaks in IE.
/******/ script.onerror = script.onload = null;
/******/ clearTimeout(timeout);
/******/ var doneFns = inProgress[url];
/******/ delete inProgress[url];
/******/ script.parentNode && script.parentNode.removeChild(script);
/******/ doneFns && doneFns.forEach((fn) => fn(event));
/******/ if(prev) return prev(event);
/******/ }
/******/ ;
/******/ var timeout = setTimeout(onScriptComplete.bind(null, undefined, { type: 'timeout', target: script }), 120000);
/******/ script.onerror = onScriptComplete.bind(null, script.onerror);
/******/ script.onload = onScriptComplete.bind(null, script.onload);
/******/ needAttach && document.head.appendChild(script);
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/make namespace object */
/******/ (() => {
/******/ // define __esModule on exports
@ -291,49 +347,24 @@ const AlternativeCreateUserAction = async name => {
/******/
/******/ // start chunk loading
/******/ var url = __webpack_require__.p + __webpack_require__.u(chunkId);
/******/ var loadingEnded = () => {
/******/ // create error before stack unwound to get useful stacktrace later
/******/ var error = new Error();
/******/ var loadingEnded = (event) => {
/******/ if(__webpack_require__.o(installedChunks, chunkId)) {
/******/ installedChunkData = installedChunks[chunkId];
/******/ if(installedChunkData !== 0) installedChunks[chunkId] = undefined;
/******/ if(installedChunkData) return installedChunkData[1];
/******/ if(installedChunkData) {
/******/ var errorType = event && (event.type === 'load' ? 'missing' : event.type);
/******/ var realSrc = event && event.target && event.target.src;
/******/ error.message = 'Loading chunk ' + chunkId + ' failed.\n(' + errorType + ': ' + realSrc + ')';
/******/ error.name = 'ChunkLoadError';
/******/ error.type = errorType;
/******/ error.request = realSrc;
/******/ installedChunkData[1](error);
/******/ }
/******/ }
/******/ };
/******/ 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;
/******/
/******/ // create error before stack unwound to get useful stacktrace later
/******/ var error = new Error();
/******/ onScriptComplete = (event) => {
/******/ onScriptComplete = () => {
/******/
/******/ }
/******/ // 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;
/******/ error.message = 'Loading chunk ' + chunkId + ' failed.\n(' + errorType + ': ' + realSrc + ')';
/******/ error.name = 'ChunkLoadError';
/******/ error.type = errorType;
/******/ error.request = realSrc;
/******/ reportError(error);
/******/ }
/******/ }
/******/ ;
/******/ var timeout = setTimeout(() => {
/******/ onScriptComplete({ type: 'timeout', target: script })
/******/ }, 120000);
/******/ script.onerror = script.onload = onScriptComplete;
/******/ document.head.appendChild(script);
/******/ __webpack_require__.l(url, loadingEnded, "chunk-" + chunkId);
/******/ } else installedChunks[chunkId] = 0;
/******/ }
/******/ }
@ -390,22 +421,10 @@ const AlternativeCreateUserAction = async name => {
</details>
``` js
(() => {
/*!********************!*\
!*** ./example.js ***!
\********************/
/*! namespace exports */
/*! exports [not provided] [unused] */
/*! runtime requirements: __webpack_require__ */
/* harmony import */ var _Actions_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Actions.js */ 1);
(async ()=> {
await (0,_Actions_js__WEBPACK_IMPORTED_MODULE_0__.CreateUserAction)("John");
})();
})();
/******/ // startup
/******/ // Load entry module
/******/ __webpack_require__(0);
/******/ // This entry module used 'exports' so it can't be inlined
/******/ })()
;
```
@ -421,8 +440,8 @@ const AlternativeCreateUserAction = async name => {
!*** ./UserApi.js ***!
\********************/
/*! namespace exports */
/*! export createUser [provided] [maybe used (runtime-defined)] [usage prevents renaming] */
/*! other exports [not provided] [maybe used (runtime-defined)] */
/*! export createUser [provided] [no usage info] [missing usage info prevents renaming] */
/*! other exports [not provided] [no usage info] */
/*! runtime requirements: __webpack_require__, __webpack_require__.r, __webpack_exports__, module, __webpack_require__.d, __webpack_require__.* */
/***/ ((module, __webpack_exports__, __webpack_require__) => {
@ -440,7 +459,7 @@ const createUser = async name => {
command = `CREATE USER ${name}`;
// This is a normal await, because it's in an async function
await (0,_db_connection_js__WEBPACK_IMPORTED_MODULE_0__.dbCall)({ command });
}
};
return __webpack_exports__;
})();
@ -451,18 +470,19 @@ return __webpack_exports__;
!*** ./db-connection.js ***!
\**************************/
/*! namespace exports */
/*! export close [provided] [unused] [could be renamed] */
/*! export dbCall [provided] [used] [could be renamed] */
/*! other exports [not provided] [unused] */
/*! runtime requirements: module, __webpack_exports__, __webpack_require__.d, __webpack_require__.* */
/*! export close [provided] [no usage info] [missing usage info prevents renaming] */
/*! export dbCall [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__.d, __webpack_require__.* */
/***/ ((module, __webpack_exports__, __webpack_require__) => {
"use strict";
module.exports = (async () => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "dbCall": () => /* binding */ dbCall
/* harmony export */ "dbCall": () => /* binding */ dbCall,
/* harmony export */ "close": () => /* binding */ close
/* harmony export */ });
/* unused harmony export close */
const connectToDB = async url => {
await new Promise(r => setTimeout(r, 1000));
};
@ -499,34 +519,34 @@ return __webpack_exports__;
```
Hash: 0a1b2c3d4e5f6a7b8c9d
Version: webpack 5.0.0-beta.16
Asset Size
497.output.js 2.39 KiB [emitted]
output.js 10.7 KiB [emitted] [name: main]
Version: webpack 5.0.0-beta.23
asset 497.output.js 2.53 KiB [emitted]
asset output.js 12.2 KiB [emitted] (name: main)
Entrypoint main = output.js
chunk output.js (main) 1.19 KiB (javascript) 4.76 KiB (runtime) [entry] [rendered]
chunk output.js (main) 1.19 KiB (javascript) 5.46 KiB (runtime) [entry] [rendered]
> ./example.js main
./Actions.js 1.09 KiB [built]
[exports: AlternativeCreateUserAction, CreateUserAction]
[only some exports used: CreateUserAction]
[used exports unknown]
harmony side effect evaluation ./Actions.js ./example.js 1:0-48
harmony import specifier ./Actions.js ./example.js 4:7-23
./example.js 103 bytes [built]
[no exports]
[no exports used]
[used exports unknown]
entry ./example.js main
+ 7 hidden chunk modules
chunk 497.output.js 622 bytes [rendered]
+ 8 hidden chunk modules
chunk 497.output.js 617 bytes [rendered]
> ./UserApi.js ./Actions.js 22:30-52
> ./UserApi.js ./Actions.js 2:16-38
./UserApi.js 220 bytes [built]
./UserApi.js 215 bytes [built]
[exports: createUser]
[used exports unknown]
import() ./UserApi.js ./Actions.js 2:16-38
import() ./UserApi.js ./Actions.js 22:30-52
./db-connection.js 402 bytes [built]
[exports: close, dbCall]
[only some exports used: dbCall]
harmony side effect evaluation ./db-connection.js ./UserApi.js 1:0-50
[used exports unknown]
harmony side effect evaluation ./db-connection.js ./UserApi.js 1:0-44
harmony import specifier ./db-connection.js ./UserApi.js 6:7-13
```
@ -534,28 +554,27 @@ chunk 497.output.js 622 bytes [rendered]
```
Hash: 0a1b2c3d4e5f6a7b8c9d
Version: webpack 5.0.0-beta.16
Asset Size
497.output.js 475 bytes [emitted]
output.js 1.65 KiB [emitted] [name: main]
Version: webpack 5.0.0-beta.23
asset 497.output.js 475 bytes [emitted]
asset output.js 2 KiB [emitted] (name: main)
Entrypoint main = output.js
chunk output.js (main) 1.19 KiB (javascript) 4.76 KiB (runtime) [entry] [rendered]
chunk (runtime: main) output.js (main) 1.19 KiB (javascript) 5.46 KiB (runtime) [entry] [rendered]
> ./example.js main
./example.js + 1 modules 1.19 KiB [built]
[no exports]
[no exports used]
entry ./example.js main
+ 7 hidden chunk modules
chunk 497.output.js 622 bytes [rendered]
+ 8 hidden chunk modules
chunk (runtime: main) 497.output.js 617 bytes [rendered]
> ./UserApi.js ./Actions.js 22:30-52
> ./UserApi.js ./Actions.js 2:16-38
./UserApi.js 220 bytes [built]
./UserApi.js 215 bytes [built]
[exports: createUser]
import() ./UserApi.js ./example.js + 1 modules ./Actions.js 2:16-38
import() ./UserApi.js ./example.js + 1 modules ./Actions.js 22:30-52
./db-connection.js 402 bytes [built]
[exports: close, dbCall]
[only some exports used: dbCall]
harmony side effect evaluation ./db-connection.js ./UserApi.js 1:0-50
harmony side effect evaluation ./db-connection.js ./UserApi.js 1:0-44
harmony import specifier ./db-connection.js ./UserApi.js 6:7-13
```

View File

@ -1,7 +1,7 @@
import await { dbCall } from "./db-connection.js";
import { dbCall } from "./db-connection.js";
export const createUser = async name => {
command = `CREATE USER ${name}`;
// This is a normal await, because it's in an async function
await dbCall({ command });
}
};

View File

@ -12,16 +12,12 @@ It's an **async module** now.
Async modules have a different evaluation semantics.
While normal modules evaluate synchronously, async modules evaluate asynchronously.
Async modules can't be imported with a normal `import`.
They need to be imported with `import await`.
Async modules can still be imported with a normal `import`.
But importing an async module makes the importing module also an async module.
The main reason for this is to make the using module aware of the different evaluation semantics.
The `import`s still hoist and are evaluated in parallel.
Using `import await` in a module also makes the module an async module.
You can see it as a form of top-level-await, but it's a bit different because imports hoist, so does `import await`.
All `import`s and `import await`s hoist and are evaluated in parallel.
`import await` doesn't affect tree shaking negatively.
Tree shaking still works as usual.
Here the `close` function is never used and will be removed from the output bundle in production mode.
# UserApi.js
@ -39,7 +35,7 @@ But you as a developer don't want this.
You want to break the chain at a point in your module graph where it makes sense.
Luckily there is a nice way to break the chain.
You can use `import("./UserApi.js")` to import the module instead of `import await`.
You can use `import("./UserApi.js")` to import the module instead of `import`.
As this returns a Promise it can be awaited to wait for module evaluation (including top-level-awaits) and handle failures.
Handling failures is an important point here.
@ -52,8 +48,7 @@ In this example connecting to the DB may fail.
_{{Actions.js}}_
```
As `Actions.js` doesn't use any top-level-await nor `import await` it's not an async module.
It's a normal module and can be used via `import`.
As `Actions.js` doesn't use any top-level-await nor `import`s an async module directly so it's not an async module.
# example.js
@ -61,10 +56,6 @@ It's a normal module and can be used via `import`.
_{{example.js}}_
```
Note that you may `import await` from a normal module too.
This is legal, but mostly not required.
`import await` may also be seen by developers as a hint that this dependency does some async actions and may delay evaluation.
As a guideline, you should prevent your application entry point to become an async module when compiling for web targets.
Doing async actions at application bootstrap will delay your application startup and may be negative for UX.
Use `import()` to do async action on-demand or in the background and use spinners or other indicators to inform the user about background actions.

View File

@ -3,7 +3,6 @@ module.exports = {
chunkIds: "deterministic" // To keep filename consistent between different modes (for example building only)
},
experiments: {
topLevelAwait: true,
importAwait: true
topLevelAwait: true
}
};

View File

@ -1,7 +1,7 @@
# example.js
```javascript
import await { get, set, getNumber } from "./magic.js";
import { get, set, getNumber } from "./magic.js";
// accessing memory
console.log(get());
@ -20,7 +20,7 @@ console.log(getNumber());
```javascript
// reexporting
export await * from "./magic.wat";
export * from "./magic.wat";
```
# magic.wat
@ -78,11 +78,12 @@ export const memory = await getMemoryFromParentInWorker();
!*** ./example.js ***!
\********************/
/*! namespace exports */
/*! exports [not provided] [unused] */
/*! runtime requirements: __webpack_require__, module, __webpack_exports__ */
/*! exports [not provided] [no usage info] */
/*! runtime requirements: __webpack_require__, __webpack_require__.r, __webpack_exports__, module, __webpack_require__.* */
/***/ ((module, __webpack_exports__, __webpack_require__) => {
module.exports = (async () => {
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var _magic_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./magic.js */ 1);
_magic_js__WEBPACK_IMPORTED_MODULE_0__ = await Promise.resolve(_magic_js__WEBPACK_IMPORTED_MODULE_0__);
@ -108,14 +109,15 @@ return __webpack_exports__;
!*** ./magic.js ***!
\******************/
/*! namespace exports */
/*! export get [provided] [used] [could be renamed] */
/*! export getNumber [provided] [used] [could be renamed] */
/*! export set [provided] [used] [could be renamed] */
/*! other exports [not provided] [unused] */
/*! runtime requirements: __webpack_require__, __webpack_exports__, __webpack_require__.d, module, __webpack_require__.* */
/*! export get [provided] [no usage info] [missing usage info prevents renaming] */
/*! export getNumber [provided] [no usage info] [missing usage info prevents renaming] */
/*! export set [provided] [no usage info] [missing usage info prevents renaming] */
/*! other exports [not provided] [no usage info] */
/*! runtime requirements: __webpack_require__, __webpack_exports__, __webpack_require__.d, __webpack_require__.r, module, __webpack_require__.* */
/***/ ((module, __webpack_exports__, __webpack_require__) => {
module.exports = (async () => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "get": () => /* reexport safe */ _magic_wat__WEBPACK_IMPORTED_MODULE_0__.get,
/* harmony export */ "getNumber": () => /* reexport safe */ _magic_wat__WEBPACK_IMPORTED_MODULE_0__.getNumber,
@ -135,17 +137,17 @@ return __webpack_exports__;
!*** ./magic.wat ***!
\*******************/
/*! namespace exports */
/*! export get [provided] [used] [provision prevents renaming] */
/*! export getNumber [provided] [used] [provision prevents renaming] */
/*! export set [provided] [used] [provision prevents renaming] */
/*! other exports [not provided] [unused] */
/*! export get [provided] [no usage info] [provision prevents renaming (no use info)] */
/*! export getNumber [provided] [no usage info] [provision prevents renaming (no use info)] */
/*! export set [provided] [no usage info] [provision prevents renaming (no use info)] */
/*! other exports [not provided] [no usage info] */
/*! runtime requirements: module, module.id, __webpack_exports__, __webpack_require__.v, __webpack_require__, __webpack_require__.* */
/***/ ((module, exports, __webpack_require__) => {
/* harmony import */ var WEBPACK_IMPORTED_MODULE_0 = __webpack_require__(/*! ./memory.js */ 3);
/* harmony import */ var WEBPACK_IMPORTED_MODULE_1 = __webpack_require__(/*! ./magic-number.js */ 4);
module.exports = Promise.resolve(WEBPACK_IMPORTED_MODULE_0).then((WEBPACK_IMPORTED_MODULE_0) => {
return __webpack_require__.v(exports, module.id, {
return __webpack_require__.v(exports, module.id, "493198b38242c233ec44", {
"./memory.js": {
"memory": WEBPACK_IMPORTED_MODULE_0.memory
},
@ -161,12 +163,13 @@ module.exports = Promise.resolve(WEBPACK_IMPORTED_MODULE_0).then((WEBPACK_IMPORT
!*** ./memory.js ***!
\*******************/
/*! namespace exports */
/*! export memory [provided] [used] [could be renamed] */
/*! other exports [not provided] [unused] */
/*! runtime requirements: module, __webpack_exports__, __webpack_require__.d, __webpack_require__.* */
/*! export memory [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__.d, __webpack_require__.* */
/***/ ((module, __webpack_exports__, __webpack_require__) => {
module.exports = (async () => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "memory": () => /* binding */ memory
/* harmony export */ });
@ -187,16 +190,17 @@ return __webpack_exports__;
!*** ./magic-number.js ***!
\*************************/
/*! namespace exports */
/*! export getNumber [provided] [unused] [could be renamed] */
/*! export getRandomNumber [provided] [used] [could be renamed] */
/*! other exports [not provided] [unused] */
/*! runtime requirements: __webpack_exports__, __webpack_require__.d, __webpack_require__.* */
/*! export getNumber [provided] [no usage info] [missing usage info prevents renaming] */
/*! export getRandomNumber [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__.d, __webpack_require__.* */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "getNumber": () => /* binding */ getNumber,
/* harmony export */ "getRandomNumber": () => /* binding */ getRandomNumber
/* harmony export */ });
/* unused harmony export getNumber */
function getNumber() {
return 42;
}
@ -255,6 +259,17 @@ function getRandomNumber() {
/******/ __webpack_require__.o = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop)
/******/ })();
/******/
/******/ /* webpack/runtime/make namespace object */
/******/ (() => {
/******/ // define __esModule on exports
/******/ __webpack_require__.r = (exports) => {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/publicPath */
/******/ (() => {
/******/ __webpack_require__.p = "dist/";
@ -262,16 +277,16 @@ function getRandomNumber() {
/******/
/******/ /* webpack/runtime/wasm chunk loading */
/******/ (() => {
/******/ __webpack_require__.v = function(exports, wasmModuleId, importsObj) {
/******/ var req = fetch(__webpack_require__.p + "" + {"2":"4961ae1f00405983e33f"}[wasmModuleId] + ".module.wasm");
/******/ if(typeof WebAssembly.instantiateStreaming === 'function') {
/******/ __webpack_require__.v = (exports, wasmModuleId, wasmModuleHash, importsObj) => {
/******/ var req = fetch(__webpack_require__.p + "" + wasmModuleHash + ".module.wasm");
/******/ if (typeof WebAssembly.instantiateStreaming === 'function') {
/******/ return WebAssembly.instantiateStreaming(req, importsObj)
/******/ .then(function(res) { return Object.assign(exports, res.instance.exports); });
/******/ .then((res) => Object.assign(exports, res.instance.exports));
/******/ }
/******/ return req
/******/ .then(function(x) { return x.arrayBuffer(); })
/******/ .then(function(bytes) { return WebAssembly.instantiate(bytes, importsObj); })
/******/ .then(function(res) { return Object.assign(exports, res.instance.exports); });
/******/ .then((x) => x.arrayBuffer())
/******/ .then((bytes) => WebAssembly.instantiate(bytes, importsObj))
/******/ .then((res) => Object.assign(exports, res.instance.exports));
/******/ };
/******/ })();
/******/
@ -295,25 +310,24 @@ function getRandomNumber() {
```
Hash: 0a1b2c3d4e5f6a7b8c9d
Version: webpack 5.0.0-beta.16
Asset Size
4961ae1f00405983e33f.module.wasm 139 bytes [emitted] [immutable] [name: (main)]
output.js 7.84 KiB [emitted] [name: main]
Entrypoint main = output.js (4961ae1f00405983e33f.module.wasm)
chunk output.js (main) 708 bytes (javascript) 139 bytes (webassembly) 1.01 KiB (runtime) [entry] [rendered]
Version: webpack 5.0.0-beta.23
asset 493198b38242c233ec44.module.wasm 139 bytes [emitted] [immutable] (auxiliary name: main)
asset output.js 8.8 KiB [emitted] (name: main)
Entrypoint main = output.js (493198b38242c233ec44.module.wasm)
chunk output.js (main) 696 bytes (javascript) 139 bytes (webassembly) 1.2 KiB (runtime) [entry] [rendered]
> ./example.js main
./example.js 253 bytes [built]
./example.js 247 bytes [built]
[no exports]
[no exports used]
[used exports unknown]
entry ./example.js main
./magic-number.js 124 bytes [built]
[exports: getNumber, getRandomNumber]
[only some exports used: getRandomNumber]
[used exports unknown]
wasm import ./magic-number.js ./magic.wat
./magic.js 50 bytes [built]
./magic.js 44 bytes [built]
[exports: get, getNumber, set]
[all exports used]
harmony side effect evaluation ./magic.js ./example.js 1:0-55
[used exports unknown]
harmony side effect evaluation ./magic.js ./example.js 1:0-49
harmony import specifier ./magic.js ./example.js 4:12-15
harmony import specifier ./magic.js ./example.js 5:0-3
harmony import specifier ./magic.js ./example.js 6:12-15
@ -324,28 +338,27 @@ chunk output.js (main) 708 bytes (javascript) 139 bytes (webassembly) 1.01 KiB (
harmony import specifier ./magic.js ./example.js 13:12-21
./magic.wat 70 bytes (javascript) 139 bytes (webassembly) [built]
[exports: get, getNumber, set]
[all exports used]
harmony side effect evaluation ./magic.wat ./magic.js 2:0-34
harmony export imported specifier ./magic.wat ./magic.js 2:0-34
[used exports unknown]
harmony side effect evaluation ./magic.wat ./magic.js 2:0-28
harmony export imported specifier ./magic.wat ./magic.js 2:0-28
./memory.js 211 bytes [built]
[exports: memory]
[all exports used]
[used exports unknown]
wasm import ./memory.js ./magic.wat
+ 4 hidden chunk modules
+ 5 hidden chunk modules
```
## Production mode
```
Hash: 0a1b2c3d4e5f6a7b8c9d
Version: webpack 5.0.0-beta.16
Asset Size
4636ea8e62e0734a195f.module.wasm 139 bytes [emitted] [immutable] [name: (main)]
output.js 1.52 KiB [emitted] [name: main]
Entrypoint main = output.js (4636ea8e62e0734a195f.module.wasm)
chunk output.js (main) 708 bytes (javascript) 139 bytes (webassembly) 1.01 KiB (runtime) [entry] [rendered]
Version: webpack 5.0.0-beta.23
asset b873a21e71d2d93bad48.module.wasm 139 bytes [emitted] [immutable] (auxiliary name: main)
asset output.js 1.43 KiB [emitted] (name: main)
Entrypoint main = output.js (b873a21e71d2d93bad48.module.wasm)
chunk (runtime: main) output.js (main) 696 bytes (javascript) 139 bytes (webassembly) 950 bytes (runtime) [entry] [rendered]
> ./example.js main
./example.js 253 bytes [built]
./example.js 247 bytes [built]
[no exports]
[no exports used]
entry ./example.js main
@ -353,10 +366,10 @@ chunk output.js (main) 708 bytes (javascript) 139 bytes (webassembly) 1.01 KiB (
[exports: getNumber, getRandomNumber]
[only some exports used: getRandomNumber]
wasm import ./magic-number.js ./magic.wat
./magic.js 50 bytes [built]
./magic.js 44 bytes [built]
[exports: get, getNumber, set]
[all exports used]
harmony side effect evaluation ./magic.js ./example.js 1:0-55
harmony side effect evaluation ./magic.js ./example.js 1:0-49
harmony import specifier ./magic.js ./example.js 4:12-15
harmony import specifier ./magic.js ./example.js 5:0-3
harmony import specifier ./magic.js ./example.js 6:12-15
@ -368,8 +381,8 @@ chunk output.js (main) 708 bytes (javascript) 139 bytes (webassembly) 1.01 KiB (
./magic.wat 70 bytes (javascript) 139 bytes (webassembly) [built]
[exports: get, getNumber, set]
[all exports used]
harmony side effect evaluation ./magic.wat ./magic.js 2:0-34
harmony export imported specifier ./magic.wat ./magic.js 2:0-34
harmony side effect evaluation ./magic.wat ./magic.js 2:0-28
harmony export imported specifier ./magic.wat ./magic.js 2:0-28
./memory.js 211 bytes [built]
[exports: memory]
[all exports used]

View File

@ -1,4 +1,4 @@
import await { get, set, getNumber } from "./magic.js";
import { get, set, getNumber } from "./magic.js";
// accessing memory
console.log(get());

View File

@ -1,2 +1,2 @@
// reexporting
export await * from "./magic.wat";
export * from "./magic.wat";

View File

@ -17,7 +17,6 @@ module.exports = {
},
experiments: {
asyncWebAssembly: true,
topLevelAwait: true,
importAwait: true
topLevelAwait: true
}
};

View File

@ -1,13 +1,19 @@
This is a simple example that shows the usage of WebAssembly.
WebAssembly modules can be imported like other async modules with `import await` or `import()`.
WebAssembly modules can be imported like other async modules with `import` or `import()`.
When importing, they are downloaded and instantiated in a streaming way.
# example.js
```javascript
import await { add } from "./add.wasm";
import await { add as mathAdd, factorial, factorialJavascript, fibonacci, fibonacciJavascript } from "./math";
import { add } from "./add.wasm";
import {
add as mathAdd,
factorial,
factorialJavascript,
fibonacci,
fibonacciJavascript
} from "./math";
console.log(add(22, 2200));
console.log(mathAdd(10, 101));
@ -21,34 +27,31 @@ timed("wasm fibonacci", () => fibonacci(22));
timed("js fibonacci", () => fibonacciJavascript(22));
function timed(name, fn) {
if(!console.time || !console.timeEnd)
return fn();
if (!console.time || !console.timeEnd) return fn();
// warmup
for(var i = 0; i < 10; i++)
fn();
console.time(name)
for(var i = 0; i < 5000; i++)
fn();
console.timeEnd(name)
for (var i = 0; i < 10; i++) fn();
console.time(name);
for (var i = 0; i < 5000; i++) fn();
console.timeEnd(name);
}
```
# math.js
```javascript
import await { add } from "./add.wasm";
import await { factorial } from "./factorial.wasm";
import await { fibonacci } from "./fibonacci.wasm";
import { add } from "./add.wasm";
import { factorial } from "./factorial.wasm";
import { fibonacci } from "./fibonacci.wasm";
export { add, factorial, fibonacci };
export function factorialJavascript(i) {
if(i < 1) return 1;
if (i < 1) return 1;
return i * factorialJavascript(i - 1);
}
export function fibonacciJavascript(i) {
if(i < 2) return 1;
if (i < 2) return 1;
return fibonacciJavascript(i - 1) + fibonacciJavascript(i - 2);
}
```
@ -64,11 +67,12 @@ export function fibonacciJavascript(i) {
!*** ./example.js ***!
\********************/
/*! namespace exports */
/*! exports [not provided] [unused] */
/*! runtime requirements: __webpack_require__, module, __webpack_exports__ */
/*! exports [not provided] [no usage info] */
/*! runtime requirements: __webpack_require__, __webpack_require__.r, __webpack_exports__, module, __webpack_require__.* */
/***/ ((module, __webpack_exports__, __webpack_require__) => {
module.exports = (async () => {
__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);
([_math__WEBPACK_IMPORTED_MODULE_1__, _add_wasm__WEBPACK_IMPORTED_MODULE_0__] = await Promise.all([_math__WEBPACK_IMPORTED_MODULE_1__, _add_wasm__WEBPACK_IMPORTED_MODULE_0__]));
@ -87,15 +91,12 @@ timed("wasm fibonacci", () => (0,_math__WEBPACK_IMPORTED_MODULE_1__.fibonacci)(2
timed("js fibonacci", () => (0,_math__WEBPACK_IMPORTED_MODULE_1__.fibonacciJavascript)(22));
function timed(name, fn) {
if(!console.time || !console.timeEnd)
return fn();
if (!console.time || !console.timeEnd) return fn();
// warmup
for(var i = 0; i < 10; i++)
fn();
console.time(name)
for(var i = 0; i < 5000; i++)
fn();
console.timeEnd(name)
for (var i = 0; i < 10; i++) fn();
console.time(name);
for (var i = 0; i < 5000; i++) fn();
console.timeEnd(name);
}
return __webpack_exports__;
@ -107,12 +108,12 @@ return __webpack_exports__;
!*** ./add.wasm ***!
\******************/
/*! namespace exports */
/*! export add [provided] [used] [provision prevents renaming] */
/*! other exports [not provided] [unused] */
/*! export add [provided] [no usage info] [provision prevents renaming (no use info)] */
/*! other exports [not provided] [no usage info] */
/*! runtime requirements: module, module.id, __webpack_exports__, __webpack_require__.v, __webpack_require__.* */
/***/ ((module, exports, __webpack_require__) => {
module.exports = __webpack_require__.v(exports, module.id)
module.exports = __webpack_require__.v(exports, module.id, "937efcc237fa853c54c5")
/***/ }),
/* 2 */
@ -120,16 +121,17 @@ module.exports = __webpack_require__.v(exports, module.id)
!*** ./math.js ***!
\*****************/
/*! namespace exports */
/*! export add [provided] [used] [could be renamed] */
/*! export factorial [provided] [used] [could be renamed] */
/*! export factorialJavascript [provided] [used] [could be renamed] */
/*! export fibonacci [provided] [used] [could be renamed] */
/*! export fibonacciJavascript [provided] [used] [could be renamed] */
/*! other exports [not provided] [unused] */
/*! runtime requirements: __webpack_require__, __webpack_exports__, __webpack_require__.d, module, __webpack_require__.* */
/*! 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__, __webpack_exports__, __webpack_require__.d, __webpack_require__.r, module, __webpack_require__.* */
/***/ ((module, __webpack_exports__, __webpack_require__) => {
module.exports = (async () => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "add": () => /* reexport safe */ _add_wasm__WEBPACK_IMPORTED_MODULE_0__.add,
/* harmony export */ "factorial": () => /* reexport safe */ _factorial_wasm__WEBPACK_IMPORTED_MODULE_1__.factorial,
@ -148,12 +150,12 @@ module.exports = (async () => {
function factorialJavascript(i) {
if(i < 1) return 1;
if (i < 1) return 1;
return i * factorialJavascript(i - 1);
}
function fibonacciJavascript(i) {
if(i < 2) return 1;
if (i < 2) return 1;
return fibonacciJavascript(i - 1) + fibonacciJavascript(i - 2);
}
@ -166,12 +168,12 @@ return __webpack_exports__;
!*** ./factorial.wasm ***!
\************************/
/*! namespace exports */
/*! export factorial [provided] [used] [provision prevents renaming] */
/*! other exports [not provided] [unused] */
/*! export factorial [provided] [no usage info] [provision prevents renaming (no use info)] */
/*! other exports [not provided] [no usage info] */
/*! runtime requirements: module, module.id, __webpack_exports__, __webpack_require__.v, __webpack_require__.* */
/***/ ((module, exports, __webpack_require__) => {
module.exports = __webpack_require__.v(exports, module.id)
module.exports = __webpack_require__.v(exports, module.id, "39f1d275c85dc3f2ce74")
/***/ }),
/* 4 */
@ -179,12 +181,12 @@ module.exports = __webpack_require__.v(exports, module.id)
!*** ./fibonacci.wasm ***!
\************************/
/*! namespace exports */
/*! export fibonacci [provided] [used] [provision prevents renaming] */
/*! other exports [not provided] [unused] */
/*! export fibonacci [provided] [no usage info] [provision prevents renaming (no use info)] */
/*! other exports [not provided] [no usage info] */
/*! runtime requirements: module, module.id, __webpack_exports__, __webpack_require__.v, __webpack_require__.* */
/***/ ((module, exports, __webpack_require__) => {
module.exports = __webpack_require__.v(exports, module.id)
module.exports = __webpack_require__.v(exports, module.id, "8daa7a900abbba23d2f2")
/***/ })
/******/ ]);
@ -235,6 +237,17 @@ module.exports = __webpack_require__.v(exports, module.id)
/******/ __webpack_require__.o = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop)
/******/ })();
/******/
/******/ /* webpack/runtime/make namespace object */
/******/ (() => {
/******/ // define __esModule on exports
/******/ __webpack_require__.r = (exports) => {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/publicPath */
/******/ (() => {
/******/ __webpack_require__.p = "dist/";
@ -242,16 +255,16 @@ module.exports = __webpack_require__.v(exports, module.id)
/******/
/******/ /* webpack/runtime/wasm chunk loading */
/******/ (() => {
/******/ __webpack_require__.v = function(exports, wasmModuleId, importsObj) {
/******/ var req = fetch(__webpack_require__.p + "" + {"1":"1c8378066da027821f98","3":"9989aee1a31bab8d342f","4":"aa9360d4a460c66559cc"}[wasmModuleId] + ".wasm");
/******/ if(typeof WebAssembly.instantiateStreaming === 'function') {
/******/ __webpack_require__.v = (exports, wasmModuleId, wasmModuleHash, importsObj) => {
/******/ var req = fetch(__webpack_require__.p + "" + wasmModuleHash + ".wasm");
/******/ if (typeof WebAssembly.instantiateStreaming === 'function') {
/******/ return WebAssembly.instantiateStreaming(req, importsObj)
/******/ .then(function(res) { return Object.assign(exports, res.instance.exports); });
/******/ .then((res) => Object.assign(exports, res.instance.exports));
/******/ }
/******/ return req
/******/ .then(function(x) { return x.arrayBuffer(); })
/******/ .then(function(bytes) { return WebAssembly.instantiate(bytes, importsObj); })
/******/ .then(function(res) { return Object.assign(exports, res.instance.exports); });
/******/ .then((x) => x.arrayBuffer())
/******/ .then((bytes) => WebAssembly.instantiate(bytes, importsObj))
/******/ .then((res) => Object.assign(exports, res.instance.exports));
/******/ };
/******/ })();
/******/
@ -275,98 +288,96 @@ module.exports = __webpack_require__.v(exports, module.id)
```
Hash: 0a1b2c3d4e5f6a7b8c9d
Version: webpack 5.0.0-beta.16
Asset Size
1c8378066da027821f98.wasm 41 bytes [emitted] [immutable] [name: (main)]
9989aee1a31bab8d342f.wasm 62 bytes [emitted] [immutable] [name: (main)]
aa9360d4a460c66559cc.wasm 67 bytes [emitted] [immutable] [name: (main)]
output.js 8.2 KiB [emitted] [name: main]
Entrypoint main = output.js (1c8378066da027821f98.wasm 9989aee1a31bab8d342f.wasm aa9360d4a460c66559cc.wasm)
chunk output.js (main) 1.3 KiB (javascript) 170 bytes (webassembly) 1.06 KiB (runtime) [entry] [rendered]
Version: webpack 5.0.0-beta.23
asset 39f1d275c85dc3f2ce74.wasm 62 bytes [emitted] [immutable] (auxiliary name: main)
asset 8daa7a900abbba23d2f2.wasm 67 bytes [emitted] [immutable] (auxiliary name: main)
asset 937efcc237fa853c54c5.wasm 41 bytes [emitted] [immutable] (auxiliary name: main)
asset output.js 8.97 KiB [emitted] (name: main)
Entrypoint main = output.js (39f1d275c85dc3f2ce74.wasm 8daa7a900abbba23d2f2.wasm 937efcc237fa853c54c5.wasm)
chunk output.js (main) 1.27 KiB (javascript) 170 bytes (webassembly) 1.19 KiB (runtime) [entry] [rendered]
> ./example.js main
./add.wasm 50 bytes (javascript) 41 bytes (webassembly) [built]
[exports: add]
[all exports used]
harmony side effect evaluation ./add.wasm ./example.js 1:0-39
harmony import specifier ./add.wasm ./example.js 4:12-15
harmony side effect evaluation ./add.wasm ./math.js 1:0-39
[used exports unknown]
harmony side effect evaluation ./add.wasm ./example.js 1:0-33
harmony import specifier ./add.wasm ./example.js 10:12-15
harmony side effect evaluation ./add.wasm ./math.js 1:0-33
harmony export imported specifier ./add.wasm ./math.js 5:0-37
./example.js 761 bytes [built]
./example.js 753 bytes [built]
[no exports]
[no exports used]
[used exports unknown]
entry ./example.js main
./factorial.wasm 50 bytes (javascript) 62 bytes (webassembly) [built]
[exports: factorial]
[all exports used]
harmony side effect evaluation ./factorial.wasm ./math.js 2:0-51
[used exports unknown]
harmony side effect evaluation ./factorial.wasm ./math.js 2:0-45
harmony export imported specifier ./factorial.wasm ./math.js 5:0-37
./fibonacci.wasm 50 bytes (javascript) 67 bytes (webassembly) [built]
[exports: fibonacci]
[all exports used]
harmony side effect evaluation ./fibonacci.wasm ./math.js 3:0-51
[used exports unknown]
harmony side effect evaluation ./fibonacci.wasm ./math.js 3:0-45
harmony export imported specifier ./fibonacci.wasm ./math.js 5:0-37
./math.js 418 bytes [built]
./math.js 402 bytes [built]
[exports: add, factorial, factorialJavascript, fibonacci, fibonacciJavascript]
[all exports used]
harmony side effect evaluation ./math ./example.js 2:0-110
harmony import specifier ./math ./example.js 5:12-19
harmony import specifier ./math ./example.js 6:12-21
harmony import specifier ./math ./example.js 7:12-31
harmony import specifier ./math ./example.js 8:12-21
harmony import specifier ./math ./example.js 9:12-31
harmony import specifier ./math ./example.js 10:30-39
harmony import specifier ./math ./example.js 11:28-47
harmony import specifier ./math ./example.js 12:30-39
harmony import specifier ./math ./example.js 13:28-47
+ 4 hidden chunk modules
[used exports unknown]
harmony side effect evaluation ./math ./example.js 2:0-8:16
harmony import specifier ./math ./example.js 11:12-19
harmony import specifier ./math ./example.js 12:12-21
harmony import specifier ./math ./example.js 13:12-31
harmony import specifier ./math ./example.js 14:12-21
harmony import specifier ./math ./example.js 15:12-31
harmony import specifier ./math ./example.js 16:30-39
harmony import specifier ./math ./example.js 17:28-47
harmony import specifier ./math ./example.js 18:30-39
harmony import specifier ./math ./example.js 19:28-47
+ 5 hidden chunk modules
```
## Production mode
```
Hash: 0a1b2c3d4e5f6a7b8c9d
Version: webpack 5.0.0-beta.16
Asset Size
5ba3e3921117e9d828f5.wasm 67 bytes [emitted] [immutable] [name: (main)]
5dd947250fab86306d49.wasm 62 bytes [emitted] [immutable] [name: (main)]
6f6c0ffc52ce3a45ff7e.wasm 41 bytes [emitted] [immutable] [name: (main)]
output.js 1.67 KiB [emitted] [name: main]
Entrypoint main = output.js (5ba3e3921117e9d828f5.wasm 5dd947250fab86306d49.wasm 6f6c0ffc52ce3a45ff7e.wasm)
chunk output.js (main) 1.3 KiB (javascript) 170 bytes (webassembly) 1.06 KiB (runtime) [entry] [rendered]
Version: webpack 5.0.0-beta.23
asset 402d0640d802f4390f09.wasm 41 bytes [emitted] [immutable] (auxiliary name: main)
asset 79f27550455ff7b728fb.wasm 62 bytes [emitted] [immutable] (auxiliary name: main)
asset c473e4ed21f109fed4d9.wasm 67 bytes [emitted] [immutable] (auxiliary name: main)
asset output.js 1.58 KiB [emitted] (name: main)
Entrypoint main = output.js (402d0640d802f4390f09.wasm 79f27550455ff7b728fb.wasm c473e4ed21f109fed4d9.wasm)
chunk (runtime: main) output.js (main) 1.27 KiB (javascript) 170 bytes (webassembly) 943 bytes (runtime) [entry] [rendered]
> ./example.js main
./add.wasm 50 bytes (javascript) 41 bytes (webassembly) [built]
[exports: add]
[all exports used]
harmony side effect evaluation ./add.wasm ./example.js 1:0-39
harmony import specifier ./add.wasm ./example.js 4:12-15
harmony side effect evaluation ./add.wasm ./math.js 1:0-39
harmony side effect evaluation ./add.wasm ./example.js 1:0-33
harmony import specifier ./add.wasm ./example.js 10:12-15
harmony side effect evaluation ./add.wasm ./math.js 1:0-33
harmony export imported specifier ./add.wasm ./math.js 5:0-37
./example.js 761 bytes [built]
./example.js 753 bytes [built]
[no exports]
[no exports used]
entry ./example.js main
./factorial.wasm 50 bytes (javascript) 62 bytes (webassembly) [built]
[exports: factorial]
[all exports used]
harmony side effect evaluation ./factorial.wasm ./math.js 2:0-51
harmony side effect evaluation ./factorial.wasm ./math.js 2:0-45
harmony export imported specifier ./factorial.wasm ./math.js 5:0-37
./fibonacci.wasm 50 bytes (javascript) 67 bytes (webassembly) [built]
[exports: fibonacci]
[all exports used]
harmony side effect evaluation ./fibonacci.wasm ./math.js 3:0-51
harmony side effect evaluation ./fibonacci.wasm ./math.js 3:0-45
harmony export imported specifier ./fibonacci.wasm ./math.js 5:0-37
./math.js 418 bytes [built]
./math.js 402 bytes [built]
[exports: add, factorial, factorialJavascript, fibonacci, fibonacciJavascript]
[all exports used]
harmony side effect evaluation ./math ./example.js 2:0-110
harmony import specifier ./math ./example.js 5:12-19
harmony import specifier ./math ./example.js 6:12-21
harmony import specifier ./math ./example.js 7:12-31
harmony import specifier ./math ./example.js 8:12-21
harmony import specifier ./math ./example.js 9:12-31
harmony import specifier ./math ./example.js 10:30-39
harmony import specifier ./math ./example.js 11:28-47
harmony import specifier ./math ./example.js 12:30-39
harmony import specifier ./math ./example.js 13:28-47
harmony side effect evaluation ./math ./example.js 2:0-8:16
harmony import specifier ./math ./example.js 11:12-19
harmony import specifier ./math ./example.js 12:12-21
harmony import specifier ./math ./example.js 13:12-31
harmony import specifier ./math ./example.js 14:12-21
harmony import specifier ./math ./example.js 15:12-31
harmony import specifier ./math ./example.js 16:30-39
harmony import specifier ./math ./example.js 17:28-47
harmony import specifier ./math ./example.js 18:30-39
harmony import specifier ./math ./example.js 19:28-47
+ 4 hidden chunk modules
```

View File

@ -1,5 +1,11 @@
import await { add } from "./add.wasm";
import await { add as mathAdd, factorial, factorialJavascript, fibonacci, fibonacciJavascript } from "./math";
import { add } from "./add.wasm";
import {
add as mathAdd,
factorial,
factorialJavascript,
fibonacci,
fibonacciJavascript
} from "./math";
console.log(add(22, 2200));
console.log(mathAdd(10, 101));
@ -13,13 +19,10 @@ timed("wasm fibonacci", () => fibonacci(22));
timed("js fibonacci", () => fibonacciJavascript(22));
function timed(name, fn) {
if(!console.time || !console.timeEnd)
return fn();
if (!console.time || !console.timeEnd) return fn();
// warmup
for(var i = 0; i < 10; i++)
fn();
console.time(name)
for(var i = 0; i < 5000; i++)
fn();
console.timeEnd(name)
for (var i = 0; i < 10; i++) fn();
console.time(name);
for (var i = 0; i < 5000; i++) fn();
console.timeEnd(name);
}

View File

@ -1,15 +1,15 @@
import await { add } from "./add.wasm";
import await { factorial } from "./factorial.wasm";
import await { fibonacci } from "./fibonacci.wasm";
import { add } from "./add.wasm";
import { factorial } from "./factorial.wasm";
import { fibonacci } from "./fibonacci.wasm";
export { add, factorial, fibonacci };
export function factorialJavascript(i) {
if(i < 1) return 1;
if (i < 1) return 1;
return i * factorialJavascript(i - 1);
}
export function fibonacciJavascript(i) {
if(i < 2) return 1;
if (i < 2) return 1;
return fibonacciJavascript(i - 1) + fibonacciJavascript(i - 2);
}

View File

@ -1,6 +1,6 @@
This is a simple example that shows the usage of WebAssembly.
WebAssembly modules can be imported like other async modules with `import await` or `import()`.
WebAssembly modules can be imported like other async modules with `import` or `import()`.
When importing, they are downloaded and instantiated in a streaming way.
# example.js

View File

@ -16,7 +16,6 @@ module.exports = {
chunkIds: "deterministic" // To keep filename consistent between different modes (for example building only)
},
experiments: {
asyncWebAssembly: true,
importAwait: true
asyncWebAssembly: true
}
};

View File

@ -305,13 +305,7 @@ class WebpackOptionsApply extends OptionsApply {
new RuntimePlugin().apply(compiler);
new InferAsyncModulesPlugin({
errorOnImport: options.experiments.importAsync
? false
: options.experiments.importAwait
? "await"
: true
}).apply(compiler);
new InferAsyncModulesPlugin().apply(compiler);
new DataUriPlugin().apply(compiler);
new FileUriPlugin().apply(compiler);
@ -319,8 +313,7 @@ class WebpackOptionsApply extends OptionsApply {
new CompatibilityPlugin().apply(compiler);
new HarmonyModulesPlugin({
module: options.module,
topLevelAwait: options.experiments.topLevelAwait,
importAwait: options.experiments.importAwait
topLevelAwait: options.experiments.topLevelAwait
}).apply(compiler);
if (options.amd !== false) {
const AMDPlugin = require("./dependencies/AMDPlugin");

View File

@ -5,21 +5,12 @@
"use strict";
const WebpackError = require("../WebpackError");
const HarmonyImportDependency = require("../dependencies/HarmonyImportDependency");
const HarmonyImportSideEffectDependency = require("../dependencies/HarmonyImportSideEffectDependency");
/** @typedef {import("../Compiler")} Compiler */
/** @typedef {import("../Module")} Module */
class InferAsyncModulesPlugin {
/**
* @param {Object} options options object
* @param {boolean | "await"=} options.errorOnImport false: no error, true: error when importing async module, "await": error when import async module without import await
*/
constructor({ errorOnImport = false } = {}) {
this.errorOnImport = errorOnImport;
}
/**
* Apply the plugin
* @param {Compiler} compiler the compiler instance
@ -47,20 +38,6 @@ class InferAsyncModulesPlugin {
dep instanceof HarmonyImportDependency &&
connection.isActive(undefined)
) {
if (
this.errorOnImport &&
dep instanceof HarmonyImportSideEffectDependency &&
(this.errorOnImport === true || !dep.await)
) {
const error = new WebpackError(
this.errorOnImport === true
? "Tried to import async module with import/export (must enable experiments.importAsync to allow this)"
: "Tried to import async module with normal import/export (must use 'import await'/'export await' instead)"
);
error.module = module;
error.loc = dep.loc;
compilation.errors.push(error);
}
queue.add(connection.originModule);
}
}

View File

@ -222,8 +222,6 @@ const applyWebpackOptionsDefaults = options => {
const applyExperimentsDefaults = experiments => {
D(experiments, "asset", false);
D(experiments, "mjs", false);
D(experiments, "importAwait", false);
D(experiments, "importAsync", false);
D(experiments, "topLevelAwait", false);
D(experiments, "syncWebAssembly", false);
D(experiments, "asyncWebAssembly", false);

View File

@ -20,7 +20,6 @@ module.exports = class HarmonyExportDependencyParserPlugin {
constructor(options) {
const { module: moduleOptions } = options;
this.strictExportPresence = moduleOptions.strictExportPresence;
this.importAwait = options.importAwait;
}
apply(parser) {
@ -50,15 +49,9 @@ module.exports = class HarmonyExportDependencyParserPlugin {
source,
parser.state.lastHarmonyImportOrder
);
sideEffectDep.await = statement.await;
sideEffectDep.loc = Object.create(statement.loc);
sideEffectDep.loc.index = -1;
parser.state.current.addDependency(sideEffectDep);
if (statement.await && !this.importAwait) {
throw new Error(
"Used 'export await' but import-await experiment is not enabled (set experiments.importAwait: true to enable it)"
);
}
return true;
}
);

View File

@ -34,7 +34,6 @@ module.exports = class HarmonyImportDependencyParserPlugin {
const { module: moduleOptions } = options;
this.strictExportPresence = moduleOptions.strictExportPresence;
this.strictThisContextOnImports = moduleOptions.strictThisContextOnImports;
this.importAwait = options.importAwait;
}
apply(parser) {
@ -51,13 +50,7 @@ module.exports = class HarmonyImportDependencyParserPlugin {
parser.state.lastHarmonyImportOrder
);
sideEffectDep.loc = statement.loc;
sideEffectDep.await = statement.await;
parser.state.module.addDependency(sideEffectDep);
if (statement.await && !this.importAwait) {
throw new Error(
"Used 'import await' but import-await experiment is not enabled (set experiments.importAwait: true to enable it)"
);
}
return true;
}
);

View File

@ -52,7 +52,7 @@ const EMPTY_ARRAY = [];
// Syntax: https://developer.mozilla.org/en/SpiderMonkey/Parser_API
const parser = AcornParser.extend(require("../parsing/importAwaitAcornPlugin"));
const parser = AcornParser;
class VariableInfo {
/**

View File

@ -1,50 +0,0 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const { tokTypes: tt } = require("acorn");
/** @typedef {typeof import("acorn").Parser} Parser */
/**
* @param {Parser} P the acorn parser
* @returns {Parser} new acorn 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 && this.value === "await") {
node.await = true;
} else {
node.await = false;
this.pos = this.start;
}
return super.parseImport(node);
}
parseExport(node) {
this.next();
// export await '...'
if (this.type === tt.name && this.value === "await") {
node.await = true;
} else {
node.await = false;
this.pos = this.start;
}
const result = super.parseExport(node);
if (node.await && !node.source) {
this.raiseRecoverable(
node.start,
"Missing from source in export await"
);
}
return result;
}
});
return /** @type {Parser} */ (NewParser);
};

View File

@ -368,14 +368,6 @@
"description": "Support WebAssembly as asynchronous EcmaScript Module.",
"type": "boolean"
},
"importAsync": {
"description": "Allow 'import/export' syntax to import async modules.",
"type": "boolean"
},
"importAwait": {
"description": "Allow 'import/export await' syntax to import async modules.",
"type": "boolean"
},
"mjs": {
"description": "Support .mjs files as way to define strict ESM file (node.js).",
"type": "boolean"

View File

@ -91,8 +91,6 @@ describe("Defaults", () => {
"experiments": Object {
"asset": false,
"asyncWebAssembly": false,
"importAsync": false,
"importAwait": false,
"mjs": false,
"outputModule": false,
"syncWebAssembly": false,
@ -715,9 +713,8 @@ describe("Defaults", () => {
@@ ... @@
- "asyncWebAssembly": false,
+ "asyncWebAssembly": true,
@@ ... @@
- "mjs": false,
+ "asyncWebAssembly": true,
+ "mjs": true,
@@ ... @@
+ },

View File

@ -179,9 +179,7 @@ const describeCases = config => {
experiments: {
mjs: true,
asyncWebAssembly: true,
topLevelAwait: true,
importAwait: true,
importAsync: true
topLevelAwait: true
}
};
beforeAll(done => {

View File

@ -354,32 +354,6 @@ Object {
"multiple": false,
"simpleType": "boolean",
},
"experiments-import-async": Object {
"configs": Array [
Object {
"description": "Allow 'import/export' syntax to import async modules.",
"multiple": false,
"path": "experiments.importAsync",
"type": "boolean",
},
],
"description": "Allow 'import/export' syntax to import async modules.",
"multiple": false,
"simpleType": "boolean",
},
"experiments-import-await": Object {
"configs": Array [
Object {
"description": "Allow 'import/export await' syntax to import async modules.",
"multiple": false,
"path": "experiments.importAwait",
"type": "boolean",
},
],
"description": "Allow 'import/export await' syntax to import async modules.",
"multiple": false,
"simpleType": "boolean",
},
"experiments-mjs": Object {
"configs": Array [
Object {

View File

@ -4299,7 +4299,7 @@ WARNING in Terser Plugin: Dropping unused function someUnRemoteUsedFunction5 [we
`;
exports[`StatsTestCases should print correct stats for wasm-explorer-examples-sync 1`] = `
"Hash: 236a7aafb9e23319b3b2
"Hash: bcdac54c787768809ad1
Time: X ms
Built at: 1970-04-20 12:42:42
asset 0506579c50fa5de37901.module.wasm 531 bytes [emitted] [immutable]
@ -4322,17 +4322,17 @@ chunk (runtime: main) bundle.js (main) 586 bytes (javascript) 5.96 KiB (runtime)
+ 9 hidden chunk modules
chunk (runtime: main) 230.bundle.js 50 bytes (javascript) 156 bytes (webassembly) [rendered]
./Q_rsqrt.wasm 50 bytes (javascript) 156 bytes (webassembly) [built]
chunk (runtime: main) 325.bundle.js 1.54 KiB (javascript) 274 bytes (webassembly) [rendered]
chunk (runtime: main) 325.bundle.js 1.5 KiB (javascript) 274 bytes (webassembly) [rendered]
./popcnt.wasm 50 bytes (javascript) 120 bytes (webassembly) [built]
./testFunction.wasm 50 bytes (javascript) 154 bytes (webassembly) [built]
./tests.js 1.44 KiB [built]
./tests.js 1.4 KiB [built]
chunk (runtime: main) 526.bundle.js (id hint: vendors) 34 bytes [rendered] split chunk (cache group: defaultVendors)
./node_modules/env.js 34 bytes [built]
chunk (runtime: main) 780.bundle.js 110 bytes (javascript) 444 bytes (webassembly) [rendered]
./fact.wasm 50 bytes (javascript) 154 bytes (webassembly) [built]
./fast-math.wasm 60 bytes (javascript) 290 bytes (webassembly) [built]
./index.js 586 bytes [built]
./tests.js 1.44 KiB [built]
./tests.js 1.4 KiB [built]
./Q_rsqrt.wasm 50 bytes (javascript) 156 bytes (webassembly) [built]
./testFunction.wasm 50 bytes (javascript) 154 bytes (webassembly) [built]
./fact.wasm 50 bytes (javascript) 154 bytes (webassembly) [built]

View File

@ -1,6 +0,0 @@
it("should allow to use import await", () => {
return import("./reexport").then(({ default: value, other }) => {
expect(value).toBe(42);
expect(other).toBe(42);
});
});

View File

@ -1 +0,0 @@
export default 42;

View File

@ -1,4 +0,0 @@
export await { default } from "./module";
import await value from "./module";
export const other = value;

View File

@ -1,6 +0,0 @@
it("should allow to use import await", () => {
return import("./reexport").then(({ default: value, other }) => {
expect(value).toBe(42);
expect(other).toBe(42);
});
});

View File

@ -1,3 +0,0 @@
await new Promise(r => setTimeout(r, 100));
export default 42;

View File

@ -1,4 +0,0 @@
export { default } from "./module";
import value from "./module";
export const other = value;

View File

@ -1,4 +1,4 @@
it("should allow to use import await", () => {
it("should allow to use top-level-await", () => {
return import("./reexport").then(({ default: value, other }) => {
expect(value).toBe(42);
expect(other).toBe(42);

View File

@ -1,4 +1,4 @@
export await { default } from "./module";
import await value from "./module";
export { default } from "./module";
import value from "./module";
export const other = value;

View File

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

View File

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

View File

@ -1,4 +1,4 @@
import await { addNumber } from "./wasm.wat";
import { addNumber } from "./wasm.wat";
export var result = addNumber(22);

View File

@ -1,4 +1,4 @@
import await { getResult } from "./wasm.wasm";
import { getResult } from "./wasm.wasm";
export var result = getResult(1);

View File

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

View File

@ -1,5 +1,5 @@
import await * as a1 from "./mem-access.wat?1";
import await * as a2 from "./mem-access.wat?2";
import * as a1 from "./mem-access.wat?1";
import * 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 await "./wasm.wat";
import "./wasm.wat";
trackA();

View File

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

View File

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

View File

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

View File

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

View File

@ -1,9 +1,9 @@
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";
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";
export function run_Q_rsqrt() {
const result = Q_rsqrt._Z7Q_rsqrtf(1/1764);

View File

@ -9,8 +9,5 @@ module.exports = {
"failing-promise-external":
"promise new Promise((resolve, reject) => setTimeout(() => reject(new Error('external reject')), 100))",
"import-external": ["import /hello/world.js", "request"]
},
experiments: {
importAsync: true
}
};

View File

@ -1,6 +1,6 @@
import { A, B, C1, C2, D1, D2, E1, E2, E3, F, G } from "./test";
export { a, b, c, d, e };
export { a, b, c, d };
if (Math.random() > 0.5) {
var a = () => A;
@ -26,21 +26,21 @@ while (Math.random() > 0.5) {
let d = () => D1;
}
if(false) {
if (false) {
E1();
}
export var e = true ? E2 : E3;
export { f, g }
export { f, g };
if(true) {
if (true) {
let inner = () => F;
var f = () => inner();
}
if(true) {
if (true) {
const inner = () => G;
var g = () => inner();

View File

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

View File

@ -18,8 +18,7 @@ module.exports = {
webassemblyModuleFilename: "[id].[hash].wasm"
},
experiments: {
asyncWebAssembly: true,
importAwait: true
asyncWebAssembly: true
},
plugins: [
/**

View File

@ -1 +0,0 @@
module.exports = [[/experiments\.importAsync/]];

View File

@ -1,3 +0,0 @@
it("should not compile the module", function () {
expect(() => require("./module"));
});

View File

@ -1,3 +0,0 @@
import { getNumber } from "./wasm.wat";
export default getNumber();

View File

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

View File

@ -1,5 +0,0 @@
(module
(func $getNumber (export "getNumber") (result i32)
(i32.const 42))
)

View File

@ -1,15 +0,0 @@
/** @type {import("../../../../").Configuration} */
module.exports = {
module: {
rules: [
{
test: /\.wat$/,
loader: "wast-loader",
type: "webassembly/async"
}
]
},
experiments: {
asyncWebAssembly: true
}
};

View File

@ -14,7 +14,6 @@ module.exports = {
]
},
experiments: {
syncWebAssembly: true,
importAwait: true
syncWebAssembly: true
}
};

View File

@ -1,9 +1,9 @@
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";
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";
export function run_Q_rsqrt() {
const result = Q_rsqrt._Z7Q_rsqrtf(1/1764);

View File

@ -19,7 +19,6 @@ module.exports = {
modules: true
},
experiments: {
asyncWebAssembly: true,
importAwait: true
asyncWebAssembly: true
}
};

10
types.d.ts vendored
View File

@ -2521,16 +2521,6 @@ declare interface Experiments {
*/
asyncWebAssembly?: boolean;
/**
* Allow 'import/export' syntax to import async modules.
*/
importAsync?: boolean;
/**
* Allow 'import/export await' syntax to import async modules.
*/
importAwait?: boolean;
/**
* Support .mjs files as way to define strict ESM file (node.js).
*/