"'use strict';\n\n/* eslint-disable node-core/prefer-primordials */\n\n// This file subclasses and stores the JS builtins that come from the VM\n// so that Node.js's builtin modules do not need to later look these up from\n// the global proxy, which can be mutated by users.\n\n// Use of primordials have sometimes a dramatic impact on performance, please\n// benchmark all changes made in performance-sensitive areas of the codebase.\n// See: https://github.com/nodejs/node/pull/38248\n\nconst {\n  defineProperty: ReflectDefineProperty,\n  getOwnPropertyDescriptor: ReflectGetOwnPropertyDescriptor,\n  ownKeys: ReflectOwnKeys,\n} = Reflect;\n\n// `uncurryThis` is equivalent to `func => Function.prototype.call.bind(func)`.\n// It is using `bind.bind(call)` to avoid using `Function.prototype.bind`\n// and `Function.prototype.call` after it may have been mutated by users.\nconst { apply, bind, call } = Function.prototype;\nconst uncurryThis = bind.bind(call);\nprimordials.uncurryThis = uncurryThis;\n\n// `applyBind` is equivalent to `func => Function.prototype.apply.bind(func)`.\n// It is using `bind.bind(apply)` to avoid using `Function.prototype.bind`\n// and `Function.prototype.apply` after it may have been mutated by users.\nconst applyBind = bind.bind(apply);\nprimordials.applyBind = applyBind;\n\n// Methods that accept a variable number of arguments, and thus it's useful to\n// also create `${prefix}${key}Apply`, which uses `Function.prototype.apply`,\n// instead of `Function.prototype.call`, and thus doesn't require iterator\n// destructuring.\nconst varargsMethods = [\n  // 'ArrayPrototypeConcat' is omitted, because it performs the spread\n  // on its own for arrays and array-likes with a truthy\n  // @@isConcatSpreadable symbol property.\n  'ArrayOf',\n  'ArrayPrototypePush',\n  'ArrayPrototypeUnshift',\n  // 'FunctionPrototypeCall' is omitted, since there's 'ReflectApply'\n  // and 'FunctionPrototypeApply'.\n  'MathHypot',\n  'MathMax',\n  'MathMin',\n  'StringPrototypeConcat',\n  'TypedArrayOf',\n];\n\nfunction getNewKey(key) {\n  return typeof key === 'symbol' ?\n    `Symbol${key.description[7].toUpperCase()}${key.description.slice(8)}` :\n    `${key[0].toUpperCase()}${key.slice(1)}`;\n}\n\nfunction copyAccessor(dest, prefix, key, { enumerable, get, set }) {\n  ReflectDefineProperty(dest, `${prefix}Get${key}`, {\n    value: uncurryThis(get),\n    enumerable\n  });\n  if (set !== undefined) {\n    ReflectDefineProperty(dest, `${prefix}Set${key}`, {\n      value: uncurryThis(set),\n      enumerable\n    });\n  }\n}\n\nfunction copyPropsRenamed(src, dest, prefix) {\n  for (const key of ReflectOwnKeys(src)) {\n    const newKey = getNewKey(key);\n    const desc = ReflectGetOwnPropertyDescriptor(src, key);\n    if ('get' in desc) {\n      copyAccessor(dest, prefix, newKey, desc);\n    } else {\n      const name = `${prefix}${newKey}`;\n      ReflectDefineProperty(dest, name, desc);\n      if (varargsMethods.includes(name)) {\n        ReflectDefineProperty(dest, `${name}Apply`, {\n          // `src` is bound as the `this` so that the static `this` points\n          // to the object it was defined on,\n          // e.g.: `ArrayOfApply` gets a `this` of `Array`:\n          value: applyBind(desc.value, src),\n        });\n      }\n    }\n  }\n}\n\nfunction copyPropsRenamedBound(src, dest, prefix) {\n  for (const key of ReflectOwnKeys(src)) {\n    const newKey = getNewKey(key);\n    const desc = ReflectGetOwnPropertyDescriptor(src, key);\n    if ('get' in desc) {\n      copyAccessor(dest, prefix, newKey, desc);\n    } else {\n      const { value } = desc;\n      if (typeof value === 'function') {\n        desc.value = value.bind(src);\n      }\n\n      const name = `${prefix}${newKey}`;\n      ReflectDefineProperty(dest, name, desc);\n      if (varargsMethods.includes(name)) {\n        ReflectDefineProperty(dest, `${name}Apply`, {\n          value: applyBind(value, src),\n        });\n      }\n    }\n  }\n}\n\nfunction copyPrototype(src, dest, prefix) {\n  for (const key of ReflectOwnKeys(src)) {\n    const newKey = getNewKey(key);\n    const desc = ReflectGetOwnPropertyDescriptor(src, key);\n    if ('get' in desc) {\n      copyAccessor(dest, prefix, newKey, desc);\n    } else {\n      const { value } = desc;\n      if (typeof value === 'function') {\n        desc.value = uncurryThis(value);\n      }\n\n      const name = `${prefix}${newKey}`;\n      ReflectDefineProperty(dest, name, desc);\n      if (varargsMethods.includes(name)) {\n        ReflectDefineProperty(dest, `${name}Apply`, {\n          value: applyBind(value),\n        });\n      }\n    }\n  }\n}\n\n// Create copies of configurable value properties of the global object\n[\n  'globalThis',\n].forEach((name) => {\n  // eslint-disable-next-line no-restricted-globals\n  primordials[name] = globalThis[name];\n});\n\n// Create copies of URI handling functions\n[\n  decodeURI,\n  decodeURIComponent,\n  encodeURI,\n  encodeURIComponent,\n].forEach((fn) => {\n  primordials[fn.name] = fn;\n});\n\n// Create copies of the namespace objects\n[\n  'JSON',\n  'Math',\n  'Reflect',\n].forEach((name) => {\n  // eslint-disable-next-line no-restricted-globals\n  copyPropsRenamed(global[name], primordials, name);\n});\n\n// Create copies of intrinsic objects\n[\n  'AggregateError',\n  'Array',\n  'ArrayBuffer',\n  'BigInt',\n  'BigInt64Array',\n  'BigUint64Array',\n  'Boolean',\n  'DataView',\n  'Date',\n  'Error',\n  'EvalError',\n  'FinalizationRegistry',\n  'Float32Array',\n  'Float64Array',\n  'Function',\n  'Int16Array',\n  'Int32Array',\n  'Int8Array',\n  'Map',\n  'Number',\n  'Object',\n  'RangeError',\n  'ReferenceError',\n  'RegExp',\n  'Set',\n  'String',\n  'Symbol',\n  'SyntaxError',\n  'TypeError',\n  'URIError',\n  'Uint16Array',\n  'Uint32Array',\n  'Uint8Array',\n  'Uint8ClampedArray',\n  'WeakMap',\n  'WeakRef',\n  'WeakSet',\n].forEach((name) => {\n  // eslint-disable-next-line no-restricted-globals\n  const original = global[name];\n  primordials[name] = original;\n  copyPropsRenamed(original, primordials, name);\n  copyPrototype(original.prototype, primordials, `${name}Prototype`);\n});\n\n// Create copies of intrinsic objects that require a valid `this` to call\n// static methods.\n// Refs: https://www.ecma-international.org/ecma-262/#sec-promise.all\n[\n  'Promise',\n].forEach((name) => {\n  // eslint-disable-next-line no-restricted-globals\n  const original = global[name];\n  primordials[name] = original;\n  copyPropsRenamedBound(original, primordials, name);\n  copyPrototype(original.prototype, primordials, `${name}Prototype`);\n});\n\n// Create copies of abstract intrinsic objects that are not directly exposed\n// on the global object.\n// Refs: https://tc39.es/ecma262/#sec-%typedarray%-intrinsic-object\n[\n  { name: 'TypedArray', original: Reflect.getPrototypeOf(Uint8Array) },\n  { name: 'ArrayIterator', original: {\n    prototype: Reflect.getPrototypeOf(Array.prototype[Symbol.iterator]()),\n  } },\n  { name: 'StringIterator', original: {\n    prototype: Reflect.getPrototypeOf(String.prototype[Symbol.iterator]()),\n  } },\n].forEach(({ name, original }) => {\n  primordials[name] = original;\n  // The static %TypedArray% methods require a valid `this`, but can't be bound,\n  // as they need a subclass constructor as the receiver:\n  copyPrototype(original, primordials, name);\n  copyPrototype(original.prototype, primordials, `${name}Prototype`);\n});\n\n/* eslint-enable node-core/prefer-primordials */\n\nconst {\n  ArrayPrototypeForEach,\n  FinalizationRegistry,\n  FunctionPrototypeCall,\n  Map,\n  ObjectFreeze,\n  ObjectSetPrototypeOf,\n  Set,\n  SymbolIterator,\n  WeakMap,\n  WeakRef,\n  WeakSet,\n} = primordials;\n\n// Because these functions are used by `makeSafe`, which is exposed\n// on the `primordials` object, it's important to use const references\n// to the primordials that they use:\nconst createSafeIterator = (factory, next) => {\n  class SafeIterator {\n    constructor(iterable) {\n      this._iterator = factory(iterable);\n    }\n    next() {\n      return next(this._iterator);\n    }\n    [SymbolIterator]() {\n      return this;\n    }\n  }\n  ObjectSetPrototypeOf(SafeIterator.prototype, null);\n  ObjectFreeze(SafeIterator.prototype);\n  ObjectFreeze(SafeIterator);\n  return SafeIterator;\n};\n\nprimordials.SafeArrayIterator = createSafeIterator(\n  primordials.ArrayPrototypeSymbolIterator,\n  primordials.ArrayIteratorPrototypeNext\n);\nprimordials.SafeStringIterator = createSafeIterator(\n  primordials.StringPrototypeSymbolIterator,\n  primordials.StringIteratorPrototypeNext\n);\n\nconst copyProps = (src, dest) => {\n  ArrayPrototypeForEach(ReflectOwnKeys(src), (key) => {\n    if (!ReflectGetOwnPropertyDescriptor(dest, key)) {\n      ReflectDefineProperty(\n        dest,\n        key,\n        ReflectGetOwnPropertyDescriptor(src, key));\n    }\n  });\n};\n\n/**\n * @type {typeof primordials.makeSafe}\n */\nconst makeSafe = (unsafe, safe) => {\n  if (SymbolIterator in unsafe.prototype) {\n    const dummy = new unsafe();\n    let next; // We can reuse the same `next` method.\n\n    ArrayPrototypeForEach(ReflectOwnKeys(unsafe.prototype), (key) => {\n      if (!ReflectGetOwnPropertyDescriptor(safe.prototype, key)) {\n        const desc = ReflectGetOwnPropertyDescriptor(unsafe.prototype, key);\n        if (\n          typeof desc.value === 'function' &&\n          desc.value.length === 0 &&\n          SymbolIterator in (FunctionPrototypeCall(desc.value, dummy) ?? {})\n        ) {\n          const createIterator = uncurryThis(desc.value);\n          next ??= uncurryThis(createIterator(dummy).next);\n          const SafeIterator = createSafeIterator(createIterator, next);\n          desc.value = function() {\n            return new SafeIterator(this);\n          };\n        }\n        ReflectDefineProperty(safe.prototype, key, desc);\n      }\n    });\n  } else {\n    copyProps(unsafe.prototype, safe.prototype);\n  }\n  copyProps(unsafe, safe);\n\n  ObjectSetPrototypeOf(safe.prototype, null);\n  ObjectFreeze(safe.prototype);\n  ObjectFreeze(safe);\n  return safe;\n};\nprimordials.makeSafe = makeSafe;\n\n// Subclass the constructors because we need to use their prototype\n// methods later.\n// Defining the `constructor` is necessary here to avoid the default\n// constructor which uses the user-mutable `%ArrayIteratorPrototype%.next`.\nprimordials.SafeMap = makeSafe(\n  Map,\n  class SafeMap extends Map {\n    constructor(i) { super(i); } // eslint-disable-line no-useless-constructor\n  }\n);\nprimordials.SafeWeakMap = makeSafe(\n  WeakMap,\n  class SafeWeakMap extends WeakMap {\n    constructor(i) { super(i); } // eslint-disable-line no-useless-constructor\n  }\n);\n\nprimordials.SafeSet = makeSafe(\n  Set,\n  class SafeSet extends Set {\n    constructor(i) { super(i); } // eslint-disable-line no-useless-constructor\n  }\n);\nprimordials.SafeWeakSet = makeSafe(\n  WeakSet,\n  class SafeWeakSet extends WeakSet {\n    constructor(i) { super(i); } // eslint-disable-line no-useless-constructor\n  }\n);\n\nprimordials.SafeFinalizationRegistry = makeSafe(\n  FinalizationRegistry,\n  class SafeFinalizationRegistry extends FinalizationRegistry {\n    // eslint-disable-next-line no-useless-constructor\n    constructor(cleanupCallback) { super(cleanupCallback); }\n  }\n);\nprimordials.SafeWeakRef = makeSafe(\n  WeakRef,\n  class SafeWeakRef extends WeakRef {\n    // eslint-disable-next-line no-useless-constructor\n    constructor(target) { super(target); }\n  }\n);\n\nObjectSetPrototypeOf(primordials, null);\nObjectFreeze(primordials);\n"
