"// This file creates the internal module & binding loaders used by built-in\n// modules. In contrast, user land modules are loaded using\n// lib/internal/modules/cjs/loader.js (CommonJS Modules) or\n// lib/internal/modules/esm/* (ES Modules).\n//\n// This file is compiled and run by node.cc before bootstrap/node.js\n// was called, therefore the loaders are bootstrapped before we start to\n// actually bootstrap Node.js. It creates the following objects:\n//\n// C++ binding loaders:\n// - process.binding(): the legacy C++ binding loader, accessible from user land\n//   because it is an object attached to the global process object.\n//   These C++ bindings are created using NODE_BUILTIN_MODULE_CONTEXT_AWARE()\n//   and have their nm_flags set to NM_F_BUILTIN. We do not make any guarantees\n//   about the stability of these bindings, but still have to take care of\n//   compatibility issues caused by them from time to time.\n// - process._linkedBinding(): intended to be used by embedders to add\n//   additional C++ bindings in their applications. These C++ bindings\n//   can be created using NODE_MODULE_CONTEXT_AWARE_CPP() with the flag\n//   NM_F_LINKED.\n// - internalBinding(): the private internal C++ binding loader, inaccessible\n//   from user land unless through `require('internal/test/binding')`.\n//   These C++ bindings are created using NODE_MODULE_CONTEXT_AWARE_INTERNAL()\n//   and have their nm_flags set to NM_F_INTERNAL.\n//\n// Internal JavaScript module loader:\n// - NativeModule: a minimal module system used to load the JavaScript core\n//   modules found in lib/**/*.js and deps/**/*.js. All core modules are\n//   compiled into the node binary via node_javascript.cc generated by js2c.py,\n//   so they can be loaded faster without the cost of I/O. This class makes the\n//   lib/internal/*, deps/internal/* modules and internalBinding() available by\n//   default to core modules, and lets the core modules require itself via\n//   require('internal/bootstrap/loaders') even when this file is not written in\n//   CommonJS style.\n//\n// Other objects:\n// - process.moduleLoadList: an array recording the bindings and the modules\n//   loaded in the process and the order in which they are loaded.\n\n'use strict';\n\n// This file is compiled as if it's wrapped in a function with arguments\n// passed by node::RunBootstrapping()\n/* global process, getLinkedBinding, getInternalBinding, primordials */\n\nconst {\n  ArrayPrototypeMap,\n  ArrayPrototypePush,\n  ArrayPrototypeSlice,\n  Error,\n  ObjectCreate,\n  ObjectDefineProperty,\n  ObjectKeys,\n  ObjectPrototypeHasOwnProperty,\n  ReflectGet,\n  SafeMap,\n  SafeSet,\n  String,\n  StringPrototypeStartsWith,\n  TypeError,\n} = primordials;\n\n// Set up process.moduleLoadList.\nconst moduleLoadList = [];\nObjectDefineProperty(process, 'moduleLoadList', {\n  value: moduleLoadList,\n  configurable: true,\n  enumerable: true,\n  writable: false\n});\n\n\n// internalBindingAllowlist contains the name of internalBinding modules\n// that are allowed for access via process.binding()... This is used\n// to provide a transition path for modules that are being moved over to\n// internalBinding.\nconst internalBindingAllowlist = new SafeSet([\n  'async_wrap',\n  'buffer',\n  'cares_wrap',\n  'config',\n  'constants',\n  'contextify',\n  'crypto',\n  'fs',\n  'fs_event_wrap',\n  'http_parser',\n  'icu',\n  'inspector',\n  'js_stream',\n  'natives',\n  'os',\n  'pipe_wrap',\n  'process_wrap',\n  'signal_wrap',\n  'spawn_sync',\n  'stream_wrap',\n  'tcp_wrap',\n  'tls_wrap',\n  'tty_wrap',\n  'udp_wrap',\n  'url',\n  'util',\n  'uv',\n  'v8',\n  'zlib',\n]);\n\nconst runtimeDeprecatedList = new SafeSet([\n  'async_wrap',\n  'crypto',\n  'http_parser',\n  'signal_wrap',\n  'url',\n  'v8',\n]);\n\nconst legacyWrapperList = new SafeSet([\n  'util',\n]);\n\n// Set up process.binding() and process._linkedBinding().\n{\n  const bindingObj = ObjectCreate(null);\n\n  process.binding = function binding(module) {\n    module = String(module);\n    // Deprecated specific process.binding() modules, but not all, allow\n    // selective fallback to internalBinding for the deprecated ones.\n    if (internalBindingAllowlist.has(module)) {\n      if (runtimeDeprecatedList.has(module)) {\n        runtimeDeprecatedList.delete(module);\n        process.emitWarning(\n          `Access to process.binding('${module}') is deprecated.`,\n          'DeprecationWarning',\n          'DEP0111');\n      }\n      if (legacyWrapperList.has(module)) {\n        return nativeModuleRequire('internal/legacy/processbinding')[module]();\n      }\n      return internalBinding(module);\n    }\n    // eslint-disable-next-line no-restricted-syntax\n    throw new Error(`No such module: ${module}`);\n  };\n\n  process._linkedBinding = function _linkedBinding(module) {\n    module = String(module);\n    let mod = bindingObj[module];\n    if (typeof mod !== 'object')\n      mod = bindingObj[module] = getLinkedBinding(module);\n    return mod;\n  };\n}\n\n// Set up internalBinding() in the closure.\n/**\n * @type {InternalBinding}\n */\nlet internalBinding;\n{\n  const bindingObj = ObjectCreate(null);\n  // eslint-disable-next-line no-global-assign\n  internalBinding = function internalBinding(module) {\n    let mod = bindingObj[module];\n    if (typeof mod !== 'object') {\n      mod = bindingObj[module] = getInternalBinding(module);\n      ArrayPrototypePush(moduleLoadList, `Internal Binding ${module}`);\n    }\n    return mod;\n  };\n}\n\nconst loaderId = 'internal/bootstrap/loaders';\nconst {\n  moduleIds,\n  compileFunction\n} = internalBinding('native_module');\n\nconst getOwn = (target, property, receiver) => {\n  return ObjectPrototypeHasOwnProperty(target, property) ?\n    ReflectGet(target, property, receiver) :\n    undefined;\n};\n\n/**\n * An internal abstraction for the built-in JavaScript modules of Node.js.\n * Be careful not to expose this to user land unless --expose-internals is\n * used, in which case there is no compatibility guarantee about this class.\n */\nclass NativeModule {\n  /**\n   * A map from the module IDs to the module instances.\n   * @type {Map<string, NativeModule>}\n  */\n  static map = new SafeMap(\n    ArrayPrototypeMap(moduleIds, (id) => [id, new NativeModule(id)])\n  );\n\n  constructor(id) {\n    this.filename = `${id}.js`;\n    this.id = id;\n    this.canBeRequiredByUsers = !StringPrototypeStartsWith(id, 'internal/');\n\n    // The CJS exports object of the module.\n    this.exports = {};\n    // States used to work around circular dependencies.\n    this.loaded = false;\n    this.loading = false;\n\n    // The following properties are used by the ESM implementation and only\n    // initialized when the native module is loaded by users.\n    /**\n     * The C++ ModuleWrap binding used to interface with the ESM implementation.\n     * @type {ModuleWrap|undefined}\n     */\n    this.module = undefined;\n    /**\n     * Exported names for the ESM imports.\n     * @type {string[]|undefined}\n     */\n    this.exportKeys = undefined;\n  }\n\n  // To be called during pre-execution when --expose-internals is on.\n  // Enables the user-land module loader to access internal modules.\n  static exposeInternals() {\n    for (const { 0: id, 1: mod } of NativeModule.map) {\n      // Do not expose this to user land even with --expose-internals.\n      if (id !== loaderId) {\n        mod.canBeRequiredByUsers = true;\n      }\n    }\n  }\n\n  static exists(id) {\n    return NativeModule.map.has(id);\n  }\n\n  static canBeRequiredByUsers(id) {\n    const mod = NativeModule.map.get(id);\n    return mod && mod.canBeRequiredByUsers;\n  }\n\n  // Used by user-land module loaders to compile and load builtins.\n  compileForPublicLoader() {\n    if (!this.canBeRequiredByUsers) {\n      // No code because this is an assertion against bugs\n      // eslint-disable-next-line no-restricted-syntax\n      throw new Error(`Should not compile ${this.id} for public use`);\n    }\n    this.compileForInternalLoader();\n    if (!this.exportKeys) {\n      // When using --expose-internals, we do not want to reflect the named\n      // exports from core modules as this can trigger unnecessary getters.\n      const internal = StringPrototypeStartsWith(this.id, 'internal/');\n      this.exportKeys = internal ? [] : ObjectKeys(this.exports);\n    }\n    this.getESMFacade();\n    this.syncExports();\n    return this.exports;\n  }\n\n  getESMFacade() {\n    if (this.module) return this.module;\n    const { ModuleWrap } = internalBinding('module_wrap');\n    const url = `node:${this.id}`;\n    const nativeModule = this;\n    const exportsKeys = ArrayPrototypeSlice(this.exportKeys);\n    ArrayPrototypePush(exportsKeys, 'default');\n    this.module = new ModuleWrap(\n      url, undefined, exportsKeys,\n      function() {\n        nativeModule.syncExports();\n        this.setExport('default', nativeModule.exports);\n      });\n    // Ensure immediate sync execution to capture exports now\n    this.module.instantiate();\n    this.module.evaluate(-1, false);\n    return this.module;\n  }\n\n  // Provide named exports for all builtin libraries so that the libraries\n  // may be imported in a nicer way for ESM users. The default export is left\n  // as the entire namespace (module.exports) and updates when this function is\n  // called so that APMs and other behavior are supported.\n  syncExports() {\n    const names = this.exportKeys;\n    if (this.module) {\n      for (let i = 0; i < names.length; i++) {\n        const exportName = names[i];\n        if (exportName === 'default') continue;\n        this.module.setExport(exportName,\n                              getOwn(this.exports, exportName, this.exports));\n      }\n    }\n  }\n\n  compileForInternalLoader() {\n    if (this.loaded || this.loading) {\n      return this.exports;\n    }\n\n    const id = this.id;\n    this.loading = true;\n\n    try {\n      const requireFn = StringPrototypeStartsWith(this.id, 'internal/deps/') ?\n        requireWithFallbackInDeps : nativeModuleRequire;\n\n      const fn = compileFunction(id);\n      fn(this.exports, requireFn, this, process, internalBinding, primordials);\n\n      this.loaded = true;\n    } finally {\n      this.loading = false;\n    }\n\n    ArrayPrototypePush(moduleLoadList, `NativeModule ${id}`);\n    return this.exports;\n  }\n}\n\n// Think of this as module.exports in this file even though it is not\n// written in CommonJS style.\nconst loaderExports = {\n  internalBinding,\n  NativeModule,\n  require: nativeModuleRequire\n};\n\nfunction nativeModuleRequire(id) {\n  if (id === loaderId) {\n    return loaderExports;\n  }\n\n  const mod = NativeModule.map.get(id);\n  // Can't load the internal errors module from here, have to use a raw error.\n  // eslint-disable-next-line no-restricted-syntax\n  if (!mod) throw new TypeError(`Missing internal module '${id}'`);\n  return mod.compileForInternalLoader();\n}\n\n// Allow internal modules from dependencies to require\n// other modules from dependencies by providing fallbacks.\nfunction requireWithFallbackInDeps(request) {\n  if (!NativeModule.map.has(request)) {\n    request = `internal/deps/${request}`;\n  }\n  return nativeModuleRequire(request);\n}\n\n// Pass the exports back to C++ land for C++ internals to use.\nreturn loaderExports;\n"
