Skip to content

Commit ef9964f

Browse files
committed
src: add an ExternalReferenceRegistry class
Add an ExternalReferenceRegistry class for registering static external references. To register the external JS to C++ references created in a binding (e.g. when a FunctionTemplate is created): - Add the binding name (same as the id used for `internalBinding()` and `NODE_MODULE_CONTEXT_AWARE_INTERNAL`) to `EXTERNAL_REFERENCE_BINDING_LIST` in `src/node_external_reference.h`. - In the file where the binding is implemented, create a registration function to register the static C++ references (e.g. the C++ functions in `v8::FunctionCallback` associated with the function templates), like this: ```c++ void RegisterExternalReferences( ExternalReferenceRegistry* registry) { registry->Register(cpp_func_1); } ``` - At the end of the file where `NODE_MODULE_CONTEXT_AWARE_INTERNAL` is also usually called, register the registration function with ``` NODE_MODULE_EXTERNAL_REFERENCE(binding_name, RegisterExternalReferences); ``` PR-URL: #32984 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Daniel Bevenius <[email protected]>
1 parent 404302f commit ef9964f

7 files changed

+114
-5
lines changed

Diff for: node.gyp

+2
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,7 @@
593593
'src/node_dir.cc',
594594
'src/node_env_var.cc',
595595
'src/node_errors.cc',
596+
'src/node_external_reference.cc',
596597
'src/node_file.cc',
597598
'src/node_http_parser.cc',
598599
'src/node_http2.cc',
@@ -687,6 +688,7 @@
687688
'src/node_contextify.h',
688689
'src/node_dir.h',
689690
'src/node_errors.h',
691+
'src/node_external_reference.h',
690692
'src/node_file.h',
691693
'src/node_file-inl.h',
692694
'src/node_http_common.h',

Diff for: src/node.cc

+1
Original file line numberDiff line numberDiff line change
@@ -1069,6 +1069,7 @@ int Start(int argc, char** argv) {
10691069
if (blob != nullptr) {
10701070
// TODO(joyeecheung): collect external references and set it in
10711071
// params.external_references.
1072+
external_references = NodeMainInstance::CollectExternalReferences();
10721073
external_references.push_back(reinterpret_cast<intptr_t>(nullptr));
10731074
params.external_references = external_references.data();
10741075
params.snapshot_blob = blob;

Diff for: src/node_external_reference.cc

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#include "node_external_reference.h"
2+
#include <cinttypes>
3+
#include <vector>
4+
#include "util.h"
5+
6+
namespace node {
7+
8+
const std::vector<intptr_t>& ExternalReferenceRegistry::external_references() {
9+
CHECK(!is_finalized_);
10+
external_references_.push_back(reinterpret_cast<intptr_t>(nullptr));
11+
is_finalized_ = true;
12+
return external_references_;
13+
}
14+
15+
ExternalReferenceRegistry::ExternalReferenceRegistry() {
16+
#define V(modname) _register_external_reference_##modname(this);
17+
EXTERNAL_REFERENCE_BINDING_LIST(V)
18+
#undef V
19+
// TODO(joyeecheung): collect more external references here.
20+
}
21+
22+
} // namespace node

Diff for: src/node_external_reference.h

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#ifndef SRC_NODE_EXTERNAL_REFERENCE_H_
2+
#define SRC_NODE_EXTERNAL_REFERENCE_H_
3+
4+
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
5+
6+
#include <cinttypes>
7+
#include <vector>
8+
#include "v8.h"
9+
10+
namespace node {
11+
12+
// This class manages the external references from the V8 heap
13+
// to the C++ addresses in Node.js.
14+
class ExternalReferenceRegistry {
15+
public:
16+
ExternalReferenceRegistry();
17+
18+
#define ALLOWED_EXTERNAL_REFERENCE_TYPES(V) \
19+
V(v8::FunctionCallback) \
20+
V(v8::AccessorGetterCallback) \
21+
V(v8::AccessorSetterCallback) \
22+
V(v8::AccessorNameGetterCallback) \
23+
V(v8::AccessorNameSetterCallback) \
24+
V(v8::GenericNamedPropertyDefinerCallback) \
25+
V(v8::GenericNamedPropertyDeleterCallback) \
26+
V(v8::GenericNamedPropertyEnumeratorCallback) \
27+
V(v8::GenericNamedPropertyQueryCallback) \
28+
V(v8::GenericNamedPropertySetterCallback)
29+
30+
#define V(ExternalReferenceType) \
31+
void Register(ExternalReferenceType addr) { RegisterT(addr); }
32+
ALLOWED_EXTERNAL_REFERENCE_TYPES(V)
33+
#undef V
34+
35+
// This can be called only once.
36+
const std::vector<intptr_t>& external_references();
37+
38+
bool is_empty() { return external_references_.empty(); }
39+
40+
private:
41+
template <typename T>
42+
void RegisterT(T* address) {
43+
external_references_.push_back(reinterpret_cast<intptr_t>(address));
44+
}
45+
bool is_finalized_ = false;
46+
std::vector<intptr_t> external_references_;
47+
};
48+
49+
#define EXTERNAL_REFERENCE_BINDING_LIST(V)
50+
51+
} // namespace node
52+
53+
// Declare all the external reference registration functions here,
54+
// and define them later with #NODE_MODULE_EXTERNAL_REFERENCE(modname, func);
55+
#define V(modname) \
56+
void _register_external_reference_##modname( \
57+
node::ExternalReferenceRegistry* registry);
58+
EXTERNAL_REFERENCE_BINDING_LIST(V)
59+
#undef V
60+
61+
#define NODE_MODULE_EXTERNAL_REFERENCE(modname, func) \
62+
void _register_external_reference_##modname( \
63+
node::ExternalReferenceRegistry* registry) { \
64+
func(registry); \
65+
}
66+
#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
67+
#endif // SRC_NODE_EXTERNAL_REFERENCE_H_

