Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Ginchereau <jasongin@microsoft.com>2017-05-26 03:05:21 +0300
committerJason Ginchereau <jasongin@microsoft.com>2017-06-01 21:46:55 +0300
commit8ab8c33985b273cd682842a26091da53ce3c3048 (patch)
tree7fee259a85ecc33139a4dd12b2de7db7a032674c /test/addons-napi/test_object
parent9b730620a741644d2df7b8c64559a6d2eea7c283 (diff)
n-api: enable napi_wrap() to work with any object
Previously, napi_wrap() would only work with objects created from a constructor returned by napi_define_class(). While the N-API team was aware of this limitation, it was not clearly documented and is likely to cause confusion anyway. It's much simpler if addons are allowed to use any JS object. Also, the specific behavior of the limitation is difficult to reimplement on other VMs that work differently from V8. V8 requires object internal fields to be declared on the object prototype (which napi_define_class() used to do). Since it's too late to modify the object prototype by the time napi_wrap() is called, napi_wrap() now inserts a new object (with the internal field) into the supplied object's prototype chain. Then it can be retrieved from there later by napi_unwrap(). This change also includes improvements to the documentation for napi_create_external(), partly to explain how it is different from napi_wrap(). PR-URL: https://github.com/nodejs/node/pull/13250 Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
Diffstat (limited to 'test/addons-napi/test_object')
-rw-r--r--test/addons-napi/test_object/test.js98
-rw-r--r--test/addons-napi/test_object/test_object.c27
2 files changed, 95 insertions, 30 deletions
diff --git a/test/addons-napi/test_object/test.js b/test/addons-napi/test_object/test.js
index d14a15421fe..4b64fa4b381 100644
--- a/test/addons-napi/test_object/test.js
+++ b/test/addons-napi/test_object/test.js
@@ -31,35 +31,73 @@ assert(test_object.Has(newObject, 'test_number'));
assert.strictEqual(newObject.test_number, 987654321);
assert.strictEqual(newObject.test_string, 'test string');
-// test_object.Inflate increases all properties by 1
-const cube = {
- x: 10,
- y: 10,
- z: 10
-};
+{
+ // test_object.Inflate increases all properties by 1
+ const cube = {
+ x: 10,
+ y: 10,
+ z: 10
+ };
-assert.deepStrictEqual(test_object.Inflate(cube), {x: 11, y: 11, z: 11});
-assert.deepStrictEqual(test_object.Inflate(cube), {x: 12, y: 12, z: 12});
-assert.deepStrictEqual(test_object.Inflate(cube), {x: 13, y: 13, z: 13});
-cube.t = 13;
-assert.deepStrictEqual(test_object.Inflate(cube), {x: 14, y: 14, z: 14, t: 14});
-
-const sym1 = Symbol('1');
-const sym2 = Symbol('2');
-const sym3 = Symbol('3');
-const sym4 = Symbol('4');
-const object2 = {
- [sym1]: '@@iterator',
- [sym2]: sym3
-};
+ assert.deepStrictEqual(test_object.Inflate(cube), {x: 11, y: 11, z: 11});
+ assert.deepStrictEqual(test_object.Inflate(cube), {x: 12, y: 12, z: 12});
+ assert.deepStrictEqual(test_object.Inflate(cube), {x: 13, y: 13, z: 13});
+ cube.t = 13;
+ assert.deepStrictEqual(
+ test_object.Inflate(cube), {x: 14, y: 14, z: 14, t: 14});
+
+ const sym1 = Symbol('1');
+ const sym2 = Symbol('2');
+ const sym3 = Symbol('3');
+ const sym4 = Symbol('4');
+ const object2 = {
+ [sym1]: '@@iterator',
+ [sym2]: sym3
+ };
+
+ assert(test_object.Has(object2, sym1));
+ assert(test_object.Has(object2, sym2));
+ assert.strictEqual(test_object.Get(object2, sym1), '@@iterator');
+ assert.strictEqual(test_object.Get(object2, sym2), sym3);
+ assert(test_object.Set(object2, 'string', 'value'));
+ assert(test_object.Set(object2, sym4, 123));
+ assert(test_object.Has(object2, 'string'));
+ assert(test_object.Has(object2, sym4));
+ assert.strictEqual(test_object.Get(object2, 'string'), 'value');
+ assert.strictEqual(test_object.Get(object2, sym4), 123);
+}
+
+{
+ // Wrap a pointer in a JS object, then verify the pointer can be unwrapped.
+ const wrapper = {};
+ test_object.Wrap(wrapper);
+
+ assert(test_object.Unwrap(wrapper));
+}
+
+{
+ // Verify that wrapping doesn't break an object's prototype chain.
+ const wrapper = {};
+ const protoA = { protoA: true };
+ Object.setPrototypeOf(wrapper, protoA);
+ test_object.Wrap(wrapper);
+
+ assert(test_object.Unwrap(wrapper));
+ assert(wrapper.protoA);
+}
+
+{
+ // Verify the pointer can be unwrapped after inserting in the prototype chain.
+ const wrapper = {};
+ const protoA = { protoA: true };
+ Object.setPrototypeOf(wrapper, protoA);
+ test_object.Wrap(wrapper);
+
+ const protoB = { protoB: true };
+ Object.setPrototypeOf(protoB, Object.getPrototypeOf(wrapper));
+ Object.setPrototypeOf(wrapper, protoB);
-assert(test_object.Has(object2, sym1));
-assert(test_object.Has(object2, sym2));
-assert.strictEqual(test_object.Get(object2, sym1), '@@iterator');
-assert.strictEqual(test_object.Get(object2, sym2), sym3);
-assert(test_object.Set(object2, 'string', 'value'));
-assert(test_object.Set(object2, sym4, 123));
-assert(test_object.Has(object2, 'string'));
-assert(test_object.Has(object2, sym4));
-assert.strictEqual(test_object.Get(object2, 'string'), 'value');
-assert.strictEqual(test_object.Get(object2, sym4), 123);
+ assert(test_object.Unwrap(wrapper));
+ assert(wrapper.protoA, true);
+ assert(wrapper.protoB, true);
+}
diff --git a/test/addons-napi/test_object/test_object.c b/test/addons-napi/test_object/test_object.c
index 9e02c1d0bb7..dd2db123f74 100644
--- a/test/addons-napi/test_object/test_object.c
+++ b/test/addons-napi/test_object/test_object.c
@@ -1,6 +1,7 @@
#include <node_api.h>
#include "../common.h"
#include <string.h>
+#include <stdlib.h>
napi_value Get(napi_env env, napi_callback_info info) {
size_t argc = 2;
@@ -138,6 +139,30 @@ napi_value Inflate(napi_env env, napi_callback_info info) {
return obj;
}
+napi_value Wrap(napi_env env, napi_callback_info info) {
+ size_t argc = 1;
+ napi_value arg;
+ NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &arg, NULL, NULL));
+
+ int32_t* data = malloc(sizeof(int32_t));
+ *data = 3;
+ NAPI_CALL(env, napi_wrap(env, arg, data, NULL, NULL, NULL));
+ return NULL;
+}
+
+napi_value Unwrap(napi_env env, napi_callback_info info) {
+ size_t argc = 1;
+ napi_value arg;
+ NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &arg, NULL, NULL));
+
+ int32_t* data;
+ NAPI_CALL(env, napi_unwrap(env, arg, &data));
+
+ napi_value result;
+ NAPI_CALL(env, napi_get_boolean(env, data != NULL && *data == 3, &result));
+ return result;
+}
+
void Init(napi_env env, napi_value exports, napi_value module, void* priv) {
napi_property_descriptor descriptors[] = {
DECLARE_NAPI_PROPERTY("Get", Get),
@@ -145,6 +170,8 @@ void Init(napi_env env, napi_value exports, napi_value module, void* priv) {
DECLARE_NAPI_PROPERTY("Has", Has),
DECLARE_NAPI_PROPERTY("New", New),
DECLARE_NAPI_PROPERTY("Inflate", Inflate),
+ DECLARE_NAPI_PROPERTY("Wrap", Wrap),
+ DECLARE_NAPI_PROPERTY("Unwrap", Unwrap),
};
NAPI_CALL_RETURN_VOID(env, napi_define_properties(