Skip to content

Commit 298ff8d

Browse files
JoseExpositomhdawson
authored andcommitted
test: add additional tests for Object
Test that Object::GetPropertyNames does not return properties whose key is a Symbol PR-URL: #923 Reviewed-By: Michael Dawson <[email protected]> Reviewed-By: NickNaso <[email protected]>
1 parent 8a1147b commit 298ff8d

File tree

6 files changed

+144
-10
lines changed

6 files changed

+144
-10
lines changed

test/binding.gyp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
'object/has_property.cc',
3636
'object/object.cc',
3737
'object/set_property.cc',
38+
'object/subscript_operator.cc',
3839
'promise.cc',
3940
'run_script.cc',
4041
'threadsafe_function/threadsafe_function_ctx.cc',

test/object/get_property.js

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,27 @@ function test(binding) {
1212
assert.strictEqual(nativeGetProperty(obj, 'test'), 1);
1313
}
1414

15+
function testShouldReturnUndefinedIfKeyIsNotPresent(nativeGetProperty) {
16+
const obj = { };
17+
assert.strictEqual(nativeGetProperty(obj, 'test'), undefined);
18+
}
19+
1520
function testShouldThrowErrorIfKeyIsInvalid(nativeGetProperty) {
1621
assert.throws(() => {
1722
nativeGetProperty(undefined, 'test');
1823
}, /Cannot convert undefined or null to object/);
1924
}
2025

21-
testGetProperty(binding.object.getPropertyWithNapiValue);
22-
testGetProperty(binding.object.getPropertyWithNapiWrapperValue);
23-
testGetProperty(binding.object.getPropertyWithCStyleString);
24-
testGetProperty(binding.object.getPropertyWithCppStyleString);
26+
const nativeFunctions = [
27+
binding.object.getPropertyWithNapiValue,
28+
binding.object.getPropertyWithNapiWrapperValue,
29+
binding.object.getPropertyWithCStyleString,
30+
binding.object.getPropertyWithCppStyleString
31+
];
2532

26-
testShouldThrowErrorIfKeyIsInvalid(binding.object.getPropertyWithNapiValue);
27-
testShouldThrowErrorIfKeyIsInvalid(binding.object.getPropertyWithNapiWrapperValue);
28-
testShouldThrowErrorIfKeyIsInvalid(binding.object.getPropertyWithCStyleString);
29-
testShouldThrowErrorIfKeyIsInvalid(binding.object.getPropertyWithCppStyleString);
33+
nativeFunctions.forEach((nativeFunction) => {
34+
testGetProperty(nativeFunction);
35+
testShouldReturnUndefinedIfKeyIsNotPresent(nativeFunction);
36+
testShouldThrowErrorIfKeyIsInvalid(nativeFunction);
37+
});
3038
}

test/object/object.cc

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,14 @@ Value HasPropertyWithCppStyleString(const CallbackInfo& info);
3636
Value AddFinalizer(const CallbackInfo& info);
3737
Value AddFinalizerWithHint(const CallbackInfo& info);
3838

