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

esm: experimental wasm modules #46

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions lib/internal/modules/esm/create_wasm_module.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
'use strict';

const { JSON } = primordials;
const debug = require('internal/util/debuglog').debuglog('esm');

/* global WebAssembly */

module.exports = function createWASMModule(module, url) {
debug('creating WASM facade for %s with exports: %j', url, exports);

const imports = WebAssembly.Module.imports(module);
const importModules = new Set();
imports.forEach(({ module }) => importModules.add(module));

const source = `const imports = Object.create(null);
${[...importModules].map((module) => {
const specifierStr = JSON.stringify(module);
const importNames = new Set(
imports
.filter(({ module: m }) => m === module)
.map(({ name }) => name)
);
const impts =
[...importNames].map((name) => `${name} as $${name}`).join(', ');
const defs = [...importNames].map((name) => `${name}: $${name}`).join(', ');
return `import { ${impts} } from ${specifierStr};
guybedford marked this conversation as resolved.
Show resolved Hide resolved
imports[${specifierStr}] = { ${defs} };`;
}).join('\n')}
const { exports } = new WebAssembly.Instance(import.meta.module, imports);
${WebAssembly.Module.exports(module)
.map(({ name }) => `export const ${name} = exports.${name};`).join('\n')}
guybedford marked this conversation as resolved.
Show resolved Hide resolved
`;

const { ModuleWrap, callbackMap } = internalBinding('module_wrap');
const m = new ModuleWrap(source, `${url}`);

callbackMap.set(m, {
initializeImportMeta: (meta, wrap) => {
meta.module = module;
},
});

return {
module: m,
reflect: undefined
};
};
25 changes: 3 additions & 22 deletions lib/internal/modules/esm/translators.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

const {
JSON,
Object,
SafeMap,
StringPrototype
} = primordials;
Expand All @@ -18,6 +17,8 @@ const CJSModule = require('internal/modules/cjs/loader');
const internalURLModule = require('internal/url');
const createDynamicModule = require(
'internal/modules/esm/create_dynamic_module');
const createWASMModule = require(
'internal/modules/esm/create_wasm_module');
const fs = require('fs');
const { fileURLToPath, URL } = require('url');
const { debuglog } = require('internal/util/debuglog');
Expand Down Expand Up @@ -152,27 +153,7 @@ translators.set('wasm', async function(url) {
debug(`Translating WASMModule ${url}`);
try {
const compiled = await WebAssembly.compile(buffer);
// Note: This approach executes dependencies early, and will
// deadlock in cycles, both of which will be resolved when
// top-level await support lands.
const loader = await esmLoader.loaderPromise;
const imports = Object.create(null);
await Promise.all(
WebAssembly.Module.imports(compiled).map(async (impt) => {
imports[impt.module] = await loader.import(impt.module, url);
})
);
const exportNames = WebAssembly.Module.exports(compiled)
.map((i) => i.name);
return createDynamicModule(exportNames, url, (reflect) => {
// Creating a wasm instance with the JS api will automatically
// run the wasm start function, so this must be done inside the
// dynamic module callback.
const { exports } = new WebAssembly.Instance(compiled, imports);
exportNames.forEach((name) => {
reflect.exports[name].set(exports[name]);
});
});
return createWASMModule(compiled, url);
} catch (err) {
err.message = pathname + ': ' + err.message;
throw err;
Expand Down
1 change: 1 addition & 0 deletions node.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@
'lib/internal/modules/cjs/loader.js',
'lib/internal/modules/esm/loader.js',
'lib/internal/modules/esm/create_dynamic_module.js',
'lib/internal/modules/esm/create_wasm_module.js',
'lib/internal/modules/esm/default_resolve.js',
'lib/internal/modules/esm/module_job.js',
'lib/internal/modules/esm/module_map.js',
Expand Down