Skip to content
This repository was archived by the owner on Apr 16, 2020. It is now read-only.

Commit aa1e86e

Browse files
committed
esm: experimental wasm modules
This is a first pass at a loader for wasm modules. It offers support for both named imports as well as deafult. It may be possible to move some of this logic down to C++, but I think the current implementation might be good enough. It doesn't currently use the ESM cache, but AFAICT it isn't currently exposed. Will dig in more with tests / examples / cache after initial implementation gets feedback.
1 parent ea59221 commit aa1e86e

File tree

5 files changed

+47
-1
lines changed

5 files changed

+47
-1
lines changed

lib/internal/modules/esm/default_resolve.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const preserveSymlinksMain = getOptionValue('--preserve-symlinks-main');
1010
const { ERR_INVALID_PACKAGE_CONFIG,
1111
ERR_TYPE_MISMATCH,
1212
ERR_UNKNOWN_FILE_EXTENSION } = require('internal/errors').codes;
13+
const experimentalWasmModules = getOptionValue('--experimental-wasm-modules');
1314
const { resolve: moduleWrapResolve } = internalBinding('module_wrap');
1415
const { pathToFileURL, fileURLToPath, URL } = require('internal/url');
1516
const asyncESM = require('internal/process/esm_loader');
@@ -34,6 +35,16 @@ const legacyExtensionFormatMap = {
3435
'.node': 'commonjs'
3536
};
3637

38+
if (experimentalWasmModules) {
39+
// This is a total hack
40+
Object.assign(extensionFormatMap, {
41+
'.wasm': 'wasm'
42+
});
43+
Object.assign(legacyExtensionFormatMap, {
44+
'.wasm': 'wasm'
45+
});
46+
}
47+
3748
function readPackageConfig(path, parentURL) {
3849
const existing = pjsonCache.get(path);
3950
if (existing !== undefined)

lib/internal/modules/esm/translators.js

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ const fs = require('fs');
1313
const {
1414
SafeMap,
1515
} = primordials;
16-
const { URL } = require('url');
16+
const { fileURLToPath, URL } = require('url');
1717
const { debuglog, promisify } = require('util');
1818
const esmLoader = require('internal/process/esm_loader');
1919

@@ -94,3 +94,24 @@ translators.set('builtin', async function(url) {
9494
reflect.exports.default.set(module.exports);
9595
});
9696
});
97+
98+
// Strategy for loading a wasm module
99+
translators.set('wasm', async function(url) {
100+
const pathname = fileURLToPath(url);
101+
const buffer = await readFileAsync(pathname);
102+
debug(`Translating WASMModule ${url}`);
103+
let result, keys;
104+
try {
105+
WebAssembly.validate(buffer);
106+
result = await WebAssembly.instantiate(buffer, {});
107+
keys = Object.keys(result.instance.exports);
108+
} catch (err) {
109+
err.message = pathname + ': ' + err.message;
110+
throw err;
111+
}
112+
return createDynamicModule([...keys, 'default'], url, (reflect) => {
113+
for (const key of keys)
114+
reflect.exports[key].set(result.instance.exports[key]);
115+
reflect.exports.default.set(result.instance.exports);
116+
});
117+
});

src/node_options.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,10 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() {
216216
"experimental ES Module support and caching modules",
217217
&EnvironmentOptions::experimental_modules,
218218
kAllowedInEnvironment);
219+
AddOption("--experimental-wasm-modules",
220+
"experimental ES Module support for webassembly modules",
221+
&EnvironmentOptions::experimental_wasm_modules,
222+
kAllowedInEnvironment);
219223
AddOption("--experimental-policy",
220224
"use the specified file as a "
221225
"security policy",

src/node_options.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ class EnvironmentOptions : public Options {
8787
bool abort_on_uncaught_exception = false;
8888
bool experimental_modules = false;
8989
std::string es_module_specifier_resolution = "explicit";
90+
bool experimental_wasm_modules = false;
9091
std::string module_type;
9192
std::string experimental_policy;
9293
bool experimental_repl_await = false;

test/es-module/test-esm-wasm.mjs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Flags: --experimental-modules --experimental-wasm-modules
2+
/* eslint-disable node-core/required-modules */
3+
import wasmMod from '../fixtures/simple.wasm'
4+
import {add} from '../fixtures/simple.wasm';
5+
import {strictEqual} from 'assert';
6+
7+
strictEqual(wasmMod.add(10, 20), 30);
8+
strictEqual(add(10, 20), 30);
9+
strictEqual(wasmMod.add, add);

0 commit comments

Comments
 (0)