39+
// Native wrappers for testing Object::operator []
40+
Value SubscriptGetWithCStyleString(const CallbackInfo& info);
41+
Value SubscriptGetWithCppStyleString(const CallbackInfo& info);
42+
Value SubscriptGetAtIndex(const CallbackInfo& info);
43+
void SubscriptSetWithCStyleString(const CallbackInfo& info);
44+
void SubscriptSetWithCppStyleString(const CallbackInfo& info);
45+
void SubscriptSetAtIndex(const CallbackInfo& info);
46+
3947
static bool testValue = true;
4048
// Used to test void* Data() integrity
4149
struct UserDataHolder {
@@ -69,6 +77,19 @@ Value TestFunctionWithUserData(const CallbackInfo& info) {
6977
return Number::New(info.Env(), holder->value);
7078
}
7179

80+
Value EmptyConstructor(const CallbackInfo& info) {
81+
auto env = info.Env();
82+
bool isEmpty = info[0].As<Boolean>();
83+
Object object = isEmpty ? Object() : Object(env, Object::New(env));
84+
return Boolean::New(env, object.IsEmpty());
85+
}
86+
87+
Value ConstructorFromObject(const CallbackInfo& info) {
88+
auto env = info.Env();
89+
Object object = info[0].As<Object>();
90+
return Object(env, object);
91+
}
92+
7293
Array GetPropertyNames(const CallbackInfo& info) {
7394
Object obj = info[0].As<Object>();
7495
Array arr = obj.GetPropertyNames();
@@ -228,9 +249,18 @@ Value CreateObjectUsingMagic(const CallbackInfo& info) {
228249
return obj;
229250
}
230251

252+
Value InstanceOf(const CallbackInfo& info) {
253+
Object obj = info[0].As<Object>();
254+
Function constructor = info[1].As<Function>();
255+
return Boolean::New(info.Env(), obj.InstanceOf(constructor));
256+
}
257+
231258
Object InitObject(Env env) {
232259
Object exports = Object::New(env);
233260

261+
exports["emptyConstructor"] = Function::New(env, EmptyConstructor);
262+
exports["constructorFromObject"] = Function::New(env, ConstructorFromObject);
263+
234264
exports["GetPropertyNames"] = Function::New(env, GetPropertyNames);
235265
exports["defineProperties"] = Function::New(env, DefineProperties);
236266
exports["defineValueProperty"] = Function::New(env, DefineValueProperty);
@@ -265,5 +295,18 @@ Object InitObject(Env env) {
265295
exports["addFinalizer"] = Function::New(env, AddFinalizer);
266296
exports["addFinalizerWithHint"] = Function::New(env, AddFinalizerWithHint);
267297

298+
exports["instanceOf"] = Function::New(env, InstanceOf);
299+
300+
exports["subscriptGetWithCStyleString"] =
301+
Function::New(env, SubscriptGetWithCStyleString);
302+
exports["subscriptGetWithCppStyleString"] =
303+
Function::New(env, SubscriptGetWithCppStyleString);
304+
exports["subscriptGetAtIndex"] = Function::New(env, SubscriptGetAtIndex);
305+
exports["subscriptSetWithCStyleString"] =
306+
Function::New(env, SubscriptSetWithCStyleString);
307+
exports["subscriptSetWithCppStyleString"] =
308+
Function::New(env, SubscriptSetWithCppStyleString);
309+
exports["subscriptSetAtIndex"] = Function::New(env, SubscriptSetAtIndex);
310+
268311
return exports;
269312
}

test/object/object.js

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,17 @@ function test(binding) {
102102
testDefineProperties('string');
103103
testDefineProperties('value');
104104

105+
{
106+
assert.strictEqual(binding.object.emptyConstructor(true), true);
107+
assert.strictEqual(binding.object.emptyConstructor(false), false);
108+
}
109+
110+
{
111+
const expected = { 'one': 1, 'two': 2, 'three': 3 };
112+
const actual = binding.object.constructorFromObject(expected);
113+
assert.deepStrictEqual(actual, expected);
114+
}
115+
105116
{
106117
const obj = {};
107118
const testSym = Symbol();
@@ -110,9 +121,10 @@ function test(binding) {
110121
}
111122

112123
{
113-
const obj = {'one': 1, 'two': 2, 'three': 3};
124+
const testSym = Symbol();
125+
const obj = { 'one': 1, 'two': 2, 'three': 3, [testSym]: 4 };
114126
var arr = binding.object.GetPropertyNames(obj);
115-
assert.deepStrictEqual(arr, ['one', 'two', 'three'])
127+
assert.deepStrictEqual(arr, ['one', 'two', 'three']);
116128
}
117129

118130
{
@@ -136,4 +148,13 @@ function test(binding) {
136148
circular2: magicObject
137149
});
138150
}
151+
152+
{
153+
function Ctor() {};
154+
155+
assert.strictEqual(binding.object.instanceOf(new Ctor(), Ctor), true);
156+
assert.strictEqual(binding.object.instanceOf(new Ctor(), Object), true);
157+
assert.strictEqual(binding.object.instanceOf({}, Ctor), false);
158+
assert.strictEqual(binding.object.instanceOf(null, Ctor), false);
159+
}
139160
}

test/object/subscript_operator.cc

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#include "napi.h"
2+
3+
using namespace Napi;
4+
5+
Value SubscriptGetWithCStyleString(const CallbackInfo& info) {
6+
Object obj = info[0].As<Object>();
7+
String jsKey = info[1].As<String>();
8+
return obj[jsKey.Utf8Value().c_str()];
9+
}
10+
11+
Value SubscriptGetWithCppStyleString(const CallbackInfo& info) {
12+
Object obj = info[0].As<Object>();
13+
String jsKey = info[1].As<String>();
14+
return obj[jsKey.Utf8Value()];
15+
}
16+
17+
Value SubscriptGetAtIndex(const CallbackInfo& info) {
18+
Object obj = info[0].As<Object>();
19+
uint32_t index = info[1].As<Napi::Number>();
20+
return obj[index];
21+
}
22+
23+
void SubscriptSetWithCStyleString(const CallbackInfo& info) {
24+
Object obj = info[0].As<Object>();
25+
String jsKey = info[1].As<String>();
26+
Value value = info[2];
27+
obj[jsKey.Utf8Value().c_str()] = value;
28+
}
29+
30+
void SubscriptSetWithCppStyleString(const CallbackInfo& info) {
31+
Object obj = info[0].As<Object>();
32+
String jsKey = info[1].As<String>();
33+
Value value = info[2];
34+
obj[jsKey.Utf8Value()] = value;
35+
}
36+
37+
void SubscriptSetAtIndex(const CallbackInfo& info) {
38+
Object obj = info[0].As<Object>();
39+
uint32_t index = info[1].As<Napi::Number>();
40+
Value value = info[2];
41+
obj[index] = value;
42+
}

test/object/subscript_operator.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
'use strict';
2+
3+
const buildType = process.config.target_defaults.default_configuration;
4+
const assert = require('assert');
5+
6+
test(require(`../build/${buildType}/binding.node`));
7+
test(require(`../build/${buildType}/binding_noexcept.node`));
8+
9+
function test(binding) {
10+
function testProperty(obj, key, value, nativeGetProperty, nativeSetProperty) {
11+
nativeSetProperty(obj, key, value);
12+
assert.strictEqual(nativeGetProperty(obj, key), value);
13+
}
14+
15+
testProperty({}, 'key', 'value', binding.object.subscriptGetWithCStyleString, binding.object.subscriptSetWithCStyleString);
16+
testProperty({ key: 'override me' }, 'key', 'value', binding.object.subscriptGetWithCppStyleString, binding.object.subscriptSetWithCppStyleString);
17+
testProperty({}, 0, 'value', binding.object.subscriptGetAtIndex, binding.object.subscriptSetAtIndex);
18+
testProperty({ key: 'override me' }, 0, 'value', binding.object.subscriptGetAtIndex, binding.object.subscriptSetAtIndex);
19+
}

0 commit comments

Comments
 (0)