From e69d35f03ba2b57c702a27d8a867c8300b7b9be2 Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Wed, 22 Jan 2025 21:02:09 +0100 Subject: [PATCH 001/205] doc: add history info for Permission Model PR-URL: https://github.com/nodejs/node/pull/56707 Reviewed-By: James M Snell Reviewed-By: Ruben Bridgewater Reviewed-By: Rafael Gonzaga --- doc/api/permissions.md | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/doc/api/permissions.md b/doc/api/permissions.md index ea3ccc17b306b7..9c2184fc585f2d 100644 --- a/doc/api/permissions.md +++ b/doc/api/permissions.md @@ -1,5 +1,9 @@ # Permissions + + + + Permissions can be used to control what system resources the Node.js process has access to or what actions the process can take with those resources. @@ -26,12 +30,16 @@ If you find a potential security vulnerability, please refer to our ### Permission Model - + > Stability: 2 - Stable. - - The Node.js Permission Model is a mechanism for restricting access to specific resources during execution. The API exists behind a flag [`--permission`][] which when enabled, From 928540d79266e2e49ad00acaa8deadffa82a815e Mon Sep 17 00:00:00 2001 From: Nathan Baulch Date: Sun, 29 Sep 2024 23:15:15 +1000 Subject: [PATCH 002/205] doc: fix typos PR-URL: https://github.com/nodejs/node/pull/55066 Reviewed-By: Luigi Pinca --- doc/api/crypto.md | 2 +- doc/api/module.md | 14 +++++++------- doc/api/packages.md | 4 ++-- doc/api/stream.md | 2 +- doc/api/test.md | 2 +- doc/api/v8.md | 4 ++-- doc/contributing/static-analysis.md | 4 ++-- 7 files changed, 16 insertions(+), 16 deletions(-) diff --git a/doc/api/crypto.md b/doc/api/crypto.md index 886427d5880305..37ffb72d810e72 100644 --- a/doc/api/crypto.md +++ b/doc/api/crypto.md @@ -5983,7 +5983,7 @@ See the [list of SSL OP Flags][] for details. ENGINE_METHOD_PKEY_METHS - Limit engine usage to PKEY_METHDS + Limit engine usage to PKEY_METHS ENGINE_METHOD_PKEY_ASN1_METHS diff --git a/doc/api/module.md b/doc/api/module.md index dc2966678baca0..72e302b6d8f5af 100644 --- a/doc/api/module.md +++ b/doc/api/module.md @@ -142,14 +142,14 @@ If `cacheDir` is not specified, Node.js will either use the directory specified [`NODE_COMPILE_CACHE=dir`][] environment variable if it's set, or use `path.join(os.tmpdir(), 'node-compile-cache')` otherwise. For general use cases, it's recommended to call `module.enableCompileCache()` without specifying the `cacheDir`, -so that the directory can be overriden by the `NODE_COMPILE_CACHE` environment +so that the directory can be overridden by the `NODE_COMPILE_CACHE` environment variable when necessary. Since compile cache is supposed to be a quiet optimization that is not required for the application to be functional, this method is designed to not throw any exception when the compile cache cannot be enabled. Instead, it will return an object containing an error message in the `message` field to aid debugging. -If compile cache is enabled successefully, the `directory` field in the returned object +If compile cache is enabled successfully, the `directory` field in the returned object contains the path to the directory where the compile cache is stored. The `status` field in the returned object would be one of the `module.constants.compileCacheStatus` values to indicate the result of the attempt to enable the [module compile cache][]. @@ -157,7 +157,7 @@ values to indicate the result of the attempt to enable the [module compile cache This method only affects the current Node.js instance. To enable it in child worker threads, either call this method in child worker threads too, or set the `process.env.NODE_COMPILE_CACHE` value to compile cache directory so the behavior can -be inheritend into the child workers. The directory can be obtained either from the +be inherited into the child workers. The directory can be obtained either from the `directory` field returned by this method, or with [`module.getCompileCacheDir()`][]. #### Module compile cache @@ -264,7 +264,7 @@ changes: **Default:** `'data:'` * `data` {any} Any arbitrary, cloneable JavaScript value to pass into the [`initialize`][] hook. - * `transferList` {Object\[]} [transferrable objects][] to be passed into the + * `transferList` {Object\[]} [transferable objects][] to be passed into the `initialize` hook. Register a module that exports [hooks][] that customize Node.js module @@ -737,7 +737,7 @@ affect the other thread(s), and message channels must be used to communicate between the threads. The `register` method can be used to pass data to an [`initialize`][] hook. The -data passed to the hook may include transferrable objects like ports. +data passed to the hook may include transferable objects like ports. ```mjs import { register } from 'node:module'; @@ -835,7 +835,7 @@ the hooks thread when the hooks module is initialized. Initialization happens when the hooks module is registered via [`register`][]. This hook can receive data from a [`register`][] invocation, including -ports and other transferrable objects. The return value of `initialize` can be a +ports and other transferable objects. The return value of `initialize` can be a {Promise}, in which case it will be awaited before the main application thread execution resumes. @@ -1503,6 +1503,6 @@ returned object contains the following keys: [prefix-only modules]: modules.md#built-in-modules-with-mandatory-node-prefix [realm]: https://tc39.es/ecma262/#realm [source map include directives]: https://sourcemaps.info/spec.html#h.lmz475t4mvbx -[transferrable objects]: worker_threads.md#portpostmessagevalue-transferlist +[transferable objects]: worker_threads.md#portpostmessagevalue-transferlist [transform TypeScript features]: typescript.md#typescript-features [type-stripping]: typescript.md#type-stripping diff --git a/doc/api/packages.md b/doc/api/packages.md index f3a89855a1fcb3..72494bf90d4b40 100644 --- a/doc/api/packages.md +++ b/doc/api/packages.md @@ -171,7 +171,7 @@ There is the CommonJS module loader: `process.dlopen()`. * It treats all files that lack `.json` or `.node` extensions as JavaScript text files. -* It can only be used to [load ECMASCript modules from CommonJS modules][] if +* It can only be used to [load ECMAScript modules from CommonJS modules][] if the module graph is synchronous (that contains no top-level `await`). When used to load a JavaScript text file that is not an ECMAScript module, the file will be loaded as a CommonJS module. @@ -1169,7 +1169,7 @@ This field defines [subpath imports][] for the current package. [entry points]: #package-entry-points [folders as modules]: modules.md#folders-as-modules [import maps]: https://github.com/WICG/import-maps -[load ECMASCript modules from CommonJS modules]: modules.md#loading-ecmascript-modules-using-require +[load ECMAScript modules from CommonJS modules]: modules.md#loading-ecmascript-modules-using-require [loader hooks]: esm.md#loaders [packages folder mapping]: https://github.com/WICG/import-maps#packages-via-trailing-slashes [self-reference]: #self-referencing-a-package-using-its-name diff --git a/doc/api/stream.md b/doc/api/stream.md index c8f1e2b528c7dc..35893acbd0afbe 100644 --- a/doc/api/stream.md +++ b/doc/api/stream.md @@ -2227,7 +2227,7 @@ stopped by having passed a `signal` option and aborting the related `return`. In either case the stream will be destroyed. This method is different from listening to the [`'data'`][] event in that it -uses the [`readable`][] event in the underlying machinary and can limit the +uses the [`readable`][] event in the underlying machinery and can limit the number of concurrent `fn` calls. ```mjs diff --git a/doc/api/test.md b/doc/api/test.md index b8d5dfb7f69ead..116a3ef4c38205 100644 --- a/doc/api/test.md +++ b/doc/api/test.md @@ -476,7 +476,7 @@ all tests have completed. If the [`NODE_V8_COVERAGE`][] environment variable is used to specify a code coverage directory, the generated V8 coverage files are written to that directory. Node.js core modules and files within `node_modules/` directories are, by default, not included in the coverage report. -However, they can be explicity included via the [`--test-coverage-include`][] flag. If +However, they can be explicitly included via the [`--test-coverage-include`][] flag. If coverage is enabled, the coverage report is sent to any [test reporters][] via the `'test:coverage'` event. diff --git a/doc/api/v8.md b/doc/api/v8.md index ed2a030b5fd015..e62c2383f484bb 100644 --- a/doc/api/v8.md +++ b/doc/api/v8.md @@ -323,7 +323,7 @@ console.log(queryObjects(B, { format: 'summary' })); // Note that, when there are child classes inheriting from a constructor, // the constructor also shows up in the prototype chain of the child -// classes's prototoype, so the child classes's prototoype would also be +// classes's prototype, so the child classes's prototype would also be // included in the result. console.log(queryObjects(A)); // 3 // [ "B { foo: 'bar', bar: 'qux' }", 'A {}', "A { foo: 'bar' }" ] @@ -347,7 +347,7 @@ console.log(queryObjects(B, { format: 'summary' })); // Note that, when there are child classes inheriting from a constructor, // the constructor also shows up in the prototype chain of the child -// classes's prototoype, so the child classes's prototoype would also be +// classes's prototype, so the child classes's prototype would also be // included in the result. console.log(queryObjects(A)); // 3 // [ "B { foo: 'bar', bar: 'qux' }", 'A {}', "A { foo: 'bar' }" ] diff --git a/doc/contributing/static-analysis.md b/doc/contributing/static-analysis.md index f535751660eae3..702e878b1389ba 100644 --- a/doc/contributing/static-analysis.md +++ b/doc/contributing/static-analysis.md @@ -10,9 +10,9 @@ through . Any collaborator can ask to be added to the Node.js coverity project by opening an issue in the [build][] repository titled `Please add me to coverity`. A member of the build WG with admin access will -verify that the requestor is an existing collaborator as listed in the +verify that the requester is an existing collaborator as listed in the [collaborators section][] on the nodejs/node project repo. Once validated the -requestor will be added to the coverity project. +requester will be added to the coverity project. [Node.js coverity project]: https://scan.coverity.com/projects/node-js [build]: https://github.com/nodejs/build From 9ec67e7ce050af9de750165c553ff0ffb837d15f Mon Sep 17 00:00:00 2001 From: Moshe Atlow Date: Thu, 19 Dec 2024 00:30:00 +0200 Subject: [PATCH 003/205] meta: move MoLow to TSC regular member MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/56276 Reviewed-By: Marco Ippolito Reviewed-By: Richard Lau Reviewed-By: Michaël Zasso Reviewed-By: Paolo Insogna Reviewed-By: Benjamin Gruenbaum Reviewed-By: Luigi Pinca Reviewed-By: Matteo Collina Reviewed-By: Joyee Cheung Reviewed-By: Ruben Bridgewater Reviewed-By: Chengzhong Wu --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 35a30716eb668c..40bcca0ed591cd 100644 --- a/README.md +++ b/README.md @@ -180,8 +180,6 @@ For information about the governance of the Node.js project, see **Matteo Collina** <> (he/him) * [mhdawson](https://github.com/mhdawson) - **Michael Dawson** <> (he/him) -* [MoLow](https://github.com/MoLow) - - **Moshe Atlow** <> (he/him) * [RafaelGSS](https://github.com/RafaelGSS) - **Rafael Gonzaga** <> (he/him) * [richardlau](https://github.com/richardlau) - @@ -211,6 +209,8 @@ For information about the governance of the Node.js project, see **Shelley Vohr** <> (she/her) * [GeoffreyBooth](https://github.com/GeoffreyBooth) - **Geoffrey Booth** <> (he/him) +* [MoLow](https://github.com/MoLow) - + **Moshe Atlow** <> (he/him) * [Trott](https://github.com/Trott) - **Rich Trott** <> (he/him) From 12f716be0a22cc1834048c2f32132f32e6f89414 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Thu, 19 Dec 2024 04:24:51 +0100 Subject: [PATCH 004/205] build: build v8 with -fvisibility=hidden on macOS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit V8 should be built with -fvisibility=hidden, otherwise the resulting binary would contain unnecessary symbols. In particular, on macOS, this leads to 5000+ weak symbols resolved at runtime, leading to a startup regression. On macOS this also reduces the binary size about ~10MB. It's only enabled on macOS in this patch as gcc can time out or run out of memory on some machines in the CI with -fvisibility=hidden. PR-URL: https://github.com/nodejs/node/pull/56275 Fixes: https://github.com/nodejs/performance/issues/180 Reviewed-By: Juan José Arboleda Reviewed-By: Daniel Lemire Reviewed-By: Rafael Gonzaga Reviewed-By: Yagiz Nizipli Reviewed-By: Geoffrey Booth Reviewed-By: Luigi Pinca Reviewed-By: Michaël Zasso Reviewed-By: Matteo Collina Reviewed-By: Chengzhong Wu Reviewed-By: Marco Ippolito --- tools/v8_gypfiles/v8.gyp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tools/v8_gypfiles/v8.gyp b/tools/v8_gypfiles/v8.gyp index 6906479ec48269..569661147bc257 100644 --- a/tools/v8_gypfiles/v8.gyp +++ b/tools/v8_gypfiles/v8.gyp @@ -41,6 +41,19 @@ 'AdditionalOptions': ['/utf-8'] } }, + 'conditions': [ + ['OS=="mac"', { + # Hide symbols that are not explicitly exported with V8_EXPORT. + # TODO(joyeecheung): enable it on other platforms. Currently gcc times out + # or run out of memory with -fvisibility=hidden on some machines in the CI. + 'xcode_settings': { + 'GCC_SYMBOLS_PRIVATE_EXTERN': 'YES', # -fvisibility=hidden + }, + 'defines': [ + 'BUILDING_V8_SHARED', # Make V8_EXPORT visible. + ], + }], + ], }, 'targets': [ { From 721104a2961ce266f486de545da92b7716e7a249 Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Thu, 19 Dec 2024 11:34:42 +0100 Subject: [PATCH 005/205] doc: fix links in `module.md` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/56283 Reviewed-By: Michaël Zasso Reviewed-By: Jacob Smith Reviewed-By: Chengzhong Wu Reviewed-By: Luigi Pinca --- doc/api/module.md | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/doc/api/module.md b/doc/api/module.md index 72e302b6d8f5af..d494a3d53f6877 100644 --- a/doc/api/module.md +++ b/doc/api/module.md @@ -1042,13 +1042,13 @@ validating the import attributes. The final value of `format` must be one of the following: -| `format` | Description | Acceptable types for `source` returned by `load` | -| ------------ | ------------------------------ | -------------------------------------------------------------------------- | -| `'builtin'` | Load a Node.js builtin module | Not applicable | -| `'commonjs'` | Load a Node.js CommonJS module | { [`string`][], [`ArrayBuffer`][], [`TypedArray`][], `null`, `undefined` } | -| `'json'` | Load a JSON file | { [`string`][], [`ArrayBuffer`][], [`TypedArray`][] } | -| `'module'` | Load an ES module | { [`string`][], [`ArrayBuffer`][], [`TypedArray`][] } | -| `'wasm'` | Load a WebAssembly module | { [`ArrayBuffer`][], [`TypedArray`][] } | +| `format` | Description | Acceptable types for `source` returned by `load` | +| ------------ | ------------------------------ | -------------------------------------------------- | +| `'builtin'` | Load a Node.js builtin module | {null} | +| `'commonjs'` | Load a Node.js CommonJS module | {string\|ArrayBuffer\|TypedArray\|null\|undefined} | +| `'json'` | Load a JSON file | {string\|ArrayBuffer\|TypedArray} | +| `'module'` | Load an ES module | {string\|ArrayBuffer\|TypedArray} | +| `'wasm'` | Load a WebAssembly module | {ArrayBuffer\|TypedArray} | The value of `source` is ignored for type `'builtin'` because currently it is not possible to replace the value of a Node.js builtin (core) module. @@ -1091,8 +1091,8 @@ export async function load(url, context, nextLoad) { > These types all correspond to classes defined in ECMAScript. -* The specific [`ArrayBuffer`][] object is a [`SharedArrayBuffer`][]. -* The specific [`TypedArray`][] object is a [`Uint8Array`][]. +* The specific {ArrayBuffer} object is a {SharedArrayBuffer}. +* The specific {TypedArray} object is a {Uint8Array}. If the source value of a text-based format (i.e., `'json'`, `'module'`) is not a string, it is converted to a string using [`util.TextDecoder`][]. @@ -1477,14 +1477,10 @@ returned object contains the following keys: [V8 code cache]: https://v8.dev/blog/code-caching-for-devs [`"exports"`]: packages.md#exports [`--enable-source-maps`]: cli.md#--enable-source-maps -[`ArrayBuffer`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer [`NODE_COMPILE_CACHE=dir`]: cli.md#node_compile_cachedir [`NODE_DISABLE_COMPILE_CACHE=1`]: cli.md#node_disable_compile_cache1 [`NODE_V8_COVERAGE=dir`]: cli.md#node_v8_coveragedir -[`SharedArrayBuffer`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer [`SourceMap`]: #class-modulesourcemap -[`TypedArray`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray -[`Uint8Array`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array [`initialize`]: #initialize [`module.constants.compileCacheStatus`]: #moduleconstantscompilecachestatus [`module.enableCompileCache()`]: #moduleenablecompilecachecachedir @@ -1493,7 +1489,6 @@ returned object contains the following keys: [`module`]: #the-module-object [`os.tmpdir()`]: os.md#ostmpdir [`register`]: #moduleregisterspecifier-parenturl-options -[`string`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String [`util.TextDecoder`]: util.md#class-utiltextdecoder [chain]: #chaining [hooks]: #customization-hooks From a3f5ef22cd7fc41fa8f0cbebd236f2169fccc21f Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Thu, 19 Dec 2024 18:11:19 +0100 Subject: [PATCH 006/205] test: make `test-permission-sqlite-load-extension` more robust MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/56295 Reviewed-By: Richard Lau Reviewed-By: Luigi Pinca Reviewed-By: Michaël Zasso Reviewed-By: Xuguang Mei --- .../test-permission-sqlite-load-extension.js | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/test/parallel/test-permission-sqlite-load-extension.js b/test/parallel/test-permission-sqlite-load-extension.js index 28d750d0cd06b6..1e6f7426ed9400 100644 --- a/test/parallel/test-permission-sqlite-load-extension.js +++ b/test/parallel/test-permission-sqlite-load-extension.js @@ -1,18 +1,16 @@ 'use strict'; const common = require('../common'); const assert = require('node:assert'); -const childProcess = require('child_process'); const code = `const sqlite = require('node:sqlite'); const db = new sqlite.DatabaseSync(':memory:', { allowExtension: true }); db.loadExtension('nonexistent');`.replace(/\n/g, ' '); -childProcess.exec( - `${process.execPath} --permission -e "${code}"`, - {}, - common.mustCall((err, _, stderr) => { - assert.strictEqual(err.code, 1); - assert.match(stderr, /Error: Cannot load SQLite extensions when the permission model is enabled/); - assert.match(stderr, /code: 'ERR_LOAD_SQLITE_EXTENSION'/); - }) -); +common.spawnPromisified( + process.execPath, + ['--permission', '--eval', code], +).then(common.mustCall(({ code, stderr }) => { + assert.match(stderr, /Error: Cannot load SQLite extensions when the permission model is enabled/); + assert.match(stderr, /code: 'ERR_LOAD_SQLITE_EXTENSION'/); + assert.strictEqual(code, 1); +})); From 9cf9046bd7beadc9b0eba7fbb5427954ee1b28e8 Mon Sep 17 00:00:00 2001 From: origranot Date: Tue, 17 Dec 2024 10:25:04 +0200 Subject: [PATCH 007/205] Revert "events: add hasEventListener util for validate" This reverts commit https://github.com/nodejs/node/commit/bdb6d12. PR-URL: https://github.com/nodejs/node/pull/56282 Reviewed-By: Luigi Pinca Reviewed-By: Jason Zhang Reviewed-By: Jake Yuesong Li --- lib/events.js | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/events.js b/lib/events.js index 570c11f566610a..5e13338985caec 100644 --- a/lib/events.js +++ b/lib/events.js @@ -287,12 +287,6 @@ ObjectDefineProperty(EventEmitter, 'defaultMaxListeners', { }, }); -function hasEventListener(self, type) { - if (type === undefined) - return self._events !== undefined; - return self._events !== undefined && self._events[type] !== undefined; -}; - ObjectDefineProperties(EventEmitter, { kMaxEventTargetListeners: { __proto__: null, @@ -686,11 +680,13 @@ EventEmitter.prototype.removeListener = function removeListener(type, listener) { checkListener(listener); - if (!hasEventListener(this, type)) + const events = this._events; + if (events === undefined) return this; - const events = this._events; const list = events[type]; + if (list === undefined) + return this; if (list === listener || list.listener === listener) { this._eventsCount -= 1; @@ -744,9 +740,9 @@ EventEmitter.prototype.off = EventEmitter.prototype.removeListener; */ EventEmitter.prototype.removeAllListeners = function removeAllListeners(type) { - if (!hasEventListener(this)) - return this; const events = this._events; + if (events === undefined) + return this; // Not listening for removeListener, no need to emit if (events.removeListener === undefined) { @@ -791,10 +787,14 @@ EventEmitter.prototype.removeAllListeners = }; function _listeners(target, type, unwrap) { - if (!hasEventListener(target, type)) + const events = target._events; + + if (events === undefined) return []; - const evlistener = target._events[type]; + const evlistener = events[type]; + if (evlistener === undefined) + return []; if (typeof evlistener === 'function') return unwrap ? [evlistener.listener || evlistener] : [evlistener]; From 8e149aac990cb928f0afa38dc0c59a17b24d2df5 Mon Sep 17 00:00:00 2001 From: origranot Date: Tue, 17 Dec 2024 10:27:59 +0200 Subject: [PATCH 008/205] test: add test case for listeners PR-URL: https://github.com/nodejs/node/pull/56282 Reviewed-By: Luigi Pinca Reviewed-By: Jason Zhang Reviewed-By: Jake Yuesong Li --- test/parallel/test-event-emitter-listeners.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/parallel/test-event-emitter-listeners.js b/test/parallel/test-event-emitter-listeners.js index eb1da829c95f21..4a08ad34c273cd 100644 --- a/test/parallel/test-event-emitter-listeners.js +++ b/test/parallel/test-event-emitter-listeners.js @@ -86,6 +86,11 @@ function listener4() { assert.deepStrictEqual(ee.listeners('foo'), []); } +{ + const ee = new events.EventEmitter(); + assert.deepStrictEqual(ee.listeners(), []); +} + { class TestStream extends events.EventEmitter {} const s = new TestStream(); From fa56ab2bba0549cd1f85ee6a04e483ac2afb28de Mon Sep 17 00:00:00 2001 From: Luigi Pinca Date: Thu, 19 Dec 2024 23:30:28 +0100 Subject: [PATCH 009/205] test: deflake test-esm-loader-hooks-inspect-brk Refs: https://github.com/nodejs/node/pull/54827 Refs: https://github.com/nodejs/node/pull/51560 PR-URL: https://github.com/nodejs/node/pull/56050 Reviewed-By: Antoine du Hamel --- .../test-esm-loader-hooks-inspect-brk.js | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/test/parallel/test-esm-loader-hooks-inspect-brk.js b/test/parallel/test-esm-loader-hooks-inspect-brk.js index 881bdfd2dd101a..251ebb230dcd31 100644 --- a/test/parallel/test-esm-loader-hooks-inspect-brk.js +++ b/test/parallel/test-esm-loader-hooks-inspect-brk.js @@ -10,23 +10,20 @@ const assert = require('assert'); const fixtures = require('../common/fixtures'); const { NodeInstance } = require('../common/inspector-helper.js'); -async function runIfWaitingForDebugger(session) { - const commands = [ - { 'method': 'Runtime.enable' }, - { 'method': 'Debugger.enable' }, - { 'method': 'Runtime.runIfWaitingForDebugger' }, - ]; - - await session.send(commands); - await session.waitForNotification('Debugger.paused'); -} - async function runTest() { const main = fixtures.path('es-module-loaders', 'register-loader.mjs'); const child = new NodeInstance(['--inspect-brk=0'], '', main); const session = await child.connectInspectorSession(); - await runIfWaitingForDebugger(session); + await session.send({ method: 'NodeRuntime.enable' }); + await session.waitForNotification('NodeRuntime.waitingForDebugger'); + await session.send([ + { 'method': 'Runtime.enable' }, + { 'method': 'Debugger.enable' }, + { 'method': 'Runtime.runIfWaitingForDebugger' }, + ]); + await session.send({ method: 'NodeRuntime.disable' }); + await session.waitForNotification('Debugger.paused'); await session.runToCompletion(); assert.strictEqual((await child.expectShutdown()).exitCode, 0); } From df06524863a0cde2fe6adfa3c9ed6cf2b3f35729 Mon Sep 17 00:00:00 2001 From: Chengzhong Wu Date: Tue, 17 Dec 2024 23:12:00 +0000 Subject: [PATCH 010/205] lib: suppress source map lookup exceptions When the source map data are invalid json strings, skip construct `SourceMap` on it. Additionally, suppress exceptions on source map lookups and fix test runners crash on invalid source maps. PR-URL: https://github.com/nodejs/node/pull/56299 Refs: https://github.com/nodejs/node/issues/56296 Reviewed-By: Matteo Collina Reviewed-By: Xuguang Mei Reviewed-By: Yagiz Nizipli Reviewed-By: Colin Ihrig Reviewed-By: Chemi Atlow Reviewed-By: Pietro Marchini --- lib/internal/source_map/source_map_cache.js | 39 ++++++++++++++----- .../test-runner-source-maps-invalid-json.js | 12 ++++++ 2 files changed, 41 insertions(+), 10 deletions(-) create mode 100644 test/parallel/test-runner-source-maps-invalid-json.js diff --git a/lib/internal/source_map/source_map_cache.js b/lib/internal/source_map/source_map_cache.js index dfb42f83f6f1b1..ea87a579636671 100644 --- a/lib/internal/source_map/source_map_cache.js +++ b/lib/internal/source_map/source_map_cache.js @@ -155,6 +155,9 @@ function maybeCacheSourceMap(filename, content, moduleInstance, isGeneratedSourc } const data = dataFromUrl(filename, sourceMapURL); + // `data` could be null if the source map is invalid. + // In this case, create a cache entry with null data with source url for test coverage. + const entry = { __proto__: null, lineLengths: lineLengths(content), @@ -277,6 +280,8 @@ function sourceMapFromDataUrl(sourceURL, url) { const parsedData = JSONParse(decodedData); return sourcesToAbsolute(sourceURL, parsedData); } catch (err) { + // TODO(legendecas): warn about invalid source map JSON string. + // But it could be verbose. debug(err); return null; } @@ -331,24 +336,38 @@ function sourceMapCacheToObject() { /** * Find a source map for a given actual source URL or path. + * + * This function may be invoked from user code or test runner, this must not throw + * any exceptions. * @param {string} sourceURL - actual source URL or path * @returns {import('internal/source_map/source_map').SourceMap | undefined} a source map or undefined if not found */ function findSourceMap(sourceURL) { - if (RegExpPrototypeExec(kLeadingProtocol, sourceURL) === null) { - sourceURL = pathToFileURL(sourceURL).href; + if (typeof sourceURL !== 'string') { + return undefined; } + SourceMap ??= require('internal/source_map/source_map').SourceMap; - const entry = getModuleSourceMapCache().get(sourceURL) ?? generatedSourceMapCache.get(sourceURL); - if (entry === undefined) { + try { + if (RegExpPrototypeExec(kLeadingProtocol, sourceURL) === null) { + // If the sourceURL is an invalid path, this will throw an error. + sourceURL = pathToFileURL(sourceURL).href; + } + const entry = getModuleSourceMapCache().get(sourceURL) ?? generatedSourceMapCache.get(sourceURL); + if (entry?.data == null) { + return undefined; + } + + let sourceMap = entry.sourceMap; + if (sourceMap === undefined) { + sourceMap = new SourceMap(entry.data, { lineLengths: entry.lineLengths }); + entry.sourceMap = sourceMap; + } + return sourceMap; + } catch (err) { + debug(err); return undefined; } - let sourceMap = entry.sourceMap; - if (sourceMap === undefined) { - sourceMap = new SourceMap(entry.data, { lineLengths: entry.lineLengths }); - entry.sourceMap = sourceMap; - } - return sourceMap; } module.exports = { diff --git a/test/parallel/test-runner-source-maps-invalid-json.js b/test/parallel/test-runner-source-maps-invalid-json.js new file mode 100644 index 00000000000000..508e2d432117f7 --- /dev/null +++ b/test/parallel/test-runner-source-maps-invalid-json.js @@ -0,0 +1,12 @@ +// Flags: --enable-source-maps +'use strict'; + +require('../common'); +const test = require('node:test'); + +// Verify that test runner can handle invalid source maps. + +test('ok', () => {}); + +// eslint-disable-next-line @stylistic/js/spaced-comment +//# sourceMappingURL=data:application/json;base64,-1 From dc003218a8a3856db49208790b343a3188ba7f25 Mon Sep 17 00:00:00 2001 From: Chengzhong Wu Date: Tue, 17 Dec 2024 23:38:54 +0000 Subject: [PATCH 011/205] lib: optimize `prepareStackTrace` on builtin frames Only invalidates source map lookup cache when a new source map is found. This improves when user codes interleave with builtin functions, like `array.map`. PR-URL: https://github.com/nodejs/node/pull/56299 Refs: https://github.com/nodejs/node/issues/56296 Reviewed-By: Matteo Collina Reviewed-By: Xuguang Mei Reviewed-By: Yagiz Nizipli Reviewed-By: Colin Ihrig Reviewed-By: Chemi Atlow Reviewed-By: Pietro Marchini --- benchmark/fixtures/simple-error-stack.js | 21 ++++++++++--------- benchmark/fixtures/simple-error-stack.ts | 12 ++++++----- .../source_map/prepare_stack_trace.js | 10 +++++++-- lib/internal/source_map/source_map_cache.js | 5 +++++ 4 files changed, 31 insertions(+), 17 deletions(-) diff --git a/benchmark/fixtures/simple-error-stack.js b/benchmark/fixtures/simple-error-stack.js index 0057807795b072..74aae191800778 100644 --- a/benchmark/fixtures/simple-error-stack.js +++ b/benchmark/fixtures/simple-error-stack.js @@ -1,15 +1,16 @@ 'use strict'; -exports.__esModule = true; -exports.simpleErrorStack = void 0; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.simpleErrorStack = simpleErrorStack; // Compile with `tsc --inlineSourceMap benchmark/fixtures/simple-error-stack.ts`. var lorem = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'; function simpleErrorStack() { - try { - lorem.BANG(); - } - catch (e) { - return e.stack; - } + [1].map(function () { + try { + lorem.BANG(); + } + catch (e) { + return e.stack; + } + }); } -exports.simpleErrorStack = simpleErrorStack; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2ltcGxlLWVycm9yLXN0YWNrLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsic2ltcGxlLWVycm9yLXN0YWNrLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLFlBQVksQ0FBQzs7O0FBRWIsaUZBQWlGO0FBRWpGLElBQU0sS0FBSyxHQUFHLCtiQUErYixDQUFDO0FBRTljLFNBQVMsZ0JBQWdCO0lBQ3ZCLElBQUk7UUFDRCxLQUFhLENBQUMsSUFBSSxFQUFFLENBQUM7S0FDdkI7SUFBQyxPQUFPLENBQUMsRUFBRTtRQUNWLE9BQU8sQ0FBQyxDQUFDLEtBQUssQ0FBQztLQUNoQjtBQUNILENBQUM7QUFHQyw0Q0FBZ0IifQ== +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2ltcGxlLWVycm9yLXN0YWNrLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsic2ltcGxlLWVycm9yLXN0YWNrLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLFlBQVksQ0FBQzs7QUFpQlgsNENBQWdCO0FBZmxCLGlGQUFpRjtBQUVqRixJQUFNLEtBQUssR0FBRywrYkFBK2IsQ0FBQztBQUU5YyxTQUFTLGdCQUFnQjtJQUN2QixDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQztRQUNOLElBQUksQ0FBQztZQUNGLEtBQWEsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUN4QixDQUFDO1FBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztZQUNYLE9BQU8sQ0FBQyxDQUFDLEtBQUssQ0FBQztRQUNqQixDQUFDO0lBQ0gsQ0FBQyxDQUFDLENBQUE7QUFDSixDQUFDIn0= \ No newline at end of file diff --git a/benchmark/fixtures/simple-error-stack.ts b/benchmark/fixtures/simple-error-stack.ts index 58034e92f24b98..1335df3478b99b 100644 --- a/benchmark/fixtures/simple-error-stack.ts +++ b/benchmark/fixtures/simple-error-stack.ts @@ -5,11 +5,13 @@ const lorem = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'; function simpleErrorStack() { - try { - (lorem as any).BANG(); - } catch (e) { - return e.stack; - } + [1].map(() => { + try { + (lorem as any).BANG(); + } catch (e) { + return e.stack; + } + }) } export { diff --git a/lib/internal/source_map/prepare_stack_trace.js b/lib/internal/source_map/prepare_stack_trace.js index 60c9d1ed3316ff..3e4b0825e7b3a5 100644 --- a/lib/internal/source_map/prepare_stack_trace.js +++ b/lib/internal/source_map/prepare_stack_trace.js @@ -53,9 +53,15 @@ function prepareStackTraceWithSourceMaps(error, trace) { const sm = fileName === lastFileName ? lastSourceMap : findSourceMap(fileName); - lastSourceMap = sm; - lastFileName = fileName; + // Only when a source map is found, cache it for the next iteration. + // This is a performance optimization to avoid interleaving with JS builtin function + // invalidating the cache. + // - at myFunc (file:///path/to/file.js:1:2) + // - at Array.map () + // - at myFunc (file:///path/to/file.js:3:4) if (sm) { + lastSourceMap = sm; + lastFileName = fileName; return `${kStackLineAt}${serializeJSStackFrame(sm, callSite, trace[i + 1])}`; } } catch (err) { diff --git a/lib/internal/source_map/source_map_cache.js b/lib/internal/source_map/source_map_cache.js index ea87a579636671..aaca27136e66a0 100644 --- a/lib/internal/source_map/source_map_cache.js +++ b/lib/internal/source_map/source_map_cache.js @@ -347,6 +347,11 @@ function findSourceMap(sourceURL) { return undefined; } + // No source maps for builtin modules. + if (sourceURL.startsWith('node:')) { + return undefined; + } + SourceMap ??= require('internal/source_map/source_map').SourceMap; try { if (RegExpPrototypeExec(kLeadingProtocol, sourceURL) === null) { From 406e7db9c3da44ab0b92471aa934f25bd7f4b088 Mon Sep 17 00:00:00 2001 From: Luigi Pinca Date: Fri, 20 Dec 2024 07:49:20 +0100 Subject: [PATCH 012/205] test: remove async-hooks/test-writewrap flaky designation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The issue is the same as other tests that time out. Refs: https://github.com/nodejs/node/issues/54918 Refs: https://github.com/nodejs/node/pull/54802 PR-URL: https://github.com/nodejs/node/pull/56048 Reviewed-By: Gerhard Stöbich --- test/async-hooks/async-hooks.status | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/async-hooks/async-hooks.status b/test/async-hooks/async-hooks.status index 5dca3cb04f240c..673883e4fe3d4d 100644 --- a/test/async-hooks/async-hooks.status +++ b/test/async-hooks/async-hooks.status @@ -9,8 +9,6 @@ prefix async-hooks [$system==win32] [$system==linux] -# https://github.com/nodejs/node/issues/54809 -test-writewrap: PASS, FLAKY [$system==macos] From e658ea6b2640c1cb57b450b8e157bbf1cc9f759d Mon Sep 17 00:00:00 2001 From: Jason Zhang Date: Fri, 20 Dec 2024 17:27:34 +1030 Subject: [PATCH 013/205] stream: validate undefined sizeAlgorithm in WritableStream PR-URL: https://github.com/nodejs/node/pull/56067 Fixes: https://github.com/nodejs/node/issues/56014 Refs: https://github.com/whatwg/streams/pull/1333 Reviewed-By: Luigi Pinca Reviewed-By: Jake Yuesong Li --- lib/internal/webstreams/writablestream.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/internal/webstreams/writablestream.js b/lib/internal/webstreams/writablestream.js index 5baaf20c30ba26..03b48dd043bc41 100644 --- a/lib/internal/webstreams/writablestream.js +++ b/lib/internal/webstreams/writablestream.js @@ -1176,9 +1176,18 @@ function writableStreamDefaultControllerGetDesiredSize(controller) { } function writableStreamDefaultControllerGetChunkSize(controller, chunk) { + const { + stream, + sizeAlgorithm, + } = controller[kState]; + if (sizeAlgorithm === undefined) { + assert(stream[kState].state === 'errored' || stream[kState].state === 'erroring'); + return 1; + } + try { return FunctionPrototypeCall( - controller[kState].sizeAlgorithm, + sizeAlgorithm, undefined, chunk); } catch (error) { From 724524528eacaeeea3b50ce4b9cc2c9e668741b4 Mon Sep 17 00:00:00 2001 From: Vladimir Morozov Date: Fri, 20 Dec 2024 08:22:34 -0800 Subject: [PATCH 014/205] node-api: remove deprecated attribute from napi_module_register PR-URL: https://github.com/nodejs/node/pull/56162 Reviewed-By: Michael Dawson Reviewed-By: Chengzhong Wu Reviewed-By: Gabriel Schulhof --- src/node_api.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/node_api.h b/src/node_api.h index 718f7541002eb9..c8c7bc6ffb9b94 100644 --- a/src/node_api.h +++ b/src/node_api.h @@ -90,9 +90,6 @@ EXTERN_C_START // Deprecated. Replaced by symbol-based registration defined by NAPI_MODULE // and NAPI_MODULE_INIT macros. -#if defined(__cplusplus) && __cplusplus >= 201402L -[[deprecated]] -#endif NAPI_EXTERN void NAPI_CDECL napi_module_register(napi_module* mod); From 2a3cdd34ff6943c9acad4fb2679acdf8cdcdca91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= Date: Fri, 20 Dec 2024 17:35:29 +0100 Subject: [PATCH 015/205] build: test macos-13 on GitHub actions We are in the process of updating macOS to version 13 in the Jenkins CI, but unfortunately this is taking longer than expected. Add it to the GitHub actions test matrix so that we have some coverage. Refs: https://github.com/nodejs/build/issues/3686 PR-URL: https://github.com/nodejs/node/pull/56307 Reviewed-By: Yagiz Nizipli Reviewed-By: Richard Lau Reviewed-By: Chengzhong Wu Reviewed-By: Joyee Cheung Reviewed-By: Luigi Pinca --- .github/workflows/test-macos.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test-macos.yml b/.github/workflows/test-macos.yml index 6bb22265032605..56e8d6fdd65999 100644 --- a/.github/workflows/test-macos.yml +++ b/.github/workflows/test-macos.yml @@ -38,7 +38,11 @@ permissions: jobs: test-macOS: if: github.event.pull_request.draft == false - runs-on: macos-14 + strategy: + fail-fast: false + matrix: + macos-version: [macos-13, macos-14] + runs-on: ${{ matrix.macos-version }} env: CC: sccache gcc CXX: sccache g++ From acba5dc87e6cec0081cba464667ae2bf396a2714 Mon Sep 17 00:00:00 2001 From: Chengzhong Wu Date: Sat, 21 Dec 2024 11:02:30 +0000 Subject: [PATCH 016/205] module: use buffer.toString base64 `btoa` only supports latin-1 charset and produces invalid source mapping urls. PR-URL: https://github.com/nodejs/node/pull/56315 Refs: https://github.com/nodejs/node/issues/56296 Reviewed-By: Yagiz Nizipli Reviewed-By: Antoine du Hamel Reviewed-By: Marco Ippolito Reviewed-By: Colin Ihrig Reviewed-By: Luigi Pinca --- lib/eslint.config_partial.mjs | 9 ++++ lib/internal/modules/typescript.js | 8 +-- test/parallel/test-module-strip-types.js | 65 ++++++++++++++---------- 3 files changed, 53 insertions(+), 29 deletions(-) diff --git a/lib/eslint.config_partial.mjs b/lib/eslint.config_partial.mjs index 0a295f71eaff9a..c3ad0d705f0616 100644 --- a/lib/eslint.config_partial.mjs +++ b/lib/eslint.config_partial.mjs @@ -13,6 +13,15 @@ const noRestrictedSyntax = [ selector: "CallExpression[callee.object.name='assert']:not([callee.property.name='ok']):not([callee.property.name='fail']):not([callee.property.name='ifError'])", message: 'Only use simple assertions', }, + { + // Forbids usages of `btoa` that are not caught by no-restricted-globals, like: + // ``` + // const { btoa } = internalBinding('buffer'); + // btoa('...'); + // ``` + selector: "CallExpression[callee.property.name='btoa'], CallExpression[callee.name='btoa']", + message: "`btoa` supports only latin-1 charset, use Buffer.from(str).toString('base64') instead", + }, { selector: 'NewExpression[callee.name=/Error$/]:not([callee.name=/^(AssertionError|NghttpError|AbortError|NodeAggregateError)$/])', message: "Use an error exported by 'internal/errors' instead.", diff --git a/lib/internal/modules/typescript.js b/lib/internal/modules/typescript.js index d1b58e86c72ee7..2f8f61266b5d03 100644 --- a/lib/internal/modules/typescript.js +++ b/lib/internal/modules/typescript.js @@ -17,6 +17,7 @@ const { } = require('internal/errors').codes; const { getOptionValue } = require('internal/options'); const assert = require('internal/assert'); +const { Buffer } = require('buffer'); /** * The TypeScript parsing mode, either 'strip-only' or 'transform'. @@ -134,9 +135,10 @@ function stripTypeScriptModuleTypes(source, filename) { * @returns {string} The code with the source map attached. */ function addSourceMap(code, sourceMap) { - // TODO(@marco-ippolito) When Buffer.transcode supports utf8 to - // base64 transformation, we should change this line. - const base64SourceMap = internalBinding('buffer').btoa(sourceMap); + // The base64 encoding should be https://datatracker.ietf.org/doc/html/rfc4648#section-4, + // not base64url https://datatracker.ietf.org/doc/html/rfc4648#section-5. See data url + // spec https://tools.ietf.org/html/rfc2397#section-2. + const base64SourceMap = Buffer.from(sourceMap).toString('base64'); return `${code}\n\n//# sourceMappingURL=data:application/json;base64,${base64SourceMap}`; } diff --git a/test/parallel/test-module-strip-types.js b/test/parallel/test-module-strip-types.js index 6e729a55936804..0f90039b563033 100644 --- a/test/parallel/test-module-strip-types.js +++ b/test/parallel/test-module-strip-types.js @@ -12,6 +12,12 @@ common.expectWarning( 'stripTypeScriptTypes is an experimental feature and might change at any time', ); +const sourceToBeTransformed = ` + namespace MathUtil { + export const add = (a: number, b: number) => a + b; + }`; +const sourceToBeTransformedMapping = 'UACY;aACK,MAAM,CAAC,GAAW,IAAc,IAAI;AACnD,GAFU,aAAA'; + test('stripTypeScriptTypes', () => { const source = 'const x: number = 1;'; const result = stripTypeScriptTypes(source); @@ -48,45 +54,52 @@ test('stripTypeScriptTypes sourceUrl throws when mode is strip', () => { }); test('stripTypeScriptTypes source map when mode is transform', () => { - const source = ` - namespace MathUtil { - export const add = (a: number, b: number) => a + b; - }`; - const result = stripTypeScriptTypes(source, { mode: 'transform', sourceMap: true }); + const result = stripTypeScriptTypes(sourceToBeTransformed, { mode: 'transform', sourceMap: true }); const script = new vm.Script(result); const sourceMap = { version: 3, - sources: [ - '', - ], - sourcesContent: [ - '\n namespace MathUtil {\n export const add = (a: number, b: number) => a + b;\n }', - ], + sources: [''], names: [], - mappings: ';UACY;aACK,MAAM,CAAC,GAAW,IAAc,IAAI;AACnD,GAFU,aAAA' + mappings: sourceToBeTransformedMapping, }; - assert(script.sourceMapURL, `sourceMappingURL=data:application/json;base64,${JSON.stringify(sourceMap)}`); + const inlinedSourceMap = Buffer.from(JSON.stringify(sourceMap)).toString('base64'); + assert.strictEqual(script.sourceMapURL, `data:application/json;base64,${inlinedSourceMap}`); }); test('stripTypeScriptTypes source map when mode is transform and sourceUrl', () => { - const source = ` - namespace MathUtil { - export const add = (a: number, b: number) => a + b; - }`; - const result = stripTypeScriptTypes(source, { mode: 'transform', sourceMap: true, sourceUrl: 'test.ts' }); + const result = stripTypeScriptTypes(sourceToBeTransformed, { + mode: 'transform', + sourceMap: true, + sourceUrl: 'test.ts' + }); + const script = new vm.Script(result); + const sourceMap = + { + version: 3, + sources: ['test.ts'], + names: [], + mappings: sourceToBeTransformedMapping, + }; + const inlinedSourceMap = Buffer.from(JSON.stringify(sourceMap)).toString('base64'); + assert.strictEqual(script.sourceMapURL, `data:application/json;base64,${inlinedSourceMap}`); +}); + +test('stripTypeScriptTypes source map when mode is transform and sourceUrl with non-latin-1 chars', () => { + const sourceUrl = 'dir%20with $unusual"chars?\'åß∂ƒ©∆¬…`.cts'; + const result = stripTypeScriptTypes(sourceToBeTransformed, { + mode: 'transform', + sourceMap: true, + sourceUrl, + }); const script = new vm.Script(result); const sourceMap = { version: 3, - sources: [ - 'test.ts', - ], - sourcesContent: [ - '\n namespace MathUtil {\n export const add = (a: number, b: number) => a + b;\n }', - ], + sources: [sourceUrl], names: [], - mappings: ';UACY;aACK,MAAM,CAAC,GAAW,IAAc,IAAI;AACnD,GAFU,aAAA' + mappings: sourceToBeTransformedMapping, }; - assert(script.sourceMapURL, `sourceMappingURL=data:application/json;base64,${JSON.stringify(sourceMap)}`); + const inlinedSourceMap = Buffer.from(JSON.stringify(sourceMap)).toString('base64'); + assert.strictEqual(script.sourceMapURL, `data:application/json;base64,${inlinedSourceMap}`); }); From 105c4ed4fb19966fa26c66544b5832eb6d010897 Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Sat, 21 Dec 2024 16:29:41 +0100 Subject: [PATCH 017/205] tools: add release line label when opening release proposal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/56317 Reviewed-By: Michaël Zasso Reviewed-By: Marco Ippolito Reviewed-By: Richard Lau Reviewed-By: Trivikram Kamat --- tools/actions/create-release.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/actions/create-release.sh b/tools/actions/create-release.sh index 1392c4dd458476..cc5e8b5b7834fd 100755 --- a/tools/actions/create-release.sh +++ b/tools/actions/create-release.sh @@ -126,4 +126,4 @@ if (data.errors?.length) { console.log(util.inspect(data, { depth: Infinity })); EOF -gh pr edit "$PR_URL" --add-label release --add-assignee "$RELEASER" +gh pr edit "$PR_URL" --add-label release --add-label "v$RELEASE_LINE.x" --add-assignee "$RELEASER" From b197dfa7ec41bfde51b6c0a910e9bc1e71ecb5d1 Mon Sep 17 00:00:00 2001 From: Cheng Date: Wed, 18 Dec 2024 12:50:24 +0900 Subject: [PATCH 018/205] build: fix GN build for ngtcp2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/56300 Reviewed-By: Juan José Arboleda Reviewed-By: Xuguang Mei Reviewed-By: Yagiz Nizipli Reviewed-By: Luigi Pinca --- deps/ngtcp2/unofficial.gni | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/deps/ngtcp2/unofficial.gni b/deps/ngtcp2/unofficial.gni index 26b8070c5a9c7f..cf9ba5363907e0 100644 --- a/deps/ngtcp2/unofficial.gni +++ b/deps/ngtcp2/unofficial.gni @@ -68,8 +68,7 @@ template("ngtcp2_gn_build") { cflags_c = [ "-Wno-extra-semi", "-Wno-implicit-fallthrough", - # Remove after https://github.com/ngtcp2/ngtcp2/issues/1050 is fixed. - "-Wno-sometimes-uninitialized", + "-Wno-unused-function", ] } } From 53b29b04697a4a1f10bee869c7e996e2b3464c0a Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Sun, 22 Dec 2024 19:44:20 +0100 Subject: [PATCH 019/205] tools: fix `require-common-first` lint rule from subfolder PR-URL: https://github.com/nodejs/node/pull/56325 Reviewed-By: Luigi Pinca Reviewed-By: LiviaMedeiros --- test/parallel/test-eslint-require-common-first.js | 6 ++++++ tools/eslint-rules/require-common-first.js | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/test/parallel/test-eslint-require-common-first.js b/test/parallel/test-eslint-require-common-first.js index ef19f95b97d635..d7980cebedbfb8 100644 --- a/test/parallel/test-eslint-require-common-first.js +++ b/test/parallel/test-eslint-require-common-first.js @@ -20,6 +20,12 @@ new RuleTester({ code: 'require("common")\n' + 'require("assert")' }, + { + code: 'import "../../../../common/index.mjs";', + languageOptions: { + sourceType: 'module', + }, + }, ], invalid: [ { diff --git a/tools/eslint-rules/require-common-first.js b/tools/eslint-rules/require-common-first.js index 2bfe146086e577..5a8980d5d1c71b 100644 --- a/tools/eslint-rules/require-common-first.js +++ b/tools/eslint-rules/require-common-first.js @@ -22,7 +22,7 @@ module.exports = { * @returns {string} module name */ function getModuleName(str) { - if (str === '../common/index.mjs') { + if (str.startsWith('../') && str.endsWith('/common/index.mjs')) { return 'common'; } From 4352bf69e91cd299d07aff831d71aa0af6738c67 Mon Sep 17 00:00:00 2001 From: Marco Ippolito Date: Mon, 23 Dec 2024 21:34:19 +0100 Subject: [PATCH 020/205] test: check typescript loader PR-URL: https://github.com/nodejs/node/pull/54657 Refs: https://github.com/nodejs/node/issues/54645 Reviewed-By: James M Snell Reviewed-By: Zeyu "Alex" Yang Reviewed-By: Benjamin Gruenbaum --- test/es-module/test-typescript.mjs | 26 ++++++++++++++++++++++ test/fixtures/typescript/ts/hook.ts | 11 +++++++++ test/fixtures/typescript/ts/test-loader.ts | 4 ++++ test/fixtures/typescript/ts/test-simple.js | 2 ++ 4 files changed, 43 insertions(+) create mode 100644 test/fixtures/typescript/ts/hook.ts create mode 100644 test/fixtures/typescript/ts/test-loader.ts create mode 100644 test/fixtures/typescript/ts/test-simple.js diff --git a/test/es-module/test-typescript.mjs b/test/es-module/test-typescript.mjs index 44a5431c37b479..abc88d4550161b 100644 --- a/test/es-module/test-typescript.mjs +++ b/test/es-module/test-typescript.mjs @@ -412,3 +412,29 @@ test('expect error when executing a TypeScript file with generics', async () => strictEqual(result.stdout, ''); strictEqual(result.code, 1); }); + +test('execute a TypeScript loader and a .ts file', async () => { + const result = await spawnPromisified(process.execPath, [ + '--experimental-strip-types', + '--no-warnings', + '--import', + fixtures.fileURL('typescript/ts/test-loader.ts'), + fixtures.path('typescript/ts/test-typescript.ts'), + ]); + strictEqual(result.stderr, ''); + match(result.stdout, /Hello, TypeScript!/); + strictEqual(result.code, 0); +}); + +test('execute a TypeScript loader and a .js file', async () => { + const result = await spawnPromisified(process.execPath, [ + '--experimental-strip-types', + '--no-warnings', + '--import', + fixtures.fileURL('typescript/ts/test-loader.ts'), + fixtures.path('typescript/ts/test-simple.js'), + ]); + strictEqual(result.stderr, ''); + match(result.stdout, /Hello, TypeScript!/); + strictEqual(result.code, 0); +}); diff --git a/test/fixtures/typescript/ts/hook.ts b/test/fixtures/typescript/ts/hook.ts new file mode 100644 index 00000000000000..e0dd46448b837e --- /dev/null +++ b/test/fixtures/typescript/ts/hook.ts @@ -0,0 +1,11 @@ +import type { ResolveHook } from 'node:module'; + +// Pass through +export const resolve: ResolveHook = async function resolve(specifier, context, nextResolve) { + if(false){ + // https://github.com/nodejs/node/issues/54645 + // A bug in the typescript parsers swc causes + // the next line to not be parsed correctly + } + return nextResolve(specifier, context); +}; diff --git a/test/fixtures/typescript/ts/test-loader.ts b/test/fixtures/typescript/ts/test-loader.ts new file mode 100644 index 00000000000000..8b957bf72f0aa0 --- /dev/null +++ b/test/fixtures/typescript/ts/test-loader.ts @@ -0,0 +1,4 @@ +import { register } from 'node:module'; +import * as fixtures from '../../../common/fixtures.mjs'; + +register(fixtures.fileURL('typescript/ts/hook.ts')); diff --git a/test/fixtures/typescript/ts/test-simple.js b/test/fixtures/typescript/ts/test-simple.js new file mode 100644 index 00000000000000..f738e60f7d61db --- /dev/null +++ b/test/fixtures/typescript/ts/test-simple.js @@ -0,0 +1,2 @@ +const str = "Hello, TypeScript!"; +console.log(str); From 6eacd19d6a4316f1e1cc34423fe2bcf991d8c0b1 Mon Sep 17 00:00:00 2001 From: "Node.js GitHub Bot" Date: Mon, 23 Dec 2024 19:59:09 -0500 Subject: [PATCH 021/205] deps: update simdutf to 5.7.0 PR-URL: https://github.com/nodejs/node/pull/56332 Reviewed-By: Luigi Pinca Reviewed-By: Antoine du Hamel --- deps/simdutf/simdutf.cpp | 903 +++++++++++++++++++++++++++++---------- deps/simdutf/simdutf.h | 15 +- 2 files changed, 680 insertions(+), 238 deletions(-) diff --git a/deps/simdutf/simdutf.cpp b/deps/simdutf/simdutf.cpp index eb3e4598407374..f1dcbe488015e6 100644 --- a/deps/simdutf/simdutf.cpp +++ b/deps/simdutf/simdutf.cpp @@ -1,4 +1,4 @@ -/* auto-generated on 2024-12-10 14:54:53 -0500. Do not edit! */ +/* auto-generated on 2024-12-17 14:54:59 -0500. Do not edit! */ /* begin file src/simdutf.cpp */ #include "simdutf.h" // We include base64_tables once. @@ -10019,6 +10019,9 @@ base64_tail_decode(char *dst, const char_type *src, size_t length, const char_type *srcend = src + length; const char_type *srcinit = src; const char *dstinit = dst; + const bool ignore_garbage = + (options == base64_options::base64_url_accept_garbage) || + (options == base64_options::base64_default_accept_garbage); uint32_t x; size_t idx; @@ -10038,27 +10041,52 @@ base64_tail_decode(char *dst, const char_type *src, size_t length, } idx = 0; // we need at least four characters. - while (idx < 4 && src < srcend) { +#ifdef __clang__ + // If possible, we read four characters at a time. (It is an optimization.) + if (ignore_garbage && src + 4 <= srcend) { + char_type c0 = src[0]; + char_type c1 = src[1]; + char_type c2 = src[2]; + char_type c3 = src[3]; + uint8_t code0 = to_base64[uint8_t(c0)]; + uint8_t code1 = to_base64[uint8_t(c1)]; + uint8_t code2 = to_base64[uint8_t(c2)]; + uint8_t code3 = to_base64[uint8_t(c3)]; + buffer[idx] = code0; + idx += (is_eight_byte(c0) && code0 <= 63); + buffer[idx] = code1; + idx += (is_eight_byte(c1) && code1 <= 63); + buffer[idx] = code2; + idx += (is_eight_byte(c2) && code2 <= 63); + buffer[idx] = code3; + idx += (is_eight_byte(c3) && code3 <= 63); + src += 4; + } +#endif + while ((idx < 4) && (src < srcend)) { char_type c = *src; uint8_t code = to_base64[uint8_t(c)]; buffer[idx] = uint8_t(code); if (is_eight_byte(c) && code <= 63) { idx++; - } else if (code > 64 || !scalar::base64::is_eight_byte(c)) { + } else if (!ignore_garbage && + (code > 64 || !scalar::base64::is_eight_byte(c))) { return {INVALID_BASE64_CHARACTER, size_t(src - srcinit), size_t(dst - dstinit)}; } else { - // We have a space or a newline. We ignore it. + // We have a space or a newline or garbage. We ignore it. } src++; } if (idx != 4) { - if (last_chunk_options == last_chunk_handling_options::strict && + if (!ignore_garbage && + last_chunk_options == last_chunk_handling_options::strict && (idx != 1) && ((idx + padded_characters) & 3) != 0) { // The partial chunk was at src - idx return {BASE64_INPUT_REMAINDER, size_t(src - srcinit), size_t(dst - dstinit)}; - } else if (last_chunk_options == + } else if (!ignore_garbage && + last_chunk_options == last_chunk_handling_options::stop_before_partial && (idx != 1) && ((idx + padded_characters) & 3) != 0) { // Rewind src to before partial chunk @@ -10068,7 +10096,8 @@ base64_tail_decode(char *dst, const char_type *src, size_t length, if (idx == 2) { uint32_t triple = (uint32_t(buffer[0]) << 3 * 6) + (uint32_t(buffer[1]) << 2 * 6); - if ((last_chunk_options == last_chunk_handling_options::strict) && + if (!ignore_garbage && + (last_chunk_options == last_chunk_handling_options::strict) && (triple & 0xffff)) { return {BASE64_EXTRA_BITS, size_t(src - srcinit), size_t(dst - dstinit)}; @@ -10086,7 +10115,8 @@ base64_tail_decode(char *dst, const char_type *src, size_t length, uint32_t triple = (uint32_t(buffer[0]) << 3 * 6) + (uint32_t(buffer[1]) << 2 * 6) + (uint32_t(buffer[2]) << 1 * 6); - if ((last_chunk_options == last_chunk_handling_options::strict) && + if (!ignore_garbage && + (last_chunk_options == last_chunk_handling_options::strict) && (triple & 0xff)) { return {BASE64_EXTRA_BITS, size_t(src - srcinit), size_t(dst - dstinit)}; @@ -10100,7 +10130,7 @@ base64_tail_decode(char *dst, const char_type *src, size_t length, std::memcpy(dst, &triple, 2); } dst += 2; - } else if (idx == 1) { + } else if (!ignore_garbage && idx == 1) { return {BASE64_INPUT_REMAINDER, size_t(src - srcinit), size_t(dst - dstinit)}; } @@ -10154,6 +10184,9 @@ result base64_tail_decode_safe( const uint32_t *d3 = (options & base64_url) ? tables::base64::base64_url::d3 : tables::base64::base64_default::d3; + const bool ignore_garbage = + (options == base64_options::base64_url_accept_garbage) || + (options == base64_options::base64_default_accept_garbage); const char_type *srcend = src + length; const char_type *srcinit = src; @@ -10184,6 +10217,28 @@ result base64_tail_decode_safe( idx = 0; const char_type *srccur = src; // We need at least four characters. +#ifdef __clang__ + // If possible, we read four characters at a time. (It is an optimization.) + if (ignore_garbage && src + 4 <= srcend) { + char_type c0 = src[0]; + char_type c1 = src[1]; + char_type c2 = src[2]; + char_type c3 = src[3]; + uint8_t code0 = to_base64[uint8_t(c0)]; + uint8_t code1 = to_base64[uint8_t(c1)]; + uint8_t code2 = to_base64[uint8_t(c2)]; + uint8_t code3 = to_base64[uint8_t(c3)]; + buffer[idx] = code0; + idx += (is_eight_byte(c0) && code0 <= 63); + buffer[idx] = code1; + idx += (is_eight_byte(c1) && code1 <= 63); + buffer[idx] = code2; + idx += (is_eight_byte(c2) && code2 <= 63); + buffer[idx] = code3; + idx += (is_eight_byte(c3) && code3 <= 63); + src += 4; + } +#endif while (idx < 4 && src < srcend) { char_type c = *src; uint8_t code = to_base64[uint8_t(c)]; @@ -10191,22 +10246,25 @@ result base64_tail_decode_safe( buffer[idx] = uint8_t(code); if (is_eight_byte(c) && code <= 63) { idx++; - } else if (code > 64 || !scalar::base64::is_eight_byte(c)) { + } else if (!ignore_garbage && + (code > 64 || !scalar::base64::is_eight_byte(c))) { outlen = size_t(dst - dstinit); srcr = src; return {INVALID_BASE64_CHARACTER, size_t(src - srcinit)}; } else { - // We have a space or a newline. We ignore it. + // We have a space or a newline or garbage. We ignore it. } src++; } if (idx != 4) { - if (last_chunk_options == last_chunk_handling_options::strict && + if (!ignore_garbage && + last_chunk_options == last_chunk_handling_options::strict && ((idx + padded_characters) & 3) != 0) { outlen = size_t(dst - dstinit); srcr = src; return {BASE64_INPUT_REMAINDER, size_t(src - srcinit)}; - } else if (last_chunk_options == + } else if (!ignore_garbage && + last_chunk_options == last_chunk_handling_options::stop_before_partial && ((idx + padded_characters) & 3) != 0) { // Rewind src to before partial chunk @@ -10219,7 +10277,7 @@ result base64_tail_decode_safe( outlen = size_t(dst - dstinit); srcr = src; return {SUCCESS, size_t(dst - dstinit)}; - } else if (idx == 1) { + } else if (!ignore_garbage && idx == 1) { // Error: Incomplete chunk of length 1 is invalid in loose mode outlen = size_t(dst - dstinit); srcr = src; @@ -10235,7 +10293,8 @@ result base64_tail_decode_safe( uint32_t triple = 0; if (idx == 2) { triple = (uint32_t(buffer[0]) << 18) + (uint32_t(buffer[1]) << 12); - if ((last_chunk_options == last_chunk_handling_options::strict) && + if (!ignore_garbage && + (last_chunk_options == last_chunk_handling_options::strict) && (triple & 0xffff)) { srcr = src; return {BASE64_EXTRA_BITS, size_t(src - srcinit)}; @@ -10247,7 +10306,8 @@ result base64_tail_decode_safe( } else if (idx == 3) { triple = (uint32_t(buffer[0]) << 18) + (uint32_t(buffer[1]) << 12) + (uint32_t(buffer[2]) << 6); - if ((last_chunk_options == last_chunk_handling_options::strict) && + if (!ignore_garbage && + (last_chunk_options == last_chunk_handling_options::strict) && (triple & 0xff)) { srcr = src; return {BASE64_EXTRA_BITS, size_t(src - srcinit)}; @@ -18540,7 +18600,7 @@ void base64_decode_block(char *out, const char *src) { vst3q_u8((uint8_t *)out, outvec); } -template +template full_result compress_decode_base64(char *dst, const char_type *src, size_t srclen, base64_options options, @@ -18571,7 +18631,7 @@ compress_decode_base64(char *dst, const char_type *src, size_t srclen, } } if (srclen == 0) { - if (equalsigns > 0) { + if (!ignore_garbage && equalsigns > 0) { return {INVALID_BASE64_CHARACTER, equallocation, 0}; } return {SUCCESS, 0, 0}; @@ -18592,7 +18652,7 @@ compress_decode_base64(char *dst, const char_type *src, size_t srclen, bool error = false; uint64_t badcharmask = to_base64_mask(&b, &error); if (badcharmask) { - if (error) { + if (error && !ignore_garbage) { src -= 64; while (src < srcend && scalar::base64::is_eight_byte(*src) && to_base64[uint8_t(*src)] <= 64) { @@ -18636,7 +18696,8 @@ compress_decode_base64(char *dst, const char_type *src, size_t srclen, while ((bufferptr - buffer_start) % 64 != 0 && src < srcend) { uint8_t val = to_base64[uint8_t(*src)]; *bufferptr = char(val); - if (!scalar::base64::is_eight_byte(*src) || val > 64) { + if ((!scalar::base64::is_eight_byte(*src) || val > 64) && + !ignore_garbage) { return {error_code::INVALID_BASE64_CHARACTER, size_t(src - srcinit), size_t(dst - dstinit)}; } @@ -18678,8 +18739,14 @@ compress_decode_base64(char *dst, const char_type *src, size_t srclen, // backtrack int leftover = int(bufferptr - buffer_start); while (leftover > 0) { - while (to_base64[uint8_t(*(src - 1))] == 64) { - src--; + if (!ignore_garbage) { + while (to_base64[uint8_t(*(src - 1))] == 64) { + src--; + } + } else { + while (to_base64[uint8_t(*(src - 1))] >= 64) { + src--; + } } src--; leftover--; @@ -18696,7 +18763,7 @@ compress_decode_base64(char *dst, const char_type *src, size_t srclen, r.output_count += size_t(dst - dstinit); } if (last_chunk_options != stop_before_partial && - r.error == error_code::SUCCESS && equalsigns > 0) { + r.error == error_code::SUCCESS && equalsigns > 0 && !ignore_garbage) { // additional checks if ((r.output_count % 3 == 0) || ((r.output_count % 3) + 1 + equalsigns != 4)) { @@ -18706,7 +18773,7 @@ compress_decode_base64(char *dst, const char_type *src, size_t srclen, } return r; } - if (equalsigns > 0) { + if (equalsigns > 0 && !ignore_garbage) { if ((size_t(dst - dstinit) % 3 == 0) || ((size_t(dst - dstinit) % 3) + 1 + equalsigns != 4)) { return {INVALID_BASE64_CHARACTER, equallocation, size_t(dst - dstinit)}; @@ -22186,21 +22253,45 @@ simdutf_warn_unused size_t implementation::maximal_binary_length_from_base64( simdutf_warn_unused result implementation::base64_to_binary( const char *input, size_t length, char *output, base64_options options, last_chunk_handling_options last_chunk_options) const noexcept { - return (options & base64_url) - ? compress_decode_base64(output, input, length, options, - last_chunk_options) - : compress_decode_base64(output, input, length, options, - last_chunk_options); + if (options & base64_url) { + if (options == base64_options::base64_url_accept_garbage) { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } else { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } + } else { + if (options == base64_options::base64_default_accept_garbage) { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } else { + return compress_decode_base64(output, input, length, + options, last_chunk_options); + } + } } simdutf_warn_unused full_result implementation::base64_to_binary_details( const char *input, size_t length, char *output, base64_options options, last_chunk_handling_options last_chunk_options) const noexcept { - return (options & base64_url) - ? compress_decode_base64(output, input, length, options, - last_chunk_options) - : compress_decode_base64(output, input, length, options, - last_chunk_options); + if (options & base64_url) { + if (options == base64_options::base64_url_accept_garbage) { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } else { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } + } else { + if (options == base64_options::base64_default_accept_garbage) { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } else { + return compress_decode_base64(output, input, length, + options, last_chunk_options); + } + } } simdutf_warn_unused size_t implementation::maximal_binary_length_from_base64( @@ -22211,21 +22302,45 @@ simdutf_warn_unused size_t implementation::maximal_binary_length_from_base64( simdutf_warn_unused result implementation::base64_to_binary( const char16_t *input, size_t length, char *output, base64_options options, last_chunk_handling_options last_chunk_options) const noexcept { - return (options & base64_url) - ? compress_decode_base64(output, input, length, options, - last_chunk_options) - : compress_decode_base64(output, input, length, options, - last_chunk_options); + if (options & base64_url) { + if (options == base64_options::base64_url_accept_garbage) { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } else { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } + } else { + if (options == base64_options::base64_default_accept_garbage) { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } else { + return compress_decode_base64(output, input, length, + options, last_chunk_options); + } + } } simdutf_warn_unused full_result implementation::base64_to_binary_details( const char16_t *input, size_t length, char *output, base64_options options, last_chunk_handling_options last_chunk_options) const noexcept { - return (options & base64_url) - ? compress_decode_base64(output, input, length, options, - last_chunk_options) - : compress_decode_base64(output, input, length, options, - last_chunk_options); + if (options & base64_url) { + if (options == base64_options::base64_url_accept_garbage) { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } else { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } + } else { + if (options == base64_options::base64_default_accept_garbage) { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } else { + return compress_decode_base64(output, input, length, + options, last_chunk_options); + } + } } simdutf_warn_unused size_t implementation::base64_length_from_binary( @@ -22735,6 +22850,9 @@ simdutf_warn_unused size_t implementation::maximal_binary_length_from_base64( simdutf_warn_unused result implementation::base64_to_binary( const char *input, size_t length, char *output, base64_options options, last_chunk_handling_options last_chunk_options) const noexcept { + const bool ignore_garbage = + (options == base64_options::base64_url_accept_garbage) || + (options == base64_options::base64_default_accept_garbage); while (length > 0 && scalar::base64::is_ascii_white_space(input[length - 1])) { length--; @@ -22757,7 +22875,7 @@ simdutf_warn_unused result implementation::base64_to_binary( } } if (length == 0) { - if (equalsigns > 0) { + if (!ignore_garbage && equalsigns > 0) { return {INVALID_BASE64_CHARACTER, equallocation}; } return {SUCCESS, 0}; @@ -22765,7 +22883,7 @@ simdutf_warn_unused result implementation::base64_to_binary( result r = scalar::base64::base64_tail_decode( output, input, length, equalsigns, options, last_chunk_options); if (last_chunk_options != stop_before_partial && - r.error == error_code::SUCCESS && equalsigns > 0) { + r.error == error_code::SUCCESS && equalsigns > 0 && !ignore_garbage) { // additional checks if ((r.count % 3 == 0) || ((r.count % 3) + 1 + equalsigns != 4)) { return {INVALID_BASE64_CHARACTER, equallocation}; @@ -22777,6 +22895,9 @@ simdutf_warn_unused result implementation::base64_to_binary( simdutf_warn_unused full_result implementation::base64_to_binary_details( const char *input, size_t length, char *output, base64_options options, last_chunk_handling_options last_chunk_options) const noexcept { + const bool ignore_garbage = + (options == base64_options::base64_url_accept_garbage) || + (options == base64_options::base64_default_accept_garbage); while (length > 0 && scalar::base64::is_ascii_white_space(input[length - 1])) { length--; @@ -22799,7 +22920,7 @@ simdutf_warn_unused full_result implementation::base64_to_binary_details( } } if (length == 0) { - if (equalsigns > 0) { + if (!ignore_garbage && equalsigns > 0) { return {INVALID_BASE64_CHARACTER, equallocation, 0}; } return {SUCCESS, 0, 0}; @@ -22807,7 +22928,7 @@ simdutf_warn_unused full_result implementation::base64_to_binary_details( full_result r = scalar::base64::base64_tail_decode( output, input, length, equalsigns, options, last_chunk_options); if (last_chunk_options != stop_before_partial && - r.error == error_code::SUCCESS && equalsigns > 0) { + r.error == error_code::SUCCESS && equalsigns > 0 && !ignore_garbage) { // additional checks if ((r.output_count % 3 == 0) || ((r.output_count % 3) + 1 + equalsigns != 4)) { @@ -22825,6 +22946,9 @@ simdutf_warn_unused size_t implementation::maximal_binary_length_from_base64( simdutf_warn_unused result implementation::base64_to_binary( const char16_t *input, size_t length, char *output, base64_options options, last_chunk_handling_options last_chunk_options) const noexcept { + const bool ignore_garbage = + (options == base64_options::base64_url_accept_garbage) || + (options == base64_options::base64_default_accept_garbage); while (length > 0 && scalar::base64::is_ascii_white_space(input[length - 1])) { length--; @@ -22847,7 +22971,7 @@ simdutf_warn_unused result implementation::base64_to_binary( } } if (length == 0) { - if (equalsigns > 0) { + if (!ignore_garbage && equalsigns > 0) { return {INVALID_BASE64_CHARACTER, equallocation}; } return {SUCCESS, 0}; @@ -22855,7 +22979,7 @@ simdutf_warn_unused result implementation::base64_to_binary( result r = scalar::base64::base64_tail_decode( output, input, length, equalsigns, options, last_chunk_options); if (last_chunk_options != stop_before_partial && - r.error == error_code::SUCCESS && equalsigns > 0) { + r.error == error_code::SUCCESS && equalsigns > 0 && !ignore_garbage) { // additional checks if ((r.count % 3 == 0) || ((r.count % 3) + 1 + equalsigns != 4)) { return {INVALID_BASE64_CHARACTER, equallocation}; @@ -22867,6 +22991,9 @@ simdutf_warn_unused result implementation::base64_to_binary( simdutf_warn_unused full_result implementation::base64_to_binary_details( const char16_t *input, size_t length, char *output, base64_options options, last_chunk_handling_options last_chunk_options) const noexcept { + const bool ignore_garbage = + (options == base64_options::base64_url_accept_garbage) || + (options == base64_options::base64_default_accept_garbage); while (length > 0 && scalar::base64::is_ascii_white_space(input[length - 1])) { length--; @@ -22889,7 +23016,7 @@ simdutf_warn_unused full_result implementation::base64_to_binary_details( } } if (length == 0) { - if (equalsigns > 0) { + if (!ignore_garbage && equalsigns > 0) { return {INVALID_BASE64_CHARACTER, equallocation, 0}; } return {SUCCESS, 0, 0}; @@ -22897,7 +23024,7 @@ simdutf_warn_unused full_result implementation::base64_to_binary_details( full_result r = scalar::base64::base64_tail_decode( output, input, length, equalsigns, options, last_chunk_options); if (last_chunk_options != stop_before_partial && - r.error == error_code::SUCCESS && equalsigns > 0) { + r.error == error_code::SUCCESS && equalsigns > 0 && !ignore_garbage) { // additional checks if ((r.output_count % 3 == 0) || ((r.output_count % 3) + 1 + equalsigns != 4)) { @@ -26267,7 +26394,7 @@ size_t encode_base64(char *dst, const char *src, size_t srclen, return (size_t)(out - (uint8_t *)dst) + output_len; } -template +template static inline uint64_t to_base64_mask(block64 *b, uint64_t *error, uint64_t input_mask = UINT64_MAX) { __m512i input = b->chunks[0]; @@ -26309,7 +26436,7 @@ static inline uint64_t to_base64_mask(block64 *b, uint64_t *error, const __m512i translated = _mm512_permutex2var_epi8(lookup0, input, lookup1); const __m512i combined = _mm512_or_si512(translated, input); const __mmask64 mask = _mm512_movepi8_mask(combined) & input_mask; - if (mask) { + if (!ignore_garbage && mask) { const __mmask64 spaces = _mm512_cmpeq_epi8_mask(_mm512_shuffle_epi8(ascii_space_tbl, input), input) & @@ -26390,7 +26517,7 @@ static inline void base64_decode_block(char *out, block64 *b) { base64_decode(out, b->chunks[0]); } -template +template full_result compress_decode_base64(char *dst, const chartype *src, size_t srclen, base64_options options, @@ -26402,11 +26529,12 @@ compress_decode_base64(char *dst, const chartype *src, size_t srclen, srclen; // location of the first padding character if any size_t equalsigns = 0; // skip trailing spaces - while (srclen > 0 && scalar::base64::is_eight_byte(src[srclen - 1]) && + while (!ignore_garbage && srclen > 0 && + scalar::base64::is_eight_byte(src[srclen - 1]) && to_base64[uint8_t(src[srclen - 1])] == 64) { srclen--; } - if (srclen > 0 && src[srclen - 1] == '=') { + if (!ignore_garbage && srclen > 0 && src[srclen - 1] == '=') { equallocation = srclen - 1; srclen--; equalsigns = 1; @@ -26422,7 +26550,7 @@ compress_decode_base64(char *dst, const chartype *src, size_t srclen, } } if (srclen == 0) { - if (equalsigns > 0) { + if (!ignore_garbage && equalsigns > 0) { return {INVALID_BASE64_CHARACTER, equallocation, 0}; } return {SUCCESS, 0, 0}; @@ -26442,8 +26570,9 @@ compress_decode_base64(char *dst, const chartype *src, size_t srclen, load_block(&b, src); src += 64; uint64_t error = 0; - uint64_t badcharmask = to_base64_mask(&b, &error); - if (error) { + uint64_t badcharmask = + to_base64_mask(&b, &error); + if (!ignore_garbage && error) { src -= 64; size_t error_offset = _tzcnt_u64(error); return {error_code::INVALID_BASE64_CHARACTER, @@ -26479,8 +26608,9 @@ compress_decode_base64(char *dst, const chartype *src, size_t srclen, block64 b; load_block_partial(&b, src, input_mask); uint64_t error = 0; - uint64_t badcharmask = to_base64_mask(&b, &error, input_mask); - if (error) { + uint64_t badcharmask = + to_base64_mask(&b, &error, input_mask); + if (!ignore_garbage && error) { size_t error_offset = _tzcnt_u64(error); return {error_code::INVALID_BASE64_CHARACTER, size_t(src - srcinit + error_offset), size_t(dst - dstinit)}; @@ -26513,14 +26643,16 @@ compress_decode_base64(char *dst, const chartype *src, size_t srclen, 5, 6, 0, 1, 2); const __m512i shuffled = _mm512_permutexvar_epi8(pack, merged); - if (last_chunk_options == last_chunk_handling_options::strict && + if (!ignore_garbage && + last_chunk_options == last_chunk_handling_options::strict && (idx != 1) && ((idx + equalsigns) & 3) != 0) { // The partial chunk was at src - idx _mm512_mask_storeu_epi8((__m512i *)dst, output_mask, shuffled); dst += output_len; return {BASE64_INPUT_REMAINDER, size_t(src - srcinit), size_t(dst - dstinit)}; - } else if (last_chunk_options == + } else if (!ignore_garbage && + last_chunk_options == last_chunk_handling_options::stop_before_partial && (idx != 1) && ((idx + equalsigns) & 3) != 0) { // Rewind src to before partial chunk @@ -26529,7 +26661,8 @@ compress_decode_base64(char *dst, const chartype *src, size_t srclen, src -= idx; } else { if (idx == 2) { - if (last_chunk_options == last_chunk_handling_options::strict) { + if (!ignore_garbage && + last_chunk_options == last_chunk_handling_options::strict) { uint32_t triple = (uint32_t(bufferptr[-2]) << 3 * 6) + (uint32_t(bufferptr[-1]) << 2 * 6); if (triple & 0xffff) { @@ -26544,7 +26677,8 @@ compress_decode_base64(char *dst, const chartype *src, size_t srclen, _mm512_mask_storeu_epi8((__m512i *)dst, output_mask, shuffled); dst += output_len; } else if (idx == 3) { - if (last_chunk_options == last_chunk_handling_options::strict) { + if (!ignore_garbage && + last_chunk_options == last_chunk_handling_options::strict) { uint32_t triple = (uint32_t(bufferptr[-3]) << 3 * 6) + (uint32_t(bufferptr[-2]) << 2 * 6) + (uint32_t(bufferptr[-1]) << 1 * 6); @@ -26559,7 +26693,7 @@ compress_decode_base64(char *dst, const chartype *src, size_t srclen, output_len += 2; _mm512_mask_storeu_epi8((__m512i *)dst, output_mask, shuffled); dst += output_len; - } else if (idx == 1) { + } else if (!ignore_garbage && idx == 1) { _mm512_mask_storeu_epi8((__m512i *)dst, output_mask, shuffled); dst += output_len; return {BASE64_INPUT_REMAINDER, size_t(src - srcinit), @@ -26570,7 +26704,8 @@ compress_decode_base64(char *dst, const chartype *src, size_t srclen, } } - if (last_chunk_options != stop_before_partial && equalsigns > 0) { + if (!ignore_garbage && last_chunk_options != stop_before_partial && + equalsigns > 0) { size_t output_count = size_t(dst - dstinit); if ((output_count % 3 == 0) || ((output_count % 3) + 1 + equalsigns != 4)) { @@ -26581,7 +26716,7 @@ compress_decode_base64(char *dst, const chartype *src, size_t srclen, return {SUCCESS, srclen, size_t(dst - dstinit)}; } - if (equalsigns > 0) { + if (!ignore_garbage && equalsigns > 0) { if ((size_t(dst - dstinit) % 3 == 0) || ((size_t(dst - dstinit) % 3) + 1 + equalsigns != 4)) { return {INVALID_BASE64_CHARACTER, equallocation, size_t(dst - dstinit)}; @@ -28141,21 +28276,45 @@ simdutf_warn_unused size_t implementation::maximal_binary_length_from_base64( simdutf_warn_unused result implementation::base64_to_binary( const char *input, size_t length, char *output, base64_options options, last_chunk_handling_options last_chunk_options) const noexcept { - return (options & base64_url) - ? compress_decode_base64(output, input, length, options, - last_chunk_options) - : compress_decode_base64(output, input, length, options, - last_chunk_options); + if (options & base64_url) { + if (options == base64_options::base64_url_accept_garbage) { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } else { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } + } else { + if (options == base64_options::base64_default_accept_garbage) { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } else { + return compress_decode_base64(output, input, length, + options, last_chunk_options); + } + } } simdutf_warn_unused full_result implementation::base64_to_binary_details( const char *input, size_t length, char *output, base64_options options, last_chunk_handling_options last_chunk_options) const noexcept { - return (options & base64_url) - ? compress_decode_base64(output, input, length, options, - last_chunk_options) - : compress_decode_base64(output, input, length, options, - last_chunk_options); + if (options & base64_url) { + if (options == base64_options::base64_url_accept_garbage) { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } else { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } + } else { + if (options == base64_options::base64_default_accept_garbage) { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } else { + return compress_decode_base64(output, input, length, + options, last_chunk_options); + } + } } simdutf_warn_unused size_t implementation::maximal_binary_length_from_base64( @@ -28166,21 +28325,45 @@ simdutf_warn_unused size_t implementation::maximal_binary_length_from_base64( simdutf_warn_unused result implementation::base64_to_binary( const char16_t *input, size_t length, char *output, base64_options options, last_chunk_handling_options last_chunk_options) const noexcept { - return (options & base64_url) - ? compress_decode_base64(output, input, length, options, - last_chunk_options) - : compress_decode_base64(output, input, length, options, - last_chunk_options); + if (options & base64_url) { + if (options == base64_options::base64_url_accept_garbage) { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } else { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } + } else { + if (options == base64_options::base64_default_accept_garbage) { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } else { + return compress_decode_base64(output, input, length, + options, last_chunk_options); + } + } } simdutf_warn_unused full_result implementation::base64_to_binary_details( const char16_t *input, size_t length, char *output, base64_options options, last_chunk_handling_options last_chunk_options) const noexcept { - return (options & base64_url) - ? compress_decode_base64(output, input, length, options, - last_chunk_options) - : compress_decode_base64(output, input, length, options, - last_chunk_options); + if (options & base64_url) { + if (options == base64_options::base64_url_accept_garbage) { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } else { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } + } else { + if (options == base64_options::base64_default_accept_garbage) { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } else { + return compress_decode_base64(output, input, length, + options, last_chunk_options); + } + } } simdutf_warn_unused size_t implementation::base64_length_from_binary( @@ -31062,7 +31245,7 @@ struct block64 { __m256i chunks[2]; }; -template +template static inline uint32_t to_base64_mask(__m256i *src, uint32_t *error) { const __m256i ascii_space_tbl = _mm256_setr_epi8(0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9, 0xa, @@ -31144,7 +31327,7 @@ static inline uint32_t to_base64_mask(__m256i *src, uint32_t *error) { const __m256i chk = _mm256_adds_epi8(_mm256_shuffle_epi8(check_values, check_hash), *src); const int mask = _mm256_movemask_epi8(chk); - if (mask) { + if (!ignore_garbage && mask) { __m256i ascii_space = _mm256_cmpeq_epi8(_mm256_shuffle_epi8(ascii_space_tbl, *src), *src); *error = (mask ^ _mm256_movemask_epi8(ascii_space)); @@ -31153,13 +31336,17 @@ static inline uint32_t to_base64_mask(__m256i *src, uint32_t *error) { return (uint32_t)mask; } -template +template static inline uint64_t to_base64_mask(block64 *b, uint64_t *error) { uint32_t err0 = 0; uint32_t err1 = 0; - uint64_t m0 = to_base64_mask(&b->chunks[0], &err0); - uint64_t m1 = to_base64_mask(&b->chunks[1], &err1); - *error = err0 | ((uint64_t)err1 << 32); + uint64_t m0 = + to_base64_mask(&b->chunks[0], &err0); + uint64_t m1 = + to_base64_mask(&b->chunks[1], &err1); + if (!ignore_garbage) { + *error = err0 | ((uint64_t)err1 << 32); + } return m0 | (m1 << 32); } @@ -31238,7 +31425,7 @@ static inline void base64_decode_block_safe(char *out, block64 *b) { std::memcpy(out + 24, buffer, 24); } -template +template full_result compress_decode_base64(char *dst, const chartype *src, size_t srclen, base64_options options, @@ -31248,12 +31435,13 @@ compress_decode_base64(char *dst, const chartype *src, size_t srclen, size_t equallocation = srclen; // location of the first padding character if any // skip trailing spaces - while (srclen > 0 && scalar::base64::is_eight_byte(src[srclen - 1]) && + while (!ignore_garbage && srclen > 0 && + scalar::base64::is_eight_byte(src[srclen - 1]) && to_base64[uint8_t(src[srclen - 1])] == 64) { srclen--; } size_t equalsigns = 0; - if (srclen > 0 && src[srclen - 1] == '=') { + if (!ignore_garbage && srclen > 0 && src[srclen - 1] == '=') { equallocation = srclen - 1; srclen--; equalsigns = 1; @@ -31269,7 +31457,7 @@ compress_decode_base64(char *dst, const chartype *src, size_t srclen, } } if (srclen == 0) { - if (equalsigns > 0) { + if (!ignore_garbage && equalsigns > 0) { return {INVALID_BASE64_CHARACTER, equallocation, 0}; } return {SUCCESS, 0, 0}; @@ -31292,8 +31480,9 @@ compress_decode_base64(char *dst, const chartype *src, size_t srclen, load_block(&b, src); src += 64; uint64_t error = 0; - uint64_t badcharmask = to_base64_mask(&b, &error); - if (error) { + uint64_t badcharmask = + to_base64_mask(&b, &error); + if (!ignore_garbage && error) { src -= 64; size_t error_offset = _tzcnt_u64(error); return {error_code::INVALID_BASE64_CHARACTER, @@ -31342,7 +31531,8 @@ compress_decode_base64(char *dst, const chartype *src, size_t srclen, while ((bufferptr - buffer_start) % 64 != 0 && src < srcend) { uint8_t val = to_base64[uint8_t(*src)]; *bufferptr = char(val); - if (!scalar::base64::is_eight_byte(*src) || val > 64) { + if (!ignore_garbage && + (!scalar::base64::is_eight_byte(*src) || val > 64)) { return {error_code::INVALID_BASE64_CHARACTER, size_t(src - srcinit), size_t(dst - dstinit)}; } @@ -31388,8 +31578,14 @@ compress_decode_base64(char *dst, const chartype *src, size_t srclen, // backtrack int leftover = int(bufferptr - buffer_start); while (leftover > 0) { - while (to_base64[uint8_t(*(src - 1))] == 64) { - src--; + if (!ignore_garbage) { + while (to_base64[uint8_t(*(src - 1))] == 64) { + src--; + } + } else { + while (to_base64[uint8_t(*(src - 1))] >= 64) { + src--; + } } src--; leftover--; @@ -31405,7 +31601,7 @@ compress_decode_base64(char *dst, const chartype *src, size_t srclen, } else { r.output_count += size_t(dst - dstinit); } - if (last_chunk_options != stop_before_partial && + if (!ignore_garbage && last_chunk_options != stop_before_partial && r.error == error_code::SUCCESS && equalsigns > 0) { // additional checks if ((r.output_count % 3 == 0) || @@ -31416,7 +31612,7 @@ compress_decode_base64(char *dst, const chartype *src, size_t srclen, } return r; } - if (equalsigns > 0) { + if (!ignore_garbage && equalsigns > 0) { if ((size_t(dst - dstinit) % 3 == 0) || ((size_t(dst - dstinit) % 3) + 1 + equalsigns != 4)) { return {INVALID_BASE64_CHARACTER, equallocation, size_t(dst - dstinit)}; @@ -34195,21 +34391,45 @@ simdutf_warn_unused size_t implementation::maximal_binary_length_from_base64( simdutf_warn_unused result implementation::base64_to_binary( const char *input, size_t length, char *output, base64_options options, last_chunk_handling_options last_chunk_options) const noexcept { - return (options & base64_url) - ? compress_decode_base64(output, input, length, options, - last_chunk_options) - : compress_decode_base64(output, input, length, options, - last_chunk_options); + if (options & base64_url) { + if (options == base64_options::base64_url_accept_garbage) { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } else { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } + } else { + if (options == base64_options::base64_default_accept_garbage) { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } else { + return compress_decode_base64(output, input, length, + options, last_chunk_options); + } + } } simdutf_warn_unused full_result implementation::base64_to_binary_details( const char *input, size_t length, char *output, base64_options options, last_chunk_handling_options last_chunk_options) const noexcept { - return (options & base64_url) - ? compress_decode_base64(output, input, length, options, - last_chunk_options) - : compress_decode_base64(output, input, length, options, - last_chunk_options); + if (options & base64_url) { + if (options == base64_options::base64_url_accept_garbage) { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } else { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } + } else { + if (options == base64_options::base64_default_accept_garbage) { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } else { + return compress_decode_base64(output, input, length, + options, last_chunk_options); + } + } } simdutf_warn_unused size_t implementation::maximal_binary_length_from_base64( @@ -34220,21 +34440,45 @@ simdutf_warn_unused size_t implementation::maximal_binary_length_from_base64( simdutf_warn_unused result implementation::base64_to_binary( const char16_t *input, size_t length, char *output, base64_options options, last_chunk_handling_options last_chunk_options) const noexcept { - return (options & base64_url) - ? compress_decode_base64(output, input, length, options, - last_chunk_options) - : compress_decode_base64(output, input, length, options, - last_chunk_options); + if (options & base64_url) { + if (options == base64_options::base64_url_accept_garbage) { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } else { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } + } else { + if (options == base64_options::base64_default_accept_garbage) { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } else { + return compress_decode_base64(output, input, length, + options, last_chunk_options); + } + } } simdutf_warn_unused full_result implementation::base64_to_binary_details( const char16_t *input, size_t length, char *output, base64_options options, last_chunk_handling_options last_chunk_options) const noexcept { - return (options & base64_url) - ? compress_decode_base64(output, input, length, options, - last_chunk_options) - : compress_decode_base64(output, input, length, options, - last_chunk_options); + if (options & base64_url) { + if (options == base64_options::base64_url_accept_garbage) { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } else { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } + } else { + if (options == base64_options::base64_default_accept_garbage) { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } else { + return compress_decode_base64(output, input, length, + options, last_chunk_options); + } + } } simdutf_warn_unused size_t implementation::base64_length_from_binary( @@ -36030,6 +36274,9 @@ simdutf_warn_unused size_t implementation::maximal_binary_length_from_base64( simdutf_warn_unused result implementation::base64_to_binary( const char *input, size_t length, char *output, base64_options options, last_chunk_handling_options last_chunk_options) const noexcept { + const bool ignore_garbage = + (options == base64_options::base64_url_accept_garbage) || + (options == base64_options::base64_default_accept_garbage); // skip trailing spaces while (length > 0 && scalar::base64::is_ascii_white_space(input[length - 1])) { @@ -36053,7 +36300,7 @@ simdutf_warn_unused result implementation::base64_to_binary( } } if (length == 0) { - if (equalsigns > 0) { + if (!ignore_garbage && equalsigns > 0) { return {INVALID_BASE64_CHARACTER, equallocation}; } return {SUCCESS, 0}; @@ -36061,7 +36308,7 @@ simdutf_warn_unused result implementation::base64_to_binary( result r = scalar::base64::base64_tail_decode( output, input, length, equalsigns, options, last_chunk_options); if (last_chunk_options != stop_before_partial && - r.error == error_code::SUCCESS && equalsigns > 0) { + r.error == error_code::SUCCESS && equalsigns > 0 && !ignore_garbage) { // additional checks if ((r.count % 3 == 0) || ((r.count % 3) + 1 + equalsigns != 4)) { return {INVALID_BASE64_CHARACTER, equallocation}; @@ -36078,6 +36325,9 @@ simdutf_warn_unused size_t implementation::maximal_binary_length_from_base64( simdutf_warn_unused result implementation::base64_to_binary( const char16_t *input, size_t length, char *output, base64_options options, last_chunk_handling_options last_chunk_options) const noexcept { + const bool ignore_garbage = + (options == base64_options::base64_url_accept_garbage) || + (options == base64_options::base64_default_accept_garbage); // skip trailing spaces while (length > 0 && scalar::base64::is_ascii_white_space(input[length - 1])) { @@ -36101,7 +36351,7 @@ simdutf_warn_unused result implementation::base64_to_binary( } } if (length == 0) { - if (equalsigns > 0) { + if (!ignore_garbage && equalsigns > 0) { return {INVALID_BASE64_CHARACTER, equallocation}; } return {SUCCESS, 0}; @@ -36109,7 +36359,7 @@ simdutf_warn_unused result implementation::base64_to_binary( result r = scalar::base64::base64_tail_decode( output, input, length, equalsigns, options, last_chunk_options); if (last_chunk_options != stop_before_partial && - r.error == error_code::SUCCESS && equalsigns > 0) { + r.error == error_code::SUCCESS && equalsigns > 0 && !ignore_garbage) { // additional checks if ((r.count % 3 == 0) || ((r.count % 3) + 1 + equalsigns != 4)) { return {INVALID_BASE64_CHARACTER, equallocation}; @@ -37828,6 +38078,9 @@ simdutf_warn_unused size_t implementation::maximal_binary_length_from_base64( simdutf_warn_unused result implementation::base64_to_binary( const char *input, size_t length, char *output, base64_options options, last_chunk_handling_options last_chunk_options) const noexcept { + const bool ignore_garbage = + (options == base64_options::base64_url_accept_garbage) || + (options == base64_options::base64_default_accept_garbage); while (length > 0 && scalar::base64::is_ascii_white_space(input[length - 1])) { length--; @@ -37850,7 +38103,7 @@ simdutf_warn_unused result implementation::base64_to_binary( } } if (length == 0) { - if (equalsigns > 0) { + if (!ignore_garbage && equalsigns > 0) { return {INVALID_BASE64_CHARACTER, equallocation}; } return {SUCCESS, 0}; @@ -37858,7 +38111,7 @@ simdutf_warn_unused result implementation::base64_to_binary( result r = scalar::base64::base64_tail_decode( output, input, length, equalsigns, options, last_chunk_options); if (last_chunk_options != stop_before_partial && - r.error == error_code::SUCCESS && equalsigns > 0) { + r.error == error_code::SUCCESS && equalsigns > 0 && !ignore_garbage) { // additional checks if ((r.count % 3 == 0) || ((r.count % 3) + 1 + equalsigns != 4)) { return {INVALID_BASE64_CHARACTER, equallocation}; @@ -37870,6 +38123,9 @@ simdutf_warn_unused result implementation::base64_to_binary( simdutf_warn_unused full_result implementation::base64_to_binary_details( const char *input, size_t length, char *output, base64_options options, last_chunk_handling_options last_chunk_options) const noexcept { + const bool ignore_garbage = + (options == base64_options::base64_url_accept_garbage) || + (options == base64_options::base64_default_accept_garbage); while (length > 0 && scalar::base64::is_ascii_white_space(input[length - 1])) { length--; @@ -37892,7 +38148,7 @@ simdutf_warn_unused full_result implementation::base64_to_binary_details( } } if (length == 0) { - if (equalsigns > 0) { + if (!ignore_garbage && equalsigns > 0) { return {INVALID_BASE64_CHARACTER, equallocation, 0}; } return {SUCCESS, 0, 0}; @@ -37900,7 +38156,7 @@ simdutf_warn_unused full_result implementation::base64_to_binary_details( full_result r = scalar::base64::base64_tail_decode( output, input, length, equalsigns, options, last_chunk_options); if (last_chunk_options != stop_before_partial && - r.error == error_code::SUCCESS && equalsigns > 0) { + r.error == error_code::SUCCESS && equalsigns > 0 && !ignore_garbage) { // additional checks if ((r.output_count % 3 == 0) || ((r.output_count % 3) + 1 + equalsigns != 4)) { @@ -37918,6 +38174,9 @@ simdutf_warn_unused size_t implementation::maximal_binary_length_from_base64( simdutf_warn_unused result implementation::base64_to_binary( const char16_t *input, size_t length, char *output, base64_options options, last_chunk_handling_options last_chunk_options) const noexcept { + const bool ignore_garbage = + (options == base64_options::base64_url_accept_garbage) || + (options == base64_options::base64_default_accept_garbage); while (length > 0 && scalar::base64::is_ascii_white_space(input[length - 1])) { length--; @@ -37940,7 +38199,7 @@ simdutf_warn_unused result implementation::base64_to_binary( } } if (length == 0) { - if (equalsigns > 0) { + if (!ignore_garbage && equalsigns > 0) { return {INVALID_BASE64_CHARACTER, equallocation}; } return {SUCCESS, 0}; @@ -37948,7 +38207,7 @@ simdutf_warn_unused result implementation::base64_to_binary( result r = scalar::base64::base64_tail_decode( output, input, length, equalsigns, options, last_chunk_options); if (last_chunk_options != stop_before_partial && - r.error == error_code::SUCCESS && equalsigns > 0) { + r.error == error_code::SUCCESS && equalsigns > 0 && !ignore_garbage) { // additional checks if ((r.count % 3 == 0) || ((r.count % 3) + 1 + equalsigns != 4)) { return {INVALID_BASE64_CHARACTER, equallocation}; @@ -37960,6 +38219,9 @@ simdutf_warn_unused result implementation::base64_to_binary( simdutf_warn_unused full_result implementation::base64_to_binary_details( const char16_t *input, size_t length, char *output, base64_options options, last_chunk_handling_options last_chunk_options) const noexcept { + const bool ignore_garbage = + (options == base64_options::base64_url_accept_garbage) || + (options == base64_options::base64_default_accept_garbage); while (length > 0 && scalar::base64::is_ascii_white_space(input[length - 1])) { length--; @@ -37982,7 +38244,7 @@ simdutf_warn_unused full_result implementation::base64_to_binary_details( } } if (length == 0) { - if (equalsigns > 0) { + if (!ignore_garbage && equalsigns > 0) { return {INVALID_BASE64_CHARACTER, equallocation, 0}; } return {SUCCESS, 0, 0}; @@ -37990,7 +38252,7 @@ simdutf_warn_unused full_result implementation::base64_to_binary_details( full_result r = scalar::base64::base64_tail_decode( output, input, length, equalsigns, options, last_chunk_options); if (last_chunk_options != stop_before_partial && - r.error == error_code::SUCCESS && equalsigns > 0) { + r.error == error_code::SUCCESS && equalsigns > 0 && !ignore_garbage) { // additional checks if ((r.output_count % 3 == 0) || ((r.output_count % 3) + 1 + equalsigns != 4)) { @@ -40813,7 +41075,7 @@ struct block64 { __m128i chunks[4]; }; -template +template static inline uint16_t to_base64_mask(__m128i *src, uint32_t *error) { const __m128i ascii_space_tbl = _mm_setr_epi8(0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9, 0xa, 0x0, @@ -40878,7 +41140,7 @@ static inline uint16_t to_base64_mask(__m128i *src, uint32_t *error) { const __m128i chk = _mm_adds_epi8(_mm_shuffle_epi8(check_values, check_hash), *src); const int mask = _mm_movemask_epi8(chk); - if (mask) { + if (!ignore_garbage && mask) { __m128i ascii_space = _mm_cmpeq_epi8(_mm_shuffle_epi8(ascii_space_tbl, *src), *src); *error = (mask ^ _mm_movemask_epi8(ascii_space)); @@ -40887,18 +41149,24 @@ static inline uint16_t to_base64_mask(__m128i *src, uint32_t *error) { return (uint16_t)mask; } -template +template static inline uint64_t to_base64_mask(block64 *b, uint64_t *error) { uint32_t err0 = 0; uint32_t err1 = 0; uint32_t err2 = 0; uint32_t err3 = 0; - uint64_t m0 = to_base64_mask(&b->chunks[0], &err0); - uint64_t m1 = to_base64_mask(&b->chunks[1], &err1); - uint64_t m2 = to_base64_mask(&b->chunks[2], &err2); - uint64_t m3 = to_base64_mask(&b->chunks[3], &err3); - *error = (err0) | ((uint64_t)err1 << 16) | ((uint64_t)err2 << 32) | - ((uint64_t)err3 << 48); + uint64_t m0 = + to_base64_mask(&b->chunks[0], &err0); + uint64_t m1 = + to_base64_mask(&b->chunks[1], &err1); + uint64_t m2 = + to_base64_mask(&b->chunks[2], &err2); + uint64_t m3 = + to_base64_mask(&b->chunks[3], &err3); + if (!ignore_garbage) { + *error = (err0) | ((uint64_t)err1 << 16) | ((uint64_t)err2 << 32) | + ((uint64_t)err3 << 48); + } return m0 | (m1 << 16) | (m2 << 32) | (m3 << 48); } @@ -41011,7 +41279,7 @@ static inline void base64_decode_block_safe(char *out, block64 *b) { std::memcpy(out + 36, buffer, 12); } -template +template full_result compress_decode_base64(char *dst, const chartype *src, size_t srclen, base64_options options, @@ -41021,12 +41289,13 @@ compress_decode_base64(char *dst, const chartype *src, size_t srclen, size_t equallocation = srclen; // location of the first padding character if any // skip trailing spaces - while (srclen > 0 && scalar::base64::is_eight_byte(src[srclen - 1]) && + while (!ignore_garbage && srclen > 0 && + scalar::base64::is_eight_byte(src[srclen - 1]) && to_base64[uint8_t(src[srclen - 1])] == 64) { srclen--; } size_t equalsigns = 0; - if (srclen > 0 && src[srclen - 1] == '=') { + if (!ignore_garbage && srclen > 0 && src[srclen - 1] == '=') { equallocation = srclen - 1; srclen--; equalsigns = 1; @@ -41042,7 +41311,7 @@ compress_decode_base64(char *dst, const chartype *src, size_t srclen, } } if (srclen == 0) { - if (equalsigns > 0) { + if (!ignore_garbage && equalsigns > 0) { return {INVALID_BASE64_CHARACTER, equallocation, 0}; } return {SUCCESS, 0, 0}; @@ -41065,8 +41334,9 @@ compress_decode_base64(char *dst, const chartype *src, size_t srclen, load_block(&b, src); src += 64; uint64_t error = 0; - uint64_t badcharmask = to_base64_mask(&b, &error); - if (error) { + uint64_t badcharmask = + to_base64_mask(&b, &error); + if (error && !ignore_garbage) { src -= 64; size_t error_offset = simdutf_tzcnt_u64(error); return {error_code::INVALID_BASE64_CHARACTER, @@ -41114,7 +41384,8 @@ compress_decode_base64(char *dst, const chartype *src, size_t srclen, while ((bufferptr - buffer_start) % 64 != 0 && src < srcend) { uint8_t val = to_base64[uint8_t(*src)]; *bufferptr = char(val); - if (!scalar::base64::is_eight_byte(*src) || val > 64) { + if ((!scalar::base64::is_eight_byte(*src) || val > 64) && + !ignore_garbage) { return {error_code::INVALID_BASE64_CHARACTER, size_t(src - srcinit), size_t(dst - dstinit)}; } @@ -41160,8 +41431,14 @@ compress_decode_base64(char *dst, const chartype *src, size_t srclen, // backtrack int leftover = int(bufferptr - buffer_start); while (leftover > 0) { - while (to_base64[uint8_t(*(src - 1))] == 64) { - src--; + if (!ignore_garbage) { + while (to_base64[uint8_t(*(src - 1))] == 64) { + src--; + } + } else { + while (to_base64[uint8_t(*(src - 1))] >= 64) { + src--; + } } src--; leftover--; @@ -41178,7 +41455,7 @@ compress_decode_base64(char *dst, const chartype *src, size_t srclen, r.output_count += size_t(dst - dstinit); } if (last_chunk_options != stop_before_partial && - r.error == error_code::SUCCESS && equalsigns > 0) { + r.error == error_code::SUCCESS && equalsigns > 0 && !ignore_garbage) { // additional checks if ((r.output_count % 3 == 0) || ((r.output_count % 3) + 1 + equalsigns != 4)) { @@ -41188,7 +41465,7 @@ compress_decode_base64(char *dst, const chartype *src, size_t srclen, } return r; } - if (equalsigns > 0) { + if (equalsigns > 0 && !ignore_garbage) { if ((size_t(dst - dstinit) % 3 == 0) || ((size_t(dst - dstinit) % 3) + 1 + equalsigns != 4)) { return {INVALID_BASE64_CHARACTER, equallocation, size_t(dst - dstinit)}; @@ -43976,21 +44253,45 @@ simdutf_warn_unused size_t implementation::maximal_binary_length_from_base64( simdutf_warn_unused result implementation::base64_to_binary( const char *input, size_t length, char *output, base64_options options, last_chunk_handling_options last_chunk_options) const noexcept { - return (options & base64_url) - ? compress_decode_base64(output, input, length, options, - last_chunk_options) - : compress_decode_base64(output, input, length, options, - last_chunk_options); + if (options & base64_url) { + if (options == base64_options::base64_url_accept_garbage) { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } else { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } + } else { + if (options == base64_options::base64_default_accept_garbage) { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } else { + return compress_decode_base64(output, input, length, + options, last_chunk_options); + } + } } simdutf_warn_unused full_result implementation::base64_to_binary_details( const char *input, size_t length, char *output, base64_options options, last_chunk_handling_options last_chunk_options) const noexcept { - return (options & base64_url) - ? compress_decode_base64(output, input, length, options, - last_chunk_options) - : compress_decode_base64(output, input, length, options, - last_chunk_options); + if (options & base64_url) { + if (options == base64_options::base64_url_accept_garbage) { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } else { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } + } else { + if (options == base64_options::base64_default_accept_garbage) { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } else { + return compress_decode_base64(output, input, length, + options, last_chunk_options); + } + } } simdutf_warn_unused size_t implementation::maximal_binary_length_from_base64( @@ -44001,21 +44302,45 @@ simdutf_warn_unused size_t implementation::maximal_binary_length_from_base64( simdutf_warn_unused result implementation::base64_to_binary( const char16_t *input, size_t length, char *output, base64_options options, last_chunk_handling_options last_chunk_options) const noexcept { - return (options & base64_url) - ? compress_decode_base64(output, input, length, options, - last_chunk_options) - : compress_decode_base64(output, input, length, options, - last_chunk_options); + if (options & base64_url) { + if (options == base64_options::base64_url_accept_garbage) { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } else { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } + } else { + if (options == base64_options::base64_default_accept_garbage) { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } else { + return compress_decode_base64(output, input, length, + options, last_chunk_options); + } + } } simdutf_warn_unused full_result implementation::base64_to_binary_details( const char16_t *input, size_t length, char *output, base64_options options, last_chunk_handling_options last_chunk_options) const noexcept { - return (options & base64_url) - ? compress_decode_base64(output, input, length, options, - last_chunk_options) - : compress_decode_base64(output, input, length, options, - last_chunk_options); + if (options & base64_url) { + if (options == base64_options::base64_url_accept_garbage) { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } else { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } + } else { + if (options == base64_options::base64_default_accept_garbage) { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } else { + return compress_decode_base64(output, input, length, + options, last_chunk_options); + } + } } simdutf_warn_unused size_t implementation::base64_length_from_binary( @@ -46960,7 +47285,7 @@ static inline void base64_decode_block_safe(char *out, block64 *b) { base64_decode_block(out, b); } -template +template full_result compress_decode_base64(char *dst, const char_type *src, size_t srclen, base64_options options, @@ -46991,7 +47316,7 @@ compress_decode_base64(char *dst, const char_type *src, size_t srclen, } } if (srclen == 0) { - if (equalsigns > 0) { + if (!ignore_garbage && equalsigns > 0) { return {INVALID_BASE64_CHARACTER, equallocation, 0}; } return {SUCCESS, 0, 0}; @@ -47012,7 +47337,7 @@ compress_decode_base64(char *dst, const char_type *src, size_t srclen, bool error = false; uint64_t badcharmask = to_base64_mask(&b, &error); if (badcharmask) { - if (error) { + if (error && !ignore_garbage) { src -= 64; while (src < srcend && scalar::base64::is_eight_byte(*src) && to_base64[uint8_t(*src)] <= 64) { @@ -47056,7 +47381,8 @@ compress_decode_base64(char *dst, const char_type *src, size_t srclen, while ((bufferptr - buffer_start) % 64 != 0 && src < srcend) { uint8_t val = to_base64[uint8_t(*src)]; *bufferptr = char(val); - if (!scalar::base64::is_eight_byte(*src) || val > 64) { + if ((!scalar::base64::is_eight_byte(*src) || val > 64) && + !ignore_garbage) { return {error_code::INVALID_BASE64_CHARACTER, size_t(src - srcinit), size_t(dst - dstinit)}; } @@ -47098,8 +47424,14 @@ compress_decode_base64(char *dst, const char_type *src, size_t srclen, // backtrack int leftover = int(bufferptr - buffer_start); while (leftover > 0) { - while (to_base64[uint8_t(*(src - 1))] == 64) { - src--; + if (!ignore_garbage) { + while (to_base64[uint8_t(*(src - 1))] == 64) { + src--; + } + } else { + while (to_base64[uint8_t(*(src - 1))] >= 64) { + src--; + } } src--; leftover--; @@ -47116,7 +47448,7 @@ compress_decode_base64(char *dst, const char_type *src, size_t srclen, r.output_count += size_t(dst - dstinit); } if (last_chunk_options != stop_before_partial && - r.error == error_code::SUCCESS && equalsigns > 0) { + r.error == error_code::SUCCESS && equalsigns > 0 && !ignore_garbage) { // additional checks if ((r.output_count % 3 == 0) || ((r.output_count % 3) + 1 + equalsigns != 4)) { @@ -47126,7 +47458,7 @@ compress_decode_base64(char *dst, const char_type *src, size_t srclen, } return r; } - if (equalsigns > 0) { + if (equalsigns > 0 && !ignore_garbage) { if ((size_t(dst - dstinit) % 3 == 0) || ((size_t(dst - dstinit) % 3) + 1 + equalsigns != 4)) { return {INVALID_BASE64_CHARACTER, equallocation, size_t(dst - dstinit)}; @@ -49864,21 +50196,45 @@ simdutf_warn_unused size_t implementation::maximal_binary_length_from_base64( simdutf_warn_unused result implementation::base64_to_binary( const char *input, size_t length, char *output, base64_options options, last_chunk_handling_options last_chunk_options) const noexcept { - return (options & base64_url) - ? compress_decode_base64(output, input, length, options, - last_chunk_options) - : compress_decode_base64(output, input, length, options, - last_chunk_options); + if (options & base64_url) { + if (options == base64_options::base64_url_accept_garbage) { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } else { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } + } else { + if (options == base64_options::base64_default_accept_garbage) { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } else { + return compress_decode_base64(output, input, length, + options, last_chunk_options); + } + } } simdutf_warn_unused full_result implementation::base64_to_binary_details( const char *input, size_t length, char *output, base64_options options, last_chunk_handling_options last_chunk_options) const noexcept { - return (options & base64_url) - ? compress_decode_base64(output, input, length, options, - last_chunk_options) - : compress_decode_base64(output, input, length, options, - last_chunk_options); + if (options & base64_url) { + if (options == base64_options::base64_url_accept_garbage) { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } else { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } + } else { + if (options == base64_options::base64_default_accept_garbage) { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } else { + return compress_decode_base64(output, input, length, + options, last_chunk_options); + } + } } simdutf_warn_unused size_t implementation::maximal_binary_length_from_base64( @@ -49889,21 +50245,45 @@ simdutf_warn_unused size_t implementation::maximal_binary_length_from_base64( simdutf_warn_unused result implementation::base64_to_binary( const char16_t *input, size_t length, char *output, base64_options options, last_chunk_handling_options last_chunk_options) const noexcept { - return (options & base64_url) - ? compress_decode_base64(output, input, length, options, - last_chunk_options) - : compress_decode_base64(output, input, length, options, - last_chunk_options); + if (options & base64_url) { + if (options == base64_options::base64_url_accept_garbage) { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } else { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } + } else { + if (options == base64_options::base64_default_accept_garbage) { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } else { + return compress_decode_base64(output, input, length, + options, last_chunk_options); + } + } } simdutf_warn_unused full_result implementation::base64_to_binary_details( const char16_t *input, size_t length, char *output, base64_options options, last_chunk_handling_options last_chunk_options) const noexcept { - return (options & base64_url) - ? compress_decode_base64(output, input, length, options, - last_chunk_options) - : compress_decode_base64(output, input, length, options, - last_chunk_options); + if (options & base64_url) { + if (options == base64_options::base64_url_accept_garbage) { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } else { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } + } else { + if (options == base64_options::base64_default_accept_garbage) { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } else { + return compress_decode_base64(output, input, length, + options, last_chunk_options); + } + } } simdutf_warn_unused size_t implementation::base64_length_from_binary( @@ -53234,7 +53614,7 @@ static inline void base64_decode_block_safe(char *out, block64 *b) { std::memcpy(out + 24, buffer, 24); } -template +template full_result compress_decode_base64(char *dst, const chartype *src, size_t srclen, base64_options options, @@ -53265,7 +53645,7 @@ compress_decode_base64(char *dst, const chartype *src, size_t srclen, } } if (srclen == 0) { - if (equalsigns > 0) { + if (!ignore_garbage && equalsigns > 0) { return {INVALID_BASE64_CHARACTER, equallocation, 0}; } return {SUCCESS, 0, 0}; @@ -53289,7 +53669,7 @@ compress_decode_base64(char *dst, const chartype *src, size_t srclen, src += 64; bool error = false; uint64_t badcharmask = to_base64_mask(&b, &error); - if (error) { + if (error && !ignore_garbage) { src -= 64; while (src < srcend && scalar::base64::is_eight_byte(*src) && to_base64[uint8_t(*src)] <= 64) { @@ -53341,7 +53721,8 @@ compress_decode_base64(char *dst, const chartype *src, size_t srclen, while ((bufferptr - buffer_start) % 64 != 0 && src < srcend) { uint8_t val = to_base64[uint8_t(*src)]; *bufferptr = char(val); - if (!scalar::base64::is_eight_byte(*src) || val > 64) { + if ((!scalar::base64::is_eight_byte(*src) || val > 64) && + !ignore_garbage) { return {error_code::INVALID_BASE64_CHARACTER, size_t(src - srcinit), size_t(dst - dstinit)}; } @@ -53387,8 +53768,14 @@ compress_decode_base64(char *dst, const chartype *src, size_t srclen, // backtrack int leftover = int(bufferptr - buffer_start); while (leftover > 0) { - while (to_base64[uint8_t(*(src - 1))] == 64) { - src--; + if (!ignore_garbage) { + while (to_base64[uint8_t(*(src - 1))] == 64) { + src--; + } + } else { + while (to_base64[uint8_t(*(src - 1))] >= 64) { + src--; + } } src--; leftover--; @@ -53405,7 +53792,7 @@ compress_decode_base64(char *dst, const chartype *src, size_t srclen, r.output_count += size_t(dst - dstinit); } if (last_chunk_options != stop_before_partial && - r.error == error_code::SUCCESS && equalsigns > 0) { + r.error == error_code::SUCCESS && equalsigns > 0 && !ignore_garbage) { // additional checks if ((r.output_count % 3 == 0) || ((r.output_count % 3) + 1 + equalsigns != 4)) { @@ -53415,7 +53802,7 @@ compress_decode_base64(char *dst, const chartype *src, size_t srclen, } return r; } - if (equalsigns > 0) { + if (equalsigns > 0 && !ignore_garbage) { if ((size_t(dst - dstinit) % 3 == 0) || ((size_t(dst - dstinit) % 3) + 1 + equalsigns != 4)) { return {INVALID_BASE64_CHARACTER, equallocation, size_t(dst - dstinit)}; @@ -56273,21 +56660,45 @@ simdutf_warn_unused size_t implementation::maximal_binary_length_from_base64( simdutf_warn_unused result implementation::base64_to_binary( const char *input, size_t length, char *output, base64_options options, last_chunk_handling_options last_chunk_options) const noexcept { - return (options & base64_url) - ? compress_decode_base64(output, input, length, options, - last_chunk_options) - : compress_decode_base64(output, input, length, options, - last_chunk_options); + if (options & base64_url) { + if (options == base64_options::base64_url_accept_garbage) { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } else { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } + } else { + if (options == base64_options::base64_default_accept_garbage) { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } else { + return compress_decode_base64(output, input, length, + options, last_chunk_options); + } + } } simdutf_warn_unused full_result implementation::base64_to_binary_details( const char *input, size_t length, char *output, base64_options options, last_chunk_handling_options last_chunk_options) const noexcept { - return (options & base64_url) - ? compress_decode_base64(output, input, length, options, - last_chunk_options) - : compress_decode_base64(output, input, length, options, - last_chunk_options); + if (options & base64_url) { + if (options == base64_options::base64_url_accept_garbage) { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } else { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } + } else { + if (options == base64_options::base64_default_accept_garbage) { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } else { + return compress_decode_base64(output, input, length, + options, last_chunk_options); + } + } } simdutf_warn_unused size_t implementation::maximal_binary_length_from_base64( @@ -56298,21 +56709,45 @@ simdutf_warn_unused size_t implementation::maximal_binary_length_from_base64( simdutf_warn_unused result implementation::base64_to_binary( const char16_t *input, size_t length, char *output, base64_options options, last_chunk_handling_options last_chunk_options) const noexcept { - return (options & base64_url) - ? compress_decode_base64(output, input, length, options, - last_chunk_options) - : compress_decode_base64(output, input, length, options, - last_chunk_options); + if (options & base64_url) { + if (options == base64_options::base64_url_accept_garbage) { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } else { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } + } else { + if (options == base64_options::base64_default_accept_garbage) { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } else { + return compress_decode_base64(output, input, length, + options, last_chunk_options); + } + } } simdutf_warn_unused full_result implementation::base64_to_binary_details( const char16_t *input, size_t length, char *output, base64_options options, last_chunk_handling_options last_chunk_options) const noexcept { - return (options & base64_url) - ? compress_decode_base64(output, input, length, options, - last_chunk_options) - : compress_decode_base64(output, input, length, options, - last_chunk_options); + if (options & base64_url) { + if (options == base64_options::base64_url_accept_garbage) { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } else { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } + } else { + if (options == base64_options::base64_default_accept_garbage) { + return compress_decode_base64(output, input, length, options, + last_chunk_options); + } else { + return compress_decode_base64(output, input, length, + options, last_chunk_options); + } + } } simdutf_warn_unused size_t implementation::base64_length_from_binary( diff --git a/deps/simdutf/simdutf.h b/deps/simdutf/simdutf.h index 2d984f40e7bc3f..383687215b010c 100644 --- a/deps/simdutf/simdutf.h +++ b/deps/simdutf/simdutf.h @@ -1,4 +1,4 @@ -/* auto-generated on 2024-12-10 14:54:53 -0500. Do not edit! */ +/* auto-generated on 2024-12-17 14:54:59 -0500. Do not edit! */ /* begin file include/simdutf.h */ #ifndef SIMDUTF_H #define SIMDUTF_H @@ -675,7 +675,7 @@ SIMDUTF_DISABLE_UNDESIRED_WARNINGS #define SIMDUTF_SIMDUTF_VERSION_H /** The version of simdutf being used (major.minor.revision) */ -#define SIMDUTF_VERSION "5.6.4" +#define SIMDUTF_VERSION "5.7.0" namespace simdutf { enum { @@ -686,11 +686,11 @@ enum { /** * The minor version (major.MINOR.revision) of simdutf being used. */ - SIMDUTF_VERSION_MINOR = 6, + SIMDUTF_VERSION_MINOR = 7, /** * The revision (major.minor.REVISION) of simdutf being used. */ - SIMDUTF_VERSION_REVISION = 4 + SIMDUTF_VERSION_REVISION = 0 }; } // namespace simdutf @@ -2702,6 +2702,9 @@ simdutf_warn_unused size_t trim_partial_utf16(const char16_t *input, size_t length); // base64_options are used to specify the base64 encoding options. +// ASCII spaces are ' ', '\t', '\n', '\r', '\f' +// garbage characters are characters that are not part of the base64 alphabet +// nor ASCII spaces. enum base64_options : uint64_t { base64_default = 0, /* standard base64 format (with padding) */ base64_url = 1, /* base64url format (no padding) */ @@ -2711,6 +2714,10 @@ enum base64_options : uint64_t { base64_reverse_padding, /* standard base64 format without padding */ base64_url_with_padding = base64_url | base64_reverse_padding, /* base64url with padding */ + base64_default_accept_garbage = + 4, /* standard base64 format accepting garbage characters */ + base64_url_accept_garbage = + 5, /* base64url format accepting garbage characters */ }; // last_chunk_handling_options are used to specify the handling of the last From 8319dc6bc57a7aa366d71fafb47a4d8eba5e161e Mon Sep 17 00:00:00 2001 From: "Node.js GitHub Bot" Date: Mon, 23 Dec 2024 19:59:16 -0500 Subject: [PATCH 022/205] deps: update ngtcp2 to 1.10.0 PR-URL: https://github.com/nodejs/node/pull/56334 Reviewed-By: Luigi Pinca Reviewed-By: Rafael Gonzaga --- deps/ngtcp2/ngtcp2/lib/includes/ngtcp2/ngtcp2.h | 4 +++- deps/ngtcp2/ngtcp2/lib/includes/ngtcp2/version.h | 4 ++-- deps/ngtcp2/ngtcp2/lib/ngtcp2_conn.c | 3 ++- deps/ngtcp2/ngtcp2/lib/ngtcp2_map.c | 4 ++-- deps/ngtcp2/ngtcp2/lib/ngtcp2_rtb.c | 15 +++++---------- 5 files changed, 14 insertions(+), 16 deletions(-) diff --git a/deps/ngtcp2/ngtcp2/lib/includes/ngtcp2/ngtcp2.h b/deps/ngtcp2/ngtcp2/lib/includes/ngtcp2/ngtcp2.h index acc79be6e0b375..87976b1444b95d 100644 --- a/deps/ngtcp2/ngtcp2/lib/includes/ngtcp2/ngtcp2.h +++ b/deps/ngtcp2/ngtcp2/lib/includes/ngtcp2/ngtcp2.h @@ -1471,7 +1471,9 @@ typedef struct ngtcp2_transport_params { uint64_t max_udp_payload_size; /** * :member:`active_connection_id_limit` is the maximum number of - * Connection ID that sender can store. + * Connection ID that sender can store. If specified, it must be in + * the range of [:macro:`NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT`, + * 8], inclusive. */ uint64_t active_connection_id_limit; /** diff --git a/deps/ngtcp2/ngtcp2/lib/includes/ngtcp2/version.h b/deps/ngtcp2/ngtcp2/lib/includes/ngtcp2/version.h index e9e7f9bf86e742..20c4ac24d2ebcd 100644 --- a/deps/ngtcp2/ngtcp2/lib/includes/ngtcp2/version.h +++ b/deps/ngtcp2/ngtcp2/lib/includes/ngtcp2/version.h @@ -36,7 +36,7 @@ * * Version number of the ngtcp2 library release. */ -#define NGTCP2_VERSION "1.9.1" +#define NGTCP2_VERSION "1.10.0" /** * @macro @@ -46,6 +46,6 @@ * number, 8 bits for minor and 8 bits for patch. Version 1.2.3 * becomes 0x010203. */ -#define NGTCP2_VERSION_NUM 0x010901 +#define NGTCP2_VERSION_NUM 0x010a00 #endif /* !defined(NGTCP2_VERSION_H) */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn.c index 8b60efabe126d0..765e4a877e00d7 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn.c @@ -11739,7 +11739,8 @@ static ngtcp2_ssize conn_write_vmsg_wrapper(ngtcp2_conn *conn, if (cstat->bytes_in_flight >= cstat->cwnd) { conn->rst.is_cwnd_limited = 1; - } else if ((cstat->cwnd >= cstat->ssthresh || + } else if (conn->rst.app_limited == 0 && + (cstat->cwnd >= cstat->ssthresh || cstat->bytes_in_flight * 2 < cstat->cwnd) && nwrite == 0 && conn_pacing_pkt_tx_allowed(conn, ts) && (conn->flags & NGTCP2_CONN_FLAG_HANDSHAKE_COMPLETED)) { diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_map.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_map.c index 9eb102f16b32e2..0b66fceac6c993 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_map.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_map.c @@ -31,7 +31,7 @@ #include "ngtcp2_conv.h" -#define NGTCP2_INITIAL_TABLE_LENBITS 4 +#define NGTCP2_INITIAL_HASHBITS 4 void ngtcp2_map_init(ngtcp2_map *map, const ngtcp2_mem *mem) { map->mem = mem; @@ -196,7 +196,7 @@ int ngtcp2_map_insert(ngtcp2_map *map, ngtcp2_map_key_type key, void *data) { return rv; } } else { - rv = map_resize(map, NGTCP2_INITIAL_TABLE_LENBITS); + rv = map_resize(map, NGTCP2_INITIAL_HASHBITS); if (rv != 0) { return rv; } diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_rtb.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_rtb.c index 4d417186e15854..090355f5dbc938 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_rtb.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_rtb.c @@ -249,9 +249,12 @@ static ngtcp2_ssize rtb_reclaim_frame(ngtcp2_rtb *rtb, uint8_t flags, if (!fr->stream.fin) { /* 0 length STREAM frame with offset == 0 must be retransmitted if no non-empty data are sent to this - stream, and no data in this stream are acknowledged. */ + stream, fin flag is not set, and no data in this stream + are acknowledged. */ if (fr->stream.offset != 0 || fr->stream.datacnt != 0 || - strm->tx.offset || (strm->flags & NGTCP2_STRM_FLAG_ANY_ACKED)) { + strm->tx.offset || + (strm->flags & + (NGTCP2_STRM_FLAG_SHUT_WR | NGTCP2_STRM_FLAG_ANY_ACKED))) { continue; } } else if (strm->flags & NGTCP2_STRM_FLAG_FIN_ACKED) { @@ -1284,14 +1287,6 @@ static int rtb_on_pkt_lost_resched_move(ngtcp2_rtb *rtb, ngtcp2_conn *conn, return 0; } - if (ent->flags & NGTCP2_RTB_ENTRY_FLAG_PMTUD_PROBE) { - ngtcp2_log_info(rtb->log, NGTCP2_LOG_EVENT_LDC, - "pkn=%" PRId64 - " is a PMTUD probe packet, no retransmission is necessary", - ent->hd.pkt_num); - return 0; - } - if (ent->flags & NGTCP2_RTB_ENTRY_FLAG_LOST_RETRANSMITTED) { --rtb->num_lost_pkts; From 6ae9950f083663ab33083569595f94e5fac182a7 Mon Sep 17 00:00:00 2001 From: Yiyun Lei Date: Tue, 31 Oct 2023 01:08:25 -0400 Subject: [PATCH 023/205] test: migrate message eval tests from Python to JS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Migrate the eval tests in the `test/message` folder from Python to JS. PR-URL: https://github.com/nodejs/node/pull/50482 Reviewed-By: Juan José Arboleda --- .../eval}/eval_messages.js | 2 +- test/fixtures/eval/eval_messages.snapshot | 76 ++++++++++++++++ .../eval}/stdin_messages.js | 2 +- test/fixtures/eval/stdin_messages.snapshot | 89 +++++++++++++++++++ test/message/eval_messages.out | 77 ---------------- test/message/stdin_messages.out | 89 ------------------- test/parallel/test-node-output-eval.mjs | 34 +++++++ 7 files changed, 201 insertions(+), 168 deletions(-) rename test/{message => fixtures/eval}/eval_messages.js (98%) create mode 100644 test/fixtures/eval/eval_messages.snapshot rename test/{message => fixtures/eval}/stdin_messages.js (98%) create mode 100644 test/fixtures/eval/stdin_messages.snapshot delete mode 100644 test/message/eval_messages.out delete mode 100644 test/message/stdin_messages.out create mode 100644 test/parallel/test-node-output-eval.mjs diff --git a/test/message/eval_messages.js b/test/fixtures/eval/eval_messages.js similarity index 98% rename from test/message/eval_messages.js rename to test/fixtures/eval/eval_messages.js index 69dcbd6efa23a7..171bff06b8d6e9 100644 --- a/test/message/eval_messages.js +++ b/test/fixtures/eval/eval_messages.js @@ -21,7 +21,7 @@ 'use strict'; -require('../common'); +require('../../common'); const spawn = require('child_process').spawn; diff --git a/test/fixtures/eval/eval_messages.snapshot b/test/fixtures/eval/eval_messages.snapshot new file mode 100644 index 00000000000000..6a37ad22634617 --- /dev/null +++ b/test/fixtures/eval/eval_messages.snapshot @@ -0,0 +1,76 @@ +[eval] +[eval]:1 +with(this){__filename} +^^^^ + +SyntaxError: Strict mode code may not include a with statement + + + + + + + +Node.js * +42 +42 +[eval]:1 +throw new Error("hello") +^ + +Error: hello + + + + + + + + +Node.js * +[eval]:1 +throw new Error("hello") +^ + +Error: hello + + + + + + + + +Node.js * +100 +[eval]:1 +var x = 100; y = x; + ^ + +ReferenceError: y is not defined + + + + + + + + +Node.js * + +[eval]:1 +var ______________________________________________; throw 10 + ^ +10 +(Use `node --trace-uncaught ...` to show where the exception was thrown) + +Node.js * + +[eval]:1 +var ______________________________________________; throw 10 + ^ +10 +(Use `node --trace-uncaught ...` to show where the exception was thrown) + +Node.js * +done diff --git a/test/message/stdin_messages.js b/test/fixtures/eval/stdin_messages.js similarity index 98% rename from test/message/stdin_messages.js rename to test/fixtures/eval/stdin_messages.js index 79475bd4d217b6..874b473be38e00 100644 --- a/test/message/stdin_messages.js +++ b/test/fixtures/eval/stdin_messages.js @@ -21,7 +21,7 @@ 'use strict'; -require('../common'); +require('../../common'); const spawn = require('child_process').spawn; diff --git a/test/fixtures/eval/stdin_messages.snapshot b/test/fixtures/eval/stdin_messages.snapshot new file mode 100644 index 00000000000000..3c03bd64072061 --- /dev/null +++ b/test/fixtures/eval/stdin_messages.snapshot @@ -0,0 +1,89 @@ +[stdin] +[stdin]:1 +with(this){__filename} +^^^^ + +SyntaxError: Strict mode code may not include a with statement + + + + + + + + + + + +Node.js * +42 +42 +[stdin]:1 +throw new Error("hello") +^ + +Error: hello + + + + + + + + + + + +Node.js * +[stdin]:1 +throw new Error("hello") +^ + +Error: hello + + + + + + + + + + + +Node.js * +100 +[stdin]:1 +let x = 100; y = x; + ^ + +ReferenceError: y is not defined + + + + + + + + + + + +Node.js * + +[stdin]:1 +let ______________________________________________; throw 10 + ^ +10 +(Use `node --trace-uncaught ...` to show where the exception was thrown) + +Node.js * + +[stdin]:1 +let ______________________________________________; throw 10 + ^ +10 +(Use `node --trace-uncaught ...` to show where the exception was thrown) + +Node.js * +done diff --git a/test/message/eval_messages.out b/test/message/eval_messages.out deleted file mode 100644 index e07bbe4d6acd3c..00000000000000 --- a/test/message/eval_messages.out +++ /dev/null @@ -1,77 +0,0 @@ -[eval] -[eval]:1 -with(this){__filename} -^^^^ - -SyntaxError: Strict mode code may not include a with statement - at makeContextifyScript (node:internal/vm:*:*) - at node:internal/process/execution:*:* - at [eval]-wrapper:*:* - at runScript (node:internal/process/execution:*:*) - at evalScript (node:internal/process/execution:*:*) - at node:internal/main/eval_string:*:* - -Node.js * -42 -42 -[eval]:1 -throw new Error("hello") -^ - -Error: hello - at [eval]:1:7 - at runScriptInThisContext (node:internal/vm:*:*) - at node:internal/process/execution:*:* - at [eval]-wrapper:*:* - at runScript (node:internal/process/execution:*:*) - at evalScript (node:internal/process/execution:*:*) - at node:internal/main/eval_string:*:* - -Node.js * - -[eval]:1 -throw new Error("hello") -^ - -Error: hello - at [eval]:1:7 - at runScriptInThisContext (node:internal/vm:*:*) - at node:internal/process/execution:*:* - at [eval]-wrapper:*:* - at runScript (node:internal/process/execution:*:*) - at evalScript (node:internal/process/execution:*:*) - at node:internal/main/eval_string:*:* - -Node.js * -100 -[eval]:1 -var x = 100; y = x; - ^ - -ReferenceError: y is not defined - at [eval]:1:16 - at runScriptInThisContext (node:internal/vm:*:*) - at node:internal/process/execution:*:* - at [eval]-wrapper:*:* - at runScript (node:internal/process/execution:*:*) - at evalScript (node:internal/process/execution:*:*) - at node:internal/main/eval_string:*:* - -Node.js * - -[eval]:1 -var ______________________________________________; throw 10 - ^ -10 -(Use `* --trace-uncaught ...` to show where the exception was thrown) - -Node.js * - -[eval]:1 -var ______________________________________________; throw 10 - ^ -10 -(Use `* --trace-uncaught ...` to show where the exception was thrown) - -Node.js * -done diff --git a/test/message/stdin_messages.out b/test/message/stdin_messages.out deleted file mode 100644 index 6afc8a62d7fcd9..00000000000000 --- a/test/message/stdin_messages.out +++ /dev/null @@ -1,89 +0,0 @@ -[stdin] -[stdin]:1 -with(this){__filename} -^^^^ - -SyntaxError: Strict mode code may not include a with statement - at makeContextifyScript (node:internal/vm:*:*) - at node:internal/process/execution:*:* - at [stdin]-wrapper:*:* - at runScript (node:internal/process/execution:*:*) - at evalScript (node:internal/process/execution:*:*) - at node:internal/main/eval_stdin:*:* - at Socket. (node:internal/process/execution:*:*) - at Socket.emit (node:events:*:*) - at endReadableNT (node:internal/streams/readable:*:*) - at process.processTicksAndRejections (node:internal/process/task_queues:*:*) - -Node.js * -42 -42 -[stdin]:1 -throw new Error("hello") -^ - -Error: hello - at [stdin]:1:7 - at runScriptInThisContext (node:internal/vm:*:*) - at node:internal/process/execution:*:* - at [stdin]-wrapper:*:* - at runScript (node:internal/process/execution:*:*) - at evalScript (node:internal/process/execution:*:*) - at node:internal/main/eval_stdin:*:* - at Socket. (node:internal/process/execution:*:*) - at Socket.emit (node:events:*:*) - at endReadableNT (node:internal/streams/readable:*:*) - -Node.js * -[stdin]:1 -throw new Error("hello") -^ - -Error: hello - at [stdin]:1:* - at runScriptInThisContext (node:internal/vm:*:*) - at node:internal/process/execution:*:* - at [stdin]-wrapper:*:* - at runScript (node:internal/process/execution:*:*) - at evalScript (node:internal/process/execution:*:*) - at node:internal/main/eval_stdin:*:* - at Socket. (node:internal/process/execution:*:*) - at Socket.emit (node:events:*:*) - at endReadableNT (node:internal/streams/readable:*:*) - -Node.js * -100 -[stdin]:1 -let x = 100; y = x; - ^ - -ReferenceError: y is not defined - at [stdin]:1:16 - at runScriptInThisContext (node:internal/vm:*:*) - at node:internal/process/execution:*:* - at [stdin]-wrapper:*:* - at runScript (node:internal/process/execution:*:*) - at evalScript (node:internal/process/execution:*:*) - at node:internal/main/eval_stdin:*:* - at Socket. (node:internal/process/execution:*:*) - at Socket.emit (node:events:*:*) - at endReadableNT (node:internal/streams/readable:*:*) - -Node.js * - -[stdin]:1 -let ______________________________________________; throw 10 - ^ -10 -(Use `* --trace-uncaught ...` to show where the exception was thrown) - -Node.js * - -[stdin]:1 -let ______________________________________________; throw 10 - ^ -10 -(Use `* --trace-uncaught ...` to show where the exception was thrown) - -Node.js * -done diff --git a/test/parallel/test-node-output-eval.mjs b/test/parallel/test-node-output-eval.mjs new file mode 100644 index 00000000000000..2fa60206e1ea1c --- /dev/null +++ b/test/parallel/test-node-output-eval.mjs @@ -0,0 +1,34 @@ +import '../common/index.mjs'; +import * as fixtures from '../common/fixtures.mjs'; +import * as snapshot from '../common/assertSnapshot.js'; +import { describe, it } from 'node:test'; + +describe('eval output', { concurrency: true }, () => { + function normalize(str) { + return str.replaceAll(snapshot.replaceWindowsPaths(process.cwd()), '') + .replaceAll(/\d+:\d+/g, '*:*'); + } + + const defaultTransform = snapshot.transform( + removeStackTraces, + normalize, + snapshot.replaceWindowsLineEndings, + snapshot.replaceWindowsPaths, + snapshot.replaceNodeVersion + ); + + function removeStackTraces(output) { + return output.replaceAll(/^ *at .+$/gm, ''); + } + + const tests = [ + { name: 'eval/eval_messages.js' }, + { name: 'eval/stdin_messages.js' }, + ]; + + for (const { name } of tests) { + it(name, async () => { + await snapshot.spawnAndAssert(fixtures.path(name), defaultTransform); + }); + } +}); From 8ffeb8b58c99ec13fbeaa779a36bcba8a471117c Mon Sep 17 00:00:00 2001 From: Michael Dawson Date: Tue, 10 Dec 2024 23:16:06 +0000 Subject: [PATCH 024/205] test: increase spin for eventloop test on s390 It was excluded as it was failing intermittently. Likely that s390 was just so fast times were rounded down to 0. Increase the spin time on s390x only. Signed-off-by: Michael Dawson PR-URL: https://github.com/nodejs/node/pull/56228 Refs: https://github.com/nodejs/node/issues/41286 Reviewed-By: Luigi Pinca Reviewed-By: James M Snell Reviewed-By: Marco Ippolito --- test/sequential/sequential.status | 4 ---- test/sequential/test-performance-eventloopdelay.js | 5 +++++ 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/test/sequential/sequential.status b/test/sequential/sequential.status index 5f4445416d95fa..67f17fec1102f0 100644 --- a/test/sequential/sequential.status +++ b/test/sequential/sequential.status @@ -48,7 +48,3 @@ test-tls-securepair-client: PASS, FLAKY [$arch==arm] # https://github.com/nodejs/node/issues/49933 test-watch-mode-inspect: SKIP - -[$arch==s390x] -# https://github.com/nodejs/node/issues/41286 -test-performance-eventloopdelay: PASS, FLAKY diff --git a/test/sequential/test-performance-eventloopdelay.js b/test/sequential/test-performance-eventloopdelay.js index 0bc1758113e480..0d38300d7b3a15 100644 --- a/test/sequential/test-performance-eventloopdelay.js +++ b/test/sequential/test-performance-eventloopdelay.js @@ -3,6 +3,7 @@ const common = require('../common'); const assert = require('assert'); +const os = require('os'); const { monitorEventLoopDelay } = require('perf_hooks'); @@ -51,9 +52,13 @@ const { sleep } = require('internal/util'); } { + const s390x = os.arch() === 's390x'; const histogram = monitorEventLoopDelay({ resolution: 1 }); histogram.enable(); let m = 5; + if (s390x) { + m = m * 2; + } function spinAWhile() { sleep(1000); if (--m > 0) { From ca6ed2190c534448e67eb36e0aefb66090ab076e Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Tue, 24 Dec 2024 20:19:12 +0100 Subject: [PATCH 025/205] test: skip `test-sqlite-extensions` when SQLite is not built by us MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/56341 Reviewed-By: Luigi Pinca Reviewed-By: Michaël Zasso --- test/sqlite/test-sqlite-extensions.mjs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/sqlite/test-sqlite-extensions.mjs b/test/sqlite/test-sqlite-extensions.mjs index 0e0acf2dc33d30..141f9c9627002c 100644 --- a/test/sqlite/test-sqlite-extensions.mjs +++ b/test/sqlite/test-sqlite-extensions.mjs @@ -7,6 +7,10 @@ import test from 'node:test'; import fs from 'node:fs'; import childProcess from 'child_process'; +if (process.config.variables.node_shared_sqlite) { + common.skip('Missing libsqlite_extension binary'); +} + // Lib extension binary is named differently on different platforms function resolveBuiltBinary(binary) { const targetFile = fs.readdirSync(path.dirname(process.execPath)).find((file) => file.startsWith(binary)); From 0f7aed8a59178a9756f2b66da35c774fa08681bd Mon Sep 17 00:00:00 2001 From: Kevin Toshihiro Uehara Date: Tue, 24 Dec 2024 17:53:53 -0300 Subject: [PATCH 026/205] doc: fix the `crc32` documentation PR-URL: https://github.com/nodejs/node/pull/55898 Fixes: https://github.com/nodejs/node/issues/55800 Reviewed-By: Luigi Pinca Reviewed-By: Antoine du Hamel --- doc/api/zlib.md | 122 ++++++++++++++++++++++++------------------------ 1 file changed, 61 insertions(+), 61 deletions(-) diff --git a/doc/api/zlib.md b/doc/api/zlib.md index 2d3ea8050f230b..db4b81e9cede89 100644 --- a/doc/api/zlib.md +++ b/doc/api/zlib.md @@ -926,67 +926,6 @@ The `zlib.bytesWritten` property specifies the number of bytes written to the engine, before the bytes are processed (compressed or decompressed, as appropriate for the derived class). -### `zlib.crc32(data[, value])` - - - -* `data` {string|Buffer|TypedArray|DataView} When `data` is a string, - it will be encoded as UTF-8 before being used for computation. -* `value` {integer} An optional starting value. It must be a 32-bit unsigned - integer. **Default:** `0` -* Returns: {integer} A 32-bit unsigned integer containing the checksum. - -Computes a 32-bit [Cyclic Redundancy Check][] checksum of `data`. If -`value` is specified, it is used as the starting value of the checksum, -otherwise, 0 is used as the starting value. - -The CRC algorithm is designed to compute checksums and to detect error -in data transmission. It's not suitable for cryptographic authentication. - -To be consistent with other APIs, if the `data` is a string, it will -be encoded with UTF-8 before being used for computation. If users only -use Node.js to compute and match the checksums, this works well with -other APIs that uses the UTF-8 encoding by default. - -Some third-party JavaScript libraries compute the checksum on a -string based on `str.charCodeAt()` so that it can be run in browsers. -If users want to match the checksum computed with this kind of library -in the browser, it's better to use the same library in Node.js -if it also runs in Node.js. If users have to use `zlib.crc32()` to -match the checksum produced by such a third-party library: - -1. If the library accepts `Uint8Array` as input, use `TextEncoder` - in the browser to encode the string into a `Uint8Array` with UTF-8 - encoding, and compute the checksum based on the UTF-8 encoded string - in the browser. -2. If the library only takes a string and compute the data based on - `str.charCodeAt()`, on the Node.js side, convert the string into - a buffer using `Buffer.from(str, 'utf16le')`. - -```mjs -import zlib from 'node:zlib'; -import { Buffer } from 'node:buffer'; - -let crc = zlib.crc32('hello'); // 907060870 -crc = zlib.crc32('world', crc); // 4192936109 - -crc = zlib.crc32(Buffer.from('hello', 'utf16le')); // 1427272415 -crc = zlib.crc32(Buffer.from('world', 'utf16le'), crc); // 4150509955 -``` - -```cjs -const zlib = require('node:zlib'); -const { Buffer } = require('node:buffer'); - -let crc = zlib.crc32('hello'); // 907060870 -crc = zlib.crc32('world', crc); // 4192936109 - -crc = zlib.crc32(Buffer.from('hello', 'utf16le')); // 1427272415 -crc = zlib.crc32(Buffer.from('world', 'utf16le'), crc); // 4150509955 -``` - ### `zlib.close([callback])` + +* `data` {string|Buffer|TypedArray|DataView} When `data` is a string, + it will be encoded as UTF-8 before being used for computation. +* `value` {integer} An optional starting value. It must be a 32-bit unsigned + integer. **Default:** `0` +* Returns: {integer} A 32-bit unsigned integer containing the checksum. + +Computes a 32-bit [Cyclic Redundancy Check][] checksum of `data`. If +`value` is specified, it is used as the starting value of the checksum, +otherwise, 0 is used as the starting value. + +The CRC algorithm is designed to compute checksums and to detect error +in data transmission. It's not suitable for cryptographic authentication. + +To be consistent with other APIs, if the `data` is a string, it will +be encoded with UTF-8 before being used for computation. If users only +use Node.js to compute and match the checksums, this works well with +other APIs that uses the UTF-8 encoding by default. + +Some third-party JavaScript libraries compute the checksum on a +string based on `str.charCodeAt()` so that it can be run in browsers. +If users want to match the checksum computed with this kind of library +in the browser, it's better to use the same library in Node.js +if it also runs in Node.js. If users have to use `zlib.crc32()` to +match the checksum produced by such a third-party library: + +1. If the library accepts `Uint8Array` as input, use `TextEncoder` + in the browser to encode the string into a `Uint8Array` with UTF-8 + encoding, and compute the checksum based on the UTF-8 encoded string + in the browser. +2. If the library only takes a string and compute the data based on + `str.charCodeAt()`, on the Node.js side, convert the string into + a buffer using `Buffer.from(str, 'utf16le')`. + +```mjs +import zlib from 'node:zlib'; +import { Buffer } from 'node:buffer'; + +let crc = zlib.crc32('hello'); // 907060870 +crc = zlib.crc32('world', crc); // 4192936109 + +crc = zlib.crc32(Buffer.from('hello', 'utf16le')); // 1427272415 +crc = zlib.crc32(Buffer.from('world', 'utf16le'), crc); // 4150509955 +``` + +```cjs +const zlib = require('node:zlib'); +const { Buffer } = require('node:buffer'); + +let crc = zlib.crc32('hello'); // 907060870 +crc = zlib.crc32('world', crc); // 4192936109 + +crc = zlib.crc32(Buffer.from('hello', 'utf16le')); // 1427272415 +crc = zlib.crc32(Buffer.from('world', 'utf16le'), crc); // 4150509955 +``` + ## `zlib.createBrotliCompress([options])` -> Stability: 1 - Experimental - ```c napi_status NAPI_CDECL node_api_create_buffer_from_arraybuffer(napi_env env, napi_value arraybuffer, @@ -2965,10 +2964,9 @@ The JavaScript `string` type is described in added: - v20.4.0 - v18.18.0 +napiVersion: 10 --> -> Stability: 1 - Experimental - ```c napi_status node_api_create_external_string_latin1(napi_env env, @@ -3045,10 +3043,9 @@ The JavaScript `string` type is described in added: - v20.4.0 - v18.18.0 +napiVersion: 10 --> -> Stability: 1 - Experimental - ```c napi_status node_api_create_external_string_utf16(napi_env env, @@ -3138,10 +3135,9 @@ creation methods. -> Stability: 1 - Experimental - ```c napi_status NAPI_CDECL node_api_create_property_key_latin1(napi_env env, const char* str, @@ -3173,10 +3169,9 @@ The JavaScript `string` type is described in added: - v21.7.0 - v20.12.0 +napiVersion: 10 --> -> Stability: 1 - Experimental - ```c napi_status NAPI_CDECL node_api_create_property_key_utf16(napi_env env, const char16_t* str, @@ -3204,10 +3199,9 @@ The JavaScript `string` type is described in -> Stability: 1 - Experimental - ```c napi_status NAPI_CDECL node_api_create_property_key_utf8(napi_env env, const char* str, @@ -6527,7 +6521,7 @@ napi_create_threadsafe_function(napi_env env, **Change History:** -* Experimental (`NAPI_EXPERIMENTAL` is defined): +* Version 10 (`NAPI_VERSION` is defined as `10` or higher): Uncaught exceptions thrown in `call_js_cb` are handled with the [`'uncaughtException'`][] event, instead of being ignored. diff --git a/doc/contributing/releases-node-api.md b/doc/contributing/releases-node-api.md index 088900f88c91e0..f8bcd273e39e70 100644 --- a/doc/contributing/releases-node-api.md +++ b/doc/contributing/releases-node-api.md @@ -85,7 +85,7 @@ with: ```bash grep \ - -E \ + -nHE \ 'N(ODE_)?API_EXPERIMENTAL' \ src/js_native_api{_types,}.h \ src/node_api{_types,}.h @@ -95,13 +95,13 @@ and update the define version guards with the release version: ```diff - #ifdef NAPI_EXPERIMENTAL -+ #if NAPI_VERSION >= 10 ++ #if NAPI_VERSION >= 11 NAPI_EXTERN napi_status NAPI_CDECL node_api_function(napi_env env); - #endif // NAPI_EXPERIMENTAL -+ #endif // NAPI_VERSION >= 10 ++ #endif // NAPI_VERSION >= 11 ``` Remove any feature flags of the form `NODE_API_EXPERIMENTAL_HAS_`. @@ -121,11 +121,11 @@ Also, update the Node-API version value of the `napi_get_version` test in #### Step 2. Update runtime version guards If this release includes runtime behavior version guards, the relevant commits -should already include `NAPI_VERSION_EXPERIMENTAL` guard for the change. Check -for these guards with: +should already include the `NAPI_VERSION_EXPERIMENTAL` guard for the change. +Check for these guards with: ```bash -grep NAPI_VERSION_EXPERIMENTAL src/js_native_api_v8* src/node_api.cc +grep -nH NAPI_VERSION_EXPERIMENTAL src/js_native_api_v8* src/node_api.cc ``` and substitute this guard version with the release version `x`. @@ -138,7 +138,7 @@ Check for these definitions with: ```bash grep \ - -E \ + -nHE \ 'N(ODE_)?API_EXPERIMENTAL' \ test/node-api/*/{*.{h,c},binding.gyp} \ test/js-native-api/*/{*.{h,c},binding.gyp} @@ -170,7 +170,7 @@ stability banner: - > Stability: 1 - Experimental @@ -186,7 +186,7 @@ For all runtime version guards updated in Step 2, check for these definitions with: ```bash -grep NAPI_EXPERIMENTAL doc/api/n-api.md +grep -nH NAPI_EXPERIMENTAL doc/api/n-api.md ``` In `doc/api/n-api.md`, update the `experimental` change history item to be the diff --git a/src/js_native_api.h b/src/js_native_api.h index 07e3df13407030..8ef079b5158249 100644 --- a/src/js_native_api.h +++ b/src/js_native_api.h @@ -92,8 +92,7 @@ NAPI_EXTERN napi_status NAPI_CDECL napi_create_string_utf16(napi_env env, const char16_t* str, size_t length, napi_value* result); -#ifdef NAPI_EXPERIMENTAL -#define NODE_API_EXPERIMENTAL_HAS_EXTERNAL_STRINGS +#if NAPI_VERSION >= 10 NAPI_EXTERN napi_status NAPI_CDECL node_api_create_external_string_latin1( napi_env env, char* str, @@ -110,17 +109,14 @@ node_api_create_external_string_utf16(napi_env env, void* finalize_hint, napi_value* result, bool* copied); -#endif // NAPI_EXPERIMENTAL -#ifdef NAPI_EXPERIMENTAL -#define NODE_API_EXPERIMENTAL_HAS_PROPERTY_KEYS NAPI_EXTERN napi_status NAPI_CDECL node_api_create_property_key_latin1( napi_env env, const char* str, size_t length, napi_value* result); NAPI_EXTERN napi_status NAPI_CDECL node_api_create_property_key_utf8( napi_env env, const char* str, size_t length, napi_value* result); NAPI_EXTERN napi_status NAPI_CDECL node_api_create_property_key_utf16( napi_env env, const char16_t* str, size_t length, napi_value* result); -#endif // NAPI_EXPERIMENTAL +#endif // NAPI_VERSION >= 10 NAPI_EXTERN napi_status NAPI_CDECL napi_create_symbol(napi_env env, napi_value description, diff --git a/src/js_native_api_v8.cc b/src/js_native_api_v8.cc index 97a59e4a17f548..de3d1f2f183274 100644 --- a/src/js_native_api_v8.cc +++ b/src/js_native_api_v8.cc @@ -2753,7 +2753,7 @@ napi_status NAPI_CDECL napi_create_reference(napi_env env, CHECK_ARG(env, result); v8::Local v8_value = v8impl::V8LocalValueFromJsValue(value); - if (env->module_api_version != NAPI_VERSION_EXPERIMENTAL) { + if (env->module_api_version < 10) { if (!(v8_value->IsObject() || v8_value->IsFunction() || v8_value->IsSymbol())) { return napi_set_last_error(env, napi_invalid_arg); diff --git a/src/js_native_api_v8.h b/src/js_native_api_v8.h index 99bb30cfbe9a9d..27aeac589b19cd 100644 --- a/src/js_native_api_v8.h +++ b/src/js_native_api_v8.h @@ -234,11 +234,11 @@ inline napi_status napi_set_last_error(node_api_basic_env basic_env, CHECK_ENV_NOT_IN_GC((env)); \ RETURN_STATUS_IF_FALSE( \ (env), (env)->last_exception.IsEmpty(), napi_pending_exception); \ - RETURN_STATUS_IF_FALSE((env), \ - (env)->can_call_into_js(), \ - (env->module_api_version == NAPI_VERSION_EXPERIMENTAL \ - ? napi_cannot_run_js \ - : napi_pending_exception)); \ + RETURN_STATUS_IF_FALSE( \ + (env), \ + (env)->can_call_into_js(), \ + (env->module_api_version >= 10 ? napi_cannot_run_js \ + : napi_pending_exception)); \ napi_clear_last_error((env)); \ v8impl::TryCatch try_catch((env)) diff --git a/src/node_api.cc b/src/node_api.cc index cccb2fd0a17f3a..1638d096969826 100644 --- a/src/node_api.cc +++ b/src/node_api.cc @@ -93,11 +93,11 @@ void node_napi_env__::CallbackIntoModule(T&& call) { return; } node::Environment* node_env = env->node_env(); - // If the module api version is less than NAPI_VERSION_EXPERIMENTAL, - // and the option --force-node-api-uncaught-exceptions-policy is not - // specified, emit a warning about the uncaught exception instead of - // triggering uncaught exception event. - if (env->module_api_version < NAPI_VERSION_EXPERIMENTAL && + // If the module api version is less than 10, and the option + // --force-node-api-uncaught-exceptions-policy is not specified, emit a + // warning about the uncaught exception instead of triggering the uncaught + // exception event. + if (env->module_api_version < 10 && !node_env->options()->force_node_api_uncaught_exceptions_policy && !enforceUncaughtExceptionPolicy) { ProcessEmitDeprecationWarning( @@ -678,11 +678,13 @@ node::addon_context_register_func get_node_api_context_register_func( const char* module_name, int32_t module_api_version) { static_assert( - NODE_API_SUPPORTED_VERSION_MAX == 9, + NODE_API_SUPPORTED_VERSION_MAX == 10, "New version of Node-API requires adding another else-if statement below " "for the new version and updating this assert condition."); if (module_api_version == 9) { return node_api_context_register_func<9>; + } else if (module_api_version == 10) { + return node_api_context_register_func<10>; } else if (module_api_version == NAPI_VERSION_EXPERIMENTAL) { return node_api_context_register_func; } else if (module_api_version >= NODE_API_SUPPORTED_VERSION_MIN && diff --git a/src/node_api.h b/src/node_api.h index c8c7bc6ffb9b94..35e5c3e49dd426 100644 --- a/src/node_api.h +++ b/src/node_api.h @@ -133,8 +133,7 @@ napi_create_external_buffer(napi_env env, napi_value* result); #endif // NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED -#ifdef NAPI_EXPERIMENTAL -#define NODE_API_EXPERIMENTAL_HAS_CREATE_BUFFER_FROM_ARRAYBUFFER +#if NAPI_VERSION >= 10 NAPI_EXTERN napi_status NAPI_CDECL node_api_create_buffer_from_arraybuffer(napi_env env, @@ -142,7 +141,7 @@ node_api_create_buffer_from_arraybuffer(napi_env env, size_t byte_offset, size_t byte_length, napi_value* result); -#endif // NAPI_EXPERIMENTAL +#endif // NAPI_VERSION >= 10 NAPI_EXTERN napi_status NAPI_CDECL napi_create_buffer_copy(napi_env env, size_t length, diff --git a/src/node_version.h b/src/node_version.h index 9c33c50bf7eefe..3c84a842db8af8 100644 --- a/src/node_version.h +++ b/src/node_version.h @@ -100,7 +100,7 @@ // The NAPI_VERSION supported by the runtime. This is the inclusive range of // versions which the Node.js binary being built supports. -#define NODE_API_SUPPORTED_VERSION_MAX 9 +#define NODE_API_SUPPORTED_VERSION_MAX 10 #define NODE_API_SUPPORTED_VERSION_MIN 1 // Node API modules use NAPI_VERSION 8 by default if it is not explicitly diff --git a/test/js-native-api/test_cannot_run_js/binding.gyp b/test/js-native-api/test_cannot_run_js/binding.gyp index 0b827ff34d129f..dfaaf408296d1d 100644 --- a/test/js-native-api/test_cannot_run_js/binding.gyp +++ b/test/js-native-api/test_cannot_run_js/binding.gyp @@ -5,14 +5,14 @@ "sources": [ "test_cannot_run_js.c" ], - "defines": [ "NAPI_EXPERIMENTAL" ], + "defines": [ "NAPI_VERSION=10" ], }, { "target_name": "test_pending_exception", "sources": [ "test_cannot_run_js.c" ], - "defines": [ "NAPI_VERSION=8" ], + "defines": [ "NAPI_VERSION=9" ], } ] } diff --git a/test/js-native-api/test_cannot_run_js/test_cannot_run_js.c b/test/js-native-api/test_cannot_run_js/test_cannot_run_js.c index 9a4b9547493505..dddb8b59421419 100644 --- a/test/js-native-api/test_cannot_run_js/test_cannot_run_js.c +++ b/test/js-native-api/test_cannot_run_js/test_cannot_run_js.c @@ -22,7 +22,7 @@ static void Finalize(napi_env env, void* data, void* hint) { // napi_pending_exception is returned). This is not deterministic from // the point of view of the addon. -#ifdef NAPI_EXPERIMENTAL +#if NAPI_VERSION > 9 NODE_API_BASIC_ASSERT_RETURN_VOID( result == napi_cannot_run_js || result == napi_ok, "getting named property from global in finalizer should succeed " @@ -32,19 +32,10 @@ static void Finalize(napi_env env, void* data, void* hint) { result == napi_pending_exception || result == napi_ok, "getting named property from global in finalizer should succeed " "or return napi_pending_exception"); -#endif // NAPI_EXPERIMENTAL +#endif // NAPI_VERSION > 9 free(ref); } -static void BasicFinalize(node_api_basic_env env, void* data, void* hint) { -#ifdef NAPI_EXPERIMENTAL - NODE_API_BASIC_CALL_RETURN_VOID( - env, node_api_post_finalizer(env, Finalize, data, hint)); -#else - Finalize(env, data, hint); -#endif -} - static napi_value CreateRef(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value cb; @@ -55,8 +46,7 @@ static napi_value CreateRef(napi_env env, napi_callback_info info) { NODE_API_CALL(env, napi_typeof(env, cb, &value_type)); NODE_API_ASSERT( env, value_type == napi_function, "argument must be function"); - NODE_API_CALL(env, - napi_add_finalizer(env, cb, ref, BasicFinalize, NULL, ref)); + NODE_API_CALL(env, napi_add_finalizer(env, cb, ref, Finalize, NULL, ref)); return cb; } diff --git a/test/js-native-api/test_general/test.js b/test/js-native-api/test_general/test.js index 3d4f2f9715678e..843c6aee3af47f 100644 --- a/test/js-native-api/test_general/test.js +++ b/test/js-native-api/test_general/test.js @@ -34,7 +34,7 @@ assert.notStrictEqual(test_general.testGetPrototype(baseObject), test_general.testGetPrototype(extendedObject)); // Test version management functions -assert.strictEqual(test_general.testGetVersion(), 9); +assert.strictEqual(test_general.testGetVersion(), 10); [ 123, diff --git a/test/js-native-api/test_string/binding.gyp b/test/js-native-api/test_string/binding.gyp index 7fc4d9c24226d4..82a1185c3d9d76 100644 --- a/test/js-native-api/test_string/binding.gyp +++ b/test/js-native-api/test_string/binding.gyp @@ -7,7 +7,7 @@ "test_null.c", ], "defines": [ - "NAPI_EXPERIMENTAL", + "NAPI_VERSION=10", ], }, ], diff --git a/test/node-api/test_buffer/binding.gyp b/test/node-api/test_buffer/binding.gyp index 2fd28280d404c4..0a1dc92de7ffb4 100644 --- a/test/node-api/test_buffer/binding.gyp +++ b/test/node-api/test_buffer/binding.gyp @@ -3,7 +3,7 @@ { "target_name": "test_buffer", "defines": [ - 'NAPI_EXPERIMENTAL' + 'NAPI_VERSION=10' ], "sources": [ "test_buffer.c" ] }, diff --git a/test/node-api/test_reference_by_node_api_version/binding.gyp b/test/node-api/test_reference_by_node_api_version/binding.gyp index 2ee1d24763b0b3..4987828ffb3d86 100644 --- a/test/node-api/test_reference_by_node_api_version/binding.gyp +++ b/test/node-api/test_reference_by_node_api_version/binding.gyp @@ -3,12 +3,12 @@ { "target_name": "test_reference_all_types", "sources": [ "test_reference_by_node_api_version.c" ], - "defines": [ "NAPI_EXPERIMENTAL" ], + "defines": [ "NAPI_VERSION=10" ], }, { "target_name": "test_reference_obj_only", "sources": [ "test_reference_by_node_api_version.c" ], - "defines": [ "NAPI_VERSION=8" ], + "defines": [ "NAPI_VERSION=9" ], } ] } From 03f25055ab8d663212a55f262295d4612d2048ae Mon Sep 17 00:00:00 2001 From: Gabriel Schulhof Date: Wed, 1 Jan 2025 11:44:30 -0800 Subject: [PATCH 043/205] doc: add example for piping ReadableStream MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When piping a `ReadableStream` created from an `Iterable` into a `WritableStream`, the sequence of objects in the `Iterable` must consist of either `Buffer`s, `TypedArray`s, or `DataView`s. Re: https://github.com/nodejs/node/issues/56297 PR-URL: https://github.com/nodejs/node/pull/56415 Reviewed-By: Luigi Pinca Reviewed-By: Chemi Atlow Reviewed-By: Ulises Gascón --- doc/api/webstreams.md | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/doc/api/webstreams.md b/doc/api/webstreams.md index 735e1b307e5d9c..b0adef0ae214b8 100644 --- a/doc/api/webstreams.md +++ b/doc/api/webstreams.md @@ -436,6 +436,41 @@ async function* asyncIterableGenerator() { })(); ``` +To pipe the resulting {ReadableStream} into a {WritableStream} the {Iterable} +should yield a sequence of {Buffer}, {TypedArray}, or {DataView} objects. + +```mjs +import { ReadableStream } from 'node:stream/web'; +import { Buffer } from 'node:buffer'; + +async function* asyncIterableGenerator() { + yield Buffer.from('a'); + yield Buffer.from('b'); + yield Buffer.from('c'); +} + +const stream = ReadableStream.from(asyncIterableGenerator()); + +await stream.pipeTo(createWritableStreamSomehow()); +``` + +```cjs +const { ReadableStream } = require('node:stream/web'); +const { Buffer } = require('node:buffer'); + +async function* asyncIterableGenerator() { + yield Buffer.from('a'); + yield Buffer.from('b'); + yield Buffer.from('c'); +} + +const stream = ReadableStream.from(asyncIterableGenerator()); + +(async () => { + await stream.pipeTo(createWritableStreamSomehow()); +})(); +``` + ### Class: `ReadableStreamDefaultReader` Snapshot tests allow arbitrary values to be serialized into string values and compared against a set of known good values. The known good values are known as @@ -1732,8 +1738,6 @@ describe('tests', async () => { added: v22.3.0 --> -> Stability: 1.0 - Early development - An object whose methods are used to configure default snapshot settings in the current process. It is possible to apply the same configuration to all files by placing common configuration code in a module preloaded with `--require` or @@ -1745,8 +1749,6 @@ placing common configuration code in a module preloaded with `--require` or added: v22.3.0 --> -> Stability: 1.0 - Early development - * `serializers` {Array} An array of synchronous functions used as the default serializers for snapshot tests. @@ -1762,8 +1764,6 @@ more robust serialization mechanism is required, this function should be used. added: v22.3.0 --> -> Stability: 1.0 - Early development - * `fn` {Function} A function used to compute the location of the snapshot file. The function receives the path of the test file as its only argument. If the test is not associated with a file (for example in the REPL), the input is @@ -3232,8 +3232,6 @@ test('test', (t) => { added: v22.3.0 --> -> Stability: 1.0 - Early development - * `value` {any} A value to serialize to a string. If Node.js was started with the [`--test-update-snapshots`][] flag, the serialized value is written to the snapshot file. Otherwise, the serialized value is compared to the diff --git a/lib/internal/test_runner/snapshot.js b/lib/internal/test_runner/snapshot.js index 7e41a0bf76f0cd..e6fcd71552c939 100644 --- a/lib/internal/test_runner/snapshot.js +++ b/lib/internal/test_runner/snapshot.js @@ -15,7 +15,7 @@ const { ERR_INVALID_STATE, }, } = require('internal/errors'); -const { emitExperimentalWarning, kEmptyObject } = require('internal/util'); +const { kEmptyObject } = require('internal/util'); let debug = require('internal/util/debuglog').debuglog('test_runner', (fn) => { debug = fn; }); @@ -28,7 +28,6 @@ const { strictEqual } = require('assert'); const { mkdirSync, readFileSync, writeFileSync } = require('fs'); const { dirname } = require('path'); const { createContext, runInContext } = require('vm'); -const kExperimentalWarning = 'Snapshot testing'; const kMissingSnapshotTip = 'Missing snapshots can be generated by rerunning ' + 'the command with the --test-update-snapshots flag.'; const defaultSerializers = [ @@ -47,13 +46,11 @@ let resolveSnapshotPathFn = defaultResolveSnapshotPath; let serializerFns = defaultSerializers; function setResolveSnapshotPath(fn) { - emitExperimentalWarning(kExperimentalWarning); validateFunction(fn, 'fn'); resolveSnapshotPathFn = fn; } function setDefaultSnapshotSerializers(serializers) { - emitExperimentalWarning(kExperimentalWarning); validateFunctionArray(serializers, 'serializers'); serializerFns = ArrayPrototypeSlice(serializers); } @@ -207,7 +204,6 @@ class SnapshotManager { const manager = this; return function snapshotAssertion(actual, options = kEmptyObject) { - emitExperimentalWarning(kExperimentalWarning); validateObject(options, 'options'); const { serializers = serializerFns, From 1705cbe0022ad57bd6b47f3f15108a6c75cb73c7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 3 Jan 2025 18:37:45 +0000 Subject: [PATCH 047/205] tools: bump the eslint group in /tools/eslint with 4 updates Bumps the eslint group in /tools/eslint with 4 updates: [@stylistic/eslint-plugin-js](https://github.com/eslint-stylistic/eslint-stylistic/tree/HEAD/packages/eslint-plugin-js), [eslint](https://github.com/eslint/eslint), [eslint-plugin-jsdoc](https://github.com/gajus/eslint-plugin-jsdoc) and [globals](https://github.com/sindresorhus/globals). Updates `@stylistic/eslint-plugin-js` from 2.11.0 to 2.12.1 - [Release notes](https://github.com/eslint-stylistic/eslint-stylistic/releases) - [Changelog](https://github.com/eslint-stylistic/eslint-stylistic/blob/main/CHANGELOG.md) - [Commits](https://github.com/eslint-stylistic/eslint-stylistic/commits/v2.12.1/packages/eslint-plugin-js) Updates `eslint` from 9.16.0 to 9.17.0 - [Release notes](https://github.com/eslint/eslint/releases) - [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md) - [Commits](https://github.com/eslint/eslint/compare/v9.16.0...v9.17.0) Updates `eslint-plugin-jsdoc` from 50.6.0 to 50.6.1 - [Release notes](https://github.com/gajus/eslint-plugin-jsdoc/releases) - [Changelog](https://github.com/gajus/eslint-plugin-jsdoc/blob/main/.releaserc) - [Commits](https://github.com/gajus/eslint-plugin-jsdoc/compare/v50.6.0...v50.6.1) Updates `globals` from 15.12.0 to 15.14.0 - [Release notes](https://github.com/sindresorhus/globals/releases) - [Commits](https://github.com/sindresorhus/globals/compare/v15.12.0...v15.14.0) --- updated-dependencies: - dependency-name: "@stylistic/eslint-plugin-js" dependency-type: direct:production update-type: version-update:semver-minor dependency-group: eslint - dependency-name: eslint dependency-type: direct:production update-type: version-update:semver-minor dependency-group: eslint - dependency-name: eslint-plugin-jsdoc dependency-type: direct:production update-type: version-update:semver-patch dependency-group: eslint - dependency-name: globals dependency-type: direct:production update-type: version-update:semver-minor dependency-group: eslint ... Signed-off-by: dependabot[bot] PR-URL: https://github.com/nodejs/node/pull/56426 Reviewed-By: Antoine du Hamel Reviewed-By: Luigi Pinca Reviewed-By: Marco Ippolito --- tools/eslint/package-lock.json | 55 ++++++++++++++++------------------ tools/eslint/package.json | 8 ++--- 2 files changed, 29 insertions(+), 34 deletions(-) diff --git a/tools/eslint/package-lock.json b/tools/eslint/package-lock.json index ddae8841e1ea39..7d57c1b57129b2 100644 --- a/tools/eslint/package-lock.json +++ b/tools/eslint/package-lock.json @@ -11,12 +11,12 @@ "@babel/core": "^7.26.0", "@babel/eslint-parser": "^7.25.9", "@babel/plugin-syntax-import-attributes": "^7.26.0", - "@stylistic/eslint-plugin-js": "^2.11.0", - "eslint": "^9.16.0", + "@stylistic/eslint-plugin-js": "^2.12.1", + "eslint": "^9.17.0", "eslint-formatter-tap": "^8.40.0", - "eslint-plugin-jsdoc": "^50.6.0", + "eslint-plugin-jsdoc": "^50.6.1", "eslint-plugin-markdown": "^5.1.0", - "globals": "^15.12.0" + "globals": "^15.14.0" } }, "node_modules/@ampproject/remapping": { @@ -382,9 +382,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.16.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.16.0.tgz", - "integrity": "sha512-tw2HxzQkrbeuvyj1tG2Yqq+0H9wGoI2IMk4EOsQeX+vmd75FtJAzf+gTA69WF+baUKRYQ3x2kbLE08js5OsTVg==", + "version": "9.17.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.17.0.tgz", + "integrity": "sha512-Sxc4hqcs1kTu0iID3kcZDW3JHq2a77HO9P8CP6YEA/FpH3Ll8UXE2r/86Rz9YJLKme39S9vU5OWNjC6Xl0Cr3w==", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } @@ -535,9 +535,9 @@ } }, "node_modules/@stylistic/eslint-plugin-js": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-2.11.0.tgz", - "integrity": "sha512-btchD0P3iij6cIk5RR5QMdEhtCCV0+L6cNheGhGCd//jaHILZMTi/EOqgEDAf1s4ZoViyExoToM+S2Iwa3U9DA==", + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-2.12.1.tgz", + "integrity": "sha512-5ybogtEgWIGCR6dMnaabztbWyVdAPDsf/5XOk6jBonWug875Q9/a6gm9QxnU3rhdyDEnckWKX7dduwYJMOWrVA==", "dependencies": { "eslint-visitor-keys": "^4.2.0", "espree": "^10.3.0" @@ -757,9 +757,9 @@ "license": "MIT" }, "node_modules/cross-spawn": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.5.tgz", - "integrity": "sha512-ZVJrKKYunU38/76t0RMOulHOnUcbU9GbpWKAOZ0mhjr7CX6FVrH+4FrAapSOekrgFQ3f/8gwMEuIft0aKq6Hug==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -812,16 +812,16 @@ } }, "node_modules/eslint": { - "version": "9.16.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.16.0.tgz", - "integrity": "sha512-whp8mSQI4C8VXd+fLgSM0lh3UlmcFtVwUQjyKCFfsp+2ItAIYhlq/hqGahGqHE6cv9unM41VlqKk2VtKYR2TaA==", + "version": "9.17.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.17.0.tgz", + "integrity": "sha512-evtlNcpJg+cZLcnVKwsai8fExnqjGPicK7gnUtlNuzu+Fv9bI0aLpND5T44VLQtoMEnI57LoXO9XAkIXwohKrA==", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.19.0", "@eslint/core": "^0.9.0", "@eslint/eslintrc": "^3.2.0", - "@eslint/js": "9.16.0", + "@eslint/js": "9.17.0", "@eslint/plugin-kit": "^0.2.3", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", @@ -830,7 +830,7 @@ "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", - "cross-spawn": "^7.0.5", + "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.2.0", @@ -882,9 +882,9 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "50.6.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.6.0.tgz", - "integrity": "sha512-tCNp4fR79Le3dYTPB0dKEv7yFyvGkUCa+Z3yuTrrNGGOxBlXo9Pn0PEgroOZikUQOGjxoGMVKNjrOHcYEdfszg==", + "version": "50.6.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.6.1.tgz", + "integrity": "sha512-UWyaYi6iURdSfdVVqvfOs2vdCVz0J40O/z/HTsv2sFjdjmdlUI/qlKLOTmwbPQ2tAfQnE5F9vqx+B+poF71DBQ==", "dependencies": { "@es-joy/jsdoccomment": "~0.49.0", "are-docs-informative": "^0.0.2", @@ -1254,9 +1254,9 @@ } }, "node_modules/globals": { - "version": "15.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.12.0.tgz", - "integrity": "sha512-1+gLErljJFhbOVyaetcwJiJ4+eLe45S2E7P5UiZ9xGfeq3ATQf5DOv9G7MH3gGbKQLkzmNh2DxfZwLdw+j6oTQ==", + "version": "15.14.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.14.0.tgz", + "integrity": "sha512-OkToC372DtlQeje9/zHIo5CT8lRP/FUgEOKBEhU4e0abL7J7CD24fD9ohiLN5hagG/kWCYj4K5oaxxtj2Z0Dig==", "engines": { "node": ">=18" }, @@ -1364,8 +1364,7 @@ "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "license": "ISC" + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, "node_modules/js-tokens": { "version": "4.0.0", @@ -1660,7 +1659,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "license": "MIT", "engines": { "node": ">=8" } @@ -1708,7 +1706,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" }, @@ -1720,7 +1717,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "license": "MIT", "engines": { "node": ">=8" } @@ -1852,7 +1848,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, diff --git a/tools/eslint/package.json b/tools/eslint/package.json index 59b2e661aa96f1..68bedee0cb10f9 100644 --- a/tools/eslint/package.json +++ b/tools/eslint/package.json @@ -6,11 +6,11 @@ "@babel/core": "^7.26.0", "@babel/eslint-parser": "^7.25.9", "@babel/plugin-syntax-import-attributes": "^7.26.0", - "@stylistic/eslint-plugin-js": "^2.11.0", - "eslint": "^9.16.0", + "@stylistic/eslint-plugin-js": "^2.12.1", + "eslint": "^9.17.0", "eslint-formatter-tap": "^8.40.0", - "eslint-plugin-jsdoc": "^50.6.0", + "eslint-plugin-jsdoc": "^50.6.1", "eslint-plugin-markdown": "^5.1.0", - "globals": "^15.12.0" + "globals": "^15.14.0" } } From d5c05328e27e9a96e3d61df39535745e93601acd Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Fri, 3 Jan 2025 20:25:17 +0100 Subject: [PATCH 048/205] tools: use a configurable value for number of open dependabot PRs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This way, we can disable all dependabot PRs from private forks. PR-URL: https://github.com/nodejs/node/pull/56427 Reviewed-By: Chemi Atlow Reviewed-By: Michaël Zasso Reviewed-By: Luigi Pinca --- .github/dependabot.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 33aaa6304fee00..b9770e23a2e353 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -8,7 +8,7 @@ updates: interval: monthly commit-message: prefix: meta - open-pull-requests-limit: 10 + open-pull-requests-limit: ${{secrets.OPEN_PR_LIMIT}} - package-ecosystem: npm directory: /tools/eslint @@ -16,7 +16,7 @@ updates: interval: monthly commit-message: prefix: tools - open-pull-requests-limit: 10 + open-pull-requests-limit: ${{secrets.OPEN_PR_LIMIT}} groups: eslint: applies-to: version-updates @@ -29,7 +29,7 @@ updates: interval: monthly commit-message: prefix: tools - open-pull-requests-limit: 10 + open-pull-requests-limit: ${{secrets.OPEN_PR_LIMIT}} groups: lint-md: applies-to: version-updates From 3e729ceec8eacfbf7a48d4de6a45fc6887647915 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Fri, 3 Jan 2025 15:12:08 -0800 Subject: [PATCH 049/205] tools: disable unneeded rule ignoring in Python linting Removing PLC1901 and RUF100 from the list of Python lint rules to ignore does not result in any errors. Keeping the ignore list as short as possible seems like a good idea, so this change removes them from the ignore list. PR-URL: https://github.com/nodejs/node/pull/56429 Reviewed-By: Yagiz Nizipli Reviewed-By: Christian Clauss Reviewed-By: Luigi Pinca Reviewed-By: Chengzhong Wu --- pyproject.toml | 2 -- 1 file changed, 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 8e97e3b4446293..03f53aa6bed6bf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -33,9 +33,7 @@ ignore = [ "E401", "E402", "E7", - "PLC1901", "RUF005", - "RUF100", ] [tool.ruff.lint.mccabe] From ec2940b418d3593afd65f9abb7315ed97b9da815 Mon Sep 17 00:00:00 2001 From: Colin Ihrig Date: Sat, 4 Jan 2025 12:18:49 -0500 Subject: [PATCH 050/205] test: update test-child-process-windows-hide to use node:test This commit updates test/parallel/test-child-process-windows-hide.js to use node:test. This allows the test to use the built in mocking functionality instead of managing spies manually. It also prevents multiple child processes from being spawned in parallel, which can be problematic in the CI. PR-URL: https://github.com/nodejs/node/pull/56437 Reviewed-By: Yagiz Nizipli Reviewed-By: James M Snell --- .../test-child-process-windows-hide.js | 47 +++++++++---------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/test/parallel/test-child-process-windows-hide.js b/test/parallel/test-child-process-windows-hide.js index ef4a8be8784ebc..c218c901a7f2ea 100644 --- a/test/parallel/test-child-process-windows-hide.js +++ b/test/parallel/test-child-process-windows-hide.js @@ -3,49 +3,48 @@ const common = require('../common'); const assert = require('assert'); const cp = require('child_process'); +const { test } = require('node:test'); const internalCp = require('internal/child_process'); const cmd = process.execPath; const args = ['-p', '42']; const options = { windowsHide: true }; -// Since windowsHide isn't really observable, monkey patch spawn() and -// spawnSync() to verify that the flag is being passed through correctly. -const originalSpawn = internalCp.ChildProcess.prototype.spawn; -const originalSpawnSync = internalCp.spawnSync; +// Since windowsHide isn't really observable, this test relies on monkey +// patching spawn() and spawnSync() to verify that the flag is being passed +// through correctly. -internalCp.ChildProcess.prototype.spawn = common.mustCall(function(options) { - assert.strictEqual(options.windowsHide, true); - return originalSpawn.apply(this, arguments); -}, 2); - -internalCp.spawnSync = common.mustCall(function(options) { - assert.strictEqual(options.windowsHide, true); - return originalSpawnSync.apply(this, arguments); -}); - -{ +test('spawnSync() passes windowsHide correctly', (t) => { + const spy = t.mock.method(internalCp, 'spawnSync'); const child = cp.spawnSync(cmd, args, options); assert.strictEqual(child.status, 0); assert.strictEqual(child.signal, null); assert.strictEqual(child.stdout.toString().trim(), '42'); assert.strictEqual(child.stderr.toString().trim(), ''); -} + assert.strictEqual(spy.mock.calls.length, 1); + assert.strictEqual(spy.mock.calls[0].arguments[0].windowsHide, true); +}); -{ +test('spawn() passes windowsHide correctly', (t, done) => { + const spy = t.mock.method(internalCp.ChildProcess.prototype, 'spawn'); const child = cp.spawn(cmd, args, options); child.on('exit', common.mustCall((code, signal) => { assert.strictEqual(code, 0); assert.strictEqual(signal, null); + assert.strictEqual(spy.mock.calls.length, 1); + assert.strictEqual(spy.mock.calls[0].arguments[0].windowsHide, true); + done(); })); -} +}); -{ - const callback = common.mustSucceed((stdout, stderr) => { +test('execFile() passes windowsHide correctly', (t, done) => { + const spy = t.mock.method(internalCp.ChildProcess.prototype, 'spawn'); + cp.execFile(cmd, args, options, common.mustSucceed((stdout, stderr) => { assert.strictEqual(stdout.trim(), '42'); assert.strictEqual(stderr.trim(), ''); - }); - - cp.execFile(cmd, args, options, callback); -} + assert.strictEqual(spy.mock.calls.length, 1); + assert.strictEqual(spy.mock.calls[0].arguments[0].windowsHide, true); + done(); + })); +}); From 926cf84e958b3e2d9121943f060e70a0f6df3063 Mon Sep 17 00:00:00 2001 From: Colin Ihrig Date: Sat, 4 Jan 2025 13:30:04 -0500 Subject: [PATCH 051/205] test_runner: add assert.register() API This commit adds a top level assert.register() API to the test runner. This function allows users to define their own custom assertion functions on the TestContext. Fixes: https://github.com/nodejs/node/issues/52033 PR-URL: https://github.com/nodejs/node/pull/56434 Reviewed-By: Jacob Smith Reviewed-By: Matteo Collina Reviewed-By: Pietro Marchini --- doc/api/test.md | 23 +++++++ lib/internal/test_runner/assert.js | 50 +++++++++++++++ lib/internal/test_runner/test.js | 52 ++++++--------- lib/test.js | 12 ++++ .../parallel/test-runner-custom-assertions.js | 63 +++++++++++++++++++ 5 files changed, 166 insertions(+), 34 deletions(-) create mode 100644 lib/internal/test_runner/assert.js create mode 100644 test/parallel/test-runner-custom-assertions.js diff --git a/doc/api/test.md b/doc/api/test.md index c2ca0e5a8c00ee..757c4788bbacdf 100644 --- a/doc/api/test.md +++ b/doc/api/test.md @@ -1732,6 +1732,29 @@ describe('tests', async () => { }); ``` +## `assert` + + + +An object whose methods are used to configure available assertions on the +`TestContext` objects in the current process. The methods from `node:assert` +and snapshot testing functions are available by default. + +It is possible to apply the same configuration to all files by placing common +configuration code in a module +preloaded with `--require` or `--import`. + +### `assert.register(name, fn)` + + + +Defines a new assertion function with the provided name and function. If an +assertion already exists with the same name, it is overwritten. + ## `snapshot` * `namedParameters` {Object} An optional object used to bind named parameters. The keys of this object are used to configure the mapping. -* `...anonymousParameters` {null|number|bigint|string|Buffer|Uint8Array} Zero or +* `...anonymousParameters` {null|number|bigint|string|Buffer|TypedArray|DataView} Zero or more values to bind to anonymous parameters. * Returns: {Array} An array of objects. Each object corresponds to a row returned by executing the prepared statement. The keys and values of each @@ -361,11 +365,15 @@ execution of this prepared statement. This property is a wrapper around * `namedParameters` {Object} An optional object used to bind named parameters. The keys of this object are used to configure the mapping. -* `...anonymousParameters` {null|number|bigint|string|Buffer|Uint8Array} Zero or +* `...anonymousParameters` {null|number|bigint|string|Buffer|TypedArray|DataView} Zero or more values to bind to anonymous parameters. * Returns: {Object|undefined} An object corresponding to the first row returned by executing the prepared statement. The keys and values of the object @@ -381,11 +389,15 @@ values in `namedParameters` and `anonymousParameters`. * `namedParameters` {Object} An optional object used to bind named parameters. The keys of this object are used to configure the mapping. -* `...anonymousParameters` {null|number|bigint|string|Buffer|Uint8Array} Zero or +* `...anonymousParameters` {null|number|bigint|string|Buffer|TypedArray|DataView} Zero or more values to bind to anonymous parameters. * Returns: {Iterator} An iterable iterator of objects. Each object corresponds to a row returned by executing the prepared statement. The keys and values of each @@ -400,11 +412,15 @@ the values in `namedParameters` and `anonymousParameters`. * `namedParameters` {Object} An optional object used to bind named parameters. The keys of this object are used to configure the mapping. -* `...anonymousParameters` {null|number|bigint|string|Buffer|Uint8Array} Zero or +* `...anonymousParameters` {null|number|bigint|string|Buffer|TypedArray|DataView} Zero or more values to bind to anonymous parameters. * Returns: {Object} * `changes`: {number|bigint} The number of rows modified, inserted, or deleted diff --git a/src/node_sqlite.cc b/src/node_sqlite.cc index abd85a98c5aebb..373931a76a54de 100644 --- a/src/node_sqlite.cc +++ b/src/node_sqlite.cc @@ -960,7 +960,7 @@ bool StatementSync::BindParams(const FunctionCallbackInfo& args) { int anon_idx = 1; int anon_start = 0; - if (args[0]->IsObject() && !args[0]->IsUint8Array()) { + if (args[0]->IsObject() && !args[0]->IsArrayBufferView()) { Local obj = args[0].As(); Local context = obj->GetIsolate()->GetCurrentContext(); Local keys; @@ -1065,7 +1065,7 @@ bool StatementSync::BindValue(const Local& value, const int index) { statement_, index, *val, val.length(), SQLITE_TRANSIENT); } else if (value->IsNull()) { r = sqlite3_bind_null(statement_, index); - } else if (value->IsUint8Array()) { + } else if (value->IsArrayBufferView()) { ArrayBufferViewContents buf(value); r = sqlite3_bind_blob( statement_, index, buf.data(), buf.length(), SQLITE_TRANSIENT); diff --git a/test/parallel/test-sqlite-typed-array-and-data-view.js b/test/parallel/test-sqlite-typed-array-and-data-view.js new file mode 100644 index 00000000000000..1cc75c541b6261 --- /dev/null +++ b/test/parallel/test-sqlite-typed-array-and-data-view.js @@ -0,0 +1,61 @@ +'use strict'; +require('../common'); +const tmpdir = require('../common/tmpdir'); +const { join } = require('node:path'); +const { DatabaseSync } = require('node:sqlite'); +const { suite, test } = require('node:test'); +let cnt = 0; + +tmpdir.refresh(); + +function nextDb() { + return join(tmpdir.path, `database-${cnt++}.db`); +} + +const arrayBuffer = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]).buffer; +const TypedArrays = [ + ['Int8Array', Int8Array], + ['Uint8Array', Uint8Array], + ['Uint8ClampedArray', Uint8ClampedArray], + ['Int16Array', Int16Array], + ['Uint16Array', Uint16Array], + ['Int32Array', Int32Array], + ['Uint32Array', Uint32Array], + ['Float32Array', Float32Array], + ['Float64Array', Float64Array], + ['BigInt64Array', BigInt64Array], + ['BigUint64Array', BigUint64Array], + ['DataView', DataView], +]; + +suite('StatementSync with TypedArray/DataView', () => { + for (const [displayName, TypedArray] of TypedArrays) { + test(displayName, (t) => { + const db = new DatabaseSync(nextDb()); + t.after(() => { db.close(); }); + db.exec('CREATE TABLE test (data BLOB)'); + // insert + { + const stmt = db.prepare('INSERT INTO test VALUES (?)'); + stmt.run(new TypedArray(arrayBuffer)); + } + // select all + { + const stmt = db.prepare('SELECT * FROM test'); + const row = stmt.get(); + t.assert.ok(row.data instanceof Uint8Array); + t.assert.strictEqual(row.data.length, 8); + t.assert.deepStrictEqual(row.data, new Uint8Array(arrayBuffer)); + } + // query + { + const stmt = db.prepare('SELECT * FROM test WHERE data = ?'); + const rows = stmt.all(new TypedArray(arrayBuffer)); + t.assert.strictEqual(rows.length, 1); + t.assert.ok(rows[0].data instanceof Uint8Array); + t.assert.strictEqual(rows[0].data.length, 8); + t.assert.deepStrictEqual(rows[0].data, new Uint8Array(arrayBuffer)); + } + }); + } +}); From 2c6124cec466dba243c4dc9291bca52ad15a755d Mon Sep 17 00:00:00 2001 From: Chengzhong Wu Date: Sun, 5 Jan 2025 11:43:44 +0000 Subject: [PATCH 057/205] inspector: report loadingFinished until the response data is consumed The `Network.loadingFinished` should be deferred until the response is complete and the data is fully consumed. Also, report correct request url with the specified port by retrieving the host from the request headers. PR-URL: https://github.com/nodejs/node/pull/56372 Refs: https://github.com/nodejs/node/issues/53946 Reviewed-By: James M Snell Reviewed-By: Kohei Ueno --- lib/internal/inspector/network.js | 31 +++ lib/internal/inspector/network_http.js | 132 ++++++++++ lib/internal/inspector_network_tracking.js | 99 +------ src/node_builtins.cc | 2 + .../parallel/test-inspector-network-domain.js | 206 --------------- test/parallel/test-inspector-network-http.js | 241 ++++++++++++++++++ 6 files changed, 412 insertions(+), 299 deletions(-) create mode 100644 lib/internal/inspector/network.js create mode 100644 lib/internal/inspector/network_http.js delete mode 100644 test/parallel/test-inspector-network-domain.js create mode 100644 test/parallel/test-inspector-network-http.js diff --git a/lib/internal/inspector/network.js b/lib/internal/inspector/network.js new file mode 100644 index 00000000000000..18424bee569302 --- /dev/null +++ b/lib/internal/inspector/network.js @@ -0,0 +1,31 @@ +'use strict'; + +const { + NumberMAX_SAFE_INTEGER, + Symbol, +} = primordials; + +const { now } = require('internal/perf/utils'); +const kInspectorRequestId = Symbol('kInspectorRequestId'); + +/** + * Return a monotonically increasing time in seconds since an arbitrary point in the past. + * @returns {number} + */ +function getMonotonicTime() { + return now() / 1000; +} + +let requestId = 0; +function getNextRequestId() { + if (requestId === NumberMAX_SAFE_INTEGER) { + requestId = 0; + } + return `node-network-event-${++requestId}`; +}; + +module.exports = { + kInspectorRequestId, + getMonotonicTime, + getNextRequestId, +}; diff --git a/lib/internal/inspector/network_http.js b/lib/internal/inspector/network_http.js new file mode 100644 index 00000000000000..87a33b419b1aed --- /dev/null +++ b/lib/internal/inspector/network_http.js @@ -0,0 +1,132 @@ +'use strict'; + +const { + ArrayIsArray, + DateNow, + ObjectEntries, + String, + Symbol, +} = primordials; + +const { + kInspectorRequestId, + getMonotonicTime, + getNextRequestId, +} = require('internal/inspector/network'); +const dc = require('diagnostics_channel'); +const { Network } = require('inspector'); + +const kResourceType = 'Other'; +const kRequestUrl = Symbol('kRequestUrl'); + +// Convert a Headers object (Map) to a plain object (Map) +const convertHeaderObject = (headers = {}) => { + // The 'host' header that contains the host and port of the URL. + let host; + const dict = {}; + for (const { 0: key, 1: value } of ObjectEntries(headers)) { + if (key.toLowerCase() === 'host') { + host = value; + } + if (typeof value === 'string') { + dict[key] = value; + } else if (ArrayIsArray(value)) { + if (key.toLowerCase() === 'cookie') dict[key] = value.join('; '); + // ChromeDevTools frontend treats 'set-cookie' as a special case + // https://github.com/ChromeDevTools/devtools-frontend/blob/4275917f84266ef40613db3c1784a25f902ea74e/front_end/core/sdk/NetworkRequest.ts#L1368 + else if (key.toLowerCase() === 'set-cookie') dict[key] = value.join('\n'); + else dict[key] = value.join(', '); + } else { + dict[key] = String(value); + } + } + return [host, dict]; +}; + +/** + * When a client request starts, emit Network.requestWillBeSent event. + * https://chromedevtools.github.io/devtools-protocol/1-3/Network/#event-requestWillBeSent + * @param {{ request: import('http').ClientRequest }} event + */ +function onClientRequestStart({ request }) { + request[kInspectorRequestId] = getNextRequestId(); + + const { 0: host, 1: headers } = convertHeaderObject(request.getHeaders()); + const url = `${request.protocol}//${host}${request.path}`; + request[kRequestUrl] = url; + + Network.requestWillBeSent({ + requestId: request[kInspectorRequestId], + timestamp: getMonotonicTime(), + wallTime: DateNow(), + request: { + url, + method: request.method, + headers, + }, + }); +} + +/** + * When a client request errors, emit Network.loadingFailed event. + * https://chromedevtools.github.io/devtools-protocol/1-3/Network/#event-loadingFailed + * @param {{ request: import('http').ClientRequest, error: any }} event + */ +function onClientRequestError({ request, error }) { + if (typeof request[kInspectorRequestId] !== 'string') { + return; + } + Network.loadingFailed({ + requestId: request[kInspectorRequestId], + timestamp: getMonotonicTime(), + type: kResourceType, + errorText: error.message, + }); +} + +/** + * When response headers are received, emit Network.responseReceived event. + * https://chromedevtools.github.io/devtools-protocol/1-3/Network/#event-responseReceived + * @param {{ request: import('http').ClientRequest, error: any }} event + */ +function onClientResponseFinish({ request, response }) { + if (typeof request[kInspectorRequestId] !== 'string') { + return; + } + Network.responseReceived({ + requestId: request[kInspectorRequestId], + timestamp: getMonotonicTime(), + type: kResourceType, + response: { + url: request[kRequestUrl], + status: response.statusCode, + statusText: response.statusMessage ?? '', + headers: convertHeaderObject(response.headers)[1], + }, + }); + + // Wait until the response body is consumed by user code. + response.once('end', () => { + Network.loadingFinished({ + requestId: request[kInspectorRequestId], + timestamp: getMonotonicTime(), + }); + }); +} + +function enable() { + dc.subscribe('http.client.request.start', onClientRequestStart); + dc.subscribe('http.client.request.error', onClientRequestError); + dc.subscribe('http.client.response.finish', onClientResponseFinish); +} + +function disable() { + dc.unsubscribe('http.client.request.start', onClientRequestStart); + dc.unsubscribe('http.client.request.error', onClientRequestError); + dc.unsubscribe('http.client.response.finish', onClientResponseFinish); +} + +module.exports = { + enable, + disable, +}; diff --git a/lib/internal/inspector_network_tracking.js b/lib/internal/inspector_network_tracking.js index de325baf77eb42..9158bb48f745f8 100644 --- a/lib/internal/inspector_network_tracking.js +++ b/lib/internal/inspector_network_tracking.js @@ -1,102 +1,15 @@ 'use strict'; -const { - ArrayIsArray, - DateNow, - ObjectEntries, - String, -} = primordials; - -let dc; -let Network; - -let requestId = 0; -const getNextRequestId = () => `node-network-event-${++requestId}`; - -// Convert a Headers object (Map) to a plain object (Map) -const headerObjectToDictionary = (headers = {}) => { - const dict = {}; - for (const { 0: key, 1: value } of ObjectEntries(headers)) { - if (typeof value === 'string') { - dict[key] = value; - } else if (ArrayIsArray(value)) { - if (key.toLowerCase() === 'cookie') dict[key] = value.join('; '); - // ChromeDevTools frontend treats 'set-cookie' as a special case - // https://github.com/ChromeDevTools/devtools-frontend/blob/4275917f84266ef40613db3c1784a25f902ea74e/front_end/core/sdk/NetworkRequest.ts#L1368 - else if (key.toLowerCase() === 'set-cookie') dict[key] = value.join('\n'); - else dict[key] = value.join(', '); - } else { - dict[key] = String(value); - } - } - return dict; -}; - -function onClientRequestStart({ request }) { - const url = `${request.protocol}//${request.host}${request.path}`; - const wallTime = DateNow(); - const timestamp = wallTime / 1000; - request._inspectorRequestId = getNextRequestId(); - Network.requestWillBeSent({ - requestId: request._inspectorRequestId, - timestamp, - wallTime, - request: { - url, - method: request.method, - headers: headerObjectToDictionary(request.getHeaders()), - }, - }); -} - -function onClientRequestError({ request, error }) { - if (typeof request._inspectorRequestId !== 'string') { - return; - } - const timestamp = DateNow() / 1000; - Network.loadingFailed({ - requestId: request._inspectorRequestId, - timestamp, - type: 'Other', - errorText: error.message, - }); -} - -function onClientResponseFinish({ request, response }) { - if (typeof request._inspectorRequestId !== 'string') { - return; - } - const url = `${request.protocol}//${request.host}${request.path}`; - const timestamp = DateNow() / 1000; - Network.responseReceived({ - requestId: request._inspectorRequestId, - timestamp, - type: 'Other', - response: { - url, - status: response.statusCode, - statusText: response.statusMessage ?? '', - headers: headerObjectToDictionary(response.headers), - }, - }); - Network.loadingFinished({ - requestId: request._inspectorRequestId, - timestamp, - }); -} - function enable() { - dc ??= require('diagnostics_channel'); - Network ??= require('inspector').Network; - dc.subscribe('http.client.request.start', onClientRequestStart); - dc.subscribe('http.client.request.error', onClientRequestError); - dc.subscribe('http.client.response.finish', onClientResponseFinish); + require('internal/inspector/network_http').enable(); + // TODO: add undici request/websocket tracking. + // https://github.com/nodejs/node/issues/53946 } function disable() { - dc.unsubscribe('http.client.request.start', onClientRequestStart); - dc.unsubscribe('http.client.request.error', onClientRequestError); - dc.unsubscribe('http.client.response.finish', onClientResponseFinish); + require('internal/inspector/network_http').disable(); + // TODO: add undici request/websocket tracking. + // https://github.com/nodejs/node/issues/53946 } module.exports = { diff --git a/src/node_builtins.cc b/src/node_builtins.cc index e5955903261397..791c16ce3942d7 100644 --- a/src/node_builtins.cc +++ b/src/node_builtins.cc @@ -119,6 +119,8 @@ BuiltinLoader::BuiltinCategories BuiltinLoader::GetBuiltinCategories() const { builtin_categories.cannot_be_required = std::set { #if !HAVE_INSPECTOR "inspector", "inspector/promises", "internal/util/inspector", + "internal/inspector/network", "internal/inspector/network_http", + "internal/inspector_async_hook", "internal/inspector_network_tracking", #endif // !HAVE_INSPECTOR #if !NODE_USE_V8_PLATFORM || !defined(NODE_HAVE_I18N_SUPPORT) diff --git a/test/parallel/test-inspector-network-domain.js b/test/parallel/test-inspector-network-domain.js deleted file mode 100644 index d2a56dca95a4ff..00000000000000 --- a/test/parallel/test-inspector-network-domain.js +++ /dev/null @@ -1,206 +0,0 @@ -// Flags: --inspect=0 --experimental-network-inspection -'use strict'; -const common = require('../common'); - -common.skipIfInspectorDisabled(); - -const assert = require('node:assert'); -const { addresses } = require('../common/internet'); -const fixtures = require('../common/fixtures'); -const http = require('node:http'); -const https = require('node:https'); -const inspector = require('node:inspector/promises'); - -const session = new inspector.Session(); -session.connect(); - -const requestHeaders = { - 'accept-language': 'en-US', - 'Cookie': ['k1=v1', 'k2=v2'], - 'age': 1000, - 'x-header1': ['value1', 'value2'] -}; - -const setResponseHeaders = (res) => { - res.setHeader('server', 'node'); - res.setHeader('etag', 12345); - res.setHeader('Set-Cookie', ['key1=value1', 'key2=value2']); - res.setHeader('x-header2', ['value1', 'value2']); -}; - -const httpServer = http.createServer((req, res) => { - const path = req.url; - switch (path) { - case '/hello-world': - setResponseHeaders(res); - res.writeHead(200); - res.end('hello world\n'); - break; - default: - assert(false, `Unexpected path: ${path}`); - } -}); - -const httpsServer = https.createServer({ - key: fixtures.readKey('agent1-key.pem'), - cert: fixtures.readKey('agent1-cert.pem') -}, (req, res) => { - const path = req.url; - switch (path) { - case '/hello-world': - setResponseHeaders(res); - res.writeHead(200); - res.end('hello world\n'); - break; - default: - assert(false, `Unexpected path: ${path}`); - } -}); - -const terminate = () => { - session.disconnect(); - httpServer.close(); - httpsServer.close(); - inspector.close(); -}; - -const testHttpGet = () => new Promise((resolve, reject) => { - session.on('Network.requestWillBeSent', common.mustCall(({ params }) => { - assert.ok(params.requestId.startsWith('node-network-event-')); - assert.strictEqual(params.request.url, 'http://127.0.0.1/hello-world'); - assert.strictEqual(params.request.method, 'GET'); - assert.strictEqual(typeof params.request.headers, 'object'); - assert.strictEqual(params.request.headers['accept-language'], 'en-US'); - assert.strictEqual(params.request.headers.cookie, 'k1=v1; k2=v2'); - assert.strictEqual(params.request.headers.age, '1000'); - assert.strictEqual(params.request.headers['x-header1'], 'value1, value2'); - assert.strictEqual(typeof params.timestamp, 'number'); - assert.strictEqual(typeof params.wallTime, 'number'); - })); - session.on('Network.responseReceived', common.mustCall(({ params }) => { - assert.ok(params.requestId.startsWith('node-network-event-')); - assert.strictEqual(typeof params.timestamp, 'number'); - assert.strictEqual(params.type, 'Other'); - assert.strictEqual(params.response.status, 200); - assert.strictEqual(params.response.statusText, 'OK'); - assert.strictEqual(params.response.url, 'http://127.0.0.1/hello-world'); - assert.strictEqual(typeof params.response.headers, 'object'); - assert.strictEqual(params.response.headers.server, 'node'); - assert.strictEqual(params.response.headers.etag, '12345'); - assert.strictEqual(params.response.headers['set-cookie'], 'key1=value1\nkey2=value2'); - assert.strictEqual(params.response.headers['x-header2'], 'value1, value2'); - })); - session.on('Network.loadingFinished', common.mustCall(({ params }) => { - assert.ok(params.requestId.startsWith('node-network-event-')); - assert.strictEqual(typeof params.timestamp, 'number'); - resolve(); - })); - - http.get({ - host: '127.0.0.1', - port: httpServer.address().port, - path: '/hello-world', - headers: requestHeaders - }, common.mustCall()); -}); - -const testHttpsGet = () => new Promise((resolve, reject) => { - session.on('Network.requestWillBeSent', common.mustCall(({ params }) => { - assert.ok(params.requestId.startsWith('node-network-event-')); - assert.strictEqual(params.request.url, 'https://127.0.0.1/hello-world'); - assert.strictEqual(params.request.method, 'GET'); - assert.strictEqual(typeof params.request.headers, 'object'); - assert.strictEqual(params.request.headers['accept-language'], 'en-US'); - assert.strictEqual(params.request.headers.cookie, 'k1=v1; k2=v2'); - assert.strictEqual(params.request.headers.age, '1000'); - assert.strictEqual(params.request.headers['x-header1'], 'value1, value2'); - assert.strictEqual(typeof params.timestamp, 'number'); - assert.strictEqual(typeof params.wallTime, 'number'); - })); - session.on('Network.responseReceived', common.mustCall(({ params }) => { - assert.ok(params.requestId.startsWith('node-network-event-')); - assert.strictEqual(typeof params.timestamp, 'number'); - assert.strictEqual(params.type, 'Other'); - assert.strictEqual(params.response.status, 200); - assert.strictEqual(params.response.statusText, 'OK'); - assert.strictEqual(params.response.url, 'https://127.0.0.1/hello-world'); - assert.strictEqual(typeof params.response.headers, 'object'); - assert.strictEqual(params.response.headers.server, 'node'); - assert.strictEqual(params.response.headers.etag, '12345'); - assert.strictEqual(params.response.headers['set-cookie'], 'key1=value1\nkey2=value2'); - assert.strictEqual(params.response.headers['x-header2'], 'value1, value2'); - })); - session.on('Network.loadingFinished', common.mustCall(({ params }) => { - assert.ok(params.requestId.startsWith('node-network-event-')); - assert.strictEqual(typeof params.timestamp, 'number'); - resolve(); - })); - - https.get({ - host: '127.0.0.1', - port: httpsServer.address().port, - path: '/hello-world', - rejectUnauthorized: false, - headers: requestHeaders, - }, common.mustCall()); -}); - -const testHttpError = () => new Promise((resolve, reject) => { - session.on('Network.requestWillBeSent', common.mustCall()); - session.on('Network.loadingFailed', common.mustCall(({ params }) => { - assert.ok(params.requestId.startsWith('node-network-event-')); - assert.strictEqual(typeof params.timestamp, 'number'); - assert.strictEqual(params.type, 'Other'); - assert.strictEqual(typeof params.errorText, 'string'); - resolve(); - })); - session.on('Network.responseReceived', common.mustNotCall()); - session.on('Network.loadingFinished', common.mustNotCall()); - - http.get({ - host: addresses.INVALID_HOST, - }, common.mustNotCall()).on('error', common.mustCall()); -}); - - -const testHttpsError = () => new Promise((resolve, reject) => { - session.on('Network.requestWillBeSent', common.mustCall()); - session.on('Network.loadingFailed', common.mustCall(({ params }) => { - assert.ok(params.requestId.startsWith('node-network-event-')); - assert.strictEqual(typeof params.timestamp, 'number'); - assert.strictEqual(params.type, 'Other'); - assert.strictEqual(typeof params.errorText, 'string'); - resolve(); - })); - session.on('Network.responseReceived', common.mustNotCall()); - session.on('Network.loadingFinished', common.mustNotCall()); - - https.get({ - host: addresses.INVALID_HOST, - }, common.mustNotCall()).on('error', common.mustCall()); -}); - -const testNetworkInspection = async () => { - await testHttpGet(); - session.removeAllListeners(); - await testHttpsGet(); - session.removeAllListeners(); - await testHttpError(); - session.removeAllListeners(); - await testHttpsError(); - session.removeAllListeners(); -}; - -httpServer.listen(0, () => { - httpsServer.listen(0, async () => { - try { - await session.post('Network.enable'); - await testNetworkInspection(); - await session.post('Network.disable'); - } catch (e) { - assert.fail(e); - } finally { - terminate(); - } - }); -}); diff --git a/test/parallel/test-inspector-network-http.js b/test/parallel/test-inspector-network-http.js new file mode 100644 index 00000000000000..e1e987cdd71e28 --- /dev/null +++ b/test/parallel/test-inspector-network-http.js @@ -0,0 +1,241 @@ +// Flags: --inspect=0 --experimental-network-inspection +'use strict'; +const common = require('../common'); + +common.skipIfInspectorDisabled(); + +const assert = require('node:assert'); +const { once } = require('node:events'); +const { addresses } = require('../common/internet'); +const fixtures = require('../common/fixtures'); +const http = require('node:http'); +const https = require('node:https'); +const inspector = require('node:inspector/promises'); + +const session = new inspector.Session(); +session.connect(); + +const requestHeaders = { + 'accept-language': 'en-US', + 'Cookie': ['k1=v1', 'k2=v2'], + 'age': 1000, + 'x-header1': ['value1', 'value2'] +}; + +const setResponseHeaders = (res) => { + res.setHeader('server', 'node'); + res.setHeader('etag', 12345); + res.setHeader('Set-Cookie', ['key1=value1', 'key2=value2']); + res.setHeader('x-header2', ['value1', 'value2']); +}; + +const kTimeout = 1000; +const kDelta = 200; + +const handleRequest = (req, res) => { + const path = req.url; + switch (path) { + case '/hello-world': + setResponseHeaders(res); + res.writeHead(200); + // Ensure the header is sent. + res.write('\n'); + + setTimeout(() => { + res.end('hello world\n'); + }, kTimeout); + break; + default: + assert(false, `Unexpected path: ${path}`); + } +}; + +const httpServer = http.createServer(handleRequest); + +const httpsServer = https.createServer({ + key: fixtures.readKey('agent1-key.pem'), + cert: fixtures.readKey('agent1-cert.pem') +}, handleRequest); + +const terminate = () => { + session.disconnect(); + httpServer.close(); + httpsServer.close(); + inspector.close(); +}; + +function verifyRequestWillBeSent({ method, params }, expect) { + assert.strictEqual(method, 'Network.requestWillBeSent'); + + assert.ok(params.requestId.startsWith('node-network-event-')); + assert.strictEqual(params.request.url, expect.url); + assert.strictEqual(params.request.method, 'GET'); + assert.strictEqual(typeof params.request.headers, 'object'); + assert.strictEqual(params.request.headers['accept-language'], 'en-US'); + assert.strictEqual(params.request.headers.cookie, 'k1=v1; k2=v2'); + assert.strictEqual(params.request.headers.age, '1000'); + assert.strictEqual(params.request.headers['x-header1'], 'value1, value2'); + assert.strictEqual(typeof params.timestamp, 'number'); + assert.strictEqual(typeof params.wallTime, 'number'); + + return params; +} + +function verifyResponseReceived({ method, params }, expect) { + assert.strictEqual(method, 'Network.responseReceived'); + + assert.ok(params.requestId.startsWith('node-network-event-')); + assert.strictEqual(typeof params.timestamp, 'number'); + assert.strictEqual(params.type, 'Other'); + assert.strictEqual(params.response.status, 200); + assert.strictEqual(params.response.statusText, 'OK'); + assert.strictEqual(params.response.url, expect.url); + assert.strictEqual(typeof params.response.headers, 'object'); + assert.strictEqual(params.response.headers.server, 'node'); + assert.strictEqual(params.response.headers.etag, '12345'); + assert.strictEqual(params.response.headers['set-cookie'], 'key1=value1\nkey2=value2'); + assert.strictEqual(params.response.headers['x-header2'], 'value1, value2'); + + return params; +} + +function verifyLoadingFinished({ method, params }) { + assert.strictEqual(method, 'Network.loadingFinished'); + + assert.ok(params.requestId.startsWith('node-network-event-')); + assert.strictEqual(typeof params.timestamp, 'number'); + return params; +} + +function verifyLoadingFailed({ method, params }) { + assert.strictEqual(method, 'Network.loadingFailed'); + + assert.ok(params.requestId.startsWith('node-network-event-')); + assert.strictEqual(typeof params.timestamp, 'number'); + assert.strictEqual(params.type, 'Other'); + assert.strictEqual(typeof params.errorText, 'string'); +} + +async function testHttpGet() { + const url = `http://127.0.0.1:${httpServer.address().port}/hello-world`; + const requestWillBeSentFuture = once(session, 'Network.requestWillBeSent') + .then(([event]) => verifyRequestWillBeSent(event, { url })); + + const responseReceivedFuture = once(session, 'Network.responseReceived') + .then(([event]) => verifyResponseReceived(event, { url })); + + const loadingFinishedFuture = once(session, 'Network.loadingFinished') + .then(([event]) => verifyLoadingFinished(event)); + + http.get({ + host: '127.0.0.1', + port: httpServer.address().port, + path: '/hello-world', + headers: requestHeaders + }, common.mustCall((res) => { + // Dump the response. + res.on('data', () => {}); + res.on('end', () => {}); + })); + + await requestWillBeSentFuture; + const responseReceived = await responseReceivedFuture; + const loadingFinished = await loadingFinishedFuture; + + const delta = (loadingFinished.timestamp - responseReceived.timestamp) * 1000; + assert.ok(delta > kDelta); +} + +async function testHttpsGet() { + const url = `https://127.0.0.1:${httpsServer.address().port}/hello-world`; + const requestWillBeSentFuture = once(session, 'Network.requestWillBeSent') + .then(([event]) => verifyRequestWillBeSent(event, { url })); + + const responseReceivedFuture = once(session, 'Network.responseReceived') + .then(([event]) => verifyResponseReceived(event, { url })); + + const loadingFinishedFuture = once(session, 'Network.loadingFinished') + .then(([event]) => verifyLoadingFinished(event)); + + https.get({ + host: '127.0.0.1', + port: httpsServer.address().port, + path: '/hello-world', + rejectUnauthorized: false, + headers: requestHeaders, + }, common.mustCall((res) => { + // Dump the response. + res.on('data', () => {}); + res.on('end', () => {}); + })); + + await requestWillBeSentFuture; + const responseReceived = await responseReceivedFuture; + const loadingFinished = await loadingFinishedFuture; + + const delta = (loadingFinished.timestamp - responseReceived.timestamp) * 1000; + assert.ok(delta > kDelta); +} + +async function testHttpError() { + const url = `http://${addresses.INVALID_HOST}/`; + const requestWillBeSentFuture = once(session, 'Network.requestWillBeSent') + .then(([event]) => verifyRequestWillBeSent(event, { url })); + session.on('Network.responseReceived', common.mustNotCall()); + session.on('Network.loadingFinished', common.mustNotCall()); + + const loadingFailedFuture = once(session, 'Network.loadingFailed') + .then(([event]) => verifyLoadingFailed(event)); + + http.get({ + host: addresses.INVALID_HOST, + headers: requestHeaders, + }, common.mustNotCall()).on('error', common.mustCall()); + + await requestWillBeSentFuture; + await loadingFailedFuture; +} + +async function testHttpsError() { + const url = `https://${addresses.INVALID_HOST}/`; + const requestWillBeSentFuture = once(session, 'Network.requestWillBeSent') + .then(([event]) => verifyRequestWillBeSent(event, { url })); + session.on('Network.responseReceived', common.mustNotCall()); + session.on('Network.loadingFinished', common.mustNotCall()); + + const loadingFailedFuture = once(session, 'Network.loadingFailed') + .then(([event]) => verifyLoadingFailed(event)); + + https.get({ + host: addresses.INVALID_HOST, + headers: requestHeaders, + }, common.mustNotCall()).on('error', common.mustCall()); + + await requestWillBeSentFuture; + await loadingFailedFuture; +} + +const testNetworkInspection = async () => { + await testHttpGet(); + session.removeAllListeners(); + await testHttpsGet(); + session.removeAllListeners(); + await testHttpError(); + session.removeAllListeners(); + await testHttpsError(); + session.removeAllListeners(); +}; + +httpServer.listen(0, () => { + httpsServer.listen(0, async () => { + try { + await session.post('Network.enable'); + await testNetworkInspection(); + await session.post('Network.disable'); + } catch (e) { + assert.fail(e); + } finally { + terminate(); + } + }); +}); From 48493e9fd55a0c66843f4ef82e57eb9fc3d50ba2 Mon Sep 17 00:00:00 2001 From: James M Snell Date: Fri, 3 Jan 2025 11:11:31 -0800 Subject: [PATCH 058/205] src: use LocalVector in more places MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/56457 Reviewed-By: Michaël Zasso Reviewed-By: Yagiz Nizipli --- src/crypto/crypto_util.h | 5 +++-- src/env.cc | 7 ++----- src/env.h | 11 ++++++++++- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/crypto/crypto_util.h b/src/crypto/crypto_util.h index 5c717c6fdb0fc4..a72c0a2a908294 100644 --- a/src/crypto/crypto_util.h +++ b/src/crypto/crypto_util.h @@ -547,7 +547,8 @@ void ThrowCryptoError(Environment* env, class CipherPushContext { public: - inline explicit CipherPushContext(Environment* env) : env_(env) {} + inline explicit CipherPushContext(Environment* env) + : list_(env->isolate()), env_(env) {} inline void push_back(const char* str) { list_.emplace_back(OneByteString(env_->isolate(), str)); @@ -558,7 +559,7 @@ class CipherPushContext { } private: - std::vector> list_; + v8::LocalVector list_; Environment* env_; }; diff --git a/src/env.cc b/src/env.cc index adb6cc1c2f1c01..b428c922ed218c 100644 --- a/src/env.cc +++ b/src/env.cc @@ -176,11 +176,7 @@ bool AsyncHooks::pop_async_context(double async_id) { } #endif native_execution_async_resources_.resize(offset); - if (native_execution_async_resources_.size() < - native_execution_async_resources_.capacity() / 2 && - native_execution_async_resources_.size() > 16) { - native_execution_async_resources_.shrink_to_fit(); - } + native_execution_async_resources_.shrink_to_fit(); } if (js_execution_async_resources()->Length() > offset) [[unlikely]] { @@ -1705,6 +1701,7 @@ AsyncHooks::AsyncHooks(Isolate* isolate, const SerializeInfo* info) fields_(isolate, kFieldsCount, MAYBE_FIELD_PTR(info, fields)), async_id_fields_( isolate, kUidFieldsCount, MAYBE_FIELD_PTR(info, async_id_fields)), + native_execution_async_resources_(isolate), info_(info) { HandleScope handle_scope(isolate); if (info == nullptr) { diff --git a/src/env.h b/src/env.h index 16312e548e526b..1239cbdbf2d375 100644 --- a/src/env.h +++ b/src/env.h @@ -405,7 +405,16 @@ class AsyncHooks : public MemoryRetainer { void grow_async_ids_stack(); v8::Global js_execution_async_resources_; - std::vector> native_execution_async_resources_; + + // TODO(@jasnell): Note that this is technically illegal use of + // v8::Locals which should be kept on the stack. Here, the entries + // in this object grows and shrinks with the C stack, and entries + // will be in the right handle scopes, but v8::Locals are supposed + // to remain on the stack and not the heap. For general purposes + // this *should* be ok but may need to be looked at further should + // v8 become stricter in the future about v8::Locals being held in + // the stack. + v8::LocalVector native_execution_async_resources_; // Non-empty during deserialization const SerializeInfo* info_ = nullptr; From f959805d016707dbb0823e51f85551b4adaa6279 Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Mon, 6 Jan 2025 02:22:27 -0500 Subject: [PATCH 059/205] worker: flush stdout and stderr on exit Signed-off-by: Matteo Collina PR-URL: https://github.com/nodejs/node/pull/56428 Reviewed-By: James M Snell Reviewed-By: Paolo Insogna --- .../bootstrap/switches/is_not_main_thread.js | 13 +++++++++- lib/internal/worker/io.js | 10 +++++--- .../test-worker-stdio-flush-inflight.js | 24 ++++++++++++++++++ test/parallel/test-worker-stdio-flush.js | 25 +++++++++++++++++++ 4 files changed, 68 insertions(+), 4 deletions(-) create mode 100644 test/parallel/test-worker-stdio-flush-inflight.js create mode 100644 test/parallel/test-worker-stdio-flush.js diff --git a/lib/internal/bootstrap/switches/is_not_main_thread.js b/lib/internal/bootstrap/switches/is_not_main_thread.js index 03aa7c3ebe12f2..6fa30aec748af0 100644 --- a/lib/internal/bootstrap/switches/is_not_main_thread.js +++ b/lib/internal/bootstrap/switches/is_not_main_thread.js @@ -33,11 +33,22 @@ process.removeListener('removeListener', stopListeningIfSignal); const { createWorkerStdio, + kStdioWantsMoreDataCallback, } = require('internal/worker/io'); let workerStdio; function lazyWorkerStdio() { - return workerStdio ??= createWorkerStdio(); + if (workerStdio === undefined) { + workerStdio = createWorkerStdio(); + process.on('exit', flushSync); + } + + return workerStdio; +} + +function flushSync() { + workerStdio.stdout[kStdioWantsMoreDataCallback](); + workerStdio.stderr[kStdioWantsMoreDataCallback](); } function getStdout() { return lazyWorkerStdio().stdout; } diff --git a/lib/internal/worker/io.js b/lib/internal/worker/io.js index 42b8845cec6711..2b28c6a2487b11 100644 --- a/lib/internal/worker/io.js +++ b/lib/internal/worker/io.js @@ -292,9 +292,13 @@ class WritableWorkerStdio extends Writable { chunks: ArrayPrototypeMap(chunks, ({ chunk, encoding }) => ({ chunk, encoding })), }); - ArrayPrototypePush(this[kWritableCallbacks], cb); - if (this[kPort][kWaitingStreams]++ === 0) - this[kPort].ref(); + if (process._exiting) { + cb(); + } else { + ArrayPrototypePush(this[kWritableCallbacks], cb); + if (this[kPort][kWaitingStreams]++ === 0) + this[kPort].ref(); + } } _final(cb) { diff --git a/test/parallel/test-worker-stdio-flush-inflight.js b/test/parallel/test-worker-stdio-flush-inflight.js new file mode 100644 index 00000000000000..34b81152811e7b --- /dev/null +++ b/test/parallel/test-worker-stdio-flush-inflight.js @@ -0,0 +1,24 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const { Worker, isMainThread } = require('worker_threads'); + +if (isMainThread) { + const w = new Worker(__filename, { stdout: true }); + const expected = 'hello world'; + + let data = ''; + w.stdout.setEncoding('utf8'); + w.stdout.on('data', (chunk) => { + data += chunk; + }); + + w.on('exit', common.mustCall(() => { + assert.strictEqual(data, expected); + })); +} else { + process.stdout.write('hello'); + process.stdout.write(' '); + process.stdout.write('world'); + process.exit(0); +} diff --git a/test/parallel/test-worker-stdio-flush.js b/test/parallel/test-worker-stdio-flush.js new file mode 100644 index 00000000000000..e52e721fc69483 --- /dev/null +++ b/test/parallel/test-worker-stdio-flush.js @@ -0,0 +1,25 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const { Worker, isMainThread } = require('worker_threads'); + +if (isMainThread) { + const w = new Worker(__filename, { stdout: true }); + const expected = 'hello world'; + + let data = ''; + w.stdout.setEncoding('utf8'); + w.stdout.on('data', (chunk) => { + data += chunk; + }); + + w.on('exit', common.mustCall(() => { + assert.strictEqual(data, expected); + })); +} else { + process.on('exit', () => { + process.stdout.write(' '); + process.stdout.write('world'); + }); + process.stdout.write('hello'); +} From 843c2389b95a564dd13a815a4919564e3da5ebb2 Mon Sep 17 00:00:00 2001 From: sebastianas Date: Mon, 6 Jan 2025 16:58:13 +0100 Subject: [PATCH 060/205] test: update error code in tls-psk-circuit for for OpenSSL 3.4 Update parallel/test-tls-psk-circuit.js to account for error code changes in OpenSSL 3.4 and probably later. Signed-off-by: Sebastian Andrzej Siewior PR-URL: https://github.com/nodejs/node/pull/56420 Reviewed-By: Luigi Pinca Reviewed-By: Richard Lau --- test/parallel/test-tls-psk-circuit.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/parallel/test-tls-psk-circuit.js b/test/parallel/test-tls-psk-circuit.js index e93db3eb1b4923..c06e61c321ef67 100644 --- a/test/parallel/test-tls-psk-circuit.js +++ b/test/parallel/test-tls-psk-circuit.js @@ -66,7 +66,8 @@ const expectedHandshakeErr = common.hasOpenSSL(3, 2) ? 'ERR_SSL_SSL/TLS_ALERT_HANDSHAKE_FAILURE' : 'ERR_SSL_SSLV3_ALERT_HANDSHAKE_FAILURE'; test({ psk: USERS.UserB, identity: 'UserC' }, {}, expectedHandshakeErr); // Recognized user but incorrect secret should fail handshake -const expectedIllegalParameterErr = common.hasOpenSSL(3, 2) ? - 'ERR_SSL_SSL/TLS_ALERT_ILLEGAL_PARAMETER' : 'ERR_SSL_SSLV3_ALERT_ILLEGAL_PARAMETER'; +const expectedIllegalParameterErr = common.hasOpenSSL(3, 4) ? 'ERR_SSL_TLSV1_ALERT_DECRYPT_ERROR' : + common.hasOpenSSL(3, 2) ? + 'ERR_SSL_SSL/TLS_ALERT_ILLEGAL_PARAMETER' : 'ERR_SSL_SSLV3_ALERT_ILLEGAL_PARAMETER'; test({ psk: USERS.UserA, identity: 'UserB' }, {}, expectedIllegalParameterErr); test({ psk: USERS.UserB, identity: 'UserB' }); From 5614993968f7e6c6b01dd68dbef0f92895c8970f Mon Sep 17 00:00:00 2001 From: Chengzhong Wu Date: Tue, 7 Jan 2025 11:03:55 +0000 Subject: [PATCH 061/205] src: drain platform tasks before creating startup snapshot Drain the loop and platform tasks before creating a snapshot. This is necessary to ensure that the no roots are held by the the platform tasks, which may reference objects associated with a context. For example, a WeakRef may schedule an per-isolate platform task as a GC root, and referencing an object in a context, causing an assertion in the snapshot creator. PR-URL: https://github.com/nodejs/node/pull/56403 Refs: https://github.com/nodejs/node/pull/56292 Reviewed-By: James M Snell Reviewed-By: Joyee Cheung --- src/node_snapshotable.cc | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/node_snapshotable.cc b/src/node_snapshotable.cc index fe04a8ee8d708b..fe3fcc7184205f 100644 --- a/src/node_snapshotable.cc +++ b/src/node_snapshotable.cc @@ -973,25 +973,29 @@ ExitCode BuildSnapshotWithoutCodeCache( } }); + Context::Scope context_scope(setup->context()); + Environment* env = setup->env(); + // Run the custom main script for fully customized snapshots. if (snapshot_type == SnapshotMetadata::Type::kFullyCustomized) { - Context::Scope context_scope(setup->context()); - Environment* env = setup->env(); #if HAVE_INSPECTOR env->InitializeInspector({}); #endif if (LoadEnvironment(env, builder_script_content.value()).IsEmpty()) { return ExitCode::kGenericUserError; } + } - // FIXME(joyeecheung): right now running the loop in the snapshot - // builder might introduce inconsistencies in JS land that need to - // be synchronized again after snapshot restoration. - ExitCode exit_code = - SpinEventLoopInternal(env).FromMaybe(ExitCode::kGenericUserError); - if (exit_code != ExitCode::kNoFailure) { - return exit_code; - } + // Drain the loop and platform tasks before creating a snapshot. This is + // necessary to ensure that the no roots are held by the the platform + // tasks, which may reference objects associated with a context. For + // example, a WeakRef may schedule an per-isolate platform task as a GC + // root, and referencing an object in a context, causing an assertion in + // the snapshot creator. + ExitCode exit_code = + SpinEventLoopInternal(env).FromMaybe(ExitCode::kGenericUserError); + if (exit_code != ExitCode::kNoFailure) { + return exit_code; } } From 98d3474267325f88cdf3bda484c9414ad85478ad Mon Sep 17 00:00:00 2001 From: Xiao-Tao Date: Wed, 8 Jan 2025 00:31:45 +0800 Subject: [PATCH 062/205] tools: fix loong64 build failed PR-URL: https://github.com/nodejs/node/pull/56466 Reviewed-By: James M Snell Reviewed-By: Luigi Pinca --- tools/v8_gypfiles/v8.gyp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tools/v8_gypfiles/v8.gyp b/tools/v8_gypfiles/v8.gyp index 569661147bc257..c4548c124df559 100644 --- a/tools/v8_gypfiles/v8.gyp +++ b/tools/v8_gypfiles/v8.gyp @@ -1222,6 +1222,11 @@ '<(V8_ROOT)/src/trap-handler/handler-outside-posix.cc', ], }], + ['(_toolset=="host" and host_arch=="x64" or _toolset=="target" and target_arch=="x64") and (OS=="linux")', { + 'sources': [ + '<(V8_ROOT)/src/trap-handler/handler-outside-simulator.cc', + ], + }], ], }], ], From 6eec5e7ec2c3a07ba08e97b2e5e10af0d7553ea8 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Tue, 7 Jan 2025 17:49:10 +0100 Subject: [PATCH 063/205] src: lock the thread properly in snapshot builder Otherwise it can crash DCHECK when V8 expects that at least someone is locking the current thread. PR-URL: https://github.com/nodejs/node/pull/56327 Fixes: https://github.com/nodejs/node-v8/issues/294 Reviewed-By: James M Snell Reviewed-By: Chengzhong Wu Reviewed-By: Minwoo Jung Reviewed-By: Anna Henningsen --- src/node_snapshotable.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/node_snapshotable.cc b/src/node_snapshotable.cc index fe3fcc7184205f..f9acb7b1d1618e 100644 --- a/src/node_snapshotable.cc +++ b/src/node_snapshotable.cc @@ -962,6 +962,8 @@ ExitCode BuildSnapshotWithoutCodeCache( } Isolate* isolate = setup->isolate(); + v8::Locker locker(isolate); + { HandleScope scope(isolate); TryCatch bootstrapCatch(isolate); From 5aa436f5a15c7e347f155be7e1541022796a9e11 Mon Sep 17 00:00:00 2001 From: James M Snell Date: Tue, 7 Jan 2025 13:08:55 -0800 Subject: [PATCH 064/205] src: make some minor ToLocalChecked cleanups PR-URL: https://github.com/nodejs/node/pull/56483 Reviewed-By: Yagiz Nizipli Reviewed-By: Daeyeon Jeong Reviewed-By: Anna Henningsen --- src/cares_wrap.cc | 48 ++++++++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/src/cares_wrap.cc b/src/cares_wrap.cc index a19e8221f34eba..e79f43d1824b60 100644 --- a/src/cares_wrap.cc +++ b/src/cares_wrap.cc @@ -1580,15 +1580,16 @@ void ConvertIpv6StringToBuffer(const FunctionCallbackInfo& args) { if (uv_inet_pton(AF_INET6, *ip, dst) != 0) { isolate->ThrowException(Exception::Error( - String::NewFromUtf8(isolate, "Invalid IPv6 address").ToLocalChecked())); + FIXED_ONE_BYTE_STRING(isolate, "Invalid IPv6 address"))); return; } - Local buffer = - node::Buffer::Copy( + Local buffer; + if (node::Buffer::Copy( isolate, reinterpret_cast(dst), sizeof(dst)) - .ToLocalChecked(); - args.GetReturnValue().Set(buffer); + .ToLocal(&buffer)) { + args.GetReturnValue().Set(buffer); + } } void GetAddrInfo(const FunctionCallbackInfo& args) { @@ -1750,22 +1751,27 @@ void SetServers(const FunctionCallbackInfo& args) { int err; for (uint32_t i = 0; i < len; i++) { - CHECK(arr->Get(env->context(), i).ToLocalChecked()->IsArray()); - - Local elm = arr->Get(env->context(), i).ToLocalChecked().As(); - - CHECK(elm->Get(env->context(), - 0).ToLocalChecked()->Int32Value(env->context()).FromJust()); - CHECK(elm->Get(env->context(), 1).ToLocalChecked()->IsString()); - CHECK(elm->Get(env->context(), - 2).ToLocalChecked()->Int32Value(env->context()).FromJust()); - - int fam = elm->Get(env->context(), 0) - .ToLocalChecked()->Int32Value(env->context()).FromJust(); - node::Utf8Value ip(env->isolate(), - elm->Get(env->context(), 1).ToLocalChecked()); - int port = elm->Get(env->context(), 2) - .ToLocalChecked()->Int32Value(env->context()).FromJust(); + Local val; + if (!arr->Get(env->context(), i).ToLocal(&val)) return; + CHECK(val->IsArray()); + + Local elm = val.As(); + + Local familyValue; + Local ipValue; + Local portValue; + + if (!elm->Get(env->context(), 0).ToLocal(&familyValue)) return; + if (!elm->Get(env->context(), 1).ToLocal(&ipValue)) return; + if (!elm->Get(env->context(), 2).ToLocal(&portValue)) return; + + CHECK(familyValue->Int32Value(env->context()).FromJust()); + CHECK(ipValue->IsString()); + CHECK(portValue->Int32Value(env->context()).FromJust()); + + int fam = familyValue->Int32Value(env->context()).FromJust(); + node::Utf8Value ip(env->isolate(), ipValue); + int port = portValue->Int32Value(env->context()).FromJust(); ares_addr_port_node* cur = &servers[i]; From 04f623b2835331b4a4a314abdfd9b6b06cbb11b2 Mon Sep 17 00:00:00 2001 From: James M Snell Date: Sun, 5 Jan 2025 13:48:35 -0800 Subject: [PATCH 065/205] src: fixup more ToLocalChecked uses in node_file PR-URL: https://github.com/nodejs/node/pull/56484 Reviewed-By: Daeyeon Jeong Reviewed-By: Anna Henningsen Reviewed-By: Yagiz Nizipli --- src/node_file.cc | 70 +++++++++++++++++++++++++----------------------- 1 file changed, 36 insertions(+), 34 deletions(-) diff --git a/src/node_file.cc b/src/node_file.cc index cb57e3df3bb150..f09defa7247461 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -1406,16 +1406,15 @@ static void ReadLink(const FunctionCallbackInfo& args) { const char* link_path = static_cast(req_wrap_sync.req.ptr); Local error; - MaybeLocal rc = StringBytes::Encode(isolate, - link_path, - encoding, - &error); - if (rc.IsEmpty()) { + Local ret; + if (!StringBytes::Encode(isolate, link_path, encoding, &error) + .ToLocal(&ret)) { + DCHECK(!error.IsEmpty()); env->isolate()->ThrowException(error); return; } - args.GetReturnValue().Set(rc.ToLocalChecked()); + args.GetReturnValue().Set(ret); } } @@ -1817,15 +1816,16 @@ static void MKDir(const FunctionCallbackInfo& args) { } if (!req_wrap_sync.continuation_data()->first_path().empty()) { Local error; + Local ret; std::string first_path(req_wrap_sync.continuation_data()->first_path()); - MaybeLocal path = StringBytes::Encode(env->isolate(), - first_path.c_str(), - UTF8, &error); - if (path.IsEmpty()) { + if (!StringBytes::Encode( + env->isolate(), first_path.c_str(), UTF8, &error) + .ToLocal(&ret)) { + DCHECK(!error.IsEmpty()); env->isolate()->ThrowException(error); return; } - args.GetReturnValue().Set(path.ToLocalChecked()); + args.GetReturnValue().Set(ret); } } else { SyncCallAndThrowOnError(env, &req_wrap_sync, uv_fs_mkdir, *path, mode); @@ -1866,16 +1866,15 @@ static void RealPath(const FunctionCallbackInfo& args) { const char* link_path = static_cast(req_wrap_sync.req.ptr); Local error; - MaybeLocal rc = StringBytes::Encode(isolate, - link_path, - encoding, - &error); - if (rc.IsEmpty()) { + Local ret; + if (!StringBytes::Encode(isolate, link_path, encoding, &error) + .ToLocal(&ret)) { + DCHECK(!error.IsEmpty()); env->isolate()->ThrowException(error); return; } - args.GetReturnValue().Set(rc.ToLocalChecked()); + args.GetReturnValue().Set(ret); } } @@ -1962,17 +1961,15 @@ static void ReadDir(const FunctionCallbackInfo& args) { } Local error; - MaybeLocal filename = StringBytes::Encode(isolate, - ent.name, - encoding, - &error); - - if (filename.IsEmpty()) { + Local fn; + if (!StringBytes::Encode(isolate, ent.name, encoding, &error) + .ToLocal(&fn)) { + DCHECK(!error.IsEmpty()); isolate->ThrowException(error); return; } - name_v.push_back(filename.ToLocalChecked()); + name_v.push_back(fn); if (with_types) { type_v.emplace_back(Integer::New(isolate, ent.type)); @@ -2993,13 +2990,14 @@ static void Mkdtemp(const FunctionCallbackInfo& args) { return; } Local error; - MaybeLocal rc = - StringBytes::Encode(isolate, req_wrap_sync.req.path, encoding, &error); - if (rc.IsEmpty()) { + Local ret; + if (!StringBytes::Encode(isolate, req_wrap_sync.req.path, encoding, &error) + .ToLocal(&ret)) { + DCHECK(!error.IsEmpty()); env->isolate()->ThrowException(error); return; } - args.GetReturnValue().Set(rc.ToLocalChecked()); + args.GetReturnValue().Set(ret); } } @@ -3311,9 +3309,11 @@ void BindingData::LegacyMainResolve(const FunctionCallbackInfo& args) { for (int i = 0; i < legacy_main_extensions_with_main_end; i++) { file_path = *initial_file_path + std::string(legacy_main_extensions[i]); // TODO(anonrig): Remove this when ToNamespacedPath supports std::string - Local local_file_path = - Buffer::Copy(env->isolate(), file_path.c_str(), file_path.size()) - .ToLocalChecked(); + Local local_file_path; + if (!Buffer::Copy(env->isolate(), file_path.c_str(), file_path.size()) + .ToLocal(&local_file_path)) { + return; + } BufferValue buff_file_path(isolate, local_file_path); ToNamespacedPath(env, &buff_file_path); @@ -3346,9 +3346,11 @@ void BindingData::LegacyMainResolve(const FunctionCallbackInfo& args) { i++) { file_path = *initial_file_path + std::string(legacy_main_extensions[i]); // TODO(anonrig): Remove this when ToNamespacedPath supports std::string - Local local_file_path = - Buffer::Copy(env->isolate(), file_path.c_str(), file_path.size()) - .ToLocalChecked(); + Local local_file_path; + if (!Buffer::Copy(env->isolate(), file_path.c_str(), file_path.size()) + .ToLocal(&local_file_path)) { + return; + } BufferValue buff_file_path(isolate, local_file_path); ToNamespacedPath(env, &buff_file_path); From b89f123a0b912adaf811de5eddcb7881d781bcbd Mon Sep 17 00:00:00 2001 From: James M Snell Date: Fri, 3 Jan 2025 15:22:12 -0800 Subject: [PATCH 066/205] crypto: make generatePrime/checkPrime interruptible The `generatePrime` and `checkPrime` functions in the `crypto` module are only somewhat interruptible. This change makes it possible to interrupt these more reliably. Note that generating overly large primes can still take a long time and may not be interruptible as this mechanism relies on a callback to check for stopping conditions but OpenSSL may perform a long running operation without calling the callback right away. Fixes: https://github.com/nodejs/node/issues/56449 PR-URL: https://github.com/nodejs/node/pull/56460 Reviewed-By: Yagiz Nizipli Reviewed-By: Antoine du Hamel --- doc/api/crypto.md | 14 +++++++++++ src/crypto/crypto_random.cc | 40 ++++++++++++++++++++++-------- test/parallel/test-crypto-prime.js | 16 ++++++++++++ 3 files changed, 59 insertions(+), 11 deletions(-) diff --git a/doc/api/crypto.md b/doc/api/crypto.md index 37ffb72d810e72..33c6283171fc2b 100644 --- a/doc/api/crypto.md +++ b/doc/api/crypto.md @@ -3933,6 +3933,13 @@ By default, the prime is encoded as a big-endian sequence of octets in an {ArrayBuffer}. If the `bigint` option is `true`, then a {bigint} is provided. +The `size` of the prime will have a direct impact on how long it takes to +generate the prime. The larger the size, the longer it will take. Because +we use OpenSSL's `BN_generate_prime_ex` function, which provides only +minimal control over our ability to interrupt the generation process, +it is not recommended to generate overly large primes, as doing so may make +the process unresponsive. + ### `crypto.generatePrimeSync(size[, options])` + +* `value` {any} A value to serialize to a string. If Node.js was started with + the [`--test-update-snapshots`][] flag, the serialized value is written to + `path`. Otherwise, the serialized value is compared to the contents of the + existing snapshot file. +* `path` {string} The file where the serialized `value` is written. +* `options` {Object} Optional configuration options. The following properties + are supported: + * `serializers` {Array} An array of synchronous functions used to serialize + `value` into a string. `value` is passed as the only argument to the first + serializer function. The return value of each serializer is passed as input + to the next serializer. Once all serializers have run, the resulting value + is coerced to a string. **Default:** If no serializers are provided, the + test runner's default serializers are used. + +This function serializes `value` and writes it to the file specified by `path`. + +```js +test('snapshot test with default serialization', (t) => { + t.assert.fileSnapshot({ value1: 1, value2: 2 }, './snapshots/snapshot.json'); +}); +``` + +This function differs from `context.assert.snapshot()` in the following ways: + +* The snapshot file path is explicitly provided by the user. +* Each snapshot file is limited to a single snapshot value. +* No additional escaping is performed by the test runner. + +These differences allow snapshot files to better support features such as syntax +highlighting. + #### `context.assert.snapshot(value[, options])` + +> Stability: 1.2 - Release candidate + +Disable the ability of starting a debugging session by sending a +`SIGUSR1` signal to the process. + ### `--disable-warning=code-or-type` > Stability: 1.1 - Active development @@ -1446,6 +1457,7 @@ added: v7.6.0 Set the `host:port` to be used when the inspector is activated. Useful when activating the inspector by sending the `SIGUSR1` signal. +Except when [`--disable-sigusr1`][] is passed. Default host is `127.0.0.1`. If port `0` is specified, a random available port will be used. @@ -3085,6 +3097,7 @@ one is included in the list below. * `--conditions`, `-C` * `--diagnostic-dir` * `--disable-proto` +* `--disable-sigusr1` * `--disable-warning` * `--disable-wasm-trap-handler` * `--dns-result-order` @@ -3670,6 +3683,7 @@ node --stack-trace-limit=12 -p -e "Error.stackTraceLimit" # prints 12 [`--build-snapshot`]: #--build-snapshot [`--cpu-prof-dir`]: #--cpu-prof-dir [`--diagnostic-dir`]: #--diagnostic-dirdirectory +[`--disable-sigusr1`]: #--disable-sigusr1 [`--env-file-if-exists`]: #--env-file-if-existsconfig [`--env-file`]: #--env-fileconfig [`--experimental-default-type=module`]: #--experimental-default-typetype diff --git a/src/env-inl.h b/src/env-inl.h index c460018af954e6..49c3513ee9b67b 100644 --- a/src/env-inl.h +++ b/src/env-inl.h @@ -691,7 +691,8 @@ inline bool Environment::no_global_search_paths() const { } inline bool Environment::should_start_debug_signal_handler() const { - return (flags_ & EnvironmentFlags::kNoStartDebugSignalHandler) == 0; + return ((flags_ & EnvironmentFlags::kNoStartDebugSignalHandler) == 0) && + !options_->disable_sigusr1; } inline bool Environment::no_browser_globals() const { diff --git a/src/node_options.cc b/src/node_options.cc index 12d62e40f6e9f0..5726b749e829a4 100644 --- a/src/node_options.cc +++ b/src/node_options.cc @@ -389,6 +389,11 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { " (default: current working directory)", &EnvironmentOptions::diagnostic_dir, kAllowedInEnvvar); + AddOption("--disable-sigusr1", + "Disable inspector thread to be listening for SIGUSR1 signal", + &EnvironmentOptions::disable_sigusr1, + kAllowedInEnvvar, + false); AddOption("--dns-result-order", "set default value of verbatim in dns.lookup. Options are " "'ipv4first' (IPv4 addresses are placed before IPv6 addresses) " diff --git a/src/node_options.h b/src/node_options.h index ab6ea77b2e9ce5..621f5eca96b106 100644 --- a/src/node_options.h +++ b/src/node_options.h @@ -116,6 +116,7 @@ class EnvironmentOptions : public Options { bool abort_on_uncaught_exception = false; std::vector conditions; bool detect_module = true; + bool disable_sigusr1 = false; bool print_required_tla = false; bool require_module = true; std::string dns_result_order; diff --git a/test/fixtures/disable-signal/sigusr1.js b/test/fixtures/disable-signal/sigusr1.js new file mode 100644 index 00000000000000..b4deb246c8cc45 --- /dev/null +++ b/test/fixtures/disable-signal/sigusr1.js @@ -0,0 +1,2 @@ +console.log('pid is', process.pid); +setInterval(() => {}, 1000); \ No newline at end of file diff --git a/test/parallel/test-disable-sigusr1.js b/test/parallel/test-disable-sigusr1.js new file mode 100644 index 00000000000000..e1d15a25ee6505 --- /dev/null +++ b/test/parallel/test-disable-sigusr1.js @@ -0,0 +1,26 @@ +'use strict'; + +const common = require('../common'); +const fixtures = require('../common/fixtures'); +const { it } = require('node:test'); +const assert = require('node:assert'); +const { NodeInstance } = require('../common/inspector-helper.js'); + +common.skipIfInspectorDisabled(); + +it('should not attach a debugger with SIGUSR1', { skip: common.isWindows }, async () => { + const file = fixtures.path('disable-signal/sigusr1.js'); + const instance = new NodeInstance(['--disable-sigusr1'], undefined, file); + + instance.on('stderr', common.mustNotCall()); + const loggedPid = await new Promise((resolve) => { + instance.on('stdout', (data) => { + const matches = data.match(/pid is (\d+)/); + if (matches) resolve(Number(matches[1])); + }); + }); + + assert.ok(process.kill(instance.pid, 'SIGUSR1')); + assert.strictEqual(loggedPid, instance.pid); + assert.ok(await instance.kill()); +}); From 1950fbf51da2f01f15a928778ae489ec58d45273 Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Fri, 6 Dec 2024 18:24:41 +0100 Subject: [PATCH 099/205] test: make test-crypto-hash compatible with OpenSSL > 3.4.0 OpenSSL 3.4 has a breaking change where the outputLength is now mandatory for shake* hash algorithms. https://github.com/openssl/openssl/commit/b911fef216d1386210ec24e201d54d709528abb4 PR-URL: https://github.com/nodejs/node/pull/56160 Refs: https://github.com/nodejs/node/issues/56159 Reviewed-By: Antoine du Hamel Reviewed-By: Luigi Pinca Reviewed-By: James M Snell Reviewed-By: Richard Lau --- test/parallel/test-crypto-hash.js | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/test/parallel/test-crypto-hash.js b/test/parallel/test-crypto-hash.js index 83218c105a4596..ca8f630b4bb7e7 100644 --- a/test/parallel/test-crypto-hash.js +++ b/test/parallel/test-crypto-hash.js @@ -7,6 +7,7 @@ const assert = require('assert'); const crypto = require('crypto'); const fs = require('fs'); +const { hasOpenSSL } = common; const fixtures = require('../common/fixtures'); let cryptoType; @@ -182,19 +183,21 @@ assert.throws( // Test XOF hash functions and the outputLength option. { - // Default outputLengths. - assert.strictEqual(crypto.createHash('shake128').digest('hex'), - '7f9c2ba4e88f827d616045507605853e'); - assert.strictEqual(crypto.createHash('shake128', null).digest('hex'), - '7f9c2ba4e88f827d616045507605853e'); - assert.strictEqual(crypto.createHash('shake256').digest('hex'), - '46b9dd2b0ba88d13233b3feb743eeb24' + - '3fcd52ea62b81b82b50c27646ed5762f'); - assert.strictEqual(crypto.createHash('shake256', { outputLength: 0 }) - .copy() // Default outputLength. - .digest('hex'), - '46b9dd2b0ba88d13233b3feb743eeb24' + - '3fcd52ea62b81b82b50c27646ed5762f'); + // Default outputLengths. Since OpenSSL 3.4 an outputLength is mandatory + if (!hasOpenSSL(3, 4)) { + assert.strictEqual(crypto.createHash('shake128').digest('hex'), + '7f9c2ba4e88f827d616045507605853e'); + assert.strictEqual(crypto.createHash('shake128', null).digest('hex'), + '7f9c2ba4e88f827d616045507605853e'); + assert.strictEqual(crypto.createHash('shake256').digest('hex'), + '46b9dd2b0ba88d13233b3feb743eeb24' + + '3fcd52ea62b81b82b50c27646ed5762f'); + assert.strictEqual(crypto.createHash('shake256', { outputLength: 0 }) + .copy() // Default outputLength. + .digest('hex'), + '46b9dd2b0ba88d13233b3feb743eeb24' + + '3fcd52ea62b81b82b50c27646ed5762f'); + } // Short outputLengths. assert.strictEqual(crypto.createHash('shake128', { outputLength: 0 }) From 2dc4a30e19da9e98db8167f65e7894bfe5f8d21d Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Fri, 6 Dec 2024 19:14:16 +0100 Subject: [PATCH 100/205] test: disable openssl 3.4.0 incompatible tests The shake128/shake256 hashing algorithms broke due to an OpenSSL 3.4 incompatible change and now throws an Error. PR-URL: https://github.com/nodejs/node/pull/56160 Refs: https://github.com/nodejs/node/issues/56159 Reviewed-By: Antoine du Hamel Reviewed-By: Luigi Pinca Reviewed-By: James M Snell Reviewed-By: Richard Lau --- test/parallel/test-crypto-oneshot-hash.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/parallel/test-crypto-oneshot-hash.js b/test/parallel/test-crypto-oneshot-hash.js index 56b4c04a65a1c1..69051c43d9e882 100644 --- a/test/parallel/test-crypto-oneshot-hash.js +++ b/test/parallel/test-crypto-oneshot-hash.js @@ -31,6 +31,9 @@ const methods = crypto.getHashes(); const input = fs.readFileSync(fixtures.path('utf8_test_text.txt')); for (const method of methods) { + // Skip failing tests on OpenSSL 3.4.0 + if (method.startsWith('shake') && common.hasOpenSSL(3, 4)) + continue; for (const outputEncoding of ['buffer', 'hex', 'base64', undefined]) { const oldDigest = crypto.createHash(method).update(input).digest(outputEncoding || 'hex'); const digestFromBuffer = crypto.hash(method, input, outputEncoding); From 12a2cae9e5a74606d36253b647d472e34c2c50e6 Mon Sep 17 00:00:00 2001 From: Colin Ihrig Date: Mon, 13 Jan 2025 15:51:55 -0500 Subject: [PATCH 101/205] test: update test-child-process-bad-stdio to use node:test This commit updates test/parallel/test-child-process-bad-stdio.js to use node:test. This change prevents multiple child processes from being spawned in parallel, which can be problematic in the CI. PR-URL: https://github.com/nodejs/node/pull/56562 Reviewed-By: Jake Yuesong Li Reviewed-By: James M Snell Reviewed-By: Yagiz Nizipli --- test/parallel/test-child-process-bad-stdio.js | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/test/parallel/test-child-process-bad-stdio.js b/test/parallel/test-child-process-bad-stdio.js index 90e8ddd0215a2b..b612fc832281a6 100644 --- a/test/parallel/test-child-process-bad-stdio.js +++ b/test/parallel/test-child-process-bad-stdio.js @@ -1,21 +1,23 @@ 'use strict'; // Flags: --expose-internals const common = require('../common'); -const assert = require('assert'); -const cp = require('child_process'); if (process.argv[2] === 'child') { setTimeout(() => {}, common.platformTimeout(100)); return; } +const assert = require('node:assert'); +const cp = require('node:child_process'); +const { mock, test } = require('node:test'); +const { ChildProcess } = require('internal/child_process'); + // Monkey patch spawn() to create a child process normally, but destroy the // stdout and stderr streams. This replicates the conditions where the streams // cannot be properly created. -const ChildProcess = require('internal/child_process').ChildProcess; const original = ChildProcess.prototype.spawn; -ChildProcess.prototype.spawn = function() { +mock.method(ChildProcess.prototype, 'spawn', function() { const err = original.apply(this, arguments); this.stdout.destroy(); @@ -24,7 +26,7 @@ ChildProcess.prototype.spawn = function() { this.stderr = null; return err; -}; +}); function createChild(options, callback) { const [cmd, opts] = common.escapePOSIXShell`"${process.execPath}" "${__filename}" child`; @@ -33,32 +35,32 @@ function createChild(options, callback) { return cp.exec(cmd, options, common.mustCall(callback)); } -// Verify that normal execution of a child process is handled. -{ +test('normal execution of a child process is handled', (_, done) => { createChild({}, (err, stdout, stderr) => { assert.strictEqual(err, null); assert.strictEqual(stdout, ''); assert.strictEqual(stderr, ''); + done(); }); -} +}); -// Verify that execution with an error event is handled. -{ +test('execution with an error event is handled', (_, done) => { const error = new Error('foo'); const child = createChild({}, (err, stdout, stderr) => { assert.strictEqual(err, error); assert.strictEqual(stdout, ''); assert.strictEqual(stderr, ''); + done(); }); child.emit('error', error); -} +}); -// Verify that execution with a killed process is handled. -{ +test('execution with a killed process is handled', (_, done) => { createChild({ timeout: 1 }, (err, stdout, stderr) => { assert.strictEqual(err.killed, true); assert.strictEqual(stdout, ''); assert.strictEqual(stderr, ''); + done(); }); -} +}); From 1641a28930c731917181aeb95c8e090e2c7c06fb Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Mon, 13 Jan 2025 22:39:25 +0100 Subject: [PATCH 102/205] doc: document CLI way to open the nodejs/bluesky PR PR-URL: https://github.com/nodejs/node/pull/56506 Reviewed-By: James M Snell Reviewed-By: Michael Dawson Reviewed-By: Ruy Adorno --- doc/contributing/releases.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/doc/contributing/releases.md b/doc/contributing/releases.md index b3b20b8ae5589e..40ba96da602033 100644 --- a/doc/contributing/releases.md +++ b/doc/contributing/releases.md @@ -1102,6 +1102,22 @@ The post content can be as simple as: > … > something here about notable changes +You can create the PR for the release post on nodejs/bluesky with the following: + +```bash +# Create a PR for a post: +gh workflow run create-pr.yml --repo "https://github.com/nodejs/bluesky" \ + -F prTitle='vx.x.x release announcement' \ + -F richText='Node.js vx.x.x is out. Check the blog post at https://nodejs.org/…. TL;DR is + +- New feature +- …' + +# Create a PR for a retweet: +gh workflow run create-pr.yml --repo "https://github.com/nodejs/bluesky" \ + -F prTitle='Retweet vx.x.x release announcement' -F postURL=… +``` +
Security release From 890eef20a1c5766d5adb52a0782788c4ef1503e7 Mon Sep 17 00:00:00 2001 From: Santiago Gimeno Date: Sat, 11 Jan 2025 14:17:38 +0100 Subject: [PATCH 103/205] crypto: fix checkPrime crash with large buffers Fixes: https://github.com/nodejs/node/issues/56512 PR-URL: https://github.com/nodejs/node/pull/56559 Reviewed-By: Colin Ihrig Reviewed-By: James M Snell Reviewed-By: Joyee Cheung --- src/crypto/crypto_random.cc | 5 +++++ test/parallel/test-crypto-prime.js | 13 +++++++++++++ 2 files changed, 18 insertions(+) diff --git a/src/crypto/crypto_random.cc b/src/crypto/crypto_random.cc index a6a206455b52c3..0c26834de3126c 100644 --- a/src/crypto/crypto_random.cc +++ b/src/crypto/crypto_random.cc @@ -176,6 +176,11 @@ Maybe CheckPrimeTraits::AdditionalConfig( ArrayBufferOrViewContents candidate(args[offset]); params->candidate = BignumPointer(candidate.data(), candidate.size()); + if (!params->candidate) { + ThrowCryptoError( + Environment::GetCurrent(args), ERR_get_error(), "BignumPointer"); + return Nothing(); + } CHECK(args[offset + 1]->IsInt32()); // Checks params->checks = args[offset + 1].As()->Value(); diff --git a/test/parallel/test-crypto-prime.js b/test/parallel/test-crypto-prime.js index 2e7edb9074d090..5ffdc1394282be 100644 --- a/test/parallel/test-crypto-prime.js +++ b/test/parallel/test-crypto-prime.js @@ -254,6 +254,19 @@ for (const checks of [-(2 ** 31), -1, 2 ** 31, 2 ** 32 - 1, 2 ** 32, 2 ** 50]) { }); } +{ + const bytes = Buffer.alloc(67108864); + bytes[0] = 0x1; + assert.throws(() => checkPrime(bytes, common.mustNotCall()), { + code: 'ERR_OSSL_BN_BIGNUM_TOO_LONG', + message: /bignum too long/ + }); + assert.throws(() => checkPrimeSync(bytes), { + code: 'ERR_OSSL_BN_BIGNUM_TOO_LONG', + message: /bignum too long/ + }); +} + assert(!checkPrimeSync(Buffer.from([0x1]))); assert(checkPrimeSync(Buffer.from([0x2]))); assert(checkPrimeSync(Buffer.from([0x3]))); From 82a9000e9e4b0e64aa565f3a9a54ca13cae74180 Mon Sep 17 00:00:00 2001 From: "Node.js GitHub Bot" Date: Mon, 13 Jan 2025 19:55:57 -0500 Subject: [PATCH 104/205] crypto: update root certificates to NSS 3.107 This is the certdata.txt[0] from NSS 3.107. This is the version of NSS that shipped in Firefox 134.0 on 2025-01-07. Certificates removed: - SecureSign RootCA11 - Entrust Root Certification Authority - G4 - Security Communication RootCA3 [0] https://raw.githubusercontent.com/nss-dev/nss/refs/tags/NSS_3_107_RTM/lib/ckfw/builtins/certdata.txt PR-URL: https://github.com/nodejs/node/pull/56566 Reviewed-By: Luigi Pinca Reviewed-By: Richard Lau Reviewed-By: James M Snell --- src/node_root_certs.h | 86 ----------- tools/certdata.txt | 343 ++++-------------------------------------- 2 files changed, 33 insertions(+), 396 deletions(-) diff --git a/src/node_root_certs.h b/src/node_root_certs.h index 2c8670be39e586..ee229fc7740627 100644 --- a/src/node_root_certs.h +++ b/src/node_root_certs.h @@ -569,27 +569,6 @@ "dZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E=\n" "-----END CERTIFICATE-----", -/* SecureSign RootCA11 */ -"-----BEGIN CERTIFICATE-----\n" -"MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDErMCkGA1UE\n" -"ChMiSmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoGA1UEAxMTU2VjdXJl\n" -"U2lnbiBSb290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0MDgwNDU2NDdaMFgxCzAJBgNV\n" -"BAYTAkpQMSswKQYDVQQKEyJKYXBhbiBDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzLCBJbmMuMRww\n" -"GgYDVQQDExNTZWN1cmVTaWduIFJvb3RDQTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB\n" -"CgKCAQEA/XeqpRyQBTvLTJszi1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1y\n" -"fIw/XwFndBWW4wI8h9uuywGOwvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyK\n" -"yiyhFTOVMdrAG/LuYpmGYz+/3ZMqg6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9\n" -"UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rPO7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni8McDWc/V\n" -"1uinMrPmmECGxc0nEovMe863ETxiYAcjPitAbpSACW22s293bzUIUPsCh8U+iQIDAQABo0Iw\n" -"QDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZXt94wDgYDVR0PAQH/BAQDAgEGMA8GA1Ud\n" -"EwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAKChOBZmLqdWHyGcBvod7bkixTgm2E5P\n" -"7KN/ed5GIaGHd48HCJqypMWvDzKYC3xmKbabfSVSSUOrTC4rbnpwrxYO4wJs+0LmGJ1F2FXI\n" -"6Dvd5+H0LgscNFxsWEr7jIhQX5Ucv+2rIrVls4W6ng+4reV6G4pQOh29Dbx7VFALuUKvVaAY\n" -"ga1lme++5Jy/xIWrQbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01y8hSyn+B/tlr0/cR\n" -"7SXf+Of5pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061lgeLKBObjBmN\n" -"QSdJQO7e5iNEOdyhIta6A/I=\n" -"-----END CERTIFICATE-----", - /* Microsec e-Szigno Root CA 2009 */ "-----BEGIN CERTIFICATE-----\n" "MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYDVQQGEwJI\n" @@ -2310,40 +2289,6 @@ "UvToiIMrVCjU8jVStDKDYmlkDJGcn5fqdBb9HxEGmpv0\n" "-----END CERTIFICATE-----", -/* Entrust Root Certification Authority - G4 */ -"-----BEGIN CERTIFICATE-----\n" -"MIIGSzCCBDOgAwIBAgIRANm1Q3+vqTkPAAAAAFVlrVgwDQYJKoZIhvcNAQELBQAwgb4xCzAJ\n" -"BgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVu\n" -"dHJ1c3QubmV0L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxNSBFbnRydXN0LCBJbmMu\n" -"IC0gZm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMjAwBgNVBAMTKUVudHJ1c3QgUm9vdCBDZXJ0\n" -"aWZpY2F0aW9uIEF1dGhvcml0eSAtIEc0MB4XDTE1MDUyNzExMTExNloXDTM3MTIyNzExNDEx\n" -"Nlowgb4xCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9T\n" -"ZWUgd3d3LmVudHJ1c3QubmV0L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxNSBFbnRy\n" -"dXN0LCBJbmMuIC0gZm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMjAwBgNVBAMTKUVudHJ1c3Qg\n" -"Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEc0MIICIjANBgkqhkiG9w0BAQEFAAOC\n" -"Ag8AMIICCgKCAgEAsewsQu7i0TD/pZJH4i3DumSXbcr3DbVZwbPLqGgZ2K+EbTBwXX7zLtJT\n" -"meH+H17ZSK9dE43b/2MzTdMAArzE+NEGCJR5WIoV3imz/f3ET+iq4qA7ec2/a0My3dl0ELn3\n" -"9GjUu9CH1apLiipvKgS1sqbHoHrmSKvS0VnM1n4j5pds8ELl3FFLFUHtSUrJ3hCX1nbB76W1\n" -"NhSXNdh4IjVS70O92yfbYVaCNNzLiGAMC1rlLAHGVK/XqsEQe9IFWrhAnoanw5CGAlZSCXqc\n" -"0ieCU0plUmr1POeo8pyvi73TDtTUXm6Hnmo9RR3RXRv06QqsYJn7ibT/mCzPfB3pAqoEmh64\n" -"3IhuJbNsZvc8kPNXwbMv9W3y+8qh+CmdRouzavbmZwe+LGcKKh9asj5XxNMhIWNlUpEbsZmO\n" -"eX7m640A2Vqq6nPopIICR5b+W45UYaPrL0swsIsjdXJ8ITzI9vF01Bx7owVV7rtNOzK+mndm\n" -"nqxpkCIHH2E6lr7lmk/MBTwoWdPBDFSoWWG9yHJM6Nyfh3+9nEg2XpWjDrk4JFX8dWbrAuMI\n" -"NClKxuMrLzOg2qOGpRKX/YAr2hRC45K9PvJdXmd0LhyIRyk0X+IyqJwlN4y6mACXi0mWHv0l\n" -"iqzc2thddG5msP9E36EYxr5ILzeUePiVSj9/E15dWf10hkNjc0kCAwEAAaNCMEAwDwYDVR0T\n" -"AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJ84xFYjwznooHFs6FRM5Og6\n" -"sb9nMA0GCSqGSIb3DQEBCwUAA4ICAQAS5UKme4sPDORGpbZgQIeMJX6tuGguW8ZAdjwD+MlZ\n" -"9POrYs4QjbRaZIxowLByQzTSGwv2LFPSypBLhmb8qoMi9IsabyZIrHZ3CL/FmFz0Jomee8O5\n" -"ZDIBf9PD3Vht7LGrhFV0d4QEJ1JrhkzO3bll/9bGXp+aEJlLdWr+aumXIOTkdnrG0CSqkM0g\n" -"kLpHZPt/B7NTeLUKYvJzQ85BK4FqLoUWlFPUa19yIqtRLULVAJyZv967lDtX/Zr1hstWO1uI\n" -"AeV8KEsD+UmDfLJ/fOPtjqF/YFOOVZ1QNBIPt5d7bIdKROf1beyAN/BYGW5KaHbwH5Lk6rWS\n" -"02FREAutp9lfx1/cH6NcjKF+m7ee01ZvZl4HliDtC3T7Zk6LERXpgUl+b7DUUH8i119lAg2m\n" -"9IUe2K4GS0qn0jFmwvjO5QimpAKWRGhXxNUzzxkvFMSUHHuk2fCfDrGA4tGeEWSpiBE6doLl\n" -"YsKA2KSD7ZPvfC+QsDJMlhVoSFLUmQjAJOgc47OlIQ6SwJAfzyBfyjs4x7dtOvPmRLgOMWuI\n" -"jnDrnBdSqEGULoe256YSxXXfW8AKbnuk5F6G+TaU33fD6Q3AOfF5u0aOq0NZJ7cguyPpVkAh\n" -"7DE9ZapD8j3fcEThuk0mEDuYn/PIjhs4ViFqUZPTkcpG2om3PVODLAgfi49T3f+sHw==\n" -"-----END CERTIFICATE-----", - /* Microsoft ECC Root Certificate Authority 2017 */ "-----BEGIN CERTIFICATE-----\n" "MIICWTCCAd+gAwIBAgIQZvI9r4fei7FK6gxXMQHC7DAKBggqhkjOPQQDAzBlMQswCQYDVQQG\n" @@ -3161,37 +3106,6 @@ "Nzf43TNRnXCve1XYAS59BWQOhriR\n" "-----END CERTIFICATE-----", -/* Security Communication RootCA3 */ -"-----BEGIN CERTIFICATE-----\n" -"MIIFfzCCA2egAwIBAgIJAOF8N0D9G/5nMA0GCSqGSIb3DQEBDAUAMF0xCzAJBgNVBAYTAkpQ\n" -"MSUwIwYDVQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMScwJQYDVQQDEx5TZWN1\n" -"cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTMwHhcNMTYwNjE2MDYxNzE2WhcNMzgwMTE4MDYx\n" -"NzE2WjBdMQswCQYDVQQGEwJKUDElMCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4s\n" -"TFRELjEnMCUGA1UEAxMeU2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBSb290Q0EzMIICIjANBgkq\n" -"hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA48lySfcw3gl8qUCBWNO0Ot26YQ+TUG5pPDXC7ltz\n" -"kBtnTCHsXzW7OT4rCmDvu20rhvtxosis5FaU+cmvsXLUIKx00rgVrVH+hXShuRD+BYD5UpOz\n" -"QD11EKzAlrenfna84xtSGc4RHwsENPXY9Wk8d/Nk9A2qhd7gCVAEF5aEt8iKvE1y/By7z/MG\n" -"TfmfZPd+pmaGNXHIEYBMwXFAWB6+oHP2/D5Q4eAvJj1+XCO1eXDe+uDRpdYMQXF79+qMHIjH\n" -"7Iv10S9VlkZ8WjtYO/u62C21Jdp6Ts9EriGmnpjKIG58u4iFW/vAEGK78vknR+/RiTlDxN/e\n" -"4UG/VHMgly1s2vPUB6PmudhvrvyMGS7TZ2crldtYXLVqAvO4g160a75BflcJdURQVc1aEWEh\n" -"CmHCqYj9E7wtiS/NYeCVvsq1e+F7NGcLH7YMx3weGVPKp7FKFSBWFHA9K4IsD50VHUeAR/94\n" -"mQ4xr28+j+2GaR57GIgUssL8gjMunEst+3A7caoreyYn8xrC3PsXuKHqy6C0rtOUfnrQq8Ps\n" -"OC0RLoi/1D+tEjtCrI8Cbn3M0V9hvqG8OmpI6iZVIhZdXw3/JzOfGAN0iltSIEdrRU0id4xV\n" -"J/CvHozJgyJUt5rQT9nO/NkuHJYosQLTA70lUhw0Zk8jq/R3gpYd0VcwCBEF/VfR2ccCAwEA\n" -"AaNCMEAwHQYDVR0OBBYEFGQUfPxYchamCik0FW8qy7z8r6irMA4GA1UdDwEB/wQEAwIBBjAP\n" -"BgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBDAUAA4ICAQDcAiMI4u8hOscNtybSYpOnpSNy\n" -"ByCCYN8Y11StaSWSntkUz5m5UoHPrmyKO1o5yGwBQ8IibQLwYs1OY0PAFNr0Y/Dq9HHuTofj\n" -"can0yVflLl8cebsjqodEV+m9NU1Bu0soo5iyG9kLFwfl9+qd9XbXv8S2gVj/yP9kaWJ5rW4O\n" -"H3/uHWnlt3Jxs/6lATWUVCvAUm2PVcTJ0rjLyjQIUYWg9by0F1jqClx6vWPGOi//lkkZhOpn\n" -"2ASxYfQAW0q3nHE3GYV5v4GwxxMOdnE+OoAGrgYWp421wsTL/0ClXI2lyTrtcoHKXJg80jQD\n" -"dwj98ClZXSEIx2C/pHF7uNkegr4Jr2VvKKu/S7XuPghHJ6APbw+LP6yVGPO5DtxnVW5inkYO\n" -"0QR4ynKudtml+LLfiAlhi+8kTtFZP1rUPcmTPCtk9YENFpb3ksP+MW/oKjJ0DvRMmEoYDjBU\n" -"1cXrvMUVnuiZIesnKwkK2/HmcBhWuwzkvvnoEKQTkrgc4NtnHVMDpCKn3F2SEDzq//wbEBrD\n" -"2NCcnWXL0CsnMQMeNuE9dnUM/0Umud1RvCPHX9jYhxBAEg09ODfnRDwYwFMJZI//1ZqmfHAu\n" -"c1Uh6N//g7kdPjIe1qZ9LPFm6Vwdp6POXiUyK+OVrCoHzrQoeIY8LaadTdJ0MN1kURXbg4NR\n" -"16/9M51NZg==\n" -"-----END CERTIFICATE-----", - /* Security Communication ECC RootCA1 */ "-----BEGIN CERTIFICATE-----\n" "MIICODCCAb6gAwIBAgIJANZdm7N4gS7rMAoGCCqGSM49BAMDMGExCzAJBgNVBAYTAkpQMSUw\n" diff --git a/tools/certdata.txt b/tools/certdata.txt index 110a814718cfd7..e0f60abcd6cf62 100644 --- a/tools/certdata.txt +++ b/tools/certdata.txt @@ -323,7 +323,10 @@ CKA_VALUE MULTILINE_OCTAL \174\136\232\166\351\131\220\305\174\203\065\021\145\121 END CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE -CKA_NSS_SERVER_DISTRUST_AFTER CK_BBOOL CK_FALSE +# For Server Distrust After: Sat Nov 30 23:59:59 2024 +CKA_NSS_SERVER_DISTRUST_AFTER MULTILINE_OCTAL +\062\064\061\061\063\060\062\063\065\071\065\071\132 +END CKA_NSS_EMAIL_DISTRUST_AFTER CK_BBOOL CK_FALSE # Trust for "Entrust.net Premium 2048 Secure Server CA" @@ -627,7 +630,10 @@ CKA_VALUE MULTILINE_OCTAL \036\177\132\264\074 END CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE -CKA_NSS_SERVER_DISTRUST_AFTER CK_BBOOL CK_FALSE +# For Server Distrust After: Sat Nov 30 23:59:59 2024 +CKA_NSS_SERVER_DISTRUST_AFTER MULTILINE_OCTAL +\062\064\061\061\063\060\062\063\065\071\065\071\132 +END CKA_NSS_EMAIL_DISTRUST_AFTER CK_BBOOL CK_FALSE # Trust for "Entrust Root Certification Authority" @@ -3808,140 +3814,6 @@ CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE -# -# Certificate "SecureSign RootCA11" -# -# Issuer: CN=SecureSign RootCA11,O="Japan Certification Services, Inc.",C=JP -# Serial Number: 1 (0x1) -# Subject: CN=SecureSign RootCA11,O="Japan Certification Services, Inc.",C=JP -# Not Valid Before: Wed Apr 08 04:56:47 2009 -# Not Valid After : Sun Apr 08 04:56:47 2029 -# Fingerprint (SHA-256): BF:0F:EE:FB:9E:3A:58:1A:D5:F9:E9:DB:75:89:98:57:43:D2:61:08:5C:4D:31:4F:6F:5D:72:59:AA:42:16:12 -# Fingerprint (SHA1): 3B:C4:9F:48:F8:F3:73:A0:9C:1E:BD:F8:5B:B1:C3:65:C7:D8:11:B3 -CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE -CKA_TOKEN CK_BBOOL CK_TRUE -CKA_PRIVATE CK_BBOOL CK_FALSE -CKA_MODIFIABLE CK_BBOOL CK_FALSE -CKA_LABEL UTF8 "SecureSign RootCA11" -CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509 -CKA_SUBJECT MULTILINE_OCTAL -\060\130\061\013\060\011\006\003\125\004\006\023\002\112\120\061 -\053\060\051\006\003\125\004\012\023\042\112\141\160\141\156\040 -\103\145\162\164\151\146\151\143\141\164\151\157\156\040\123\145 -\162\166\151\143\145\163\054\040\111\156\143\056\061\034\060\032 -\006\003\125\004\003\023\023\123\145\143\165\162\145\123\151\147 -\156\040\122\157\157\164\103\101\061\061 -END -CKA_ID UTF8 "0" -CKA_ISSUER MULTILINE_OCTAL -\060\130\061\013\060\011\006\003\125\004\006\023\002\112\120\061 -\053\060\051\006\003\125\004\012\023\042\112\141\160\141\156\040 -\103\145\162\164\151\146\151\143\141\164\151\157\156\040\123\145 -\162\166\151\143\145\163\054\040\111\156\143\056\061\034\060\032 -\006\003\125\004\003\023\023\123\145\143\165\162\145\123\151\147 -\156\040\122\157\157\164\103\101\061\061 -END -CKA_SERIAL_NUMBER MULTILINE_OCTAL -\002\001\001 -END -CKA_VALUE MULTILINE_OCTAL -\060\202\003\155\060\202\002\125\240\003\002\001\002\002\001\001 -\060\015\006\011\052\206\110\206\367\015\001\001\005\005\000\060 -\130\061\013\060\011\006\003\125\004\006\023\002\112\120\061\053 -\060\051\006\003\125\004\012\023\042\112\141\160\141\156\040\103 -\145\162\164\151\146\151\143\141\164\151\157\156\040\123\145\162 -\166\151\143\145\163\054\040\111\156\143\056\061\034\060\032\006 -\003\125\004\003\023\023\123\145\143\165\162\145\123\151\147\156 -\040\122\157\157\164\103\101\061\061\060\036\027\015\060\071\060 -\064\060\070\060\064\065\066\064\067\132\027\015\062\071\060\064 -\060\070\060\064\065\066\064\067\132\060\130\061\013\060\011\006 -\003\125\004\006\023\002\112\120\061\053\060\051\006\003\125\004 -\012\023\042\112\141\160\141\156\040\103\145\162\164\151\146\151 -\143\141\164\151\157\156\040\123\145\162\166\151\143\145\163\054 -\040\111\156\143\056\061\034\060\032\006\003\125\004\003\023\023 -\123\145\143\165\162\145\123\151\147\156\040\122\157\157\164\103 -\101\061\061\060\202\001\042\060\015\006\011\052\206\110\206\367 -\015\001\001\001\005\000\003\202\001\017\000\060\202\001\012\002 -\202\001\001\000\375\167\252\245\034\220\005\073\313\114\233\063 -\213\132\024\105\244\347\220\026\321\337\127\322\041\020\244\027 -\375\337\254\326\037\247\344\333\174\367\354\337\270\003\332\224 -\130\375\135\162\174\214\077\137\001\147\164\025\226\343\002\074 -\207\333\256\313\001\216\302\363\146\306\205\105\364\002\306\072 -\265\142\262\257\372\234\277\244\346\324\200\060\230\363\015\266 -\223\217\251\324\330\066\362\260\374\212\312\054\241\025\063\225 -\061\332\300\033\362\356\142\231\206\143\077\277\335\223\052\203 -\250\166\271\023\037\267\316\116\102\205\217\042\347\056\032\362 -\225\011\262\005\265\104\116\167\241\040\275\251\362\116\012\175 -\120\255\365\005\015\105\117\106\161\375\050\076\123\373\004\330 -\055\327\145\035\112\033\372\317\073\260\061\232\065\156\310\213 -\006\323\000\221\362\224\010\145\114\261\064\006\000\172\211\342 -\360\307\003\131\317\325\326\350\247\062\263\346\230\100\206\305 -\315\047\022\213\314\173\316\267\021\074\142\140\007\043\076\053 -\100\156\224\200\011\155\266\263\157\167\157\065\010\120\373\002 -\207\305\076\211\002\003\001\000\001\243\102\060\100\060\035\006 -\003\125\035\016\004\026\004\024\133\370\115\117\262\245\206\324 -\072\322\361\143\232\240\276\011\366\127\267\336\060\016\006\003 -\125\035\017\001\001\377\004\004\003\002\001\006\060\017\006\003 -\125\035\023\001\001\377\004\005\060\003\001\001\377\060\015\006 -\011\052\206\110\206\367\015\001\001\005\005\000\003\202\001\001 -\000\240\241\070\026\146\056\247\126\037\041\234\006\372\035\355 -\271\042\305\070\046\330\116\117\354\243\177\171\336\106\041\241 -\207\167\217\007\010\232\262\244\305\257\017\062\230\013\174\146 -\051\266\233\175\045\122\111\103\253\114\056\053\156\172\160\257 -\026\016\343\002\154\373\102\346\030\235\105\330\125\310\350\073 -\335\347\341\364\056\013\034\064\134\154\130\112\373\214\210\120 -\137\225\034\277\355\253\042\265\145\263\205\272\236\017\270\255 -\345\172\033\212\120\072\035\275\015\274\173\124\120\013\271\102 -\257\125\240\030\201\255\145\231\357\276\344\234\277\304\205\253 -\101\262\124\157\334\045\315\355\170\342\216\014\215\011\111\335 -\143\173\132\151\226\002\041\250\275\122\131\351\175\065\313\310 -\122\312\177\201\376\331\153\323\367\021\355\045\337\370\347\371 -\244\372\162\227\204\123\015\245\320\062\030\121\166\131\024\154 -\017\353\354\137\200\214\165\103\203\303\205\230\377\114\236\055 -\015\344\167\203\223\116\265\226\007\213\050\023\233\214\031\215 -\101\047\111\100\356\336\346\043\104\071\334\241\042\326\272\003 -\362 -END -CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE -CKA_NSS_SERVER_DISTRUST_AFTER CK_BBOOL CK_FALSE -CKA_NSS_EMAIL_DISTRUST_AFTER CK_BBOOL CK_FALSE - -# Trust for "SecureSign RootCA11" -# Issuer: CN=SecureSign RootCA11,O="Japan Certification Services, Inc.",C=JP -# Serial Number: 1 (0x1) -# Subject: CN=SecureSign RootCA11,O="Japan Certification Services, Inc.",C=JP -# Not Valid Before: Wed Apr 08 04:56:47 2009 -# Not Valid After : Sun Apr 08 04:56:47 2029 -# Fingerprint (SHA-256): BF:0F:EE:FB:9E:3A:58:1A:D5:F9:E9:DB:75:89:98:57:43:D2:61:08:5C:4D:31:4F:6F:5D:72:59:AA:42:16:12 -# Fingerprint (SHA1): 3B:C4:9F:48:F8:F3:73:A0:9C:1E:BD:F8:5B:B1:C3:65:C7:D8:11:B3 -CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST -CKA_TOKEN CK_BBOOL CK_TRUE -CKA_PRIVATE CK_BBOOL CK_FALSE -CKA_MODIFIABLE CK_BBOOL CK_FALSE -CKA_LABEL UTF8 "SecureSign RootCA11" -CKA_CERT_SHA1_HASH MULTILINE_OCTAL -\073\304\237\110\370\363\163\240\234\036\275\370\133\261\303\145 -\307\330\021\263 -END -CKA_CERT_MD5_HASH MULTILINE_OCTAL -\267\122\164\342\222\264\200\223\362\165\344\314\327\362\352\046 -END -CKA_ISSUER MULTILINE_OCTAL -\060\130\061\013\060\011\006\003\125\004\006\023\002\112\120\061 -\053\060\051\006\003\125\004\012\023\042\112\141\160\141\156\040 -\103\145\162\164\151\146\151\143\141\164\151\157\156\040\123\145 -\162\166\151\143\145\163\054\040\111\156\143\056\061\034\060\032 -\006\003\125\004\003\023\023\123\145\143\165\162\145\123\151\147 -\156\040\122\157\157\164\103\101\061\061 -END -CKA_SERIAL_NUMBER MULTILINE_OCTAL -\002\001\001 -END -CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR -CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_MUST_VERIFY_TRUST -CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST -CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE - # # Certificate "Microsec e-Szigno Root CA 2009" # @@ -4939,7 +4811,10 @@ CKA_VALUE MULTILINE_OCTAL \007\072\027\144\265\004\265\043\041\231\012\225\073\227\174\357 END CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE -CKA_NSS_SERVER_DISTRUST_AFTER CK_BBOOL CK_FALSE +# For Server Distrust After: Sat Nov 30 23:59:59 2024 +CKA_NSS_SERVER_DISTRUST_AFTER MULTILINE_OCTAL +\062\064\061\061\063\060\062\063\065\071\065\071\132 +END CKA_NSS_EMAIL_DISTRUST_AFTER CK_BBOOL CK_FALSE # Trust for "AffirmTrust Commercial" @@ -5067,7 +4942,10 @@ CKA_VALUE MULTILINE_OCTAL \355\132\000\124\205\034\026\066\222\014\134\372\246\255\277\333 END CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE -CKA_NSS_SERVER_DISTRUST_AFTER CK_BBOOL CK_FALSE +# For Server Distrust After: Sat Nov 30 23:59:59 2024 +CKA_NSS_SERVER_DISTRUST_AFTER MULTILINE_OCTAL +\062\064\061\061\063\060\062\063\065\071\065\071\132 +END CKA_NSS_EMAIL_DISTRUST_AFTER CK_BBOOL CK_FALSE # Trust for "AffirmTrust Networking" @@ -5227,7 +5105,10 @@ CKA_VALUE MULTILINE_OCTAL \051\340\266\270\011\150\031\034\030\103 END CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE -CKA_NSS_SERVER_DISTRUST_AFTER CK_BBOOL CK_FALSE +# For Server Distrust After: Sat Nov 30 23:59:59 2024 +CKA_NSS_SERVER_DISTRUST_AFTER MULTILINE_OCTAL +\062\064\061\061\063\060\062\063\065\071\065\071\132 +END CKA_NSS_EMAIL_DISTRUST_AFTER CK_BBOOL CK_FALSE # Trust for "AffirmTrust Premium" @@ -5335,7 +5216,10 @@ CKA_VALUE MULTILINE_OCTAL \214\171 END CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE -CKA_NSS_SERVER_DISTRUST_AFTER CK_BBOOL CK_FALSE +# For Server Distrust After: Sat Nov 30 23:59:59 2024 +CKA_NSS_SERVER_DISTRUST_AFTER MULTILINE_OCTAL +\062\064\061\061\063\060\062\063\065\071\065\071\132 +END CKA_NSS_EMAIL_DISTRUST_AFTER CK_BBOOL CK_FALSE # Trust for "AffirmTrust Premium ECC" @@ -10269,7 +10153,10 @@ CKA_VALUE MULTILINE_OCTAL \105\366 END CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE -CKA_NSS_SERVER_DISTRUST_AFTER CK_BBOOL CK_FALSE +# For Server Distrust After: Sat Nov 30 23:59:59 2024 +CKA_NSS_SERVER_DISTRUST_AFTER MULTILINE_OCTAL +\062\064\061\061\063\060\062\063\065\071\065\071\132 +END CKA_NSS_EMAIL_DISTRUST_AFTER CK_BBOOL CK_FALSE # Trust for "Entrust Root Certification Authority - G2" @@ -10416,7 +10303,10 @@ CKA_VALUE MULTILINE_OCTAL \231\267\046\101\133\045\140\256\320\110\032\356\006 END CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE -CKA_NSS_SERVER_DISTRUST_AFTER CK_BBOOL CK_FALSE +# For Server Distrust After: Sat Nov 30 23:59:59 2024 +CKA_NSS_SERVER_DISTRUST_AFTER MULTILINE_OCTAL +\062\064\061\061\063\060\062\063\065\071\065\071\132 +END CKA_NSS_EMAIL_DISTRUST_AFTER CK_BBOOL CK_FALSE # Trust for "Entrust Root Certification Authority - EC1" @@ -15014,7 +14904,7 @@ CKA_SERIAL_NUMBER MULTILINE_OCTAL \002\021\000\331\265\103\177\257\251\071\017\000\000\000\000\125 \145\255\130 END -CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR +CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_MUST_VERIFY_TRUST CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE @@ -21228,173 +21118,6 @@ CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE -# -# Certificate "Security Communication RootCA3" -# -# Issuer: CN=Security Communication RootCA3,O="SECOM Trust Systems CO.,LTD.",C=JP -# Serial Number:00:e1:7c:37:40:fd:1b:fe:67 -# Subject: CN=Security Communication RootCA3,O="SECOM Trust Systems CO.,LTD.",C=JP -# Not Valid Before: Thu Jun 16 06:17:16 2016 -# Not Valid After : Mon Jan 18 06:17:16 2038 -# Fingerprint (SHA-256): 24:A5:5C:2A:B0:51:44:2D:06:17:76:65:41:23:9A:4A:D0:32:D7:C5:51:75:AA:34:FF:DE:2F:BC:4F:5C:52:94 -# Fingerprint (SHA1): C3:03:C8:22:74:92:E5:61:A2:9C:5F:79:91:2B:1E:44:13:91:30:3A -CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE -CKA_TOKEN CK_BBOOL CK_TRUE -CKA_PRIVATE CK_BBOOL CK_FALSE -CKA_MODIFIABLE CK_BBOOL CK_FALSE -CKA_LABEL UTF8 "Security Communication RootCA3" -CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509 -CKA_SUBJECT MULTILINE_OCTAL -\060\135\061\013\060\011\006\003\125\004\006\023\002\112\120\061 -\045\060\043\006\003\125\004\012\023\034\123\105\103\117\115\040 -\124\162\165\163\164\040\123\171\163\164\145\155\163\040\103\117 -\056\054\114\124\104\056\061\047\060\045\006\003\125\004\003\023 -\036\123\145\143\165\162\151\164\171\040\103\157\155\155\165\156 -\151\143\141\164\151\157\156\040\122\157\157\164\103\101\063 -END -CKA_ID UTF8 "0" -CKA_ISSUER MULTILINE_OCTAL -\060\135\061\013\060\011\006\003\125\004\006\023\002\112\120\061 -\045\060\043\006\003\125\004\012\023\034\123\105\103\117\115\040 -\124\162\165\163\164\040\123\171\163\164\145\155\163\040\103\117 -\056\054\114\124\104\056\061\047\060\045\006\003\125\004\003\023 -\036\123\145\143\165\162\151\164\171\040\103\157\155\155\165\156 -\151\143\141\164\151\157\156\040\122\157\157\164\103\101\063 -END -CKA_SERIAL_NUMBER MULTILINE_OCTAL -\002\011\000\341\174\067\100\375\033\376\147 -END -CKA_VALUE MULTILINE_OCTAL -\060\202\005\177\060\202\003\147\240\003\002\001\002\002\011\000 -\341\174\067\100\375\033\376\147\060\015\006\011\052\206\110\206 -\367\015\001\001\014\005\000\060\135\061\013\060\011\006\003\125 -\004\006\023\002\112\120\061\045\060\043\006\003\125\004\012\023 -\034\123\105\103\117\115\040\124\162\165\163\164\040\123\171\163 -\164\145\155\163\040\103\117\056\054\114\124\104\056\061\047\060 -\045\006\003\125\004\003\023\036\123\145\143\165\162\151\164\171 -\040\103\157\155\155\165\156\151\143\141\164\151\157\156\040\122 -\157\157\164\103\101\063\060\036\027\015\061\066\060\066\061\066 -\060\066\061\067\061\066\132\027\015\063\070\060\061\061\070\060 -\066\061\067\061\066\132\060\135\061\013\060\011\006\003\125\004 -\006\023\002\112\120\061\045\060\043\006\003\125\004\012\023\034 -\123\105\103\117\115\040\124\162\165\163\164\040\123\171\163\164 -\145\155\163\040\103\117\056\054\114\124\104\056\061\047\060\045 -\006\003\125\004\003\023\036\123\145\143\165\162\151\164\171\040 -\103\157\155\155\165\156\151\143\141\164\151\157\156\040\122\157 -\157\164\103\101\063\060\202\002\042\060\015\006\011\052\206\110 -\206\367\015\001\001\001\005\000\003\202\002\017\000\060\202\002 -\012\002\202\002\001\000\343\311\162\111\367\060\336\011\174\251 -\100\201\130\323\264\072\335\272\141\017\223\120\156\151\074\065 -\302\356\133\163\220\033\147\114\041\354\137\065\273\071\076\053 -\012\140\357\273\155\053\206\373\161\242\310\254\344\126\224\371 -\311\257\261\162\324\040\254\164\322\270\025\255\121\376\205\164 -\241\271\020\376\005\200\371\122\223\263\100\075\165\020\254\300 -\226\267\247\176\166\274\343\033\122\031\316\021\037\013\004\064 -\365\330\365\151\074\167\363\144\364\015\252\205\336\340\011\120 -\004\027\226\204\267\310\212\274\115\162\374\034\273\317\363\006 -\115\371\237\144\367\176\246\146\206\065\161\310\021\200\114\301 -\161\100\130\036\276\240\163\366\374\076\120\341\340\057\046\075 -\176\134\043\265\171\160\336\372\340\321\245\326\014\101\161\173 -\367\352\214\034\210\307\354\213\365\321\057\125\226\106\174\132 -\073\130\073\373\272\330\055\265\045\332\172\116\317\104\256\041 -\246\236\230\312\040\156\174\273\210\205\133\373\300\020\142\273 -\362\371\047\107\357\321\211\071\103\304\337\336\341\101\277\124 -\163\040\227\055\154\332\363\324\007\243\346\271\330\157\256\374 -\214\031\056\323\147\147\053\225\333\130\134\265\152\002\363\270 -\203\136\264\153\276\101\176\127\011\165\104\120\125\315\132\021 -\141\041\012\141\302\251\210\375\023\274\055\211\057\315\141\340 -\225\276\312\265\173\341\173\064\147\013\037\266\014\307\174\036 -\031\123\312\247\261\112\025\040\126\024\160\075\053\202\054\017 -\235\025\035\107\200\107\377\170\231\016\061\257\157\076\217\355 -\206\151\036\173\030\210\024\262\302\374\202\063\056\234\113\055 -\373\160\073\161\252\053\173\046\047\363\032\302\334\373\027\270 -\241\352\313\240\264\256\323\224\176\172\320\253\303\354\070\055 -\021\056\210\277\324\077\255\022\073\102\254\217\002\156\175\314 -\321\137\141\276\241\274\072\152\110\352\046\125\042\026\135\137 -\015\377\047\063\237\030\003\164\212\133\122\040\107\153\105\115 -\042\167\214\125\047\360\257\036\214\311\203\042\124\267\232\320 -\117\331\316\374\331\056\034\226\050\261\002\323\003\275\045\122 -\034\064\146\117\043\253\364\167\202\226\035\321\127\060\010\021 -\005\375\127\321\331\307\002\003\001\000\001\243\102\060\100\060 -\035\006\003\125\035\016\004\026\004\024\144\024\174\374\130\162 -\026\246\012\051\064\025\157\052\313\274\374\257\250\253\060\016 -\006\003\125\035\017\001\001\377\004\004\003\002\001\006\060\017 -\006\003\125\035\023\001\001\377\004\005\060\003\001\001\377\060 -\015\006\011\052\206\110\206\367\015\001\001\014\005\000\003\202 -\002\001\000\334\002\043\010\342\357\041\072\307\015\267\046\322 -\142\223\247\245\043\162\007\040\202\140\337\030\327\124\255\151 -\045\222\236\331\024\317\231\271\122\201\317\256\154\212\073\132 -\071\310\154\001\103\302\042\155\002\360\142\315\116\143\103\300 -\024\332\364\143\360\352\364\161\356\116\207\343\161\251\364\311 -\127\345\056\137\034\171\273\043\252\207\104\127\351\275\065\115 -\101\273\113\050\243\230\262\033\331\013\027\007\345\367\352\235 -\365\166\327\277\304\266\201\130\377\310\377\144\151\142\171\255 -\156\016\037\177\356\035\151\345\267\162\161\263\376\245\001\065 -\224\124\053\300\122\155\217\125\304\311\322\270\313\312\064\010 -\121\205\240\365\274\264\027\130\352\012\134\172\275\143\306\072 -\057\377\226\111\031\204\352\147\330\004\261\141\364\000\133\112 -\267\234\161\067\031\205\171\277\201\260\307\023\016\166\161\076 -\072\200\006\256\006\026\247\215\265\302\304\313\377\100\245\134 -\215\245\311\072\355\162\201\312\134\230\074\322\064\003\167\010 -\375\360\051\131\135\041\010\307\140\277\244\161\173\270\331\036 -\202\276\011\257\145\157\050\253\277\113\265\356\076\010\107\047 -\240\017\157\017\213\077\254\225\030\363\271\016\334\147\125\156 -\142\236\106\016\321\004\170\312\162\256\166\331\245\370\262\337 -\210\011\141\213\357\044\116\321\131\077\132\324\075\311\223\074 -\053\144\365\201\015\026\226\367\222\303\376\061\157\350\052\062 -\164\016\364\114\230\112\030\016\060\124\325\305\353\274\305\025 -\236\350\231\041\353\047\053\011\012\333\361\346\160\030\126\273 -\014\344\276\371\350\020\244\023\222\270\034\340\333\147\035\123 -\003\244\042\247\334\135\222\020\074\352\377\374\033\020\032\303 -\330\320\234\235\145\313\320\053\047\061\003\036\066\341\075\166 -\165\014\377\105\046\271\335\121\274\043\307\137\330\330\207\020 -\100\022\015\075\070\067\347\104\074\030\300\123\011\144\217\377 -\325\232\246\174\160\056\163\125\041\350\337\377\203\271\035\076 -\062\036\326\246\175\054\361\146\351\134\035\247\243\316\136\045 -\062\053\343\225\254\052\007\316\264\050\170\206\074\055\246\235 -\115\322\164\060\335\144\121\025\333\203\203\121\327\257\375\063 -\235\115\146 -END -CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_TRUE -CKA_NSS_SERVER_DISTRUST_AFTER CK_BBOOL CK_FALSE -CKA_NSS_EMAIL_DISTRUST_AFTER CK_BBOOL CK_FALSE - -# Trust for "Security Communication RootCA3" -# Issuer: CN=Security Communication RootCA3,O="SECOM Trust Systems CO.,LTD.",C=JP -# Serial Number:00:e1:7c:37:40:fd:1b:fe:67 -# Subject: CN=Security Communication RootCA3,O="SECOM Trust Systems CO.,LTD.",C=JP -# Not Valid Before: Thu Jun 16 06:17:16 2016 -# Not Valid After : Mon Jan 18 06:17:16 2038 -# Fingerprint (SHA-256): 24:A5:5C:2A:B0:51:44:2D:06:17:76:65:41:23:9A:4A:D0:32:D7:C5:51:75:AA:34:FF:DE:2F:BC:4F:5C:52:94 -# Fingerprint (SHA1): C3:03:C8:22:74:92:E5:61:A2:9C:5F:79:91:2B:1E:44:13:91:30:3A -CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST -CKA_TOKEN CK_BBOOL CK_TRUE -CKA_PRIVATE CK_BBOOL CK_FALSE -CKA_MODIFIABLE CK_BBOOL CK_FALSE -CKA_LABEL UTF8 "Security Communication RootCA3" -CKA_CERT_SHA1_HASH MULTILINE_OCTAL -\303\003\310\042\164\222\345\141\242\234\137\171\221\053\036\104 -\023\221\060\072 -END -CKA_CERT_MD5_HASH MULTILINE_OCTAL -\034\232\026\377\236\134\340\115\212\024\001\364\065\135\051\046 -END -CKA_ISSUER MULTILINE_OCTAL -\060\135\061\013\060\011\006\003\125\004\006\023\002\112\120\061 -\045\060\043\006\003\125\004\012\023\034\123\105\103\117\115\040 -\124\162\165\163\164\040\123\171\163\164\145\155\163\040\103\117 -\056\054\114\124\104\056\061\047\060\045\006\003\125\004\003\023 -\036\123\145\143\165\162\151\164\171\040\103\157\155\155\165\156 -\151\143\141\164\151\157\156\040\122\157\157\164\103\101\063 -END -CKA_SERIAL_NUMBER MULTILINE_OCTAL -\002\011\000\341\174\067\100\375\033\376\147 -END -CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR -CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR -CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_MUST_VERIFY_TRUST -CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE - # # Certificate "Security Communication ECC RootCA1" # From 46bd4b8731f7553f9171df6b35e054823f7f93f8 Mon Sep 17 00:00:00 2001 From: "Node.js GitHub Bot" Date: Mon, 13 Jan 2025 19:56:11 -0500 Subject: [PATCH 105/205] deps: update simdutf to 6.0.3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/56567 Reviewed-By: Luigi Pinca Reviewed-By: James M Snell Reviewed-By: Ulises Gascón --- deps/simdutf/simdutf.cpp | 495 +++++++++++++++--- deps/simdutf/simdutf.h | 1044 +++++++++++++++++++++++++++++++++++--- 2 files changed, 1403 insertions(+), 136 deletions(-) diff --git a/deps/simdutf/simdutf.cpp b/deps/simdutf/simdutf.cpp index 12a2f494e0a7aa..21962c3bad378d 100644 --- a/deps/simdutf/simdutf.cpp +++ b/deps/simdutf/simdutf.cpp @@ -1,4 +1,4 @@ -/* auto-generated on 2024-12-26 12:42:33 -0500. Do not edit! */ +/* auto-generated on 2025-01-08 17:51:07 -0500. Do not edit! */ /* begin file src/simdutf.cpp */ #include "simdutf.h" // We include base64_tables once. @@ -17142,8 +17142,33 @@ size_t convert_masked_utf8_to_utf16(const char *input, for (int k = 0; k < 6; k++) { utf16_output[k] = buffer[k]; } // the loop might compiler to a couple of instructions. - utf16_output += 6; // We wrote 3 32-bit surrogate pairs. - return 12; // We consumed 12 bytes. + // We need some validation. See + // https://github.com/simdutf/simdutf/pull/631 +#ifdef SIMDUTF_REGULAR_VISUAL_STUDIO + uint8x16_t expected_mask = simdutf_make_uint8x16_t( + 0xf8, 0xc0, 0xc0, 0xc0, 0xf8, 0xc0, 0xc0, 0xc0, 0xf8, 0xc0, 0xc0, + 0xc0, 0x0, 0x0, 0x0, 0x0); +#else + uint8x16_t expected_mask = {0xf8, 0xc0, 0xc0, 0xc0, 0xf8, 0xc0, + 0xc0, 0xc0, 0xf8, 0xc0, 0xc0, 0xc0, + 0x0, 0x0, 0x0, 0x0}; +#endif +#ifdef SIMDUTF_REGULAR_VISUAL_STUDIO + uint8x16_t expected = simdutf_make_uint8x16_t( + 0xf0, 0x80, 0x80, 0x80, 0xf0, 0x80, 0x80, 0x80, 0xf0, 0x80, 0x80, + 0x80, 0x0, 0x0, 0x0, 0x0); +#else + uint8x16_t expected = {0xf0, 0x80, 0x80, 0x80, 0xf0, 0x80, 0x80, 0x80, + 0xf0, 0x80, 0x80, 0x80, 0x0, 0x0, 0x0, 0x0}; +#endif + uint8x16_t check = vceqq_u8(vandq_u8(in, expected_mask), expected); + bool correct = (vminvq_u32(vreinterpretq_u32_u8(check)) == 0xFFFFFFFF); + // The validation is just three instructions and it is not on a critical + // path. + if (correct) { + utf16_output += 6; // We wrote 3 32-bit surrogate pairs. + } + return 12; // We consumed 12 bytes. } // 3 1-4 byte sequences uint8x16_t sh = vld1q_u8(reinterpret_cast( @@ -18634,6 +18659,12 @@ compress_decode_base64(char *dst, const char_type *src, size_t srclen, } if (srclen == 0) { if (!ignore_garbage && equalsigns > 0) { + if (last_chunk_options == last_chunk_handling_options::strict) { + return {BASE64_INPUT_REMAINDER, 0, 0}; + } else if (last_chunk_options == + last_chunk_handling_options::stop_before_partial) { + return {SUCCESS, 0, 0}; + } return {INVALID_BASE64_CHARACTER, equallocation, 0}; } return {SUCCESS, 0, 0}; @@ -22881,6 +22912,12 @@ simdutf_warn_unused result implementation::base64_to_binary( } if (length == 0) { if (!ignore_garbage && equalsigns > 0) { + if (last_chunk_options == last_chunk_handling_options::strict) { + return {BASE64_INPUT_REMAINDER, 0}; + } else if (last_chunk_options == + last_chunk_handling_options::stop_before_partial) { + return {SUCCESS, 0}; + } return {INVALID_BASE64_CHARACTER, equallocation}; } return {SUCCESS, 0}; @@ -22926,6 +22963,12 @@ simdutf_warn_unused full_result implementation::base64_to_binary_details( } if (length == 0) { if (!ignore_garbage && equalsigns > 0) { + if (last_chunk_options == last_chunk_handling_options::strict) { + return {BASE64_INPUT_REMAINDER, 0, 0}; + } else if (last_chunk_options == + last_chunk_handling_options::stop_before_partial) { + return {SUCCESS, 0, 0}; + } return {INVALID_BASE64_CHARACTER, equallocation, 0}; } return {SUCCESS, 0, 0}; @@ -22977,6 +23020,12 @@ simdutf_warn_unused result implementation::base64_to_binary( } if (length == 0) { if (!ignore_garbage && equalsigns > 0) { + if (last_chunk_options == last_chunk_handling_options::strict) { + return {BASE64_INPUT_REMAINDER, 0}; + } else if (last_chunk_options == + last_chunk_handling_options::stop_before_partial) { + return {SUCCESS, 0}; + } return {INVALID_BASE64_CHARACTER, equallocation}; } return {SUCCESS, 0}; @@ -23022,6 +23071,12 @@ simdutf_warn_unused full_result implementation::base64_to_binary_details( } if (length == 0) { if (!ignore_garbage && equalsigns > 0) { + if (last_chunk_options == last_chunk_handling_options::strict) { + return {BASE64_INPUT_REMAINDER, 0, 0}; + } else if (last_chunk_options == + last_chunk_handling_options::stop_before_partial) { + return {SUCCESS, 0, 0}; + } return {INVALID_BASE64_CHARACTER, equallocation, 0}; } return {SUCCESS, 0, 0}; @@ -23058,6 +23113,8 @@ size_t implementation::binary_to_base64(const char *input, size_t length, #endif #if SIMDUTF_IMPLEMENTATION_ICELAKE /* begin file src/icelake/implementation.cpp */ +#include +#include /* begin file src/simdutf/icelake/begin.h */ @@ -26106,17 +26163,17 @@ bool validate_ascii(const char *buf, size_t len) { /* begin file src/icelake/icelake_utf32_validation.inl.cpp */ // file included directly -const char32_t *validate_utf32(const char32_t *buf, size_t len) { - if (len < 16) { - return buf; +bool validate_utf32(const char32_t *buf, size_t len) { + if (len == 0) { + return true; } - const char32_t *end = buf + len - 16; + const char32_t *end = buf + len; const __m512i offset = _mm512_set1_epi32((uint32_t)0xffff2000); __m512i currentmax = _mm512_setzero_si512(); __m512i currentoffsetmax = _mm512_setzero_si512(); - while (buf <= end) { + while (buf < end - 16) { __m512i utf32 = _mm512_loadu_si512((const __m512i *)buf); buf += 16; currentoffsetmax = @@ -26124,20 +26181,26 @@ const char32_t *validate_utf32(const char32_t *buf, size_t len) { currentmax = _mm512_max_epu32(utf32, currentmax); } + __m512i utf32 = + _mm512_maskz_loadu_epi32(__mmask16((1 << (end - buf)) - 1), buf); + currentoffsetmax = + _mm512_max_epu32(_mm512_add_epi32(utf32, offset), currentoffsetmax); + currentmax = _mm512_max_epu32(utf32, currentmax); + const __m512i standardmax = _mm512_set1_epi32((uint32_t)0x10ffff); const __m512i standardoffsetmax = _mm512_set1_epi32((uint32_t)0xfffff7ff); __m512i is_zero = _mm512_xor_si512(_mm512_max_epu32(currentmax, standardmax), standardmax); if (_mm512_test_epi8_mask(is_zero, is_zero) != 0) { - return nullptr; + return false; } is_zero = _mm512_xor_si512( _mm512_max_epu32(currentoffsetmax, standardoffsetmax), standardoffsetmax); if (_mm512_test_epi8_mask(is_zero, is_zero) != 0) { - return nullptr; + return false; } - return buf; + return true; } /* end file src/icelake/icelake_utf32_validation.inl.cpp */ /* begin file src/icelake/icelake_convert_latin1_to_utf8.inl.cpp */ @@ -26556,6 +26619,12 @@ compress_decode_base64(char *dst, const chartype *src, size_t srclen, } if (srclen == 0) { if (!ignore_garbage && equalsigns > 0) { + if (last_chunk_options == last_chunk_handling_options::strict) { + return {BASE64_INPUT_REMAINDER, 0, 0}; + } else if (last_chunk_options == + last_chunk_handling_options::stop_before_partial) { + return {SUCCESS, 0, 0}; + } return {INVALID_BASE64_CHARACTER, equallocation, 0}; } return {SUCCESS, 0, 0}; @@ -26753,24 +26822,76 @@ implementation::detect_encodings(const char *input, size_t length) const noexcept { // If there is a BOM, then we trust it. auto bom_encoding = simdutf::BOM::check_bom(input, length); - // todo: convert to a one-pass algorithm if (bom_encoding != encoding_type::unspecified) { return bom_encoding; } + int out = 0; - if (validate_utf8(input, length)) { + uint32_t utf16_err = (length % 2); + uint32_t utf32_err = (length % 4); + uint32_t ends_with_high = 0; + avx512_utf8_checker checker{}; + const __m512i offset = _mm512_set1_epi32((uint32_t)0xffff2000); + __m512i currentmax = _mm512_setzero_si512(); + __m512i currentoffsetmax = _mm512_setzero_si512(); + const char *ptr = input; + const char *end = ptr + length; + for (; end - ptr >= 64; ptr += 64) { + // utf8 checks + const __m512i data = _mm512_loadu_si512((const __m512i *)ptr); + checker.check_next_input(data); + + // utf16le_checks + __m512i diff = _mm512_sub_epi16(data, _mm512_set1_epi16(uint16_t(0xD800))); + __mmask32 surrogates = + _mm512_cmplt_epu16_mask(diff, _mm512_set1_epi16(uint16_t(0x0800))); + __mmask32 highsurrogates = + _mm512_cmplt_epu16_mask(diff, _mm512_set1_epi16(uint16_t(0x0400))); + __mmask32 lowsurrogates = surrogates ^ highsurrogates; + utf16_err |= (((highsurrogates << 1) | ends_with_high) != lowsurrogates); + ends_with_high = ((highsurrogates & 0x80000000) != 0); + + // utf32le checks + currentoffsetmax = + _mm512_max_epu32(_mm512_add_epi32(data, offset), currentoffsetmax); + currentmax = _mm512_max_epu32(data, currentmax); + } + + // last block with 0 <= len < 64 + __mmask64 read_mask = (__mmask64(1) << (end - ptr)) - 1; + const __m512i data = _mm512_maskz_loadu_epi8(read_mask, (const __m512i *)ptr); + checker.check_next_input(data); + + __m512i diff = _mm512_sub_epi16(data, _mm512_set1_epi16(uint16_t(0xD800))); + __mmask32 surrogates = + _mm512_cmplt_epu16_mask(diff, _mm512_set1_epi16(uint16_t(0x0800))); + __mmask32 highsurrogates = + _mm512_cmplt_epu16_mask(diff, _mm512_set1_epi16(uint16_t(0x0400))); + __mmask32 lowsurrogates = surrogates ^ highsurrogates; + utf16_err |= (((highsurrogates << 1) | ends_with_high) != lowsurrogates); + + currentoffsetmax = + _mm512_max_epu32(_mm512_add_epi32(data, offset), currentoffsetmax); + currentmax = _mm512_max_epu32(data, currentmax); + + const __m512i standardmax = _mm512_set1_epi32((uint32_t)0x10ffff); + const __m512i standardoffsetmax = _mm512_set1_epi32((uint32_t)0xfffff7ff); + __m512i is_zero = + _mm512_xor_si512(_mm512_max_epu32(currentmax, standardmax), standardmax); + utf32_err |= (_mm512_test_epi8_mask(is_zero, is_zero) != 0); + is_zero = _mm512_xor_si512( + _mm512_max_epu32(currentoffsetmax, standardoffsetmax), standardoffsetmax); + utf32_err |= (_mm512_test_epi8_mask(is_zero, is_zero) != 0); + checker.check_eof(); + bool is_valid_utf8 = !checker.errors(); + if (is_valid_utf8) { out |= encoding_type::UTF8; } - if ((length % 2) == 0) { - if (validate_utf16le(reinterpret_cast(input), - length / 2)) { - out |= encoding_type::UTF16_LE; - } + if (utf16_err == 0) { + out |= encoding_type::UTF16_LE; } - if ((length % 4) == 0) { - if (validate_utf32(reinterpret_cast(input), length / 4)) { - out |= encoding_type::UTF32_LE; - } + if (utf32_err == 0) { + out |= encoding_type::UTF32_LE; } return out; } @@ -27092,14 +27213,7 @@ simdutf_warn_unused result implementation::validate_utf16be_with_errors( simdutf_warn_unused bool implementation::validate_utf32(const char32_t *buf, size_t len) const noexcept { - const char32_t *tail = icelake::validate_utf32(buf, len); - if (tail) { - return scalar::utf32::validate(tail, len - (tail - buf)); - } else { - // we come here if there was an error, or buf was nullptr which may happen - // for empty input. - return len == 0; - } + return icelake::validate_utf32(buf, len); } simdutf_warn_unused result implementation::validate_utf32_with_errors( @@ -27980,16 +28094,7 @@ implementation::count_utf8(const char *input, size_t length) const noexcept { } } - __m256i first_half = _mm512_extracti64x4_epi64(unrolled_popcount, 0); - __m256i second_half = _mm512_extracti64x4_epi64(unrolled_popcount, 1); - answer -= (size_t)_mm256_extract_epi64(first_half, 0) + - (size_t)_mm256_extract_epi64(first_half, 1) + - (size_t)_mm256_extract_epi64(first_half, 2) + - (size_t)_mm256_extract_epi64(first_half, 3) + - (size_t)_mm256_extract_epi64(second_half, 0) + - (size_t)_mm256_extract_epi64(second_half, 1) + - (size_t)_mm256_extract_epi64(second_half, 2) + - (size_t)_mm256_extract_epi64(second_half, 3); + answer -= _mm512_reduce_add_epi64(unrolled_popcount); return answer + scalar::utf8::count_code_points( reinterpret_cast(str + i), length - i); @@ -28175,16 +28280,7 @@ simdutf_warn_unused size_t implementation::utf8_length_from_latin1( eight_64bits, _mm512_sad_epu8(runner, _mm512_setzero_si512())); } - __m256i first_half = _mm512_extracti64x4_epi64(eight_64bits, 0); - __m256i second_half = _mm512_extracti64x4_epi64(eight_64bits, 1); - answer += (size_t)_mm256_extract_epi64(first_half, 0) + - (size_t)_mm256_extract_epi64(first_half, 1) + - (size_t)_mm256_extract_epi64(first_half, 2) + - (size_t)_mm256_extract_epi64(first_half, 3) + - (size_t)_mm256_extract_epi64(second_half, 0) + - (size_t)_mm256_extract_epi64(second_half, 1) + - (size_t)_mm256_extract_epi64(second_half, 2) + - (size_t)_mm256_extract_epi64(second_half, 3); + answer += _mm512_reduce_add_epi64(eight_64bits); } else if (answer > 0) { for (; i + sizeof(__m512i) <= length; i += sizeof(__m512i)) { __m512i latin = _mm512_loadu_si512((const __m512i *)(str + i)); @@ -31471,6 +31567,12 @@ compress_decode_base64(char *dst, const chartype *src, size_t srclen, } if (srclen == 0) { if (!ignore_garbage && equalsigns > 0) { + if (last_chunk_options == last_chunk_handling_options::strict) { + return {BASE64_INPUT_REMAINDER, 0, 0}; + } else if (last_chunk_options == + last_chunk_handling_options::stop_before_partial) { + return {SUCCESS, 0, 0}; + } return {INVALID_BASE64_CHARACTER, equallocation, 0}; } return {SUCCESS, 0, 0}; @@ -33426,20 +33528,103 @@ implementation::detect_encodings(const char *input, if (bom_encoding != encoding_type::unspecified) { return bom_encoding; } + int out = 0; - if (validate_utf8(input, length)) { + uint32_t utf16_err = (length % 2); + uint32_t utf32_err = (length % 4); + uint32_t ends_with_high = 0; + const auto v_d8 = simd8::splat(0xd8); + const auto v_f8 = simd8::splat(0xf8); + const auto v_fc = simd8::splat(0xfc); + const auto v_dc = simd8::splat(0xdc); + const __m256i standardmax = _mm256_set1_epi32(0x10ffff); + const __m256i offset = _mm256_set1_epi32(0xffff2000); + const __m256i standardoffsetmax = _mm256_set1_epi32(0xfffff7ff); + __m256i currentmax = _mm256_setzero_si256(); + __m256i currentoffsetmax = _mm256_setzero_si256(); + + utf8_checker c{}; + buf_block_reader<64> reader(reinterpret_cast(input), length); + while (reader.has_full_block()) { + simd::simd8x64 in(reader.full_block()); + // utf8 checks + c.check_next_input(in); + + // utf16le checks + auto in0 = simd16(in.chunks[0]); + auto in1 = simd16(in.chunks[1]); + const auto t0 = in0.shr<8>(); + const auto t1 = in1.shr<8>(); + const auto in2 = simd16::pack(t0, t1); + const auto surrogates_wordmask = (in2 & v_f8) == v_d8; + const uint32_t surrogates_bitmask = surrogates_wordmask.to_bitmask(); + const auto vL = (in2 & v_fc) == v_dc; + const uint32_t L = vL.to_bitmask(); + const uint32_t H = L ^ surrogates_bitmask; + utf16_err |= (((H << 1) | ends_with_high) != L); + ends_with_high = (H & 0x80000000) != 0; + + // utf32le checks + currentmax = _mm256_max_epu32(in.chunks[0], currentmax); + currentoffsetmax = _mm256_max_epu32(_mm256_add_epi32(in.chunks[0], offset), + currentoffsetmax); + currentmax = _mm256_max_epu32(in.chunks[1], currentmax); + currentoffsetmax = _mm256_max_epu32(_mm256_add_epi32(in.chunks[1], offset), + currentoffsetmax); + + reader.advance(); + } + + uint8_t block[64]{}; + size_t idx = reader.block_index(); + std::memcpy(block, &input[idx], length - idx); + simd::simd8x64 in(block); + c.check_next_input(in); + + // utf16le last block check + auto in0 = simd16(in.chunks[0]); + auto in1 = simd16(in.chunks[1]); + const auto t0 = in0.shr<8>(); + const auto t1 = in1.shr<8>(); + const auto in2 = simd16::pack(t0, t1); + const auto surrogates_wordmask = (in2 & v_f8) == v_d8; + const uint32_t surrogates_bitmask = surrogates_wordmask.to_bitmask(); + const auto vL = (in2 & v_fc) == v_dc; + const uint32_t L = vL.to_bitmask(); + const uint32_t H = L ^ surrogates_bitmask; + utf16_err |= (((H << 1) | ends_with_high) != L); + // this is required to check for last byte ending in high and end of input + // is reached + ends_with_high = (H & 0x80000000) != 0; + utf16_err |= ends_with_high; + + // utf32le last block check + currentmax = _mm256_max_epu32(in.chunks[0], currentmax); + currentoffsetmax = _mm256_max_epu32(_mm256_add_epi32(in.chunks[0], offset), + currentoffsetmax); + currentmax = _mm256_max_epu32(in.chunks[1], currentmax); + currentoffsetmax = _mm256_max_epu32(_mm256_add_epi32(in.chunks[1], offset), + currentoffsetmax); + + reader.advance(); + + c.check_eof(); + bool is_valid_utf8 = !c.errors(); + __m256i is_zero = + _mm256_xor_si256(_mm256_max_epu32(currentmax, standardmax), standardmax); + utf32_err |= (_mm256_testz_si256(is_zero, is_zero) == 0); + + is_zero = _mm256_xor_si256( + _mm256_max_epu32(currentoffsetmax, standardoffsetmax), standardoffsetmax); + utf32_err |= (_mm256_testz_si256(is_zero, is_zero) == 0); + if (is_valid_utf8) { out |= encoding_type::UTF8; } - if ((length % 2) == 0) { - if (validate_utf16le(reinterpret_cast(input), - length / 2)) { - out |= encoding_type::UTF16_LE; - } + if (utf16_err == 0) { + out |= encoding_type::UTF16_LE; } - if ((length % 4) == 0) { - if (validate_utf32(reinterpret_cast(input), length / 4)) { - out |= encoding_type::UTF32_LE; - } + if (utf32_err == 0) { + out |= encoding_type::UTF32_LE; } return out; } @@ -36317,6 +36502,12 @@ simdutf_warn_unused result implementation::base64_to_binary( } if (length == 0) { if (!ignore_garbage && equalsigns > 0) { + if (last_chunk_options == last_chunk_handling_options::strict) { + return {BASE64_INPUT_REMAINDER, 0}; + } else if (last_chunk_options == + last_chunk_handling_options::stop_before_partial) { + return {SUCCESS, 0}; + } return {INVALID_BASE64_CHARACTER, equallocation}; } return {SUCCESS, 0}; @@ -36368,6 +36559,12 @@ simdutf_warn_unused result implementation::base64_to_binary( } if (length == 0) { if (!ignore_garbage && equalsigns > 0) { + if (last_chunk_options == last_chunk_handling_options::strict) { + return {BASE64_INPUT_REMAINDER, 0}; + } else if (last_chunk_options == + last_chunk_handling_options::stop_before_partial) { + return {SUCCESS, 0}; + } return {INVALID_BASE64_CHARACTER, equallocation}; } return {SUCCESS, 0}; @@ -38120,6 +38317,12 @@ simdutf_warn_unused result implementation::base64_to_binary( } if (length == 0) { if (!ignore_garbage && equalsigns > 0) { + if (last_chunk_options == last_chunk_handling_options::strict) { + return {BASE64_INPUT_REMAINDER, 0}; + } else if (last_chunk_options == + last_chunk_handling_options::stop_before_partial) { + return {SUCCESS, 0}; + } return {INVALID_BASE64_CHARACTER, equallocation}; } return {SUCCESS, 0}; @@ -38165,6 +38368,12 @@ simdutf_warn_unused full_result implementation::base64_to_binary_details( } if (length == 0) { if (!ignore_garbage && equalsigns > 0) { + if (last_chunk_options == last_chunk_handling_options::strict) { + return {BASE64_INPUT_REMAINDER, 0, 0}; + } else if (last_chunk_options == + last_chunk_handling_options::stop_before_partial) { + return {SUCCESS, 0, 0}; + } return {INVALID_BASE64_CHARACTER, equallocation, 0}; } return {SUCCESS, 0, 0}; @@ -38216,6 +38425,12 @@ simdutf_warn_unused result implementation::base64_to_binary( } if (length == 0) { if (!ignore_garbage && equalsigns > 0) { + if (last_chunk_options == last_chunk_handling_options::strict) { + return {BASE64_INPUT_REMAINDER, 0}; + } else if (last_chunk_options == + last_chunk_handling_options::stop_before_partial) { + return {SUCCESS, 0}; + } return {INVALID_BASE64_CHARACTER, equallocation}; } return {SUCCESS, 0}; @@ -38261,6 +38476,12 @@ simdutf_warn_unused full_result implementation::base64_to_binary_details( } if (length == 0) { if (!ignore_garbage && equalsigns > 0) { + if (last_chunk_options == last_chunk_handling_options::strict) { + return {BASE64_INPUT_REMAINDER, 0, 0}; + } else if (last_chunk_options == + last_chunk_handling_options::stop_before_partial) { + return {SUCCESS, 0, 0}; + } return {INVALID_BASE64_CHARACTER, equallocation, 0}; } return {SUCCESS, 0, 0}; @@ -41328,6 +41549,12 @@ compress_decode_base64(char *dst, const chartype *src, size_t srclen, } if (srclen == 0) { if (!ignore_garbage && equalsigns > 0) { + if (last_chunk_options == last_chunk_handling_options::strict) { + return {BASE64_INPUT_REMAINDER, 0, 0}; + } else if (last_chunk_options == + last_chunk_handling_options::stop_before_partial) { + return {SUCCESS, 0, 0}; + } return {INVALID_BASE64_CHARACTER, equallocation, 0}; } return {SUCCESS, 0, 0}; @@ -43282,24 +43509,138 @@ implementation::detect_encodings(const char *input, size_t length) const noexcept { // If there is a BOM, then we trust it. auto bom_encoding = simdutf::BOM::check_bom(input, length); - // todo: reimplement as a one-pass algorithm. if (bom_encoding != encoding_type::unspecified) { return bom_encoding; } + int out = 0; - if (validate_utf8(input, length)) { + uint32_t utf16_err = (length % 2); + uint32_t utf32_err = (length % 4); + uint32_t ends_with_high = 0; + const auto v_d8 = simd8::splat(0xd8); + const auto v_f8 = simd8::splat(0xf8); + const auto v_fc = simd8::splat(0xfc); + const auto v_dc = simd8::splat(0xdc); + const __m128i standardmax = _mm_set1_epi32(0x10ffff); + const __m128i offset = _mm_set1_epi32(0xffff2000); + const __m128i standardoffsetmax = _mm_set1_epi32(0xfffff7ff); + __m128i currentmax = _mm_setzero_si128(); + __m128i currentoffsetmax = _mm_setzero_si128(); + + utf8_checker c{}; + buf_block_reader<64> reader(reinterpret_cast(input), length); + while (reader.has_full_block()) { + simd::simd8x64 in(reader.full_block()); + // utf8 checks + c.check_next_input(in); + + // utf16le checks + auto in0 = simd16(in.chunks[0]); + auto in1 = simd16(in.chunks[1]); + const auto t0 = in0.shr<8>(); + const auto t1 = in1.shr<8>(); + const auto packed1 = simd16::pack(t0, t1); + auto in2 = simd16(in.chunks[2]); + auto in3 = simd16(in.chunks[3]); + const auto t2 = in2.shr<8>(); + const auto t3 = in3.shr<8>(); + const auto packed2 = simd16::pack(t2, t3); + + const auto surrogates_wordmask_lo = (packed1 & v_f8) == v_d8; + const auto surrogates_wordmask_hi = (packed2 & v_f8) == v_d8; + const uint32_t surrogates_bitmask = + (surrogates_wordmask_hi.to_bitmask() << 16) | + surrogates_wordmask_lo.to_bitmask(); + const auto vL_lo = (packed1 & v_fc) == v_dc; + const auto vL_hi = (packed2 & v_fc) == v_dc; + const uint32_t L = (vL_hi.to_bitmask() << 16) | vL_lo.to_bitmask(); + const uint32_t H = L ^ surrogates_bitmask; + utf16_err |= (((H << 1) | ends_with_high) != L); + ends_with_high = (H & 0x80000000) != 0; + + // utf32le checks + currentmax = _mm_max_epu32(in.chunks[0], currentmax); + currentoffsetmax = + _mm_max_epu32(_mm_add_epi32(in.chunks[0], offset), currentoffsetmax); + currentmax = _mm_max_epu32(in.chunks[1], currentmax); + currentoffsetmax = + _mm_max_epu32(_mm_add_epi32(in.chunks[1], offset), currentoffsetmax); + currentmax = _mm_max_epu32(in.chunks[2], currentmax); + currentoffsetmax = + _mm_max_epu32(_mm_add_epi32(in.chunks[2], offset), currentoffsetmax); + currentmax = _mm_max_epu32(in.chunks[3], currentmax); + currentoffsetmax = + _mm_max_epu32(_mm_add_epi32(in.chunks[3], offset), currentoffsetmax); + + reader.advance(); + } + + uint8_t block[64]{}; + size_t idx = reader.block_index(); + std::memcpy(block, &input[idx], length - idx); + simd::simd8x64 in(block); + c.check_next_input(in); + + // utf16le last block check + auto in0 = simd16(in.chunks[0]); + auto in1 = simd16(in.chunks[1]); + const auto t0 = in0.shr<8>(); + const auto t1 = in1.shr<8>(); + const auto packed1 = simd16::pack(t0, t1); + auto in2 = simd16(in.chunks[2]); + auto in3 = simd16(in.chunks[3]); + const auto t2 = in2.shr<8>(); + const auto t3 = in3.shr<8>(); + const auto packed2 = simd16::pack(t2, t3); + + const auto surrogates_wordmask_lo = (packed1 & v_f8) == v_d8; + const auto surrogates_wordmask_hi = (packed2 & v_f8) == v_d8; + const uint32_t surrogates_bitmask = + (surrogates_wordmask_hi.to_bitmask() << 16) | + surrogates_wordmask_lo.to_bitmask(); + const auto vL_lo = (packed1 & v_fc) == v_dc; + const auto vL_hi = (packed2 & v_fc) == v_dc; + const uint32_t L = (vL_hi.to_bitmask() << 16) | vL_lo.to_bitmask(); + const uint32_t H = L ^ surrogates_bitmask; + utf16_err |= (((H << 1) | ends_with_high) != L); + // this is required to check for last byte ending in high and end of input + // is reached + ends_with_high = (H & 0x80000000) != 0; + utf16_err |= ends_with_high; + + // utf32le last block check + currentmax = _mm_max_epu32(in.chunks[0], currentmax); + currentoffsetmax = + _mm_max_epu32(_mm_add_epi32(in.chunks[0], offset), currentoffsetmax); + currentmax = _mm_max_epu32(in.chunks[1], currentmax); + currentoffsetmax = + _mm_max_epu32(_mm_add_epi32(in.chunks[1], offset), currentoffsetmax); + currentmax = _mm_max_epu32(in.chunks[2], currentmax); + currentoffsetmax = + _mm_max_epu32(_mm_add_epi32(in.chunks[2], offset), currentoffsetmax); + currentmax = _mm_max_epu32(in.chunks[3], currentmax); + currentoffsetmax = + _mm_max_epu32(_mm_add_epi32(in.chunks[3], offset), currentoffsetmax); + + reader.advance(); + + c.check_eof(); + bool is_valid_utf8 = !c.errors(); + __m128i is_zero = + _mm_xor_si128(_mm_max_epu32(currentmax, standardmax), standardmax); + utf32_err |= (_mm_test_all_zeros(is_zero, is_zero) == 0); + + is_zero = _mm_xor_si128(_mm_max_epu32(currentoffsetmax, standardoffsetmax), + standardoffsetmax); + utf32_err |= (_mm_test_all_zeros(is_zero, is_zero) == 0); + if (is_valid_utf8) { out |= encoding_type::UTF8; } - if ((length % 2) == 0) { - if (validate_utf16le(reinterpret_cast(input), - length / 2)) { - out |= encoding_type::UTF16_LE; - } + if (utf16_err == 0) { + out |= encoding_type::UTF16_LE; } - if ((length % 4) == 0) { - if (validate_utf32(reinterpret_cast(input), length / 4)) { - out |= encoding_type::UTF32_LE; - } + if (utf32_err == 0) { + out |= encoding_type::UTF32_LE; } return out; } @@ -47336,6 +47677,12 @@ compress_decode_base64(char *dst, const char_type *src, size_t srclen, } if (srclen == 0) { if (!ignore_garbage && equalsigns > 0) { + if (last_chunk_options == last_chunk_handling_options::strict) { + return {BASE64_INPUT_REMAINDER, 0, 0}; + } else if (last_chunk_options == + last_chunk_handling_options::stop_before_partial) { + return {SUCCESS, 0, 0}; + } return {INVALID_BASE64_CHARACTER, equallocation, 0}; } return {SUCCESS, 0, 0}; @@ -53668,6 +54015,12 @@ compress_decode_base64(char *dst, const chartype *src, size_t srclen, } if (srclen == 0) { if (!ignore_garbage && equalsigns > 0) { + if (last_chunk_options == last_chunk_handling_options::strict) { + return {BASE64_INPUT_REMAINDER, 0, 0}; + } else if (last_chunk_options == + last_chunk_handling_options::stop_before_partial) { + return {SUCCESS, 0, 0}; + } return {INVALID_BASE64_CHARACTER, equallocation, 0}; } return {SUCCESS, 0, 0}; diff --git a/deps/simdutf/simdutf.h b/deps/simdutf/simdutf.h index 9a4b4580da91a1..4bec0cf300292a 100644 --- a/deps/simdutf/simdutf.h +++ b/deps/simdutf/simdutf.h @@ -1,4 +1,4 @@ -/* auto-generated on 2024-12-26 12:42:33 -0500. Do not edit! */ +/* auto-generated on 2025-01-08 17:51:07 -0500. Do not edit! */ /* begin file include/simdutf.h */ #ifndef SIMDUTF_H #define SIMDUTF_H @@ -55,21 +55,35 @@ #ifndef SIMDUTF_COMMON_DEFS_H #define SIMDUTF_COMMON_DEFS_H -#include /* begin file include/simdutf/portability.h */ #ifndef SIMDUTF_PORTABILITY_H #define SIMDUTF_PORTABILITY_H + +#include #include #include #include -#include -#include #ifndef _WIN32 // strcasecmp, strncasecmp #include #endif +#if defined(__apple_build_version__) + #if __apple_build_version__ < 14000000 + #define SIMDUTF_SPAN_DISABLED \ + 1 // apple-clang/13 doesn't support std::convertible_to + #endif +#endif + +#if SIMDUTF_CPLUSPLUS20 + #include + #if __cpp_concepts >= 201907L && __cpp_lib_span >= 202002L && \ + !defined(SIMDUTF_SPAN_DISABLED) + #define SIMDUTF_SPAN 1 + #endif +#endif + /** * We want to check that it is actually a little endian system at * compile-time. @@ -291,27 +305,6 @@ #define simdutf_strncasecmp strncasecmp #endif -#ifdef NDEBUG - - #ifdef SIMDUTF_VISUAL_STUDIO - #define SIMDUTF_UNREACHABLE() __assume(0) - #define SIMDUTF_ASSUME(COND) __assume(COND) - #else - #define SIMDUTF_UNREACHABLE() __builtin_unreachable(); - #define SIMDUTF_ASSUME(COND) \ - do { \ - if (!(COND)) \ - __builtin_unreachable(); \ - } while (0) - #endif - -#else // NDEBUG - - #define SIMDUTF_UNREACHABLE() assert(0); - #define SIMDUTF_ASSUME(COND) assert(COND) - -#endif - #if defined(__GNUC__) && !defined(__clang__) #if __GNUC__ >= 11 #define SIMDUTF_GCC11ORMORE 1 @@ -402,27 +395,6 @@ #endif // SIMDUTF_AVX512_H_ /* end file include/simdutf/avx512.h */ -#if defined(__GNUC__) - // Marks a block with a name so that MCA analysis can see it. - #define SIMDUTF_BEGIN_DEBUG_BLOCK(name) \ - __asm volatile("# LLVM-MCA-BEGIN " #name); - #define SIMDUTF_END_DEBUG_BLOCK(name) __asm volatile("# LLVM-MCA-END " #name); - #define SIMDUTF_DEBUG_BLOCK(name, block) \ - BEGIN_DEBUG_BLOCK(name); \ - block; \ - END_DEBUG_BLOCK(name); -#else - #define SIMDUTF_BEGIN_DEBUG_BLOCK(name) - #define SIMDUTF_END_DEBUG_BLOCK(name) - #define SIMDUTF_DEBUG_BLOCK(name, block) -#endif - -// Align to N-byte boundary -#define SIMDUTF_ROUNDUP_N(a, n) (((a) + ((n) - 1)) & ~((n) - 1)) -#define SIMDUTF_ROUNDDOWN_N(a, n) ((a) & ~((n) - 1)) - -#define SIMDUTF_ISALIGNED_N(ptr, n) (((uintptr_t)(ptr) & ((n) - 1)) == 0) - #if defined(SIMDUTF_REGULAR_VISUAL_STUDIO) #define SIMDUTF_DEPRECATED __declspec(deprecated) @@ -536,18 +508,11 @@ #endif #endif -/// If EXPR is an error, returns it. -#define SIMDUTF_TRY(EXPR) \ - { \ - auto _err = (EXPR); \ - if (_err) { \ - return _err; \ - } \ - } - #endif // SIMDUTF_COMMON_DEFS_H /* end file include/simdutf/common_defs.h */ /* begin file include/simdutf/encoding_types.h */ +#ifndef SIMDUTF_ENCODING_TYPES_H +#define SIMDUTF_ENCODING_TYPES_H #include namespace simdutf { @@ -591,6 +556,7 @@ size_t bom_byte_size(encoding_type bom); } // namespace BOM } // namespace simdutf +#endif /* end file include/simdutf/encoding_types.h */ /* begin file include/simdutf/error.h */ #ifndef SIMDUTF_ERROR_H @@ -675,22 +641,22 @@ SIMDUTF_DISABLE_UNDESIRED_WARNINGS #define SIMDUTF_SIMDUTF_VERSION_H /** The version of simdutf being used (major.minor.revision) */ -#define SIMDUTF_VERSION "5.7.2" +#define SIMDUTF_VERSION "6.0.3" namespace simdutf { enum { /** * The major version (MAJOR.minor.revision) of simdutf being used. */ - SIMDUTF_VERSION_MAJOR = 5, + SIMDUTF_VERSION_MAJOR = 6, /** * The minor version (major.MINOR.revision) of simdutf being used. */ - SIMDUTF_VERSION_MINOR = 7, + SIMDUTF_VERSION_MINOR = 0, /** * The revision (major.minor.REVISION) of simdutf being used. */ - SIMDUTF_VERSION_REVISION = 2 + SIMDUTF_VERSION_REVISION = 3 }; } // namespace simdutf @@ -699,11 +665,10 @@ enum { /* begin file include/simdutf/implementation.h */ #ifndef SIMDUTF_IMPLEMENTATION_H #define SIMDUTF_IMPLEMENTATION_H -#include #if !defined(SIMDUTF_NO_THREADS) #include #endif -#include +#include #include /* begin file include/simdutf/internal/isadetection.h */ /* From @@ -1031,8 +996,61 @@ static inline uint32_t detect_supported_architectures() { #endif // SIMDutf_INTERNAL_ISADETECTION_H /* end file include/simdutf/internal/isadetection.h */ +#if SIMDUTF_SPAN + #include + #include + #include +#endif + namespace simdutf { +#if SIMDUTF_SPAN +/// helpers placed in namespace detail are not a part of the public API +namespace detail { +/** + * matches a byte, in the many ways C++ allows. note that these + * are all distinct types. + */ +template +concept byte_like = std::is_same_v || // + std::is_same_v || // + std::is_same_v || // + std::is_same_v; + +template +concept is_byte_like = byte_like>; + +template +concept is_pointer = std::is_pointer_v; + +/** + * matches anything that behaves like std::span and points to character-like + * data such as: std::byte, char, unsigned char, signed char, std::int8_t, + * std::uint8_t + */ +template +concept input_span_of_byte_like = requires(const T &t) { + { t.size() } noexcept -> std::convertible_to; + { t.data() } noexcept -> is_pointer; + { *t.data() } noexcept -> is_byte_like; +}; + +template +concept is_mutable = !std::is_const_v>; + +/** + * like span_of_byte_like, but for an output span (intended to be written to) + */ +template +concept output_span_of_byte_like = requires(T &t) { + { t.size() } noexcept -> std::convertible_to; + { t.data() } noexcept -> is_pointer; + { *t.data() } noexcept -> is_byte_like; + { *t.data() } noexcept -> is_mutable; +}; +} // namespace detail +#endif + /** * Autodetect the encoding of the input, a single encoding is recommended. * E.g., the function might return simdutf::encoding_type::UTF8, @@ -1049,6 +1067,25 @@ simdutf_really_inline simdutf_warn_unused simdutf::encoding_type autodetect_encoding(const uint8_t *input, size_t length) noexcept { return autodetect_encoding(reinterpret_cast(input), length); } +#if SIMDUTF_SPAN +/** + * Autodetect the encoding of the input, a single encoding is recommended. + * E.g., the function might return simdutf::encoding_type::UTF8, + * simdutf::encoding_type::UTF16_LE, simdutf::encoding_type::UTF16_BE, or + * simdutf::encoding_type::UTF32_LE. + * + * @param input the string to analyze. can be a anything span-like that has a + * data() and size() that points to character data: std::string, + * std::string_view, std::vector, std::span etc. + * @return the detected encoding type + */ +simdutf_really_inline simdutf_warn_unused simdutf::encoding_type +autodetect_encoding( + const detail::input_span_of_byte_like auto &input) noexcept { + return autodetect_encoding(reinterpret_cast(input.data()), + input.size()); +} +#endif /** * Autodetect the possible encodings of the input in one pass. @@ -1067,6 +1104,13 @@ simdutf_really_inline simdutf_warn_unused int detect_encodings(const uint8_t *input, size_t length) noexcept { return detect_encodings(reinterpret_cast(input), length); } +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused int +detect_encodings(const detail::input_span_of_byte_like auto &input) noexcept { + return detect_encodings(reinterpret_cast(input.data()), + input.size()); +} +#endif /** * Validate the UTF-8 string. This function may be best when you expect @@ -1080,6 +1124,13 @@ detect_encodings(const uint8_t *input, size_t length) noexcept { * @return true if and only if the string is valid UTF-8. */ simdutf_warn_unused bool validate_utf8(const char *buf, size_t len) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused bool +validate_utf8(const detail::input_span_of_byte_like auto &input) noexcept { + return validate_utf8(reinterpret_cast(input.data()), + input.size()); +} +#endif /** * Validate the UTF-8 string and stop on error. @@ -1095,6 +1146,13 @@ simdutf_warn_unused bool validate_utf8(const char *buf, size_t len) noexcept; */ simdutf_warn_unused result validate_utf8_with_errors(const char *buf, size_t len) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused result validate_utf8_with_errors( + const detail::input_span_of_byte_like auto &input) noexcept { + return validate_utf8_with_errors(reinterpret_cast(input.data()), + input.size()); +} +#endif /** * Validate the ASCII string. @@ -1106,6 +1164,13 @@ simdutf_warn_unused result validate_utf8_with_errors(const char *buf, * @return true if and only if the string is valid ASCII. */ simdutf_warn_unused bool validate_ascii(const char *buf, size_t len) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused bool +validate_ascii(const detail::input_span_of_byte_like auto &input) noexcept { + return validate_ascii(reinterpret_cast(input.data()), + input.size()); +} +#endif /** * Validate the ASCII string and stop on error. It might be faster than @@ -1122,6 +1187,13 @@ simdutf_warn_unused bool validate_ascii(const char *buf, size_t len) noexcept; */ simdutf_warn_unused result validate_ascii_with_errors(const char *buf, size_t len) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused result validate_ascii_with_errors( + const detail::input_span_of_byte_like auto &input) noexcept { + return validate_ascii_with_errors( + reinterpret_cast(input.data()), input.size()); +} +#endif /** * Using native endianness; Validate the UTF-16 string. @@ -1139,6 +1211,12 @@ simdutf_warn_unused result validate_ascii_with_errors(const char *buf, */ simdutf_warn_unused bool validate_utf16(const char16_t *buf, size_t len) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused bool +validate_utf16(std::span input) noexcept { + return validate_utf16(input.data(), input.size()); +} +#endif /** * Validate the UTF-16LE string. This function may be best when you expect @@ -1156,6 +1234,12 @@ simdutf_warn_unused bool validate_utf16(const char16_t *buf, */ simdutf_warn_unused bool validate_utf16le(const char16_t *buf, size_t len) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused bool +validate_utf16le(std::span input) noexcept { + return validate_utf16le(input.data(), input.size()); +} +#endif /** * Validate the UTF-16BE string. This function may be best when you expect @@ -1173,6 +1257,12 @@ simdutf_warn_unused bool validate_utf16le(const char16_t *buf, */ simdutf_warn_unused bool validate_utf16be(const char16_t *buf, size_t len) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused bool +validate_utf16be(std::span input) noexcept { + return validate_utf16be(input.data(), input.size()); +} +#endif /** * Using native endianness; Validate the UTF-16 string and stop on error. @@ -1193,6 +1283,12 @@ simdutf_warn_unused bool validate_utf16be(const char16_t *buf, */ simdutf_warn_unused result validate_utf16_with_errors(const char16_t *buf, size_t len) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused result +validate_utf16_with_errors(std::span input) noexcept { + return validate_utf16_with_errors(input.data(), input.size()); +} +#endif /** * Validate the UTF-16LE string and stop on error. It might be faster than @@ -1212,6 +1308,12 @@ simdutf_warn_unused result validate_utf16_with_errors(const char16_t *buf, */ simdutf_warn_unused result validate_utf16le_with_errors(const char16_t *buf, size_t len) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused result +validate_utf16le_with_errors(std::span input) noexcept { + return validate_utf16le_with_errors(input.data(), input.size()); +} +#endif /** * Validate the UTF-16BE string and stop on error. It might be faster than @@ -1231,6 +1333,12 @@ simdutf_warn_unused result validate_utf16le_with_errors(const char16_t *buf, */ simdutf_warn_unused result validate_utf16be_with_errors(const char16_t *buf, size_t len) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused result +validate_utf16be_with_errors(std::span input) noexcept { + return validate_utf16be_with_errors(input.data(), input.size()); +} +#endif /** * Validate the UTF-32 string. This function may be best when you expect @@ -1248,6 +1356,12 @@ simdutf_warn_unused result validate_utf16be_with_errors(const char16_t *buf, */ simdutf_warn_unused bool validate_utf32(const char32_t *buf, size_t len) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused bool +validate_utf32(std::span input) noexcept { + return validate_utf32(input.data(), input.size()); +} +#endif /** * Validate the UTF-32 string and stop on error. It might be faster than @@ -1267,6 +1381,12 @@ simdutf_warn_unused bool validate_utf32(const char32_t *buf, */ simdutf_warn_unused result validate_utf32_with_errors(const char32_t *buf, size_t len) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused result +validate_utf32_with_errors(std::span input) noexcept { + return validate_utf32_with_errors(input.data(), input.size()); +} +#endif /** * Convert Latin1 string into UTF8 string. @@ -1281,6 +1401,15 @@ simdutf_warn_unused result validate_utf32_with_errors(const char32_t *buf, simdutf_warn_unused size_t convert_latin1_to_utf8(const char *input, size_t length, char *utf8_output) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t convert_latin1_to_utf8( + const detail::input_span_of_byte_like auto &latin1_input, + detail::output_span_of_byte_like auto &&utf8_output) noexcept { + return convert_latin1_to_utf8( + reinterpret_cast(latin1_input.data()), latin1_input.size(), + utf8_output.data()); +} +#endif /** * Convert Latin1 string into UTF8 string with output limit. @@ -1296,6 +1425,21 @@ simdutf_warn_unused size_t convert_latin1_to_utf8(const char *input, simdutf_warn_unused size_t convert_latin1_to_utf8_safe(const char *input, size_t length, char *utf8_output, size_t utf8_len) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t convert_latin1_to_utf8_safe( + const detail::input_span_of_byte_like auto &input, + detail::output_span_of_byte_like auto &&utf8_output) noexcept { + // implementation note: outputspan is a forwarding ref to avoid copying and + // allow both lvalues and rvalues. std::span can be copied without problems, + // but std::vector should not, and this function should accept both. it will + // allow using an owning rvalue ref (example: passing a temporary std::string) + // as output, but the user will quickly find out that he has no way of getting + // the data out of the object in that case. + return convert_latin1_to_utf8_safe( + input.data(), input.size(), reinterpret_cast(utf8_output.data()), + utf8_output.size()); +} +#endif /** * Convert possibly Latin1 string into UTF-16LE string. @@ -1309,6 +1453,15 @@ convert_latin1_to_utf8_safe(const char *input, size_t length, char *utf8_output, */ simdutf_warn_unused size_t convert_latin1_to_utf16le( const char *input, size_t length, char16_t *utf16_output) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t convert_latin1_to_utf16le( + const detail::input_span_of_byte_like auto &latin1_input, + std::span utf16_output) noexcept { + return convert_latin1_to_utf16le( + reinterpret_cast(latin1_input.data()), latin1_input.size(), + utf16_output.data()); +} +#endif /** * Convert Latin1 string into UTF-16BE string. @@ -1322,6 +1475,14 @@ simdutf_warn_unused size_t convert_latin1_to_utf16le( */ simdutf_warn_unused size_t convert_latin1_to_utf16be( const char *input, size_t length, char16_t *utf16_output) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t +convert_latin1_to_utf16be(const detail::input_span_of_byte_like auto &input, + std::span output) noexcept { + return convert_latin1_to_utf16be(reinterpret_cast(input.data()), + input.size(), output.data()); +} +#endif /** * Convert Latin1 string into UTF-32 string. @@ -1335,6 +1496,15 @@ simdutf_warn_unused size_t convert_latin1_to_utf16be( */ simdutf_warn_unused size_t convert_latin1_to_utf32( const char *input, size_t length, char32_t *utf32_buffer) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t convert_latin1_to_utf32( + const detail::input_span_of_byte_like auto &latin1_input, + std::span utf32_output) noexcept { + return convert_latin1_to_utf32( + reinterpret_cast(latin1_input.data()), latin1_input.size(), + utf32_output.data()); +} +#endif /** * Convert possibly broken UTF-8 string into latin1 string. @@ -1351,6 +1521,15 @@ simdutf_warn_unused size_t convert_latin1_to_utf32( simdutf_warn_unused size_t convert_utf8_to_latin1(const char *input, size_t length, char *latin1_output) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t convert_utf8_to_latin1( + const detail::input_span_of_byte_like auto &input, + detail::output_span_of_byte_like auto &&output) noexcept { + return convert_utf8_to_latin1(reinterpret_cast(input.data()), + input.size(), + reinterpret_cast(output.data())); +} +#endif /** * Using native endianness, convert possibly broken UTF-8 string into a UTF-16 @@ -1367,6 +1546,14 @@ simdutf_warn_unused size_t convert_utf8_to_latin1(const char *input, */ simdutf_warn_unused size_t convert_utf8_to_utf16( const char *input, size_t length, char16_t *utf16_output) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t +convert_utf8_to_utf16(const detail::input_span_of_byte_like auto &input, + std::span output) noexcept { + return convert_utf8_to_utf16(reinterpret_cast(input.data()), + input.size(), output.data()); +} +#endif /** * Using native endianness, convert a Latin1 string into a UTF-16 string. @@ -1378,6 +1565,14 @@ simdutf_warn_unused size_t convert_utf8_to_utf16( */ simdutf_warn_unused size_t convert_latin1_to_utf16( const char *input, size_t length, char16_t *utf16_output) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t +convert_latin1_to_utf16(const detail::input_span_of_byte_like auto &input, + std::span output) noexcept { + return convert_latin1_to_utf16(reinterpret_cast(input.data()), + input.size(), output.data()); +} +#endif /** * Convert possibly broken UTF-8 string into UTF-16LE string. @@ -1393,6 +1588,15 @@ simdutf_warn_unused size_t convert_latin1_to_utf16( */ simdutf_warn_unused size_t convert_utf8_to_utf16le( const char *input, size_t length, char16_t *utf16_output) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t +convert_utf8_to_utf16le(const detail::input_span_of_byte_like auto &utf8_input, + std::span utf16_output) noexcept { + return convert_utf8_to_utf16le( + reinterpret_cast(utf8_input.data()), utf8_input.size(), + utf16_output.data()); +} +#endif /** * Convert possibly broken UTF-8 string into UTF-16BE string. @@ -1408,6 +1612,15 @@ simdutf_warn_unused size_t convert_utf8_to_utf16le( */ simdutf_warn_unused size_t convert_utf8_to_utf16be( const char *input, size_t length, char16_t *utf16_output) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t +convert_utf8_to_utf16be(const detail::input_span_of_byte_like auto &utf8_input, + std::span utf16_output) noexcept { + return convert_utf8_to_utf16be( + reinterpret_cast(utf8_input.data()), utf8_input.size(), + utf16_output.data()); +} +#endif /** * Convert possibly broken UTF-8 string into latin1 string with errors. @@ -1427,6 +1640,16 @@ simdutf_warn_unused size_t convert_utf8_to_utf16be( */ simdutf_warn_unused result convert_utf8_to_latin1_with_errors( const char *input, size_t length, char *latin1_output) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused result +convert_utf8_to_latin1_with_errors( + const detail::input_span_of_byte_like auto &utf8_input, + detail::output_span_of_byte_like auto &&latin1_output) noexcept { + return convert_utf8_to_latin1_with_errors( + reinterpret_cast(utf8_input.data()), utf8_input.size(), + reinterpret_cast(latin1_output.data())); +} +#endif /** * Using native endianness, convert possibly broken UTF-8 string into UTF-16 @@ -1445,6 +1668,16 @@ simdutf_warn_unused result convert_utf8_to_latin1_with_errors( */ simdutf_warn_unused result convert_utf8_to_utf16_with_errors( const char *input, size_t length, char16_t *utf16_output) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused result +convert_utf8_to_utf16_with_errors( + const detail::input_span_of_byte_like auto &utf8_input, + std::span utf16_output) noexcept { + return convert_utf8_to_utf16_with_errors( + reinterpret_cast(utf8_input.data()), utf8_input.size(), + utf16_output.data()); +} +#endif /** * Convert possibly broken UTF-8 string into UTF-16LE string and stop on error. @@ -1462,6 +1695,16 @@ simdutf_warn_unused result convert_utf8_to_utf16_with_errors( */ simdutf_warn_unused result convert_utf8_to_utf16le_with_errors( const char *input, size_t length, char16_t *utf16_output) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused result +convert_utf8_to_utf16le_with_errors( + const detail::input_span_of_byte_like auto &utf8_input, + std::span utf16_output) noexcept { + return convert_utf8_to_utf16le_with_errors( + reinterpret_cast(utf8_input.data()), utf8_input.size(), + utf16_output.data()); +} +#endif /** * Convert possibly broken UTF-8 string into UTF-16BE string and stop on error. @@ -1479,6 +1722,16 @@ simdutf_warn_unused result convert_utf8_to_utf16le_with_errors( */ simdutf_warn_unused result convert_utf8_to_utf16be_with_errors( const char *input, size_t length, char16_t *utf16_output) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused result +convert_utf8_to_utf16be_with_errors( + const detail::input_span_of_byte_like auto &utf8_input, + std::span utf16_output) noexcept { + return convert_utf8_to_utf16be_with_errors( + reinterpret_cast(utf8_input.data()), utf8_input.size(), + utf16_output.data()); +} +#endif /** * Convert possibly broken UTF-8 string into UTF-32 string. @@ -1494,6 +1747,15 @@ simdutf_warn_unused result convert_utf8_to_utf16be_with_errors( */ simdutf_warn_unused size_t convert_utf8_to_utf32( const char *input, size_t length, char32_t *utf32_output) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t +convert_utf8_to_utf32(const detail::input_span_of_byte_like auto &utf8_input, + std::span utf32_output) noexcept { + return convert_utf8_to_utf32( + reinterpret_cast(utf8_input.data()), utf8_input.size(), + utf32_output.data()); +} +#endif /** * Convert possibly broken UTF-8 string into UTF-32 string and stop on error. @@ -1511,6 +1773,16 @@ simdutf_warn_unused size_t convert_utf8_to_utf32( */ simdutf_warn_unused result convert_utf8_to_utf32_with_errors( const char *input, size_t length, char32_t *utf32_output) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused result +convert_utf8_to_utf32_with_errors( + const detail::input_span_of_byte_like auto &utf8_input, + std::span utf32_output) noexcept { + return convert_utf8_to_utf32_with_errors( + reinterpret_cast(utf8_input.data()), utf8_input.size(), + utf32_output.data()); +} +#endif /** * Convert valid UTF-8 string into latin1 string. @@ -1533,6 +1805,15 @@ simdutf_warn_unused result convert_utf8_to_utf32_with_errors( */ simdutf_warn_unused size_t convert_valid_utf8_to_latin1( const char *input, size_t length, char *latin1_output) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t convert_valid_utf8_to_latin1( + const detail::input_span_of_byte_like auto &valid_utf8_input, + detail::output_span_of_byte_like auto &&latin1_output) noexcept { + return convert_valid_utf8_to_latin1( + reinterpret_cast(valid_utf8_input.data()), + valid_utf8_input.size(), latin1_output.data()); +} +#endif /** * Using native endianness, convert valid UTF-8 string into a UTF-16 string. @@ -1546,6 +1827,15 @@ simdutf_warn_unused size_t convert_valid_utf8_to_latin1( */ simdutf_warn_unused size_t convert_valid_utf8_to_utf16( const char *input, size_t length, char16_t *utf16_buffer) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t convert_valid_utf8_to_utf16( + const detail::input_span_of_byte_like auto &valid_utf8_input, + std::span utf16_output) noexcept { + return convert_valid_utf8_to_utf16( + reinterpret_cast(valid_utf8_input.data()), + valid_utf8_input.size(), utf16_output.data()); +} +#endif /** * Convert valid UTF-8 string into UTF-16LE string. @@ -1559,6 +1849,15 @@ simdutf_warn_unused size_t convert_valid_utf8_to_utf16( */ simdutf_warn_unused size_t convert_valid_utf8_to_utf16le( const char *input, size_t length, char16_t *utf16_buffer) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t convert_valid_utf8_to_utf16le( + const detail::input_span_of_byte_like auto &valid_utf8_input, + std::span utf16_output) noexcept { + return convert_valid_utf8_to_utf16le( + reinterpret_cast(valid_utf8_input.data()), + valid_utf8_input.size(), utf16_output.data()); +} +#endif /** * Convert valid UTF-8 string into UTF-16BE string. @@ -1572,6 +1871,15 @@ simdutf_warn_unused size_t convert_valid_utf8_to_utf16le( */ simdutf_warn_unused size_t convert_valid_utf8_to_utf16be( const char *input, size_t length, char16_t *utf16_buffer) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t convert_valid_utf8_to_utf16be( + const detail::input_span_of_byte_like auto &valid_utf8_input, + std::span utf16_output) noexcept { + return convert_valid_utf8_to_utf16be( + reinterpret_cast(valid_utf8_input.data()), + valid_utf8_input.size(), utf16_output.data()); +} +#endif /** * Convert valid UTF-8 string into UTF-32 string. @@ -1585,6 +1893,15 @@ simdutf_warn_unused size_t convert_valid_utf8_to_utf16be( */ simdutf_warn_unused size_t convert_valid_utf8_to_utf32( const char *input, size_t length, char32_t *utf32_buffer) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t convert_valid_utf8_to_utf32( + const detail::input_span_of_byte_like auto &valid_utf8_input, + std::span utf32_output) noexcept { + return convert_valid_utf8_to_utf32( + reinterpret_cast(valid_utf8_input.data()), + valid_utf8_input.size(), utf32_output.data()); +} +#endif /** * Return the number of bytes that this Latin1 string would require in UTF-8 @@ -1596,6 +1913,13 @@ simdutf_warn_unused size_t convert_valid_utf8_to_utf32( */ simdutf_warn_unused size_t utf8_length_from_latin1(const char *input, size_t length) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t utf8_length_from_latin1( + const detail::input_span_of_byte_like auto &latin1_input) noexcept { + return utf8_length_from_latin1( + reinterpret_cast(latin1_input.data()), latin1_input.size()); +} +#endif /** * Compute the number of bytes that this UTF-8 string would require in Latin1 @@ -1612,6 +1936,14 @@ simdutf_warn_unused size_t utf8_length_from_latin1(const char *input, */ simdutf_warn_unused size_t latin1_length_from_utf8(const char *input, size_t length) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t latin1_length_from_utf8( + const detail::input_span_of_byte_like auto &valid_utf8_input) noexcept { + return latin1_length_from_utf8( + reinterpret_cast(valid_utf8_input.data()), + valid_utf8_input.size()); +} +#endif /** * Compute the number of 2-byte code units that this UTF-8 string would require @@ -1629,6 +1961,14 @@ simdutf_warn_unused size_t latin1_length_from_utf8(const char *input, */ simdutf_warn_unused size_t utf16_length_from_utf8(const char *input, size_t length) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t utf16_length_from_utf8( + const detail::input_span_of_byte_like auto &valid_utf8_input) noexcept { + return utf16_length_from_utf8( + reinterpret_cast(valid_utf8_input.data()), + valid_utf8_input.size()); +} +#endif /** * Compute the number of 4-byte code units that this UTF-8 string would require @@ -1648,6 +1988,14 @@ simdutf_warn_unused size_t utf16_length_from_utf8(const char *input, */ simdutf_warn_unused size_t utf32_length_from_utf8(const char *input, size_t length) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t utf32_length_from_utf8( + const detail::input_span_of_byte_like auto &valid_utf8_input) noexcept { + return utf32_length_from_utf8( + reinterpret_cast(valid_utf8_input.data()), + valid_utf8_input.size()); +} +#endif /** * Using native endianness, convert possibly broken UTF-16 string into UTF-8 @@ -1667,6 +2015,14 @@ simdutf_warn_unused size_t utf32_length_from_utf8(const char *input, simdutf_warn_unused size_t convert_utf16_to_utf8(const char16_t *input, size_t length, char *utf8_buffer) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t convert_utf16_to_utf8( + std::span utf16_input, + detail::output_span_of_byte_like auto &&utf8_output) noexcept { + return convert_utf16_to_utf8(utf16_input.data(), utf16_input.size(), + reinterpret_cast(utf8_output.data())); +} +#endif /** * Using native endianness, convert possibly broken UTF-16 string into Latin1 @@ -1685,6 +2041,15 @@ simdutf_warn_unused size_t convert_utf16_to_utf8(const char16_t *input, */ simdutf_warn_unused size_t convert_utf16_to_latin1( const char16_t *input, size_t length, char *latin1_buffer) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t convert_utf16_to_latin1( + std::span utf16_input, + detail::output_span_of_byte_like auto &&latin1_output) noexcept { + return convert_utf16_to_latin1( + utf16_input.data(), utf16_input.size(), + reinterpret_cast(latin1_output.data())); +} +#endif /** * Convert possibly broken UTF-16LE string into Latin1 string. @@ -1704,6 +2069,15 @@ simdutf_warn_unused size_t convert_utf16_to_latin1( */ simdutf_warn_unused size_t convert_utf16le_to_latin1( const char16_t *input, size_t length, char *latin1_buffer) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t convert_utf16le_to_latin1( + std::span utf16_input, + detail::output_span_of_byte_like auto &&latin1_output) noexcept { + return convert_utf16le_to_latin1( + utf16_input.data(), utf16_input.size(), + reinterpret_cast(latin1_output.data())); +} +#endif /** * Convert possibly broken UTF-16BE string into Latin1 string. @@ -1721,6 +2095,15 @@ simdutf_warn_unused size_t convert_utf16le_to_latin1( */ simdutf_warn_unused size_t convert_utf16be_to_latin1( const char16_t *input, size_t length, char *latin1_buffer) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t convert_utf16be_to_latin1( + std::span utf16_input, + detail::output_span_of_byte_like auto &&latin1_output) noexcept { + return convert_utf16be_to_latin1( + utf16_input.data(), utf16_input.size(), + reinterpret_cast(latin1_output.data())); +} +#endif /** * Convert possibly broken UTF-16LE string into UTF-8 string. @@ -1739,6 +2122,14 @@ simdutf_warn_unused size_t convert_utf16be_to_latin1( simdutf_warn_unused size_t convert_utf16le_to_utf8(const char16_t *input, size_t length, char *utf8_buffer) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t convert_utf16le_to_utf8( + std::span utf16_input, + detail::output_span_of_byte_like auto &&utf8_output) noexcept { + return convert_utf16le_to_utf8(utf16_input.data(), utf16_input.size(), + reinterpret_cast(utf8_output.data())); +} +#endif /** * Convert possibly broken UTF-16BE string into UTF-8 string. @@ -1757,6 +2148,14 @@ simdutf_warn_unused size_t convert_utf16le_to_utf8(const char16_t *input, simdutf_warn_unused size_t convert_utf16be_to_utf8(const char16_t *input, size_t length, char *utf8_buffer) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t convert_utf16be_to_utf8( + std::span utf16_input, + detail::output_span_of_byte_like auto &&utf8_output) noexcept { + return convert_utf16be_to_utf8(utf16_input.data(), utf16_input.size(), + reinterpret_cast(utf8_output.data())); +} +#endif /** * Using native endianness, convert possibly broken UTF-16 string into Latin1 @@ -1776,6 +2175,16 @@ simdutf_warn_unused size_t convert_utf16be_to_utf8(const char16_t *input, */ simdutf_warn_unused result convert_utf16_to_latin1_with_errors( const char16_t *input, size_t length, char *latin1_buffer) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused result +convert_utf16_to_latin1_with_errors( + std::span utf16_input, + detail::output_span_of_byte_like auto &&latin1_output) noexcept { + return convert_utf16_to_latin1_with_errors( + utf16_input.data(), utf16_input.size(), + reinterpret_cast(latin1_output.data())); +} +#endif /** * Convert possibly broken UTF-16LE string into Latin1 string. @@ -1794,6 +2203,16 @@ simdutf_warn_unused result convert_utf16_to_latin1_with_errors( */ simdutf_warn_unused result convert_utf16le_to_latin1_with_errors( const char16_t *input, size_t length, char *latin1_buffer) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused result +convert_utf16le_to_latin1_with_errors( + std::span utf16_input, + detail::output_span_of_byte_like auto &&latin1_output) noexcept { + return convert_utf16le_to_latin1_with_errors( + utf16_input.data(), utf16_input.size(), + reinterpret_cast(latin1_output.data())); +} +#endif /** * Convert possibly broken UTF-16BE string into Latin1 string. @@ -1814,6 +2233,16 @@ simdutf_warn_unused result convert_utf16le_to_latin1_with_errors( */ simdutf_warn_unused result convert_utf16be_to_latin1_with_errors( const char16_t *input, size_t length, char *latin1_buffer) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused result +convert_utf16be_to_latin1_with_errors( + std::span utf16_input, + detail::output_span_of_byte_like auto &&latin1_output) noexcept { + return convert_utf16be_to_latin1_with_errors( + utf16_input.data(), utf16_input.size(), + reinterpret_cast(latin1_output.data())); +} +#endif /** * Using native endianness, convert possibly broken UTF-16 string into UTF-8 @@ -1834,6 +2263,16 @@ simdutf_warn_unused result convert_utf16be_to_latin1_with_errors( */ simdutf_warn_unused result convert_utf16_to_utf8_with_errors( const char16_t *input, size_t length, char *utf8_buffer) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused result +convert_utf16_to_utf8_with_errors( + std::span utf16_input, + detail::output_span_of_byte_like auto &&utf8_output) noexcept { + return convert_utf16_to_utf8_with_errors( + utf16_input.data(), utf16_input.size(), + reinterpret_cast(utf8_output.data())); +} +#endif /** * Convert possibly broken UTF-16LE string into UTF-8 string and stop on error. @@ -1853,6 +2292,16 @@ simdutf_warn_unused result convert_utf16_to_utf8_with_errors( */ simdutf_warn_unused result convert_utf16le_to_utf8_with_errors( const char16_t *input, size_t length, char *utf8_buffer) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused result +convert_utf16le_to_utf8_with_errors( + std::span utf16_input, + detail::output_span_of_byte_like auto &&utf8_output) noexcept { + return convert_utf16le_to_utf8_with_errors( + utf16_input.data(), utf16_input.size(), + reinterpret_cast(utf8_output.data())); +} +#endif /** * Convert possibly broken UTF-16BE string into UTF-8 string and stop on error. @@ -1872,6 +2321,16 @@ simdutf_warn_unused result convert_utf16le_to_utf8_with_errors( */ simdutf_warn_unused result convert_utf16be_to_utf8_with_errors( const char16_t *input, size_t length, char *utf8_buffer) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused result +convert_utf16be_to_utf8_with_errors( + std::span utf16_input, + detail::output_span_of_byte_like auto &&utf8_output) noexcept { + return convert_utf16be_to_utf8_with_errors( + utf16_input.data(), utf16_input.size(), + reinterpret_cast(utf8_output.data())); +} +#endif /** * Using native endianness, convert valid UTF-16 string into UTF-8 string. @@ -1888,6 +2347,15 @@ simdutf_warn_unused result convert_utf16be_to_utf8_with_errors( */ simdutf_warn_unused size_t convert_valid_utf16_to_utf8( const char16_t *input, size_t length, char *utf8_buffer) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t convert_valid_utf16_to_utf8( + std::span valid_utf16_input, + detail::output_span_of_byte_like auto &&utf8_output) noexcept { + return convert_valid_utf16_to_utf8( + valid_utf16_input.data(), valid_utf16_input.size(), + reinterpret_cast(utf8_output.data())); +} +#endif /** * Using native endianness, convert UTF-16 string into Latin1 string. @@ -1910,6 +2378,15 @@ simdutf_warn_unused size_t convert_valid_utf16_to_utf8( */ simdutf_warn_unused size_t convert_valid_utf16_to_latin1( const char16_t *input, size_t length, char *latin1_buffer) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t convert_valid_utf16_to_latin1( + std::span valid_utf16_input, + detail::output_span_of_byte_like auto &&latin1_output) noexcept { + return convert_valid_utf16_to_latin1( + valid_utf16_input.data(), valid_utf16_input.size(), + reinterpret_cast(latin1_output.data())); +} +#endif /** * Convert valid UTF-16LE string into Latin1 string. @@ -1932,6 +2409,16 @@ simdutf_warn_unused size_t convert_valid_utf16_to_latin1( */ simdutf_warn_unused size_t convert_valid_utf16le_to_latin1( const char16_t *input, size_t length, char *latin1_buffer) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t +convert_valid_utf16le_to_latin1( + std::span valid_utf16_input, + detail::output_span_of_byte_like auto &&latin1_output) noexcept { + return convert_valid_utf16le_to_latin1( + valid_utf16_input.data(), valid_utf16_input.size(), + reinterpret_cast(latin1_output.data())); +} +#endif /** * Convert valid UTF-16BE string into Latin1 string. @@ -1954,6 +2441,16 @@ simdutf_warn_unused size_t convert_valid_utf16le_to_latin1( */ simdutf_warn_unused size_t convert_valid_utf16be_to_latin1( const char16_t *input, size_t length, char *latin1_buffer) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t +convert_valid_utf16be_to_latin1( + std::span valid_utf16_input, + detail::output_span_of_byte_like auto &&latin1_output) noexcept { + return convert_valid_utf16be_to_latin1( + valid_utf16_input.data(), valid_utf16_input.size(), + reinterpret_cast(latin1_output.data())); +} +#endif /** * Convert valid UTF-16LE string into UTF-8 string. @@ -1971,6 +2468,15 @@ simdutf_warn_unused size_t convert_valid_utf16be_to_latin1( */ simdutf_warn_unused size_t convert_valid_utf16le_to_utf8( const char16_t *input, size_t length, char *utf8_buffer) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t convert_valid_utf16le_to_utf8( + std::span valid_utf16_input, + detail::output_span_of_byte_like auto &&utf8_output) noexcept { + return convert_valid_utf16le_to_utf8( + valid_utf16_input.data(), valid_utf16_input.size(), + reinterpret_cast(utf8_output.data())); +} +#endif /** * Convert valid UTF-16BE string into UTF-8 string. @@ -1987,6 +2493,15 @@ simdutf_warn_unused size_t convert_valid_utf16le_to_utf8( */ simdutf_warn_unused size_t convert_valid_utf16be_to_utf8( const char16_t *input, size_t length, char *utf8_buffer) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t convert_valid_utf16be_to_utf8( + std::span valid_utf16_input, + detail::output_span_of_byte_like auto &&utf8_output) noexcept { + return convert_valid_utf16be_to_utf8( + valid_utf16_input.data(), valid_utf16_input.size(), + reinterpret_cast(utf8_output.data())); +} +#endif /** * Using native endianness, convert possibly broken UTF-16 string into UTF-32 @@ -2005,6 +2520,14 @@ simdutf_warn_unused size_t convert_valid_utf16be_to_utf8( */ simdutf_warn_unused size_t convert_utf16_to_utf32( const char16_t *input, size_t length, char32_t *utf32_buffer) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t +convert_utf16_to_utf32(std::span utf16_input, + std::span utf32_output) noexcept { + return convert_utf16_to_utf32(utf16_input.data(), utf16_input.size(), + utf32_output.data()); +} +#endif /** * Convert possibly broken UTF-16LE string into UTF-32 string. @@ -2022,6 +2545,14 @@ simdutf_warn_unused size_t convert_utf16_to_utf32( */ simdutf_warn_unused size_t convert_utf16le_to_utf32( const char16_t *input, size_t length, char32_t *utf32_buffer) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t +convert_utf16le_to_utf32(std::span utf16_input, + std::span utf32_output) noexcept { + return convert_utf16le_to_utf32(utf16_input.data(), utf16_input.size(), + utf32_output.data()); +} +#endif /** * Convert possibly broken UTF-16BE string into UTF-32 string. @@ -2039,6 +2570,14 @@ simdutf_warn_unused size_t convert_utf16le_to_utf32( */ simdutf_warn_unused size_t convert_utf16be_to_utf32( const char16_t *input, size_t length, char32_t *utf32_buffer) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t +convert_utf16be_to_utf32(std::span utf16_input, + std::span utf32_output) noexcept { + return convert_utf16be_to_utf32(utf16_input.data(), utf16_input.size(), + utf32_output.data()); +} +#endif /** * Using native endianness, convert possibly broken UTF-16 string into @@ -2059,6 +2598,14 @@ simdutf_warn_unused size_t convert_utf16be_to_utf32( */ simdutf_warn_unused result convert_utf16_to_utf32_with_errors( const char16_t *input, size_t length, char32_t *utf32_buffer) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused result +convert_utf16_to_utf32_with_errors(std::span utf16_input, + std::span utf32_output) noexcept { + return convert_utf16_to_utf32_with_errors( + utf16_input.data(), utf16_input.size(), utf32_output.data()); +} +#endif /** * Convert possibly broken UTF-16LE string into UTF-32 string and stop on error. @@ -2078,6 +2625,15 @@ simdutf_warn_unused result convert_utf16_to_utf32_with_errors( */ simdutf_warn_unused result convert_utf16le_to_utf32_with_errors( const char16_t *input, size_t length, char32_t *utf32_buffer) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused result +convert_utf16le_to_utf32_with_errors( + std::span utf16_input, + std::span utf32_output) noexcept { + return convert_utf16le_to_utf32_with_errors( + utf16_input.data(), utf16_input.size(), utf32_output.data()); +} +#endif /** * Convert possibly broken UTF-16BE string into UTF-32 string and stop on error. @@ -2097,6 +2653,15 @@ simdutf_warn_unused result convert_utf16le_to_utf32_with_errors( */ simdutf_warn_unused result convert_utf16be_to_utf32_with_errors( const char16_t *input, size_t length, char32_t *utf32_buffer) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused result +convert_utf16be_to_utf32_with_errors( + std::span utf16_input, + std::span utf32_output) noexcept { + return convert_utf16be_to_utf32_with_errors( + utf16_input.data(), utf16_input.size(), utf32_output.data()); +} +#endif /** * Using native endianness, convert valid UTF-16 string into UTF-32 string. @@ -2114,6 +2679,14 @@ simdutf_warn_unused result convert_utf16be_to_utf32_with_errors( */ simdutf_warn_unused size_t convert_valid_utf16_to_utf32( const char16_t *input, size_t length, char32_t *utf32_buffer) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t +convert_valid_utf16_to_utf32(std::span valid_utf16_input, + std::span utf32_output) noexcept { + return convert_valid_utf16_to_utf32( + valid_utf16_input.data(), valid_utf16_input.size(), utf32_output.data()); +} +#endif /** * Convert valid UTF-16LE string into UTF-32 string. @@ -2130,6 +2703,14 @@ simdutf_warn_unused size_t convert_valid_utf16_to_utf32( */ simdutf_warn_unused size_t convert_valid_utf16le_to_utf32( const char16_t *input, size_t length, char32_t *utf32_buffer) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t +convert_valid_utf16le_to_utf32(std::span valid_utf16_input, + std::span utf32_output) noexcept { + return convert_valid_utf16le_to_utf32( + valid_utf16_input.data(), valid_utf16_input.size(), utf32_output.data()); +} +#endif /** * Convert valid UTF-16BE string into UTF-32 string. @@ -2146,8 +2727,16 @@ simdutf_warn_unused size_t convert_valid_utf16le_to_utf32( */ simdutf_warn_unused size_t convert_valid_utf16be_to_utf32( const char16_t *input, size_t length, char32_t *utf32_buffer) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t +convert_valid_utf16be_to_utf32(std::span valid_utf16_input, + std::span utf32_output) noexcept { + return convert_valid_utf16be_to_utf32( + valid_utf16_input.data(), valid_utf16_input.size(), utf32_output.data()); +} +#endif -/* +/** * Compute the number of bytes that this UTF-16LE/BE string would require in * Latin1 format. * @@ -2174,6 +2763,13 @@ simdutf_warn_unused size_t latin1_length_from_utf16(size_t length) noexcept; */ simdutf_warn_unused size_t utf8_length_from_utf16(const char16_t *input, size_t length) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t +utf8_length_from_utf16(std::span valid_utf16_input) noexcept { + return utf8_length_from_utf16(valid_utf16_input.data(), + valid_utf16_input.size()); +} +#endif /** * Compute the number of bytes that this UTF-16LE string would require in UTF-8 @@ -2188,6 +2784,13 @@ simdutf_warn_unused size_t utf8_length_from_utf16(const char16_t *input, */ simdutf_warn_unused size_t utf8_length_from_utf16le(const char16_t *input, size_t length) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t +utf8_length_from_utf16le(std::span valid_utf16_input) noexcept { + return utf8_length_from_utf16le(valid_utf16_input.data(), + valid_utf16_input.size()); +} +#endif /** * Compute the number of bytes that this UTF-16BE string would require in UTF-8 @@ -2202,6 +2805,13 @@ simdutf_warn_unused size_t utf8_length_from_utf16le(const char16_t *input, */ simdutf_warn_unused size_t utf8_length_from_utf16be(const char16_t *input, size_t length) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t +utf8_length_from_utf16be(std::span valid_utf16_input) noexcept { + return utf8_length_from_utf16be(valid_utf16_input.data(), + valid_utf16_input.size()); +} +#endif /** * Convert possibly broken UTF-32 string into UTF-8 string. @@ -2219,6 +2829,14 @@ simdutf_warn_unused size_t utf8_length_from_utf16be(const char16_t *input, simdutf_warn_unused size_t convert_utf32_to_utf8(const char32_t *input, size_t length, char *utf8_buffer) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t convert_utf32_to_utf8( + std::span utf32_input, + detail::output_span_of_byte_like auto &&utf8_output) noexcept { + return convert_utf32_to_utf8(utf32_input.data(), utf32_input.size(), + reinterpret_cast(utf8_output.data())); +} +#endif /** * Convert possibly broken UTF-32 string into UTF-8 string and stop on error. @@ -2238,6 +2856,16 @@ simdutf_warn_unused size_t convert_utf32_to_utf8(const char32_t *input, */ simdutf_warn_unused result convert_utf32_to_utf8_with_errors( const char32_t *input, size_t length, char *utf8_buffer) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused result +convert_utf32_to_utf8_with_errors( + std::span utf32_input, + detail::output_span_of_byte_like auto &&utf8_output) noexcept { + return convert_utf32_to_utf8_with_errors( + utf32_input.data(), utf32_input.size(), + reinterpret_cast(utf8_output.data())); +} +#endif /** * Convert valid UTF-32 string into UTF-8 string. @@ -2254,6 +2882,15 @@ simdutf_warn_unused result convert_utf32_to_utf8_with_errors( */ simdutf_warn_unused size_t convert_valid_utf32_to_utf8( const char32_t *input, size_t length, char *utf8_buffer) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t convert_valid_utf32_to_utf8( + std::span valid_utf32_input, + detail::output_span_of_byte_like auto &&utf8_output) noexcept { + return convert_valid_utf32_to_utf8( + valid_utf32_input.data(), valid_utf32_input.size(), + reinterpret_cast(utf8_output.data())); +} +#endif /** * Using native endianness, convert possibly broken UTF-32 string into a UTF-16 @@ -2271,6 +2908,14 @@ simdutf_warn_unused size_t convert_valid_utf32_to_utf8( */ simdutf_warn_unused size_t convert_utf32_to_utf16( const char32_t *input, size_t length, char16_t *utf16_buffer) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t +convert_utf32_to_utf16(std::span utf32_input, + std::span utf16_output) noexcept { + return convert_utf32_to_utf16(utf32_input.data(), utf32_input.size(), + utf16_output.data()); +} +#endif /** * Convert possibly broken UTF-32 string into UTF-16LE string. @@ -2287,6 +2932,14 @@ simdutf_warn_unused size_t convert_utf32_to_utf16( */ simdutf_warn_unused size_t convert_utf32_to_utf16le( const char32_t *input, size_t length, char16_t *utf16_buffer) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t +convert_utf32_to_utf16le(std::span utf32_input, + std::span utf16_output) noexcept { + return convert_utf32_to_utf16le(utf32_input.data(), utf32_input.size(), + utf16_output.data()); +} +#endif /** * Convert possibly broken UTF-32 string into Latin1 string. @@ -2304,6 +2957,15 @@ simdutf_warn_unused size_t convert_utf32_to_utf16le( */ simdutf_warn_unused size_t convert_utf32_to_latin1( const char32_t *input, size_t length, char *latin1_buffer) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t convert_utf32_to_latin1( + std::span utf32_input, + detail::output_span_of_byte_like auto &&latin1_output) noexcept { + return convert_utf32_to_latin1( + utf32_input.data(), utf32_input.size(), + reinterpret_cast(latin1_output.data())); +} +#endif /** * Convert possibly broken UTF-32 string into Latin1 string and stop on error. @@ -2324,6 +2986,16 @@ simdutf_warn_unused size_t convert_utf32_to_latin1( */ simdutf_warn_unused result convert_utf32_to_latin1_with_errors( const char32_t *input, size_t length, char *latin1_buffer) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused result +convert_utf32_to_latin1_with_errors( + std::span utf32_input, + detail::output_span_of_byte_like auto &&latin1_output) noexcept { + return convert_utf32_to_latin1_with_errors( + utf32_input.data(), utf32_input.size(), + reinterpret_cast(latin1_output.data())); +} +#endif /** * Convert valid UTF-32 string into Latin1 string. @@ -2347,6 +3019,15 @@ simdutf_warn_unused result convert_utf32_to_latin1_with_errors( */ simdutf_warn_unused size_t convert_valid_utf32_to_latin1( const char32_t *input, size_t length, char *latin1_buffer) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t convert_valid_utf32_to_latin1( + std::span valid_utf32_input, + detail::output_span_of_byte_like auto &&latin1_output) noexcept { + return convert_valid_utf32_to_latin1( + valid_utf32_input.data(), valid_utf32_input.size(), + reinterpret_cast(latin1_output.data())); +} +#endif /** * Convert possibly broken UTF-32 string into UTF-16BE string. @@ -2363,6 +3044,14 @@ simdutf_warn_unused size_t convert_valid_utf32_to_latin1( */ simdutf_warn_unused size_t convert_utf32_to_utf16be( const char32_t *input, size_t length, char16_t *utf16_buffer) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t +convert_utf32_to_utf16be(std::span utf32_input, + std::span utf16_output) noexcept { + return convert_utf32_to_utf16be(utf32_input.data(), utf32_input.size(), + utf16_output.data()); +} +#endif /** * Using native endianness, convert possibly broken UTF-32 string into UTF-16 @@ -2383,6 +3072,14 @@ simdutf_warn_unused size_t convert_utf32_to_utf16be( */ simdutf_warn_unused result convert_utf32_to_utf16_with_errors( const char32_t *input, size_t length, char16_t *utf16_buffer) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused result +convert_utf32_to_utf16_with_errors(std::span utf32_input, + std::span utf16_output) noexcept { + return convert_utf32_to_utf16_with_errors( + utf32_input.data(), utf32_input.size(), utf16_output.data()); +} +#endif /** * Convert possibly broken UTF-32 string into UTF-16LE string and stop on error. @@ -2402,6 +3099,15 @@ simdutf_warn_unused result convert_utf32_to_utf16_with_errors( */ simdutf_warn_unused result convert_utf32_to_utf16le_with_errors( const char32_t *input, size_t length, char16_t *utf16_buffer) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused result +convert_utf32_to_utf16le_with_errors( + std::span utf32_input, + std::span utf16_output) noexcept { + return convert_utf32_to_utf16le_with_errors( + utf32_input.data(), utf32_input.size(), utf16_output.data()); +} +#endif /** * Convert possibly broken UTF-32 string into UTF-16BE string and stop on error. @@ -2421,6 +3127,15 @@ simdutf_warn_unused result convert_utf32_to_utf16le_with_errors( */ simdutf_warn_unused result convert_utf32_to_utf16be_with_errors( const char32_t *input, size_t length, char16_t *utf16_buffer) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused result +convert_utf32_to_utf16be_with_errors( + std::span utf32_input, + std::span utf16_output) noexcept { + return convert_utf32_to_utf16be_with_errors( + utf32_input.data(), utf32_input.size(), utf16_output.data()); +} +#endif /** * Using native endianness, convert valid UTF-32 string into a UTF-16 string. @@ -2437,6 +3152,14 @@ simdutf_warn_unused result convert_utf32_to_utf16be_with_errors( */ simdutf_warn_unused size_t convert_valid_utf32_to_utf16( const char32_t *input, size_t length, char16_t *utf16_buffer) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t +convert_valid_utf32_to_utf16(std::span valid_utf32_input, + std::span utf16_output) noexcept { + return convert_valid_utf32_to_utf16( + valid_utf32_input.data(), valid_utf32_input.size(), utf16_output.data()); +} +#endif /** * Convert valid UTF-32 string into UTF-16LE string. @@ -2453,6 +3176,14 @@ simdutf_warn_unused size_t convert_valid_utf32_to_utf16( */ simdutf_warn_unused size_t convert_valid_utf32_to_utf16le( const char32_t *input, size_t length, char16_t *utf16_buffer) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t +convert_valid_utf32_to_utf16le(std::span valid_utf32_input, + std::span utf16_output) noexcept { + return convert_valid_utf32_to_utf16le( + valid_utf32_input.data(), valid_utf32_input.size(), utf16_output.data()); +} +#endif /** * Convert valid UTF-32 string into UTF-16BE string. @@ -2469,6 +3200,14 @@ simdutf_warn_unused size_t convert_valid_utf32_to_utf16le( */ simdutf_warn_unused size_t convert_valid_utf32_to_utf16be( const char32_t *input, size_t length, char16_t *utf16_buffer) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t +convert_valid_utf32_to_utf16be(std::span valid_utf32_input, + std::span utf16_output) noexcept { + return convert_valid_utf32_to_utf16be( + valid_utf32_input.data(), valid_utf32_input.size(), utf16_output.data()); +} +#endif /** * Change the endianness of the input. Can be used to go from UTF-16LE to @@ -2485,6 +3224,14 @@ simdutf_warn_unused size_t convert_valid_utf32_to_utf16be( */ void change_endianness_utf16(const char16_t *input, size_t length, char16_t *output) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline void +change_endianness_utf16(std::span utf16_input, + std::span utf16_output) noexcept { + return change_endianness_utf16(utf16_input.data(), utf16_input.size(), + utf16_output.data()); +} +#endif /** * Compute the number of bytes that this UTF-32 string would require in UTF-8 @@ -2499,6 +3246,13 @@ void change_endianness_utf16(const char16_t *input, size_t length, */ simdutf_warn_unused size_t utf8_length_from_utf32(const char32_t *input, size_t length) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t +utf8_length_from_utf32(std::span valid_utf32_input) noexcept { + return utf8_length_from_utf32(valid_utf32_input.data(), + valid_utf32_input.size()); +} +#endif /** * Compute the number of two-byte code units that this UTF-32 string would @@ -2513,6 +3267,13 @@ simdutf_warn_unused size_t utf8_length_from_utf32(const char32_t *input, */ simdutf_warn_unused size_t utf16_length_from_utf32(const char32_t *input, size_t length) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t +utf16_length_from_utf32(std::span valid_utf32_input) noexcept { + return utf16_length_from_utf32(valid_utf32_input.data(), + valid_utf32_input.size()); +} +#endif /** * Using native endianness; Compute the number of bytes that this UTF-16 @@ -2531,6 +3292,13 @@ simdutf_warn_unused size_t utf16_length_from_utf32(const char32_t *input, */ simdutf_warn_unused size_t utf32_length_from_utf16(const char16_t *input, size_t length) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t +utf32_length_from_utf16(std::span valid_utf16_input) noexcept { + return utf32_length_from_utf16(valid_utf16_input.data(), + valid_utf16_input.size()); +} +#endif /** * Compute the number of bytes that this UTF-16LE string would require in UTF-32 @@ -2549,6 +3317,13 @@ simdutf_warn_unused size_t utf32_length_from_utf16(const char16_t *input, */ simdutf_warn_unused size_t utf32_length_from_utf16le(const char16_t *input, size_t length) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t utf32_length_from_utf16le( + std::span valid_utf16_input) noexcept { + return utf32_length_from_utf16le(valid_utf16_input.data(), + valid_utf16_input.size()); +} +#endif /** * Compute the number of bytes that this UTF-16BE string would require in UTF-32 @@ -2567,6 +3342,13 @@ simdutf_warn_unused size_t utf32_length_from_utf16le(const char16_t *input, */ simdutf_warn_unused size_t utf32_length_from_utf16be(const char16_t *input, size_t length) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t utf32_length_from_utf16be( + std::span valid_utf16_input) noexcept { + return utf32_length_from_utf16be(valid_utf16_input.data(), + valid_utf16_input.size()); +} +#endif /** * Count the number of code points (characters) in the string assuming that @@ -2584,6 +3366,12 @@ simdutf_warn_unused size_t utf32_length_from_utf16be(const char16_t *input, */ simdutf_warn_unused size_t count_utf16(const char16_t *input, size_t length) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t +count_utf16(std::span valid_utf16_input) noexcept { + return count_utf16(valid_utf16_input.data(), valid_utf16_input.size()); +} +#endif /** * Count the number of code points (characters) in the string assuming that @@ -2601,6 +3389,12 @@ simdutf_warn_unused size_t count_utf16(const char16_t *input, */ simdutf_warn_unused size_t count_utf16le(const char16_t *input, size_t length) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t +count_utf16le(std::span valid_utf16_input) noexcept { + return count_utf16le(valid_utf16_input.data(), valid_utf16_input.size()); +} +#endif /** * Count the number of code points (characters) in the string assuming that @@ -2618,6 +3412,12 @@ simdutf_warn_unused size_t count_utf16le(const char16_t *input, */ simdutf_warn_unused size_t count_utf16be(const char16_t *input, size_t length) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t +count_utf16be(std::span valid_utf16_input) noexcept { + return count_utf16be(valid_utf16_input.data(), valid_utf16_input.size()); +} +#endif /** * Count the number of code points (characters) in the string assuming that @@ -2633,6 +3433,13 @@ simdutf_warn_unused size_t count_utf16be(const char16_t *input, */ simdutf_warn_unused size_t count_utf8(const char *input, size_t length) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t count_utf8( + const detail::input_span_of_byte_like auto &valid_utf8_input) noexcept { + return count_utf8(reinterpret_cast(valid_utf8_input.data()), + valid_utf8_input.size()); +} +#endif /** * Given a valid UTF-8 string having a possibly truncated last character, @@ -2649,6 +3456,14 @@ simdutf_warn_unused size_t count_utf8(const char *input, * @return the length of the string in bytes, possibly shorter by 1 to 3 bytes */ simdutf_warn_unused size_t trim_partial_utf8(const char *input, size_t length); +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t trim_partial_utf8( + const detail::input_span_of_byte_like auto &valid_utf8_input) noexcept { + return trim_partial_utf8( + reinterpret_cast(valid_utf8_input.data()), + valid_utf8_input.size()); +} +#endif /** * Given a valid UTF-16BE string having a possibly truncated last character, @@ -2666,6 +3481,13 @@ simdutf_warn_unused size_t trim_partial_utf8(const char *input, size_t length); */ simdutf_warn_unused size_t trim_partial_utf16be(const char16_t *input, size_t length); +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t +trim_partial_utf16be(std::span valid_utf16_input) noexcept { + return trim_partial_utf16be(valid_utf16_input.data(), + valid_utf16_input.size()); +} +#endif /** * Given a valid UTF-16LE string having a possibly truncated last character, @@ -2683,6 +3505,13 @@ simdutf_warn_unused size_t trim_partial_utf16be(const char16_t *input, */ simdutf_warn_unused size_t trim_partial_utf16le(const char16_t *input, size_t length); +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t +trim_partial_utf16le(std::span valid_utf16_input) noexcept { + return trim_partial_utf16le(valid_utf16_input.data(), + valid_utf16_input.size()); +} +#endif /** * Given a valid UTF-16 string having a possibly truncated last character, @@ -2700,6 +3529,12 @@ simdutf_warn_unused size_t trim_partial_utf16le(const char16_t *input, */ simdutf_warn_unused size_t trim_partial_utf16(const char16_t *input, size_t length); +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t +trim_partial_utf16(std::span valid_utf16_input) noexcept { + return trim_partial_utf16(valid_utf16_input.data(), valid_utf16_input.size()); +} +#endif // base64_options are used to specify the base64 encoding options. // ASCII spaces are ' ', '\t', '\n', '\r', '\f' @@ -2742,6 +3577,14 @@ enum last_chunk_handling_options : uint64_t { */ simdutf_warn_unused size_t maximal_binary_length_from_base64(const char *input, size_t length) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t +maximal_binary_length_from_base64( + const detail::input_span_of_byte_like auto &input) noexcept { + return maximal_binary_length_from_base64( + reinterpret_cast(input.data()), input.size()); +} +#endif /** * Provide the maximal binary length in bytes given the base64 input. @@ -2755,6 +3598,12 @@ maximal_binary_length_from_base64(const char *input, size_t length) noexcept; */ simdutf_warn_unused size_t maximal_binary_length_from_base64( const char16_t *input, size_t length) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t +maximal_binary_length_from_base64(std::span input) noexcept { + return maximal_binary_length_from_base64(input.data(), input.size()); +} +#endif /** * Convert a base64 input to a binary output. @@ -2814,6 +3663,18 @@ simdutf_warn_unused result base64_to_binary( const char *input, size_t length, char *output, base64_options options = base64_default, last_chunk_handling_options last_chunk_options = loose) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused result base64_to_binary( + const detail::input_span_of_byte_like auto &input, + detail::output_span_of_byte_like auto &&binary_output, + base64_options options = base64_default, + last_chunk_handling_options last_chunk_options = loose) noexcept { + return base64_to_binary(reinterpret_cast(input.data()), + input.size(), + reinterpret_cast(binary_output.data()), + options, last_chunk_options); +} +#endif /** * Provide the base64 length in bytes given the length of a binary input. @@ -2847,6 +3708,16 @@ simdutf_warn_unused size_t base64_length_from_binary( */ size_t binary_to_base64(const char *input, size_t length, char *output, base64_options options = base64_default) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused size_t +binary_to_base64(const detail::input_span_of_byte_like auto &input, + detail::output_span_of_byte_like auto &&binary_output, + base64_options options = base64_default) noexcept { + return binary_to_base64( + reinterpret_cast(input.data()), input.size(), + reinterpret_cast(binary_output.data()), options); +} +#endif /** * Convert a base64 input to a binary output. @@ -2909,6 +3780,17 @@ base64_to_binary(const char16_t *input, size_t length, char *output, base64_options options = base64_default, last_chunk_handling_options last_chunk_options = last_chunk_handling_options::loose) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused result base64_to_binary( + std::span input, + detail::output_span_of_byte_like auto &&binary_output, + base64_options options = base64_default, + last_chunk_handling_options last_chunk_options = loose) noexcept { + return base64_to_binary(input.data(), input.size(), + reinterpret_cast(binary_output.data()), + options, last_chunk_options); +} +#endif /** * Convert a base64 input to a binary output. @@ -2976,11 +3858,43 @@ base64_to_binary_safe(const char *input, size_t length, char *output, size_t &outlen, base64_options options = base64_default, last_chunk_handling_options last_chunk_options = last_chunk_handling_options::loose) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused result base64_to_binary_safe( + const detail::input_span_of_byte_like auto &input, + detail::output_span_of_byte_like auto &&binary_output, + base64_options options = base64_default, + last_chunk_handling_options last_chunk_options = loose) noexcept { + // we can't write the outlen to the provided output span, the user will have + // to pick it up from the returned value instead (assuming success). we still + // get the benefit of providing info of how long the output buffer is. + size_t outlen = binary_output.size(); + return base64_to_binary_safe(reinterpret_cast(input.data()), + input.size(), + reinterpret_cast(binary_output.data()), + outlen, options, last_chunk_options); +} +#endif + simdutf_warn_unused result base64_to_binary_safe(const char16_t *input, size_t length, char *output, size_t &outlen, base64_options options = base64_default, last_chunk_handling_options last_chunk_options = last_chunk_handling_options::loose) noexcept; +#if SIMDUTF_SPAN +simdutf_really_inline simdutf_warn_unused result base64_to_binary_safe( + std::span input, + detail::output_span_of_byte_like auto &&binary_output, + base64_options options = base64_default, + last_chunk_handling_options last_chunk_options = loose) noexcept { + // we can't write the outlen to the provided output span, the user will have + // to pick it up from the returned value instead (assuming success). we still + // get the benefit of providing info of how long the output buffer is. + size_t outlen = binary_output.size(); + return base64_to_binary_safe(input.data(), input.size(), + reinterpret_cast(binary_output.data()), + outlen, options, last_chunk_options); +} +#endif /** * An implementation of simdutf for a particular CPU architecture. @@ -4243,7 +5157,7 @@ class implementation { simdutf_warn_unused virtual size_t latin1_length_from_utf8(const char *input, size_t length) const noexcept = 0; - /* + /** * Compute the number of bytes that this UTF-16LE/BE string would require in * Latin1 format. * @@ -4289,7 +5203,7 @@ class implementation { simdutf_warn_unused virtual size_t utf32_length_from_latin1(size_t length) const noexcept = 0; - /* + /** * Compute the number of bytes that this UTF-16LE string would require in * UTF-32 format. * @@ -4310,7 +5224,7 @@ class implementation { utf32_length_from_utf16le(const char16_t *input, size_t length) const noexcept = 0; - /* + /** * Compute the number of bytes that this UTF-16BE string would require in * UTF-32 format. * From 5afffb4415b6c63525076202fb9490b40af64dcd Mon Sep 17 00:00:00 2001 From: Carlos Espa <43477095+Ceres6@users.noreply.github.com> Date: Tue, 14 Jan 2025 19:24:30 +0100 Subject: [PATCH 106/205] src,worker: add isInternalWorker PR-URL: https://github.com/nodejs/node/pull/56469 Reviewed-By: Jacob Smith Reviewed-By: James M Snell Reviewed-By: Bryan English --- doc/api/worker_threads.md | 38 ++++++++++++++++++++++ lib/internal/worker.js | 2 ++ lib/worker_threads.js | 2 ++ src/node_worker.cc | 19 +++++++++-- src/node_worker.h | 5 ++- test/fixtures/loader-is-internal-thread.js | 3 ++ test/fixtures/worker-is-internal-thread.js | 3 ++ test/parallel/test-is-internal-thread.mjs | 36 ++++++++++++++++++++ 8 files changed, 104 insertions(+), 4 deletions(-) create mode 100644 test/fixtures/loader-is-internal-thread.js create mode 100644 test/fixtures/worker-is-internal-thread.js create mode 100644 test/parallel/test-is-internal-thread.mjs diff --git a/doc/api/worker_threads.md b/doc/api/worker_threads.md index 36a088027edc5f..d9f6e356fd7519 100644 --- a/doc/api/worker_threads.md +++ b/doc/api/worker_threads.md @@ -100,6 +100,44 @@ if (isMainThread) { } ``` +## `worker.isInternalThread` + + + +* {boolean} + +Is `true` if this code is running inside of an internal [`Worker`][] thread (e.g the loader thread). + +```bash +node --experimental-loader ./loader.js main.js +``` + +```cjs +// loader.js +const { isInternalThread } = require('node:worker_threads'); +console.log(isInternalThread); // true +``` + +```mjs +// loader.js +import { isInternalThread } from 'node:worker_threads'; +console.log(isInternalThread); // true +``` + +```cjs +// main.js +const { isInternalThread } = require('node:worker_threads'); +console.log(isInternalThread); // false +``` + +```mjs +// main.js +import { isInternalThread } from 'node:worker_threads'; +console.log(isInternalThread); // false +``` + ## `worker.isMainThread` + +* `condition` {Function|AsyncFunction} An assertion function that is invoked + periodically until it completes successfully or the defined polling timeout + elapses. Successful completion is defined as not throwing or rejecting. This + function does not accept any arguments, and is allowed to return any value. +* `options` {Object} An optional configuration object for the polling operation. + The following properties are supported: + * `interval` {number} The number of milliseconds to wait after an unsuccessful + invocation of `condition` before trying again. **Default:** `50`. + * `timeout` {number} The poll timeout in milliseconds. If `condition` has not + succeeded by the time this elapses, an error occurs. **Default:** `1000`. +* Returns: {Promise} Fulfilled with the value returned by `condition`. + +This method polls a `condition` function until that function either returns +successfully or the operation times out. + ## Class: `SuiteContext` + +* +* +* +* +* + + + +#### Project contacts + +* @marco-ippolito From d3c0a2831d3df04d5580cb4ce70783f9e4467633 Mon Sep 17 00:00:00 2001 From: Michael Dawson Date: Thu, 16 Jan 2025 17:44:06 -0500 Subject: [PATCH 126/205] doc: tweak info on reposts in ambassador program Signed-off-by: Michael Dawson PR-URL: https://github.com/nodejs/node/pull/56589 Reviewed-By: Rafael Gonzaga Reviewed-By: James M Snell Reviewed-By: Marco Ippolito --- doc/contributing/advocacy-ambassador-program.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/doc/contributing/advocacy-ambassador-program.md b/doc/contributing/advocacy-ambassador-program.md index 058a4d7c45cd69..76f29b73586691 100644 --- a/doc/contributing/advocacy-ambassador-program.md +++ b/doc/contributing/advocacy-ambassador-program.md @@ -94,11 +94,14 @@ process. An ambassador can request promotion of content in the following ways: * Posting a link to the content in the "what's new" issue in nodejs/ambassadors so that it goes out on the news feed. -Foundation staff will repost the social media post -without any need for validation based on the request coming from -an ambassador. These requests can be made through the existing social channel -in the OpenJS Slack. For that reason and for communication purposes and -collaboration opportunities, ambassadors should be members of the +For accounts managed by foundation staff, the staff will repost the social +media post without any need for validation based on the request coming from +an ambassador. For accounts managed by the project with an approval process, +(for example bluesky) documentation for the approval process will indicate +that repost requests from ambassadors should generally be approved. These +requests can be made through the existing social channel in the OpenJS Slack. +For that reason and for communication purposes and collaboration opportunities, +ambassadors should be members of the [OpenJS Slack](https://slack-invite.openjsf.org/). ## Messages and topics to promote From 1f426bad9ab01583a8e0b73232938f4d8020a9ef Mon Sep 17 00:00:00 2001 From: Pietro Marchini Date: Fri, 17 Jan 2025 11:34:55 +0100 Subject: [PATCH 127/205] test_runner: remove unused errors PR-URL: https://github.com/nodejs/node/pull/56607 Reviewed-By: Colin Ihrig Reviewed-By: Jacob Smith --- doc/api/errors.md | 38 +++++++++++++++++++------------------- lib/internal/errors.js | 15 --------------- 2 files changed, 19 insertions(+), 34 deletions(-) diff --git a/doc/api/errors.md b/doc/api/errors.md index affb78e84ccbca..3c0158457b3563 100644 --- a/doc/api/errors.md +++ b/doc/api/errors.md @@ -2816,25 +2816,6 @@ An unspecified or non-specific system error has occurred within the Node.js process. The error object will have an `err.info` object property with additional details. - - -### `ERR_TAP_LEXER_ERROR` - -An error representing a failing lexer state. - - - -### `ERR_TAP_PARSER_ERROR` - -An error representing a failing parser state. Additional information about -the token causing the error is available via the `cause` property. - - - -### `ERR_TAP_VALIDATION_ERROR` - -This error represents a failed TAP validation. - ### `ERR_TEST_FAILURE` @@ -3847,6 +3828,25 @@ removed: v10.0.0 Used when an attempt is made to use a readable stream that has not implemented [`readable._read()`][]. + + +### `ERR_TAP_LEXER_ERROR` + +An error representing a failing lexer state. + + + +### `ERR_TAP_PARSER_ERROR` + +An error representing a failing parser state. Additional information about +the token causing the error is available via the `cause` property. + + + +### `ERR_TAP_VALIDATION_ERROR` + +This error represents a failed TAP validation. + ### `ERR_TLS_RENEGOTIATION_FAILED` diff --git a/lib/internal/errors.js b/lib/internal/errors.js index 4389d32e47619e..de880fedd03515 100644 --- a/lib/internal/errors.js +++ b/lib/internal/errors.js @@ -1742,21 +1742,6 @@ E('ERR_STREAM_WRAP', 'Stream has StringDecoder set or is in objectMode', Error); E('ERR_STREAM_WRITE_AFTER_END', 'write after end', Error); E('ERR_SYNTHETIC', 'JavaScript Callstack', Error); E('ERR_SYSTEM_ERROR', 'A system error occurred', SystemError, HideStackFramesError); -E('ERR_TAP_LEXER_ERROR', function(errorMsg) { - hideInternalStackFrames(this); - return errorMsg; -}, Error); -E('ERR_TAP_PARSER_ERROR', function(errorMsg, details, tokenCausedError, source) { - hideInternalStackFrames(this); - this.cause = tokenCausedError; - const { column, line, start, end } = tokenCausedError.location; - const errorDetails = `${details} at line ${line}, column ${column} (start ${start}, end ${end})`; - return errorMsg + errorDetails; -}, SyntaxError); -E('ERR_TAP_VALIDATION_ERROR', function(errorMsg) { - hideInternalStackFrames(this); - return errorMsg; -}, Error); E('ERR_TEST_FAILURE', function(error, failureType) { hideInternalStackFrames(this); assert(typeof failureType === 'string' || typeof failureType === 'symbol', From f5b8499ad0e3e2cef505853af11c752fe771af60 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Tue, 14 Jan 2025 13:35:54 +0100 Subject: [PATCH 128/205] test: add maxCount and gcOptions to gcUntil() PR-URL: https://github.com/nodejs/node/pull/56522 Reviewed-By: James M Snell Reviewed-By: Chengzhong Wu --- test/common/gc.js | 38 +++++++++++++++++--------------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/test/common/gc.js b/test/common/gc.js index 82cc4c79edc3dd..87625068c2cbca 100644 --- a/test/common/gc.js +++ b/test/common/gc.js @@ -3,6 +3,8 @@ const wait = require('timers/promises').setTimeout; const assert = require('assert'); const common = require('../common'); +// TODO(joyeecheung): rewrite checkIfCollectable to use this too. +const { setImmediate: setImmediatePromisified } = require('timers/promises'); const gcTrackerMap = new WeakMap(); const gcTrackerTag = 'NODE_TEST_COMMON_GC_TRACKER'; @@ -40,32 +42,26 @@ function onGC(obj, gcListener) { /** * Repeatedly triggers garbage collection until a specified condition is met or a maximum number of attempts is reached. + * This utillity must be run in a Node.js instance that enables --expose-gc. * @param {string|Function} [name] - Optional name, used in the rejection message if the condition is not met. * @param {Function} condition - A function that returns true when the desired condition is met. + * @param {number} maxCount - Maximum number of garbage collections that should be tried. + * @param {object} gcOptions - Options to pass into the global gc() function. * @returns {Promise} A promise that resolves when the condition is met, or rejects after 10 failed attempts. */ -function gcUntil(name, condition) { - if (typeof name === 'function') { - condition = name; - name = undefined; - } - return new Promise((resolve, reject) => { - let count = 0; - function gcAndCheck() { - setImmediate(() => { - count++; - global.gc(); - if (condition()) { - resolve(); - } else if (count < 10) { - gcAndCheck(); - } else { - reject(name === undefined ? undefined : 'Test ' + name + ' failed'); - } - }); +async function gcUntil(name, condition, maxCount = 10, gcOptions) { + for (let count = 0; count < maxCount; ++count) { + await setImmediatePromisified(); + if (gcOptions) { + await global.gc(gcOptions); + } else { + await global.gc(); // Passing in undefined is not the same as empty. } - gcAndCheck(); - }); + if (condition()) { + return; + } + } + throw new Error(`Test ${name} failed`); } // This function can be used to check if an object factor leaks or not, From 9827f7d395192237a87701384ec02b7f6488eba2 Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Fri, 17 Jan 2025 17:43:26 +0100 Subject: [PATCH 129/205] tools: fix permissions in `lint-release-proposal` workflow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/56614 Reviewed-By: Michaël Zasso Reviewed-By: Ruy Adorno Reviewed-By: Luigi Pinca --- .github/workflows/lint-release-proposal.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/lint-release-proposal.yml b/.github/workflows/lint-release-proposal.yml index ecda2b616c0d02..9d8ba5998a7a5c 100644 --- a/.github/workflows/lint-release-proposal.yml +++ b/.github/workflows/lint-release-proposal.yml @@ -19,6 +19,8 @@ permissions: jobs: lint-release-commit: runs-on: ubuntu-latest + permissions: + pull-requests: read steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: From 8346b8fc2c70721caa9ee02c12b793cd1b288cb5 Mon Sep 17 00:00:00 2001 From: Michael Dawson Date: Fri, 17 Jan 2025 12:58:47 -0500 Subject: [PATCH 130/205] crypto: add missing return value check Add return value check for call to SSL_CTX_add_client_CA to be consistent with other places it is called Fixed unused warning in one of the static analysis tools we use at Red Hat even though it is not being reported by coverity in the configuration we run. Signed-off-by: Michael Dawson PR-URL: https://github.com/nodejs/node/pull/56615 Reviewed-By: Luigi Pinca Reviewed-By: James M Snell --- src/crypto/crypto_context.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/crypto/crypto_context.cc b/src/crypto/crypto_context.cc index 8f1e6dc7110b11..c7574e67f03f03 100644 --- a/src/crypto/crypto_context.cc +++ b/src/crypto/crypto_context.cc @@ -1164,7 +1164,7 @@ void SecureContext::LoadPKCS12(const FunctionCallbackInfo& args) { X509* ca = sk_X509_value(extra_certs.get(), i); X509_STORE_add_cert(sc->GetCertStoreOwnedByThisSecureContext(), ca); - SSL_CTX_add_client_CA(sc->ctx_.get(), ca); + CHECK_EQ(1, SSL_CTX_add_client_CA(sc->ctx_.get(), ca)); } ret = true; From acd2a2fda58ae34d21c7f7f22cb345b50f6413c6 Mon Sep 17 00:00:00 2001 From: Rafael Gonzaga Date: Fri, 17 Jan 2025 18:50:56 -0300 Subject: [PATCH 131/205] doc: mention prepare --security PR-URL: https://github.com/nodejs/node/pull/56617 Reviewed-By: Marco Ippolito Reviewed-By: Luigi Pinca --- doc/contributing/releases.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/doc/contributing/releases.md b/doc/contributing/releases.md index 40ba96da602033..5b6d2180515565 100644 --- a/doc/contributing/releases.md +++ b/doc/contributing/releases.md @@ -308,6 +308,22 @@ branch. git checkout -b v1.2.3-proposal upstream/v1.x-staging ``` +You can also run: + +```bash +git node release -S --prepare --security --filterLabel vX.x +``` + +Example: + +```bash +git checkout v20.x +git node release -S --prepare --security --filterLabel v20.x +``` + +to automate the remaining steps until step 6 or you can perform it manually +following the below steps. +
Security release From fa49f0f7d540a257a4eff0ff5f488f3baea985ff Mon Sep 17 00:00:00 2001 From: Colin Ihrig Date: Sat, 18 Jan 2025 13:01:54 -0500 Subject: [PATCH 132/205] punycode: limit deprecation warning DEP0040 is an extremely annoying warning. Most of the people seeing it cannot do anything about it. This commit updates the warning logic to only emit outside of node_modules. This is similar to other warnings such as the Buffer() constructor warning. Ideally, this should be backported to Node 22. Refs: https://github.com/nodejs/node/pull/47202 PR-URL: https://github.com/nodejs/node/pull/56632 Reviewed-By: Jordan Harband Reviewed-By: Richard Lau Reviewed-By: Yagiz Nizipli Reviewed-By: Luigi Pinca Reviewed-By: Matteo Collina Reviewed-By: Antoine du Hamel Reviewed-By: Joyee Cheung --- lib/punycode.js | 19 ++++++++++++------- .../errors/core_line_numbers.snapshot | 6 +++--- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/lib/punycode.js b/lib/punycode.js index 7dfe552a5c9efa..e303a5373b8839 100644 --- a/lib/punycode.js +++ b/lib/punycode.js @@ -1,11 +1,16 @@ 'use strict'; - -process.emitWarning( - 'The `punycode` module is deprecated. Please use a userland ' + - 'alternative instead.', - 'DeprecationWarning', - 'DEP0040', -); +const { + isInsideNodeModules, +} = internalBinding('util'); + +if (!isInsideNodeModules(100, true)) { + process.emitWarning( + 'The `punycode` module is deprecated. Please use a userland ' + + 'alternative instead.', + 'DeprecationWarning', + 'DEP0040', + ); +} /** Highest positive signed 32-bit float value */ const maxInt = 2147483647; // aka. 0x7FFFFFFF or 2^31-1 diff --git a/test/fixtures/errors/core_line_numbers.snapshot b/test/fixtures/errors/core_line_numbers.snapshot index 54cdb52744b29e..9ef06c33af8e28 100644 --- a/test/fixtures/errors/core_line_numbers.snapshot +++ b/test/fixtures/errors/core_line_numbers.snapshot @@ -1,10 +1,10 @@ -node:punycode:49 +node:punycode:54 throw new RangeError(errors[type]); ^ RangeError: Invalid input - at error (node:punycode:49:8) - at Object.decode (node:punycode:242:5) + at error (node:punycode:54:8) + at Object.decode (node:punycode:247:5) at Object. (*core_line_numbers.js:13:10) Node.js * From c5ca15bd349b2c4dda2df4a620d5ecfcc4d285a4 Mon Sep 17 00:00:00 2001 From: Maksim Gorkov <33923276+MGorkov@users.noreply.github.com> Date: Sat, 18 Jan 2025 22:39:56 +0300 Subject: [PATCH 133/205] child_process: fix parsing messages with splitted length field MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: https://github.com/nodejs/node/issues/55834 PR-URL: https://github.com/nodejs/node/pull/56106 Reviewed-By: Luigi Pinca Reviewed-By: Juan José Arboleda Reviewed-By: James M Snell --- lib/internal/child_process/serialization.js | 7 +++++- ...ced-serialization-splitted-length-field.js | 24 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 test/parallel/test-child-process-advanced-serialization-splitted-length-field.js diff --git a/lib/internal/child_process/serialization.js b/lib/internal/child_process/serialization.js index 7be39f0d48c3c2..46bb1faaf9fc21 100644 --- a/lib/internal/child_process/serialization.js +++ b/lib/internal/child_process/serialization.js @@ -61,7 +61,12 @@ const advanced = { *parseChannelMessages(channel, readData) { if (readData.length === 0) return; - ArrayPrototypePush(channel[kMessageBuffer], readData); + if (channel[kMessageBufferSize] && channel[kMessageBuffer][0].length < 4) { + // Message length split into two buffers, so let's concatenate it. + channel[kMessageBuffer][0] = Buffer.concat([channel[kMessageBuffer][0], readData]); + } else { + ArrayPrototypePush(channel[kMessageBuffer], readData); + } channel[kMessageBufferSize] += readData.length; // Index 0 should always be present because we just pushed data into it. diff --git a/test/parallel/test-child-process-advanced-serialization-splitted-length-field.js b/test/parallel/test-child-process-advanced-serialization-splitted-length-field.js new file mode 100644 index 00000000000000..5407a56f495c8f --- /dev/null +++ b/test/parallel/test-child-process-advanced-serialization-splitted-length-field.js @@ -0,0 +1,24 @@ +'use strict'; +const common = require('../common'); +const child_process = require('child_process'); + +// Regression test for https://github.com/nodejs/node/issues/55834 +const msgLen = 65521; +let cnt = 10; + +if (process.argv[2] === 'child') { + const msg = Buffer.allocUnsafe(msgLen); + (function send() { + if (cnt--) { + process.send(msg, send); + } else { + process.disconnect(); + } + })(); +} else { + const child = child_process.spawn(process.execPath, [__filename, 'child'], { + stdio: ['inherit', 'inherit', 'inherit', 'ipc'], + serialization: 'advanced' + }); + child.on('message', common.mustCall(cnt)); +} From 8c9eaf82f0a02099f6b90b826abeb290a49950a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= Date: Sun, 19 Jan 2025 17:47:50 +0100 Subject: [PATCH 134/205] src: initialize FSReqWrapSync in path that uses it PR-URL: https://github.com/nodejs/node/pull/56613 Reviewed-By: James M Snell Reviewed-By: Yagiz Nizipli Reviewed-By: Luigi Pinca --- src/node_file.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/node_file.cc b/src/node_file.cc index f09defa7247461..9676cd4fe78c4e 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -2383,7 +2383,6 @@ static void WriteString(const FunctionCallbackInfo& args) { } } else { // write(fd, string, pos, enc, undefined, ctx) CHECK_EQ(argc, 6); - FSReqWrapSync req_wrap_sync; FSReqBase::FSReqBuffer stack_buffer; if (buf == nullptr) { if (!StringBytes::StorageSize(isolate, value, enc).To(&len)) @@ -2397,6 +2396,7 @@ static void WriteString(const FunctionCallbackInfo& args) { buf = *stack_buffer; } uv_buf_t uvbuf = uv_buf_init(buf, len); + FSReqWrapSync req_wrap_sync("write"); FS_SYNC_TRACE_BEGIN(write); int bytesWritten = SyncCall(env, args[5], &req_wrap_sync, "write", uv_fs_write, fd, &uvbuf, 1, pos); From fa869ea0f27c774895b0f2c7c979c27b70d76dc5 Mon Sep 17 00:00:00 2001 From: James M Snell Date: Sun, 19 Jan 2025 08:55:54 -0800 Subject: [PATCH 135/205] deps: fixup some minor coverity warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: https://github.com/nodejs/node/issues/56611 PR-URL: https://github.com/nodejs/node/pull/56612 Reviewed-By: Michaël Zasso Reviewed-By: Benjamin Gruenbaum Reviewed-By: Yagiz Nizipli Reviewed-By: Michael Dawson Reviewed-By: Ulises Gascón --- deps/ncrypto/ncrypto.cc | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/deps/ncrypto/ncrypto.cc b/deps/ncrypto/ncrypto.cc index fa0cf58062d897..ce2e7b384eb198 100644 --- a/deps/ncrypto/ncrypto.cc +++ b/deps/ncrypto/ncrypto.cc @@ -1346,8 +1346,11 @@ DHPointer DHPointer::New(BignumPointer&& p, BignumPointer&& g) { if (DH_set0_pqg(dh.get(), p.get(), nullptr, g.get()) != 1) return {}; // If the call above is successful, the DH object takes ownership of the - // BIGNUMs, so we must release them here. + // BIGNUMs, so we must release them here. Unfortunately coverity does not + // know that so we need to tell it not to complain. + // coverity[resource_leak] p.release(); + // coverity[resource_leak] g.release(); return dh; @@ -1430,7 +1433,10 @@ DataPointer DHPointer::generateKeys() const { size_t DHPointer::size() const { if (!dh_) return 0; - return DH_size(dh_.get()); + int ret = DH_size(dh_.get()); + // DH_size can return a -1 on error but we just want to return a 0 + // in that case so we don't wrap around when returning the size_t. + return ret >= 0 ? static_cast(ret) : 0; } DataPointer DHPointer::computeSecret(const BignumPointer& peer) const { @@ -1459,6 +1465,10 @@ DataPointer DHPointer::computeSecret(const BignumPointer& peer) const { bool DHPointer::setPublicKey(BignumPointer&& key) { if (!dh_) return false; if (DH_set0_key(dh_.get(), key.get(), nullptr) == 1) { + // If DH_set0_key returns successfully, then dh_ takes ownership of the + // BIGNUM, so we must release it here. Unfortunately coverity does not + // know that so we need to tell it not to complain. + // coverity[resource_leak] key.release(); return true; } @@ -1468,6 +1478,10 @@ bool DHPointer::setPublicKey(BignumPointer&& key) { bool DHPointer::setPrivateKey(BignumPointer&& key) { if (!dh_) return false; if (DH_set0_key(dh_.get(), nullptr, key.get()) == 1) { + // If DH_set0_key returns successfully, then dh_ takes ownership of the + // BIGNUM, so we must release it here. Unfortunately coverity does not + // know that so we need to tell it not to complain. + // coverity[resource_leak] key.release(); return true; } From de81d90fce1e9aa0b482a41d6cb3d43991d2a572 Mon Sep 17 00:00:00 2001 From: Meghan Denny Date: Sun, 19 Jan 2025 08:56:09 -0800 Subject: [PATCH 136/205] test: test-stream-compose.js doesn't need internals PR-URL: https://github.com/nodejs/node/pull/56619 Reviewed-By: Yagiz Nizipli Reviewed-By: Luigi Pinca Reviewed-By: Jake Yuesong Li Reviewed-By: James M Snell --- test/parallel/test-stream-compose.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test/parallel/test-stream-compose.js b/test/parallel/test-stream-compose.js index 1ff8c39b7a2234..d7a54e177668a2 100644 --- a/test/parallel/test-stream-compose.js +++ b/test/parallel/test-stream-compose.js @@ -1,5 +1,3 @@ -// Flags: --expose-internals - 'use strict'; const common = require('../common'); @@ -9,9 +7,9 @@ const { Transform, Writable, finished, + compose, PassThrough } = require('stream'); -const compose = require('internal/streams/compose'); const assert = require('assert'); { From 6ca27c2a59e9f5e1466eb48ddaa7fbf26eb322a4 Mon Sep 17 00:00:00 2001 From: islandryu Date: Sun, 29 Dec 2024 13:41:34 +0900 Subject: [PATCH 137/205] http2: omit server name when HTTP2 host is IP address Fixes: https://github.com/nodejs/node/issues/56189 PR-URL: https://github.com/nodejs/node/pull/56530 Reviewed-By: Matteo Collina Reviewed-By: Yongsheng Zhang Reviewed-By: Luigi Pinca --- lib/internal/http2/core.js | 24 ++++++---- test/parallel/test-http2-ip-address-host.js | 53 +++++++++++++++++++++ 2 files changed, 68 insertions(+), 9 deletions(-) create mode 100644 test/parallel/test-http2-ip-address-host.js diff --git a/lib/internal/http2/core.js b/lib/internal/http2/core.js index 5809b384338904..d7f9d1f4491f56 100644 --- a/lib/internal/http2/core.js +++ b/lib/internal/http2/core.js @@ -645,15 +645,21 @@ function initOriginSet(session) { if (originSet === undefined) { const socket = session[kSocket]; session[kState].originSet = originSet = new SafeSet(); - if (socket.servername != null) { - let originString = `https://${socket.servername}`; - if (socket.remotePort != null) - originString += `:${socket.remotePort}`; - // We have to ensure that it is a properly serialized - // ASCII origin string. The socket.servername might not - // be properly ASCII encoded. - originSet.add(getURLOrigin(originString)); + let hostName = socket.servername; + if (hostName === null || hostName === false) { + if (socket.remoteFamily === 'IPv6') { + hostName = `[${socket.remoteAddress}]`; + } else { + hostName = socket.remoteAddress; + } } + let originString = `https://${hostName}`; + if (socket.remotePort != null) + originString += `:${socket.remotePort}`; + // We have to ensure that it is a properly serialized + // ASCII origin string. The socket.servername might not + // be properly ASCII encoded. + originSet.add(getURLOrigin(originString)); } return originSet; } @@ -3342,7 +3348,7 @@ function connect(authority, options, listener) { socket = net.connect({ port, host, ...options }); break; case 'https:': - socket = tls.connect(port, host, initializeTLSOptions(options, host)); + socket = tls.connect(port, host, initializeTLSOptions(options, net.isIP(host) ? undefined : host)); break; default: throw new ERR_HTTP2_UNSUPPORTED_PROTOCOL(protocol); diff --git a/test/parallel/test-http2-ip-address-host.js b/test/parallel/test-http2-ip-address-host.js new file mode 100644 index 00000000000000..c0699a89169153 --- /dev/null +++ b/test/parallel/test-http2-ip-address-host.js @@ -0,0 +1,53 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) { common.skip('missing crypto'); }; +const assert = require('assert'); +const fixtures = require('../common/fixtures'); +const h2 = require('http2'); + +function loadKey(keyname) { + return fixtures.readKey(keyname, 'binary'); +} + +const key = loadKey('agent8-key.pem'); +const cert = fixtures.readKey('agent8-cert.pem'); + +const server = h2.createSecureServer({ key, cert }); +const hasIPv6 = common.hasIPv6; +const testCount = hasIPv6 ? 2 : 1; + +server.on('stream', common.mustCall((stream) => { + const session = stream.session; + assert.strictEqual(session.servername, undefined); + stream.respond({ 'content-type': 'application/json' }); + stream.end(JSON.stringify({ + servername: session.servername, + originSet: session.originSet + }) + ); +}, testCount)); + +let done = 0; + +server.listen(0, common.mustCall(() => { + function handleRequest(url) { + const client = h2.connect(url, + { rejectUnauthorized: false }); + const req = client.request(); + let data = ''; + req.setEncoding('utf8'); + req.on('data', (d) => data += d); + req.on('end', common.mustCall(() => { + const originSet = req.session.originSet; + assert.strictEqual(originSet[0], url); + client.close(); + if (++done === testCount) server.close(); + })); + } + + const ipv4Url = `https://127.0.0.1:${server.address().port}`; + const ipv6Url = `https://[::1]:${server.address().port}`; + handleRequest(ipv4Url); + if (hasIPv6) handleRequest(ipv6Url); +})); From ae360c30dc1066f2ba5f39bc1761e2de7f42783a Mon Sep 17 00:00:00 2001 From: Shreyans Pathak Date: Mon, 20 Jan 2025 15:18:21 -0500 Subject: [PATCH 138/205] doc: `WeakSet` and `WeakMap` comparison details PR-URL: https://github.com/nodejs/node/pull/56648 Reviewed-By: Luigi Pinca Reviewed-By: James M Snell --- doc/api/assert.md | 84 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 60 insertions(+), 24 deletions(-) diff --git a/doc/api/assert.md b/doc/api/assert.md index 336fcd8cc5ffb9..6ab2d74f6e8a61 100644 --- a/doc/api/assert.md +++ b/doc/api/assert.md @@ -799,8 +799,10 @@ are recursively evaluated also by the following rules. * [`Map`][] keys and [`Set`][] items are compared unordered. * Recursion stops when both sides differ or both sides encounter a circular reference. -* [`WeakMap`][] and [`WeakSet`][] comparison does not rely on their values. See - below for further details. +* [`WeakMap`][] and [`WeakSet`][] instances are **not** compared structurally. + They are only equal if they reference the same object. Any comparison between + different `WeakMap` or `WeakSet` instances will result in inequality, + even if they contain the same entries. * [`RegExp`][] lastIndex, flags, and source are always compared, even if these are not enumerable properties. @@ -877,23 +879,40 @@ assert.deepStrictEqual({ [symbol1]: 1 }, { [symbol2]: 1 }); // } const weakMap1 = new WeakMap(); -const weakMap2 = new WeakMap([[{}, {}]]); -const weakMap3 = new WeakMap(); -weakMap3.unequal = true; +const weakMap2 = new WeakMap(); +const obj = {}; +weakMap1.set(obj, 'value'); +weakMap2.set(obj, 'value'); + +// Comparing different instances fails, even with same contents assert.deepStrictEqual(weakMap1, weakMap2); -// OK, because it is impossible to compare the entries +// AssertionError: Values have same structure but are not reference-equal: +// +// WeakMap { +// +// } + +// Comparing the same instance to itself succeeds +assert.deepStrictEqual(weakMap1, weakMap1); +// OK -// Fails because weakMap3 has a property that weakMap1 does not contain: -assert.deepStrictEqual(weakMap1, weakMap3); +const weakSet1 = new WeakSet(); +const weakSet2 = new WeakSet(); +weakSet1.add(obj); +weakSet2.add(obj); + +// Comparing different instances fails, even with same contents +assert.deepStrictEqual(weakSet1, weakSet2); // AssertionError: Expected inputs to be strictly deep-equal: // + actual - expected // -// WeakMap { -// + [items unknown] -// - [items unknown], -// - unequal: true -// } +// + WeakSet { } +// - WeakSet { } + +// Comparing the same instance to itself succeeds +assert.deepStrictEqual(weakSet1, weakSet1); +// OK ``` ```cjs @@ -969,23 +988,40 @@ assert.deepStrictEqual({ [symbol1]: 1 }, { [symbol2]: 1 }); // } const weakMap1 = new WeakMap(); -const weakMap2 = new WeakMap([[{}, {}]]); -const weakMap3 = new WeakMap(); -weakMap3.unequal = true; +const weakMap2 = new WeakMap(); +const obj = {}; +weakMap1.set(obj, 'value'); +weakMap2.set(obj, 'value'); + +// Comparing different instances fails, even with same contents assert.deepStrictEqual(weakMap1, weakMap2); -// OK, because it is impossible to compare the entries +// AssertionError: Values have same structure but are not reference-equal: +// +// WeakMap { +// +// } + +// Comparing the same instance to itself succeeds +assert.deepStrictEqual(weakMap1, weakMap1); +// OK -// Fails because weakMap3 has a property that weakMap1 does not contain: -assert.deepStrictEqual(weakMap1, weakMap3); +const weakSet1 = new WeakSet(); +const weakSet2 = new WeakSet(); +weakSet1.add(obj); +weakSet2.add(obj); + +// Comparing different instances fails, even with same contents +assert.deepStrictEqual(weakSet1, weakSet2); // AssertionError: Expected inputs to be strictly deep-equal: // + actual - expected // -// WeakMap { -// + [items unknown] -// - [items unknown], -// - unequal: true -// } +// + WeakSet { } +// - WeakSet { } + +// Comparing the same instance to itself succeeds +assert.deepStrictEqual(weakSet1, weakSet1); +// OK ``` If the values are not equal, an [`AssertionError`][] is thrown with a `message` From 8e978bdee120b54fdccd77305f2f747969ae08dc Mon Sep 17 00:00:00 2001 From: Dario Piotrowicz Date: Tue, 21 Jan 2025 17:16:17 +0000 Subject: [PATCH 139/205] doc: clarify cjs/esm diff in `queueMicrotask()` vs `process.nextTick()` the section comparing `queueMicrotask()` and `process.nextTick()` doesn't address the different scheduling behavior that the two functions have in cjs and esm modules, the section's introductory mjs example also provides an incorrect output, the changes here address such by explaining the difference between the two module types and updating the example accordingly PR-URL: https://github.com/nodejs/node/pull/56659 Fixes: https://github.com/nodejs/node/issues/45048 Reviewed-By: Yagiz Nizipli Reviewed-By: James M Snell Reviewed-By: Luigi Pinca --- doc/api/process.md | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/doc/api/process.md b/doc/api/process.md index 8e7fe148daa9a6..a711b3685662a5 100644 --- a/doc/api/process.md +++ b/doc/api/process.md @@ -2993,34 +2993,40 @@ function definitelyAsync(arg, cb) { ### When to use `queueMicrotask()` vs. `process.nextTick()` -The [`queueMicrotask()`][] API is an alternative to `process.nextTick()` that -also defers execution of a function using the same microtask queue used to -execute the then, catch, and finally handlers of resolved promises. Within -Node.js, every time the "next tick queue" is drained, the microtask queue +The [`queueMicrotask()`][] API is an alternative to `process.nextTick()` that instead of using the +"next tick queue" defers execution of a function using the same microtask queue used to execute the +then, catch, and finally handlers of resolved promises. + +Within Node.js, every time the "next tick queue" is drained, the microtask queue is drained immediately after. +So in CJS modules `process.nextTick()` callbacks are always run before `queueMicrotask()` ones. +However since ESM modules are processed already as part of the microtask queue, there +`queueMicrotask()` callbacks are always exectued before `process.nextTick()` ones since Node.js +is already in the process of draining the microtask queue. + ```mjs import { nextTick } from 'node:process'; -Promise.resolve().then(() => console.log(2)); -queueMicrotask(() => console.log(3)); -nextTick(() => console.log(1)); +Promise.resolve().then(() => console.log('resolve')); +queueMicrotask(() => console.log('microtask')); +nextTick(() => console.log('nextTick')); // Output: -// 1 -// 2 -// 3 +// resolve +// microtask +// nextTick ``` ```cjs const { nextTick } = require('node:process'); -Promise.resolve().then(() => console.log(2)); -queueMicrotask(() => console.log(3)); -nextTick(() => console.log(1)); +Promise.resolve().then(() => console.log('resolve')); +queueMicrotask(() => console.log('microtask')); +nextTick(() => console.log('nextTick')); // Output: -// 1 -// 2 -// 3 +// nextTick +// resolve +// microtask ``` For _most_ userland use cases, the `queueMicrotask()` API provides a portable From feba5d327411cbb2ca2d13062c53ce2c073dc84a Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Wed, 22 Jan 2025 13:54:31 +0100 Subject: [PATCH 140/205] tools: do not throw on missing `create-release-proposal.sh` PR-URL: https://github.com/nodejs/node/pull/56695 Reviewed-By: Marco Ippolito Reviewed-By: Pietro Marchini --- .github/workflows/create-release-proposal.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/create-release-proposal.yml b/.github/workflows/create-release-proposal.yml index 55bc892eb909a4..33426bdcda4a5b 100644 --- a/.github/workflows/create-release-proposal.yml +++ b/.github/workflows/create-release-proposal.yml @@ -71,9 +71,11 @@ jobs: git config --local user.name "Node.js GitHub Bot" - name: Start git node release prepare + # `git update-index` tells git to ignore future changes to the `.sh` file, + # `|| true` is there to ignore the error if such file doesn't exist yet. # The curl command is to make sure we run the version of the script corresponding to the current workflow. run: | - git update-index --assume-unchanged tools/actions/create-release-proposal.sh + git update-index --assume-unchanged tools/actions/create-release-proposal.sh || true curl -fsSLo tools/actions/create-release-proposal.sh https://github.com/${GITHUB_REPOSITORY}/raw/${GITHUB_SHA}/tools/actions/create-release-proposal.sh ./tools/actions/create-release-proposal.sh "${RELEASE_DATE}" "${RELEASE_LINE}" "${GITHUB_ACTOR}" env: From 48b72f119542a64f9d90a3802cbb59c685d8d861 Mon Sep 17 00:00:00 2001 From: Rafael Gonzaga Date: Wed, 22 Jan 2025 12:09:00 -0300 Subject: [PATCH 141/205] test: use --permission instead of --experimental-permission PR-URL: https://github.com/nodejs/node/pull/56685 Reviewed-By: Marco Ippolito Reviewed-By: Colin Ihrig Reviewed-By: Pietro Marchini Reviewed-By: LiviaMedeiros Reviewed-By: Luigi Pinca Reviewed-By: Ruben Bridgewater --- test/parallel/test-permission-dc-worker-threads.js | 2 +- test/parallel/test-runner-module-mocking.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/parallel/test-permission-dc-worker-threads.js b/test/parallel/test-permission-dc-worker-threads.js index 73cbf02981fa88..4fdb566f9e1701 100644 --- a/test/parallel/test-permission-dc-worker-threads.js +++ b/test/parallel/test-permission-dc-worker-threads.js @@ -1,4 +1,4 @@ -// Flags: --experimental-permission --allow-fs-read=* --experimental-test-module-mocks +// Flags: --permission --allow-fs-read=* --experimental-test-module-mocks 'use strict'; const common = require('../common'); diff --git a/test/parallel/test-runner-module-mocking.js b/test/parallel/test-runner-module-mocking.js index 53b764d9ec5f93..a832c6a2a7ef03 100644 --- a/test/parallel/test-runner-module-mocking.js +++ b/test/parallel/test-runner-module-mocking.js @@ -656,7 +656,7 @@ test('should throw ERR_ACCESS_DENIED when permission model is enabled', async (t const cwd = fixtures.path('test-runner'); const fixture = fixtures.path('test-runner', 'mock-nm.js'); const args = [ - '--experimental-permission', + '--permission', '--allow-fs-read=*', '--experimental-test-module-mocks', fixture, @@ -674,7 +674,7 @@ test('should work when --allow-worker is passed and permission model is enabled' const cwd = fixtures.path('test-runner'); const fixture = fixtures.path('test-runner', 'mock-nm.js'); const args = [ - '--experimental-permission', + '--permission', '--allow-fs-read=*', '--allow-worker', '--experimental-test-module-mocks', From 2e5d038f4850008ae3c98cd52c40ee9068075d48 Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Thu, 23 Jan 2025 09:36:52 +0100 Subject: [PATCH 142/205] worker: refactor stdio to improve performance Signed-off-by: Matteo Collina PR-URL: https://github.com/nodejs/node/pull/56630 Reviewed-By: Yagiz Nizipli Reviewed-By: Robert Nagy Reviewed-By: Paolo Insogna Reviewed-By: Luigi Pinca --- lib/internal/worker.js | 6 ++++-- lib/internal/worker/io.js | 35 ++++++++++++++++++++++------------- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/lib/internal/worker.js b/lib/internal/worker.js index dcc9651802c4e4..e5a2cd06892c75 100644 --- a/lib/internal/worker.js +++ b/lib/internal/worker.js @@ -340,9 +340,11 @@ class Worker extends EventEmitter { { const { stream, chunks } = message; const readable = this[kParentSideStdio][stream]; - ArrayPrototypeForEach(chunks, ({ chunk, encoding }) => { + // This is a hot path, use a for(;;) loop + for (let i = 0; i < chunks.length; i++) { + const { chunk, encoding } = chunks[i]; readable.push(chunk, encoding); - }); + } return; } case messageTypes.STDIO_WANTS_MORE_DATA: diff --git a/lib/internal/worker/io.js b/lib/internal/worker/io.js index 2b28c6a2487b11..29c7914982b67a 100644 --- a/lib/internal/worker/io.js +++ b/lib/internal/worker/io.js @@ -1,9 +1,7 @@ 'use strict'; const { - ArrayPrototypeForEach, - ArrayPrototypeMap, - ArrayPrototypePush, + Array, FunctionPrototypeBind, FunctionPrototypeCall, ObjectAssign, @@ -77,7 +75,7 @@ const kOnMessage = Symbol('kOnMessage'); const kOnMessageError = Symbol('kOnMessageError'); const kPort = Symbol('kPort'); const kWaitingStreams = Symbol('kWaitingStreams'); -const kWritableCallbacks = Symbol('kWritableCallbacks'); +const kWritableCallback = Symbol('kWritableCallback'); const kStartedReading = Symbol('kStartedReading'); const kStdioWantsMoreDataCallback = Symbol('kStdioWantsMoreDataCallback'); const kCurrentlyReceivingPorts = @@ -282,20 +280,29 @@ class WritableWorkerStdio extends Writable { super({ decodeStrings: false }); this[kPort] = port; this[kName] = name; - this[kWritableCallbacks] = []; + this[kWritableCallback] = null; } _writev(chunks, cb) { + const toSend = new Array(chunks.length); + + // We avoid .map() because it's a hot path + for (let i = 0; i < chunks.length; i++) { + const { chunk, encoding } = chunks[i]; + toSend[i] = { chunk, encoding }; + } + this[kPort].postMessage({ type: messageTypes.STDIO_PAYLOAD, stream: this[kName], - chunks: ArrayPrototypeMap(chunks, - ({ chunk, encoding }) => ({ chunk, encoding })), + chunks: toSend, }); if (process._exiting) { cb(); } else { - ArrayPrototypePush(this[kWritableCallbacks], cb); + // Only one writev happens at any given time, + // so we can safely overwrite the callback. + this[kWritableCallback] = cb; if (this[kPort][kWaitingStreams]++ === 0) this[kPort].ref(); } @@ -311,11 +318,13 @@ class WritableWorkerStdio extends Writable { } [kStdioWantsMoreDataCallback]() { - const cbs = this[kWritableCallbacks]; - this[kWritableCallbacks] = []; - ArrayPrototypeForEach(cbs, (cb) => cb()); - if ((this[kPort][kWaitingStreams] -= cbs.length) === 0) - this[kPort].unref(); + const cb = this[kWritableCallback]; + if (cb) { + this[kWritableCallback] = null; + cb(); + if (--this[kPort][kWaitingStreams] === 0) + this[kPort].unref(); + } } } From 55533bf1472ff396f58d5fd42e1c69ca1d5b6f72 Mon Sep 17 00:00:00 2001 From: Rafael Gonzaga Date: Thu, 23 Jan 2025 16:05:11 -0300 Subject: [PATCH 143/205] doc: add RafaelGSS as latest sec release stewards MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/56682 Refs: https://github.com/nodejs-private/security-release/pull/41 Reviewed-By: Richard Lau Reviewed-By: Ulises Gascón Reviewed-By: Marco Ippolito Reviewed-By: Matteo Collina Reviewed-By: Antoine du Hamel --- doc/contributing/security-release-process.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/contributing/security-release-process.md b/doc/contributing/security-release-process.md index d8a871bd96922c..7027b16a00d5e5 100644 --- a/doc/contributing/security-release-process.md +++ b/doc/contributing/security-release-process.md @@ -35,6 +35,7 @@ The current security stewards are documented in the main Node.js | NodeSource | Rafael | 2024-Apr-03 | | NodeSource | Rafael | 2024-Apr-10 | | NodeSource | Rafael | 2024-Jul-08 | +| NodeSource | Rafael | 2025-Jan-21 | | Datadog | Bryan | | | IBM | Joe | | | Platformatic | Matteo | | From fade5225387ca0ee9f0f7df6288bd58598b341d3 Mon Sep 17 00:00:00 2001 From: Shreyans Pathak Date: Thu, 23 Jan 2025 14:24:28 -0500 Subject: [PATCH 144/205] doc: fix inconsistencies in `WeakSet` and `WeakMap` comparison details MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/56683 Reviewed-By: Ruben Bridgewater Reviewed-By: Ulises Gascón Reviewed-By: Jason Zhang Reviewed-By: Luigi Pinca --- doc/api/assert.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/doc/api/assert.md b/doc/api/assert.md index 6ab2d74f6e8a61..50592004136b70 100644 --- a/doc/api/assert.md +++ b/doc/api/assert.md @@ -904,11 +904,12 @@ weakSet2.add(obj); // Comparing different instances fails, even with same contents assert.deepStrictEqual(weakSet1, weakSet2); -// AssertionError: Expected inputs to be strictly deep-equal: +// AssertionError: Values have same structure but are not reference-equal: // + actual - expected // -// + WeakSet { } -// - WeakSet { } +// WeakSet { +// +// } // Comparing the same instance to itself succeeds assert.deepStrictEqual(weakSet1, weakSet1); @@ -1013,11 +1014,12 @@ weakSet2.add(obj); // Comparing different instances fails, even with same contents assert.deepStrictEqual(weakSet1, weakSet2); -// AssertionError: Expected inputs to be strictly deep-equal: +// AssertionError: Values have same structure but are not reference-equal: // + actual - expected // -// + WeakSet { } -// - WeakSet { } +// WeakSet { +// +// } // Comparing the same instance to itself succeeds assert.deepStrictEqual(weakSet1, weakSet1); From df8b835953497b9ff4a7a6b9d3d12199a6381ab4 Mon Sep 17 00:00:00 2001 From: Daniel Lemire Date: Thu, 23 Jan 2025 14:24:38 -0500 Subject: [PATCH 145/205] tools: fix tools-deps-update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/56684 Reviewed-By: Antoine du Hamel Reviewed-By: James M Snell Reviewed-By: Michaël Zasso Reviewed-By: Michael Dawson --- .github/workflows/tools.yml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/workflows/tools.yml b/.github/workflows/tools.yml index abbdc2824817f2..b768638d9d9cbd 100644 --- a/.github/workflows/tools.yml +++ b/.github/workflows/tools.yml @@ -284,6 +284,10 @@ jobs: tail -n1 temp-output | grep "NEW_VERSION=" >> "$GITHUB_ENV" || true rm temp-output steps: + - name: Setup Git config + run: | + git config --global user.name "Node.js GitHub Bot" + git config --global user.email "github-bot@iojs.org" - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 if: github.event_name == 'schedule' || inputs.id == 'all' || inputs.id == matrix.id with: @@ -301,17 +305,15 @@ jobs: if: env.COMMIT_MSG == '' && (github.event_name == 'schedule' || inputs.id == 'all' || inputs.id == matrix.id) run: | echo "COMMIT_MSG=${{ matrix.subsystem }}: update ${{ matrix.id }} to ${{ env.NEW_VERSION }}" >> "$GITHUB_ENV" - - uses: gr2m/create-or-update-pull-request-action@86ec1766034c8173518f61d2075cc2a173fb8c97 # v1.9.4 + - uses: peter-evans/create-pull-request@5e914681df9dc83aa4e4905692ca88beb2f9e91f # v7.0.5 if: github.event_name == 'schedule' || inputs.id == 'all' || inputs.id == matrix.id # Creates a PR or update the Action's existing PR, or # no-op if the base branch is already up-to-date. - env: - GITHUB_TOKEN: ${{ secrets.GH_USER_TOKEN }} with: - author: Node.js GitHub Bot - body: This is an automated update of ${{ matrix.id }} to ${{ env.NEW_VERSION }}. + token: ${{ secrets.GH_USER_TOKEN }} branch: actions/tools-update-${{ matrix.id }} # Custom branch *just* for this Action. + delete-branch: true commit-message: ${{ env.COMMIT_MSG }} labels: ${{ matrix.label }} title: '${{ matrix.subsystem }}: update ${{ matrix.id }} to ${{ env.NEW_VERSION }}' - update-pull-request-title-and-body: true + body: This is an automated update of ${{ matrix.id }} to ${{ env.NEW_VERSION }}. From c96792d7f87be844b66fece6803cc3a014b4f835 Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Thu, 23 Jan 2025 23:14:10 +0100 Subject: [PATCH 146/205] test: fix localization data for ICU 74.2 PR-URL: https://github.com/nodejs/node/pull/56661 Refs: https://github.com/nodejs/node/pull/55618 Reviewed-By: James M Snell Reviewed-By: Luigi Pinca Reviewed-By: LiviaMedeiros Reviewed-By: Ruben Bridgewater Reviewed-By: Michael Dawson --- test/fixtures/icu/localizationData-v74.2.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/fixtures/icu/localizationData-v74.2.json b/test/fixtures/icu/localizationData-v74.2.json index 65671ba5acb299..1cca79672ac25e 100644 --- a/test/fixtures/icu/localizationData-v74.2.json +++ b/test/fixtures/icu/localizationData-v74.2.json @@ -20,14 +20,14 @@ "dateTimeFormats": { "en": "7/25/1980, 1:35:33 AM", "zh": "1980/7/25 01:35:33", - "hi": "25/7/1980, 1:35:33 am", + "hi": "25/7/1980, पू 1:35:33", "es": "25/7/1980, 1:35:33", "fr": "25/07/1980 01:35:33", - "ar": "٢٥‏/٧‏/١٩٨٠، ١:٣٥:٣٣ ص", + "ar": "25‏/7‏/1980، 1:35:33 ص", "bn": "২৫/৭/১৯৮০, ১:৩৫:৩৩ AM", "ru": "25.07.1980, 01:35:33", "pt": "25/07/1980, 01:35:33", - "ur": "25/7/1980، 1:35:33 AM", + "ur": "25/7/1980، 1:35:33 ق.د.", "id": "25/7/1980, 01.35.33", "de": "25.7.1980, 01:35:33", "ja": "1980/7/25 1:35:33", @@ -41,7 +41,7 @@ "hi": "25/7/1980", "es": "25/7/1980", "fr": "25/07/1980", - "ar": "٢٥‏/٧‏/١٩٨٠", + "ar": "25‏/7‏/1980", "bn": "২৫/৭/১৯৮০", "ru": "25.07.1980", "pt": "25/07/1980", @@ -77,7 +77,7 @@ "hi": "2,75,760.913", "es": "275.760,913", "fr": "275 760,913", - "ar": "٢٧٥٬٧٦٠٫٩١٣", + "ar": "275,760.913", "bn": "২,৭৫,৭৬০.৯১৩", "ru": "275 760,913", "pt": "275.760,913", @@ -113,7 +113,7 @@ "hi": "5,86,920.617 घंटे पहले", "es": "hace 586.920,617 horas", "fr": "il y a 586 920,617 heures", - "ar": "قبل ٥٨٦٬٩٢٠٫٦١٧ ساعة", + "ar": "قبل 586,920.617 ساعة", "bn": "৫,৮৬,৯২০.৬১৭ ঘন্টা আগে", "ru": "586 920,617 часа назад", "pt": "há 586.920,617 horas", From e08af61537ef5e0e2bff855a824d3d1992d23ec7 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Thu, 23 Jan 2025 20:38:49 -0800 Subject: [PATCH 147/205] test: enforce strict mode in test-zlib-const MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of checking that assignments fail silently in sloppy mode, check that they throw in strict mode. PR-URL: https://github.com/nodejs/node/pull/56689 Reviewed-By: Michaël Zasso Reviewed-By: Luigi Pinca Reviewed-By: James M Snell --- test/parallel/test-zlib-const.js | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/test/parallel/test-zlib-const.js b/test/parallel/test-zlib-const.js index 342c8c712a475b..5b9a127f0eaa02 100644 --- a/test/parallel/test-zlib-const.js +++ b/test/parallel/test-zlib-const.js @@ -1,4 +1,4 @@ -/* eslint-disable strict */ +'use strict'; require('../common'); const assert = require('assert'); @@ -9,27 +9,17 @@ assert.strictEqual(zlib.constants.Z_OK, 0, 'Expected Z_OK to be 0;', `got ${zlib.constants.Z_OK}`, ].join(' ')); -zlib.constants.Z_OK = 1; -assert.strictEqual(zlib.constants.Z_OK, 0, - [ - 'Z_OK should be immutable.', - `Expected to get 0, got ${zlib.constants.Z_OK}`, - ].join(' ')); + +assert.throws(() => { zlib.constants.Z_OK = 1; }, + TypeError, 'zlib.constants.Z_OK should be immutable'); assert.strictEqual(zlib.codes.Z_OK, 0, `Expected Z_OK to be 0; got ${zlib.codes.Z_OK}`); -zlib.codes.Z_OK = 1; -assert.strictEqual(zlib.codes.Z_OK, 0, - [ - 'Z_OK should be immutable.', - `Expected to get 0, got ${zlib.codes.Z_OK}`, - ].join(' ')); -zlib.codes = { Z_OK: 1 }; -assert.strictEqual(zlib.codes.Z_OK, 0, - [ - 'Z_OK should be immutable.', - `Expected to get 0, got ${zlib.codes.Z_OK}`, - ].join(' ')); +assert.throws(() => { zlib.codes.Z_OK = 1; }, + TypeError, 'zlib.codes.Z_OK should be immutable'); + +assert.throws(() => { zlib.codes = { Z_OK: 1 }; }, + TypeError, 'zlib.codes should be immutable'); assert.ok(Object.isFrozen(zlib.codes), [ From 362272b0a412d4f6efb3ba136a596ac2a4d25494 Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Fri, 24 Jan 2025 15:22:12 +0100 Subject: [PATCH 148/205] tools: do not throw on missing `create-release-proposal.sh` PR-URL: https://github.com/nodejs/node/pull/56704 Reviewed-By: James M Snell Reviewed-By: Tierney Cyren Reviewed-By: Rafael Gonzaga --- .github/workflows/create-release-proposal.yml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/workflows/create-release-proposal.yml b/.github/workflows/create-release-proposal.yml index 33426bdcda4a5b..0b580eab81ac76 100644 --- a/.github/workflows/create-release-proposal.yml +++ b/.github/workflows/create-release-proposal.yml @@ -71,13 +71,10 @@ jobs: git config --local user.name "Node.js GitHub Bot" - name: Start git node release prepare - # `git update-index` tells git to ignore future changes to the `.sh` file, - # `|| true` is there to ignore the error if such file doesn't exist yet. # The curl command is to make sure we run the version of the script corresponding to the current workflow. run: | - git update-index --assume-unchanged tools/actions/create-release-proposal.sh || true - curl -fsSLo tools/actions/create-release-proposal.sh https://github.com/${GITHUB_REPOSITORY}/raw/${GITHUB_SHA}/tools/actions/create-release-proposal.sh - ./tools/actions/create-release-proposal.sh "${RELEASE_DATE}" "${RELEASE_LINE}" "${GITHUB_ACTOR}" + curl -fsSL https://github.com/${GITHUB_REPOSITORY}/raw/${GITHUB_SHA}/tools/actions/create-release-proposal.sh |\ + sh -s -- "${RELEASE_DATE}" "${RELEASE_LINE}" "${GITHUB_ACTOR}" env: GH_TOKEN: ${{ github.token }} # We want the bot to push the push the release commit so CI runs on it. From a0aef4dfb69af9063e2f52984d31689b63c9915b Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Sun, 12 Jan 2025 13:04:40 -0800 Subject: [PATCH 149/205] util: inspect: do not crash on an Error stack that contains a Symbol See #56570 PR-URL: https://github.com/nodejs/node/pull/56573 Reviewed-By: James M Snell Reviewed-By: Luigi Pinca Reviewed-By: Jason Zhang Reviewed-By: Ruben Bridgewater --- lib/internal/util/inspect.js | 14 ++++++++++---- test/parallel/test-util-inspect.js | 20 ++++++++++++++++---- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/lib/internal/util/inspect.js b/lib/internal/util/inspect.js index 6d0496b151b0fe..091d3a53f10c10 100644 --- a/lib/internal/util/inspect.js +++ b/lib/internal/util/inspect.js @@ -1287,8 +1287,14 @@ function identicalSequenceRange(a, b) { return { len: 0, offset: 0 }; } -function getStackString(error) { - return error.stack ? String(error.stack) : ErrorPrototypeToString(error); +function getStackString(ctx, error) { + if (error.stack) { + if (typeof error.stack === 'string') { + return error.stack; + } + return formatValue(ctx, error.stack); + } + return ErrorPrototypeToString(error); } function getStackFrames(ctx, err, stack) { @@ -1303,7 +1309,7 @@ function getStackFrames(ctx, err, stack) { // Remove stack frames identical to frames in cause. if (cause != null && isError(cause)) { - const causeStack = getStackString(cause); + const causeStack = getStackString(ctx, cause); const causeStackStart = StringPrototypeIndexOf(causeStack, '\n at'); if (causeStackStart !== -1) { const causeFrames = StringPrototypeSplit(StringPrototypeSlice(causeStack, causeStackStart + 1), '\n'); @@ -1426,7 +1432,7 @@ function safeGetCWD() { function formatError(err, constructor, tag, ctx, keys) { const name = err.name != null ? err.name : 'Error'; - let stack = getStackString(err); + let stack = getStackString(ctx, err); removeDuplicateErrorKeys(ctx, keys, err, stack); diff --git a/test/parallel/test-util-inspect.js b/test/parallel/test-util-inspect.js index b3b08a82d5b7b0..e84d80073bb3ad 100644 --- a/test/parallel/test-util-inspect.js +++ b/test/parallel/test-util-inspect.js @@ -777,16 +777,18 @@ assert.strictEqual(util.inspect(-5e-324), '-5e-324'); [undefined, 'RangeError: foo', '[RangeError: foo]'], [false, 'false [RangeError]: foo', '[RangeError: foo]'], ['', 'foo', '[RangeError: foo]'], - [[1, 2, 3], '1,2,3 [RangeError]: foo', '[1,2,3]'], + [[1, 2, 3], '1,2,3 [RangeError]: foo', '[[\n 1,\n 2,\n 3\n]]'], ].forEach(([value, outputStart, stack]) => { let err = new RangeError('foo'); err.name = value; + const result = util.inspect(err); assert( - util.inspect(err).startsWith(outputStart), + result.startsWith(outputStart), util.format( - 'The name set to %o did not result in the expected output "%s"', + 'The name set to %o did not result in the expected output "%s", got "%s"', value, - outputStart + outputStart, + result.split('\n')[0] ) ); @@ -3416,3 +3418,13 @@ assert.strictEqual( ${error.stack.split('\n').slice(1).join('\n')}`, ); } + +{ + const error = new Error(); + error.stack = [Symbol('foo')]; + + assert.strictEqual( + inspect(error), + '[[\n Symbol(foo)\n]]' + ); +} From fe79d63be024e80960da5576be35544d46dfa853 Mon Sep 17 00:00:00 2001 From: Jonas Date: Fri, 24 Jan 2025 11:22:54 -0500 Subject: [PATCH 150/205] test: add missing test for env file PR-URL: https://github.com/nodejs/node/pull/56642 Reviewed-By: Yagiz Nizipli Reviewed-By: Luigi Pinca Reviewed-By: Jake Yuesong Li Reviewed-By: Matteo Collina Reviewed-By: James M Snell --- test/parallel/test-dotenv-edge-cases.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/parallel/test-dotenv-edge-cases.js b/test/parallel/test-dotenv-edge-cases.js index 769d33a13b8ce9..926c8d0793ac8b 100644 --- a/test/parallel/test-dotenv-edge-cases.js +++ b/test/parallel/test-dotenv-edge-cases.js @@ -170,4 +170,16 @@ describe('.env supports edge cases', () => { assert.strictEqual(SingleQuotesChild.stderr, ''); assert.strictEqual(SingleQuotesChild.code, 0); }); + + it('should reject invalid env file flag', async () => { + const child = await common.spawnPromisified( + process.execPath, + ['--env-file-ABCD', validEnvFilePath], + { cwd: __dirname }, + ); + + assert.strictEqual(child.stdout, ''); + assert.strictEqual(child.code, 9); + assert.match(child.stderr, /bad option: --env-file-ABCD/); + }); }); From 1c3204a4cc053f1126b8f59abab5329a403cb7c7 Mon Sep 17 00:00:00 2001 From: James M Snell Date: Fri, 24 Jan 2025 16:58:32 -0800 Subject: [PATCH 151/205] test: move crypto related common utilities in common/crypto Since `common/crypto` already exists, it makes sense to keep crypto-related utilities there. The only exception being common.hasCrypto which is needed up front to determine if tests should be skipped. Eliminate the redundant check in hasFipsCrypto and just use crypto.getFips() directly where needed. PR-URL: https://github.com/nodejs/node/pull/56714 Reviewed-By: Yagiz Nizipli Reviewed-By: Luigi Pinca --- test/addons/openssl-providers/providers.cjs | 7 ++- test/benchmark/test-benchmark-crypto.js | 5 +- test/common/README.md | 17 ------ test/common/crypto.js | 52 ++++++++++++++++++- test/common/index.js | 52 ------------------- test/common/index.mjs | 2 - test/parallel/test-cli-node-options.js | 3 +- test/parallel/test-crypto-authenticated.js | 20 ++++--- .../test-crypto-cipheriv-decipheriv.js | 10 ++-- test/parallel/test-crypto-classes.js | 6 +-- test/parallel/test-crypto-dh-constructor.js | 3 +- test/parallel/test-crypto-dh-errors.js | 3 +- test/parallel/test-crypto-dh-generate-keys.js | 3 +- test/parallel/test-crypto-dh-leak.js | 3 +- test/parallel/test-crypto-dh-odd-key.js | 8 +-- test/parallel/test-crypto-dh-stateless.js | 7 +-- test/parallel/test-crypto-dh.js | 17 +++--- test/parallel/test-crypto-ecb.js | 13 +++-- test/parallel/test-crypto-fips.js | 5 +- test/parallel/test-crypto-hash.js | 7 +-- test/parallel/test-crypto-hkdf.js | 5 +- test/parallel/test-crypto-hmac.js | 5 +- test/parallel/test-crypto-key-objects.js | 10 ++-- ...test-crypto-keygen-async-dsa-key-object.js | 8 +-- test/parallel/test-crypto-keygen-async-dsa.js | 8 +-- ...-explicit-elliptic-curve-encrypted-p256.js | 4 +- ...nc-explicit-elliptic-curve-encrypted.js.js | 3 +- ...ync-named-elliptic-curve-encrypted-p256.js | 3 +- ...en-async-named-elliptic-curve-encrypted.js | 3 +- test/parallel/test-crypto-keygen-async-rsa.js | 3 +- .../parallel/test-crypto-keygen-bit-length.js | 3 +- ...rypto-keygen-empty-passphrase-no-prompt.js | 3 +- .../test-crypto-keygen-missing-oid.js | 4 +- test/parallel/test-crypto-keygen.js | 3 +- test/parallel/test-crypto-no-algorithm.js | 4 +- test/parallel/test-crypto-oneshot-hash.js | 3 +- test/parallel/test-crypto-padding.js | 5 +- test/parallel/test-crypto-pbkdf2.js | 3 +- .../test-crypto-private-decrypt-gh32240.js | 4 +- ...t-crypto-publicDecrypt-fails-first-time.js | 8 ++- test/parallel/test-crypto-rsa-dsa.js | 7 +-- test/parallel/test-crypto-secure-heap.js | 13 +++-- test/parallel/test-crypto-sign-verify.js | 13 +++-- test/parallel/test-crypto-stream.js | 8 +-- test/parallel/test-crypto-x509.js | 5 +- test/parallel/test-crypto.js | 7 +-- test/parallel/test-dsa-fips-invalid-key.js | 10 +++- .../test-https-agent-session-eviction.js | 9 ++-- .../test-https-client-renegotiation-limit.js | 8 ++- test/parallel/test-https-foafssl.js | 10 ++-- ...rocess-env-allowed-flags-are-documented.js | 7 +-- test/parallel/test-process-versions.js | 3 +- test/parallel/test-tls-alert-handling.js | 20 ++++--- test/parallel/test-tls-alert.js | 15 ++++-- test/parallel/test-tls-alpn-server-client.js | 5 +- test/parallel/test-tls-cert-ext-encoding.js | 4 +- test/parallel/test-tls-client-auth.js | 7 ++- .../test-tls-client-getephemeralkeyinfo.js | 3 +- test/parallel/test-tls-client-mindhsize.js | 5 +- .../test-tls-client-renegotiation-13.js | 8 ++- .../test-tls-client-renegotiation-limit.js | 8 ++- test/parallel/test-tls-dhe.js | 17 ++++-- test/parallel/test-tls-ecdh-auto.js | 10 ++-- test/parallel/test-tls-ecdh-multiple.js | 14 +++-- test/parallel/test-tls-ecdh.js | 10 ++-- test/parallel/test-tls-empty-sni-context.js | 4 +- test/parallel/test-tls-getprotocol.js | 6 ++- test/parallel/test-tls-junk-server.js | 7 ++- test/parallel/test-tls-key-mismatch.js | 6 ++- test/parallel/test-tls-legacy-pfx.js | 9 +++- test/parallel/test-tls-min-max-version.js | 16 ++++-- test/parallel/test-tls-no-sslv3.js | 10 ++-- test/parallel/test-tls-ocsp-callback.js | 15 ++++-- test/parallel/test-tls-psk-circuit.js | 10 ++-- test/parallel/test-tls-psk-server.js | 11 ++-- test/parallel/test-tls-securepair-server.js | 10 ++-- test/parallel/test-tls-server-verify.js | 10 ++-- test/parallel/test-tls-session-cache.js | 20 ++++--- test/parallel/test-tls-set-ciphers.js | 16 ++++-- test/parallel/test-tls-set-secure-context.js | 6 ++- test/parallel/test-tls-set-sigalgs.js | 7 ++- test/parallel/test-trace-env.js | 8 +-- test/parallel/test-x509-escaping.js | 5 +- test/pummel/test-crypto-dh-hash.js | 4 +- test/pummel/test-crypto-dh-keys.js | 3 +- test/pummel/test-dh-regr.js | 3 +- test/sequential/test-tls-psk-client.js | 11 ++-- test/sequential/test-tls-securepair-client.js | 25 +++++---- test/sequential/test-tls-session-timeout.js | 10 ++-- 89 files changed, 505 insertions(+), 288 deletions(-) diff --git a/test/addons/openssl-providers/providers.cjs b/test/addons/openssl-providers/providers.cjs index 2dabbf020e2a41..efa1019c62d99c 100644 --- a/test/addons/openssl-providers/providers.cjs +++ b/test/addons/openssl-providers/providers.cjs @@ -1,11 +1,14 @@ 'use strict'; const common = require('../../common'); -if (!common.hasCrypto) +if (!common.hasCrypto) { common.skip('missing crypto'); +} +const { hasOpenSSL3 } = require('../../common/crypto'); -if (!common.hasOpenSSL3) +if (!hasOpenSSL3) { common.skip('this test requires OpenSSL 3.x'); +} const assert = require('node:assert'); const { createHash, getCiphers, getHashes } = require('node:crypto'); const { debuglog } = require('node:util'); diff --git a/test/benchmark/test-benchmark-crypto.js b/test/benchmark/test-benchmark-crypto.js index 7f6988acf234d8..72d79ece13e787 100644 --- a/test/benchmark/test-benchmark-crypto.js +++ b/test/benchmark/test-benchmark-crypto.js @@ -5,8 +5,11 @@ const common = require('../common'); if (!common.hasCrypto) common.skip('missing crypto'); -if (common.hasFipsCrypto) +const { getFips } = require('crypto'); + +if (getFips()) { common.skip('some benchmarks are FIPS-incompatible'); +} const runBenchmark = require('../common/benchmark'); diff --git a/test/common/README.md b/test/common/README.md index 5f5ff75fca2431..ee36503f920001 100644 --- a/test/common/README.md +++ b/test/common/README.md @@ -226,17 +226,6 @@ The TTY file descriptor is assumed to be capable of being writable. Indicates whether OpenSSL is available. -### `hasFipsCrypto` - -* [\][] - -Indicates that Node.js has been linked with a FIPS compatible OpenSSL library, -and that FIPS as been enabled using `--enable-fips`. - -To only detect if the OpenSSL library is FIPS compatible, regardless if it has -been enabled or not, then `process.config.variables.openssl_is_fips` can be -used to determine that situation. - ### `hasIntl` * [\][] @@ -417,12 +406,6 @@ Returns `true` if the exit code `exitCode` and/or signal name `signal` represent the exit code and/or signal name of a node process that aborted, `false` otherwise. -### `opensslCli` - -* [\][] - -Indicates whether 'opensslCli' is supported. - ### `platformTimeout(ms)` * `ms` [\][] | [\][] diff --git a/test/common/crypto.js b/test/common/crypto.js index 10432d7e7a7e32..f50d3895a1783b 100644 --- a/test/common/crypto.js +++ b/test/common/crypto.js @@ -1,8 +1,9 @@ 'use strict'; const common = require('../common'); -if (!common.hasCrypto) +if (!common.hasCrypto) { common.skip('missing crypto'); +} const assert = require('assert'); const crypto = require('crypto'); @@ -98,6 +99,27 @@ const pkcs8EncExp = getRegExpForPEM('ENCRYPTED PRIVATE KEY'); const sec1Exp = getRegExpForPEM('EC PRIVATE KEY'); const sec1EncExp = (cipher) => getRegExpForPEM('EC PRIVATE KEY', cipher); +// Synthesize OPENSSL_VERSION_NUMBER format with the layout 0xMNN00PPSL +const opensslVersionNumber = (major = 0, minor = 0, patch = 0) => { + assert(major >= 0 && major <= 0xf); + assert(minor >= 0 && minor <= 0xff); + assert(patch >= 0 && patch <= 0xff); + return (major << 28) | (minor << 20) | (patch << 4); +}; + +let OPENSSL_VERSION_NUMBER; +const hasOpenSSL = (major = 0, minor = 0, patch = 0) => { + if (!common.hasCrypto) return false; + if (OPENSSL_VERSION_NUMBER === undefined) { + const regexp = /(?\d+)\.(?\d+)\.(?

\d+)/; + const { m, n, p } = process.versions.openssl.match(regexp).groups; + OPENSSL_VERSION_NUMBER = opensslVersionNumber(m, n, p); + } + return OPENSSL_VERSION_NUMBER >= opensslVersionNumber(major, minor, patch); +}; + +let opensslCli = null; + module.exports = { modp2buf, assertApproximateSize, @@ -111,4 +133,32 @@ module.exports = { pkcs8EncExp, // used once sec1Exp, sec1EncExp, + hasOpenSSL, + get hasOpenSSL3() { + return hasOpenSSL(3); + }, + // opensslCli defined lazily to reduce overhead of spawnSync + get opensslCli() { + if (opensslCli !== null) return opensslCli; + + if (process.config.variables.node_shared_openssl) { + // Use external command + opensslCli = 'openssl'; + } else { + const path = require('path'); + // Use command built from sources included in Node.js repository + opensslCli = path.join(path.dirname(process.execPath), 'openssl-cli'); + } + + if (exports.isWindows) opensslCli += '.exe'; + + const { spawnSync } = require('child_process'); + + const opensslCmd = spawnSync(opensslCli, ['version']); + if (opensslCmd.status !== 0 || opensslCmd.error !== undefined) { + // OpenSSL command cannot be executed + opensslCli = false; + } + return opensslCli; + }, }; diff --git a/test/common/index.js b/test/common/index.js index b5592a66a081c3..d2c39578324600 100644 --- a/test/common/index.js +++ b/test/common/index.js @@ -19,7 +19,6 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. -/* eslint-disable node-core/crypto-check */ 'use strict'; const process = global.process; // Some tests tamper with the process global. @@ -57,25 +56,6 @@ const noop = () => {}; const hasCrypto = Boolean(process.versions.openssl) && !process.env.NODE_SKIP_CRYPTO; -// Synthesize OPENSSL_VERSION_NUMBER format with the layout 0xMNN00PPSL -const opensslVersionNumber = (major = 0, minor = 0, patch = 0) => { - assert(major >= 0 && major <= 0xf); - assert(minor >= 0 && minor <= 0xff); - assert(patch >= 0 && patch <= 0xff); - return (major << 28) | (minor << 20) | (patch << 4); -}; - -let OPENSSL_VERSION_NUMBER; -const hasOpenSSL = (major = 0, minor = 0, patch = 0) => { - if (!hasCrypto) return false; - if (OPENSSL_VERSION_NUMBER === undefined) { - const regexp = /(?\d+)\.(?\d+)\.(?

\d+)/; - const { m, n, p } = process.versions.openssl.match(regexp).groups; - OPENSSL_VERSION_NUMBER = opensslVersionNumber(m, n, p); - } - return OPENSSL_VERSION_NUMBER >= opensslVersionNumber(major, minor, patch); -}; - const hasQuic = hasCrypto && !!process.config.variables.openssl_quic; function parseTestFlags(filename = process.argv[1]) { @@ -220,7 +200,6 @@ if (process.env.NODE_TEST_WITH_ASYNC_HOOKS) { }).enable(); } -let opensslCli = null; let inFreeBSDJail = null; let localhostIPv4 = null; @@ -985,7 +964,6 @@ const common = { getTTYfd, hasIntl, hasCrypto, - hasOpenSSL, hasQuic, hasMultiLocalhost, invalidArgTypeHelper, @@ -1027,10 +1005,6 @@ const common = { return require('os').totalmem() > 0x70000000; /* 1.75 Gb */ }, - get hasFipsCrypto() { - return hasCrypto && require('crypto').getFips(); - }, - get hasIPv6() { const iFaces = require('os').networkInterfaces(); let re; @@ -1047,10 +1021,6 @@ const common = { }); }, - get hasOpenSSL3() { - return hasOpenSSL(3); - }, - get inFreeBSDJail() { if (inFreeBSDJail !== null) return inFreeBSDJail; @@ -1100,28 +1070,6 @@ const common = { return localhostIPv4; }, - // opensslCli defined lazily to reduce overhead of spawnSync - get opensslCli() { - if (opensslCli !== null) return opensslCli; - - if (process.config.variables.node_shared_openssl) { - // Use external command - opensslCli = 'openssl'; - } else { - // Use command built from sources included in Node.js repository - opensslCli = path.join(path.dirname(process.execPath), 'openssl-cli'); - } - - if (exports.isWindows) opensslCli += '.exe'; - - const opensslCmd = spawnSync(opensslCli, ['version']); - if (opensslCmd.status !== 0 || opensslCmd.error !== undefined) { - // OpenSSL command cannot be executed - opensslCli = false; - } - return opensslCli; - }, - get PORT() { if (+process.env.TEST_PARALLEL) { throw new Error('common.PORT cannot be used in a parallelized test'); diff --git a/test/common/index.mjs b/test/common/index.mjs index b252f2dc4aac5e..23328ac90ea3c9 100644 --- a/test/common/index.mjs +++ b/test/common/index.mjs @@ -41,7 +41,6 @@ const { mustNotMutateObjectDeep, mustSucceed, nodeProcessAborted, - opensslCli, parseTestFlags, PIPE, platformTimeout, @@ -97,7 +96,6 @@ export { mustNotMutateObjectDeep, mustSucceed, nodeProcessAborted, - opensslCli, parseTestFlags, PIPE, platformTimeout, diff --git a/test/parallel/test-cli-node-options.js b/test/parallel/test-cli-node-options.js index 03ffe7aa03f481..b1d5c44ceeeebc 100644 --- a/test/parallel/test-cli-node-options.js +++ b/test/parallel/test-cli-node-options.js @@ -12,6 +12,7 @@ const { Worker } = require('worker_threads'); const fixtures = require('../common/fixtures'); const tmpdir = require('../common/tmpdir'); +const { hasOpenSSL3 } = require('../common/crypto'); tmpdir.refresh(); const printA = path.relative(tmpdir.path, fixtures.path('printA.js')); @@ -64,7 +65,7 @@ if (common.isLinux) { if (common.hasCrypto) { expectNoWorker('--use-openssl-ca', 'B\n'); expectNoWorker('--use-bundled-ca', 'B\n'); - if (!common.hasOpenSSL3) + if (!hasOpenSSL3) expectNoWorker('--openssl-config=_ossl_cfg', 'B\n'); } diff --git a/test/parallel/test-crypto-authenticated.js b/test/parallel/test-crypto-authenticated.js index d191ab7be2de20..181ea732b91281 100644 --- a/test/parallel/test-crypto-authenticated.js +++ b/test/parallel/test-crypto-authenticated.js @@ -21,13 +21,17 @@ // Flags: --no-warnings 'use strict'; const common = require('../common'); -if (!common.hasCrypto) +if (!common.hasCrypto) { common.skip('missing crypto'); +} const assert = require('assert'); const crypto = require('crypto'); const { inspect } = require('util'); const fixtures = require('../common/fixtures'); +const { hasOpenSSL3 } = require('../common/crypto'); + +const isFipsEnabled = crypto.getFips(); // // Test authenticated encryption modes. @@ -53,7 +57,7 @@ for (const test of TEST_CASES) { continue; } - if (common.hasFipsCrypto && test.iv.length < 24) { + if (isFipsEnabled && test.iv.length < 24) { common.printSkipMessage('IV len < 12 bytes unsupported in FIPS mode'); continue; } @@ -95,7 +99,7 @@ for (const test of TEST_CASES) { } { - if (isCCM && common.hasFipsCrypto) { + if (isCCM && isFipsEnabled) { assert.throws(() => { crypto.createDecipheriv(test.algo, Buffer.from(test.key, 'hex'), @@ -286,7 +290,7 @@ for (const test of TEST_CASES) { }); }, errMessages.authTagLength); - if (!common.hasFipsCrypto) { + if (!isFipsEnabled) { assert.throws(() => { crypto.createDecipheriv('aes-256-ccm', 'FxLKsqdmv0E9xrQhp0b1ZgI0K7JFZJM8', @@ -312,7 +316,7 @@ for (const test of TEST_CASES) { }); // CCM decryption and create(De|C)ipher are unsupported in FIPS mode. - if (!common.hasFipsCrypto) { + if (!isFipsEnabled) { assert.throws(() => { crypto.createDecipheriv(`aes-256-${mode}`, 'FxLKsqdmv0E9xrQhp0b1ZgI0K7JFZJM8', @@ -388,7 +392,7 @@ for (const test of TEST_CASES) { cipher.setAAD(Buffer.from('0123456789', 'hex')); }, /options\.plaintextLength required for CCM mode with AAD/); - if (!common.hasFipsCrypto) { + if (!isFipsEnabled) { assert.throws(() => { const cipher = crypto.createDecipheriv('aes-256-ccm', 'FxLKsqdmv0E9xrQhp0b1ZgI0K7JFZJM8', @@ -403,7 +407,7 @@ for (const test of TEST_CASES) { // Test that final() throws in CCM mode when no authentication tag is provided. { - if (!common.hasFipsCrypto) { + if (!isFipsEnabled) { const key = Buffer.from('1ed2233fa2223ef5d7df08546049406c', 'hex'); const iv = Buffer.from('7305220bca40d4c90e1791e9', 'hex'); const ct = Buffer.from('8beba09d4d4d861f957d51c0794f4abf8030848e', 'hex'); @@ -562,7 +566,7 @@ for (const test of TEST_CASES) { ]) { assert.throws(() => { cipher.final(); - }, common.hasOpenSSL3 ? { + }, hasOpenSSL3 ? { code: 'ERR_OSSL_TAG_NOT_SET' } : { message: /Unsupported state/ diff --git a/test/parallel/test-crypto-cipheriv-decipheriv.js b/test/parallel/test-crypto-cipheriv-decipheriv.js index 3e3632203af72c..88d07c3b957f57 100644 --- a/test/parallel/test-crypto-cipheriv-decipheriv.js +++ b/test/parallel/test-crypto-cipheriv-decipheriv.js @@ -5,6 +5,8 @@ if (!common.hasCrypto) const assert = require('assert'); const crypto = require('crypto'); +const { hasOpenSSL3 } = require('../common/crypto'); +const isFipsEnabled = crypto.getFips(); function testCipher1(key, iv) { // Test encryption and decryption with explicit key and iv @@ -150,7 +152,7 @@ testCipher1(Buffer.from('0123456789abcd0123456789'), '12345678'); testCipher1(Buffer.from('0123456789abcd0123456789'), Buffer.from('12345678')); testCipher2(Buffer.from('0123456789abcd0123456789'), Buffer.from('12345678')); -if (!common.hasFipsCrypto) { +if (!isFipsEnabled) { testCipher3(Buffer.from('000102030405060708090A0B0C0D0E0F', 'hex'), Buffer.from('A6A6A6A6A6A6A6A6', 'hex')); } @@ -193,10 +195,10 @@ assert.throws( errMessage); // But all other IV lengths should be accepted. -const minIvLength = common.hasOpenSSL3 ? 8 : 1; -const maxIvLength = common.hasOpenSSL3 ? 64 : 256; +const minIvLength = hasOpenSSL3 ? 8 : 1; +const maxIvLength = hasOpenSSL3 ? 64 : 256; for (let n = minIvLength; n < maxIvLength; n += 1) { - if (common.hasFipsCrypto && n < 12) continue; + if (isFipsEnabled && n < 12) continue; crypto.createCipheriv('aes-128-gcm', Buffer.alloc(16), Buffer.alloc(n)); } diff --git a/test/parallel/test-crypto-classes.js b/test/parallel/test-crypto-classes.js index f736921476a1c5..429bc91d4412be 100644 --- a/test/parallel/test-crypto-classes.js +++ b/test/parallel/test-crypto-classes.js @@ -4,9 +4,9 @@ const assert = require('assert'); if (!common.hasCrypto) { common.skip('missing crypto'); - return; } const crypto = require('crypto'); +const { hasOpenSSL3 } = require('../common/crypto'); // 'ClassName' : ['args', 'for', 'constructor'] const TEST_CASES = { @@ -21,8 +21,8 @@ const TEST_CASES = { 'ECDH': ['prime256v1'], }; -if (!common.hasFipsCrypto) { - TEST_CASES.DiffieHellman = [common.hasOpenSSL3 ? 1024 : 256]; +if (!crypto.getFips()) { + TEST_CASES.DiffieHellman = [hasOpenSSL3 ? 1024 : 256]; } for (const [clazz, args] of Object.entries(TEST_CASES)) { diff --git a/test/parallel/test-crypto-dh-constructor.js b/test/parallel/test-crypto-dh-constructor.js index c7eaca29347a2b..eb8674932484ed 100644 --- a/test/parallel/test-crypto-dh-constructor.js +++ b/test/parallel/test-crypto-dh-constructor.js @@ -5,8 +5,9 @@ if (!common.hasCrypto) const assert = require('assert'); const crypto = require('crypto'); +const { hasOpenSSL3 } = require('../common/crypto'); -const size = common.hasFipsCrypto || common.hasOpenSSL3 ? 1024 : 256; +const size = crypto.getFips() || hasOpenSSL3 ? 1024 : 256; const dh1 = crypto.createDiffieHellman(size); const p1 = dh1.getPrime('buffer'); diff --git a/test/parallel/test-crypto-dh-errors.js b/test/parallel/test-crypto-dh-errors.js index 476ca64b4425b5..0af4db0310750c 100644 --- a/test/parallel/test-crypto-dh-errors.js +++ b/test/parallel/test-crypto-dh-errors.js @@ -5,6 +5,7 @@ if (!common.hasCrypto) const assert = require('assert'); const crypto = require('crypto'); +const { hasOpenSSL3 } = require('../common/crypto'); // https://github.com/nodejs/node/issues/32738 // XXX(bnoordhuis) validateInt32() throwing ERR_OUT_OF_RANGE and RangeError @@ -24,7 +25,7 @@ assert.throws(() => crypto.createDiffieHellman('abcdef', 13.37), { }); for (const bits of [-1, 0, 1]) { - if (common.hasOpenSSL3) { + if (hasOpenSSL3) { assert.throws(() => crypto.createDiffieHellman(bits), { code: 'ERR_OSSL_DH_MODULUS_TOO_SMALL', name: 'Error', diff --git a/test/parallel/test-crypto-dh-generate-keys.js b/test/parallel/test-crypto-dh-generate-keys.js index fc277bb0d9b8e4..e4598274328bd8 100644 --- a/test/parallel/test-crypto-dh-generate-keys.js +++ b/test/parallel/test-crypto-dh-generate-keys.js @@ -6,9 +6,10 @@ if (!common.hasCrypto) const assert = require('assert'); const crypto = require('crypto'); +const { hasOpenSSL3 } = require('../common/crypto'); { - const size = common.hasFipsCrypto || common.hasOpenSSL3 ? 1024 : 256; + const size = crypto.getFips() || hasOpenSSL3 ? 1024 : 256; function unlessInvalidState(f) { try { diff --git a/test/parallel/test-crypto-dh-leak.js b/test/parallel/test-crypto-dh-leak.js index 1998d61d4affd7..3b5051feb43cd8 100644 --- a/test/parallel/test-crypto-dh-leak.js +++ b/test/parallel/test-crypto-dh-leak.js @@ -9,10 +9,11 @@ if (common.isASan) const assert = require('assert'); const crypto = require('crypto'); +const { hasOpenSSL3 } = require('../common/crypto'); const before = process.memoryUsage.rss(); { - const size = common.hasFipsCrypto || common.hasOpenSSL3 ? 1024 : 256; + const size = crypto.getFips() || hasOpenSSL3 ? 1024 : 256; const dh = crypto.createDiffieHellman(size); const publicKey = dh.generateKeys(); const privateKey = dh.getPrivateKey(); diff --git a/test/parallel/test-crypto-dh-odd-key.js b/test/parallel/test-crypto-dh-odd-key.js index 69a1eb56c866b3..fbe42be425ed1c 100644 --- a/test/parallel/test-crypto-dh-odd-key.js +++ b/test/parallel/test-crypto-dh-odd-key.js @@ -21,22 +21,24 @@ 'use strict'; const common = require('../common'); -if (!common.hasCrypto) +if (!common.hasCrypto) { common.skip('missing crypto'); +} const assert = require('assert'); const crypto = require('crypto'); +const { hasOpenSSL3 } = require('../common/crypto'); function test() { const odd = Buffer.alloc(39, 'A'); - const c = crypto.createDiffieHellman(common.hasOpenSSL3 ? 1024 : 32); + const c = crypto.createDiffieHellman(hasOpenSSL3 ? 1024 : 32); c.setPrivateKey(odd); c.generateKeys(); } // FIPS requires a length of at least 1024 -if (!common.hasFipsCrypto) { +if (!crypto.getFips()) { test(); } else { assert.throws(function() { test(); }, /key size too small/); diff --git a/test/parallel/test-crypto-dh-stateless.js b/test/parallel/test-crypto-dh-stateless.js index 2ccac322e23958..f4fc1849699e31 100644 --- a/test/parallel/test-crypto-dh-stateless.js +++ b/test/parallel/test-crypto-dh-stateless.js @@ -5,6 +5,7 @@ if (!common.hasCrypto) const assert = require('assert'); const crypto = require('crypto'); +const { hasOpenSSL3 } = require('../common/crypto'); assert.throws(() => crypto.diffieHellman(), { name: 'TypeError', @@ -150,7 +151,7 @@ const list = [ // TODO(danbev): Take a closer look if there should be a check in OpenSSL3 // when the dh parameters differ. -if (!common.hasOpenSSL3) { +if (!hasOpenSSL3) { // Same primes, but different generator. list.push([{ group: 'modp5' }, { prime: group.getPrime(), generator: 5 }]); // Same generator, but different primes. @@ -161,7 +162,7 @@ for (const [params1, params2] of list) { assert.throws(() => { test(crypto.generateKeyPairSync('dh', params1), crypto.generateKeyPairSync('dh', params2)); - }, common.hasOpenSSL3 ? { + }, hasOpenSSL3 ? { name: 'Error', code: 'ERR_OSSL_MISMATCHING_DOMAIN_PARAMETERS' } : { @@ -220,7 +221,7 @@ const not256k1 = crypto.getCurves().find((c) => /^sec.*(224|384|512)/.test(c)); assert.throws(() => { test(crypto.generateKeyPairSync('ec', { namedCurve: 'secp256k1' }), crypto.generateKeyPairSync('ec', { namedCurve: not256k1 })); -}, common.hasOpenSSL3 ? { +}, hasOpenSSL3 ? { name: 'Error', code: 'ERR_OSSL_MISMATCHING_DOMAIN_PARAMETERS' } : { diff --git a/test/parallel/test-crypto-dh.js b/test/parallel/test-crypto-dh.js index 9ebe14011eed22..d7ffbe5eca9273 100644 --- a/test/parallel/test-crypto-dh.js +++ b/test/parallel/test-crypto-dh.js @@ -1,13 +1,18 @@ 'use strict'; const common = require('../common'); -if (!common.hasCrypto) +if (!common.hasCrypto) { common.skip('missing crypto'); +} const assert = require('assert'); const crypto = require('crypto'); +const { + hasOpenSSL3, + hasOpenSSL, +} = require('../common/crypto'); { - const size = common.hasFipsCrypto || common.hasOpenSSL3 ? 1024 : 256; + const size = crypto.getFips() || hasOpenSSL3 ? 1024 : 256; const dh1 = crypto.createDiffieHellman(size); const p1 = dh1.getPrime('buffer'); const dh2 = crypto.createDiffieHellman(p1, 'buffer'); @@ -53,7 +58,7 @@ const crypto = require('crypto'); assert.strictEqual(secret1, secret4); let wrongBlockLength; - if (common.hasOpenSSL3) { + if (hasOpenSSL3) { wrongBlockLength = { message: 'error:1C80006B:Provider routines::wrong final block length', code: 'ERR_OSSL_WRONG_FINAL_BLOCK_LENGTH', @@ -87,11 +92,11 @@ const crypto = require('crypto'); { // Error message was changed in OpenSSL 3.0.x from 3.0.12, and 3.1.x from 3.1.4. - const hasOpenSSL3WithNewErrorMessage = (common.hasOpenSSL(3, 0, 12) && !common.hasOpenSSL(3, 1, 0)) || - (common.hasOpenSSL(3, 1, 4)); + const hasOpenSSL3WithNewErrorMessage = (hasOpenSSL(3, 0, 12) && !hasOpenSSL(3, 1, 0)) || + (hasOpenSSL(3, 1, 4)); assert.throws(() => { dh3.computeSecret(''); - }, { message: common.hasOpenSSL3 && !hasOpenSSL3WithNewErrorMessage ? + }, { message: hasOpenSSL3 && !hasOpenSSL3WithNewErrorMessage ? 'Unspecified validation error' : 'Supplied key is too small' }); } diff --git a/test/parallel/test-crypto-ecb.js b/test/parallel/test-crypto-ecb.js index aecd858ef3bf1e..6439c9354a059e 100644 --- a/test/parallel/test-crypto-ecb.js +++ b/test/parallel/test-crypto-ecb.js @@ -21,18 +21,23 @@ 'use strict'; const common = require('../common'); -if (!common.hasCrypto) +if (!common.hasCrypto) { common.skip('missing crypto'); +} + +const { hasOpenSSL3 } = require('../common/crypto'); +const crypto = require('crypto'); -if (common.hasFipsCrypto) +if (crypto.getFips()) { common.skip('BF-ECB is not FIPS 140-2 compatible'); +} -if (common.hasOpenSSL3) +if (hasOpenSSL3) { common.skip('Blowfish is only available with the legacy provider in ' + 'OpenSSl 3.x'); +} const assert = require('assert'); -const crypto = require('crypto'); // Testing whether EVP_CipherInit_ex is functioning correctly. // Reference: bug#1997 diff --git a/test/parallel/test-crypto-fips.js b/test/parallel/test-crypto-fips.js index 8a8a8089a3cf3b..de004b9a9e8f23 100644 --- a/test/parallel/test-crypto-fips.js +++ b/test/parallel/test-crypto-fips.js @@ -10,6 +10,7 @@ const path = require('path'); const fixtures = require('../common/fixtures'); const { internalBinding } = require('internal/test/binding'); const { testFipsCrypto } = internalBinding('crypto'); +const { hasOpenSSL3 } = require('../common/crypto'); const FIPS_ENABLED = 1; const FIPS_DISABLED = 0; @@ -114,7 +115,7 @@ assert.ok(test_result === 1 || test_result === 0); // ("Error: Cannot set FIPS mode in a non-FIPS build."). // Due to this uncertainty the following tests are skipped when configured // with --shared-openssl. -if (!sharedOpenSSL() && !common.hasOpenSSL3) { +if (!sharedOpenSSL() && !hasOpenSSL3) { // OpenSSL config file should be able to turn on FIPS mode testHelper( 'stdout', @@ -144,7 +145,7 @@ if (!sharedOpenSSL() && !common.hasOpenSSL3) { // will not work as expected with that version. // TODO(danbev) Revisit these test once FIPS support is available in // OpenSSL 3.x. -if (!common.hasOpenSSL3) { +if (!hasOpenSSL3) { testHelper( 'stdout', [`--openssl-config=${CNF_FIPS_OFF}`], diff --git a/test/parallel/test-crypto-hash.js b/test/parallel/test-crypto-hash.js index ca8f630b4bb7e7..61145aee0727fb 100644 --- a/test/parallel/test-crypto-hash.js +++ b/test/parallel/test-crypto-hash.js @@ -1,13 +1,14 @@ 'use strict'; const common = require('../common'); -if (!common.hasCrypto) +if (!common.hasCrypto) { common.skip('missing crypto'); +} const assert = require('assert'); const crypto = require('crypto'); const fs = require('fs'); -const { hasOpenSSL } = common; +const { hasOpenSSL } = require('../common/crypto'); const fixtures = require('../common/fixtures'); let cryptoType; @@ -40,7 +41,7 @@ a8.write(''); a8.end(); a8 = a8.read(); -if (!common.hasFipsCrypto) { +if (!crypto.getFips()) { cryptoType = 'md5'; digest = 'latin1'; const a0 = crypto.createHash(cryptoType).update('Test123').digest(digest); diff --git a/test/parallel/test-crypto-hkdf.js b/test/parallel/test-crypto-hkdf.js index ff3abdf291efcd..3f7e61e9b2ebc0 100644 --- a/test/parallel/test-crypto-hkdf.js +++ b/test/parallel/test-crypto-hkdf.js @@ -13,6 +13,7 @@ const { hkdfSync, getHashes } = require('crypto'); +const { hasOpenSSL3 } = require('../common/crypto'); { assert.throws(() => hkdf(), { @@ -124,7 +125,7 @@ const algorithms = [ ['sha256', '', 'salt', '', 10], ['sha512', 'secret', 'salt', '', 15], ]; -if (!common.hasOpenSSL3) +if (!hasOpenSSL3) algorithms.push(['whirlpool', 'secret', '', 'info', 20]); algorithms.forEach(([ hash, secret, salt, info, length ]) => { @@ -215,7 +216,7 @@ algorithms.forEach(([ hash, secret, salt, info, length ]) => { }); -if (!common.hasOpenSSL3) { +if (!hasOpenSSL3) { const kKnownUnsupported = ['shake128', 'shake256']; getHashes() .filter((hash) => !kKnownUnsupported.includes(hash)) diff --git a/test/parallel/test-crypto-hmac.js b/test/parallel/test-crypto-hmac.js index 62a6ac18d25265..afb5f74cbf076b 100644 --- a/test/parallel/test-crypto-hmac.js +++ b/test/parallel/test-crypto-hmac.js @@ -1,7 +1,8 @@ 'use strict'; const common = require('../common'); -if (!common.hasCrypto) +if (!common.hasCrypto) { common.skip('missing crypto'); +} const assert = require('assert'); const crypto = require('crypto'); @@ -40,7 +41,7 @@ assert.throws( function testHmac(algo, key, data, expected) { // FIPS does not support MD5. - if (common.hasFipsCrypto && algo === 'md5') + if (crypto.getFips() && algo === 'md5') return; if (!Array.isArray(data)) diff --git a/test/parallel/test-crypto-key-objects.js b/test/parallel/test-crypto-key-objects.js index f5271f16d346c0..0c516d80950694 100644 --- a/test/parallel/test-crypto-key-objects.js +++ b/test/parallel/test-crypto-key-objects.js @@ -24,6 +24,8 @@ const { generateKeyPairSync, } = require('crypto'); +const { hasOpenSSL3 } = require('../common/crypto'); + const fixtures = require('../common/fixtures'); const publicPem = fixtures.readKey('rsa_public.pem', 'ascii'); @@ -297,7 +299,7 @@ const privateDsa = fixtures.readKey('dsa_private_encrypted_1025.pem', // This should not cause a crash: https://github.com/nodejs/node/issues/25247 assert.throws(() => { createPrivateKey({ key: '' }); - }, common.hasOpenSSL3 ? { + }, hasOpenSSL3 ? { message: 'error:1E08010C:DECODER routines::unsupported', } : { message: 'error:0909006C:PEM routines:get_name:no start line', @@ -323,7 +325,7 @@ const privateDsa = fixtures.readKey('dsa_private_encrypted_1025.pem', type: 'pkcs1' }); createPrivateKey({ key, format: 'der', type: 'pkcs1' }); - }, common.hasOpenSSL3 ? { + }, hasOpenSSL3 ? { message: /error:1E08010C:DECODER routines::unsupported/, library: 'DECODER routines' } : { @@ -510,7 +512,7 @@ const privateDsa = fixtures.readKey('dsa_private_encrypted_1025.pem', { // Reading an encrypted key without a passphrase should fail. - assert.throws(() => createPrivateKey(privateDsa), common.hasOpenSSL3 ? { + assert.throws(() => createPrivateKey(privateDsa), hasOpenSSL3 ? { name: 'Error', message: 'error:07880109:common libcrypto routines::interrupted or ' + 'cancelled', @@ -526,7 +528,7 @@ const privateDsa = fixtures.readKey('dsa_private_encrypted_1025.pem', key: privateDsa, format: 'pem', passphrase: Buffer.alloc(1025, 'a') - }), common.hasOpenSSL3 ? { name: 'Error' } : { + }), hasOpenSSL3 ? { name: 'Error' } : { code: 'ERR_OSSL_PEM_BAD_PASSWORD_READ', name: 'Error' }); diff --git a/test/parallel/test-crypto-keygen-async-dsa-key-object.js b/test/parallel/test-crypto-keygen-async-dsa-key-object.js index c15807295541e2..a3df136230d0f8 100644 --- a/test/parallel/test-crypto-keygen-async-dsa-key-object.js +++ b/test/parallel/test-crypto-keygen-async-dsa-key-object.js @@ -9,23 +9,25 @@ const { generateKeyPair, } = require('crypto'); +const { hasOpenSSL3 } = require('../common/crypto'); + // Test async DSA key object generation. { generateKeyPair('dsa', { - modulusLength: common.hasOpenSSL3 ? 2048 : 512, + modulusLength: hasOpenSSL3 ? 2048 : 512, divisorLength: 256 }, common.mustSucceed((publicKey, privateKey) => { assert.strictEqual(publicKey.type, 'public'); assert.strictEqual(publicKey.asymmetricKeyType, 'dsa'); assert.deepStrictEqual(publicKey.asymmetricKeyDetails, { - modulusLength: common.hasOpenSSL3 ? 2048 : 512, + modulusLength: hasOpenSSL3 ? 2048 : 512, divisorLength: 256 }); assert.strictEqual(privateKey.type, 'private'); assert.strictEqual(privateKey.asymmetricKeyType, 'dsa'); assert.deepStrictEqual(privateKey.asymmetricKeyDetails, { - modulusLength: common.hasOpenSSL3 ? 2048 : 512, + modulusLength: hasOpenSSL3 ? 2048 : 512, divisorLength: 256 }); })); diff --git a/test/parallel/test-crypto-keygen-async-dsa.js b/test/parallel/test-crypto-keygen-async-dsa.js index 048c0ce6fb92ef..41968d8cc23365 100644 --- a/test/parallel/test-crypto-keygen-async-dsa.js +++ b/test/parallel/test-crypto-keygen-async-dsa.js @@ -14,6 +14,8 @@ const { spkiExp, } = require('../common/crypto'); +const { hasOpenSSL3 } = require('../common/crypto'); + // Test async DSA key generation. { const privateKeyEncoding = { @@ -22,7 +24,7 @@ const { }; generateKeyPair('dsa', { - modulusLength: common.hasOpenSSL3 ? 2048 : 512, + modulusLength: hasOpenSSL3 ? 2048 : 512, divisorLength: 256, publicKeyEncoding: { type: 'spki', @@ -39,8 +41,8 @@ const { // The private key is DER-encoded. assert(Buffer.isBuffer(privateKeyDER)); - assertApproximateSize(publicKey, common.hasOpenSSL3 ? 1194 : 440); - assertApproximateSize(privateKeyDER, common.hasOpenSSL3 ? 721 : 336); + assertApproximateSize(publicKey, hasOpenSSL3 ? 1194 : 440); + assertApproximateSize(privateKeyDER, hasOpenSSL3 ? 721 : 336); // Since the private key is encrypted, signing shouldn't work anymore. assert.throws(() => { diff --git a/test/parallel/test-crypto-keygen-async-explicit-elliptic-curve-encrypted-p256.js b/test/parallel/test-crypto-keygen-async-explicit-elliptic-curve-encrypted-p256.js index 553674774571d3..55aa3831c4233b 100644 --- a/test/parallel/test-crypto-keygen-async-explicit-elliptic-curve-encrypted-p256.js +++ b/test/parallel/test-crypto-keygen-async-explicit-elliptic-curve-encrypted-p256.js @@ -14,6 +14,8 @@ const { pkcs8EncExp, } = require('../common/crypto'); +const { hasOpenSSL3 } = require('../common/crypto'); + // Test async elliptic curve key generation, e.g. for ECDSA, with an encrypted // private key with paramEncoding explicit. { @@ -38,7 +40,7 @@ const { // Since the private key is encrypted, signing shouldn't work anymore. assert.throws(() => testSignVerify(publicKey, privateKey), - common.hasOpenSSL3 ? { + hasOpenSSL3 ? { message: 'error:07880109:common libcrypto ' + 'routines::interrupted or cancelled' } : { diff --git a/test/parallel/test-crypto-keygen-async-explicit-elliptic-curve-encrypted.js.js b/test/parallel/test-crypto-keygen-async-explicit-elliptic-curve-encrypted.js.js index 79a132eed0b854..8a55d4338bc72f 100644 --- a/test/parallel/test-crypto-keygen-async-explicit-elliptic-curve-encrypted.js.js +++ b/test/parallel/test-crypto-keygen-async-explicit-elliptic-curve-encrypted.js.js @@ -12,6 +12,7 @@ const { testSignVerify, spkiExp, sec1EncExp, + hasOpenSSL3, } = require('../common/crypto'); { @@ -38,7 +39,7 @@ const { // Since the private key is encrypted, signing shouldn't work anymore. assert.throws(() => testSignVerify(publicKey, privateKey), - common.hasOpenSSL3 ? { + hasOpenSSL3 ? { message: 'error:07880109:common libcrypto ' + 'routines::interrupted or cancelled' } : { diff --git a/test/parallel/test-crypto-keygen-async-named-elliptic-curve-encrypted-p256.js b/test/parallel/test-crypto-keygen-async-named-elliptic-curve-encrypted-p256.js index 5e7d1a6c9b6611..4c11401d0fc516 100644 --- a/test/parallel/test-crypto-keygen-async-named-elliptic-curve-encrypted-p256.js +++ b/test/parallel/test-crypto-keygen-async-named-elliptic-curve-encrypted-p256.js @@ -12,6 +12,7 @@ const { testSignVerify, spkiExp, pkcs8EncExp, + hasOpenSSL3, } = require('../common/crypto'); // Test async elliptic curve key generation, e.g. for ECDSA, with an encrypted @@ -38,7 +39,7 @@ const { // Since the private key is encrypted, signing shouldn't work anymore. assert.throws(() => testSignVerify(publicKey, privateKey), - common.hasOpenSSL3 ? { + hasOpenSSL3 ? { message: 'error:07880109:common libcrypto ' + 'routines::interrupted or cancelled' } : { diff --git a/test/parallel/test-crypto-keygen-async-named-elliptic-curve-encrypted.js b/test/parallel/test-crypto-keygen-async-named-elliptic-curve-encrypted.js index 1cc93d0a794931..0503ff74787f37 100644 --- a/test/parallel/test-crypto-keygen-async-named-elliptic-curve-encrypted.js +++ b/test/parallel/test-crypto-keygen-async-named-elliptic-curve-encrypted.js @@ -12,6 +12,7 @@ const { testSignVerify, spkiExp, sec1EncExp, + hasOpenSSL3, } = require('../common/crypto'); { @@ -38,7 +39,7 @@ const { // Since the private key is encrypted, signing shouldn't work anymore. assert.throws(() => testSignVerify(publicKey, privateKey), - common.hasOpenSSL3 ? { + hasOpenSSL3 ? { message: 'error:07880109:common libcrypto ' + 'routines::interrupted or cancelled' } : { diff --git a/test/parallel/test-crypto-keygen-async-rsa.js b/test/parallel/test-crypto-keygen-async-rsa.js index f4a83809dc73c7..c80d7d33492923 100644 --- a/test/parallel/test-crypto-keygen-async-rsa.js +++ b/test/parallel/test-crypto-keygen-async-rsa.js @@ -13,6 +13,7 @@ const { testEncryptDecrypt, testSignVerify, pkcs1EncExp, + hasOpenSSL3, } = require('../common/crypto'); // Test async RSA key generation with an encrypted private key. @@ -43,7 +44,7 @@ const { type: 'pkcs1', format: 'der', }; - const expectedError = common.hasOpenSSL3 ? { + const expectedError = hasOpenSSL3 ? { name: 'Error', message: 'error:07880109:common libcrypto routines::interrupted or ' + 'cancelled' diff --git a/test/parallel/test-crypto-keygen-bit-length.js b/test/parallel/test-crypto-keygen-bit-length.js index 08772ba2e496b8..63a80659bb2f53 100644 --- a/test/parallel/test-crypto-keygen-bit-length.js +++ b/test/parallel/test-crypto-keygen-bit-length.js @@ -8,6 +8,7 @@ const assert = require('assert'); const { generateKeyPair, } = require('crypto'); +const { hasOpenSSL3 } = require('../common/crypto'); // This tests check that generateKeyPair returns correct bit length in // KeyObject's asymmetricKeyDetails. @@ -27,7 +28,7 @@ const { assert.strictEqual(publicKey.asymmetricKeyDetails.modulusLength, 513); })); - if (common.hasOpenSSL3) { + if (hasOpenSSL3) { generateKeyPair('dsa', { modulusLength: 2049, divisorLength: 256, diff --git a/test/parallel/test-crypto-keygen-empty-passphrase-no-prompt.js b/test/parallel/test-crypto-keygen-empty-passphrase-no-prompt.js index 7679a492c3194c..cb873ff04748b7 100644 --- a/test/parallel/test-crypto-keygen-empty-passphrase-no-prompt.js +++ b/test/parallel/test-crypto-keygen-empty-passphrase-no-prompt.js @@ -11,6 +11,7 @@ const { } = require('crypto'); const { testSignVerify, + hasOpenSSL3, } = require('../common/crypto'); // Passing an empty passphrase string should not cause OpenSSL's default @@ -40,7 +41,7 @@ for (const type of ['pkcs1', 'pkcs8']) { // the key, and not specifying a passphrase should fail when decoding it. assert.throws(() => { return testSignVerify(publicKey, privateKey); - }, common.hasOpenSSL3 ? { + }, hasOpenSSL3 ? { name: 'Error', code: 'ERR_OSSL_CRYPTO_INTERRUPTED_OR_CANCELLED', message: 'error:07880109:common libcrypto routines::interrupted or cancelled' diff --git a/test/parallel/test-crypto-keygen-missing-oid.js b/test/parallel/test-crypto-keygen-missing-oid.js index f7fefe13848d4b..1e4f309292eb47 100644 --- a/test/parallel/test-crypto-keygen-missing-oid.js +++ b/test/parallel/test-crypto-keygen-missing-oid.js @@ -11,6 +11,8 @@ const { getCurves, } = require('crypto'); +const { hasOpenSSL3 } = require('../common/crypto'); + // This test creates EC key pairs on curves without associated OIDs. // Specifying a key encoding should not crash. { @@ -20,7 +22,7 @@ const { continue; const expectedErrorCode = - common.hasOpenSSL3 ? 'ERR_OSSL_MISSING_OID' : 'ERR_OSSL_EC_MISSING_OID'; + hasOpenSSL3 ? 'ERR_OSSL_MISSING_OID' : 'ERR_OSSL_EC_MISSING_OID'; const params = { namedCurve, publicKeyEncoding: { diff --git a/test/parallel/test-crypto-keygen.js b/test/parallel/test-crypto-keygen.js index b09ca9e7c531ea..edaee845075668 100644 --- a/test/parallel/test-crypto-keygen.js +++ b/test/parallel/test-crypto-keygen.js @@ -14,6 +14,7 @@ const { } = require('crypto'); const { inspect } = require('util'); +const { hasOpenSSL3 } = require('../common/crypto'); // Test invalid parameter encoding. { @@ -351,7 +352,7 @@ const { inspect } = require('util'); publicExponent }, common.mustCall((err) => { assert.strictEqual(err.name, 'Error'); - assert.match(err.message, common.hasOpenSSL3 ? /exponent/ : /bad e value/); + assert.match(err.message, hasOpenSSL3 ? /exponent/ : /bad e value/); })); } } diff --git a/test/parallel/test-crypto-no-algorithm.js b/test/parallel/test-crypto-no-algorithm.js index 37db38cf613b65..06124e3d465e41 100644 --- a/test/parallel/test-crypto-no-algorithm.js +++ b/test/parallel/test-crypto-no-algorithm.js @@ -4,7 +4,9 @@ const common = require('../common'); if (!common.hasCrypto) common.skip('missing crypto'); -if (!common.hasOpenSSL3) +const { hasOpenSSL3 } = require('../common/crypto'); + +if (!hasOpenSSL3) common.skip('this test requires OpenSSL 3.x'); const assert = require('node:assert/strict'); diff --git a/test/parallel/test-crypto-oneshot-hash.js b/test/parallel/test-crypto-oneshot-hash.js index 69051c43d9e882..861aded5dd3f60 100644 --- a/test/parallel/test-crypto-oneshot-hash.js +++ b/test/parallel/test-crypto-oneshot-hash.js @@ -8,6 +8,7 @@ if (!common.hasCrypto) const assert = require('assert'); const crypto = require('crypto'); const fixtures = require('../common/fixtures'); +const { hasOpenSSL } = require('../common/crypto'); const fs = require('fs'); // Test errors for invalid arguments. @@ -32,7 +33,7 @@ const input = fs.readFileSync(fixtures.path('utf8_test_text.txt')); for (const method of methods) { // Skip failing tests on OpenSSL 3.4.0 - if (method.startsWith('shake') && common.hasOpenSSL(3, 4)) + if (method.startsWith('shake') && hasOpenSSL(3, 4)) continue; for (const outputEncoding of ['buffer', 'hex', 'base64', undefined]) { const oldDigest = crypto.createHash(method).update(input).digest(outputEncoding || 'hex'); diff --git a/test/parallel/test-crypto-padding.js b/test/parallel/test-crypto-padding.js index f1f14b472997e7..48cd1ed4df61aa 100644 --- a/test/parallel/test-crypto-padding.js +++ b/test/parallel/test-crypto-padding.js @@ -26,6 +26,7 @@ if (!common.hasCrypto) const assert = require('assert'); const crypto = require('crypto'); +const { hasOpenSSL3 } = require('../common/crypto'); // Input data. const ODD_LENGTH_PLAIN = 'Hello node world!'; @@ -82,7 +83,7 @@ assert.strictEqual(enc(EVEN_LENGTH_PLAIN, true), EVEN_LENGTH_ENCRYPTED); assert.throws(function() { // Input must have block length %. enc(ODD_LENGTH_PLAIN, false); -}, common.hasOpenSSL3 ? { +}, hasOpenSSL3 ? { message: 'error:1C80006B:Provider routines::wrong final block length', code: 'ERR_OSSL_WRONG_FINAL_BLOCK_LENGTH', reason: 'wrong final block length', @@ -109,7 +110,7 @@ assert.strictEqual(dec(EVEN_LENGTH_ENCRYPTED, false).length, 48); assert.throws(function() { // Must have at least 1 byte of padding (PKCS): assert.strictEqual(dec(EVEN_LENGTH_ENCRYPTED_NOPAD, true), EVEN_LENGTH_PLAIN); -}, common.hasOpenSSL3 ? { +}, hasOpenSSL3 ? { message: 'error:1C800064:Provider routines::bad decrypt', reason: 'bad decrypt', code: 'ERR_OSSL_BAD_DECRYPT', diff --git a/test/parallel/test-crypto-pbkdf2.js b/test/parallel/test-crypto-pbkdf2.js index 1f8e6a81f300e7..efd8d6eaf0d640 100644 --- a/test/parallel/test-crypto-pbkdf2.js +++ b/test/parallel/test-crypto-pbkdf2.js @@ -5,6 +5,7 @@ if (!common.hasCrypto) const assert = require('assert'); const crypto = require('crypto'); +const { hasOpenSSL3 } = require('../common/crypto'); function runPBKDF2(password, salt, iterations, keylen, hash) { const syncResult = @@ -219,7 +220,7 @@ assert.throws( } ); -if (!common.hasOpenSSL3) { +if (!hasOpenSSL3) { const kNotPBKDF2Supported = ['shake128', 'shake256']; crypto.getHashes() .filter((hash) => !kNotPBKDF2Supported.includes(hash)) diff --git a/test/parallel/test-crypto-private-decrypt-gh32240.js b/test/parallel/test-crypto-private-decrypt-gh32240.js index e88227a215ba4f..1ff5b565d6d5f4 100644 --- a/test/parallel/test-crypto-private-decrypt-gh32240.js +++ b/test/parallel/test-crypto-private-decrypt-gh32240.js @@ -14,6 +14,8 @@ const { privateDecrypt, } = require('crypto'); +const { hasOpenSSL3 } = require('../common/crypto'); + const pair = generateKeyPairSync('rsa', { modulusLength: 512 }); const expected = Buffer.from('shibboleth'); @@ -34,7 +36,7 @@ function decrypt(key) { } decrypt(pkey); -assert.throws(() => decrypt(pkeyEncrypted), common.hasOpenSSL3 ? +assert.throws(() => decrypt(pkeyEncrypted), hasOpenSSL3 ? { message: 'error:07880109:common libcrypto routines::interrupted or ' + 'cancelled' } : { code: 'ERR_MISSING_PASSPHRASE' }); diff --git a/test/parallel/test-crypto-publicDecrypt-fails-first-time.js b/test/parallel/test-crypto-publicDecrypt-fails-first-time.js index a60b87dbf65229..1d64e08920c63b 100644 --- a/test/parallel/test-crypto-publicDecrypt-fails-first-time.js +++ b/test/parallel/test-crypto-publicDecrypt-fails-first-time.js @@ -3,11 +3,15 @@ const common = require('../common'); // Test for https://github.com/nodejs/node/issues/40814 -if (!common.hasCrypto) +if (!common.hasCrypto) { common.skip('missing crypto'); +} -if (!common.hasOpenSSL3) +const { hasOpenSSL3 } = require('../common/crypto'); + +if (!hasOpenSSL3) { common.skip('only openssl3'); // https://github.com/nodejs/node/pull/42793#issuecomment-1107491901 +} const assert = require('assert'); const crypto = require('crypto'); diff --git a/test/parallel/test-crypto-rsa-dsa.js b/test/parallel/test-crypto-rsa-dsa.js index 5f4fafdfffbf72..dcd5045daaf58c 100644 --- a/test/parallel/test-crypto-rsa-dsa.js +++ b/test/parallel/test-crypto-rsa-dsa.js @@ -9,6 +9,7 @@ const crypto = require('crypto'); const constants = crypto.constants; const fixtures = require('../common/fixtures'); +const { hasOpenSSL3 } = require('../common/crypto'); // Test certificates const certPem = fixtures.readKey('rsa_cert.crt'); @@ -36,11 +37,11 @@ const openssl1DecryptError = { library: 'digital envelope routines', }; -const decryptError = common.hasOpenSSL3 ? +const decryptError = hasOpenSSL3 ? { message: 'error:1C800064:Provider routines::bad decrypt' } : openssl1DecryptError; -const decryptPrivateKeyError = common.hasOpenSSL3 ? { +const decryptPrivateKeyError = hasOpenSSL3 ? { message: 'error:1C800064:Provider routines::bad decrypt', } : openssl1DecryptError; @@ -146,7 +147,7 @@ function getBufferCopy(buf) { // Now with RSA_NO_PADDING. Plaintext needs to match key size. // OpenSSL 3.x has a rsa_check_padding that will cause an error if // RSA_NO_PADDING is used. - if (!common.hasOpenSSL3) { + if (!hasOpenSSL3) { { const plaintext = 'x'.repeat(rsaKeySize / 8); encryptedBuffer = crypto.privateEncrypt({ diff --git a/test/parallel/test-crypto-secure-heap.js b/test/parallel/test-crypto-secure-heap.js index 0e5788f00e4a44..c20b01a91a9840 100644 --- a/test/parallel/test-crypto-secure-heap.js +++ b/test/parallel/test-crypto-secure-heap.js @@ -1,21 +1,26 @@ 'use strict'; const common = require('../common'); -if (!common.hasCrypto) +if (!common.hasCrypto) { common.skip('missing crypto'); +} -if (common.isWindows) +if (common.isWindows) { common.skip('Not supported on Windows'); +} -if (common.isASan) +if (common.isASan) { common.skip('ASan does not play well with secure heap allocations'); +} const assert = require('assert'); const { fork } = require('child_process'); const fixtures = require('../common/fixtures'); +const { hasOpenSSL3 } = require('../common/crypto'); const { secureHeapUsed, createDiffieHellman, + getFips, } = require('crypto'); if (process.argv[2] === 'child') { @@ -29,7 +34,7 @@ if (process.argv[2] === 'child') { assert.strictEqual(a.used, 0); { - const size = common.hasFipsCrypto || common.hasOpenSSL3 ? 1024 : 256; + const size = getFips() || hasOpenSSL3 ? 1024 : 256; const dh1 = createDiffieHellman(size); const p1 = dh1.getPrime('buffer'); const dh2 = createDiffieHellman(p1, 'buffer'); diff --git a/test/parallel/test-crypto-sign-verify.js b/test/parallel/test-crypto-sign-verify.js index 8a263ec3350f55..0589d60736e377 100644 --- a/test/parallel/test-crypto-sign-verify.js +++ b/test/parallel/test-crypto-sign-verify.js @@ -8,6 +8,10 @@ const fs = require('fs'); const exec = require('child_process').exec; const crypto = require('crypto'); const fixtures = require('../common/fixtures'); +const { + hasOpenSSL3, + opensslCli, +} = require('../common/crypto'); // Test certificates const certPem = fixtures.readKey('rsa_cert.crt'); @@ -62,7 +66,7 @@ const keySize = 2048; key: keyPem, padding: crypto.constants.RSA_PKCS1_OAEP_PADDING }); - }, { message: common.hasOpenSSL3 ? + }, { message: hasOpenSSL3 ? 'error:1C8000A5:Provider routines::illegal or unsupported padding mode' : 'bye, bye, error stack' }); @@ -340,7 +344,7 @@ assert.throws( key: keyPem, padding: crypto.constants.RSA_PKCS1_OAEP_PADDING }); - }, common.hasOpenSSL3 ? { + }, hasOpenSSL3 ? { code: 'ERR_OSSL_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE', message: /illegal or unsupported padding mode/, } : { @@ -599,8 +603,9 @@ assert.throws( // Note: this particular test *must* be the last in this file as it will exit // early if no openssl binary is found { - if (!common.opensslCli) + if (!opensslCli) { common.skip('node compiled without OpenSSL CLI.'); + } const pubfile = fixtures.path('keys', 'rsa_public_2048.pem'); const privkey = fixtures.readKey('rsa_private_2048.pem'); @@ -622,7 +627,7 @@ assert.throws( fs.writeFileSync(msgfile, msg); exec(...common.escapePOSIXShell`"${ - common.opensslCli}" dgst -sha256 -verify "${pubfile}" -signature "${ + opensslCli}" dgst -sha256 -verify "${pubfile}" -signature "${ sigfile}" -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:-2 "${msgfile }"`, common.mustCall((err, stdout, stderr) => { assert(stdout.includes('Verified OK')); diff --git a/test/parallel/test-crypto-stream.js b/test/parallel/test-crypto-stream.js index 008ab129f0e019..62be4eaf6edfb0 100644 --- a/test/parallel/test-crypto-stream.js +++ b/test/parallel/test-crypto-stream.js @@ -21,14 +21,16 @@ 'use strict'; const common = require('../common'); -if (!common.hasCrypto) +if (!common.hasCrypto) { common.skip('missing crypto'); +} const assert = require('assert'); const stream = require('stream'); const crypto = require('crypto'); +const { hasOpenSSL3 } = require('../common/crypto'); -if (!common.hasFipsCrypto) { +if (!crypto.getFips()) { // Small stream to buffer converter class Stream2buffer extends stream.Writable { constructor(callback) { @@ -71,7 +73,7 @@ const cipher = crypto.createCipheriv('aes-128-cbc', key, iv); const decipher = crypto.createDecipheriv('aes-128-cbc', badkey, iv); cipher.pipe(decipher) - .on('error', common.expectsError(common.hasOpenSSL3 ? { + .on('error', common.expectsError(hasOpenSSL3 ? { message: /bad decrypt/, library: 'Provider routines', reason: 'bad decrypt', diff --git a/test/parallel/test-crypto-x509.js b/test/parallel/test-crypto-x509.js index bd906c25b9ee19..f75e1d63470bfb 100644 --- a/test/parallel/test-crypto-x509.js +++ b/test/parallel/test-crypto-x509.js @@ -18,6 +18,7 @@ const { const assert = require('assert'); const fixtures = require('../common/fixtures'); +const { hasOpenSSL3 } = require('../common/crypto'); const { readFileSync } = require('fs'); const cert = readFileSync(fixtures.path('keys', 'agent1-cert.pem')); @@ -50,7 +51,7 @@ emailAddress=ry@tinyclouds.org`; let infoAccessCheck = `OCSP - URI:http://ocsp.nodejs.org/ CA Issuers - URI:http://ca.nodejs.org/ca.cert`; -if (!common.hasOpenSSL3) +if (!hasOpenSSL3) infoAccessCheck += '\n'; const der = Buffer.from( @@ -357,7 +358,7 @@ UcXd/5qu2GhokrKU2cPttU+XAN2Om6a0 const cert = new X509Certificate(certPem); assert.throws(() => cert.publicKey, { - message: common.hasOpenSSL3 ? /decode error/ : /wrong tag/, + message: hasOpenSSL3 ? /decode error/ : /wrong tag/, name: 'Error' }); diff --git a/test/parallel/test-crypto.js b/test/parallel/test-crypto.js index 4271121881379b..93644e016de447 100644 --- a/test/parallel/test-crypto.js +++ b/test/parallel/test-crypto.js @@ -29,6 +29,7 @@ const assert = require('assert'); const crypto = require('crypto'); const tls = require('tls'); const fixtures = require('../common/fixtures'); +const { hasOpenSSL3 } = require('../common/crypto'); // Test Certificates const certPfx = fixtures.readKey('rsa_cert.pfx'); @@ -208,9 +209,9 @@ assert.throws(() => { ].join('\n'); crypto.createSign('SHA256').update('test').sign(priv); }, (err) => { - if (!common.hasOpenSSL3) + if (!hasOpenSSL3) assert.ok(!('opensslErrorStack' in err)); - assert.throws(() => { throw err; }, common.hasOpenSSL3 ? { + assert.throws(() => { throw err; }, hasOpenSSL3 ? { name: 'Error', message: 'error:02000070:rsa routines::digest too big for rsa key', library: 'rsa routines', @@ -225,7 +226,7 @@ assert.throws(() => { return true; }); -if (!common.hasOpenSSL3) { +if (!hasOpenSSL3) { assert.throws(() => { // The correct header inside `rsa_private_pkcs8_bad.pem` should have been // -----BEGIN PRIVATE KEY----- and -----END PRIVATE KEY----- diff --git a/test/parallel/test-dsa-fips-invalid-key.js b/test/parallel/test-dsa-fips-invalid-key.js index 05cc1d143aca6e..3df51bfbed3517 100644 --- a/test/parallel/test-dsa-fips-invalid-key.js +++ b/test/parallel/test-dsa-fips-invalid-key.js @@ -1,12 +1,18 @@ 'use strict'; const common = require('../common'); + +if (!common.hasCrypto) { + common.skip('no crypto'); +} + const fixtures = require('../common/fixtures'); +const crypto = require('crypto'); -if (!common.hasFipsCrypto) +if (!crypto.getFips()) { common.skip('node compiled without FIPS OpenSSL.'); +} const assert = require('assert'); -const crypto = require('crypto'); const input = 'hello'; diff --git a/test/parallel/test-https-agent-session-eviction.js b/test/parallel/test-https-agent-session-eviction.js index e0986e53c1103b..6f88e81e9ff29d 100644 --- a/test/parallel/test-https-agent-session-eviction.js +++ b/test/parallel/test-https-agent-session-eviction.js @@ -2,10 +2,13 @@ 'use strict'; const common = require('../common'); -const { readKey } = require('../common/fixtures'); -if (!common.hasCrypto) +if (!common.hasCrypto) { common.skip('missing crypto'); +} + +const { readKey } = require('../common/fixtures'); +const { hasOpenSSL } = require('../common/crypto'); const https = require('https'); const { SSL_OP_NO_TICKET } = require('crypto').constants; @@ -56,7 +59,7 @@ function faultyServer(port) { function second(server, session) { const req = https.request({ port: server.address().port, - ciphers: (common.hasOpenSSL(3, 1) ? 'DEFAULT:@SECLEVEL=0' : 'DEFAULT'), + ciphers: (hasOpenSSL(3, 1) ? 'DEFAULT:@SECLEVEL=0' : 'DEFAULT'), rejectUnauthorized: false }, function(res) { res.resume(); diff --git a/test/parallel/test-https-client-renegotiation-limit.js b/test/parallel/test-https-client-renegotiation-limit.js index 35fcc6bfcc6e43..18a602d738c316 100644 --- a/test/parallel/test-https-client-renegotiation-limit.js +++ b/test/parallel/test-https-client-renegotiation-limit.js @@ -21,11 +21,15 @@ 'use strict'; const common = require('../common'); -if (!common.hasCrypto) +if (!common.hasCrypto) { common.skip('missing crypto'); +} + +const { opensslCli } = require('../common/crypto'); -if (!common.opensslCli) +if (!opensslCli) { common.skip('node compiled without OpenSSL CLI.'); +} const assert = require('assert'); const tls = require('tls'); diff --git a/test/parallel/test-https-foafssl.js b/test/parallel/test-https-foafssl.js index d6dde97a41da9c..df375e7d22201e 100644 --- a/test/parallel/test-https-foafssl.js +++ b/test/parallel/test-https-foafssl.js @@ -21,11 +21,15 @@ 'use strict'; const common = require('../common'); -if (!common.hasCrypto) +if (!common.hasCrypto) { common.skip('missing crypto'); +} -if (!common.opensslCli) +const { opensslCli } = require('../common/crypto'); + +if (!opensslCli) { common.skip('node compiled without OpenSSL CLI.'); +} const assert = require('assert'); const fixtures = require('../common/fixtures'); @@ -67,7 +71,7 @@ server.listen(0, function() { '-cert', fixtures.path('keys/rsa_cert_foafssl_b.crt'), '-key', fixtures.path('keys/rsa_private_b.pem')]; - const client = spawn(common.opensslCli, args); + const client = spawn(opensslCli, args); client.stdout.on('data', function(data) { console.log('response received'); diff --git a/test/parallel/test-process-env-allowed-flags-are-documented.js b/test/parallel/test-process-env-allowed-flags-are-documented.js index 3480b2c1482f17..730adb682ad7f1 100644 --- a/test/parallel/test-process-env-allowed-flags-are-documented.js +++ b/test/parallel/test-process-env-allowed-flags-are-documented.js @@ -5,6 +5,7 @@ const common = require('../common'); const assert = require('assert'); const fs = require('fs'); const path = require('path'); +const { hasOpenSSL3 } = require('../common/crypto'); const rootDir = path.resolve(__dirname, '..', '..'); const cliMd = path.join(rootDir, 'doc', 'api', 'cli.md'); @@ -43,7 +44,7 @@ for (const line of [...nodeOptionsLines, ...v8OptionsLines]) { } } -if (!common.hasOpenSSL3) { +if (!hasOpenSSL3) { documented.delete('--openssl-legacy-provider'); documented.delete('--openssl-shared-config'); } @@ -55,8 +56,8 @@ const conditionalOpts = [ filter: (opt) => { return [ '--openssl-config', - common.hasOpenSSL3 ? '--openssl-legacy-provider' : '', - common.hasOpenSSL3 ? '--openssl-shared-config' : '', + hasOpenSSL3 ? '--openssl-legacy-provider' : '', + hasOpenSSL3 ? '--openssl-shared-config' : '', '--tls-cipher-list', '--use-bundled-ca', '--use-openssl-ca', diff --git a/test/parallel/test-process-versions.js b/test/parallel/test-process-versions.js index 3b8af4b5b52526..0a2a4014f18d6b 100644 --- a/test/parallel/test-process-versions.js +++ b/test/parallel/test-process-versions.js @@ -85,11 +85,12 @@ assert.match(process.versions.modules, /^\d+$/); assert.match(process.versions.cjs_module_lexer, commonTemplate); if (common.hasCrypto) { + const { hasOpenSSL3 } = require('../common/crypto'); assert.match(process.versions.ncrypto, commonTemplate); if (process.config.variables.node_shared_openssl) { assert.ok(process.versions.openssl); } else { - const versionRegex = common.hasOpenSSL3 ? + const versionRegex = hasOpenSSL3 ? // The following also matches a development version of OpenSSL 3.x which // can be in the format '3.0.0-alpha4-dev'. This can be handy when // building and linking against the main development branch of OpenSSL. diff --git a/test/parallel/test-tls-alert-handling.js b/test/parallel/test-tls-alert-handling.js index b14438bc92d7e6..eec072796063dc 100644 --- a/test/parallel/test-tls-alert-handling.js +++ b/test/parallel/test-tls-alert-handling.js @@ -1,11 +1,19 @@ 'use strict'; const common = require('../common'); -if (!common.hasCrypto) +if (!common.hasCrypto) { common.skip('missing crypto'); +} + +const { + hasOpenSSL, + hasOpenSSL3, + opensslCli, +} = require('../common/crypto'); -if (!common.opensslCli) +if (!opensslCli) { common.skip('node compiled without OpenSSL CLI'); +} const assert = require('assert'); const net = require('net'); @@ -33,14 +41,14 @@ let iter = 0; const errorHandler = common.mustCall((err) => { let expectedErrorCode = 'ERR_SSL_WRONG_VERSION_NUMBER'; let expectedErrorReason = 'wrong version number'; - if (common.hasOpenSSL(3, 2)) { + if (hasOpenSSL(3, 2)) { expectedErrorCode = 'ERR_SSL_PACKET_LENGTH_TOO_LONG'; expectedErrorReason = 'packet length too long'; }; assert.strictEqual(err.code, expectedErrorCode); assert.strictEqual(err.library, 'SSL routines'); - if (!common.hasOpenSSL3) assert.strictEqual(err.function, 'ssl3_get_record'); + if (!hasOpenSSL3) assert.strictEqual(err.function, 'ssl3_get_record'); assert.strictEqual(err.reason, expectedErrorReason); errorReceived = true; if (canCloseServer()) @@ -96,13 +104,13 @@ function sendBADTLSRecord() { client.on('error', common.mustCall((err) => { let expectedErrorCode = 'ERR_SSL_TLSV1_ALERT_PROTOCOL_VERSION'; let expectedErrorReason = 'tlsv1 alert protocol version'; - if (common.hasOpenSSL(3, 2)) { + if (hasOpenSSL(3, 2)) { expectedErrorCode = 'ERR_SSL_TLSV1_ALERT_RECORD_OVERFLOW'; expectedErrorReason = 'tlsv1 alert record overflow'; } assert.strictEqual(err.code, expectedErrorCode); assert.strictEqual(err.library, 'SSL routines'); - if (!common.hasOpenSSL3) + if (!hasOpenSSL3) assert.strictEqual(err.function, 'ssl3_read_bytes'); assert.strictEqual(err.reason, expectedErrorReason); })); diff --git a/test/parallel/test-tls-alert.js b/test/parallel/test-tls-alert.js index e6aaaedfe59d72..23c92e7293458f 100644 --- a/test/parallel/test-tls-alert.js +++ b/test/parallel/test-tls-alert.js @@ -21,11 +21,18 @@ 'use strict'; const common = require('../common'); -if (!common.hasCrypto) +if (!common.hasCrypto) { common.skip('missing crypto'); +} + +const { + hasOpenSSL, + opensslCli, +} = require('../common/crypto'); -if (!common.opensslCli) +if (!opensslCli) { common.skip('node compiled without OpenSSL CLI.'); +} const assert = require('assert'); const { execFile } = require('child_process'); @@ -42,10 +49,10 @@ const server = tls.Server({ cert: loadPEM('agent2-cert') }, null).listen(0, common.mustCall(() => { const args = ['s_client', '-quiet', '-tls1_1', - '-cipher', (common.hasOpenSSL(3, 1) ? 'DEFAULT:@SECLEVEL=0' : 'DEFAULT'), + '-cipher', (hasOpenSSL(3, 1) ? 'DEFAULT:@SECLEVEL=0' : 'DEFAULT'), '-connect', `127.0.0.1:${server.address().port}`]; - execFile(common.opensslCli, args, common.mustCall((err, _, stderr) => { + execFile(opensslCli, args, common.mustCall((err, _, stderr) => { assert.strictEqual(err.code, 1); assert.match(stderr, /SSL alert number 70/); server.close(); diff --git a/test/parallel/test-tls-alpn-server-client.js b/test/parallel/test-tls-alpn-server-client.js index 8f1a4b8e439aab..b7cd2806471e67 100644 --- a/test/parallel/test-tls-alpn-server-client.js +++ b/test/parallel/test-tls-alpn-server-client.js @@ -1,8 +1,9 @@ 'use strict'; const common = require('../common'); -if (!common.hasCrypto) +if (!common.hasCrypto) { common.skip('missing crypto'); +} const assert = require('assert'); const { spawn } = require('child_process'); @@ -198,7 +199,7 @@ function TestFatalAlert() { // OpenSSL's s_client should output the TLS alert number, which is 120 // for the 'no_application_protocol' alert. - const { opensslCli } = common; + const { opensslCli } = require('../common/crypto'); if (opensslCli) { const addr = `${serverIP}:${port}`; let stderr = ''; diff --git a/test/parallel/test-tls-cert-ext-encoding.js b/test/parallel/test-tls-cert-ext-encoding.js index 4556b5791851c5..154e0cdcf02294 100644 --- a/test/parallel/test-tls-cert-ext-encoding.js +++ b/test/parallel/test-tls-cert-ext-encoding.js @@ -3,7 +3,9 @@ const common = require('../common'); if (!common.hasCrypto) common.skip('missing crypto'); -if (common.hasOpenSSL3) +const { hasOpenSSL3 } = require('../common/crypto'); + +if (hasOpenSSL3) // TODO(danbev) This test fails with the following error: // error:0D00008F:asn1 encoding routines::no matching choice type // diff --git a/test/parallel/test-tls-client-auth.js b/test/parallel/test-tls-client-auth.js index de4c8f038ec073..b347c0a88df571 100644 --- a/test/parallel/test-tls-client-auth.js +++ b/test/parallel/test-tls-client-auth.js @@ -3,6 +3,11 @@ const common = require('../common'); const fixtures = require('../common/fixtures'); +if (!common.hasCrypto) { + common.skip('missing crypto'); +} +const { hasOpenSSL } = require('../common/crypto'); + const { assert, connect, keys, tls } = require(fixtures.path('tls-connect')); @@ -79,7 +84,7 @@ connect({ }, function(err, pair, cleanup) { assert.strictEqual(pair.server.err.code, 'ERR_SSL_PEER_DID_NOT_RETURN_A_CERTIFICATE'); - const expectedErr = common.hasOpenSSL(3, 2) ? + const expectedErr = hasOpenSSL(3, 2) ? 'ERR_SSL_SSL/TLS_ALERT_HANDSHAKE_FAILURE' : 'ERR_SSL_SSLV3_ALERT_HANDSHAKE_FAILURE'; assert.strictEqual(pair.client.err.code, expectedErr); diff --git a/test/parallel/test-tls-client-getephemeralkeyinfo.js b/test/parallel/test-tls-client-getephemeralkeyinfo.js index 0bacd8702fc650..0f132c565e4400 100644 --- a/test/parallel/test-tls-client-getephemeralkeyinfo.js +++ b/test/parallel/test-tls-client-getephemeralkeyinfo.js @@ -3,6 +3,7 @@ const common = require('../common'); if (!common.hasCrypto) common.skip('missing crypto'); const fixtures = require('../common/fixtures'); +const { hasOpenSSL } = require('../common/crypto'); const assert = require('assert'); const { X509Certificate } = require('crypto'); @@ -69,7 +70,7 @@ function test(size, type, name, cipher) { test(undefined, undefined, undefined, 'AES256-SHA256'); test('auto', 'DH', undefined, 'DHE-RSA-AES256-GCM-SHA384'); -if (!common.hasOpenSSL(3, 2)) { +if (!hasOpenSSL(3, 2)) { test(1024, 'DH', undefined, 'DHE-RSA-AES256-GCM-SHA384'); } else { test(3072, 'DH', undefined, 'DHE-RSA-AES256-GCM-SHA384'); diff --git a/test/parallel/test-tls-client-mindhsize.js b/test/parallel/test-tls-client-mindhsize.js index 15c086842e1e4a..1ab5b5fe1bffd7 100644 --- a/test/parallel/test-tls-client-mindhsize.js +++ b/test/parallel/test-tls-client-mindhsize.js @@ -3,6 +3,7 @@ const common = require('../common'); if (!common.hasCrypto) common.skip('missing crypto'); +const { hasOpenSSL } = require('../common/crypto'); const assert = require('assert'); const tls = require('tls'); const fixtures = require('../common/fixtures'); @@ -38,7 +39,7 @@ function test(size, err, next) { // Client set minimum DH parameter size to 2048 or 3072 bits // so that it fails when it makes a connection to the tls // server where is too small - const minDHSize = common.hasOpenSSL(3, 2) ? 3072 : 2048; + const minDHSize = hasOpenSSL(3, 2) ? 3072 : 2048; const client = tls.connect({ minDHSize: minDHSize, port: this.address().port, @@ -76,7 +77,7 @@ function testDHE3072() { test(3072, false, null); } -if (common.hasOpenSSL(3, 2)) { +if (hasOpenSSL(3, 2)) { // Minimum size for OpenSSL 3.2 is 2048 by default testDHE2048(true, testDHE3072); } else { diff --git a/test/parallel/test-tls-client-renegotiation-13.js b/test/parallel/test-tls-client-renegotiation-13.js index a32baed0249a0a..38a72fb525b430 100644 --- a/test/parallel/test-tls-client-renegotiation-13.js +++ b/test/parallel/test-tls-client-renegotiation-13.js @@ -1,6 +1,12 @@ 'use strict'; const common = require('../common'); + +if (!common.hasCrypto) { + common.skip('missing crypto'); +} +const { hasOpenSSL3 } = require('../common/crypto'); + const fixtures = require('../common/fixtures'); // Confirm that for TLSv1.3, renegotiate() is disallowed. @@ -29,7 +35,7 @@ connect({ const ok = client.renegotiate({}, common.mustCall((err) => { assert.throws(() => { throw err; }, { - message: common.hasOpenSSL3 ? + message: hasOpenSSL3 ? 'error:0A00010A:SSL routines::wrong ssl version' : 'error:1420410A:SSL routines:SSL_renegotiate:wrong ssl version', code: 'ERR_SSL_WRONG_SSL_VERSION', diff --git a/test/parallel/test-tls-client-renegotiation-limit.js b/test/parallel/test-tls-client-renegotiation-limit.js index 71d7a85bae468b..b35140e8964ac1 100644 --- a/test/parallel/test-tls-client-renegotiation-limit.js +++ b/test/parallel/test-tls-client-renegotiation-limit.js @@ -21,11 +21,15 @@ 'use strict'; const common = require('../common'); -if (!common.hasCrypto) +if (!common.hasCrypto) { common.skip('missing crypto'); +} + +const { opensslCli } = require('../common/crypto'); -if (!common.opensslCli) +if (!opensslCli) { common.skip('node compiled without OpenSSL CLI.'); +} const assert = require('assert'); const tls = require('tls'); diff --git a/test/parallel/test-tls-dhe.js b/test/parallel/test-tls-dhe.js index 21739ce42428eb..25b58191e1d413 100644 --- a/test/parallel/test-tls-dhe.js +++ b/test/parallel/test-tls-dhe.js @@ -22,11 +22,18 @@ 'use strict'; const common = require('../common'); -if (!common.hasCrypto) +if (!common.hasCrypto) { common.skip('missing crypto'); +} + +const { + hasOpenSSL, + opensslCli, +} = require('../common/crypto'); -if (!common.opensslCli) +if (!opensslCli) { common.skip('missing openssl-cli'); +} const assert = require('assert'); const { X509Certificate } = require('crypto'); @@ -43,7 +50,7 @@ const dheCipher = 'DHE-RSA-AES128-SHA256'; const ecdheCipher = 'ECDHE-RSA-AES128-SHA256'; const ciphers = `${dheCipher}:${ecdheCipher}`; -if (!common.hasOpenSSL(3, 2)) { +if (!hasOpenSSL(3, 2)) { // Test will emit a warning because the DH parameter size is < 2048 bits // when the test is run on versions lower than OpenSSL32 common.expectWarning('SecurityWarning', @@ -70,7 +77,7 @@ function test(dhparam, keylen, expectedCipher) { const args = ['s_client', '-connect', `127.0.0.1:${server.address().port}`, '-cipher', `${ciphers}:@SECLEVEL=1`]; - execFile(common.opensslCli, args, common.mustSucceed((stdout) => { + execFile(opensslCli, args, common.mustSucceed((stdout) => { assert(keylen === null || stdout.includes(`Server Temp Key: DH, ${keylen} bits`)); assert(stdout.includes(`Cipher : ${expectedCipher}`)); @@ -107,7 +114,7 @@ function testCustomParam(keylen, expectedCipher) { }, /DH parameter is less than 1024 bits/); // Custom DHE parameters are supported (but discouraged). - if (!common.hasOpenSSL(3, 2)) { + if (!hasOpenSSL(3, 2)) { await testCustomParam(1024, dheCipher); } else { await testCustomParam(3072, dheCipher); diff --git a/test/parallel/test-tls-ecdh-auto.js b/test/parallel/test-tls-ecdh-auto.js index 11c588d8ac8ce1..adc7817b729aa8 100644 --- a/test/parallel/test-tls-ecdh-auto.js +++ b/test/parallel/test-tls-ecdh-auto.js @@ -4,11 +4,15 @@ const common = require('../common'); // This test ensures that the value "auto" on ecdhCurve option is // supported to enable automatic curve selection in TLS server. -if (!common.hasCrypto) +if (!common.hasCrypto) { common.skip('missing crypto'); +} + +const { opensslCli } = require('../common/crypto'); -if (!common.opensslCli) +if (!opensslCli) { common.skip('missing openssl-cli'); +} const assert = require('assert'); const tls = require('tls'); @@ -36,7 +40,7 @@ const server = tls.createServer(options, (conn) => { '-cipher', `${options.ciphers}`, '-connect', `127.0.0.1:${server.address().port}`]; - execFile(common.opensslCli, args, common.mustSucceed((stdout) => { + execFile(opensslCli, args, common.mustSucceed((stdout) => { assert(stdout.includes(reply)); server.close(); })); diff --git a/test/parallel/test-tls-ecdh-multiple.js b/test/parallel/test-tls-ecdh-multiple.js index 5bf119f48bacad..957f8e0407a6de 100644 --- a/test/parallel/test-tls-ecdh-multiple.js +++ b/test/parallel/test-tls-ecdh-multiple.js @@ -4,11 +4,16 @@ const common = require('../common'); // This test ensures that ecdhCurve option of TLS server supports colon // separated ECDH curve names as value. -if (!common.hasCrypto) +if (!common.hasCrypto) { common.skip('missing crypto'); +} + +const { opensslCli } = require('../common/crypto'); +const crypto = require('crypto'); -if (!common.opensslCli) +if (!opensslCli) { common.skip('missing openssl-cli'); +} const assert = require('assert'); const tls = require('tls'); @@ -36,7 +41,7 @@ const server = tls.createServer(options, (conn) => { '-cipher', `${options.ciphers}`, '-connect', `127.0.0.1:${server.address().port}`]; - execFile(common.opensslCli, args, common.mustSucceed((stdout) => { + execFile(opensslCli, args, common.mustSucceed((stdout) => { assert(stdout.includes(reply)); server.close(); })); @@ -51,8 +56,9 @@ const server = tls.createServer(options, (conn) => { ]; // Brainpool is not supported in FIPS mode. - if (common.hasFipsCrypto) + if (crypto.getFips()) { unsupportedCurves.push('brainpoolP256r1'); + } unsupportedCurves.forEach((ecdhCurve) => { assert.throws(() => tls.createServer({ ecdhCurve }), diff --git a/test/parallel/test-tls-ecdh.js b/test/parallel/test-tls-ecdh.js index 276b713f5ecf70..4d45e7f024586e 100644 --- a/test/parallel/test-tls-ecdh.js +++ b/test/parallel/test-tls-ecdh.js @@ -23,11 +23,15 @@ const common = require('../common'); const fixtures = require('../common/fixtures'); -if (!common.hasCrypto) +if (!common.hasCrypto) { common.skip('missing crypto'); +} -if (!common.opensslCli) +const { opensslCli } = require('../common/crypto'); + +if (!opensslCli) { common.skip('missing openssl-cli'); +} const assert = require('assert'); const tls = require('tls'); @@ -49,7 +53,7 @@ const server = tls.createServer(options, common.mustCall(function(conn) { })); server.listen(0, '127.0.0.1', common.mustCall(function() { - const cmd = common.escapePOSIXShell`"${common.opensslCli}" s_client -cipher ${ + const cmd = common.escapePOSIXShell`"${opensslCli}" s_client -cipher ${ options.ciphers} -connect 127.0.0.1:${this.address().port}`; exec(...cmd, common.mustSucceed((stdout, stderr) => { diff --git a/test/parallel/test-tls-empty-sni-context.js b/test/parallel/test-tls-empty-sni-context.js index 093e5cca712d2c..79f1ddd341d938 100644 --- a/test/parallel/test-tls-empty-sni-context.js +++ b/test/parallel/test-tls-empty-sni-context.js @@ -3,7 +3,7 @@ const common = require('../common'); if (!common.hasCrypto) common.skip('missing crypto'); - +const { hasOpenSSL } = require('../common/crypto'); const assert = require('assert'); const tls = require('tls'); @@ -26,7 +26,7 @@ const server = tls.createServer(options, (c) => { }, common.mustNotCall()); c.on('error', common.mustCall((err) => { - const expectedErr = common.hasOpenSSL(3, 2) ? + const expectedErr = hasOpenSSL(3, 2) ? 'ERR_SSL_SSL/TLS_ALERT_HANDSHAKE_FAILURE' : 'ERR_SSL_SSLV3_ALERT_HANDSHAKE_FAILURE'; assert.strictEqual(err.code, expectedErr); })); diff --git a/test/parallel/test-tls-getprotocol.js b/test/parallel/test-tls-getprotocol.js index a9c8775e2f112f..b1eab88fd6517e 100644 --- a/test/parallel/test-tls-getprotocol.js +++ b/test/parallel/test-tls-getprotocol.js @@ -3,6 +3,8 @@ const common = require('../common'); if (!common.hasCrypto) common.skip('missing crypto'); +const { hasOpenSSL } = require('../common/crypto'); + // This test ensures that `getProtocol` returns the right protocol // from a TLS connection @@ -14,11 +16,11 @@ const clientConfigs = [ { secureProtocol: 'TLSv1_method', version: 'TLSv1', - ciphers: (common.hasOpenSSL(3, 1) ? 'DEFAULT:@SECLEVEL=0' : 'DEFAULT') + ciphers: (hasOpenSSL(3, 1) ? 'DEFAULT:@SECLEVEL=0' : 'DEFAULT') }, { secureProtocol: 'TLSv1_1_method', version: 'TLSv1.1', - ciphers: (common.hasOpenSSL(3, 1) ? 'DEFAULT:@SECLEVEL=0' : 'DEFAULT') + ciphers: (hasOpenSSL(3, 1) ? 'DEFAULT:@SECLEVEL=0' : 'DEFAULT') }, { secureProtocol: 'TLSv1_2_method', version: 'TLSv1.2' diff --git a/test/parallel/test-tls-junk-server.js b/test/parallel/test-tls-junk-server.js index cc520383ede45f..0e536a66884e94 100644 --- a/test/parallel/test-tls-junk-server.js +++ b/test/parallel/test-tls-junk-server.js @@ -1,8 +1,11 @@ 'use strict'; const common = require('../common'); -if (!common.hasCrypto) +if (!common.hasCrypto) { common.skip('missing crypto'); +} + +const { hasOpenSSL } = require('../common/crypto'); const assert = require('assert'); const https = require('https'); @@ -21,7 +24,7 @@ server.listen(0, function() { req.end(); let expectedErrorMessage = new RegExp('wrong version number'); - if (common.hasOpenSSL(3, 2)) { + if (hasOpenSSL(3, 2)) { expectedErrorMessage = new RegExp('packet length too long'); }; req.once('error', common.mustCall(function(err) { diff --git a/test/parallel/test-tls-key-mismatch.js b/test/parallel/test-tls-key-mismatch.js index fdbb3676267a9d..df8848a03de4a9 100644 --- a/test/parallel/test-tls-key-mismatch.js +++ b/test/parallel/test-tls-key-mismatch.js @@ -22,14 +22,16 @@ 'use strict'; const common = require('../common'); -if (!common.hasCrypto) +if (!common.hasCrypto) { common.skip('missing crypto'); +} const fixtures = require('../common/fixtures'); +const { hasOpenSSL3 } = require('../common/crypto'); const assert = require('assert'); const tls = require('tls'); -const errorMessageRegex = common.hasOpenSSL3 ? +const errorMessageRegex = hasOpenSSL3 ? /^Error: error:05800074:x509 certificate routines::key values mismatch$/ : /^Error: error:0B080074:x509 certificate routines:X509_check_private_key:key values mismatch$/; diff --git a/test/parallel/test-tls-legacy-pfx.js b/test/parallel/test-tls-legacy-pfx.js index 33b4c58fc6ccc3..5106217718dbdc 100644 --- a/test/parallel/test-tls-legacy-pfx.js +++ b/test/parallel/test-tls-legacy-pfx.js @@ -1,9 +1,14 @@ 'use strict'; const common = require('../common'); -if (!common.hasCrypto) +if (!common.hasCrypto) { common.skip('missing crypto'); -if (!common.hasOpenSSL3) +} + +const { hasOpenSSL3 } = require('../common/crypto'); + +if (!hasOpenSSL3) { common.skip('OpenSSL legacy failures are only testable with OpenSSL 3+'); +} const fixtures = require('../common/fixtures'); diff --git a/test/parallel/test-tls-min-max-version.js b/test/parallel/test-tls-min-max-version.js index af32468eea6a68..4903d92f5c5700 100644 --- a/test/parallel/test-tls-min-max-version.js +++ b/test/parallel/test-tls-min-max-version.js @@ -1,5 +1,13 @@ 'use strict'; const common = require('../common'); + +if (!common.hasCrypto) { + common.skip('missing crypto'); +} +const { + hasOpenSSL, + hasOpenSSL3, +} = require('../common/crypto'); const fixtures = require('../common/fixtures'); const { inspect } = require('util'); @@ -16,13 +24,13 @@ function test(cmin, cmax, cprot, smin, smax, sprot, proto, cerr, serr) { assert(proto || cerr || serr, 'test missing any expectations'); let ciphers; - if (common.hasOpenSSL3 && (proto === 'TLSv1' || proto === 'TLSv1.1' || + if (hasOpenSSL3 && (proto === 'TLSv1' || proto === 'TLSv1.1' || proto === 'TLSv1_1_method' || proto === 'TLSv1_method' || sprot === 'TLSv1_1_method' || sprot === 'TLSv1_method')) { if (serr !== 'ERR_SSL_UNSUPPORTED_PROTOCOL') ciphers = 'ALL@SECLEVEL=0'; } - if (common.hasOpenSSL(3, 1) && cerr === 'ERR_SSL_TLSV1_ALERT_PROTOCOL_VERSION') { + if (hasOpenSSL(3, 1) && cerr === 'ERR_SSL_TLSV1_ALERT_PROTOCOL_VERSION') { ciphers = 'DEFAULT@SECLEVEL=0'; } // Report where test was called from. Strip leading garbage from @@ -125,9 +133,9 @@ test(U, U, 'TLS_method', U, U, 'TLSv1_method', 'TLSv1'); // OpenSSL 1.1.1 and 3.0 use a different error code and alert (sent to the // client) when no protocols are enabled on the server. -const NO_PROTOCOLS_AVAILABLE_SERVER = common.hasOpenSSL3 ? +const NO_PROTOCOLS_AVAILABLE_SERVER = hasOpenSSL3 ? 'ERR_SSL_NO_PROTOCOLS_AVAILABLE' : 'ERR_SSL_INTERNAL_ERROR'; -const NO_PROTOCOLS_AVAILABLE_SERVER_ALERT = common.hasOpenSSL3 ? +const NO_PROTOCOLS_AVAILABLE_SERVER_ALERT = hasOpenSSL3 ? 'ERR_SSL_TLSV1_ALERT_PROTOCOL_VERSION' : 'ERR_SSL_TLSV1_ALERT_INTERNAL_ERROR'; // SSLv23 also means "any supported protocol" greater than the default diff --git a/test/parallel/test-tls-no-sslv3.js b/test/parallel/test-tls-no-sslv3.js index 9282beb4bdac2c..cd5f4ad944a6c5 100644 --- a/test/parallel/test-tls-no-sslv3.js +++ b/test/parallel/test-tls-no-sslv3.js @@ -1,10 +1,14 @@ 'use strict'; const common = require('../common'); -if (!common.hasCrypto) +if (!common.hasCrypto) { common.skip('missing crypto'); +} -if (common.opensslCli === false) +const { opensslCli } = require('../common/crypto'); + +if (opensslCli === false) { common.skip('node compiled without OpenSSL CLI.'); +} const assert = require('assert'); const tls = require('tls'); @@ -23,7 +27,7 @@ server.listen(0, '127.0.0.1', function() { '-ssl3', '-connect', address]; - const client = spawn(common.opensslCli, args, { stdio: 'pipe' }); + const client = spawn(opensslCli, args, { stdio: 'pipe' }); client.stdout.pipe(process.stdout); client.stderr.pipe(process.stderr); client.stderr.setEncoding('utf8'); diff --git a/test/parallel/test-tls-ocsp-callback.js b/test/parallel/test-tls-ocsp-callback.js index 04a60a0890c506..bdf622d4686ec1 100644 --- a/test/parallel/test-tls-ocsp-callback.js +++ b/test/parallel/test-tls-ocsp-callback.js @@ -22,12 +22,17 @@ 'use strict'; const common = require('../common'); -if (!common.opensslCli) - common.skip('node compiled without OpenSSL CLI.'); - -if (!common.hasCrypto) +if (!common.hasCrypto) { common.skip('missing crypto'); +} + +const { opensslCli } = require('../common/crypto'); + +if (!opensslCli) { + common.skip('node compiled without OpenSSL CLI.'); +} +const crypto = require('crypto'); const tls = require('tls'); const fixtures = require('../common/fixtures'); @@ -108,6 +113,6 @@ test({ ocsp: true, response: false }); test({ ocsp: true, response: 'hello world' }); test({ ocsp: false }); -if (!common.hasFipsCrypto) { +if (!crypto.getFips()) { test({ ocsp: true, response: 'hello pfx', pfx: pfx, passphrase: 'sample' }); } diff --git a/test/parallel/test-tls-psk-circuit.js b/test/parallel/test-tls-psk-circuit.js index c06e61c321ef67..61861ecf4dafa6 100644 --- a/test/parallel/test-tls-psk-circuit.js +++ b/test/parallel/test-tls-psk-circuit.js @@ -1,9 +1,11 @@ 'use strict'; const common = require('../common'); -if (!common.hasCrypto) +if (!common.hasCrypto) { common.skip('missing crypto'); +} +const { hasOpenSSL } = require('../common/crypto'); const assert = require('assert'); const tls = require('tls'); @@ -62,12 +64,12 @@ test({ psk: USERS.UserA, identity: 'UserA' }, { minVersion: 'TLSv1.3' }); test({ psk: USERS.UserB, identity: 'UserB' }); test({ psk: USERS.UserB, identity: 'UserB' }, { minVersion: 'TLSv1.3' }); // Unrecognized user should fail handshake -const expectedHandshakeErr = common.hasOpenSSL(3, 2) ? +const expectedHandshakeErr = hasOpenSSL(3, 2) ? 'ERR_SSL_SSL/TLS_ALERT_HANDSHAKE_FAILURE' : 'ERR_SSL_SSLV3_ALERT_HANDSHAKE_FAILURE'; test({ psk: USERS.UserB, identity: 'UserC' }, {}, expectedHandshakeErr); // Recognized user but incorrect secret should fail handshake -const expectedIllegalParameterErr = common.hasOpenSSL(3, 4) ? 'ERR_SSL_TLSV1_ALERT_DECRYPT_ERROR' : - common.hasOpenSSL(3, 2) ? +const expectedIllegalParameterErr = hasOpenSSL(3, 4) ? 'ERR_SSL_TLSV1_ALERT_DECRYPT_ERROR' : + hasOpenSSL(3, 2) ? 'ERR_SSL_SSL/TLS_ALERT_ILLEGAL_PARAMETER' : 'ERR_SSL_SSLV3_ALERT_ILLEGAL_PARAMETER'; test({ psk: USERS.UserA, identity: 'UserB' }, {}, expectedIllegalParameterErr); test({ psk: USERS.UserB, identity: 'UserB' }); diff --git a/test/parallel/test-tls-psk-server.js b/test/parallel/test-tls-psk-server.js index b9260958401522..87fad86083e1ab 100644 --- a/test/parallel/test-tls-psk-server.js +++ b/test/parallel/test-tls-psk-server.js @@ -1,10 +1,15 @@ 'use strict'; const common = require('../common'); -if (!common.hasCrypto) +if (!common.hasCrypto) { common.skip('missing crypto'); -if (!common.opensslCli) +} + +const { opensslCli } = require('../common/crypto'); + +if (!opensslCli) { common.skip('missing openssl cli'); +} const assert = require('assert'); @@ -41,7 +46,7 @@ let sentWorld = false; let gotWorld = false; server.listen(0, () => { - const client = spawn(common.opensslCli, [ + const client = spawn(opensslCli, [ 's_client', '-connect', `127.0.0.1:${server.address().port}`, '-cipher', CIPHERS, diff --git a/test/parallel/test-tls-securepair-server.js b/test/parallel/test-tls-securepair-server.js index 78cd9f725401ed..fb4ebe6a2511cf 100644 --- a/test/parallel/test-tls-securepair-server.js +++ b/test/parallel/test-tls-securepair-server.js @@ -21,11 +21,15 @@ 'use strict'; const common = require('../common'); -if (!common.hasCrypto) +if (!common.hasCrypto) { common.skip('missing crypto'); +} + +const { opensslCli } = require('../common/crypto'); -if (!common.opensslCli) +if (!opensslCli) { common.skip('missing openssl-cli'); +} const assert = require('assert'); const tls = require('tls'); @@ -109,7 +113,7 @@ server.listen(0, common.mustCall(function() { const args = ['s_client', '-connect', `127.0.0.1:${this.address().port}`]; - const client = spawn(common.opensslCli, args); + const client = spawn(opensslCli, args); let out = ''; diff --git a/test/parallel/test-tls-server-verify.js b/test/parallel/test-tls-server-verify.js index 51ccd0d747fdf5..2517c7c8dbbb1f 100644 --- a/test/parallel/test-tls-server-verify.js +++ b/test/parallel/test-tls-server-verify.js @@ -22,11 +22,15 @@ 'use strict'; const common = require('../common'); -if (!common.hasCrypto) +if (!common.hasCrypto) { common.skip('missing crypto'); +} + +const { opensslCli } = require('../common/crypto'); -if (!common.opensslCli) +if (!opensslCli) { common.skip('node compiled without OpenSSL CLI.'); +} // This is a rather complex test which sets up various TLS servers with node // and connects to them using the 'openssl s_client' command line utility @@ -188,7 +192,7 @@ function runClient(prefix, port, options, cb) { } // To test use: openssl s_client -connect localhost:8000 - const client = spawn(common.opensslCli, args); + const client = spawn(opensslCli, args); let out = ''; diff --git a/test/parallel/test-tls-session-cache.js b/test/parallel/test-tls-session-cache.js index b55e150401d8a2..9524764aa609ee 100644 --- a/test/parallel/test-tls-session-cache.js +++ b/test/parallel/test-tls-session-cache.js @@ -21,17 +21,23 @@ 'use strict'; const common = require('../common'); -if (!common.hasCrypto) +if (!common.hasCrypto) { common.skip('missing crypto'); +} +const { + hasOpenSSL, + opensslCli, +} = require('../common/crypto'); + +if (!opensslCli) { + common.skip('node compiled without OpenSSL CLI.'); +} + const fixtures = require('../common/fixtures'); const assert = require('assert'); const tls = require('tls'); const { spawn } = require('child_process'); -if (!common.opensslCli) - common.skip('node compiled without OpenSSL CLI.'); - - doTest({ tickets: false }, function() { doTest({ tickets: true }, function() { doTest({ tickets: false, invalidSession: true }, function() { @@ -100,7 +106,7 @@ function doTest(testOptions, callback) { const args = [ 's_client', '-tls1', - '-cipher', (common.hasOpenSSL(3, 1) ? 'DEFAULT:@SECLEVEL=0' : 'DEFAULT'), + '-cipher', (hasOpenSSL(3, 1) ? 'DEFAULT:@SECLEVEL=0' : 'DEFAULT'), '-connect', `localhost:${this.address().port}`, '-servername', 'ohgod', '-key', fixtures.path('keys/rsa_private.pem'), @@ -109,7 +115,7 @@ function doTest(testOptions, callback) { ].concat(testOptions.tickets ? [] : '-no_ticket'); function spawnClient() { - const client = spawn(common.opensslCli, args, { + const client = spawn(opensslCli, args, { stdio: [ 0, 1, 'pipe' ] }); let err = ''; diff --git a/test/parallel/test-tls-set-ciphers.js b/test/parallel/test-tls-set-ciphers.js index f7062e73c9403c..1e63e9376e134b 100644 --- a/test/parallel/test-tls-set-ciphers.js +++ b/test/parallel/test-tls-set-ciphers.js @@ -1,7 +1,17 @@ 'use strict'; const common = require('../common'); -if (!common.hasOpenSSL3) +if (!common.hasCrypto) { common.skip('missing crypto, or OpenSSL version lower than 3'); +} + +const { + hasOpenSSL, + hasOpenSSL3, +} = require('../common/crypto'); + +if (!hasOpenSSL3) { + common.skip('missing crypto, or OpenSSL version lower than 3'); +} const fixtures = require('../common/fixtures'); const { inspect } = require('util'); @@ -80,7 +90,7 @@ function test(cciphers, sciphers, cipher, cerr, serr, options) { const U = undefined; let expectedTLSAlertError = 'ERR_SSL_SSLV3_ALERT_HANDSHAKE_FAILURE'; -if (common.hasOpenSSL(3, 2)) { +if (hasOpenSSL(3, 2)) { expectedTLSAlertError = 'ERR_SSL_SSL/TLS_ALERT_HANDSHAKE_FAILURE'; } @@ -117,7 +127,7 @@ test(U, 'AES256-SHA', 'TLS_AES_256_GCM_SHA384', U, U, { maxVersion: 'TLSv1.3' }) // default, but work. // However, for OpenSSL32 AES_128 is not enabled due to the // default security level -if (!common.hasOpenSSL(3, 2)) { +if (!hasOpenSSL(3, 2)) { test('TLS_AES_128_CCM_8_SHA256', U, U, 'ERR_SSL_SSLV3_ALERT_HANDSHAKE_FAILURE', 'ERR_SSL_NO_SHARED_CIPHER'); diff --git a/test/parallel/test-tls-set-secure-context.js b/test/parallel/test-tls-set-secure-context.js index c056875e14ddfb..3d2de6b3321414 100644 --- a/test/parallel/test-tls-set-secure-context.js +++ b/test/parallel/test-tls-set-secure-context.js @@ -1,8 +1,9 @@ 'use strict'; const common = require('../common'); -if (!common.hasCrypto) +if (!common.hasCrypto) { common.skip('missing crypto'); +} // This test verifies the behavior of the tls setSecureContext() method. // It also verifies that existing connections are not disrupted when the @@ -12,6 +13,7 @@ const assert = require('assert'); const events = require('events'); const https = require('https'); const timers = require('timers/promises'); +const { hasOpenSSL3 } = require('../common/crypto'); const fixtures = require('../common/fixtures'); const credentialOptions = [ { @@ -55,7 +57,7 @@ server.listen(0, common.mustCall(() => { server.setSecureContext(credentialOptions[1]); firstResponse.write('request-'); - const errorMessageRegex = common.hasOpenSSL3 ? + const errorMessageRegex = hasOpenSSL3 ? /^Error: self-signed certificate$/ : /^Error: self signed certificate$/; await assert.rejects(makeRequest(port, 3), errorMessageRegex); diff --git a/test/parallel/test-tls-set-sigalgs.js b/test/parallel/test-tls-set-sigalgs.js index 3f3d152f4d877e..985ca13ba2ac7d 100644 --- a/test/parallel/test-tls-set-sigalgs.js +++ b/test/parallel/test-tls-set-sigalgs.js @@ -1,6 +1,9 @@ 'use strict'; const common = require('../common'); -if (!common.hasCrypto) common.skip('missing crypto'); +if (!common.hasCrypto) { + common.skip('missing crypto'); +} +const { hasOpenSSL } = require('../common/crypto'); const fixtures = require('../common/fixtures'); // Test sigalgs: option for TLS. @@ -63,7 +66,7 @@ test('RSA-PSS+SHA256:RSA-PSS+SHA512:ECDSA+SHA256', ['RSA-PSS+SHA256', 'ECDSA+SHA256']); // Do not have shared sigalgs. -const handshakeErr = common.hasOpenSSL(3, 2) ? +const handshakeErr = hasOpenSSL(3, 2) ? 'ERR_SSL_SSL/TLS_ALERT_HANDSHAKE_FAILURE' : 'ERR_SSL_SSLV3_ALERT_HANDSHAKE_FAILURE'; test('RSA-PSS+SHA384', 'ECDSA+SHA256', undefined, handshakeErr, diff --git a/test/parallel/test-trace-env.js b/test/parallel/test-trace-env.js index ba08e0af2aad1d..7a7b80fa4c1094 100644 --- a/test/parallel/test-trace-env.js +++ b/test/parallel/test-trace-env.js @@ -18,9 +18,11 @@ spawnSyncAndAssert(process.execPath, ['--trace-env', fixtures.path('empty.js')], } if (common.hasCrypto) { assert.match(output, /get "NODE_EXTRA_CA_CERTS"/); - } - if (common.hasOpenSSL3) { - assert.match(output, /get "OPENSSL_CONF"/); + + const { hasOpenSSL3 } = require('../common/crypto'); + if (hasOpenSSL3) { + assert.match(output, /get "OPENSSL_CONF"/); + } } assert.match(output, /get "NODE_DEBUG_NATIVE"/); assert.match(output, /get "NODE_COMPILE_CACHE"/); diff --git a/test/parallel/test-x509-escaping.js b/test/parallel/test-x509-escaping.js index e6ae4d886908cb..b507af88e1f7f3 100644 --- a/test/parallel/test-x509-escaping.js +++ b/test/parallel/test-x509-escaping.js @@ -1,15 +1,16 @@ 'use strict'; const common = require('../common'); -if (!common.hasCrypto) +if (!common.hasCrypto) { common.skip('missing crypto'); +} const assert = require('assert'); const { X509Certificate } = require('crypto'); const tls = require('tls'); const fixtures = require('../common/fixtures'); -const { hasOpenSSL3 } = common; +const { hasOpenSSL3 } = require('../common/crypto'); // Test that all certificate chains provided by the reporter are rejected. { diff --git a/test/pummel/test-crypto-dh-hash.js b/test/pummel/test-crypto-dh-hash.js index ef5a640688c9bb..b59f556a2042b9 100644 --- a/test/pummel/test-crypto-dh-hash.js +++ b/test/pummel/test-crypto-dh-hash.js @@ -30,7 +30,9 @@ if (common.isPi) { common.skip('Too slow for Raspberry Pi devices'); } -if (!common.hasOpenSSL3) { +const { hasOpenSSL3 } = require('../common/crypto'); + +if (!hasOpenSSL3) { common.skip('Too slow when dynamically linked against OpenSSL 1.1.1'); } diff --git a/test/pummel/test-crypto-dh-keys.js b/test/pummel/test-crypto-dh-keys.js index 2caa4e244a9859..abce6a07acf4ac 100644 --- a/test/pummel/test-crypto-dh-keys.js +++ b/test/pummel/test-crypto-dh-keys.js @@ -36,8 +36,9 @@ const crypto = require('crypto'); [ 'modp1', 'modp2', 'modp5', 'modp14', 'modp15', 'modp16', 'modp17' ] .forEach((name) => { // modp1 is 768 bits, FIPS requires >= 1024 - if (name === 'modp1' && common.hasFipsCrypto) + if (name === 'modp1' && crypto.getFips()) { return; + } const group1 = crypto.getDiffieHellman(name); const group2 = crypto.getDiffieHellman(name); group1.generateKeys(); diff --git a/test/pummel/test-dh-regr.js b/test/pummel/test-dh-regr.js index 41d5bf872f97ec..cfae57d0728bdb 100644 --- a/test/pummel/test-dh-regr.js +++ b/test/pummel/test-dh-regr.js @@ -32,10 +32,11 @@ if (common.isPi) { const assert = require('assert'); const crypto = require('crypto'); +const { hasOpenSSL3 } = require('../common/crypto'); // FIPS requires length >= 1024 but we use 512/256 in this test to keep it from // taking too long and timing out in CI. -const length = (common.hasFipsCrypto) ? 1024 : common.hasOpenSSL3 ? 512 : 256; +const length = crypto.getFips() ? 1024 : hasOpenSSL3 ? 512 : 256; const p = crypto.createDiffieHellman(length).getPrime(); diff --git a/test/sequential/test-tls-psk-client.js b/test/sequential/test-tls-psk-client.js index ddebc8f8cc9807..c07b1f92d98376 100644 --- a/test/sequential/test-tls-psk-client.js +++ b/test/sequential/test-tls-psk-client.js @@ -1,10 +1,15 @@ 'use strict'; const common = require('../common'); -if (!common.hasCrypto) +if (!common.hasCrypto) { common.skip('missing crypto'); -if (!common.opensslCli) +} + +const { opensslCli } = require('../common/crypto'); + +if (!opensslCli) { common.skip('missing openssl cli'); +} const assert = require('assert'); const tls = require('tls'); @@ -16,7 +21,7 @@ const KEY = 'd731ef57be09e5204f0b205b60627028'; const IDENTITY = 'Client_identity'; // Hardcoded by `openssl s_server` const useIPv4 = !common.hasIPv6; -const server = spawn(common.opensslCli, [ +const server = spawn(opensslCli, [ 's_server', '-accept', common.PORT, '-cipher', CIPHERS, diff --git a/test/sequential/test-tls-securepair-client.js b/test/sequential/test-tls-securepair-client.js index f3ca42ad6edfb0..262518621b5f3f 100644 --- a/test/sequential/test-tls-securepair-client.js +++ b/test/sequential/test-tls-securepair-client.js @@ -23,14 +23,19 @@ const common = require('../common'); -if (!common.opensslCli) - common.skip('node compiled without OpenSSL CLI.'); - -if (!common.hasCrypto) +if (!common.hasCrypto) { common.skip('missing crypto'); +} + +const { opensslCli } = require('../common/crypto'); -if (common.isWindows) +if (!opensslCli) { + common.skip('node compiled without OpenSSL CLI.'); +} + +if (common.isWindows) { common.skip('test does not work on Windows'); // ...but it should! +} const net = require('net'); const assert = require('assert'); @@ -63,11 +68,11 @@ function test(keyPath, certPath, check, next) { const key = fixtures.readSync(keyPath).toString(); const cert = fixtures.readSync(certPath).toString(); - const server = spawn(common.opensslCli, ['s_server', - '-accept', 0, - '-cert', fixtures.path(certPath), - '-key', fixtures.path(keyPath), - ...(useIPv4 ? ['-4'] : []), + const server = spawn(opensslCli, ['s_server', + '-accept', 0, + '-cert', fixtures.path(certPath), + '-key', fixtures.path(keyPath), + ...(useIPv4 ? ['-4'] : []), ]); server.stdout.pipe(process.stdout); server.stderr.pipe(process.stdout); diff --git a/test/sequential/test-tls-session-timeout.js b/test/sequential/test-tls-session-timeout.js index 09107011aeda52..a93cdc793a2337 100644 --- a/test/sequential/test-tls-session-timeout.js +++ b/test/sequential/test-tls-session-timeout.js @@ -22,8 +22,11 @@ 'use strict'; const common = require('../common'); -if (!common.hasCrypto) +if (!common.hasCrypto) { common.skip('missing crypto'); +} + +const { opensslCli } = require('../common/crypto'); const tmpdir = require('../common/tmpdir'); tmpdir.refresh(); @@ -56,8 +59,9 @@ const cert = fixtures.readKey('rsa_cert.crt'); } } -if (!common.opensslCli) +if (!opensslCli) { common.skip('node compiled without OpenSSL CLI.'); +} doTest(); @@ -105,7 +109,7 @@ function doTest() { '-sess_in', sessionFileName, '-sess_out', sessionFileName, ]; - const client = spawn(common.opensslCli, flags, { + const client = spawn(opensslCli, flags, { stdio: ['ignore', 'pipe', 'ignore'] }); From 92e99780f0b383b6d5feadcde463612ab0387f82 Mon Sep 17 00:00:00 2001 From: James M Snell Date: Fri, 24 Jan 2025 17:35:59 -0800 Subject: [PATCH 152/205] test: move hasMultiLocalhost to common/net Given that `common/net` already exists and hasMultiLocalhost is net specific, let's move it out of common/index to better encapsulate and simplify common/index more PR-URL: https://github.com/nodejs/node/pull/56716 Reviewed-By: Yagiz Nizipli Reviewed-By: Richard Lau Reviewed-By: Luigi Pinca --- test/common/README.md | 6 ------ test/common/index.js | 10 ---------- test/common/index.mjs | 2 -- test/common/net.js | 10 ++++++++++ test/parallel/test-http-localaddress.js | 4 +++- test/parallel/test-http2-connect-options.js | 4 +++- test/parallel/test-https-localaddress.js | 4 +++- 7 files changed, 19 insertions(+), 21 deletions(-) diff --git a/test/common/README.md b/test/common/README.md index ee36503f920001..9ecee39b64a3df 100644 --- a/test/common/README.md +++ b/test/common/README.md @@ -238,12 +238,6 @@ Indicates if [internationalization][] is supported. Indicates whether `IPv6` is supported on this platform. -### `hasMultiLocalhost` - -* [\][] - -Indicates if there are multiple localhosts available. - ### `inFreeBSDJail` * [\][] diff --git a/test/common/index.js b/test/common/index.js index d2c39578324600..e8bf65d0a6edb4 100644 --- a/test/common/index.js +++ b/test/common/index.js @@ -489,15 +489,6 @@ function _mustCallInner(fn, criteria = 1, field) { return _return; } -function hasMultiLocalhost() { - const { internalBinding } = require('internal/test/binding'); - const { TCP, constants: TCPConstants } = internalBinding('tcp_wrap'); - const t = new TCP(TCPConstants.SOCKET); - const ret = t.bind('127.0.0.2', 0); - t.close(); - return ret === 0; -} - function skipIfEslintMissing() { if (!fs.existsSync( path.join(__dirname, '..', '..', 'tools', 'eslint', 'node_modules', 'eslint'), @@ -965,7 +956,6 @@ const common = { hasIntl, hasCrypto, hasQuic, - hasMultiLocalhost, invalidArgTypeHelper, isAlive, isASan, diff --git a/test/common/index.mjs b/test/common/index.mjs index 23328ac90ea3c9..090659f93be8ef 100644 --- a/test/common/index.mjs +++ b/test/common/index.mjs @@ -20,7 +20,6 @@ const { hasCrypto, hasIntl, hasIPv6, - hasMultiLocalhost, isAIX, isAlive, isDumbTerminal, @@ -75,7 +74,6 @@ export { hasCrypto, hasIntl, hasIPv6, - hasMultiLocalhost, isAIX, isAlive, isDumbTerminal, diff --git a/test/common/net.js b/test/common/net.js index 84eddd0966ed56..3886c542421005 100644 --- a/test/common/net.js +++ b/test/common/net.js @@ -17,7 +17,17 @@ function checkSupportReusePort() { }); } +function hasMultiLocalhost() { + const { internalBinding } = require('internal/test/binding'); + const { TCP, constants: TCPConstants } = internalBinding('tcp_wrap'); + const t = new TCP(TCPConstants.SOCKET); + const ret = t.bind('127.0.0.2', 0); + t.close(); + return ret === 0; +} + module.exports = { checkSupportReusePort, + hasMultiLocalhost, options, }; diff --git a/test/parallel/test-http-localaddress.js b/test/parallel/test-http-localaddress.js index a0e4bb80a3f8c2..da25ab3047613f 100644 --- a/test/parallel/test-http-localaddress.js +++ b/test/parallel/test-http-localaddress.js @@ -22,8 +22,10 @@ // Flags: --expose-internals 'use strict'; const common = require('../common'); -if (!common.hasMultiLocalhost()) +const { hasMultiLocalhost } = require('../common/net'); +if (!hasMultiLocalhost()) { common.skip('platform-specific test.'); +} const http = require('http'); const assert = require('assert'); diff --git a/test/parallel/test-http2-connect-options.js b/test/parallel/test-http2-connect-options.js index 233ced016974e2..1abcee99e06433 100644 --- a/test/parallel/test-http2-connect-options.js +++ b/test/parallel/test-http2-connect-options.js @@ -4,8 +4,10 @@ const common = require('../common'); if (!common.hasCrypto) common.skip('missing crypto'); -if (!common.hasMultiLocalhost()) +const { hasMultiLocalhost } = require('../common/net'); +if (!hasMultiLocalhost()) { common.skip('platform-specific test.'); +} const http2 = require('http2'); const assert = require('assert'); diff --git a/test/parallel/test-https-localaddress.js b/test/parallel/test-https-localaddress.js index 0de0974dc69b04..2a4629b34e4105 100644 --- a/test/parallel/test-https-localaddress.js +++ b/test/parallel/test-https-localaddress.js @@ -25,8 +25,10 @@ const common = require('../common'); if (!common.hasCrypto) common.skip('missing crypto'); -if (!common.hasMultiLocalhost()) +const { hasMultiLocalhost } = require('../common/net'); +if (!hasMultiLocalhost()) { common.skip('platform-specific test.'); +} const fixtures = require('../common/fixtures'); const assert = require('assert'); From 5be29a274e42bad0a60ceb762a4f02c3feea575e Mon Sep 17 00:00:00 2001 From: James M Snell Date: Wed, 22 Jan 2025 13:05:54 -0800 Subject: [PATCH 153/205] test: simplify common/index.js Move single or trivial and limited use things out of common/index.js for the purpose of simplifying and reducing common/index.js PR-URL: https://github.com/nodejs/node/pull/56712 Reviewed-By: Yagiz Nizipli Reviewed-By: Matteo Collina --- test/common/README.md | 6 ------ test/common/index.js | 12 ------------ test/common/index.mjs | 4 ---- test/parallel/test-source-map-enable.js | 3 ++- test/tick-processor/util.js | 11 +++++++++-- test/wasi/test-wasi-io.js | 11 ++++++++--- 6 files changed, 19 insertions(+), 28 deletions(-) diff --git a/test/common/README.md b/test/common/README.md index 9ecee39b64a3df..c3c44e32b3788c 100644 --- a/test/common/README.md +++ b/test/common/README.md @@ -279,12 +279,6 @@ Platform check for IBMi. Platform check for Linux. -### `isLinuxPPCBE` - -* [\][] - -Platform check for Linux on PowerPC. - ### `isMacOS` * [\][] diff --git a/test/common/index.js b/test/common/index.js index e8bf65d0a6edb4..238d66e96fe257 100644 --- a/test/common/index.js +++ b/test/common/index.js @@ -1034,11 +1034,6 @@ const common = { return require('os').type() === 'OS400'; }, - get isLinuxPPCBE() { - return (process.platform === 'linux') && (process.arch === 'ppc64') && - (require('os').endianness() === 'BE'); - }, - get localhostIPv4() { if (localhostIPv4 !== null) return localhostIPv4; @@ -1067,13 +1062,6 @@ const common = { return +process.env.NODE_COMMON_PORT || 12346; }, - /** - * Returns the EOL character used by this Git checkout. - */ - get checkoutEOL() { - return fs.readFileSync(__filename).includes('\r\n') ? '\r\n' : '\n'; - }, - get isInsideDirWithUnusualChars() { return __dirname.includes('%') || (!isWindows && __dirname.includes('\\')) || diff --git a/test/common/index.mjs b/test/common/index.mjs index 090659f93be8ef..aafef1453bd78a 100644 --- a/test/common/index.mjs +++ b/test/common/index.mjs @@ -7,7 +7,6 @@ const { allowGlobals, buildType, canCreateSymLink, - checkoutEOL, childShouldThrowAndAbort, createZeroFilledFile, enoughTestMem, @@ -27,7 +26,6 @@ const { isIBMi, isInsideDirWithUnusualChars, isLinux, - isLinuxPPCBE, isMainThread, isOpenBSD, isMacOS, @@ -59,7 +57,6 @@ export { allowGlobals, buildType, canCreateSymLink, - checkoutEOL, childShouldThrowAndAbort, createRequire, createZeroFilledFile, @@ -81,7 +78,6 @@ export { isIBMi, isInsideDirWithUnusualChars, isLinux, - isLinuxPPCBE, isMainThread, isOpenBSD, isMacOS, diff --git a/test/parallel/test-source-map-enable.js b/test/parallel/test-source-map-enable.js index 46c25d26cfa8e7..64f4254fcddbc6 100644 --- a/test/parallel/test-source-map-enable.js +++ b/test/parallel/test-source-map-enable.js @@ -242,6 +242,7 @@ function nextdir() { // Persists line lengths for in-memory representation of source file. { + const checkoutEOL = fs.readFileSync(__filename).includes('\r\n') ? '\r\n' : '\n'; const coverageDirectory = nextdir(); spawnSync(process.execPath, [ require.resolve('../fixtures/source-map/istanbul-throw.js'), @@ -250,7 +251,7 @@ function nextdir() { 'istanbul-throw.js', coverageDirectory ); - if (common.checkoutEOL === '\r\n') { + if (checkoutEOL === '\r\n') { assert.deepStrictEqual(sourceMap.lineLengths, [1086, 31, 185, 649, 0]); } else { assert.deepStrictEqual(sourceMap.lineLengths, [1085, 30, 184, 648, 0]); diff --git a/test/tick-processor/util.js b/test/tick-processor/util.js index 6d118b7c38bc66..9586a81c276a65 100644 --- a/test/tick-processor/util.js +++ b/test/tick-processor/util.js @@ -5,14 +5,21 @@ const { isWindows, isSunOS, isAIX, - isLinuxPPCBE, isFreeBSD, } = require('../common'); +const { endianness } = require('os'); + +function isLinuxPPCBE() { + return (process.platform === 'linux') && + (process.arch === 'ppc64') && + (endianness() === 'BE'); +} + module.exports = { isCPPSymbolsNotMapped: isWindows || isSunOS || isAIX || - isLinuxPPCBE || + isLinuxPPCBE() || isFreeBSD, }; diff --git a/test/wasi/test-wasi-io.js b/test/wasi/test-wasi-io.js index 061ac88a73ece4..f5348644f1cfbf 100644 --- a/test/wasi/test-wasi-io.js +++ b/test/wasi/test-wasi-io.js @@ -1,14 +1,19 @@ 'use strict'; -const common = require('../common'); -const { checkoutEOL } = common; +require('../common'); +const { readFileSync } = require('fs'); const { testWasiPreview1 } = require('../common/wasi'); +const checkoutEOL = readFileSync(__filename).includes('\r\n') ? '\r\n' : '\n'; + +// TODO(@jasnell): It's not entirely clear what this test is asserting. +// More comments would be helpful. + testWasiPreview1(['freopen'], {}, { stdout: `hello from input2.txt${checkoutEOL}` }); testWasiPreview1(['read_file'], {}, { stdout: `hello from input.txt${checkoutEOL}` }); testWasiPreview1(['read_file_twice'], {}, { stdout: `hello from input.txt${checkoutEOL}hello from input.txt${checkoutEOL}`, }); // Tests that are currently unsupported on Windows. -if (!common.isWindows) { +if (process.platform !== 'win32') { testWasiPreview1(['stdin'], { input: 'hello world' }, { stdout: 'hello world' }); } From 1795202d1995fa87f0d3c66d63f6a1be6e808e4b Mon Sep 17 00:00:00 2001 From: James M Snell Date: Wed, 22 Jan 2025 14:19:38 -0800 Subject: [PATCH 154/205] test: rely less on duplicative common test harness utilities There are several cleanups here that are not just style nits... 1. The `common.isMainThread` was just a passthrough to the `isMainThread` export on the worker_thread module. It's use was inconsistent and just obfuscated the fact that the test file depend on the `worker_threads` built-in. By eliminating it we simplify the test harness a bit and make it clearer which tests depend on the worker_threads check. 2. The `common.isDumbTerminal` is fairly unnecesary since that just wraps a public API check. 3. Several of the `common.skipIf....` checks were inconsistently used and really don't need to be separate utility functions. A key part of the motivation here is to work towards making more of the tests more self-contained and less reliant on the common test harness where possible. PR-URL: https://github.com/nodejs/node/pull/56712 Reviewed-By: Yagiz Nizipli Reviewed-By: Matteo Collina --- test/abort/test-abort-backtrace.js | 45 ++++++++++++- test/async-hooks/init-hooks.js | 5 +- test/async-hooks/test-crypto-pbkdf2.js | 7 +- test/async-hooks/test-crypto-randomBytes.js | 7 +- test/async-hooks/test-enable-disable.js | 3 +- test/async-hooks/test-fseventwrap.js | 7 +- .../test-fsreqcallback-readFile.js | 4 +- test/async-hooks/test-getaddrinforeqwrap.js | 4 +- test/async-hooks/test-getnameinforeqwrap.js | 4 +- test/async-hooks/test-graph.signal.js | 7 +- .../test-no-assert-when-disabled.js | 5 +- test/async-hooks/test-pipewrap.js | 4 +- ...promise.chain-promise-before-init-hooks.js | 4 +- test/async-hooks/test-promise.js | 4 +- test/async-hooks/test-signalwrap.js | 7 +- test/async-hooks/test-statwatcher.js | 5 +- .../test-unhandled-rejection-context.js | 4 +- test/benchmark/test-benchmark-napi.js | 4 +- test/common/README.md | 17 ----- test/common/index.js | 66 ------------------- test/common/index.mjs | 8 --- test/es-module/test-esm-resolve-type.mjs | 4 +- .../test-vm-main-context-default-loader.js | 6 +- test/fixtures/permission/fs-write.js | 8 ++- test/fixtures/permission/processbinding.js | 6 +- test/internet/test-trace-events-dns.js | 4 +- ...test-async-hooks-disable-during-promise.js | 4 +- .../test-async-hooks-promise-triggerid.js | 4 +- test/parallel/test-async-hooks-promise.js | 4 +- ...st-async-hooks-top-level-clearimmediate.js | 4 +- .../test-async-wrap-promise-after-enabled.js | 4 +- test/parallel/test-bootstrap-modules.js | 10 +-- .../test-child-process-validate-stdio.js | 4 +- .../test-cluster-net-listen-relative-path.js | 9 ++- test/parallel/test-code-cache.js | 3 +- test/parallel/test-console-clear.js | 4 +- test/parallel/test-console.js | 4 +- test/parallel/test-crypto-no-algorithm.js | 3 +- test/parallel/test-cwd-enoent-preload.js | 9 ++- test/parallel/test-cwd-enoent-repl.js | 9 ++- test/parallel/test-cwd-enoent.js | 9 ++- test/parallel/test-fs-mkdir.js | 3 +- test/parallel/test-fs-realpath.js | 4 +- test/parallel/test-fs-whatwg-url.js | 4 +- test/parallel/test-fs-write-file-sync.js | 4 +- test/parallel/test-http-chunk-problem.js | 11 +++- test/parallel/test-icu-env.js | 4 +- .../test-inspector-already-activated-cli.js | 7 +- .../test-inspector-async-hook-after-done.js | 7 +- ...st-inspector-async-hook-setup-at-signal.js | 6 +- .../test-inspector-connect-main-thread.js | 4 +- .../test-inspector-connect-to-main-thread.js | 4 +- test/parallel/test-inspector-contexts.js | 3 +- ...ctor-exit-worker-in-wait-for-connection.js | 12 +++- ...tor-exit-worker-in-wait-for-connection2.js | 6 +- test/parallel/test-inspector-open-coverage.js | 7 +- ...st-inspector-open-port-integer-overflow.js | 7 +- .../test-inspector-overwrite-config.js | 4 +- .../test-inspector-port-zero-cluster.js | 7 +- .../parallel/test-inspector-tracing-domain.js | 8 ++- .../test-inspector-workers-flat-list.js | 4 +- test/parallel/test-internal-module-require.js | 3 +- ...st-performance-nodetiming-uvmetricsinfo.js | 6 +- .../test-permission-allow-addons-cli.js | 6 +- ...test-permission-allow-child-process-cli.js | 8 ++- .../test-permission-allow-wasi-cli.js | 6 +- .../test-permission-child-process-cli.js | 7 +- .../test-permission-fs-absolute-path.js | 6 +- ...test-permission-fs-internal-module-stat.js | 6 +- test/parallel/test-permission-fs-read.js | 6 +- .../test-permission-fs-relative-path.js | 6 +- .../test-permission-fs-repeat-path.js | 6 +- test/parallel/test-permission-fs-require.js | 8 ++- .../test-permission-fs-symlink-relative.js | 7 +- ...test-permission-fs-symlink-target-write.js | 18 +++-- test/parallel/test-permission-fs-symlink.js | 12 +++- .../test-permission-fs-traversal-path.js | 13 +++- test/parallel/test-permission-fs-wildcard.js | 6 +- .../test-permission-fs-windows-path.js | 6 +- .../test-permission-fs-write-report.js | 10 ++- test/parallel/test-permission-fs-write-v8.js | 10 ++- test/parallel/test-permission-fs-write.js | 10 ++- .../parallel/test-permission-inspector-brk.js | 6 +- test/parallel/test-permission-inspector.js | 7 +- test/parallel/test-permission-no-addons.js | 6 +- .../test-permission-processbinding.js | 6 +- .../test-permission-worker-threads-cli.js | 8 ++- test/parallel/test-pipe-file-to-http.js | 7 +- .../parallel/test-preload-self-referential.js | 4 +- test/parallel/test-process-abort.js | 4 +- .../test-process-beforeexit-throw-exit.js | 6 +- .../test-process-chdir-errormessage.js | 5 +- test/parallel/test-process-chdir.js | 4 +- test/parallel/test-process-env-tz.js | 7 +- test/parallel/test-process-euid-egid.js | 5 +- test/parallel/test-process-exit-handler.js | 4 +- test/parallel/test-process-get-builtin.mjs | 3 +- test/parallel/test-process-initgroups.js | 5 +- test/parallel/test-process-load-env-file.js | 5 +- test/parallel/test-process-setgroups.js | 4 +- test/parallel/test-process-uid-gid.js | 4 +- test/parallel/test-process-umask-mask.js | 3 +- test/parallel/test-process-umask.js | 3 +- ...-readline-interface-no-trailing-newline.js | 4 +- ...est-readline-interface-recursive-writes.js | 4 +- test/parallel/test-readline-interface.js | 5 +- test/parallel/test-readline-position.js | 4 +- .../test-readline-promises-interface.js | 5 +- .../test-readline-promises-tab-complete.js | 4 +- test/parallel/test-readline-tab-complete.js | 4 +- .../test-readline-undefined-columns.js | 4 +- test/parallel/test-readline.js | 4 +- test/parallel/test-repl-autocomplete.js | 4 +- test/parallel/test-repl-editor.js | 4 +- test/parallel/test-repl-history-navigation.js | 4 +- ...repl-load-multiline-no-trailing-newline.js | 4 +- test/parallel/test-repl-load-multiline.js | 4 +- test/parallel/test-repl-mode.js | 4 +- test/parallel/test-repl-permission-model.js | 4 +- test/parallel/test-repl-persistent-history.js | 4 +- .../test-repl-programmatic-history.js | 4 +- .../test-repl-require-self-referential.js | 4 +- test/parallel/test-repl-require.js | 4 +- test/parallel/test-repl-reverse-search.js | 5 +- test/parallel/test-repl-sigint-nested-eval.js | 6 +- test/parallel/test-repl-sigint.js | 6 +- .../test-repl-strict-mode-previews.js | 5 +- .../parallel/test-repl-tab-complete-import.js | 5 +- test/parallel/test-repl-tab-complete.js | 4 +- test/parallel/test-require-symlink.js | 8 ++- test/parallel/test-runner-module-mocking.js | 3 +- test/parallel/test-set-process-debug-port.js | 6 +- test/parallel/test-setproctitle.js | 14 ++-- .../test-shadow-realm-import-value-resolve.js | 5 +- test/parallel/test-signal-args.js | 9 ++- test/parallel/test-signal-handler.js | 9 ++- test/parallel/test-stdio-pipe-access.js | 5 +- test/parallel/test-stdio-pipe-redirect.js | 5 +- .../test-timers-immediate-unref-simple.js | 3 +- test/parallel/test-trace-events-api.js | 7 +- .../test-trace-events-dynamic-enable.js | 8 ++- test/parallel/test-warn-sigprof.js | 9 ++- test/parallel/test-worker-name.js | 11 +++- test/report/test-report-signal.js | 8 ++- test/sequential/test-fs-watch.js | 4 +- test/sequential/test-heapdump.js | 4 +- test/sequential/test-init.js | 4 +- test/sequential/test-perf-hooks.js | 5 +- 148 files changed, 671 insertions(+), 290 deletions(-) diff --git a/test/abort/test-abort-backtrace.js b/test/abort/test-abort-backtrace.js index ce9ed39196eb1f..455bbf2361cf51 100644 --- a/test/abort/test-abort-backtrace.js +++ b/test/abort/test-abort-backtrace.js @@ -1,8 +1,47 @@ 'use strict'; -const common = require('../common'); +require('../common'); const assert = require('assert'); const cp = require('child_process'); +function getPrintedStackTrace(stderr) { + const lines = stderr.split('\n'); + + let state = 'initial'; + const result = { + message: [], + nativeStack: [], + jsStack: [], + }; + for (let i = 0; i < lines.length; ++i) { + const line = lines[i].trim(); + if (line.length === 0) { + continue; // Skip empty lines. + } + + switch (state) { + case 'initial': + result.message.push(line); + if (line.includes('Native stack trace')) { + state = 'native-stack'; + } else { + result.message.push(line); + } + break; + case 'native-stack': + if (line.includes('JavaScript stack trace')) { + state = 'js-stack'; + } else { + result.nativeStack.push(line); + } + break; + case 'js-stack': + result.jsStack.push(line); + break; + } + } + return result; +} + if (process.argv[2] === 'child') { process.abort(); } else { @@ -10,7 +49,7 @@ if (process.argv[2] === 'child') { const stderr = child.stderr.toString(); assert.strictEqual(child.stdout.toString(), ''); - const { nativeStack, jsStack } = common.getPrintedStackTrace(stderr); + const { nativeStack, jsStack } = getPrintedStackTrace(stderr); if (!nativeStack.every((frame, index) => frame.startsWith(`${index + 1}:`))) { assert.fail(`Each frame should start with a frame number:\n${stderr}`); @@ -18,7 +57,7 @@ if (process.argv[2] === 'child') { // For systems that don't support backtraces, the native stack is // going to be empty. - if (!common.isWindows && nativeStack.length > 0) { + if (process.platform !== 'win32' && nativeStack.length > 0) { const { getBinaryPath } = require('../common/shared-lib-util'); if (!nativeStack.some((frame) => frame.includes(`[${getBinaryPath()}]`))) { assert.fail(`Some native stack frame include the binary name:\n${stderr}`); diff --git a/test/async-hooks/init-hooks.js b/test/async-hooks/init-hooks.js index 2206ab31eba75f..8fc44994fbc497 100644 --- a/test/async-hooks/init-hooks.js +++ b/test/async-hooks/init-hooks.js @@ -1,9 +1,10 @@ 'use strict'; // Flags: --expose-gc -const common = require('../common'); +require('../common'); const assert = require('assert'); const async_hooks = require('async_hooks'); +const { isMainThread } = require('worker_threads'); const util = require('util'); const print = process._rawDebug; @@ -161,7 +162,7 @@ class ActivityCollector { const stub = { uid, type: 'Unknown', handleIsObject: true, handle: {} }; this._activities.set(uid, stub); return stub; - } else if (!common.isMainThread) { + } else if (!isMainThread) { // Worker threads start main script execution inside of an AsyncWrap // callback, so we don't yield errors for these. return null; diff --git a/test/async-hooks/test-crypto-pbkdf2.js b/test/async-hooks/test-crypto-pbkdf2.js index 4788ce4a580656..c607adf7258760 100644 --- a/test/async-hooks/test-crypto-pbkdf2.js +++ b/test/async-hooks/test-crypto-pbkdf2.js @@ -1,10 +1,13 @@ 'use strict'; const common = require('../common'); -if (!common.hasCrypto) +if (!common.hasCrypto) { common.skip('missing crypto'); -if (!common.isMainThread) +} +const { isMainThread } = require('worker_threads'); +if (!isMainThread) { common.skip('Worker bootstrapping works differently -> different async IDs'); +} const assert = require('assert'); const tick = require('../common/tick'); diff --git a/test/async-hooks/test-crypto-randomBytes.js b/test/async-hooks/test-crypto-randomBytes.js index 88cd4643ab6638..8ecc1c45a9a524 100644 --- a/test/async-hooks/test-crypto-randomBytes.js +++ b/test/async-hooks/test-crypto-randomBytes.js @@ -1,10 +1,13 @@ 'use strict'; const common = require('../common'); -if (!common.hasCrypto) +if (!common.hasCrypto) { common.skip('missing crypto'); -if (!common.isMainThread) +} +const { isMainThread } = require('worker_threads'); +if (!isMainThread) { common.skip('Worker bootstrapping works differently -> different async IDs'); +} const assert = require('assert'); const tick = require('../common/tick'); diff --git a/test/async-hooks/test-enable-disable.js b/test/async-hooks/test-enable-disable.js index 64139408a48209..d408338e892c32 100644 --- a/test/async-hooks/test-enable-disable.js +++ b/test/async-hooks/test-enable-disable.js @@ -87,8 +87,9 @@ const assert = require('assert'); const tick = require('../common/tick'); const initHooks = require('./init-hooks'); const { checkInvocations } = require('./hook-checks'); +const { isMainThread } = require('worker_threads'); -if (!common.isMainThread) +if (!isMainThread) common.skip('Worker bootstrapping works differently -> different timing'); // Include "Unknown"s because hook2 will not be able to identify diff --git a/test/async-hooks/test-fseventwrap.js b/test/async-hooks/test-fseventwrap.js index 12a439f8033cbc..a5e1a3b9d2f232 100644 --- a/test/async-hooks/test-fseventwrap.js +++ b/test/async-hooks/test-fseventwrap.js @@ -6,12 +6,15 @@ const initHooks = require('./init-hooks'); const tick = require('../common/tick'); const { checkInvocations } = require('./hook-checks'); const fs = require('fs'); +const { isMainThread } = require('worker_threads'); -if (!common.isMainThread) +if (!isMainThread) { common.skip('Worker bootstrapping works differently -> different async IDs'); +} -if (common.isIBMi) +if (common.isIBMi) { common.skip('IBMi does not support fs.watch()'); +} const hooks = initHooks(); diff --git a/test/async-hooks/test-fsreqcallback-readFile.js b/test/async-hooks/test-fsreqcallback-readFile.js index 01ccce9b4cc694..65f3652f12f988 100644 --- a/test/async-hooks/test-fsreqcallback-readFile.js +++ b/test/async-hooks/test-fsreqcallback-readFile.js @@ -6,9 +6,11 @@ const tick = require('../common/tick'); const initHooks = require('./init-hooks'); const { checkInvocations } = require('./hook-checks'); const fs = require('fs'); +const { isMainThread } = require('worker_threads'); -if (!common.isMainThread) +if (!isMainThread) { common.skip('Worker bootstrapping works differently -> different async IDs'); +} const hooks = initHooks(); diff --git a/test/async-hooks/test-getaddrinforeqwrap.js b/test/async-hooks/test-getaddrinforeqwrap.js index 7291ea8a301954..a21557bcd56e7a 100644 --- a/test/async-hooks/test-getaddrinforeqwrap.js +++ b/test/async-hooks/test-getaddrinforeqwrap.js @@ -6,9 +6,11 @@ const tick = require('../common/tick'); const initHooks = require('./init-hooks'); const { checkInvocations } = require('./hook-checks'); const dns = require('dns'); +const { isMainThread } = require('worker_threads'); -if (!common.isMainThread) +if (!isMainThread) { common.skip('Worker bootstrapping works differently -> different async IDs'); +} const hooks = initHooks(); diff --git a/test/async-hooks/test-getnameinforeqwrap.js b/test/async-hooks/test-getnameinforeqwrap.js index c7a3937ff3ceef..b00fa0d4d9dd54 100644 --- a/test/async-hooks/test-getnameinforeqwrap.js +++ b/test/async-hooks/test-getnameinforeqwrap.js @@ -6,9 +6,11 @@ const tick = require('../common/tick'); const initHooks = require('./init-hooks'); const { checkInvocations } = require('./hook-checks'); const dns = require('dns'); +const { isMainThread } = require('worker_threads'); -if (!common.isMainThread) +if (!isMainThread) { common.skip('Worker bootstrapping works differently -> different async IDs'); +} const hooks = initHooks(); diff --git a/test/async-hooks/test-graph.signal.js b/test/async-hooks/test-graph.signal.js index f87b1215b523b9..351fb7550af431 100644 --- a/test/async-hooks/test-graph.signal.js +++ b/test/async-hooks/test-graph.signal.js @@ -1,10 +1,13 @@ 'use strict'; const common = require('../common'); -if (common.isWindows) +if (common.isWindows) { common.skip('no signals on Windows'); -if (!common.isMainThread) +} +const { isMainThread } = require('worker_threads'); +if (!isMainThread) { common.skip('No signal handling available in Workers'); +} const initHooks = require('./init-hooks'); const verifyGraph = require('./verify-graph'); diff --git a/test/async-hooks/test-no-assert-when-disabled.js b/test/async-hooks/test-no-assert-when-disabled.js index 70114d1e1140f8..0e7c0568cc09fa 100644 --- a/test/async-hooks/test-no-assert-when-disabled.js +++ b/test/async-hooks/test-no-assert-when-disabled.js @@ -1,9 +1,10 @@ 'use strict'; // Flags: --no-force-async-hooks-checks --expose-internals const common = require('../common'); - -if (!common.isMainThread) +const { isMainThread } = require('worker_threads'); +if (!isMainThread) { common.skip('Workers don\'t inherit per-env state like the check flag'); +} const async_hooks = require('internal/async_hooks'); diff --git a/test/async-hooks/test-pipewrap.js b/test/async-hooks/test-pipewrap.js index 2d42e769cfd1f3..7ea5f38adc85e2 100644 --- a/test/async-hooks/test-pipewrap.js +++ b/test/async-hooks/test-pipewrap.js @@ -9,9 +9,11 @@ const tick = require('../common/tick'); const initHooks = require('./init-hooks'); const { checkInvocations } = require('./hook-checks'); const { spawn } = require('child_process'); +const { isMainThread } = require('worker_threads'); -if (!common.isMainThread) +if (!isMainThread) { common.skip('Worker bootstrapping works differently -> different async IDs'); +} const hooks = initHooks(); diff --git a/test/async-hooks/test-promise.chain-promise-before-init-hooks.js b/test/async-hooks/test-promise.chain-promise-before-init-hooks.js index 52a312dbdfe196..c5e67b6f94ca68 100644 --- a/test/async-hooks/test-promise.chain-promise-before-init-hooks.js +++ b/test/async-hooks/test-promise.chain-promise-before-init-hooks.js @@ -4,9 +4,11 @@ const common = require('../common'); const assert = require('assert'); const initHooks = require('./init-hooks'); const { checkInvocations } = require('./hook-checks'); +const { isMainThread } = require('worker_threads'); -if (!common.isMainThread) +if (!isMainThread) { common.skip('Worker bootstrapping works differently -> different async IDs'); +} const p = new Promise(common.mustCall(function executor(resolve) { resolve(5); diff --git a/test/async-hooks/test-promise.js b/test/async-hooks/test-promise.js index 417cb3c80d6298..554c3ae7dd711e 100644 --- a/test/async-hooks/test-promise.js +++ b/test/async-hooks/test-promise.js @@ -5,9 +5,11 @@ const common = require('../common'); const assert = require('assert'); const initHooks = require('./init-hooks'); const { checkInvocations } = require('./hook-checks'); +const { isMainThread } = require('worker_threads'); -if (!common.isMainThread) +if (!isMainThread) { common.skip('Worker bootstrapping works differently -> different async IDs'); +} const hooks = initHooks(); diff --git a/test/async-hooks/test-signalwrap.js b/test/async-hooks/test-signalwrap.js index 4584d140ce1d0f..60adaedd476f27 100644 --- a/test/async-hooks/test-signalwrap.js +++ b/test/async-hooks/test-signalwrap.js @@ -1,10 +1,13 @@ 'use strict'; const common = require('../common'); -if (common.isWindows) +if (common.isWindows) { common.skip('no signals in Windows'); -if (!common.isMainThread) +} +const { isMainThread } = require('worker_threads'); +if (!isMainThread) { common.skip('No signal handling available in Workers'); +} const assert = require('assert'); const initHooks = require('./init-hooks'); diff --git a/test/async-hooks/test-statwatcher.js b/test/async-hooks/test-statwatcher.js index f3c0e74355eeba..8f4fb2175885f3 100644 --- a/test/async-hooks/test-statwatcher.js +++ b/test/async-hooks/test-statwatcher.js @@ -7,8 +7,11 @@ const initHooks = require('./init-hooks'); const { checkInvocations } = require('./hook-checks'); const fs = require('fs'); -if (!common.isMainThread) +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { common.skip('Worker bootstrapping works differently -> different async IDs'); +} tmpdir.refresh(); diff --git a/test/async-hooks/test-unhandled-rejection-context.js b/test/async-hooks/test-unhandled-rejection-context.js index 8404cf71f0db6f..168b51a3331f7f 100644 --- a/test/async-hooks/test-unhandled-rejection-context.js +++ b/test/async-hooks/test-unhandled-rejection-context.js @@ -5,9 +5,11 @@ const common = require('../common'); const assert = require('assert'); const initHooks = require('./init-hooks'); const async_hooks = require('async_hooks'); +const { isMainThread } = require('worker_threads'); -if (!common.isMainThread) +if (!isMainThread) { common.skip('Worker bootstrapping works differently -> different async IDs'); +} const promiseAsyncIds = []; const hooks = initHooks({ diff --git a/test/benchmark/test-benchmark-napi.js b/test/benchmark/test-benchmark-napi.js index 7164efe3d4e718..518e10a5111a5b 100644 --- a/test/benchmark/test-benchmark-napi.js +++ b/test/benchmark/test-benchmark-napi.js @@ -6,7 +6,9 @@ if (common.isWindows) { common.skip('vcbuild.bat doesn\'t build the n-api benchmarks yet'); } -if (!common.isMainThread) { +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { common.skip('addons are not supported in workers'); } diff --git a/test/common/README.md b/test/common/README.md index c3c44e32b3788c..887dee2783ad72 100644 --- a/test/common/README.md +++ b/test/common/README.md @@ -102,10 +102,6 @@ symlinks ([SeCreateSymbolicLinkPrivilege](https://msdn.microsoft.com/en-us/library/windows/desktop/bb530716\(v=vs.85\).aspx)). On non-Windows platforms, this always returns `true`. -### `createZeroFilledFile(filename)` - -Creates a 10 MiB file of all null characters. - ### `enoughTestMem` * [\][] @@ -257,10 +253,6 @@ Platform check for Advanced Interactive eXecutive (AIX). Attempts to 'kill' `pid` -### `isDumbTerminal` - -* [\][] - ### `isFreeBSD` * [\][] @@ -456,10 +448,6 @@ will not be run. Logs '1..0 # Skipped: ' + `msg` and exits with exit code `0`. -### `skipIfDumbTerminal()` - -Skip the rest of the tests if the current terminal is a dumb terminal - ### `skipIfEslintMissing()` Skip the rest of the tests in the current file when `ESLint` is not available @@ -475,11 +463,6 @@ was disabled at compile time. Skip the rest of the tests in the current file when the Node.js executable was compiled with a pointer size smaller than 64 bits. -### `skipIfWorker()` - -Skip the rest of the tests in the current file when not running on a main -thread. - ## ArrayStream module The `ArrayStream` module provides a simple `Stream` that pushes elements from diff --git a/test/common/index.js b/test/common/index.js index 238d66e96fe257..6086d584f0b595 100644 --- a/test/common/index.js +++ b/test/common/index.js @@ -139,8 +139,6 @@ const isPi = (() => { } })(); -const isDumbTerminal = process.env.TERM === 'dumb'; - // When using high concurrency or in the CI we need much more time for each connection attempt net.setDefaultAutoSelectFamilyAttemptTimeout(platformTimeout(net.getDefaultAutoSelectFamilyAttemptTimeout() * 10)); const defaultAutoSelectFamilyAttemptTimeout = net.getDefaultAutoSelectFamilyAttemptTimeout(); @@ -243,13 +241,6 @@ function childShouldThrowAndAbort() { }); } -function createZeroFilledFile(filename) { - const fd = fs.openSync(filename, 'w'); - fs.ftruncateSync(fd, 10 * 1024 * 1024); - fs.closeSync(fd); -} - - const pwdCommand = isWindows ? ['cmd.exe', ['/d', '/c', 'cd']] : ['pwd', []]; @@ -716,12 +707,6 @@ function skipIf32Bits() { } } -function skipIfWorker() { - if (!isMainThread) { - skip('This test only works on a main thread'); - } -} - function getArrayBufferViews(buf) { const { buffer, byteOffset, byteLength } = buf; @@ -806,12 +791,6 @@ function invalidArgTypeHelper(input) { return ` Received type ${typeof input} (${inspected})`; } -function skipIfDumbTerminal() { - if (isDumbTerminal) { - skip('skipping - dumb terminal'); - } -} - function requireNoPackageJSONAbove(dir = __dirname) { let possiblePackage = path.join(dir, '..', 'package.json'); let lastPackage = null; @@ -882,45 +861,6 @@ function escapePOSIXShell(cmdParts, ...args) { return [cmd, { env }]; }; -function getPrintedStackTrace(stderr) { - const lines = stderr.split('\n'); - - let state = 'initial'; - const result = { - message: [], - nativeStack: [], - jsStack: [], - }; - for (let i = 0; i < lines.length; ++i) { - const line = lines[i].trim(); - if (line.length === 0) { - continue; // Skip empty lines. - } - - switch (state) { - case 'initial': - result.message.push(line); - if (line.includes('Native stack trace')) { - state = 'native-stack'; - } else { - result.message.push(line); - } - break; - case 'native-stack': - if (line.includes('JavaScript stack trace')) { - state = 'js-stack'; - } else { - result.nativeStack.push(line); - } - break; - case 'js-stack': - result.jsStack.push(line); - break; - } - } - return result; -} - /** * Check the exports of require(esm). * TODO(joyeecheung): use it in all the test-require-module-* tests to minimize changes @@ -943,7 +883,6 @@ const common = { buildType, canCreateSymLink, childShouldThrowAndAbort, - createZeroFilledFile, defaultAutoSelectFamilyAttemptTimeout, escapePOSIXShell, expectsError, @@ -951,7 +890,6 @@ const common = { expectWarning, getArrayBufferViews, getBufferSources, - getPrintedStackTrace, getTTYfd, hasIntl, hasCrypto, @@ -960,10 +898,8 @@ const common = { isAlive, isASan, isDebug, - isDumbTerminal, isFreeBSD, isLinux, - isMainThread, isOpenBSD, isMacOS, isPi, @@ -985,10 +921,8 @@ const common = { runWithInvalidFD, skip, skipIf32Bits, - skipIfDumbTerminal, skipIfEslintMissing, skipIfInspectorDisabled, - skipIfWorker, spawnPromisified, get enoughTestMem() { diff --git a/test/common/index.mjs b/test/common/index.mjs index aafef1453bd78a..dd0adadcb28d38 100644 --- a/test/common/index.mjs +++ b/test/common/index.mjs @@ -8,7 +8,6 @@ const { buildType, canCreateSymLink, childShouldThrowAndAbort, - createZeroFilledFile, enoughTestMem, escapePOSIXShell, expectsError, @@ -21,12 +20,10 @@ const { hasIPv6, isAIX, isAlive, - isDumbTerminal, isFreeBSD, isIBMi, isInsideDirWithUnusualChars, isLinux, - isMainThread, isOpenBSD, isMacOS, isSunOS, @@ -45,7 +42,6 @@ const { runWithInvalidFD, skip, skipIf32Bits, - skipIfDumbTerminal, skipIfEslintMissing, skipIfInspectorDisabled, spawnPromisified, @@ -59,7 +55,6 @@ export { canCreateSymLink, childShouldThrowAndAbort, createRequire, - createZeroFilledFile, enoughTestMem, escapePOSIXShell, expectsError, @@ -73,12 +68,10 @@ export { hasIPv6, isAIX, isAlive, - isDumbTerminal, isFreeBSD, isIBMi, isInsideDirWithUnusualChars, isLinux, - isMainThread, isOpenBSD, isMacOS, isSunOS, @@ -97,7 +90,6 @@ export { runWithInvalidFD, skip, skipIf32Bits, - skipIfDumbTerminal, skipIfEslintMissing, skipIfInspectorDisabled, spawnPromisified, diff --git a/test/es-module/test-esm-resolve-type.mjs b/test/es-module/test-esm-resolve-type.mjs index 7ba1fcbf1437ce..b005ada776f5d3 100644 --- a/test/es-module/test-esm-resolve-type.mjs +++ b/test/es-module/test-esm-resolve-type.mjs @@ -13,8 +13,10 @@ import path from 'path'; import fs from 'fs'; import url from 'url'; import process from 'process'; +import { isMainThread } from 'worker_threads'; -if (!common.isMainThread) { + +if (!isMainThread) { common.skip( 'test-esm-resolve-type.mjs: process.chdir is not available in Workers' ); diff --git a/test/es-module/test-vm-main-context-default-loader.js b/test/es-module/test-vm-main-context-default-loader.js index f9edc761465d96..bda954be6ebf97 100644 --- a/test/es-module/test-vm-main-context-default-loader.js +++ b/test/es-module/test-vm-main-context-default-loader.js @@ -3,7 +3,11 @@ const common = require('../common'); // Can't process.chdir() in worker. -common.skipIfWorker(); +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { + common.skip('This test only works on a main thread'); +} const tmpdir = require('../common/tmpdir'); const fixtures = require('../common/fixtures'); diff --git a/test/fixtures/permission/fs-write.js b/test/fixtures/permission/fs-write.js index 0c0ec72602041a..83fe3d234db290 100644 --- a/test/fixtures/permission/fs-write.js +++ b/test/fixtures/permission/fs-write.js @@ -1,7 +1,11 @@ 'use strict'; const common = require('../../common'); -common.skipIfWorker(); +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { + common.skip('This test only works on a main thread'); +} const assert = require('assert'); const fs = require('fs'); @@ -553,4 +557,4 @@ const relativeProtectedFolder = process.env.RELATIVEBLOCKEDFOLDER; }, { code: 'ERR_ACCESS_DENIED', }); -} \ No newline at end of file +} diff --git a/test/fixtures/permission/processbinding.js b/test/fixtures/permission/processbinding.js index bdb958fb01b5ca..69e2fac5d7f151 100644 --- a/test/fixtures/permission/processbinding.js +++ b/test/fixtures/permission/processbinding.js @@ -1,5 +1,9 @@ const common = require('../../common'); -common.skipIfWorker(); +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { + common.skip('This test only works on a main thread'); +} const assert = require('assert'); diff --git a/test/internet/test-trace-events-dns.js b/test/internet/test-trace-events-dns.js index c18a49bc9496c8..c5df4751374399 100644 --- a/test/internet/test-trace-events-dns.js +++ b/test/internet/test-trace-events-dns.js @@ -5,9 +5,11 @@ const cp = require('child_process'); const tmpdir = require('../common/tmpdir'); const fs = require('fs'); const util = require('util'); +const { isMainThread } = require('worker_threads'); -if (!common.isMainThread) +if (!isMainThread) { common.skip('process.chdir is not available in Workers'); +} const traceFile = 'node_trace.1.log'; diff --git a/test/parallel/test-async-hooks-disable-during-promise.js b/test/parallel/test-async-hooks-disable-during-promise.js index 6b9b53bd30f0f5..a25dae51e1f82d 100644 --- a/test/parallel/test-async-hooks-disable-during-promise.js +++ b/test/parallel/test-async-hooks-disable-during-promise.js @@ -1,9 +1,11 @@ 'use strict'; const common = require('../common'); const async_hooks = require('async_hooks'); +const { isMainThread } = require('worker_threads'); -if (!common.isMainThread) +if (!isMainThread) { common.skip('Worker bootstrapping works differently -> different AsyncWraps'); +} const hook = async_hooks.createHook({ init: common.mustCall(2), diff --git a/test/parallel/test-async-hooks-promise-triggerid.js b/test/parallel/test-async-hooks-promise-triggerid.js index b860d60999e1ef..89e5bc1464f8d5 100644 --- a/test/parallel/test-async-hooks-promise-triggerid.js +++ b/test/parallel/test-async-hooks-promise-triggerid.js @@ -2,9 +2,11 @@ const common = require('../common'); const assert = require('assert'); const async_hooks = require('async_hooks'); +const { isMainThread } = require('worker_threads'); -if (!common.isMainThread) +if (!isMainThread) { common.skip('Worker bootstrapping works differently -> different async IDs'); +} const promiseAsyncIds = []; diff --git a/test/parallel/test-async-hooks-promise.js b/test/parallel/test-async-hooks-promise.js index 9db510e329ffad..74f72a188240a0 100644 --- a/test/parallel/test-async-hooks-promise.js +++ b/test/parallel/test-async-hooks-promise.js @@ -2,9 +2,11 @@ const common = require('../common'); const assert = require('assert'); const async_hooks = require('async_hooks'); +const { isMainThread } = require('worker_threads'); -if (!common.isMainThread) +if (!isMainThread) { common.skip('Worker bootstrapping works differently -> different async IDs'); +} const initCalls = []; const resolveCalls = []; diff --git a/test/parallel/test-async-hooks-top-level-clearimmediate.js b/test/parallel/test-async-hooks-top-level-clearimmediate.js index cc5fcf48eb50b3..fd91fefa9c4bce 100644 --- a/test/parallel/test-async-hooks-top-level-clearimmediate.js +++ b/test/parallel/test-async-hooks-top-level-clearimmediate.js @@ -5,9 +5,11 @@ const common = require('../common'); const assert = require('assert'); const async_hooks = require('async_hooks'); +const { isMainThread } = require('worker_threads'); -if (!common.isMainThread) +if (!isMainThread) { common.skip('Worker bootstrapping works differently -> different async IDs'); +} let seenId, seenResource; diff --git a/test/parallel/test-async-wrap-promise-after-enabled.js b/test/parallel/test-async-wrap-promise-after-enabled.js index 0d58cbd653868b..cbca873574c1f8 100644 --- a/test/parallel/test-async-wrap-promise-after-enabled.js +++ b/test/parallel/test-async-wrap-promise-after-enabled.js @@ -4,9 +4,11 @@ const common = require('../common'); const assert = require('assert'); +const { isMainThread } = require('worker_threads'); -if (!common.isMainThread) +if (!isMainThread) { common.skip('Worker bootstrapping works differently -> different timing'); +} const async_hooks = require('async_hooks'); diff --git a/test/parallel/test-bootstrap-modules.js b/test/parallel/test-bootstrap-modules.js index 12adfaa7f5c5e1..9d3802e2f110fa 100644 --- a/test/parallel/test-bootstrap-modules.js +++ b/test/parallel/test-bootstrap-modules.js @@ -116,7 +116,9 @@ expected.atRunTime = new Set([ 'NativeModule internal/modules/esm/utils', ]); -if (common.isMainThread) { +const { isMainThread } = require('worker_threads'); + +if (isMainThread) { [ 'NativeModule url', ].forEach(expected.beforePreExec.add.bind(expected.beforePreExec)); @@ -187,7 +189,7 @@ function err(message) { } } -if (common.isMainThread) { +if (isMainThread) { const missing = expected.beforePreExec.difference(actual.beforePreExec); const extra = actual.beforePreExec.difference(expected.beforePreExec); if (missing.size !== 0) { @@ -213,10 +215,10 @@ if (common.isMainThread) { } } -if (!common.isMainThread) { +if (!isMainThread) { // For workers, just merge beforePreExec into atRunTime for now. // When we start adding modules to the worker snapshot, this branch - // can be removed and we can just remove the common.isMainThread + // can be removed and we can just remove the isMainThread // conditions. expected.beforePreExec.forEach(expected.atRunTime.add.bind(expected.atRunTime)); actual.beforePreExec.forEach(actual.atRunTime.add.bind(actual.atRunTime)); diff --git a/test/parallel/test-child-process-validate-stdio.js b/test/parallel/test-child-process-validate-stdio.js index d5958c694ff6ff..5ba6f0fd123cc1 100644 --- a/test/parallel/test-child-process-validate-stdio.js +++ b/test/parallel/test-child-process-validate-stdio.js @@ -43,7 +43,9 @@ assert.throws(() => getValidStdio(stdio2, true), assert.throws(() => getValidStdio(stdio), expectedError); } -if (common.isMainThread) { +const { isMainThread } = require('worker_threads'); + +if (isMainThread) { const stdio3 = [process.stdin, process.stdout, process.stderr]; const result = getValidStdio(stdio3, false); assert.deepStrictEqual(result, { diff --git a/test/parallel/test-cluster-net-listen-relative-path.js b/test/parallel/test-cluster-net-listen-relative-path.js index bb4d0b90f203e6..16d2bf5c836b53 100644 --- a/test/parallel/test-cluster-net-listen-relative-path.js +++ b/test/parallel/test-cluster-net-listen-relative-path.js @@ -1,11 +1,16 @@ 'use strict'; const common = require('../common'); -if (common.isWindows) +if (common.isWindows) { common.skip('On Windows named pipes live in their own ' + 'filesystem and don\'t have a ~100 byte limit'); -if (!common.isMainThread) +} + +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { common.skip('process.chdir is not available in Workers'); +} const assert = require('assert'); const cluster = require('cluster'); diff --git a/test/parallel/test-code-cache.js b/test/parallel/test-code-cache.js index 1c768d664c8a18..576f713af1b02a 100644 --- a/test/parallel/test-code-cache.js +++ b/test/parallel/test-code-cache.js @@ -5,7 +5,8 @@ // and the cache is used when built in modules are compiled. // Otherwise, verifies that no cache is used when compiling builtins. -const { isMainThread } = require('../common'); +require('../common'); +const { isMainThread } = require('worker_threads'); const assert = require('assert'); const { internalBinding diff --git a/test/parallel/test-console-clear.js b/test/parallel/test-console-clear.js index 5975602547922a..8ded51595f654e 100644 --- a/test/parallel/test-console-clear.js +++ b/test/parallel/test-console-clear.js @@ -1,6 +1,6 @@ 'use strict'; -const common = require('../common'); +require('../common'); const assert = require('assert'); const stdoutWrite = process.stdout.write; @@ -18,7 +18,7 @@ function doTest(isTTY, check) { } // Fake TTY -if (!common.isDumbTerminal) { +if (process.env.TERM !== 'dumb') { doTest(true, check); } doTest(false, ''); diff --git a/test/parallel/test-console.js b/test/parallel/test-console.js index 85b46a7c992552..e25ac7178722c0 100644 --- a/test/parallel/test-console.js +++ b/test/parallel/test-console.js @@ -31,10 +31,12 @@ const { restoreStderr } = require('../common/hijackstdio'); +const { isMainThread } = require('worker_threads'); + assert.ok(process.stdout.writable); assert.ok(process.stderr.writable); // Support legacy API -if (common.isMainThread) { +if (isMainThread) { assert.strictEqual(typeof process.stdout.fd, 'number'); assert.strictEqual(typeof process.stderr.fd, 'number'); } diff --git a/test/parallel/test-crypto-no-algorithm.js b/test/parallel/test-crypto-no-algorithm.js index 06124e3d465e41..bb5b81e119c87d 100644 --- a/test/parallel/test-crypto-no-algorithm.js +++ b/test/parallel/test-crypto-no-algorithm.js @@ -11,8 +11,9 @@ if (!hasOpenSSL3) const assert = require('node:assert/strict'); const crypto = require('node:crypto'); +const { isMainThread } = require('worker_threads'); -if (common.isMainThread) { +if (isMainThread) { // TODO(richardlau): Decide if `crypto.setFips` should error if the // provider named "fips" is not available. crypto.setFips(1); diff --git a/test/parallel/test-cwd-enoent-preload.js b/test/parallel/test-cwd-enoent-preload.js index 21b20d6d035672..a7841e984d0eab 100644 --- a/test/parallel/test-cwd-enoent-preload.js +++ b/test/parallel/test-cwd-enoent-preload.js @@ -1,10 +1,15 @@ 'use strict'; const common = require('../common'); // Fails with EINVAL on SmartOS, EBUSY on Windows, EBUSY on AIX. -if (common.isSunOS || common.isWindows || common.isAIX || common.isIBMi) +if (common.isSunOS || common.isWindows || common.isAIX || common.isIBMi) { common.skip('cannot rmdir current working directory'); -if (!common.isMainThread) +} + +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { common.skip('process.chdir is not available in Workers'); +} const assert = require('assert'); const fs = require('fs'); diff --git a/test/parallel/test-cwd-enoent-repl.js b/test/parallel/test-cwd-enoent-repl.js index 0a61cbfbced9b4..fcb08c004f345c 100644 --- a/test/parallel/test-cwd-enoent-repl.js +++ b/test/parallel/test-cwd-enoent-repl.js @@ -1,10 +1,15 @@ 'use strict'; const common = require('../common'); // Fails with EINVAL on SmartOS, EBUSY on Windows, EBUSY on AIX. -if (common.isSunOS || common.isWindows || common.isAIX || common.isIBMi) +if (common.isSunOS || common.isWindows || common.isAIX || common.isIBMi) { common.skip('cannot rmdir current working directory'); -if (!common.isMainThread) +} + +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { common.skip('process.chdir is not available in Workers'); +} const assert = require('assert'); const fs = require('fs'); diff --git a/test/parallel/test-cwd-enoent.js b/test/parallel/test-cwd-enoent.js index 876888bc2be518..ca8b460835d45a 100644 --- a/test/parallel/test-cwd-enoent.js +++ b/test/parallel/test-cwd-enoent.js @@ -1,10 +1,15 @@ 'use strict'; const common = require('../common'); // Fails with EINVAL on SmartOS, EBUSY on Windows, EBUSY on AIX. -if (common.isSunOS || common.isWindows || common.isAIX || common.isIBMi) +if (common.isSunOS || common.isWindows || common.isAIX || common.isIBMi) { common.skip('cannot rmdir current working directory'); -if (!common.isMainThread) +} + +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { common.skip('process.chdir is not available in Workers'); +} const assert = require('assert'); const fs = require('fs'); diff --git a/test/parallel/test-fs-mkdir.js b/test/parallel/test-fs-mkdir.js index 89b8b436d5c9f4..f7685c7de0a962 100644 --- a/test/parallel/test-fs-mkdir.js +++ b/test/parallel/test-fs-mkdir.js @@ -24,6 +24,7 @@ const common = require('../common'); const assert = require('assert'); const fs = require('fs'); const path = require('path'); +const { isMainThread } = require('worker_threads'); const tmpdir = require('../common/tmpdir'); tmpdir.refresh(); @@ -217,7 +218,7 @@ function nextdir() { // mkdirpSync dirname loop // XXX: windows and smartos have issues removing a directory that you're in. -if (common.isMainThread && (common.isLinux || common.isMacOS)) { +if (isMainThread && (common.isLinux || common.isMacOS)) { const pathname = tmpdir.resolve(nextdir()); fs.mkdirSync(pathname); process.chdir(pathname); diff --git a/test/parallel/test-fs-realpath.js b/test/parallel/test-fs-realpath.js index d944195de3de0c..69237e3974e5b0 100644 --- a/test/parallel/test-fs-realpath.js +++ b/test/parallel/test-fs-realpath.js @@ -23,9 +23,11 @@ const common = require('../common'); const fixtures = require('../common/fixtures'); const tmpdir = require('../common/tmpdir'); +const { isMainThread } = require('worker_threads'); -if (!common.isMainThread) +if (!isMainThread) { common.skip('process.chdir is not available in Workers'); +} const assert = require('assert'); const fs = require('fs'); diff --git a/test/parallel/test-fs-whatwg-url.js b/test/parallel/test-fs-whatwg-url.js index 7401ed7e76ecd1..2d5664cd12015c 100644 --- a/test/parallel/test-fs-whatwg-url.js +++ b/test/parallel/test-fs-whatwg-url.js @@ -5,6 +5,8 @@ const fixtures = require('../common/fixtures'); const assert = require('assert'); const fs = require('fs'); const tmpdir = require('../common/tmpdir'); +const { isMainThread } = require('worker_threads'); + tmpdir.refresh(); const url = fixtures.fileURL('a.js'); @@ -86,7 +88,7 @@ if (common.isWindows) { // Test that strings are interpreted as paths and not as URL // Can't use process.chdir in Workers // Please avoid testing fs.rmdir('file:') or using it as cleanup -if (common.isMainThread && !common.isWindows) { +if (isMainThread && !common.isWindows) { const oldCwd = process.cwd(); process.chdir(tmpdir.path); diff --git a/test/parallel/test-fs-write-file-sync.js b/test/parallel/test-fs-write-file-sync.js index 4ead91530bb748..e5fbe32eab6d14 100644 --- a/test/parallel/test-fs-write-file-sync.js +++ b/test/parallel/test-fs-write-file-sync.js @@ -21,9 +21,11 @@ 'use strict'; const common = require('../common'); +const { isMainThread } = require('worker_threads'); -if (!common.isMainThread) +if (!isMainThread) { common.skip('Setting process.umask is not supported in Workers'); +} const assert = require('assert'); const fs = require('fs'); diff --git a/test/parallel/test-http-chunk-problem.js b/test/parallel/test-http-chunk-problem.js index 3629b7576600e8..90c54b8f5c7dcb 100644 --- a/test/parallel/test-http-chunk-problem.js +++ b/test/parallel/test-http-chunk-problem.js @@ -1,9 +1,12 @@ 'use strict'; // http://groups.google.com/group/nodejs/browse_thread/thread/f66cd3c960406919 const common = require('../common'); -if (!common.hasCrypto) + +if (!common.hasCrypto) { common.skip('missing crypto'); +} +const fs = require('fs'); const assert = require('assert'); if (process.argv[2] === 'request') { @@ -73,7 +76,11 @@ function executeRequest(cb) { tmpdir.refresh(); -common.createZeroFilledFile(filename); + +// Create a zero-filled file. +const fd = fs.openSync(filename, 'w'); +fs.ftruncateSync(fd, 10 * 1024 * 1024); +fs.closeSync(fd); server = http.createServer(function(req, res) { res.writeHead(200); diff --git a/test/parallel/test-icu-env.js b/test/parallel/test-icu-env.js index afa36132f60e8d..26075a3d0acec2 100644 --- a/test/parallel/test-icu-env.js +++ b/test/parallel/test-icu-env.js @@ -4,7 +4,7 @@ const assert = require('assert'); const { execFileSync } = require('child_process'); const { readFileSync, globSync } = require('fs'); const { path } = require('../common/fixtures'); - +const { isMainThread } = require('worker_threads'); // This test checks for regressions in environment variable handling and // caching, but the localization data originated from ICU might change @@ -169,7 +169,7 @@ if (isMockable) { // Tests with process.env mutated inside { // process.env.TZ is not intercepted in Workers - if (common.isMainThread) { + if (isMainThread) { assert.strictEqual( isSet(zones.map((TZ) => runEnvInside({ TZ }, () => new Date(333333333333).toString()))), true diff --git a/test/parallel/test-inspector-already-activated-cli.js b/test/parallel/test-inspector-already-activated-cli.js index ba76d5168c14b9..9de226cedca60c 100644 --- a/test/parallel/test-inspector-already-activated-cli.js +++ b/test/parallel/test-inspector-already-activated-cli.js @@ -3,7 +3,12 @@ const common = require('../common'); common.skipIfInspectorDisabled(); -common.skipIfWorker(); + +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { + common.skip('This test only works on a main thread'); +} const assert = require('assert'); const inspector = require('inspector'); diff --git a/test/parallel/test-inspector-async-hook-after-done.js b/test/parallel/test-inspector-async-hook-after-done.js index 9f96fdb7b0da84..b49fe32982e132 100644 --- a/test/parallel/test-inspector-async-hook-after-done.js +++ b/test/parallel/test-inspector-async-hook-after-done.js @@ -3,7 +3,12 @@ const common = require('../common'); common.skipIfInspectorDisabled(); -common.skipIfWorker(); + +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { + common.skip('This test only works on a main thread'); +} const assert = require('assert'); const { Worker } = require('worker_threads'); diff --git a/test/parallel/test-inspector-async-hook-setup-at-signal.js b/test/parallel/test-inspector-async-hook-setup-at-signal.js index 43f50d00615723..64a3835e415746 100644 --- a/test/parallel/test-inspector-async-hook-setup-at-signal.js +++ b/test/parallel/test-inspector-async-hook-setup-at-signal.js @@ -6,7 +6,11 @@ common.skipIf32Bits(); const { NodeInstance } = require('../common/inspector-helper.js'); const assert = require('assert'); -common.skipIfWorker(); // Signal starts a server for a main thread inspector +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { + common.skip('This test only works on a main thread'); +} const script = ` process._rawDebug('Waiting until a signal enables the inspector...'); diff --git a/test/parallel/test-inspector-connect-main-thread.js b/test/parallel/test-inspector-connect-main-thread.js index b724bf3cd9d62f..2281b5efcf3ed8 100644 --- a/test/parallel/test-inspector-connect-main-thread.js +++ b/test/parallel/test-inspector-connect-main-thread.js @@ -10,8 +10,8 @@ const { pathToFileURL } = require('url'); const { isMainThread, parentPort, Worker, workerData } = require('worker_threads'); -if (!workerData) { - common.skipIfWorker(); +if (!workerData && !isMainThread) { + common.skip('This test only works on a main thread'); } function toDebug() { diff --git a/test/parallel/test-inspector-connect-to-main-thread.js b/test/parallel/test-inspector-connect-to-main-thread.js index 7254145a2733f0..9244a85f21b15a 100644 --- a/test/parallel/test-inspector-connect-to-main-thread.js +++ b/test/parallel/test-inspector-connect-to-main-thread.js @@ -6,8 +6,8 @@ common.skipIfInspectorDisabled(); const { Session } = require('inspector'); const { Worker, isMainThread, workerData } = require('worker_threads'); -if (!workerData) { - common.skipIfWorker(); +if (!workerData && !isMainThread) { + common.skip('This test only works on a main thread'); } if (isMainThread) { diff --git a/test/parallel/test-inspector-contexts.js b/test/parallel/test-inspector-contexts.js index 9cdf2d0017c4be..e7bdc53f8cd576 100644 --- a/test/parallel/test-inspector-contexts.js +++ b/test/parallel/test-inspector-contexts.js @@ -8,6 +8,7 @@ common.skipIfInspectorDisabled(); const assert = require('assert'); const vm = require('vm'); const { Session } = require('inspector'); +const { isMainThread } = require('worker_threads'); const session = new Session(); session.connect(); @@ -34,7 +35,7 @@ async function testContextCreatedAndDestroyed() { assert.strictEqual(name.includes(`[${process.pid}]`), true); } else { let expects = `${process.argv0}[${process.pid}]`; - if (!common.isMainThread) { + if (!isMainThread) { expects = `Worker[${require('worker_threads').threadId}]`; } assert.strictEqual(expects, name); diff --git a/test/parallel/test-inspector-exit-worker-in-wait-for-connection.js b/test/parallel/test-inspector-exit-worker-in-wait-for-connection.js index 4fcbb092fd23cf..9215d4969fb92f 100644 --- a/test/parallel/test-inspector-exit-worker-in-wait-for-connection.js +++ b/test/parallel/test-inspector-exit-worker-in-wait-for-connection.js @@ -3,9 +3,15 @@ const common = require('../common'); common.skipIfInspectorDisabled(); -const { parentPort, workerData, Worker } = require('node:worker_threads'); -if (!workerData) { - common.skipIfWorker(); +const { + isMainThread, + parentPort, + workerData, + Worker, +} = require('node:worker_threads'); + +if (!workerData && !isMainThread) { + common.skip('This test only works on a main thread'); } const inspector = require('node:inspector'); diff --git a/test/parallel/test-inspector-exit-worker-in-wait-for-connection2.js b/test/parallel/test-inspector-exit-worker-in-wait-for-connection2.js index fb13fc3f969304..cf485ae3a4318f 100644 --- a/test/parallel/test-inspector-exit-worker-in-wait-for-connection2.js +++ b/test/parallel/test-inspector-exit-worker-in-wait-for-connection2.js @@ -3,9 +3,9 @@ const common = require('../common'); common.skipIfInspectorDisabled(); -const { workerData, Worker } = require('node:worker_threads'); -if (!workerData) { - common.skipIfWorker(); +const { isMainThread, workerData, Worker } = require('node:worker_threads'); +if (!workerData && !isMainThread) { + common.skip('This test only works on a main thread'); } const assert = require('node:assert'); diff --git a/test/parallel/test-inspector-open-coverage.js b/test/parallel/test-inspector-open-coverage.js index 259049c36822ab..33f50bfc3f53c4 100644 --- a/test/parallel/test-inspector-open-coverage.js +++ b/test/parallel/test-inspector-open-coverage.js @@ -7,7 +7,12 @@ const fixtures = require('../common/fixtures'); const tmpdir = require('../common/tmpdir'); common.skipIfInspectorDisabled(); -common.skipIfWorker(); + +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { + common.skip('This test only works on a main thread'); +} tmpdir.refresh(); diff --git a/test/parallel/test-inspector-open-port-integer-overflow.js b/test/parallel/test-inspector-open-port-integer-overflow.js index 0f9a4799d0642a..a1b5c640c4c18d 100644 --- a/test/parallel/test-inspector-open-port-integer-overflow.js +++ b/test/parallel/test-inspector-open-port-integer-overflow.js @@ -5,7 +5,12 @@ const common = require('../common'); common.skipIfInspectorDisabled(); -common.skipIfWorker(); + +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { + common.skip('This test only works on a main thread'); +} const assert = require('assert'); const inspector = require('inspector'); diff --git a/test/parallel/test-inspector-overwrite-config.js b/test/parallel/test-inspector-overwrite-config.js index c20df083256120..53599b31df8acc 100644 --- a/test/parallel/test-inspector-overwrite-config.js +++ b/test/parallel/test-inspector-overwrite-config.js @@ -13,9 +13,11 @@ const common = require('../common'); const assert = require('assert'); +const { isMainThread } = require('worker_threads'); -if (!common.isMainThread) +if (!isMainThread) { common.skip('--require does not work with Workers'); +} const inspector = require('inspector'); const msg = 'Test inspector logging'; diff --git a/test/parallel/test-inspector-port-zero-cluster.js b/test/parallel/test-inspector-port-zero-cluster.js index 8e2db0b69d5ca0..5ee7bcf7417345 100644 --- a/test/parallel/test-inspector-port-zero-cluster.js +++ b/test/parallel/test-inspector-port-zero-cluster.js @@ -3,7 +3,12 @@ const common = require('../common'); common.skipIfInspectorDisabled(); -common.skipIfWorker(); + +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { + common.skip('This test only works on a main thread'); +} // Assert that even when started with `--inspect=0` workers are assigned // consecutive (i.e. deterministically predictable) debug ports diff --git a/test/parallel/test-inspector-tracing-domain.js b/test/parallel/test-inspector-tracing-domain.js index f5ac6875a0f643..aa31d63a01577d 100644 --- a/test/parallel/test-inspector-tracing-domain.js +++ b/test/parallel/test-inspector-tracing-domain.js @@ -3,7 +3,13 @@ const common = require('../common'); common.skipIfInspectorDisabled(); -common.skipIfWorker(); // https://github.com/nodejs/node/issues/22767 + +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { + // https://github.com/nodejs/node/issues/22767 + common.skip('This test only works on a main thread'); +} const assert = require('assert'); const { Session } = require('inspector'); diff --git a/test/parallel/test-inspector-workers-flat-list.js b/test/parallel/test-inspector-workers-flat-list.js index 9f6495d10fb147..a7b57fbb0a353b 100644 --- a/test/parallel/test-inspector-workers-flat-list.js +++ b/test/parallel/test-inspector-workers-flat-list.js @@ -6,8 +6,8 @@ common.skipIfInspectorDisabled(); const { Worker, isMainThread, parentPort, workerData } = require('worker_threads'); -if (isMainThread || workerData !== 'launched by test') { - common.skipIfWorker(); +if (!isMainThread || workerData !== 'launched by test') { + common.skip('This test only works on a main thread'); } const { Session } = require('inspector'); diff --git a/test/parallel/test-internal-module-require.js b/test/parallel/test-internal-module-require.js index c6e2057d3da1ee..b4f772b09be98a 100644 --- a/test/parallel/test-internal-module-require.js +++ b/test/parallel/test-internal-module-require.js @@ -8,8 +8,9 @@ // 3. Deprecated modules are properly deprecated. const common = require('../common'); +const { isMainThread } = require('worker_threads'); -if (!common.isMainThread) { +if (!isMainThread) { common.skip('Cannot test the existence of --expose-internals from worker'); } diff --git a/test/parallel/test-performance-nodetiming-uvmetricsinfo.js b/test/parallel/test-performance-nodetiming-uvmetricsinfo.js index 3d32e0deb72e94..b67682b0ff3559 100644 --- a/test/parallel/test-performance-nodetiming-uvmetricsinfo.js +++ b/test/parallel/test-performance-nodetiming-uvmetricsinfo.js @@ -1,7 +1,11 @@ 'use strict'; const common = require('../common'); -common.skipIfWorker(); +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { + common.skip('This test only works on a main thread'); +} const { spawnSync } = require('node:child_process'); const assert = require('node:assert'); diff --git a/test/parallel/test-permission-allow-addons-cli.js b/test/parallel/test-permission-allow-addons-cli.js index 484f16e0acb3b5..342bdb6bc01e35 100644 --- a/test/parallel/test-permission-allow-addons-cli.js +++ b/test/parallel/test-permission-allow-addons-cli.js @@ -2,7 +2,11 @@ 'use strict'; const common = require('../common'); -common.skipIfWorker(); +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { + common.skip('This test only works on a main thread'); +} const { createRequire } = require('node:module'); const assert = require('node:assert'); diff --git a/test/parallel/test-permission-allow-child-process-cli.js b/test/parallel/test-permission-allow-child-process-cli.js index 794f55ecf9a68c..cf7e79e208d389 100644 --- a/test/parallel/test-permission-allow-child-process-cli.js +++ b/test/parallel/test-permission-allow-child-process-cli.js @@ -2,7 +2,13 @@ 'use strict'; const common = require('../common'); -common.skipIfWorker(); + +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { + common.skip('This test only works on a main thread'); +} + const assert = require('assert'); const childProcess = require('child_process'); const fs = require('fs'); diff --git a/test/parallel/test-permission-allow-wasi-cli.js b/test/parallel/test-permission-allow-wasi-cli.js index c6bea9fb39cf0a..20aca9292533d5 100644 --- a/test/parallel/test-permission-allow-wasi-cli.js +++ b/test/parallel/test-permission-allow-wasi-cli.js @@ -2,7 +2,11 @@ 'use strict'; const common = require('../common'); -common.skipIfWorker(); +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { + common.skip('This test only works on a main thread'); +} const assert = require('assert'); const { WASI } = require('wasi'); diff --git a/test/parallel/test-permission-child-process-cli.js b/test/parallel/test-permission-child-process-cli.js index dfea008a60407b..7d8fbf0564d5ef 100644 --- a/test/parallel/test-permission-child-process-cli.js +++ b/test/parallel/test-permission-child-process-cli.js @@ -2,7 +2,12 @@ 'use strict'; const common = require('../common'); -common.skipIfWorker(); +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { + common.skip('This test only works on a main thread'); +} + const assert = require('assert'); const childProcess = require('child_process'); diff --git a/test/parallel/test-permission-fs-absolute-path.js b/test/parallel/test-permission-fs-absolute-path.js index 2c2257052c8b02..c3bf9ef5cfb2d1 100644 --- a/test/parallel/test-permission-fs-absolute-path.js +++ b/test/parallel/test-permission-fs-absolute-path.js @@ -3,7 +3,11 @@ const common = require('../common'); const path = require('path'); -common.skipIfWorker(); +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { + common.skip('This test only works on a main thread'); +} const assert = require('assert'); const { spawnSync } = require('child_process'); diff --git a/test/parallel/test-permission-fs-internal-module-stat.js b/test/parallel/test-permission-fs-internal-module-stat.js index fd0222cc34fa2e..ef99e4cca73a4f 100644 --- a/test/parallel/test-permission-fs-internal-module-stat.js +++ b/test/parallel/test-permission-fs-internal-module-stat.js @@ -2,7 +2,11 @@ 'use strict'; const common = require('../common'); -common.skipIfWorker(); +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { + common.skip('This test only works on a main thread'); +} if (!common.hasCrypto) { common.skip('no crypto'); diff --git a/test/parallel/test-permission-fs-read.js b/test/parallel/test-permission-fs-read.js index ed8e866a6a4c10..b719207bdbd820 100644 --- a/test/parallel/test-permission-fs-read.js +++ b/test/parallel/test-permission-fs-read.js @@ -2,7 +2,11 @@ 'use strict'; const common = require('../common'); -common.skipIfWorker(); +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { + common.skip('This test only works on a main thread'); +} if (!common.hasCrypto) { common.skip('no crypto'); diff --git a/test/parallel/test-permission-fs-relative-path.js b/test/parallel/test-permission-fs-relative-path.js index 3b115ee35d1227..9f4ce25f0f7d37 100644 --- a/test/parallel/test-permission-fs-relative-path.js +++ b/test/parallel/test-permission-fs-relative-path.js @@ -2,7 +2,11 @@ 'use strict'; const common = require('../common'); -common.skipIfWorker(); +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { + common.skip('This test only works on a main thread'); +} const assert = require('assert'); const { spawnSync } = require('child_process'); diff --git a/test/parallel/test-permission-fs-repeat-path.js b/test/parallel/test-permission-fs-repeat-path.js index 764c7d91497248..d24197e905063d 100644 --- a/test/parallel/test-permission-fs-repeat-path.js +++ b/test/parallel/test-permission-fs-repeat-path.js @@ -3,7 +3,11 @@ const common = require('../common'); const path = require('path'); -common.skipIfWorker(); +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { + common.skip('This test only works on a main thread'); +} const assert = require('assert'); const { spawnSync } = require('child_process'); diff --git a/test/parallel/test-permission-fs-require.js b/test/parallel/test-permission-fs-require.js index 5d3a407708371e..8406f9ec052eae 100644 --- a/test/parallel/test-permission-fs-require.js +++ b/test/parallel/test-permission-fs-require.js @@ -2,7 +2,13 @@ 'use strict'; const common = require('../common'); -common.skipIfWorker(); + +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { + common.skip('This test only works on a main thread'); +} + const fixtures = require('../common/fixtures'); const assert = require('node:assert'); diff --git a/test/parallel/test-permission-fs-symlink-relative.js b/test/parallel/test-permission-fs-symlink-relative.js index cf9b37ea79b059..e1fe5d064a8756 100644 --- a/test/parallel/test-permission-fs-symlink-relative.js +++ b/test/parallel/test-permission-fs-symlink-relative.js @@ -2,7 +2,12 @@ 'use strict'; const common = require('../common'); -common.skipIfWorker(); + +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { + common.skip('This test only works on a main thread'); +} const assert = require('assert'); const path = require('path'); diff --git a/test/parallel/test-permission-fs-symlink-target-write.js b/test/parallel/test-permission-fs-symlink-target-write.js index f55b19fa764a89..1cffead4dd7e71 100644 --- a/test/parallel/test-permission-fs-symlink-target-write.js +++ b/test/parallel/test-permission-fs-symlink-target-write.js @@ -2,11 +2,19 @@ 'use strict'; const common = require('../common'); -common.skipIfWorker(); -if (!common.canCreateSymLink()) +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { + common.skip('This test only works on a main thread'); +} + +if (!common.canCreateSymLink()) { common.skip('insufficient privileges'); -if (!common.hasCrypto) +} + +if (!common.hasCrypto) { common.skip('no crypto'); +} const assert = require('assert'); const fs = require('fs'); @@ -15,9 +23,7 @@ const tmpdir = require('../common/tmpdir'); const fixtures = require('../common/fixtures'); const { spawnSync } = require('child_process'); -{ - tmpdir.refresh(); -} +tmpdir.refresh(); const readOnlyFolder = tmpdir.resolve('read-only'); const readWriteFolder = tmpdir.resolve('read-write'); diff --git a/test/parallel/test-permission-fs-symlink.js b/test/parallel/test-permission-fs-symlink.js index 92965c960177d4..e5a80dba44ddf4 100644 --- a/test/parallel/test-permission-fs-symlink.js +++ b/test/parallel/test-permission-fs-symlink.js @@ -2,13 +2,19 @@ 'use strict'; const common = require('../common'); -common.skipIfWorker(); +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { + common.skip('This test only works on a main thread'); +} const fixtures = require('../common/fixtures'); -if (!common.canCreateSymLink()) +if (!common.canCreateSymLink()) { common.skip('insufficient privileges'); -if (!common.hasCrypto) +} +if (!common.hasCrypto) { common.skip('no crypto'); +} const assert = require('assert'); const fs = require('fs'); diff --git a/test/parallel/test-permission-fs-traversal-path.js b/test/parallel/test-permission-fs-traversal-path.js index 03571c2d01c861..ed9e434b6b862b 100644 --- a/test/parallel/test-permission-fs-traversal-path.js +++ b/test/parallel/test-permission-fs-traversal-path.js @@ -2,13 +2,20 @@ 'use strict'; const common = require('../common'); -common.skipIfWorker(); +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { + common.skip('This test only works on a main thread'); +} const fixtures = require('../common/fixtures'); -if (!common.canCreateSymLink()) +if (!common.canCreateSymLink()) { common.skip('insufficient privileges'); -if (!common.hasCrypto) +} + +if (!common.hasCrypto) { common.skip('no crypto'); +} const assert = require('assert'); const fs = require('fs'); diff --git a/test/parallel/test-permission-fs-wildcard.js b/test/parallel/test-permission-fs-wildcard.js index adca56ed0dba6d..1b67f37c2dcda2 100644 --- a/test/parallel/test-permission-fs-wildcard.js +++ b/test/parallel/test-permission-fs-wildcard.js @@ -2,7 +2,11 @@ 'use strict'; const common = require('../common'); -common.skipIfWorker(); +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { + common.skip('This test only works on a main thread'); +} const assert = require('assert'); const path = require('path'); diff --git a/test/parallel/test-permission-fs-windows-path.js b/test/parallel/test-permission-fs-windows-path.js index 6869b347cf283f..c3b3683b6479f7 100644 --- a/test/parallel/test-permission-fs-windows-path.js +++ b/test/parallel/test-permission-fs-windows-path.js @@ -2,7 +2,11 @@ 'use strict'; const common = require('../common'); -common.skipIfWorker(); +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { + common.skip('This test only works on a main thread'); +} const assert = require('assert'); const { spawnSync } = require('child_process'); diff --git a/test/parallel/test-permission-fs-write-report.js b/test/parallel/test-permission-fs-write-report.js index 111f73b7bcc1ed..a5f8d74904fedc 100644 --- a/test/parallel/test-permission-fs-write-report.js +++ b/test/parallel/test-permission-fs-write-report.js @@ -2,9 +2,15 @@ 'use strict'; const common = require('../common'); -common.skipIfWorker(); -if (!common.hasCrypto) +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { + common.skip('This test only works on a main thread'); +} + +if (!common.hasCrypto) { common.skip('no crypto'); +} const assert = require('assert'); diff --git a/test/parallel/test-permission-fs-write-v8.js b/test/parallel/test-permission-fs-write-v8.js index 85cb9a5519b3af..1b8691969b7afb 100644 --- a/test/parallel/test-permission-fs-write-v8.js +++ b/test/parallel/test-permission-fs-write-v8.js @@ -2,9 +2,15 @@ 'use strict'; const common = require('../common'); -common.skipIfWorker(); -if (!common.hasCrypto) +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { + common.skip('This test only works on a main thread'); +} + +if (!common.hasCrypto) { common.skip('no crypto'); +} const assert = require('assert'); const v8 = require('v8'); diff --git a/test/parallel/test-permission-fs-write.js b/test/parallel/test-permission-fs-write.js index 34eab7a40005db..385a37e2a92d86 100644 --- a/test/parallel/test-permission-fs-write.js +++ b/test/parallel/test-permission-fs-write.js @@ -2,9 +2,15 @@ 'use strict'; const common = require('../common'); -common.skipIfWorker(); -if (!common.hasCrypto) +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { + common.skip('This test only works on a main thread'); +} + +if (!common.hasCrypto) { common.skip('no crypto'); +} const assert = require('assert'); const path = require('path'); diff --git a/test/parallel/test-permission-inspector-brk.js b/test/parallel/test-permission-inspector-brk.js index 61c9c799ba7eb6..3cc7caabd42ba1 100644 --- a/test/parallel/test-permission-inspector-brk.js +++ b/test/parallel/test-permission-inspector-brk.js @@ -5,8 +5,12 @@ const assert = require('assert'); const { spawnSync } = require('child_process'); const fixtures = require('../common/fixtures'); const file = fixtures.path('permission', 'inspector-brk.js'); +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { + common.skip('This test only works on a main thread'); +} -common.skipIfWorker(); common.skipIfInspectorDisabled(); // See https://github.com/nodejs/node/issues/53385 diff --git a/test/parallel/test-permission-inspector.js b/test/parallel/test-permission-inspector.js index 9d3bf485fc4348..4b52e12abca090 100644 --- a/test/parallel/test-permission-inspector.js +++ b/test/parallel/test-permission-inspector.js @@ -2,7 +2,12 @@ 'use strict'; const common = require('../common'); -common.skipIfWorker(); +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { + common.skip('This test only works on a main thread'); +} + common.skipIfInspectorDisabled(); const { Session } = require('inspector'); diff --git a/test/parallel/test-permission-no-addons.js b/test/parallel/test-permission-no-addons.js index a3ae6f4be10641..df08c4aa9f9db5 100644 --- a/test/parallel/test-permission-no-addons.js +++ b/test/parallel/test-permission-no-addons.js @@ -2,7 +2,11 @@ 'use strict'; const common = require('../common'); -common.skipIfWorker(); +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { + common.skip('This test only works on a main thread'); +} const { createRequire } = require('node:module'); const assert = require('node:assert'); diff --git a/test/parallel/test-permission-processbinding.js b/test/parallel/test-permission-processbinding.js index 47a1364f19e303..f5e33dac4deb52 100644 --- a/test/parallel/test-permission-processbinding.js +++ b/test/parallel/test-permission-processbinding.js @@ -1,7 +1,11 @@ 'use strict'; const common = require('../common'); -common.skipIfWorker(); +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { + common.skip('This test only works on a main thread'); +} if (!common.hasCrypto) { common.skip('no crypto'); diff --git a/test/parallel/test-permission-worker-threads-cli.js b/test/parallel/test-permission-worker-threads-cli.js index efd98b2a3881aa..cf397c280474c1 100644 --- a/test/parallel/test-permission-worker-threads-cli.js +++ b/test/parallel/test-permission-worker-threads-cli.js @@ -2,13 +2,17 @@ 'use strict'; const common = require('../common'); -common.skipIfWorker(); -const assert = require('assert'); const { Worker, isMainThread, } = require('worker_threads'); +if (!isMainThread) { + common.skip('This test only works on a main thread'); +} + +const assert = require('assert'); + // Guarantee the initial state { assert.ok(!process.permission.has('worker')); diff --git a/test/parallel/test-pipe-file-to-http.js b/test/parallel/test-pipe-file-to-http.js index 82bdbe6a832a98..ffbab21f71fd9d 100644 --- a/test/parallel/test-pipe-file-to-http.js +++ b/test/parallel/test-pipe-file-to-http.js @@ -54,7 +54,12 @@ const server = http.createServer((req, res) => { server.listen(0); server.on('listening', () => { - common.createZeroFilledFile(filename); + + // Create a zero-filled file + const fd = fs.openSync(filename, 'w'); + fs.ftruncateSync(fd, 10 * 1024 * 1024); + fs.closeSync(fd); + makeRequest(); }); diff --git a/test/parallel/test-preload-self-referential.js b/test/parallel/test-preload-self-referential.js index 867e1c67983c83..68681332978ea6 100644 --- a/test/parallel/test-preload-self-referential.js +++ b/test/parallel/test-preload-self-referential.js @@ -4,11 +4,13 @@ const common = require('../common'); const fixtures = require('../common/fixtures'); const assert = require('assert'); const { exec } = require('child_process'); +const { isMainThread } = require('worker_threads'); const nodeBinary = process.argv[0]; -if (!common.isMainThread) +if (!isMainThread) { common.skip('process.chdir is not available in Workers'); +} const selfRefModule = fixtures.path('self_ref_module'); const fixtureA = fixtures.path('printA.js'); diff --git a/test/parallel/test-process-abort.js b/test/parallel/test-process-abort.js index 665e1399a3f362..34353befb02a44 100644 --- a/test/parallel/test-process-abort.js +++ b/test/parallel/test-process-abort.js @@ -2,9 +2,11 @@ const common = require('../common'); const assert = require('assert'); +const { isMainThread } = require('worker_threads'); -if (!common.isMainThread) +if (!isMainThread) { common.skip('process.abort() is not available in Workers'); +} // Check that our built-in methods do not have a prototype/constructor behaviour // if they don't need to. This could be tested for any of our C++ methods. diff --git a/test/parallel/test-process-beforeexit-throw-exit.js b/test/parallel/test-process-beforeexit-throw-exit.js index 6e9d764be90baa..c967d3a62712a7 100644 --- a/test/parallel/test-process-beforeexit-throw-exit.js +++ b/test/parallel/test-process-beforeexit-throw-exit.js @@ -1,6 +1,10 @@ 'use strict'; const common = require('../common'); -common.skipIfWorker(); +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { + common.skip('This test only works on a main thread'); +} // Test that 'exit' is emitted if 'beforeExit' throws. diff --git a/test/parallel/test-process-chdir-errormessage.js b/test/parallel/test-process-chdir-errormessage.js index 0ed368287b377e..727a13f6f63f16 100644 --- a/test/parallel/test-process-chdir-errormessage.js +++ b/test/parallel/test-process-chdir-errormessage.js @@ -1,8 +1,11 @@ 'use strict'; const common = require('../common'); -if (!common.isMainThread) +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { common.skip('process.chdir is not available in Workers'); +} const assert = require('assert'); assert.throws( diff --git a/test/parallel/test-process-chdir.js b/test/parallel/test-process-chdir.js index ee59df853b24ce..42d2a60c8ec63e 100644 --- a/test/parallel/test-process-chdir.js +++ b/test/parallel/test-process-chdir.js @@ -4,9 +4,11 @@ const common = require('../common'); const assert = require('assert'); const fs = require('fs'); const path = require('path'); +const { isMainThread } = require('worker_threads'); -if (!common.isMainThread) +if (!isMainThread) { common.skip('process.chdir is not available in Workers'); +} const tmpdir = require('../common/tmpdir'); diff --git a/test/parallel/test-process-env-tz.js b/test/parallel/test-process-env-tz.js index dcc69ed4bf1d3b..b7bf730a9afa38 100644 --- a/test/parallel/test-process-env-tz.js +++ b/test/parallel/test-process-env-tz.js @@ -1,12 +1,15 @@ 'use strict'; const common = require('../common'); const assert = require('assert'); +const { isMainThread } = require('worker_threads'); -if (!common.isMainThread) +if (!isMainThread) { common.skip('process.env.TZ is not intercepted in Workers'); +} -if (common.isWindows) // Using a different TZ format. +if (common.isWindows) { // Using a different TZ format. common.skip('todo: test on Windows'); +} const date = new Date('2018-04-14T12:34:56.789Z'); diff --git a/test/parallel/test-process-euid-egid.js b/test/parallel/test-process-euid-egid.js index 11a8cfa0ed2b3c..3f4934233a6308 100644 --- a/test/parallel/test-process-euid-egid.js +++ b/test/parallel/test-process-euid-egid.js @@ -3,6 +3,8 @@ const common = require('../common'); const assert = require('assert'); +const { isMainThread } = require('worker_threads'); + if (common.isWindows) { assert.strictEqual(process.geteuid, undefined); assert.strictEqual(process.getegid, undefined); @@ -11,8 +13,9 @@ if (common.isWindows) { return; } -if (!common.isMainThread) +if (!isMainThread) { return; +} assert.throws(() => { process.seteuid({}); diff --git a/test/parallel/test-process-exit-handler.js b/test/parallel/test-process-exit-handler.js index d74e320fe63082..2546aa60a5cf89 100644 --- a/test/parallel/test-process-exit-handler.js +++ b/test/parallel/test-process-exit-handler.js @@ -1,8 +1,10 @@ 'use strict'; const common = require('../common'); +const { isMainThread } = require('worker_threads'); -if (!common.isMainThread) +if (!isMainThread) { common.skip('execArgv does not affect Workers'); +} // This test ensures that no asynchronous operations are performed in the 'exit' // handler. diff --git a/test/parallel/test-process-get-builtin.mjs b/test/parallel/test-process-get-builtin.mjs index 4b840585f2ad33..f22cf8a1a4728b 100644 --- a/test/parallel/test-process-get-builtin.mjs +++ b/test/parallel/test-process-get-builtin.mjs @@ -1,6 +1,7 @@ -import { isMainThread, hasCrypto, hasIntl } from '../common/index.mjs'; +import { hasCrypto, hasIntl } from '../common/index.mjs'; import assert from 'node:assert'; import { builtinModules } from 'node:module'; +import { isMainThread } from 'node:worker_threads'; for (const invalid of [1, undefined, null, false, [], {}, () => {}, Symbol('test')]) { assert.throws(() => process.getBuiltinModule(invalid), { code: 'ERR_INVALID_ARG_TYPE' }); diff --git a/test/parallel/test-process-initgroups.js b/test/parallel/test-process-initgroups.js index 6b4e3bdf1470b4..52597e096175e9 100644 --- a/test/parallel/test-process-initgroups.js +++ b/test/parallel/test-process-initgroups.js @@ -7,8 +7,11 @@ if (common.isWindows) { return; } -if (!common.isMainThread) +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { return; +} [undefined, null, true, {}, [], () => {}].forEach((val) => { assert.throws( diff --git a/test/parallel/test-process-load-env-file.js b/test/parallel/test-process-load-env-file.js index 1dada3aa9b7016..ec99c099d11b80 100644 --- a/test/parallel/test-process-load-env-file.js +++ b/test/parallel/test-process-load-env-file.js @@ -5,6 +5,7 @@ const fixtures = require('../../test/common/fixtures'); const assert = require('node:assert'); const { describe, it } = require('node:test'); const { join } = require('node:path'); +const { isMainThread } = require('worker_threads'); const basicValidEnvFilePath = fixtures.path('dotenv/basic-valid.env'); const validEnvFilePath = fixtures.path('dotenv/valid.env'); @@ -58,7 +59,7 @@ describe('process.loadEnvFile()', () => { const originalCwd = process.cwd(); try { - if (common.isMainThread) { + if (isMainThread) { process.chdir(join(originalCwd, 'lib')); } @@ -66,7 +67,7 @@ describe('process.loadEnvFile()', () => { process.loadEnvFile(); }, { code: 'ENOENT', syscall: 'open', path: '.env' }); } finally { - if (common.isMainThread) { + if (isMainThread) { process.chdir(originalCwd); } } diff --git a/test/parallel/test-process-setgroups.js b/test/parallel/test-process-setgroups.js index 9506f24a5f3447..49d147b6c2ddf5 100644 --- a/test/parallel/test-process-setgroups.js +++ b/test/parallel/test-process-setgroups.js @@ -1,14 +1,16 @@ 'use strict'; const common = require('../common'); const assert = require('assert'); +const { isMainThread } = require('worker_threads'); if (common.isWindows) { assert.strictEqual(process.setgroups, undefined); return; } -if (!common.isMainThread) +if (!isMainThread) { return; +} assert.throws( () => { diff --git a/test/parallel/test-process-uid-gid.js b/test/parallel/test-process-uid-gid.js index 54e87a6ff5c6e0..10eee45af1555b 100644 --- a/test/parallel/test-process-uid-gid.js +++ b/test/parallel/test-process-uid-gid.js @@ -23,6 +23,7 @@ const common = require('../common'); const assert = require('assert'); +const { isMainThread } = require('worker_threads'); if (common.isWindows) { // uid/gid functions are POSIX only. @@ -33,8 +34,9 @@ if (common.isWindows) { return; } -if (!common.isMainThread) +if (!isMainThread) { return; +} assert.throws(() => { process.setuid({}); diff --git a/test/parallel/test-process-umask-mask.js b/test/parallel/test-process-umask-mask.js index d599379761fd40..f0a67b8f14e895 100644 --- a/test/parallel/test-process-umask-mask.js +++ b/test/parallel/test-process-umask-mask.js @@ -5,8 +5,9 @@ const common = require('../common'); const assert = require('assert'); +const { isMainThread } = require('worker_threads'); -if (!common.isMainThread) +if (!isMainThread) common.skip('Setting process.umask is not supported in Workers'); let mask; diff --git a/test/parallel/test-process-umask.js b/test/parallel/test-process-umask.js index e90955f394df4e..594f75ebebed2b 100644 --- a/test/parallel/test-process-umask.js +++ b/test/parallel/test-process-umask.js @@ -22,8 +22,9 @@ 'use strict'; const common = require('../common'); const assert = require('assert'); +const { isMainThread } = require('worker_threads'); -if (!common.isMainThread) { +if (!isMainThread) { assert.strictEqual(typeof process.umask(), 'number'); assert.throws(() => { process.umask('0664'); diff --git a/test/parallel/test-readline-interface-no-trailing-newline.js b/test/parallel/test-readline-interface-no-trailing-newline.js index b3392db8619c95..398b85838c8b71 100644 --- a/test/parallel/test-readline-interface-no-trailing-newline.js +++ b/test/parallel/test-readline-interface-no-trailing-newline.js @@ -3,7 +3,9 @@ const common = require('../common'); const ArrayStream = require('../common/arraystream'); const assert = require('assert'); -common.skipIfDumbTerminal(); +if (process.env.TERM === 'dumb') { + common.skip('skipping - dumb terminal'); +} const readline = require('readline'); const rli = new readline.Interface({ diff --git a/test/parallel/test-readline-interface-recursive-writes.js b/test/parallel/test-readline-interface-recursive-writes.js index 3a0aee5be9d619..ea3df1968d08d8 100644 --- a/test/parallel/test-readline-interface-recursive-writes.js +++ b/test/parallel/test-readline-interface-recursive-writes.js @@ -3,7 +3,9 @@ const common = require('../common'); const ArrayStream = require('../common/arraystream'); const assert = require('assert'); -common.skipIfDumbTerminal(); +if (process.env.TERM === 'dumb') { + common.skip('skipping - dumb terminal'); +} const readline = require('readline'); const rli = new readline.Interface({ diff --git a/test/parallel/test-readline-interface.js b/test/parallel/test-readline-interface.js index a90e07d235030f..12ba0c709622e9 100644 --- a/test/parallel/test-readline-interface.js +++ b/test/parallel/test-readline-interface.js @@ -22,7 +22,10 @@ // Flags: --expose-internals 'use strict'; const common = require('../common'); -common.skipIfDumbTerminal(); + +if (process.env.TERM === 'dumb') { + common.skip('skipping - dumb terminal'); +} const assert = require('assert'); const readline = require('readline'); diff --git a/test/parallel/test-readline-position.js b/test/parallel/test-readline-position.js index 3603a42ecedc68..ac2fe43b37a097 100644 --- a/test/parallel/test-readline-position.js +++ b/test/parallel/test-readline-position.js @@ -7,7 +7,9 @@ const assert = require('assert'); const ctrlU = { ctrl: true, name: 'u' }; -common.skipIfDumbTerminal(); +if (process.env.TERM === 'dumb') { + common.skip('skipping - dumb terminal'); +} { const input = new PassThrough(); diff --git a/test/parallel/test-readline-promises-interface.js b/test/parallel/test-readline-promises-interface.js index 8e42d977301267..97424c1372629c 100644 --- a/test/parallel/test-readline-promises-interface.js +++ b/test/parallel/test-readline-promises-interface.js @@ -1,7 +1,10 @@ // Flags: --expose-internals 'use strict'; const common = require('../common'); -common.skipIfDumbTerminal(); + +if (process.env.TERM === 'dumb') { + common.skip('skipping - dumb terminal'); +} const assert = require('assert'); const readline = require('readline/promises'); diff --git a/test/parallel/test-readline-promises-tab-complete.js b/test/parallel/test-readline-promises-tab-complete.js index fd32900e71d096..d8b0ac30ee779d 100644 --- a/test/parallel/test-readline-promises-tab-complete.js +++ b/test/parallel/test-readline-promises-tab-complete.js @@ -8,7 +8,9 @@ const assert = require('assert'); const { EventEmitter } = require('events'); const { getStringWidth } = require('internal/util/inspect'); -common.skipIfDumbTerminal(); +if (process.env.TERM === 'dumb') { + common.skip('skipping - dumb terminal'); +} // This test verifies that the tab completion supports unicode and the writes // are limited to the minimum. diff --git a/test/parallel/test-readline-tab-complete.js b/test/parallel/test-readline-tab-complete.js index 64df237d56ad44..5b7b19102f412a 100644 --- a/test/parallel/test-readline-tab-complete.js +++ b/test/parallel/test-readline-tab-complete.js @@ -8,7 +8,9 @@ const assert = require('assert'); const EventEmitter = require('events').EventEmitter; const { getStringWidth } = require('internal/util/inspect'); -common.skipIfDumbTerminal(); +if (process.env.TERM === 'dumb') { + common.skip('skipping - dumb terminal'); +} // This test verifies that the tab completion supports unicode and the writes // are limited to the minimum. diff --git a/test/parallel/test-readline-undefined-columns.js b/test/parallel/test-readline-undefined-columns.js index 25bafe957fa40a..d7000a16dd88a7 100644 --- a/test/parallel/test-readline-undefined-columns.js +++ b/test/parallel/test-readline-undefined-columns.js @@ -5,7 +5,9 @@ const assert = require('assert'); const PassThrough = require('stream').PassThrough; const readline = require('readline'); -common.skipIfDumbTerminal(); +if (process.env.TERM === 'dumb') { + common.skip('skipping - dumb terminal'); +} // Checks that tab completion still works // when output column size is undefined diff --git a/test/parallel/test-readline.js b/test/parallel/test-readline.js index 77799fc14cf75f..0cf577942915a6 100644 --- a/test/parallel/test-readline.js +++ b/test/parallel/test-readline.js @@ -4,7 +4,9 @@ const { PassThrough } = require('stream'); const readline = require('readline'); const assert = require('assert'); -common.skipIfDumbTerminal(); +if (process.env.TERM === 'dumb') { + common.skip('skipping - dumb terminal'); +} { const input = new PassThrough(); diff --git a/test/parallel/test-repl-autocomplete.js b/test/parallel/test-repl-autocomplete.js index cb17523494b2ff..a68322c501e264 100644 --- a/test/parallel/test-repl-autocomplete.js +++ b/test/parallel/test-repl-autocomplete.js @@ -9,7 +9,9 @@ const assert = require('assert'); const fs = require('fs'); const { inspect } = require('util'); -common.skipIfDumbTerminal(); +if (process.env.TERM === 'dumb') { + common.skip('skipping - dumb terminal'); +} const tmpdir = require('../common/tmpdir'); tmpdir.refresh(); diff --git a/test/parallel/test-repl-editor.js b/test/parallel/test-repl-editor.js index e260f5e89174a8..fee647d0478e50 100644 --- a/test/parallel/test-repl-editor.js +++ b/test/parallel/test-repl-editor.js @@ -5,7 +5,9 @@ const assert = require('assert'); const repl = require('repl'); const ArrayStream = require('../common/arraystream'); -common.skipIfDumbTerminal(); +if (process.env.TERM === 'dumb') { + common.skip('skipping - dumb terminal'); +} // \u001b[nG - Moves the cursor to n st column // \u001b[0J - Clear screen diff --git a/test/parallel/test-repl-history-navigation.js b/test/parallel/test-repl-history-navigation.js index 4df120d7cb9eae..64317be960e8d1 100644 --- a/test/parallel/test-repl-history-navigation.js +++ b/test/parallel/test-repl-history-navigation.js @@ -9,7 +9,9 @@ const assert = require('assert'); const fs = require('fs'); const { inspect } = require('util'); -common.skipIfDumbTerminal(); +if (process.env.TERM === 'dumb') { + common.skip('skipping - dumb terminal'); +} const tmpdir = require('../common/tmpdir'); tmpdir.refresh(); diff --git a/test/parallel/test-repl-load-multiline-no-trailing-newline.js b/test/parallel/test-repl-load-multiline-no-trailing-newline.js index f57638d2521bbe..8fda91e35d1030 100644 --- a/test/parallel/test-repl-load-multiline-no-trailing-newline.js +++ b/test/parallel/test-repl-load-multiline-no-trailing-newline.js @@ -5,7 +5,9 @@ const fixtures = require('../common/fixtures'); const assert = require('assert'); const repl = require('repl'); -common.skipIfDumbTerminal(); +if (process.env.TERM === 'dumb') { + common.skip('skipping - dumb terminal'); +} const command = `.load ${fixtures.path('repl-load-multiline-no-trailing-newline.js')}`; const terminalCode = '\u001b[1G\u001b[0J \u001b[1G'; diff --git a/test/parallel/test-repl-load-multiline.js b/test/parallel/test-repl-load-multiline.js index 4fcf206bef1be1..920f4b1c25d144 100644 --- a/test/parallel/test-repl-load-multiline.js +++ b/test/parallel/test-repl-load-multiline.js @@ -5,7 +5,9 @@ const fixtures = require('../common/fixtures'); const assert = require('assert'); const repl = require('repl'); -common.skipIfDumbTerminal(); +if (process.env.TERM === 'dumb') { + common.skip('skipping - dumb terminal'); +} const command = `.load ${fixtures.path('repl-load-multiline.js')}`; const terminalCode = '\u001b[1G\u001b[0J \u001b[1G'; diff --git a/test/parallel/test-repl-mode.js b/test/parallel/test-repl-mode.js index aca8418904d082..f8a54d34089b00 100644 --- a/test/parallel/test-repl-mode.js +++ b/test/parallel/test-repl-mode.js @@ -4,7 +4,9 @@ const assert = require('assert'); const Stream = require('stream'); const repl = require('repl'); -common.skipIfDumbTerminal(); +if (process.env.TERM === 'dumb') { + common.skip('skipping - dumb terminal'); +} const tests = [ testSloppyMode, diff --git a/test/parallel/test-repl-permission-model.js b/test/parallel/test-repl-permission-model.js index 938f5121163a23..ab5c7bff06cde8 100644 --- a/test/parallel/test-repl-permission-model.js +++ b/test/parallel/test-repl-permission-model.js @@ -8,7 +8,9 @@ const REPL = require('internal/repl'); const assert = require('assert'); const { inspect } = require('util'); -common.skipIfDumbTerminal(); +if (process.env.TERM === 'dumb') { + common.skip('skipping - dumb terminal'); +} // Create an input stream specialized for testing an array of actions class ActionStream extends stream.Stream { diff --git a/test/parallel/test-repl-persistent-history.js b/test/parallel/test-repl-persistent-history.js index 99ba92eda4cf3d..f5e2d48139f449 100644 --- a/test/parallel/test-repl-persistent-history.js +++ b/test/parallel/test-repl-persistent-history.js @@ -11,7 +11,9 @@ const fs = require('fs'); const os = require('os'); const util = require('util'); -common.skipIfDumbTerminal(); +if (process.env.TERM === 'dumb') { + common.skip('skipping - dumb terminal'); +} const tmpdir = require('../common/tmpdir'); tmpdir.refresh(); diff --git a/test/parallel/test-repl-programmatic-history.js b/test/parallel/test-repl-programmatic-history.js index 1ae5123c6c8ea1..aae15eb752c862 100644 --- a/test/parallel/test-repl-programmatic-history.js +++ b/test/parallel/test-repl-programmatic-history.js @@ -9,7 +9,9 @@ const fs = require('fs'); const os = require('os'); const util = require('util'); -common.skipIfDumbTerminal(); +if (process.env.TERM === 'dumb') { + common.skip('skipping - dumb terminal'); +} const tmpdir = require('../common/tmpdir'); tmpdir.refresh(); diff --git a/test/parallel/test-repl-require-self-referential.js b/test/parallel/test-repl-require-self-referential.js index 7ced6dbf11721e..9a4fe000bbb7e3 100644 --- a/test/parallel/test-repl-require-self-referential.js +++ b/test/parallel/test-repl-require-self-referential.js @@ -4,9 +4,11 @@ const common = require('../common'); const fixtures = require('../common/fixtures'); const assert = require('assert'); const { spawn } = require('child_process'); +const { isMainThread } = require('worker_threads'); -if (!common.isMainThread) +if (!isMainThread) { common.skip('process.chdir is not available in Workers'); +} const selfRefModule = fixtures.path('self_ref_module'); const child = spawn(process.execPath, diff --git a/test/parallel/test-repl-require.js b/test/parallel/test-repl-require.js index fc431dea9f0f69..e740acef08b068 100644 --- a/test/parallel/test-repl-require.js +++ b/test/parallel/test-repl-require.js @@ -4,9 +4,11 @@ const common = require('../common'); const fixtures = require('../common/fixtures'); const assert = require('assert'); const net = require('net'); +const { isMainThread } = require('worker_threads'); -if (!common.isMainThread) +if (!isMainThread) { common.skip('process.chdir is not available in Workers'); +} process.chdir(fixtures.fixturesDir); const repl = require('repl'); diff --git a/test/parallel/test-repl-reverse-search.js b/test/parallel/test-repl-reverse-search.js index 93fb037c392c01..246488cbd0ef5f 100644 --- a/test/parallel/test-repl-reverse-search.js +++ b/test/parallel/test-repl-reverse-search.js @@ -9,7 +9,10 @@ const assert = require('assert'); const fs = require('fs'); const { inspect } = require('util'); -common.skipIfDumbTerminal(); +if (process.env.TERM === 'dumb') { + common.skip('skipping - dumb terminal'); +} + common.allowGlobals('aaaa'); const tmpdir = require('../common/tmpdir'); diff --git a/test/parallel/test-repl-sigint-nested-eval.js b/test/parallel/test-repl-sigint-nested-eval.js index 62eb46e0af6759..7955cf413f7c49 100644 --- a/test/parallel/test-repl-sigint-nested-eval.js +++ b/test/parallel/test-repl-sigint-nested-eval.js @@ -4,8 +4,12 @@ if (common.isWindows) { // No way to send CTRL_C_EVENT to processes from JS right now. common.skip('platform not supported'); } -if (!common.isMainThread) + +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { common.skip('No signal handling available in Workers'); +} const assert = require('assert'); const spawn = require('child_process').spawn; diff --git a/test/parallel/test-repl-sigint.js b/test/parallel/test-repl-sigint.js index 8ad0b2f5c2c853..f4087b11d488d6 100644 --- a/test/parallel/test-repl-sigint.js +++ b/test/parallel/test-repl-sigint.js @@ -4,8 +4,12 @@ if (common.isWindows) { // No way to send CTRL_C_EVENT to processes from JS right now. common.skip('platform not supported'); } -if (!common.isMainThread) + +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { common.skip('No signal handling available in Workers'); +} const assert = require('assert'); const spawn = require('child_process').spawn; diff --git a/test/parallel/test-repl-strict-mode-previews.js b/test/parallel/test-repl-strict-mode-previews.js index a05e11b39cf3ee..e7fc1ea5191ea3 100644 --- a/test/parallel/test-repl-strict-mode-previews.js +++ b/test/parallel/test-repl-strict-mode-previews.js @@ -5,7 +5,10 @@ const common = require('../common'); common.skipIfInspectorDisabled(); -common.skipIfDumbTerminal(); + +if (process.env.TERM === 'dumb') { + common.skip('skipping - dumb terminal'); +} if (process.argv[2] === 'child') { const stream = require('stream'); diff --git a/test/parallel/test-repl-tab-complete-import.js b/test/parallel/test-repl-tab-complete-import.js index e328d95db5986c..60f97835c970bb 100644 --- a/test/parallel/test-repl-tab-complete-import.js +++ b/test/parallel/test-repl-tab-complete-import.js @@ -7,8 +7,11 @@ const assert = require('assert'); const { builtinModules } = require('module'); const publicModules = builtinModules.filter((lib) => !lib.startsWith('_')); -if (!common.isMainThread) +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { common.skip('process.chdir is not available in Workers'); +} // We have to change the directory to ../fixtures before requiring repl // in order to make the tests for completion of node_modules work properly diff --git a/test/parallel/test-repl-tab-complete.js b/test/parallel/test-repl-tab-complete.js index 57278f52ccf2c6..b8d29c7967c10d 100644 --- a/test/parallel/test-repl-tab-complete.js +++ b/test/parallel/test-repl-tab-complete.js @@ -34,9 +34,11 @@ const { builtinModules } = require('module'); const publicModules = builtinModules.filter((lib) => !lib.startsWith('_')); const hasInspector = process.features.inspector; +const { isMainThread } = require('worker_threads'); -if (!common.isMainThread) +if (!isMainThread) { common.skip('process.chdir is not available in Workers'); +} // We have to change the directory to ../fixtures before requiring repl // in order to make the tests for completion of node_modules work properly diff --git a/test/parallel/test-require-symlink.js b/test/parallel/test-require-symlink.js index 0c4477023bc90b..9ca543e8d64ca4 100644 --- a/test/parallel/test-require-symlink.js +++ b/test/parallel/test-require-symlink.js @@ -2,10 +2,14 @@ 'use strict'; const common = require('../common'); -if (!common.canCreateSymLink()) +if (!common.canCreateSymLink()) { common.skip('insufficient privileges'); -if (!common.isMainThread) +} +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { common.skip('process.chdir is not available in Workers'); +} const assert = require('assert'); const { spawn } = require('child_process'); diff --git a/test/parallel/test-runner-module-mocking.js b/test/parallel/test-runner-module-mocking.js index a832c6a2a7ef03..7f84e9df54eaa8 100644 --- a/test/parallel/test-runner-module-mocking.js +++ b/test/parallel/test-runner-module-mocking.js @@ -1,8 +1,9 @@ // Flags: --experimental-test-module-mocks --experimental-require-module 'use strict'; const common = require('../common'); +const { isMainThread } = require('worker_threads'); -if (!common.isMainThread) { +if (!isMainThread) { common.skip('registering customization hooks in Workers does not work'); } diff --git a/test/parallel/test-set-process-debug-port.js b/test/parallel/test-set-process-debug-port.js index d00a1ddf68ebb6..7f0cbe068549d0 100644 --- a/test/parallel/test-set-process-debug-port.js +++ b/test/parallel/test-set-process-debug-port.js @@ -2,7 +2,11 @@ const common = require('../common'); common.skipIfInspectorDisabled(); -common.skipIfWorker(); +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { + common.skip('This test only works on a main thread'); +} const assert = require('assert'); const kMinPort = 1024; diff --git a/test/parallel/test-setproctitle.js b/test/parallel/test-setproctitle.js index 7c4287829f7c0a..b08302e0a35ac0 100644 --- a/test/parallel/test-setproctitle.js +++ b/test/parallel/test-setproctitle.js @@ -1,15 +1,16 @@ 'use strict'; // Original test written by Jakub Lekstan const common = require('../common'); +const { isMainThread } = require('worker_threads'); // FIXME add sunos support -if (common.isSunOS) +if (common.isSunOS || common.isIBMi) { common.skip(`Unsupported platform [${process.platform}]`); -// FIXME add IBMi support -if (common.isIBMi) - common.skip('Unsupported platform IBMi'); -if (!common.isMainThread) +} + +if (!isMainThread) { common.skip('Setting the process title from Workers is not supported'); +} const assert = require('assert'); const { exec, execSync } = require('child_process'); @@ -25,8 +26,9 @@ process.title = title; assert.strictEqual(process.title, title); // Test setting the title but do not try to run `ps` on Windows. -if (common.isWindows) +if (common.isWindows) { common.skip('Windows does not have "ps" utility'); +} try { execSync('command -v ps'); diff --git a/test/parallel/test-shadow-realm-import-value-resolve.js b/test/parallel/test-shadow-realm-import-value-resolve.js index ee1c17d67c12f1..eeb00509d53a6c 100644 --- a/test/parallel/test-shadow-realm-import-value-resolve.js +++ b/test/parallel/test-shadow-realm-import-value-resolve.js @@ -3,8 +3,11 @@ const common = require('../common'); const assert = require('assert'); const path = require('path'); +const { isMainThread } = require('worker_threads'); -common.skipIfWorker('process.chdir is not supported in workers.'); +if (!isMainThread) { + common.skip('This test only works on a main thread'); +} async function main() { const realm = new ShadowRealm(); diff --git a/test/parallel/test-signal-args.js b/test/parallel/test-signal-args.js index 7b72ed6dcb92d5..28a077ecc1c7d9 100644 --- a/test/parallel/test-signal-args.js +++ b/test/parallel/test-signal-args.js @@ -3,10 +3,15 @@ const common = require('../common'); const assert = require('assert'); -if (common.isWindows) +if (common.isWindows) { common.skip('Sending signals with process.kill is not supported on Windows'); -if (!common.isMainThread) +} + +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { common.skip('No signal handling available in Workers'); +} process.once('SIGINT', common.mustCall((signal) => { assert.strictEqual(signal, 'SIGINT'); diff --git a/test/parallel/test-signal-handler.js b/test/parallel/test-signal-handler.js index 05ec4e7f73faf5..b84d2063a288db 100644 --- a/test/parallel/test-signal-handler.js +++ b/test/parallel/test-signal-handler.js @@ -23,10 +23,15 @@ const common = require('../common'); -if (common.isWindows) +if (common.isWindows) { common.skip('SIGUSR1 and SIGHUP signals are not supported'); -if (!common.isMainThread) +} + +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { common.skip('Signal handling in Workers is not supported'); +} console.log(`process.pid: ${process.pid}`); diff --git a/test/parallel/test-stdio-pipe-access.js b/test/parallel/test-stdio-pipe-access.js index ac0e22c399a1b9..6bf6b107c60e92 100644 --- a/test/parallel/test-stdio-pipe-access.js +++ b/test/parallel/test-stdio-pipe-access.js @@ -1,7 +1,10 @@ 'use strict'; const common = require('../common'); -if (!common.isMainThread) +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { common.skip("Workers don't have process-like stdio"); +} // Test if Node handles accessing process.stdin if it is a redirected // pipe without deadlocking diff --git a/test/parallel/test-stdio-pipe-redirect.js b/test/parallel/test-stdio-pipe-redirect.js index 8b48133c8b0317..69367119ed3402 100644 --- a/test/parallel/test-stdio-pipe-redirect.js +++ b/test/parallel/test-stdio-pipe-redirect.js @@ -1,7 +1,10 @@ 'use strict'; const common = require('../common'); -if (!common.isMainThread) +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { common.skip("Workers don't have process-like stdio"); +} // Test if Node handles redirecting one child process stdout to another // process stdin without crashing. diff --git a/test/parallel/test-timers-immediate-unref-simple.js b/test/parallel/test-timers-immediate-unref-simple.js index 369894fcdebbae..fae8ad3eaea801 100644 --- a/test/parallel/test-timers-immediate-unref-simple.js +++ b/test/parallel/test-timers-immediate-unref-simple.js @@ -1,8 +1,9 @@ 'use strict'; const common = require('../common'); +const { isMainThread } = require('worker_threads'); -if (!common.isMainThread) { +if (!isMainThread) { // Note that test-timers-immediate-unref-nested-once works instead. common.skip('Worker bootstrapping works differently -> different timing'); } diff --git a/test/parallel/test-trace-events-api.js b/test/parallel/test-trace-events-api.js index 709f8de9097906..8792a40cf00c80 100644 --- a/test/parallel/test-trace-events-api.js +++ b/test/parallel/test-trace-events-api.js @@ -2,7 +2,12 @@ 'use strict'; const common = require('../common'); -common.skipIfWorker(); // https://github.com/nodejs/node/issues/22767 +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { + // https://github.com/nodejs/node/issues/22767 + common.skip('This test only works on a main thread'); +} try { require('trace_events'); diff --git a/test/parallel/test-trace-events-dynamic-enable.js b/test/parallel/test-trace-events-dynamic-enable.js index 69251944031e1f..5b2ce313421568 100644 --- a/test/parallel/test-trace-events-dynamic-enable.js +++ b/test/parallel/test-trace-events-dynamic-enable.js @@ -4,7 +4,13 @@ const common = require('../common'); common.skipIfInspectorDisabled(); -common.skipIfWorker(); // https://github.com/nodejs/node/issues/22767 + +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { + // https://github.com/nodejs/node/issues/22767 + common.skip('This test only works on a main thread'); +} const { internalBinding } = require('internal/test/binding'); diff --git a/test/parallel/test-warn-sigprof.js b/test/parallel/test-warn-sigprof.js index 36b0db78d82687..929deb69addb17 100644 --- a/test/parallel/test-warn-sigprof.js +++ b/test/parallel/test-warn-sigprof.js @@ -7,10 +7,15 @@ const common = require('../common'); common.skipIfInspectorDisabled(); -if (common.isWindows) +if (common.isWindows) { common.skip('test does not apply to Windows'); +} -common.skipIfWorker(); // Worker inspector never has a server running +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { + common.skip('This test only works on a main thread'); +} common.expectWarning('Warning', 'process.on(SIGPROF) is reserved while debugging'); diff --git a/test/parallel/test-worker-name.js b/test/parallel/test-worker-name.js index 952fcee0e05429..30f3710a826caf 100644 --- a/test/parallel/test-worker-name.js +++ b/test/parallel/test-worker-name.js @@ -4,10 +4,17 @@ const common = require('../common'); const fixtures = require('../common/fixtures'); common.skipIfInspectorDisabled(); -common.skipIfWorker(); // This test requires both main and worker threads. + +const { + Worker, + isMainThread, +} = require('worker_threads'); + +if (!isMainThread) { + common.skip('This test only works on a main thread'); +} const assert = require('assert'); -const { Worker, isMainThread } = require('worker_threads'); if (isMainThread) { const name = 'Hello Thread'; diff --git a/test/report/test-report-signal.js b/test/report/test-report-signal.js index cb5efd9fc39fe2..03908ddcf24f16 100644 --- a/test/report/test-report-signal.js +++ b/test/report/test-report-signal.js @@ -3,11 +3,15 @@ // Test producing a report via signal. const common = require('../common'); -if (common.isWindows) +if (common.isWindows) { return common.skip('Unsupported on Windows.'); +} -if (!common.isMainThread) +const { isMainThread } = require('worker_threads'); + +if (!isMainThread) { common.skip('Signal reporting is only supported in the main thread'); +} const assert = require('assert'); const helper = require('../common/report'); diff --git a/test/sequential/test-fs-watch.js b/test/sequential/test-fs-watch.js index cb12acfc115a4b..8db27a79e33d0a 100644 --- a/test/sequential/test-fs-watch.js +++ b/test/sequential/test-fs-watch.js @@ -29,9 +29,11 @@ const fs = require('fs'); const path = require('path'); const tmpdir = require('../common/tmpdir'); +const { isMainThread } = require('worker_threads'); -if (!common.isMainThread) +if (!isMainThread) { common.skip('process.chdir is not available in Workers'); +} const expectFilePath = common.isWindows || common.isLinux || diff --git a/test/sequential/test-heapdump.js b/test/sequential/test-heapdump.js index 1388623e61f939..f9df88375ae596 100644 --- a/test/sequential/test-heapdump.js +++ b/test/sequential/test-heapdump.js @@ -1,9 +1,11 @@ 'use strict'; const common = require('../common'); +const { isMainThread } = require('worker_threads'); -if (!common.isMainThread) +if (!isMainThread) { common.skip('process.chdir is not available in Workers'); +} const { writeHeapSnapshot, getHeapSnapshot } = require('v8'); const assert = require('assert'); diff --git a/test/sequential/test-init.js b/test/sequential/test-init.js index 7195369e0e4f8e..dd5db5640d1f0c 100644 --- a/test/sequential/test-init.js +++ b/test/sequential/test-init.js @@ -24,9 +24,11 @@ const common = require('../common'); const assert = require('assert'); const child = require('child_process'); const fixtures = require('../common/fixtures'); +const { isMainThread } = require('worker_threads'); -if (!common.isMainThread) +if (!isMainThread) { common.skip('process.chdir is not available in Workers'); +} if (process.env.TEST_INIT) { return process.stdout.write('Loaded successfully!'); diff --git a/test/sequential/test-perf-hooks.js b/test/sequential/test-perf-hooks.js index 1e11f26571480d..847decdef18bfc 100644 --- a/test/sequential/test-perf-hooks.js +++ b/test/sequential/test-perf-hooks.js @@ -1,11 +1,12 @@ 'use strict'; -const common = require('../common'); +require('../common'); const { performance } = require('perf_hooks'); // Get the start time as soon as possible. const testStartTime = performance.now(); const assert = require('assert'); const { writeSync } = require('fs'); +const { isMainThread } = require('worker_threads'); // Use writeSync to stdout to avoid disturbing the loop. function log(str) { @@ -131,7 +132,7 @@ function checkValue(timing, name, min, max) { } let loopStart = initialTiming.loopStart; -if (common.isMainThread) { +if (isMainThread) { // In the main thread, the loop does not start until we start an operation // that requires it, e.g. setTimeout(). assert.strictEqual(initialTiming.loopStart, -1); From eb97076199c48f9d79d0f67ec9ac046f0989490e Mon Sep 17 00:00:00 2001 From: James M Snell Date: Wed, 22 Jan 2025 15:08:23 -0800 Subject: [PATCH 155/205] test: make common/index slightly less node.js specific * s/global/globalThis * clean up knownGlobals a bit, make it a Set instead of an array and condense a bit. PR-URL: https://github.com/nodejs/node/pull/56712 Reviewed-By: Yagiz Nizipli Reviewed-By: Matteo Collina --- test/common/index.js | 140 ++++++++++++++++++------------------------- 1 file changed, 57 insertions(+), 83 deletions(-) diff --git a/test/common/index.js b/test/common/index.js index 6086d584f0b595..8f6c3e82b3869d 100644 --- a/test/common/index.js +++ b/test/common/index.js @@ -20,7 +20,7 @@ // USE OR OTHER DEALINGS IN THE SOFTWARE. 'use strict'; -const process = global.process; // Some tests tamper with the process global. +const process = globalThis.process; // Some tests tamper with the process globalThis. const assert = require('assert'); const { exec, execSync, spawn, spawnSync } = require('child_process'); @@ -266,7 +266,7 @@ function platformTimeout(ms) { return ms; } -let knownGlobals = [ +const knownGlobals = new Set([ AbortController, atob, btoa, @@ -278,88 +278,59 @@ let knownGlobals = [ setInterval, setTimeout, queueMicrotask, -]; - -if (global.gc) { - knownGlobals.push(global.gc); -} - -if (global.navigator) { - knownGlobals.push(global.navigator); -} - -if (global.Navigator) { - knownGlobals.push(global.Navigator); -} - -if (global.Performance) { - knownGlobals.push(global.Performance); -} -if (global.performance) { - knownGlobals.push(global.performance); -} -if (global.PerformanceMark) { - knownGlobals.push(global.PerformanceMark); -} -if (global.PerformanceMeasure) { - knownGlobals.push(global.PerformanceMeasure); -} - -// TODO(@ethan-arrowood): Similar to previous checks, this can be temporary -// until v16.x is EOL. Once all supported versions have structuredClone we -// can add this to the list above instead. -if (global.structuredClone) { - knownGlobals.push(global.structuredClone); -} - -if (global.EventSource) { - knownGlobals.push(EventSource); -} - -if (global.fetch) { - knownGlobals.push(fetch); -} -if (hasCrypto && global.crypto) { - knownGlobals.push(global.crypto); - knownGlobals.push(global.Crypto); - knownGlobals.push(global.CryptoKey); - knownGlobals.push(global.SubtleCrypto); -} -if (global.CustomEvent) { - knownGlobals.push(global.CustomEvent); -} -if (global.ReadableStream) { - knownGlobals.push( - global.ReadableStream, - global.ReadableStreamDefaultReader, - global.ReadableStreamBYOBReader, - global.ReadableStreamBYOBRequest, - global.ReadableByteStreamController, - global.ReadableStreamDefaultController, - global.TransformStream, - global.TransformStreamDefaultController, - global.WritableStream, - global.WritableStreamDefaultWriter, - global.WritableStreamDefaultController, - global.ByteLengthQueuingStrategy, - global.CountQueuingStrategy, - global.TextEncoderStream, - global.TextDecoderStream, - global.CompressionStream, - global.DecompressionStream, - ); -} + structuredClone, +]); + +['gc', + // The following are assumed to be conditionally available in the + // global object currently. They can likely be added to the fixed + // set of known globals, however. + 'fetch', + 'navigator', + 'Navigator', + 'performance', + 'Performance', + 'PerformanceMark', + 'PerformanceMeasure', + 'EventSource', + 'CustomEvent', + 'ReadableStream', + 'ReadableStreamDefaultReader', + 'ReadableStreamBYOBReader', + 'ReadableStreamBYOBRequest', + 'ReadableByteStreamController', + 'ReadableStreamDefaultController', + 'TransformStream', + 'TransformStreamDefaultController', + 'WritableStream', + 'WritableStreamDefaultWriter', + 'WritableStreamDefaultController', + 'ByteLengthQueuingStrategy', + 'CountQueuingStrategy', + 'TextEncoderStream', + 'TextDecoderStream', + 'CompressionStream', + 'DecompressionStream', + 'Storage', + 'localStorage', + 'sessionStorage', +].forEach((i) => { + if (globalThis[i] !== undefined) { + knownGlobals.add(globalThis[i]); + } +}); -if (global.Storage) { - knownGlobals.push( - global.localStorage, - global.sessionStorage, - global.Storage, - ); +if (hasCrypto) { + knownGlobals.add(globalThis.crypto); + knownGlobals.add(globalThis.Crypto); + knownGlobals.add(globalThis.CryptoKey); + knownGlobals.add(globalThis.SubtleCrypto); } function allowGlobals(...allowlist) { - knownGlobals = knownGlobals.concat(allowlist); + for (const val of allowlist) { + knownGlobals.add(val); + } } if (process.env.NODE_TEST_KNOWN_GLOBALS !== '0') { @@ -371,10 +342,13 @@ if (process.env.NODE_TEST_KNOWN_GLOBALS !== '0') { function leakedGlobals() { const leaked = []; - for (const val in global) { + for (const val in globalThis) { // globalThis.crypto is a getter that throws if Node.js was compiled - // without OpenSSL. - if (val !== 'crypto' && !knownGlobals.includes(global[val])) { + // without OpenSSL so we'll skip it if it is not available. + if (val === 'crypto' && !hasCrypto) { + continue; + } + if (!knownGlobals.has(globalThis[val])) { leaked.push(val); } } From b811dea85ac08d3c424cdff1a38f4b1d53377a05 Mon Sep 17 00:00:00 2001 From: James M Snell Date: Wed, 22 Jan 2025 15:30:30 -0800 Subject: [PATCH 156/205] test: replace more uses of `global` with `globalThis` PR-URL: https://github.com/nodejs/node/pull/56712 Reviewed-By: Yagiz Nizipli Reviewed-By: Matteo Collina --- test/parallel/test-aborted-util.js | 2 +- .../test-abortsignal-drop-settled-signals.mjs | 10 +-- test/parallel/test-assert-checktag.js | 8 +-- .../test-async-hooks-destroy-on-gc.js | 2 +- .../test-async-hooks-disable-gc-tracking.js | 2 +- ...test-async-hooks-prevent-double-destroy.js | 2 +- test/parallel/test-cli-eval.js | 2 +- test/parallel/test-common-gc.js | 4 +- .../parallel/test-console-assign-undefined.js | 16 ++--- test/parallel/test-console-instance.js | 4 +- test/parallel/test-console-self-assign.js | 2 +- test/parallel/test-crypto-dh-leak.js | 2 +- test/parallel/test-domain-crypto.js | 2 +- .../test-eventtarget-memoryleakwarning.js | 2 +- test/parallel/test-eventtarget.js | 2 +- .../test-finalization-registry-shutdown.js | 2 +- test/parallel/test-fs-filehandle.js | 2 +- .../test-fs-promises-file-handle-close.js | 2 +- test/parallel/test-fs-write-reuse-callback.js | 2 +- test/parallel/test-fs-write.js | 8 ++- .../test-gc-http-client-connaborted.js | 2 +- test/parallel/test-gc-net-timeout.js | 2 +- test/parallel/test-gc-tls-external-memory.js | 2 +- test/parallel/test-global-setters.js | 12 ++-- test/parallel/test-global.js | 14 ++-- ...-h2leak-destroy-session-on-socket-ended.js | 4 +- .../test-heapdump-async-hooks-init-promise.js | 2 +- .../test-http-agent-domain-reused-gc.js | 2 +- test/parallel/test-http-parser-bad-ref.js | 2 +- ...t-http-server-connections-checking-leak.js | 2 +- .../test-http-server-keepalive-req-gc.js | 4 +- test/parallel/test-http2-createwritereq.js | 2 +- ...-http2-session-gc-while-write-scheduled.js | 2 +- ...tp2-write-finishes-after-stream-destroy.js | 2 +- ...-https-server-connections-checking-leak.js | 2 +- .../test-inspector-scriptparsed-context.js | 4 +- ...r-vm-global-accessors-getter-sideeffect.js | 2 +- test/parallel/test-module-relative-lookup.js | 2 +- test/parallel/test-net-connect-memleak.js | 2 +- .../test-net-write-fully-async-buffer.js | 2 +- .../test-net-write-fully-async-hex-string.js | 2 +- test/parallel/test-performance-gc.js | 4 +- test/parallel/test-primitive-timer-leak.js | 2 +- test/parallel/test-repl-autolibs.js | 6 +- test/parallel/test-repl-underscore.js | 4 +- test/parallel/test-repl-use-global.js | 6 +- test/parallel/test-repl.js | 6 +- test/parallel/test-runner-mock-timers.js | 68 +++++++++---------- test/parallel/test-timers-api-refs.js | 12 ++-- .../parallel/test-timers-process-tampering.js | 4 +- test/parallel/test-tls-connect-memleak.js | 2 +- test/parallel/test-tls-securepair-leak.js | 2 +- ...test-tls-transport-destroy-after-own-gc.js | 6 +- test/parallel/test-trace-events-api.js | 2 +- test/parallel/test-util-format.js | 4 +- test/parallel/test-util-inspect.js | 6 +- test/parallel/test-vm-basic.js | 6 +- .../test-vm-create-and-run-in-context.js | 2 +- test/parallel/test-vm-cross-context.js | 2 +- test/parallel/test-vm-global-get-own.js | 26 +++---- test/parallel/test-vm-measure-memory-lazy.js | 10 +-- test/parallel/test-vm-module-basic.js | 12 ++-- .../test-vm-new-script-new-context.js | 34 +++++----- .../test-vm-new-script-this-context.js | 32 ++++----- test/parallel/test-vm-run-in-new-context.js | 34 +++++----- test/parallel/test-vm-static-this.js | 26 +++---- test/parallel/test-webstorage.js | 4 +- .../parallel/test-whatwg-url-custom-global.js | 4 +- test/parallel/test-worker-cli-options.js | 2 +- ...orker-message-channel-sharedarraybuffer.js | 2 +- .../parallel/test-worker-message-port-move.js | 2 +- ...est-worker-workerdata-sharedarraybuffer.js | 2 +- .../test-zlib-invalid-input-memory.js | 2 +- test/parallel/test-zlib-unused-weak.js | 4 +- 74 files changed, 246 insertions(+), 242 deletions(-) diff --git a/test/parallel/test-aborted-util.js b/test/parallel/test-aborted-util.js index 4bc45b9f5529bb..0566204ccdb074 100644 --- a/test/parallel/test-aborted-util.js +++ b/test/parallel/test-aborted-util.js @@ -32,7 +32,7 @@ test('Aborted with gc cleanup', async () => { const { promise, resolve } = Promise.withResolvers(); setImmediate(() => { - global.gc(); + globalThis.gc(); ac.abort(); strictEqual(ac.signal.aborted, true); strictEqual(getEventListeners(ac.signal, 'abort').length, 0); diff --git a/test/parallel/test-abortsignal-drop-settled-signals.mjs b/test/parallel/test-abortsignal-drop-settled-signals.mjs index 0abcaf81012716..b300b0e223fc93 100644 --- a/test/parallel/test-abortsignal-drop-settled-signals.mjs +++ b/test/parallel/test-abortsignal-drop-settled-signals.mjs @@ -16,7 +16,7 @@ function makeSubsequentCalls(limit, done, holdReferences = false) { // This setImmediate is necessary to ensure that in the last iteration the remaining signal is GCed (if not // retained) setImmediate(() => { - global.gc(); + globalThis.gc(); done(ac.signal, dependantSymbol); }); return; @@ -50,7 +50,7 @@ function runShortLivedSourceSignal(limit, done) { function run(iteration) { if (iteration > limit) { - global.gc(); + globalThis.gc(); done(signalRefs); return; } @@ -74,9 +74,9 @@ function runWithOrphanListeners(limit, done) { const ac = new AbortController(); if (iteration > limit) { setImmediate(() => { - global.gc(); + globalThis.gc(); setImmediate(() => { - global.gc(); + globalThis.gc(); done(composedSignalRefs); }); @@ -147,7 +147,7 @@ it('drops settled dependant signals when signal is composite', (t, done) => { t.assert.strictEqual(controllers[1].signal[kDependantSignals].size, 1); setImmediate(() => { - global.gc({ execution: 'async' }).then(async () => { + globalThis.gc({ execution: 'async' }).then(async () => { await gcUntil('all signals are GCed', () => { const totalDependantSignals = Math.max( controllers[0].signal[kDependantSignals].size, diff --git a/test/parallel/test-assert-checktag.js b/test/parallel/test-assert-checktag.js index 7587939436f40d..b86a1bde7f096d 100644 --- a/test/parallel/test-assert-checktag.js +++ b/test/parallel/test-assert-checktag.js @@ -49,13 +49,13 @@ test('', { skip: !hasCrypto }, () => { { // At the moment global has its own type tag const fakeGlobal = {}; - Object.setPrototypeOf(fakeGlobal, Object.getPrototypeOf(global)); - for (const prop of Object.keys(global)) { + Object.setPrototypeOf(fakeGlobal, Object.getPrototypeOf(globalThis)); + for (const prop of Object.keys(globalThis)) { fakeGlobal[prop] = global[prop]; } - assert.notDeepEqual(fakeGlobal, global); + assert.notDeepEqual(fakeGlobal, globalThis); // Message will be truncated anyway, don't validate - assert.throws(() => assert.deepStrictEqual(fakeGlobal, global), + assert.throws(() => assert.deepStrictEqual(fakeGlobal, globalThis), assert.AssertionError); } diff --git a/test/parallel/test-async-hooks-destroy-on-gc.js b/test/parallel/test-async-hooks-destroy-on-gc.js index fe6325e189734b..dd7eef8776cdf3 100644 --- a/test/parallel/test-async-hooks-destroy-on-gc.js +++ b/test/parallel/test-async-hooks-destroy-on-gc.js @@ -22,6 +22,6 @@ let asyncId = null; } setImmediate(() => { - global.gc(); + globalThis.gc(); setImmediate(() => assert.ok(destroyedIds.has(asyncId))); }); diff --git a/test/parallel/test-async-hooks-disable-gc-tracking.js b/test/parallel/test-async-hooks-disable-gc-tracking.js index 84c5043aad3335..87b096c258121c 100644 --- a/test/parallel/test-async-hooks-disable-gc-tracking.js +++ b/test/parallel/test-async-hooks-disable-gc-tracking.js @@ -14,7 +14,7 @@ const hook = async_hooks.createHook({ new async_hooks.AsyncResource('foobar', { requireManualDestroy: true }); setImmediate(() => { - global.gc(); + globalThis.gc(); setImmediate(() => { hook.disable(); }); diff --git a/test/parallel/test-async-hooks-prevent-double-destroy.js b/test/parallel/test-async-hooks-prevent-double-destroy.js index 689dc399f9d2f2..4aa55a5a6c87bf 100644 --- a/test/parallel/test-async-hooks-prevent-double-destroy.js +++ b/test/parallel/test-async-hooks-prevent-double-destroy.js @@ -17,7 +17,7 @@ const hook = async_hooks.createHook({ } setImmediate(() => { - global.gc(); + globalThis.gc(); setImmediate(() => { hook.disable(); }); diff --git a/test/parallel/test-cli-eval.js b/test/parallel/test-cli-eval.js index 0a4faf9c43311f..42e9369f6aa876 100644 --- a/test/parallel/test-cli-eval.js +++ b/test/parallel/test-cli-eval.js @@ -350,7 +350,7 @@ child.exec( // Regression test for https://github.com/nodejs/node/issues/45336 child.execFile(process.execPath, ['-p', - 'Object.defineProperty(global, "fs", { configurable: false });' + + 'Object.defineProperty(globalThis, "fs", { configurable: false });' + 'fs === require("node:fs")'], common.mustSucceed((stdout) => { assert.match(stdout, /^true/); diff --git a/test/parallel/test-common-gc.js b/test/parallel/test-common-gc.js index f7d73ccd0423e3..54abe3695cc3be 100644 --- a/test/parallel/test-common-gc.js +++ b/test/parallel/test-common-gc.js @@ -5,10 +5,10 @@ const { onGC } = require('../common/gc'); { onGC({}, { ongc: common.mustCall() }); - global.gc(); + globalThis.gc(); } { onGC(process, { ongc: common.mustNotCall() }); - global.gc(); + globalThis.gc(); } diff --git a/test/parallel/test-console-assign-undefined.js b/test/parallel/test-console-assign-undefined.js index 1021307b3c5f22..7f5b0e04727679 100644 --- a/test/parallel/test-console-assign-undefined.js +++ b/test/parallel/test-console-assign-undefined.js @@ -1,28 +1,28 @@ 'use strict'; -// Patch global.console before importing modules that may modify the console +// Patch globalThis.console before importing modules that may modify the console // object. -const tmp = global.console; -global.console = 42; +const tmp = globalThis.console; +globalThis.console = 42; require('../common'); const assert = require('assert'); // Originally the console had a getter. Test twice to verify it had no side // effect. -assert.strictEqual(global.console, 42); -assert.strictEqual(global.console, 42); +assert.strictEqual(globalThis.console, 42); +assert.strictEqual(globalThis.console, 42); assert.throws( () => console.log('foo'), { name: 'TypeError' } ); -global.console = 1; -assert.strictEqual(global.console, 1); +globalThis.console = 1; +assert.strictEqual(globalThis.console, 1); assert.strictEqual(console, 1); // Reset the console -global.console = tmp; +globalThis.console = tmp; console.log('foo'); diff --git a/test/parallel/test-console-instance.js b/test/parallel/test-console-instance.js index bf22314e22e031..0364a6213bc726 100644 --- a/test/parallel/test-console-instance.js +++ b/test/parallel/test-console-instance.js @@ -36,9 +36,9 @@ process.stdout.write = process.stderr.write = common.mustNotCall(); // Make sure that the "Console" function exists. assert.strictEqual(typeof Console, 'function'); -assert.strictEqual(requiredConsole, global.console); +assert.strictEqual(requiredConsole, globalThis.console); // Make sure the custom instanceof of Console works -assert.ok(global.console instanceof Console); +assert.ok(globalThis.console instanceof Console); assert.ok(!({} instanceof Console)); // Make sure that the Console constructor throws diff --git a/test/parallel/test-console-self-assign.js b/test/parallel/test-console-self-assign.js index 53c54ab9a327cf..46f9bc93d4f2bf 100644 --- a/test/parallel/test-console-self-assign.js +++ b/test/parallel/test-console-self-assign.js @@ -3,4 +3,4 @@ require('../common'); // Assigning to itself should not throw. -global.console = global.console; // eslint-disable-line no-self-assign +globalThis.console = globalThis.console; // eslint-disable-line no-self-assign diff --git a/test/parallel/test-crypto-dh-leak.js b/test/parallel/test-crypto-dh-leak.js index 3b5051feb43cd8..df1ba89737c619 100644 --- a/test/parallel/test-crypto-dh-leak.js +++ b/test/parallel/test-crypto-dh-leak.js @@ -22,7 +22,7 @@ const before = process.memoryUsage.rss(); dh.setPrivateKey(privateKey); } } -global.gc(); +globalThis.gc(); const after = process.memoryUsage.rss(); // RSS should stay the same, ceteris paribus, but allow for diff --git a/test/parallel/test-domain-crypto.js b/test/parallel/test-domain-crypto.js index e0a470bd9db515..47eb33f70aae45 100644 --- a/test/parallel/test-domain-crypto.js +++ b/test/parallel/test-domain-crypto.js @@ -31,7 +31,7 @@ const crypto = require('crypto'); // Pollution of global is intentional as part of test. common.allowGlobals(require('domain')); // See https://github.com/nodejs/node/commit/d1eff9ab -global.domain = require('domain'); +globalThis.domain = require('domain'); // Should not throw a 'TypeError: undefined is not a function' exception crypto.randomBytes(8); diff --git a/test/parallel/test-eventtarget-memoryleakwarning.js b/test/parallel/test-eventtarget-memoryleakwarning.js index 2c907165d865d9..2ec48720c8a8c5 100644 --- a/test/parallel/test-eventtarget-memoryleakwarning.js +++ b/test/parallel/test-eventtarget-memoryleakwarning.js @@ -103,7 +103,7 @@ common.expectWarning({ }); await setTimeout(0); - global.gc(); + globalThis.gc(); } })().then(common.mustCall(), common.mustNotCall()); } diff --git a/test/parallel/test-eventtarget.js b/test/parallel/test-eventtarget.js index cbe7eb3b0e8687..7153da172c1cf6 100644 --- a/test/parallel/test-eventtarget.js +++ b/test/parallel/test-eventtarget.js @@ -683,7 +683,7 @@ let asyncTest = Promise.resolve(); const et = new EventTarget(); et.addEventListener('foo', common.mustNotCall(), { [kWeakHandler]: {} }); setImmediate(() => { - global.gc(); + globalThis.gc(); et.dispatchEvent(new Event('foo')); }); } diff --git a/test/parallel/test-finalization-registry-shutdown.js b/test/parallel/test-finalization-registry-shutdown.js index f896aa2f285c75..e288d8fecca7e6 100644 --- a/test/parallel/test-finalization-registry-shutdown.js +++ b/test/parallel/test-finalization-registry-shutdown.js @@ -19,5 +19,5 @@ process.on('exit', () => { // This is the final chance to execute JavaScript. register(); // Queue a FinalizationRegistryCleanupTask by a testing gc request. - global.gc(); + globalThis.gc(); }); diff --git a/test/parallel/test-fs-filehandle.js b/test/parallel/test-fs-filehandle.js index 818a3824904431..bcb62da9e4c2cc 100644 --- a/test/parallel/test-fs-filehandle.js +++ b/test/parallel/test-fs-filehandle.js @@ -35,6 +35,6 @@ common.expectWarning({ 'DeprecationWarning': [[deprecationWarning, 'DEP0137']] }); -global.gc(); +globalThis.gc(); setTimeout(() => {}, 10); diff --git a/test/parallel/test-fs-promises-file-handle-close.js b/test/parallel/test-fs-promises-file-handle-close.js index d6417964746720..288bc31ea0ada5 100644 --- a/test/parallel/test-fs-promises-file-handle-close.js +++ b/test/parallel/test-fs-promises-file-handle-close.js @@ -32,7 +32,7 @@ doOpen().then(common.mustCall((fd) => { })).then(common.mustCall(() => { setImmediate(() => { // The FileHandle should be out-of-scope and no longer accessed now. - global.gc(); + globalThis.gc(); // Wait an extra event loop turn, as the warning is emitted from the // native layer in an unref()'ed setImmediate() callback. diff --git a/test/parallel/test-fs-write-reuse-callback.js b/test/parallel/test-fs-write-reuse-callback.js index 82c772ab340fed..c80902e54103fc 100644 --- a/test/parallel/test-fs-write-reuse-callback.js +++ b/test/parallel/test-fs-write-reuse-callback.js @@ -20,7 +20,7 @@ let done = 0; const ondone = common.mustSucceed(() => { if (++done < writes) { - if (done % 25 === 0) global.gc(); + if (done % 25 === 0) globalThis.gc(); setImmediate(write); } else { assert.strictEqual( diff --git a/test/parallel/test-fs-write.js b/test/parallel/test-fs-write.js index a4aeb4e16a748f..82f3425de2aa16 100644 --- a/test/parallel/test-fs-write.js +++ b/test/parallel/test-fs-write.js @@ -39,14 +39,18 @@ const { createExternalizableString, externalizeString, isOneByteString, -} = global; +} = globalThis; + +assert.notStrictEqual(createExternalizableString, undefined); +assert.notStrictEqual(externalizeString, undefined); +assert.notStrictEqual(isOneByteString, undefined); // Account for extra globals exposed by --expose_externalize_string. common.allowGlobals( createExternalizableString, externalizeString, isOneByteString, - global.x, + globalThis.x, ); { diff --git a/test/parallel/test-gc-http-client-connaborted.js b/test/parallel/test-gc-http-client-connaborted.js index 93ca8ee4de59f1..e52a555d788085 100644 --- a/test/parallel/test-gc-http-client-connaborted.js +++ b/test/parallel/test-gc-http-client-connaborted.js @@ -53,7 +53,7 @@ setImmediate(status); function status() { if (done > 0) { createClients = false; - global.gc(); + globalThis.gc(); console.log(`done/collected/total: ${done}/${countGC}/${count}`); if (countGC === count) { server.close(); diff --git a/test/parallel/test-gc-net-timeout.js b/test/parallel/test-gc-net-timeout.js index c4f74b34b79ec9..7a195c26bcdd6b 100644 --- a/test/parallel/test-gc-net-timeout.js +++ b/test/parallel/test-gc-net-timeout.js @@ -64,7 +64,7 @@ setImmediate(status); function status() { if (done > 0) { createClients = false; - global.gc(); + globalThis.gc(); console.log(`done/collected/total: ${done}/${countGC}/${count}`); if (countGC === count) { server.close(); diff --git a/test/parallel/test-gc-tls-external-memory.js b/test/parallel/test-gc-tls-external-memory.js index dcf38e11f6c6bf..480b1086b5395e 100644 --- a/test/parallel/test-gc-tls-external-memory.js +++ b/test/parallel/test-gc-tls-external-memory.js @@ -27,7 +27,7 @@ connect(); function connect() { if (runs % 64 === 0) - global.gc(); + globalThis.gc(); const externalMemoryUsage = process.memoryUsage().external; assert(externalMemoryUsage >= 0, `${externalMemoryUsage} < 0`); if (runs++ === 512) { diff --git a/test/parallel/test-global-setters.js b/test/parallel/test-global-setters.js index 7fd070ed8e1c4e..2da1097867261f 100644 --- a/test/parallel/test-global-setters.js +++ b/test/parallel/test-global-setters.js @@ -8,20 +8,20 @@ assert.strictEqual(process, _process); // eslint-disable-next-line no-global-assign process = 'asdf'; assert.strictEqual(process, 'asdf'); -assert.strictEqual(global.process, 'asdf'); -global.process = _process; +assert.strictEqual(globalThis.process, 'asdf'); +globalThis.process = _process; assert.strictEqual(process, _process); assert.strictEqual( - typeof Object.getOwnPropertyDescriptor(global, 'process').get, + typeof Object.getOwnPropertyDescriptor(globalThis, 'process').get, 'function'); assert.strictEqual(Buffer, _Buffer); // eslint-disable-next-line no-global-assign Buffer = 'asdf'; assert.strictEqual(Buffer, 'asdf'); -assert.strictEqual(global.Buffer, 'asdf'); -global.Buffer = _Buffer; +assert.strictEqual(globalThis.Buffer, 'asdf'); +globalThis.Buffer = _Buffer; assert.strictEqual(Buffer, _Buffer); assert.strictEqual( - typeof Object.getOwnPropertyDescriptor(global, 'Buffer').get, + typeof Object.getOwnPropertyDescriptor(globalThis, 'Buffer').get, 'function'); diff --git a/test/parallel/test-global.js b/test/parallel/test-global.js index 37f4db5252be5c..835bcc75a83e3b 100644 --- a/test/parallel/test-global.js +++ b/test/parallel/test-global.js @@ -60,9 +60,9 @@ for (const moduleName of builtinModules) { 'crypto', 'navigator', ]; - assert.deepStrictEqual(new Set(Object.keys(global)), new Set(expected)); + assert.deepStrictEqual(new Set(Object.keys(globalThis)), new Set(expected)); expected.forEach((value) => { - const desc = Object.getOwnPropertyDescriptor(global, value); + const desc = Object.getOwnPropertyDescriptor(globalThis, value); if (typeof desc.value === 'function') { assert.strictEqual(desc.value.name, value); } else if (typeof desc.get === 'function') { @@ -74,15 +74,15 @@ for (const moduleName of builtinModules) { common.allowGlobals('bar', 'foo'); baseFoo = 'foo'; // eslint-disable-line no-undef -global.baseBar = 'bar'; +globalThis.baseBar = 'bar'; -assert.strictEqual(global.baseFoo, 'foo', - `x -> global.x failed: global.baseFoo = ${global.baseFoo}`); +assert.strictEqual(globalThis.baseFoo, 'foo', + `x -> globalThis.x failed: globalThis.baseFoo = ${globalThis.baseFoo}`); assert.strictEqual(baseBar, // eslint-disable-line no-undef 'bar', // eslint-disable-next-line no-undef - `global.x -> x failed: baseBar = ${baseBar}`); + `globalThis.x -> x failed: baseBar = ${baseBar}`); const mod = require(fixtures.path('global', 'plain')); const fooBar = mod.fooBar; @@ -91,4 +91,4 @@ assert.strictEqual(fooBar.foo, 'foo'); assert.strictEqual(fooBar.bar, 'bar'); -assert.strictEqual(Object.prototype.toString.call(global), '[object global]'); +assert.strictEqual(Object.prototype.toString.call(globalThis), '[object global]'); diff --git a/test/parallel/test-h2leak-destroy-session-on-socket-ended.js b/test/parallel/test-h2leak-destroy-session-on-socket-ended.js index 3f0fe3e69d924d..af692b278f7d06 100644 --- a/test/parallel/test-h2leak-destroy-session-on-socket-ended.js +++ b/test/parallel/test-h2leak-destroy-session-on-socket-ended.js @@ -31,8 +31,8 @@ server.on('secureConnection', (s) => { firstServerStream = null; setImmediate(() => { - global.gc(); - global.gc(); + globalThis.gc(); + globalThis.gc(); server.close(); }); diff --git a/test/parallel/test-heapdump-async-hooks-init-promise.js b/test/parallel/test-heapdump-async-hooks-init-promise.js index c59cb89baa3d18..63b26843d1254e 100644 --- a/test/parallel/test-heapdump-async-hooks-init-promise.js +++ b/test/parallel/test-heapdump-async-hooks-init-promise.js @@ -43,4 +43,4 @@ async_hooks.createHook({ Promise.resolve().then(() => {}); -setImmediate(global.gc); +setImmediate(globalThis.gc); diff --git a/test/parallel/test-http-agent-domain-reused-gc.js b/test/parallel/test-http-agent-domain-reused-gc.js index 35146ee688eb9b..4f12c2ede839cd 100644 --- a/test/parallel/test-http-agent-domain-reused-gc.js +++ b/test/parallel/test-http-agent-domain-reused-gc.js @@ -26,7 +26,7 @@ async_hooks.createHook({ }, before(id) { if (id === reusedHandleId) { - global.gc(); + globalThis.gc(); checkBeforeCalled(); } } diff --git a/test/parallel/test-http-parser-bad-ref.js b/test/parallel/test-http-parser-bad-ref.js index 2c1bfe67485db7..e34054eca67063 100644 --- a/test/parallel/test-http-parser-bad-ref.js +++ b/test/parallel/test-http-parser-bad-ref.js @@ -18,7 +18,7 @@ let messagesComplete = 0; function flushPool() { Buffer.allocUnsafe(Buffer.poolSize - 1); - global.gc(); + globalThis.gc(); } function demoBug(part1, part2) { diff --git a/test/parallel/test-http-server-connections-checking-leak.js b/test/parallel/test-http-server-connections-checking-leak.js index 282c9a569fba7d..38dca83102cfea 100644 --- a/test/parallel/test-http-server-connections-checking-leak.js +++ b/test/parallel/test-http-server-connections-checking-leak.js @@ -20,5 +20,5 @@ for (let i = 0; i < max; i++) { } setImmediate(() => { - global.gc(); + globalThis.gc(); }); diff --git a/test/parallel/test-http-server-keepalive-req-gc.js b/test/parallel/test-http-server-keepalive-req-gc.js index 3bfb6c9600cc24..c827cd19ad7222 100644 --- a/test/parallel/test-http-server-keepalive-req-gc.js +++ b/test/parallel/test-http-server-keepalive-req-gc.js @@ -16,8 +16,8 @@ const server = createServer(common.mustCall((req, res) => { req.on('end', common.mustCall(() => { setImmediate(async () => { client.end(); - await global.gc({ type: 'major', execution: 'async' }); - await global.gc({ type: 'major', execution: 'async' }); + await globalThis.gc({ type: 'major', execution: 'async' }); + await globalThis.gc({ type: 'major', execution: 'async' }); }); })); res.end('hello world'); diff --git a/test/parallel/test-http2-createwritereq.js b/test/parallel/test-http2-createwritereq.js index 3015ad6c642801..6d2b07d5849ad0 100644 --- a/test/parallel/test-http2-createwritereq.js +++ b/test/parallel/test-http2-createwritereq.js @@ -69,7 +69,7 @@ server.listen(0, common.mustCall(function() { req.destroy = function(...args) { // Schedule a garbage collection event at the end of the current // MakeCallback() run. - process.nextTick(global.gc); + process.nextTick(globalThis.gc); return origDestroy.call(this, ...args); }; diff --git a/test/parallel/test-http2-session-gc-while-write-scheduled.js b/test/parallel/test-http2-session-gc-while-write-scheduled.js index 62379f7d7ed678..9693ded17c0a18 100644 --- a/test/parallel/test-http2-session-gc-while-write-scheduled.js +++ b/test/parallel/test-http2-session-gc-while-write-scheduled.js @@ -23,6 +23,6 @@ const tick = require('../common/tick'); // This schedules a write. client.settings(http2.getDefaultSettings()); client = null; - global.gc(); + globalThis.gc(); }); } diff --git a/test/parallel/test-http2-write-finishes-after-stream-destroy.js b/test/parallel/test-http2-write-finishes-after-stream-destroy.js index ed8833fdb926b1..bf9de8f9291917 100644 --- a/test/parallel/test-http2-write-finishes-after-stream-destroy.js +++ b/test/parallel/test-http2-write-finishes-after-stream-destroy.js @@ -9,7 +9,7 @@ const { duplexPair } = require('stream'); // Make sure the Http2Stream destructor works, since we don't clean the // stream up like we would otherwise do. -process.on('exit', global.gc); +process.on('exit', globalThis.gc); { const [ clientSide, serverSide ] = duplexPair(); diff --git a/test/parallel/test-https-server-connections-checking-leak.js b/test/parallel/test-https-server-connections-checking-leak.js index e920c8e403705f..f79149ef70a9ab 100644 --- a/test/parallel/test-https-server-connections-checking-leak.js +++ b/test/parallel/test-https-server-connections-checking-leak.js @@ -25,5 +25,5 @@ for (let i = 0; i < max; i++) { } setImmediate(() => { - global.gc(); + globalThis.gc(); }); diff --git a/test/parallel/test-inspector-scriptparsed-context.js b/test/parallel/test-inspector-scriptparsed-context.js index bd86ba53d4c986..31ae896c818b82 100644 --- a/test/parallel/test-inspector-scriptparsed-context.js +++ b/test/parallel/test-inspector-scriptparsed-context.js @@ -8,8 +8,8 @@ const script = ` 'use strict'; const assert = require('assert'); const vm = require('vm'); - global.outer = true; - global.inner = false; + globalThis.outer = true; + globalThis.inner = false; const context = vm.createContext({ outer: false, inner: true diff --git a/test/parallel/test-inspector-vm-global-accessors-getter-sideeffect.js b/test/parallel/test-inspector-vm-global-accessors-getter-sideeffect.js index 8b367e98c37f49..89414e50346871 100644 --- a/test/parallel/test-inspector-vm-global-accessors-getter-sideeffect.js +++ b/test/parallel/test-inspector-vm-global-accessors-getter-sideeffect.js @@ -14,7 +14,7 @@ session.connect(); const context = vm.createContext({ get a() { - global.foo = '1'; + globalThis.foo = '1'; return 100; } }); diff --git a/test/parallel/test-module-relative-lookup.js b/test/parallel/test-module-relative-lookup.js index 675c12c541fd4d..76af2b3b30c2e0 100644 --- a/test/parallel/test-module-relative-lookup.js +++ b/test/parallel/test-module-relative-lookup.js @@ -2,7 +2,7 @@ const common = require('../common'); const assert = require('assert'); -const _module = require('module'); // Avoid collision with global.module +const _module = require('module'); // Avoid collision with globalThis.module // Current directory gets highest priority for local modules function testFirstInPath(moduleName, isLocalModule) { diff --git a/test/parallel/test-net-connect-memleak.js b/test/parallel/test-net-connect-memleak.js index 84f643746838b6..079e45f7223a8b 100644 --- a/test/parallel/test-net-connect-memleak.js +++ b/test/parallel/test-net-connect-memleak.js @@ -49,7 +49,7 @@ const gcListener = { ongc() { collected = true; } }; } function done(sock) { - global.gc(); + globalThis.gc(); setImmediate(() => { assert.strictEqual(collected, true); sock.end(); diff --git a/test/parallel/test-net-write-fully-async-buffer.js b/test/parallel/test-net-write-fully-async-buffer.js index 0dddb51bd76ade..042dd79cb03127 100644 --- a/test/parallel/test-net-write-fully-async-buffer.js +++ b/test/parallel/test-net-write-fully-async-buffer.js @@ -23,7 +23,7 @@ const server = net.createServer(common.mustCall(function(conn) { } while (conn.write(Buffer.from(data))); - global.gc({ type: 'minor' }); + globalThis.gc({ type: 'minor' }); // The buffer allocated above should still be alive. } diff --git a/test/parallel/test-net-write-fully-async-hex-string.js b/test/parallel/test-net-write-fully-async-hex-string.js index 37b5cd75c1385c..b80b09f3244585 100644 --- a/test/parallel/test-net-write-fully-async-hex-string.js +++ b/test/parallel/test-net-write-fully-async-hex-string.js @@ -21,7 +21,7 @@ const server = net.createServer(common.mustCall(function(conn) { } while (conn.write(data, 'hex')); - global.gc({ type: 'minor' }); + globalThis.gc({ type: 'minor' }); // The buffer allocated inside the .write() call should still be alive. } diff --git a/test/parallel/test-performance-gc.js b/test/parallel/test-performance-gc.js index 9c4a3a850a22dd..9dddf7207f59d2 100644 --- a/test/parallel/test-performance-gc.js +++ b/test/parallel/test-performance-gc.js @@ -40,7 +40,7 @@ const kinds = [ obs.disconnect(); })); obs.observe({ entryTypes: ['gc'] }); - global.gc(); + globalThis.gc(); // Keep the event loop alive to witness the GC async callback happen. setImmediate(() => setImmediate(() => 0)); } @@ -51,6 +51,6 @@ const kinds = [ process.on('beforeExit', () => { assert(!didCall); didCall = true; - global.gc(); + globalThis.gc(); }); } diff --git a/test/parallel/test-primitive-timer-leak.js b/test/parallel/test-primitive-timer-leak.js index d590a0347b9cac..a0fe2765e1282d 100644 --- a/test/parallel/test-primitive-timer-leak.js +++ b/test/parallel/test-primitive-timer-leak.js @@ -5,7 +5,7 @@ const { onGC } = require('../common/gc'); // See https://github.com/nodejs/node/issues/53335 const poller = setInterval(() => { - global.gc(); + globalThis.gc(); }, 100); let count = 0; diff --git a/test/parallel/test-repl-autolibs.js b/test/parallel/test-repl-autolibs.js index 5cf3b1497221d0..a1eb476ef530b1 100644 --- a/test/parallel/test-repl-autolibs.js +++ b/test/parallel/test-repl-autolibs.js @@ -41,7 +41,7 @@ function test1() { assert.strictEqual(data, `${util.inspect(require('fs'), null, 2, false)}\n`); // Globally added lib matches required lib - assert.strictEqual(global.fs, require('fs')); + assert.strictEqual(globalThis.fs, require('fs')); test2(); } }; @@ -58,11 +58,11 @@ function test2() { // REPL response error message assert.strictEqual(data, '{}\n'); // Original value wasn't overwritten - assert.strictEqual(val, global.url); + assert.strictEqual(val, globalThis.url); } }; const val = {}; - global.url = val; + globalThis.url = val; common.allowGlobals(val); assert(!gotWrite); putIn.run(['url']); diff --git a/test/parallel/test-repl-underscore.js b/test/parallel/test-repl-underscore.js index 0f8103ce4573cd..8ce9de5563acfb 100644 --- a/test/parallel/test-repl-underscore.js +++ b/test/parallel/test-repl-underscore.js @@ -150,8 +150,8 @@ function testResetContextGlobal() { ]); // Delete globals leaked by REPL when `useGlobal` is `true` - delete global.module; - delete global.require; + delete globalThis.module; + delete globalThis.require; } function testError() { diff --git a/test/parallel/test-repl-use-global.js b/test/parallel/test-repl-use-global.js index 3457d0c5ba7210..06cda54f4d6fa2 100644 --- a/test/parallel/test-repl-use-global.js +++ b/test/parallel/test-repl-use-global.js @@ -20,10 +20,10 @@ const globalTest = (useGlobal, cb, output) => (err, repl) => { let str = ''; output.on('data', (data) => (str += data)); - global.lunch = 'tacos'; - repl.write('global.lunch;\n'); + globalThis.lunch = 'tacos'; + repl.write('globalThis.lunch;\n'); repl.close(); - delete global.lunch; + delete globalThis.lunch; cb(null, str.trim()); }; diff --git a/test/parallel/test-repl.js b/test/parallel/test-repl.js index be389072ce3638..0b29b973ee7e5c 100644 --- a/test/parallel/test-repl.js +++ b/test/parallel/test-repl.js @@ -36,7 +36,7 @@ const prompt_tcp = 'node via TCP socket> '; const moduleFilename = fixtures.path('a'); // Function for REPL to run -global.invoke_me = function(arg) { +globalThis.invoke_me = function(arg) { return `invoked ${arg}`; }; @@ -937,8 +937,8 @@ alternatively use dynamic import: const { default: alias, namedExport } = await socket.end(); } - common.allowGlobals(global.invoke_me, global.message, global.a, global.blah, - global.I, global.f, global.path, global.x, global.name, global.foo); + common.allowGlobals(globalThis.invoke_me, globalThis.message, globalThis.a, globalThis.blah, + globalThis.I, globalThis.f, globalThis.path, globalThis.x, globalThis.name, globalThis.foo); })().then(common.mustCall()); function startTCPRepl() { diff --git a/test/parallel/test-runner-mock-timers.js b/test/parallel/test-runner-mock-timers.js index 87b8ba7e3784d2..da7458b4c46dd3 100644 --- a/test/parallel/test-runner-mock-timers.js +++ b/test/parallel/test-runner-mock-timers.js @@ -69,7 +69,7 @@ describe('Mock Timers Test Suite', () => { 'clearImmediate', ]; - const globalTimersDescriptors = timers.map((fn) => getDescriptor(global, fn)); + const globalTimersDescriptors = timers.map((fn) => getDescriptor(globalThis, fn)); const nodeTimersDescriptors = timers.map((fn) => getDescriptor(nodeTimers, fn)); const nodeTimersPromisesDescriptors = timers .filter((fn) => !fn.includes('clear')) @@ -116,7 +116,7 @@ describe('Mock Timers Test Suite', () => { it('should reset all timers when calling .reset function', (t) => { t.mock.timers.enable(); const fn = t.mock.fn(); - global.setTimeout(fn, 1000); + globalThis.setTimeout(fn, 1000); t.mock.timers.reset(); assert.deepStrictEqual(Date.now, globalThis.Date.now); assert.throws(() => { @@ -131,7 +131,7 @@ describe('Mock Timers Test Suite', () => { it('should reset all timers when calling Symbol.dispose', (t) => { t.mock.timers.enable(); const fn = t.mock.fn(); - global.setTimeout(fn, 1000); + globalThis.setTimeout(fn, 1000); // TODO(benjamingr) refactor to `using` t.mock.timers[Symbol.dispose](); assert.throws(() => { @@ -148,8 +148,8 @@ describe('Mock Timers Test Suite', () => { const order = []; const fn1 = t.mock.fn(() => order.push('f1')); const fn2 = t.mock.fn(() => order.push('f2')); - global.setTimeout(fn1, 1000); - global.setTimeout(fn2, 1000); + globalThis.setTimeout(fn1, 1000); + globalThis.setTimeout(fn2, 1000); t.mock.timers.tick(1000); assert.strictEqual(fn1.mock.callCount(), 1); assert.strictEqual(fn2.mock.callCount(), 1); @@ -170,11 +170,11 @@ describe('Mock Timers Test Suite', () => { const intervalFn = t.mock.fn(); t.mock.timers.enable(); - global.setTimeout(timeoutFn, 1111); - const id = global.setInterval(intervalFn, 9999); + globalThis.setTimeout(timeoutFn, 1111); + const id = globalThis.setInterval(intervalFn, 9999); t.mock.timers.runAll(); - global.clearInterval(id); + globalThis.clearInterval(id); assert.strictEqual(timeoutFn.mock.callCount(), 1); assert.strictEqual(intervalFn.mock.callCount(), 1); }); @@ -184,11 +184,11 @@ describe('Mock Timers Test Suite', () => { const intervalFn = t.mock.fn(); t.mock.timers.enable(); - global.setTimeout(timeoutFn, 1111); - const id = global.setInterval(intervalFn, 9999); + globalThis.setTimeout(timeoutFn, 1111); + const id = globalThis.setInterval(intervalFn, 9999); t.mock.timers.runAll(); - global.clearInterval(id); + globalThis.clearInterval(id); assert.strictEqual(timeoutFn.mock.callCount(), 1); assert.strictEqual(intervalFn.mock.callCount(), 1); assert.strictEqual(Date.now(), 9999); @@ -209,7 +209,7 @@ describe('Mock Timers Test Suite', () => { const fn = mock.fn(); - global.setTimeout(fn, 4000); + globalThis.setTimeout(fn, 4000); mock.timers.tick(4000); assert.strictEqual(fn.mock.callCount(), 1); @@ -220,7 +220,7 @@ describe('Mock Timers Test Suite', () => { t.mock.timers.enable({ apis: ['setTimeout'] }); const fn = t.mock.fn(); - global.setTimeout(fn, 2000); + globalThis.setTimeout(fn, 2000); t.mock.timers.tick(1000); assert.strictEqual(fn.mock.callCount(), 0); @@ -234,7 +234,7 @@ describe('Mock Timers Test Suite', () => { t.mock.timers.enable({ apis: ['setTimeout'] }); const fn = t.mock.fn(); const args = ['a', 'b', 'c']; - global.setTimeout(fn, 2000, ...args); + globalThis.setTimeout(fn, 2000, ...args); t.mock.timers.tick(1000); t.mock.timers.tick(500); @@ -248,7 +248,7 @@ describe('Mock Timers Test Suite', () => { const now = Date.now(); const timeout = 2; const expected = () => now - timeout; - global.setTimeout(common.mustCall(() => { + globalThis.setTimeout(common.mustCall(() => { assert.strictEqual(now - timeout, expected()); done(); }), timeout); @@ -257,7 +257,7 @@ describe('Mock Timers Test Suite', () => { it('should change timeout to 1ms when it is > TIMEOUT_MAX', (t) => { t.mock.timers.enable({ apis: ['setTimeout'] }); const fn = t.mock.fn(); - global.setTimeout(fn, TIMEOUT_MAX + 1); + globalThis.setTimeout(fn, TIMEOUT_MAX + 1); t.mock.timers.tick(1); assert.strictEqual(fn.mock.callCount(), 1); }); @@ -265,7 +265,7 @@ describe('Mock Timers Test Suite', () => { it('should change the delay to one if timeout < 0', (t) => { t.mock.timers.enable({ apis: ['setTimeout'] }); const fn = t.mock.fn(); - global.setTimeout(fn, -1); + globalThis.setTimeout(fn, -1); t.mock.timers.tick(1); assert.strictEqual(fn.mock.callCount(), 1); }); @@ -277,8 +277,8 @@ describe('Mock Timers Test Suite', () => { const fn = mock.fn(); - const id = global.setTimeout(fn, 4000); - global.clearTimeout(id); + const id = globalThis.setTimeout(fn, 4000); + globalThis.clearTimeout(id); t.mock.timers.tick(4000); assert.strictEqual(fn.mock.callCount(), 0); @@ -297,13 +297,13 @@ describe('Mock Timers Test Suite', () => { t.mock.timers.enable({ apis: ['setInterval'] }); const fn = t.mock.fn(); - const id = global.setInterval(fn, 200); + const id = globalThis.setInterval(fn, 200); t.mock.timers.tick(200); t.mock.timers.tick(200); t.mock.timers.tick(200); - global.clearInterval(id); + globalThis.clearInterval(id); assert.strictEqual(fn.mock.callCount(), 3); }); @@ -312,13 +312,13 @@ describe('Mock Timers Test Suite', () => { t.mock.timers.enable({ apis: ['setInterval'] }); const fn = t.mock.fn(); const args = ['a', 'b', 'c']; - const id = global.setInterval(fn, 200, ...args); + const id = globalThis.setInterval(fn, 200, ...args); t.mock.timers.tick(200); t.mock.timers.tick(200); t.mock.timers.tick(200); - global.clearInterval(id); + globalThis.clearInterval(id); assert.strictEqual(fn.mock.callCount(), 3); assert.deepStrictEqual(fn.mock.calls[0].arguments, args); @@ -332,8 +332,8 @@ describe('Mock Timers Test Suite', () => { t.mock.timers.enable({ apis: ['setInterval'] }); const fn = mock.fn(); - const id = global.setInterval(fn, 200); - global.clearInterval(id); + const id = globalThis.setInterval(fn, 200); + globalThis.clearInterval(id); t.mock.timers.tick(200); assert.strictEqual(fn.mock.callCount(), 0); @@ -352,7 +352,7 @@ describe('Mock Timers Test Suite', () => { const now = Date.now(); const timeout = 2; const expected = () => now - timeout; - global.setImmediate(common.mustCall(() => { + globalThis.setImmediate(common.mustCall(() => { assert.strictEqual(now - timeout, expected()); done(); })); @@ -362,7 +362,7 @@ describe('Mock Timers Test Suite', () => { t.mock.timers.enable({ apis: ['setImmediate'] }); const fn = t.mock.fn(); const args = ['a', 'b', 'c']; - global.setImmediate(fn, ...args); + globalThis.setImmediate(fn, ...args); t.mock.timers.tick(9999); assert.strictEqual(fn.mock.callCount(), 1); @@ -372,14 +372,14 @@ describe('Mock Timers Test Suite', () => { it('should not advance in time if clearImmediate was invoked', (t) => { t.mock.timers.enable({ apis: ['setImmediate'] }); - const id = global.setImmediate(common.mustNotCall()); - global.clearImmediate(id); + const id = globalThis.setImmediate(common.mustNotCall()); + globalThis.clearImmediate(id); t.mock.timers.tick(200); }); it('should advance in time and trigger timers when calling the .tick function', (t) => { t.mock.timers.enable({ apis: ['setImmediate'] }); - global.setImmediate(common.mustCall(1)); + globalThis.setImmediate(common.mustCall(1)); t.mock.timers.tick(0); }); @@ -389,8 +389,8 @@ describe('Mock Timers Test Suite', () => { const fn1 = t.mock.fn(common.mustCall(() => order.push('f1'), 1)); const fn2 = t.mock.fn(common.mustCall(() => order.push('f2'), 1)); - global.setImmediate(fn1); - global.setImmediate(fn2); + globalThis.setImmediate(fn1); + globalThis.setImmediate(fn2); t.mock.timers.tick(0); @@ -403,8 +403,8 @@ describe('Mock Timers Test Suite', () => { const fn1 = t.mock.fn(common.mustCall(() => order.push('f1'), 1)); const fn2 = t.mock.fn(common.mustCall(() => order.push('f2'), 1)); - global.setTimeout(fn2, 0); - global.setImmediate(fn1); + globalThis.setTimeout(fn2, 0); + globalThis.setImmediate(fn1); t.mock.timers.tick(100); diff --git a/test/parallel/test-timers-api-refs.js b/test/parallel/test-timers-api-refs.js index 3c55a05ac4c20a..a6a541963110bb 100644 --- a/test/parallel/test-timers-api-refs.js +++ b/test/parallel/test-timers-api-refs.js @@ -4,12 +4,12 @@ const timers = require('timers'); // Delete global APIs to make sure they're not relied on by the internal timers // code -delete global.setTimeout; -delete global.clearTimeout; -delete global.setInterval; -delete global.clearInterval; -delete global.setImmediate; -delete global.clearImmediate; +delete globalThis.setTimeout; +delete globalThis.clearTimeout; +delete globalThis.setInterval; +delete globalThis.clearInterval; +delete globalThis.setImmediate; +delete globalThis.clearImmediate; const timeoutCallback = () => { timers.clearTimeout(timeout); }; const timeout = timers.setTimeout(common.mustCall(timeoutCallback), 1); diff --git a/test/parallel/test-timers-process-tampering.js b/test/parallel/test-timers-process-tampering.js index 766cc9f3560c82..8632e7c96fa086 100644 --- a/test/parallel/test-timers-process-tampering.js +++ b/test/parallel/test-timers-process-tampering.js @@ -3,6 +3,6 @@ 'use strict'; const common = require('../common'); -global.process = {}; // Boom! -common.allowGlobals(global.process); +globalThis.process = {}; // Boom! +common.allowGlobals(globalThis.process); setImmediate(common.mustCall()); diff --git a/test/parallel/test-tls-connect-memleak.js b/test/parallel/test-tls-connect-memleak.js index 5bdcbe89f785f6..7b9cb71d8df0ba 100644 --- a/test/parallel/test-tls-connect-memleak.js +++ b/test/parallel/test-tls-connect-memleak.js @@ -57,7 +57,7 @@ const gcListener = { ongc() { collected = true; } }; } function done(sock) { - global.gc(); + globalThis.gc(); setImmediate(() => { assert.strictEqual(collected, true); sock.end(); diff --git a/test/parallel/test-tls-securepair-leak.js b/test/parallel/test-tls-securepair-leak.js index 98bdcde76ec034..e3d5c2cdf37b5d 100644 --- a/test/parallel/test-tls-securepair-leak.js +++ b/test/parallel/test-tls-securepair-leak.js @@ -17,7 +17,7 @@ const before = process.memoryUsage().external; createSecurePair(context, false, false, false, options).destroy(); } setImmediate(() => { - global.gc(); + globalThis.gc(); const after = process.memoryUsage().external; // It's not an exact science but a SecurePair grows .external by about 45 KiB. diff --git a/test/parallel/test-tls-transport-destroy-after-own-gc.js b/test/parallel/test-tls-transport-destroy-after-own-gc.js index 17c494ca0b79d1..bcac2c6ebde2b8 100644 --- a/test/parallel/test-tls-transport-destroy-after-own-gc.js +++ b/test/parallel/test-tls-transport-destroy-after-own-gc.js @@ -19,11 +19,11 @@ let clientTLSHandle = clientTLS._handle; // eslint-disable-line no-unused-vars setImmediate(() => { clientTLS = null; - global.gc(); + globalThis.gc(); clientTLSHandle = null; - global.gc(); + globalThis.gc(); setImmediate(() => { clientSide = null; - global.gc(); + globalThis.gc(); }); }); diff --git a/test/parallel/test-trace-events-api.js b/test/parallel/test-trace-events-api.js index 8792a40cf00c80..9bffb3b78c4ba3 100644 --- a/test/parallel/test-trace-events-api.js +++ b/test/parallel/test-trace-events-api.js @@ -109,7 +109,7 @@ if (isChild) { assert.strictEqual(getEnabledCategories(), 'abc'); tracing3 = undefined; } - global.gc(); + globalThis.gc(); assert.strictEqual(getEnabledCategories(), 'abc'); // Not able to disable the thing after this point, however. } diff --git a/test/parallel/test-util-format.js b/test/parallel/test-util-format.js index 8d2cab5a9c7a1c..6f222d0fea0fb8 100644 --- a/test/parallel/test-util-format.js +++ b/test/parallel/test-util-format.js @@ -197,9 +197,9 @@ assert.strictEqual(util.format('%s', -Infinity), '-Infinity'); util.format('%s', Object.setPrototypeOf(new Foo(), null)), '[Foo: null prototype] {}' ); - global.Foo = Foo; + globalThis.Foo = Foo; assert.strictEqual(util.format('%s', new Foo()), 'Bar'); - delete global.Foo; + delete globalThis.Foo; class Bar { abc = true; } assert.strictEqual(util.format('%s', new Bar()), 'Bar { abc: true }'); class Foobar extends Array { aaa = true; } diff --git a/test/parallel/test-util-inspect.js b/test/parallel/test-util-inspect.js index e84d80073bb3ad..48aaad977282fb 100644 --- a/test/parallel/test-util-inspect.js +++ b/test/parallel/test-util-inspect.js @@ -1265,9 +1265,9 @@ if (typeof Symbol !== 'undefined') { // a bonafide native Promise. { const oldPromise = Promise; - global.Promise = function() { this.bar = 42; }; + globalThis.Promise = function() { this.bar = 42; }; assert.strictEqual(util.inspect(new Promise()), '{ bar: 42 }'); - global.Promise = oldPromise; + globalThis.Promise = oldPromise; } // Test Map iterators. @@ -3181,7 +3181,7 @@ assert.strictEqual( } // Consistency check. - assert(fullObjectGraph(global).has(Function.prototype)); + assert(fullObjectGraph(globalThis).has(Function.prototype)); } { diff --git a/test/parallel/test-vm-basic.js b/test/parallel/test-vm-basic.js index 93c3fbaea631ab..5687987faeb0b9 100644 --- a/test/parallel/test-vm-basic.js +++ b/test/parallel/test-vm-basic.js @@ -59,9 +59,9 @@ const vm = require('vm'); const result = vm.runInThisContext( 'vmResult = "foo"; Object.prototype.toString.call(process);' ); - assert.strictEqual(global.vmResult, 'foo'); + assert.strictEqual(globalThis.vmResult, 'foo'); assert.strictEqual(result, '[object process]'); - delete global.vmResult; + delete globalThis.vmResult; } // vm.runInNewContext @@ -69,7 +69,7 @@ const vm = require('vm'); const result = vm.runInNewContext( 'vmResult = "foo"; typeof process;' ); - assert.strictEqual(global.vmResult, undefined); + assert.strictEqual(globalThis.vmResult, undefined); assert.strictEqual(result, 'undefined'); } diff --git a/test/parallel/test-vm-create-and-run-in-context.js b/test/parallel/test-vm-create-and-run-in-context.js index bd746cf2df7080..314ab9525743dc 100644 --- a/test/parallel/test-vm-create-and-run-in-context.js +++ b/test/parallel/test-vm-create-and-run-in-context.js @@ -45,6 +45,6 @@ assert.strictEqual(context.thing, 'lala'); // Run in contextified sandbox without referencing the context const sandbox = { x: 1 }; vm.createContext(sandbox); -global.gc(); +globalThis.gc(); vm.runInContext('x = 2', sandbox); // Should not crash. diff --git a/test/parallel/test-vm-cross-context.js b/test/parallel/test-vm-cross-context.js index b7cf1309d3689f..abdfde32a8d847 100644 --- a/test/parallel/test-vm-cross-context.js +++ b/test/parallel/test-vm-cross-context.js @@ -23,7 +23,7 @@ require('../common'); const vm = require('vm'); -const ctx = vm.createContext(global); +const ctx = vm.createContext(globalThis); // Should not throw. vm.runInContext('!function() { var x = console.log; }()', ctx); diff --git a/test/parallel/test-vm-global-get-own.js b/test/parallel/test-vm-global-get-own.js index 246fcbf866b8b6..de5e0a9619af65 100644 --- a/test/parallel/test-vm-global-get-own.js +++ b/test/parallel/test-vm-global-get-own.js @@ -9,7 +9,7 @@ const vm = require('vm'); // Related to: // - https://github.com/nodejs/node/issues/45983 -const global = vm.runInContext('this', vm.createContext()); +const contextGlobal = vm.runInContext('this', vm.createContext()); function runAssertions(data, property, viaDefine, value1, value2, value3) { // Define the property for the first time @@ -35,20 +35,20 @@ function runAssertionsOnSandbox(builder) { } // Assertions on: define property -runAssertions(global, 'toto', true, 1, 2, 3); -runAssertions(global, Symbol.for('toto'), true, 1, 2, 3); -runAssertions(global, 'tutu', true, fun1, fun2, fun3); -runAssertions(global, Symbol.for('tutu'), true, fun1, fun2, fun3); -runAssertions(global, 'tyty', true, fun1, 2, 3); -runAssertions(global, Symbol.for('tyty'), true, fun1, 2, 3); +runAssertions(contextGlobal, 'toto', true, 1, 2, 3); +runAssertions(contextGlobal, Symbol.for('toto'), true, 1, 2, 3); +runAssertions(contextGlobal, 'tutu', true, fun1, fun2, fun3); +runAssertions(contextGlobal, Symbol.for('tutu'), true, fun1, fun2, fun3); +runAssertions(contextGlobal, 'tyty', true, fun1, 2, 3); +runAssertions(contextGlobal, Symbol.for('tyty'), true, fun1, 2, 3); // Assertions on: direct assignment -runAssertions(global, 'titi', false, 1, 2, 3); -runAssertions(global, Symbol.for('titi'), false, 1, 2, 3); -runAssertions(global, 'tata', false, fun1, fun2, fun3); -runAssertions(global, Symbol.for('tata'), false, fun1, fun2, fun3); -runAssertions(global, 'tztz', false, fun1, 2, 3); -runAssertions(global, Symbol.for('tztz'), false, fun1, 2, 3); +runAssertions(contextGlobal, 'titi', false, 1, 2, 3); +runAssertions(contextGlobal, Symbol.for('titi'), false, 1, 2, 3); +runAssertions(contextGlobal, 'tata', false, fun1, fun2, fun3); +runAssertions(contextGlobal, Symbol.for('tata'), false, fun1, fun2, fun3); +runAssertions(contextGlobal, 'tztz', false, fun1, 2, 3); +runAssertions(contextGlobal, Symbol.for('tztz'), false, fun1, 2, 3); // Assertions on: define property from sandbox runAssertionsOnSandbox( diff --git a/test/parallel/test-vm-measure-memory-lazy.js b/test/parallel/test-vm-measure-memory-lazy.js index 513cfbc3672451..7f85f8d6ca9656 100644 --- a/test/parallel/test-vm-measure-memory-lazy.js +++ b/test/parallel/test-vm-measure-memory-lazy.js @@ -10,28 +10,28 @@ const vm = require('vm'); expectExperimentalWarning(); -// Test lazy memory measurement - we will need to global.gc() +// Test lazy memory measurement - we will need to globalThis.gc() // or otherwise these may not resolve. { vm.measureMemory() .then(common.mustCall(assertSummaryShape)); - global.gc(); + globalThis.gc(); } { vm.measureMemory({}) .then(common.mustCall(assertSummaryShape)); - global.gc(); + globalThis.gc(); } { vm.measureMemory({ mode: 'summary' }) .then(common.mustCall(assertSummaryShape)); - global.gc(); + globalThis.gc(); } { vm.measureMemory({ mode: 'detailed' }) .then(common.mustCall(assertSummaryShape)); - global.gc(); + globalThis.gc(); } diff --git a/test/parallel/test-vm-module-basic.js b/test/parallel/test-vm-module-basic.js index cba1e037ac455a..53fed6536079a0 100644 --- a/test/parallel/test-vm-module-basic.js +++ b/test/parallel/test-vm-module-basic.js @@ -37,15 +37,15 @@ const util = require('util'); (async () => { const m = new SourceTextModule(` - global.vmResultFoo = "foo"; - global.vmResultTypeofProcess = Object.prototype.toString.call(process); + globalThis.vmResultFoo = "foo"; + globalThis.vmResultTypeofProcess = Object.prototype.toString.call(process); `); await m.link(common.mustNotCall()); await m.evaluate(); - assert.strictEqual(global.vmResultFoo, 'foo'); - assert.strictEqual(global.vmResultTypeofProcess, '[object process]'); - delete global.vmResultFoo; - delete global.vmResultTypeofProcess; + assert.strictEqual(globalThis.vmResultFoo, 'foo'); + assert.strictEqual(globalThis.vmResultTypeofProcess, '[object process]'); + delete globalThis.vmResultFoo; + delete globalThis.vmResultTypeofProcess; })().then(common.mustCall()); (async () => { diff --git a/test/parallel/test-vm-new-script-new-context.js b/test/parallel/test-vm-new-script-new-context.js index 482b4130d615d9..b4221d81d98dcb 100644 --- a/test/parallel/test-vm-new-script-new-context.js +++ b/test/parallel/test-vm-new-script-new-context.js @@ -49,43 +49,43 @@ const Script = require('vm').Script; } { - global.hello = 5; + globalThis.hello = 5; const script = new Script('hello = 2'); script.runInNewContext(); - assert.strictEqual(global.hello, 5); + assert.strictEqual(globalThis.hello, 5); // Cleanup - delete global.hello; + delete globalThis.hello; } { - global.code = 'foo = 1;' + + globalThis.code = 'foo = 1;' + 'bar = 2;' + 'if (baz !== 3) throw new Error(\'test fail\');'; - global.foo = 2; - global.obj = { foo: 0, baz: 3 }; - const script = new Script(global.code); + globalThis.foo = 2; + globalThis.obj = { foo: 0, baz: 3 }; + const script = new Script(globalThis.code); /* eslint-disable no-unused-vars */ - const baz = script.runInNewContext(global.obj); + const baz = script.runInNewContext(globalThis.obj); /* eslint-enable no-unused-vars */ - assert.strictEqual(global.obj.foo, 1); - assert.strictEqual(global.obj.bar, 2); - assert.strictEqual(global.foo, 2); + assert.strictEqual(globalThis.obj.foo, 1); + assert.strictEqual(globalThis.obj.bar, 2); + assert.strictEqual(globalThis.foo, 2); // cleanup - delete global.code; - delete global.foo; - delete global.obj; + delete globalThis.code; + delete globalThis.foo; + delete globalThis.obj; } { const script = new Script('f()'); - function changeFoo() { global.foo = 100; } + function changeFoo() { globalThis.foo = 100; } script.runInNewContext({ f: changeFoo }); - assert.strictEqual(global.foo, 100); + assert.strictEqual(globalThis.foo, 100); // cleanup - delete global.foo; + delete globalThis.foo; } { diff --git a/test/parallel/test-vm-new-script-this-context.js b/test/parallel/test-vm-new-script-this-context.js index 18f39f9086ae2a..30b220e3d4a2c2 100644 --- a/test/parallel/test-vm-new-script-this-context.js +++ b/test/parallel/test-vm-new-script-this-context.js @@ -35,34 +35,34 @@ assert.throws(() => { script.runInThisContext(script); }, /^Error: test$/); -global.hello = 5; +globalThis.hello = 5; script = new Script('hello = 2'); script.runInThisContext(script); -assert.strictEqual(global.hello, 2); +assert.strictEqual(globalThis.hello, 2); // Pass values -global.code = 'foo = 1;' + +globalThis.code = 'foo = 1;' + 'bar = 2;' + 'if (typeof baz !== "undefined") throw new Error("test fail");'; -global.foo = 2; -global.obj = { foo: 0, baz: 3 }; -script = new Script(global.code); +globalThis.foo = 2; +globalThis.obj = { foo: 0, baz: 3 }; +script = new Script(globalThis.code); script.runInThisContext(script); -assert.strictEqual(global.obj.foo, 0); -assert.strictEqual(global.bar, 2); -assert.strictEqual(global.foo, 1); +assert.strictEqual(globalThis.obj.foo, 0); +assert.strictEqual(globalThis.bar, 2); +assert.strictEqual(globalThis.foo, 1); // Call a function -global.f = function() { global.foo = 100; }; +globalThis.f = function() { globalThis.foo = 100; }; script = new Script('f()'); script.runInThisContext(script); -assert.strictEqual(global.foo, 100); +assert.strictEqual(globalThis.foo, 100); common.allowGlobals( - global.hello, - global.code, - global.foo, - global.obj, - global.f + globalThis.hello, + globalThis.code, + globalThis.foo, + globalThis.obj, + globalThis.f ); diff --git a/test/parallel/test-vm-run-in-new-context.js b/test/parallel/test-vm-run-in-new-context.js index 6e8c42812bbc88..c6f8fbf893ca9a 100644 --- a/test/parallel/test-vm-run-in-new-context.js +++ b/test/parallel/test-vm-run-in-new-context.js @@ -26,7 +26,7 @@ const common = require('../common'); const assert = require('assert'); const vm = require('vm'); -if (typeof global.gc !== 'function') +if (typeof globalThis.gc !== 'function') assert.fail('Run this test with --expose-gc'); // Run a string @@ -38,28 +38,28 @@ assert.throws(() => { vm.runInNewContext('throw new Error(\'test\');'); }, /^Error: test$/); -global.hello = 5; +globalThis.hello = 5; vm.runInNewContext('hello = 2'); -assert.strictEqual(global.hello, 5); +assert.strictEqual(globalThis.hello, 5); // Pass values in and out -global.code = 'foo = 1;' + +globalThis.code = 'foo = 1;' + 'bar = 2;' + 'if (baz !== 3) throw new Error(\'test fail\');'; -global.foo = 2; -global.obj = { foo: 0, baz: 3 }; +globalThis.foo = 2; +globalThis.obj = { foo: 0, baz: 3 }; /* eslint-disable no-unused-vars */ -const baz = vm.runInNewContext(global.code, global.obj); +const baz = vm.runInNewContext(globalThis.code, globalThis.obj); /* eslint-enable no-unused-vars */ -assert.strictEqual(global.obj.foo, 1); -assert.strictEqual(global.obj.bar, 2); -assert.strictEqual(global.foo, 2); +assert.strictEqual(globalThis.obj.foo, 1); +assert.strictEqual(globalThis.obj.bar, 2); +assert.strictEqual(globalThis.foo, 2); // Call a function by reference -function changeFoo() { global.foo = 100; } +function changeFoo() { globalThis.foo = 100; } vm.runInNewContext('f()', { f: changeFoo }); -assert.strictEqual(global.foo, 100); +assert.strictEqual(globalThis.foo, 100); // Modify an object by reference const f = { a: 1 }; @@ -68,7 +68,7 @@ assert.strictEqual(f.a, 2); // Use function in context without referencing context const fn = vm.runInNewContext('(function() { obj.p = {}; })', { obj: {} }); -global.gc(); +globalThis.gc(); fn(); // Should not crash @@ -93,8 +93,8 @@ for (const arg of [filename, { filename }]) { } common.allowGlobals( - global.hello, - global.code, - global.foo, - global.obj + globalThis.hello, + globalThis.code, + globalThis.foo, + globalThis.obj ); diff --git a/test/parallel/test-vm-static-this.js b/test/parallel/test-vm-static-this.js index e9382d6c3b4c1a..f47c0b5d0d056a 100644 --- a/test/parallel/test-vm-static-this.js +++ b/test/parallel/test-vm-static-this.js @@ -33,9 +33,9 @@ assert.throws(function() { vm.runInThisContext('throw new Error(\'test\');'); }, /test/); -global.hello = 5; +globalThis.hello = 5; vm.runInThisContext('hello = 2'); -assert.strictEqual(global.hello, 2); +assert.strictEqual(globalThis.hello, 2); // pass values @@ -43,23 +43,23 @@ const code = 'foo = 1;' + 'bar = 2;' + 'if (typeof baz !== \'undefined\')' + 'throw new Error(\'test fail\');'; -global.foo = 2; -global.obj = { foo: 0, baz: 3 }; +globalThis.foo = 2; +globalThis.obj = { foo: 0, baz: 3 }; /* eslint-disable no-unused-vars */ const baz = vm.runInThisContext(code); /* eslint-enable no-unused-vars */ -assert.strictEqual(global.obj.foo, 0); -assert.strictEqual(global.bar, 2); -assert.strictEqual(global.foo, 1); +assert.strictEqual(globalThis.obj.foo, 0); +assert.strictEqual(globalThis.bar, 2); +assert.strictEqual(globalThis.foo, 1); // call a function -global.f = function() { global.foo = 100; }; +globalThis.f = function() { globalThis.foo = 100; }; vm.runInThisContext('f()'); -assert.strictEqual(global.foo, 100); +assert.strictEqual(globalThis.foo, 100); common.allowGlobals( - global.hello, - global.foo, - global.obj, - global.f + globalThis.hello, + globalThis.foo, + globalThis.obj, + globalThis.f ); diff --git a/test/parallel/test-webstorage.js b/test/parallel/test-webstorage.js index 4da6b67bd2932b..7f9fe8dfa53391 100644 --- a/test/parallel/test-webstorage.js +++ b/test/parallel/test-webstorage.js @@ -69,7 +69,7 @@ test('sessionStorage is not persisted', async () => { test('localStorage throws without --localstorage-file ', async () => { const cp = await spawnPromisified(process.execPath, [ '--experimental-webstorage', - '-pe', 'localStorage === global.localStorage', + '-pe', 'localStorage === globalThis.localStorage', ]); assert.strictEqual(cp.code, 1); assert.strictEqual(cp.signal, null); @@ -81,7 +81,7 @@ test('localStorage is not persisted if it is unused', async () => { const cp = await spawnPromisified(process.execPath, [ '--experimental-webstorage', '--localstorage-file', nextLocalStorage(), - '-pe', 'localStorage === global.localStorage', + '-pe', 'localStorage === globalThis.localStorage', ]); assert.strictEqual(cp.code, 0); assert.match(cp.stdout, /true/); diff --git a/test/parallel/test-whatwg-url-custom-global.js b/test/parallel/test-whatwg-url-custom-global.js index b99dfd8f3e7d94..16efdfa8df1174 100644 --- a/test/parallel/test-whatwg-url-custom-global.js +++ b/test/parallel/test-whatwg-url-custom-global.js @@ -6,7 +6,7 @@ require('../common'); const assert = require('assert'); assert.deepStrictEqual( - Object.getOwnPropertyDescriptor(global, 'URL'), + Object.getOwnPropertyDescriptor(globalThis, 'URL'), { value: URL, writable: true, @@ -16,7 +16,7 @@ assert.deepStrictEqual( ); assert.deepStrictEqual( - Object.getOwnPropertyDescriptor(global, 'URLSearchParams'), + Object.getOwnPropertyDescriptor(globalThis, 'URLSearchParams'), { value: URLSearchParams, writable: true, diff --git a/test/parallel/test-worker-cli-options.js b/test/parallel/test-worker-cli-options.js index 0c243d251e97bc..3e6ab46db6ea74 100644 --- a/test/parallel/test-worker-cli-options.js +++ b/test/parallel/test-worker-cli-options.js @@ -8,7 +8,7 @@ const CODE = ` // If the --expose-internals flag does not pass to worker // require function will throw an error require('internal/options'); -global.gc(); +globalThis.gc(); `; // Test if the flags is passed to worker threads correctly diff --git a/test/parallel/test-worker-message-channel-sharedarraybuffer.js b/test/parallel/test-worker-message-channel-sharedarraybuffer.js index 220aa978b12051..6ee577d447ec97 100644 --- a/test/parallel/test-worker-message-channel-sharedarraybuffer.js +++ b/test/parallel/test-worker-message-channel-sharedarraybuffer.js @@ -19,7 +19,7 @@ const { Worker } = require('worker_threads'); `, { eval: true }); w.on('message', common.mustCall(() => { assert.strictEqual(local.toString(), 'Hello world!'); - global.gc(); + globalThis.gc(); w.terminate(); })); w.postMessage({ sharedArrayBuffer }); diff --git a/test/parallel/test-worker-message-port-move.js b/test/parallel/test-worker-message-port-move.js index 44efd2e6a6b94f..b8db31b88c7bc4 100644 --- a/test/parallel/test-worker-message-port-move.js +++ b/test/parallel/test-worker-message-port-move.js @@ -48,7 +48,7 @@ vm.runInContext('(' + function() { { let threw = false; try { - port.postMessage(global); + port.postMessage(globalThis); } catch (e) { assert.strictEqual(e.constructor.name, 'DOMException'); assert(e instanceof Object); diff --git a/test/parallel/test-worker-workerdata-sharedarraybuffer.js b/test/parallel/test-worker-workerdata-sharedarraybuffer.js index 4e3d508ac94941..4f1b332461280f 100644 --- a/test/parallel/test-worker-workerdata-sharedarraybuffer.js +++ b/test/parallel/test-worker-workerdata-sharedarraybuffer.js @@ -23,7 +23,7 @@ const { Worker } = require('worker_threads'); }); w.on('message', common.mustCall(() => { assert.strictEqual(local.toString(), 'Hello world!'); - global.gc(); + globalThis.gc(); w.terminate(); })); w.postMessage({}); diff --git a/test/parallel/test-zlib-invalid-input-memory.js b/test/parallel/test-zlib-invalid-input-memory.js index 9761e4bbf097d8..ac718395dae184 100644 --- a/test/parallel/test-zlib-invalid-input-memory.js +++ b/test/parallel/test-zlib-invalid-input-memory.js @@ -17,7 +17,7 @@ const ongc = common.mustCall(); strm.once('error', common.mustCall((err) => { assert(err); setImmediate(() => { - global.gc(); + globalThis.gc(); // Keep the event loop alive for seeing the async_hooks destroy hook // we use for GC tracking... // TODO(addaleax): This should maybe not be necessary? diff --git a/test/parallel/test-zlib-unused-weak.js b/test/parallel/test-zlib-unused-weak.js index 2c1e2d729030dd..cd1ab91ceb5c4b 100644 --- a/test/parallel/test-zlib-unused-weak.js +++ b/test/parallel/test-zlib-unused-weak.js @@ -6,12 +6,12 @@ const zlib = require('zlib'); // Tests that native zlib handles start out their life as weak handles. -global.gc(); +globalThis.gc(); const before = process.memoryUsage().external; for (let i = 0; i < 100; ++i) zlib.createGzip(); const afterCreation = process.memoryUsage().external; -global.gc(); +globalThis.gc(); const afterGC = process.memoryUsage().external; assert((afterGC - before) / (afterCreation - before) <= 0.05, From 52ef3767881b5cfdaeb03be3f5e63377d2cfbbb9 Mon Sep 17 00:00:00 2001 From: yamachu Date: Wed, 22 Jan 2025 20:21:46 +0900 Subject: [PATCH 157/205] test: add test that uses multibyte for path and resolves modules PR-URL: https://github.com/nodejs/node/pull/56696 Fixes: https://github.com/nodejs/node/issues/56650 Refs: https://github.com/nodejs/node/pull/56657 Reviewed-By: James M Snell Reviewed-By: Yagiz Nizipli Reviewed-By: Luigi Pinca --- .../experimental.json" | 3 +++ .../test-module-create-require-multibyte.js | 24 +++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 "test/fixtures/copy/utf/\346\226\260\345\273\272\346\226\207\344\273\266\345\244\271/experimental.json" create mode 100644 test/parallel/test-module-create-require-multibyte.js diff --git "a/test/fixtures/copy/utf/\346\226\260\345\273\272\346\226\207\344\273\266\345\244\271/experimental.json" "b/test/fixtures/copy/utf/\346\226\260\345\273\272\346\226\207\344\273\266\345\244\271/experimental.json" new file mode 100644 index 00000000000000..12611d2385a5a5 --- /dev/null +++ "b/test/fixtures/copy/utf/\346\226\260\345\273\272\346\226\207\344\273\266\345\244\271/experimental.json" @@ -0,0 +1,3 @@ +{ + "ofLife": 42 +} diff --git a/test/parallel/test-module-create-require-multibyte.js b/test/parallel/test-module-create-require-multibyte.js new file mode 100644 index 00000000000000..f9c4b6345dc59e --- /dev/null +++ b/test/parallel/test-module-create-require-multibyte.js @@ -0,0 +1,24 @@ +'use strict'; + +require('../common'); +const fixtures = require('../common/fixtures'); +const assert = require('assert'); + +// This test ensures that the module can be resolved +// even if the path given to createRequire contains multibyte characters. + +const { createRequire } = require('module'); + +{ + const u = fixtures.fileURL('あ.js'); + + const reqToo = createRequire(u); + assert.deepStrictEqual(reqToo('./experimental'), { ofLife: 42 }); +} + +{ + const u = fixtures.fileURL('copy/utf/新建文件夹/index.js'); + + const reqToo = createRequire(u); + assert.deepStrictEqual(reqToo('./experimental'), { ofLife: 42 }); +} From 432a4b8bd6c4ccf76542e43435645aa0de52fab3 Mon Sep 17 00:00:00 2001 From: yamachu Date: Wed, 22 Jan 2025 20:24:38 +0900 Subject: [PATCH 158/205] src: fix to generate path from wchar_t via wstring Take a similar approach to node_file and allow the creation of paths code point must be specified to convert from wchar_t to utf8. PR-URL: https://github.com/nodejs/node/pull/56696 Fixes: https://github.com/nodejs/node/issues/56650 Refs: https://github.com/nodejs/node/pull/56657 Reviewed-By: James M Snell Reviewed-By: Yagiz Nizipli Reviewed-By: Luigi Pinca --- src/node_file.cc | 15 +-------------- src/node_modules.cc | 24 ++++++++++++++++++++---- src/util-inl.h | 16 ++++++++++++++++ 3 files changed, 37 insertions(+), 18 deletions(-) diff --git a/src/node_file.cc b/src/node_file.cc index 9676cd4fe78c4e..1d22e19f16d5ad 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -3047,21 +3047,8 @@ static void GetFormatOfExtensionlessFile( } #ifdef _WIN32 -std::wstring ConvertToWideString(const std::string& str) { - int size_needed = MultiByteToWideChar( - CP_UTF8, 0, &str[0], static_cast(str.size()), nullptr, 0); - std::wstring wstrTo(size_needed, 0); - MultiByteToWideChar(CP_UTF8, - 0, - &str[0], - static_cast(str.size()), - &wstrTo[0], - size_needed); - return wstrTo; -} - #define BufferValueToPath(str) \ - std::filesystem::path(ConvertToWideString(str.ToString())) + std::filesystem::path(ConvertToWideString(str.ToString(), CP_UTF8)) std::string ConvertWideToUTF8(const std::wstring& wstr) { if (wstr.empty()) return std::string(); diff --git a/src/node_modules.cc b/src/node_modules.cc index 4b522a91323c9f..210a01d24e1176 100644 --- a/src/node_modules.cc +++ b/src/node_modules.cc @@ -344,8 +344,16 @@ void BindingData::GetNearestParentPackageJSON( path_value_str.push_back(kPathSeparator); } - auto package_json = - TraverseParent(realm, std::filesystem::path(path_value_str)); + std::filesystem::path path; + +#ifdef _WIN32 + std::wstring wide_path = ConvertToWideString(path_value_str, GetACP()); + path = std::filesystem::path(wide_path); +#else + path = std::filesystem::path(path_value_str); +#endif + + auto package_json = TraverseParent(realm, path); if (package_json != nullptr) { args.GetReturnValue().Set(package_json->Serialize(realm)); @@ -370,8 +378,16 @@ void BindingData::GetNearestParentPackageJSONType( path_value_str.push_back(kPathSeparator); } - auto package_json = - TraverseParent(realm, std::filesystem::path(path_value_str)); + std::filesystem::path path; + +#ifdef _WIN32 + std::wstring wide_path = ConvertToWideString(path_value_str, GetACP()); + path = std::filesystem::path(wide_path); +#else + path = std::filesystem::path(path_value_str); +#endif + + auto package_json = TraverseParent(realm, path); if (package_json == nullptr) { return; diff --git a/src/util-inl.h b/src/util-inl.h index a35e15eeed6576..b5ae5950b62767 100644 --- a/src/util-inl.h +++ b/src/util-inl.h @@ -562,6 +562,22 @@ bool IsWindowsBatchFile(const char* filename) { #endif // _WIN32 } +#ifdef _WIN32 +inline std::wstring ConvertToWideString(const std::string& str, + UINT code_page) { + int size_needed = MultiByteToWideChar( + code_page, 0, &str[0], static_cast(str.size()), nullptr, 0); + std::wstring wstrTo(size_needed, 0); + MultiByteToWideChar(code_page, + 0, + &str[0], + static_cast(str.size()), + &wstrTo[0], + size_needed); + return wstrTo; +} +#endif // _WIN32 + } // namespace node #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS From 7bae51e62e1452e2abe38c62157b235eca94fd21 Mon Sep 17 00:00:00 2001 From: tjuhaszrh Date: Sat, 25 Jan 2025 10:34:54 +0100 Subject: [PATCH 159/205] src: fix build with GCC 15 Added cstdint to worker_inspector as on more recent version of gcc the build was failing due to changes to libstdc++ and the removal of transitive includes. PR-URL: https://github.com/nodejs/node/pull/56740 Fixes: https://github.com/nodejs/node/issues/56731 Reviewed-By: Antoine du Hamel Reviewed-By: Chengzhong Wu Reviewed-By: Richard Lau Reviewed-By: James M Snell --- src/inspector/worker_inspector.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/inspector/worker_inspector.h b/src/inspector/worker_inspector.h index d3254d5aa0ebe4..24403bb1704c40 100644 --- a/src/inspector/worker_inspector.h +++ b/src/inspector/worker_inspector.h @@ -5,6 +5,7 @@ #error("This header can only be used when inspector is enabled") #endif +#include #include #include #include From 927c7e47e44b30a9eac44498ba23ba6b5d11166b Mon Sep 17 00:00:00 2001 From: Robin Mehner Date: Sat, 25 Jan 2025 12:02:31 +0100 Subject: [PATCH 160/205] doc: fix typo in example code for util.styleText MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Code shows how to style `errorMessage`, but then only logs out `successMessage` twice. This might trip people up when copying the code. PR-URL: https://github.com/nodejs/node/pull/56720 Reviewed-By: Ulises Gascón Reviewed-By: Richard Lau Reviewed-By: James M Snell Reviewed-By: Luigi Pinca Reviewed-By: Minwoo Jung --- doc/api/util.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/api/util.md b/doc/api/util.md index 405b38e032587f..19b41c7dcc9d4a 100644 --- a/doc/api/util.md +++ b/doc/api/util.md @@ -1964,7 +1964,7 @@ const errorMessage = styleText( // Validate if process.stderr has TTY { stream: stderr }, ); -console.error(successMessage); +console.error(errorMessage); ``` ```cjs From 89a7c82e0c3ae5ebfbfa0b588b4782cad0e0021d Mon Sep 17 00:00:00 2001 From: Burkov Egor Date: Wed, 22 Jan 2025 16:27:26 +0300 Subject: [PATCH 161/205] src: add default value for RSACipherConfig mode field MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using default init of enum is UB Refs: https://github.com/nodejs/node/issues/56693 PR-URL: https://github.com/nodejs/node/pull/56701 Reviewed-By: Juan José Arboleda Reviewed-By: Yagiz Nizipli Reviewed-By: James M Snell --- src/crypto/crypto_rsa.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/crypto/crypto_rsa.h b/src/crypto/crypto_rsa.h index 29b259ae2f5284..6fc48da1aea2cd 100644 --- a/src/crypto/crypto_rsa.h +++ b/src/crypto/crypto_rsa.h @@ -77,7 +77,7 @@ struct RSAKeyExportTraits final { using RSAKeyExportJob = KeyExportJob; struct RSACipherConfig final : public MemoryRetainer { - CryptoJobMode mode; + CryptoJobMode mode = kCryptoJobAsync; ByteSource label; int padding = 0; const EVP_MD* digest = nullptr; From 49405bd9e7ed8dfb7d705143ccc697a85f15e2c5 Mon Sep 17 00:00:00 2001 From: James M Snell Date: Wed, 22 Jan 2025 16:58:49 -0800 Subject: [PATCH 162/205] test: make some requires lazy in common/index PR-URL: https://github.com/nodejs/node/pull/56715 Reviewed-By: Yagiz Nizipli Reviewed-By: Richard Lau Reviewed-By: Matteo Collina --- test/common/index.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/test/common/index.js b/test/common/index.js index 8f6c3e82b3869d..92c7294e6f6298 100644 --- a/test/common/index.js +++ b/test/common/index.js @@ -23,7 +23,6 @@ const process = globalThis.process; // Some tests tamper with the process globalThis. const assert = require('assert'); -const { exec, execSync, spawn, spawnSync } = require('child_process'); const fs = require('fs'); const net = require('net'); // Do not require 'os' until needed so that test-os-checked-function can @@ -31,7 +30,6 @@ const net = require('net'); const path = require('path'); const { inspect, getCallSites } = require('util'); const { isMainThread } = require('worker_threads'); -const { isModuleNamespaceObject } = require('util/types'); const tmpdir = require('./tmpdir'); const bits = ['arm64', 'loong64', 'mips', 'mipsel', 'ppc64', 'riscv64', 's390x', 'x64'] @@ -104,6 +102,7 @@ if (process.argv.length === 2 && inspect(flags), 'Use NODE_SKIP_FLAG_CHECK to run the test with the original flags.', ); + const { spawnSync } = require('child_process'); const args = [...flags, ...process.execArgv, ...process.argv.slice(1)]; const options = { encoding: 'utf8', stdio: 'inherit' }; const result = spawnSync(process.execPath, args, options); @@ -232,6 +231,7 @@ function childShouldThrowAndAbort() { // continuous testing and developers' machines escapedArgs[0] = 'ulimit -c 0 && ' + escapedArgs[0]; } + const { exec } = require('child_process'); const child = exec(...escapedArgs); child.on('exit', function onExit(exitCode, signal) { const errMsg = 'Test should have aborted ' + @@ -474,6 +474,7 @@ function canCreateSymLink() { 'System32', 'whoami.exe'); try { + const { execSync } = require('child_process'); const output = execSync(`${whoamiPath} /priv`, { timeout: 1000 }); return output.includes('SeCreateSymbolicLinkPrivilege'); } catch { @@ -780,6 +781,7 @@ function requireNoPackageJSONAbove(dir = __dirname) { } function spawnPromisified(...args) { + const { spawn } = require('child_process'); let stderr = ''; let stdout = ''; @@ -843,6 +845,7 @@ function escapePOSIXShell(cmdParts, ...args) { * @param {object} expectation shape of expected namespace. */ function expectRequiredModule(mod, expectation, checkESModule = true) { + const { isModuleNamespaceObject } = require('util/types'); const clone = { ...mod }; if (Object.hasOwn(mod, 'default') && checkESModule) { assert.strictEqual(mod.__esModule, true); @@ -920,6 +923,7 @@ const common = { }, get inFreeBSDJail() { + const { execSync } = require('child_process'); if (inFreeBSDJail !== null) return inFreeBSDJail; if (exports.isFreeBSD && From 5dd7116e09a521de07e84f6347022c5a5edb2206 Mon Sep 17 00:00:00 2001 From: Jonas Date: Sat, 25 Jan 2025 17:02:54 -0500 Subject: [PATCH 163/205] watch: reload env file for --env-file-if-exists PR-URL: https://github.com/nodejs/node/pull/56643 Reviewed-By: Yagiz Nizipli Reviewed-By: James M Snell --- lib/internal/main/watch_mode.js | 2 +- test/sequential/test-watch-mode.mjs | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/lib/internal/main/watch_mode.js b/lib/internal/main/watch_mode.js index 6e2528e64737c7..60639efb45482d 100644 --- a/lib/internal/main/watch_mode.js +++ b/lib/internal/main/watch_mode.js @@ -33,7 +33,7 @@ markBootstrapComplete(); // TODO(MoLow): Make kill signal configurable const kKillSignal = 'SIGTERM'; const kShouldFilterModules = getOptionValue('--watch-path').length === 0; -const kEnvFile = getOptionValue('--env-file'); +const kEnvFile = getOptionValue('--env-file') || getOptionValue('--env-file-if-exists'); const kWatchedPaths = ArrayPrototypeMap(getOptionValue('--watch-path'), (path) => resolve(path)); const kPreserveOutput = getOptionValue('--watch-preserve-output'); const kCommand = ArrayPrototypeSlice(process.argv, 1); diff --git a/test/sequential/test-watch-mode.mjs b/test/sequential/test-watch-mode.mjs index 39bc7223dffdfc..324cdd10b3b4ef 100644 --- a/test/sequential/test-watch-mode.mjs +++ b/test/sequential/test-watch-mode.mjs @@ -242,6 +242,32 @@ describe('watch mode', { concurrency: !process.env.TEST_PARALLEL, timeout: 60_00 } }); + it('should load new env variables when --env-file-if-exists changes', async () => { + const envKey = `TEST_ENV_${Date.now()}`; + const envKey2 = `TEST_ENV_2_${Date.now()}`; + const jsFile = createTmpFile(`console.log('ENV: ' + process.env.${envKey} + '\\n' + 'ENV2: ' + process.env.${envKey2});`); + const envFile = createTmpFile(`${envKey}=value1`, '.env'); + const { done, restart } = runInBackground({ args: ['--watch', `--env-file-if-exists=${envFile}`, jsFile] }); + + try { + await restart(); + writeFileSync(envFile, `${envKey}=value1\n${envKey2}=newValue`); + + // Second restart, after env change + const { stderr, stdout } = await restart(); + + assert.strictEqual(stderr, ''); + assert.deepStrictEqual(stdout, [ + `Restarting ${inspect(jsFile)}`, + 'ENV: value1', + 'ENV2: newValue', + `Completed running ${inspect(jsFile)}`, + ]); + } finally { + await done(); + } + }); + it('should watch changes to a failing file', async () => { const file = createTmpFile('throw new Error("fails");'); const { stderr, stdout } = await runWriteSucceed({ From cd7ce18233078a6b7a644c0e484850278520bafa Mon Sep 17 00:00:00 2001 From: Dario Piotrowicz Date: Sat, 25 Jan 2025 23:32:13 +0000 Subject: [PATCH 164/205] module: fix bad `require.resolve` with option paths for `.` and `..` this change fixes `require.resolve` used with the `paths` option not considering `.` and `..` as relative Fixes: https://github.com/nodejs/node/issues/47000 PR-URL: https://github.com/nodejs/node/pull/56735 Reviewed-By: Yagiz Nizipli Reviewed-By: James M Snell Reviewed-By: Jordan Harband Reviewed-By: Matteo Collina --- lib/internal/modules/cjs/loader.js | 34 +++++++-------- .../relative/subdir/relative-subdir.js | 1 + ...est-require-resolve-opts-paths-relative.js | 43 +++++++++++++++++++ 3 files changed, 61 insertions(+), 17 deletions(-) create mode 100644 test/fixtures/module-require/relative/subdir/relative-subdir.js create mode 100644 test/parallel/test-require-resolve-opts-paths-relative.js diff --git a/lib/internal/modules/cjs/loader.js b/lib/internal/modules/cjs/loader.js index 236b2484049c43..e21bcb798c4d53 100644 --- a/lib/internal/modules/cjs/loader.js +++ b/lib/internal/modules/cjs/loader.js @@ -713,18 +713,8 @@ Module._findPath = function(request, paths, isMain) { ) )); - const isRelative = StringPrototypeCharCodeAt(request, 0) === CHAR_DOT && - ( - request.length === 1 || - StringPrototypeCharCodeAt(request, 1) === CHAR_FORWARD_SLASH || - (isWindows && StringPrototypeCharCodeAt(request, 1) === CHAR_BACKWARD_SLASH) || - (StringPrototypeCharCodeAt(request, 1) === CHAR_DOT && (( - request.length === 2 || - StringPrototypeCharCodeAt(request, 2) === CHAR_FORWARD_SLASH) || - (isWindows && StringPrototypeCharCodeAt(request, 2) === CHAR_BACKWARD_SLASH))) - ); let insidePath = true; - if (isRelative) { + if (isRelative(request)) { const normalizedRequest = path.normalize(request); if (StringPrototypeStartsWith(normalizedRequest, '..')) { insidePath = false; @@ -1164,12 +1154,7 @@ Module._resolveFilename = function(request, parent, isMain, options) { if (typeof options === 'object' && options !== null) { if (ArrayIsArray(options.paths)) { - const isRelative = StringPrototypeStartsWith(request, './') || - StringPrototypeStartsWith(request, '../') || - ((isWindows && StringPrototypeStartsWith(request, '.\\')) || - StringPrototypeStartsWith(request, '..\\')); - - if (isRelative) { + if (isRelative(request)) { paths = options.paths; } else { const fakeParent = new Module('', null); @@ -1774,6 +1759,21 @@ function createRequire(filename) { return createRequireFromPath(filepath); } +/** + * Checks if a path is relative + * @param {string} path the target path + * @returns {boolean} true if the path is relative, false otherwise + */ +function isRelative(path) { + if (StringPrototypeCharCodeAt(path, 0) !== CHAR_DOT) { return false; } + + return path.length === 1 || path === '..' || + StringPrototypeStartsWith(path, './') || + StringPrototypeStartsWith(path, '../') || + ((isWindows && StringPrototypeStartsWith(path, '.\\')) || + StringPrototypeStartsWith(path, '..\\')); +} + Module.createRequire = createRequire; /** diff --git a/test/fixtures/module-require/relative/subdir/relative-subdir.js b/test/fixtures/module-require/relative/subdir/relative-subdir.js new file mode 100644 index 00000000000000..34eb71b3c6ca39 --- /dev/null +++ b/test/fixtures/module-require/relative/subdir/relative-subdir.js @@ -0,0 +1 @@ +exports.value = 'relative subdir'; diff --git a/test/parallel/test-require-resolve-opts-paths-relative.js b/test/parallel/test-require-resolve-opts-paths-relative.js new file mode 100644 index 00000000000000..522a1fdbce82a4 --- /dev/null +++ b/test/parallel/test-require-resolve-opts-paths-relative.js @@ -0,0 +1,43 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const fixtures = require('../common/fixtures'); + +if (!common.isMainThread) + common.skip('process.chdir is not available in Workers'); + +const subdir = fixtures.path('module-require', 'relative', 'subdir'); + +process.chdir(subdir); + +// Parent directory paths (`..`) work as intended +{ + assert(require.resolve('.', { paths: ['../'] }).endsWith('index.js')); + assert(require.resolve('./index.js', { paths: ['../'] }).endsWith('index.js')); + + // paths: [".."] should resolve like paths: ["../"] + assert(require.resolve('.', { paths: ['..'] }).endsWith('index.js')); + assert(require.resolve('./index.js', { paths: ['..'] }).endsWith('index.js')); +} + +process.chdir('..'); + +// Current directory paths (`.`) work as intended +{ + assert(require.resolve('.', { paths: ['.'] }).endsWith('index.js')); + assert(require.resolve('./index.js', { paths: ['./'] }).endsWith('index.js')); + + // paths: ["."] should resolve like paths: ["../"] + assert(require.resolve('.', { paths: ['.'] }).endsWith('index.js')); + assert(require.resolve('./index.js', { paths: ['.'] }).endsWith('index.js')); +} + +// Sub directory paths work as intended +{ + // assert.deepStrictEqual(fs.readdirSync('./subdir'), [5]); + assert(require.resolve('./relative-subdir.js', { paths: ['./subdir'] }).endsWith('relative-subdir.js')); + + // paths: ["subdir"] should resolve like paths: ["./subdir"] + assert(require.resolve('./relative-subdir.js', { paths: ['subdir'] }).endsWith('relative-subdir.js')); +} From 1a79e876871bebb733eb522b4f7258b7d64a5949 Mon Sep 17 00:00:00 2001 From: Dario Piotrowicz Date: Sun, 26 Jan 2025 01:30:11 +0000 Subject: [PATCH 165/205] doc: add note regarding commit message trailers Co-authored-by: Yagiz Nizipli Co-authored-by: Antoine du Hamel PR-URL: https://github.com/nodejs/node/pull/56736 Reviewed-By: James M Snell Reviewed-By: Antoine du Hamel Reviewed-By: Rafael Gonzaga Reviewed-By: Luigi Pinca --- doc/contributing/pull-requests.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/contributing/pull-requests.md b/doc/contributing/pull-requests.md index 2ad538b3fd8e29..8914d60c95aa2f 100644 --- a/doc/contributing/pull-requests.md +++ b/doc/contributing/pull-requests.md @@ -184,6 +184,11 @@ A good commit message should describe what changed and why. of the log. 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. + Examples: * `Fixes: https://github.com/nodejs/node/issues/1337` From 89ba3af743872086ab027654b93301c3d0d4973c Mon Sep 17 00:00:00 2001 From: Burkov Egor Date: Wed, 22 Jan 2025 16:16:31 +0300 Subject: [PATCH 166/205] src: add nullptr handling from X509_STORE_new() In openssl we should check result of X509_STORE_new() for nullptr Refs: https://github.com/nodejs/node/issues/56694 PR-URL: https://github.com/nodejs/node/pull/56700 Reviewed-By: James M Snell Reviewed-By: Luigi Pinca --- src/crypto/crypto_context.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/crypto/crypto_context.cc b/src/crypto/crypto_context.cc index c7574e67f03f03..c89d591c6804ab 100644 --- a/src/crypto/crypto_context.cc +++ b/src/crypto/crypto_context.cc @@ -272,6 +272,7 @@ X509_STORE* NewRootCertStore() { } X509_STORE* store = X509_STORE_new(); + CHECK_NOT_NULL(store); if (*system_cert_path != '\0') { ERR_set_mark(); X509_STORE_load_locations(store, system_cert_path, nullptr); From f1442d6eafcb95d5c67dafe5789a3391c0e950a2 Mon Sep 17 00:00:00 2001 From: Luigi Pinca Date: Sun, 26 Jan 2025 17:41:21 +0100 Subject: [PATCH 167/205] test: do not use common.isMainThread MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `common.isMainThread` was removed in https://github.com/nodejs/node/commit/8caa1dcee63b2c6fd7a9, use the `isMainThread` export of the `worker_threads` module instead. PR-URL: https://github.com/nodejs/node/pull/56768 Reviewed-By: Michaël Zasso Reviewed-By: James M Snell Reviewed-By: Chengzhong Wu Reviewed-By: Matteo Collina --- test/parallel/test-require-resolve-opts-paths-relative.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/parallel/test-require-resolve-opts-paths-relative.js b/test/parallel/test-require-resolve-opts-paths-relative.js index 522a1fdbce82a4..13d17d478b753d 100644 --- a/test/parallel/test-require-resolve-opts-paths-relative.js +++ b/test/parallel/test-require-resolve-opts-paths-relative.js @@ -3,8 +3,9 @@ const common = require('../common'); const assert = require('assert'); const fixtures = require('../common/fixtures'); +const { isMainThread } = require('worker_threads'); -if (!common.isMainThread) +if (!isMainThread) common.skip('process.chdir is not available in Workers'); const subdir = fixtures.path('module-require', 'relative', 'subdir'); From 5c030da42f778f232c101cf3cd0db2ca485e86fc Mon Sep 17 00:00:00 2001 From: James M Snell Date: Sun, 26 Jan 2025 09:19:39 -0800 Subject: [PATCH 168/205] test: cleanup and simplify test-crypto-aes-wrap * Add comment explaining purpose of the test * Eliminate duplicative/extraneous buffer allocations PR-URL: https://github.com/nodejs/node/pull/56748 Reviewed-By: Yagiz Nizipli Reviewed-By: Richard Lau Reviewed-By: Luigi Pinca Reviewed-By: Matteo Collina --- test/parallel/test-crypto-aes-wrap.js | 58 +++++++++++++-------------- 1 file changed, 28 insertions(+), 30 deletions(-) diff --git a/test/parallel/test-crypto-aes-wrap.js b/test/parallel/test-crypto-aes-wrap.js index 6fe35258f7d6b2..21d48d8a3fbae7 100644 --- a/test/parallel/test-crypto-aes-wrap.js +++ b/test/parallel/test-crypto-aes-wrap.js @@ -1,62 +1,60 @@ 'use strict'; const common = require('../common'); -if (!common.hasCrypto) +if (!common.hasCrypto) { common.skip('missing crypto'); +} + +// Tests that the AES wrap and unwrap functions are working correctly. const assert = require('assert'); const crypto = require('crypto'); -const test = [ +const ivShort = Buffer.from('3fd838af', 'hex'); +const ivLong = Buffer.from('3fd838af4093d749', 'hex'); +const key1 = Buffer.from('b26f309fbe57e9b3bb6ae5ef31d54450', 'hex'); +const key2 = Buffer.from('40978085d68091f7dfca0d7dfc7a5ee76d2cc7f2f345a304', 'hex'); +const key3 = Buffer.from('29c9eab5ed5ad44134a1437fe2e673b4d88a5b7c72e68454fea08721392b7323', 'hex'); + +[ { algorithm: 'aes128-wrap', - key: 'b26f309fbe57e9b3bb6ae5ef31d54450', - iv: '3fd838af4093d749', + key: key1, + iv: ivLong, text: '12345678123456781234567812345678' }, { algorithm: 'id-aes128-wrap-pad', - key: 'b26f309fbe57e9b3bb6ae5ef31d54450', - iv: '3fd838af', + key: key1, + iv: ivShort, text: '12345678123456781234567812345678123' }, { algorithm: 'aes192-wrap', - key: '40978085d68091f7dfca0d7dfc7a5ee76d2cc7f2f345a304', - iv: '3fd838af4093d749', + key: key2, + iv: ivLong, text: '12345678123456781234567812345678' }, { algorithm: 'id-aes192-wrap-pad', - key: '40978085d68091f7dfca0d7dfc7a5ee76d2cc7f2f345a304', - iv: '3fd838af', + key: key2, + iv: ivShort, text: '12345678123456781234567812345678123' }, { algorithm: 'aes256-wrap', - key: '29c9eab5ed5ad44134a1437fe2e673b4d88a5b7c72e68454fea08721392b7323', - iv: '3fd838af4093d749', + key: key3, + iv: ivLong, text: '12345678123456781234567812345678' }, { algorithm: 'id-aes256-wrap-pad', - key: '29c9eab5ed5ad44134a1437fe2e673b4d88a5b7c72e68454fea08721392b7323', - iv: '3fd838af', + key: key3, + iv: ivShort, text: '12345678123456781234567812345678123' }, -]; - -test.forEach((data) => { - const cipher = crypto.createCipheriv( - data.algorithm, - Buffer.from(data.key, 'hex'), - Buffer.from(data.iv, 'hex')); - const ciphertext = cipher.update(data.text, 'utf8'); - - const decipher = crypto.createDecipheriv( - data.algorithm, - Buffer.from(data.key, 'hex'), - Buffer.from(data.iv, 'hex')); - const msg = decipher.update(ciphertext, 'buffer', 'utf8'); - - assert.strictEqual(msg, data.text, `${data.algorithm} test case failed`); +].forEach(({ algorithm, key, iv, text }) => { + const cipher = crypto.createCipheriv(algorithm, key, iv); + const decipher = crypto.createDecipheriv(algorithm, key, iv); + const msg = decipher.update(cipher.update(text, 'utf8'), 'buffer', 'utf8'); + assert.strictEqual(msg, text, `${algorithm} test case failed`); }); From edeb157d759d8fb34d8d892ce607958fc5a86830 Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Sun, 26 Jan 2025 19:31:35 +0100 Subject: [PATCH 169/205] doc: improve accessibility of expandable lists MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/56749 Reviewed-By: James M Snell Reviewed-By: Ulises Gascón Reviewed-By: Claudio Wunder --- doc/api_assets/api.js | 6 +++++- doc/api_assets/style.css | 17 ++++++----------- doc/template.html | 6 +++--- tools/doc/html.mjs | 12 ++++++------ 4 files changed, 20 insertions(+), 21 deletions(-) diff --git a/doc/api_assets/api.js b/doc/api_assets/api.js index 394b5ba990946c..e86f110e0346bf 100644 --- a/doc/api_assets/api.js +++ b/doc/api_assets/api.js @@ -41,6 +41,7 @@ function closeAllPickers() { for (const picker of pickers) { picker.parentNode.classList.remove('expanded'); + picker.ariaExpanded = false; } window.removeEventListener('click', closeAllPickers); @@ -58,6 +59,7 @@ for (const picker of pickers) { const parentNode = picker.parentNode; + picker.ariaExpanded = parentNode.classList.contains('expanded'); picker.addEventListener('click', function(e) { e.preventDefault(); @@ -65,7 +67,7 @@ closeAllPickers as window event trigger already closed all the pickers, if it already closed there is nothing else to do here */ - if (parentNode.classList.contains('expanded')) { + if (picker.ariaExpanded === 'true') { return; } @@ -75,9 +77,11 @@ */ requestAnimationFrame(function() { + picker.ariaExpanded = true; parentNode.classList.add('expanded'); window.addEventListener('click', closeAllPickers); window.addEventListener('keydown', onKeyDown); + parentNode.querySelector('.picker a').focus(); }); }); } diff --git a/doc/api_assets/style.css b/doc/api_assets/style.css index 28a284e3b975b8..a40990a39252a4 100644 --- a/doc/api_assets/style.css +++ b/doc/api_assets/style.css @@ -182,22 +182,15 @@ li.picker-header .picker-arrow { height: .6rem; border-top: .3rem solid transparent; border-bottom: .3rem solid transparent; - border-left: .6rem solid var(--color-links); + border-left: .6rem solid currentColor; border-right: none; margin: 0 .2rem .05rem 0; } -li.picker-header a:focus .picker-arrow, -li.picker-header a:active .picker-arrow, -li.picker-header a:hover .picker-arrow { - border-left: .6rem solid var(--white); -} - -li.picker-header.expanded a:focus .picker-arrow, -li.picker-header.expanded a:active .picker-arrow, -li.picker-header.expanded a:hover .picker-arrow, +li.picker-header.expanded .picker-arrow, +:root:not(.has-js) li.picker-header:focus-within .picker-arrow, :root:not(.has-js) li.picker-header:hover .picker-arrow { - border-top: .6rem solid var(--white); + border-top: .6rem solid currentColor; border-bottom: none; border-left: .35rem solid transparent; border-right: .35rem solid transparent; @@ -205,11 +198,13 @@ li.picker-header.expanded a:hover .picker-arrow, } li.picker-header.expanded > a, +:root:not(.has-js) li.picker-header:focus-within > a, :root:not(.has-js) li.picker-header:hover > a { border-radius: 2px 2px 0 0; } li.picker-header.expanded > .picker, +:root:not(.has-js) li.picker-header:focus-within > .picker, :root:not(.has-js) li.picker-header:hover > .picker { display: block; z-index: 1; diff --git a/doc/template.html b/doc/template.html index ab8be0e747f492..51e789b7e6168c 100644 --- a/doc/template.html +++ b/doc/template.html @@ -59,13 +59,13 @@

Node.js __VERSION__ documentation

__GTOC_PICKER__ __ALTDOCS__
  • - + Options -
    -
      +
      +
      • View on single page
      • diff --git a/tools/doc/html.mjs b/tools/doc/html.mjs index 68762d89e048ce..d61d335c7b8957 100644 --- a/tools/doc/html.mjs +++ b/tools/doc/html.mjs @@ -527,11 +527,11 @@ function altDocs(filename, docCreated, versions) { return list ? `
      • - + Other versions -
          ${list}
        +
          ${list}
      • ` : ''; } @@ -557,12 +557,12 @@ function gtocPicker(id) { return `
      • - + Index -
        ${gtoc}
        +
        ${gtoc}
      • `; } @@ -574,12 +574,12 @@ function tocPicker(id, content) { return `
      • - + Table of contents -
        ${content.tocPicker}
        +
        ${content.tocPicker.replace('
      • `; } From d4236382818d62919d81b5fe56745512b2ac898f Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Sun, 26 Jan 2025 19:41:45 +0100 Subject: [PATCH 170/205] doc: add "Skip to content" button MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/56750 Reviewed-By: James M Snell Reviewed-By: Ulises Gascón Reviewed-By: Claudio Wunder --- doc/api_assets/style.css | 13 +++++++++++++ doc/template.html | 1 + 2 files changed, 14 insertions(+) diff --git a/doc/api_assets/style.css b/doc/api_assets/style.css index a40990a39252a4..35c216bb0523fc 100644 --- a/doc/api_assets/style.css +++ b/doc/api_assets/style.css @@ -122,6 +122,19 @@ a.type { font-size: .9em; } +.skip-to-content { + position: fixed; + top: -300%; +} +.skip-to-content:focus { + display: block; + top: 0; + left: 0; + background-color: var(--green1); + padding: 1rem; + z-index: 999999; +} + #content { position: relative; } diff --git a/doc/template.html b/doc/template.html index 51e789b7e6168c..34edf068df5c8d 100644 --- a/doc/template.html +++ b/doc/template.html @@ -26,6 +26,7 @@ __JS_FLAVORED_DYNAMIC_CSS__ + Skip to content