Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: add common.mustNotMutateObjectDeep() #43196

Merged
merged 2 commits into from
Jul 13, 2022

Conversation

LiviaMedeiros
Copy link
Contributor

@LiviaMedeiros LiviaMedeiros commented May 24, 2022

Problem

tl;dr: usually we don't want core methods to have side effects of mutating input values.

Let's imagine function having the following flow inside:

function makeRequest(ipaddr, options) {
  if (typeof options.port === 'number')
    return _mkRq(ipaddr, options);
  switch (options.protocol) {
    case 'ftp': options.port = 21; break;
    case 'http': options.port = 80; break;
    default: // unknown, whatever
  }
  return _mkRq(ipaddr, options);
}

Let's try to use it:

const opts = { headers };
makeRequest(addr, opts); // unknown://addr:unknown --- ok
opts.protocol = 'http';
makeRequest(addr, opts); // http://addr:80 --- got side effects
opts.protocol = 'ftp';
makeRequest(addr, opts); // ftp://addr:80 --- suffered from side effects

To run into such things in tests, we need to perform specific calls in specific order, and it still doesn't guarantee catching. Simple tests like makeRequest(addr, Object.freeze({})) won't help if mutation is conditional.

Solution

This PR adds common.mustNotMutate() which improves our ability to test functions for undesired side effects.

Pass an object into it and use returned value in tests whenever it must remain unchanged:

...
opts.protocol = 'http';
makeRequest(addr, common.mustNotMutate(opts)); // http://addr:80 --- testing for side effects
AssertionError [ERR_ASSERTION]: Expected no side effects, got 80 assigned to port

Or make an immutable "view" on any object:

const mFoo = { bar: 'baz' };
const iFoo = mustNotMutate(mFoo);
mFoo.bar = 'qux'; // affects BOTH mFoo and iFoo
iFoo.bar = 'gwak'; // AssertionError

Or keep mutable "view" and make an object immutable:

const realProcessEnv = process.env;
process.env = mustNotMutate(process.env);
realProcessEnv.LANG = 'en_GB'; // affects BOTH realProcessEnv and process.env
process.env.LANG = 'en_GB'; // AssertionError

Example

[WIP] Using this function in some fs tests: LiviaMedeiros@48a8bd1

@nodejs-github-bot nodejs-github-bot added needs-ci PRs that need a full CI run. test Issues and PRs related to the tests. labels May 24, 2022
@nodejs-github-bot

This comment was marked as outdated.

@tniessen
Copy link
Member

Where would we use this? There must be tens of thousands of function calls that pass options objects or other data structures that should not be mutated.

@LiviaMedeiros
Copy link
Contributor Author

Utopically, everywhere - just like common.mustSucceed() wraps most callbacks. :)

Practically, in places where there is a reasonable chance that accidental side effects might happen. Mainly in new tests or refactoring old ones. A lot of options objects in fs, http* and crypto require additional testing for that.

Mandatory, whenever a fix for such issues is introduced. Example:

node/lib/https.js

Lines 114 to 131 in 304e06a

function createConnection(port, host, options) {
if (port !== null && typeof port === 'object') {
options = port;
} else if (host !== null && typeof host === 'object') {
options = { ...host };
} else if (options === null || typeof options !== 'object') {
options = {};
} else {
options = { ...options };
}
if (typeof port === 'number') {
options.port = port;
}
if (typeof host === 'string') {
options.host = host;
}

// options = { ...port };
// Regression test for https://github.com/nodejs/node/issues/31119
agent.createConnection(mustNotMutate({ port: 443 }), 'nodejs.org');

@F3n67u
Copy link
Member

F3n67u commented May 24, 2022

Where would we use this? There must be tens of thousands of function calls that pass options objects or other data structures that should not be mutated.

hi! @tniessen I am new to node source code. Could you help me to understand why there is so many side effect(mutation) to function parameter? I don't think it's a good practice to mutate function prameter.

@tniessen
Copy link
Member

Utopically, everywhere - just like common.mustSucceed() wraps most callbacks. :)

Yeah, I wrote mustSucceed and IIRC not everyone liked the idea. Still, in that case, most of the modified sources only simplified mustCall(ifError()) to mustSucceed() and didn't require additions beyond that. Luckily, for the most part, that's somewhat legacy now, since async addresses the problem at the language level for new Promise APIs. In this case, the closest thing to a language-level solution might be proposal-record-tuple, unfortunately.

Don't get me wrong, I like having this guarantee, and ideally, we'd have some mechanism to detect these modifications. I am just not sure if I like the idea of bloating our test files with thousands of such checks to guard against this specific problem. I only remember very few issues that reported such side effects. And, because there is no good coverage metric for this, we'd probably have to wrap every argument in such a call, even arguments that aren't object literals, and then we'd still only be guarding against this specific side effect. (For example, we also don't check if functions modify any existing prototypes or built-in objects.)

(It might be less work to rewrite core in TypeScript and declare most inputs as deep-readonly objects.)

Mandatory, whenever a fix for such issues is introduced. Example:

For regression tests, I agree, this is a good idea, but in those cases, we can usually write a specific test for the specific mutation in one or two lines of code.

hi! @tniessen I am new to node source code. Could you help me to understand why there is so many side effect(mutation) to function parameter?

@F3n67u It's the opposite. We usually don't mutate function parameters, but we don't test that explicitly because it would require adding tens of thousands of checks.

@LiviaMedeiros
Copy link
Contributor Author

In this case, the closest thing to a language-level solution might be proposal-record-tuple, unfortunately.

Yep, looking forward to this as well as proposal-type-annotations, and hoping for eventual deprecation of most callback-oriented APIs in Node.js; but at this moment we still need to deal with callbacks, dynamic typings, etc.

