Skip to content

Commit 8bc82da

Browse files
authored
Merge pull request webpack#6128 from webpack/bugfix/wasm-esm-and-exports
WASM bugfixes/improvements (fix weird extra default)
2 parents 44209f6 + 91e6692 commit 8bc82da

File tree

42 files changed

+165
-147
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+165
-147
lines changed

examples/wasm-simple/README.md

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ export function fibonacciJavascript(i) {
186186
/******/
187187
/******/ // a Promise means "currently loading" or "already loaded".
188188
/******/ promises.push(installedWasmModuleData ||
189-
/******/ (installedWasmModules[wasmModuleId] = fetch(__webpack_require__.p + "" + {"1":"27bb124d07adac2541fe","3":"0e736bedbc15ed9c8e33","4":"435e0d0a43195d073ec9"}[wasmModuleId] + ".wasm").then(function(response) {
189+
/******/ (installedWasmModules[wasmModuleId] = fetch(__webpack_require__.p + "" + {"1":"77ca5181080bbc4c2f55","3":"b6b19efd9d04360b0a8d","4":"61f7b7b231ff2e0b5d25"}[wasmModuleId] + ".wasm").then(function(response) {
190190
/******/ if(WebAssembly.compileStreaming) {
191191
/******/ return WebAssembly.compileStreaming(response);
192192
/******/ } else {
@@ -264,7 +264,7 @@ export function fibonacciJavascript(i) {
264264
/*! no static exports found */
265265
/***/ (function(module, exports, __webpack_require__) {
266266

267-
__webpack_require__.e/* import() */(1).then(function() { var module = __webpack_require__(/*! ./add.wasm */1); return typeof module === "object" && module && module.__esModule ? module : /* fake namespace object */ { "default": module }; }).then(addModule => {
267+
__webpack_require__.e/* import() */(1).then(__webpack_require__.bind(null, /*! ./add.wasm */1)).then(addModule => {
268268
console.log(addModule.add(22, 2200));
269269
__webpack_require__.e/* import() */(0).then(__webpack_require__.bind(null, /*! ./math */2)).then(math => {
270270
console.log(math.add(10, 101));
@@ -305,7 +305,7 @@ function timed(name, fn) {
305305
/*!******************!*\
306306
!*** ./add.wasm ***!
307307
\******************/
308-
/*! no static exports found */
308+
/*! exports provided: add */
309309
/***/ (function(module, exports, __webpack_require__) {
310310

311311
"use strict";
@@ -329,15 +329,12 @@ __webpack_require__.r(__webpack_exports__);
329329
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "factorialJavascript", function() { return factorialJavascript; });
330330
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "fibonacciJavascript", function() { return fibonacciJavascript; });
331331
/* harmony import */ var _add_wasm__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./add.wasm */1);
332-
/* harmony import */ var _add_wasm__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_add_wasm__WEBPACK_IMPORTED_MODULE_0__);
333332
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "add", function() { return _add_wasm__WEBPACK_IMPORTED_MODULE_0__["add"]; });
334333

335334
/* harmony import */ var _factorial_wasm__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./factorial.wasm */3);
336-
/* harmony import */ var _factorial_wasm__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_factorial_wasm__WEBPACK_IMPORTED_MODULE_1__);
337335
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "factorial", function() { return _factorial_wasm__WEBPACK_IMPORTED_MODULE_1__["factorial"]; });
338336

339337
/* harmony import */ var _fibonacci_wasm__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./fibonacci.wasm */4);
340-
/* harmony import */ var _fibonacci_wasm__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_fibonacci_wasm__WEBPACK_IMPORTED_MODULE_2__);
341338
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "fibonacci", function() { return _fibonacci_wasm__WEBPACK_IMPORTED_MODULE_2__["fibonacci"]; });
342339

343340

@@ -362,7 +359,7 @@ function fibonacciJavascript(i) {
362359
/*!************************!*\
363360
!*** ./factorial.wasm ***!
364361
\************************/
365-
/*! no static exports found */
362+
/*! exports provided: factorial */
366363
/***/ (function(module, exports, __webpack_require__) {
367364

368365
"use strict";
@@ -378,7 +375,7 @@ module.exports = instance.exports;
378375
/*!************************!*\
379376
!*** ./fibonacci.wasm ***!
380377
\************************/
381-
/*! no static exports found */
378+
/*! exports provided: fibonacci */
382379
/***/ (function(module, exports, __webpack_require__) {
383380

384381
"use strict";
@@ -402,7 +399,7 @@ module.exports = instance.exports;
402399
/*!******************!*\
403400
!*** ./add.wasm ***!
404401
\******************/
405-
/*! no static exports found */
402+
/*! exports provided: add */
406403
/***/ (function(module, exports, __webpack_require__) {
407404

408405
"use strict";
@@ -425,31 +422,35 @@ module.exports = instance.exports;
425422
Hash: 0a1b2c3d4e5f6a7b8c9d
426423
Version: webpack next
427424
Asset Size Chunks Chunk Names
428-
0.output.js 3.33 KiB 0 [emitted]
429-
27bb124d07adac2541fe.wasm 41 bytes 0, 1 [emitted]
430-
0e736bedbc15ed9c8e33.wasm 62 bytes 0 [emitted]
431-
435e0d0a43195d073ec9.wasm 67 bytes 0 [emitted]
432-
1.output.js 462 bytes 1 [emitted]
433-
output.js 9 KiB 2 [emitted] main
425+
0.output.js 2.87 KiB 0 [emitted]
426+
77ca5181080bbc4c2f55.wasm 41 bytes 0, 1 [emitted]
427+
b6b19efd9d04360b0a8d.wasm 62 bytes 0 [emitted]
428+
61f7b7b231ff2e0b5d25.wasm 67 bytes 0 [emitted]
429+
1.output.js 460 bytes 1 [emitted]
430+
output.js 8.86 KiB 2 [emitted] main
434431
Entrypoint main = output.js
435-
chunk {0} 0.output.js, 27bb124d07adac2541fe.wasm, 0e736bedbc15ed9c8e33.wasm, 435e0d0a43195d073ec9.wasm 585 bytes {2} [rendered]
432+
chunk {0} 0.output.js, 77ca5181080bbc4c2f55.wasm, b6b19efd9d04360b0a8d.wasm, 61f7b7b231ff2e0b5d25.wasm 585 bytes {2} [rendered]
436433
> [0] ./example.js 3:1-17
437434
[1] ./add.wasm 41 bytes {0} {1} [built]
435+
[exports: add]
438436
import() ./add.wasm [0] ./example.js 1:0-20
439437
harmony side effect evaluation ./add.wasm [2] ./math.js 1:0-33
440438
harmony export imported specifier ./add.wasm [2] ./math.js 5:0-37
441439
[2] ./math.js 415 bytes {0} [built]
442440
[exports: add, factorial, fibonacci, factorialJavascript, fibonacciJavascript]
443441
import() ./math [0] ./example.js 3:1-17
444442
[3] ./factorial.wasm 62 bytes {0} [built]
443+
[exports: factorial]
445444
harmony side effect evaluation ./factorial.wasm [2] ./math.js 2:0-45
446445
harmony export imported specifier ./factorial.wasm [2] ./math.js 5:0-37
447446
[4] ./fibonacci.wasm 67 bytes {0} [built]
447+
[exports: fibonacci]
448448
harmony side effect evaluation ./fibonacci.wasm [2] ./math.js 3:0-45
449449
harmony export imported specifier ./fibonacci.wasm [2] ./math.js 5:0-37
450-
chunk {1} 1.output.js, 27bb124d07adac2541fe.wasm 41 bytes {2} [rendered]
450+
chunk {1} 1.output.js, 77ca5181080bbc4c2f55.wasm 41 bytes {2} [rendered]
451451
> [0] ./example.js 1:0-20
452452
[1] ./add.wasm 41 bytes {0} {1} [built]
453+
[exports: add]
453454
import() ./add.wasm [0] ./example.js 1:0-20
454455
harmony side effect evaluation ./add.wasm [2] ./math.js 1:0-33
455456
harmony export imported specifier ./add.wasm [2] ./math.js 5:0-37
@@ -465,33 +466,37 @@ chunk {2} output.js (main) 788 bytes [entry] [rendered]
465466
Hash: 0a1b2c3d4e5f6a7b8c9d
466467
Version: webpack next
467468
Asset Size Chunks Chunk Names
468-
0.output.js 730 bytes 0, 1 [emitted]
469-
ca9c9d58a020ad464842.wasm 41 bytes 0, 1, 1 [emitted]
470-
64fb1a95d49da0773219.wasm 62 bytes 0, 1 [emitted]
471-
bc9b931dad77c0bbc6cc.wasm 67 bytes 0, 1 [emitted]
469+
0.output.js 722 bytes 0, 1 [emitted]
470+
a1752e23bae9d6697e19.wasm 41 bytes 0, 1, 1 [emitted]
471+
0b5fb42103459586a7f7.wasm 62 bytes 0, 1 [emitted]
472+
48b4a645ac3841813d4e.wasm 67 bytes 0, 1 [emitted]
472473
1.output.js 155 bytes 1 [emitted]
473-
output.js 2.58 KiB 2 [emitted] main
474+
output.js 2.52 KiB 2 [emitted] main
474475
Entrypoint main = output.js
475-
chunk {0} 0.output.js, ca9c9d58a020ad464842.wasm, 64fb1a95d49da0773219.wasm, bc9b931dad77c0bbc6cc.wasm 585 bytes {2} [rendered]
476+
chunk {0} 0.output.js, a1752e23bae9d6697e19.wasm, 0b5fb42103459586a7f7.wasm, 48b4a645ac3841813d4e.wasm 585 bytes {2} [rendered]
476477
> [0] ./example.js 3:1-17
477478
[1] ./add.wasm 41 bytes {0} {1} [built]
479+
[exports: add]
478480
import() ./add.wasm [0] ./example.js 1:0-20
479481
harmony side effect evaluation ./add.wasm [2] ./math.js 1:0-33
480482
harmony export imported specifier ./add.wasm [2] ./math.js 5:0-37
481483
[2] ./math.js 415 bytes {0} [built]
482484
[exports: add, factorial, fibonacci, factorialJavascript, fibonacciJavascript]
483485
import() ./math [0] ./example.js 3:1-17
484486
[3] ./factorial.wasm 62 bytes {0} [built]
487+
[exports: factorial]
485488
[only some exports used: factorial]
486489
harmony side effect evaluation ./factorial.wasm [2] ./math.js 2:0-45
487490
harmony export imported specifier ./factorial.wasm [2] ./math.js 5:0-37
488491
[4] ./fibonacci.wasm 67 bytes {0} [built]
492+
[exports: fibonacci]
489493
[only some exports used: fibonacci]
490494
harmony side effect evaluation ./fibonacci.wasm [2] ./math.js 3:0-45
491495
harmony export imported specifier ./fibonacci.wasm [2] ./math.js 5:0-37
492-
chunk {1} 1.output.js, ca9c9d58a020ad464842.wasm 41 bytes {2} [rendered]
496+
chunk {1} 1.output.js, a1752e23bae9d6697e19.wasm 41 bytes {2} [rendered]
493497
> [0] ./example.js 1:0-20
494498
[1] ./add.wasm 41 bytes {0} {1} [built]
499+
[exports: add]
495500
import() ./add.wasm [0] ./example.js 1:0-20
496501
harmony side effect evaluation ./add.wasm [2] ./math.js 1:0-33
497502
harmony export imported specifier ./add.wasm [2] ./math.js 5:0-37

lib/NormalModule.js

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -313,22 +313,38 @@ class NormalModule extends Module {
313313
return callback();
314314
}
315315

316+
const handleParseError = e => {
317+
const source = this._source.source();
318+
const error = new ModuleParseError(this, source, e);
319+
this.markModuleAsErrored(error);
320+
return callback();
321+
};
322+
323+
const handleParseResult = result => {
324+
this._lastSuccessfulBuildMeta = this.buildMeta;
325+
return callback();
326+
};
327+
316328
try {
317-
this.parser.parse(this._ast || this._source.source(), {
329+
const result = this.parser.parse(this._ast || this._source.source(), {
318330
current: this,
319331
module: this,
320332
compilation: compilation,
321333
options: options
334+
}, (err, result) => {
335+
if(err) {
336+
handleParseError(err);
337+
} else {
338+
handleParseResult(result);
339+
}
322340
});
341+
if(result !== undefined) {
342+
// parse is sync
343+
handleParseResult(result);
344+
}
323345
} catch(e) {
324-
const source = this._source.source();
325-
const error = new ModuleParseError(this, source, e);
326-
this.markModuleAsErrored(error);
327-
return callback();
346+
handleParseError(e);
328347
}
329-
330-
this._lastSuccessfulBuildMeta = this.buildMeta;
331-
return callback();
332348
});
333349
}
334350

lib/WebAssemblyParser.js

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
MIT License http://www.opensource.org/licenses/mit-license.php
33
Author Tobias Koppers @sokra
44
*/
5+
/* globals WebAssembly */
56
"use strict";
67

78
// Syntax: https://developer.mozilla.org/en/SpiderMonkey/Parser_API
@@ -15,11 +16,24 @@ class WebAssemblyParser extends Tapable {
1516
this.options = options;
1617
}
1718

18-
parse(source, initialState) {
19-
// Does nothing current
19+
parse(source, state, callback) {
2020
// TODO parse WASM AST and walk it
21-
// extract exports, imports
22-
return initialState;
21+
// TODO extract imports
22+
23+
// flag it as ESM
24+
state.module.buildMeta.harmonyModule = true;
25+
26+
// extract exports
27+
// TODO find more efficient way doing it
28+
// TODO use Promises
29+
if(typeof WebAssembly !== "undefined") {
30+
WebAssembly.compile(source).then(module => {
31+
state.module.buildMeta.providedExports = WebAssembly.Module.exports(module).map(exp => exp.name);
32+
}).then(() => callback(null, state), err => callback(err));
33+
} else {
34+
state.module.buildMeta.providedExports = false;
35+
callback(null, state);
36+
}
2337
}
2438
}
2539

lib/node/ReadFileCompileWasmTemplatePlugin.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@
55
"use strict";
66

77
const ReadFileCompileWasmMainTemplatePlugin = require("./ReadFileCompileWasmMainTemplatePlugin");
8-
const ReadFileCompileWasmModuleTemplatePlugin = require("./ReadFileCompileWasmModuleTemplatePlugin");
8+
const WasmModuleTemplatePlugin = require("../wasm/WasmModuleTemplatePlugin");
99

1010
class ReadFileCompileWasmTemplatePlugin {
1111
apply(compiler) {
1212
compiler.hooks.thisCompilation.tap("ReadFileCompileWasmTemplatePlugin", (compilation) => {
1313
compilation.mainTemplate.apply(new ReadFileCompileWasmMainTemplatePlugin());
14-
compilation.moduleTemplates.javascript.apply(new ReadFileCompileWasmModuleTemplatePlugin());
14+
compilation.moduleTemplates.javascript.apply(new WasmModuleTemplatePlugin());
1515
});
1616
}
1717
}

lib/node/ReadFileCompileWasmModuleTemplatePlugin.js renamed to lib/wasm/WasmModuleTemplatePlugin.js

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,30 @@
66

77
const RawSource = require("webpack-sources").RawSource;
88

9-
class ReadFileCompileWasmModuleTemplatePlugin {
9+
class WasmModuleTemplatePlugin {
1010
apply(moduleTemplate) {
1111
moduleTemplate.plugin("content", (moduleSource, module, {
1212
chunk
1313
}) => {
1414
if(module.type && module.type.startsWith("webassembly")) {
1515
if(chunk.isInitial())
1616
throw new Error("Sync WebAsssmbly compilation is not yet implemented");
17+
const generateExports = () => {
18+
if(Array.isArray(module.buildMeta.providedExports) && Array.isArray(module.usedExports)) {
19+
// generate mangled exports
20+
return module.buildMeta.providedExports.map(exp => {
21+
const usedName = module.isUsed(exp);
22+
if(usedName) {
23+
return `${module.exportsArgument}[${JSON.stringify(usedName)}] = instance.exports[${JSON.stringify(exp)}];`;
24+
} else {
25+
return `// unused ${JSON.stringify(exp)} export`;
26+
}
27+
}).join("\n");
28+
} else {
29+
// generate simple export
30+
return `${module.moduleArgument}.exports = instance.exports;`;
31+
}
32+
};
1733
const source = new RawSource([
1834
"\"use strict\";",
1935
"",
@@ -22,7 +38,7 @@ class ReadFileCompileWasmModuleTemplatePlugin {
2238
"",
2339
"// export exports from WebAssmbly module",
2440
// TODO rewrite this to getters depending on exports to support circular dependencies
25-
"module.exports = instance.exports;"
41+
generateExports()
2642
].join("\n"));
2743
return source;
2844
} else {
@@ -31,9 +47,9 @@ class ReadFileCompileWasmModuleTemplatePlugin {
3147
});
3248

3349
moduleTemplate.plugin("hash", hash => {
34-
hash.update("ReadFileCompileWasmModuleTemplatePlugin");
50+
hash.update("WasmModuleTemplatePlugin");
3551
hash.update("1");
3652
});
3753
}
3854
}
39-
module.exports = ReadFileCompileWasmModuleTemplatePlugin;
55+
module.exports = WasmModuleTemplatePlugin;

lib/web/FetchCompileWasmModuleTemplatePlugin.js

Lines changed: 0 additions & 39 deletions
This file was deleted.

lib/web/FetchCompileWasmTemplatePlugin.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@
55
"use strict";
66

77
const FetchCompileWasmMainTemplatePlugin = require("./FetchCompileWasmMainTemplatePlugin");
8-
const FetchCompileWasmModuleTemplatePlugin = require("./FetchCompileWasmModuleTemplatePlugin");
8+
const WasmModuleTemplatePlugin = require("../wasm/WasmModuleTemplatePlugin");
99

1010
class FetchCompileWasmTemplatePlugin {
1111
apply(compiler) {
1212
compiler.hooks.thisCompilation.tap("FetchCompileWasmTemplatePlugin", (compilation) => {
1313
compilation.mainTemplate.apply(new FetchCompileWasmMainTemplatePlugin());
14-
compilation.moduleTemplates.javascript.apply(new FetchCompileWasmModuleTemplatePlugin());
14+
compilation.moduleTemplates.javascript.apply(new WasmModuleTemplatePlugin());
1515
});
1616
}
1717
}

test/cases/wasm/simple/index.js

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
1-
it("should allow to run a WebAssembly module", function(done) {
2-
import("./module").then(function(module) {
1+
it("should allow to run a WebAssembly module (indirect)", function() {
2+
return import("./module").then(function(module) {
33
const result = module.run();
44
result.should.be.eql(42);
5-
done();
5+
});
6+
});
7+
8+
it("should allow to run a WebAssembly module (direct)", function() {
9+
return import("./wasm.wasm?2").then(function(wasm) {
10+
const result = wasm.add(wasm.getNumber(), 2);
11+
result.should.be.eql(42);
612
});
713
});

test/cases/wasm/simple/module.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { add, getNumber } from "./wasm.wasm";
1+
import { add, getNumber } from "./wasm.wasm?1";
22

33
export function run() {
44
return add(getNumber(), 2);

0 commit comments

Comments
 (0)