. * @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 { registerModule, compileSourceTextModule } = require('internal/modules/esm/utils'); const m = compileSourceTextModule(`${url}`, source); const readyfns = new SafeSet(); /** @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 = () => { evaluate(reflect); reflect.onReady = (cb) => cb(reflect); for (const fn of readyfns) { readyfns.delete(fn); fn(reflect); } }; }, }); return { module: m, reflect, }; }; module.exports = createDynamicModule;