/*!
 * /**
 *  * Copyright (c) Meta Platforms, Inc. and affiliates.
 *  *
 *  * This source code is licensed under the MIT license found in the
 *  * LICENSE file in the root directory of this source tree.
 *  * /
 */
/******/ (() => { // webpackBootstrap
/******/ 	"use strict";
var __webpack_exports__ = {};
// This entry needs to be wrapped in an IIFE because it uses a non-standard name for the exports (exports).
(() => {
var exports = __webpack_exports__;


Object.defineProperty(exports, "__esModule", ({
  value: true
}));
exports["default"] = exports.TestEnvironment = void 0;
function _vm() {
  const data = require("vm");
  _vm = function () {
    return data;
  };
  return data;
}
function _fakeTimers() {
  const data = require("@jest/fake-timers");
  _fakeTimers = function () {
    return data;
  };
  return data;
}
function _jestMock() {
  const data = require("jest-mock");
  _jestMock = function () {
    return data;
  };
  return data;
}
function _jestUtil() {
  const data = require("jest-util");
  _jestUtil = function () {
    return data;
  };
  return data;
}
function _jestValidate() {
  const data = require("jest-validate");
  _jestValidate = function () {
    return data;
  };
  return data;
}
/**
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

// some globals we do not want, either because deprecated or we set it ourselves
const denyList = new Set(['GLOBAL', 'root', 'global', 'globalThis', 'Buffer', 'ArrayBuffer', 'Uint8Array',
// if env is loaded within a jest test
'jest-symbol-do-not-touch']);
const nodeGlobals = new Map(Object.getOwnPropertyNames(globalThis).filter(global => !denyList.has(global)).map(nodeGlobalsKey => {
  const descriptor = Object.getOwnPropertyDescriptor(globalThis, nodeGlobalsKey);
  if (!descriptor) {
    throw new Error(`No property descriptor for ${nodeGlobalsKey}, this is a bug in Jest.`);
  }
  return [nodeGlobalsKey, descriptor];
}));
function isString(value) {
  return typeof value === 'string';
}
const timerIdToRef = id => ({
  id,
  ref() {
    return this;
  },
  unref() {
    return this;
  }
});
const timerRefToId = timer => timer?.id;
class NodeEnvironment {
  context;
  fakeTimers;
  fakeTimersModern;
  global;
  moduleMocker;
  customExportConditions = ['node', 'node-addons'];
  _configuredExportConditions;
  _globalProxy;

  // while `context` is unused, it should always be passed
  constructor(config, _context) {
    const {
      projectConfig
    } = config;
    const globalsCleanupMode = readGlobalsCleanupConfig(projectConfig);
    (0, _jestUtil().initializeGarbageCollectionUtils)(globalThis, globalsCleanupMode);
    this._globalProxy = new GlobalProxy();
    this.context = (0, _vm().createContext)(this._globalProxy.proxy());
    const global = (0, _vm().runInContext)('this', Object.assign(this.context, projectConfig.testEnvironmentOptions));
    this.global = global;
    const contextGlobals = new Set(Object.getOwnPropertyNames(global));
    for (const [nodeGlobalsKey, descriptor] of nodeGlobals) {
      (0, _jestUtil().protectProperties)(globalThis[nodeGlobalsKey]);
      if (!contextGlobals.has(nodeGlobalsKey)) {
        if (descriptor.configurable) {
          Object.defineProperty(global, nodeGlobalsKey, {
            configurable: true,
            enumerable: descriptor.enumerable,
            get() {
              const value = globalThis[nodeGlobalsKey];

              // override lazy getter
              Object.defineProperty(global, nodeGlobalsKey, {
                configurable: true,
                enumerable: descriptor.enumerable,
                value,
                writable: true
              });
              return value;
            },
            set(value) {
              // override lazy getter
              Object.defineProperty(global, nodeGlobalsKey, {
                configurable: true,
                enumerable: descriptor.enumerable,
                value,
                writable: true
              });
            }
          });
        } else if ('value' in descriptor) {
          Object.defineProperty(global, nodeGlobalsKey, {
            configurable: false,
            enumerable: descriptor.enumerable,
            value: descriptor.value,
            writable: descriptor.writable
          });
        } else {
          Object.defineProperty(global, nodeGlobalsKey, {
            configurable: false,
            enumerable: descriptor.enumerable,
            get: descriptor.get,
            set: descriptor.set
          });
        }
      }
    }
    global.global = global;
    global.Buffer = Buffer;
    global.ArrayBuffer = ArrayBuffer;
    // TextEncoder (global or via 'util') references a Uint8Array constructor
    // different than the global one used by users in tests. This makes sure the
    // same constructor is referenced by both.
    global.Uint8Array = Uint8Array;
    (0, _jestUtil().installCommonGlobals)(global, projectConfig.globals, globalsCleanupMode);
    if ('asyncDispose' in Symbol && !('asyncDispose' in global.Symbol)) {
      const globalSymbol = global.Symbol;
      // @ts-expect-error - it's readonly - but we have checked above that it's not there
      globalSymbol.asyncDispose = globalSymbol.for('nodejs.asyncDispose');
      // @ts-expect-error - it's readonly - but we have checked above that it's not there
      globalSymbol.dispose = globalSymbol.for('nodejs.dispose');
    }

    // Node's error-message stack size is limited at 10, but it's pretty useful
    // to see more than that when a test fails.
    global.Error.stackTraceLimit = 100;
    if ('customExportConditions' in projectConfig.testEnvironmentOptions) {
      const {
        customExportConditions
      } = projectConfig.testEnvironmentOptions;
      if (Array.isArray(customExportConditions) && customExportConditions.every(isString)) {
        this._configuredExportConditions = customExportConditions;
      } else {
        throw new Error('Custom export conditions specified but they are not an array of strings');
      }
    }
    this.moduleMocker = new (_jestMock().ModuleMocker)(global);
    this.fakeTimers = new (_fakeTimers().LegacyFakeTimers)({
      config: projectConfig,
      global,
      moduleMocker: this.moduleMocker,
      timerConfig: {
        idToRef: timerIdToRef,
        refToId: timerRefToId
      }
    });
    this.fakeTimersModern = new (_fakeTimers().ModernFakeTimers)({
      config: projectConfig,
      global
    });
    this._globalProxy.envSetupCompleted();
  }

  // eslint-disable-next-line @typescript-eslint/no-empty-function
  async setup() {}
  async teardown() {
    if (this.fakeTimers) {
      this.fakeTimers.dispose();
    }
    if (this.fakeTimersModern) {
      this.fakeTimersModern.dispose();
    }
    this.context = null;
    this.fakeTimers = null;
    this.fakeTimersModern = null;
    this._globalProxy.clear();
  }
  exportConditions() {
    return this._configuredExportConditions ?? this.customExportConditions;
  }
  getVmContext() {
    return this.context;
  }
}
exports["default"] = NodeEnvironment;
const TestEnvironment = exports.TestEnvironment = NodeEnvironment;

/**
 * Creates a new empty global object and wraps it with a {@link Proxy}.
 *
 * The purpose is to register any property set on the global object,
 * and {@link #deleteProperties} on them at environment teardown,
 * to clean up memory and prevent leaks.
 */
class GlobalProxy {
  global = Object.create(Object.getPrototypeOf(globalThis));
  globalProxy = new Proxy(this.global, this);
  isEnvSetup = false;
  propertyToValue = new Map();
  leftovers = [];
  constructor() {
    this.register = this.register.bind(this);
  }
  proxy() {
    return this.globalProxy;
  }

  /**
   * Marks that the environment setup has completed, and properties set on
   * the global object from now on should be deleted at teardown.
   */
  envSetupCompleted() {
    this.isEnvSetup = true;
  }

  /**
   * Deletes any property that was set on the global object, except for:
   * 1. Properties that were set before {@link #envSetupCompleted} was invoked.
   * 2. Properties protected by {@link #protectProperties}.
   */
  clear() {
    for (const {
      value
    } of [...[...this.propertyToValue.entries()].map(([property, value]) => ({
      property,
      value
    })), ...this.leftovers]) {
      (0, _jestUtil().deleteProperties)(value);
    }
    this.propertyToValue.clear();
    this.leftovers = [];
    this.global = {};
    this.globalProxy = {};
  }
  defineProperty(target, property, attributes) {
    const newAttributes = {
      ...attributes
    };
    if ('set' in newAttributes && newAttributes.set !== undefined) {
      const originalSet = newAttributes.set;
      const register = this.register;
      newAttributes.set = value => {
        originalSet(value);
        const newValue = Reflect.get(target, property);
        register(property, newValue);
      };
    }
    const result = Reflect.defineProperty(target, property, newAttributes);
    if ('value' in newAttributes) {
      this.register(property, newAttributes.value);
    }
    return result;
  }
  deleteProperty(target, property) {
    const result = Reflect.deleteProperty(target, property);
    const value = this.propertyToValue.get(property);
    if (value) {
      this.leftovers.push({
        property,
        value
      });
      this.propertyToValue.delete(property);
    }
    return result;
  }
  register(property, value) {
    const currentValue = this.propertyToValue.get(property);
    if (value !== currentValue) {
      if (!this.isEnvSetup && (0, _jestUtil().canDeleteProperties)(value)) {
        (0, _jestUtil().protectProperties)(value);
      }
      if (currentValue) {
        this.leftovers.push({
          property,
          value: currentValue
        });
      }
      this.propertyToValue.set(property, value);
    }
  }
}
function readGlobalsCleanupConfig(projectConfig) {
  const rawConfig = projectConfig.testEnvironmentOptions.globalsCleanup;
  const config = rawConfig?.toString()?.toLowerCase();
  switch (config) {
    case 'off':
    case 'on':
    case 'soft':
      return config;
    default:
      {
        if (config !== undefined) {
          (0, _jestValidate().logValidationWarning)('testEnvironmentOptions.globalsCleanup', `Unknown value given: ${rawConfig}`, 'Available options are: [on, soft, off]');
        }
        return 'soft';
      }
  }
}
})();

module.exports = __webpack_exports__;
/******/ })()
;