node/lib/internal/loader/CreateDynamicModule.js
Joyee Cheung ebdcf91dcc
src: put bootstrappers in lib/internal/bootstrap/
Create `lib/internal/bootstrap/` and put bootstrappers there:

Before:

```
lib/internal
├── ...
├── bootstrap_loaders.js
└── bootstrap_node.js
```

After:

```
lib/internal
├── ...
└── bootstrap
    ├── loaders.js
    └── node.js
```

Backport-PR-URL: https://github.com/nodejs/node/pull/19374
PR-URL: https://github.com/nodejs/node/pull/19177
Refs: https://github.com/nodejs/node/pull/19112
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
2018-04-04 16:21:09 +02:00

62 lines
1.9 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()();
// 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();
return {
module,
reflect
};
};
module.exports = createDynamicModule;