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,14 @@
{
"targets": [
{
"target_name": "test_reference_all_types",
"sources": [ "test_reference_by_node_api_version.c" ],
"defines": [ "NAPI_VERSION=10" ],
},
{
"target_name": "test_reference_obj_only",
"sources": [ "test_reference_by_node_api_version.c" ],
"defines": [ "NAPI_VERSION=9" ],
}
]
}

View File

@ -0,0 +1,125 @@
'use strict';
// Flags: --expose-gc
//
// Testing API calls for Node-API references.
// We compare their behavior between Node-API version 8 and later.
// In version 8 references can be created only for object, function,
// and symbol types, while in newer versions they can be created for
// any value type.
//
const { buildType } = require('../../common');
const { gcUntil } = require('../../common/gc');
const assert = require('assert');
const addon_v8 = require(`./build/${buildType}/test_reference_obj_only`);
const addon_new = require(`./build/${buildType}/test_reference_all_types`);
async function runTests(addon, isVersion8, isLocalSymbol) {
let allEntries = [];
(() => {
// Create values of all napi_valuetype types.
const undefinedValue = undefined;
const nullValue = null;
const booleanValue = false;
const numberValue = 42;
const stringValue = 'test_string';
const globalSymbolValue = Symbol.for('test_symbol_global');
const localSymbolValue = Symbol('test_symbol_local');
const symbolValue = isLocalSymbol ? localSymbolValue : globalSymbolValue;
const objectValue = { x: 1, y: 2 };
const functionValue = (x, y) => x + y;
const externalValue = addon.createExternal();
const bigintValue = 9007199254740991n;
// The position of entries in the allEntries array corresponds to the
// napi_valuetype enum value. See the CreateRef function for the
// implementation details.
allEntries = [
{ value: undefinedValue, canBeWeak: false, canBeRefV8: false },
{ value: nullValue, canBeWeak: false, canBeRefV8: false },
{ value: booleanValue, canBeWeak: false, canBeRefV8: false },
{ value: numberValue, canBeWeak: false, canBeRefV8: false },
{ value: stringValue, canBeWeak: false, canBeRefV8: false },
{ value: symbolValue, canBeWeak: isLocalSymbol, canBeRefV8: true,
isAlwaysStrong: !isLocalSymbol },
{ value: objectValue, canBeWeak: true, canBeRefV8: true },
{ value: functionValue, canBeWeak: true, canBeRefV8: true },
{ value: externalValue, canBeWeak: true, canBeRefV8: true },
{ value: bigintValue, canBeWeak: false, canBeRefV8: false },
];
// Go over all values of different types, create strong ref values for
// them, read the stored values, and check how the ref count works.
for (const entry of allEntries) {
if (!isVersion8 || entry.canBeRefV8) {
const index = addon.createRef(entry.value);
const refValue = addon.getRefValue(index);
assert.strictEqual(entry.value, refValue);
assert.strictEqual(addon.ref(index), 2);
assert.strictEqual(addon.unref(index), 1);
assert.strictEqual(addon.unref(index), 0);
} else {
assert.throws(() => { addon.createRef(entry.value); },
{
name: 'Error',
message: 'Invalid argument',
});
}
}
// When the reference count is zero, then object types become weak pointers
// and other types are released.
// Here we know that the GC is not run yet because the values are
// still in the allEntries array.
allEntries.forEach((entry, index) => {
if (!isVersion8 || entry.canBeRefV8) {
if (entry.canBeWeak || entry.isAlwaysStrong) {
assert.strictEqual(addon.getRefValue(index), entry.value);
} else {
assert.strictEqual(addon.getRefValue(index), undefined);
}
}
// Set to undefined to allow GC collect the value.
entry.value = undefined;
});
// To check that GC pass is done.
const objWithFinalizer = {};
addon.addFinalizer(objWithFinalizer);
})();
addon.initFinalizeCount();
assert.strictEqual(addon.getFinalizeCount(), 0);
await gcUntil('Wait until a finalizer is called',
() => (addon.getFinalizeCount() === 1));
// Create and call finalizer again to make sure that we had another GC pass.
(() => {
const objWithFinalizer = {};
addon.addFinalizer(objWithFinalizer);
})();
await gcUntil('Wait until a finalizer is called again',
() => (addon.getFinalizeCount() === 2));
// After GC and finalizers run, all values that support weak reference
// semantic must return undefined value.
allEntries.forEach((entry, index) => {
if (!isVersion8 || entry.canBeRefV8) {
if (!entry.isAlwaysStrong) {
assert.strictEqual(addon.getRefValue(index), undefined);
} else {
assert.notStrictEqual(addon.getRefValue(index), undefined);
}
addon.deleteRef(index);
}
});
}
async function runAllTests() {
await runTests(addon_v8, /* isVersion8 */ true, /* isLocalSymbol */ true);
await runTests(addon_v8, /* isVersion8 */ true, /* isLocalSymbol */ false);
await runTests(addon_new, /* isVersion8 */ false, /* isLocalSymbol */ true);
await runTests(addon_new, /* isVersion8 */ false, /* isLocalSymbol */ false);
}
runAllTests();

View File

