@@ -28,18 +28,20 @@ const { |
28 | 28 | } = require('internal/test_runner/utils'); |
29 | 29 | const { queueMicrotask } = require('internal/process/task_queues'); |
30 | 30 | const { bigint: hrtime } = process.hrtime; |
31 | | - |
| 31 | +const resolvedPromise = PromiseResolve(); |
32 | 32 | const testResources = new SafeMap(); |
| 33 | +let globalRoot; |
33 | 34 |
|
34 | 35 | testResources.set(reporterScope.asyncId(), reporterScope); |
35 | 36 |
|
36 | 37 | function createTestTree(options = kEmptyObject) { |
37 | | - return setup(new Test({ __proto__: null, ...options, name: '<root>' })); |
| 38 | + globalRoot = setup(new Test({ __proto__: null, ...options, name: '<root>' })); |
| 39 | + return globalRoot; |
38 | 40 | } |
39 | 41 |
|
40 | 42 | function createProcessEventHandler(eventName, rootTest) { |
41 | 43 | return (err) => { |
42 | | - if (!rootTest.harness.bootstrapComplete) { |
| 44 | + if (rootTest.harness.bootstrapPromise) { |
43 | 45 | // Something went wrong during the asynchronous portion of bootstrapping |
44 | 46 | // the test runner. Since the test runner is not setup properly, we can't |
45 | 47 | // do anything but throw the error. |
@@ -196,7 +198,7 @@ function setup(root) { |
196 | 198 | root.harness = { |
197 | 199 | __proto__: null, |
198 | 200 | allowTestsToRun: false, |
199 | | - bootstrapComplete: false, |
| 201 | + bootstrapPromise: resolvedPromise, |
200 | 202 | watching: false, |
201 | 203 | coverage: FunctionPrototypeBind(collectCoverage, null, root, coverage), |
202 | 204 | resetCounters() { |
@@ -222,33 +224,30 @@ function setup(root) { |
222 | 224 | return root; |
223 | 225 | } |
224 | 226 |
|
225 | | -let globalRoot; |
226 | | -let asyncBootstrap; |
227 | 227 | function lazyBootstrapRoot() { |
228 | 228 | if (!globalRoot) { |
229 | | - globalRoot = createTestTree({ __proto__: null, entryFile: process.argv?.[1] }); |
| 229 | + // This is where the test runner is bootstrapped when node:test is used |
| 230 | + // without the --test flag or the run() API. |
| 231 | + createTestTree({ __proto__: null, entryFile: process.argv?.[1] }); |
230 | 232 | globalRoot.reporter.on('test:fail', (data) => { |
231 | 233 | if (data.todo === undefined || data.todo === false) { |
232 | 234 | process.exitCode = kGenericUserError; |
233 | 235 | } |
234 | 236 | }); |
235 | | - asyncBootstrap = setupTestReporters(globalRoot.reporter); |
| 237 | + globalRoot.harness.bootstrapPromise = setupTestReporters(globalRoot.reporter); |
236 | 238 | } |
237 | 239 | return globalRoot; |
238 | 240 | } |
239 | 241 |
|
240 | | -async function startSubtest(subtest) { |
241 | | - if (asyncBootstrap) { |
| 242 | +async function startSubtestAfterBootstrap(subtest) { |
| 243 | + if (subtest.root.harness.bootstrapPromise) { |
242 | 244 | // Only incur the overhead of awaiting the Promise once. |
243 | | - await asyncBootstrap; |
244 | | - asyncBootstrap = undefined; |
245 | | - if (!subtest.root.harness.bootstrapComplete) { |
246 | | - subtest.root.harness.bootstrapComplete = true; |
247 | | - queueMicrotask(() => { |
248 | | - subtest.root.harness.allowTestsToRun = true; |
249 | | - subtest.root.processPendingSubtests(); |
250 | | - }); |
251 | | - } |
| 245 | + await subtest.root.harness.bootstrapPromise; |
| 246 | + subtest.root.harness.bootstrapPromise = null; |
| 247 | + queueMicrotask(() => { |
| 248 | + subtest.root.harness.allowTestsToRun = true; |
| 249 | + subtest.root.processPendingSubtests(); |
| 250 | + }); |
252 | 251 | } |
253 | 252 |
|
254 | 253 | await subtest.start(); |
@@ -262,7 +261,7 @@ function runInParentContext(Factory) { |
262 | 261 | return PromiseResolve(); |
263 | 262 | } |
264 | 263 |
|
265 | | - return startSubtest(subtest); |
| 264 | + return startSubtestAfterBootstrap(subtest); |
266 | 265 | } |
267 | 266 |
|
268 | 267 | const test = (name, options, fn) => { |
|