mirror of
				https://github.com/lightpanda-io/browser.git
				synced 2025-10-30 15:41:48 +00:00 
			
		
		
		
	Merge pull request #595 from lightpanda-io/env_debug_ergonomics
Improve the debug ergonomics of the Env generic.
This commit is contained in:
		| @@ -9,23 +9,39 @@ const Loop = @import("../runtime/loop.zig").Loop; | |||||||
| const HttpClient = @import("../http/client.zig").Client; | const HttpClient = @import("../http/client.zig").Client; | ||||||
| const Renderer = @import("browser.zig").Renderer; | const Renderer = @import("browser.zig").Renderer; | ||||||
|  |  | ||||||
| const Interfaces = generate.Tuple(.{ | const WebApis = struct { | ||||||
|     @import("crypto/crypto.zig").Crypto, |     // Wrapped like this for debug ergonomics. | ||||||
|     @import("console/console.zig").Console, |     // When we create our Env, a few lines down, we define it as: | ||||||
|     @import("dom/dom.zig").Interfaces, |     //   pub const Env = js.Env(*SessionState, WebApis); | ||||||
|     @import("events/event.zig").Interfaces, |     // | ||||||
|     @import("html/html.zig").Interfaces, |     // If there's a compile time error witht he Env, it's type will be readable, | ||||||
|     @import("iterator/iterator.zig").Interfaces, |     // i.e.: runtime.js.Env(*browser.env.SessionState, browser.env.WebApis) | ||||||
|     @import("storage/storage.zig").Interfaces, |     // | ||||||
|     @import("url/url.zig").Interfaces, |     // But if we didn't wrap it in the struct, like we once didn't, and defined | ||||||
|     @import("xhr/xhr.zig").Interfaces, |     // env as: | ||||||
|     @import("xmlserializer/xmlserializer.zig").Interfaces, |     //   pub const Env = js.Env(*SessionState, Interfaces); | ||||||
| }); |     // | ||||||
|  |     // Because Interfaces is an anynoumous type, it doesn't have a friendly name | ||||||
|  |     // and errors would be something like: | ||||||
|  |     //   runtime.js.Env(*browser.env.SessionState, .{...A HUNDRED TYPES...}) | ||||||
|  |     pub const Interfaces = generate.Tuple(.{ | ||||||
|  |         @import("crypto/crypto.zig").Crypto, | ||||||
|  |         @import("console/console.zig").Console, | ||||||
|  |         @import("dom/dom.zig").Interfaces, | ||||||
|  |         @import("events/event.zig").Interfaces, | ||||||
|  |         @import("html/html.zig").Interfaces, | ||||||
|  |         @import("iterator/iterator.zig").Interfaces, | ||||||
|  |         @import("storage/storage.zig").Interfaces, | ||||||
|  |         @import("url/url.zig").Interfaces, | ||||||
|  |         @import("xhr/xhr.zig").Interfaces, | ||||||
|  |         @import("xmlserializer/xmlserializer.zig").Interfaces, | ||||||
|  |     }); | ||||||
|  | }; | ||||||
|  |  | ||||||
| pub const JsThis = Env.JsThis; | pub const JsThis = Env.JsThis; | ||||||
| pub const JsObject = Env.JsObject; | pub const JsObject = Env.JsObject; | ||||||
| pub const Callback = Env.Callback; | pub const Callback = Env.Callback; | ||||||
| pub const Env = js.Env(*SessionState, Interfaces{}); | pub const Env = js.Env(*SessionState, WebApis); | ||||||
| pub const Global = @import("html/window.zig").Window; | pub const Global = @import("html/window.zig").Window; | ||||||
|  |  | ||||||
| pub const SessionState = struct { | pub const SessionState = struct { | ||||||
|   | |||||||
| @@ -57,8 +57,8 @@ pub const Platform = struct { | |||||||
| // The `S` parameter is arbitrary state. When we start an Executor, an instance | // The `S` parameter is arbitrary state. When we start an Executor, an instance | ||||||
| // of S must be given. This instance is available to any Zig binding. | // of S must be given. This instance is available to any Zig binding. | ||||||
| // The `types` parameter is a tuple of Zig structures we want to bind to V8. | // The `types` parameter is a tuple of Zig structures we want to bind to V8. | ||||||
| pub fn Env(comptime S: type, comptime types: anytype) type { | pub fn Env(comptime S: type, comptime WebApis: type) type { | ||||||
|     const Types = @typeInfo(@TypeOf(types)).@"struct".fields; |     const Types = @typeInfo(WebApis.Interfaces).@"struct".fields; | ||||||
|  |  | ||||||
|     // Imagine we have a type Cat which has a getter: |     // Imagine we have a type Cat which has a getter: | ||||||
|     // |     // | ||||||
| @@ -97,14 +97,14 @@ pub fn Env(comptime S: type, comptime types: anytype) type { | |||||||
|             // TypeLookup. But we put it here, early, so that the rest of the |             // TypeLookup. But we put it here, early, so that the rest of the | ||||||
|             // code doesn't have to worry about checking if Struct.prototype is |             // code doesn't have to worry about checking if Struct.prototype is | ||||||
|             // a pointer. |             // a pointer. | ||||||
|             const Struct = @field(types, s.name); |             const Struct = s.defaultValue().?; | ||||||
|             if (@hasDecl(Struct, "prototype") and @typeInfo(Struct.prototype) != .pointer) { |             if (@hasDecl(Struct, "prototype") and @typeInfo(Struct.prototype) != .pointer) { | ||||||
|                 @compileError(std.fmt.comptimePrint("Prototype '{s}' for type '{s} must be a pointer", .{ @typeName(Struct.prototype), @typeName(Struct) })); |                 @compileError(std.fmt.comptimePrint("Prototype '{s}' for type '{s} must be a pointer", .{ @typeName(Struct.prototype), @typeName(Struct) })); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             const subtype: ?SubType = if (@hasDecl(Struct, "subtype")) Struct.subtype else null; |             const subtype: ?SubType = if (@hasDecl(Struct, "subtype")) Struct.subtype else null; | ||||||
|  |  | ||||||
|             const R = Receiver(@field(types, s.name)); |             const R = Receiver(Struct); | ||||||
|             fields[i] = .{ |             fields[i] = .{ | ||||||
|                 .name = @typeName(R), |                 .name = @typeName(R), | ||||||
|                 .type = TypeMeta, |                 .type = TypeMeta, | ||||||
| @@ -141,7 +141,7 @@ pub fn Env(comptime S: type, comptime types: anytype) type { | |||||||
|         const TYPE_LOOKUP = TypeLookup{}; |         const TYPE_LOOKUP = TypeLookup{}; | ||||||
|         for (Types, 0..) |s, i| { |         for (Types, 0..) |s, i| { | ||||||
|             var prototype_index = i; |             var prototype_index = i; | ||||||
|             const Struct = @field(types, s.name); |             const Struct = s.defaultValue().?; | ||||||
|             if (@hasDecl(Struct, "prototype")) { |             if (@hasDecl(Struct, "prototype")) { | ||||||
|                 const TI = @typeInfo(Struct.prototype); |                 const TI = @typeInfo(Struct.prototype); | ||||||
|                 const proto_name = @typeName(Receiver(TI.pointer.child)); |                 const proto_name = @typeName(Receiver(TI.pointer.child)); | ||||||
| @@ -225,13 +225,13 @@ pub fn Env(comptime S: type, comptime types: anytype) type { | |||||||
|             const templates = &env.templates; |             const templates = &env.templates; | ||||||
|             inline for (Types, 0..) |s, i| { |             inline for (Types, 0..) |s, i| { | ||||||
|                 @setEvalBranchQuota(10_000); |                 @setEvalBranchQuota(10_000); | ||||||
|                 templates[i] = v8.Persistent(v8.FunctionTemplate).init(isolate, generateClass(@field(types, s.name), isolate)).castToFunctionTemplate(); |                 templates[i] = v8.Persistent(v8.FunctionTemplate).init(isolate, generateClass(s.defaultValue().?, isolate)).castToFunctionTemplate(); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             // Above, we've created all our our FunctionTemplates. Now that we |             // Above, we've created all our our FunctionTemplates. Now that we | ||||||
|             // have them all, we can hook up the prototypes. |             // have them all, we can hook up the prototypes. | ||||||
|             inline for (Types, 0..) |s, i| { |             inline for (Types, 0..) |s, i| { | ||||||
|                 const Struct = @field(types, s.name); |                 const Struct = s.defaultValue().?; | ||||||
|                 if (@hasDecl(Struct, "prototype")) { |                 if (@hasDecl(Struct, "prototype")) { | ||||||
|                     const TI = @typeInfo(Struct.prototype); |                     const TI = @typeInfo(Struct.prototype); | ||||||
|                     const proto_name = @typeName(Receiver(TI.pointer.child)); |                     const proto_name = @typeName(Receiver(TI.pointer.child)); | ||||||
| @@ -359,7 +359,7 @@ pub fn Env(comptime S: type, comptime types: anytype) type { | |||||||
|                     // are now going to get associated with our global instance. |                     // are now going to get associated with our global instance. | ||||||
|                     const templates = &self.env.templates; |                     const templates = &self.env.templates; | ||||||
|                     inline for (Types, 0..) |s, i| { |                     inline for (Types, 0..) |s, i| { | ||||||
|                         const Struct = @field(types, s.name); |                         const Struct = s.defaultValue().?; | ||||||
|                         const class_name = v8.String.initUtf8(isolate, comptime classNameForStruct(Struct)); |                         const class_name = v8.String.initUtf8(isolate, comptime classNameForStruct(Struct)); | ||||||
|                         global_template.set(class_name.toName(), templates[i], v8.PropertyAttribute.None); |                         global_template.set(class_name.toName(), templates[i], v8.PropertyAttribute.None); | ||||||
|                     } |                     } | ||||||
| @@ -386,7 +386,7 @@ pub fn Env(comptime S: type, comptime types: anytype) type { | |||||||
|                     // https://groups.google.com/g/v8-users/c/qAQQBmbi--8 |                     // https://groups.google.com/g/v8-users/c/qAQQBmbi--8 | ||||||
|                     // TODO: see if newer V8 engines have a way around this. |                     // TODO: see if newer V8 engines have a way around this. | ||||||
|                     inline for (Types, 0..) |s, i| { |                     inline for (Types, 0..) |s, i| { | ||||||
|                         const Struct = @field(types, s.name); |                         const Struct = s.defaultValue().?; | ||||||
|  |  | ||||||
|                         if (@hasDecl(Struct, "prototype")) { |                         if (@hasDecl(Struct, "prototype")) { | ||||||
|                             const proto_type = Receiver(@typeInfo(Struct.prototype).pointer.child); |                             const proto_type = Receiver(@typeInfo(Struct.prototype).pointer.child); | ||||||
| @@ -462,7 +462,7 @@ pub fn Env(comptime S: type, comptime types: anytype) type { | |||||||
|                 // NOTE: there is no way in v8 to subclass the Error built-in type |                 // NOTE: there is no way in v8 to subclass the Error built-in type | ||||||
|                 // TODO: this is an horrible hack |                 // TODO: this is an horrible hack | ||||||
|                 inline for (Types) |s| { |                 inline for (Types) |s| { | ||||||
|                     const Struct = @field(types, s.name); |                     const Struct = s.defaultValue().?; | ||||||
|                     if (@hasDecl(Struct, "ErrorSet")) { |                     if (@hasDecl(Struct, "ErrorSet")) { | ||||||
|                         const script = comptime classNameForStruct(Struct) ++ ".prototype.__proto__ = Error.prototype"; |                         const script = comptime classNameForStruct(Struct) ++ ".prototype.__proto__ = Error.prototype"; | ||||||
|                         _ = try scope.exec(script, "errorSubclass"); |                         _ = try scope.exec(script, "errorSubclass"); | ||||||
|   | |||||||
| @@ -26,7 +26,7 @@ pub const allocator = std.testing.allocator; | |||||||
| // browser.Env or the browser.SessionState | // browser.Env or the browser.SessionState | ||||||
| pub fn Runner(comptime State: type, comptime Global: type, comptime types: anytype) type { | pub fn Runner(comptime State: type, comptime Global: type, comptime types: anytype) type { | ||||||
|     const AdjustedTypes = if (Global == void) generate.Tuple(.{ types, DefaultGlobal }) else types; |     const AdjustedTypes = if (Global == void) generate.Tuple(.{ types, DefaultGlobal }) else types; | ||||||
|     const Env = js.Env(State, AdjustedTypes{}); |     const Env = js.Env(State, struct {pub const Interfaces = AdjustedTypes;}); | ||||||
|  |  | ||||||
|     return struct { |     return struct { | ||||||
|         env: *Env, |         env: *Env, | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Karl Seguin
					Karl Seguin