Skip to content

Commit ca07aba

Browse files
authored
src: per-realm binding data
Binding data is inherited from BaseObject and created in a specific realm. They need to be tracked on a per-realm basis so that they can be released properly when a realm is disposed. PR-URL: nodejs#46556 Reviewed-By: Joyee Cheung <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Matteo Collina <[email protected]>
1 parent 0093fd3 commit ca07aba

27 files changed

+211
-203
lines changed

src/README.md

+5-5
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,7 @@ Which explains that the unregistered external reference is
482482

483483
Some internal bindings, such as the HTTP parser, maintain internal state that
484484
only affects that particular binding. In that case, one common way to store
485-
that state is through the use of `Environment::AddBindingData`, which gives
485+
that state is through the use of `Realm::AddBindingData`, which gives
486486
binding functions access to an object for storing such state.
487487
That object is always a [`BaseObject`][].
488488

@@ -507,7 +507,7 @@ class BindingData : public BaseObject {
507507

508508
// Available for binding functions, e.g. the HTTP Parser constructor:
509509
static void New(const FunctionCallbackInfo<Value>& args) {
510-
BindingData* binding_data = Environment::GetBindingData<BindingData>(args);
510+
BindingData* binding_data = Realm::GetBindingData<BindingData>(args);
511511
new Parser(binding_data, args.This());
512512
}
513513

@@ -517,12 +517,12 @@ void InitializeHttpParser(Local<Object> target,
517517
Local<Value> unused,
518518
Local<Context> context,
519519
void* priv) {
520-
Environment* env = Environment::GetCurrent(context);
520+
Realm* realm = Realm::GetCurrent(context);
521521
BindingData* const binding_data =
522-
env->AddBindingData<BindingData>(context, target);
522+
realm->AddBindingData<BindingData>(context, target);
523523
if (binding_data == nullptr) return;
524524

525-
Local<FunctionTemplate> t = env->NewFunctionTemplate(Parser::New);
525+
Local<FunctionTemplate> t = NewFunctionTemplate(realm->isolate(), Parser::New);
526526
...
527527
}
528528
```

src/base_object-inl.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,10 @@
3333
namespace node {
3434

3535
BaseObject::BaseObject(Environment* env, v8::Local<v8::Object> object)
36-
: BaseObject(env->principal_realm(), object) {}
36+
: BaseObject(env->principal_realm(), object) {
37+
// TODO(legendecas): Check the shorthand is only used in the principal realm
38+
// while allowing to create a BaseObject in a vm context.
39+
}
3740

3841
// static
3942
v8::Local<v8::FunctionTemplate> BaseObject::GetConstructorTemplate(

src/dataqueue/queue.cc

+7-7
Original file line numberDiff line numberDiff line change
@@ -874,14 +874,14 @@ class FdEntry final : public EntryImpl {
874874
uv_fs_close(nullptr, &req, file, nullptr);
875875
return nullptr;
876876
}
877+
Realm* realm = entry->env()->principal_realm();
877878
return std::make_shared<ReaderImpl>(
878-
BaseObjectPtr<fs::FileHandle>(
879-
fs::FileHandle::New(entry->env()->GetBindingData<fs::BindingData>(
880-
entry->env()->context()),
881-
file,
882-
Local<Object>(),
883-
entry->start_,
884-
entry->end_)),
879+
BaseObjectPtr<fs::FileHandle>(fs::FileHandle::New(
880+
realm->GetBindingData<fs::BindingData>(realm->context()),
881+
file,
882+
Local<Object>(),
883+
entry->start_,
884+
entry->end_)),
885885
entry);
886886
}
887887

src/env-inl.h

-42
Original file line numberDiff line numberDiff line change
@@ -201,48 +201,6 @@ inline Environment* Environment::GetCurrent(
201201
return GetCurrent(info.GetIsolate()->GetCurrentContext());
202202
}
203203

204-
template <typename T, typename U>
205-
inline T* Environment::GetBindingData(const v8::PropertyCallbackInfo<U>& info) {
206-
return GetBindingData<T>(info.GetIsolate()->GetCurrentContext());
207-
}
208-
209-
template <typename T>
210-
inline T* Environment::GetBindingData(
211-
const v8::FunctionCallbackInfo<v8::Value>& info) {
212-
return GetBindingData<T>(info.GetIsolate()->GetCurrentContext());
213-
}
214-
215-
template <typename T>
216-
inline T* Environment::GetBindingData(v8::Local<v8::Context> context) {
217-
BindingDataStore* map = static_cast<BindingDataStore*>(
218-
context->GetAlignedPointerFromEmbedderData(
219-
ContextEmbedderIndex::kBindingListIndex));
220-
DCHECK_NOT_NULL(map);
221-
auto it = map->find(T::type_name);
222-
if (UNLIKELY(it == map->end())) return nullptr;
223-
T* result = static_cast<T*>(it->second.get());
224-
DCHECK_NOT_NULL(result);
225-
DCHECK_EQ(result->env(), GetCurrent(context));
226-
return result;
227-
}
228-
229-
template <typename T>
230-
inline T* Environment::AddBindingData(
231-
v8::Local<v8::Context> context,
232-
v8::Local<v8::Object> target) {
233-
DCHECK_EQ(GetCurrent(context), this);
234-
// This won't compile if T is not a BaseObject subclass.
235-
BaseObjectPtr<T> item = MakeDetachedBaseObject<T>(this, target);
236-
BindingDataStore* map = static_cast<BindingDataStore*>(
237-
context->GetAlignedPointerFromEmbedderData(
238-
ContextEmbedderIndex::kBindingListIndex));
239-
DCHECK_NOT_NULL(map);
240-
auto result = map->emplace(T::type_name, item);
241-
CHECK(result.second);
242-
DCHECK_EQ(GetBindingData<T>(context), item.get());
243-
return item.get();
244-
}
245-
246204
inline v8::Isolate* Environment::isolate() const {
247205
return isolate_;
248206
}

src/env.cc

+2-2
Original file line numberDiff line numberDiff line change
@@ -545,7 +545,8 @@ void Environment::AssignToContext(Local<v8::Context> context,
545545
context->SetAlignedPointerInEmbedderData(ContextEmbedderIndex::kRealm, realm);
546546
// Used to retrieve bindings
547547
context->SetAlignedPointerInEmbedderData(
548-
ContextEmbedderIndex::kBindingListIndex, &(this->bindings_));
548+
ContextEmbedderIndex::kBindingDataStoreIndex,
549+
realm->binding_data_store());
549550

550551
// ContextifyContexts will update this to a pointer to the native object.
551552
context->SetAlignedPointerInEmbedderData(
@@ -1019,7 +1020,6 @@ MaybeLocal<Value> Environment::RunSnapshotDeserializeMain() const {
10191020
void Environment::RunCleanup() {
10201021
started_cleanup_ = true;
10211022
TRACE_EVENT0(TRACING_CATEGORY_NODE1(environment), "RunCleanup");
1022-
bindings_.clear();
10231023
// Only BaseObject's cleanups are registered as per-realm cleanup hooks now.
10241024
// Defer the BaseObject cleanup after handles are cleaned up.
10251025
CleanupHandles();

src/env.h

-21
Original file line numberDiff line numberDiff line change
@@ -587,25 +587,6 @@ class Environment : public MemoryRetainer {
587587
static inline Environment* GetCurrent(
588588
const v8::PropertyCallbackInfo<T>& info);
589589

590-
// Methods created using SetMethod(), SetPrototypeMethod(), etc. inside
591-
// this scope can access the created T* object using
592-
// GetBindingData<T>(args) later.
593-
template <typename T>
594-
T* AddBindingData(v8::Local<v8::Context> context,
595-
v8::Local<v8::Object> target);
596-
template <typename T, typename U>
597-
static inline T* GetBindingData(const v8::PropertyCallbackInfo<U>& info);
598-
template <typename T>
599-
static inline T* GetBindingData(
600-
const v8::FunctionCallbackInfo<v8::Value>& info);
601-
template <typename T>
602-
static inline T* GetBindingData(v8::Local<v8::Context> context);
603-
604-
typedef std::unordered_map<
605-
FastStringKey,
606-
BaseObjectPtr<BaseObject>,
607-
FastStringKey::Hash> BindingDataStore;
608-
609590
// Create an Environment without initializing a main Context. Use
610591
// InitializeMainContext() to initialize a main context for it.
611592
Environment(IsolateData* isolate_data,
@@ -1134,8 +1115,6 @@ class Environment : public MemoryRetainer {
11341115
void RequestInterruptFromV8();
11351116
static void CheckImmediate(uv_check_t* handle);
11361117

1137-
BindingDataStore bindings_;
1138-
11391118
CleanupQueue cleanup_queue_;
11401119
bool started_cleanup_ = false;
11411120

src/node_blob.cc

+9-12
Original file line numberDiff line numberDiff line change
@@ -110,10 +110,10 @@ void Blob::Initialize(
110110
Local<Value> unused,
111111
Local<Context> context,
112112
void* priv) {
113-
Environment* env = Environment::GetCurrent(context);
113+
Realm* realm = Realm::GetCurrent(context);
114114

115115
BlobBindingData* const binding_data =
116-
env->AddBindingData<BlobBindingData>(context, target);
116+
realm->AddBindingData<BlobBindingData>(context, target);
117117
if (binding_data == nullptr) return;
118118

119119
SetMethod(context, target, "createBlob", New);
@@ -394,8 +394,7 @@ std::unique_ptr<worker::TransferData> Blob::CloneForMessaging() const {
394394

395395
void Blob::StoreDataObject(const v8::FunctionCallbackInfo<v8::Value>& args) {
396396
Environment* env = Environment::GetCurrent(args);
397-
BlobBindingData* binding_data =
398-
Environment::GetBindingData<BlobBindingData>(args);
397+
BlobBindingData* binding_data = Realm::GetBindingData<BlobBindingData>(args);
399398

400399
CHECK(args[0]->IsString()); // ID key
401400
CHECK(Blob::HasInstance(env, args[1])); // Blob
@@ -418,8 +417,7 @@ void Blob::StoreDataObject(const v8::FunctionCallbackInfo<v8::Value>& args) {
418417
}
419418

420419
void Blob::RevokeDataObject(const v8::FunctionCallbackInfo<v8::Value>& args) {
421-
BlobBindingData* binding_data =
422-
Environment::GetBindingData<BlobBindingData>(args);
420+
BlobBindingData* binding_data = Realm::GetBindingData<BlobBindingData>(args);
423421

424422
Environment* env = Environment::GetCurrent(args);
425423
CHECK(args[0]->IsString()); // ID key
@@ -430,8 +428,7 @@ void Blob::RevokeDataObject(const v8::FunctionCallbackInfo<v8::Value>& args) {
430428
}
431429

432430
void Blob::GetDataObject(const v8::FunctionCallbackInfo<v8::Value>& args) {
433-
BlobBindingData* binding_data =
434-
Environment::GetBindingData<BlobBindingData>(args);
431+
BlobBindingData* binding_data = Realm::GetBindingData<BlobBindingData>(args);
435432

436433
Environment* env = Environment::GetCurrent(args);
437434
CHECK(args[0]->IsString());
@@ -477,8 +474,8 @@ BlobBindingData::StoredDataObject::StoredDataObject(
477474
length(length_),
478475
type(type_) {}
479476

480-
BlobBindingData::BlobBindingData(Environment* env, Local<Object> wrap)
481-
: SnapshotableObject(env, wrap, type_int) {
477+
BlobBindingData::BlobBindingData(Realm* realm, Local<Object> wrap)
478+
: SnapshotableObject(realm, wrap, type_int) {
482479
MakeWeak();
483480
}
484481

@@ -516,9 +513,9 @@ void BlobBindingData::Deserialize(Local<Context> context,
516513
InternalFieldInfoBase* info) {
517514
DCHECK_EQ(index, BaseObject::kEmbedderType);
518515
HandleScope scope(context->GetIsolate());
519-
Environment* env = Environment::GetCurrent(context);
516+
Realm* realm = Realm::GetCurrent(context);
520517
BlobBindingData* binding =
521-
env->AddBindingData<BlobBindingData>(context, holder);
518+
realm->AddBindingData<BlobBindingData>(context, holder);
522519
CHECK_NOT_NULL(binding);
523520
}
524521

src/node_blob.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ class Blob : public BaseObject {
111111

112112
class BlobBindingData : public SnapshotableObject {
113113
public:
114-
explicit BlobBindingData(Environment* env, v8::Local<v8::Object> wrap);
114+
explicit BlobBindingData(Realm* realm, v8::Local<v8::Object> wrap);
115115

116116
using InternalFieldInfo = InternalFieldInfoBase;
117117

src/node_context_data.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ namespace node {
2424
#define NODE_CONTEXT_ALLOW_WASM_CODE_GENERATION_INDEX 34
2525
#endif
2626

27-
#ifndef NODE_BINDING_LIST
28-
#define NODE_BINDING_LIST_INDEX 35
27+
#ifndef NODE_BINDING_DATA_STORE_INDEX
28+
#define NODE_BINDING_DATA_STORE_INDEX 35
2929
#endif
3030

3131
#ifndef NODE_CONTEXT_ALLOW_CODE_GENERATION_FROM_STRINGS_INDEX
@@ -51,7 +51,7 @@ enum ContextEmbedderIndex {
5151
kEnvironment = NODE_CONTEXT_EMBEDDER_DATA_INDEX,
5252
kSandboxObject = NODE_CONTEXT_SANDBOX_OBJECT_INDEX,
5353
kAllowWasmCodeGeneration = NODE_CONTEXT_ALLOW_WASM_CODE_GENERATION_INDEX,
54-
kBindingListIndex = NODE_BINDING_LIST_INDEX,
54+
kBindingDataStoreIndex = NODE_BINDING_DATA_STORE_INDEX,
5555
kAllowCodeGenerationFromStrings =
5656
NODE_CONTEXT_ALLOW_CODE_GENERATION_FROM_STRINGS_INDEX,
5757
kContextifyContext = NODE_CONTEXT_CONTEXTIFY_CONTEXT_INDEX,

src/node_file-inl.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ FSReqBase* GetReqWrap(const v8::FunctionCallbackInfo<v8::Value>& args,
277277
return Unwrap<FSReqBase>(value.As<v8::Object>());
278278
}
279279

280-
BindingData* binding_data = Environment::GetBindingData<BindingData>(args);
280+
BindingData* binding_data = Realm::GetBindingData<BindingData>(args);
281281
Environment* env = binding_data->env();
282282
if (value->StrictEquals(env->fs_use_promises_symbol())) {
283283
if (use_bigint) {

0 commit comments

Comments
 (0)