Skip to content

Commit 5b2c0f8

Browse files
committed
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.
1 parent 6d584ae commit 5b2c0f8

26 files changed

+206
-196
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

+5-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,11 @@
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+
// Check the shorthand is only used in the principal realm.
38+
DCHECK_EQ(object->GetCreationContextChecked(),
39+
env->principal_realm()->context());
40+
}
3741

3842
// static
3943
v8::Local<v8::FunctionTemplate> BaseObject::GetConstructorTemplate(

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(
@@ -1018,7 +1019,6 @@ MaybeLocal<Value> Environment::RunSnapshotDeserializeMain() const {
10181019
void Environment::RunCleanup() {
10191020
started_cleanup_ = true;
10201021
TRACE_EVENT0(TRACING_CATEGORY_NODE1(environment), "RunCleanup");
1021-
bindings_.clear();
10221022
// Only BaseObject's cleanups are registered as per-realm cleanup hooks now.
10231023
// Defer the BaseObject cleanup after handles are cleaned up.
10241024
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

+10-12
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,11 @@ void Blob::Initialize(
3737
Local<Value> unused,
3838
Local<Context> context,
3939
void* priv) {
40-
Environment* env = Environment::GetCurrent(context);
40+
Realm* realm = Realm::GetCurrent(context);
41+
Environment* env = realm->env();
4142

4243
BlobBindingData* const binding_data =
43-
env->AddBindingData<BlobBindingData>(context, target);
44+
realm->AddBindingData<BlobBindingData>(context, target);
4445
if (binding_data == nullptr) return;
4546

4647
SetMethod(context, target, "createBlob", New);
@@ -238,8 +239,7 @@ std::unique_ptr<worker::TransferData> Blob::CloneForMessaging() const {
238239

239240
void Blob::StoreDataObject(const v8::FunctionCallbackInfo<v8::Value>& args) {
240241
Environment* env = Environment::GetCurrent(args);
241-
BlobBindingData* binding_data =
242-
Environment::GetBindingData<BlobBindingData>(args);
242+
BlobBindingData* binding_data = Realm::GetBindingData<BlobBindingData>(args);
243243

244244
CHECK(args[0]->IsString()); // ID key
245245
CHECK(Blob::HasInstance(env, args[1])); // Blob
@@ -262,8 +262,7 @@ void Blob::StoreDataObject(const v8::FunctionCallbackInfo<v8::Value>& args) {
262262
}
263263

264264
void Blob::RevokeDataObject(const v8::FunctionCallbackInfo<v8::Value>& args) {
265-
BlobBindingData* binding_data =
266-
Environment::GetBindingData<BlobBindingData>(args);
265+
BlobBindingData* binding_data = Realm::GetBindingData<BlobBindingData>(args);
267266

268267
Environment* env = Environment::GetCurrent(args);
269268
CHECK(args[0]->IsString()); // ID key
@@ -274,8 +273,7 @@ void Blob::RevokeDataObject(const v8::FunctionCallbackInfo<v8::Value>& args) {
274273
}
275274

276275
void Blob::GetDataObject(const v8::FunctionCallbackInfo<v8::Value>& args) {
277-
BlobBindingData* binding_data =
278-
Environment::GetBindingData<BlobBindingData>(args);
276+
BlobBindingData* binding_data = Realm::GetBindingData<BlobBindingData>(args);
279277

280278
Environment* env = Environment::GetCurrent(args);
281279
CHECK(args[0]->IsString());
@@ -430,8 +428,8 @@ BlobBindingData::StoredDataObject::StoredDataObject(
430428
length(length_),
431429
type(type_) {}
432430

433-
BlobBindingData::BlobBindingData(Environment* env, Local<Object> wrap)
434-
: SnapshotableObject(env, wrap, type_int) {
431+
BlobBindingData::BlobBindingData(Realm* realm, Local<Object> wrap)
432+
: SnapshotableObject(realm, wrap, type_int) {
435433
MakeWeak();
436434
}
437435

@@ -467,9 +465,9 @@ void BlobBindingData::Deserialize(Local<Context> context,
467465
InternalFieldInfoBase* info) {
468466
DCHECK_EQ(index, BaseObject::kEmbedderType);
469467
HandleScope scope(context->GetIsolate());
470-
Environment* env = Environment::GetCurrent(context);
468+
Realm* realm = Realm::GetCurrent(context);
471469
BlobBindingData* binding =
472-
env->AddBindingData<BlobBindingData>(context, holder);
470+
realm->AddBindingData<BlobBindingData>(context, holder);
473471
CHECK_NOT_NULL(binding);
474472
}
475473

src/node_blob.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ class FixedSizeBlobCopyJob : public AsyncWrap, public ThreadPoolWork {
141141

142142
class BlobBindingData : public SnapshotableObject {
143143
public:
144-
explicit BlobBindingData(Environment* env, v8::Local<v8::Object> wrap);
144+
explicit BlobBindingData(Realm* realm, v8::Local<v8::Object> wrap);
145145

146146
using InternalFieldInfo = InternalFieldInfoBase;
147147

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) {

src/node_file.cc

+29-26
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ FileHandle* FileHandle::New(BindingData* binding_data,
253253
}
254254

255255
void FileHandle::New(const FunctionCallbackInfo<Value>& args) {
256-
BindingData* binding_data = Environment::GetBindingData<BindingData>(args);
256+
BindingData* binding_data = Realm::GetBindingData<BindingData>(args);
257257
Environment* env = binding_data->env();
258258
CHECK(args.IsConstructCall());
259259
CHECK(args[0]->IsInt32());
@@ -313,7 +313,7 @@ BaseObjectPtr<BaseObject> FileHandle::TransferData::Deserialize(
313313
Environment* env,
314314
v8::Local<v8::Context> context,
315315
std::unique_ptr<worker::TransferData> self) {
316-
BindingData* bd = Environment::GetBindingData<BindingData>(context);
316+
BindingData* bd = Realm::GetBindingData<BindingData>(context);
317317
if (bd == nullptr) return {};
318318

319319
int fd = fd_;
@@ -708,7 +708,7 @@ void FSReqCallback::SetReturnValue(const FunctionCallbackInfo<Value>& args) {
708708

709709
void NewFSReqCallback(const FunctionCallbackInfo<Value>& args) {
710710
CHECK(args.IsConstructCall());
711-
BindingData* binding_data = Environment::GetBindingData<BindingData>(args);
711+
BindingData* binding_data = Realm::GetBindingData<BindingData>(args);
712712
new FSReqCallback(binding_data, args.This(), args[0]->IsTrue());
713713
}
714714

@@ -1115,7 +1115,7 @@ static void InternalModuleStat(const FunctionCallbackInfo<Value>& args) {
11151115
}
11161116

11171117
static void Stat(const FunctionCallbackInfo<Value>& args) {
1118-
BindingData* binding_data = Environment::GetBindingData<BindingData>(args);
1118+
BindingData* binding_data = Realm::GetBindingData<BindingData>(args);
11191119
Environment* env = binding_data->env();
11201120

11211121
const int argc = args.Length();
@@ -1148,7 +1148,7 @@ static void Stat(const FunctionCallbackInfo<Value>& args) {
11481148
}
11491149

11501150
static void LStat(const FunctionCallbackInfo<Value>& args) {
1151-
BindingData* binding_data = Environment::GetBindingData<BindingData>(args);
1151+
BindingData* binding_data = Realm::GetBindingData<BindingData>(args);
11521152
Environment* env = binding_data->env();
11531153

11541154
const int argc = args.Length();
@@ -1182,7 +1182,7 @@ static void LStat(const FunctionCallbackInfo<Value>& args) {
11821182
}
11831183

11841184
static void FStat(const FunctionCallbackInfo<Value>& args) {
1185-
BindingData* binding_data = Environment::GetBindingData<BindingData>(args);
1185+
BindingData* binding_data = Realm::GetBindingData<BindingData>(args);
11861186
Environment* env = binding_data->env();
11871187

11881188
const int argc = args.Length();
@@ -1214,7 +1214,7 @@ static void FStat(const FunctionCallbackInfo<Value>& args) {
12141214
}
12151215

12161216
static void StatFs(const FunctionCallbackInfo<Value>& args) {
1217-
BindingData* binding_data = Environment::GetBindingData<BindingData>(args);
1217+
BindingData* binding_data = Realm::GetBindingData<BindingData>(args);
12181218
Environment* env = binding_data->env();
12191219

12201220
const int argc = args.Length();
@@ -1929,7 +1929,7 @@ static void Open(const FunctionCallbackInfo<Value>& args) {
19291929
}
19301930

19311931
static void OpenFileHandle(const FunctionCallbackInfo<Value>& args) {
1932-
BindingData* binding_data = Environment::GetBindingData<BindingData>(args);
1932+
BindingData* binding_data = Realm::GetBindingData<BindingData>(args);
19331933
Environment* env = binding_data->env();
19341934
Isolate* isolate = env->isolate();
19351935

@@ -2619,29 +2619,31 @@ void BindingData::MemoryInfo(MemoryTracker* tracker) const {
26192619
file_handle_read_wrap_freelist);
26202620
}
26212621

2622-
BindingData::BindingData(Environment* env, v8::Local<v8::Object> wrap)
2623-
: SnapshotableObject(env, wrap, type_int),
2624-
stats_field_array(env->isolate(), kFsStatsBufferLength),
2625-
stats_field_bigint_array(env->isolate(), kFsStatsBufferLength),
2626-
statfs_field_array(env->isolate(), kFsStatFsBufferLength),
2627-
statfs_field_bigint_array(env->isolate(), kFsStatFsBufferLength) {
2628-
wrap->Set(env->context(),
2629-
FIXED_ONE_BYTE_STRING(env->isolate(), "statValues"),
2622+
BindingData::BindingData(Realm* realm, v8::Local<v8::Object> wrap)
2623+
: SnapshotableObject(realm, wrap, type_int),
2624+
stats_field_array(realm->isolate(), kFsStatsBufferLength),
2625+
stats_field_bigint_array(realm->isolate(), kFsStatsBufferLength),
2626+
statfs_field_array(realm->isolate(), kFsStatFsBufferLength),
2627+
statfs_field_bigint_array(realm->isolate(), kFsStatFsBufferLength) {
2628+
Isolate* isolate = realm->isolate();
2629+
Local<Context> context = realm->context();
2630+
wrap->Set(context,
2631+
FIXED_ONE_BYTE_STRING(isolate, "statValues"),
26302632
stats_field_array.GetJSArray())
26312633
.Check();
26322634

2633-
wrap->Set(env->context(),
2634-
FIXED_ONE_BYTE_STRING(env->isolate(), "bigintStatValues"),
2635+
wrap->Set(context,
2636+
FIXED_ONE_BYTE_STRING(isolate, "bigintStatValues"),
26352637
stats_field_bigint_array.GetJSArray())
26362638
.Check();
26372639

2638-
wrap->Set(env->context(),
2639-
FIXED_ONE_BYTE_STRING(env->isolate(), "statFsValues"),
2640+
wrap->Set(context,
2641+
FIXED_ONE_BYTE_STRING(isolate, "statFsValues"),
26402642
statfs_field_array.GetJSArray())
26412643
.Check();
26422644

2643-
wrap->Set(env->context(),
2644-
FIXED_ONE_BYTE_STRING(env->isolate(), "bigintStatFsValues"),
2645+
wrap->Set(context,
2646+
FIXED_ONE_BYTE_STRING(isolate, "bigintStatFsValues"),
26452647
statfs_field_bigint_array.GetJSArray())
26462648
.Check();
26472649
}
@@ -2652,8 +2654,8 @@ void BindingData::Deserialize(Local<Context> context,
26522654
InternalFieldInfoBase* info) {
26532655
DCHECK_EQ(index, BaseObject::kEmbedderType);
26542656
HandleScope scope(context->GetIsolate());
2655-
Environment* env = Environment::GetCurrent(context);
2656-
BindingData* binding = env->AddBindingData<BindingData>(context, holder);
2657+
Realm* realm = Realm::GetCurrent(context);
2658+
BindingData* binding = realm->AddBindingData<BindingData>(context, holder);
26572659
CHECK_NOT_NULL(binding);
26582660
}
26592661

@@ -2682,10 +2684,11 @@ void Initialize(Local<Object> target,
26822684
Local<Value> unused,
26832685
Local<Context> context,
26842686
void* priv) {
2685-
Environment* env = Environment::GetCurrent(context);
2687+
Realm* realm = Realm::GetCurrent(context);
2688+
Environment* env = realm->env();
26862689
Isolate* isolate = env->isolate();
26872690
BindingData* const binding_data =
2688-
env->AddBindingData<BindingData>(context, target);
2691+
realm->AddBindingData<BindingData>(context, target);
26892692
if (binding_data == nullptr) return;
26902693

26912694
SetMethod(context, target, "access", Access);

0 commit comments

Comments
 (0)