Skip to content

Commit c979aea

Browse files
jasnelltargos
authored andcommitted
src: improve handling of internal field counting
Change suggested by bnoordhuis. Improve handing of internal field counting by using enums. Helps protect against future possible breakage if field indexes are ever changed or added to. Signed-off-by: James M Snell <jasnell@gmail.com> PR-URL: #31960 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
1 parent 0847bc3 commit c979aea

40 files changed

+151
-92
lines changed

src/async_wrap.cc

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,10 @@ void AsyncWrap::EmitAfter(Environment* env, double async_id) {
175175

176176
class PromiseWrap : public AsyncWrap {
177177
public:
178+
enum InternalFields {
179+
kIsChainedPromiseField = AsyncWrap::kInternalFieldCount,
180+
kInternalFieldCount
181+
};
178182
PromiseWrap(Environment* env, Local<Object> object, bool silent)
179183
: AsyncWrap(env, object, PROVIDER_PROMISE, kInvalidAsyncId, silent) {
180184
MakeWeak();
@@ -184,9 +188,6 @@ class PromiseWrap : public AsyncWrap {
184188
SET_MEMORY_INFO_NAME(PromiseWrap)
185189
SET_SELF_SIZE(PromiseWrap)
186190

187-
static constexpr int kIsChainedPromiseField = 1;
188-
static constexpr int kInternalFieldCount = 2;
189-
190191
static PromiseWrap* New(Environment* env,
191192
Local<Promise> promise,
192193
PromiseWrap* parent_wrap,
@@ -213,15 +214,16 @@ PromiseWrap* PromiseWrap::New(Environment* env,
213214
void PromiseWrap::getIsChainedPromise(Local<String> property,
214215
const PropertyCallbackInfo<Value>& info) {
215216
info.GetReturnValue().Set(
216-
info.Holder()->GetInternalField(kIsChainedPromiseField));
217+
info.Holder()->GetInternalField(PromiseWrap::kIsChainedPromiseField));
217218
}
218219

219220
static PromiseWrap* extractPromiseWrap(Local<Promise> promise) {
220-
Local<Value> resource_object_value = promise->GetInternalField(0);
221-
if (resource_object_value->IsObject()) {
222-
return Unwrap<PromiseWrap>(resource_object_value.As<Object>());
223-
}
224-
return nullptr;
221+
// This check is imperfect. If the internal field is set, it should
222+
// be an object. If it's not, we just ignore it. Ideally v8 would
223+
// have had GetInternalField returning a MaybeLocal but this works
224+
// for now.
225+
Local<Value> obj = promise->GetInternalField(0);
226+
return obj->IsObject() ? Unwrap<PromiseWrap>(obj.As<Object>()) : nullptr;
225227
}
226228

227229
static void PromiseHook(PromiseHookType type, Local<Promise> promise,
@@ -566,7 +568,7 @@ void AsyncWrap::Initialize(Local<Object> target,
566568
function_template->SetClassName(class_name);
567569
function_template->Inherit(AsyncWrap::GetConstructorTemplate(env));
568570
auto instance_template = function_template->InstanceTemplate();
569-
instance_template->SetInternalFieldCount(1);
571+
instance_template->SetInternalFieldCount(AsyncWrap::kInternalFieldCount);
570572
auto function =
571573
function_template->GetFunction(env->context()).ToLocalChecked();
572574
target->Set(env->context(), class_name, function).Check();

src/base_object-inl.h

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@ BaseObject::BaseObject(Environment* env, v8::Local<v8::Object> object)
4343
: persistent_handle_(env->isolate(), object), env_(env) {
4444
CHECK_EQ(false, object.IsEmpty());
4545
CHECK_GT(object->InternalFieldCount(), 0);
46-
object->SetAlignedPointerInInternalField(0, static_cast<void*>(this));
46+
object->SetAlignedPointerInInternalField(
47+
BaseObject::kSlot,
48+
static_cast<void*>(this));
4749
env->AddCleanupHook(DeleteMe, static_cast<void*>(this));
4850
env->modify_base_object_count(1);
4951
}
@@ -67,7 +69,7 @@ BaseObject::~BaseObject() {
6769

6870
{
6971
v8::HandleScope handle_scope(env()->isolate());
70-
object()->SetAlignedPointerInInternalField(0, nullptr);
72+
object()->SetAlignedPointerInInternalField(BaseObject::kSlot, nullptr);
7173
}
7274
}
7375

@@ -100,7 +102,8 @@ Environment* BaseObject::env() const {
100102

101103
BaseObject* BaseObject::FromJSObject(v8::Local<v8::Object> obj) {
102104
CHECK_GT(obj->InternalFieldCount(), 0);
103-
return static_cast<BaseObject*>(obj->GetAlignedPointerFromInternalField(0));
105+
return static_cast<BaseObject*>(
106+
obj->GetAlignedPointerFromInternalField(BaseObject::kSlot));
104107
}
105108

106109

@@ -148,11 +151,12 @@ BaseObject::MakeLazilyInitializedJSTemplate(Environment* env) {
148151
auto constructor = [](const v8::FunctionCallbackInfo<v8::Value>& args) {
149152
DCHECK(args.IsConstructCall());
150153
DCHECK_GT(args.This()->InternalFieldCount(), 0);
151-
args.This()->SetAlignedPointerInInternalField(0, nullptr);
154+
args.This()->SetAlignedPointerInInternalField(BaseObject::kSlot, nullptr);
152155
};
153156

154157
v8::Local<v8::FunctionTemplate> t = env->NewFunctionTemplate(constructor);
155-
t->InstanceTemplate()->SetInternalFieldCount(1);
158+
t->InstanceTemplate()->SetInternalFieldCount(
159+
BaseObject::kInternalFieldCount);
156160
return t;
157161
}
158162

src/base_object.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ class BaseObjectPtrImpl;
3636

3737
class BaseObject : public MemoryRetainer {
3838
public:
39+
enum InternalFields { kSlot, kInternalFieldCount };
40+
3941
// Associates this object with `object`. It uses the 0th internal field for
4042
// that, and in particular aborts if there is no such field.
4143
inline BaseObject(Environment* env, v8::Local<v8::Object> object);

src/cares_wrap.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2224,7 +2224,8 @@ void Initialize(Local<Object> target,
22242224

22252225
Local<FunctionTemplate> channel_wrap =
22262226
env->NewFunctionTemplate(ChannelWrap::New);
2227-
channel_wrap->InstanceTemplate()->SetInternalFieldCount(1);
2227+
channel_wrap->InstanceTemplate()->SetInternalFieldCount(
2228+
ChannelWrap::kInternalFieldCount);
22282229
channel_wrap->Inherit(AsyncWrap::GetConstructorTemplate(env));
22292230

22302231
env->SetProtoMethod(channel_wrap, "queryAny", Query<QueryAnyWrap>);

src/fs_event_wrap.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,8 @@ void FSEventWrap::Initialize(Local<Object> target,
9797

9898
auto fsevent_string = FIXED_ONE_BYTE_STRING(env->isolate(), "FSEvent");
9999
Local<FunctionTemplate> t = env->NewFunctionTemplate(New);
100-
t->InstanceTemplate()->SetInternalFieldCount(1);
100+
t->InstanceTemplate()->SetInternalFieldCount(
101+
FSEventWrap::kInternalFieldCount);
101102
t->SetClassName(fsevent_string);
102103

103104
t->Inherit(AsyncWrap::GetConstructorTemplate(env));

src/heap_utils.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ BaseObjectPtr<AsyncWrap> CreateHeapSnapshotStream(
341341
Local<FunctionTemplate> os = FunctionTemplate::New(env->isolate());
342342
os->Inherit(AsyncWrap::GetConstructorTemplate(env));
343343
Local<ObjectTemplate> ost = os->InstanceTemplate();
344-
ost->SetInternalFieldCount(StreamBase::kStreamBaseFieldCount);
344+
ost->SetInternalFieldCount(StreamBase::kInternalFieldCount);
345345
os->SetClassName(
346346
FIXED_ONE_BYTE_STRING(env->isolate(), "HeapSnapshotStream"));
347347
StreamBase::AddMethods(env, os);

src/inspector_js_api.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,8 @@ class JSBindingsConnection : public AsyncWrap {
105105
Local<String> class_name = ConnectionType::GetClassName(env);
106106
Local<FunctionTemplate> tmpl =
107107
env->NewFunctionTemplate(JSBindingsConnection::New);
108-
tmpl->InstanceTemplate()->SetInternalFieldCount(1);
108+
tmpl->InstanceTemplate()->SetInternalFieldCount(
109+
JSBindingsConnection::kInternalFieldCount);
109110
tmpl->SetClassName(class_name);
110111
tmpl->Inherit(AsyncWrap::GetConstructorTemplate(env));
111112
env->SetProtoMethod(tmpl, "dispatch", JSBindingsConnection::Dispatch);

src/js_stream.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ void JSStream::Initialize(Local<Object> target,
204204
FIXED_ONE_BYTE_STRING(env->isolate(), "JSStream");
205205
t->SetClassName(jsStreamString);
206206
t->InstanceTemplate()
207-
->SetInternalFieldCount(StreamBase::kStreamBaseFieldCount);
207+
->SetInternalFieldCount(StreamBase::kInternalFieldCount);
208208
t->Inherit(AsyncWrap::GetConstructorTemplate(env));
209209

210210
env->SetProtoMethod(t, "finishWrite", Finish<WriteWrap>);

src/module_wrap.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1639,7 +1639,8 @@ void ModuleWrap::Initialize(Local<Object> target,
16391639

16401640
Local<FunctionTemplate> tpl = env->NewFunctionTemplate(New);
16411641
tpl->SetClassName(FIXED_ONE_BYTE_STRING(isolate, "ModuleWrap"));
1642-
tpl->InstanceTemplate()->SetInternalFieldCount(1);
1642+
tpl->InstanceTemplate()->SetInternalFieldCount(
1643+
ModuleWrap::kInternalFieldCount);
16431644

16441645
env->SetProtoMethod(tpl, "link", Link);
16451646
env->SetProtoMethod(tpl, "instantiate", Instantiate);

src/node_contextify.cc

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ MaybeLocal<Object> ContextifyContext::CreateDataWrapper(Environment* env) {
142142
return MaybeLocal<Object>();
143143
}
144144

145-
wrapper->SetAlignedPointerInInternalField(0, this);
145+
wrapper->SetAlignedPointerInInternalField(ContextifyContext::kSlot, this);
146146
return wrapper;
147147
}
148148

@@ -229,7 +229,8 @@ MaybeLocal<Context> ContextifyContext::CreateV8Context(
229229
void ContextifyContext::Init(Environment* env, Local<Object> target) {
230230
Local<FunctionTemplate> function_template =
231231
FunctionTemplate::New(env->isolate());
232-
function_template->InstanceTemplate()->SetInternalFieldCount(1);
232+
function_template->InstanceTemplate()->SetInternalFieldCount(
233+
ContextifyContext::kInternalFieldCount);
233234
env->set_script_data_constructor_function(
234235
function_template->GetFunction(env->context()).ToLocalChecked());
235236

@@ -328,7 +329,8 @@ template <typename T>
328329
ContextifyContext* ContextifyContext::Get(const PropertyCallbackInfo<T>& args) {
329330
Local<Value> data = args.Data();
330331
return static_cast<ContextifyContext*>(
331-
data.As<Object>()->GetAlignedPointerFromInternalField(0));
332+
data.As<Object>()->GetAlignedPointerFromInternalField(
333+
ContextifyContext::kSlot));
332334
}
333335

334336
// static
@@ -625,7 +627,8 @@ void ContextifyScript::Init(Environment* env, Local<Object> target) {
625627
FIXED_ONE_BYTE_STRING(env->isolate(), "ContextifyScript");
626628

627629
Local<FunctionTemplate> script_tmpl = env->NewFunctionTemplate(New);
628-
script_tmpl->InstanceTemplate()->SetInternalFieldCount(1);
630+
script_tmpl->InstanceTemplate()->SetInternalFieldCount(
631+
ContextifyScript::kInternalFieldCount);
629632
script_tmpl->SetClassName(class_name);
630633
env->SetProtoMethod(script_tmpl, "createCachedData", CreateCachedData);
631634
env->SetProtoMethod(script_tmpl, "runInContext", RunInContext);
@@ -1220,7 +1223,8 @@ void Initialize(Local<Object> target,
12201223
{
12211224
Local<FunctionTemplate> tpl = FunctionTemplate::New(env->isolate());
12221225
tpl->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "CompiledFnEntry"));
1223-
tpl->InstanceTemplate()->SetInternalFieldCount(1);
1226+
tpl->InstanceTemplate()->SetInternalFieldCount(
1227+
CompiledFnEntry::kInternalFieldCount);
12241228

12251229
env->set_compiled_fn_entry_template(tpl->InstanceTemplate());
12261230
}

0 commit comments

Comments
 (0)