diff --git a/nan_callbacks_12_inl.h b/nan_callbacks_12_inl.h index ff3b654d..835580dc 100644 --- a/nan_callbacks_12_inl.h +++ b/nan_callbacks_12_inl.h @@ -179,13 +179,30 @@ class PropertyCallbackInfo { }; namespace imp { + +// Recent V8 versions (currently Chromium/Electron's V8 snapshot; not yet in +// any released Node) gained an ExternalPointerTypeTag parameter on +// v8::External::Value(). Detect that API via the V8_EXTERNAL_POINTER_TAG_COUNT +// macro (defined in alongside the new signature) rather than a +// V8_MAJOR_VERSION cutoff, since Node and Chromium ship divergent V8 +// snapshots under the same major version. Externals created by nan use +// kExternalPointerTypeTagDefault (see imp::NewExternal in +// nan_implementation_12_inl.h), so the same tag is used here on read. +inline void* GetExternalPointer(v8::Local ext) { +#ifdef V8_EXTERNAL_POINTER_TAG_COUNT + return ext->Value(v8::kExternalPointerTypeTagDefault); +#else + return ext->Value(); +#endif +} + static void FunctionCallbackWrapper(const v8::FunctionCallbackInfo &info) { v8::Local obj = info.Data().As(); FunctionCallback callback = reinterpret_cast( reinterpret_cast( - obj->GetInternalField(kFunctionIndex) - .As().As()->Value())); + imp::GetExternalPointer(obj->GetInternalField(kFunctionIndex) + .As().As()))); FunctionCallbackInfo cbinfo(info, obj->GetInternalField(kDataIndex).As()); callback(cbinfo); @@ -203,8 +220,8 @@ void GetterCallbackWrapper( cbinfo(info, obj->GetInternalField(kDataIndex).As()); GetterCallback callback = reinterpret_cast( reinterpret_cast( - obj->GetInternalField(kGetterIndex) - .As().As()->Value())); + imp::GetExternalPointer(obj->GetInternalField(kGetterIndex) + .As().As()))); callback(property.As(), cbinfo); } @@ -221,8 +238,8 @@ void SetterCallbackWrapper( cbinfo(info, obj->GetInternalField(kDataIndex).As()); SetterCallback callback = reinterpret_cast( reinterpret_cast( - obj->GetInternalField(kSetterIndex) - .As().As()->Value())); + imp::GetExternalPointer(obj->GetInternalField(kSetterIndex) + .As().As()))); callback(property.As(), value, cbinfo); } @@ -240,8 +257,8 @@ void GetterCallbackWrapper( cbinfo(info, obj->GetInternalField(kDataIndex).As()); GetterCallback callback = reinterpret_cast( reinterpret_cast( - obj->GetInternalField(kGetterIndex) - .As().As()->Value())); + imp::GetExternalPointer(obj->GetInternalField(kGetterIndex) + .As().As()))); callback(property, cbinfo); } @@ -258,8 +275,8 @@ void SetterCallbackWrapper( cbinfo(info, obj->GetInternalField(kDataIndex).As()); SetterCallback callback = reinterpret_cast( reinterpret_cast( - obj->GetInternalField(kSetterIndex) - .As().As()->Value())); + imp::GetExternalPointer(obj->GetInternalField(kSetterIndex) + .As().As()))); callback(property, value, cbinfo); } @@ -282,8 +299,8 @@ v8::Intercepted PropertyGetterCallbackWrapper( cbinfo(info, obj->GetInternalField(kDataIndex).As()); PropertyGetterCallback callback = reinterpret_cast( reinterpret_cast( - obj->GetInternalField(kPropertyGetterIndex) - .As().As()->Value())); + imp::GetExternalPointer(obj->GetInternalField(kPropertyGetterIndex) + .As().As()))); return callback(property.As(), cbinfo); } @@ -300,8 +317,8 @@ v8::Intercepted PropertySetterCallbackWrapper( cbinfo(info, obj->GetInternalField(kDataIndex).As()); PropertySetterCallback callback = reinterpret_cast( reinterpret_cast( - obj->GetInternalField(kPropertySetterIndex) - .As().As()->Value())); + imp::GetExternalPointer(obj->GetInternalField(kPropertySetterIndex) + .As().As()))); return callback(property.As(), value, cbinfo); } @@ -320,8 +337,8 @@ void PropertyGetterCallbackWrapper( cbinfo(info, obj->GetInternalField(kDataIndex).As()); PropertyGetterCallback callback = reinterpret_cast( reinterpret_cast( - obj->GetInternalField(kPropertyGetterIndex) - .As().As()->Value())); + imp::GetExternalPointer(obj->GetInternalField(kPropertyGetterIndex) + .As().As()))); callback(property.As(), cbinfo); } @@ -338,8 +355,8 @@ void PropertySetterCallbackWrapper( cbinfo(info, obj->GetInternalField(kDataIndex).As()); PropertySetterCallback callback = reinterpret_cast( reinterpret_cast( - obj->GetInternalField(kPropertySetterIndex) - .As().As()->Value())); + imp::GetExternalPointer(obj->GetInternalField(kPropertySetterIndex) + .As().As()))); callback(property.As(), value, cbinfo); } @@ -357,8 +374,8 @@ void PropertyEnumeratorCallbackWrapper( cbinfo(info, obj->GetInternalField(kDataIndex).As()); PropertyEnumeratorCallback callback = reinterpret_cast(reinterpret_cast( - obj->GetInternalField(kPropertyEnumeratorIndex) - .As().As()->Value())); + imp::GetExternalPointer(obj->GetInternalField(kPropertyEnumeratorIndex) + .As().As()))); callback(cbinfo); } @@ -376,8 +393,8 @@ v8::Intercepted PropertyDeleterCallbackWrapper( cbinfo(info, obj->GetInternalField(kDataIndex).As()); PropertyDeleterCallback callback = reinterpret_cast( reinterpret_cast( - obj->GetInternalField(kPropertyDeleterIndex) - .As().As()->Value())); + imp::GetExternalPointer(obj->GetInternalField(kPropertyDeleterIndex) + .As().As()))); return callback(property.As(), cbinfo); } @@ -394,8 +411,8 @@ v8::Intercepted PropertyQueryCallbackWrapper( cbinfo(info, obj->GetInternalField(kDataIndex).As()); PropertyQueryCallback callback = reinterpret_cast( reinterpret_cast( - obj->GetInternalField(kPropertyQueryIndex) - .As().As()->Value())); + imp::GetExternalPointer(obj->GetInternalField(kPropertyQueryIndex) + .As().As()))); return callback(property.As(), cbinfo); } @@ -411,8 +428,8 @@ void PropertyDeleterCallbackWrapper( cbinfo(info, obj->GetInternalField(kDataIndex).As()); PropertyDeleterCallback callback = reinterpret_cast( reinterpret_cast( - obj->GetInternalField(kPropertyDeleterIndex) - .As().As()->Value())); + imp::GetExternalPointer(obj->GetInternalField(kPropertyDeleterIndex) + .As().As()))); callback(property.As(), cbinfo); } @@ -428,8 +445,8 @@ void PropertyQueryCallbackWrapper( cbinfo(info, obj->GetInternalField(kDataIndex).As()); PropertyQueryCallback callback = reinterpret_cast( reinterpret_cast( - obj->GetInternalField(kPropertyQueryIndex) - .As().As()->Value())); + imp::GetExternalPointer(obj->GetInternalField(kPropertyQueryIndex) + .As().As()))); callback(property.As(), cbinfo); } @@ -446,8 +463,8 @@ void PropertyGetterCallbackWrapper( cbinfo(info, obj->GetInternalField(kDataIndex).As()); PropertyGetterCallback callback = reinterpret_cast( reinterpret_cast( - obj->GetInternalField(kPropertyGetterIndex) - .As().As()->Value())); + imp::GetExternalPointer(obj->GetInternalField(kPropertyGetterIndex) + .As().As()))); callback(property, cbinfo); } @@ -464,8 +481,8 @@ void PropertySetterCallbackWrapper( cbinfo(info, obj->GetInternalField(kDataIndex).As()); PropertySetterCallback callback = reinterpret_cast( reinterpret_cast( - obj->GetInternalField(kPropertySetterIndex) - .As().As()->Value())); + imp::GetExternalPointer(obj->GetInternalField(kPropertySetterIndex) + .As().As()))); callback(property, value, cbinfo); } @@ -482,8 +499,8 @@ void PropertyEnumeratorCallbackWrapper( cbinfo(info, obj->GetInternalField(kDataIndex).As()); PropertyEnumeratorCallback callback = reinterpret_cast(reinterpret_cast( - obj->GetInternalField(kPropertyEnumeratorIndex) - .As().As()->Value())); + imp::GetExternalPointer(obj->GetInternalField(kPropertyEnumeratorIndex) + .As().As()))); callback(cbinfo); } @@ -499,8 +516,8 @@ void PropertyDeleterCallbackWrapper( cbinfo(info, obj->GetInternalField(kDataIndex).As()); PropertyDeleterCallback callback = reinterpret_cast( reinterpret_cast( - obj->GetInternalField(kPropertyDeleterIndex) - .As().As()->Value())); + imp::GetExternalPointer(obj->GetInternalField(kPropertyDeleterIndex) + .As().As()))); callback(property, cbinfo); } @@ -516,8 +533,8 @@ void PropertyQueryCallbackWrapper( cbinfo(info, obj->GetInternalField(kDataIndex).As()); PropertyQueryCallback callback = reinterpret_cast( reinterpret_cast( - obj->GetInternalField(kPropertyQueryIndex) - .As().As()->Value())); + imp::GetExternalPointer(obj->GetInternalField(kPropertyQueryIndex) + .As().As()))); callback(property, cbinfo); } @@ -535,8 +552,8 @@ v8::Intercepted IndexGetterCallbackWrapper( cbinfo(info, obj->GetInternalField(kDataIndex).As()); IndexGetterCallback callback = reinterpret_cast( reinterpret_cast( - obj->GetInternalField(kIndexPropertyGetterIndex) - .As().As()->Value())); + imp::GetExternalPointer(obj->GetInternalField(kIndexPropertyGetterIndex) + .As().As()))); return callback(index, cbinfo); } @@ -553,8 +570,8 @@ v8::Intercepted IndexSetterCallbackWrapper( cbinfo(info, obj->GetInternalField(kDataIndex).As()); IndexSetterCallback callback = reinterpret_cast( reinterpret_cast( - obj->GetInternalField(kIndexPropertySetterIndex) - .As().As()->Value())); + imp::GetExternalPointer(obj->GetInternalField(kIndexPropertySetterIndex) + .As().As()))); return callback(index, value, cbinfo); } @@ -572,8 +589,8 @@ void IndexGetterCallbackWrapper( cbinfo(info, obj->GetInternalField(kDataIndex).As()); IndexGetterCallback callback = reinterpret_cast( reinterpret_cast( - obj->GetInternalField(kIndexPropertyGetterIndex) - .As().As()->Value())); + imp::GetExternalPointer(obj->GetInternalField(kIndexPropertyGetterIndex) + .As().As()))); callback(index, cbinfo); } @@ -589,8 +606,8 @@ void IndexSetterCallbackWrapper( cbinfo(info, obj->GetInternalField(kDataIndex).As()); IndexSetterCallback callback = reinterpret_cast( reinterpret_cast( - obj->GetInternalField(kIndexPropertySetterIndex) - .As().As()->Value())); + imp::GetExternalPointer(obj->GetInternalField(kIndexPropertySetterIndex) + .As().As()))); callback(index, value, cbinfo); } @@ -609,9 +626,9 @@ void IndexEnumeratorCallbackWrapper( cbinfo(info, obj->GetInternalField(kDataIndex).As()); IndexEnumeratorCallback callback = reinterpret_cast( reinterpret_cast( - obj->GetInternalField( + imp::GetExternalPointer(obj->GetInternalField( kIndexPropertyEnumeratorIndex) - .As().As()->Value())); + .As().As()))); callback(cbinfo); } @@ -628,8 +645,8 @@ v8::Intercepted IndexDeleterCallbackWrapper( cbinfo(info, obj->GetInternalField(kDataIndex).As()); IndexDeleterCallback callback = reinterpret_cast( reinterpret_cast( - obj->GetInternalField(kIndexPropertyDeleterIndex) - .As().As()->Value())); + imp::GetExternalPointer(obj->GetInternalField(kIndexPropertyDeleterIndex) + .As().As()))); return callback(index, cbinfo); } @@ -644,8 +661,8 @@ v8::Intercepted IndexQueryCallbackWrapper( cbinfo(info, obj->GetInternalField(kDataIndex).As()); IndexQueryCallback callback = reinterpret_cast( reinterpret_cast( - obj->GetInternalField(kIndexPropertyQueryIndex) - .As().As()->Value())); + imp::GetExternalPointer(obj->GetInternalField(kIndexPropertyQueryIndex) + .As().As()))); return callback(index, cbinfo); } @@ -660,8 +677,8 @@ void IndexDeleterCallbackWrapper( cbinfo(info, obj->GetInternalField(kDataIndex).As()); IndexDeleterCallback callback = reinterpret_cast( reinterpret_cast( - obj->GetInternalField(kIndexPropertyDeleterIndex) - .As().As()->Value())); + imp::GetExternalPointer(obj->GetInternalField(kIndexPropertyDeleterIndex) + .As().As()))); callback(index, cbinfo); } @@ -676,8 +693,8 @@ void IndexQueryCallbackWrapper( cbinfo(info, obj->GetInternalField(kDataIndex).As()); IndexQueryCallback callback = reinterpret_cast( reinterpret_cast( - obj->GetInternalField(kIndexPropertyQueryIndex) - .As().As()->Value())); + imp::GetExternalPointer(obj->GetInternalField(kIndexPropertyQueryIndex) + .As().As()))); callback(index, cbinfo); } diff --git a/nan_implementation_12_inl.h b/nan_implementation_12_inl.h index 255293ac..79731c76 100644 --- a/nan_implementation_12_inl.h +++ b/nan_implementation_12_inl.h @@ -14,6 +14,22 @@ namespace imp { +// Recent V8 versions (currently Chromium/Electron's V8 snapshot; not yet in +// any released Node) gained an ExternalPointerTypeTag parameter on +// v8::External::New(). Detect that API via the V8_EXTERNAL_POINTER_TAG_COUNT +// macro (defined in alongside the new signature) rather than +// a V8_MAJOR_VERSION cutoff, since Node and Chromium ship divergent V8 +// snapshots under the same major version. Externals created via this helper +// are read back through imp::GetExternalPointer in nan_callbacks_12_inl.h, +// which uses the matching kExternalPointerTypeTagDefault tag. +inline v8::Local NewExternal(v8::Isolate* isolate, void* value) { +#ifdef V8_EXTERNAL_POINTER_TAG_COUNT + return v8::External::New(isolate, value, v8::kExternalPointerTypeTagDefault); +#else + return v8::External::New(isolate, value); +#endif +} + //=== Array ==================================================================== Factory::return_t @@ -76,7 +92,7 @@ Factory::New(double value) { Factory::return_t Factory::New(void * value) { - return v8::External::New(v8::Isolate::GetCurrent(), value); + return imp::NewExternal(v8::Isolate::GetCurrent(), value); } //=== Function ================================================================= @@ -92,7 +108,7 @@ Factory::New( FunctionCallback callback obj->SetInternalField( imp::kFunctionIndex - , v8::External::New(isolate, reinterpret_cast(callback))); + , imp::NewExternal(isolate, reinterpret_cast(callback))); v8::Local val = v8::Local::New(isolate, data); @@ -128,7 +144,7 @@ Factory::New( FunctionCallback callback obj->SetInternalField( imp::kFunctionIndex - , v8::External::New(isolate, reinterpret_cast(callback))); + , imp::NewExternal(isolate, reinterpret_cast(callback))); v8::Local val = v8::Local::New(isolate, data); if (!val.IsEmpty()) { diff --git a/test/cpp/nannew.cpp b/test/cpp/nannew.cpp index e36ce4f8..267b6b21 100644 --- a/test/cpp/nannew.cpp +++ b/test/cpp/nannew.cpp @@ -136,7 +136,11 @@ NAN_METHOD(testExternal) { t.plan(2); +#ifdef V8_EXTERNAL_POINTER_TAG_COUNT + t.ok(_(New(&ttt)->Value(v8::kExternalPointerTypeTagDefault) == &ttt)); +#else t.ok(_(New(&ttt)->Value() == &ttt)); +#endif t.ok(_( assertType(New(&ttt)))); info.GetReturnValue().SetUndefined(); diff --git a/test/cpp/news.cpp b/test/cpp/news.cpp index 3597f0fc..c966af37 100644 --- a/test/cpp/news.cpp +++ b/test/cpp/news.cpp @@ -93,7 +93,12 @@ NAN_METHOD(NewBooleanObject) { NAN_METHOD(NewExternal) { v8::Local ext = New(&magic); +#ifdef V8_EXTERNAL_POINTER_TAG_COUNT + assert(*static_cast( + ext->Value(v8::kExternalPointerTypeTagDefault)) == 1337); +#else assert(*static_cast(ext->Value()) == 1337); +#endif info.GetReturnValue().Set(New("passed").ToLocalChecked()); }