diff --git a/src/browser/js/Context.zig b/src/browser/js/Context.zig index ee3a7ef25..c1fc24bef 100644 --- a/src/browser/js/Context.zig +++ b/src/browser/js/Context.zig @@ -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 + 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 { diff --git a/src/browser/js/js.zig b/src/browser/js/js.zig index 5471f3000..1504e8461 100644 --- a/src/browser/js/js.zig +++ b/src/browser/js/js.zig @@ -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) { @@ -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),