Skip to content

Commit 1743568

Browse files
MylesBorinsBridgeAR
authored andcommitted
esm: refactor dynamic modules
This is a change from the ecmascript-modules fork. There is no change to behavior and we would like to upstream to reduce the delta between our repos. Refs: https://github.com/nodejs/ecmascript-modules#9 PR-URL: #24560 Refs: nodejs/ecmascript-modules#9 Reviewed-By: Guy Bedford <guybedford@gmail.com> Reviewed-By: Gus Caplan <me@gus.host>
1 parent 8ffe04f commit 1743568

3 files changed

Lines changed: 58 additions & 59 deletions

File tree

‎lib/internal/modules/cjs/loader.js‎

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -623,23 +623,24 @@ Module.prototype.load = function(filename) {
623623
if(experimentalModules){
624624
if(asyncESM===undefined)lazyLoadESM();
625625
constESMLoader=asyncESM.ESMLoader;
626-
consturl=pathToFileURL(filename);
627-
consturlString=`${url}`;
626+
consturl=`${pathToFileURL(filename)}`;
627+
constmodule=ESMLoader.moduleMap.get(url);
628+
// create module entry at load time to snapshot exports correctly
628629
constexports=this.exports;
629-
if(ESMLoader.moduleMap.has(urlString)!==true){
630+
if(module!==undefined){// called from cjs translator
631+
module.reflect.onReady((reflect)=>{
632+
reflect.exports.default.set(exports);
633+
});
634+
}else{// preemptively cache
630635
ESMLoader.moduleMap.set(
631-
urlString,
636+
url,
632637
newModuleJob(ESMLoader,url,async()=>{
633-
constctx=createDynamicModule(
634-
['default'],url);
635-
ctx.reflect.exports.default.set(exports);
636-
returnctx;
638+
returncreateDynamicModule(
639+
['default'],url,(reflect)=>{
640+
reflect.exports.default.set(exports);
641+
});
637642
})
638643
);
639-
}else{
640-
constjob=ESMLoader.moduleMap.get(urlString);
641-
if(job.reflect)
642-
job.reflect.exports.default.set(exports);
643644
}
644645
}
645646
};

‎lib/internal/modules/esm/create_dynamic_module.js‎

Lines changed: 41 additions & 44 deletions
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
constdebug=require('util').debuglog('esm');
55
constArrayJoin=Function.call.bind(Array.prototype.join);
66
constArrayMap=Function.call.bind(Array.prototype.map);
@@ -10,50 +10,47 @@ const createDynamicModule = (exports, url = '', evaluate) => {
1010
`creating ESM facade for ${url} with exports: ${ArrayJoin(exports,', ')}`
1111
);
1212
constnames=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-
constsrc=`
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-
constreflectiveModule=newModuleWrap(src,`cjs-facade:${url}`);
33-
reflectiveModule.instantiate();
34-
const{ setExecutor, reflect }=reflectiveModule.evaluate(-1,false)();
35-
// public exposed ESM
36-
constreexports=`
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(typeofevaluate==='function'){
49-
setExecutor(()=>evaluate(reflect));
50-
}
51-
constmodule=newModuleWrap(reexports,`${url}`);
52-
module.link(async()=>reflectiveModule);
53-
module.instantiate();
54-
reflect.namespace=module.namespace();
13+
14+
constsource=`
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+
};`),'\n')
22+
}
23+
24+
import.meta.done();
25+
`;
26+
27+
constm=newModuleWrap(source,`${url}`);
28+
m.link(()=>0);
29+
m.instantiate();
30+
31+
constreadyfns=newSet();
32+
constreflect={
33+
namespace: m.namespace(),
34+
exports: {},
35+
onReady: (cb)=>{readyfns.add(cb);},
36+
};
37+
38+
callbackMap.set(m,{
39+
initializeImportMeta: (meta,wrap)=>{
40+
meta.exports=reflect.exports;
41+
meta.done=()=>{
42+
evaluate(reflect);
43+
reflect.onReady=(cb)=>cb(reflect);
44+
for(constfnofreadyfns){
45+
readyfns.delete(fn);
46+
fn(reflect);
47+
}
48+
};
49+
},
50+
});
51+
5552
return{
56-
module,
53+
module: m,
5754
reflect,
5855
};
5956
};

‎lib/internal/modules/esm/translators.js‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,10 @@ translators.set('cjs', async (url, isMain) => {
6060
constmodule=CJSModule._cache[
6161
isWindows ? StringReplace(pathname,winSepRegEx,'\\') : pathname];
6262
if(module&&module.loaded){
63-
constctx=createDynamicModule(['default'],url);
64-
ctx.reflect.exports.default.set(module.exports);
65-
returnctx;
63+
constexports=module.exports;
64+
returncreateDynamicModule(['default'],url,(reflect)=>{
65+
reflect.exports.default.set(exports);
66+
});
6667
}
6768
returncreateDynamicModule(['default'],url,()=>{
6869
debug(`Loading CJSModule ${url}`);

0 commit comments

Comments
 (0)