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

Commit c84a41b

Browse files
committed
esm: refactor dynamic modules
1 parent 47aac7c commit c84a41b

File tree

3 files changed

+48
-60
lines changed

3 files changed

+48
-60
lines changed

lib/internal/modules/cjs/loader.js

+11-13
Original file line numberDiff line numberDiff line change
@@ -617,23 +617,21 @@ Module.prototype.load = function(filename) {
617617
if (experimentalModules) {
618618
if (asyncESM === undefined) lazyLoadESM();
619619
const ESMLoader = asyncESM.ESMLoader;
620-
const url = pathToFileURL(filename);
621-
const urlString = `${url}`;
622-
const exports = this.exports;
623-
if (ESMLoader.moduleMap.has(urlString) !== true) {
620+
const url = `${pathToFileURL(filename)}`;
621+
const module = ESMLoader.moduleMap.get(url);
622+
if (module !== undefined) {
623+
module.reflect.exports.default.set(this.exports);
624+
} else {
625+
const exports = this.exports;
624626
ESMLoader.moduleMap.set(
625-
urlString,
627+
url,
626628
new ModuleJob(ESMLoader, url, async () => {
627-
const ctx = createDynamicModule(
628-
['default'], url);
629-
ctx.reflect.exports.default.set(exports);
630-
return ctx;
629+
return createDynamicModule(
630+
['default'], url, (reflect) => {
631+
reflect.exports.default.set(exports);
632+
});
631633
})
632634
);
633-
} else {
634-
const job = ESMLoader.moduleMap.get(urlString);
635-
if (job.reflect)
636-
job.reflect.exports.default.set(exports);
637635
}
638636
}
639637
};

lib/internal/modules/esm/create_dynamic_module.js

+33-44
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use strict';
22

3-
const { ModuleWrap } = internalBinding('module_wrap');
3+
const { ModuleWrap, callbackMap } = internalBinding('module_wrap');
44
const debug = require('util').debuglog('esm');
55
const ArrayJoin = Function.call.bind(Array.prototype.join);
66
const ArrayMap = Function.call.bind(Array.prototype.map);
@@ -10,50 +10,39 @@ const createDynamicModule = (exports, url = '', evaluate) => {
1010
`creating ESM facade for ${url} with exports: ${ArrayJoin(exports, ', ')}`
1111
);
1212
const names = ArrayMap(exports, (name) => `${name}`);
13-
// Create two modules: One whose exports are get- and set-able ('reflective'),
14-
// and one which re-exports all of these but additionally may
15-
// run an executor function once everything is set up.
16-
const src = `
17-
export let executor;
18-
${ArrayJoin(ArrayMap(names, (name) => `export let $${name};`), '\n')}
19-
/* This function is implicitly returned as the module's completion value */
20-
(() => ({
21-
setExecutor: fn => executor = fn,
22-
reflect: {
23-
exports: { ${
24-
ArrayJoin(ArrayMap(names, (name) => `
25-
${name}: {
26-
get: () => $${name},
27-
set: v => $${name} = v
28-
}`), ', \n')}
29-
}
30-
}
31-
}));`;
32-
const reflectiveModule = new ModuleWrap(src, `cjs-facade:${url}`);
33-
reflectiveModule.instantiate();
34-
const { setExecutor, reflect } = reflectiveModule.evaluate(-1, false)();
35-
// public exposed ESM
36-
const reexports = `
37-
import {
38-
executor,
39-
${ArrayMap(names, (name) => `$${name}`)}
40-
} from "";
41-
export {
42-
${ArrayJoin(ArrayMap(names, (name) => `$${name} as ${name}`), ', ')}
43-
}
44-
if (typeof executor === "function") {
45-
// add await to this later if top level await comes along
46-
executor()
47-
}`;
48-
if (typeof evaluate === 'function') {
49-
setExecutor(() => evaluate(reflect));
50-
}
51-
const module = new ModuleWrap(reexports, `${url}`);
52-
module.link(async () => reflectiveModule);
53-
module.instantiate();
54-
reflect.namespace = module.namespace();
13+
14+
const source = `
15+
${ArrayJoin(ArrayMap(names, (name) => {
16+
`let $${name};
17+
export { $$name as ${name} };
18+
import.meta.exports.${name} = {
19+
get: () => $${name},
20+
set: (v) => $${name} = v,
21+
};`;
22+
}), '\n')
23+
}
24+
25+
import.meta.done();
26+
`;
27+
28+
const m = new ModuleWrap(source, `${url}`);
29+
m.link(() => 0);
30+
m.instantiate();
31+
32+
const reflect = {
33+
namespace: m.namespace,
34+
exports: {},
35+
};
36+
37+
callbackMap.set(m, {
38+
initializeImportMeta: (meta, wrap) => {
39+
meta.exports = reflect.exports;
40+
meta.done = () => evaluate(reflect);
41+
},
42+
});
43+
5544
return {
56-
module,
45+
module: m,
5746
reflect,
5847
};
5948
};

lib/internal/modules/esm/translators.js

+4-3
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,10 @@ translators.set('cjs', async (url, isMain) => {
5656
const module = CJSModule._cache[
5757
isWindows ? StringReplace(pathname, winSepRegEx, '\\') : pathname];
5858
if (module && module.loaded) {
59-
const ctx = createDynamicModule(['default'], url);
60-
ctx.reflect.exports.default.set(module.exports);
61-
return ctx;
59+
const exports = module.exports;
60+
return createDynamicModule(['default'], url, (reflect) => {
61+
reflect.exports.default.set(exports);
62+
});
6263
}
6364
return createDynamicModule(['default'], url, () => {
6465
debug(`Loading CJSModule ${url}`);

0 commit comments

Comments
 (0)