Upload Kmake

This commit is contained in:
Gorochu
2026-05-26 23:36:42 -07:00
parent ba051b2f74
commit 555ec72358
41615 changed files with 13344630 additions and 1 deletions

View File

@ -0,0 +1,17 @@
{
"targets": [
{
"target_name": "test_object",
"sources": [
"test_null.c",
"test_object.c"
]
},
{
"target_name": "test_exceptions",
"sources": [
"test_exceptions.c",
]
}
]
}

View File

@ -0,0 +1,393 @@
'use strict';
const common = require('../../common');
const assert = require('assert');
// Testing api calls for objects
const test_object = require(`./build/${common.buildType}/test_object`);
const object = {
hello: 'world',
array: [
1, 94, 'str', 12.321, { test: 'obj in arr' },
],
newObject: {
test: 'obj in obj',
},
};
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' }]);
assert.deepStrictEqual(test_object.Get(object, 'newObject'),
{ test: 'obj in obj' });
assert(test_object.Has(object, 'hello'));
assert(test_object.HasNamed(object, 'hello'));
assert(test_object.Has(object, 'array'));
assert(test_object.Has(object, 'newObject'));
const newObject = test_object.New();
assert(test_object.Has(newObject, 'test_number'));
assert.strictEqual(newObject.test_number, 987654321);
assert.strictEqual(newObject.test_string, 'test string');
{
// Verify that napi_get_property() walks the prototype chain.
function MyObject() {
this.foo = 42;
this.bar = 43;
}
MyObject.prototype.bar = 44;
MyObject.prototype.baz = 45;
const obj = new MyObject();
assert.strictEqual(test_object.Get(obj, 'foo'), 42);
assert.strictEqual(test_object.Get(obj, 'bar'), 43);
assert.strictEqual(test_object.Get(obj, 'baz'), 45);
assert.strictEqual(test_object.Get(obj, 'toString'),
Object.prototype.toString);
}
{
// 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,
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(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.SetNamed(object2, 'named_string', 'value'));
assert(test_object.Set(object2, sym4, 123));
assert(test_object.Has(object2, 'string'));
assert(test_object.HasNamed(object2, 'named_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.Unwrap(wrapper));
assert(wrapper.protoA, true);
assert(wrapper.protoB, true);
}
{
// Verify that objects can be type-tagged and type-tag-checked.
const obj1 = test_object.TypeTaggedInstance(0);
const obj2 = test_object.TypeTaggedInstance(1);
const obj3 = test_object.TypeTaggedInstance(2);
const obj4 = test_object.TypeTaggedInstance(3);
const external = test_object.TypeTaggedExternal(2);
const plainExternal = test_object.PlainExternal();
// Verify that we do not allow type tag indices greater than the largest
// available index.
assert.throws(() => test_object.TypeTaggedInstance(39), {
name: 'RangeError',
message: 'Invalid type index',
});
assert.throws(() => test_object.TypeTaggedExternal(39), {
name: 'RangeError',
message: 'Invalid type index',
});
// Verify that type tags are correctly accepted.
assert.strictEqual(test_object.CheckTypeTag(0, obj1), true);
assert.strictEqual(test_object.CheckTypeTag(1, obj2), true);
assert.strictEqual(test_object.CheckTypeTag(2, obj3), true);
assert.strictEqual(test_object.CheckTypeTag(3, obj4), true);
assert.strictEqual(test_object.CheckTypeTag(2, external), true);
// Verify that wrongly tagged objects are rejected.
assert.strictEqual(test_object.CheckTypeTag(0, obj2), false);
assert.strictEqual(test_object.CheckTypeTag(1, obj1), false);
assert.strictEqual(test_object.CheckTypeTag(0, obj3), false);
assert.strictEqual(test_object.CheckTypeTag(1, obj4), false);
assert.strictEqual(test_object.CheckTypeTag(2, obj4), false);
assert.strictEqual(test_object.CheckTypeTag(3, obj3), false);
assert.strictEqual(test_object.CheckTypeTag(4, obj3), false);
assert.strictEqual(test_object.CheckTypeTag(0, external), false);
assert.strictEqual(test_object.CheckTypeTag(1, external), false);
assert.strictEqual(test_object.CheckTypeTag(3, external), false);
assert.strictEqual(test_object.CheckTypeTag(4, external), false);
// Verify that untagged objects are rejected.
assert.strictEqual(test_object.CheckTypeTag(0, {}), false);
assert.strictEqual(test_object.CheckTypeTag(1, {}), false);
assert.strictEqual(test_object.CheckTypeTag(0, plainExternal), false);
assert.strictEqual(test_object.CheckTypeTag(1, plainExternal), false);
assert.strictEqual(test_object.CheckTypeTag(2, plainExternal), false);
assert.strictEqual(test_object.CheckTypeTag(3, plainExternal), false);
assert.strictEqual(test_object.CheckTypeTag(4, plainExternal), false);
}
{
// Verify that normal and nonexistent properties can be deleted.
const sym = Symbol();
const obj = { foo: 'bar', [sym]: 'baz' };
assert.strictEqual('foo' in obj, true);
assert.strictEqual(sym in obj, true);
assert.strictEqual('does_not_exist' in obj, false);
assert.strictEqual(test_object.Delete(obj, 'foo'), true);
assert.strictEqual('foo' in obj, false);
assert.strictEqual(sym in obj, true);
assert.strictEqual('does_not_exist' in obj, false);
assert.strictEqual(test_object.Delete(obj, sym), true);
assert.strictEqual('foo' in obj, false);
assert.strictEqual(sym in obj, false);
assert.strictEqual('does_not_exist' in obj, false);
}
{
// Verify that non-configurable properties are not deleted.
const obj = {};
Object.defineProperty(obj, 'foo', { configurable: false });
assert.strictEqual(test_object.Delete(obj, 'foo'), false);
assert.strictEqual('foo' in obj, true);
}
{
// Verify that prototype properties are not deleted.
function Foo() {
this.foo = 'bar';
}
Foo.prototype.foo = 'baz';
const obj = new Foo();
assert.strictEqual(obj.foo, 'bar');
assert.strictEqual(test_object.Delete(obj, 'foo'), true);
assert.strictEqual(obj.foo, 'baz');
assert.strictEqual(test_object.Delete(obj, 'foo'), true);
assert.strictEqual(obj.foo, 'baz');
}
{
// Verify that napi_get_property_names gets the right set of property names,
// i.e.: includes prototypes, only enumerable properties, skips symbols,
// and includes indices and converts them to strings.
const object = { __proto__: {
inherited: 1,
} };
const fooSymbol = Symbol('foo');
object.normal = 2;
object[fooSymbol] = 3;
Object.defineProperty(object, 'unenumerable', {
value: 4,
enumerable: false,
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',
'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
// error.
assert.deepStrictEqual(test_object.TestSetProperty(), {
envIsNull: 'Invalid argument',
objectIsNull: 'Invalid argument',
keyIsNull: 'Invalid argument',
valueIsNull: 'Invalid argument',
});
// Verify that passing NULL to napi_has_property() results in the correct
// error.
assert.deepStrictEqual(test_object.TestHasProperty(), {
envIsNull: 'Invalid argument',
objectIsNull: 'Invalid argument',
keyIsNull: 'Invalid argument',
resultIsNull: 'Invalid argument',
});
// Verify that passing NULL to napi_get_property() results in the correct
// error.
assert.deepStrictEqual(test_object.TestGetProperty(), {
envIsNull: 'Invalid argument',
objectIsNull: 'Invalid argument',
keyIsNull: 'Invalid argument',
resultIsNull: 'Invalid argument',
});
{
const obj = { x: 'a', y: 'b', z: 'c' };
test_object.TestSeal(obj);
assert.strictEqual(Object.isSealed(obj), true);
assert.throws(() => {
obj.w = 'd';
}, /Cannot add property w, object is not extensible/);
assert.throws(() => {
delete obj.x;
}, /Cannot delete property 'x' of #<Object>/);
// Sealed objects allow updating existing properties,
// so this should not throw.
obj.x = 'd';
}
{
const obj = { x: 10, y: 10, z: 10 };
test_object.TestFreeze(obj);
assert.strictEqual(Object.isFrozen(obj), true);
assert.throws(() => {
obj.x = 10;
}, /Cannot assign to read only property 'x' of object '#<Object>/);
assert.throws(() => {
obj.w = 15;
}, /Cannot add property w, object is not extensible/);
assert.throws(() => {
delete obj.x;
}, /Cannot delete property 'x' of #<Object>/);
}

View File

@ -0,0 +1,82 @@
#include <assert.h>
#include <js_native_api.h>
#include <string.h>
#include "../common.h"
#include "../entry_point.h"
static napi_value TestExceptions(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));
napi_value target = args[0];
napi_value exception, key, value;
napi_status status;
bool is_exception_pending;
bool bool_result;
NODE_API_CALL(env,
napi_create_string_utf8(env, "key", NAPI_AUTO_LENGTH, &key));
NODE_API_CALL(
env, napi_create_string_utf8(env, "value", NAPI_AUTO_LENGTH, &value));
#define PROCEDURE(call) \
{ \
status = (call); \
NODE_API_ASSERT( \
env, status == napi_pending_exception, "expect exception pending"); \
NODE_API_CALL(env, napi_is_exception_pending(env, &is_exception_pending)); \
NODE_API_ASSERT(env, is_exception_pending, "expect exception pending"); \
NODE_API_CALL(env, napi_get_and_clear_last_exception(env, &exception)); \
}
// discard the exception values.
// properties
PROCEDURE(napi_set_property(env, target, key, value));
PROCEDURE(napi_set_named_property(env, target, "key", value));
PROCEDURE(napi_has_property(env, target, key, &bool_result));
PROCEDURE(napi_has_own_property(env, target, key, &bool_result));
PROCEDURE(napi_has_named_property(env, target, "key", &bool_result));
PROCEDURE(napi_get_property(env, target, key, &value));
PROCEDURE(napi_get_named_property(env, target, "key", &value));
PROCEDURE(napi_delete_property(env, target, key, &bool_result));
// elements
PROCEDURE(napi_set_element(env, target, 0, value));
PROCEDURE(napi_has_element(env, target, 0, &bool_result));
PROCEDURE(napi_get_element(env, target, 0, &value));
PROCEDURE(napi_delete_element(env, target, 0, &bool_result));
napi_property_descriptor descriptors[] = {
DECLARE_NODE_API_PROPERTY_VALUE("key", value),
};
PROCEDURE(napi_define_properties(
env, target, sizeof(descriptors) / sizeof(*descriptors), descriptors));
PROCEDURE(napi_get_all_property_names(env,
target,
napi_key_own_only,
napi_key_enumerable,
napi_key_keep_numbers,
&value));
PROCEDURE(napi_get_property_names(env, target, &value));
return NULL;
}
EXTERN_C_START
napi_value Init(napi_env env, napi_value exports) {
napi_property_descriptor descriptors[] = {
DECLARE_NODE_API_PROPERTY("testExceptions", TestExceptions),
};
NODE_API_CALL(
env,
napi_define_properties(env,
exports,
sizeof(descriptors) / sizeof(*descriptors),
descriptors));
return exports;
}
EXTERN_C_END

View File

@ -0,0 +1,18 @@
'use strict';
const common = require('../../common');
// Test
const { testExceptions } = require(`./build/${common.buildType}/test_exceptions`);
function throws() {
throw new Error('foobar');
}
testExceptions(new Proxy({}, {
get: common.mustCallAtLeast(throws, 1),
getOwnPropertyDescriptor: common.mustCallAtLeast(throws, 1),
defineProperty: common.mustCallAtLeast(throws, 1),
deleteProperty: common.mustCallAtLeast(throws, 1),
has: common.mustCallAtLeast(throws, 1),
set: common.mustCallAtLeast(throws, 1),
ownKeys: common.mustCallAtLeast(throws, 1),
}));

View File

@ -0,0 +1,400 @@
#include <js_native_api.h>
#include "../common.h"
#include "test_null.h"
static napi_value SetProperty(napi_env env, napi_callback_info info) {
napi_value return_value, object, key;
NODE_API_CALL(env, napi_create_object(env, &return_value));
NODE_API_CALL(env, napi_create_object(env, &object));
NODE_API_CALL(env,
napi_create_string_utf8(env, "someString", NAPI_AUTO_LENGTH, &key));
add_returned_status(env,
"envIsNull",
return_value,
"Invalid argument",
napi_invalid_arg,
napi_set_property(NULL, object, key, object));
napi_set_property(env, NULL, key, object);
add_last_status(env, "objectIsNull", return_value);
napi_set_property(env, object, NULL, object);
add_last_status(env, "keyIsNull", return_value);
napi_set_property(env, object, key, NULL);
add_last_status(env, "valueIsNull", return_value);
return return_value;
}
static napi_value GetProperty(napi_env env, napi_callback_info info) {
napi_value return_value, object, key, prop;
NODE_API_CALL(env, napi_create_object(env, &return_value));
NODE_API_CALL(env, napi_create_object(env, &object));
NODE_API_CALL(env,
napi_create_string_utf8(env, "someString", NAPI_AUTO_LENGTH, &key));
add_returned_status(env,
"envIsNull",
return_value,
"Invalid argument",
napi_invalid_arg,
napi_get_property(NULL, object, key, &prop));
napi_get_property(env, NULL, key, &prop);
add_last_status(env, "objectIsNull", return_value);
napi_get_property(env, object, NULL, &prop);
add_last_status(env, "keyIsNull", return_value);
napi_get_property(env, object, key, NULL);
add_last_status(env, "valueIsNull", return_value);
return return_value;
}
static napi_value TestBoolValuedPropApi(napi_env env,
napi_status (*api)(napi_env, napi_value, napi_value, bool*)) {
napi_value return_value, object, key;
bool result;
NODE_API_CALL(env, napi_create_object(env, &return_value));
NODE_API_CALL(env, napi_create_object(env, &object));
NODE_API_CALL(env,
napi_create_string_utf8(env, "someString", NAPI_AUTO_LENGTH, &key));
add_returned_status(env,
"envIsNull",
return_value,
"Invalid argument",
napi_invalid_arg,
api(NULL, object, key, &result));
api(env, NULL, key, &result);
add_last_status(env, "objectIsNull", return_value);
api(env, object, NULL, &result);
add_last_status(env, "keyIsNull", return_value);
api(env, object, key, NULL);
add_last_status(env, "valueIsNull", return_value);
return return_value;
}
static napi_value HasProperty(napi_env env, napi_callback_info info) {
return TestBoolValuedPropApi(env, napi_has_property);
}
static napi_value HasOwnProperty(napi_env env, napi_callback_info info) {
return TestBoolValuedPropApi(env, napi_has_own_property);
}
static napi_value DeleteProperty(napi_env env, napi_callback_info info) {
return TestBoolValuedPropApi(env, napi_delete_property);
}
static napi_value SetNamedProperty(napi_env env, napi_callback_info info) {
napi_value return_value, object;
NODE_API_CALL(env, napi_create_object(env, &return_value));
NODE_API_CALL(env, napi_create_object(env, &object));
add_returned_status(env,
"envIsNull",
return_value,
"Invalid argument",
napi_invalid_arg,
napi_set_named_property(NULL, object, "key", object));
napi_set_named_property(env, NULL, "key", object);
add_last_status(env, "objectIsNull", return_value);
napi_set_named_property(env, object, NULL, object);
add_last_status(env, "keyIsNull", return_value);
napi_set_named_property(env, object, "key", NULL);
add_last_status(env, "valueIsNull", return_value);
return return_value;
}
static napi_value GetNamedProperty(napi_env env, napi_callback_info info) {
napi_value return_value, object, prop;
NODE_API_CALL(env, napi_create_object(env, &return_value));
NODE_API_CALL(env, napi_create_object(env, &object));
add_returned_status(env,
"envIsNull",
return_value,
"Invalid argument",
napi_invalid_arg,
napi_get_named_property(NULL, object, "key", &prop));
napi_get_named_property(env, NULL, "key", &prop);
add_last_status(env, "objectIsNull", return_value);
napi_get_named_property(env, object, NULL, &prop);
add_last_status(env, "keyIsNull", return_value);
napi_get_named_property(env, object, "key", NULL);
add_last_status(env, "valueIsNull", return_value);
return return_value;
}
static napi_value HasNamedProperty(napi_env env, napi_callback_info info) {
napi_value return_value, object;
bool result;
NODE_API_CALL(env, napi_create_object(env, &return_value));
NODE_API_CALL(env, napi_create_object(env, &object));
add_returned_status(env,
"envIsNull",
return_value,
"Invalid argument",
napi_invalid_arg,
napi_has_named_property(NULL, object, "key", &result));
napi_has_named_property(env, NULL, "key", &result);
add_last_status(env, "objectIsNull", return_value);
napi_has_named_property(env, object, NULL, &result);
add_last_status(env, "keyIsNull", return_value);
napi_has_named_property(env, object, "key", NULL);
add_last_status(env, "valueIsNull", return_value);
return return_value;
}
static napi_value SetElement(napi_env env, napi_callback_info info) {
napi_value return_value, object;
NODE_API_CALL(env, napi_create_object(env, &return_value));
NODE_API_CALL(env, napi_create_object(env, &object));
add_returned_status(env,
"envIsNull",
return_value,
"Invalid argument",
napi_invalid_arg,
napi_set_element(NULL, object, 0, object));
napi_set_element(env, NULL, 0, object);
add_last_status(env, "objectIsNull", return_value);
napi_set_property(env, object, 0, NULL);
add_last_status(env, "valueIsNull", return_value);
return return_value;
}
static napi_value GetElement(napi_env env, napi_callback_info info) {
napi_value return_value, object, prop;
NODE_API_CALL(env, napi_create_object(env, &return_value));
NODE_API_CALL(env, napi_create_object(env, &object));
add_returned_status(env,
"envIsNull",
return_value,
"Invalid argument",
napi_invalid_arg,
napi_get_element(NULL, object, 0, &prop));
napi_get_property(env, NULL, 0, &prop);
add_last_status(env, "objectIsNull", return_value);
napi_get_property(env, object, 0, NULL);
add_last_status(env, "valueIsNull", return_value);
return return_value;
}
static napi_value TestBoolValuedElementApi(napi_env env,
napi_status (*api)(napi_env, napi_value, uint32_t, bool*)) {
napi_value return_value, object;
bool result;
NODE_API_CALL(env, napi_create_object(env, &return_value));
NODE_API_CALL(env, napi_create_object(env, &object));
add_returned_status(env,
"envIsNull",
return_value,
"Invalid argument",
napi_invalid_arg,
api(NULL, object, 0, &result));
api(env, NULL, 0, &result);
add_last_status(env, "objectIsNull", return_value);
api(env, object, 0, NULL);
add_last_status(env, "valueIsNull", return_value);
return return_value;
}
static napi_value HasElement(napi_env env, napi_callback_info info) {
return TestBoolValuedElementApi(env, napi_has_element);
}
static napi_value DeleteElement(napi_env env, napi_callback_info info) {
return TestBoolValuedElementApi(env, napi_delete_element);
}
static napi_value DefineProperties(napi_env env, napi_callback_info info) {
napi_value object, return_value;
napi_property_descriptor desc = {
"prop", NULL, DefineProperties, NULL, NULL, NULL, napi_enumerable, NULL
};
NODE_API_CALL(env, napi_create_object(env, &object));
NODE_API_CALL(env, napi_create_object(env, &return_value));
add_returned_status(env,
"envIsNull",
return_value,
"Invalid argument",
napi_invalid_arg,
napi_define_properties(NULL, object, 1, &desc));
napi_define_properties(env, NULL, 1, &desc);
add_last_status(env, "objectIsNull", return_value);
napi_define_properties(env, object, 1, NULL);
add_last_status(env, "descriptorListIsNull", return_value);
desc.utf8name = NULL;
napi_define_properties(env, object, 1, NULL);
add_last_status(env, "utf8nameIsNull", return_value);
desc.utf8name = "prop";
desc.method = NULL;
napi_define_properties(env, object, 1, NULL);
add_last_status(env, "methodIsNull", return_value);
desc.method = DefineProperties;
return return_value;
}
static napi_value GetPropertyNames(napi_env env, napi_callback_info info) {
napi_value return_value, props;
NODE_API_CALL(env, napi_create_object(env, &return_value));
add_returned_status(env,
"envIsNull",
return_value,
"Invalid argument",
napi_invalid_arg,
napi_get_property_names(NULL, return_value, &props));
napi_get_property_names(env, NULL, &props);
add_last_status(env, "objectIsNull", return_value);
napi_get_property_names(env, return_value, NULL);
add_last_status(env, "valueIsNull", return_value);
return return_value;
}
static napi_value GetAllPropertyNames(napi_env env, napi_callback_info info) {
napi_value return_value, props;
NODE_API_CALL(env, napi_create_object(env, &return_value));
add_returned_status(env,
"envIsNull",
return_value,
"Invalid argument",
napi_invalid_arg,
napi_get_all_property_names(NULL,
return_value,
napi_key_own_only,
napi_key_writable,
napi_key_keep_numbers,
&props));
napi_get_all_property_names(env,
NULL,
napi_key_own_only,
napi_key_writable,
napi_key_keep_numbers,
&props);
add_last_status(env, "objectIsNull", return_value);
napi_get_all_property_names(env,
return_value,
napi_key_own_only,
napi_key_writable,
napi_key_keep_numbers,
NULL);
add_last_status(env, "valueIsNull", return_value);
return return_value;
}
static napi_value GetPrototype(napi_env env, napi_callback_info info) {
napi_value return_value, proto;
NODE_API_CALL(env, napi_create_object(env, &return_value));
add_returned_status(env,
"envIsNull",
return_value,
"Invalid argument",
napi_invalid_arg,
napi_get_prototype(NULL, return_value, &proto));
napi_get_prototype(env, NULL, &proto);
add_last_status(env, "objectIsNull", return_value);
napi_get_prototype(env, return_value, NULL);
add_last_status(env, "valueIsNull", return_value);
return return_value;
}
void init_test_null(napi_env env, napi_value exports) {
napi_value test_null;
const napi_property_descriptor test_null_props[] = {
DECLARE_NODE_API_PROPERTY("setProperty", SetProperty),
DECLARE_NODE_API_PROPERTY("getProperty", GetProperty),
DECLARE_NODE_API_PROPERTY("hasProperty", HasProperty),
DECLARE_NODE_API_PROPERTY("hasOwnProperty", HasOwnProperty),
DECLARE_NODE_API_PROPERTY("deleteProperty", DeleteProperty),
DECLARE_NODE_API_PROPERTY("setNamedProperty", SetNamedProperty),
DECLARE_NODE_API_PROPERTY("getNamedProperty", GetNamedProperty),
DECLARE_NODE_API_PROPERTY("hasNamedProperty", HasNamedProperty),
DECLARE_NODE_API_PROPERTY("setElement", SetElement),
DECLARE_NODE_API_PROPERTY("getElement", GetElement),
DECLARE_NODE_API_PROPERTY("hasElement", HasElement),
DECLARE_NODE_API_PROPERTY("deleteElement", DeleteElement),
DECLARE_NODE_API_PROPERTY("defineProperties", DefineProperties),
DECLARE_NODE_API_PROPERTY("getPropertyNames", GetPropertyNames),
DECLARE_NODE_API_PROPERTY("getAllPropertyNames", GetAllPropertyNames),
DECLARE_NODE_API_PROPERTY("getPrototype", GetPrototype),
};
NODE_API_CALL_RETURN_VOID(env, napi_create_object(env, &test_null));
NODE_API_CALL_RETURN_VOID(env, napi_define_properties(
env, test_null, sizeof(test_null_props) / sizeof(*test_null_props),
test_null_props));
const napi_property_descriptor test_null_set = {
"testNull", NULL, NULL, NULL, NULL, test_null, napi_enumerable, NULL
};
NODE_API_CALL_RETURN_VOID(env,
napi_define_properties(env, exports, 1, &test_null_set));
}

View File

@ -0,0 +1,8 @@
#ifndef TEST_JS_NATIVE_API_TEST_OBJECT_TEST_NULL_H_
#define TEST_JS_NATIVE_API_TEST_OBJECT_TEST_NULL_H_
#include <js_native_api.h>
void init_test_null(napi_env env, napi_value exports);
#endif // TEST_JS_NATIVE_API_TEST_OBJECT_TEST_NULL_H_

View File

@ -0,0 +1,53 @@
'use strict';
const common = require('../../common');
const assert = require('assert');
// Test passing NULL to object-related N-APIs.
const { testNull } = require(`./build/${common.buildType}/test_object`);
const expectedForProperty = {
envIsNull: 'Invalid argument',
objectIsNull: 'Invalid argument',
keyIsNull: 'Invalid argument',
valueIsNull: 'Invalid argument',
};
assert.deepStrictEqual(testNull.setProperty(), expectedForProperty);
assert.deepStrictEqual(testNull.getProperty(), expectedForProperty);
assert.deepStrictEqual(testNull.hasProperty(), expectedForProperty);
// eslint-disable-next-line no-prototype-builtins
assert.deepStrictEqual(testNull.hasOwnProperty(), expectedForProperty);
// It's OK not to want the result of a deletion.
assert.deepStrictEqual(testNull.deleteProperty(),
Object.assign({},
expectedForProperty,
{ valueIsNull: 'napi_ok' }));
assert.deepStrictEqual(testNull.setNamedProperty(), expectedForProperty);
assert.deepStrictEqual(testNull.getNamedProperty(), expectedForProperty);
assert.deepStrictEqual(testNull.hasNamedProperty(), expectedForProperty);
const expectedForElement = {
envIsNull: 'Invalid argument',
objectIsNull: 'Invalid argument',
valueIsNull: 'Invalid argument',
};
assert.deepStrictEqual(testNull.setElement(), expectedForElement);
assert.deepStrictEqual(testNull.getElement(), expectedForElement);
assert.deepStrictEqual(testNull.hasElement(), expectedForElement);
// It's OK not to want the result of a deletion.
assert.deepStrictEqual(testNull.deleteElement(),
Object.assign({},
expectedForElement,
{ valueIsNull: 'napi_ok' }));
assert.deepStrictEqual(testNull.defineProperties(), {
envIsNull: 'Invalid argument',
objectIsNull: 'Invalid argument',
descriptorListIsNull: 'Invalid argument',
utf8nameIsNull: 'Invalid argument',
methodIsNull: 'Invalid argument',
});
// `expectedForElement` also works for the APIs below.
assert.deepStrictEqual(testNull.getPropertyNames(), expectedForElement);
assert.deepStrictEqual(testNull.getAllPropertyNames(), expectedForElement);
assert.deepStrictEqual(testNull.getPrototype(), expectedForElement);

View File

@ -0,0 +1,755 @@
#include <js_native_api.h>
#include <string.h>
#include "../common.h"
#include "../entry_point.h"
#include "test_null.h"
static int test_value = 3;
static napi_value Get(napi_env env, napi_callback_info info) {
size_t argc = 2;
napi_value args[2];
NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
NODE_API_ASSERT(env, argc >= 2, "Wrong number of arguments");
napi_valuetype valuetype0;
NODE_API_CALL(env, napi_typeof(env, args[0], &valuetype0));
NODE_API_ASSERT(env, valuetype0 == napi_object,
"Wrong type of arguments. Expects an object as first argument.");
napi_valuetype valuetype1;
NODE_API_CALL(env, napi_typeof(env, args[1], &valuetype1));
NODE_API_ASSERT(env, valuetype1 == napi_string || valuetype1 == napi_symbol,
"Wrong type of arguments. Expects a string or symbol as second.");
napi_value object = args[0];
napi_value output;
NODE_API_CALL(env, napi_get_property(env, object, args[1], &output));
return output;
}
static napi_value GetNamed(napi_env env, napi_callback_info info) {
size_t argc = 2;
napi_value args[2];
char key[256] = "";
size_t key_length;
NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
NODE_API_ASSERT(env, argc >= 2, "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_valuetype value_type1;
NODE_API_CALL(env, napi_typeof(env, args[1], &value_type1));
NODE_API_ASSERT(env, value_type1 == napi_string,
"Wrong type of arguments. Expects a string as second.");
napi_value object = args[0];
NODE_API_CALL(env,
napi_get_value_string_utf8(env, args[1], key, 255, &key_length));
key[255] = 0;
NODE_API_ASSERT(env, key_length <= 255,
"Cannot accommodate keys longer than 255 bytes");
napi_value output;
NODE_API_CALL(env, napi_get_named_property(env, object, key, &output));
return output;
}
static napi_value GetPropertyNames(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_property_names(env, args[0], &output));
return output;
}
static napi_value GetSymbolNames(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_skip_strings,
napi_key_numbers_to_strings, &output));
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];
NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
NODE_API_ASSERT(env, argc >= 3, "Wrong number of arguments");
napi_valuetype valuetype0;
NODE_API_CALL(env, napi_typeof(env, args[0], &valuetype0));
NODE_API_ASSERT(env, valuetype0 == napi_object,
"Wrong type of arguments. Expects an object as first argument.");
napi_valuetype valuetype1;
NODE_API_CALL(env, napi_typeof(env, args[1], &valuetype1));
NODE_API_ASSERT(env, valuetype1 == napi_string || valuetype1 == napi_symbol,
"Wrong type of arguments. Expects a string or symbol as second.");
NODE_API_CALL(env, napi_set_property(env, args[0], args[1], args[2]));
napi_value valuetrue;
NODE_API_CALL(env, napi_get_boolean(env, true, &valuetrue));
return valuetrue;
}
static napi_value SetNamed(napi_env env, napi_callback_info info) {
size_t argc = 3;
napi_value args[3];
char key[256] = "";
size_t key_length;
NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
NODE_API_ASSERT(env, argc >= 3, "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_valuetype value_type1;
NODE_API_CALL(env, napi_typeof(env, args[1], &value_type1));
NODE_API_ASSERT(env, value_type1 == napi_string,
"Wrong type of arguments. Expects a string as second.");
NODE_API_CALL(env,
napi_get_value_string_utf8(env, args[1], key, 255, &key_length));
key[255] = 0;
NODE_API_ASSERT(env, key_length <= 255,
"Cannot accommodate keys longer than 255 bytes");
NODE_API_CALL(env, napi_set_named_property(env, args[0], key, args[2]));
napi_value value_true;
NODE_API_CALL(env, napi_get_boolean(env, true, &value_true));
return value_true;
}
static napi_value Has(napi_env env, napi_callback_info info) {
size_t argc = 2;
napi_value args[2];
NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
NODE_API_ASSERT(env, argc >= 2, "Wrong number of arguments");
napi_valuetype valuetype0;
NODE_API_CALL(env, napi_typeof(env, args[0], &valuetype0));
NODE_API_ASSERT(env, valuetype0 == napi_object,
"Wrong type of arguments. Expects an object as first argument.");
napi_valuetype valuetype1;
NODE_API_CALL(env, napi_typeof(env, args[1], &valuetype1));
NODE_API_ASSERT(env, valuetype1 == napi_string || valuetype1 == napi_symbol,
"Wrong type of arguments. Expects a string or symbol as second.");
bool has_property;
NODE_API_CALL(env, napi_has_property(env, args[0], args[1], &has_property));
napi_value ret;
NODE_API_CALL(env, napi_get_boolean(env, has_property, &ret));
return ret;
}
static napi_value HasNamed(napi_env env, napi_callback_info info) {
size_t argc = 2;
napi_value args[2];
char key[256] = "";
size_t key_length;
NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
NODE_API_ASSERT(env, argc >= 2, "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_valuetype value_type1;
NODE_API_CALL(env, napi_typeof(env, args[1], &value_type1));
NODE_API_ASSERT(env, value_type1 == napi_string || value_type1 == napi_symbol,
"Wrong type of arguments. Expects a string as second.");
NODE_API_CALL(env,
napi_get_value_string_utf8(env, args[1], key, 255, &key_length));
key[255] = 0;
NODE_API_ASSERT(env, key_length <= 255,
"Cannot accommodate keys longer than 255 bytes");
bool has_property;
NODE_API_CALL(env, napi_has_named_property(env, args[0], key, &has_property));
napi_value ret;
NODE_API_CALL(env, napi_get_boolean(env, has_property, &ret));
return ret;
}
static napi_value HasOwn(napi_env env, napi_callback_info info) {
size_t argc = 2;
napi_value args[2];
NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
NODE_API_ASSERT(env, argc == 2, "Wrong number of arguments");
napi_valuetype valuetype0;
NODE_API_CALL(env, napi_typeof(env, args[0], &valuetype0));
NODE_API_ASSERT(env, valuetype0 == napi_object,
"Wrong type of arguments. Expects an object as first argument.");
// napi_valuetype valuetype1;
// NODE_API_CALL(env, napi_typeof(env, args[1], &valuetype1));
//
// NODE_API_ASSERT(env, valuetype1 == napi_string || valuetype1 == napi_symbol,
// "Wrong type of arguments. Expects a string or symbol as second.");
bool has_property;
NODE_API_CALL(env, napi_has_own_property(env, args[0], args[1], &has_property));
napi_value ret;
NODE_API_CALL(env, napi_get_boolean(env, has_property, &ret));
return ret;
}
static napi_value Delete(napi_env env, napi_callback_info info) {
size_t argc = 2;
napi_value args[2];
NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
NODE_API_ASSERT(env, argc == 2, "Wrong number of arguments");
napi_valuetype valuetype0;
NODE_API_CALL(env, napi_typeof(env, args[0], &valuetype0));
NODE_API_ASSERT(env, valuetype0 == napi_object,
"Wrong type of arguments. Expects an object as first argument.");
napi_valuetype valuetype1;
NODE_API_CALL(env, napi_typeof(env, args[1], &valuetype1));
NODE_API_ASSERT(env, valuetype1 == napi_string || valuetype1 == napi_symbol,
"Wrong type of arguments. Expects a string or symbol as second.");
bool result;
napi_value ret;
NODE_API_CALL(env, napi_delete_property(env, args[0], args[1], &result));
NODE_API_CALL(env, napi_get_boolean(env, result, &ret));
return ret;
}
static napi_value New(napi_env env, napi_callback_info info) {
napi_value ret;
NODE_API_CALL(env, napi_create_object(env, &ret));
napi_value num;
NODE_API_CALL(env, napi_create_int32(env, 987654321, &num));
NODE_API_CALL(env, napi_set_named_property(env, ret, "test_number", num));
napi_value str;
const char* str_val = "test string";
size_t str_len = strlen(str_val);
NODE_API_CALL(env, napi_create_string_utf8(env, str_val, str_len, &str));
NODE_API_CALL(env, napi_set_named_property(env, ret, "test_string", str));
return ret;
}
static napi_value Inflate(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 valuetype0;
NODE_API_CALL(env, napi_typeof(env, args[0], &valuetype0));
NODE_API_ASSERT(env, valuetype0 == napi_object,
"Wrong type of arguments. Expects an object as first argument.");
napi_value obj = args[0];
napi_value propertynames;
NODE_API_CALL(env, napi_get_property_names(env, obj, &propertynames));
uint32_t i, length;
NODE_API_CALL(env, napi_get_array_length(env, propertynames, &length));
for (i = 0; i < length; i++) {
napi_value property_str;
NODE_API_CALL(env, napi_get_element(env, propertynames, i, &property_str));
napi_value value;
NODE_API_CALL(env, napi_get_property(env, obj, property_str, &value));
double double_val;
NODE_API_CALL(env, napi_get_value_double(env, value, &double_val));
NODE_API_CALL(env, napi_create_double(env, double_val + 1, &value));
NODE_API_CALL(env, napi_set_property(env, obj, property_str, value));
}
return obj;
}
static napi_value Wrap(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value arg;
NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, &arg, NULL, NULL));
NODE_API_CALL(env, napi_wrap(env, arg, &test_value, NULL, NULL, NULL));
return NULL;
}
static napi_value Unwrap(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value arg;
NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, &arg, NULL, NULL));
void* data;
NODE_API_CALL(env, napi_unwrap(env, arg, &data));
bool is_expected = (data != NULL && *(int*)data == 3);
napi_value result;
NODE_API_CALL(env, napi_get_boolean(env, is_expected, &result));
return result;
}
static napi_value TestSetProperty(napi_env env,
napi_callback_info info) {
napi_status status;
napi_value object, key, value;
NODE_API_CALL(env, napi_create_object(env, &object));
NODE_API_CALL(env, napi_create_string_utf8(env, "", NAPI_AUTO_LENGTH, &key));
NODE_API_CALL(env, napi_create_object(env, &value));
status = napi_set_property(NULL, object, key, value);
add_returned_status(env,
"envIsNull",
object,
"Invalid argument",
napi_invalid_arg,
status);
napi_set_property(env, NULL, key, value);
add_last_status(env, "objectIsNull", object);
napi_set_property(env, object, NULL, value);
add_last_status(env, "keyIsNull", object);
napi_set_property(env, object, key, NULL);
add_last_status(env, "valueIsNull", object);
return object;
}
static napi_value TestHasProperty(napi_env env,
napi_callback_info info) {
napi_status status;
napi_value object, key;
bool result;
NODE_API_CALL(env, napi_create_object(env, &object));
NODE_API_CALL(env, napi_create_string_utf8(env, "", NAPI_AUTO_LENGTH, &key));
status = napi_has_property(NULL, object, key, &result);
add_returned_status(env,
"envIsNull",
object,
"Invalid argument",
napi_invalid_arg,
status);
napi_has_property(env, NULL, key, &result);
add_last_status(env, "objectIsNull", object);
napi_has_property(env, object, NULL, &result);
add_last_status(env, "keyIsNull", object);
napi_has_property(env, object, key, NULL);
add_last_status(env, "resultIsNull", object);
return object;
}
static napi_value TestGetProperty(napi_env env,
napi_callback_info info) {
napi_status status;
napi_value object, key, result;
NODE_API_CALL(env, napi_create_object(env, &object));
NODE_API_CALL(env, napi_create_string_utf8(env, "", NAPI_AUTO_LENGTH, &key));
NODE_API_CALL(env, napi_create_object(env, &result));
status = napi_get_property(NULL, object, key, &result);
add_returned_status(env,
"envIsNull",
object,
"Invalid argument",
napi_invalid_arg,
status);
napi_get_property(env, NULL, key, &result);
add_last_status(env, "objectIsNull", object);
napi_get_property(env, object, NULL, &result);
add_last_status(env, "keyIsNull", object);
napi_get_property(env, object, key, NULL);
add_last_status(env, "resultIsNull", object);
return object;
}
static napi_value TestFreeze(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));
napi_value object = args[0];
NODE_API_CALL(env, napi_object_freeze(env, object));
return object;
}
static napi_value TestSeal(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));
napi_value object = args[0];
NODE_API_CALL(env, napi_object_seal(env, object));
return object;
}
// We create two type tags. They are basically 128-bit UUIDs.
#define TYPE_TAG_COUNT 5
static const napi_type_tag type_tags[TYPE_TAG_COUNT] = {
{0xdaf987b3cc62481a, 0xb745b0497f299531},
{0xbb7936c374084d9b, 0xa9548d0762eeedb9},
{0xa5ed9ce2e4c00c38, 0},
{0, 0},
{0xa5ed9ce2e4c00c38, 0xdaf987b3cc62481a},
};
#define VALIDATE_TYPE_INDEX(env, type_index) \
do { \
if ((type_index) >= TYPE_TAG_COUNT) { \
NODE_API_CALL((env), \
napi_throw_range_error((env), \
"NODE_API_TEST_INVALID_TYPE_INDEX", \
"Invalid type index")); \
} \
} while (0)
static napi_value
TypeTaggedInstance(napi_env env, napi_callback_info info) {
size_t argc = 1;
uint32_t type_index;
napi_value instance, which_type;
napi_type_tag tag;
// Below we copy the tag before setting it to prevent bugs where a pointer
// to the tag (instead of the 128-bit tag value) is stored.
NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, &which_type, NULL, NULL));
NODE_API_CALL(env, napi_get_value_uint32(env, which_type, &type_index));
VALIDATE_TYPE_INDEX(env, type_index);
NODE_API_CALL(env, napi_create_object(env, &instance));
tag = type_tags[type_index];
NODE_API_CALL(env, napi_type_tag_object(env, instance, &tag));
// Since the tag passed to napi_type_tag_object() was copied to the stack,
// a type tagging implementation that uses a pointer instead of the
// tag value would end up pointing to stack memory.
// When CheckTypeTag() is called later on, it might be the case that this
// stack address has been left untouched by accident (if no subsequent
// function call has clobbered it), which means the pointer would still
// point to valid data.
// To make sure that tags are stored by value and not by reference,
// clear this copy; any implementation using a pointer would end up with
// random stack data or { 0, 0 }, but not the original tag value, and fail.
memset(&tag, 0, sizeof(tag));
return instance;
}
// V8 will not allow us to construct an external with a NULL data value.
#define IN_LIEU_OF_NULL ((void*)0x1)
static napi_value PlainExternal(napi_env env, napi_callback_info info) {
napi_value instance;
NODE_API_CALL(
env, napi_create_external(env, IN_LIEU_OF_NULL, NULL, NULL, &instance));
return instance;
}
static napi_value TypeTaggedExternal(napi_env env, napi_callback_info info) {
size_t argc = 1;
uint32_t type_index;
napi_value instance, which_type;
napi_type_tag tag;
// See TypeTaggedInstance() for an explanation about why we copy the tag
// to the stack and why we call memset on it after the external is tagged.
NODE_API_CALL(env,
napi_get_cb_info(env, info, &argc, &which_type, NULL, NULL));
NODE_API_CALL(env, napi_get_value_uint32(env, which_type, &type_index));
VALIDATE_TYPE_INDEX(env, type_index);
NODE_API_CALL(
env, napi_create_external(env, IN_LIEU_OF_NULL, NULL, NULL, &instance));
tag = type_tags[type_index];
NODE_API_CALL(env, napi_type_tag_object(env, instance, &tag));
memset(&tag, 0, sizeof(tag));
return instance;
}
static napi_value
CheckTypeTag(napi_env env, napi_callback_info info) {
size_t argc = 2;
bool result;
napi_value argv[2], js_result;
uint32_t type_index;
NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, argv, NULL, NULL));
NODE_API_CALL(env, napi_get_value_uint32(env, argv[0], &type_index));
VALIDATE_TYPE_INDEX(env, type_index);
NODE_API_CALL(env, napi_check_object_type_tag(env,
argv[1],
&type_tags[type_index],
&result));
NODE_API_CALL(env, napi_get_boolean(env, result, &js_result));
return js_result;
}
EXTERN_C_START
napi_value Init(napi_env env, napi_value exports) {
napi_property_descriptor descriptors[] = {
DECLARE_NODE_API_PROPERTY("Get", Get),
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),
DECLARE_NODE_API_PROPERTY("HasNamed", HasNamed),
DECLARE_NODE_API_PROPERTY("HasOwn", HasOwn),
DECLARE_NODE_API_PROPERTY("Delete", Delete),
DECLARE_NODE_API_PROPERTY("New", New),
DECLARE_NODE_API_PROPERTY("Inflate", Inflate),
DECLARE_NODE_API_PROPERTY("Wrap", Wrap),
DECLARE_NODE_API_PROPERTY("Unwrap", Unwrap),
DECLARE_NODE_API_PROPERTY("TestSetProperty", TestSetProperty),
DECLARE_NODE_API_PROPERTY("TestHasProperty", TestHasProperty),
DECLARE_NODE_API_PROPERTY("TypeTaggedInstance", TypeTaggedInstance),
DECLARE_NODE_API_PROPERTY("TypeTaggedExternal", TypeTaggedExternal),
DECLARE_NODE_API_PROPERTY("PlainExternal", PlainExternal),
DECLARE_NODE_API_PROPERTY("CheckTypeTag", CheckTypeTag),
DECLARE_NODE_API_PROPERTY("TestGetProperty", TestGetProperty),
DECLARE_NODE_API_PROPERTY("TestFreeze", TestFreeze),
DECLARE_NODE_API_PROPERTY("TestSeal", TestSeal),
};
init_test_null(env, exports);
NODE_API_CALL(env, napi_define_properties(
env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors));
return exports;
}
EXTERN_C_END