summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcjihrig <cjihrig@gmail.com>2017-07-03 15:06:46 -0400
committercjihrig <cjihrig@gmail.com>2017-07-06 15:25:30 -0400
commit9c6804c1dff0203751dd01da4e226e19de636a71 (patch)
tree094482a716eb83d81a56658e2725e947a9b15f07
parent29df1a87fa230bc86f460620173b9fedd2919f68 (diff)
downloadandroid-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.md24
-rw-r--r--src/node_api.cc21
-rw-r--r--src/node_api.h4
-rw-r--r--test/addons-napi/test_object/test.js34
-rw-r--r--test/addons-napi/test_object/test_object.c29
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),