mirror of
https://github.com/zebrajr/node.git
synced 2026-01-15 12:15:26 +00:00
src: tag v8 aligned pointer slots with embedder data type tags
PR-URL: https://github.com/nodejs/node/pull/60602 Fixes: https://github.com/nodejs/node/issues/60589 Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: Juan José Arboleda <soyjuanarbol@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
This commit is contained in:
@@ -126,10 +126,10 @@ Typical ways of working with internal fields are:
|
||||
* `obj->GetInternalField(i)` to get a JavaScript value from an internal field.
|
||||
* `obj->SetInternalField(i, v)` to store a JavaScript value in an
|
||||
internal field.
|
||||
* `obj->GetAlignedPointerFromInternalField(i)` to get a `void*` pointer from an
|
||||
internal field.
|
||||
* `obj->SetAlignedPointerInInternalField(i, p)` to store a `void*` pointer in an
|
||||
internal field.
|
||||
* `obj->GetAlignedPointerFromInternalField(i, EmbedderDataTag::kDefault)` to get
|
||||
a `void*` pointer from an internal field.
|
||||
* `obj->SetAlignedPointerInInternalField(i, p, EmbedderDataTag::kDefault)` to store
|
||||
a `void*` pointer in an internal field.
|
||||
|
||||
[`Context`][]s provide the same feature under the name “embedder data”.
|
||||
|
||||
|
||||
@@ -74,8 +74,9 @@ bool BaseObject::IsBaseObject(IsolateData* isolate_data,
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16_t* ptr = static_cast<uint16_t*>(
|
||||
obj->GetAlignedPointerFromInternalField(BaseObject::kEmbedderType));
|
||||
uint16_t* ptr =
|
||||
static_cast<uint16_t*>(obj->GetAlignedPointerFromInternalField(
|
||||
BaseObject::kEmbedderType, EmbedderDataTag::kEmbedderType));
|
||||
return ptr == isolate_data->embedder_id_for_non_cppgc();
|
||||
}
|
||||
|
||||
@@ -83,21 +84,24 @@ void BaseObject::TagBaseObject(IsolateData* isolate_data,
|
||||
v8::Local<v8::Object> object) {
|
||||
DCHECK_GE(object->InternalFieldCount(), BaseObject::kInternalFieldCount);
|
||||
object->SetAlignedPointerInInternalField(
|
||||
BaseObject::kEmbedderType, isolate_data->embedder_id_for_non_cppgc());
|
||||
BaseObject::kEmbedderType,
|
||||
isolate_data->embedder_id_for_non_cppgc(),
|
||||
EmbedderDataTag::kEmbedderType);
|
||||
}
|
||||
|
||||
void BaseObject::SetInternalFields(IsolateData* isolate_data,
|
||||
v8::Local<v8::Object> object,
|
||||
void* slot) {
|
||||
TagBaseObject(isolate_data, object);
|
||||
object->SetAlignedPointerInInternalField(BaseObject::kSlot, slot);
|
||||
object->SetAlignedPointerInInternalField(
|
||||
BaseObject::kSlot, slot, EmbedderDataTag::kDefault);
|
||||
}
|
||||
|
||||
BaseObject* BaseObject::FromJSObject(v8::Local<v8::Value> value) {
|
||||
v8::Local<v8::Object> obj = value.As<v8::Object>();
|
||||
DCHECK_GE(obj->InternalFieldCount(), BaseObject::kInternalFieldCount);
|
||||
return static_cast<BaseObject*>(
|
||||
obj->GetAlignedPointerFromInternalField(BaseObject::kSlot));
|
||||
return static_cast<BaseObject*>(obj->GetAlignedPointerFromInternalField(
|
||||
BaseObject::kSlot, EmbedderDataTag::kDefault));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
||||
@@ -45,7 +45,8 @@ BaseObject::~BaseObject() {
|
||||
|
||||
{
|
||||
HandleScope handle_scope(realm()->isolate());
|
||||
object()->SetAlignedPointerInInternalField(BaseObject::kSlot, nullptr);
|
||||
object()->SetAlignedPointerInInternalField(
|
||||
BaseObject::kSlot, nullptr, EmbedderDataTag::kDefault);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <type_traits> // std::remove_reference
|
||||
#include "base_object_types.h"
|
||||
#include "memory_tracker.h"
|
||||
#include "node_v8_embedder.h"
|
||||
#include "util.h"
|
||||
#include "v8.h"
|
||||
|
||||
|
||||
@@ -19,8 +19,10 @@ void CppgcMixin::Wrap(T* ptr, Realm* realm, v8::Local<v8::Object> obj) {
|
||||
v8::Object::Wrap<v8::CppHeapPointerTag::kDefaultTag>(isolate, obj, wrappable);
|
||||
// Keep the layout consistent with BaseObjects.
|
||||
obj->SetAlignedPointerInInternalField(
|
||||
kEmbedderType, realm->isolate_data()->embedder_id_for_cppgc());
|
||||
obj->SetAlignedPointerInInternalField(kSlot, ptr);
|
||||
kEmbedderType,
|
||||
realm->isolate_data()->embedder_id_for_cppgc(),
|
||||
EmbedderDataTag::kEmbedderType);
|
||||
obj->SetAlignedPointerInInternalField(kSlot, ptr, EmbedderDataTag::kDefault);
|
||||
realm->TrackCppgcWrapper(ptr);
|
||||
}
|
||||
|
||||
@@ -41,7 +43,8 @@ T* CppgcMixin::Unwrap(v8::Local<v8::Object> obj) {
|
||||
if (obj->InternalFieldCount() != T::kInternalFieldCount) {
|
||||
return nullptr;
|
||||
}
|
||||
T* ptr = static_cast<T*>(obj->GetAlignedPointerFromInternalField(T::kSlot));
|
||||
T* ptr = static_cast<T*>(obj->GetAlignedPointerFromInternalField(
|
||||
T::kSlot, EmbedderDataTag::kDefault));
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -196,9 +196,8 @@ inline Environment* Environment::GetCurrent(v8::Local<v8::Context> context) {
|
||||
if (!ContextEmbedderTag::IsNodeContext(context)) [[unlikely]] {
|
||||
return nullptr;
|
||||
}
|
||||
return static_cast<Environment*>(
|
||||
context->GetAlignedPointerFromEmbedderData(
|
||||
ContextEmbedderIndex::kEnvironment));
|
||||
return static_cast<Environment*>(context->GetAlignedPointerFromEmbedderData(
|
||||
ContextEmbedderIndex::kEnvironment, EmbedderDataTag::kPerContextData));
|
||||
}
|
||||
|
||||
inline Environment* Environment::GetCurrent(
|
||||
|
||||
20
src/env.cc
20
src/env.cc
@@ -674,12 +674,16 @@ void Environment::AssignToContext(Local<v8::Context> context,
|
||||
Realm* realm,
|
||||
const ContextInfo& info) {
|
||||
context->SetAlignedPointerInEmbedderData(ContextEmbedderIndex::kEnvironment,
|
||||
this);
|
||||
context->SetAlignedPointerInEmbedderData(ContextEmbedderIndex::kRealm, realm);
|
||||
this,
|
||||
EmbedderDataTag::kPerContextData);
|
||||
context->SetAlignedPointerInEmbedderData(
|
||||
ContextEmbedderIndex::kRealm, realm, EmbedderDataTag::kPerContextData);
|
||||
|
||||
// ContextifyContexts will update this to a pointer to the native object.
|
||||
context->SetAlignedPointerInEmbedderData(
|
||||
ContextEmbedderIndex::kContextifyContext, nullptr);
|
||||
ContextEmbedderIndex::kContextifyContext,
|
||||
nullptr,
|
||||
EmbedderDataTag::kPerContextData);
|
||||
|
||||
// This must not be done before other context fields are initialized.
|
||||
ContextEmbedderTag::TagNodeContext(context);
|
||||
@@ -695,11 +699,15 @@ void Environment::AssignToContext(Local<v8::Context> context,
|
||||
void Environment::UnassignFromContext(Local<v8::Context> context) {
|
||||
if (!context.IsEmpty()) {
|
||||
context->SetAlignedPointerInEmbedderData(ContextEmbedderIndex::kEnvironment,
|
||||
nullptr);
|
||||
nullptr,
|
||||
EmbedderDataTag::kPerContextData);
|
||||
context->SetAlignedPointerInEmbedderData(ContextEmbedderIndex::kRealm,
|
||||
nullptr);
|
||||
nullptr,
|
||||
EmbedderDataTag::kPerContextData);
|
||||
context->SetAlignedPointerInEmbedderData(
|
||||
ContextEmbedderIndex::kContextifyContext, nullptr);
|
||||
ContextEmbedderIndex::kContextifyContext,
|
||||
nullptr,
|
||||
EmbedderDataTag::kPerContextData);
|
||||
}
|
||||
UntrackContext(context);
|
||||
}
|
||||
|
||||
@@ -136,7 +136,8 @@ HistogramBase::HistogramBase(
|
||||
MakeWeak();
|
||||
wrap->SetAlignedPointerInInternalField(
|
||||
HistogramImpl::InternalFields::kImplField,
|
||||
static_cast<HistogramImpl*>(this));
|
||||
static_cast<HistogramImpl*>(this),
|
||||
EmbedderDataTag::kDefault);
|
||||
}
|
||||
|
||||
HistogramBase::HistogramBase(
|
||||
@@ -148,7 +149,8 @@ HistogramBase::HistogramBase(
|
||||
MakeWeak();
|
||||
wrap->SetAlignedPointerInInternalField(
|
||||
HistogramImpl::InternalFields::kImplField,
|
||||
static_cast<HistogramImpl*>(this));
|
||||
static_cast<HistogramImpl*>(this),
|
||||
EmbedderDataTag::kDefault);
|
||||
}
|
||||
|
||||
void HistogramBase::MemoryInfo(MemoryTracker* tracker) const {
|
||||
@@ -362,7 +364,8 @@ IntervalHistogram::IntervalHistogram(
|
||||
MakeWeak();
|
||||
wrap->SetAlignedPointerInInternalField(
|
||||
HistogramImpl::InternalFields::kImplField,
|
||||
static_cast<HistogramImpl*>(this));
|
||||
static_cast<HistogramImpl*>(this),
|
||||
EmbedderDataTag::kDefault);
|
||||
uv_timer_init(env->event_loop(), &timer_);
|
||||
}
|
||||
|
||||
@@ -600,8 +603,8 @@ double HistogramImpl::FastGetPercentile(Local<Value> receiver,
|
||||
HistogramImpl* HistogramImpl::FromJSObject(Local<Value> value) {
|
||||
auto obj = value.As<Object>();
|
||||
DCHECK_GE(obj->InternalFieldCount(), HistogramImpl::kInternalFieldCount);
|
||||
return static_cast<HistogramImpl*>(
|
||||
obj->GetAlignedPointerFromInternalField(HistogramImpl::kImplField));
|
||||
return static_cast<HistogramImpl*>(obj->GetAlignedPointerFromInternalField(
|
||||
HistogramImpl::kImplField, EmbedderDataTag::kDefault));
|
||||
}
|
||||
|
||||
std::unique_ptr<worker::TransferData>
|
||||
|
||||
@@ -55,8 +55,9 @@ JSUDPWrap::JSUDPWrap(Environment* env, Local<Object> obj)
|
||||
: AsyncWrap(env, obj, PROVIDER_JSUDPWRAP) {
|
||||
MakeWeak();
|
||||
|
||||
obj->SetAlignedPointerInInternalField(
|
||||
kUDPWrapBaseField, static_cast<UDPWrapBase*>(this));
|
||||
obj->SetAlignedPointerInInternalField(kUDPWrapBaseField,
|
||||
static_cast<UDPWrapBase*>(this),
|
||||
EmbedderDataTag::kDefault);
|
||||
}
|
||||
|
||||
int JSUDPWrap::RecvStart() {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
|
||||
|
||||
#include "node_v8_embedder.h"
|
||||
#include "util.h"
|
||||
#include "v8.h"
|
||||
|
||||
@@ -135,7 +136,8 @@ class ContextEmbedderTag {
|
||||
// context.
|
||||
context->SetAlignedPointerInEmbedderData(
|
||||
ContextEmbedderIndex::kContextTag,
|
||||
ContextEmbedderTag::kNodeContextTagPtr);
|
||||
ContextEmbedderTag::kNodeContextTagPtr,
|
||||
EmbedderDataTag::kPerContextData);
|
||||
}
|
||||
|
||||
static inline bool IsNodeContext(v8::Local<v8::Context> context) {
|
||||
@@ -147,7 +149,8 @@ class ContextEmbedderTag {
|
||||
return false;
|
||||
}
|
||||
if (context->GetAlignedPointerFromEmbedderData(
|
||||
ContextEmbedderIndex::kContextTag) !=
|
||||
ContextEmbedderIndex::kContextTag,
|
||||
EmbedderDataTag::kPerContextData) !=
|
||||
ContextEmbedderTag::kNodeContextTagPtr) [[unlikely]] {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -164,9 +164,12 @@ ContextifyContext::ContextifyContext(Environment* env,
|
||||
// This should only be done after the initial initializations of the context
|
||||
// global object is finished.
|
||||
DCHECK_NULL(v8_context->GetAlignedPointerFromEmbedderData(
|
||||
ContextEmbedderIndex::kContextifyContext));
|
||||
ContextEmbedderIndex::kContextifyContext,
|
||||
EmbedderDataTag::kPerContextData));
|
||||
v8_context->SetAlignedPointerInEmbedderData(
|
||||
ContextEmbedderIndex::kContextifyContext, this);
|
||||
ContextEmbedderIndex::kContextifyContext,
|
||||
this,
|
||||
EmbedderDataTag::kPerContextData);
|
||||
}
|
||||
|
||||
void ContextifyContext::InitializeGlobalTemplates(IsolateData* isolate_data) {
|
||||
@@ -473,7 +476,8 @@ ContextifyContext* ContextifyContext::Get(Local<Object> object) {
|
||||
}
|
||||
return static_cast<ContextifyContext*>(
|
||||
context->GetAlignedPointerFromEmbedderData(
|
||||
ContextEmbedderIndex::kContextifyContext));
|
||||
ContextEmbedderIndex::kContextifyContext,
|
||||
EmbedderDataTag::kPerContextData));
|
||||
}
|
||||
|
||||
bool ContextifyContext::IsStillInitializing(const ContextifyContext* ctx) {
|
||||
|
||||
@@ -49,7 +49,8 @@ class ObjectWrap {
|
||||
assert(handle->InternalFieldCount() > 0);
|
||||
// Cast to ObjectWrap before casting to T. A direct cast from void
|
||||
// to T won't work right when T has more than one base class.
|
||||
void* ptr = handle->GetAlignedPointerFromInternalField(0);
|
||||
void* ptr = handle->GetAlignedPointerFromInternalField(
|
||||
0, v8::kEmbedderDataTypeTagDefault);
|
||||
ObjectWrap* wrap = static_cast<ObjectWrap*>(ptr);
|
||||
return static_cast<T*>(wrap);
|
||||
}
|
||||
@@ -75,7 +76,8 @@ class ObjectWrap {
|
||||
inline void Wrap(v8::Local<v8::Object> handle) {
|
||||
assert(persistent().IsEmpty());
|
||||
assert(handle->InternalFieldCount() > 0);
|
||||
handle->SetAlignedPointerInInternalField(0, this);
|
||||
handle->SetAlignedPointerInInternalField(
|
||||
0, this, v8::kEmbedderDataTypeTagDefault);
|
||||
persistent().Reset(v8::Isolate::GetCurrent(), handle);
|
||||
MakeWeak();
|
||||
}
|
||||
|
||||
@@ -673,7 +673,8 @@ void BindingData::RegisterExternalReferences(
|
||||
BindingData* BindingData::FromV8Value(Local<Value> value) {
|
||||
Local<Object> v8_object = value.As<Object>();
|
||||
return static_cast<BindingData*>(
|
||||
v8_object->GetAlignedPointerFromInternalField(BaseObject::kSlot));
|
||||
v8_object->GetAlignedPointerFromInternalField(BaseObject::kSlot,
|
||||
EmbedderDataTag::kDefault));
|
||||
}
|
||||
|
||||
void BindingData::MemoryInfo(MemoryTracker* tracker) const {
|
||||
|
||||
@@ -20,8 +20,8 @@ inline Realm* Realm::GetCurrent(v8::Local<v8::Context> context) {
|
||||
if (!ContextEmbedderTag::IsNodeContext(context)) [[unlikely]] {
|
||||
return nullptr;
|
||||
}
|
||||
return static_cast<Realm*>(
|
||||
context->GetAlignedPointerFromEmbedderData(ContextEmbedderIndex::kRealm));
|
||||
return static_cast<Realm*>(context->GetAlignedPointerFromEmbedderData(
|
||||
ContextEmbedderIndex::kRealm, EmbedderDataTag::kPerContextData));
|
||||
}
|
||||
|
||||
inline Realm* Realm::GetCurrent(
|
||||
|
||||
@@ -1309,7 +1309,8 @@ StartupData SerializeNodeContextData(Local<Context> holder,
|
||||
case ContextEmbedderIndex::kContextifyContext:
|
||||
case ContextEmbedderIndex::kRealm:
|
||||
case ContextEmbedderIndex::kContextTag: {
|
||||
void* data = holder->GetAlignedPointerFromEmbedderData(index);
|
||||
void* data = holder->GetAlignedPointerFromEmbedderData(
|
||||
index, EmbedderDataTag::kPerContextData);
|
||||
per_process::Debug(
|
||||
DebugCategory::MKSNAPSHOT,
|
||||
"Serialize context data, index=%d, holder=%p, ptr=%p\n",
|
||||
@@ -1400,7 +1401,8 @@ StartupData SerializeNodeContextInternalFields(Local<Object> holder,
|
||||
// For the moment we do not set any internal fields in ArrayBuffer
|
||||
// or ArrayBufferViews, so just return nullptr.
|
||||
if (holder->IsArrayBuffer() || holder->IsArrayBufferView()) {
|
||||
CHECK_NULL(holder->GetAlignedPointerFromInternalField(index));
|
||||
CHECK_NULL(holder->GetAlignedPointerFromInternalField(
|
||||
index, EmbedderDataTag::kDefault));
|
||||
return StartupData{nullptr, 0};
|
||||
}
|
||||
|
||||
@@ -1419,8 +1421,9 @@ StartupData SerializeNodeContextInternalFields(Local<Object> holder,
|
||||
static_cast<int>(index),
|
||||
*holder);
|
||||
|
||||
BaseObject* object_ptr = static_cast<BaseObject*>(
|
||||
holder->GetAlignedPointerFromInternalField(BaseObject::kSlot));
|
||||
BaseObject* object_ptr =
|
||||
static_cast<BaseObject*>(holder->GetAlignedPointerFromInternalField(
|
||||
BaseObject::kSlot, EmbedderDataTag::kDefault));
|
||||
// If the native object is already set to null, ignore it.
|
||||
if (object_ptr == nullptr) {
|
||||
return StartupData{nullptr, 0};
|
||||
|
||||
26
src/node_v8_embedder.h
Normal file
26
src/node_v8_embedder.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef SRC_NODE_V8_EMBEDDER_H_
|
||||
#define SRC_NODE_V8_EMBEDDER_H_
|
||||
|
||||
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace node {
|
||||
|
||||
// Type tags for different kinds of embedder data stored in V8 aligned pointer
|
||||
// slots.
|
||||
enum EmbedderDataTag : uint16_t {
|
||||
// kDefault is used in slots that don't use V8 type tagging.
|
||||
kDefault = 0,
|
||||
// kEmbedderType is used by BaseObject to store the kEmbedderType value.
|
||||
kEmbedderType,
|
||||
// kPerContextData is used to store data on a `v8::Context`, including
|
||||
// slots indexed by ContextEmbedderIndex.
|
||||
kPerContextData,
|
||||
};
|
||||
|
||||
} // namespace node
|
||||
|
||||
#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
|
||||
|
||||
#endif // SRC_NODE_V8_EMBEDDER_H_
|
||||
@@ -22,19 +22,19 @@ void StreamReq::AttachToObject(v8::Local<v8::Object> req_wrap_obj) {
|
||||
StreamReq::kStreamReqField),
|
||||
nullptr);
|
||||
req_wrap_obj->SetAlignedPointerInInternalField(
|
||||
StreamReq::kStreamReqField, this);
|
||||
StreamReq::kStreamReqField, this, EmbedderDataTag::kDefault);
|
||||
}
|
||||
|
||||
StreamReq* StreamReq::FromObject(v8::Local<v8::Object> req_wrap_obj) {
|
||||
return static_cast<StreamReq*>(
|
||||
req_wrap_obj->GetAlignedPointerFromInternalField(
|
||||
StreamReq::kStreamReqField));
|
||||
StreamReq::kStreamReqField, EmbedderDataTag::kDefault));
|
||||
}
|
||||
|
||||
void StreamReq::Dispose() {
|
||||
BaseObjectPtr<AsyncWrap> destroy_me{GetAsyncWrap()};
|
||||
object()->SetAlignedPointerInInternalField(
|
||||
StreamReq::kStreamReqField, nullptr);
|
||||
StreamReq::kStreamReqField, nullptr, EmbedderDataTag::kDefault);
|
||||
destroy_me->Detach();
|
||||
}
|
||||
|
||||
@@ -120,16 +120,16 @@ SimpleWriteWrap<OtherBase>::SimpleWriteWrap(
|
||||
|
||||
void StreamBase::AttachToObject(v8::Local<v8::Object> obj) {
|
||||
obj->SetAlignedPointerInInternalField(
|
||||
StreamBase::kStreamBaseField, this);
|
||||
StreamBase::kStreamBaseField, this, EmbedderDataTag::kDefault);
|
||||
}
|
||||
|
||||
StreamBase* StreamBase::FromObject(v8::Local<v8::Object> obj) {
|
||||
if (obj->GetAlignedPointerFromInternalField(StreamBase::kSlot) == nullptr)
|
||||
if (obj->GetAlignedPointerFromInternalField(
|
||||
StreamBase::kSlot, EmbedderDataTag::kDefault) == nullptr)
|
||||
return nullptr;
|
||||
|
||||
return static_cast<StreamBase*>(
|
||||
obj->GetAlignedPointerFromInternalField(
|
||||
StreamBase::kStreamBaseField));
|
||||
return static_cast<StreamBase*>(obj->GetAlignedPointerFromInternalField(
|
||||
StreamBase::kStreamBaseField, EmbedderDataTag::kDefault));
|
||||
}
|
||||
|
||||
WriteWrap* WriteWrap::FromObject(v8::Local<v8::Object> req_wrap_obj) {
|
||||
@@ -162,8 +162,10 @@ void WriteWrap::SetBackingStore(std::unique_ptr<v8::BackingStore> bs) {
|
||||
void StreamReq::ResetObject(v8::Local<v8::Object> obj) {
|
||||
DCHECK_GT(obj->InternalFieldCount(), StreamReq::kStreamReqField);
|
||||
|
||||
obj->SetAlignedPointerInInternalField(StreamReq::kSlot, nullptr);
|
||||
obj->SetAlignedPointerInInternalField(StreamReq::kStreamReqField, nullptr);
|
||||
obj->SetAlignedPointerInInternalField(
|
||||
StreamReq::kSlot, nullptr, EmbedderDataTag::kDefault);
|
||||
obj->SetAlignedPointerInInternalField(
|
||||
StreamReq::kStreamReqField, nullptr, EmbedderDataTag::kDefault);
|
||||
}
|
||||
|
||||
} // namespace node
|
||||
|
||||
@@ -127,8 +127,8 @@ void UDPWrapBase::set_listener(UDPListener* listener) {
|
||||
|
||||
UDPWrapBase* UDPWrapBase::FromObject(Local<Object> obj) {
|
||||
CHECK_GT(obj->InternalFieldCount(), UDPWrapBase::kUDPWrapBaseField);
|
||||
return static_cast<UDPWrapBase*>(
|
||||
obj->GetAlignedPointerFromInternalField(UDPWrapBase::kUDPWrapBaseField));
|
||||
return static_cast<UDPWrapBase*>(obj->GetAlignedPointerFromInternalField(
|
||||
UDPWrapBase::kUDPWrapBaseField, EmbedderDataTag::kDefault));
|
||||
}
|
||||
|
||||
void UDPWrapBase::AddMethods(Environment* env, Local<FunctionTemplate> t) {
|
||||
@@ -147,8 +147,9 @@ UDPWrap::UDPWrap(Environment* env, Local<Object> object)
|
||||
object,
|
||||
reinterpret_cast<uv_handle_t*>(&handle_),
|
||||
AsyncWrap::PROVIDER_UDPWRAP) {
|
||||
object->SetAlignedPointerInInternalField(
|
||||
UDPWrapBase::kUDPWrapBaseField, static_cast<UDPWrapBase*>(this));
|
||||
object->SetAlignedPointerInInternalField(UDPWrapBase::kUDPWrapBaseField,
|
||||
static_cast<UDPWrapBase*>(this),
|
||||
EmbedderDataTag::kDefault);
|
||||
|
||||
int r = uv_udp_init(env->event_loop(), &handle_);
|
||||
CHECK_EQ(r, 0); // can't fail anyway
|
||||
|
||||
Reference in New Issue
Block a user