Skip to content

Commit 2ff3173

Browse files
committed
fixup! squash! src: retrieve binding data from the context
1 parent a3e1371 commit 2ff3173

20 files changed

+127
-111
lines changed

src/README.md

+13-8
Original file line numberDiff line numberDiff line change
@@ -400,16 +400,22 @@ NODE_MODULE_CONTEXT_AWARE_INTERNAL(cares_wrap, Initialize)
400400

401401
Some internal bindings, such as the HTTP parser, maintain internal state that
402402
only affects that particular binding. In that case, one common way to store
403-
that state is through the use of `Environment::BindingScope`, which gives all
404-
new functions created within it access to an object for storing such state.
403+
that state is through the use of `Environment::AddBindingData`, which gives
404+
binding functions access to an object for storing such state.
405405
That object is always a [`BaseObject`][].
406406

407+
Its class needs to have a static `binding_data_name` field that based on a
408+
constant string, in order to disambiguate it from other classes of this type,
409+
and which could e.g. match the binding’s name.
410+
407411
```c++
408412
// In the HTTP parser source code file:
409413
class BindingData : public BaseObject {
410414
public:
411415
BindingData(Environment* env, Local<Object> obj) : BaseObject(env, obj) {}
412416

417+
static constexpr FastStringKey binding_data_name { "http_parser" };
418+
413419
std::vector<char> parser_buffer;
414420
bool parser_buffer_in_use = false;
415421

@@ -422,18 +428,17 @@ static void New(const FunctionCallbackInfo<Value>& args) {
422428
new Parser(binding_data, args.This());
423429
}
424430

425-
// ... because the initialization function told the Environment to use this
426-
// BindingData class for all functions created by it:
431+
// ... because the initialization function told the Environment to store the
432+
// BindingData object:
427433
void InitializeHttpParser(Local<Object> target,
428434
Local<Value> unused,
429435
Local<Context> context,
430436
void* priv) {
431437
Environment* env = Environment::GetCurrent(context);
432-
Environment::BindingScope<BindingData> binding_scope(context, target);
433-
if (!binding_scope) return;
434-
BindingData* binding_data = binding_scope.data;
438+
BindingData* const binding_data =
439+
env->AddBindingData<BindingData>(context, target);
440+
if (binding_data == nullptr) return;
435441

436-
// Created within the Environment::BindingScope
437442
Local<FunctionTemplate> t = env->NewFunctionTemplate(Parser::New);
438443
...
439444
}

src/env-inl.h

+13-37
Original file line numberDiff line numberDiff line change
@@ -333,58 +333,43 @@ inline Environment* Environment::GetCurrent(
333333

334334
template <typename T, typename U>
335335
inline T* Environment::GetBindingData(const v8::PropertyCallbackInfo<U>& info) {
336-
return GetBindingData<T>(info.GetIsolate()->GetCurrentContext(), info.Data());
336+
return GetBindingData<T>(info.GetIsolate()->GetCurrentContext());
337337
}
338338

339339
template <typename T>
340340
inline T* Environment::GetBindingData(
341341
const v8::FunctionCallbackInfo<v8::Value>& info) {
342-
return GetBindingData<T>(info.GetIsolate()->GetCurrentContext(), info.Data());
342+
return GetBindingData<T>(info.GetIsolate()->GetCurrentContext());
343343
}
344344

345345
template <typename T>
346-
inline T* Environment::GetBindingData(v8::Local<v8::Context> context,
347-
v8::Local<v8::Value> val) {
348-
DCHECK(val->IsUint32());
349-
uint32_t index = val.As<v8::Uint32>()->Value();
350-
BindingDataList* list = static_cast<BindingDataList*>(
346+
inline T* Environment::GetBindingData(v8::Local<v8::Context> context) {
347+
BindingDataStore* list = static_cast<BindingDataStore*>(
351348
context->GetAlignedPointerFromEmbedderData(
352349
ContextEmbedderIndex::kBindingListIndex));
353350
DCHECK_NOT_NULL(list);
354-
DCHECK_GT(list->size(), index);
355-
T* result = static_cast<T*>(list->at(index).get());
351+
auto it = list->find(T::binding_data_name);
352+
DCHECK_NE(it, list->end());
353+
T* result = static_cast<T*>(it->second.get());
356354
DCHECK_NOT_NULL(result);
357355
DCHECK_EQ(result->env(), GetCurrent(context));
358356
return result;
359357
}
360358

361359
template <typename T>
362-
inline std::pair<T*, uint32_t> Environment::NewBindingData(
360+
inline T* Environment::AddBindingData(
363361
v8::Local<v8::Context> context,
364362
v8::Local<v8::Object> target) {
365363
DCHECK_EQ(GetCurrent(context), this);
366364
// This won't compile if T is not a BaseObject subclass.
367365
BaseObjectPtr<T> item = MakeDetachedBaseObject<T>(this, target);
368-
BindingDataList* list = static_cast<BindingDataList*>(
366+
BindingDataStore* list = static_cast<BindingDataStore*>(
369367
context->GetAlignedPointerFromEmbedderData(
370368
ContextEmbedderIndex::kBindingListIndex));
371369
DCHECK_NOT_NULL(list);
372-
size_t index = list->size();
373-
list->emplace_back(item);
374-
return std::make_pair(item.get(), index);
375-
}
376-
377-
template <typename T>
378-
Environment::BindingScope<T>::BindingScope(v8::Local<v8::Context> context,
379-
v8::Local<v8::Object> target)
380-
: env(Environment::GetCurrent(context)) {
381-
std::tie(data, env->current_callback_data_) =
382-
env->NewBindingData<T>(context, target);
383-
}
384-
385-
template <typename T>
386-
Environment::BindingScope<T>::~BindingScope() {
387-
env->current_callback_data_ = env->default_callback_data_;
370+
auto result = list->emplace(T::binding_data_name, item);
371+
CHECK(result.second);
372+
return item.get();
388373
}
389374

390375
inline Environment* Environment::GetThreadLocalEnv() {
@@ -1103,8 +1088,7 @@ inline v8::Local<v8::FunctionTemplate>
11031088
v8::Local<v8::Signature> signature,
11041089
v8::ConstructorBehavior behavior,
11051090
v8::SideEffectType side_effect_type) {
1106-
v8::Local<v8::Value> external = current_callback_data();
1107-
return v8::FunctionTemplate::New(isolate(), callback, external,
1091+
return v8::FunctionTemplate::New(isolate(), callback, v8::Local<v8::Value>(),
11081092
signature, 0, behavior, side_effect_type);
11091093
}
11101094

@@ -1300,14 +1284,6 @@ v8::Local<v8::Context> Environment::context() const {
13001284
return PersistentToLocal::Strong(context_);
13011285
}
13021286

1303-
v8::Local<v8::Value> Environment::as_callback_data() const {
1304-
return v8::Integer::NewFromUnsigned(isolate(), default_callback_data_);
1305-
}
1306-
1307-
v8::Local<v8::Value> Environment::current_callback_data() const {
1308-
return v8::Integer::NewFromUnsigned(isolate(), current_callback_data_);
1309-
}
1310-
13111287
} // namespace node
13121288

13131289
// These two files depend on each other. Including base_object-inl.h after this

src/env.cc

-15
Original file line numberDiff line numberDiff line change
@@ -261,16 +261,6 @@ void TrackingTraceStateObserver::UpdateTraceCategoryState() {
261261
USE(cb->Call(env_->context(), Undefined(isolate), arraysize(args), args));
262262
}
263263

264-
class NoBindingData : public BaseObject {
265-
public:
266-
NoBindingData(Environment* env, Local<Object> obj)
267-
: BaseObject(env, obj) {}
268-
269-
SET_NO_MEMORY_INFO()
270-
SET_MEMORY_INFO_NAME(NoBindingData)
271-
SET_SELF_SIZE(NoBindingData)
272-
};
273-
274264
void Environment::CreateProperties() {
275265
HandleScope handle_scope(isolate_);
276266
Local<Context> ctx = context();
@@ -282,11 +272,6 @@ void Environment::CreateProperties() {
282272
BaseObject::kInternalFieldCount);
283273

284274
set_binding_data_ctor_template(templ);
285-
Local<Function> ctor = templ->GetFunction(ctx).ToLocalChecked();
286-
Local<Object> obj = ctor->NewInstance(ctx).ToLocalChecked();
287-
uint32_t index = NewBindingData<NoBindingData>(ctx, obj).second;
288-
default_callback_data_ = index;
289-
current_callback_data_ = index;
290275
}
291276

292277
// Store primordials setup by the per-context script in the environment.

src/env.h

+9-30
Original file line numberDiff line numberDiff line change
@@ -864,38 +864,22 @@ class Environment : public MemoryRetainer {
864864

865865
// Methods created using SetMethod(), SetPrototypeMethod(), etc. inside
866866
// this scope can access the created T* object using
867-
// GetBindingData<T>(args.Data()) later.
867+
// GetBindingData<T>(args) later.
868868
template <typename T>
869-
struct BindingScope {
870-
explicit inline BindingScope(v8::Local<v8::Context> context,
871-
v8::Local<v8::Object> target);
872-
inline ~BindingScope();
873-
874-
T* data = nullptr;
875-
Environment* env;
876-
877-
inline operator bool() const { return data != nullptr; }
878-
inline bool operator !() const { return data == nullptr; }
879-
};
880-
869+
T* AddBindingData(v8::Local<v8::Context> context,
870+
v8::Local<v8::Object> target);
881871
template <typename T, typename U>
882872
static inline T* GetBindingData(const v8::PropertyCallbackInfo<U>& info);
883873
template <typename T>
884874
static inline T* GetBindingData(
885875
const v8::FunctionCallbackInfo<v8::Value>& info);
886-
887-
// Unwrap a subclass T object from a v8::Value which needs to be an
888-
// v8::Uint32
889-
template <typename T>
890-
static inline T* GetBindingData(v8::Local<v8::Context> context,
891-
v8::Local<v8::Value> val);
892-
// Create a BindingData of subclass T, put it into the context binding list,
893-
// return the index as an integer
894876
template <typename T>
895-
inline std::pair<T*, uint32_t> NewBindingData(v8::Local<v8::Context> context,
896-
v8::Local<v8::Object> target);
877+
static inline T* GetBindingData(v8::Local<v8::Context> context);
897878

898-
typedef std::vector<BaseObjectPtr<BaseObject>> BindingDataList;
879+
typedef std::unordered_map<
880+
FastStringKey,
881+
BaseObjectPtr<BaseObject>,
882+
FastStringKey::Hash> BindingDataStore;
899883

900884
static uv_key_t thread_local_env;
901885
static inline Environment* GetThreadLocalEnv();
@@ -1146,8 +1130,6 @@ class Environment : public MemoryRetainer {
11461130
#undef V
11471131

11481132
inline v8::Local<v8::Context> context() const;
1149-
inline v8::Local<v8::Value> as_callback_data() const;
1150-
inline v8::Local<v8::Value> current_callback_data() const;
11511133

11521134
#if HAVE_INSPECTOR
11531135
inline inspector::Agent* inspector_agent() const {
@@ -1443,7 +1425,7 @@ class Environment : public MemoryRetainer {
14431425
void RequestInterruptFromV8();
14441426
static void CheckImmediate(uv_check_t* handle);
14451427

1446-
BindingDataList bindings_;
1428+
BindingDataStore bindings_;
14471429

14481430
// Use an unordered_set, so that we have efficient insertion and removal.
14491431
std::unordered_set<CleanupHookCallback,
@@ -1469,9 +1451,6 @@ class Environment : public MemoryRetainer {
14691451

14701452
v8::Global<v8::Context> context_;
14711453

1472-
uint32_t default_callback_data_;
1473-
uint32_t current_callback_data_;
1474-
14751454
// Keeps the main script source alive is one was passed to LoadEnvironment().
14761455
// We should probably find a way to just use plain `v8::String`s created from
14771456
// the source passed to LoadEnvironment() directly instead.

src/fs_event_wrap.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ void FSEventWrap::Initialize(Local<Object> target,
108108
Local<FunctionTemplate> get_initialized_templ =
109109
FunctionTemplate::New(env->isolate(),
110110
GetInitialized,
111-
env->current_callback_data(),
111+
Local<Value>(),
112112
Signature::New(env->isolate(), t));
113113

114114
t->PrototypeTemplate()->SetAccessorProperty(

src/node.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ MaybeLocal<Value> Environment::BootstrapNode() {
331331

332332
Local<String> env_string = FIXED_ONE_BYTE_STRING(isolate_, "env");
333333
Local<Object> env_var_proxy;
334-
if (!CreateEnvVarProxy(context(), isolate_, current_callback_data())
334+
if (!CreateEnvVarProxy(context(), isolate_, Local<Value>())
335335
.ToLocal(&env_var_proxy) ||
336336
process_object()->Set(context(), env_string, env_var_proxy).IsNothing()) {
337337
return MaybeLocal<Value>();

src/node_crypto.cc

+2-2
Original file line numberDiff line numberDiff line change
@@ -505,7 +505,7 @@ void SecureContext::Initialize(Environment* env, Local<Object> target) {
505505
Local<FunctionTemplate> ctx_getter_templ =
506506
FunctionTemplate::New(env->isolate(),
507507
CtxGetter,
508-
env->current_callback_data(),
508+
Local<Value>(),
509509
Signature::New(env->isolate(), t));
510510

511511

@@ -5103,7 +5103,7 @@ void DiffieHellman::Initialize(Environment* env, Local<Object> target) {
51035103
Local<FunctionTemplate> verify_error_getter_templ =
51045104
FunctionTemplate::New(env->isolate(),
51055105
DiffieHellman::VerifyErrorGetter,
5106-
env->current_callback_data(),
5106+
Local<Value>(),
51075107
Signature::New(env->isolate(), t),
51085108
/* length */ 0,
51095109
ConstructorBehavior::kThrow,

src/node_file.cc

+6-3
Original file line numberDiff line numberDiff line change
@@ -2303,15 +2303,18 @@ void BindingData::MemoryInfo(MemoryTracker* tracker) const {
23032303
file_handle_read_wrap_freelist);
23042304
}
23052305

2306+
// TODO(addaleax): Remove once we're on C++17.
2307+
constexpr FastStringKey BindingData::binding_data_name;
2308+
23062309
void Initialize(Local<Object> target,
23072310
Local<Value> unused,
23082311
Local<Context> context,
23092312
void* priv) {
23102313
Environment* env = Environment::GetCurrent(context);
23112314
Isolate* isolate = env->isolate();
2312-
Environment::BindingScope<BindingData> binding_scope(context, target);
2313-
if (!binding_scope) return;
2314-
BindingData* binding_data = binding_scope.data;
2315+
BindingData* const binding_data =
2316+
env->AddBindingData<BindingData>(context, target);
2317+
if (binding_data == nullptr) return;
23152318

23162319
env->SetMethod(target, "access", Access);
23172320
env->SetMethod(target, "close", Close);

src/node_file.h

+2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ class BindingData : public BaseObject {
2626
std::vector<BaseObjectPtr<FileHandleReadWrap>>
2727
file_handle_read_wrap_freelist;
2828

29+
static constexpr FastStringKey binding_data_name { "fs" };
30+
2931
void MemoryInfo(MemoryTracker* tracker) const override;
3032
SET_SELF_SIZE(BindingData)
3133
SET_MEMORY_INFO_NAME(BindingData)

src/node_http2.cc

+5-3
Original file line numberDiff line numberDiff line change
@@ -2941,6 +2941,9 @@ void Http2State::MemoryInfo(MemoryTracker* tracker) const {
29412941
tracker->TrackField("root_buffer", root_buffer);
29422942
}
29432943

2944+
// TODO(addaleax): Remove once we're on C++17.
2945+
constexpr FastStringKey Http2State::binding_data_name;
2946+
29442947
// Set up the process.binding('http2') binding.
29452948
void Initialize(Local<Object> target,
29462949
Local<Value> unused,
@@ -2950,9 +2953,8 @@ void Initialize(Local<Object> target,
29502953
Isolate* isolate = env->isolate();
29512954
HandleScope handle_scope(isolate);
29522955

2953-
Environment::BindingScope<Http2State> binding_scope(context, target);
2954-
if (!binding_scope) return;
2955-
Http2State* state = binding_scope.data;
2956+
Http2State* const state = env->AddBindingData<Http2State>(context, target);
2957+
if (state == nullptr) return;
29562958

29572959
#define SET_STATE_TYPEDARRAY(name, field) \
29582960
target->Set(context, \

src/node_http2_state.h

+2
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,8 @@ class Http2State : public BaseObject {
126126
SET_SELF_SIZE(Http2State)
127127
SET_MEMORY_INFO_NAME(Http2State)
128128

129+
static constexpr FastStringKey binding_data_name { "http2" };
130+
129131
private:
130132
struct http2_state_internal {
131133
// doubles first so that they are always sizeof(double)-aligned

src/node_http_parser.cc

+8-2
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ class BindingData : public BaseObject {
8787
BindingData(Environment* env, Local<Object> obj)
8888
: BaseObject(env, obj) {}
8989

90+
static constexpr FastStringKey binding_data_name { "http_parser" };
91+
9092
std::vector<char> parser_buffer;
9193
bool parser_buffer_in_use = false;
9294

@@ -97,6 +99,9 @@ class BindingData : public BaseObject {
9799
SET_MEMORY_INFO_NAME(BindingData)
98100
};
99101

102+
// TODO(addaleax): Remove once we're on C++17.
103+
constexpr FastStringKey BindingData::binding_data_name;
104+
100105
// helper class for the Parser
101106
struct StringPtr {
102107
StringPtr() {
@@ -921,8 +926,9 @@ void InitializeHttpParser(Local<Object> target,
921926
Local<Context> context,
922927
void* priv) {
923928
Environment* env = Environment::GetCurrent(context);
924-
Environment::BindingScope<BindingData> binding_scope(context, target);
925-
if (!binding_scope) return;
929+
BindingData* const binding_data =
930+
env->AddBindingData<BindingData>(context, target);
931+
if (binding_data == nullptr) return;
926932

927933
Local<FunctionTemplate> t = env->NewFunctionTemplate(Parser::New);
928934
t->InstanceTemplate()->SetInternalFieldCount(Parser::kInternalFieldCount);

src/node_native_module_env.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ void NativeModuleEnv::Initialize(Local<Object> target,
190190
FIXED_ONE_BYTE_STRING(env->isolate(), "moduleCategories"),
191191
GetModuleCategories,
192192
nullptr,
193-
env->as_callback_data(),
193+
Local<Value>(),
194194
DEFAULT,
195195
None,
196196
SideEffectType::kHasNoSideEffect)

0 commit comments

Comments
 (0)