Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/actions/install/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ inputs:
zig-v8:
description: 'zig v8 version to install'
required: false
default: 'v0.1.20'
default: 'v0.1.21'
v8:
description: 'v8 version to install'
required: false
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -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.20
ARG ZIG_V8=v0.1.21

RUN apt-get update -yq && \
apt-get install -yq xz-utils \
Expand Down
4 changes: 2 additions & 2 deletions build.zig.zon
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
.hash = "tigerbeetle_io-0.0.0-ViLgxpyRBAB5BMfIcj3KMXfbJzwARs9uSl8aRy2OXULd",
},
.v8 = .{
.url = "https://github.com/lightpanda-io/zig-v8-fork/archive/f0c7eaaffe39f2f1a224fbe97e550daca0ca1801.tar.gz",
.hash = "v8-0.0.0-xddH62T4IADchAHFgo4nx79w1VedNDhIVErtSNgup-Tk",
.url = "https://github.com/lightpanda-io/zig-v8-fork/archive/fc764e7d29bc1514924e8df09255a057e03d453a.tar.gz",
.hash = "v8-0.0.0-xddH6zUZIQBJf109L94sC-mWH1NJXWCnOJGJttKtfasI",
},
//.v8 = .{ .path = "../zig-v8-fork" },
//.tigerbeetle_io = .{ .path = "../tigerbeetle-io" },
Expand Down
63 changes: 63 additions & 0 deletions src/runtime/js.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1012,6 +1012,22 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
}
};

// If a function returns a []i32, should that map to a plain-old
// JavaScript array, or a Int32Array? It's ambiguous. By default, we'll
// map arrays/slices to the JavaScript arrays. If you want a TypedArray
// wrap it in this.
// Also, this type has nothing to do with the Env. But we place it here
// for consistency. Want a callback? Env.Callback. Want a JsObject?
// Env.JsObject. Want a TypedArray? Env.TypedArray.
pub fn TypedArray(comptime T: type) type {
return struct {
// See Callback._CALLBACK_ID_KLUDGE
const _TYPED_ARRAY_ID_KLUDGE = true;

values: []const T,
};
}

pub const Inspector = struct {
isolate: v8.Isolate,
inner: *v8.Inspector,
Expand Down Expand Up @@ -2632,6 +2648,53 @@ fn simpleZigValueToJs(isolate: v8.Isolate, value: anytype, comptime fail: bool)
}
return v8.initNull(isolate).toValue();
},
.@"struct" => {
const T = @TypeOf(value);
if (@hasDecl(T, "_TYPED_ARRAY_ID_KLUDGE")) {
const values = value.values;
const value_type = @typeInfo(@TypeOf(values)).pointer.child;
const len = values.len;
const bits = switch (@typeInfo(value_type)) {
.int => |n| n.bits,
.float => |f| f.bits,
else => @compileError("Invalid TypeArray type: " ++ @typeName(value_type)),
};

const buffer_len = len * bits / 8;
const backing_store = v8.BackingStore.init(isolate, buffer_len);
const data: [*]u8 = @alignCast(@ptrCast(backing_store.getData()));
@memcpy(data[0..buffer_len], @as([]const u8, @ptrCast(values))[0..buffer_len]);
const array_buffer = v8.ArrayBuffer.initWithBackingStore(isolate, &backing_store.toSharedPtr());

switch (@typeInfo(value_type)) {
.int => |n| switch (n.signedness) {
.unsigned => switch (n.bits) {
8 => return v8.Uint8Array.init(array_buffer, 0, len).toValue(),
16 => return v8.Uint16Array.init(array_buffer, 0, len).toValue(),
32 => return v8.Uint32Array.init(array_buffer, 0, len).toValue(),
64 => return v8.BigUint64Array.init(array_buffer, 0, len).toValue(),
else => {},
},
.signed => switch (n.bits) {
8 => return v8.Int8Array.init(array_buffer, 0, len).toValue(),
16 => return v8.Int16Array.init(array_buffer, 0, len).toValue(),
32 => return v8.Int32Array.init(array_buffer, 0, len).toValue(),
64 => return v8.BigInt64Array.init(array_buffer, 0, len).toValue(),
else => {},
},
},
.float => |f| switch (f.bits) {
32 => return v8.Float32Array.init(array_buffer, 0, len).toValue(),
64 => return v8.Float64Array.init(array_buffer, 0, len).toValue(),
else => {},
},
else => {},
}
// We normally don't fail in this function unless fail == true
// but this can never be valid.
@compileError("Invalid TypeArray type: " ++ @typeName(value_type));
}
},
.@"union" => return simpleZigValueToJs(isolate, std.meta.activeTag(value), fail),
else => {},
}
Expand Down
57 changes: 56 additions & 1 deletion src/runtime/test_primitive_types.zig
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.

// TODO: use functions instead of "fake" struct once we handle function API generation

const Runner = testing.Runner(void, void, .{Primitives});
const Env = Runner.Env;

const Primitives = struct {
pub fn constructor() Primitives {
return .{};
Expand Down Expand Up @@ -114,6 +118,46 @@ const Primitives = struct {
}
}

pub fn _returnUint8(_: *const Primitives) Env.TypedArray(u8) {
return .{ .values = &.{ 10, 20, 250 } };
}

pub fn _returnInt8(_: *const Primitives) Env.TypedArray(i8) {
return .{ .values = &.{ 10, -20, -120 } };
}

pub fn _returnUint16(_: *const Primitives) Env.TypedArray(u16) {
return .{ .values = &.{ 10, 200, 2050 } };
}

pub fn _returnInt16(_: *const Primitives) Env.TypedArray(i16) {
return .{ .values = &.{ 10, -420, 0 } };
}

pub fn _returnUint32(_: *const Primitives) Env.TypedArray(u32) {
return .{ .values = &.{ 10, 2444343, 43432432 } };
}

pub fn _returnInt32(_: *const Primitives) Env.TypedArray(i32) {
return .{ .values = &.{ 10, -20, -495929123 } };
}

pub fn _returnUint64(_: *const Primitives) Env.TypedArray(u64) {
return .{ .values = &.{ 10, 495812375924, 0 } };
}

pub fn _returnInt64(_: *const Primitives) Env.TypedArray(i64) {
return .{ .values = &.{ 10, -49283838122, -2 } };
}

pub fn _returnFloat32(_: *const Primitives) Env.TypedArray(f32) {
return .{ .values = &.{ 1.1, -200.035, 0.0003 } };
}

pub fn _returnFloat64(_: *const Primitives) Env.TypedArray(f64) {
return .{ .values = &.{ 8881.22284, -4928.3838122, -0.00004 } };
}

pub fn _int16(_: *const Primitives, arr: []i16) void {
for (arr) |*a| {
a.* -= @intCast(arr.len);
Expand Down Expand Up @@ -153,7 +197,7 @@ const Primitives = struct {

const testing = @import("testing.zig");
test "JS: primitive types" {
var runner = try testing.Runner(void, void, .{Primitives}).init({}, {});
var runner = try Runner.init({}, {});
defer runner.deinit();

// constructor
Expand Down Expand Up @@ -280,5 +324,16 @@ test "JS: primitive types" {
.{ "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" },

.{ "p.returnUint8()", "10,20,250" },
.{ "p.returnInt8()", "10,-20,-120" },
.{ "p.returnUint16()", "10,200,2050" },
.{ "p.returnInt16()", "10,-420,0" },
.{ "p.returnUint32()", "10,2444343,43432432" },
.{ "p.returnInt32()", "10,-20,-495929123" },
.{ "p.returnUint64()", "10,495812375924,0" },
.{ "p.returnInt64()", "10,-49283838122,-2" },
.{ "p.returnFloat32()", "1.100000023841858,-200.03500366210938,0.0003000000142492354" },
.{ "p.returnFloat64()", "8881.22284,-4928.3838122,-0.00004" },
}, .{});
}
7 changes: 4 additions & 3 deletions src/runtime/testing.zig
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,16 @@ pub const allocator = std.testing.allocator;
// browser.Env or the browser.SessionState
pub fn Runner(comptime State: type, comptime Global: type, comptime types: anytype) type {
const AdjustedTypes = if (Global == void) generate.Tuple(.{ types, DefaultGlobal }) else types;
const Env = js.Env(State, struct {
pub const Interfaces = AdjustedTypes;
});

return struct {
env: *Env,
scope: *Env.Scope,
executor: Env.Executor,

pub const Env = js.Env(State, struct {
pub const Interfaces = AdjustedTypes;
});

const Self = @This();

pub fn init(state: State, global: Global) !*Self {
Expand Down