Skip to content

Commit a3323dc

Browse files
committed
add support for mapping integer typed arrays into zig slices
1 parent ba0505c commit a3323dc

File tree

5 files changed

+169
-18
lines changed

5 files changed

+169
-18
lines changed

.github/actions/install/action.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ inputs:
1717
zig-v8:
1818
description: 'zig v8 version to install'
1919
required: false
20-
default: 'v0.1.18'
20+
default: 'v0.1.19'
2121
v8:
2222
description: 'v8 version to install'
2323
required: false

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ ARG ZIG=0.14.0
55
ARG ZIG_MINISIG=RWSGOq2NVecA2UPNdBUZykf1CCb147pkmdtYxgb3Ti+JO/wCYvhbAb/U
66
ARG ARCH=x86_64
77
ARG V8=11.1.134
8-
ARG ZIG_V8=v0.1.18
8+
ARG ZIG_V8=v0.1.19
99

1010
RUN apt-get update -yq && \
1111
apt-get install -yq xz-utils \

build.zig.zon

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
.hash = "tigerbeetle_io-0.0.0-ViLgxpyRBAB5BMfIcj3KMXfbJzwARs9uSl8aRy2OXULd",
1414
},
1515
.v8 = .{
16-
.url = "https://github.com/lightpanda-io/zig-v8-fork/archive/97bcfb61da8c97de1321d677a6727a927a9db9a4.tar.gz",
17-
.hash = "v8-0.0.0-xddH69DoIADZ8YXZ_EIx_tKdQKEoGsgob_3_ZIi0O_nV",
16+
.url = "https://github.com/lightpanda-io/zig-v8-fork/archive/5d46f159ca44535cfb4fccd9d46f719eb7eac5fc.tar.gz",
17+
.hash = "v8-0.0.0-xddH66zuIADu8FcQx2kkczC0yhqBY7LoA08-GRWF_zMA",
1818
},
1919
//.v8 = .{ .path = "../zig-v8-fork" },
2020
//.tigerbeetle_io = .{ .path = "../tigerbeetle-io" },

src/runtime/js.zig