I am just not sure if I like the idea of bloating our test files with thousands of such checks to guard against this specific problem.

Sorry if I worded it wrong. I'm definitely not proposing rewriting even hundreds of test files with this method, even ideally. Only utopically, if we could magically have zero performance, readability and maintainability cost for that.

My current plan is to cover all most-likely-to-become-affected methods in fs with this approach, which is about ten files, ideally w/o creating new ones. After that, to check most-suspiciously-looking methods in other subsystems, which probably also is a few tens of files. This task alone would be significantly harder and uglier without a common helper method.

Aside from that, if people will find ability to use bulltin wrapper instead of writing specific tests or shaping specific test flows to make proper immutability testing possible, that's great. If anyone will integrate it in existing tests where this check is important, that's cool as well. Even if not, well, AFAICT it doesn't add any overhead to the node binary. :)

Regarding other types of side effects - maybe guarding against them makes sense, and maybe some of them are doable even as "automatic" job of common module. However, unless mustNotMutate() should play major role in it and requires some specific redesign, it's out of scope for this PR.
As for now, we can do some generic stuff using it, such as:

Math = mustNotMutate(Math);
Math.random = ()=>Number.EPSILON; // AssertionError

const mutableRealProcess = process;
process = mustNotMutate(process);
process.env.HOME = '/proc'; // AssertionError
mutableRealProcess.env.HOME = '/sys';
console.log(process.env.HOME); // /sys

@RaisinTen
Copy link
Contributor

I think test/common is for utilities that are repeated across multiple tests. Are there occurrences of this testing pattern in places other than what we have in

assert.deepStrictEqual(options, {
port: 3000, rejectUnauthorized: false
});
? If so, I agree it would make sense to place this utility in here and use this in all of those places.

@LiviaMedeiros
Copy link
Contributor Author

I think test/common is for utilities that are repeated across multiple tests. Are there occurrences of this testing pattern in places other than what we have in [...]? If so, I agree it would make sense to place this utility in here and use this in all of those places.

Tens of thousands of potential places. Covered (hopefully near-exhaustive) fs via 3da5607 as an example of wrapper pattern usage.

As for already-existing examples, I know about

  1. fs: don't alter user provided options object #7831 (whole test-fs-options-immutable.js)
  2. https: make opts optional & immutable when create #13599:
    // Test for immutable `opts`
    {
    const opts = { foo: 'bar', ALPNProtocols: [ 'http/1.1' ] };
    const server = https.createServer(opts);
    tls.convertALPNProtocols([ 'http/1.1' ], dftProtocol);
    assert.deepStrictEqual(opts, { foo: 'bar', ALPNProtocols: [ 'http/1.1' ] });
    assert.strictEqual(server.ALPNProtocols.compare(dftProtocol.ALPNProtocols),
    0);
    }

(1) one is good, but basically uses the same idea (making object immutable and then passing it everywhere) and doesn't cover possible conditional failures.
(2) is good as well, but I think const server = https.createServer(mustNotMutate({ foo: 'bar', ALPNProtocols: [ 'http/1.1' ] })); would allow to avoid surrounding boilerplate code, and that boilerplate code like this one is the main reason why immutability check is not widespread enough.

@nodejs-github-bot
Copy link
Collaborator

@RaisinTen
Copy link
Contributor

Okay, so the known list of existing tests that uses this pattern is:

I would suggest that we should limit the scope of this PR to adding common.mustNotMutate() + docs + changing only these ^ tests + the test/parallel/test-common-must-not-mutate.mjs test that you've already added.

The rest of the modifications in the current state of this PR starts using common.mustNotMutate() in places where input mutation wasn't actually tested before. I think that should be done in its own PR separate from this change.

@nodejs-github-bot
Copy link
Collaborator

@LiviaMedeiros
Copy link
Contributor Author

Agreed, done.

test/common/README.md Outdated Show resolved Hide resolved
test/common/README.md Outdated Show resolved Hide resolved
Copy link
Contributor

@RaisinTen RaisinTen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@RaisinTen
Copy link
Contributor

@nodejs/testing wdyt?

@ljharb
Copy link
Member

ljharb commented May 31, 2022

Proxies aren’t transparent for builtins without a full membrane; i would expect this to cause all sorts of weird problems when used with any builtin object.

@LiviaMedeiros
Copy link
Contributor Author

Proxies aren’t transparent for builtins without a full membrane; i would expect this to cause all sorts of weird problems when used with any builtin object.

Yep, that's fair. I didn't meet (yet?) any situation in tests where this function was applicable to an object with unproxyable internal slots, but it's definitely worth a caveat for now, and a workaround if usecases will surface.

Is there a list of such builtins to put a reference?

@ljharb
Copy link
Member

ljharb commented May 31, 2022

Everything in JavaScript - arrays, promises, dates, regexes, maps, sets, errors, etc.

@ljharb
Copy link
Member

ljharb commented May 31, 2022

@LiviaMedeiros to add more context, there's a reason no test framework in JS that i'm aware of has this kind of helper - Proxies, absent a full membrane, simply aren't generic stand-ins for JS objects. In particular, Maps and Sets can't be generically made immutable (you can hardcode knowledge of all of the builtin functions, but Map.prototype.add.call would throw because a Proxy for a Map would lack the internal slots of a Map). Objects can be, with Object.freeze, but that's itself a mutation, and one that can't be cleaned up/reversed later. This also applies to virtually all of node core, since node core uses the primordials pattern, and thus doesn't typically access members of objects.

This also applies to any userland object that uses identity in a closed-over collection, or private fields, since the Proxy for the instance wouldn't have the same identity as the instance itself.

