Skip to content

Commit 646fcaf

Browse files
Merge pull request #541 from lightpanda-io/subtype_fix
Change TypeLookup values from simple index (usize) to a TypeMeta
2 parents 1c08b3e + 615453a commit 646fcaf

File tree

3 files changed

+66
-20
lines changed

3 files changed

+66
-20
lines changed

src/browser/html/document.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ pub const HTMLDocument = struct {
3636
pub const Self = parser.DocumentHTML;
3737
pub const prototype = *Document;
3838

39-
pub const sub_type = "node";
39+
pub const subtype = "node";
4040

4141
// JS funcs
4242
// --------

src/runtime/js.zig

Lines changed: 45 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ const std = @import("std");
2020
const builtin = @import("builtin");
2121
const v8 = @import("v8");
2222

23+
const SubType = @import("subtype.zig").SubType;
24+
2325
const Allocator = std.mem.Allocator;
2426
const ArenaAllocator = std.heap.ArenaAllocator;
2527

@@ -72,14 +74,14 @@ pub fn Env(comptime S: type, comptime types: anytype) type {
7274
// that looks like:
7375
//
7476
// const TypeLookup = struct {
75-
// comptime cat: usize = 0,
76-
// comptime owner: usize = 1,
77+
// comptime cat: usize = TypeMeta{.index = 0, ...},
78+
// comptime owner: usize = TypeMeta{.index = 1, ...},
7779
// ...
7880
// }
7981
//
8082
// So to get the template index of `owner`, we can do:
8183
//
82-
// const index_id = @field(type_lookup, @typeName(@TypeOf(res));
84+
// const index_id = @field(type_lookup, @typeName(@TypeOf(res)).index;
8385
//
8486
const TypeLookup = comptime blk: {
8587
var fields: [Types.len]std.builtin.Type.StructField = undefined;
@@ -94,13 +96,16 @@ pub fn Env(comptime S: type, comptime types: anytype) type {
9496
@compileError(std.fmt.comptimePrint("Prototype '{s}' for type '{s} must be a pointer", .{ @typeName(Struct.prototype), @typeName(Struct) }));
9597
}
9698

99+
const subtype: ?SubType =
100+
if (@hasDecl(Struct, "subtype")) std.meta.stringToEnum(SubType, Struct.subtype) else null;
101+
97102
const R = Receiver(@field(types, s.name));
98103
fields[i] = .{
99104
.name = @typeName(R),
100-
.type = usize,
105+
.type = TypeMeta,
101106
.is_comptime = true,
102107
.alignment = @alignOf(usize),
103-
.default_value_ptr = @ptrCast(&i),
108+
.default_value_ptr = &TypeMeta{ .index = i, .subtype = subtype },
104109
};
105110
}
106111
break :blk @Type(.{ .@"struct" = .{
@@ -135,7 +140,7 @@ pub fn Env(comptime S: type, comptime types: anytype) type {
135140
if (@hasDecl(Struct, "prototype")) {
136141
const TI = @typeInfo(Struct.prototype);
137142
const proto_name = @typeName(Receiver(TI.pointer.child));
138-
prototype_index = @field(TYPE_LOOKUP, proto_name);
143+
prototype_index = @field(TYPE_LOOKUP, proto_name).index;
139144
}
140145
table[i] = prototype_index;
141146
}
@@ -158,7 +163,7 @@ pub fn Env(comptime S: type, comptime types: anytype) type {
158163
// access to its TunctionTemplate (the thing we need to create an instance
159164
// of it)
160165
// I.e.:
161-
// const index = @field(TYPE_LOOKUP, @typeName(type_name))
166+
// const index = @field(TYPE_LOOKUP, @typeName(type_name)).index
162167
// const template = templates[index];
163168
templates: [Types.len]v8.FunctionTemplate,
164169

@@ -214,7 +219,7 @@ pub fn Env(comptime S: type, comptime types: anytype) type {
214219
// Populate our templates lookup. generateClass creates the
215220
// v8.FunctionTemplate, which we store in our env.templates.
216221
// The ordering doesn't matter. What matters is that, given a type
217-
// we can get its index via: @field(TYPE_LOOKUP, type_name)
222+
// we can get its index via: @field(TYPE_LOOKUP, type_name).index
218223
const templates = &env.templates;
219224
inline for (Types, 0..) |s, i| {
220225
templates[i] = env.generateClass(@field(types, s.name));
@@ -234,7 +239,7 @@ pub fn Env(comptime S: type, comptime types: anytype) type {
234239
// Just like we said above, given a type, we can get its
235240
// template index.
236241

237-
const proto_index = @field(TYPE_LOOKUP, proto_name);
242+
const proto_index = @field(TYPE_LOOKUP, proto_name).index;
238243
templates[i].inherit(templates[proto_index]);
239244
}
240245
}
@@ -288,7 +293,7 @@ pub fn Env(comptime S: type, comptime types: anytype) type {
288293
if (@hasDecl(Global, "prototype")) {
289294
const proto_type = Receiver(@typeInfo(Global.prototype).pointer.child);
290295
const proto_name = @typeName(proto_type);
291-
const proto_index = @field(TYPE_LOOKUP, proto_name);
296+
const proto_index = @field(TYPE_LOOKUP, proto_name).index;
292297
globals.inherit(templates[proto_index]);
293298
}
294299

@@ -309,7 +314,7 @@ pub fn Env(comptime S: type, comptime types: anytype) type {
309314
@compileError("Type '" ++ @typeName(Struct) ++ "' defines an unknown prototype: " ++ proto_name);
310315
}
311316

312-
const proto_index = @field(TYPE_LOOKUP, proto_name);
317+
const proto_index = @field(TYPE_LOOKUP, proto_name).index;
313318
const proto_obj = templates[proto_index].getFunction(context).toObject();
314319

315320
const self_obj = templates[i].getFunction(context).toObject();
@@ -640,7 +645,7 @@ pub fn Env(comptime S: type, comptime types: anytype) type {
640645
.one => {
641646
const type_name = @typeName(ptr.child);
642647
if (@hasField(TypeLookup, type_name)) {
643-
const template = templates[@field(TYPE_LOOKUP, type_name)];
648+
const template = templates[@field(TYPE_LOOKUP, type_name).index];
644649
const js_obj = try Executor.mapZigInstanceToJs(context, template, value);
645650
return js_obj.toValue();
646651
}
@@ -676,7 +681,7 @@ pub fn Env(comptime S: type, comptime types: anytype) type {
676681
.@"struct" => |s| {
677682
const type_name = @typeName(T);
678683
if (@hasField(TypeLookup, type_name)) {
679-
const template = templates[@field(TYPE_LOOKUP, type_name)];
684+
const template = templates[@field(TYPE_LOOKUP, type_name).index];
680685
const js_obj = try Executor.mapZigInstanceToJs(context, template, value);
681686
return js_obj.toValue();
682687
}
@@ -960,10 +965,11 @@ pub fn Env(comptime S: type, comptime types: anytype) type {
960965
// well as any meta data we'll need to use it later.
961966
// See the TaggedAnyOpaque struct for more details.
962967
const tao = try scope_arena.create(TaggedAnyOpaque);
968+
const meta = @field(TYPE_LOOKUP, @typeName(ptr.child));
963969
tao.* = .{
964970
.ptr = value,
965-
.index = @field(TYPE_LOOKUP, @typeName(ptr.child)),
966-
.sub_type = if (@hasDecl(ptr.child, "sub_type")) ptr.child.sub_type else null,
971+
.index = meta.index,
972+
.subtype = meta.subtype,
967973
.offset = if (@typeInfo(ptr.child) != .@"opaque" and @hasField(ptr.child, "proto")) @offsetOf(ptr.child, "proto") else -1,
968974
};
969975

@@ -1345,7 +1351,7 @@ pub fn Env(comptime S: type, comptime types: anytype) type {
13451351

13461352
const op = js_obj.getInternalField(0).castTo(v8.External).get();
13471353
const toa: *TaggedAnyOpaque = @alignCast(@ptrCast(op));
1348-
const expected_type_index = @field(TYPE_LOOKUP, type_name);
1354+
const expected_type_index = @field(TYPE_LOOKUP, type_name).index;
13491355

13501356
var type_index = toa.index;
13511357
if (type_index == expected_type_index) {
@@ -1379,6 +1385,26 @@ pub fn Env(comptime S: type, comptime types: anytype) type {
13791385
};
13801386
}
13811387

1388+
// We'll create a struct with all the types we want to bind to JavaScript. The
1389+
// fields for this struct will be the type names. The values, will be an
1390+
// instance of this struct.
1391+
// const TypeLookup = struct {
1392+
// comptime cat: usize = TypeMeta{.index = 0, subtype = null},
1393+
// comptime owner: usize = TypeMeta{.index = 1, subtype = .array}.
1394+
// ...
1395+
// }
1396+
// This is essentially meta data for each type.
1397+
const TypeMeta = struct {
1398+
// Every type is given a unique index. That index is used to lookup various
1399+
// things, i.e. the prototype chain.
1400+
index: usize,
1401+
1402+
// We store the type's subtype here, so that when we create an instance of
1403+
// the type, and bind it to JavaScript, we can store the subtype along with
1404+
// the created TaggedAnyOpaque.s
1405+
subtype: ?SubType,
1406+
};
1407+
13821408
fn isEmpty(comptime T: type) bool {
13831409
return @typeInfo(T) != .@"opaque" and @sizeOf(T) == 0;
13841410
}
@@ -2204,7 +2230,7 @@ const TaggedAnyOpaque = struct {
22042230
// V8 will give us a Value and ask us for the subtype. From the v8.Value we
22052231
// can get a v8.Object, and from the v8.Object, we can get out TaggedAnyOpaque
22062232
// which is where we store the subtype.
2207-
sub_type: ?[*c]const u8,
2233+
subtype: ?SubType,
22082234
};
22092235

22102236
fn valueToString(allocator: Allocator, value: v8.Value, isolate: v8.Isolate, context: v8.Context) ![]u8 {
@@ -2263,7 +2289,7 @@ pub export fn v8_inspector__Client__IMPL__valueSubtype(
22632289
c_value: *const v8.C_Value,
22642290
) callconv(.C) [*c]const u8 {
22652291
const external_entry = getTaggedAnyOpaque(.{ .handle = c_value }) orelse return null;
2266-
return if (external_entry.sub_type) |st| st else null;
2292+
return if (external_entry.subtype) |st| @tagName(st) else null;
22672293
}
22682294

22692295
// Same as valueSubType above, but for the optional description field.
@@ -2280,7 +2306,7 @@ pub export fn v8_inspector__Client__IMPL__descriptionForValueSubtype(
22802306
// We _must_ include a non-null description in order for the subtype value
22812307
// to be included. Besides that, I don't know if the value has any meaning
22822308
const external_entry = getTaggedAnyOpaque(.{ .handle = c_value }) orelse return null;
2283-
return if (external_entry.sub_type == null) null else "";
2309+
return if (external_entry.subtype == null) null else "";
22842310
}
22852311

22862312
fn getTaggedAnyOpaque(value: v8.Value) ?*TaggedAnyOpaque {

src/runtime/subtype.zig

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
pub const SubType = enum {
2+
@"error",
3+
array,
4+
arraybuffer,
5+
dataview,
6+
date,
7+
generator,
8+
iterator,
9+
map,
10+
node,
11+
promise,
12+
proxy,
13+
regexp,
14+
set,
15+
typedarray,
16+
wasmvalue,
17+
weakmap,
18+
weakset,
19+
webassemblymemory,
20+
};

0 commit comments

Comments
 (0)