From d59680348e49e7ca76fccfcc4b9da6526182b44e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?0hm=E2=98=98=EF=B8=8F?= <109351887+0hmX@users.noreply.github.com> Date: Mon, 9 Jun 2025 14:00:30 +0530 Subject: [PATCH 01/43] doc: add path rules and validation for export targets in package.json PR-URL: https://github.com/nodejs/node/pull/58604 Reviewed-By: Jacob Smith Reviewed-By: Marco Ippolito Reviewed-By: Antoine du Hamel --- doc/api/packages.md | 53 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/doc/api/packages.md b/doc/api/packages.md index 8a62ce2d3b61c6..e4335698c98e6b 100644 --- a/doc/api/packages.md +++ b/doc/api/packages.md @@ -433,6 +433,59 @@ subpaths where possible instead of a separate map entry per package subpath export. This also mirrors the requirement of using [the full specifier path][] in relative and absolute import specifiers. +#### Path Rules and Validation for Export Targets + +When defining paths as targets in the [`"exports"`][] field, Node.js enforces +several rules to ensure security, predictability, and proper encapsulation. +Understanding these rules is crucial for authors publishing packages. + +##### Targets must be relative URLs + +All target paths in the [`"exports"`][] map (the values associated with export +keys) must be relative URL strings starting with `./`. + +```json +// package.json +{ + "name": "my-package", + "exports": { + ".": "./dist/main.js", // Correct + "./feature": "./lib/feature.js", // Correct + // "./origin-relative": "/dist/main.js", // Incorrect: Must start with ./ + // "./absolute": "file:///dev/null", // Incorrect: Must start with ./ + // "./outside": "../common/util.js" // Incorrect: Must start with ./ + } +} +``` + +Reasons for this behavior include: + +* **Security:** Prevents exporting arbitrary files from outside the + package's own directory. +* **Encapsulation:** Ensures all exported paths are resolved relative to + the package root, making the package self-contained. + +##### No path traversal or invalid segments + +Export targets must not resolve to a location outside the package's root +directory. Additionally, path segments like `.` (single dot), `..` (double dot), +or `node_modules` (and their URL-encoded equivalents) are generally disallowed +within the `target` string after the initial `./` and in any `subpath` part +substituted into a target pattern. + +```json +// package.json +{ + "name": "my-package", + "exports": { + // ".": "./dist/../../elsewhere/file.js", // Invalid: path traversal + // ".": "././dist/main.js", // Invalid: contains "." segment + // ".": "./dist/../dist/main.js", // Invalid: contains ".." segment + // "./utils/./helper.js": "./utils/helper.js" // Key has invalid segment + } +} +``` + ### Exports sugar + +The `MockPropertyContext` class is used to inspect or manipulate the behavior +of property mocks created via the [`MockTracker`][] APIs. + +### `ctx.accesses` + +* {Array} + +A getter that returns a copy of the internal array used to track accesses (get/set) to +the mocked property. Each entry in the array is an object with the following properties: + +* `type` {string} Either `'get'` or `'set'`, indicating the type of access. +* `value` {any} The value that was read (for `'get'`) or written (for `'set'`). +* `stack` {Error} An `Error` object whose stack can be used to determine the + callsite of the mocked function invocation. + +### `ctx.accessCount()` + +* Returns: {integer} The number of times that the property was accessed (read or written). + +This function returns the number of times that the property was accessed. +This function is more efficient than checking `ctx.accesses.length` because +`ctx.accesses` is a getter that creates a copy of the internal access tracking array. + +### `ctx.mockImplementation(value)` + +* `value` {any} The new value to be set as the mocked property value. + +This function is used to change the value returned by the mocked property getter. + +### `ctx.mockImplementationOnce(value[, onAccess])` + +* `value` {any} The value to be used as the mock's + implementation for the invocation number specified by `onAccess`. +* `onAccess` {integer} The invocation number that will use `value`. If + the specified invocation has already occurred then an exception is thrown. + **Default:** The number of the next invocation. + +This function is used to change the behavior of an existing mock for a single +invocation. Once invocation `onAccess` has occurred, the mock will revert to +whatever behavior it would have used had `mockImplementationOnce()` not been +called. + +The following example creates a mock function using `t.mock.property()`, calls the +mock property, changes the mock implementation to a different value for the +next invocation, and then resumes its previous behavior. + +```js +test('changes a mock behavior once', (t) => { + const obj = { foo: 1 }; + + const prop = t.mock.property(obj, 'foo', 5); + + assert.strictEqual(obj.foo, 5); + prop.mock.mockImplementationOnce(25); + assert.strictEqual(obj.foo, 25); + assert.strictEqual(obj.foo, 5); +}); +``` + +#### Caveat + +For consistency with the rest of the mocking API, this function treats both property gets and sets +as accesses. If a property set occurs at the same access index, the "once" value will be consumed +by the set operation, and the mocked property value will be changed to the "once" value. This may +lead to unexpected behavior if you intend the "once" value to only be used for a get operation. + +### `ctx.resetAccesses()` + +Resets the access history of the mocked property. + +### `ctx.restore()` + +Resets the implementation of the mock property to its original behavior. The +mock can still be used after calling this function. + ## Class: `MockTracker` + +* `object` {Object} The object whose value is being mocked. +* `propertyName` {string|symbol} The identifier of the property on `object` to mock. +* `value` {any} An optional value used as the mock value + for `object[propertyName]`. **Default:** The original property value. +* Returns: {Proxy} A proxy to the mocked object. The mocked object contains a + special `mock` property, which is an instance of [`MockPropertyContext`][], and + can be used for inspecting and changing the behavior of the mocked property. + +Creates a mock for a property value on an object. This allows you to track and control access to a specific property, +including how many times it is read (getter) or written (setter), and to restore the original value after mocking. + +```js +test('mocks a property value', (t) => { + const obj = { foo: 42 }; + const prop = t.mock.property(obj, 'foo', 100); + + assert.strictEqual(obj.foo, 100); + assert.strictEqual(prop.mock.accessCount(), 1); + assert.strictEqual(prop.mock.accesses[0].type, 'get'); + assert.strictEqual(prop.mock.accesses[0].value, 100); + + obj.foo = 200; + assert.strictEqual(prop.mock.accessCount(), 2); + assert.strictEqual(prop.mock.accesses[1].type, 'set'); + assert.strictEqual(prop.mock.accesses[1].value, 200); + + prop.mock.restore(); + assert.strictEqual(obj.foo, 42); +}); +``` + ### `mock.reset()` + +* `url` {URL | string} The file URL string or URL object to convert to a path. +* `options` {Object} + * `windows` {boolean|undefined} `true` if the `path` should be + return as a windows filepath, `false` for posix, and + `undefined` for the system default. + **Default:** `undefined`. +* Returns: {Buffer} The fully-resolved platform-specific Node.js file path + as a {Buffer}. + +Like `url.fileURLToPath(...)` except that instead of returning a string +representation of the path, a `Buffer` is returned. This conversion is +helpful when the input URL contains percent-encoded segments that are +not valid UTF-8 / Unicode sequences. + ### `url.format(URL[, options])` The `MockPropertyContext` class is used to inspect or manipulate the behavior @@ -2336,7 +2336,7 @@ test('mocks a builtin module in both module systems', async (t) => { ### `mock.property(object, propertyName[, value])` * `object` {Object} The object whose value is being mocked. diff --git a/doc/api/typescript.md b/doc/api/typescript.md index 66f95d6b878a1b..642e3f26db7cb3 100644 --- a/doc/api/typescript.md +++ b/doc/api/typescript.md @@ -2,7 +2,7 @@ * `url` {URL | string} The file URL string or URL object to convert to a path. diff --git a/doc/changelogs/CHANGELOG_V24.md b/doc/changelogs/CHANGELOG_V24.md index 71a4c975fafda6..739bd428e2d4a7 100644 --- a/doc/changelogs/CHANGELOG_V24.md +++ b/doc/changelogs/CHANGELOG_V24.md @@ -8,6 +8,7 @@ +24.3.0
24.2.0
24.1.0
24.0.2
@@ -43,6 +44,63 @@ * [io.js](CHANGELOG_IOJS.md) * [Archive](CHANGELOG_ARCHIVE.md) + + +## 2025-06-17, Version 24.3.0 (Current), @RafaelGSS + +### Notable Changes + +* \[[`841609ac1c`](https://github.com/nodejs/node/commit/841609ac1c)] - **doc**: add islandryu to collaborators (Shima Ryuhei) [#58714](https://github.com/nodejs/node/pull/58714) +* \[[`839964ece8`](https://github.com/nodejs/node/commit/839964ece8)] - **(SEMVER-MINOR)** **fs**: allow correct handling of burst in fs-events with AsyncIterator (Philipp Dunkel) [#58490](https://github.com/nodejs/node/pull/58490) +* \[[`9b28f40834`](https://github.com/nodejs/node/commit/9b28f40834)] - **(SEMVER-MINOR)** **module**: remove experimental warning from type stripping (Marco Ippolito) [#58643](https://github.com/nodejs/node/pull/58643) +* \[[`713fbad7b6`](https://github.com/nodejs/node/commit/713fbad7b6)] - **(SEMVER-MINOR)** **test\_runner**: support object property mocking (Idan Goshen) [#58438](https://github.com/nodejs/node/pull/58438) +* \[[`ef0230abaf`](https://github.com/nodejs/node/commit/ef0230abaf)] - **(SEMVER-MINOR)** **url**: add fileURLToPathBuffer API (James M Snell) [#58700](https://github.com/nodejs/node/pull/58700) + +### Commits + +* \[[`450f4815b3`](https://github.com/nodejs/node/commit/450f4815b3)] - **deps**: update amaro to 1.0.0 (Node.js GitHub Bot) [#58639](https://github.com/nodejs/node/pull/58639) +* \[[`3aa2762e96`](https://github.com/nodejs/node/commit/3aa2762e96)] - **deps**: update sqlite to 3.50.1 (Node.js GitHub Bot) [#58630](https://github.com/nodejs/node/pull/58630) +* \[[`80eac147e6`](https://github.com/nodejs/node/commit/80eac147e6)] - **deps**: update simdjson to 3.13.0 (Node.js GitHub Bot) [#58629](https://github.com/nodejs/node/pull/58629) +* \[[`dc1023878c`](https://github.com/nodejs/node/commit/dc1023878c)] - **deps**: update zlib to 1.3.1-470d3a2 (Node.js GitHub Bot) [#58628](https://github.com/nodejs/node/pull/58628) +* \[[`841609ac1c`](https://github.com/nodejs/node/commit/841609ac1c)] - **doc**: add islandryu to collaborators (Shima Ryuhei) [#58714](https://github.com/nodejs/node/pull/58714) +* \[[`1cc77c7ee6`](https://github.com/nodejs/node/commit/1cc77c7ee6)] - **doc**: punctuation fix for Node-API versioning clarification (Jiacai Liu) [#58599](https://github.com/nodejs/node/pull/58599) +* \[[`d59680348e`](https://github.com/nodejs/node/commit/d59680348e)] - **doc**: add path rules and validation for export targets in package.json (0hm☘️) [#58604](https://github.com/nodejs/node/pull/58604) +* \[[`b6760b3379`](https://github.com/nodejs/node/commit/b6760b3379)] - **esm**: syncify default path of `ModuleLoader.load` (Jacob Smith) [#57419](https://github.com/nodejs/node/pull/57419) +* \[[`839964ece8`](https://github.com/nodejs/node/commit/839964ece8)] - **(SEMVER-MINOR)** **fs**: allow correct handling of burst in fs-events with AsyncIterator (Philipp Dunkel) [#58490](https://github.com/nodejs/node/pull/58490) +* \[[`b11da1115e`](https://github.com/nodejs/node/commit/b11da1115e)] - **http2**: fix DEP0194 message (KaKa) [#58669](https://github.com/nodejs/node/pull/58669) +* \[[`b1f60d2f18`](https://github.com/nodejs/node/commit/b1f60d2f18)] - **http2**: add diagnostics channel 'http2.server.stream.close' (Darshan Sen) [#58602](https://github.com/nodejs/node/pull/58602) +* \[[`6390f70da2`](https://github.com/nodejs/node/commit/6390f70da2)] - **lib,src**: support DOMException ser-des (Chengzhong Wu) [#58649](https://github.com/nodejs/node/pull/58649) +* \[[`ff8a3691c4`](https://github.com/nodejs/node/commit/ff8a3691c4)] - **module**: fix typescript import.meta.main (Marco Ippolito) [#58661](https://github.com/nodejs/node/pull/58661) +* \[[`45f7d160ed`](https://github.com/nodejs/node/commit/45f7d160ed)] - **module**: refactor commonjs typescript loader (Marco Ippolito) [#58657](https://github.com/nodejs/node/pull/58657) +* \[[`9b28f40834`](https://github.com/nodejs/node/commit/9b28f40834)] - **(SEMVER-MINOR)** **module**: remove experimental warning from type stripping (Marco Ippolito) [#58643](https://github.com/nodejs/node/pull/58643) +* \[[`a3c7a63c73`](https://github.com/nodejs/node/commit/a3c7a63c73)] - **module**: allow cycles in require() in the CJS handling in ESM loader (Joyee Cheung) [#58598](https://github.com/nodejs/node/pull/58598) +* \[[`dfb0144490`](https://github.com/nodejs/node/commit/dfb0144490)] - **src**: enhance error messages for unknown options (Pietro Marchini) [#58677](https://github.com/nodejs/node/pull/58677) +* \[[`e9c6fa514c`](https://github.com/nodejs/node/commit/e9c6fa514c)] - **src**: replace std::array with static arrays in contextify (Mert Can Altin) [#58580](https://github.com/nodejs/node/pull/58580) +* \[[`4347ce3dba`](https://github.com/nodejs/node/commit/4347ce3dba)] - **src**: add new CopyUtimes function to reduce code duplication (Dario Piotrowicz) [#58625](https://github.com/nodejs/node/pull/58625) +* \[[`893999e0ee`](https://github.com/nodejs/node/commit/893999e0ee)] - **src**: replace V8 Fast API todo comment with note comment (Dario Piotrowicz) [#58614](https://github.com/nodejs/node/pull/58614) +* \[[`704b1fa075`](https://github.com/nodejs/node/commit/704b1fa075)] - **test**: add tests for REPL custom evals (Dario Piotrowicz) [#57850](https://github.com/nodejs/node/pull/57850) +* \[[`c39d570871`](https://github.com/nodejs/node/commit/c39d570871)] - **test**: reduce the use of private symbols in test-events-once.js (Yoshiya Hinosawa) [#58685](https://github.com/nodejs/node/pull/58685) +* \[[`b7e488c77f`](https://github.com/nodejs/node/commit/b7e488c77f)] - **test**: refactor repl tab complete tests (Dario Piotrowicz) [#58636](https://github.com/nodejs/node/pull/58636) +* \[[`ec808b3e06`](https://github.com/nodejs/node/commit/ec808b3e06)] - **test**: use `common.skipIfInspectorDisabled()` to skip tests (Dario Piotrowicz) [#58675](https://github.com/nodejs/node/pull/58675) +* \[[`94e53d4f6c`](https://github.com/nodejs/node/commit/94e53d4f6c)] - **test**: update WPT for urlpattern to 3ffda23e5a (Node.js GitHub Bot) [#58537](https://github.com/nodejs/node/pull/58537) +* \[[`fa089d610f`](https://github.com/nodejs/node/commit/fa089d610f)] - **test**: update WPT for dom/abort to dc928169ee (Node.js GitHub Bot) [#58644](https://github.com/nodejs/node/pull/58644) +* \[[`aa657f0fc4`](https://github.com/nodejs/node/commit/aa657f0fc4)] - **test**: split indirect eval import tests (Chengzhong Wu) [#58637](https://github.com/nodejs/node/pull/58637) +* \[[`76e3c8aaf2`](https://github.com/nodejs/node/commit/76e3c8aaf2)] - **test**: update WPT for es-exceptions to 2f96fa1996 (Node.js GitHub Bot) [#58640](https://github.com/nodejs/node/pull/58640) +* \[[`7e34aa4eaa`](https://github.com/nodejs/node/commit/7e34aa4eaa)] - **test**: skip tests failing when run under root (Livia Medeiros) [#58610](https://github.com/nodejs/node/pull/58610) +* \[[`85f062c22e`](https://github.com/nodejs/node/commit/85f062c22e)] - **test**: deflake async-hooks/test-improper-order on AIX (Baki Gul) [#58567](https://github.com/nodejs/node/pull/58567) +* \[[`181014a8fe`](https://github.com/nodejs/node/commit/181014a8fe)] - **test**: cleanup status files (Filip Skokan) [#58633](https://github.com/nodejs/node/pull/58633) +* \[[`a4d756068d`](https://github.com/nodejs/node/commit/a4d756068d)] - **test**: close FileHandle objects in tests explicitly (James M Snell) [#58615](https://github.com/nodejs/node/pull/58615) +* \[[`713fbad7b6`](https://github.com/nodejs/node/commit/713fbad7b6)] - **(SEMVER-MINOR)** **test\_runner**: support object property mocking (Idan Goshen) [#58438](https://github.com/nodejs/node/pull/58438) +* \[[`dc2f23e986`](https://github.com/nodejs/node/commit/dc2f23e986)] - **tools**: bump `brace-expansion` in `/tools/clang-format` (dependabot\[bot]) [#58699](https://github.com/nodejs/node/pull/58699) +* \[[`e6a1787140`](https://github.com/nodejs/node/commit/e6a1787140)] - **tools**: bump brace-expansion from 1.1.11 to 1.1.12 in /tools/eslint (dependabot\[bot]) [#58698](https://github.com/nodejs/node/pull/58698) +* \[[`b22e970774`](https://github.com/nodejs/node/commit/b22e970774)] - **tools**: switch to `@stylistic/eslint-plugin` (Michaël Zasso) [#58623](https://github.com/nodejs/node/pull/58623) +* \[[`268c8c1799`](https://github.com/nodejs/node/commit/268c8c1799)] - **tools**: remove config.status under `make distclean` (René) [#58603](https://github.com/nodejs/node/pull/58603) +* \[[`c1f9791844`](https://github.com/nodejs/node/commit/c1f9791844)] - **tools**: edit commit-queue workflow file (Antoine du Hamel) [#58667](https://github.com/nodejs/node/pull/58667) +* \[[`afbaf9277b`](https://github.com/nodejs/node/commit/afbaf9277b)] - **tools**: improve release proposal linter (Antoine du Hamel) [#58647](https://github.com/nodejs/node/pull/58647) +* \[[`17df800b90`](https://github.com/nodejs/node/commit/17df800b90)] - **typings**: add Atomics primordials (Renegade334) [#58577](https://github.com/nodejs/node/pull/58577) +* \[[`ffff8ce3a4`](https://github.com/nodejs/node/commit/ffff8ce3a4)] - **typings**: add ZSTD\_COMPRESS, ZSTD\_DECOMPRESS to internalBinding (Meghan Denny) [#58655](https://github.com/nodejs/node/pull/58655) +* \[[`ef0230abaf`](https://github.com/nodejs/node/commit/ef0230abaf)] - **(SEMVER-MINOR)** **url**: add fileURLToPathBuffer API (James M Snell) [#58700](https://github.com/nodejs/node/pull/58700) + ## 2025-06-09, Version 24.2.0 (Current), @aduh95 diff --git a/src/node_version.h b/src/node_version.h index 1f8a0f455cbf62..22638e83ff3416 100644 --- a/src/node_version.h +++ b/src/node_version.h @@ -23,13 +23,13 @@ #define SRC_NODE_VERSION_H_ #define NODE_MAJOR_VERSION 24 -#define NODE_MINOR_VERSION 2 -#define NODE_PATCH_VERSION 1 +#define NODE_MINOR_VERSION 3 +#define NODE_PATCH_VERSION 0 #define NODE_VERSION_IS_LTS 0 #define NODE_VERSION_LTS_CODENAME "" -#define NODE_VERSION_IS_RELEASE 0 +#define NODE_VERSION_IS_RELEASE 1 #ifndef NODE_STRINGIFY #define NODE_STRINGIFY(n) NODE_STRINGIFY_HELPER(n)