text: // Hello, and welcome to hacking node.js!
  //
  // This file is invoked by node::LoadEnvironment in src/node.cc, and is
  // responsible for bootstrapping the node.js core. As special caution is given
  // to the performance of the startup process, many dependencies are invoked
  // lazily.
  
  'use strict';
  
  (function(process) {
  
    function startup() {
      const EventEmitter = NativeModule.require('events');
      process._eventsCount = 0;
  
      const origProcProto = Object.getPrototypeOf(process);
      Object.setPrototypeOf(process, Object.create(EventEmitter.prototype, {
        constructor: Object.getOwnPropertyDescriptor(origProcProto, 'constructor')
      }));
  
      EventEmitter.call(process);
  
      setupProcessObject();
  
      // do this good and early, since it handles errors.
      setupProcessFatal();
  
      setupProcessICUVersions();
  
      setupGlobalVariables();
      if (!process._noBrowserGlobals) {
        setupGlobalTimeouts();
        setupGlobalConsole();
      }
  
      const _process = NativeModule.require('internal/process');
  
      _process.setup_hrtime();
      _process.setup_cpuUsage();
      _process.setupMemoryUsage();
      _process.setupConfig(NativeModule._source);
      NativeModule.require('internal/process/warning').setup();
      NativeModule.require('internal/process/next_tick').setup();
      NativeModule.require('internal/process/stdio').setup();
      _process.setupKillAndExit();
      _process.setupSignalHandlers();
      if (global.__coverage__)
        NativeModule.require('internal/process/write-coverage').setup();
  
      // Do not initialize channel in debugger agent, it deletes env variable
      // and the main thread won't see it.
      if (process.argv[1] !== '--debug-agent')
        _process.setupChannel();
  
      _process.setupRawDebug();
  
      // Ensure setURLConstructor() is called before the native
      // URL::ToObject() method is used.
      NativeModule.require('internal/url');
  
      Object.defineProperty(process, 'argv0', {
        enumerable: true,
        configurable: false,
        value: process.argv[0]
      });
      process.argv[0] = process.execPath;
  
      // Handle `--debug*` deprecation and invalidation
      if (process._invalidDebug) {
        process.emitWarning(
          '`node --debug` and `node --debug-brk` are invalid. ' +
          'Please use `node --inspect` or `node --inspect-brk` instead.',
          'DeprecationWarning', 'DEP0062', startup, true);
        process.exit(9);
      } else if (process._deprecatedDebugBrk) {
        process.emitWarning(
          '`node --inspect --debug-brk` is deprecated. ' +
          'Please use `node --inspect-brk` instead.',
          'DeprecationWarning', 'DEP0062', startup, true);
      }
  
      // There are various modes that Node can run in. The most common two
      // are running from a script and running the REPL - but there are a few
      // others like the debugger or running --eval arguments. Here we decide
      // which mode we run in.
  
      if (NativeModule.exists('_third_party_main')) {
        // To allow people to extend Node in different ways, this hook allows
        // one to drop a file lib/_third_party_main.js into the build
        // directory which will be executed instead of Node's normal loading.
        process.nextTick(function() {
          NativeModule.require('_third_party_main');
        });
  
      } else if (process.argv[1] === 'inspect' || process.argv[1] === 'debug') {
        if (process.argv[1] === 'debug') {
          process.emitWarning(
            '`node debug` is deprecated. Please use `node inspect` instead.',
            'DeprecationWarning', 'DEP0068');
        }
  
        // Start the debugger agent
        process.nextTick(function() {
          NativeModule.require('node-inspect/lib/_inspect').start();
        });
  
      } else if (process.argv[1] === '--remote_debugging_server') {
        // Start the debugging server
        NativeModule.require('internal/inspector/remote_debugging_server');
  
      } else if (process.argv[1] === '--debug-agent') {
        // Start the debugger agent
        NativeModule.require('_debug_agent').start();
  
      } else if (process.profProcess) {
        NativeModule.require('internal/v8_prof_processor');
  
      } else {
        // There is user code to be run
  
        // If this is a worker in cluster mode, start up the communication
        // channel. This needs to be done before any user code gets executed
        // (including preload modules).
        if (process.argv[1] && process.env.NODE_UNIQUE_ID) {
          const cluster = NativeModule.require('cluster');
          cluster._setupWorker();
  
          // Make sure it's not accidentally inherited by child processes.
          delete process.env.NODE_UNIQUE_ID;
        }
  
        if (process._eval != null && !process._forceRepl) {
          // User passed '-e' or '--eval' arguments to Node without '-i' or
          // '--interactive'
          preloadModules();
  
          const internalModule = NativeModule.require('internal/module');
          internalModule.addBuiltinLibsToObject(global);
          evalScript('[eval]');
        } else if (process.argv[1] && process.argv[1] !== '-') {
          // make process.argv[1] into a full path
          const path = NativeModule.require('path');
          process.argv[1] = path.resolve(process.argv[1]);
  
          const Module = NativeModule.require('module');
  
          // check if user passed `-c` or `--check` arguments to Node.
          if (process._syntax_check_only != null) {
            const fs = NativeModule.require('fs');
            // read the source
            const filename = Module._resolveFilename(process.argv[1]);
            var source = fs.readFileSync(filename, 'utf-8');
            checkScriptSyntax(source, filename);
            process.exit(0);
          }
  
          preloadModules();
          Module.runMain();
        } else {
          preloadModules();
          // If -i or --interactive were passed, or stdin is a TTY.
          if (process._forceRepl || NativeModule.require('tty').isatty(0)) {
            // REPL
            const cliRepl = NativeModule.require('internal/repl');
            cliRepl.createInternalRepl(process.env, function(err, repl) {
              if (err) {
                throw err;
              }
              repl.on('exit', function() {
                if (repl._flushing) {
                  repl.pause();
                  return repl.once('flushHistory', function() {
                    process.exit();
                  });
                }
                process.exit();
              });
            });
  
            if (process._eval != null) {
              // User passed '-e' or '--eval'
              evalScript('[eval]');
            }
          } else {
            // Read all of stdin - execute it.
            process.stdin.setEncoding('utf8');
  
            var code = '';
            process.stdin.on('data', function(d) {
              code += d;
            });
  
            process.stdin.on('end', function() {
              if (process._syntax_check_only != null) {
                checkScriptSyntax(code, '[stdin]');
              } else {
                process._eval = code;
                evalScript('[stdin]');
              }
            });
          }
        }
      }
    }
  
    function setupProcessObject() {
      process._setupProcessObject(pushValueToArray);
  
      function pushValueToArray() {
        for (var i = 0; i < arguments.length; i++)
          this.push(arguments[i]);
      }
    }
  
    function setupGlobalVariables() {
      Object.defineProperty(global, Symbol.toStringTag, {
        value: 'global',
        writable: false,
        enumerable: false,
        configurable: true
      });
      global.process = process;
      const util = NativeModule.require('util');
  
      function makeGetter(name) {
        return util.deprecate(function() {
          return this;
        }, `'${name}' is deprecated, use 'global'`, 'DEP0016');
      }
  
      function makeSetter(name) {
        return util.deprecate(function(value) {
          Object.defineProperty(this, name, {
            configurable: true,
            writable: true,
            enumerable: true,
            value: value
          });
        }, `'${name}' is deprecated, use 'global'`, 'DEP0016');
      }
  
      Object.defineProperties(global, {
        GLOBAL: {
          configurable: true,
          get: makeGetter('GLOBAL'),
          set: makeSetter('GLOBAL')
        },
        root: {
          configurable: true,
          get: makeGetter('root'),
          set: makeSetter('root')
        }
      });
  
      global.Buffer = NativeModule.require('buffer').Buffer;
      process.domain = null;
      process._exiting = false;
    }
  
    function setupGlobalTimeouts() {
      const timers = NativeModule.require('timers');
      global.clearImmediate = timers.clearImmediate;
      global.clearInterval = timers.clearInterval;
      global.clearTimeout = timers.clearTimeout;
      global.setImmediate = timers.setImmediate;
      global.setInterval = timers.setInterval;
      global.setTimeout = timers.setTimeout;
    }
  
    function setupGlobalConsole() {
      const originalConsole = global.console;
      let console;
      Object.defineProperty(global, 'console', {
        configurable: true,
        enumerable: true,
        get: function() {
          if (!console) {
            console = originalConsole === undefined ?
                NativeModule.require('console') :
                installInspectorConsole(originalConsole);
          }
          return console;
        }
      });
    }
  
    function installInspectorConsole(globalConsole) {
      const wrappedConsole = NativeModule.require('console');
      const inspector = process.binding('inspector');
      const config = {};
      for (const key of Object.keys(wrappedConsole)) {
        if (!globalConsole.hasOwnProperty(key))
          continue;
        // If global console has the same method as inspector console,
        // then wrap these two methods into one. Native wrapper will preserve
        // the original stack.
        wrappedConsole[key] = inspector.consoleCall.bind(wrappedConsole,
                                                         globalConsole[key],
                                                         wrappedConsole[key],
                                                         config);
      }
      for (const key of Object.keys(globalConsole)) {
        if (wrappedConsole.hasOwnProperty(key))
          continue;
        wrappedConsole[key] = globalConsole[key];
      }
      return wrappedConsole;
    }
  
    function setupProcessFatal() {
      const async_wrap = process.binding('async_wrap');
      // Arrays containing hook flags and ids for async_hook calls.
      const { async_hook_fields, async_uid_fields } = async_wrap;
      // Internal functions needed to manipulate the stack.
      const { clearIdStack, popAsyncIds } = async_wrap;
      const { kAfter, kCurrentAsyncId, kInitTriggerId } = async_wrap.constants;
  
      process._fatalException = function(er) {
        var caught;
  
        // It's possible that kInitTriggerId was set for a constructor call that
        // threw and was never cleared. So clear it now.
        async_uid_fields[kInitTriggerId] = 0;
  
        if (process.domain && process.domain._errorHandler)
          caught = process.domain._errorHandler(er);
  
        if (!caught)
          caught = process.emit('uncaughtException', er);
  
        // If someone handled it, then great.  otherwise, die in C++ land
        // since that means that we'll exit the process, emit the 'exit' event
        if (!caught) {
          try {
            if (!process._exiting) {
              process._exiting = true;
              process.emit('exit', 1);
            }
          } catch (er) {
            // nothing to be done about it at this point.
          }
  
        } else {
          // If we handled an error, then make sure any ticks get processed
          NativeModule.require('timers').setImmediate(process._tickCallback);
  
          // Emit the after() hooks now that the exception has been handled.
          if (async_hook_fields[kAfter] > 0) {
            do {
              NativeModule.require('async_hooks').emitAfter(
                  async_uid_fields[kCurrentAsyncId]);
            // popAsyncIds() returns true if there are more ids on the stack.
            } while (popAsyncIds(async_uid_fields[kCurrentAsyncId]));
          // Or completely empty the id stack.
          } else {
            clearIdStack();
          }
        }
  
        return caught;
      };
    }
  
    function setupProcessICUVersions() {
      const icu = process.binding('config').hasIntl ?
        process.binding('icu') : undefined;
      if (!icu) return;  // no Intl/ICU: nothing to add here.
      // With no argument, getVersion() returns a comma separated list
      // of possible types.
      const versionTypes = icu.getVersion().split(',');
  
      function makeGetter(name) {
        return () => {
          // With an argument, getVersion(type) returns
          // the actual version string.
          const version = icu.getVersion(name);
          // Replace the current getter with a new property.
          delete process.versions[name];
          Object.defineProperty(process.versions, name, {
            value: version,
            writable: false,
            enumerable: true
          });
          return version;
        };
      }
  
      for (var n = 0; n < versionTypes.length; n++) {
        var name = versionTypes[n];
        Object.defineProperty(process.versions, name, {
          configurable: true,
          enumerable: true,
          get: makeGetter(name)
        });
      }
    }
  
    function tryGetCwd(path) {
      var threw = true;
      var cwd;
      try {
        cwd = process.cwd();
        threw = false;
      } finally {
        if (threw) {
          // getcwd(3) can fail if the current working directory has been deleted.
          // Fall back to the directory name of the (absolute) executable path.
          // It's not really correct but what are the alternatives?
          return path.dirname(process.execPath);
        }
      }
      return cwd;
    }
  
    function evalScript(name) {
      const Module = NativeModule.require('module');
      const path = NativeModule.require('path');
      const cwd = tryGetCwd(path);
  
      const module = new Module(name);
      module.filename = path.join(cwd, name);
      module.paths = Module._nodeModulePaths(cwd);
      const body = process._eval;
      const script = `global.__filename = ${JSON.stringify(name)};\n` +
                     'global.exports = exports;\n' +
                     'global.module = module;\n' +
                     'global.__dirname = __dirname;\n' +
                     'global.require = require;\n' +
                     'return require("vm").runInThisContext(' +
                     `${JSON.stringify(body)}, { filename: ` +
                     `${JSON.stringify(name)}, displayErrors: true });\n`;
      const result = module._compile(script, `${name}-wrapper`);
      if (process._print_eval) console.log(result);
      // Handle any nextTicks added in the first tick of the program.
      process._tickCallback();
    }
  
    // Load preload modules
    function preloadModules() {
      if (process._preload_modules) {
        NativeModule.require('module')._preloadModules(process._preload_modules);
      }
    }
  
    function checkScriptSyntax(source, filename) {
      const Module = NativeModule.require('module');
      const vm = NativeModule.require('vm');
      const internalModule = NativeModule.require('internal/module');
  
      // remove Shebang
      source = internalModule.stripShebang(source);
      // remove BOM
      source = internalModule.stripBOM(source);
      // wrap it
      source = Module.wrap(source);
      // compile the script, this will throw if it fails
      new vm.Script(source, {displayErrors: true, filename});
    }
  
    // Below you find a minimal module system, which is used to load the node
    // core modules found in lib/*.js. All core modules are compiled into the
    // node binary, so they can be loaded faster.
  
    const ContextifyScript = process.binding('contextify').ContextifyScript;
    function runInThisContext(code, options) {
      const script = new ContextifyScript(code, options);
      return script.runInThisContext();
    }
  
    function NativeModule(id) {
      this.filename = `${id}.js`;
      this.id = id;
      this.exports = {};
      this.loaded = false;
      this.loading = false;
    }
  
    NativeModule._source = process.binding('natives');
    NativeModule._cache = {};
  
    NativeModule.require = function(id) {
      if (id === 'native_module') {
        return NativeModule;
      }
  
      const cached = NativeModule.getCached(id);
      if (cached && (cached.loaded || cached.loading)) {
        return cached.exports;
      }
  
      if (!NativeModule.exists(id)) {
        // Model the error off the internal/errors.js model, but
        // do not use that module given that it could actually be
        // the one causing the error if there's a bug in Node.js
        const err = new Error(`No such built-in module: ${id}`);
        err.code = 'ERR_UNKNOWN_BUILTIN_MODULE';
        err.name = 'Error [ERR_UNKNOWN_BUILTIN_MODULE]';
        throw err;
      }
  
      process.moduleLoadList.push(`NativeModule ${id}`);
  
      const nativeModule = new NativeModule(id);
  
      nativeModule.cache();
      nativeModule.compile();
  
      return nativeModule.exports;
    };
  
    NativeModule.getCached = function(id) {
      return NativeModule._cache[id];
    };
  
    NativeModule.exists = function(id) {
      return NativeModule._source.hasOwnProperty(id);
    };
  
    const config = process.binding('config');
  
    if (config.exposeInternals) {
      NativeModule.nonInternalExists = NativeModule.exists;
  
      NativeModule.isInternal = function(id) {
        return false;
      };
    } else {
      NativeModule.nonInternalExists = function(id) {
        return NativeModule.exists(id) && !NativeModule.isInternal(id);
      };
  
      NativeModule.isInternal = function(id) {
        return id.startsWith('internal/');
      };
    }
  
  
    NativeModule.getSource = function(id) {
      return NativeModule._source[id];
    };
  
    NativeModule.wrap = function(script) {
      return NativeModule.wrapper[0] + script + NativeModule.wrapper[1];
    };
  
    NativeModule.wrapper = [
      '(function (exports, require, module, __filename, __dirname) { ',
      '\n});'
    ];
  
    NativeModule.prototype.compile = function() {
      var source = NativeModule.getSource(this.id);
      source = NativeModule.wrap(source);
  
      this.loading = true;
  
      try {
        const fn = runInThisContext(source, {
          filename: this.filename,
          lineOffset: 0,
          displayErrors: true
        });
        fn(this.exports, NativeModule.require, this, this.filename);
  
        this.loaded = true;
      } finally {
        this.loading = false;
      }
    };
  
    NativeModule.prototype.cache = function() {
      NativeModule._cache[this.id] = this;
    };
  
    startup();
  });
  