diff --git a/.github/actions/install/action.yml b/.github/actions/install/action.yml index ac34cffb..98379b98 100644 --- a/.github/actions/install/action.yml +++ b/.github/actions/install/action.yml @@ -17,7 +17,7 @@ inputs: zig-v8: description: 'zig v8 version to install' required: false - default: 'v0.1.18' + default: 'v0.1.19' v8: description: 'v8 version to install' required: false diff --git a/Dockerfile b/Dockerfile index e3c23039..c4ab1282 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,7 +5,7 @@ ARG ZIG=0.14.0 ARG ZIG_MINISIG=RWSGOq2NVecA2UPNdBUZykf1CCb147pkmdtYxgb3Ti+JO/wCYvhbAb/U ARG ARCH=x86_64 ARG V8=11.1.134 -ARG ZIG_V8=v0.1.18 +ARG ZIG_V8=v0.1.19 RUN apt-get update -yq && \ apt-get install -yq xz-utils \ diff --git a/build.zig.zon b/build.zig.zon index aa2dda2d..896236da 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -13,8 +13,8 @@ .hash = "tigerbeetle_io-0.0.0-ViLgxpyRBAB5BMfIcj3KMXfbJzwARs9uSl8aRy2OXULd", }, .v8 = .{ - .url = "https://github.com/lightpanda-io/zig-v8-fork/archive/97bcfb61da8c97de1321d677a6727a927a9db9a4.tar.gz", - .hash = "v8-0.0.0-xddH69DoIADZ8YXZ_EIx_tKdQKEoGsgob_3_ZIi0O_nV", + .url = "https://github.com/lightpanda-io/zig-v8-fork/archive/5d46f159ca44535cfb4fccd9d46f719eb7eac5fc.tar.gz", + .hash = "v8-0.0.0-xddH66zuIADu8FcQx2kkczC0yhqBY7LoA08-GRWF_zMA", }, //.v8 = .{ .path = "../zig-v8-fork" }, //.tigerbeetle_io = .{ .path = "../tigerbeetle-io" }, diff --git a/src/runtime/js.zig b/src/runtime/js.zig index e1a577c6..ebe90ee5 100644 --- a/src/runtime/js.zig +++ b/src/runtime/js.zig @@ -1932,7 +1932,7 @@ fn Caller(comptime E: type) type { if (last_parameter_type_info == .pointer and last_parameter_type_info.pointer.size == .slice) { const slice_type = last_parameter_type_info.pointer.child; const corresponding_js_value = info.getArg(@as(u32, @intCast(last_js_parameter))); - if (corresponding_js_value.isArray() == false and slice_type != u8) { + if (corresponding_js_value.isArray() == false and corresponding_js_value.isTypedArray() == false and slice_type != u8) { is_variadic = true; if (js_parameter_count == 0) { @field(args, tupleFieldName(params_to_map.len + offset - 1)) = &.{}; @@ -2005,6 +2005,70 @@ fn Caller(comptime E: type) type { } }, .slice => { + if (js_value.isTypedArray()) { + const buffer_view = js_value.castTo(v8.ArrayBufferView); + const buffer = buffer_view.getBuffer(); + const backing_store = v8.BackingStore.sharedPtrGet(&buffer.getBackingStore()); + const data = backing_store.getData(); + const byte_len = backing_store.getByteLength(); + + switch (ptr.child) { + u8 => { + // need this sentinel check to keep the compiler happy + if (ptr.sentinel() == null) { + if (js_value.isUint8Array() or js_value.isUint8ClampedArray()) { + const arr_ptr = @as([*]u8, @alignCast(@ptrCast(data))); + return arr_ptr[0..byte_len]; + } + } + }, + i8 => { + if (js_value.isInt8Array()) { + const arr_ptr = @as([*]i8, @alignCast(@ptrCast(data))); + return arr_ptr[0..byte_len]; + } + }, + u16 => { + if (js_value.isUint16Array()) { + const arr_ptr = @as([*]u16, @alignCast(@ptrCast(data))); + return arr_ptr[0 .. byte_len / 2]; + } + }, + i16 => { + if (js_value.isInt16Array()) { + const arr_ptr = @as([*]i16, @alignCast(@ptrCast(data))); + return arr_ptr[0 .. byte_len / 2]; + } + }, + u32 => { + if (js_value.isUint32Array()) { + const arr_ptr = @as([*]u32, @alignCast(@ptrCast(data))); + return arr_ptr[0 .. byte_len / 4]; + } + }, + i32 => { + if (js_value.isInt32Array()) { + const arr_ptr = @as([*]i32, @alignCast(@ptrCast(data))); + return arr_ptr[0 .. byte_len / 4]; + } + }, + u64 => { + if (js_value.isBigUint64Array()) { + const arr_ptr = @as([*]u64, @alignCast(@ptrCast(data))); + return arr_ptr[0 .. byte_len / 8]; + } + }, + i64 => { + if (js_value.isBigInt64Array()) { + const arr_ptr = @as([*]i64, @alignCast(@ptrCast(data))); + return arr_ptr[0 .. byte_len / 8]; + } + }, + else => {}, + } + return error.InvalidArgument; + } + if (ptr.child == u8) { if (ptr.sentinel()) |s| { if (comptime s == 0) { @@ -2015,18 +2079,6 @@ fn Caller(comptime E: type) type { } } - // TODO: TypedArray - // if (js_value.isArrayBufferView()) { - // const abv = js_value.castTo(v8.ArrayBufferView); - // const ab = abv.getBuffer(); - // const bs = v8.BackingStore.sharedPtrGet(&ab.getBackingStore()); - // const data = bs.getData(); - // var arr = @as([*]i32, @alignCast(@ptrCast(data)))[0..2]; - // std.debug.print("{d} {d} {d}\n", .{arr[0], arr[1], bs.getByteLength()}); - // arr[1] = 3333; - // return &.{}; - // } - if (!js_value.isArray()) { return error.InvalidArgument; } @@ -2101,7 +2153,7 @@ fn Caller(comptime E: type) type { else => {}, } - @compileError(std.fmt.comptimePrint("{s} has an unsupported parameter type: {s}", .{ named_function.full_name, @typeName(T) })); + @compileError(named_function.full_name ++ " has an unsupported parameter type: " ++ @typeName(T)); } fn jsIntToZig(comptime T: type, js_value: v8.Value, context: v8.Context) !T { diff --git a/src/runtime/test_primitive_types.zig b/src/runtime/test_primitive_types.zig index a2b64f93..9ba04261 100644 --- a/src/runtime/test_primitive_types.zig +++ b/src/runtime/test_primitive_types.zig @@ -104,6 +104,54 @@ const Primitives = struct { pub fn _echoStringZ(_: *const Primitives, a: [:0]const u8) []const u8 { return a; } + + pub fn _int8(_: *const Primitives, arr: []i8) void { + for (arr) |*a| { + a.* -= @intCast(arr.len); + } + } + + pub fn _uint8(_: *const Primitives, arr: []u8) void { + for (arr) |*a| { + a.* += @intCast(arr.len); + } + } + + pub fn _int16(_: *const Primitives, arr: []i16) void { + for (arr) |*a| { + a.* -= @intCast(arr.len); + } + } + + pub fn _uint16(_: *const Primitives, arr: []u16) void { + for (arr) |*a| { + a.* += @intCast(arr.len); + } + } + + pub fn _int32(_: *const Primitives, arr: []i32) void { + for (arr) |*a| { + a.* -= @intCast(arr.len); + } + } + + pub fn _uint32(_: *const Primitives, arr: []u32) void { + for (arr) |*a| { + a.* += @intCast(arr.len); + } + } + + pub fn _int64(_: *const Primitives, arr: []i64) void { + for (arr) |*a| { + a.* -= @intCast(arr.len); + } + } + + pub fn _uint64(_: *const Primitives, arr: []u64) void { + for (arr) |*a| { + a.* += @intCast(arr.len); + } + } }; const testing = @import("testing.zig"); @@ -185,4 +233,55 @@ test "JS: primitive types" { .{ "p.echoString('over 9000!');", "over 9000!" }, .{ "p.echoStringZ('Teg');", "Teg" }, }, .{}); + + // typed arrays + try runner.testCases(&.{ + .{ "let arr_i8 = new Int8Array([-10, -20, -30]);", "undefined" }, + .{ "p.int8(arr_i8)", "undefined" }, + .{ "arr_i8;", "-13,-23,-33" }, + + .{ "let arr_u8 = new Uint8Array([10, 20, 30]);", "undefined" }, + .{ "p.uint8(arr_u8)", "undefined" }, + .{ "arr_u8;", "13,23,33" }, + + .{ "let arr_i16 = new Int16Array([-1000, -2000, -3000]);", "undefined" }, + .{ "p.int16(arr_i16)", "undefined" }, + .{ "arr_i16;", "-1003,-2003,-3003" }, + + .{ "let arr_u16 = new Uint16Array([1000, 2000, 3000]);", "undefined" }, + .{ "p.uint16(arr_u16)", "undefined" }, + .{ "arr_u16;", "1003,2003,3003" }, + + .{ "let arr_i32 = new Int32Array([-1000000, -2000000, -3000000]);", "undefined" }, + .{ "p.int32(arr_i32)", "undefined" }, + .{ "arr_i32;", "-1000003,-2000003,-3000003" }, + + .{ "let arr_u32 = new Uint32Array([1000000, 2000000, 3000000]);", "undefined" }, + .{ "p.uint32(arr_u32)", "undefined" }, + .{ "arr_u32;", "1000003,2000003,3000003" }, + + .{ "let arr_i64 = new BigInt64Array([-1000000000n, -2000000000n, -3000000000n]);", "undefined" }, + .{ "p.int64(arr_i64)", "undefined" }, + .{ "arr_i64;", "-1000000003,-2000000003,-3000000003" }, + + .{ "let arr_u64 = new BigUint64Array([1000000000n, 2000000000n, 3000000000n]);", "undefined" }, + .{ "p.uint64(arr_u64)", "undefined" }, + .{ "arr_u64;", "1000000003,2000000003,3000000003" }, + + .{ "try { p.int8(arr_u8) } catch(e) { e instanceof TypeError; }", "true" }, + .{ "try { p.intu8(arr_i8) } catch(e) { e instanceof TypeError; }", "true" }, + .{ "try { p.intu8(arr_u32) } catch(e) { e instanceof TypeError; }", "true" }, + + .{ "try { p.int16(arr_u8) } catch(e) { e instanceof TypeError; }", "true" }, + .{ "try { p.intu16(arr_i16) } catch(e) { e instanceof TypeError; }", "true" }, + .{ "try { p.int16(arr_i64) } catch(e) { e instanceof TypeError; }", "true" }, + + .{ "try { p.int32(arr_u32) } catch(e) { e instanceof TypeError; }", "true" }, + .{ "try { p.intu32(arr_i32) } catch(e) { e instanceof TypeError; }", "true" }, + .{ "try { p.intu32(arr_u32) } catch(e) { e instanceof TypeError; }", "true" }, + + .{ "try { p.int64(arr_u64) } catch(e) { e instanceof TypeError; }", "true" }, + .{ "try { p.intu64(arr_i64) } catch(e) { e instanceof TypeError; }", "true" }, + .{ "try { p.intu64(arr_u32) } catch(e) { e instanceof TypeError; }", "true" }, + }, .{}); }