mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-12-16 08:18:59 +00:00
JS API table changes for zigdom
Applies the `rework-types` changes to zigdom branch.
This commit is contained in:
@@ -457,8 +457,7 @@ pub fn zigValueToJs(self: *Context, value: anytype, comptime opts: Caller.CallOp
|
|||||||
.pointer => |ptr| switch (ptr.size) {
|
.pointer => |ptr| switch (ptr.size) {
|
||||||
.one => {
|
.one => {
|
||||||
if (@typeInfo(ptr.child) == .@"struct" and @hasDecl(ptr.child, "JsApi")) {
|
if (@typeInfo(ptr.child) == .@"struct" and @hasDecl(ptr.child, "JsApi")) {
|
||||||
const type_name = @typeName(ptr.child.JsApi);
|
if (bridge.JsApiLookup.has(ptr.child.JsApi)) {
|
||||||
if (@hasField(bridge.JsApiLookup, type_name)) {
|
|
||||||
const js_obj = try self.mapZigInstanceToJs(null, value);
|
const js_obj = try self.mapZigInstanceToJs(null, value);
|
||||||
return js_obj.toValue();
|
return js_obj.toValue();
|
||||||
}
|
}
|
||||||
@@ -499,8 +498,7 @@ pub fn zigValueToJs(self: *Context, value: anytype, comptime opts: Caller.CallOp
|
|||||||
},
|
},
|
||||||
.@"struct" => |s| {
|
.@"struct" => |s| {
|
||||||
if (@hasDecl(T, "JsApi")) {
|
if (@hasDecl(T, "JsApi")) {
|
||||||
const type_name = @typeName(T.JsApi);
|
if (bridge.JsApiLookup.has(T.JsApi)) {
|
||||||
if (@hasField(bridge.JsApiLookup, type_name)) {
|
|
||||||
const js_obj = try self.mapZigInstanceToJs(null, value);
|
const js_obj = try self.mapZigInstanceToJs(null, value);
|
||||||
return js_obj.toValue();
|
return js_obj.toValue();
|
||||||
}
|
}
|
||||||
@@ -707,7 +705,7 @@ pub fn jsValueToZig(self: *Context, comptime T: type, js_value: v8.Value) !T {
|
|||||||
return error.InvalidArgument;
|
return error.InvalidArgument;
|
||||||
}
|
}
|
||||||
if (@hasDecl(ptr.child, "JsApi")) {
|
if (@hasDecl(ptr.child, "JsApi")) {
|
||||||
std.debug.assert(@hasField(bridge.JsApiLookup, @typeName(ptr.child.JsApi)));
|
//std.debug.assert(bridge.JsApiLookup.has(ptr.child.JsApi));
|
||||||
const js_obj = js_value.castTo(v8.Object);
|
const js_obj = js_value.castTo(v8.Object);
|
||||||
return typeTaggedAnyOpaque(*ptr.child, js_obj);
|
return typeTaggedAnyOpaque(*ptr.child, js_obj);
|
||||||
}
|
}
|
||||||
@@ -1537,14 +1535,13 @@ pub fn typeTaggedAnyOpaque(comptime R: type, js_obj: v8.Object) !R {
|
|||||||
return error.InvalidArgument;
|
return error.InvalidArgument;
|
||||||
}
|
}
|
||||||
|
|
||||||
const type_name = @typeName(JsApi);
|
if (!bridge.JsApiLookup.has(JsApi)) {
|
||||||
if (@hasField(bridge.JsApiLookup, type_name) == false) {
|
|
||||||
@compileError("unknown Zig type: " ++ @typeName(R));
|
@compileError("unknown Zig type: " ++ @typeName(R));
|
||||||
}
|
}
|
||||||
|
|
||||||
const op = js_obj.getInternalField(0).castTo(v8.External).get();
|
const op = js_obj.getInternalField(0).castTo(v8.External).get();
|
||||||
const tao: *TaggedAnyOpaque = @ptrCast(@alignCast(op));
|
const tao: *TaggedAnyOpaque = @ptrCast(@alignCast(op));
|
||||||
const expected_type_index = @field(bridge.JS_API_LOOKUP, type_name);
|
const expected_type_index = bridge.JsApiLookup.getId(JsApi);
|
||||||
|
|
||||||
const prototype_chain = tao.prototype_chain[0..tao.prototype_len];
|
const prototype_chain = tao.prototype_chain[0..tao.prototype_len];
|
||||||
if (prototype_chain[0].index == expected_type_index) {
|
if (prototype_chain[0].index == expected_type_index) {
|
||||||
@@ -1643,7 +1640,7 @@ fn probeJsValueToZig(self: *Context, comptime T: type, js_value: v8.Value) !Prob
|
|||||||
if (!js_value.isObject()) {
|
if (!js_value.isObject()) {
|
||||||
return .{ .invalid = {} };
|
return .{ .invalid = {} };
|
||||||
}
|
}
|
||||||
if (@hasField(bridge.JsApiLookup, @typeName(ptr.child.JsApi))) {
|
if (bridge.JsApiLookup.has(ptr.child.JsApi)) {
|
||||||
const js_obj = js_value.castTo(v8.Object);
|
const js_obj = js_value.castTo(v8.Object);
|
||||||
// There's a bit of overhead in doing this, so instead
|
// There's a bit of overhead in doing this, so instead
|
||||||
// of having a version of typeTaggedAnyOpaque which
|
// of having a version of typeTaggedAnyOpaque which
|
||||||
|
|||||||
@@ -335,7 +335,7 @@ fn generateConstructor(comptime JsApi: type, isolate: v8.Isolate) v8.FunctionTem
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
pub fn protoIndexLookup(comptime JsApi: type) ?u16 {
|
pub fn protoIndexLookup(comptime JsApi: type) ?bridge.JsApiLookup.BackingInt {
|
||||||
@setEvalBranchQuota(2000);
|
@setEvalBranchQuota(2000);
|
||||||
comptime {
|
comptime {
|
||||||
const T = JsApi.bridge.type;
|
const T = JsApi.bridge.type;
|
||||||
@@ -344,6 +344,6 @@ pub fn protoIndexLookup(comptime JsApi: type) ?u16 {
|
|||||||
}
|
}
|
||||||
const Ptr = std.meta.fieldInfo(T, ._proto).type;
|
const Ptr = std.meta.fieldInfo(T, ._proto).type;
|
||||||
const F = @typeInfo(Ptr).pointer.child;
|
const F = @typeInfo(Ptr).pointer.child;
|
||||||
return @field(bridge.JS_API_LOOKUP, @typeName(F.JsApi));
|
return bridge.JsApiLookup.getId(F.JsApi);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ pub fn createContext(self: *ExecutionWorld, page: *Page, enter: bool, global_cal
|
|||||||
// specific instance of the the Window.
|
// specific instance of the the Window.
|
||||||
{
|
{
|
||||||
const proto_type = @typeInfo(@TypeOf(page.window._proto)).pointer.child;
|
const proto_type = @typeInfo(@TypeOf(page.window._proto)).pointer.child;
|
||||||
const proto_index = @field(bridge.JS_API_LOOKUP, @typeName(proto_type.JsApi));
|
const proto_index = bridge.JsApiLookup.getId(proto_type.JsApi);
|
||||||
js_global.inherit(templates[proto_index]);
|
js_global.inherit(templates[proto_index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -64,20 +64,17 @@ pub fn Builder(comptime T: type) type {
|
|||||||
pub fn prototypeChain() [prototypeChainLength(T)]js.PrototypeChainEntry {
|
pub fn prototypeChain() [prototypeChainLength(T)]js.PrototypeChainEntry {
|
||||||
var entries: [prototypeChainLength(T)]js.PrototypeChainEntry = undefined;
|
var entries: [prototypeChainLength(T)]js.PrototypeChainEntry = undefined;
|
||||||
|
|
||||||
entries[0] = .{
|
entries[0] = .{ .offset = 0, .index = JsApiLookup.getId(T.JsApi) };
|
||||||
.offset = 0,
|
|
||||||
.index = @field(JS_API_LOOKUP, @typeName(T.JsApi)),
|
|
||||||
};
|
|
||||||
|
|
||||||
if (entries.len == 1) {
|
if (entries.len == 1) {
|
||||||
return entries;
|
return entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
var Prototype = T;
|
var Prototype = T;
|
||||||
for (entries[1..]) |*entry| {
|
inline for (entries[1..]) |*entry| {
|
||||||
const Next = PrototypeType(Prototype).?;
|
const Next = PrototypeType(Prototype).?;
|
||||||
entry.* = .{
|
entry.* = .{
|
||||||
.index = @field(JS_API_LOOKUP, @typeName(Next.JsApi)),
|
.index = JsApiLookup.getId(Next.JsApi),
|
||||||
.offset = @offsetOf(Prototype, "_proto"),
|
.offset = @offsetOf(Prototype, "_proto"),
|
||||||
};
|
};
|
||||||
Prototype = Next;
|
Prototype = Next;
|
||||||
@@ -394,55 +391,72 @@ pub fn Struct(comptime T: type) type {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Imagine we have a type Cat which has a getter:
|
pub const JsApiLookup = struct {
|
||||||
//
|
/// Integer type we use for `JsApiLookup` enum. Can be u8 at min.
|
||||||
// fn getOwner(self: *Cat) *Owner {
|
pub const BackingInt = std.math.IntFittingRange(0, @max(std.math.maxInt(u8), JsApis.len));
|
||||||
// return self.owner;
|
|
||||||
// }
|
/// Imagine we have a type `Cat` which has a getter:
|
||||||
//
|
///
|
||||||
// When we execute caller.getter, we'll end up doing something like:
|
/// fn get_owner(self: *Cat) *Owner {
|
||||||
// const res = @call(.auto, Cat.getOwner, .{cat_instance});
|
/// return self.owner;
|
||||||
//
|
/// }
|
||||||
// How do we turn `res`, which is an *Owner, into something we can return
|
///
|
||||||
// to v8? We need the ObjectTemplate associated with Owner. How do we
|
/// When we execute `caller.getter`, we'll end up doing something like:
|
||||||
// get that? Well, we store all the ObjectTemplates in an array that's
|
///
|
||||||
// tied to env. So we do something like:
|
/// const res = @call(.auto, Cat.get_owner, .{cat_instance});
|
||||||
//
|
///
|
||||||
// env.templates[index_of_owner].initInstance(...);
|
/// How do we turn `res`, which is an *Owner, into something we can return
|
||||||
//
|
/// to v8? We need the ObjectTemplate associated with Owner. How do we
|
||||||
// But how do we get that `index_of_owner`? `Lookup` is a struct
|
/// get that? Well, we store all the ObjectTemplates in an array that's
|
||||||
// that looks like:
|
/// tied to env. So we do something like:
|
||||||
//
|
///
|
||||||
// const Lookup = struct {
|
/// env.templates[index_of_owner].initInstance(...);
|
||||||
// comptime cat: usize = 0,
|
///
|
||||||
// comptime owner: usize = 1,
|
/// But how do we get that `index_of_owner`? `Index` is an enum
|
||||||
// ...
|
/// that looks like:
|
||||||
// }
|
///
|
||||||
//
|
/// pub const Enum = enum(BackingInt) {
|
||||||
// So to get the template index of `owner`, we can do:
|
/// cat = 0,
|
||||||
//
|
/// owner = 1,
|
||||||
// const index_id = @field(type_lookup, @typeName(@TypeOf(res));
|
/// ...
|
||||||
//
|
/// }
|
||||||
pub const JsApiLookup = blk: {
|
///
|
||||||
var fields: [JsApis.len]std.builtin.Type.StructField = undefined;
|
/// (`BackingInt` is calculated at comptime regarding to interfaces we have)
|
||||||
|
/// So to get the template index of `owner`, simply do:
|
||||||
|
///
|
||||||
|
/// const index_id = types.getId(@TypeOf(res));
|
||||||
|
///
|
||||||
|
pub const Enum = blk: {
|
||||||
|
var fields: [JsApis.len]std.builtin.Type.EnumField = undefined;
|
||||||
for (JsApis, 0..) |JsApi, i| {
|
for (JsApis, 0..) |JsApi, i| {
|
||||||
fields[i] = .{
|
fields[i] = .{ .name = @typeName(JsApi), .value = i };
|
||||||
.name = @typeName(JsApi),
|
|
||||||
.type = u16,
|
|
||||||
.is_comptime = true,
|
|
||||||
.alignment = @alignOf(u16),
|
|
||||||
.default_value_ptr = @ptrCast(&i),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
break :blk @Type(.{ .@"struct" = .{
|
|
||||||
.layout = .auto,
|
break :blk @Type(.{
|
||||||
.decls = &.{},
|
.@"enum" = .{
|
||||||
.is_tuple = false,
|
|
||||||
.fields = &fields,
|
.fields = &fields,
|
||||||
} });
|
.tag_type = BackingInt,
|
||||||
|
.is_exhaustive = true,
|
||||||
|
.decls = &.{},
|
||||||
|
},
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const JS_API_LOOKUP = JsApiLookup{};
|
/// Returns a boolean indicating if a type exist in the lookup.
|
||||||
|
pub inline fn has(t: type) bool {
|
||||||
|
return @hasField(Enum, @typeName(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the `Enum` for the given type.
|
||||||
|
pub inline fn getIndex(t: type) Enum {
|
||||||
|
return @field(Enum, @typeName(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the ID for the given type.
|
||||||
|
pub inline fn getId(t: type) BackingInt {
|
||||||
|
return @intFromEnum(getIndex(t));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
pub const SubType = enum {
|
pub const SubType = enum {
|
||||||
@"error",
|
@"error",
|
||||||
|
|||||||
@@ -478,7 +478,7 @@ pub const TaggedAnyOpaque = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub const PrototypeChainEntry = struct {
|
pub const PrototypeChainEntry = struct {
|
||||||
index: u16,
|
index: bridge.JsApiLookup.BackingInt,
|
||||||
offset: u16, // offset to the _proto field
|
offset: u16, // offset to the _proto field
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user