@ -0,0 +1,169 @@
#include <node_api.h>
#include "../../js-native-api/common.h"
#include "stdlib.h"
static uint32_t finalizeCount = 0;
static void FreeData(node_api_basic_env env, void* data, void* hint) {
NODE_API_BASIC_ASSERT_RETURN_VOID(data != NULL, "Expects non-NULL data.");
free(data);
}
static void Finalize(node_api_basic_env env, void* data, void* hint) {
++finalizeCount;
}
static napi_status GetArgValue(napi_env env,
napi_callback_info info,
napi_value* argValue) {
size_t argc = 1;
NODE_API_CHECK_STATUS(
napi_get_cb_info(env, info, &argc, argValue, NULL, NULL));
NODE_API_ASSERT_STATUS(env, argc == 1, "Expects one arg.");
return napi_ok;
}
static napi_status GetArgValueAsIndex(napi_env env,
napi_callback_info info,
uint32_t* index) {
napi_value argValue;
NODE_API_CHECK_STATUS(GetArgValue(env, info, &argValue));
napi_valuetype valueType;
NODE_API_CHECK_STATUS(napi_typeof(env, argValue, &valueType));
NODE_API_ASSERT_STATUS(
env, valueType == napi_number, "Argument must be a number.");
return napi_get_value_uint32(env, argValue, index);
}
static napi_status GetRef(napi_env env,
napi_callback_info info,
napi_ref* ref) {
uint32_t index;
NODE_API_CHECK_STATUS(GetArgValueAsIndex(env, info, &index));
napi_ref* refValues;
NODE_API_CHECK_STATUS(napi_get_instance_data(env, (void**)&refValues));
NODE_API_ASSERT_STATUS(env, refValues != NULL, "Cannot get instance data.");
*ref = refValues[index];
return napi_ok;
}
static napi_value ToUInt32Value(napi_env env, uint32_t value) {
napi_value result;
NODE_API_CALL(env, napi_create_uint32(env, value, &result));
return result;
}
static napi_status InitRefArray(napi_env env) {
// valueRefs array has one entry per napi_valuetype
napi_ref* valueRefs = malloc(sizeof(napi_ref) * ((int)napi_bigint + 1));
return napi_set_instance_data(env, valueRefs, (napi_finalize)&FreeData, NULL);
}
static napi_value CreateExternal(napi_env env, napi_callback_info info) {
napi_value result;
int* data = (int*)malloc(sizeof(int));
*data = 42;
NODE_API_CALL(env, napi_create_external(env, data, &FreeData, NULL, &result));
return result;
}
static napi_value CreateRef(napi_env env, napi_callback_info info) {
napi_value argValue;
NODE_API_CALL(env, GetArgValue(env, info, &argValue));
napi_valuetype valueType;
NODE_API_CALL(env, napi_typeof(env, argValue, &valueType));
uint32_t index = (uint32_t)valueType;
napi_ref* valueRefs;
NODE_API_CALL(env, napi_get_instance_data(env, (void**)&valueRefs));
NODE_API_CALL(env,
napi_create_reference(env, argValue, 1, valueRefs + index));
return ToUInt32Value(env, index);
}
static napi_value GetRefValue(napi_env env, napi_callback_info info) {
napi_ref refValue;
NODE_API_CALL(env, GetRef(env, info, &refValue));
napi_value value;
NODE_API_CALL(env, napi_get_reference_value(env, refValue, &value));
return value;
}
static napi_value Ref(napi_env env, napi_callback_info info) {
napi_ref refValue;
NODE_API_CALL(env, GetRef(env, info, &refValue));
uint32_t refCount;
NODE_API_CALL(env, napi_reference_ref(env, refValue, &refCount));
return ToUInt32Value(env, refCount);
}
static napi_value Unref(napi_env env, napi_callback_info info) {
napi_ref refValue;
NODE_API_CALL(env, GetRef(env, info, &refValue));
uint32_t refCount;
NODE_API_CALL(env, napi_reference_unref(env, refValue, &refCount));
return ToUInt32Value(env, refCount);
}
static napi_value DeleteRef(napi_env env, napi_callback_info info) {
napi_ref refValue;
NODE_API_CALL(env, GetRef(env, info, &refValue));
NODE_API_CALL(env, napi_delete_reference(env, refValue));
return NULL;
}
static napi_value AddFinalizer(napi_env env, napi_callback_info info) {
napi_value obj;
NODE_API_CALL(env, GetArgValue(env, info, &obj));
napi_valuetype valueType;
NODE_API_CALL(env, napi_typeof(env, obj, &valueType));
NODE_API_ASSERT(env, valueType == napi_object, "Argument must be an object.");
NODE_API_CALL(env, napi_add_finalizer(env, obj, NULL, &Finalize, NULL, NULL));
return NULL;
}
static napi_value GetFinalizeCount(napi_env env, napi_callback_info info) {
return ToUInt32Value(env, finalizeCount);
}
static napi_value InitFinalizeCount(napi_env env, napi_callback_info info) {
finalizeCount = 0;
return NULL;
}
EXTERN_C_START
NAPI_MODULE_INIT() {
finalizeCount = 0;
NODE_API_CALL(env, InitRefArray(env));
napi_property_descriptor properties[] = {
DECLARE_NODE_API_PROPERTY("createExternal", CreateExternal),
DECLARE_NODE_API_PROPERTY("createRef", CreateRef),
DECLARE_NODE_API_PROPERTY("getRefValue", GetRefValue),
DECLARE_NODE_API_PROPERTY("ref", Ref),
DECLARE_NODE_API_PROPERTY("unref", Unref),
DECLARE_NODE_API_PROPERTY("deleteRef", DeleteRef),
DECLARE_NODE_API_PROPERTY("addFinalizer", AddFinalizer),
DECLARE_NODE_API_PROPERTY("getFinalizeCount", GetFinalizeCount),
DECLARE_NODE_API_PROPERTY("initFinalizeCount", InitFinalizeCount),
};
NODE_API_CALL(
env,
napi_define_properties(
env, exports, sizeof(properties) / sizeof(*properties), properties));
return exports;
}
EXTERN_C_END