Skip to content

Commit 14983e9

Browse files
mihailtclaude
andcommitted
test(startup): record the server's modules on Node before 22.15 too
test-startup-imports.js and the repro test-startup-heavy-imports.js failed at client.connect ("Connection closed") on every Node before 22.15.0: checked on 18.20.8, 20.19.5, 20.20.2 and 22.14.0. Their preload imported registerHooks from node:module, which Node has only from 22.15.0 / 23.5.0. On older Node the preload failed to link ("does not provide an export named 'registerHooks'") and the server never started. The preload now uses registerHooks() where it exists. Before 22.15 it records imports through module.register() (record-modules-hooks.mjs) and requires through Module._resolveFilename, in the same log format. At the commit before, the test fails at connect on 20.20.2 and 22.14.0. Here it passes on 18.20.8, 20.20.2, 22.14.0, 22.15.0 and 24.18.0, with the same 374 modules recorded before initialize on each. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
1 parent a185755 commit 14983e9

2 files changed

Lines changed: 37 additions & 8 deletions

File tree

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Registered by record-modules-preload.mjs with module.register() on Node
2+
// before 22.15. Runs on Node's loader thread and writes every module an import
3+
// resolves to DC_TEST_MODULE_LOG, in the preload's format.
4+
import fs from 'node:fs';
5+
6+
const log = fs.openSync(process.env.DC_TEST_MODULE_LOG, 'a');
7+
8+
export async function resolve(specifier, context, nextResolve) {
9+
const resolved = await nextResolve(specifier, context);
10+
fs.writeSync(log, `${Date.now()} ${resolved.url} ${context.parentURL ?? ''}\n`);
11+
return resolved;
12+
}
Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,32 @@
11
// Preloaded into the real server (node --import) by test/helpers/server-modules.js:
22
// writes every module the server resolves, through import or require, to
33
// DC_TEST_MODULE_LOG as it happens, one "<Date.now()> <url> <parent url>" line each.
4+
// module.registerHooks() sees both, but Node has it only from 22.15. Before
5+
// that, imports are recorded by record-modules-hooks.mjs through
6+
// module.register(), and requires through Module._resolveFilename (which a
7+
// require('node:...') of a built-in skips; the tests leave built-ins out).
48
import fs from 'node:fs';
5-
import { registerHooks } from 'node:module';
9+
import Module from 'node:module';
10+
import { pathToFileURL } from 'node:url';
611

712
const log = fs.openSync(process.env.DC_TEST_MODULE_LOG, 'a');
13+
const record = (url, parentURL) => fs.writeSync(log, `${Date.now()} ${url} ${parentURL ?? ''}\n`);
814

9-
registerHooks({
10-
resolve(specifier, context, nextResolve) {
11-
const resolved = nextResolve(specifier, context);
12-
fs.writeSync(log, `${Date.now()} ${resolved.url} ${context.parentURL ?? ''}\n`);
13-
return resolved;
14-
},
15-
});
15+
if (Module.registerHooks) {
16+
Module.registerHooks({
17+
resolve(specifier, context, nextResolve) {
18+
const resolved = nextResolve(specifier, context);
19+
record(resolved.url, context.parentURL);
20+
return resolved;
21+
},
22+
});
23+
} else {
24+
Module.register('./record-modules-hooks.mjs', import.meta.url);
25+
const resolveFilename = Module._resolveFilename;
26+
Module._resolveFilename = function (request, parent, ...rest) {
27+
const filename = resolveFilename.call(this, request, parent, ...rest);
28+
const url = Module.isBuiltin(filename) ? `node:${filename.replace(/^node:/, '')}` : pathToFileURL(filename).href;
29+
record(url, parent?.filename && pathToFileURL(parent.filename).href);
30+
return filename;
31+
};
32+
}

0 commit comments

Comments
 (0)