Skip to content

Commit 321015e

Browse files
Merge branch 'nodejs:main' into headers-request-timers-fix
2 parents 5db2538 + 2fca7ea commit 321015e

28 files changed

+491
-118
lines changed

CHANGELOG.md

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
Select a Node.js version below to view the changelog history:
44

55
* [Node.js 20](doc/changelogs/CHANGELOG_V20.md) **Current**
6-
* [Node.js 19](doc/changelogs/CHANGELOG_V19.md) **Current**
6+
* [Node.js 19](doc/changelogs/CHANGELOG_V19.md) End-of-Life
77
* [Node.js 18](doc/changelogs/CHANGELOG_V18.md) **Long Term Support**
88
* [Node.js 17](doc/changelogs/CHANGELOG_V17.md) End-of-Life
99
* [Node.js 16](doc/changelogs/CHANGELOG_V16.md) **Long Term Support**
@@ -30,7 +30,6 @@ release.
3030
<table>
3131
<tr>
3232
<th title="Current"><a href="doc/changelogs/CHANGELOG_V20.md">20</a> (Current)</th>
33-
<th title="Current"><a href="doc/changelogs/CHANGELOG_V19.md">19</a> (Current)</th>
3433
<th title="LTS Until 2025-04"><a href="doc/changelogs/CHANGELOG_V18.md">18</a> (LTS)</th>
3534
<th title="LTS Until 2023-09"><a href="doc/changelogs/CHANGELOG_V16.md">16</a> (LTS)</th>
3635
</tr>
@@ -41,21 +40,6 @@ release.
4140
<a href="doc/changelogs/CHANGELOG_V20.md#20.0.0">20.0.0</a><br/>
4241
</td>
4342
<td valign="top">
44-
<b><a href="doc/changelogs/CHANGELOG_V19.md#19.9.0">19.9.0</a></b><br/>
45-
<a href="doc/changelogs/CHANGELOG_V19.md#19.8.1">19.8.1</a><br/>
46-
<a href="doc/changelogs/CHANGELOG_V19.md#19.8.0">19.8.0</a><br/>
47-
<a href="doc/changelogs/CHANGELOG_V19.md#19.7.0">19.7.0</a><br/>
48-
<a href="doc/changelogs/CHANGELOG_V19.md#19.6.1">19.6.1</a><br/>
49-
<a href="doc/changelogs/CHANGELOG_V19.md#19.6.0">19.6.0</a><br/>
50-
<a href="doc/changelogs/CHANGELOG_V19.md#19.5.0">19.5.0</a><br/>
51-
<a href="doc/changelogs/CHANGELOG_V19.md#19.4.0">19.4.0</a><br/>
52-
<a href="doc/changelogs/CHANGELOG_V19.md#19.3.0">19.3.0</a><br/>
53-
<a href="doc/changelogs/CHANGELOG_V19.md#19.2.0">19.2.0</a><br/>
54-
<a href="doc/changelogs/CHANGELOG_V19.md#19.1.0">19.1.0</a><br/>
55-
<a href="doc/changelogs/CHANGELOG_V19.md#19.0.1">19.0.1</a><br/>
56-
<a href="doc/changelogs/CHANGELOG_V19.md#19.0.0">19.0.0</a><br/>
57-
</td>
58-
<td valign="top">
5943
<b><a href="doc/changelogs/CHANGELOG_V18.md#18.16.0">18.16.0</a></b><br/>
6044
<a href="doc/changelogs/CHANGELOG_V18.md#18.15.0">18.15.0</a><br/>
6145
<a href="doc/changelogs/CHANGELOG_V18.md#18.14.2">18.14.2</a><br/>

configure.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1471,7 +1471,7 @@ def configure_library(lib, output, pkgname=None):
14711471

14721472

14731473
def configure_v8(o):
1474-
o['variables']['v8_enable_webassembly'] = 1
1474+
o['variables']['v8_enable_webassembly'] = 0 if options.v8_lite_mode else 1
14751475
o['variables']['v8_enable_javascript_promise_hooks'] = 1
14761476
o['variables']['v8_enable_lite_mode'] = 1 if options.v8_lite_mode else 0
14771477
o['variables']['v8_enable_gdbjit'] = 1 if options.gdb else 0

