Skip to content

Commit d3f62e3

Browse files
romandevmhdawson
authored andcommitted
Fix a crash when setter is nullpta
In the current implementation, if we want to make a readonly property, we should pass empty setter that is actual function but has no body as follows: void HelloSetter(const Npai::CallbackInfo& info, const Npai::Value& value) { // This is an empty setter to make a readonly property. // Do nothing } InstanceAccessor("hello_property", &HelloGetter, &HelloSetter); If we allows taking `nullptr` as the argument, we can simplify user's code more as follows: InstanceAccessor("hello_property", &HelloGetter, nullptr); Currently, above code makes a crash. So, this patch makes InstanceAccessor() take `nullptr` as the argument and then add some tests for them. PR-URL: #159 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Michael Dawson <[email protected]> Reviewed-By: Jason Ginchereau <[email protected]>
1 parent 4173b09 commit d3f62e3

File tree

3 files changed

+54
-11
lines changed

3 files changed

+54
-11
lines changed

napi-inl.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2562,8 +2562,8 @@ inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceAccessor(
25622562

25632563
napi_property_descriptor desc = {};
25642564
desc.utf8name = utf8name;
2565-
desc.getter = T::InstanceGetterCallbackWrapper;
2566-
desc.setter = T::InstanceSetterCallbackWrapper;
2565+
desc.getter = getter != nullptr ? T::InstanceGetterCallbackWrapper : nullptr;
2566+
desc.setter = setter != nullptr ? T::InstanceSetterCallbackWrapper : nullptr;
25672567
desc.data = callbackData;
25682568
desc.attributes = attributes;
25692569
return desc;

test/objectwrap.cc

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,23 +27,34 @@ class Test : public Napi::ObjectWrap<Test> {
2727
Napi::ObjectWrap<Test>(info) {
2828
}
2929

30-
void Set(const Napi::CallbackInfo& info) {
30+
void SetMethod(const Napi::CallbackInfo& info) {
3131
value = info[0].As<Napi::Number>();
3232
}
3333

34-
Napi::Value Get(const Napi::CallbackInfo& info) {
34+
Napi::Value GetMethod(const Napi::CallbackInfo& info) {
3535
return Napi::Number::New(info.Env(), value);
3636
}
3737

3838
Napi::Value Iter(const Napi::CallbackInfo& info) {
3939
return TestIter::Constructor.New({});
4040
}
4141

42+
void Setter(const Napi::CallbackInfo& info, const Napi::Value& new_value) {
43+
value = new_value.As<Napi::Number>();
44+
}
45+
46+
Napi::Value Getter(const Napi::CallbackInfo& info) {
47+
return Napi::Number::New(info.Env(), value);
48+
}
49+
4250
static void Initialize(Napi::Env env, Napi::Object exports) {
4351
exports.Set("Test", DefineClass(env, "Test", {
44-
InstanceMethod("test_set", &Test::Set),
45-
InstanceMethod("test_get", &Test::Get),
46-
InstanceMethod(Napi::Symbol::WellKnown(env, "iterator"), &Test::Iter)
52+
InstanceMethod("test_set_method", &Test::SetMethod),
53+
InstanceMethod("test_get_method", &Test::GetMethod),
54+
InstanceMethod(Napi::Symbol::WellKnown(env, "iterator"), &Test::Iter),
55+
InstanceAccessor("test_getter_only", &Test::Getter, nullptr),
56+
InstanceAccessor("test_setter_only", nullptr, &Test::Setter),
57+
InstanceAccessor("test_getter_setter", &Test::Getter, &Test::Setter),
4758
}));
4859
}
4960

test/objectwrap.js

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,51 @@ test(require(`./build/${buildType}/binding_noexcept.node`));
88
function test(binding) {
99
var Test = binding.objectwrap.Test;
1010

11-
function testSetGet(obj) {
12-
obj.test_set(90);
13-
assert.strictEqual(obj.test_get(), 90);
11+
function testSetGetMethod(obj) {
12+
obj.test_set_method(90);
13+
assert.strictEqual(obj.test_get_method(), 90);
1414
}
1515

1616
function testIter(obj) {
1717
for (const value of obj) {
1818
}
1919
}
2020

21+
function testGetterOnly(obj) {
22+
obj.test_set_method(91);
23+
assert.strictEqual(obj.test_getter_only, 91);
24+
25+
let error;
26+
try {
27+
// Can not assign to read only property.
28+
obj.test_getter_only = 92;
29+
} catch(e) {
30+
error = e;
31+
} finally {
32+
assert.strictEqual(error.name, 'TypeError');
33+
}
34+
}
35+
36+
function testSetterOnly(obj) {
37+
obj.test_setter_only = 93;
38+
assert.strictEqual(obj.test_setter_only, undefined);
39+
assert.strictEqual(obj.test_getter_only, 93);
40+
}
41+
42+
function testGetterSetter(obj) {
43+
obj.test_getter_setter = 94;
44+
assert.strictEqual(obj.test_getter_setter, 94);
45+
46+
obj.test_getter_setter = 95;
47+
assert.strictEqual(obj.test_getter_setter, 95);
48+
}
49+
2150
function testObj(obj) {
22-
testSetGet(obj);
51+
testSetGetMethod(obj);
2352
testIter(obj);
53+
testGetterOnly(obj);
54+
testSetterOnly(obj);
55+
testGetterSetter(obj);
2456
}
2557

2658
testObj(new Test());

0 commit comments

Comments
 (0)