Skip to content

Commit 594830d

Browse files
committed
esm: fallback to readFileSync when source is nullish
When using the Modules Customization Hooks API to load CommonJS modules, we want to support the returned value of `defaultLoad` which must be nullish to preserve backward compatibility. This can be achieved by fetching the source from the translator.
1 parent a9a4778 commit 594830d

File tree

3 files changed

+44
-1
lines changed

3 files changed

+44
-1
lines changed

lib/internal/modules/esm/load.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,5 +261,6 @@ function throwUnknownModuleFormat(url, format) {
261261
module.exports = {
262262
defaultLoad,
263263
defaultLoadSync,
264+
getSourceSync,
264265
throwUnknownModuleFormat,
265266
};

lib/internal/modules/esm/translators.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,13 @@ const asyncESM = require('internal/process/esm_loader');
5858
const { emitWarningSync } = require('internal/process/warning');
5959
const { internalCompileFunction } = require('internal/vm');
6060

61+
// Lazy-loading to avoid circular dependencies.
62+
let getSourceSync;
63+
function getSource(url) {
64+
getSourceSync ??= require('internal/modules/esm/load').getSourceSync;
65+
return getSourceSync(url).source;
66+
}
67+
6168
/** @type {import('deps/cjs-module-lexer/lexer.js').parse} */
6269
let cjsParse;
6370
/**
@@ -276,7 +283,7 @@ function createCJSModuleWrap(url, source, isMain, loadCJS = loadCJSModule) {
276283
debug(`Translating CJSModule ${url}`);
277284

278285
const filename = StringPrototypeStartsWith(url, 'file://') ? fileURLToPath(url) : url;
279-
source = stringify(source);
286+
source = stringify(source ?? getSource(new URL(url)));
280287

281288
const { exportNames, module } = cjsPreparseModuleExports(filename, source);
282289
cjsCache.set(url, module);

test/es-module/test-esm-loader-hooks.mjs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -746,4 +746,39 @@ describe('Loader hooks', { concurrency: true }, () => {
746746
assert.strictEqual(code, 0);
747747
assert.strictEqual(signal, null);
748748
});
749+
750+
it('should handle mixed of opt-in modules and non-opt-in ones', async () => {
751+
const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [
752+
'--no-warnings',
753+
'--experimental-loader',
754+
`data:text/javascript,const fixtures=${JSON.stringify(fixtures.path('empty.js'))};export ${
755+
encodeURIComponent(function resolve(s, c, n) {
756+
if (s.endsWith('entry-point')) {
757+
return {
758+
shortCircuit: true,
759+
url: 'file:///virtual-entry-point',
760+
format: 'commonjs',
761+
};
762+
}
763+
return n(s, c);
764+
})
765+
}export ${
766+
encodeURIComponent(async function load(u, c, n) {
767+
if (u === 'file:///virtual-entry-point') {
768+
return {
769+
shortCircuit: true,
770+
source: `"use strict";require(${JSON.stringify(fixtures)});console.log("Hello");`,
771+
format: 'commonjs',
772+
};
773+
}
774+
return n(u, c);
775+
})}`,
776+
'entry-point',
777+
]);
778+
779+
assert.strictEqual(stderr, '');
780+
assert.strictEqual(stdout, 'Hello\n');
781+
assert.strictEqual(code, 0);
782+
assert.strictEqual(signal, null);
783+
});
749784
});

0 commit comments

Comments
 (0)