From 649a0546a42ee638ca68ee0d470c6ea4e3bdeb3e Mon Sep 17 00:00:00 2001 From: Vicente Eduardo Ferrer Garcia Date: Wed, 14 Aug 2024 17:02:05 +0200 Subject: [PATCH] Improved node port and added metacallfms. --- .../node_loader/source/node_loader_port.cpp | 112 +++++++++++++++++- source/ports/node_port/index.d.ts | 1 + source/ports/node_port/index.js | 15 ++- source/ports/node_port/test.js | 2 +- source/ports/node_port/test/index.js | 9 ++ 5 files changed, 131 insertions(+), 8 deletions(-) diff --git a/source/loaders/node_loader/source/node_loader_port.cpp b/source/loaders/node_loader/source/node_loader_port.cpp index c77592ff6..ed681f1e9 100644 --- a/source/loaders/node_loader/source/node_loader_port.cpp +++ b/source/loaders/node_loader/source/node_loader_port.cpp @@ -47,7 +47,6 @@ napi_value node_loader_port_metacall(napi_env env, napi_callback_info info) if (argc == 0) { napi_throw_error(env, nullptr, "Invalid number of arguments"); - return nullptr; } @@ -65,7 +64,8 @@ napi_value node_loader_port_metacall(napi_env env, napi_callback_info info) if (name == nullptr) { napi_throw_error(env, nullptr, "Invalid function name allocation"); - + delete[] argv; + delete[] args; return nullptr; } @@ -114,6 +114,105 @@ napi_value node_loader_port_metacall(napi_env env, napi_callback_info info) return result; } +napi_value node_loader_port_metacallfms(napi_env env, napi_callback_info info) +{ + size_t argc = 0; + + napi_get_cb_info(env, info, &argc, nullptr, nullptr, nullptr); + + if (argc != 2) + { + napi_throw_error(env, nullptr, "Invalid number of arguments"); + return nullptr; + } + + napi_value *argv = new napi_value[argc]; + napi_value recv; + + napi_get_cb_info(env, info, &argc, argv, &recv, nullptr); + + size_t name_length; + napi_status status = napi_get_value_string_utf8(env, argv[0], nullptr, 0, &name_length); + + char *name = new char[name_length + 1]; + + if (name == nullptr) + { + napi_throw_error(env, nullptr, "Invalid function name allocation"); + delete[] argv; + return nullptr; + } + + status = napi_get_value_string_utf8(env, argv[0], name, name_length + 1, &name_length); + + name[name_length] = '\0'; + + node_loader_impl_exception(env, status); + + void *func = metacall_function(name); + + if (func == NULL) + { + napi_throw_error(env, nullptr, "The function does not exist"); + delete[] argv; + delete[] name; + return nullptr; + } + + size_t buffer_length; + status = napi_get_value_string_utf8(env, argv[1], nullptr, 0, &buffer_length); + + char *buffer = new char[buffer_length + 1]; + + if (buffer == nullptr) + { + napi_throw_error(env, nullptr, "Invalid function buffer allocation"); + delete[] argv; + delete[] name; + return nullptr; + } + + status = napi_get_value_string_utf8(env, argv[1], buffer, buffer_length + 1, &buffer_length); + + buffer[buffer_length] = '\0'; + + node_loader_impl_exception(env, status); + + /* Obtain NodeJS loader implementation */ + loader_impl impl = loader_get_impl(node_loader_tag); + loader_impl_node node_impl = (loader_impl_node)loader_impl_get(impl); + + /* Store current reference of the environment */ + node_loader_impl_env(node_impl, env); + + struct metacall_allocator_std_type std_ctx = { &std::malloc, &std::realloc, &std::free }; + + void *allocator = metacall_allocator_create(METACALL_ALLOCATOR_STD, (void *)&std_ctx); + + /* Call to the function */ + void *ret = metacallfms(func, buffer, buffer_length + 1, allocator); + + metacall_allocator_destroy(allocator); + + napi_value result = node_loader_impl_value_to_napi(node_impl, env, ret); + + if (metacall_value_id(ret) == METACALL_THROWABLE) + { + napi_throw(env, result); + } + + /* Release current reference of the environment */ + // node_loader_impl_env(node_impl, nullptr); + + metacall_value_destroy(ret); + + delete[] argv; + delete[] name; + delete[] buffer; + + return result; +} + napi_value node_loader_port_metacall_await(napi_env env, napi_callback_info info) { size_t argc = 0; @@ -123,7 +222,6 @@ napi_value node_loader_port_metacall_await(napi_env env, napi_callback_info info if (argc == 0) { napi_throw_error(env, nullptr, "Invalid number of arguments"); - return nullptr; } @@ -142,7 +240,8 @@ napi_value node_loader_port_metacall_await(napi_env env, napi_callback_info info if (name == nullptr) { napi_throw_error(env, nullptr, "Invalid function name allocation"); - + delete[] argv; + delete[] args; return nullptr; } @@ -414,8 +513,8 @@ napi_value node_loader_port_metacall_load_from_memory(napi_env env, napi_callbac if (script == nullptr) { - delete[] tag; napi_throw_error(env, nullptr, "MetaCall could not load from memory, script allocation failed"); + delete[] tag; return nullptr; } @@ -489,8 +588,8 @@ napi_value node_loader_port_metacall_load_from_memory_export(napi_env env, napi_ if (script == nullptr) { - delete[] tag; napi_throw_error(env, nullptr, "MetaCall could not load from memory, script allocation failed"); + delete[] tag; return nullptr; } @@ -715,6 +814,7 @@ void node_loader_port_exports(napi_env env, napi_value exports) #define NODE_LOADER_PORT_DECL_X_MACRO(x) \ x(metacall); \ + x(metacallfms); \ x(metacall_await); \ x(metacall_load_from_file); \ x(metacall_load_from_file_export); \ diff --git a/source/ports/node_port/index.d.ts b/source/ports/node_port/index.d.ts index 40f4c1c56..7b1d6d1bd 100644 --- a/source/ports/node_port/index.d.ts +++ b/source/ports/node_port/index.d.ts @@ -1,5 +1,6 @@ declare module 'metacall' { export function metacall(name: string, ...args: any): any; + export function metacallfms(name: string, buffer: string): any; export function metacall_load_from_file(tag: string, paths: string[]): number; export function metacall_load_from_file_export(tag: string, paths: string[]): any; export function metacall_load_from_memory(tag: string, code: string): number; diff --git a/source/ports/node_port/index.js b/source/ports/node_port/index.js index 2aa604289..10fcbf24e 100644 --- a/source/ports/node_port/index.js +++ b/source/ports/node_port/index.js @@ -82,6 +82,18 @@ const metacall = (name, ...args) => { return addon.metacall(name, ...args); }; +const metacallfms = (name, buffer) => { + if (Object.prototype.toString.call(name) !== '[object String]') { + throw Error('Function name should be of string type.'); + } + + if (Object.prototype.toString.call(buffer) !== '[object String]') { + throw Error('Buffer should be of string type.'); + } + + return addon.metacallfms(name, buffer); +}; + const metacall_await = (name, ...args) => { if (Object.prototype.toString.call(name) !== '[object String]') { throw Error('Function name should be of string type.'); @@ -172,7 +184,7 @@ const metacall_handle = (tag, name) => { // TODO: This can be implemented with metacall_handle C API, meanwhile we use this trick const inspect = metacall_inspect(); - if (inspect === {} || inspect === undefined) { + if (inspect === undefined) { return null; } @@ -192,6 +204,7 @@ const metacall_require = (tag, name) => { /* Module exports */ const module_exports = { metacall, + metacallfms, metacall_await, metacall_inspect, metacall_load_from_file, diff --git a/source/ports/node_port/test.js b/source/ports/node_port/test.js index 1bab3e30b..fb04ea5b1 100644 --- a/source/ports/node_port/test.js +++ b/source/ports/node_port/test.js @@ -26,7 +26,7 @@ const mocha = new Mocha(); const testDir = path.resolve(__dirname, 'test'); fs.readdirSync(testDir).filter((file) => { - return file.substr(-3) === '.js'; + return path.extname(file) === '.js'; }).forEach((file) => { mocha.addFile( path.join(testDir, file) diff --git a/source/ports/node_port/test/index.js b/source/ports/node_port/test/index.js index 83d66e0f6..c6a71114c 100644 --- a/source/ports/node_port/test/index.js +++ b/source/ports/node_port/test/index.js @@ -24,6 +24,7 @@ const assert = require('assert'); const { metacall, + metacallfms, metacall_load_from_file, metacall_load_from_file_export, metacall_load_from_memory, @@ -37,6 +38,7 @@ describe('metacall', () => { describe('defined', () => { it('functions metacall and metacall_load_from_file must be defined', () => { assert.notStrictEqual(metacall, undefined); + assert.notStrictEqual(metacallfms, undefined); assert.notStrictEqual(metacall_load_from_memory, undefined); assert.notStrictEqual(metacall_load_from_file, undefined); assert.notStrictEqual(metacall_load_from_memory_export, undefined); @@ -280,6 +282,13 @@ describe('metacall', () => { } }); + describe('call by map', () => { + it('metacallfms (py)', () => { + assert.strictEqual(metacallfms('s_sum', '{"left":2,"right":2}'), 4); + assert.strictEqual(metacallfms('s_sum', '{"right":2,"left":2}'), 4); + }); + }); + describe('callback', () => { it('callback (py)', () => { const py_f = require('function.py');