summaryrefslogtreecommitdiff
path: root/lib/internal/modules/esm
diff options
context:
space:
mode:
authorMyles Borins <myles.borins@gmail.com>2019-04-30 00:27:20 +0800
committerGuy Bedford <guybedford@gmail.com>2019-05-17 02:25:20 +0200
commitbbc254db5db672643aad89a436a4938412a5704e (patch)
tree8fcd7de8b502008c81f11c92931d1304050e4c73 /lib/internal/modules/esm
parent6982dc7198c92757f54c26f71ca4d1ab2b381118 (diff)
downloadandroid-node-v8-bbc254db5db672643aad89a436a4938412a5704e.tar.gz
android-node-v8-bbc254db5db672643aad89a436a4938412a5704e.tar.bz2
android-node-v8-bbc254db5db672643aad89a436a4938412a5704e.zip
esm: --experimental-wasm-modules integration support
PR-URL: https://github.com/nodejs/node/pull/27659 Reviewed-By: Gus Caplan <me@gus.host> Reviewed-By: Michaƫl Zasso <targos@protonmail.com> Reviewed-By: Myles Borins <myles.borins@gmail.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Diffstat (limited to 'lib/internal/modules/esm')
-rw-r--r--lib/internal/modules/esm/create_dynamic_module.js18
-rw-r--r--lib/internal/modules/esm/default_resolve.js21
-rw-r--r--lib/internal/modules/esm/loader.js2
-rw-r--r--lib/internal/modules/esm/translators.js41
4 files changed, 54 insertions, 28 deletions
diff --git a/lib/internal/modules/esm/create_dynamic_module.js b/lib/internal/modules/esm/create_dynamic_module.js
index eea01bed31..45f964d5ad 100644
--- a/lib/internal/modules/esm/create_dynamic_module.js
+++ b/lib/internal/modules/esm/create_dynamic_module.js
@@ -1,14 +1,18 @@
'use strict';
-const { ArrayPrototype } = primordials;
+const { ArrayPrototype, JSON, Object } = primordials;
const debug = require('internal/util/debuglog').debuglog('esm');
-const createDynamicModule = (exports, url = '', evaluate) => {
+const createDynamicModule = (imports, exports, url = '', evaluate) => {
debug('creating ESM facade for %s with exports: %j', url, exports);
const names = ArrayPrototype.map(exports, (name) => `${name}`);
const source = `
+${ArrayPrototype.join(ArrayPrototype.map(imports, (impt, index) =>
+ `import * as $import_${index} from ${JSON.stringify(impt)};
+import.meta.imports[${JSON.stringify(impt)}] = $import_${index};`), '\n')
+}
${ArrayPrototype.join(ArrayPrototype.map(names, (name) =>
`let $${name};
export { $${name} as ${name} };
@@ -22,19 +26,21 @@ import.meta.done();
`;
const { ModuleWrap, callbackMap } = internalBinding('module_wrap');
const m = new ModuleWrap(source, `${url}`);
- m.link(() => 0);
- m.instantiate();
const readyfns = new Set();
const reflect = {
- namespace: m.namespace(),
- exports: {},
+ exports: Object.create(null),
onReady: (cb) => { readyfns.add(cb); },
};
+ if (imports.length)
+ reflect.imports = Object.create(null);
+
callbackMap.set(m, {
initializeImportMeta: (meta, wrap) => {
meta.exports = reflect.exports;
+ if (reflect.imports)
+ meta.imports = reflect.imports;
meta.done = () => {
evaluate(reflect);
reflect.onReady = (cb) => cb(reflect);
diff --git a/lib/internal/modules/esm/default_resolve.js b/lib/internal/modules/esm/default_resolve.js
index a83cf9c675..67b8db716c 100644
--- a/lib/internal/modules/esm/default_resolve.js
+++ b/lib/internal/modules/esm/default_resolve.js
@@ -10,17 +10,14 @@ const preserveSymlinks = getOptionValue('--preserve-symlinks');
const preserveSymlinksMain = getOptionValue('--preserve-symlinks-main');
const experimentalJsonModules = getOptionValue('--experimental-json-modules');
const typeFlag = getOptionValue('--input-type');
-
+const experimentalWasmModules = getOptionValue('--experimental-wasm-modules');
const { resolve: moduleWrapResolve,
getPackageType } = internalBinding('module_wrap');
const { pathToFileURL, fileURLToPath } = require('internal/url');
const { ERR_INPUT_TYPE_NOT_ALLOWED,
ERR_UNKNOWN_FILE_EXTENSION } = require('internal/errors').codes;
-const {
- Object,
- SafeMap
-} = primordials;
+const { SafeMap } = primordials;
const realpathCache = new SafeMap();
@@ -44,15 +41,11 @@ const legacyExtensionFormatMap = {
'.node': 'commonjs'
};
-if (experimentalJsonModules) {
- // This is a total hack
- Object.assign(extensionFormatMap, {
- '.json': 'json'
- });
- Object.assign(legacyExtensionFormatMap, {
- '.json': 'json'
- });
-}
+if (experimentalWasmModules)
+ extensionFormatMap['.wasm'] = legacyExtensionFormatMap['.wasm'] = 'wasm';
+
+if (experimentalJsonModules)
+ extensionFormatMap['.json'] = legacyExtensionFormatMap['.json'] = 'json';
function resolve(specifier, parentURL) {
if (NativeModule.canBeRequiredByUsers(specifier)) {
diff --git a/lib/internal/modules/esm/loader.js b/lib/internal/modules/esm/loader.js
index f752550d12..0ea1e6f4e5 100644
--- a/lib/internal/modules/esm/loader.js
+++ b/lib/internal/modules/esm/loader.js
@@ -153,7 +153,7 @@ class Loader {
loaderInstance = async (url) => {
debug(`Translating dynamic ${url}`);
const { exports, execute } = await this._dynamicInstantiate(url);
- return createDynamicModule(exports, url, (reflect) => {
+ return createDynamicModule([], exports, url, (reflect) => {
debug(`Loading dynamic ${url}`);
execute(reflect.exports);
});
diff --git a/lib/internal/modules/esm/translators.js b/lib/internal/modules/esm/translators.js
index 72350fb2b2..4ca9be4d62 100644
--- a/lib/internal/modules/esm/translators.js
+++ b/lib/internal/modules/esm/translators.js
@@ -1,9 +1,12 @@
'use strict';
+/* global WebAssembly */
+
const {
+ JSON,
+ Object,
SafeMap,
- StringPrototype,
- JSON
+ StringPrototype
} = primordials;
const { NativeModule } = require('internal/bootstrap/loaders');
@@ -72,11 +75,11 @@ translators.set('commonjs', async function commonjsStrategy(url, isMain) {
];
if (module && module.loaded) {
const exports = module.exports;
- return createDynamicModule(['default'], url, (reflect) => {
+ return createDynamicModule([], ['default'], url, (reflect) => {
reflect.exports.default.set(exports);
});
}
- return createDynamicModule(['default'], url, () => {
+ return createDynamicModule([], ['default'], url, () => {
debug(`Loading CJSModule ${url}`);
// We don't care about the return val of _load here because Module#load
// will handle it for us by checking the loader registry and filling the
@@ -97,7 +100,7 @@ translators.set('builtin', async function builtinStrategy(url) {
}
module.compileForPublicLoader(true);
return createDynamicModule(
- [...module.exportKeys, 'default'], url, (reflect) => {
+ [], [...module.exportKeys, 'default'], url, (reflect) => {
debug(`Loading BuiltinModule ${url}`);
module.reflect = reflect;
for (const key of module.exportKeys)
@@ -116,7 +119,7 @@ translators.set('json', async function jsonStrategy(url) {
let module = CJSModule._cache[modulePath];
if (module && module.loaded) {
const exports = module.exports;
- return createDynamicModule(['default'], url, (reflect) => {
+ return createDynamicModule([], ['default'], url, (reflect) => {
reflect.exports.default.set(exports);
});
}
@@ -136,8 +139,32 @@ translators.set('json', async function jsonStrategy(url) {
throw err;
}
CJSModule._cache[modulePath] = module;
- return createDynamicModule(['default'], url, (reflect) => {
+ return createDynamicModule([], ['default'], url, (reflect) => {
debug(`Parsing JSONModule ${url}`);
reflect.exports.default.set(module.exports);
});
});
+
+// Strategy for loading a wasm module
+translators.set('wasm', async function(url) {
+ const pathname = fileURLToPath(url);
+ const buffer = await readFileAsync(pathname);
+ debug(`Translating WASMModule ${url}`);
+ let compiled;
+ try {
+ compiled = await WebAssembly.compile(buffer);
+ } catch (err) {
+ err.message = pathname + ': ' + err.message;
+ throw err;
+ }
+
+ const imports =
+ WebAssembly.Module.imports(compiled).map(({ module }) => module);
+ const exports = WebAssembly.Module.exports(compiled).map(({ name }) => name);
+
+ return createDynamicModule(imports, exports, url, (reflect) => {
+ const { exports } = new WebAssembly.Instance(compiled, reflect.imports);
+ for (const expt of Object.keys(exports))
+ reflect.exports[expt].set(exports[expt]);
+ });
+});