text: // Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
  
  // Based on https://github.com/nodejs/node/blob/889ad35d3d41e376870f785b0c1b669cb732013d/lib/internal/per_context/primordials.js
  // Copyright Joyent, Inc. and other Node contributors.
  //
  // 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.
  // 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
  
  "use strict";
  
  (() => {
    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) => {
      primordials[name] = globalThis[name];
    });
  
    // Create copy of isNaN
    primordials[isNaN.name] = isNaN;
  
    // 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) => {
      copyPropsRenamed(globalThis[name], primordials, name);
    });
  
    // Create copies of intrinsic objects
    [
      "AggregateError",
      "Array",
      "ArrayBuffer",
      "BigInt",
      "BigInt64Array",
      "BigUint64Array",
      "Boolean",
      "DataView",
      "Date",
      "Error",
      "EvalError",
      // TODO(lucacasonato): not present in snapshots. Why?
      // "FinalizationRegistry",
      "Float32Array",
      "Float64Array",
      "Function",
      "Int16Array",
      "Int32Array",
      "Int8Array",
      "Map",
      "Number",
      "Object",
      "RangeError",
      "ReferenceError",
      "RegExp",
      "Set",
      "String",
      "Symbol",
      "SyntaxError",
      "TypeError",
      "URIError",
      "Uint16Array",
      "Uint32Array",
      "Uint8Array",
      "Uint8ClampedArray",
      "WeakMap",
      // TODO(lucacasonato): not present in snapshots. Why?
      // "WeakRef",
      "WeakSet",
    ].forEach((name) => {
      const original = globalThis[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) => {
      const original = globalThis[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`);
    });
  
    const {
      ArrayPrototypeForEach,
      FunctionPrototypeCall,
      Map,
      ObjectFreeze,
      ObjectSetPrototypeOf,
      Promise,
      PromisePrototypeThen,
      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),
          );
        }
      });
    };
  
    /**
   * @type {typeof primordials.makeSafe}
   */
    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 ??= 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);
        }
      },
    );
    primordials.SafeWeakMap = makeSafe(
      WeakMap,
      class SafeWeakMap extends WeakMap {
        constructor(i) {
          super(i);
        }
      },
    );
  
    primordials.SafeSet = makeSafe(
      Set,
      class SafeSet extends Set {
        constructor(i) {
          super(i);
        }
      },
    );
    primordials.SafeWeakSet = makeSafe(
      WeakSet,
      class SafeWeakSet extends WeakSet {
        constructor(i) {
          super(i);
        }
      },
    );
  
    // TODO(lucacasonato): not present in snapshots. Why?
    // primordials.SafeFinalizationRegistry = makeSafe(
    //   FinalizationRegistry,
    //   class SafeFinalizationRegistry extends FinalizationRegistry {
    //     constructor(cleanupCallback) {
    //       super(cleanupCallback);
    //     }
    //   },
    // );
  
    // TODO(lucacasonato): not present in snapshots. Why?
    // primordials.SafeWeakRef = makeSafe(
    //   WeakRef,
    //   class SafeWeakRef extends WeakRef {
    //     constructor(target) {
    //       super(target);
    //     }
    //   },
    // );
  
    const SafePromise = makeSafe(
      Promise,
      class SafePromise extends Promise {
        constructor(executor) {
          super(executor);
        }
      },
    );
  
    primordials.PromisePrototypeCatch = (thisPromise, onRejected) =>
      PromisePrototypeThen(thisPromise, undefined, onRejected);
  
    /**
     * Attaches a callback that is invoked when the Promise is settled (fulfilled or
     * rejected). The resolved value cannot be modified from the callback.
     * Prefer using async functions when possible.
     * @param {Promise<any>} thisPromise
     * @param {() => void) | undefined | null} onFinally The callback to execute
     *        when the Promise is settled (fulfilled or rejected).
     * @returns A Promise for the completion of the callback.
     */
    primordials.SafePromisePrototypeFinally = (thisPromise, onFinally) =>
      // Wrapping on a new Promise is necessary to not expose the SafePromise
      // prototype to user-land.
      new Promise((a, b) =>
        new SafePromise((a, b) => PromisePrototypeThen(thisPromise, a, b))
          .finally(onFinally)
          .then(a, b)
      );
  
    ObjectSetPrototypeOf(primordials, null);
    ObjectFreeze(primordials);
  
    // Provide bootstrap namespace
    globalThis.__bootstrap = { primordials };
  })();
  