nodejs/node
Execution begins in `src/node_main.cc` (`main`/`wmain`) which calls `node::Start`, which after SEA argv fixup loads the V8 startup snapshot and runs a `NodeMainInstance`. C++ then picks exactly one main script from `lib/internal/main/` via a linear dispatch in `src/node.cc`; that script calls into `lib/internal/process/pre_execution.js` to configure the realm before user code. The JS layer talks to C++ only through `internalBinding()`, whose registry is the `NODE_BUILTIN_*_BINDINGS` macro list in `src/node_binding.h`. Build is GYP/Make (`configure.py` → `node.gyp` → `Makefile`) with a secondary GN path, plus Cargo for `deps/crates`. There is no deployment target in the usual sense: the artifact is the `node` binary, optionally repackaged as a single executable application by `src/node_sea.cc`.
- The process entrypoint is `main()` (POSIX) / `wmain()` (Windows, which UTF-8-converts wide argv and refuses pre-Windows-10 unless `NODE_SKIP_PLATFORM_CHECK=1`), both delegating to `node::Start`.
- `node::Start` first runs `sea::FixupArgsForSEA` so a single-executable build can rewrite its own argv, then calls `StartInternal`, which branches to `sea::BuildSingleExecutable`/`WriteSingleExecutableBlob` or `GenerateAndWriteSnapshotData` before falling through to `LoadSnapshotData` + `NodeMainInstance::Run`.
- C++ selects the JS main script by an ordered if-chain in `src/node.cc`: worker_thread → inspect → print_help → prof_process → eval_string → check_syntax → bench_runner → test_runner → watch_mode → run_main_module → repl → eval_stdin. Adding a new run mode means adding a branch here plus a file in `lib/internal/main/`.
- The JS↔C++ boundary is the `internalBinding()` registry declared by macro lists in `src/node_binding.h`; optional subsystems are compiled in conditionally — `quic` behind `HAVE_OPENSSL && OPENSSL_NO_QUIC != 1`, `dtls` behind `HAVE_OPENSSL && HAVE_DTLS`, `sqlite`/`webstorage` behind `HAVE_SQLITE`, `ffi` behind `HAVE_FFI`.
- `lib/internal/bootstrap/node.js` is executed by `Realm::BootstrapRealm()` and is normally *not* run at startup — its resulting V8 heap is captured into the build-time snapshot by `SnapshotBuilder::Generate()`; `--no-node-snapshot` forces real execution. It must stay synchronous and must not read argv or env at top level.
- `prepareExecution()` in `pre_execution.js` is the single funnel every main script passes through; it patches the process object, runs ~25 `setupX()` initializers, calls `initializePermission()`, initializes the module loaders, and mounts the VFS before returning the resolved main entry.
- The storage layer is threefold: the real file system via the `fs`/`fs_dir`/`glob` bindings, SQLite via `src/node_sqlite.cc` (which now exposes virtual tables through a `VirtualTableModule` wrapping `sqlite3_module`), and Web Storage via the `webstorage` binding gated on `--experimental-webstorage`.
- External native dependencies are vendored under `deps/` (v8, uv, openssl, ada, llhttp, nghttp2, ngtcp2, simdjson, sqlite, undici, zlib, zstd, libffi, LIEF, perfetto, postject) rather than fetched, so builds are hermetic.
- `deps/crates` is a Rust staticlib (`crate-type = ["staticlib"]`, `node_crates` v14.6.202, rust-version 1.86) vendoring `temporal_rs`/`temporal_capi` and the ICU4X crates; its Cargo.toml is generated by node-core-utils and must not be hand-edited.
- Build/test commands: `./configure && make -j4`, `make test` (tooltest + addon builds + cctest + jstest), `make test-only` (skips doc build), `make test-ci` for CI, `make lint` (js/cpp/md/yaml), `make coverage`.
- `configure.py` owns feature toggles that become gyp variables — `--shared-ffi`/`--without-ffi` set `node_use_ffi`, and `--v8-enable-temporal-support` gates the Rust temporal path; `node.gyp` defaults `node_use_ffi%` to `false` and only pulls in `deps/libffi/libffi.gyp:libffi` when it is true.
- Type checking of `lib/` is opt-in and non-emitting: `tsconfig.json` sets `allowJs: true`, `checkJs: false`, `noEmit: true`, excludes `src`/`tools`, and maps every public builtin id to its `lib/*.js` file plus `internal/*` to `lib/internal/*`.
- Hand-written ambient types for the C++ boundary live in `typings/internalBinding/*.d.ts` (one file per binding, including `ffi.d.ts`), loaded via `tsconfig.json`'s `files` list alongside `typings/globals.d.ts` and `typings/primordials.d.ts`.
- Python tooling is linted by ruff configured in `pyproject.toml` with deliberately huge thresholds (`max-complexity = 100`, `max-statements = 289`, `line-length = 172`), reflecting long-lived legacy scripts like `configure.py` (112 KB) and `tools/test.py`.