Skip to content

Fixes issue with deprecated info.Holder() in latest version of V8. Adds support for Node.js 23 and 24 tests. #1000

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 1 addition & 9 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
steps:
- uses: actions/checkout@v4
- uses: pre-commit/[email protected]

ci:
strategy:
fail-fast: false
Expand All @@ -35,14 +35,6 @@ jobs:
os: ubuntu-24.04-arm # Linux on arm64
- node-version: lts/*
os: windows-2025
- node-version: 14.x
os: windows-2019
- node-version: 12.x
os: windows-2019
- node-version: 10.x
os: windows-2019
- node-version: 8.x
os: windows-2019
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
Expand Down
2 changes: 2 additions & 0 deletions appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ environment:
NODE_GYP_FORCE_PYTHON: C:\Python39-x64\python.exe
matrix: # Test against these versions of Io.js and Node.js.
# - nodejs_version: "23" # Enable after nodejs/nan#979 or similar.
- nodejs_version: "24"
- nodejs_version: "23"
- nodejs_version: "22"
- nodejs_version: "22"
NODE_GYP_FORCE_PYTHON: C:\Python312-x64\python.exe
Expand Down
13 changes: 13 additions & 0 deletions nan_callbacks.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,19 @@ template<typename T> class FunctionCallbackInfo;
template<typename T> class PropertyCallbackInfo;
template<typename T> class Global;

#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 12 || \
(V8_MAJOR_VERSION == 12 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION > 4))
namespace Intercepted {
constexpr v8::Intercepted No() { return v8::Intercepted::kNo; }
constexpr v8::Intercepted Yes() { return v8::Intercepted::kYes; }
};
#else
namespace Intercepted {
inline void No() {}
inline void Yes() {}
};
#endif

typedef void(*FunctionCallback)(const FunctionCallbackInfo<v8::Value>&);
typedef void(*GetterCallback)
(v8::Local<v8::String>, const PropertyCallbackInfo<v8::Value>&);
Expand Down
19 changes: 17 additions & 2 deletions nan_callbacks_12_inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,25 @@ class FunctionCallbackInfo {
}

#if NODE_MAJOR_VERSION < 10
inline v8::Local<v8::Function> Callee() const { return info_.Callee(); }
NAN_DEPRECATED inline v8::Local<v8::Function> Callee() const {
return info_.Callee();
}
#endif
inline v8::Local<v8::Value> Data() const { return data_; }
inline v8::Local<v8::Object> Holder() const { return info_.Holder(); }

inline v8::Local<v8::Object> Holder() const {
#if defined(V8_MAJOR_VERSION) && \
(V8_MAJOR_VERSION > 12 || \
(V8_MAJOR_VERSION == 12 && \
(defined(V8_MINOR_VERSION) && \
(V8_MINOR_VERSION > 5 || \
(V8_MINOR_VERSION == 5 && defined(V8_BUILD_NUMBER) && \
V8_BUILD_NUMBER >= 214)))))
return info_.This();
#else
return info_.Holder();
#endif
}
inline bool IsConstructCall() const { return info_.IsConstructCall(); }
inline int Length() const { return info_.Length(); }
inline v8::Local<v8::Value> operator[](int i) const { return info_[i]; }
Expand Down
8 changes: 6 additions & 2 deletions nan_callbacks_pre_12_inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,13 @@ class FunctionCallbackInfo {
return ReturnValue<T>(return_value_);
}

inline v8::Local<v8::Function> Callee() const { return args_.Callee(); }
NAN_DEPRECATED inline v8::Local<v8::Function> Callee() const {
return args_.Callee();
}
inline v8::Local<v8::Value> Data() const { return data_; }
inline v8::Local<v8::Object> Holder() const { return args_.Holder(); }
inline v8::Local<v8::Object> Holder() const {
return args_.Holder();
}
inline bool IsConstructCall() const { return args_.IsConstructCall(); }
inline int Length() const { return args_.Length(); }
inline v8::Local<v8::Value> operator[](int i) const { return args_[i]; }
Expand Down
7 changes: 7 additions & 0 deletions test/cpp/indexedinterceptors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ NAN_INDEX_GETTER(IndexedInterceptor::PropertyGetter) {
} else {
info.GetReturnValue().Set(Nan::New("bar").ToLocalChecked());
}
return Intercepted::Yes();
}

NAN_INDEX_SETTER(IndexedInterceptor::PropertySetter) {
Expand All @@ -94,28 +95,34 @@ NAN_INDEX_SETTER(IndexedInterceptor::PropertySetter) {
} else {
info.GetReturnValue().Set(info.This());
}
return Intercepted::Yes();
}

NAN_INDEX_ENUMERATOR(IndexedInterceptor::PropertyEnumerator) {
v8::Local<v8::Array> arr = Nan::New<v8::Array>();
Set(arr, 0, Nan::New(42));
info.GetReturnValue().Set(arr);
return Intercepted::Yes();
}

NAN_INDEX_DELETER(IndexedInterceptor::PropertyDeleter) {
IndexedInterceptor* interceptor =
ObjectWrap::Unwrap<IndexedInterceptor>(info.Holder());
std::strncpy(interceptor->buf, "goober", sizeof (interceptor->buf));
info.GetReturnValue().Set(True());
return Intercepted::Yes();
}

NAN_INDEX_QUERY(IndexedInterceptor::PropertyQuery) {
if (index == 1) {
info.GetReturnValue().Set(Nan::New<v8::Integer>(v8::DontEnum));
return Intercepted::Yes();
}
if (index == 42) {
info.GetReturnValue().Set(Nan::New(0));
return Intercepted::Yes();
}
return Intercepted::Yes();
}

NODE_MODULE(indexedinterceptors, IndexedInterceptor::Init)
10 changes: 8 additions & 2 deletions test/cpp/namedinterceptors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ NAN_PROPERTY_GETTER(NamedInterceptor::PropertyGetter) {
} else {
info.GetReturnValue().Set(Nan::New("bar").ToLocalChecked());
}
return Intercepted::Yes();
}

NAN_PROPERTY_SETTER(NamedInterceptor::PropertySetter) {
Expand All @@ -94,6 +95,7 @@ NAN_PROPERTY_SETTER(NamedInterceptor::PropertySetter) {
} else {
info.GetReturnValue().Set(info.This());
}
return Intercepted::Yes();
}

NAN_PROPERTY_ENUMERATOR(NamedInterceptor::PropertyEnumerator) {
Expand All @@ -107,16 +109,20 @@ NAN_PROPERTY_DELETER(NamedInterceptor::PropertyDeleter) {
ObjectWrap::Unwrap<NamedInterceptor>(info.Holder());
std::strncpy(interceptor->buf, "goober", sizeof (interceptor->buf));
info.GetReturnValue().Set(True());
return Intercepted::Yes();
}

NAN_PROPERTY_QUERY(NamedInterceptor::PropertyQuery) {
Nan::Utf8String s(property);
if (!std::strcmp(*s, "thing")) {
return info.GetReturnValue().Set(Nan::New<v8::Integer>(v8::DontEnum));
info.GetReturnValue().Set(Nan::New<v8::Integer>(v8::DontEnum));
return Intercepted::Yes();
}
if (!std::strcmp(*s, "value")) {
return info.GetReturnValue().Set(Nan::New(0));
info.GetReturnValue().Set(Nan::New(0));
return Intercepted::Yes();
}
return Intercepted::Yes();
}

NODE_MODULE(namedinterceptors, NamedInterceptor::Init)
10 changes: 2 additions & 8 deletions test/cpp/news.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,10 +114,7 @@ NAN_METHOD(NewScript) {
}

NAN_METHOD(NewScript2) {
v8::ScriptOrigin origin(
#if NODE_MODULE_VERSION >= NODE_18_0_MODULE_VERSION
info.GetIsolate(),
#endif
ScriptOrigin origin(
New<v8::String>("x").ToLocalChecked());
v8::Local<UnboundScript> script =
New<UnboundScript>(
Expand All @@ -135,10 +132,7 @@ NAN_METHOD(CompileScript) {
}

NAN_METHOD(CompileScript2) {
v8::ScriptOrigin origin(
#if NODE_MODULE_VERSION >= NODE_18_0_MODULE_VERSION
info.GetIsolate(),
#endif
ScriptOrigin origin(
New<v8::String>("x").ToLocalChecked());
v8::Local<BoundScript> script =
CompileScript(New("2+4").ToLocalChecked(), origin).ToLocalChecked();
Expand Down
58 changes: 42 additions & 16 deletions test/js/accessors-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,50 @@
const test = require('tap').test
, testRoot = require('path').resolve(__dirname, '..')
, bindings = require('bindings')({ module_root: testRoot, bindings: 'accessors' });
const nodeVersion = parseInt(process.versions.node.split('.')[0]);

test('accessors', function (t) {
t.plan(7)
var settergetter = bindings.create()
t.equal(settergetter.prop1, 'this is property 1')
t.ok(settergetter.prop2 === '')
settergetter.prop2 = 'setting a value'
t.equal(settergetter.prop2, 'setting a value')
t.equal(settergetter.log(),
'New()\n' +
'Prop1:GETTER(this is property 1)\n' +
'Prop2:GETTER()\n' +
'Prop2:SETTER(setting a value)\n' +
'Prop2:GETTER(setting a value)\n'
)
var derived = Object.create(settergetter)
t.equal(derived.prop1, 'this is property 1')
derived.prop2 = 'setting a new value'
t.equal(derived.prop2, 'setting a new value')
t.equal(settergetter.prop2, 'setting a new value')
if(nodeVersion > 22){
t.plan(9)
t.equal(settergetter.prop1, 'this is property 1')
t.ok(settergetter.prop2 === '')
settergetter.prop2 = 'setting a value'
t.equal(settergetter.prop2, 'setting a value')
t.equal(settergetter.log(),
'New()\n' +
'Prop1:GETTER(this is property 1)\n' +
'Prop2:GETTER()\n' +
'Prop2:SETTER(setting a value)\n' +
'Prop2:GETTER(setting a value)\n'
)
t.equal(derived.prop1, 'this is property 1')
derived.prop2 = 'setting a new value'
t.equal(derived.prop2, 'setting a new value')
t.equal(settergetter.prop2, 'setting a value')
settergetter.prop2 = 'setting another value'
t.equal(settergetter.prop2, 'setting another value')
t.equal(derived.prop2, 'setting a new value')

}
else{
t.plan(7)
t.equal(settergetter.prop1, 'this is property 1')
t.ok(settergetter.prop2 === '')
settergetter.prop2 = 'setting a value'
t.equal(settergetter.prop2, 'setting a value')
t.equal(settergetter.log(),
'New()\n' +
'Prop1:GETTER(this is property 1)\n' +
'Prop2:GETTER()\n' +
'Prop2:SETTER(setting a value)\n' +
'Prop2:GETTER(setting a value)\n'
)
t.equal(derived.prop1, 'this is property 1')
derived.prop2 = 'setting a new value'
t.equal(derived.prop2, 'setting a new value')
t.equal(settergetter.prop2, 'setting a new value')

}
})
57 changes: 41 additions & 16 deletions test/js/methodswithdata-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,30 +9,55 @@
const test = require('tap').test
, testRoot = require('path').resolve(__dirname, '..')
, bindings = require('bindings')({ module_root: testRoot, bindings: 'methodswithdata' })
const nodeVersion = parseInt(process.versions.node.split('.')[0]);

test('SetMethod with data', function (t) {
t.plan(1);
t.ok(bindings.testWithData());
});

test('accessors with data', function (t) {
t.plan(7)
var settergetter = bindings.create()
t.equal(settergetter.prop1, 'this is property 1')
t.ok(settergetter.prop2 === '')
settergetter.prop2 = 'setting a value'
t.equal(settergetter.prop2, 'setting a value')
t.equal(settergetter.log(),
'New()\n' +
'Prop1:GETTER(this is property 1)\n' +
'Prop2:GETTER()\n' +
'Prop2:SETTER(setting a value)\n' +
'Prop2:GETTER(setting a value)\n'
)
var derived = Object.create(settergetter)
t.equal(derived.prop1, 'this is property 1')
derived.prop2 = 'setting a new value'
t.equal(derived.prop2, 'setting a new value')
t.equal(settergetter.prop2, 'setting a new value')
if(nodeVersion > 22){
t.plan(9)
t.equal(settergetter.prop1, 'this is property 1')
t.ok(settergetter.prop2 === '')
settergetter.prop2 = 'setting a value'
t.equal(settergetter.prop2, 'setting a value')
t.equal(settergetter.log(),
'New()\n' +
'Prop1:GETTER(this is property 1)\n' +
'Prop2:GETTER()\n' +
'Prop2:SETTER(setting a value)\n' +
'Prop2:GETTER(setting a value)\n'
)
t.equal(derived.prop1, 'this is property 1')
derived.prop2 = 'setting a new value'
t.equal(derived.prop2, 'setting a new value')
t.equal(settergetter.prop2, 'setting a value')
settergetter.prop2 = 'setting another value'
t.equal(settergetter.prop2, 'setting another value')
t.equal(derived.prop2, 'setting a new value')
}
else{
t.plan(7)
t.equal(settergetter.prop1, 'this is property 1')
t.ok(settergetter.prop2 === '')
settergetter.prop2 = 'setting a value'
t.equal(settergetter.prop2, 'setting a value')
t.equal(settergetter.log(),
'New()\n' +
'Prop1:GETTER(this is property 1)\n' +
'Prop2:GETTER()\n' +
'Prop2:SETTER(setting a value)\n' +
'Prop2:GETTER(setting a value)\n'
)
t.equal(derived.prop1, 'this is property 1')
derived.prop2 = 'setting a new value'
t.equal(derived.prop2, 'setting a new value')
t.equal(settergetter.prop2, 'setting a new value')

}
})

Loading