node/lib/internal/modules/esm/create_dynamic_module.js
Geoffrey Booth 7517c9f95b
module, esm: jsdoc for modules files
PR-URL: https://github.com/nodejs/node/pull/49523
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
2023-09-19 02:48:24 +00:00

96 lines
2.7 KiB
JavaScript

'use strict';
const {
ArrayPrototypeJoin,
ArrayPrototypeMap,
JSONStringify,
SafeSet,
} = primordials;
let debug = require('internal/util/debuglog').debuglog('esm', (fn) => {
debug = fn;
});
/**
* Creates an import statement for a given module path and index.
* @param {string} impt - The module path to import.
* @param {number} index - The index of the import statement.
*/
function createImport(impt, index) {
const imptPath = JSONStringify(impt);
return `import * as $import_${index} from ${imptPath};
import.meta.imports[${imptPath}] = $import_${index};`;
}
/**
* Creates an export for a given module.
* @param {string} expt - The name of the export.
*/
function createExport(expt) {
const name = `${expt}`;
return `let $${name};
export { $${name} as ${name} };
import.meta.exports.${name} = {
get: () => $${name},
set: (v) => $${name} = v,
};`;
}
/**
* Creates a dynamic module with the given imports, exports, URL, and evaluate function.
* @param {string[]} imports - An array of imports.
* @param {string[]} exports - An array of exports.
* @param {string} [url=''] - The URL of the module.
* @param {(reflect: DynamicModuleReflect) => void} evaluate - The function to evaluate the module.
* @typedef {object} DynamicModuleReflect
* @property {string[]} imports - The imports of the module.
* @property {string[]} exports - The exports of the module.
* @property {(cb: (reflect: DynamicModuleReflect) => void) => void} onReady - Callback to evaluate the module.
*/
const createDynamicModule = (imports, exports, url = '', evaluate) => {
debug('creating ESM facade for %s with exports: %j', url, exports);
const source = `
${ArrayPrototypeJoin(ArrayPrototypeMap(imports, createImport), '\n')}
${ArrayPrototypeJoin(ArrayPrototypeMap(exports, createExport), '\n')}
import.meta.done();
`;
const { ModuleWrap } = internalBinding('module_wrap');
const m = new ModuleWrap(`${url}`, undefined, source, 0, 0);
const readyfns = new SafeSet();
/** @type {DynamicModuleReflect} */
const reflect = {
exports: { __proto__: null },
onReady: (cb) => { readyfns.add(cb); },
};
if (imports.length) {
reflect.imports = { __proto__: null };
}
const { registerModule } = require('internal/modules/esm/utils');
registerModule(m, {
__proto__: null,
initializeImportMeta: (meta, wrap) => {
meta.exports = reflect.exports;
if (reflect.imports) {
meta.imports = reflect.imports;
}
meta.done = () => {
evaluate(reflect);
reflect.onReady = (cb) => cb(reflect);
for (const fn of readyfns) {
readyfns.delete(fn);
fn(reflect);
}
};
},
});
return {
module: m,
reflect,
};
};
module.exports = createDynamicModule;