diff options
author | cjihrig <cjihrig@gmail.com> | 2017-07-03 15:06:46 -0400 |
---|---|---|
committer | cjihrig <cjihrig@gmail.com> | 2017-07-06 15:25:30 -0400 |
commit | 9c6804c1dff0203751dd01da4e226e19de636a71 (patch) | |
tree | 094482a716eb83d81a56658e2725e947a9b15f07 | |
parent | 29df1a87fa230bc86f460620173b9fedd2919f68 (diff) | |
download | android-node-v8-9c6804c1dff0203751dd01da4e226e19de636a71.tar.gz android-node-v8-9c6804c1dff0203751dd01da4e226e19de636a71.tar.bz2 android-node-v8-9c6804c1dff0203751dd01da4e226e19de636a71.zip |
n-api: add napi_has_own_property()
Refs: https://github.com/nodejs/node/issues/13925
PR-URL: https://github.com/nodejs/node/pull/14063
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com>
-rw-r--r-- | doc/api/n-api.md | 24 | ||||
-rw-r--r-- | src/node_api.cc | 21 | ||||
-rw-r--r-- | src/node_api.h | 4 | ||||
-rw-r--r-- | test/addons-napi/test_object/test.js | 34 | ||||
-rw-r--r-- | test/addons-napi/test_object/test_object.c | 29 |
5 files changed, 112 insertions, 0 deletions
diff --git a/doc/api/n-api.md b/doc/api/n-api.md index 16d64d3d5f..ac66f27035 100644 --- a/doc/api/n-api.md +++ b/doc/api/n-api.md @@ -2298,6 +2298,29 @@ Returns `napi_ok` if the API succeeded. This API attempts to delete the `key` own property from `object`. +#### *napi_has_own_property* +<!-- YAML +added: REPLACEME +--> +```C +napi_status napi_has_own_property(napi_env env, + napi_value object, + napi_value key, + bool* result); +``` + +- `[in] env`: The environment that the N-API call is invoked under. +- `[in] object`: The object to query. +- `[in] key`: The name of the own property whose existence to check. +- `[out] result`: Whether the own property exists on the object or not. + +Returns `napi_ok` if the API succeeded. + +This API checks if the Object passed in has the named own property. `key` must +be a string or a Symbol, or an error will be thrown. N-API will not perform any +conversion between data types. + + #### *napi_set_named_property* <!-- YAML added: v8.0.0 @@ -3102,6 +3125,7 @@ support it: [`napi_get_element`]: #n_api_napi_get_element [`napi_get_property`]: #n_api_napi_get_property [`napi_has_property`]: #n_api_napi_has_property +[`napi_has_own_property`]: #n_api_napi_has_own_property [`napi_set_property`]: #n_api_napi_set_property [`napi_get_reference_value`]: #n_api_napi_get_reference_value [`napi_is_error`]: #n_api_napi_is_error diff --git a/src/node_api.cc b/src/node_api.cc index 85b066746d..ffccff5b8e 100644 --- a/src/node_api.cc +++ b/src/node_api.cc @@ -1042,6 +1042,27 @@ napi_status napi_delete_property(napi_env env, return GET_RETURN_STATUS(env); } +NAPI_EXTERN napi_status napi_has_own_property(napi_env env, + napi_value object, + napi_value key, + bool* result) { + NAPI_PREAMBLE(env); + CHECK_ARG(env, key); + + v8::Isolate* isolate = env->isolate; + v8::Local<v8::Context> context = isolate->GetCurrentContext(); + v8::Local<v8::Object> obj; + + CHECK_TO_OBJECT(env, context, obj, object); + v8::Local<v8::Value> k = v8impl::V8LocalValueFromJsValue(key); + RETURN_STATUS_IF_FALSE(env, k->IsName(), napi_name_expected); + v8::Maybe<bool> has_maybe = obj->HasOwnProperty(context, k.As<v8::Name>()); + CHECK_MAYBE_NOTHING(env, has_maybe, napi_generic_failure); + *result = has_maybe.FromMaybe(false); + + return GET_RETURN_STATUS(env); +} + napi_status napi_set_named_property(napi_env env, napi_value object, const char* utf8name, diff --git a/src/node_api.h b/src/node_api.h index 503ea25888..e346b762dd 100644 --- a/src/node_api.h +++ b/src/node_api.h @@ -230,6 +230,10 @@ NAPI_EXTERN napi_status napi_delete_property(napi_env env, napi_value object, napi_value key, bool* result); +NAPI_EXTERN napi_status napi_has_own_property(napi_env env, + napi_value object, + napi_value key, + bool* result); NAPI_EXTERN napi_status napi_set_named_property(napi_env env, napi_value object, const char* utf8name, diff --git a/test/addons-napi/test_object/test.js b/test/addons-napi/test_object/test.js index fe6fb169b6..9e8f17de28 100644 --- a/test/addons-napi/test_object/test.js +++ b/test/addons-napi/test_object/test.js @@ -51,6 +51,40 @@ 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) => { + assert.throws(() => { + test_object.HasOwn({}, value); + }, /^Error: A string or symbol was expected$/); + }); +} + +{ + // Verify that napi_has_own_property() does not walk the prototype chain. + const symbol1 = Symbol(); + const symbol2 = Symbol(); + + function MyObject() { + this.foo = 42; + this.bar = 43; + this[symbol1] = 44; + } + + MyObject.prototype.bar = 45; + MyObject.prototype.baz = 46; + MyObject.prototype[symbol2] = 47; + + const obj = new MyObject(); + + assert.strictEqual(test_object.HasOwn(obj, 'foo'), true); + assert.strictEqual(test_object.HasOwn(obj, 'bar'), true); + assert.strictEqual(test_object.HasOwn(obj, symbol1), true); + assert.strictEqual(test_object.HasOwn(obj, 'baz'), false); + assert.strictEqual(test_object.HasOwn(obj, 'toString'), false); + assert.strictEqual(test_object.HasOwn(obj, symbol2), false); +} + +{ // test_object.Inflate increases all properties by 1 const cube = { x: 10, diff --git a/test/addons-napi/test_object/test_object.c b/test/addons-napi/test_object/test_object.c index ad24d61ca7..96a7aa9c20 100644 --- a/test/addons-napi/test_object/test_object.c +++ b/test/addons-napi/test_object/test_object.c @@ -86,6 +86,34 @@ napi_value Has(napi_env env, napi_callback_info info) { return ret; } +napi_value HasOwn(napi_env env, napi_callback_info info) { + size_t argc = 2; + napi_value args[2]; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + + NAPI_ASSERT(env, argc == 2, "Wrong number of arguments"); + + napi_valuetype valuetype0; + NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0)); + + NAPI_ASSERT(env, valuetype0 == napi_object, + "Wrong type of arguments. Expects an object as first argument."); + + // napi_valuetype valuetype1; + // NAPI_CALL(env, napi_typeof(env, args[1], &valuetype1)); + // + // NAPI_ASSERT(env, valuetype1 == napi_string || valuetype1 == napi_symbol, + // "Wrong type of arguments. Expects a string or symbol as second."); + + bool has_property; + NAPI_CALL(env, napi_has_own_property(env, args[0], args[1], &has_property)); + + napi_value ret; + NAPI_CALL(env, napi_get_boolean(env, has_property, &ret)); + + return ret; +} + napi_value Delete(napi_env env, napi_callback_info info) { size_t argc = 2; napi_value args[2]; @@ -196,6 +224,7 @@ void Init(napi_env env, napi_value exports, napi_value module, void* priv) { DECLARE_NAPI_PROPERTY("Get", Get), DECLARE_NAPI_PROPERTY("Set", Set), DECLARE_NAPI_PROPERTY("Has", Has), + DECLARE_NAPI_PROPERTY("HasOwn", HasOwn), DECLARE_NAPI_PROPERTY("Delete", Delete), DECLARE_NAPI_PROPERTY("New", New), DECLARE_NAPI_PROPERTY("Inflate", Inflate), |