I think this kind of helper is simply inappropriate to build into core, or into any testing framework - the way to ensure no mutations is to snapshot in some way the object before and after, and compare the snapshots.

@LiviaMedeiros
Copy link
Contributor Author

This function is intended to be used only within Node.js tests, i.e. it won't be a part of public API or a part of underlying core. It is not intended to be an example for testing frameworks; if there is a high chance that the code would be used in more generic testing, we can add more warnings in docs or even code comments later. I'm open for suggestions on how it should be documented to avoid any confusion or pitfalls.
If there will be high chance of misusing in Node.js tests, we can add workarounds when this function gets instanceof Map || ....

Right now I don't see any considerable amount of places where problematic builtins or private fields are expected to be used, but I see a lot of places where we have predefined Objects that need this testing and from my understanding are completely safe for being wrapped into Proxy.

On top of that, I don't see a huge problem in methods throwing on Proxy in this context. Yes, things like new Proxy(new Map,{}).set('foo', 'bar') or new Proxy(new Set,{}).add('baz') will throw TypeError. We do want them to throw, because we don't want them to be called. In fact, we do want non-AssertionError and right now we do want throwing new Proxy(new Map,{}).has('foo') as well, because it would help preventing situation where someone expects this to work. :)
For typical usecase when we pass completely arbitrary garbage to test for ERR_INVALID_ARG_TYPE, it seems to fit perfectly as well.

Regarding alternative way of snapshoting and comparing, there are at least two major issues:

  1. It is verbose, it is inconvenient (depending on what and how we test), it bloats the code. Adding this function to most of applicable tests in most of subsystems is achievable. Adding same amount of testing with "traditional" way - I doubt. Asking people to wrap some objects into common function in new tests sounds okay, asking to add seemingly-unrelated boilerplate code or separate tests for that - not really.
  2. This approach is not failproof. For example, what if a method makes internal copy, mutates nested object and in the end replaces everything back? Wouldn't it remain unnoticed until someone's asynchronous code goes crazy?

@ljharb
Copy link
Member

ljharb commented Jun 1, 2022

I agree that a snapshotting approach isn’t viable for the reasons you indicate - it’s that i think this isn’t a solvable problem in a practical sense at all.

objects. Otherwise, it returns `target` directly.

Caveat: built-in objects that make use of their internal slots (for example,
`Map`s and `Set`s) might not work with this function.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer the documentation to include a guideline, maybe something along the lines Use of this function is encouraged only for relevant regression tests.

test/common/README.md Outdated Show resolved Hide resolved
@LiviaMedeiros LiviaMedeiros added author ready PRs that have at least one approval, no pending requests for changes, and a CI started. request-ci Add this label to start a Jenkins CI on a PR. commit-queue-rebase Add this label to allow the Commit Queue to land a PR in several commits. labels Jul 9, 2022
Copy link
Contributor

@aduh95 aduh95 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nits:

],
};

// Make a copy to make sure original doesn't get altered by the function itself
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Make a copy to make sure original doesn't get altered by the function itself
// Make a copy to make sure original doesn't get altered by the function itself.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a stlyguide-ish reference for that? All the comments are grouped with corresponding code lines by having empty lines, so I'm not sure if punctuation helps.

test/parallel/test-common-can-not-mutate-object-deep.mjs Outdated Show resolved Hide resolved
test/parallel/test-common-can-not-mutate-object-deep.mjs Outdated Show resolved Hide resolved
test/parallel/test-common-can-not-mutate-object-deep.mjs Outdated Show resolved Hide resolved
test/parallel/test-common-can-not-mutate-object-deep.mjs Outdated Show resolved Hide resolved
test/parallel/test-common-can-not-mutate-object-deep.mjs Outdated Show resolved Hide resolved
test/parallel/test-common-can-not-mutate-object-deep.mjs Outdated Show resolved Hide resolved
test/parallel/test-common-can-not-mutate-object-deep.mjs Outdated Show resolved Hide resolved
test/parallel/test-common-can-not-mutate-object-deep.mjs Outdated Show resolved Hide resolved
@nodejs-github-bot

This comment was marked as outdated.

@LiviaMedeiros LiviaMedeiros changed the title test: add common.canNotMutateObjectDeep() test: add common.mustNotMutateObjectDeep() Jul 12, 2022
@nodejs-github-bot
Copy link
Collaborator

@LiviaMedeiros LiviaMedeiros added the commit-queue Add this label to land a pull request using GitHub Actions. label Jul 13, 2022
@nodejs-github-bot nodejs-github-bot added commit-queue-failed An error occurred while landing this pull request using GitHub Actions. and removed commit-queue Add this label to land a pull request using GitHub Actions. labels Jul 13, 2022
@nodejs-github-bot
Copy link
Collaborator