Diff for: src/node_main_instance.cc

+14-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
#include <memory>
22

3-
#include "node_main_instance.h"
3+
#include "node_errors.h"
4+
#include "node_external_reference.h"
45
#include "node_internals.h"
6+
#include "node_main_instance.h"
57
#include "node_options-inl.h"
68
#include "node_v8_platform-inl.h"
79
#include "util-inl.h"
@@ -22,6 +24,8 @@ using v8::Local;
2224
using v8::Locker;
2325
using v8::SealHandleScope;
2426

27+
std::unique_ptr<ExternalReferenceRegistry> NodeMainInstance::registry_ =
28+
nullptr;
2529
NodeMainInstance::NodeMainInstance(Isolate* isolate,
2630
uv_loop_t* event_loop,
2731
MultiIsolatePlatform* platform,
@@ -41,6 +45,15 @@ NodeMainInstance::NodeMainInstance(Isolate* isolate,
4145
SetIsolateMiscHandlers(isolate_, {});
4246
}
4347

48+
const std::vector<intptr_t>& NodeMainInstance::CollectExternalReferences() {
49+
// Cannot be called more than once.
50+
CHECK_NULL(registry_);
51+
registry_.reset(new ExternalReferenceRegistry());
52+
53+
// TODO(joyeecheung): collect more external references here.
54+
return registry_->external_references();
55+
}
56+
4457
std::unique_ptr<NodeMainInstance> NodeMainInstance::Create(
4558
Isolate* isolate,
4659
uv_loop_t* event_loop,

Diff for: src/node_main_instance.h

+4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313

1414
namespace node {
1515

16+
class ExternalReferenceRegistry;
17+
1618
// TODO(joyeecheung): align this with the Worker/WorkerThreadData class.
1719
// We may be able to create an abstract class to reuse some of the routines.
1820
class NodeMainInstance {
@@ -66,6 +68,7 @@ class NodeMainInstance {
6668
// snapshot.
6769
static const std::vector<size_t>* GetIsolateDataIndexes();
6870
static v8::StartupData* GetEmbeddedSnapshotBlob();
71+
static const std::vector<intptr_t>& CollectExternalReferences();
6972

7073
static const size_t kNodeContextIndex = 0;
7174
NodeMainInstance(const NodeMainInstance&) = delete;
@@ -80,6 +83,7 @@ class NodeMainInstance {
8083
const std::vector<std::string>& args,
8184
const std::vector<std::string>& exec_args);
8285

86+
static std::unique_ptr<ExternalReferenceRegistry> registry_;
8387
std::vector<std::string> args_;
8488
std::vector<std::string> exec_args_;
8589
std::unique_ptr<ArrayBufferAllocator> array_buffer_allocator_;

Diff for: tools/snapshot/snapshot_builder.cc

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#include "snapshot_builder.h"
22
#include <iostream>
33
#include <sstream>
4+
#include "env-inl.h"
5+
#include "node_external_reference.h"
46
#include "node_internals.h"
57
#include "node_main_instance.h"
68
#include "node_v8_platform-inl.h"
@@ -63,10 +65,8 @@ const std::vector<size_t>* NodeMainInstance::GetIsolateDataIndexes() {
6365
std::string SnapshotBuilder::Generate(
6466
const std::vector<std::string> args,
6567
const std::vector<std::string> exec_args) {
66-
// TODO(joyeecheung): collect external references and set it in
67-
// params.external_references.
68-
std::vector<intptr_t> external_references = {
69-
reinterpret_cast<intptr_t>(nullptr)};
68+
const std::vector<intptr_t>& external_references =
69+
NodeMainInstance::CollectExternalReferences();
7070
Isolate* isolate = Isolate::Allocate();
7171
per_process::v8_platform.Platform()->RegisterIsolate(isolate,
7272
uv_default_loop());

0 commit comments

Comments
 (0)