mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-10-28 14:43:28 +00:00
Ability to return typed arrays
This commit is contained in:
@@ -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" },
|
||||
|
||||
@@ -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,
|
||||
@@ -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 => {},
|
||||
}
|
||||
|
||||
@@ -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 .{};
|
||||
@@ -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);
|
||||
@@ -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
|
||||
@@ -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" },
|
||||
}, .{});
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user