diff --git a/packages/jest-util/src/__tests__/createProcessObject.test.ts b/packages/jest-util/src/__tests__/createProcessObject.test.ts index 4eca00c977a2..baa29639c6c5 100644 --- a/packages/jest-util/src/__tests__/createProcessObject.test.ts +++ b/packages/jest-util/src/__tests__/createProcessObject.test.ts @@ -6,9 +6,17 @@ */ import EventEmitter from 'events'; -import createProcessObject from '../createProcessObject'; + +let createProcessObject; + +function requireCreateProcessObject() { + jest.isolateModules(() => { + createProcessObject = require('../createProcessObject').default; + }); +} it('creates a process object that looks like the original one', () => { + requireCreateProcessObject(); const fakeProcess = createProcessObject(); // "process" inherits from EventEmitter through the prototype chain. @@ -35,6 +43,7 @@ it('fakes require("process") so it is equal to "global.process"', () => { it('checks that process.env works as expected on Linux platforms', () => { Object.defineProperty(process, 'platform', {get: () => 'linux'}); + requireCreateProcessObject(); // Existing properties inside process.env are copied to the fake environment. process.env.PROP_STRING = 'foo'; @@ -73,6 +82,7 @@ it('checks that process.env works as expected on Linux platforms', () => { it('checks that process.env works as expected in Windows platforms', () => { Object.defineProperty(process, 'platform', {get: () => 'win32'}); + requireCreateProcessObject(); // Windows is not case sensitive when it comes to property names. process.env.PROP_STRING = 'foo'; diff --git a/packages/jest-util/src/createProcessObject.ts b/packages/jest-util/src/createProcessObject.ts index 903336636bdd..53d18dd43cb5 100644 --- a/packages/jest-util/src/createProcessObject.ts +++ b/packages/jest-util/src/createProcessObject.ts @@ -8,6 +8,8 @@ import deepCyclicCopy from './deepCyclicCopy'; const BLACKLIST = new Set(['env', 'mainModule', '_events']); +const isWin32 = process.platform === 'win32'; +const proto: Record = Object.getPrototypeOf(process.env); // The "process.env" object has a bunch of particularities: first, it does not // directly extend from Object; second, it converts any assigned value to a @@ -15,42 +17,51 @@ const BLACKLIST = new Set(['env', 'mainModule', '_events']); // mimic it (see https://nodejs.org/api/process.html#process_process_env). function createProcessEnv(): NodeJS.ProcessEnv { - if (typeof Proxy === 'undefined') { - return deepCyclicCopy(process.env); - } - - const proto: Record = Object.getPrototypeOf(process.env); const real = Object.create(proto); const lookup: typeof process.env = {}; - const proxy = new Proxy(real, { - deleteProperty(_target, key) { - for (const name in real) { - if (real.hasOwnProperty(name)) { - if (typeof key === 'string' && process.platform === 'win32') { - if (name.toLowerCase() === key.toLowerCase()) { - delete real[name]; - delete lookup[name.toLowerCase()]; - } - } else { - if (key === name) { - delete real[name]; - delete lookup[name]; - } + function deletePropertyWin32(_target: any, key: any) { + for (const name in real) { + if (real.hasOwnProperty(name)) { + if (typeof key === 'string') { + if (name.toLowerCase() === key.toLowerCase()) { + delete real[name]; + delete lookup[name.toLowerCase()]; + } + } else { + if (key === name) { + delete real[name]; + delete lookup[name]; } } } + } - return true; - }, + return true; + } - get(_target, key) { - if (typeof key === 'string' && process.platform === 'win32') { - return lookup[key in proto ? key : key.toLowerCase()]; - } else { - return real[key]; - } - }, + function deleteProperty(_target: any, key: any) { + delete real[key]; + delete lookup[key]; + + return true; + } + + function getProperty(_target: any, key: any) { + return real[key]; + } + + function getPropertyWin32(_target: any, key: any) { + if (typeof key === 'string') { + return lookup[key in proto ? key : key.toLowerCase()]; + } else { + return real[key]; + } + } + + const proxy = new Proxy(real, { + deleteProperty: isWin32 ? deletePropertyWin32 : deleteProperty, + get: isWin32 ? getPropertyWin32 : getProperty, set(_target, key, value) { const strValue = '' + value;