Skip to content

Commit

Permalink
Make "process.env" case insensitive in Windows (#5465)
Browse files Browse the repository at this point in the history
  • Loading branch information
mjesun authored Feb 5, 2018
1 parent af09be8 commit ae3d55e
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 1 deletion.
44 changes: 44 additions & 0 deletions packages/jest-util/src/__tests__/create_process_object.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,47 @@ it('creates a process object that looks like the original one', () => {
it('fakes require("process") so it is equal to "global.process"', () => {
expect(require('process') === process).toBe(true);
});

it('checks that process.env works as expected on Linux platforms', () => {
Object.defineProperty(process, 'platform', {get: () => 'linux'});

// Existing properties inside process.env are copied to the fake environment.
process.env.PROP_STRING = 'foo';
process.env.PROP_NUMBER = 3;
process.env.PROP_UNDEFINED = undefined;

const fake = createProcessObject().env;

// All values converted to strings.
expect(fake.PROP_STRING).toBe('foo');
expect(fake.PROP_NUMBER).toBe('3');
expect(fake.PROP_UNDEFINED).toBe('undefined');

// Mac and Linux are case sensitive.
expect(fake.PROP_string).toBe(undefined);

// Added properties to the fake object are not added to the real one.
fake.PROP_ADDED = 'new!';

expect(fake.PROP_ADDED).toBe('new!');
expect(process.env.PROP_ADDED).toBe(undefined);
});

it('checks that process.env works as expected in Windows platforms', () => {
Object.defineProperty(process, 'platform', {get: () => 'win32'});

// Windows is not case sensitive when it comes to property names.
process.env.PROP_STRING = 'foo';

const fake = createProcessObject().env;

expect(fake.PROP_STRING).toBe('foo');
expect(fake.PROP_string).toBe('foo');

// Inherited methods, however, are not affected by case insensitiveness.
expect(typeof fake.toString).toBe('function');
expect(typeof fake.valueOf).toBe('function');

expect(typeof fake.tostring).toBe('undefined');
expect(typeof fake.valueof).toBe('undefined');
});
40 changes: 39 additions & 1 deletion packages/jest-util/src/create_process_object.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,43 @@

import deepCyclicCopy from './deep_cyclic_copy';

const BLACKLIST = new Set(['mainModule', '_events']);
const BLACKLIST = new Set(['env', 'mainModule', '_events']);

// 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
// string; and third, it is case-insensitive in Windows. We use a proxy here to
// mimic it (see https://nodejs.org/api/process.html#process_process_env).

function createProcessEnv() {
// $FlowFixMe: Apparently Flow does not understand that this is a prototype.
const proto: Object = Object.getPrototypeOf(process.env);
const real = Object.create(proto);
const lookup = {};

const proxy = new Proxy(real, {
get(target, key) {
if ((typeof key === 'string') && (process.platform === 'win32')) {
return lookup[key in proto ? key : key.toLowerCase()];
} else {
return real[key];
}
},

set(target, key, value) {
const strValue = '' + value;

if (typeof key === 'string') {
lookup[key.toLowerCase()] = strValue;
}

real[key] = strValue;

return true;
},
});

return Object.assign(proxy, process.env);
}

export default function() {
const process = require('process');
Expand All @@ -29,5 +65,7 @@ export default function() {
}
}

newProcess.env = createProcessEnv();

return newProcess;
}

0 comments on commit ae3d55e

Please sign in to comment.