mirror of
https://github.com/nodejs/node.git
synced 2025-08-15 13:48:44 +02:00
module: improve error message from asynchronicity in require(esm)
- Improve the error message that shows up when there is a race from doing require(esm) and import(esm) at the same time. - Improve error message of ERR_REQUIRE_ASYNC_MODULE by showing parent and target file names, if available. Drive-by: split the require(tla) tests since we are modifying the tests already. PR-URL: https://github.com/nodejs/node/pull/57126 Refs: https://github.com/fisker/prettier-issue-17139 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
This commit is contained in:
parent
d601c7d104
commit
8d10bc7b09
13 changed files with 190 additions and 79 deletions
|
@ -338,20 +338,37 @@ class ModuleLoader {
|
|||
// TODO(joyeecheung): ensure that imported synchronous graphs are evaluated
|
||||
// synchronously so that any previously imported synchronous graph is already
|
||||
// evaluated at this point.
|
||||
// TODO(joyeecheung): add something similar to CJS loader's requireStack to help
|
||||
// debugging the the problematic links in the graph for import.
|
||||
if (job !== undefined) {
|
||||
mod[kRequiredModuleSymbol] = job.module;
|
||||
if (job.module.async) {
|
||||
throw new ERR_REQUIRE_ASYNC_MODULE();
|
||||
const parentFilename = urlToFilename(parent?.filename);
|
||||
// TODO(node:55782): this race may stop to happen when the ESM resolution and loading become synchronous.
|
||||
if (!job.module) {
|
||||
let message = `Cannot require() ES Module ${filename} because it is not yet fully loaded. `;
|
||||
message += 'This may be caused by a race condition if the module is simultaneously dynamically ';
|
||||
message += 'import()-ed via Promise.all(). Try await-ing the import() sequentially in a loop instead.';
|
||||
if (parentFilename) {
|
||||
message += ` (from ${parentFilename})`;
|
||||
}
|
||||
assert(job.module, message);
|
||||
}
|
||||
if (job.module.async) {
|
||||
throw new ERR_REQUIRE_ASYNC_MODULE(filename, parentFilename);
|
||||
}
|
||||
// job.module may be undefined if it's asynchronously loaded. Which means
|
||||
// there is likely a cycle.
|
||||
if (job.module.getStatus() !== kEvaluated) {
|
||||
const parentFilename = urlToFilename(parent?.filename);
|
||||
let message = `Cannot require() ES Module ${filename} in a cycle.`;
|
||||
if (parentFilename) {
|
||||
message += ` (from ${parentFilename})`;
|
||||
}
|
||||
message += 'A cycle involving require(esm) is disallowed to maintain ';
|
||||
message += 'invariants madated by the ECMAScript specification';
|
||||
message += 'Try making at least part of the dependency in the graph lazily loaded.';
|
||||
throw new ERR_REQUIRE_CYCLE_MODULE(message);
|
||||
}
|
||||
return { wrap: job.module, namespace: job.module.getNamespaceSync() };
|
||||
return { wrap: job.module, namespace: job.module.getNamespaceSync(filename, parentFilename) };
|
||||
}
|
||||
// TODO(joyeecheung): refactor this so that we pre-parse in C++ and hit the
|
||||
// cache here, or use a carrier object to carry the compiled module script
|
||||
|
@ -363,7 +380,7 @@ class ModuleLoader {
|
|||
job = new ModuleJobSync(this, url, kEmptyObject, wrap, isMain, inspectBrk);
|
||||
this.loadCache.set(url, kImplicitTypeAttribute, job);
|
||||
mod[kRequiredModuleSymbol] = job.module;
|
||||
return { wrap: job.module, namespace: job.runSync().namespace };
|
||||
return { wrap: job.module, namespace: job.runSync(parent).namespace };
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue