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,8 @@
{
"targets": [
{
"target_name": "test_async",
"sources": [ "test_async.c" ]
}
]
}

View File

@ -0,0 +1,60 @@
'use strict';
const common = require('../../common');
const assert = require('assert');
const async_hooks = require('async_hooks');
const test_async = require(`./build/${common.buildType}/test_async`);
const events = [];
let testId;
const initAsyncId = async_hooks.executionAsyncId();
async_hooks.createHook({
init(id, provider, triggerAsyncId, resource) {
if (provider === 'TestResource') {
testId = id;
events.push({ type: 'init', id, provider, triggerAsyncId, resource });
}
},
before(id) {
if (testId === id) {
events.push({ type: 'before', id });
}
},
after(id) {
if (testId === id) {
events.push({ type: 'after', id });
}
},
destroy(id) {
if (testId === id) {
events.push({ type: 'destroy', id });
}
},
}).enable();
const resource = { foo: 'foo' };
events.push({ type: 'start' });
test_async.Test(5, resource, common.mustCall(function(err, val) {
assert.strictEqual(err, null);
assert.strictEqual(val, 10);
events.push({ type: 'complete' });
process.nextTick(common.mustCall());
}));
events.push({ type: 'scheduled' });
process.on('exit', () => {
assert.deepStrictEqual(events, [
{ type: 'start' },
{ type: 'init',
id: testId,
provider: 'TestResource',
triggerAsyncId: initAsyncId,
resource },
{ type: 'scheduled' },
{ type: 'before', id: testId },
{ type: 'complete' },
{ type: 'after', id: testId },
{ type: 'destroy', id: testId },
]);
});

View File

@ -0,0 +1,14 @@
'use strict';
const common = require('../../common');
const assert = require('assert');
const test_async = require(`./build/${common.buildType}/test_async`);
const iterations = 500;
let x = 0;
const workDone = common.mustCall((status) => {
assert.strictEqual(status, 0);
if (++x < iterations) {
setImmediate(() => test_async.DoRepeatedWork(workDone));
}
}, iterations);
test_async.DoRepeatedWork(workDone);

View File

@ -0,0 +1,18 @@
'use strict';
const common = require('../../common');
const assert = require('assert');
const test_async = require(`./build/${common.buildType}/test_async`);
process.on('uncaughtException', common.mustCall(function(err) {
try {
throw new Error('should not fail');
} catch (err) {
assert.strictEqual(err.message, 'should not fail');
}
assert.strictEqual(err.message, 'uncaught');
}));
// Successful async execution and completion callback.
test_async.Test(5, {}, common.mustCall(function() {
throw new Error('uncaught');
}));

View File

@ -0,0 +1,30 @@
'use strict';
const common = require('../../common');
const assert = require('assert');
const child_process = require('child_process');
const test_async = require(`./build/${common.buildType}/test_async`);
const testException = 'test_async_cb_exception';
// Exception thrown from async completion callback.
// (Tested in a spawned process because the exception is fatal.)
if (process.argv[2] === 'child') {
test_async.Test(1, {}, common.mustCall(function() {
throw new Error(testException);
}));
return;
}
const p = child_process.spawnSync(
process.execPath, [ __filename, 'child' ]);
assert.ifError(p.error);
assert.ok(p.stderr.toString().includes(testException));
// Successful async execution and completion callback.
test_async.Test(5, {}, common.mustCall(function(err, val) {
assert.strictEqual(err, null);
assert.strictEqual(val, 10);
process.nextTick(common.mustCall());
}));
// Async work item cancellation with callback.
test_async.TestCancel(common.mustCall());

View File

@ -0,0 +1,216 @@
#include <assert.h>
#include <stdio.h>
#include <node_api.h>
#include <uv.h>
#include "../../js-native-api/common.h"
// this needs to be greater than the thread pool size
#define MAX_CANCEL_THREADS 6
typedef struct {
int32_t _input;
int32_t _output;
napi_ref _callback;
napi_async_work _request;
} carrier;
static carrier the_carrier;
static carrier async_carrier[MAX_CANCEL_THREADS];
static void Execute(napi_env env, void* data) {
uv_sleep(1000);
carrier* c = (carrier*)(data);
assert(c == &the_carrier);
c->_output = c->_input * 2;
}
static void Complete(napi_env env, napi_status status, void* data) {
carrier* c = (carrier*)(data);
if (c != &the_carrier) {
napi_throw_type_error(env, NULL, "Wrong data parameter to Complete.");
return;
}
if (status != napi_ok) {
napi_throw_type_error(env, NULL, "Execute callback failed.");
return;
}
napi_value argv[2];
NODE_API_CALL_RETURN_VOID(env, napi_get_null(env, &argv[0]));
NODE_API_CALL_RETURN_VOID(env, napi_create_int32(env, c->_output, &argv[1]));
napi_value callback;
NODE_API_CALL_RETURN_VOID(env,
napi_get_reference_value(env, c->_callback, &callback));
napi_value global;
NODE_API_CALL_RETURN_VOID(env, napi_get_global(env, &global));
napi_value result;
NODE_API_CALL_RETURN_VOID(env,
napi_call_function(env, global, callback, 2, argv, &result));
NODE_API_CALL_RETURN_VOID(env, napi_delete_reference(env, c->_callback));
NODE_API_CALL_RETURN_VOID(env, napi_delete_async_work(env, c->_request));
}
static napi_value Test(napi_env env, napi_callback_info info) {
size_t argc = 3;
napi_value argv[3];
napi_value _this;
napi_value resource_name;
void* data;
NODE_API_CALL(env,
napi_get_cb_info(env, info, &argc, argv, &_this, &data));
NODE_API_ASSERT(env, argc >= 3, "Not enough arguments, expected 3.");
napi_valuetype t;
NODE_API_CALL(env, napi_typeof(env, argv[0], &t));
NODE_API_ASSERT(env, t == napi_number,
"Wrong first argument, integer expected.");
NODE_API_CALL(env, napi_typeof(env, argv[1], &t));
NODE_API_ASSERT(env, t == napi_object,
"Wrong second argument, object expected.");
NODE_API_CALL(env, napi_typeof(env, argv[2], &t));
NODE_API_ASSERT(env, t == napi_function,
"Wrong third argument, function expected.");
the_carrier._output = 0;
NODE_API_CALL(env,
napi_get_value_int32(env, argv[0], &the_carrier._input));
NODE_API_CALL(env,
napi_create_reference(env, argv[2], 1, &the_carrier._callback));
NODE_API_CALL(env, napi_create_string_utf8(
env, "TestResource", NAPI_AUTO_LENGTH, &resource_name));
NODE_API_CALL(env, napi_create_async_work(env, argv[1], resource_name,
Execute, Complete, &the_carrier, &the_carrier._request));
NODE_API_CALL(env,
napi_queue_async_work(env, the_carrier._request));
return NULL;
}
static void BusyCancelComplete(napi_env env, napi_status status, void* data) {
carrier* c = (carrier*)(data);
NODE_API_CALL_RETURN_VOID(env, napi_delete_async_work(env, c->_request));
}
static void CancelComplete(napi_env env, napi_status status, void* data) {
carrier* c = (carrier*)(data);
if (status == napi_cancelled) {
// ok we got the status we expected so make the callback to
// indicate the cancel succeeded.
napi_value callback;
NODE_API_CALL_RETURN_VOID(env,
napi_get_reference_value(env, c->_callback, &callback));
napi_value global;
NODE_API_CALL_RETURN_VOID(env, napi_get_global(env, &global));
napi_value result;
NODE_API_CALL_RETURN_VOID(env,
napi_call_function(env, global, callback, 0, NULL, &result));
}
NODE_API_CALL_RETURN_VOID(env, napi_delete_async_work(env, c->_request));
NODE_API_CALL_RETURN_VOID(env, napi_delete_reference(env, c->_callback));
}
static void CancelExecute(napi_env env, void* data) {
uv_sleep(1000);
}
static napi_value TestCancel(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value argv[1];
napi_value _this;
napi_value resource_name;
void* data;
NODE_API_CALL(env, napi_create_string_utf8(
env, "TestResource", NAPI_AUTO_LENGTH, &resource_name));
// make sure the work we are going to cancel will not be
// able to start by using all the threads in the pool
for (int i = 1; i < MAX_CANCEL_THREADS; i++) {
NODE_API_CALL(env, napi_create_async_work(env, NULL, resource_name,
CancelExecute, BusyCancelComplete,
&async_carrier[i], &async_carrier[i]._request));
NODE_API_CALL(env, napi_queue_async_work(env, async_carrier[i]._request));
}
// now queue the work we are going to cancel and then cancel it.
// cancel will fail if the work has already started, but
// we have prevented it from starting by consuming all of the
// workers above.
NODE_API_CALL(env,
napi_get_cb_info(env, info, &argc, argv, &_this, &data));
NODE_API_CALL(env, napi_create_async_work(env, NULL, resource_name,
CancelExecute, CancelComplete,
&async_carrier[0], &async_carrier[0]._request));
NODE_API_CALL(env,
napi_create_reference(env, argv[0], 1, &async_carrier[0]._callback));
NODE_API_CALL(env, napi_queue_async_work(env, async_carrier[0]._request));
NODE_API_CALL(env, napi_cancel_async_work(env, async_carrier[0]._request));
return NULL;
}
struct {
napi_ref ref;
napi_async_work work;
} repeated_work_info = { NULL, NULL };
static void RepeatedWorkerThread(napi_env env, void* data) {}
static void RepeatedWorkComplete(napi_env env, napi_status status, void* data) {
napi_value cb, js_status;
NODE_API_CALL_RETURN_VOID(env,
napi_get_reference_value(env, repeated_work_info.ref, &cb));
NODE_API_CALL_RETURN_VOID(env,
napi_delete_async_work(env, repeated_work_info.work));
NODE_API_CALL_RETURN_VOID(env,
napi_delete_reference(env, repeated_work_info.ref));
repeated_work_info.work = NULL;
repeated_work_info.ref = NULL;
NODE_API_CALL_RETURN_VOID(env,
napi_create_uint32(env, (uint32_t)status, &js_status));
NODE_API_CALL_RETURN_VOID(env,
napi_call_function(env, cb, cb, 1, &js_status, NULL));
}
static napi_value DoRepeatedWork(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value cb, name;
NODE_API_ASSERT(env, repeated_work_info.ref == NULL,
"Reference left over from previous work");
NODE_API_ASSERT(env, repeated_work_info.work == NULL,
"Work pointer left over from previous work");
NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, &cb, NULL, NULL));
NODE_API_CALL(env, napi_create_reference(env, cb, 1, &repeated_work_info.ref));
NODE_API_CALL(env,
napi_create_string_utf8(env, "Repeated Work", NAPI_AUTO_LENGTH, &name));
NODE_API_CALL(env,
napi_create_async_work(env, NULL, name, RepeatedWorkerThread,
RepeatedWorkComplete, &repeated_work_info, &repeated_work_info.work));
NODE_API_CALL(env, napi_queue_async_work(env, repeated_work_info.work));
return NULL;
}
static napi_value Init(napi_env env, napi_value exports) {
napi_property_descriptor properties[] = {
DECLARE_NODE_API_PROPERTY("Test", Test),
DECLARE_NODE_API_PROPERTY("TestCancel", TestCancel),
DECLARE_NODE_API_PROPERTY("DoRepeatedWork", DoRepeatedWork),
};
NODE_API_CALL(env, napi_define_properties(
env, exports, sizeof(properties) / sizeof(*properties), properties));
return exports;
}
NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)