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

Commit da0667d

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 7c92011 commit da0667d

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
@@ -7,6 +7,7 @@ const { realpathSync } = require('fs');
77
const { getOptionValue } = require('internal/options');
88
const preserveSymlinks = getOptionValue('--preserve-symlinks');
99
const preserveSymlinksMain = getOptionValue('--preserve-symlinks-main');
10+
const experimentalWasmModules = getOptionValue('--experimental-wasm-modules');
1011
const { ERR_UNKNOWN_FILE_EXTENSION } = require('internal/errors').codes;
1112
const { resolve: moduleWrapResolve } = internalBinding('module_wrap');
1213
const { pathToFileURL, fileURLToPath } = require('internal/url');
@@ -30,6 +31,16 @@ const legacyExtensionFormatMap = {
3031
'.node': 'cjs'
3132
};
3233

34+
if (experimentalWasmModules) {
35+
// This is a total hack
36+
Object.assign(extensionFormatMap, {
37+
'.wasm': 'wasm'
38+
});
39+
Object.assign(legacyExtensionFormatMap, {
40+
'.wasm': 'wasm'
41+
});
42+
}
43+
3344
function resolve(specifier, parentURL) {
3445
if (NativeModule.canBeRequiredByUsers(specifier)) {
3546
return {

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
@@ -164,6 +164,10 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() {
164164
"experimental ES Module support and caching modules",
165165
&EnvironmentOptions::experimental_modules,
166166
kAllowedInEnvironment);
167+
AddOption("--experimental-wasm-modules",
168+
"experimental ES Module support for webassembly modules",
169+
&EnvironmentOptions::experimental_wasm_modules,
170+
kAllowedInEnvironment);
167171
AddOption("--experimental-policy",
168172
"use the specified file as a "
169173
"security policy",

src/node_options.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ class EnvironmentOptions : public Options {
8686
public:
8787
bool abort_on_uncaught_exception = false;
8888
bool experimental_modules = false;
89+
bool experimental_wasm_modules = false;
8990
std::string module_type;
9091
std::string experimental_policy;
9192
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)