benchmark: add n-api function args benchmark
This benchmark suite is added to measure the performance of n-api function call with various type/number of arguments. The cases in this suite are carefully selected to efficiently show the performance trend. PR-URL: https://github.com/nodejs/node/pull/21555 Reviewed-By: Gabriel Schulhof <gabriel.schulhof@intel.com> Reviewed-By: Kyle Farnung <kfarnung@microsoft.com>
This commit is contained in:
parent
0a78f7d622
commit
3314b3a2f5
9
Makefile
9
Makefile
@ -305,6 +305,15 @@ benchmark/napi/function_call/build/Release/binding.node: all \
|
|||||||
--directory="$(shell pwd)/benchmark/napi/function_call" \
|
--directory="$(shell pwd)/benchmark/napi/function_call" \
|
||||||
--nodedir="$(shell pwd)"
|
--nodedir="$(shell pwd)"
|
||||||
|
|
||||||
|
benchmark/napi/function_args/build/Release/binding.node: all \
|
||||||
|
benchmark/napi/function_args/napi_binding.c \
|
||||||
|
benchmark/napi/function_args/binding.cc \
|
||||||
|
benchmark/napi/function_args/binding.gyp
|
||||||
|
$(NODE) deps/npm/node_modules/node-gyp/bin/node-gyp rebuild \
|
||||||
|
--python="$(PYTHON)" \
|
||||||
|
--directory="$(shell pwd)/benchmark/napi/function_args" \
|
||||||
|
--nodedir="$(shell pwd)"
|
||||||
|
|
||||||
# Implicitly depends on $(NODE_EXE). We don't depend on it explicitly because
|
# Implicitly depends on $(NODE_EXE). We don't depend on it explicitly because
|
||||||
# it always triggers a rebuild due to it being a .PHONY rule. See the comment
|
# it always triggers a rebuild due to it being a .PHONY rule. See the comment
|
||||||
# near the build-addons rule for more background.
|
# near the build-addons rule for more background.
|
||||||
|
1
benchmark/napi/function_args/.gitignore
vendored
Normal file
1
benchmark/napi/function_args/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
build/
|
142
benchmark/napi/function_args/binding.cc
Normal file
142
benchmark/napi/function_args/binding.cc
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
#include <v8.h>
|
||||||
|
#include <node.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
using v8::Isolate;
|
||||||
|
using v8::Context;
|
||||||
|
using v8::Local;
|
||||||
|
using v8::MaybeLocal;
|
||||||
|
using v8::Value;
|
||||||
|
using v8::Number;
|
||||||
|
using v8::String;
|
||||||
|
using v8::Object;
|
||||||
|
using v8::Array;
|
||||||
|
using v8::ArrayBufferView;
|
||||||
|
using v8::ArrayBuffer;
|
||||||
|
using v8::FunctionCallbackInfo;
|
||||||
|
|
||||||
|
void CallWithString(const FunctionCallbackInfo<Value>& args) {
|
||||||
|
assert(args.Length() == 1 && args[0]->IsString());
|
||||||
|
if (args.Length() == 1 && args[0]->IsString()) {
|
||||||
|
Local<String> str = args[0].As<String>();
|
||||||
|
const int32_t length = str->Utf8Length() + 1;
|
||||||
|
char* buf = new char[length];
|
||||||
|
str->WriteUtf8(buf, length);
|
||||||
|
delete [] buf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallWithArray(const FunctionCallbackInfo<Value>& args) {
|
||||||
|
assert(args.Length() == 1 && args[0]->IsArray());
|
||||||
|
if (args.Length() == 1 && args[0]->IsArray()) {
|
||||||
|
const Local<Array> array = args[0].As<Array>();
|
||||||
|
uint32_t length = array->Length();
|
||||||
|
for (uint32_t i = 0; i < length; ++ i) {
|
||||||
|
Local<Value> v;
|
||||||
|
v = array->Get(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallWithNumber(const FunctionCallbackInfo<Value>& args) {
|
||||||
|
assert(args.Length() == 1 && args[0]->IsNumber());
|
||||||
|
if (args.Length() == 1 && args[0]->IsNumber()) {
|
||||||
|
args[0].As<Number>()->Value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallWithObject(const FunctionCallbackInfo<Value>& args) {
|
||||||
|
Isolate* isolate = args.GetIsolate();
|
||||||
|
Local<Context> context = isolate->GetCurrentContext();
|
||||||
|
|
||||||
|
assert(args.Length() == 1 && args[0]->IsObject());
|
||||||
|
if (args.Length() == 1 && args[0]->IsObject()) {
|
||||||
|
Local<Object> obj = args[0].As<Object>();
|
||||||
|
|
||||||
|
MaybeLocal<String> map_key = String::NewFromUtf8(isolate,
|
||||||
|
"map", v8::NewStringType::kNormal);
|
||||||
|
assert(!map_key.IsEmpty());
|
||||||
|
MaybeLocal<Value> map_maybe = obj->Get(context,
|
||||||
|
map_key.ToLocalChecked());
|
||||||
|
assert(!map_maybe.IsEmpty());
|
||||||
|
Local<Value> map;
|
||||||
|
map = map_maybe.ToLocalChecked();
|
||||||
|
|
||||||
|
MaybeLocal<String> operand_key = String::NewFromUtf8(isolate,
|
||||||
|
"operand", v8::NewStringType::kNormal);
|
||||||
|
assert(!operand_key.IsEmpty());
|
||||||
|
MaybeLocal<Value> operand_maybe = obj->Get(context,
|
||||||
|
operand_key.ToLocalChecked());
|
||||||
|
assert(!operand_maybe.IsEmpty());
|
||||||
|
Local<Value> operand;
|
||||||
|
operand = operand_maybe.ToLocalChecked();
|
||||||
|
|
||||||
|
MaybeLocal<String> data_key = String::NewFromUtf8(isolate,
|
||||||
|
"data", v8::NewStringType::kNormal);
|
||||||
|
assert(!data_key.IsEmpty());
|
||||||
|
MaybeLocal<Value> data_maybe = obj->Get(context,
|
||||||
|
data_key.ToLocalChecked());
|
||||||
|
assert(!data_maybe.IsEmpty());
|
||||||
|
Local<Value> data;
|
||||||
|
data = data_maybe.ToLocalChecked();
|
||||||
|
|
||||||
|
MaybeLocal<String> reduce_key = String::NewFromUtf8(isolate,
|
||||||
|
"reduce", v8::NewStringType::kNormal);
|
||||||
|
assert(!reduce_key.IsEmpty());
|
||||||
|
MaybeLocal<Value> reduce_maybe = obj->Get(context,
|
||||||
|
reduce_key.ToLocalChecked());
|
||||||
|
assert(!reduce_maybe.IsEmpty());
|
||||||
|
Local<Value> reduce;
|
||||||
|
reduce = reduce_maybe.ToLocalChecked();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallWithTypedarray(const FunctionCallbackInfo<Value>& args) {
|
||||||
|
assert(args.Length() == 1 && args[0]->IsArrayBufferView());
|
||||||
|
if (args.Length() == 1 && args[0]->IsArrayBufferView()) {
|
||||||
|
assert(args[0]->IsArrayBufferView());
|
||||||
|
Local<ArrayBufferView> view = args[0].As<ArrayBufferView>();
|
||||||
|
const size_t byte_offset = view->ByteOffset();
|
||||||
|
const size_t byte_length = view->ByteLength();
|
||||||
|
assert(byte_length > 0);
|
||||||
|
assert(view->HasBuffer());
|
||||||
|
Local<ArrayBuffer> buffer;
|
||||||
|
buffer = view->Buffer();
|
||||||
|
ArrayBuffer::Contents contents;
|
||||||
|
contents = buffer->GetContents();
|
||||||
|
const uint32_t* data = reinterpret_cast<uint32_t*>(
|
||||||
|
static_cast<uint8_t*>(contents.Data()) + byte_offset);
|
||||||
|
assert(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallWithArguments(const FunctionCallbackInfo<Value>& args) {
|
||||||
|
assert(args.Length() > 1 && args[0]->IsNumber());
|
||||||
|
if (args.Length() > 1 && args[0]->IsNumber()) {
|
||||||
|
int32_t loop = args[0].As<v8::Uint32>()->Value();
|
||||||
|
for (int32_t i = 1; i < loop; ++i) {
|
||||||
|
assert(i < args.Length());
|
||||||
|
assert(args[i]->IsUint32());
|
||||||
|
args[i].As<v8::Uint32>()->Value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Initialize(Local<Object> target) {
|
||||||
|
NODE_SET_METHOD(target, "callWithString", CallWithString);
|
||||||
|
NODE_SET_METHOD(target, "callWithLongString", CallWithString);
|
||||||
|
|
||||||
|
NODE_SET_METHOD(target, "callWithArray", CallWithArray);
|
||||||
|
NODE_SET_METHOD(target, "callWithLargeArray", CallWithArray);
|
||||||
|
NODE_SET_METHOD(target, "callWithHugeArray", CallWithArray);
|
||||||
|
|
||||||
|
NODE_SET_METHOD(target, "callWithNumber", CallWithNumber);
|
||||||
|
NODE_SET_METHOD(target, "callWithObject", CallWithObject);
|
||||||
|
NODE_SET_METHOD(target, "callWithTypedarray", CallWithTypedarray);
|
||||||
|
|
||||||
|
NODE_SET_METHOD(target, "callWith10Numbers", CallWithArguments);
|
||||||
|
NODE_SET_METHOD(target, "callWith100Numbers", CallWithArguments);
|
||||||
|
NODE_SET_METHOD(target, "callWith1000Numbers", CallWithArguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
NODE_MODULE(NODE_GYP_MODULE_NAME, Initialize)
|
12
benchmark/napi/function_args/binding.gyp
Normal file
12
benchmark/napi/function_args/binding.gyp
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
'targets': [
|
||||||
|
{
|
||||||
|
'target_name': 'napi_binding',
|
||||||
|
'sources': [ 'napi_binding.c' ]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'target_name': 'binding',
|
||||||
|
'sources': [ 'binding.cc' ]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
99
benchmark/napi/function_args/index.js
Normal file
99
benchmark/napi/function_args/index.js
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
// show the difference between calling a V8 binding C++ function
|
||||||
|
// relative to a comparable N-API C++ function,
|
||||||
|
// in various types/numbers of arguments.
|
||||||
|
// Reports n of calls per second.
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const common = require('../../common.js');
|
||||||
|
|
||||||
|
let v8;
|
||||||
|
let napi;
|
||||||
|
|
||||||
|
try {
|
||||||
|
v8 = require('./build/Release/binding');
|
||||||
|
} catch (err) {
|
||||||
|
// eslint-disable-next-line no-path-concat
|
||||||
|
console.error(__filename + ': V8 Binding failed to load');
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
napi = require('./build/Release/napi_binding');
|
||||||
|
} catch (err) {
|
||||||
|
// eslint-disable-next-line no-path-concat
|
||||||
|
console.error(__filename + ': NAPI-Binding failed to load');
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const argsTypes = ['String', 'Number', 'Object', 'Array', 'Typedarray',
|
||||||
|
'10Numbers', '100Numbers', '1000Numbers'];
|
||||||
|
|
||||||
|
const generateArgs = (argType) => {
|
||||||
|
let args = [];
|
||||||
|
|
||||||
|
if (argType === 'String') {
|
||||||
|
args.push('The quick brown fox jumps over the lazy dog');
|
||||||
|
} else if (argType === 'LongString') {
|
||||||
|
args.push(Buffer.alloc(32768, '42').toString());
|
||||||
|
} else if (argType === 'Number') {
|
||||||
|
args.push(Math.floor(314158964 * Math.random()));
|
||||||
|
} else if (argType === 'Object') {
|
||||||
|
args.push({
|
||||||
|
map: 'add',
|
||||||
|
operand: 10,
|
||||||
|
data: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
|
||||||
|
reduce: 'add',
|
||||||
|
});
|
||||||
|
} else if (argType === 'Array') {
|
||||||
|
const arr = [];
|
||||||
|
for (let i = 0; i < 50; ++i) {
|
||||||
|
arr.push(Math.random() * 10e9);
|
||||||
|
}
|
||||||
|
args.push(arr);
|
||||||
|
} else if (argType === 'Typedarray') {
|
||||||
|
const arr = new Uint32Array(1000);
|
||||||
|
for (let i = 0; i < 1000; ++i) {
|
||||||
|
arr[i] = Math.random() * 4294967296;
|
||||||
|
}
|
||||||
|
args.push(arr);
|
||||||
|
} else if (argType === '10Numbers') {
|
||||||
|
args.push(10);
|
||||||
|
for (let i = 0; i < 9; ++i) {
|
||||||
|
args = [...args, ...generateArgs('Number')];
|
||||||
|
}
|
||||||
|
} else if (argType === '100Numbers') {
|
||||||
|
args.push(100);
|
||||||
|
for (let i = 0; i < 99; ++i) {
|
||||||
|
args = [...args, ...generateArgs('Number')];
|
||||||
|
}
|
||||||
|
} else if (argType === '1000Numbers') {
|
||||||
|
args.push(1000);
|
||||||
|
for (let i = 0; i < 999; ++i) {
|
||||||
|
args = [...args, ...generateArgs('Number')];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return args;
|
||||||
|
};
|
||||||
|
|
||||||
|
const bench = common.createBenchmark(main, {
|
||||||
|
type: argsTypes,
|
||||||
|
engine: ['v8', 'napi'],
|
||||||
|
n: [1, 1e1, 1e2, 1e3, 1e4, 1e5],
|
||||||
|
});
|
||||||
|
|
||||||
|
function main({ n, engine, type }) {
|
||||||
|
const bindings = engine === 'v8' ? v8 : napi;
|
||||||
|
const methodName = 'callWith' + type;
|
||||||
|
const fn = bindings[methodName];
|
||||||
|
|
||||||
|
if (fn) {
|
||||||
|
const args = generateArgs(type);
|
||||||
|
|
||||||
|
bench.start();
|
||||||
|
for (var i = 0; i < n; i++) {
|
||||||
|
fn.apply(null, args);
|
||||||
|
}
|
||||||
|
bench.end(n);
|
||||||
|
}
|
||||||
|
}
|
229
benchmark/napi/function_args/napi_binding.c
Normal file
229
benchmark/napi/function_args/napi_binding.c
Normal file
@ -0,0 +1,229 @@
|
|||||||
|
#include <node_api.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static napi_value CallWithString(napi_env env, napi_callback_info info) {
|
||||||
|
napi_status status;
|
||||||
|
|
||||||
|
size_t argc = 1;
|
||||||
|
napi_value args[1];
|
||||||
|
status = napi_get_cb_info(env, info, &argc, args, NULL, NULL);
|
||||||
|
assert(status == napi_ok);
|
||||||
|
|
||||||
|
napi_valuetype types[1];
|
||||||
|
status = napi_typeof(env, args[0], types);
|
||||||
|
assert(status == napi_ok);
|
||||||
|
|
||||||
|
assert(types[0] == napi_string);
|
||||||
|
if (types[0] == napi_string) {
|
||||||
|
size_t len = 0;
|
||||||
|
// Get the length
|
||||||
|
status = napi_get_value_string_utf8(env, args[0], NULL, 0, &len);
|
||||||
|
assert(status == napi_ok);
|
||||||
|
char* buf = (char*)malloc(len + 1);
|
||||||
|
status = napi_get_value_string_utf8(env, args[0], buf, len + 1, &len);
|
||||||
|
assert(status == napi_ok);
|
||||||
|
free(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static napi_value CallWithArray(napi_env env, napi_callback_info info) {
|
||||||
|
napi_status status;
|
||||||
|
|
||||||
|
size_t argc = 1;
|
||||||
|
napi_value args[1];
|
||||||
|
status = napi_get_cb_info(env, info, &argc, args, NULL, NULL);
|
||||||
|
assert(status == napi_ok);
|
||||||
|
|
||||||
|
napi_value array = args[0];
|
||||||
|
bool is_array = false;
|
||||||
|
status = napi_is_array(env, array, &is_array);
|
||||||
|
assert(status == napi_ok);
|
||||||
|
|
||||||
|
assert(is_array);
|
||||||
|
if (is_array) {
|
||||||
|
uint32_t length;
|
||||||
|
status = napi_get_array_length(env, array, &length);
|
||||||
|
assert(status == napi_ok);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < length; ++i) {
|
||||||
|
napi_value v;
|
||||||
|
status = napi_get_element(env, array, i, &v);
|
||||||
|
assert(status == napi_ok);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static napi_value CallWithNumber(napi_env env, napi_callback_info info) {
|
||||||
|
napi_status status;
|
||||||
|
|
||||||
|
size_t argc = 1;
|
||||||
|
napi_value args[1];
|
||||||
|
status = napi_get_cb_info(env, info, &argc, args, NULL, NULL);
|
||||||
|
assert(status == napi_ok);
|
||||||
|
|
||||||
|
napi_valuetype types[1];
|
||||||
|
status = napi_typeof(env, args[0], types);
|
||||||
|
assert(status == napi_ok);
|
||||||
|
|
||||||
|
assert(types[0] == napi_number);
|
||||||
|
if (types[0] == napi_number) {
|
||||||
|
double value = 0.0;
|
||||||
|
status = napi_get_value_double(env, args[0], &value);
|
||||||
|
assert(status == napi_ok);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static napi_value CallWithObject(napi_env env, napi_callback_info info) {
|
||||||
|
napi_status status;
|
||||||
|
|
||||||
|
size_t argc = 1;
|
||||||
|
napi_value args[1];
|
||||||
|
status = napi_get_cb_info(env, info, &argc, args, NULL, NULL);
|
||||||
|
assert(status == napi_ok);
|
||||||
|
|
||||||
|
napi_valuetype types[1];
|
||||||
|
status = napi_typeof(env, args[0], types);
|
||||||
|
assert(status == napi_ok);
|
||||||
|
|
||||||
|
assert(argc == 1 && types[0] == napi_object);
|
||||||
|
if (argc == 1 && types[0] == napi_object) {
|
||||||
|
napi_value value;
|
||||||
|
|
||||||
|
status = napi_get_named_property(env, args[0], "map", &value);
|
||||||
|
assert(status == napi_ok);
|
||||||
|
|
||||||
|
status = napi_get_named_property(env, args[0], "operand", &value);
|
||||||
|
assert(status == napi_ok);
|
||||||
|
|
||||||
|
status = napi_get_named_property(env, args[0], "data", &value);
|
||||||
|
assert(status == napi_ok);
|
||||||
|
|
||||||
|
status = napi_get_named_property(env, args[0], "reduce", &value);
|
||||||
|
assert(status == napi_ok);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static napi_value CallWithTypedarray(napi_env env, napi_callback_info info) {
|
||||||
|
napi_status status;
|
||||||
|
|
||||||
|
size_t argc = 1;
|
||||||
|
napi_value args[1];
|
||||||
|
status = napi_get_cb_info(env, info, &argc, args, NULL, NULL);
|
||||||
|
assert(status == napi_ok);
|
||||||
|
|
||||||
|
bool is_typedarray = false;
|
||||||
|
status = napi_is_typedarray(env, args[0], &is_typedarray);
|
||||||
|
assert(status == napi_ok);
|
||||||
|
|
||||||
|
assert(is_typedarray);
|
||||||
|
if (is_typedarray) {
|
||||||
|
napi_typedarray_type type;
|
||||||
|
napi_value input_buffer;
|
||||||
|
size_t byte_offset = 0;
|
||||||
|
size_t length = 0;
|
||||||
|
status = napi_get_typedarray_info(env, args[0], &type, &length,
|
||||||
|
NULL, &input_buffer, &byte_offset);
|
||||||
|
assert(status == napi_ok);
|
||||||
|
assert(length > 0);
|
||||||
|
|
||||||
|
void* data = NULL;
|
||||||
|
size_t byte_length = 0;
|
||||||
|
status = napi_get_arraybuffer_info(env,
|
||||||
|
input_buffer, &data, &byte_length);
|
||||||
|
assert(status == napi_ok);
|
||||||
|
|
||||||
|
uint32_t* input_integers = (uint32_t*)((uint8_t*)(data) + byte_offset);
|
||||||
|
assert(input_integers);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static napi_value CallWithArguments(napi_env env, napi_callback_info info) {
|
||||||
|
napi_status status;
|
||||||
|
|
||||||
|
size_t argc = 1;
|
||||||
|
napi_value args[1000];
|
||||||
|
// Get the length
|
||||||
|
status = napi_get_cb_info(env, info, &argc, NULL, NULL, NULL);
|
||||||
|
assert(status == napi_ok);
|
||||||
|
|
||||||
|
status = napi_get_cb_info(env, info, &argc, args, NULL, NULL);
|
||||||
|
assert(status == napi_ok);
|
||||||
|
assert(argc <= 1000);
|
||||||
|
|
||||||
|
napi_valuetype types[1];
|
||||||
|
status = napi_typeof(env, args[0], types);
|
||||||
|
assert(status == napi_ok);
|
||||||
|
|
||||||
|
assert(argc > 1 && types[0] == napi_number);
|
||||||
|
if (argc > 1 && types[0] == napi_number) {
|
||||||
|
uint32_t loop = 0;
|
||||||
|
status = napi_get_value_uint32(env, args[0], &loop);
|
||||||
|
assert(status == napi_ok);
|
||||||
|
|
||||||
|
for (uint32_t i = 1; i < loop; ++i) {
|
||||||
|
assert(i < argc);
|
||||||
|
status = napi_typeof(env, args[i], types);
|
||||||
|
assert(status == napi_ok);
|
||||||
|
assert(types[0] == napi_number);
|
||||||
|
|
||||||
|
uint32_t value = 0;
|
||||||
|
status = napi_get_value_uint32(env, args[i], &value);
|
||||||
|
assert(status == napi_ok);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define EXPORT_FUNC(env, exports, name, func) \
|
||||||
|
do { \
|
||||||
|
napi_status status; \
|
||||||
|
napi_value js_func; \
|
||||||
|
status = napi_create_function((env), \
|
||||||
|
(name), \
|
||||||
|
NAPI_AUTO_LENGTH, \
|
||||||
|
(func), \
|
||||||
|
NULL, \
|
||||||
|
&js_func); \
|
||||||
|
assert(status == napi_ok); \
|
||||||
|
status = napi_set_named_property((env), \
|
||||||
|
(exports), \
|
||||||
|
(name), \
|
||||||
|
js_func); \
|
||||||
|
assert(status == napi_ok); \
|
||||||
|
} while (0);
|
||||||
|
|
||||||
|
|
||||||
|
NAPI_MODULE_INIT() {
|
||||||
|
EXPORT_FUNC(env, exports, "callWithString", CallWithString);
|
||||||
|
EXPORT_FUNC(env, exports, "callWithLongString", CallWithString);
|
||||||
|
|
||||||
|
EXPORT_FUNC(env, exports, "callWithArray", CallWithArray);
|
||||||
|
EXPORT_FUNC(env, exports, "callWithLargeArray", CallWithArray);
|
||||||
|
EXPORT_FUNC(env, exports, "callWithHugeArray", CallWithArray);
|
||||||
|
|
||||||
|
EXPORT_FUNC(env, exports, "callWithNumber", CallWithNumber);
|
||||||
|
|
||||||
|
EXPORT_FUNC(env, exports, "callWithObject", CallWithObject);
|
||||||
|
EXPORT_FUNC(env, exports, "callWithTypedarray", CallWithTypedarray);
|
||||||
|
|
||||||
|
EXPORT_FUNC(env, exports, "callWith10Numbers", CallWithArguments);
|
||||||
|
EXPORT_FUNC(env, exports, "callWith100Numbers", CallWithArguments);
|
||||||
|
EXPORT_FUNC(env, exports, "callWith1000Numbers", CallWithArguments);
|
||||||
|
|
||||||
|
return exports;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user