doc/api/test.md

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -744,25 +744,26 @@ changes:
744744
**Default:** `false`.
745745
* `files`: {Array} An array containing the list of files to run.
746746
**Default** matching files from [test runner execution model][].
747-
* `setup` {Function} A function that accepts the `TestsStream` instance
748-
and can be used to setup listeners before any tests are run.
749-
**Default:** `undefined`.
750-
* `signal` {AbortSignal} Allows aborting an in-progress test execution.
751-
* `timeout` {number} A number of milliseconds the test execution will
752-
fail after.
753-
If unspecified, subtests inherit this value from their parent.
754-
**Default:** `Infinity`.
755747
* `inspectPort` {number|Function} Sets inspector port of test child process.
756748
This can be a number, or a function that takes no arguments and returns a
757749
number. If a nullish value is provided, each process gets its own port,
758750
incremented from the primary's `process.debugPort`.
759751
**Default:** `undefined`.
752+
* `setup` {Function} A function that accepts the `TestsStream` instance
753+
and can be used to setup listeners before any tests are run.
754+
**Default:** `undefined`.
755+
* `signal` {AbortSignal} Allows aborting an in-progress test execution.
760756
* `testNamePatterns` {string|RegExp|Array} A String, RegExp or a RegExp Array,
761757
that can be used to only run tests whose name matches the provided pattern.
762758
Test name patterns are interpreted as JavaScript regular expressions.
763759
For each test that is executed, any corresponding test hooks, such as
764760
`beforeEach()`, are also run.
765761
**Default:** `undefined`.
762+
* `timeout` {number} A number of milliseconds the test execution will
763+
fail after.
764+
If unspecified, subtests inherit this value from their parent.
765+
**Default:** `Infinity`.
766+
* `watch` {boolean} Whether to run in watch mode or not. **Default:** `false`.
766767
* Returns: {TestsStream}
767768

