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
90 changes: 45 additions & 45 deletions src/browser/js/Context.zig
Original file line number Diff line number Diff line change
Expand Up @@ -780,55 +780,55 @@ pub fn jsValueToZig(self: *Context, comptime named_function: NamedFunction, comp
// Extracted so that it can be used in both jsValueToZig and in
// probeJsValueToZig. Avoids having to duplicate this logic when probing.
fn jsValueToStruct(self: *Context, comptime named_function: NamedFunction, comptime T: type, js_value: v8.Value) !?T {
if (T == js.Function) {
if (!js_value.isFunction()) {
return null;
}
return try self.createFunction(js_value);
}

if (@hasDecl(T, "_TYPED_ARRAY_ID_KLUDGE")) {
const VT = @typeInfo(std.meta.fieldInfo(T, .values).type).pointer.child;
const arr = (try self.jsValueToTypedArray(VT, js_value)) orelse return null;
return .{ .values = arr };
}

if (T == js.String) {
return .{ .string = try self.valueToString(js_value, .{ .allocator = self.arena }) };
}

const js_obj = js_value.castTo(v8.Object);
return switch (T) {
js.Function => {
if (!js_value.isFunction()) {
return null;
}

if (comptime T == js.Object) {
return try self.createFunction(js_value);
},
// zig fmt: off
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TIL

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same 👀

js.TypedArray(u8), js.TypedArray(u16), js.TypedArray(u32), js.TypedArray(u64),
js.TypedArray(i8), js.TypedArray(i16), js.TypedArray(i32), js.TypedArray(i64),
js.TypedArray(f32), js.TypedArray(f64),
// zig fmt: on
=> {
const ValueType = @typeInfo(std.meta.fieldInfo(T, .values).type).pointer.child;
const slice = (try self.jsValueToTypedArray(ValueType, js_value)) orelse return null;
return .{ .values = slice };
},
js.String => .{ .string = try self.valueToString(js_value, .{ .allocator = self.arena }) },
// Caller wants an opaque js.Object. Probably a parameter
// that it needs to pass back into a callback
return js.Object{
.js_obj = js_obj,
// that it needs to pass back into a callback.
js.Object => js.Object{
.js_obj = js_value.castTo(v8.Object),
.context = self,
};
}

if (!js_value.isObject()) {
return null;
}

const v8_context = self.v8_context;
const isolate = self.isolate;
},
else => {
const js_obj = js_value.castTo(v8.Object);
if (!js_value.isObject()) {
return null;
}

var value: T = undefined;
inline for (@typeInfo(T).@"struct".fields) |field| {
const name = field.name;
const key = v8.String.initUtf8(isolate, name);
if (js_obj.has(v8_context, key.toValue())) {
@field(value, name) = try self.jsValueToZig(named_function, field.type, try js_obj.getValue(v8_context, key));
} else if (@typeInfo(field.type) == .optional) {
@field(value, name) = null;
} else {
const dflt = field.defaultValue() orelse return null;
@field(value, name) = dflt;
}
}
return value;
const v8_context = self.v8_context;
const isolate = self.isolate;
var value: T = undefined;
inline for (@typeInfo(T).@"struct".fields) |field| {
const name = field.name;
const key = v8.String.initUtf8(isolate, name);
if (js_obj.has(v8_context, key.toValue())) {
@field(value, name) = try self.jsValueToZig(named_function, field.type, try js_obj.getValue(v8_context, key));
} else if (@typeInfo(field.type) == .optional) {
@field(value, name) = null;
} else {
const dflt = field.defaultValue() orelse return null;
@field(value, name) = dflt;
}
}
return value;
},
};
}

fn jsValueToTypedArray(_: *Context, comptime T: type, js_value: v8.Value) !?[]T {
Expand Down
117 changes: 60 additions & 57 deletions src/browser/js/js.zig
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,6 @@ const NamedFunction = Context.NamedFunction;
// Env.JsObject. Want a TypedArray? Env.TypedArray.
pub fn TypedArray(comptime T: type) type {
return struct {
pub const _TYPED_ARRAY_ID_KLUDGE = true;

values: []const T,

pub fn dupe(self: TypedArray(T), allocator: Allocator) !TypedArray(T) {
Expand Down Expand Up @@ -327,68 +325,73 @@ pub fn simpleZigValueToJs(isolate: v8.Isolate, value: anytype, comptime fail: bo
return v8.initNull(isolate).toValue();
},
.@"struct" => {
const T = @TypeOf(value);

if (T == ArrayBuffer) {
const values = value.values;
const len = values.len;
var array_buffer: v8.ArrayBuffer = undefined;
const backing_store = v8.BackingStore.init(isolate, len);
const data: [*]u8 = @ptrCast(@alignCast(backing_store.getData()));
@memcpy(data[0..len], @as([]const u8, @ptrCast(values))[0..len]);
array_buffer = v8.ArrayBuffer.initWithBackingStore(isolate, &backing_store.toSharedPtr());

return .{ .handle = array_buffer.handle };
}

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)),
};

var array_buffer: v8.ArrayBuffer = undefined;
if (len == 0) {
array_buffer = v8.ArrayBuffer.init(isolate, 0);
} else {
const buffer_len = len * bits / 8;
const backing_store = v8.BackingStore.init(isolate, buffer_len);
switch (@TypeOf(value)) {
ArrayBuffer => {
const values = value.values;
const len = values.len;
var array_buffer: v8.ArrayBuffer = undefined;
const backing_store = v8.BackingStore.init(isolate, len);
const data: [*]u8 = @ptrCast(@alignCast(backing_store.getData()));
@memcpy(data[0..buffer_len], @as([]const u8, @ptrCast(values))[0..buffer_len]);
@memcpy(data[0..len], @as([]const u8, @ptrCast(values))[0..len]);
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 => {},
return .{ .handle = array_buffer.handle };
},
// zig fmt: off
TypedArray(u8), TypedArray(u16), TypedArray(u32), TypedArray(u64),
TypedArray(i8), TypedArray(i16), TypedArray(i32), TypedArray(i64),
TypedArray(f32), TypedArray(f64),
// zig fmt: on
=> {
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 TypedArray type: " ++ @typeName(value_type)),
};

var array_buffer: v8.ArrayBuffer = undefined;
if (len == 0) {
array_buffer = v8.ArrayBuffer.init(isolate, 0);
} else {
const buffer_len = len * bits / 8;
const backing_store = v8.BackingStore.init(isolate, buffer_len);
const data: [*]u8 = @ptrCast(@alignCast(backing_store.getData()));
@memcpy(data[0..buffer_len], @as([]const u8, @ptrCast(values))[0..buffer_len]);
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 => {},
},
},
.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(),
.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 => {},
},
},
.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));
}
// We normally don't fail in this function unless fail == true
// but this can never be valid.
@compileError("Invalid TypedArray type: " ++ @typeName(value_type));
},
else => {},
}
},
.@"union" => return simpleZigValueToJs(isolate, std.meta.activeTag(value), fail),
Expand Down