Tooling in the ecosystem have been using the __esModule property to
recognize transpiled ESM in consuming code. For example, a 'log'
package written in ESM:
export function log(val) { console.log(val); }
Can be transpiled as:
exports.__esModule = true;
exports.default = function log(val) { console.log(val); }
The consuming code may be written like this in ESM:
import log from 'log'
Which gets transpiled to:
const _mod = require('log');
const log = _mod.__esModule ? _mod.default : _mod;
So to allow transpiled consuming code to recognize require()'d real ESM
as ESM and pick up the default exports, we add a __esModule property by
building a source text module facade for any module that has a default
export and add .__esModule = true to the exports. We don't do this to
modules that don't have default exports to avoid the unnecessary
overhead. This maintains the enumerability of the re-exported names
and the live binding of the exports.
The source of the facade is defined as a constant per-isolate property
required_module_facade_source_string, which looks like this
export * from 'original';
export { default } from 'original';
export const __esModule = true;
And the 'original' module request is always resolved by
createRequiredModuleFacade() to wrap which is a ModuleWrap wrapping
over the original module.
PR-URL: https://github.com/nodejs/node/pull/52166
Refs: https://github.com/nodejs/node/issues/52134
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
Reviewed-By: Guy Bedford <guybedford@gmail.com>
Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com>
23 lines
1,003 B
JavaScript
23 lines
1,003 B
JavaScript
'use strict';
|
|
|
|
// This script is used to transpile ESM fixtures from the src/ directory
|
|
// to CJS modules in dist/. The transpiled CJS files are used to test
|
|
// integration of transpiled CJS modules loading real ESM.
|
|
|
|
const { readFileSync, writeFileSync, readdirSync } = require('node:fs');
|
|
|
|
// We use typescript.js because it's already in the code base as a fixture.
|
|
// Most ecosystem tools follow a similar pattern, and this produces a bare
|
|
// minimum integration test for existing patterns.
|
|
const ts = require('../../snapshot/typescript');
|
|
const { join } = require('node:path');
|
|
const sourceDir = join(__dirname, 'src');
|
|
const files = readdirSync(sourceDir);
|
|
for (const filename of files) {
|
|
const filePath = join(sourceDir, filename);
|
|
const source = readFileSync(filePath, 'utf8');
|
|
const { outputText } = ts.transpileModule(source, {
|
|
compilerOptions: { module: ts.ModuleKind.NodeNext }
|
|
});
|
|
writeFileSync(join(__dirname, 'dist', filename.replace('.mjs', '.cjs')), outputText, 'utf8');
|
|
}
|