From 417d019dc250de20cee46ca1ad56d1654819b0b7 Mon Sep 17 00:00:00 2001 From: Vladimir Morozov Date: Wed, 13 Apr 2022 14:24:13 -0700 Subject: [PATCH] node-api: fix napi_get_all_property_names PR-URL: https://github.com/nodejs/node/pull/42463 Reviewed-By: Michael Dawson Reviewed-By: Chengzhong Wu Reviewed-By: James M Snell --- src/js_native_api_v8.cc | 4 +- test/js-native-api/test_object/test.js | 50 +++++++- test/js-native-api/test_object/test_object.c | 117 +++++++++++++++++++ 3 files changed, 166 insertions(+), 5 deletions(-) diff --git a/src/js_native_api_v8.cc b/src/js_native_api_v8.cc index 611a0521fceab8..54e6c6adf1c4cc 100644 --- a/src/js_native_api_v8.cc +++ b/src/js_native_api_v8.cc @@ -936,8 +936,8 @@ napi_status napi_get_all_property_names(napi_env env, filter | v8::PropertyFilter::ONLY_ENUMERABLE); } if (key_filter & napi_key_configurable) { - filter = static_cast(filter | - v8::PropertyFilter::ONLY_WRITABLE); + filter = static_cast( + filter | v8::PropertyFilter::ONLY_CONFIGURABLE); } if (key_filter & napi_key_skip_strings) { filter = static_cast(filter | diff --git a/test/js-native-api/test_object/test.js b/test/js-native-api/test_object/test.js index 807c920bd46b54..021f45b55f407a 100644 --- a/test/js-native-api/test_object/test.js +++ b/test/js-native-api/test_object/test.js @@ -19,7 +19,7 @@ const object = { assert.strictEqual(test_object.Get(object, 'hello'), 'world'); assert.strictEqual(test_object.GetNamed(object, 'hello'), 'world'); assert.deepStrictEqual(test_object.Get(object, 'array'), - [ 1, 94, 'str', 12.321, { test: 'obj in arr' } ]); + [1, 94, 'str', 12.321, { test: 'obj in arr' }]); assert.deepStrictEqual(test_object.Get(object, 'newObject'), { test: 'obj in obj' }); @@ -54,7 +54,7 @@ assert.strictEqual(newObject.test_string, 'test string'); { // Verify that napi_has_own_property() fails if property is not a name. - [true, false, null, undefined, {}, [], 0, 1, () => {}].forEach((value) => { + [true, false, null, undefined, {}, [], 0, 1, () => { }].forEach((value) => { assert.throws(() => { test_object.HasOwn({}, value); }, /^Error: A string or symbol was expected$/); @@ -240,13 +240,57 @@ assert.strictEqual(newObject.test_string, 'test string'); writable: true, configurable: true }); + Object.defineProperty(object, 'writable', { + value: 4, + enumerable: true, + writable: true, + configurable: false + }); + Object.defineProperty(object, 'configurable', { + value: 4, + enumerable: true, + writable: false, + configurable: true + }); object[5] = 5; assert.deepStrictEqual(test_object.GetPropertyNames(object), - ['5', 'normal', 'inherited']); + ['5', + 'normal', + 'writable', + 'configurable', + 'inherited']); assert.deepStrictEqual(test_object.GetSymbolNames(object), [fooSymbol]); + + assert.deepStrictEqual(test_object.GetEnumerableWritableNames(object), + ['5', + 'normal', + 'writable', + fooSymbol, + 'inherited']); + + assert.deepStrictEqual(test_object.GetOwnWritableNames(object), + ['5', + 'normal', + 'unenumerable', + 'writable', + fooSymbol]); + + assert.deepStrictEqual(test_object.GetEnumerableConfigurableNames(object), + ['5', + 'normal', + 'configurable', + fooSymbol, + 'inherited']); + + assert.deepStrictEqual(test_object.GetOwnConfigurableNames(object), + ['5', + 'normal', + 'unenumerable', + 'configurable', + fooSymbol]); } // Verify that passing NULL to napi_set_property() results in the correct diff --git a/test/js-native-api/test_object/test_object.c b/test/js-native-api/test_object/test_object.c index d897e8d0d041f6..46a99a1e9ee1ed 100644 --- a/test/js-native-api/test_object/test_object.c +++ b/test/js-native-api/test_object/test_object.c @@ -106,6 +106,119 @@ static napi_value GetSymbolNames(napi_env env, napi_callback_info info) { return output; } +static napi_value GetEnumerableWritableNames(napi_env env, + napi_callback_info info) { + size_t argc = 1; + napi_value args[1]; + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + + NODE_API_ASSERT(env, argc >= 1, "Wrong number of arguments"); + + napi_valuetype value_type0; + NODE_API_CALL(env, napi_typeof(env, args[0], &value_type0)); + + NODE_API_ASSERT( + env, + value_type0 == napi_object, + "Wrong type of arguments. Expects an object as first argument."); + + napi_value output; + NODE_API_CALL( + env, + napi_get_all_property_names(env, + args[0], + napi_key_include_prototypes, + napi_key_enumerable | napi_key_writable, + napi_key_numbers_to_strings, + &output)); + + return output; +} + +static napi_value GetOwnWritableNames(napi_env env, napi_callback_info info) { + size_t argc = 1; + napi_value args[1]; + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + + NODE_API_ASSERT(env, argc >= 1, "Wrong number of arguments"); + + napi_valuetype value_type0; + NODE_API_CALL(env, napi_typeof(env, args[0], &value_type0)); + + NODE_API_ASSERT( + env, + value_type0 == napi_object, + "Wrong type of arguments. Expects an object as first argument."); + + napi_value output; + NODE_API_CALL(env, + napi_get_all_property_names(env, + args[0], + napi_key_own_only, + napi_key_writable, + napi_key_numbers_to_strings, + &output)); + + return output; +} + +static napi_value GetEnumerableConfigurableNames(napi_env env, + napi_callback_info info) { + size_t argc = 1; + napi_value args[1]; + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + + NODE_API_ASSERT(env, argc >= 1, "Wrong number of arguments"); + + napi_valuetype value_type0; + NODE_API_CALL(env, napi_typeof(env, args[0], &value_type0)); + + NODE_API_ASSERT( + env, + value_type0 == napi_object, + "Wrong type of arguments. Expects an object as first argument."); + + napi_value output; + NODE_API_CALL( + env, + napi_get_all_property_names(env, + args[0], + napi_key_include_prototypes, + napi_key_enumerable | napi_key_configurable, + napi_key_numbers_to_strings, + &output)); + + return output; +} + +static napi_value GetOwnConfigurableNames(napi_env env, + napi_callback_info info) { + size_t argc = 1; + napi_value args[1]; + NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + + NODE_API_ASSERT(env, argc >= 1, "Wrong number of arguments"); + + napi_valuetype value_type0; + NODE_API_CALL(env, napi_typeof(env, args[0], &value_type0)); + + NODE_API_ASSERT( + env, + value_type0 == napi_object, + "Wrong type of arguments. Expects an object as first argument."); + + napi_value output; + NODE_API_CALL(env, + napi_get_all_property_names(env, + args[0], + napi_key_own_only, + napi_key_configurable, + napi_key_numbers_to_strings, + &output)); + + return output; +} + static napi_value Set(napi_env env, napi_callback_info info) { size_t argc = 3; napi_value args[3]; @@ -536,6 +649,10 @@ napi_value Init(napi_env env, napi_value exports) { DECLARE_NODE_API_PROPERTY("GetNamed", GetNamed), DECLARE_NODE_API_PROPERTY("GetPropertyNames", GetPropertyNames), DECLARE_NODE_API_PROPERTY("GetSymbolNames", GetSymbolNames), + DECLARE_NODE_API_PROPERTY("GetEnumerableWritableNames", GetEnumerableWritableNames), + DECLARE_NODE_API_PROPERTY("GetOwnWritableNames", GetOwnWritableNames), + DECLARE_NODE_API_PROPERTY("GetEnumerableConfigurableNames", GetEnumerableConfigurableNames), + DECLARE_NODE_API_PROPERTY("GetOwnConfigurableNames", GetOwnConfigurableNames), DECLARE_NODE_API_PROPERTY("Set", Set), DECLARE_NODE_API_PROPERTY("SetNamed", SetNamed), DECLARE_NODE_API_PROPERTY("Has", Has),