nstdlib-nightly
Version:
Node.js standard library converted to runtime-agnostic ES modules.
92 lines (83 loc) • 2.92 kB
JavaScript
// Source: https://github.com/nodejs/node/blob/65eff1eb/lib/internal/modules/esm/create_dynamic_module.js
import * as __hoisted_internal_modules_esm_utils__ from "nstdlib/lib/internal/modules/esm/utils";
/**
* 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.
* @param {number} index - The index of the export statement.
*/
function createExport(expt, index) {
const nameStringLit = JSONStringify(expt);
return `let $export_${index};
export { $export_${index} as ${nameStringLit} };
import.meta.exports[${nameStringLit}] = {
get: () => $export_${index},
set: (v) => $export_${index} = 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 */
}
const source = `
${Array.prototype.join.call(Array.prototype.map.call(imports, createImport), "\n")}
${Array.prototype.join.call(Array.prototype.map.call(exports, createExport), "\n")}
import.meta.done();
`;
const { registerModule, compileSourceTextModule } =
__hoisted_internal_modules_esm_utils__;
const m = compileSourceTextModule(`${url}`, source);
const readyfns = new Set();
/** @type {DynamicModuleReflect} */
const reflect = {
exports: { __proto__: null },
onReady: (cb) => {
readyfns.add(cb);
},
};
if (imports.length) {
reflect.imports = { __proto__: null };
}
registerModule(m, {
__proto__: null,
initializeImportMeta: (meta, wrap) => {
meta.exports = reflect.exports;
if (reflect.imports) {
meta.imports = reflect.imports;
}
meta.done = () => {
((...args) => globalThis.evaluate(...args))(reflect);
reflect.onReady = (cb) => cb(reflect);
for (const fn of readyfns) {
readyfns.delete(fn);
fn(reflect);
}
};
},
});
return {
module: m,
reflect,
};
};
export default createDynamicModule;