Repository navigation
Console logs from module loader hooks worker are not printed #51668
Description
Activity
- addedesmIssues and PRs related to the ECMAScript Modules implementation.Issues and PRs related to the ECMAScript Modules implementation.loadersIssues and PRs related to ES module loaders.Issues and PRs related to ES module loaders.
on Apr 28, 2024 Can confirm this is also happening on Windows.
Reacted by uhyo- addedconfirmed-bugIssues and PRs for confirmed bugs.Issues and PRs for confirmed bugs.and removedconfirmed-bugIssues and PRs for confirmed bugs.Issues and PRs for confirmed bugs.
on May 4, 2024 I've been unable to reproduce (on Node.JS v22):
└─$ node --import 'data:text/javascript,import { register } from "node:module"; import { pathToFileURL } from "node:url"; register("./hooks.mjs", pathToFileURL("./"));' ./main.mjs resolve file:///█████████████████/node/testing/main.mjs load { format: 'module', importAttributes: {} } resolve fs load { format: 'builtin', importAttributes: {} }@redyetidev Thanks for looking into it, but I did reproduce this in v22.1.0.
You can try below code to see the issue more clearly. Below code emits logs to the console and a file simulnateously. You should see that only 4 lines are printed to the console, while much more lines are written in
./log.Also you seem to have replaced
graphqlwithfs, but doing so hides the issue becausefsis a built-in module. You need to import a third-party multi-file package written in CJS to reproduce the issue. (the point is to prepare a module graph of form ESM → CJS → CJS so you could prepare multile CJS files locally, but I'd assume this is more burdening than installing a random external package)hooks.mjs:
import { inspect } from "util"; import { readFile } from "fs/promises"; import { appendFileSync } from "fs"; export async function resolve(specifier, context, defaultResolve) { const result = await defaultResolve(specifier, context); console.log("resolve", specifier); appendFileSync("./log", `resolve ${specifier}\n`); return result; } export async function load(url, context, nextLoad) { const result = await nextLoad(url, context); if (result.format === "commonjs") { // This seems the way to opt into the new CJS loader result.source ??= await readFile( new URL(result.responseURL ?? url), "utf-8" ); } console.log("load", context); appendFileSync("./log", `load ${inspect(context)}\n`); return result; }
Thanks! I'll test again later today, using your code with
graphqlI've been able to reproduce now. I'll look into the cause, thanks for the bug report!
- addedconfirmed-bugIssues and PRs for confirmed bugs.Issues and PRs for confirmed bugs.help wantedIssues that need assistance from volunteers or PRs that need help to proceed.Issues that need assistance from volunteers or PRs that need help to proceed.
on May 5, 2024 This is known and documented: https://nodejs.org/docs/latest/api/module.html#hooks
The hooks thread may be terminated by the main thread at any time, so do not depend on asynchronous operations (like
console.log) to complete.Reacted by Aviv Keller- removedconfirmed-bugIssues and PRs for confirmed bugs.Issues and PRs for confirmed bugs.help wantedIssues that need assistance from volunteers or PRs that need help to proceed.Issues that need assistance from volunteers or PRs that need help to proceed.
on May 5, 2024
Version
v20.11.0
Platform
Linux Lenovo-X13 5.15.133.1-microsoft-standard-WSL2 #1 SMP Thu Oct 5 21:02:42 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux
Subsystem
module
What steps will reproduce the bug?
index.mjs:
hooks.mjs:
command to run:
node --import 'data:text/javascript,import { register } from "node:module"; import { pathToFileURL } from "node:url"; register("./hooks.mjs", pathToFileURL("./"));' ./main.mjsHow often does it reproduce? Is there a required condition?
Always
What is the expected behavior? Why is that the expected behavior?
All logs produced by the
console.logcalls in hooks.mjs should be printed to the console that runsnode.What do you see instead?
Only a small part of logs are printed. Below is the entirety of the logs that reached the console. Actually, many more logs have been printed by the hooks.
Additional information
Apparently, logs that aren't shown are ones that are produced during the hooks worker processes CJS -> CJS
requirecalls. In other words, when the main thread is communicating synchronously with the worker, logs fail to reach the screen.This reminds me of Synchronous blocking of stdio documented in the
WorkerAPI reference. In the case of module loader hooks, the main process seems to shut down before the logs have chance to get to the screen.I spent several hours figuring out this why module loader hooks weren't emitting any logs. Improvement would be helpful a lot.