Merge pull request #1213 from lightpanda-io/nikneym/remove-kludge
Some checks failed
e2e-test / zig build release (push) Has been cancelled
e2e-test / demo-scripts (push) Has been cancelled
e2e-test / cdp-and-hyperfine-bench (push) Has been cancelled
e2e-test / perf-fmt (push) Has been cancelled
zig-test / zig build dev (push) Has been cancelled
zig-test / browser fetch (push) Has been cancelled
zig-test / zig test (push) Has been cancelled
zig-test / perf-fmt (push) Has been cancelled

This commit is contained in:
Halil Durak
2025-11-17 10:01:26 +03:00
committed by GitHub
2 changed files with 106 additions and 103 deletions

View File

@@ -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 // Extracted so that it can be used in both jsValueToZig and in
// probeJsValueToZig. Avoids having to duplicate this logic when probing. // 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 { fn jsValueToStruct(self: *Context, comptime named_function: NamedFunction, comptime T: type, js_value: v8.Value) !?T {
if (T == js.Function) { return switch (T) {
if (!js_value.isFunction()) { js.Function => {
return null; if (!js_value.isFunction()) {
} return null;
return try self.createFunction(js_value); }
}
if (@hasDecl(T, "_TYPED_ARRAY_ID_KLUDGE")) { return try self.createFunction(js_value);
const VT = @typeInfo(std.meta.fieldInfo(T, .values).type).pointer.child; },
const arr = (try self.jsValueToTypedArray(VT, js_value)) orelse return null; // zig fmt: off
return .{ .values = arr }; 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),
if (T == js.String) { // zig fmt: on
return .{ .string = try self.valueToString(js_value, .{ .allocator = self.arena }) }; => {
} const ValueType = @typeInfo(std.meta.fieldInfo(T, .values).type).pointer.child;
const slice = (try self.jsValueToTypedArray(ValueType, js_value)) orelse return null;
const js_obj = js_value.castTo(v8.Object); return .{ .values = slice };
},
if (comptime T == js.Object) { js.String => .{ .string = try self.valueToString(js_value, .{ .allocator = self.arena }) },
// Caller wants an opaque js.Object. Probably a parameter // Caller wants an opaque js.Object. Probably a parameter
// that it needs to pass back into a callback // that it needs to pass back into a callback.
return js.Object{ js.Object => js.Object{
.js_obj = js_obj, .js_obj = js_value.castTo(v8.Object),
.context = self, .context = self,
}; },
} else => {
const js_obj = js_value.castTo(v8.Object);
if (!js_value.isObject()) {
return null;
}
if (!js_value.isObject()) { const v8_context = self.v8_context;
return null; const isolate = self.isolate;
} var value: T = undefined;
inline for (@typeInfo(T).@"struct".fields) |field| {
const v8_context = self.v8_context; const name = field.name;
const isolate = self.isolate; const key = v8.String.initUtf8(isolate, name);
if (js_obj.has(v8_context, key.toValue())) {
var value: T = undefined; @field(value, name) = try self.jsValueToZig(named_function, field.type, try js_obj.getValue(v8_context, key));
inline for (@typeInfo(T).@"struct".fields) |field| { } else if (@typeInfo(field.type) == .optional) {
const name = field.name; @field(value, name) = null;
const key = v8.String.initUtf8(isolate, name); } else {
if (js_obj.has(v8_context, key.toValue())) { const dflt = field.defaultValue() orelse return null;
@field(value, name) = try self.jsValueToZig(named_function, field.type, try js_obj.getValue(v8_context, key)); @field(value, name) = dflt;
} else if (@typeInfo(field.type) == .optional) { }
@field(value, name) = null; }
} else { return value;
const dflt = field.defaultValue() orelse return null; },
@field(value, name) = dflt; };
}
}
return value;
} }
fn jsValueToTypedArray(_: *Context, comptime T: type, js_value: v8.Value) !?[]T { fn jsValueToTypedArray(_: *Context, comptime T: type, js_value: v8.Value) !?[]T {

View File

@@ -48,8 +48,6 @@ const NamedFunction = Context.NamedFunction;
// Env.JsObject. Want a TypedArray? Env.TypedArray. // Env.JsObject. Want a TypedArray? Env.TypedArray.
pub fn TypedArray(comptime T: type) type { pub fn TypedArray(comptime T: type) type {
return struct { return struct {
pub const _TYPED_ARRAY_ID_KLUDGE = true;
values: []const T, values: []const T,
pub fn dupe(self: TypedArray(T), allocator: Allocator) !TypedArray(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(); return v8.initNull(isolate).toValue();
}, },
.@"struct" => { .@"struct" => {
const T = @TypeOf(value); switch (@TypeOf(value)) {
ArrayBuffer => {
if (T == ArrayBuffer) { const values = value.values;
const values = value.values; const len = values.len;
const len = values.len; var array_buffer: v8.ArrayBuffer = undefined;
var array_buffer: v8.ArrayBuffer = undefined; const backing_store = v8.BackingStore.init(isolate, len);
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);
const data: [*]u8 = @ptrCast(@alignCast(backing_store.getData())); 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()); array_buffer = v8.ArrayBuffer.initWithBackingStore(isolate, &backing_store.toSharedPtr());
}
switch (@typeInfo(value_type)) { return .{ .handle = array_buffer.handle };
.int => |n| switch (n.signedness) { },
.unsigned => switch (n.bits) { // zig fmt: off
8 => return v8.Uint8Array.init(array_buffer, 0, len).toValue(), TypedArray(u8), TypedArray(u16), TypedArray(u32), TypedArray(u64),
16 => return v8.Uint16Array.init(array_buffer, 0, len).toValue(), TypedArray(i8), TypedArray(i16), TypedArray(i32), TypedArray(i64),
32 => return v8.Uint32Array.init(array_buffer, 0, len).toValue(), TypedArray(f32), TypedArray(f64),
64 => return v8.BigUint64Array.init(array_buffer, 0, len).toValue(), // 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 => {},
},
},
.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 => {},
}, },
.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 => {},
}, }
else => {}, // We normally don't fail in this function unless fail == true
} // but this can never be valid.
// We normally don't fail in this function unless fail == true @compileError("Invalid TypedArray type: " ++ @typeName(value_type));
// but this can never be valid. },
@compileError("Invalid TypeArray type: " ++ @typeName(value_type)); else => {},
} }
}, },
.@"union" => return simpleZigValueToJs(isolate, std.meta.activeTag(value), fail), .@"union" => return simpleZigValueToJs(isolate, std.meta.activeTag(value), fail),