mirror of
https://github.com/nodejs/node.git
synced 2025-05-07 23:52:40 +00:00

Provide named exports for all builtin libraries so that the libraries may be imported in a nicer way for esm users. The default export is left as the entire namespace (module.exports) and wrapped in a proxy such that APMs and other behavior are still left intact. PR-URL: https://github.com/nodejs/node/pull/20403 Reviewed-By: Bradley Farias <bradley.meck@gmail.com> Reviewed-By: Guy Bedford <guybedford@gmail.com> Reviewed-By: Jan Krems <jan.krems@gmail.com>
63 lines
2.0 KiB
JavaScript
63 lines
2.0 KiB
JavaScript
'use strict';
|
|
|
|
const { internalBinding } = require('internal/bootstrap/loaders');
|
|
const { ModuleWrap } = internalBinding('module_wrap');
|
|
const debug = require('util').debuglog('esm');
|
|
const ArrayJoin = Function.call.bind(Array.prototype.join);
|
|
const ArrayMap = Function.call.bind(Array.prototype.map);
|
|
|
|
const createDynamicModule = (exports, url = '', evaluate) => {
|
|
debug(
|
|
`creating ESM facade for ${url} with exports: ${ArrayJoin(exports, ', ')}`
|
|
);
|
|
const names = ArrayMap(exports, (name) => `${name}`);
|
|
// Create two modules: One whose exports are get- and set-able ('reflective'),
|
|
// and one which re-exports all of these but additionally may
|
|
// run an executor function once everything is set up.
|
|
const src = `
|
|
export let executor;
|
|
${ArrayJoin(ArrayMap(names, (name) => `export let $${name};`), '\n')}
|
|
/* This function is implicitly returned as the module's completion value */
|
|
(() => ({
|
|
setExecutor: fn => executor = fn,
|
|
reflect: {
|
|
exports: { ${
|
|
ArrayJoin(ArrayMap(names, (name) => `
|
|
${name}: {
|
|
get: () => $${name},
|
|
set: v => $${name} = v
|
|
}`), ', \n')}
|
|
}
|
|
}
|
|
}));`;
|
|
const reflectiveModule = new ModuleWrap(src, `cjs-facade:${url}`);
|
|
reflectiveModule.instantiate();
|
|
const { setExecutor, reflect } = reflectiveModule.evaluate(-1, false)();
|
|
// public exposed ESM
|
|
const reexports = `
|
|
import {
|
|
executor,
|
|
${ArrayMap(names, (name) => `$${name}`)}
|
|
} from "";
|
|
export {
|
|
${ArrayJoin(ArrayMap(names, (name) => `$${name} as ${name}`), ', ')}
|
|
}
|
|
if (typeof executor === "function") {
|
|
// add await to this later if top level await comes along
|
|
executor()
|
|
}`;
|
|
if (typeof evaluate === 'function') {
|
|
setExecutor(() => evaluate(reflect));
|
|
}
|
|
const module = new ModuleWrap(reexports, `${url}`);
|
|
module.link(async () => reflectiveModule);
|
|
module.instantiate();
|
|
reflect.namespace = module.namespace();
|
|
return {
|
|
module,
|
|
reflect,
|
|
};
|
|
};
|
|
|
|
module.exports = createDynamicModule;
|