diff --git a/CHANGELOG.md b/CHANGELOG.md index 0fc8df52ae20..6225ec6c0fc5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,7 +26,7 @@ - `[jest-environment-node]` [**BREAKING**] Add default `node` and `node-addon` conditions to `exportConditions` for `node` environment ([#11924](https://github.com/facebook/jest/pull/11924)) - `[jest-environment-node]` [**BREAKING**] Pass global config to Jest environment constructor for `node` environment ([#12461](https://github.com/facebook/jest/pull/12461)) - `[jest-environment-node]` [**BREAKING**] Second argument `context` to constructor is mandatory ([#12469](https://github.com/facebook/jest/pull/12469)) -- `[jest-environment-node]` Add all available globals to test globals, not just explicit ones ([#12642](https://github.com/facebook/jest/pull/12642)) +- `[jest-environment-node]` Add all available globals to test globals, not just explicit ones ([#12642](https://github.com/facebook/jest/pull/12642), [#12696](https://github.com/facebook/jest/pull/12696)) - `[@jest/expect]` New module which extends `expect` with `jest-snapshot` matchers ([#12404](https://github.com/facebook/jest/pull/12404), [#12410](https://github.com/facebook/jest/pull/12410), [#12418](https://github.com/facebook/jest/pull/12418)) - `[@jest/expect-utils]` New module exporting utils for `expect` ([#12323](https://github.com/facebook/jest/pull/12323)) - `[@jest/fake-timers]` [**BREAKING**] Rename `timers` configuration option to `fakeTimers` ([#12572](https://github.com/facebook/jest/pull/12572)) diff --git a/packages/jest-environment-node/src/index.ts b/packages/jest-environment-node/src/index.ts index b6bdd65d895e..ec2b61f09ac0 100644 --- a/packages/jest-environment-node/src/index.ts +++ b/packages/jest-environment-node/src/index.ts @@ -30,12 +30,27 @@ const denyList = new Set([ 'Buffer', 'ArrayBuffer', 'Uint8Array', + // if env is loaded within a jest test + 'jest-symbol-do-not-touch', ]); -const nodeGlobals = new Set( - Object.getOwnPropertyNames(globalThis).filter( - global => !denyList.has(global), - ), +const nodeGlobals = new Map( + Object.getOwnPropertyNames(globalThis) + .filter(global => !denyList.has(global)) + .map(nodeGlobalsKey => { + const descriptor = Object.getOwnPropertyDescriptor( + globalThis, + nodeGlobalsKey, + ); + + if (!descriptor) { + throw new Error( + `No property descriptor for ${nodeGlobalsKey}, this is a bug in Jest.`, + ); + } + + return [nodeGlobalsKey, descriptor]; + }), ); export default class NodeEnvironment implements JestEnvironment { @@ -55,10 +70,34 @@ export default class NodeEnvironment implements JestEnvironment { )); const contextGlobals = new Set(Object.getOwnPropertyNames(global)); - for (const nodeGlobalsKey of nodeGlobals) { + for (const [nodeGlobalsKey, descriptor] of nodeGlobals) { if (!contextGlobals.has(nodeGlobalsKey)) { - // @ts-expect-error - global[nodeGlobalsKey] = globalThis[nodeGlobalsKey]; + Object.defineProperty(global, nodeGlobalsKey, { + configurable: descriptor.configurable, + enumerable: descriptor.enumerable, + get() { + // @ts-expect-error + const val = globalThis[nodeGlobalsKey]; + + // override lazy getter + Object.defineProperty(global, nodeGlobalsKey, { + configurable: descriptor.configurable, + enumerable: descriptor.enumerable, + value: val, + writable: descriptor.writable, + }); + return val; + }, + set(val) { + // override lazy getter + Object.defineProperty(global, nodeGlobalsKey, { + configurable: descriptor.configurable, + enumerable: descriptor.enumerable, + value: val, + writable: true, + }); + }, + }); } }