Skip to content

Commit ed5d760

Browse files
committed
test: improve ESM loader regression coverage
Assisted-by: Codex Signed-off-by: Geoffrey Booth <webadmin@geoffreybooth.com>
1 parent 2f42366 commit ed5d760

4 files changed

Lines changed: 34 additions & 44 deletions

File tree

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import '../common/index.mjs';
2+
import { spawnSyncAndAssert } from '../common/child_process.js';
3+
import * as fixtures from '../common/fixtures.mjs';
4+
import assert from 'assert';
5+
6+
const entryPoint = fixtures.path('es-modules', 'package-cjs-named-error', 'single-quote.mjs');
7+
spawnSyncAndAssert(process.execPath, [entryPoint], {
8+
status: 1,
9+
stderr(stderr) {
10+
assert(stderr.includes("Named export 'comeOn' not found."),
11+
'entry point should show the missing named export');
12+
assert(stderr.includes('CommonJS modules can always be imported via the default export'),
13+
'entry point should show the CommonJS named export hint');
14+
assert(stderr.includes("import pkg from './fail.cjs';"),
15+
'entry point hint should recommend the default import');
16+
assert(stderr.includes('const { comeOn } = pkg;'),
17+
'entry point hint should show the named import as destructuring');
18+
assert(stderr.includes("import { comeOn } from './fail.cjs';"),
19+
'entry point error should include the source import statement');
20+
},
21+
});

‎test/es-module/test-esm-cjs-named-error.mjs‎

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
import { spawnPromisified } from '../common/index.mjs';
2-
import * as fixtures from '../common/fixtures.mjs';
1+
import '../common/index.mjs';
32
import assert from 'assert';
4-
import { execPath } from 'node:process';
53

64
const fixtureBase = '../fixtures/es-modules/package-cjs-named-error';
75

@@ -77,17 +75,3 @@ await assert.rejects(async () => {
7775
await assert.rejects(async () => {
7876
await import(`${fixtureBase}/escaped-single-quote.mjs`);
7977
}, /import pkg from '\.\/oh'no\.cjs'/, 'should support relative specifiers with escaped single quote');
80-
81-
const entryPoint = fixtures.path('es-modules', 'package-cjs-named-error', 'single-quote.mjs');
82-
const { code, stderr } = await spawnPromisified(execPath, [entryPoint]);
83-
assert.strictEqual(code, 1);
84-
assert.ok(stderr.includes("Named export 'comeOn' not found."),
85-
'entry point should show the missing named export');
86-
assert.ok(stderr.includes('CommonJS modules can always be imported via the default export'),
87-
'entry point should show the CommonJS named export hint');
88-
assert.ok(stderr.includes("import pkg from './fail.cjs';"),
89-
'entry point hint should recommend the default import');
90-
assert.ok(stderr.includes('const { comeOn } = pkg;'),
91-
'entry point hint should show the named import as destructuring');
92-
assert.ok(stderr.includes("import { comeOn } from './fail.cjs';"),
93-
'entry point error should include the source import statement');
Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,40 @@
11
// Flags: --no-warnings
2-
import { spawnPromisified } from '../common/index.mjs';
2+
import '../common/index.mjs';
3+
import { spawnSyncAndAssert } from '../common/child_process.js';
34
import * as fixtures from '../common/fixtures.mjs';
45
import { describe, it } from 'node:test';
56
import assert from 'node:assert';
67

8+
// Promise counts are implementation details tracked for regressions, not API guarantees.
79

810
describe('synchronous ESM loading', () => {
911
it('should create minimal promises for ESM importing ESM', async () => {
10-
// import-esm.mjs imports imported-esm.mjs — a pure ESM graph.
11-
const count = await getPromiseCount(fixtures.path('es-modules', 'import-esm.mjs'));
12-
// V8's Module::Evaluate returns one promise for the entire graph.
12+
const count = getPromiseCount(fixtures.path('es-modules', 'import-esm.mjs'));
1313
assert.strictEqual(count, 1);
1414
});
1515

1616
it('should create minimal promises for ESM importing CJS', async () => {
17-
// builtin-imports-case.mjs imports node:assert (builtin) + dep1.js and dep2.js (CJS).
18-
const count = await getPromiseCount(fixtures.path('es-modules', 'builtin-imports-case.mjs'));
19-
// V8 creates one promise for the ESM entry evaluation, plus one per CJS module
20-
// in the graph (each CJS namespace is wrapped in a promise).
21-
// entry (ESM, 1) + node:assert (CJS, 1) + dep1.js (CJS, 1) + dep2.js (CJS, 1) = 4.
17+
const count = getPromiseCount(fixtures.path('es-modules', 'builtin-imports-case.mjs'));
2218
assert.strictEqual(count, 4);
2319
});
2420

2521
it('should fall back to async evaluation for top-level await', async () => {
26-
// tla/resolved.mjs uses top-level await, so the sync path detects TLA
27-
// and falls back to async evaluation.
28-
const count = await getPromiseCount(fixtures.path('es-modules', 'tla', 'resolved.mjs'));
29-
// The async fallback creates more promises — just verify the module
30-
// still runs successfully. The promise count will be higher than the
31-
// sync path but should remain bounded.
22+
const count = getPromiseCount(fixtures.path('es-modules', 'tla', 'resolved.mjs'));
3223
assert(count > 1, `Expected TLA fallback to create multiple promises, got ${count}`);
3324
});
3425

3526
it('should create minimal promises when entry point is CJS importing ESM', async () => {
36-
// When a CJS entry point uses require(esm), the ESM module is loaded via
37-
// ModuleJobSync, so the same promise minimization applies.
38-
const count = await getPromiseCount(fixtures.path('es-modules', 'require-esm-entry.cjs'));
39-
// V8's Module::Evaluate returns one promise for the ESM module.
27+
const count = getPromiseCount(fixtures.path('es-modules', 'require-esm-entry.cjs'));
4028
assert.strictEqual(count, 1);
4129
});
4230
});
4331

44-
45-
async function getPromiseCount(entry) {
46-
const { stdout, stderr, code } = await spawnPromisified(process.execPath, [
32+
function getPromiseCount(entry) {
33+
const { stderr } = spawnSyncAndAssert(process.execPath, [
4734
'--trace-promises',
4835
entry,
49-
]);
50-
assert.strictEqual(code, 0, `child failed:\nstdout: ${stdout}\nstderr: ${stderr}`);
36+
], {
37+
stderr: /created promise #/,
38+
});
5139
return stderr.match(/created promise #/g)?.length ?? 0;
5240
}

‎test/parallel/test-inspector-debug-brk-flag-esm-tla.js‎

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,6 @@ async function testBreakpointOnStart(session) {
1818
'params': { 'state': 'none' } },
1919
{ 'method': 'Debugger.setAsyncCallStackDepth',
2020
'params': { 'maxDepth': 0 } },
21-
{ 'method': 'Profiler.enable' },
22-
{ 'method': 'Profiler.setSamplingInterval',
23-
'params': { 'interval': 100 } },
2421
{ 'method': 'Debugger.setBlackboxPatterns',
2522
'params': { 'patterns': [] } },
2623
{ 'method': 'Runtime.runIfWaitingForDebugger' },

0 commit comments

Comments
 (0)