Skip to content

Commit 33732bb

Browse files
joyeecheungjuanarbol
authored andcommitted
src: add more checks and clarify docs for external references
To help catch unregistered bindings. PR-URL: #61719 Refs: #61718 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent 6f9002c commit 33732bb

2 files changed

Lines changed: 68 additions & 3 deletions

File tree

src/README.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -506,12 +506,17 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
506506
} // namespace util
507507
} // namespace node
508508
509-
// The first argument passed to `NODE_BINDING_EXTERNAL_REFERENCE`,
510-
// which is `util` here, needs to be added to the
511-
// `EXTERNAL_REFERENCE_BINDING_LIST_BASE` list in node_external_reference.h
512509
NODE_BINDING_EXTERNAL_REFERENCE(util, node::util::RegisterExternalReferences)
513510
```
514511

512+
And add the first argument passed to `NODE_BINDING_EXTERNAL_REFERENCE` to
513+
the list of external references in `src/node_external_reference.h`:
514+
515+
```cpp
516+
#define EXTERNAL_REFERENCE_LIST_BASE(V) \
517+
V(util) \
518+
```
519+
515520
Otherwise, you might see an error message like this when building the
516521
executables:
517522

src/node_snapshotable.cc

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -967,6 +967,61 @@ std::optional<SnapshotConfig> ReadSnapshotConfig(const char* config_path) {
967967
return result;
968968
}
969969

970+
// Find bindings that have been loaded by internalBinding() but the external
971+
// reference method have not been called. This requires that the caller
972+
// match the id passed into their NODE_BINDING_CONTEXT_AWARE_INTERNAL() and
973+
// NODE_BINDING_EXTERNAL_REFERENCE() calls. Note that this only serves as a
974+
// preemptive check. Binding methods create the actual external references
975+
// (usually through function templates) and there's currently no easy way
976+
// to verify at that level of granularity. See "Registering binding functions
977+
// used in bootstrap" in src/README.md.
978+
bool ValidateBindings(Environment* env) {
979+
std::set<std::string> registered;
980+
#define V(modname) registered.insert(#modname);
981+
EXTERNAL_REFERENCE_BINDING_LIST(V)
982+
#undef V
983+
984+
std::set<std::string> bindings_without_external_references = {
985+
"async_context_frame",
986+
"constants",
987+
"symbols",
988+
};
989+
990+
std::set<std::string> unregistered;
991+
for (auto* mod : env->principal_realm()->internal_bindings) {
992+
if (registered.count(mod->nm_modname) == 0 &&
993+
bindings_without_external_references.count(mod->nm_modname) == 0) {
994+
unregistered.insert(mod->nm_modname);
995+
}
996+
}
997+
998+
if (unregistered.size() == 0) {
999+
return true;
1000+
}
1001+
1002+
FPrintF(
1003+
stderr,
1004+
"\n---- snapshot building check failed ---\n\n"
1005+
"The following bindings are loaded during the snapshot building process,"
1006+
" but their external reference registration methods have not been "
1007+
"called:\n\n");
1008+
for (auto& binding : unregistered) {
1009+
FPrintF(stderr, " - %s\n", binding);
1010+
}
1011+
FPrintF(stderr,
1012+
"\nIf the binding does not have any external references, "
1013+
"add it to the list of bindings_without_external_references "
1014+
"in src/node_snapshotable.cc.\n"
1015+
"Otherwise, make sure to call NODE_BINDING_EXTERNAL_REFERENCE() "
1016+
"with an appropriate register method for the binding, "
1017+
"and add it to EXTERNAL_REFERENCE_BINDING_LIST in "
1018+
"src/node_external_reference.h"
1019+
"\n\nSee \"Registering binding functions used in bootstrap\" "
1020+
"in src/README.md for more details."
1021+
"\n----\n\n");
1022+
return false;
1023+
}
1024+
9701025
ExitCode BuildSnapshotWithoutCodeCache(
9711026
SnapshotData* out,
9721027
const std::vector<std::string>& args,
@@ -1032,6 +1087,11 @@ ExitCode BuildSnapshotWithoutCodeCache(
10321087
if (exit_code != ExitCode::kNoFailure) {
10331088
return exit_code;
10341089
}
1090+
1091+
if (snapshot_type == SnapshotMetadata::Type::kDefault &&
1092+
!ValidateBindings(env)) {
1093+
return ExitCode::kStartupSnapshotFailure;
1094+
}
10351095
}
10361096

10371097
return SnapshotBuilder::CreateSnapshot(out, setup.get());

0 commit comments

Comments
 (0)