Commit Queue failed
- Loading data for nodejs/node/pull/43196
✔  Done loading data for nodejs/node/pull/43196
----------------------------------- PR info ------------------------------------
Title      test: add `common.mustNotMutateObjectDeep()` (#43196)
   ⚠  Could not retrieve the email or name of the PR author's from user's GitHub profile!
Branch     LiviaMedeiros:ft-must-not-mutate -> nodejs:main
Labels     test, author ready, needs-ci, commit-queue-rebase
Commits    2
 - test: add `common.mustNotMutateObjectDeep()`
 - test: use `common.mustNotMutateObjectDeep()` in immutability tests
Committers 1
 - LiviaMedeiros 
PR-URL: https://github.com/nodejs/node/pull/43196
Reviewed-By: Darshan Sen 
Reviewed-By: Antoine du Hamel 
------------------------------ Generated metadata ------------------------------
PR-URL: https://github.com/nodejs/node/pull/43196
Reviewed-By: Darshan Sen 
Reviewed-By: Antoine du Hamel 
--------------------------------------------------------------------------------
   ⚠  Commits were pushed since the last review:
   ⚠  - test: add `common.mustNotMutateObjectDeep()`
   ⚠  - test: use `common.mustNotMutateObjectDeep()` in immutability tests
   ℹ  This PR was created on Tue, 24 May 2022 12:23:10 GMT
   ✔  Approvals: 2
   ✔  - Darshan Sen (@RaisinTen) (TSC): https://github.com/nodejs/node/pull/43196#pullrequestreview-990592889
   ✔  - Antoine du Hamel (@aduh95) (TSC): https://github.com/nodejs/node/pull/43196#pullrequestreview-1036243936
   ✔  Last GitHub CI successful
   ℹ  Last Full PR CI on 2022-07-12T21:56:39Z: https://ci.nodejs.org/job/node-test-pull-request/45374/
- Querying data for job/node-test-pull-request/45374/
   ✔  Last Jenkins CI successful
--------------------------------------------------------------------------------
   ✔  Aborted `git node land` session in /home/runner/work/node/node/.ncu
https://github.com/nodejs/node/actions/runs/2663402216

@LiviaMedeiros LiviaMedeiros self-assigned this Jul 13, 2022
This function returns a Proxy object that throws on attempt to mutate it
Functions and primitives are returned directly

PR-URL: nodejs#43196
Reviewed-By: Darshan Sen <[email protected]>
Reviewed-By: Antoine du Hamel <[email protected]>
@LiviaMedeiros LiviaMedeiros merged commit 0c3b00e into nodejs:main Jul 13, 2022
@LiviaMedeiros
Copy link
Contributor Author

Landed in 99b109f...0c3b00e

danielleadams pushed a commit that referenced this pull request Jul 26, 2022
This function returns a Proxy object that throws on attempt to mutate it
Functions and primitives are returned directly

PR-URL: #43196
Reviewed-By: Darshan Sen <[email protected]>
Reviewed-By: Antoine du Hamel <[email protected]>
danielleadams pushed a commit that referenced this pull request Jul 26, 2022
@danielleadams danielleadams mentioned this pull request Jul 26, 2022
targos pushed a commit that referenced this pull request Jul 31, 2022
This function returns a Proxy object that throws on attempt to mutate it
Functions and primitives are returned directly

PR-URL: #43196
Reviewed-By: Darshan Sen <[email protected]>
Reviewed-By: Antoine du Hamel <[email protected]>
targos pushed a commit that referenced this pull request Jul 31, 2022
viceice-bot added a commit to renovate-reproductions/docker-node-versioning-issue that referenced this pull request Aug 10, 2022
##### [\`v18.7.0\`](https://github.com/nodejs/node/releases/tag/v18.7.0)

##### Notable changes

-   **doc**:
    -   add F3n67u to collaborators (Feng Yu) [#43953](nodejs/node#43953)
    -   deprecate coercion to integer in process.exit (Daeyeon Jeong) [#43738](nodejs/node#43738)
    -   **(SEMVER-MINOR)** deprecate diagnostics_channel object subscribe method (Stephen Belanger) [#42714](nodejs/node#42714)
-   **events**:
    -   **(SEMVER-MINOR)** expose CustomEvent on global with CLI flag (Daeyeon Jeong) [#43885](nodejs/node#43885)
    -   **(SEMVER-MINOR)** add `CustomEvent` (Daeyeon Jeong) [#43514](nodejs/node#43514)
-   **http**:
    -   **(SEMVER-MINOR)** add drop request event for http server (theanarkh) [#43806](nodejs/node#43806)
-   **lib**:
    -   **(SEMVER-MINOR)** improved diagnostics_channel subscribe/unsubscribe (Stephen Belanger) [#42714](nodejs/node#42714)
-   **util**:
    -   **(SEMVER-MINOR)** add tokens to parseArgs (John Gee) [#43459](nodejs/node#43459)

##### Commits

-   \[[`0aa255ab72`](nodejs/node@0aa255ab72)] - **bootstrap**: handle snapshot errors gracefully (Joyee Cheung) [#43531](nodejs/node#43531)
-   \[[`0783ddf57e`](nodejs/node@0783ddf57e)] - **buffer**: do not leak memory if buffer is too big (Keyhan Vakil) [#43938](nodejs/node#43938)
-   \[[`12657accdd`](nodejs/node@12657accdd)] - **build**: add .gitattributes for npm and other shims (Hrishikesh Kadam) [#43879](nodejs/node#43879)
-   \[[`c2db4f4581`](nodejs/node@c2db4f4581)] - **build**: make GitPod less noisy (Rich Trott) [#43829](nodejs/node#43829)
-   \[[`364deeadcd`](nodejs/node@364deeadcd)] - **build**: add GitHub token permissions for workflows (Varun Sharma) [#43743](nodejs/node#43743)
-   \[[`8b83b4d5be`](nodejs/node@8b83b4d5be)] - **child_process**: do not need to count length when maxBuffer is Infinity (theanarkh) [#43822](nodejs/node#43822)
-   \[[`c1893b7a7c`](nodejs/node@c1893b7a7c)] - **child_process**: avoid repeated calls to `normalizeSpawnArguments` (木杉) [#43345](nodejs/node#43345)
-   \[[`7b276b89b9`](nodejs/node@7b276b89b9)] - **cluster**: send connection to other server when worker drop it (theanarkh) [#43747](nodejs/node#43747)
-   \[[`e8c66f92a5`](nodejs/node@e8c66f92a5)] - **crypto**: remove unneeded guard (Rich Trott) [#43856](nodejs/node#43856)
-   \[[`c95132e9ea`](nodejs/node@c95132e9ea)] - **deps**: cherry-pick [libuv/libuv@`3a7b955`](libuv/libuv@3a7b955) (Ben Noordhuis) [#43950](nodejs/node#43950)
-   \[[`cc8d5426d2`](nodejs/node@cc8d5426d2)] - **deps**: cherry-pick [libuv/libuv@`abb109f`](libuv/libuv@abb109f) (Ben Noordhuis) [#43950](nodejs/node#43950)
-   \[[`7762e463d6`](nodejs/node@7762e463d6)] - **deps**: update corepack to 0.12.1 (Node.js GitHub Bot) [#43965](nodejs/node#43965)
-   \[[`1256c4dad5`](nodejs/node@1256c4dad5)] - **deps**: update hast-util-raw (Moshe Atlow) [#43927](nodejs/node#43927)
-   \[[`aac97c2d2a`](nodejs/node@aac97c2d2a)] - **deps**: update undici to 5.8.0 (Node.js GitHub Bot) [#43886](nodejs/node#43886)
-   \[[`cdff61917d`](nodejs/node@cdff61917d)] - **deps**: clean archs files for OpenSSL (RafaelGSS) [#43735](nodejs/node#43735)
-   \[[`fc936a84e4`](nodejs/node@fc936a84e4)] - **deps**: remove not used architectures (RafaelGSS) [#43735](nodejs/node#43735)
-   \[[`361a643d8b`](nodejs/node@361a643d8b)] - **deps**: V8: backport [`f3cad8c`](nodejs/node@f3cad8cec656) (Joyee Cheung) [#43531](nodejs/node#43531)
-   \[[`2e1732ebd0`](nodejs/node@2e1732ebd0)] - **deps**: V8: backport [`22698d2`](nodejs/node@22698d267667) (Chengzhong Wu) [#43751](nodejs/node#43751)
-   \[[`979f469d3a`](nodejs/node@979f469d3a)] - **deps**: upgrade npm to 8.15.0 (npm team) [#43917](nodejs/node#43917)
-   \[[`4096d81988`](nodejs/node@4096d81988)] - **deps**: upgrade npm to 8.14.0 (npm team) [#43826](nodejs/node#43826)
-   \[[`2ec8092e2c`](nodejs/node@2ec8092e2c)] - **deps,src**: use SIMD for normal base64 encoding (Brian White) [#39775](nodejs/node#39775)
-   \[[`67b4edde37`](nodejs/node@67b4edde37)] - **dns**: fix getServers return undefined (jiahao.si) [#43922](nodejs/node#43922)
-   \[[`7c75539a88`](nodejs/node@7c75539a88)] - **dns**: fix cares memory leak (theanarkh) [#43912](nodejs/node#43912)
-   \[[`1f80b88da5`](nodejs/node@1f80b88da5)] - **doc**: update email and mailmap for BethGriggs (Beth Griggs) [#43985](nodejs/node#43985)
-   \[[`8a2a6e16eb`](nodejs/node@8a2a6e16eb)] - **doc**: add 15.x - 18.x to Other Versions section (shhh7612) [#43940](nodejs/node#43940)
-   \[[`51cb0d42ca`](nodejs/node@51cb0d42ca)] - **doc**: inspector.close undefined in worker threads (Keyhan Vakil) [#43867](nodejs/node#43867)
-   \[[`c789c0f5f7`](nodejs/node@c789c0f5f7)] - **doc**: improve documentation for safe `Promise` statics alternatives (Antoine du Hamel) [#43759](nodejs/node#43759)
-   \[[`cb9b0e0011`](nodejs/node@cb9b0e0011)] - **doc**: recommend git-node-v8 (Keyhan Vakil) [#43934](nodejs/node#43934)
-   \[[`d7e9bd1830`](nodejs/node@d7e9bd1830)] - **doc**: clarify subprocess.stdout/in/err property (Kohei Ueno) [#43910](nodejs/node#43910)
-   \[[`808793ebb5`](nodejs/node@808793ebb5)] - **doc**: fix typo in `src/crypto/README.md` (Jianru Lin) [#43968](nodejs/node#43968)
-   \[[`bbc455c4f9`](nodejs/node@bbc455c4f9)] - **doc**: remind backporter about v8\_embedder_string (Keyhan Vakil) [#43924](nodejs/node#43924)
-   \[[`a86b66c8b4`](nodejs/node@a86b66c8b4)] - **doc**: fix typo in http.md (Airing) [#43933](nodejs/node#43933)
-   \[[`a96af37233`](nodejs/node@a96af37233)] - **doc**: add F3n67u to collaborators (Feng Yu) [#43953](nodejs/node#43953)
-   \[[`aa7d4e59f7`](nodejs/node@aa7d4e59f7)] - **doc**: improve test runner timeout docs (Tobias Nießen) [#43836](nodejs/node#43836)
-   \[[`80c2fa8212`](nodejs/node@80c2fa8212)] - **doc**: mention Win 32-bit openssl build issue (RafaelGSS) [#43853](nodejs/node#43853)
-   \[[`8b8c55df7e`](nodejs/node@8b8c55df7e)] - **doc**: add security release specifics to releases.md (Beth Griggs) [#43835](nodejs/node#43835)
-   \[[`42693aaf9f`](nodejs/node@42693aaf9f)] - **doc**: add history info for `global.performance` (Antoine du Hamel) [#43841](nodejs/node#43841)
-   \[[`140d6af572`](nodejs/node@140d6af572)] - **doc**: add platform-windows-arm to who to CC (Michael Dawson) [#43808](nodejs/node#43808)
-   \[[`976093efe3`](nodejs/node@976093efe3)] - **doc**: document ES2022's Error "cause" property (James Ide) [#43830](nodejs/node#43830)
-   \[[`ec7e45e4a2`](nodejs/node@ec7e45e4a2)] - **doc**: include make clean to openssl arch (RafaelGSS) [#43735](nodejs/node#43735)
-   \[[`d64dfd53c9`](nodejs/node@d64dfd53c9)] - **doc**: add link to diagnostic tools (Rafael Gonzaga) [#43736](nodejs/node#43736)
-   \[[`2910136920`](nodejs/node@2910136920)] - **doc**: update links to MDN page about dynamic imports (Jannis R) [#43847](nodejs/node#43847)
-   \[[`d88a9fae79`](nodejs/node@d88a9fae79)] - **doc**: deprecate coercion to integer in process.exit (Daeyeon Jeong) [#43738](nodejs/node#43738)
-   \[[`fc843e103d`](nodejs/node@fc843e103d)] - **doc**: add MoLow to triagers (Moshe Atlow) [#43799](nodejs/node#43799)
-   \[[`8c8c97da61`](nodejs/node@8c8c97da61)] - **(SEMVER-MINOR)** **doc**: deprecate diagnostics_channel object subscribe method (Stephen Belanger) [#42714](nodejs/node#42714)
-   \[[`9b53a694b5`](nodejs/node@9b53a694b5)] - **doc**: revert anachronistic 'node:' module require()s in API history notes (DeeDeeG) [#43768](nodejs/node#43768)
-   \[[`2815bd3002`](nodejs/node@2815bd3002)] - **doc**: clarify release process for new releasers (Rafael Gonzaga) [#43739](nodejs/node#43739)
-   \[[`50b3750e67`](nodejs/node@50b3750e67)] - **doc**: fix typo in ngtcp2 readme (Dan Castillo) [#43767](nodejs/node#43767)
-   \[[`6bcd40dd85`](nodejs/node@6bcd40dd85)] - **domain**: fix vm promise tracking while keeping isolation (Stephen Belanger) [#43556](nodejs/node#43556)
-   \[[`e89e0b470b`](nodejs/node@e89e0b470b)] - **esm**: remove superfluous argument (Rich Trott) [#43884](nodejs/node#43884)
-   \[[`0d2921f396`](nodejs/node@0d2921f396)] - **esm**: fix erroneous re-initialization of ESMLoader (Jacob Smith) [#43763](nodejs/node#43763)
-   \[[`9b5b8d78c3`](nodejs/node@9b5b8d78c3)] - **esm**: throw on any non-2xx response (LiviaMedeiros) [#43742](nodejs/node#43742)
-   \[[`dfc4832ef1`](nodejs/node@dfc4832ef1)] - **(SEMVER-MINOR)** **events**: expose CustomEvent on global with CLI flag (Daeyeon Jeong) [#43885](nodejs/node#43885)
-   \[[`e4473952ae`](nodejs/node@e4473952ae)] - **(SEMVER-MINOR)** **events**: add `CustomEvent` (Daeyeon Jeong) [#43514](nodejs/node#43514)
-   \[[`100f6deb09`](nodejs/node@100f6deb09)] - **fs**: use signed types for stat data (LiviaMedeiros) [#43714](nodejs/node#43714)
-   \[[`25ec71db63`](nodejs/node@25ec71db63)] - **http**: fix http server connection list when close (theanarkh) [#43949](nodejs/node#43949)
-   \[[`ca658c8afe`](nodejs/node@ca658c8afe)] - **(SEMVER-MINOR)** **http**: add drop request event for http server (theanarkh) [#43806](nodejs/node#43806)
-   \[[`9c699bd8a8`](nodejs/node@9c699bd8a8)] - **http**: wait for pending responses in closeIdleConnections (Paolo Insogna) [#43890](nodejs/node#43890)
-   \[[`781d5e54e3`](nodejs/node@781d5e54e3)] - **inspector**: set sampling interval before start (Shelley Vohr) [#43779](nodejs/node#43779)
-   \[[`0b5dbb2a56`](nodejs/node@0b5dbb2a56)] - **lib**: refactor PriorityQueue to use private field (Finn Yu) [#43889](nodejs/node#43889)
-   \[[`324473ca32`](nodejs/node@324473ca32)] - **(SEMVER-MINOR)** **lib**: improved diagnostics_channel subscribe/unsubscribe (Stephen Belanger) [#42714](nodejs/node#42714)
-   \[[`5aa3b213ac`](nodejs/node@5aa3b213ac)] - **meta**: update AUTHORS (Node.js GitHub Bot) [#43966](nodejs/node#43966)
-   \[[`e707552357`](nodejs/node@e707552357)] - **meta**: update `node-api` in label-pr-config (Daeyeon Jeong) [#43794](nodejs/node#43794)
-   \[[`8a8de94034`](nodejs/node@8a8de94034)] - **meta**: update AUTHORS (Node.js GitHub Bot) [#43872](nodejs/node#43872)
-   \[[`7d49fc766c`](nodejs/node@7d49fc766c)] - **meta**: use platform dropdown on flaky template (Rafael Gonzaga) [#43855](nodejs/node#43855)
-   \[[`e4aa50fc3f`](nodejs/node@e4aa50fc3f)] - **meta**: enable blank issues (Matteo Collina) [#43775](nodejs/node#43775)
-   \[[`ceb7c150ec`](nodejs/node@ceb7c150ec)] - **meta**: move one or more collaborators to emeritus (Node.js GitHub Bot) [#43770](nodejs/node#43770)
-   \[[`29bcd47738`](nodejs/node@29bcd47738)] - **net**: fix socket.\_getpeername (Daeyeon Jeong) [#43010](nodejs/node#43010)
-   \[[`380659daf1`](nodejs/node@380659daf1)] - **process**: use `defineProperty` instead of assignment (Mark S. Miller) [#43907](nodejs/node#43907)
-   \[[`aba9c8ebea`](nodejs/node@aba9c8ebea)] - **repl**: fix overzealous top-level await (Tobias Nießen) [#43827](nodejs/node#43827)
-   \[[`1deb6b73b7`](nodejs/node@1deb6b73b7)] - **repl**: use `SafePromiseAll` and `SafePromiseRace` (Antoine du Hamel) [#43758](nodejs/node#43758)
-   \[[`bf8f2e23ff`](nodejs/node@bf8f2e23ff)] - **src**: refactor DH groups to delete crypto_groups.h (Tobias Nießen) [#43896](nodejs/node#43896)
-   \[[`9435fbf8cd`](nodejs/node@9435fbf8cd)] - **src**: remove dead code in base64\_encode (Tobias Nießen) [#43979](nodejs/node#43979)
-   \[[`2c47e58ea0`](nodejs/node@2c47e58ea0)] - **src**: fix regression that a source marker is lost (cola119) [#43086](nodejs/node#43086)
-   \[[`d084150320`](nodejs/node@d084150320)] - **src**: per-isolate eternal template properties (Chengzhong Wu) [#43802](nodejs/node#43802)
-   \[[`9f9d00ccbb`](nodejs/node@9f9d00ccbb)] - **src**: merge NativeModuleEnv into NativeModuleLoader (Joyee Cheung) [#43824](nodejs/node#43824)
-   \[[`bb512904e9`](nodejs/node@bb512904e9)] - **src**: use named struct instead of typedef (Tobias Nießen) [#43881](nodejs/node#43881)
-   \[[`bb5511e8cc`](nodejs/node@bb5511e8cc)] - **src**: use named enum instead of typedef (Tobias Nießen) [#43880](nodejs/node#43880)
-   \[[`5db0c8f667`](nodejs/node@5db0c8f667)] - **src**: pass only Isolate\* and env_vars to EnabledDebugList::Parse() (Darshan Sen) [#43668](nodejs/node#43668)
-   \[[`249365524e`](nodejs/node@249365524e)] - **src**: fix node watchdog race condition (theanarkh) [#43780](nodejs/node#43780)
-   \[[`17cb27237d`](nodejs/node@17cb27237d)] - **src**: deduplicate `SetALPN` implementations (Tobias Nießen) [#43756](nodejs/node#43756)
-   \[[`b4c75a96be`](nodejs/node@b4c75a96be)] - **src**: fix `napi_check_object_type_tag()` (Daeyeon Jeong) [#43788](nodejs/node#43788)
-   \[[`8432d6596f`](nodejs/node@8432d6596f)] - **src**: slim down env-inl.h (Ben Noordhuis) [#43745](nodejs/node#43745)
-   \[[`2266a4b6d6`](nodejs/node@2266a4b6d6)] - **stream**: improve `respondWithNewView()` (Daeyeon Jeong) [#43866](nodejs/node#43866)
-   \[[`bf3991b406`](nodejs/node@bf3991b406)] - **stream**: fix 0 transform hwm backpressure (Robert Nagy) [#43685](nodejs/node#43685)
-   \[[`a057510037`](nodejs/node@a057510037)] - **stream**: initial approach to include strategy options on Readable.toWeb() (txxnano) [#43515](nodejs/node#43515)
-   \[[`198cf59d2c`](nodejs/node@198cf59d2c)] - **test**: update WPT encoding tests (Kohei Ueno) [#43958](nodejs/node#43958)
-   \[[`f0ed1aed8d`](nodejs/node@f0ed1aed8d)] - **test**: remove test-whatwg-events-add-event-listener-options-once.js (Feng Yu) [#43877](nodejs/node#43877)
-   \[[`88505556fe`](nodejs/node@88505556fe)] - **test**: work scheduled in process.nextTick can keep the event loop alive (Andreu Botella) [#43787](nodejs/node#43787)
-   \[[`81a21946eb`](nodejs/node@81a21946eb)] - **test**: simplify test-tls-set-secure-context (Tobias Nießen) [#43878](nodejs/node#43878)
-   \[[`61cd11a8a7`](nodejs/node@61cd11a8a7)] - **test**: use `common.mustNotMutateObjectDeep()` in fs tests (LiviaMedeiros) [#43819](nodejs/node#43819)
-   \[[`b1081dbe12`](nodejs/node@b1081dbe12)] - **test**: fix test http upload timeout (theanarkh) [#43935](nodejs/node#43935)
-   \[[`efd5e0e925`](nodejs/node@efd5e0e925)] - **test**: simplify ReplStream.wait() (Tobias Nießen) [#43857](nodejs/node#43857)
-   \[[`ef21ad2996`](nodejs/node@ef21ad2996)] - **test**: merge test-crypto-dh-hash with modp18 test (Tobias Nießen) [#43891](nodejs/node#43891)
-   \[[`e502c50a90`](nodejs/node@e502c50a90)] - **test**: refactor `test/es-module/test-esm-resolve-type` (Antoine du Hamel) [#43178](nodejs/node#43178)
-   \[[`c782c3dc69`](nodejs/node@c782c3dc69)] - **test**: ensure NODE_EXTRA_CA_CERTS not set before tests (KrayzeeKev) [#43858](nodejs/node#43858)
-   \[[`bb6787cb57`](nodejs/node@bb6787cb57)] - **test**: add check to test-fs-readfile-tostring-fail (Richard Lau) [#43850](nodejs/node#43850)
-   \[[`7571704186`](nodejs/node@7571704186)] - **test**: complete TODO in test/wpt/test-url.js (Kohei Ueno) [#43797](nodejs/node#43797)
-   \[[`6f1d2dfb9d`](nodejs/node@6f1d2dfb9d)] - **test**: add test on worker process.exit in async modules (Chengzhong Wu) [#43751](nodejs/node#43751)
-   \[[`776cc3abbd`](nodejs/node@776cc3abbd)] - **test**: use `common.mustNotMutateObjectDeep()` in immutability tests (LiviaMedeiros) [#43196](nodejs/node#43196)
-   \[[`42f2deb3a0`](nodejs/node@42f2deb3a0)] - **test**: add `common.mustNotMutateObjectDeep()` (LiviaMedeiros) [#43196](nodejs/node#43196)
-   \[[`f3fc51c508`](nodejs/node@f3fc51c508)] - **test**: fix coverity warning in test (Michael Dawson) [#43631](nodejs/node#43631)
-   \[[`a9ecba2fa8`](nodejs/node@a9ecba2fa8)] - **test**: mark test-http-client-response-timeout flaky (Tobias Nießen) [#43792](nodejs/node#43792)
-   \[[`cd0d9ddb7c`](nodejs/node@cd0d9ddb7c)] - **test_runner**: add support for boolean values for `concurrency` option (Lenvin Gonsalves) [#43887](nodejs/node#43887)
-   \[[`f98020138a`](nodejs/node@f98020138a)] - **test_runner**: validate `timeout` option (Antoine du Hamel) [#43843](nodejs/node#43843)
-   \[[`58d15b3687`](nodejs/node@58d15b3687)] - **test_runner**: pass signal on timeout (Moshe Atlow) [#43911](nodejs/node#43911)
-   \[[`8b0248506f`](nodejs/node@8b0248506f)] - **test_runner**: do not report an error when tests are passing (Antoine du Hamel) [#43919](nodejs/node#43919)
-   \[[`aa8053e1fa`](nodejs/node@aa8053e1fa)] - **test_runner**: recieve and pass AbortSignal (Moshe Atlow) [#43554](nodejs/node#43554)
-   \[[`f13e4c1be9`](nodejs/node@f13e4c1be9)] - **test_runner**: fix `it` concurrency (Moshe Atlow) [#43757](nodejs/node#43757)
-   \[[`e404a3ef6d`](nodejs/node@e404a3ef6d)] - **test_runner**: support timeout for tests (Moshe Atlow) [#43505](nodejs/node#43505)
-   \[[`f28198cc05`](nodejs/node@f28198cc05)] - **test_runner**: catch errors thrown within `describe` (Moshe Atlow) [#43729](nodejs/node#43729)
-   \[[`bfe0ac6cd0`](nodejs/node@bfe0ac6cd0)] - **tools**: add more options to track flaky tests (Antoine du Hamel) [#43954](nodejs/node#43954)
-   \[[`17a4e5e775`](nodejs/node@17a4e5e775)] - **tools**: add verbose flag to inactive TSC finder (Rich Trott) [#43913](nodejs/node#43913)
-   \[[`373304b0c7`](nodejs/node@373304b0c7)] - **tools**: add support for using API key to vuln checking script (Facundo Tuesca) [#43909](nodejs/node#43909)
-   \[[`ed45088c14`](nodejs/node@ed45088c14)] - **tools**: support versioned node shared libs on z/OS (alexcfyung) [#42256](nodejs/node#42256)
-   \[[`c9ecd6d21f`](nodejs/node@c9ecd6d21f)] - **tools**: update doc to [email protected] (Node.js GitHub Bot) [#43870](nodejs/node#43870)
-   \[[`c92135aa0f`](nodejs/node@c92135aa0f)] - **tools**: update lint-md-dependencies to [email protected] (Node.js GitHub Bot) [#43871](nodejs/node#43871)
-   \[[`e12bf40fd1`](nodejs/node@e12bf40fd1)] - **tools**: update eslint to 8.20.0 (Node.js GitHub Bot) [#43873](nodejs/node#43873)
-   \[[`09fe9b30a9`](nodejs/node@09fe9b30a9)] - **tools**: add script for vulnerability checking (Facundo Tuesca) [#43362](nodejs/node#43362)
-   \[[`19e8876877`](nodejs/node@19e8876877)] - **trace_events**: trace net connect event (theanarkh) [#43903](nodejs/node#43903)
-   \[[`1af7f24143`](nodejs/node@1af7f24143)] - **util**: remove unicode support todo for perf implications (Rhys) [#43762](nodejs/node#43762)
-   \[[`acfc33ca8c`](nodejs/node@acfc33ca8c)] - **(SEMVER-MINOR)** **util**: add tokens to parseArgs (John Gee) [#43459](nodejs/node#43459)
-   \[[`f32aec8a6d`](nodejs/node@f32aec8a6d)] - **util**: refactor to use validateObject (Kohei Ueno) [#43769](nodejs/node#43769)
-   \[[`d7cfd0c5ba`](nodejs/node@d7cfd0c5ba)] - **v8**: serialize BigInt64Array and BigUint64Array (Ben Noordhuis) [#43571](nodejs/node#43571)
guangwong pushed a commit to noslate-project/node that referenced this pull request Oct 10, 2022
This function returns a Proxy object that throws on attempt to mutate it
Functions and primitives are returned directly

PR-URL: nodejs/node#43196
Reviewed-By: Darshan Sen <[email protected]>
Reviewed-By: Antoine du Hamel <[email protected]>
guangwong pushed a commit to noslate-project/node that referenced this pull request Oct 10, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
author ready PRs that have at least one approval, no pending requests for changes, and a CI started. commit-queue-failed An error occurred while landing this pull request using GitHub Actions. commit-queue-rebase Add this label to allow the Commit Queue to land a PR in several commits. needs-ci PRs that need a full CI run. test Issues and PRs related to the tests.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants