394 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			394 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
/*
 | 
						|
This file is copied from https://github.com/nodejs/node/blob/v14.19.3/lib/internal/per_context/primordials.js
 | 
						|
under the following license:
 | 
						|
 | 
						|
Copyright Node.js contributors. All rights reserved.
 | 
						|
 | 
						|
Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
						|
of this software and associated documentation files (the "Software"), to
 | 
						|
deal in the Software without restriction, including without limitation the
 | 
						|
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 | 
						|
sell copies of the Software, and to permit persons to whom the Software is
 | 
						|
furnished to do so, subject to the following conditions:
 | 
						|
 | 
						|
The above copyright notice and this permission notice shall be included in
 | 
						|
all copies or substantial portions of the Software.
 | 
						|
 | 
						|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
						|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
						|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
						|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
						|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 | 
						|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 | 
						|
IN THE SOFTWARE.
 | 
						|
*/
 | 
						|
 | 
						|
'use strict';
 | 
						|
 | 
						|
/* eslint-disable node-core/prefer-primordials */
 | 
						|
 | 
						|
// This file subclasses and stores the JS builtins that come from the VM
 | 
						|
// so that Node.js's builtin modules do not need to later look these up from
 | 
						|
// the global proxy, which can be mutated by users.
 | 
						|
 | 
						|
// Use of primordials have sometimes a dramatic impact on performance, please
 | 
						|
// benchmark all changes made in performance-sensitive areas of the codebase.
 | 
						|
// See: https://github.com/nodejs/node/pull/38248
 | 
						|
 | 
						|
const primordials = {};
 | 
						|
 | 
						|
const {
 | 
						|
  defineProperty: ReflectDefineProperty,
 | 
						|
  getOwnPropertyDescriptor: ReflectGetOwnPropertyDescriptor,
 | 
						|
  ownKeys: ReflectOwnKeys,
 | 
						|
} = Reflect;
 | 
						|
 | 
						|
// `uncurryThis` is equivalent to `func => Function.prototype.call.bind(func)`.
 | 
						|
// It is using `bind.bind(call)` to avoid using `Function.prototype.bind`
 | 
						|
// and `Function.prototype.call` after it may have been mutated by users.
 | 
						|
const { apply, bind, call } = Function.prototype;
 | 
						|
const uncurryThis = bind.bind(call);
 | 
						|
primordials.uncurryThis = uncurryThis;
 | 
						|
 | 
						|
// `applyBind` is equivalent to `func => Function.prototype.apply.bind(func)`.
 | 
						|
// It is using `bind.bind(apply)` to avoid using `Function.prototype.bind`
 | 
						|
// and `Function.prototype.apply` after it may have been mutated by users.
 | 
						|
const applyBind = bind.bind(apply);
 | 
						|
primordials.applyBind = applyBind;
 | 
						|
 | 
						|
// Methods that accept a variable number of arguments, and thus it's useful to
 | 
						|
// also create `${prefix}${key}Apply`, which uses `Function.prototype.apply`,
 | 
						|
// instead of `Function.prototype.call`, and thus doesn't require iterator
 | 
						|
// destructuring.
 | 
						|
const varargsMethods = [
 | 
						|
  // 'ArrayPrototypeConcat' is omitted, because it performs the spread
 | 
						|
  // on its own for arrays and array-likes with a truthy
 | 
						|
  // @@isConcatSpreadable symbol property.
 | 
						|
  'ArrayOf',
 | 
						|
  'ArrayPrototypePush',
 | 
						|
  'ArrayPrototypeUnshift',
 | 
						|
  // 'FunctionPrototypeCall' is omitted, since there's 'ReflectApply'
 | 
						|
  // and 'FunctionPrototypeApply'.
 | 
						|
  'MathHypot',
 | 
						|
  'MathMax',
 | 
						|
  'MathMin',
 | 
						|
  'StringPrototypeConcat',
 | 
						|
  'TypedArrayOf',
 | 
						|
];
 | 
						|
 | 
						|
function getNewKey(key) {
 | 
						|
  return typeof key === 'symbol' ?
 | 
						|
    `Symbol${key.description[7].toUpperCase()}${key.description.slice(8)}` :
 | 
						|
    `${key[0].toUpperCase()}${key.slice(1)}`;
 | 
						|
}
 | 
						|
 | 
						|
function copyAccessor(dest, prefix, key, { enumerable, get, set }) {
 | 
						|
  ReflectDefineProperty(dest, `${prefix}Get${key}`, {
 | 
						|
    value: uncurryThis(get),
 | 
						|
    enumerable
 | 
						|
  });
 | 
						|
  if (set !== undefined) {
 | 
						|
    ReflectDefineProperty(dest, `${prefix}Set${key}`, {
 | 
						|
      value: uncurryThis(set),
 | 
						|
      enumerable
 | 
						|
    });
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
function copyPropsRenamed(src, dest, prefix) {
 | 
						|
  for (const key of ReflectOwnKeys(src)) {
 | 
						|
    const newKey = getNewKey(key);
 | 
						|
    const desc = ReflectGetOwnPropertyDescriptor(src, key);
 | 
						|
    if ('get' in desc) {
 | 
						|
      copyAccessor(dest, prefix, newKey, desc);
 | 
						|
    } else {
 | 
						|
      const name = `${prefix}${newKey}`;
 | 
						|
      ReflectDefineProperty(dest, name, desc);
 | 
						|
      if (varargsMethods.includes(name)) {
 | 
						|
        ReflectDefineProperty(dest, `${name}Apply`, {
 | 
						|
          // `src` is bound as the `this` so that the static `this` points
 | 
						|
          // to the object it was defined on,
 | 
						|
          // e.g.: `ArrayOfApply` gets a `this` of `Array`:
 | 
						|
          value: applyBind(desc.value, src),
 | 
						|
        });
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
function copyPropsRenamedBound(src, dest, prefix) {
 | 
						|
  for (const key of ReflectOwnKeys(src)) {
 | 
						|
    const newKey = getNewKey(key);
 | 
						|
    const desc = ReflectGetOwnPropertyDescriptor(src, key);
 | 
						|
    if ('get' in desc) {
 | 
						|
      copyAccessor(dest, prefix, newKey, desc);
 | 
						|
    } else {
 | 
						|
      const { value } = desc;
 | 
						|
      if (typeof value === 'function') {
 | 
						|
        desc.value = value.bind(src);
 | 
						|
      }
 | 
						|
 | 
						|
      const name = `${prefix}${newKey}`;
 | 
						|
      ReflectDefineProperty(dest, name, desc);
 | 
						|
      if (varargsMethods.includes(name)) {
 | 
						|
        ReflectDefineProperty(dest, `${name}Apply`, {
 | 
						|
          value: applyBind(value, src),
 | 
						|
        });
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
function copyPrototype(src, dest, prefix) {
 | 
						|
  for (const key of ReflectOwnKeys(src)) {
 | 
						|
    const newKey = getNewKey(key);
 | 
						|
    const desc = ReflectGetOwnPropertyDescriptor(src, key);
 | 
						|
    if ('get' in desc) {
 | 
						|
      copyAccessor(dest, prefix, newKey, desc);
 | 
						|
    } else {
 | 
						|
      const { value } = desc;
 | 
						|
      if (typeof value === 'function') {
 | 
						|
        desc.value = uncurryThis(value);
 | 
						|
      }
 | 
						|
 | 
						|
      const name = `${prefix}${newKey}`;
 | 
						|
      ReflectDefineProperty(dest, name, desc);
 | 
						|
      if (varargsMethods.includes(name)) {
 | 
						|
        ReflectDefineProperty(dest, `${name}Apply`, {
 | 
						|
          value: applyBind(value),
 | 
						|
        });
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
// Create copies of configurable value properties of the global object
 | 
						|
[
 | 
						|
  'Proxy',
 | 
						|
  'globalThis',
 | 
						|
].forEach((name) => {
 | 
						|
  // eslint-disable-next-line no-restricted-globals
 | 
						|
  primordials[name] = globalThis[name];
 | 
						|
});
 | 
						|
 | 
						|
// Create copies of URI handling functions
 | 
						|
[
 | 
						|
  decodeURI,
 | 
						|
  decodeURIComponent,
 | 
						|
  encodeURI,
 | 
						|
  encodeURIComponent,
 | 
						|
].forEach((fn) => {
 | 
						|
  primordials[fn.name] = fn;
 | 
						|
});
 | 
						|
 | 
						|
// Create copies of the namespace objects
 | 
						|
[
 | 
						|
  'JSON',
 | 
						|
  'Math',
 | 
						|
  'Proxy',
 | 
						|
  'Reflect',
 | 
						|
].forEach((name) => {
 | 
						|
  // eslint-disable-next-line no-restricted-globals
 | 
						|
  copyPropsRenamed(global[name], primordials, name);
 | 
						|
});
 | 
						|
 | 
						|
// Create copies of intrinsic objects
 | 
						|
[
 | 
						|
  'Array',
 | 
						|
  'ArrayBuffer',
 | 
						|
  'BigInt',
 | 
						|
  'BigInt64Array',
 | 
						|
  'BigUint64Array',
 | 
						|
  'Boolean',
 | 
						|
  'DataView',
 | 
						|
  'Date',
 | 
						|
  'Error',
 | 
						|
  'EvalError',
 | 
						|
  'Float32Array',
 | 
						|
  'Float64Array',
 | 
						|
  'Function',
 | 
						|
  'Int16Array',
 | 
						|
  'Int32Array',
 | 
						|
  'Int8Array',
 | 
						|
  'Map',
 | 
						|
  'Number',
 | 
						|
  'Object',
 | 
						|
  'RangeError',
 | 
						|
  'ReferenceError',
 | 
						|
  'RegExp',
 | 
						|
  'Set',
 | 
						|
  'String',
 | 
						|
  'Symbol',
 | 
						|
  'SyntaxError',
 | 
						|
  'TypeError',
 | 
						|
  'URIError',
 | 
						|
  'Uint16Array',
 | 
						|
  'Uint32Array',
 | 
						|
  'Uint8Array',
 | 
						|
  'Uint8ClampedArray',
 | 
						|
  'WeakMap',
 | 
						|
  'WeakSet',
 | 
						|
].forEach((name) => {
 | 
						|
  // eslint-disable-next-line no-restricted-globals
 | 
						|
  const original = global[name];
 | 
						|
  primordials[name] = original;
 | 
						|
  copyPropsRenamed(original, primordials, name);
 | 
						|
  copyPrototype(original.prototype, primordials, `${name}Prototype`);
 | 
						|
});
 | 
						|
 | 
						|
// Create copies of intrinsic objects that require a valid `this` to call
 | 
						|
// static methods.
 | 
						|
// Refs: https://www.ecma-international.org/ecma-262/#sec-promise.all
 | 
						|
[
 | 
						|
  'Promise',
 | 
						|
].forEach((name) => {
 | 
						|
  // eslint-disable-next-line no-restricted-globals
 | 
						|
  const original = global[name];
 | 
						|
  primordials[name] = original;
 | 
						|
  copyPropsRenamedBound(original, primordials, name);
 | 
						|
  copyPrototype(original.prototype, primordials, `${name}Prototype`);
 | 
						|
});
 | 
						|
 | 
						|
// Create copies of abstract intrinsic objects that are not directly exposed
 | 
						|
// on the global object.
 | 
						|
// Refs: https://tc39.es/ecma262/#sec-%typedarray%-intrinsic-object
 | 
						|
[
 | 
						|
  { name: 'TypedArray', original: Reflect.getPrototypeOf(Uint8Array) },
 | 
						|
  { name: 'ArrayIterator', original: {
 | 
						|
    prototype: Reflect.getPrototypeOf(Array.prototype[Symbol.iterator]()),
 | 
						|
  } },
 | 
						|
  { name: 'StringIterator', original: {
 | 
						|
    prototype: Reflect.getPrototypeOf(String.prototype[Symbol.iterator]()),
 | 
						|
  } },
 | 
						|
].forEach(({ name, original }) => {
 | 
						|
  primordials[name] = original;
 | 
						|
  // The static %TypedArray% methods require a valid `this`, but can't be bound,
 | 
						|
  // as they need a subclass constructor as the receiver:
 | 
						|
  copyPrototype(original, primordials, name);
 | 
						|
  copyPrototype(original.prototype, primordials, `${name}Prototype`);
 | 
						|
});
 | 
						|
 | 
						|
/* eslint-enable node-core/prefer-primordials */
 | 
						|
 | 
						|
const {
 | 
						|
  ArrayPrototypeForEach,
 | 
						|
  FunctionPrototypeCall,
 | 
						|
  Map,
 | 
						|
  ObjectFreeze,
 | 
						|
  ObjectSetPrototypeOf,
 | 
						|
  Set,
 | 
						|
  SymbolIterator,
 | 
						|
  WeakMap,
 | 
						|
  WeakSet,
 | 
						|
} = primordials;
 | 
						|
 | 
						|
// Because these functions are used by `makeSafe`, which is exposed
 | 
						|
// on the `primordials` object, it's important to use const references
 | 
						|
// to the primordials that they use:
 | 
						|
const createSafeIterator = (factory, next) => {
 | 
						|
  class SafeIterator {
 | 
						|
    constructor(iterable) {
 | 
						|
      this._iterator = factory(iterable);
 | 
						|
    }
 | 
						|
    next() {
 | 
						|
      return next(this._iterator);
 | 
						|
    }
 | 
						|
    [SymbolIterator]() {
 | 
						|
      return this;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  ObjectSetPrototypeOf(SafeIterator.prototype, null);
 | 
						|
  ObjectFreeze(SafeIterator.prototype);
 | 
						|
  ObjectFreeze(SafeIterator);
 | 
						|
  return SafeIterator;
 | 
						|
};
 | 
						|
 | 
						|
primordials.SafeArrayIterator = createSafeIterator(
 | 
						|
  primordials.ArrayPrototypeSymbolIterator,
 | 
						|
  primordials.ArrayIteratorPrototypeNext
 | 
						|
);
 | 
						|
primordials.SafeStringIterator = createSafeIterator(
 | 
						|
  primordials.StringPrototypeSymbolIterator,
 | 
						|
  primordials.StringIteratorPrototypeNext
 | 
						|
);
 | 
						|
 | 
						|
const copyProps = (src, dest) => {
 | 
						|
  ArrayPrototypeForEach(ReflectOwnKeys(src), (key) => {
 | 
						|
    if (!ReflectGetOwnPropertyDescriptor(dest, key)) {
 | 
						|
      ReflectDefineProperty(
 | 
						|
        dest,
 | 
						|
        key,
 | 
						|
        ReflectGetOwnPropertyDescriptor(src, key));
 | 
						|
    }
 | 
						|
  });
 | 
						|
};
 | 
						|
 | 
						|
const makeSafe = (unsafe, safe) => {
 | 
						|
  if (SymbolIterator in unsafe.prototype) {
 | 
						|
    const dummy = new unsafe();
 | 
						|
    let next; // We can reuse the same `next` method.
 | 
						|
 | 
						|
    ArrayPrototypeForEach(ReflectOwnKeys(unsafe.prototype), (key) => {
 | 
						|
      if (!ReflectGetOwnPropertyDescriptor(safe.prototype, key)) {
 | 
						|
        const desc = ReflectGetOwnPropertyDescriptor(unsafe.prototype, key);
 | 
						|
        if (
 | 
						|
          typeof desc.value === 'function' &&
 | 
						|
          desc.value.length === 0 &&
 | 
						|
          SymbolIterator in (FunctionPrototypeCall(desc.value, dummy) ?? {})
 | 
						|
        ) {
 | 
						|
          const createIterator = uncurryThis(desc.value);
 | 
						|
          next = next ?? uncurryThis(createIterator(dummy).next);
 | 
						|
          const SafeIterator = createSafeIterator(createIterator, next);
 | 
						|
          desc.value = function() {
 | 
						|
            return new SafeIterator(this);
 | 
						|
          };
 | 
						|
        }
 | 
						|
        ReflectDefineProperty(safe.prototype, key, desc);
 | 
						|
      }
 | 
						|
    });
 | 
						|
  } else {
 | 
						|
    copyProps(unsafe.prototype, safe.prototype);
 | 
						|
  }
 | 
						|
  copyProps(unsafe, safe);
 | 
						|
 | 
						|
  ObjectSetPrototypeOf(safe.prototype, null);
 | 
						|
  ObjectFreeze(safe.prototype);
 | 
						|
  ObjectFreeze(safe);
 | 
						|
  return safe;
 | 
						|
};
 | 
						|
primordials.makeSafe = makeSafe;
 | 
						|
 | 
						|
// Subclass the constructors because we need to use their prototype
 | 
						|
// methods later.
 | 
						|
// Defining the `constructor` is necessary here to avoid the default
 | 
						|
// constructor which uses the user-mutable `%ArrayIteratorPrototype%.next`.
 | 
						|
primordials.SafeMap = makeSafe(
 | 
						|
  Map,
 | 
						|
  class SafeMap extends Map {
 | 
						|
    constructor(i) { super(i); } // eslint-disable-line no-useless-constructor
 | 
						|
  }
 | 
						|
);
 | 
						|
primordials.SafeWeakMap = makeSafe(
 | 
						|
  WeakMap,
 | 
						|
  class SafeWeakMap extends WeakMap {
 | 
						|
    constructor(i) { super(i); } // eslint-disable-line no-useless-constructor
 | 
						|
  }
 | 
						|
);
 | 
						|
primordials.SafeSet = makeSafe(
 | 
						|
  Set,
 | 
						|
  class SafeSet extends Set {
 | 
						|
    constructor(i) { super(i); } // eslint-disable-line no-useless-constructor
 | 
						|
  }
 | 
						|
);
 | 
						|
primordials.SafeWeakSet = makeSafe(
 | 
						|
  WeakSet,
 | 
						|
  class SafeWeakSet extends WeakSet {
 | 
						|
    constructor(i) { super(i); } // eslint-disable-line no-useless-constructor
 | 
						|
  }
 | 
						|
);
 | 
						|
 | 
						|
ObjectSetPrototypeOf(primordials, null);
 | 
						|
ObjectFreeze(primordials);
 | 
						|
 | 
						|
module.exports = primordials;
 |