createProcessObject.js 3.47 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
'use strict';

Object.defineProperty(exports, '__esModule', {
  value: true
});
exports.default = _default;

var _deepCyclicCopy = _interopRequireDefault(require('./deepCyclicCopy'));

function _interopRequireDefault(obj) {
  return obj && obj.__esModule ? obj : {default: obj};
}

/**
 * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */
const BLACKLIST = new Set(['env', 'mainModule', '_events']);
const isWin32 = process.platform === 'win32';
const proto = 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
// 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() {
  const real = Object.create(proto);
  const lookup = {};

  function deletePropertyWin32(_target, key) {
    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;
  }

  function deleteProperty(_target, key) {
    delete real[key];
    delete lookup[key];
    return true;
  }

  function getProperty(_target, key) {
    return real[key];
  }

  function getPropertyWin32(_target, key) {
    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;

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

      real[key] = strValue;
      return true;
    }
  });
  return Object.assign(proxy, process.env);
}

function _default() {
  const process = require('process');

  const newProcess = (0, _deepCyclicCopy.default)(process, {
    blacklist: BLACKLIST,
    keepPrototype: true
  });

  try {
    // This fails on Node 12, but it's already set to 'process'
    newProcess[Symbol.toStringTag] = 'process';
  } catch (e) {
    // Make sure it's actually set instead of potentially ignoring errors
    if (newProcess[Symbol.toStringTag] !== 'process') {
      e.message =
        'Unable to set toStringTag on process. Please open up an issue at https://github.com/facebook/jest\n\n' +
        e.message;
      throw e;
    }
  } // Sequentially execute all constructors over the object.

  let proto = process;

  while ((proto = Object.getPrototypeOf(proto))) {
    if (typeof proto.constructor === 'function') {
      proto.constructor.call(newProcess);
    }
  }

  newProcess.env = createProcessEnv();

  newProcess.send = () => {};

  const domainPropertyDescriptor = Object.getOwnPropertyDescriptor(
    newProcess,
    'domain'
  );

  if (domainPropertyDescriptor && !domainPropertyDescriptor.enumerable) {
    Object.defineProperty(newProcess, 'domain', {
      get() {
        return process.domain;
      }
    });
  }

  return newProcess;
}