From 7a73edb20b6eca189236627586614859df8e8052 Mon Sep 17 00:00:00 2001 From: Felix D Rodriguez Perez Date: Tue, 16 May 2023 16:23:11 +0100 Subject: [PATCH 1/3] Update translate.zig to zig v 0.11 --- src/translate.zig | 134 ++++++++++++++++++++++++++-------------------- 1 file changed, 77 insertions(+), 57 deletions(-) diff --git a/src/translate.zig b/src/translate.zig index 5546b33..93e4f3f 100644 --- a/src/translate.zig +++ b/src/translate.zig @@ -2,6 +2,16 @@ // // SPDX-License-Identifier: Apache-2.0 +// References: +// https://github.com/staltz/zig-nodejs-example +// https://github.com/tigerbeetledb/tigerbeetle-node + +// Fix error: parameter of type 'fn' must be declared comptime +// https://stackoverflow.com/questions/74251650/how-to-pass-zig-function-pointers-to-other-functions +// Starting with 0.10, there are 2 ways to pass a function as an argument: +// As a function body. Must be comptime-known. +// As a function pointer. + const std = @import("std"); const assert = std.debug.assert; const c = @import("c.zig"); @@ -10,14 +20,14 @@ pub fn register_function( env: c.napi_env, exports: c.napi_value, comptime name: [:0]const u8, - function: fn (env: c.napi_env, info: c.napi_callback_info) callconv(.C) c.napi_value, + comptime function: fn (env: c.napi_env, info: c.napi_callback_info) callconv(.C) c.napi_value, ) !void { var napi_function: c.napi_value = undefined; - if (c.napi_create_function(env, null, 0, function, null, &napi_function) != .napi_ok) { + if (c.napi_create_function(env, null, 0, function, null, &napi_function) != c.napi_ok) { return throw(env, "Failed to create function " ++ name ++ "()."); } - if (c.napi_set_named_property(env, exports, name, napi_function) != .napi_ok) { + if (c.napi_set_named_property(env, exports, name, napi_function) != c.napi_ok) { return throw(env, "Failed to add " ++ name ++ "() to exports."); } } @@ -26,7 +36,7 @@ const TranslationError = error{ExceptionThrown}; pub fn throw(env: c.napi_env, comptime message: [:0]const u8) TranslationError { var result = c.napi_throw_error(env, null, message); switch (result) { - .napi_ok, .napi_pending_exception => {}, + c.napi_ok, c.napi_pending_exception => {}, else => unreachable, } @@ -35,7 +45,7 @@ pub fn throw(env: c.napi_env, comptime message: [:0]const u8) TranslationError { pub fn capture_undefined(env: c.napi_env) !c.napi_value { var result: c.napi_value = undefined; - if (c.napi_get_undefined(env, &result) != .napi_ok) { + if (c.napi_get_undefined(env, &result) != c.napi_ok) { return throw(env, "Failed to capture the value of \"undefined\"."); } @@ -44,17 +54,17 @@ pub fn capture_undefined(env: c.napi_env) !c.napi_value { pub fn set_instance_data( env: c.napi_env, - data: *c_void, - finalize_callback: fn (env: c.napi_env, data: ?*c_void, hint: ?*c_void) callconv(.C) void, + data: *anyopaque, + finalize_callback: fn (env: c.napi_env, data: ?*anyopaque, hint: ?*anyopaque) callconv(.C) void, ) !void { - if (c.napi_set_instance_data(env, data, finalize_callback, null) != .napi_ok) { + if (c.napi_set_instance_data(env, data, finalize_callback, null) != c.napi_ok) { return throw(env, "Failed to initialize environment."); } } -pub fn create_external(env: c.napi_env, context: *c_void) !c.napi_value { +pub fn create_external(env: c.napi_env, context: *anyopaque) !c.napi_value { var result: c.napi_value = null; - if (c.napi_create_external(env, context, null, null, &result) != .napi_ok) { + if (c.napi_create_external(env, context, null, null, &result) != c.napi_ok) { return throw(env, "Failed to create external for client context."); } @@ -65,9 +75,9 @@ pub fn value_external( env: c.napi_env, value: c.napi_value, comptime error_message: [:0]const u8, -) !?*c_void { - var result: ?*c_void = undefined; - if (c.napi_get_value_external(env, value, &result) != .napi_ok) { +) !?*anyopaque { + var result: ?*anyopaque = undefined; + if (c.napi_get_value_external(env, value, &result) != c.napi_ok) { return throw(env, error_message); } @@ -83,13 +93,13 @@ pub const UserData = packed struct { /// This reference will be destroyed when we return the server response to JS. pub fn user_data_from_value(env: c.napi_env, value: c.napi_value) !UserData { var callback_type: c.napi_valuetype = undefined; - if (c.napi_typeof(env, value, &callback_type) != .napi_ok) { + if (c.napi_typeof(env, value, &callback_type) != c.napi_ok) { return throw(env, "Failed to check callback type."); } - if (callback_type != .napi_function) return throw(env, "Callback must be a Function."); + if (callback_type != c.napi_function) return throw(env, "Callback must be a Function."); var callback_reference: c.napi_ref = undefined; - if (c.napi_create_reference(env, value, 1, &callback_reference) != .napi_ok) { + if (c.napi_create_reference(env, value, 1, &callback_reference) != c.napi_ok) { return throw(env, "Failed to create reference to callback."); } @@ -99,9 +109,9 @@ pub fn user_data_from_value(env: c.napi_env, value: c.napi_value) !UserData { }; } -pub fn globals(env: c.napi_env) !?*c_void { - var data: ?*c_void = null; - if (c.napi_get_instance_data(env, &data) != .napi_ok) { +pub fn globals(env: c.napi_env) !?*anyopaque { + var data: ?*anyopaque = null; + if (c.napi_get_instance_data(env, &data) != c.napi_ok) { return throw(env, "Failed to decode globals."); } @@ -114,7 +124,7 @@ pub fn slice_from_object( comptime key: [:0]const u8, ) ![]const u8 { var property: c.napi_value = undefined; - if (c.napi_get_named_property(env, object, key, &property) != .napi_ok) { + if (c.napi_get_named_property(env, object, key, &property) != c.napi_ok) { return throw(env, key ++ " must be defined"); } @@ -127,13 +137,13 @@ pub fn slice_from_value( comptime key: [:0]const u8, ) ![]u8 { var is_buffer: bool = undefined; - assert(c.napi_is_buffer(env, value, &is_buffer) == .napi_ok); + assert(c.napi_is_buffer(env, value, &is_buffer) == c.napi_ok); if (!is_buffer) return throw(env, key ++ " must be a buffer"); - var data: ?*c_void = null; + var data: ?*anyopaque = null; var data_length: usize = undefined; - assert(c.napi_get_buffer_info(env, value, &data, &data_length) == .napi_ok); + assert(c.napi_get_buffer_info(env, value, &data, &data_length) == c.napi_ok); if (data_length < 1) return throw(env, key ++ " must not be empty"); @@ -147,7 +157,7 @@ pub fn bytes_from_object( comptime key: [:0]const u8, ) ![length]u8 { var property: c.napi_value = undefined; - if (c.napi_get_named_property(env, object, key, &property) != .napi_ok) { + if (c.napi_get_named_property(env, object, key, &property) != c.napi_ok) { return throw(env, key ++ " must be defined"); } @@ -185,7 +195,7 @@ pub fn bytes_from_buffer( pub fn u128_from_object(env: c.napi_env, object: c.napi_value, comptime key: [:0]const u8) !u128 { var property: c.napi_value = undefined; - if (c.napi_get_named_property(env, object, key, &property) != .napi_ok) { + if (c.napi_get_named_property(env, object, key, &property) != c.napi_ok) { return throw(env, key ++ " must be defined"); } @@ -194,7 +204,7 @@ pub fn u128_from_object(env: c.napi_env, object: c.napi_value, comptime key: [:0 pub fn u64_from_object(env: c.napi_env, object: c.napi_value, comptime key: [:0]const u8) !u64 { var property: c.napi_value = undefined; - if (c.napi_get_named_property(env, object, key, &property) != .napi_ok) { + if (c.napi_get_named_property(env, object, key, &property) != c.napi_ok) { return throw(env, key ++ " must be defined"); } @@ -203,7 +213,7 @@ pub fn u64_from_object(env: c.napi_env, object: c.napi_value, comptime key: [:0] pub fn u32_from_object(env: c.napi_env, object: c.napi_value, comptime key: [:0]const u8) !u32 { var property: c.napi_value = undefined; - if (c.napi_get_named_property(env, object, key, &property) != .napi_ok) { + if (c.napi_get_named_property(env, object, key, &property) != c.napi_ok) { return throw(env, key ++ " must be defined"); } @@ -229,8 +239,8 @@ pub fn u128_from_value(env: c.napi_env, value: c.napi_value, comptime name: [:0] const words = @ptrCast(*[2]u64, &result); var word_count: usize = 2; switch (c.napi_get_value_bigint_words(env, value, &sign_bit, &word_count, words)) { - .napi_ok => {}, - .napi_bigint_expected => return throw(env, name ++ " must be a BigInt"), + c.napi_ok => {}, + c.napi_bigint_expected => return throw(env, name ++ " must be a BigInt"), else => unreachable, } if (sign_bit != 0) return throw(env, name ++ " must be positive"); @@ -243,8 +253,8 @@ pub fn u64_from_value(env: c.napi_env, value: c.napi_value, comptime name: [:0]c var result: u64 = undefined; var lossless: bool = undefined; switch (c.napi_get_value_bigint_uint64(env, value, &result, &lossless)) { - .napi_ok => {}, - .napi_bigint_expected => return throw(env, name ++ " must be an unsigned 64-bit BigInt"), + c.napi_ok => {}, + c.napi_bigint_expected => return throw(env, name ++ " must be an unsigned 64-bit BigInt"), else => unreachable, } if (!lossless) return throw(env, name ++ " conversion was lossy"); @@ -258,8 +268,8 @@ pub fn u32_from_value(env: c.napi_env, value: c.napi_value, comptime name: [:0]c // In that case we need to use the appropriate napi method to do more type checking here. // We want to make sure this is: unsigned, and an integer. switch (c.napi_get_value_uint32(env, value, &result)) { - .napi_ok => {}, - .napi_number_expected => return throw(env, name ++ " must be a number"), + c.napi_ok => {}, + c.napi_number_expected => return throw(env, name ++ " must be a number"), else => unreachable, } return result; @@ -274,11 +284,11 @@ pub fn byte_slice_into_object( ) !void { var result: c.napi_value = undefined; // create a copy that is managed by V8. - if (c.napi_create_buffer_copy(env, value.len, value.ptr, null, &result) != .napi_ok) { + if (c.napi_create_buffer_copy(env, value.len, value.ptr, null, &result) != c.napi_ok) { return throw(env, error_message ++ " Failed to allocate Buffer in V8."); } - if (c.napi_set_named_property(env, object, key, result) != .napi_ok) { + if (c.napi_set_named_property(env, object, key, result) != c.napi_ok) { return throw(env, error_message); } } @@ -301,11 +311,11 @@ pub fn u128_into_object( 2, @ptrCast(*const [2]u64, &value), &bigint, - ) != .napi_ok) { + ) != c.napi_ok) { return throw(env, error_message); } - if (c.napi_set_named_property(env, object, key, bigint) != .napi_ok) { + if (c.napi_set_named_property(env, object, key, bigint) != c.napi_ok) { return throw(env, error_message); } } @@ -318,11 +328,11 @@ pub fn u64_into_object( comptime error_message: [:0]const u8, ) !void { var result: c.napi_value = undefined; - if (c.napi_create_bigint_uint64(env, value, &result) != .napi_ok) { + if (c.napi_create_bigint_uint64(env, value, &result) != c.napi_ok) { return throw(env, error_message); } - if (c.napi_set_named_property(env, object, key, result) != .napi_ok) { + if (c.napi_set_named_property(env, object, key, result) != c.napi_ok) { return throw(env, error_message); } } @@ -335,18 +345,28 @@ pub fn u32_into_object( comptime error_message: [:0]const u8, ) !void { var result: c.napi_value = undefined; - if (c.napi_create_uint32(env, value, &result) != .napi_ok) { + if (c.napi_create_uint32(env, value, &result) != c.napi_ok) { return throw(env, error_message); } - if (c.napi_set_named_property(env, object, key, result) != .napi_ok) { + if (c.napi_set_named_property(env, object, key, result) != c.napi_ok) { return throw(env, error_message); } } +pub fn u16_into_object( + env: c.napi_env, + object: c.napi_value, + comptime key: [:0]const u8, + value: u16, + comptime error_message: [:0]const u8, +) !void { + try u32_into_object(env, object, key, value, error_message); +} + pub fn create_object(env: c.napi_env, comptime error_message: [:0]const u8) !c.napi_value { var result: c.napi_value = undefined; - if (c.napi_create_object(env, &result) != .napi_ok) { + if (c.napi_create_object(env, &result) != c.napi_ok) { return throw(env, error_message); } @@ -355,7 +375,7 @@ pub fn create_object(env: c.napi_env, comptime error_message: [:0]const u8) !c.n pub fn create_string(env: c.napi_env, value: [:0]const u8) !c.napi_value { var result: c.napi_value = undefined; - if (c.napi_create_string_utf8(env, value, value.len, &result) != .napi_ok) { + if (c.napi_create_string_utf8(env, value, value.len, &result) != c.napi_ok) { return throw(env, "Failed to create string"); } @@ -367,9 +387,9 @@ fn create_buffer( value: []const u8, comptime error_message: [:0]const u8, ) !c.napi_value { - var data: ?*c_void = undefined; + var data: ?*anyopaque = undefined; var result: c.napi_value = undefined; - if (c.napi_create_buffer(env, value.len, &data, &result) != .napi_ok) { + if (c.napi_create_buffer(env, value.len, &data, &result) != c.napi_ok) { return throw(env, error_message); } @@ -384,7 +404,7 @@ pub fn create_array( comptime error_message: [:0]const u8, ) !c.napi_value { var result: c.napi_value = undefined; - if (c.napi_create_array_with_length(env, length, &result) != .napi_ok) { + if (c.napi_create_array_with_length(env, length, &result) != c.napi_ok) { return throw(env, error_message); } @@ -398,14 +418,14 @@ pub fn set_array_element( value: c.napi_value, comptime error_message: [:0]const u8, ) !void { - if (c.napi_set_element(env, array, index, value) != .napi_ok) { + if (c.napi_set_element(env, array, index, value) != c.napi_ok) { return throw(env, error_message); } } pub fn array_element(env: c.napi_env, array: c.napi_value, index: u32) !c.napi_value { var element: c.napi_value = undefined; - if (c.napi_get_element(env, array, index, &element) != .napi_ok) { + if (c.napi_get_element(env, array, index, &element) != c.napi_ok) { return throw(env, "Failed to get array element."); } @@ -414,17 +434,17 @@ pub fn array_element(env: c.napi_env, array: c.napi_value, index: u32) !c.napi_v pub fn array_length(env: c.napi_env, array: c.napi_value) !u32 { var is_array: bool = undefined; - assert(c.napi_is_array(env, array, &is_array) == .napi_ok); + assert(c.napi_is_array(env, array, &is_array) == c.napi_ok); if (!is_array) return throw(env, "Batch must be an Array."); var length: u32 = undefined; - assert(c.napi_get_array_length(env, array, &length) == .napi_ok); + assert(c.napi_get_array_length(env, array, &length) == c.napi_ok); return length; } pub fn delete_reference(env: c.napi_env, reference: c.napi_ref) !void { - if (c.napi_delete_reference(env, reference) != .napi_ok) { + if (c.napi_delete_reference(env, reference) != c.napi_ok) { return throw(env, "Failed to delete callback reference."); } } @@ -434,12 +454,12 @@ pub fn create_error( comptime message: [:0]const u8, ) TranslationError!c.napi_value { var napi_string: c.napi_value = undefined; - if (c.napi_create_string_utf8(env, message, std.mem.len(message), &napi_string) != .napi_ok) { + if (c.napi_create_string_utf8(env, message, std.mem.len(message), &napi_string) != c.napi_ok) { return TranslationError.ExceptionThrown; } var napi_error: c.napi_value = undefined; - if (c.napi_create_error(env, null, napi_string, &napi_error) != .napi_ok) { + if (c.napi_create_error(env, null, napi_string, &napi_error) != c.napi_ok) { return TranslationError.ExceptionThrown; } @@ -455,17 +475,17 @@ pub fn call_function( ) !void { const result = c.napi_call_function(env, this, callback, argc, argv, null); switch (result) { - .napi_ok => {}, + c.napi_ok => {}, // the user's callback may throw a JS exception or call other functions that do so. We // therefore don't throw another error. - .napi_pending_exception => {}, + c.napi_pending_exception => {}, else => return throw(env, "Failed to invoke results callback."), } } pub fn scope(env: c.napi_env, comptime error_message: [:0]const u8) !c.napi_value { var result: c.napi_value = undefined; - if (c.napi_get_global(env, &result) != .napi_ok) { + if (c.napi_get_global(env, &result) != c.napi_ok) { return throw(env, error_message); } @@ -478,7 +498,7 @@ pub fn reference_value( comptime error_message: [:0]const u8, ) !c.napi_value { var result: c.napi_value = undefined; - if (c.napi_get_reference_value(env, callback_reference, &result) != .napi_ok) { + if (c.napi_get_reference_value(env, callback_reference, &result) != c.napi_ok) { return throw(env, error_message); } From ae7c76a41949331e6c7e96177cd9e8deda211de4 Mon Sep 17 00:00:00 2001 From: Felix D Rodriguez Perez Date: Tue, 16 May 2023 16:29:04 +0100 Subject: [PATCH 2/3] Update lib.zig unused var MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Here we’ve had to assign values to _, as Zig does not allow us to have unused values. https://ziglearn.org/chapter-1/#for --- src/lib.zig | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib.zig b/src/lib.zig index 042459f..c806621 100644 --- a/src/lib.zig +++ b/src/lib.zig @@ -4,6 +4,7 @@ const c = @import("c.zig"); const translate = @import("translate.zig"); export fn napi_register_module_v1(env: c.napi_env, exports: c.napi_value) c.napi_value { + _ = info; translate.register_function(env, exports, "greet", greet) catch return null; return exports; } From 4f406470a583573492ba06e358728a39f3473966 Mon Sep 17 00:00:00 2001 From: Felix D Rodriguez Perez Date: Tue, 16 May 2023 16:30:56 +0100 Subject: [PATCH 3/3] Fix Update lib.zig unused var MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Here we’ve had to assign values to _, as Zig does not allow us to have unused values. https://ziglearn.org/chapter-1/#for --- src/lib.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.zig b/src/lib.zig index c806621..4f744b3 100644 --- a/src/lib.zig +++ b/src/lib.zig @@ -4,11 +4,11 @@ const c = @import("c.zig"); const translate = @import("translate.zig"); export fn napi_register_module_v1(env: c.napi_env, exports: c.napi_value) c.napi_value { - _ = info; translate.register_function(env, exports, "greet", greet) catch return null; return exports; } fn greet(env: c.napi_env, info: c.napi_callback_info) callconv(.C) c.napi_value { + _ = info; return translate.create_string(env, "world") catch return null; }