diff --git a/.github/workflows/build-shared.yml b/.github/workflows/build-shared.yml
index 61441571427eff..285834cf52e571 100644
--- a/.github/workflows/build-shared.yml
+++ b/.github/workflows/build-shared.yml
@@ -38,7 +38,6 @@ jobs:
steps:
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
- name: tarballs
path: tarballs
- name: Extract tarball
diff --git a/.github/workflows/build-tarball.yml b/.github/workflows/build-tarball.yml
index bd72e7dd404794..67ef806c53c1fc 100644
--- a/.github/workflows/build-tarball.yml
+++ b/.github/workflows/build-tarball.yml
@@ -91,9 +91,8 @@ jobs:
- name: Upload tarball artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
- name: tarballs
path: '*.tar.gz'
- compression-level: 0
+ archive: false
test-tarball-linux:
needs: build-tarball
runs-on: ubuntu-24.04-arm
@@ -125,7 +124,6 @@ jobs:
- name: Download tarball
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
- name: tarballs
path: tarballs
- name: Extract tarball
run: |
diff --git a/.github/workflows/test-shared.yml b/.github/workflows/test-shared.yml
index cd9804d0d87d04..3638aa51371f54 100644
--- a/.github/workflows/test-shared.yml
+++ b/.github/workflows/test-shared.yml
@@ -130,9 +130,8 @@ jobs:
- name: Upload tarball artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
- name: tarballs
path: '*.tar.gz'
- compression-level: 0
+ archive: false
build:
needs: build-tarball
@@ -172,7 +171,6 @@ jobs:
steps:
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
- name: tarballs
path: tarballs
- name: Extract tarball
diff --git a/doc/api/deprecations.md b/doc/api/deprecations.md
index 2109fbe54f93ea..330e4c0fcc6f76 100644
--- a/doc/api/deprecations.md
+++ b/doc/api/deprecations.md
@@ -4564,7 +4564,7 @@ The `module.register()` API provides off-thread async hooks for customizing ES m
the `module.registerHooks()` API provides similar hooks that are synchronous, in-thread, and
work for all types of modules.
Supporting async hooks has proven to be complex, involving worker threads orchestration, and there are issues
-that have proven unresolveable. See [caveats of asynchronous customization hooks][]. Please migrate to
+that have proven unresolvable. See [caveats of asynchronous customization hooks][]. Please migrate to
`module.registerHooks()` as soon as possible as `module.register()` will be
removed in a future version of Node.js.
diff --git a/doc/api/errors.md b/doc/api/errors.md
index 29cd9e8a4937d1..d321f666bb48d8 100644
--- a/doc/api/errors.md
+++ b/doc/api/errors.md
@@ -3441,7 +3441,7 @@ import 'package-name'; // supported
added: v22.6.0
-->
-Type stripping is not supported for files descendent of a `node_modules` directory.
+Type stripping is not supported for files descendant of a `node_modules` directory.
diff --git a/doc/api/n-api.md b/doc/api/n-api.md
index 1b1b21fe0ab769..72410ab7b5407d 100644
--- a/doc/api/n-api.md
+++ b/doc/api/n-api.md
@@ -4329,7 +4329,7 @@ napi_status napi_strict_equals(napi_env env,
Returns `napi_ok` if the API succeeded.
This API represents the invocation of the Strict Equality algorithm as
-defined in [Section IsStrctEqual][] of the ECMAScript Language Specification.
+defined in [Section IsStrictlyEqual][] of the ECMAScript Language Specification.
### `napi_detach_arraybuffer`
@@ -4636,7 +4636,7 @@ They can be one or more of the following bit flags:
opposed to an instance property, which is the default. This is used only by
[`napi_define_class`][]. It is ignored by `napi_define_properties`.
* `napi_default_method`: Like a method in a JS class, the property is
- configurable and writeable, but not enumerable.
+ configurable and writable, but not enumerable.
* `napi_default_jsproperty`: Like a property set via assignment in JavaScript,
the property is writable, enumerable, and configurable.
@@ -6986,7 +6986,7 @@ the add-on's file name during loading.
[Section DefineOwnProperty]: https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-defineownproperty-p-desc
[Section Function objects]: https://tc39.es/ecma262/#sec-function-objects
[Section IsArray]: https://tc39.es/ecma262/#sec-isarray
-[Section IsStrctEqual]: https://tc39.es/ecma262/#sec-strict-equality-comparison
+[Section IsStrictlyEqual]: https://tc39.es/ecma262/#sec-strict-equality-comparison
[Section Promise objects]: https://tc39.es/ecma262/#sec-promise-objects
[Section SharedArrayBuffer objects]: https://tc39.es/ecma262/#sec-sharedarraybuffer-objects
[Section ToBoolean]: https://tc39.es/ecma262/#sec-toboolean
diff --git a/doc/api/stream.md b/doc/api/stream.md
index a8cb69c29f35c9..2f7fd7961a7334 100644
--- a/doc/api/stream.md
+++ b/doc/api/stream.md
@@ -3552,7 +3552,7 @@ changes:
* `stream` {Stream|ReadableStream|WritableStream} A stream to attach a signal
to.
-Attaches an AbortSignal to a readable or writeable stream. This lets code
+Attaches an AbortSignal to a readable or writable stream. This lets code
control stream destruction using an `AbortController`.
Calling `abort` on the `AbortController` corresponding to the passed
@@ -3844,7 +3844,7 @@ const myWritable = new Writable({
Calling `abort` on the `AbortController` corresponding to the passed
`AbortSignal` will behave the same way as calling `.destroy(new AbortError())`
-on the writeable stream.
+on the writable stream.
```js
const { Writable } = require('node:stream');
diff --git a/doc/contributing/advocacy-ambassador-program.md b/doc/contributing/advocacy-ambassador-program.md
index 6275003c82512d..ba79079245c607 100644
--- a/doc/contributing/advocacy-ambassador-program.md
+++ b/doc/contributing/advocacy-ambassador-program.md
@@ -196,7 +196,7 @@ Some of the things to highlight include:
time we all have other responsibilities that affect how much time we have
available to do so.
* People are volunteering their time to review your PRs and answer questions in
- the issues you open. Be mindfull of your asks for their time and acknowledge
+ the issues you open. Be mindful of your asks for their time and acknowledge
the gift of their time. Too many issues/PRs in a short period of time may
overwhelm maintainers leading to less progress versus more, try to pace your
issues and PRs so that you don't have too many open at the same time. The
diff --git a/doc/contributing/issues.md b/doc/contributing/issues.md
index e9bbc4de28ed9e..c997c223b49ef8 100644
--- a/doc/contributing/issues.md
+++ b/doc/contributing/issues.md
@@ -60,7 +60,7 @@ activities, such as applying labels and closing/reopening/assigning issues.
For more information on the roles and permissions, see ["Permission levels for
repositories owned by an organization"](https://docs.github.com/en/github/setting-up-and-managing-organizations-and-teams/repository-permission-levels-for-an-organization#permission-levels-for-repositories-owned-by-an-organization).
-When triagging issues and PRs:
+When triaging issues and PRs:
* Show patience and empathy, especially to first-time contributors.
* Show no patience towards spam or troll, close the issue without interacting with it and
diff --git a/doc/contributing/maintaining/maintaining-dependencies.md b/doc/contributing/maintaining/maintaining-dependencies.md
index f22c15561e65dc..d6950e42e79123 100644
--- a/doc/contributing/maintaining/maintaining-dependencies.md
+++ b/doc/contributing/maintaining/maintaining-dependencies.md
@@ -167,7 +167,7 @@ dependencies.
The container provides a durable copy of the versions of the tools
used for a specific build which are under the control of the Node.js
-project. In addition, the tools and verions are documented through metadata
+project. In addition, the tools and versions are documented through metadata
within the container in the `/home/node/metadata directory`.
The available tools can be found by looking at the current version of the
diff --git a/doc/contributing/pull-requests.md b/doc/contributing/pull-requests.md
index 7215c2440a8441..def629c14933f1 100644
--- a/doc/contributing/pull-requests.md
+++ b/doc/contributing/pull-requests.md
@@ -180,14 +180,13 @@ A good commit message should describe what changed and why.
3. Wrap all other lines at 72 columns (except for long URLs).
-4. If your patch fixes an open issue, you can add a reference to it at the end
- of the log. Use the `Fixes:` prefix and the full issue URL. For other
- references use `Refs:`.
+4. If your patch fixes an open issue, include a reference in the pull request
+ description. Use the `Fixes:` prefix and the full issue URL. For other
+ references, use `Refs:`.
- `Fixes:` and `Refs:` trailers get automatically added to your commit message
- when the Pull Request lands as long as they are included in the
- Pull Request's description. If the Pull Request lands in several commits,
- by default the trailers found in the description are added to each commits.
+ `Fixes:` and `Refs:` trailers are automatically added to the commit message
+ when the pull request lands. If the pull request lands as several commits,
+ the trailers from the description are added to each commit by default.
Examples:
@@ -207,7 +206,7 @@ A good commit message should describe what changed and why.
This rule does not apply to dependency updates (e.g. cherry-picks), release
commits, or backport commits.
-Sample complete commit message:
+Sample final commit message after landing:
```text
subsystem: explain the commit in one line
diff --git a/lib/events.js b/lib/events.js
index e385e8dddc4274..5719d948c739d1 100644
--- a/lib/events.js
+++ b/lib/events.js
@@ -86,7 +86,6 @@ const { addAbortListener } = require('internal/events/abort_listener');
const kCapture = Symbol('kCapture');
const kErrorMonitor = Symbol('events.errorMonitor');
-const kShapeMode = Symbol('shapeMode');
const kEmitting = Symbol('events.emitting');
const kMaxEventTargetListeners = Symbol('events.maxEventTargetListeners');
const kMaxEventTargetListenersWarned =
@@ -335,9 +334,6 @@ EventEmitter.init = function(opts) {
this._events === ObjectGetPrototypeOf(this)._events) {
this._events = { __proto__: null };
this._eventsCount = 0;
- this[kShapeMode] = false;
- } else {
- this[kShapeMode] = true;
}
this._maxListeners ||= undefined;
@@ -446,6 +442,39 @@ function enhanceStackTrace(err, own) {
return err.stack + sep + ArrayPrototypeJoin(ownStack, '\n');
}
+function getUnhandledErrorException(ee, args) {
+ let er;
+ if (args.length > 0)
+ er = args[0];
+ if (er instanceof Error) {
+ try {
+ const capture = {};
+ ErrorCaptureStackTrace(capture, EventEmitter.prototype.emit);
+ ObjectDefineProperty(er, kEnhanceStackBeforeInspector, {
+ __proto__: null,
+ value: FunctionPrototypeBind(enhanceStackTrace, ee, er, capture),
+ configurable: true,
+ });
+ } catch {
+ // Continue regardless of error.
+ }
+
+ return er;
+ }
+
+ let stringifiedEr;
+ try {
+ stringifiedEr = inspect(er);
+ } catch {
+ stringifiedEr = er;
+ }
+
+ // At least give some kind of context to the user
+ const err = new ERR_UNHANDLED_ERROR(stringifiedEr);
+ err.context = er;
+ return err;
+}
+
/**
* Synchronously calls each of the listeners registered
* for the event.
@@ -466,38 +495,10 @@ EventEmitter.prototype.emit = function emit(type, ...args) {
// If there is no 'error' event listener then throw.
if (doError) {
- let er;
- if (args.length > 0)
- er = args[0];
- if (er instanceof Error) {
- try {
- const capture = {};
- ErrorCaptureStackTrace(capture, EventEmitter.prototype.emit);
- ObjectDefineProperty(er, kEnhanceStackBeforeInspector, {
- __proto__: null,
- value: FunctionPrototypeBind(enhanceStackTrace, this, er, capture),
- configurable: true,
- });
- } catch {
- // Continue regardless of error.
- }
-
- // Note: The comments on the `throw` lines are intentional, they show
- // up in Node's output if this results in an unhandled exception.
- throw er; // Unhandled 'error' event
- }
-
- let stringifiedEr;
- try {
- stringifiedEr = inspect(er);
- } catch {
- stringifiedEr = er;
- }
-
- // At least give some kind of context to the user
- const err = new ERR_UNHANDLED_ERROR(stringifiedEr);
- err.context = er;
- throw err; // Unhandled 'error' event
+ const er = getUnhandledErrorException(this, args);
+ // Note: The comments on the `throw` lines are intentional, they show
+ // up in Node's output if this results in an unhandled exception.
+ throw er; // Unhandled 'error' event
}
const handler = events[type];
@@ -584,20 +585,23 @@ function _addListener(target, type, listener, prepend) {
// Check for listener leak
m = _getMaxListeners(target);
- if (m > 0 && existing.length > m && !existing.warned) {
- existing.warned = true;
- // No error code for this since it is a Warning
- const w = genericNodeError(
- `Possible EventEmitter memory leak detected. ${existing.length} ${String(type)} listeners ` +
- `added to ${inspect(target, { depth: -1 })}. MaxListeners is ${m}. Use emitter.setMaxListeners() to increase limit`,
- { name: 'MaxListenersExceededWarning', emitter: target, type: type, count: existing.length });
- process.emitWarning(w);
- }
+ if (m > 0 && existing.length > m && !existing.warned)
+ warnMaxListenersExceeded(target, type, existing, m);
}
return target;
}
+function warnMaxListenersExceeded(target, type, existing, m) {
+ existing.warned = true;
+ // No error code for this since it is a Warning
+ const w = genericNodeError(
+ `Possible EventEmitter memory leak detected. ${existing.length} ${String(type)} listeners ` +
+ `added to ${inspect(target, { depth: -1 })}. MaxListeners is ${m}. Use emitter.setMaxListeners() to increase limit`,
+ { name: 'MaxListenersExceededWarning', emitter: target, type: type, count: existing.length });
+ process.emitWarning(w);
+}
+
/**
* Adds a listener to the event emitter.
* @param {string | symbol} type
@@ -622,22 +626,16 @@ EventEmitter.prototype.prependListener =
return _addListener(this, type, listener, true);
};
-function onceWrapper() {
- if (!this.fired) {
- this.target.removeListener(this.type, this.wrapFn);
- this.fired = true;
- if (arguments.length === 0)
- return this.listener.call(this.target);
- return ReflectApply(this.listener, this.target, arguments);
- }
-}
-
function _onceWrap(target, type, listener) {
- const state = { fired: false, wrapFn: undefined, target, type, listener };
- const wrapped = onceWrapper.bind(state);
- wrapped.listener = listener;
- state.wrapFn = wrapped;
- return wrapped;
+ let fired = false;
+ function wrapper(...args) {
+ if (fired) return;
+ fired = true;
+ target.removeListener(type, wrapper);
+ return ReflectApply(listener, target, args);
+ }
+ wrapper.listener = listener;
+ return wrapper;
}
/**
@@ -689,13 +687,12 @@ EventEmitter.prototype.removeListener =
if (list === listener || list.listener === listener) {
this._eventsCount -= 1;
- if (this[kShapeMode]) {
- events[type] = undefined;
- } else if (this._eventsCount === 0) {
- this._events = { __proto__: null };
- } else {
- delete events[type];
- }
+ // Leave the key in place with an `undefined` value: repeatedly
+ // adding and removing a listener for the same event this way keeps
+ // the `events` object in the same shape and avoids both a `delete`
+ // (which would put the object into dictionary mode) and allocating
+ // a fresh object when the last listener is removed.
+ events[type] = undefined;
if (events.removeListener !== undefined)
this.emit('removeListener', type, list.listener || listener);
@@ -755,7 +752,6 @@ EventEmitter.prototype.removeAllListeners =
else
delete events[type];
}
- this[kShapeMode] = false;
return this;
}
@@ -768,7 +764,6 @@ EventEmitter.prototype.removeAllListeners =
this.removeAllListeners('removeListener');
this._events = { __proto__: null };
this._eventsCount = 0;
- this[kShapeMode] = false;
return this;
}
@@ -868,7 +863,16 @@ EventEmitter.prototype.listenerCount = function listenerCount(type, listener) {
* @returns {(string | symbol)[]}
*/
EventEmitter.prototype.eventNames = function eventNames() {
- return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : [];
+ if (this._eventsCount === 0)
+ return [];
+ const events = this._events;
+ const names = [];
+ for (const key of ReflectOwnKeys(events)) {
+ // Removed listeners leave the key in place with an `undefined` value.
+ if (events[key] !== undefined)
+ ArrayPrototypePush(names, key);
+ }
+ return names;
};
function arrayClone(arr) {
diff --git a/src/crypto/README.md b/src/crypto/README.md
index 8d66f34c6c29b9..cc5093a385cad3 100644
--- a/src/crypto/README.md
+++ b/src/crypto/README.md
@@ -4,7 +4,7 @@ Welcome. You've found your way to the Node.js native crypto subsystem.
Do not be afraid.
-While crypto may be a dark, mysterious, and forboding subject; and while
+While crypto may be a dark, mysterious, and foreboding subject; and while
this directory may be filled with many `*.h` and `*.cc` files, finding
your way around is not too difficult. And I can promise you that a Gru
will not jump out of the shadows and eat you (well, "promise" may be a
diff --git a/test/fixtures/errors/events_unhandled_error_common_trace.snapshot b/test/fixtures/errors/events_unhandled_error_common_trace.snapshot
index 5c4a3c02d33825..9573dbc455de7a 100644
--- a/test/fixtures/errors/events_unhandled_error_common_trace.snapshot
+++ b/test/fixtures/errors/events_unhandled_error_common_trace.snapshot
@@ -1,6 +1,6 @@
node:events:
- throw er; // Unhandled 'error' event
- ^
+ throw er; // Unhandled 'error' event
+ ^
Error: foo:bar
at bar (/test/fixtures/errors/events_unhandled_error_common_trace.js:9:12)
diff --git a/test/fixtures/errors/events_unhandled_error_nexttick.snapshot b/test/fixtures/errors/events_unhandled_error_nexttick.snapshot
index e789ecab2ab047..b2ddffd6990791 100644
--- a/test/fixtures/errors/events_unhandled_error_nexttick.snapshot
+++ b/test/fixtures/errors/events_unhandled_error_nexttick.snapshot
@@ -1,6 +1,6 @@
node:events:
- throw er; // Unhandled 'error' event
- ^
+ throw er; // Unhandled 'error' event
+ ^
Error
at Object. (/test/fixtures/errors/events_unhandled_error_nexttick.js:6:12)
diff --git a/test/fixtures/errors/events_unhandled_error_sameline.snapshot b/test/fixtures/errors/events_unhandled_error_sameline.snapshot
index 15e44b748edaff..4c1456c2fb5f39 100644
--- a/test/fixtures/errors/events_unhandled_error_sameline.snapshot
+++ b/test/fixtures/errors/events_unhandled_error_sameline.snapshot
@@ -1,6 +1,6 @@
node:events:
- throw er; // Unhandled 'error' event
- ^
+ throw er; // Unhandled 'error' event
+ ^
Error
at Object. (/test/fixtures/errors/events_unhandled_error_sameline.js:6:34)
diff --git a/test/fixtures/errors/events_unhandled_error_subclass.snapshot b/test/fixtures/errors/events_unhandled_error_subclass.snapshot
index 1584badd956515..e92caad4a8db40 100644
--- a/test/fixtures/errors/events_unhandled_error_subclass.snapshot
+++ b/test/fixtures/errors/events_unhandled_error_subclass.snapshot
@@ -1,6 +1,6 @@
node:events:
- throw er; // Unhandled 'error' event
- ^
+ throw er; // Unhandled 'error' event
+ ^
Error
at Object. (/test/fixtures/errors/events_unhandled_error_subclass.js:7:25)
diff --git a/test/parallel/test-http2-origin-set-max-size.mjs b/test/parallel/test-http2-origin-set-max-size.mjs
index 08bdf1ed7f9753..53cadb797a1885 100644
--- a/test/parallel/test-http2-origin-set-max-size.mjs
+++ b/test/parallel/test-http2-origin-set-max-size.mjs
@@ -22,10 +22,6 @@ const cert = fixtures.readKey('agent8-cert.pem', 'binary');
const ca = fixtures.readKey('fake-startcom-root-cert.pem', 'binary');
const server = createSecureServer({ key, cert });
-server.on('stream', (stream) => {
- stream.respond();
- stream.end('ok');
-});
server.on('session', (session) => {
let i = 0;
const timer = setInterval(() => {
@@ -72,8 +68,6 @@ await new Promise((resolve) => {
}));
client.on('goaway', mustNotCall());
client.on('close', resolve);
-
- client.request().resume();
});
// Test non-default values
@@ -86,8 +80,6 @@ await Promise.all([-0, 9, 1.5].map((maxOriginSetSize) => new Promise((resolve) =
}));
client.on('goaway', mustNotCall());
client.on('close', resolve);
-
- client.request().resume();
})));
@@ -103,8 +95,6 @@ await Promise.all([512, Infinity].map((maxOriginSetSize) => new Promise((resolve
client.on('error', mustNotCall());
client.on('goaway', mustNotCall());
client.on('close', resolve);
-
- client.request().resume();
})));
server.close();