|
1 | 1 | // Flags: --no-warnings |
2 | | -import { spawnPromisified } from '../common/index.mjs'; |
| 2 | +import '../common/index.mjs'; |
| 3 | +import { spawnSyncAndAssert } from '../common/child_process.js'; |
3 | 4 | import * as fixtures from '../common/fixtures.mjs'; |
4 | 5 | import { describe, it } from 'node:test'; |
5 | 6 | import assert from 'node:assert'; |
6 | 7 |
|
| 8 | +// Promise counts are implementation details tracked for regressions, not API guarantees. |
7 | 9 |
|
8 | 10 | describe('synchronous ESM loading', () => { |
9 | 11 | 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')); |
13 | 13 | assert.strictEqual(count, 1); |
14 | 14 | }); |
15 | 15 |
|
16 | 16 | 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')); |
22 | 18 | assert.strictEqual(count, 4); |
23 | 19 | }); |
24 | 20 |
|
25 | 21 | 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')); |
32 | 23 | assert(count > 1, `Expected TLA fallback to create multiple promises, got ${count}`); |
33 | 24 | }); |
34 | 25 |
|
35 | 26 | 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')); |
40 | 28 | assert.strictEqual(count, 1); |
41 | 29 | }); |
42 | 30 | }); |
43 | 31 |
|
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, [ |
47 | 34 | '--trace-promises', |
48 | 35 | entry, |
49 | | - ]); |
50 | | - assert.strictEqual(code, 0, `child failed:\nstdout: ${stdout}\nstderr: ${stderr}`); |
| 36 | + ], { |
| 37 | + stderr: /created promise #/, |
| 38 | + }); |
51 | 39 | return stderr.match(/created promise #/g)?.length ?? 0; |
52 | 40 | } |
0 commit comments