module: allow cycles in require() in the CJS handling in ESM loader
When --import is used, the ESM loader is used to handle even pure CJS entry points, and it can run into CJS module facades in the evaluating state when the parent CJS module is being evaluated. In this case it should be allowed, since the ESM <-> CJS cycles that are meant to be disallowed (for the time being) should already be detected before evaluation and wouldn't get here, and CJS <-> CJS cycles are fine. PR-URL: https://github.com/nodejs/node/pull/58598 Fixes: https://github.com/nodejs/node/issues/58515 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Ethan Arrowood <ethan@arrowood.dev>
This commit is contained in:
parent
ccf105df2a
commit
8c17ceb38f
@ -26,6 +26,7 @@ const {
|
||||
ModuleWrap,
|
||||
kErrored,
|
||||
kEvaluated,
|
||||
kEvaluating,
|
||||
kEvaluationPhase,
|
||||
kInstantiated,
|
||||
kUninstantiated,
|
||||
@ -338,8 +339,14 @@ class ModuleJob extends ModuleJobBase {
|
||||
return { __proto__: null, module: this.module, namespace };
|
||||
}
|
||||
throw this.module.getError();
|
||||
|
||||
} else if (status === kEvaluated) {
|
||||
} else if (status === kEvaluating || status === kEvaluated) {
|
||||
// kEvaluating can show up when this is being used to deal with CJS <-> CJS cycles.
|
||||
// Allow it for now, since we only need to ban ESM <-> CJS cycles which would be
|
||||
// detected earlier during the linking phase, though the CJS handling in the ESM
|
||||
// loader won't be able to emit warnings on pending circular exports like what
|
||||
// the CJS loader does.
|
||||
// TODO(joyeecheung): remove the re-invented require() in the ESM loader and
|
||||
// always handle CJS using the CJS loader to eliminate the quirks.
|
||||
return { __proto__: null, module: this.module, namespace: this.module.getNamespaceSync() };
|
||||
}
|
||||
assert.fail(`Unexpected module status ${status}.`);
|
||||
|
@ -783,11 +783,10 @@ void ModuleWrap::GetNamespaceSync(const FunctionCallbackInfo<Value>& args) {
|
||||
return realm->env()->ThrowError(
|
||||
"Cannot get namespace, module has not been instantiated");
|
||||
case Module::Status::kInstantiated:
|
||||
case Module::Status::kEvaluating:
|
||||
case Module::Status::kEvaluated:
|
||||
case Module::Status::kErrored:
|
||||
break;
|
||||
case Module::Status::kEvaluating:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
if (module->IsGraphAsync()) {
|
||||
|
20
test/es-module/test-import-preload-require-cycle.js
Normal file
20
test/es-module/test-import-preload-require-cycle.js
Normal file
@ -0,0 +1,20 @@
|
||||
'use strict';
|
||||
|
||||
// This tests that --import preload does not break CJS entry points that contains
|
||||
// require cycles.
|
||||
|
||||
require('../common');
|
||||
const fixtures = require('../common/fixtures');
|
||||
const { spawnSyncAndAssert } = require('../common/child_process');
|
||||
|
||||
spawnSyncAndAssert(
|
||||
process.execPath,
|
||||
[
|
||||
'--import',
|
||||
fixtures.fileURL('import-require-cycle/preload.mjs'),
|
||||
fixtures.path('import-require-cycle/c.js'),
|
||||
],
|
||||
{
|
||||
stdout: /cycle equality true/,
|
||||
}
|
||||
);
|
1
test/fixtures/import-require-cycle/a.js
vendored
Normal file
1
test/fixtures/import-require-cycle/a.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
module.exports.b = require('./b.js');
|
1
test/fixtures/import-require-cycle/b.js
vendored
Normal file
1
test/fixtures/import-require-cycle/b.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
module.exports.a = require('./a.js');
|
3
test/fixtures/import-require-cycle/c.js
vendored
Normal file
3
test/fixtures/import-require-cycle/c.js
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
const obj = require('./b.js');
|
||||
|
||||
console.log('cycle equality', obj.a.b === obj);
|
7
test/fixtures/import-require-cycle/preload.mjs
vendored
Normal file
7
test/fixtures/import-require-cycle/preload.mjs
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
import * as mod from "module";
|
||||
|
||||
mod.registerHooks({
|
||||
load(url, context, nextLoad) {
|
||||
return nextLoad(url, context);
|
||||
},
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user