768769
```mjs
@@ -1539,6 +1540,10 @@ This event is only emitted if `--test` flag is passed.
15391540
Emitted when a running test writes to `stdout`.
15401541
This event is only emitted if `--test` flag is passed.
15411542

1543+
### Event: `'test:watch:drained'`
1544+
1545+
Emitted when no more tests are queued for execution in watch mode.
1546+
15421547
## Class: `TestContext`
15431548

15441549
<!-- YAML

lib/_tls_wrap.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -634,8 +634,8 @@ TLSSocket.prototype._wrapHandle = function(wrap, handle) {
634634
};
635635

636636
TLSSocket.prototype[kReinitializeHandle] = function reinitializeHandle(handle) {
637-
const originalServername = this._handle.getServername();
638-
const originalSession = this._handle.getSession();
637+
const originalServername = this.ssl ? this._handle.getServername() : null;
638+
const originalSession = this.ssl ? this._handle.getSession() : null;
639639

640640
this.handle = this._wrapHandle(null, handle);
641641
this.ssl = this._handle;
@@ -832,6 +832,14 @@ TLSSocket.prototype._init = function(socket, wrap) {
832832
}
833833
}
834834

835+
// We can only come here via [kWrapConnectedHandle]() call that happens
836+
// if the connection is established with `autoSelectFamily` set to `true`.
837+
const connectOptions = this[kConnectOptions];
838+
if (!options.isServer && connectOptions) {
839+
if (connectOptions.servername) {
840+
this.setServername(connectOptions.servername);
841+
}
842+
}
835843

836844
if (options.handshakeTimeout > 0)
837845
this.setTimeout(options.handshakeTimeout, this._handleTimeout);

lib/internal/modules/esm/hooks.js

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ class Hooks {
169169
port: insideLoader,
170170
});
171171

172-
if (preloaded == null) { return; }
172+
if (preloaded == null) { continue; }
173173

174174
if (typeof preloaded !== 'string') { // [2]
175175
throw new ERR_INVALID_RETURN_VALUE(
@@ -590,16 +590,17 @@ class HooksProxy {
590590
if (response.message.status === 'never-settle') {
591591
return new Promise(() => {});
592592
}
593-
if (response.message.status === 'error') {
594-
if (response.message.body == null) throw response.message.body;
595-
if (response.message.body.serializationFailed || response.message.body.serialized == null) {
593+
const { status, body } = response.message;
594+
if (status === 'error') {
595+
if (body == null || typeof body !== 'object') throw body;
596+
if (body.serializationFailed || body.serialized == null) {
596597
throw ERR_WORKER_UNSERIALIZABLE_ERROR();
597598
}
598599

599600
// eslint-disable-next-line no-restricted-syntax
600-
throw deserializeError(response.message.body.serialized);
601+
throw deserializeError(body.serialized);
601602
} else {
602-
return response.message.body;
603+
return body;
603604
}
604605
}
605606

lib/internal/modules/esm/worker.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,10 @@ function transferArrayBuffer(hasError, source) {
4848
}
4949

5050
function wrapMessage(status, body) {
51-
if (status === 'success' || body === null || typeof body !== 'object') {
51+
if (status === 'success' || body === null ||
52+
(typeof body !== 'object' &&
53+
typeof body !== 'function' &&
54+
typeof body !== 'symbol')) {
5255
return { status, body };
5356
}
5457

lib/internal/test_runner/harness.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,8 @@ function setup(root) {
140140
const rejectionHandler =
141141
createProcessEventHandler('unhandledRejection', root);
142142
const coverage = configureCoverage(root, globalOptions);
143-
const exitHandler = () => {
144-
root.postRun(new ERR_TEST_FAILURE(
143+
const exitHandler = async () => {
144+
await root.run(new ERR_TEST_FAILURE(
145145
'Promise resolution is still pending but the event loop has already resolved',
146146
kCancelledByParent));
147147

@@ -150,8 +150,8 @@ function setup(root) {
150150
process.removeListener('uncaughtException', exceptionHandler);
151151
};
152152

153-
const terminationHandler = () => {
154-
exitHandler();
153+
const terminationHandler = async () => {
154+
await exitHandler();
155155
process.exit();
156156
};
157157

lib/internal/test_runner/runner.js

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -335,15 +335,13 @@ class FileTest extends Test {
335335
}
336336
}
337337

338-
const runningProcesses = new SafeMap();
339-
const runningSubtests = new SafeMap();
340-
341338
function runTestFile(path, root, inspectPort, filesWatcher, testNamePatterns) {
339+
const watchMode = filesWatcher != null;
342340
const subtest = root.createSubtest(FileTest, path, async (t) => {
343341
const args = getRunArgs({ path, inspectPort, testNamePatterns });
344342
const stdio = ['pipe', 'pipe', 'pipe'];
345343
const env = { ...process.env, NODE_TEST_CONTEXT: 'child-v8' };
346-
if (filesWatcher) {
344+
if (watchMode) {
347345
stdio.push('ipc');
348346
env.WATCH_REPORT_DEPENDENCIES = '1';
349347
}
@@ -352,11 +350,13 @@ function runTestFile(path, root, inspectPort, filesWatcher, testNamePatterns) {
352350
}
353351

354352
const child = spawn(process.execPath, args, { signal: t.signal, encoding: 'utf8', env, stdio });
355-
runningProcesses.set(path, child);
353+
if (watchMode) {
354+
filesWatcher.runningProcesses.set(path, child);
355+
filesWatcher.watcher.watchChildProcessModules(child, path);
356+
}
356357

357358
let err;
358359

359-
filesWatcher?.watchChildProcessModules(child, path);
360360

361361
child.on('error', (error) => {
362362
err = error;
@@ -388,8 +388,14 @@ function runTestFile(path, root, inspectPort, filesWatcher, testNamePatterns) {
388388
finished(child.stdout, { signal: t.signal }),
389389
]);
390390

391-
runningProcesses.delete(path);
392-
runningSubtests.delete(path);
391+
if (watchMode) {
392+
filesWatcher.runningProcesses.delete(path);
393+
filesWatcher.runningSubtests.delete(path);
394+
if (filesWatcher.runningSubtests.size === 0) {
395+
root.reporter[kEmitMessage]('test:watch:drained');
396+
}
397+
}
398+
393399
if (code !== 0 || signal !== null) {
394400
if (!err) {
395401
const failureType = subtest.failedSubtests ? kSubtestsFailed : kTestCodeFailure;
@@ -409,10 +415,14 @@ function runTestFile(path, root, inspectPort, filesWatcher, testNamePatterns) {
409415
return subtest.start();
410416
}
411417

412-
function watchFiles(testFiles, root, inspectPort, testNamePatterns) {
413-
const filesWatcher = new FilesWatcher({ throttle: 500, mode: 'filter' });
414-
filesWatcher.on('changed', ({ owners }) => {
415-
filesWatcher.unfilterFilesOwnedBy(owners);
418+
function watchFiles(testFiles, root, inspectPort, signal, testNamePatterns) {
419+
const runningProcesses = new SafeMap();
420+
const runningSubtests = new SafeMap();
421+
const watcher = new FilesWatcher({ throttle: 500, mode: 'filter', signal });
422+
const filesWatcher = { __proto__: null, watcher, runningProcesses, runningSubtests };
423+
424+
watcher.on('changed', ({ owners }) => {
425+
watcher.unfilterFilesOwnedBy(owners);
416426
PromisePrototypeThen(SafePromiseAllReturnVoid(testFiles, async (file) => {
417427
if (!owners.has(file)) {
418428
return;
@@ -432,6 +442,8 @@ function watchFiles(testFiles, root, inspectPort, testNamePatterns) {
432442
triggerUncaughtException(error, true /* fromPromise */);
433443
}));
434444
});
445+
signal?.addEventListener('abort', () => root.postRun(), { __proto__: null, once: true });
446+
435447
return filesWatcher;
436448
}
437449

@@ -474,14 +486,14 @@ function run(options) {
474486
let postRun = () => root.postRun();
475487
let filesWatcher;
476488
if (watch) {
477-
filesWatcher = watchFiles(testFiles, root, inspectPort, testNamePatterns);
489+
filesWatcher = watchFiles(testFiles, root, inspectPort, signal, testNamePatterns);
478490
postRun = undefined;
479491
}
480492
const runFiles = () => {
481493
root.harness.bootstrapComplete = true;
482494
return SafePromiseAllSettledReturnVoid(testFiles, (path) => {
483495
const subtest = runTestFile(path, root, inspectPort, filesWatcher, testNamePatterns);
484-
runningSubtests.set(path, subtest);
496+
filesWatcher?.runningSubtests.set(path, subtest);
485497
return subtest;
486498
});
487499
};

lib/internal/test_runner/test.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,7 @@ class Test extends AsyncResource {
427427
validateOneOf(name, 'hook name', kHookNames);
428428
// eslint-disable-next-line no-use-before-define
429429
const hook = new TestHook(fn, options);
430-
if (name === 'before') {
430+
if (name === 'before' || name === 'after') {
431431
hook.run = runOnce(hook.run);
432432
}
433433
ArrayPrototypePush(this.hooks[name], hook);
@@ -514,7 +514,7 @@ class Test extends AsyncResource {
514514
}
515515
}
516516

517-
async run() {
517+
async run(pendingSubtestsError) {
518518
if (this.parent !== null) {
519519
this.parent.activeSubtests++;
520520
}
@@ -526,11 +526,11 @@ class Test extends AsyncResource {
526526
}
527527

528528
const { args, ctx } = this.getRunArgs();
529-
const after = runOnce(async () => {
529+
const after = async () => {
530530
if (this.hooks.after.length > 0) {
531531
await this.runHook('after', { args, ctx });
532532
}
533-
});
533+
};
534534
const afterEach = runOnce(async () => {
535535
if (this.parent?.hooks.afterEach.length > 0) {
536536
await this.parent.runHook('afterEach', { args, ctx });
@@ -579,8 +579,8 @@ class Test extends AsyncResource {
579579
await after();
580580
this.pass();
581581
} catch (err) {
582-
try { await after(); } catch { /* Ignore error. */ }
583582
try { await afterEach(); } catch { /* test is already failing, let's ignore the error */ }
583+
try { await after(); } catch { /* Ignore error. */ }
584584
if (isTestFailureError(err)) {
585585
if (err.failureType === kTestTimeoutFailure) {
586586
this.#cancel(err);
@@ -594,7 +594,7 @@ class Test extends AsyncResource {
594594

595595
// Clean up the test. Then, try to report the results and execute any
596596
// tests that were pending due to available concurrency.
597-
this.postRun();
597+
this.postRun(pendingSubtestsError);
598598
}
599599

600600
postRun(pendingSubtestsError) {

lib/internal/watch_mode/files_watcher.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,18 @@ class FilesWatcher extends EventEmitter {
3030
#ownerDependencies = new SafeMap();
3131
#throttle;
3232
#mode;
33+
#signal;
3334

34-
constructor({ throttle = 500, mode = 'filter' } = kEmptyObject) {
35+
constructor({ throttle = 500, mode = 'filter', signal } = kEmptyObject) {
3536
super();
3637

3738
validateNumber(throttle, 'options.throttle', 0, TIMEOUT_MAX);
3839
validateOneOf(mode, 'options.mode', ['filter', 'all']);
3940
this.#throttle = throttle;
4041
this.#mode = mode;
42+
this.#signal = signal;
43+
44+
signal?.addEventListener('abort', () => this.clear(), { __proto__: null, once: true });
4145
}
4246

4347
#isPathWatched(path) {
@@ -89,7 +93,7 @@ class FilesWatcher extends EventEmitter {
8993
if (this.#isPathWatched(path)) {
9094
return;
9195
}
92-
const watcher = watch(path, { recursive });
96+
const watcher = watch(path, { recursive, signal: this.#signal });
9397
watcher.on('change', (eventType, fileName) => this
9498
.#onChange(recursive ? resolve(path, fileName) : path));
9599
this.#watchers.set(path, { handle: watcher, recursive });

0 commit comments

Comments
 (0)