Lines changed: 66 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1932,7 +1932,7 @@ fn Caller(comptime E: type) type {
19321932
if (last_parameter_type_info == .pointer and last_parameter_type_info.pointer.size == .slice) {
19331933
const slice_type = last_parameter_type_info.pointer.child;
19341934
const corresponding_js_value = info.getArg(@as(u32, @intCast(last_js_parameter)));
1935-
if (corresponding_js_value.isArray() == false and slice_type != u8) {
1935+
if (corresponding_js_value.isArray() == false and corresponding_js_value.isTypedArray() == false and slice_type != u8) {
19361936
is_variadic = true;
19371937
if (js_parameter_count == 0) {
19381938
@field(args, tupleFieldName(params_to_map.len + offset - 1)) = &.{};
@@ -2005,6 +2005,70 @@ fn Caller(comptime E: type) type {
20052005
}
20062006
},
20072007
.slice => {
2008+
if (js_value.isTypedArray()) {
2009+
const buffer_view = js_value.castTo(v8.ArrayBufferView);
2010+
const buffer = buffer_view.getBuffer();
2011+
const backing_store = v8.BackingStore.sharedPtrGet(&buffer.getBackingStore());
2012+
const data = backing_store.getData();
2013+
const byte_len = backing_store.getByteLength();
2014+
2015+
switch (ptr.child) {
2016+
u8 => {
2017+
// need this sentinel check to keep the compiler happy
2018+
if (ptr.sentinel() == null) {
2019+
if (js_value.isUint8Array() or js_value.isUint8ClampedArray()) {
2020+
const arr_ptr = @as([*]u8, @alignCast(@ptrCast(data)));
2021+
return arr_ptr[0..byte_len];
2022+
}
2023+
}
2024+
},
2025+
i8 => {
2026+
if (js_value.isInt8Array()) {
2027+
const arr_ptr = @as([*]i8, @alignCast(@ptrCast(data)));
2028+
return arr_ptr[0..byte_len];
2029+
}
2030+
},
2031+
u16 => {
2032+
if (js_value.isUint16Array()) {
2033+
const arr_ptr = @as([*]u16, @alignCast(@ptrCast(data)));
2034+
return arr_ptr[0 .. byte_len / 2];
2035+
}
2036+
},
2037+
i16 => {
2038+
if (js_value.isInt16Array()) {
2039+
const arr_ptr = @as([*]i16, @alignCast(@ptrCast(data)));
2040+
return arr_ptr[0 .. byte_len / 2];
2041+
}
2042+
},
2043+
u32 => {
2044+
if (js_value.isUint32Array()) {
2045+
const arr_ptr = @as([*]u32, @alignCast(@ptrCast(data)));
2046+
return arr_ptr[0 .. byte_len / 4];
2047+
}
2048+
},
2049+
i32 => {
2050+
if (js_value.isInt32Array()) {
2051+
const arr_ptr = @as([*]i32, @alignCast(@ptrCast(data)));
2052+
return arr_ptr[0 .. byte_len / 4];
2053+
}
2054+
},
2055+
u64 => {
2056+
if (js_value.isBigUint64Array()) {
2057+
const arr_ptr = @as([*]u64, @alignCast(@ptrCast(data)));
2058+
return arr_ptr[0 .. byte_len / 8];
2059+
}
2060+
},
2061+
i64 => {
2062+
if (js_value.isBigInt64Array()) {
2063+
const arr_ptr = @as([*]i64, @alignCast(@ptrCast(data)));
2064+
return arr_ptr[0 .. byte_len / 8];
2065+
}
2066+
},
2067+
else => {},
2068+
}
2069+
return error.InvalidArgument;
2070+
}
2071+
20082072
if (ptr.child == u8) {
20092073
if (ptr.sentinel()) |s| {
20102074
if (comptime s == 0) {
@@ -2015,18 +2079,6 @@ fn Caller(comptime E: type) type {
20152079
}
20162080
}
20172081

2018-
// TODO: TypedArray
2019-
// if (js_value.isArrayBufferView()) {
2020-
// const abv = js_value.castTo(v8.ArrayBufferView);
2021-
// const ab = abv.getBuffer();
2022-
// const bs = v8.BackingStore.sharedPtrGet(&ab.getBackingStore());
2023-
// const data = bs.getData();
2024-
// var arr = @as([*]i32, @alignCast(@ptrCast(data)))[0..2];
2025-
// std.debug.print("{d} {d} {d}\n", .{arr[0], arr[1], bs.getByteLength()});
2026-
// arr[1] = 3333;
2027-
// return &.{};
2028-
// }
2029-
20302082
if (!js_value.isArray()) {
20312083
return error.InvalidArgument;
20322084
}
@@ -2101,7 +2153,7 @@ fn Caller(comptime E: type) type {
21012153
else => {},
21022154
}
21032155

2104-
@compileError(std.fmt.comptimePrint("{s} has an unsupported parameter type: {s}", .{ named_function.full_name, @typeName(T) }));
2156+
@compileError(named_function.full_name ++ " has an unsupported parameter type: " ++ @typeName(T));
21052157
}
21062158

21072159
fn jsIntToZig(comptime T: type, js_value: v8.Value, context: v8.Context) !T {

src/runtime/test_primitive_types.zig

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,54 @@ const Primitives = struct {
104104
pub fn _echoStringZ(_: *const Primitives, a: [:0]const u8) []const u8 {
105105
return a;
106106
}
107+
108+
pub fn _int8(_: *const Primitives, arr: []i8) void {
109+
for (arr) |*a| {
110+
a.* -= @intCast(arr.len);
111+
}
112+
}
113+
114+
pub fn _uint8(_: *const Primitives, arr: []u8) void {
115+
for (arr) |*a| {
116+
a.* += @intCast(arr.len);
117+
}
118+
}
119+
120+
pub fn _int16(_: *const Primitives, arr: []i16) void {
121+
for (arr) |*a| {
122+
a.* -= @intCast(arr.len);
123+
}
124+
}
125+
126+
pub fn _uint16(_: *const Primitives, arr: []u16) void {
127+
for (arr) |*a| {
128+
a.* += @intCast(arr.len);
129+
}
130+
}
131+
132+
pub fn _int32(_: *const Primitives, arr: []i32) void {
133+
for (arr) |*a| {
134+
a.* -= @intCast(arr.len);
135+
}
136+
}
137+
138+
pub fn _uint32(_: *const Primitives, arr: []u32) void {
139+
for (arr) |*a| {
140+
a.* += @intCast(arr.len);
141+
}
142+
}
143+
144+
pub fn _int64(_: *const Primitives, arr: []i64) void {
145+
for (arr) |*a| {
146+
a.* -= @intCast(arr.len);
147+
}
148+
}
149+
150+
pub fn _uint64(_: *const Primitives, arr: []u64) void {
151+
for (arr) |*a| {
152+
a.* += @intCast(arr.len);
153+
}
154+
}
107155
};
108156

109157
const testing = @import("testing.zig");
@@ -185,4 +233,55 @@ test "JS: primitive types" {
185233
.{ "p.echoString('over 9000!');", "over 9000!" },
186234
.{ "p.echoStringZ('Teg');", "Teg" },
187235
}, .{});
236+
237+
// typed arrays
238+
try runner.testCases(&.{
239+
.{ "let arr_i8 = new Int8Array([-10, -20, -30]);", "undefined" },
240+
.{ "p.int8(arr_i8)", "undefined" },
241+
.{ "arr_i8;", "-13,-23,-33" },
242+
243+
.{ "let arr_u8 = new Uint8Array([10, 20, 30]);", "undefined" },
244+
.{ "p.uint8(arr_u8)", "undefined" },
245+
.{ "arr_u8;", "13,23,33" },
246+
247+
.{ "let arr_i16 = new Int16Array([-1000, -2000, -3000]);", "undefined" },
248+
.{ "p.int16(arr_i16)", "undefined" },
249+
.{ "arr_i16;", "-1003,-2003,-3003" },
250+
251+
.{ "let arr_u16 = new Uint16Array([1000, 2000, 3000]);", "undefined" },
252+
.{ "p.uint16(arr_u16)", "undefined" },
253+
.{ "arr_u16;", "1003,2003,3003" },
254+
255+
.{ "let arr_i32 = new Int32Array([-1000000, -2000000, -3000000]);", "undefined" },
256+
.{ "p.int32(arr_i32)", "undefined" },
257+
.{ "arr_i32;", "-1000003,-2000003,-3000003" },
258+
259+
.{ "let arr_u32 = new Uint32Array([1000000, 2000000, 3000000]);", "undefined" },
260+
.{ "p.uint32(arr_u32)", "undefined" },
261+
.{ "arr_u32;", "1000003,2000003,3000003" },
262+
263+
.{ "let arr_i64 = new BigInt64Array([-1000000000n, -2000000000n, -3000000000n]);", "undefined" },
264+
.{ "p.int64(arr_i64)", "undefined" },
265+
.{ "arr_i64;", "-1000000003,-2000000003,-3000000003" },
266+
267+
.{ "let arr_u64 = new BigUint64Array([1000000000n, 2000000000n, 3000000000n]);", "undefined" },
268+
.{ "p.uint64(arr_u64)", "undefined" },
269+
.{ "arr_u64;", "1000000003,2000000003,3000000003" },
270+
271+
.{ "try { p.int8(arr_u8) } catch(e) { e instanceof TypeError; }", "true" },
272+
.{ "try { p.intu8(arr_i8) } catch(e) { e instanceof TypeError; }", "true" },
273+
.{ "try { p.intu8(arr_u32) } catch(e) { e instanceof TypeError; }", "true" },
274+
275+
.{ "try { p.int16(arr_u8) } catch(e) { e instanceof TypeError; }", "true" },
276+
.{ "try { p.intu16(arr_i16) } catch(e) { e instanceof TypeError; }", "true" },
277+
.{ "try { p.int16(arr_i64) } catch(e) { e instanceof TypeError; }", "true" },
278+
279+
.{ "try { p.int32(arr_u32) } catch(e) { e instanceof TypeError; }", "true" },
280+
.{ "try { p.intu32(arr_i32) } catch(e) { e instanceof TypeError; }", "true" },
281+
.{ "try { p.intu32(arr_u32) } catch(e) { e instanceof TypeError; }", "true" },
282+
283+
.{ "try { p.int64(arr_u64) } catch(e) { e instanceof TypeError; }", "true" },
284+
.{ "try { p.intu64(arr_i64) } catch(e) { e instanceof TypeError; }", "true" },
285+
.{ "try { p.intu64(arr_u32) } catch(e) { e instanceof TypeError; }", "true" },
286+
}, .{});
188287
}

0 commit comments

Comments
 (0)