Skip to content

Commit b5a7a8a

Browse files
authored
Define XxxStream.prototype.onread as an accessor in JavaScript sense (#183)
Previously is was defined via soon-to-be-deprecated `v8::ObjectTemplate::SetAccessor(..)` which used to call setter even for property stores via stream object. The replacement V8 Api `v8::ObjectTemplate::SetNativeDataProperty(..)` defines a properly behaving data property and thus a store to a stream object will not trigger the "onread" setter callback. In order to preserve the desired behavior of storing the value in the receiver's internal field the "onread" property should be defined as a proper JavaScript accessor.
1 parent c8ffbdd commit b5a7a8a

File tree

4 files changed

+48
-19
lines changed

4 files changed

+48
-19
lines changed

src/base_object-inl.h

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -132,19 +132,18 @@ v8::EmbedderGraph::Node::Detachedness BaseObject::GetDetachedness() const {
132132

133133
template <int Field>
134134
void BaseObject::InternalFieldGet(
135-
v8::Local<v8::Name> property,
136-
const v8::PropertyCallbackInfo<v8::Value>& info) {
137-
info.GetReturnValue().Set(
138-
info.This()->GetInternalField(Field).As<v8::Value>());
135+
const v8::FunctionCallbackInfo<v8::Value>& args) {
136+
args.GetReturnValue().Set(
137+
args.This()->GetInternalField(Field).As<v8::Value>());
139138
}
140139

141-
template <int Field, bool (v8::Value::* typecheck)() const>
142-
void BaseObject::InternalFieldSet(v8::Local<v8::Name> property,
143-
v8::Local<v8::Value> value,
144-
const v8::PropertyCallbackInfo<void>& info) {
140+
template <int Field, bool (v8::Value::*typecheck)() const>
141+
void BaseObject::InternalFieldSet(
142+
const v8::FunctionCallbackInfo<v8::Value>& args) {
145143
// This could be e.g. value->IsFunction().
144+
v8::Local<v8::Value> value = args[0];
146145
CHECK(((*value)->*typecheck)());
147-
info.This()->SetInternalField(Field, value);
146+
args.This()->SetInternalField(Field, value);
148147
}
149148

150149
bool BaseObject::has_pointer_data() const {

src/base_object.h

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -111,12 +111,9 @@ class BaseObject : public MemoryRetainer {
111111

112112
// Setter/Getter pair for internal fields that can be passed to SetAccessor.
113113
template <int Field>
114-
static void InternalFieldGet(v8::Local<v8::Name> property,
115-
const v8::PropertyCallbackInfo<v8::Value>& info);
114+
static void InternalFieldGet(const v8::FunctionCallbackInfo<v8::Value>& args);
116115
template <int Field, bool (v8::Value::*typecheck)() const>
117-
static void InternalFieldSet(v8::Local<v8::Name> property,
118-
v8::Local<v8::Value> value,
119-
const v8::PropertyCallbackInfo<void>& info);
116+
static void InternalFieldSet(const v8::FunctionCallbackInfo<v8::Value>& args);
120117

121118
// This is a bit of a hack. See the override in async_wrap.cc for details.
122119
virtual bool IsDoneInitializing() const;

src/stream_base.cc

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,29 @@ Local<Object> StreamBase::GetObject() {
492492
return GetAsyncWrap()->object();
493493
}
494494

495+
void StreamBase::AddAccessor(v8::Isolate* isolate,
496+
v8::Local<v8::Signature> signature,
497+
enum v8::PropertyAttribute attributes,
498+
v8::Local<v8::FunctionTemplate> t,
499+
JSMethodFunction* getter,
500+
JSMethodFunction* setter,
501+
v8::Local<v8::String> string) {
502+
Local<FunctionTemplate> getter_templ =
503+
NewFunctionTemplate(isolate,
504+
getter,
505+
signature,
506+
ConstructorBehavior::kThrow,
507+
SideEffectType::kHasNoSideEffect);
508+
Local<FunctionTemplate> setter_templ =
509+
NewFunctionTemplate(isolate,
510+
setter,
511+
signature,
512+
ConstructorBehavior::kThrow,
513+
SideEffectType::kHasSideEffect);
514+
t->PrototypeTemplate()->SetAccessorProperty(
515+
string, getter_templ, setter_templ, attributes);
516+
}
517+
495518
void StreamBase::AddMethod(Isolate* isolate,
496519
Local<Signature> signature,
497520
enum PropertyAttribute attributes,
@@ -561,11 +584,14 @@ void StreamBase::AddMethods(IsolateData* isolate_data,
561584
JSMethod<&StreamBase::WriteString<LATIN1>>);
562585
t->PrototypeTemplate()->Set(FIXED_ONE_BYTE_STRING(isolate, "isStreamBase"),
563586
True(isolate));
564-
t->PrototypeTemplate()->SetAccessor(
565-
FIXED_ONE_BYTE_STRING(isolate, "onread"),
566-
BaseObject::InternalFieldGet<StreamBase::kOnReadFunctionField>,
567-
BaseObject::InternalFieldSet<StreamBase::kOnReadFunctionField,
568-
&Value::IsFunction>);
587+
AddAccessor(isolate,
588+
sig,
589+
static_cast<PropertyAttribute>(DontDelete | DontEnum),
590+
t,
591+
BaseObject::InternalFieldGet<StreamBase::kOnReadFunctionField>,
592+
BaseObject::InternalFieldSet<StreamBase::kOnReadFunctionField,
593+
&Value::IsFunction>,
594+
FIXED_ONE_BYTE_STRING(isolate, "onread"));
569595
}
570596

571597
void StreamBase::RegisterExternalReferences(

src/stream_base.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,13 @@ class StreamBase : public StreamResource {
413413
EmitToJSStreamListener default_listener_;
414414

415415
void SetWriteResult(const StreamWriteResult& res);
416+
static void AddAccessor(v8::Isolate* isolate,
417+
v8::Local<v8::Signature> sig,
418+
enum v8::PropertyAttribute attributes,
419+
v8::Local<v8::FunctionTemplate> t,
420+
JSMethodFunction* getter,
421+
JSMethodFunction* setter,
422+
v8::Local<v8::String> str);
416423
static void AddMethod(v8::Isolate* isolate,
417424
v8::Local<v8::Signature> sig,
418425
enum v8::PropertyAttribute attributes,

0 commit comments

Comments
 (0)