Repository: nodejs/node
Pull request: doc: improve internal documentation on built-in snapshot

Part of the tools/snapshot/README.md is out of date since we have made more progress on the snapshot integration, so update it accordingly with some details about the various snapshots in the snapshot blob.

Also update the section in src/README.md about external reference registration for clarification.

<!--
Before submitting a pull request, please read:

- the CONTRIBUTING guide at https://github.com/nodejs/node/blob/HEAD/CONTRIBUTING.md
- the commit message formatting guidelines at
  https://github.com/nodejs/node/blob/HEAD/doc/contributing/pull-requests.md#commit-message-guidelines

For code changes:
1. Include tests for any bug fixes or new features.
2. Update documentation if relevant.
3. Ensure that `make -j4 test` (UNIX), or `vcbuild test` (Windows) passes.

If you believe this PR should be highlighted in the Node.js CHANGELOG
please add the `notable-change` label.

Developer's Certificate of Origin 1.1

By making a contribution to this project, I certify that:

(a) The contribution was created in whole or in part by me and I
    have the right to submit it under the open source license
    indicated in the file; or

(b) The contribution is based upon previous work that, to the best
    of my knowledge, is covered under an appropriate open source
    license and I have the right under that license to submit that
    work with modifications, whether created in whole or in part
    by me, under the same open source license (unless I am
    permitted to submit under a different license), as indicated
    in the file; or

(c) The contribution was provided directly to me by some other
    person who certified (a), (b) or (c) and I have not modified
    it.

(d) I understand and agree that this project and the contribution
    are public and that a record of the contribution (including all
    personal information I submit with it, including my sign-off) is
    maintained indefinitely and may be redistributed consistent with
    this project or the open source license(s) involved.
-->


Changed files:
filename: src/README.md
patch: @@ -467,10 +467,16 @@ void Initialize(Local<Object> target,
 NODE_BINDING_CONTEXT_AWARE_INTERNAL(cares_wrap, Initialize)
 ```
 
-If the C++ binding is loaded during bootstrap, it needs to be registered
-with the utilities in `node_external_reference.h`, like this:
+#### Registering binding functions used in bootstrap
+
+If the C++ binding is loaded during bootstrap, in addition to registering it
+using `NODE_BINDING_CONTEXT_AWARE_INTERNAL` for `internalBinding()` lookup,
+it also needs to be registered with `NODE_BINDING_EXTERNAL_REFERENCE` so that
+the external references can be resolved from the built-in snapshot, like this:
 
 ```cpp
+#include "node_external_reference.h"
+
 namespace node {
 namespace util {
 void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
@@ -498,7 +504,8 @@ Unknown external reference 0x107769200.
 /bin/sh: line 1:  6963 Illegal instruction: 4  out/Release/node_mksnapshot out/Release/gen/node_snapshot.cc
 ```
 
-You can try using a debugger to symbolicate the external reference. For example,
+You can try using a debugger to symbolicate the external reference in order to find
+out the binding functions that you forget to register. For example,
 with lldb's `image lookup --address` command (with gdb it's `info symbol`):
 
 ```console
@@ -514,7 +521,9 @@ Process 7012 stopped
 ```
 
 Which explains that the unregistered external reference is
-`node::util::GetHiddenValue` defined in `node_util.cc`.
+`node::util::GetHiddenValue` defined in `node_util.cc`, and should be registered
+using `registry->Register()` in a registration function marked by
+`NODE_BINDING_EXTERNAL_REFERENCE`.
 
 <a id="per-binding-state"></a>
 

filename: tools/snapshot/README.md
patch: @@ -8,9 +8,46 @@ instead of executing code to bootstrap, it can deserialize the context from
 an embedded snapshot, which readily contains the result of the bootstrap, so
 that Node.js can start up faster.
 
-Currently only the main context of the main Node.js instance supports snapshot
-deserialization, and the snapshot does not yet cover the entire bootstrap
-process. Work is being done to expand the support.
+The built-in snapshot consists of the following snapshots:
+
+## Isolate snapshot
+
+Which is used whenever a `v8::Isolate` is created using the data returned by
+`node::SnapshotBuilder::GetEmbeddedSnapshotData`.
+
+## Context snapshots
+
+Which are used when a `v8::Context` is created from a `v8::Isolate` deserialized
+from the snapshot. There are four context snapshots in the snapshot blob.
+
+1. The default context snapshot, used for contexts created by
+  `v8::Context::New()`, it only contains V8 built-ins, matching the
+  layout of the isolate snapshot.
+1. The vm context snapshot, which can be deserialized using 
+  `v8::Context::FromSnapshot(isolate, node::SnapshotData::kNodeVMContextIndex, ...)`.
+  It captures initializations specific to vm contexts done by
+  `node::contextify::ContextifyContext::CreateV8Context()`.
+1. The base context snapshot, which can be deserialized using
+  `v8::Context::FromSnapshot(isolate, node::SnapshotData::kNodeBaseContextIndex, ...)`.
+  It currently captures initializations done by `node::NewContext()`
+  but is intended to include more as a basis for worker thread
+  contexts.
+1. The main context snapshot, which can be deserialized using
+  `v8::Context::FromSnapshot(isolate, node::SnapshotData::kNodeMainContextIndex, ...)`.
+  This is the snapshot for the main context on the main thread, and
+  captures initializations done by `node::CommonEnvironmentSetup::CreateForSnapshotting()`,
+  most notably `node::CreateEnvironment()`, which runs the following scripts via
+  `node::Realm::RunBootstrapping()` for the main context as a principal realm,
+  so that at runtime, these scripts do not need to be run. Instead only the context
+  initialized by them is deserialized at runtime.
+     1. `internal/bootstrap/realm`
+     2. `internal/bootstrap/node`
+     3. `internal/bootstrap/web/exposed-wildcard`
+     4. `internal/bootstrap/web/exposed-window-or-worker`
+     5. `internal/bootstrap/switches/is_main_thread`
+     6. `internal/bootstrap/switches/does_own_process_state`
+
+For more information about these contexts, see the comment in `src/node_context_data.h`.
 
 ## How it's built and used
 
@@ -39,3 +76,22 @@ For debugging, Node.js can be built without Node.js's own snapshot if
 `--without-node-snapshot` is passed to `configure`. A Node.js executable
 with Node.js snapshot embedded can also be launched without deserializing
 from it if the command line argument `--no-node-snapshot` is passed.
+
+### When `node_mksnapshot` crashes..
+
+Due to this two-phase building process, sometimes when there is an issue
+in the code, the build may crash early at executing `node_mksnapshot` instead of crashing
+at executing the final executable `node`. If the crash can be reproduced when running
+the `node` executable built with `--without-node-snapshot`, it means the crash likely
+has nothing to do with snapshots, and only shows up in `node_mksnapshot` because it's
+the first Node.js executable being run.
+
+If the crash comes from a `mksnapshot` executable (notice that it doesn't have the `node_`
+prefix), that comes from V8's own snapshot building process, not the one in Node.js, and the
+fix likely needs to be in V8 or the build configurations of V8.
+
+If it `node_mksnapshot` crashes with an error message containing
+something like `Unknown external reference 0x107769200`, see
+[Registering binding functions used in bootstrap][] on how to fix it.
+
+[Registering binding functions used in bootstrap]: ../../src/README.md#registering-binding-functions-used-in-bootstrap