mirror of
				https://github.com/lightpanda-io/browser.git
				synced 2025-10-30 15:41:48 +00:00 
			
		
		
		
	Merge pull request #1021 from lightpanda-io/patchright
	
		
			
	
		
	
	
		
	
		
			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
				
			
		
			
				
	
				nightly build / build-linux-x86_64 (push) Has been cancelled
				
			
		
			
				
	
				nightly build / build-linux-aarch64 (push) Has been cancelled
				
			
		
			
				
	
				nightly build / build-macos-aarch64 (push) Has been cancelled
				
			
		
			
				
	
				nightly build / build-macos-x86_64 (push) Has been cancelled
				
			
		
			
				
	
				wpt / web platform tests json output (push) Has been cancelled
				
			
		
			
				
	
				wpt / perf-fmt (push) Has been cancelled
				
			
		
		
	
	
				
					
				
			
		
			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
				
			nightly build / build-linux-x86_64 (push) Has been cancelled
				
			nightly build / build-linux-aarch64 (push) Has been cancelled
				
			nightly build / build-macos-aarch64 (push) Has been cancelled
				
			nightly build / build-macos-x86_64 (push) Has been cancelled
				
			wpt / web platform tests json output (push) Has been cancelled
				
			wpt / perf-fmt (push) Has been cancelled
				
			Patchright compatibility
This commit is contained in:
		| @@ -821,7 +821,8 @@ pub const Parser = struct { | |||||||
| // nameStart returns whether c can be the first character of an identifier | // nameStart returns whether c can be the first character of an identifier | ||||||
| // (not counting an initial hyphen, or an escape sequence). | // (not counting an initial hyphen, or an escape sequence). | ||||||
| fn nameStart(c: u8) bool { | fn nameStart(c: u8) bool { | ||||||
|     return 'a' <= c and c <= 'z' or 'A' <= c and c <= 'Z' or c == '_' or c > 127; |     return 'a' <= c and c <= 'z' or 'A' <= c and c <= 'Z' or c == '_' or c > 127 or | ||||||
|  |         '0' <= c and c <= '9'; | ||||||
| } | } | ||||||
|  |  | ||||||
| // nameChar returns whether c can be a character within an identifier | // nameChar returns whether c can be a character within an identifier | ||||||
| @@ -890,7 +891,7 @@ test "parser.parseIdentifier" { | |||||||
|         err: bool = false, |         err: bool = false, | ||||||
|     }{ |     }{ | ||||||
|         .{ .s = "x", .exp = "x" }, |         .{ .s = "x", .exp = "x" }, | ||||||
|         .{ .s = "96", .exp = "", .err = true }, |         .{ .s = "96", .exp = "96", .err = false }, | ||||||
|         .{ .s = "-x", .exp = "-x" }, |         .{ .s = "-x", .exp = "-x" }, | ||||||
|         .{ .s = "r\\e9 sumé", .exp = "résumé" }, |         .{ .s = "r\\e9 sumé", .exp = "résumé" }, | ||||||
|         .{ .s = "r\\0000e9 sumé", .exp = "résumé" }, |         .{ .s = "r\\0000e9 sumé", .exp = "résumé" }, | ||||||
| @@ -975,6 +976,7 @@ test "parser.parse" { | |||||||
|         .{ .s = ":root", .exp = .{ .pseudo_class = .root } }, |         .{ .s = ":root", .exp = .{ .pseudo_class = .root } }, | ||||||
|         .{ .s = ".\\:bar", .exp = .{ .class = ":bar" } }, |         .{ .s = ".\\:bar", .exp = .{ .class = ":bar" } }, | ||||||
|         .{ .s = ".foo\\:bar", .exp = .{ .class = "foo:bar" } }, |         .{ .s = ".foo\\:bar", .exp = .{ .class = "foo:bar" } }, | ||||||
|  |         .{ .s = "[class=75c0fa18a94b9e3a6b8e14d6cbe688a27f5da10a]", .exp = .{ .attribute = .{ .key = "class", .val = "75c0fa18a94b9e3a6b8e14d6cbe688a27f5da10a", .op = .eql } } }, | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     for (testcases) |tc| { |     for (testcases) |tc| { | ||||||
|   | |||||||
| @@ -993,6 +993,11 @@ test "Browser.CSS.Selector: matchFirst" { | |||||||
|             .n = .{ .child = &.{ .name = "p", .sibling = &.{ .name = "p", .att = "bar" } } }, |             .n = .{ .child = &.{ .name = "p", .sibling = &.{ .name = "p", .att = "bar" } } }, | ||||||
|             .exp = 0, |             .exp = 0, | ||||||
|         }, |         }, | ||||||
|  |         .{ | ||||||
|  |             .q = "[foo=1baz]", | ||||||
|  |             .n = .{ .child = &.{ .name = "p", .sibling = &.{ .name = "p", .att = "bar" } } }, | ||||||
|  |             .exp = 0, | ||||||
|  |         }, | ||||||
|         .{ |         .{ | ||||||
|             .q = "[foo!=bar]", |             .q = "[foo!=bar]", | ||||||
|             .n = .{ .child = &.{ .name = "p", .sibling = &.{ .name = "p", .att = "bar" } } }, |             .n = .{ .child = &.{ .name = "p", .sibling = &.{ .name = "p", .att = "bar" } } }, | ||||||
|   | |||||||
| @@ -151,18 +151,18 @@ pub fn CDPT(comptime TypeProvider: type) type { | |||||||
|                 if (std.mem.eql(u8, input_session_id, "STARTUP")) { |                 if (std.mem.eql(u8, input_session_id, "STARTUP")) { | ||||||
|                     is_startup = true; |                     is_startup = true; | ||||||
|                 } else if (self.isValidSessionId(input_session_id) == false) { |                 } else if (self.isValidSessionId(input_session_id) == false) { | ||||||
|                     return command.sendError(-32001, "Unknown sessionId"); |                     return command.sendError(-32001, "Unknown sessionId", .{}); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             if (is_startup) { |             if (is_startup) { | ||||||
|                 dispatchStartupCommand(&command) catch |err| { |                 dispatchStartupCommand(&command) catch |err| { | ||||||
|                     command.sendError(-31999, @errorName(err)) catch {}; |                     command.sendError(-31999, @errorName(err), .{}) catch {}; | ||||||
|                     return err; |                     return err; | ||||||
|                 }; |                 }; | ||||||
|             } else { |             } else { | ||||||
|                 dispatchCommand(&command, input.method) catch |err| { |                 dispatchCommand(&command, input.method) catch |err| { | ||||||
|                     command.sendError(-31998, @errorName(err)) catch {}; |                     command.sendError(-31998, @errorName(err), .{}) catch {}; | ||||||
|                     return err; |                     return err; | ||||||
|                 }; |                 }; | ||||||
|             } |             } | ||||||
| @@ -331,7 +331,7 @@ pub fn BrowserContext(comptime CDP_T: type) type { | |||||||
|         node_search_list: Node.Search.List, |         node_search_list: Node.Search.List, | ||||||
|  |  | ||||||
|         inspector: Inspector, |         inspector: Inspector, | ||||||
|         isolated_world: ?IsolatedWorld, |         isolated_worlds: std.ArrayListUnmanaged(IsolatedWorld), | ||||||
|  |  | ||||||
|         http_proxy_changed: bool = false, |         http_proxy_changed: bool = false, | ||||||
|  |  | ||||||
| @@ -375,7 +375,7 @@ pub fn BrowserContext(comptime CDP_T: type) type { | |||||||
|                 .page_life_cycle_events = false, // TODO; Target based value |                 .page_life_cycle_events = false, // TODO; Target based value | ||||||
|                 .node_registry = registry, |                 .node_registry = registry, | ||||||
|                 .node_search_list = undefined, |                 .node_search_list = undefined, | ||||||
|                 .isolated_world = null, |                 .isolated_worlds = .empty, | ||||||
|                 .inspector = inspector, |                 .inspector = inspector, | ||||||
|                 .notification_arena = cdp.notification_arena.allocator(), |                 .notification_arena = cdp.notification_arena.allocator(), | ||||||
|                 .intercept_state = try InterceptState.init(allocator), |                 .intercept_state = try InterceptState.init(allocator), | ||||||
| @@ -404,9 +404,10 @@ pub fn BrowserContext(comptime CDP_T: type) type { | |||||||
|             // so we need to shutdown the page one first. |             // so we need to shutdown the page one first. | ||||||
|             self.cdp.browser.closeSession(); |             self.cdp.browser.closeSession(); | ||||||
|  |  | ||||||
|             if (self.isolated_world) |*world| { |             for (self.isolated_worlds.items) |*world| { | ||||||
|                 world.deinit(); |                 world.deinit(); | ||||||
|             } |             } | ||||||
|  |             self.isolated_worlds.clearRetainingCapacity(); | ||||||
|             self.node_registry.deinit(); |             self.node_registry.deinit(); | ||||||
|             self.node_search_list.deinit(); |             self.node_search_list.deinit(); | ||||||
|             self.cdp.browser.notification.unregisterAll(self); |             self.cdp.browser.notification.unregisterAll(self); | ||||||
| @@ -427,19 +428,19 @@ pub fn BrowserContext(comptime CDP_T: type) type { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         pub fn createIsolatedWorld(self: *Self, world_name: []const u8, grant_universal_access: bool) !*IsolatedWorld { |         pub fn createIsolatedWorld(self: *Self, world_name: []const u8, grant_universal_access: bool) !*IsolatedWorld { | ||||||
|             if (self.isolated_world != null) { |  | ||||||
|                 return error.CurrentlyOnly1IsolatedWorldSupported; |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             var executor = try self.cdp.browser.env.newExecutionWorld(); |             var executor = try self.cdp.browser.env.newExecutionWorld(); | ||||||
|             errdefer executor.deinit(); |             errdefer executor.deinit(); | ||||||
|  |  | ||||||
|             self.isolated_world = .{ |             const owned_name = try self.arena.dupe(u8, world_name); | ||||||
|                 .name = try self.arena.dupe(u8, world_name), |             const world = try self.isolated_worlds.addOne(self.arena); | ||||||
|  |  | ||||||
|  |             world.* = .{ | ||||||
|  |                 .name = owned_name, | ||||||
|                 .executor = executor, |                 .executor = executor, | ||||||
|                 .grant_universal_access = grant_universal_access, |                 .grant_universal_access = grant_universal_access, | ||||||
|             }; |             }; | ||||||
|             return &self.isolated_world.?; |  | ||||||
|  |             return world; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         pub fn nodeWriter(self: *Self, root: *const Node, opts: Node.Writer.Opts) Node.Writer { |         pub fn nodeWriter(self: *Self, root: *const Node, opts: Node.Writer.Opts) Node.Writer { | ||||||
| @@ -682,7 +683,14 @@ const IsolatedWorld = struct { | |||||||
|     // This also means this pointer becomes invalid after removePage untill a new page is created. |     // This also means this pointer becomes invalid after removePage untill a new page is created. | ||||||
|     // Currently we have only 1 page/frame and thus also only 1 state in the isolate world. |     // Currently we have only 1 page/frame and thus also only 1 state in the isolate world. | ||||||
|     pub fn createContext(self: *IsolatedWorld, page: *Page) !void { |     pub fn createContext(self: *IsolatedWorld, page: *Page) !void { | ||||||
|         if (self.executor.js_context != null) return error.Only1IsolatedContextSupported; |         // if (self.executor.js_context != null) return error.Only1IsolatedContextSupported; | ||||||
|  |         if (self.executor.js_context != null) { | ||||||
|  |             log.warn(.cdp, "not implemented", .{ | ||||||
|  |                 .feature = "createContext: Not implemented second isolated context creation", | ||||||
|  |                 .info = "reuse existing context", | ||||||
|  |             }); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|         _ = try self.executor.createJsContext( |         _ = try self.executor.createJsContext( | ||||||
|             &page.window, |             &page.window, | ||||||
|             page, |             page, | ||||||
| @@ -691,6 +699,14 @@ const IsolatedWorld = struct { | |||||||
|             Env.GlobalMissingCallback.init(&self.polyfill_loader), |             Env.GlobalMissingCallback.init(&self.polyfill_loader), | ||||||
|         ); |         ); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     pub fn createContextAndLoadPolyfills(self: *IsolatedWorld, arena: Allocator, page: *Page) !void { | ||||||
|  |         // We need to recreate the isolated world context | ||||||
|  |         try self.createContext(page); | ||||||
|  |  | ||||||
|  |         const loader = @import("../browser/polyfill/polyfill.zig"); | ||||||
|  |         try loader.preload(arena, &self.executor.js_context.?); | ||||||
|  |     } | ||||||
| }; | }; | ||||||
|  |  | ||||||
| // This is a generic because when we send a result we have two different | // This is a generic because when we send a result we have two different | ||||||
| @@ -757,10 +773,14 @@ pub fn Command(comptime CDP_T: type, comptime Sender: type) type { | |||||||
|             return self.cdp.sendEvent(method, p, opts); |             return self.cdp.sendEvent(method, p, opts); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         pub fn sendError(self: *Self, code: i32, message: []const u8) !void { |         const SendErrorOpts = struct { | ||||||
|  |             include_session_id: bool = true, | ||||||
|  |         }; | ||||||
|  |         pub fn sendError(self: *Self, code: i32, message: []const u8, opts: SendErrorOpts) !void { | ||||||
|             return self.sender.sendJSON(.{ |             return self.sender.sendJSON(.{ | ||||||
|                 .id = self.input.id, |                 .id = self.input.id, | ||||||
|                 .@"error" = .{ .code = code, .message = message }, |                 .@"error" = .{ .code = code, .message = message }, | ||||||
|  |                 .sessionId = if (opts.include_session_id) self.input.session_id else null, | ||||||
|             }); |             }); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -17,6 +17,7 @@ | |||||||
| // along with this program.  If not, see <https://www.gnu.org/licenses/>. | // along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||||
|  |  | ||||||
| const std = @import("std"); | const std = @import("std"); | ||||||
|  | const log = @import("../../log.zig"); | ||||||
| const Allocator = std.mem.Allocator; | const Allocator = std.mem.Allocator; | ||||||
| const Node = @import("../Node.zig"); | const Node = @import("../Node.zig"); | ||||||
| const css = @import("../../browser/dom/css.zig"); | const css = @import("../../browser/dom/css.zig"); | ||||||
| @@ -39,6 +40,7 @@ pub fn processMessage(cmd: anytype) !void { | |||||||
|         getContentQuads, |         getContentQuads, | ||||||
|         getBoxModel, |         getBoxModel, | ||||||
|         requestChildNodes, |         requestChildNodes, | ||||||
|  |         getFrameOwner, | ||||||
|     }, cmd.input.action) orelse return error.UnknownMethod; |     }, cmd.input.action) orelse return error.UnknownMethod; | ||||||
|  |  | ||||||
|     switch (action) { |     switch (action) { | ||||||
| @@ -55,6 +57,7 @@ pub fn processMessage(cmd: anytype) !void { | |||||||
|         .getContentQuads => return getContentQuads(cmd), |         .getContentQuads => return getContentQuads(cmd), | ||||||
|         .getBoxModel => return getBoxModel(cmd), |         .getBoxModel => return getBoxModel(cmd), | ||||||
|         .requestChildNodes => return requestChildNodes(cmd), |         .requestChildNodes => return requestChildNodes(cmd), | ||||||
|  |         .getFrameOwner => return getFrameOwner(cmd), | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -67,6 +70,10 @@ fn getDocument(cmd: anytype) !void { | |||||||
|     }; |     }; | ||||||
|     const params = try cmd.params(Params) orelse Params{}; |     const params = try cmd.params(Params) orelse Params{}; | ||||||
|  |  | ||||||
|  |     if (params.pierce) { | ||||||
|  |         log.warn(.cdp, "not implemented", .{ .feature = "DOM.getDocument: Not implemented pierce parameter" }); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded; |     const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded; | ||||||
|     const page = bc.session.currentPage() orelse return error.PageNotLoaded; |     const page = bc.session.currentPage() orelse return error.PageNotLoaded; | ||||||
|     const doc = parser.documentHTMLToDocument(page.window.document); |     const doc = parser.documentHTMLToDocument(page.window.document); | ||||||
| @@ -206,7 +213,9 @@ fn querySelector(cmd: anytype) !void { | |||||||
|  |  | ||||||
|     const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded; |     const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded; | ||||||
|  |  | ||||||
|     const node = bc.node_registry.lookup_by_id.get(params.nodeId) orelse return error.UnknownNode; |     const node = bc.node_registry.lookup_by_id.get(params.nodeId) orelse { | ||||||
|  |         return cmd.sendError(-32000, "Could not find node with given id", .{}); | ||||||
|  |     }; | ||||||
|  |  | ||||||
|     const selected_node = try css.querySelector( |     const selected_node = try css.querySelector( | ||||||
|         cmd.arena, |         cmd.arena, | ||||||
| @@ -233,7 +242,9 @@ fn querySelectorAll(cmd: anytype) !void { | |||||||
|  |  | ||||||
|     const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded; |     const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded; | ||||||
|  |  | ||||||
|     const node = bc.node_registry.lookup_by_id.get(params.nodeId) orelse return error.UnknownNode; |     const node = bc.node_registry.lookup_by_id.get(params.nodeId) orelse { | ||||||
|  |         return cmd.sendError(-32000, "Could not find node with given id", .{}); | ||||||
|  |     }; | ||||||
|  |  | ||||||
|     const arena = cmd.arena; |     const arena = cmd.arena; | ||||||
|     const selected_nodes = try css.querySelectorAll(arena, node._node, params.selector); |     const selected_nodes = try css.querySelectorAll(arena, node._node, params.selector); | ||||||
| @@ -266,10 +277,12 @@ fn resolveNode(cmd: anytype) !void { | |||||||
|     var js_context = page.main_context; |     var js_context = page.main_context; | ||||||
|     if (params.executionContextId) |context_id| { |     if (params.executionContextId) |context_id| { | ||||||
|         if (js_context.v8_context.debugContextId() != context_id) { |         if (js_context.v8_context.debugContextId() != context_id) { | ||||||
|             var isolated_world = bc.isolated_world orelse return error.ContextNotFound; |             for (bc.isolated_worlds.items) |*isolated_world| { | ||||||
|             js_context = &(isolated_world.executor.js_context orelse return error.ContextNotFound); |                 js_context = &(isolated_world.executor.js_context orelse return error.ContextNotFound); | ||||||
|  |                 if (js_context.v8_context.debugContextId() == context_id) { | ||||||
|             if (js_context.v8_context.debugContextId() != context_id) return error.ContextNotFound; |                     break; | ||||||
|  |                 } | ||||||
|  |             } else return error.ContextNotFound; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -300,16 +313,18 @@ fn describeNode(cmd: anytype) !void { | |||||||
|         nodeId: ?Node.Id = null, |         nodeId: ?Node.Id = null, | ||||||
|         backendNodeId: ?Node.Id = null, |         backendNodeId: ?Node.Id = null, | ||||||
|         objectId: ?[]const u8 = null, |         objectId: ?[]const u8 = null, | ||||||
|         depth: u32 = 1, |         depth: i32 = 1, | ||||||
|         pierce: bool = false, |         pierce: bool = false, | ||||||
|     })) orelse return error.InvalidParams; |     })) orelse return error.InvalidParams; | ||||||
|  |  | ||||||
|     if (params.depth != 1 or params.pierce) return error.NotImplemented; |     if (params.pierce) { | ||||||
|  |         log.warn(.cdp, "not implemented", .{ .feature = "DOM.describeNode: Not implemented pierce parameter" }); | ||||||
|  |     } | ||||||
|     const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded; |     const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded; | ||||||
|  |  | ||||||
|     const node = try getNode(cmd.arena, bc, params.nodeId, params.backendNodeId, params.objectId); |     const node = try getNode(cmd.arena, bc, params.nodeId, params.backendNodeId, params.objectId); | ||||||
|  |  | ||||||
|     return cmd.sendResult(.{ .node = bc.nodeWriter(node, .{}) }, .{}); |     return cmd.sendResult(.{ .node = bc.nodeWriter(node, .{ .depth = params.depth }) }, .{}); | ||||||
| } | } | ||||||
|  |  | ||||||
| // An array of quad vertices, x immediately followed by y for each point, points clock-wise. | // An array of quad vertices, x immediately followed by y for each point, points clock-wise. | ||||||
| @@ -461,6 +476,24 @@ fn requestChildNodes(cmd: anytype) !void { | |||||||
|     return cmd.sendResult(null, .{}); |     return cmd.sendResult(null, .{}); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | fn getFrameOwner(cmd: anytype) !void { | ||||||
|  |     const params = (try cmd.params(struct { | ||||||
|  |         frameId: []const u8, | ||||||
|  |     })) orelse return error.InvalidParams; | ||||||
|  |  | ||||||
|  |     const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded; | ||||||
|  |     const target_id = bc.target_id orelse return error.TargetNotLoaded; | ||||||
|  |     if (std.mem.eql(u8, target_id, params.frameId) == false) { | ||||||
|  |         return cmd.sendError(-32000, "Frame with the given id does not belong to the target.", .{}); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     const page = bc.session.currentPage() orelse return error.PageNotLoaded; | ||||||
|  |     const doc = parser.documentHTMLToDocument(page.window.document); | ||||||
|  |  | ||||||
|  |     const node = try bc.node_registry.register(parser.documentToNode(doc)); | ||||||
|  |     return cmd.sendResult(.{ .nodeId = node.id, .backendNodeId = node.id }, .{}); | ||||||
|  | } | ||||||
|  |  | ||||||
| const testing = @import("../testing.zig"); | const testing = @import("../testing.zig"); | ||||||
|  |  | ||||||
| test "cdp.dom: getSearchResults unknown search id" { | test "cdp.dom: getSearchResults unknown search id" { | ||||||
| @@ -534,16 +567,19 @@ test "cdp.dom: querySelector unknown search id" { | |||||||
|  |  | ||||||
|     _ = try ctx.loadBrowserContext(.{ .id = "BID-A", .html = "<p>1</p> <p>2</p>" }); |     _ = try ctx.loadBrowserContext(.{ .id = "BID-A", .html = "<p>1</p> <p>2</p>" }); | ||||||
|  |  | ||||||
|     try testing.expectError(error.UnknownNode, ctx.processMessage(.{ |     try ctx.processMessage(.{ | ||||||
|         .id = 9, |         .id = 9, | ||||||
|         .method = "DOM.querySelector", |         .method = "DOM.querySelector", | ||||||
|         .params = .{ .nodeId = 99, .selector = "" }, |         .params = .{ .nodeId = 99, .selector = "" }, | ||||||
|     })); |     }); | ||||||
|     try testing.expectError(error.UnknownNode, ctx.processMessage(.{ |     try ctx.expectSentError(-32000, "Could not find node with given id", .{}); | ||||||
|  |  | ||||||
|  |     try ctx.processMessage(.{ | ||||||
|         .id = 9, |         .id = 9, | ||||||
|         .method = "DOM.querySelectorAll", |         .method = "DOM.querySelectorAll", | ||||||
|         .params = .{ .nodeId = 99, .selector = "" }, |         .params = .{ .nodeId = 99, .selector = "" }, | ||||||
|     })); |     }); | ||||||
|  |     try ctx.expectSentError(-32000, "Could not find node with given id", .{}); | ||||||
| } | } | ||||||
|  |  | ||||||
| test "cdp.dom: querySelector Node not found" { | test "cdp.dom: querySelector Node not found" { | ||||||
|   | |||||||
| @@ -244,7 +244,14 @@ pub fn httpRequestStart(arena: Allocator, bc: anytype, msg: *const Notification. | |||||||
|  |  | ||||||
|     const transfer = msg.transfer; |     const transfer = msg.transfer; | ||||||
|     // We're missing a bunch of fields, but, for now, this seems like enough |     // We're missing a bunch of fields, but, for now, this seems like enough | ||||||
|     try bc.cdp.sendEvent("Network.requestWillBeSent", .{ .requestId = try std.fmt.allocPrint(arena, "REQ-{d}", .{transfer.id}), .frameId = target_id, .loaderId = bc.loader_id, .documentUrl = DocumentUrlWriter.init(&page.url.uri), .request = TransferAsRequestWriter.init(transfer) }, .{ .session_id = session_id }); |     try bc.cdp.sendEvent("Network.requestWillBeSent", .{ | ||||||
|  |         .requestId = try std.fmt.allocPrint(arena, "REQ-{d}", .{transfer.id}), | ||||||
|  |         .frameId = target_id, | ||||||
|  |         .loaderId = bc.loader_id, | ||||||
|  |         .documentUrl = DocumentUrlWriter.init(&page.url.uri), | ||||||
|  |         .request = TransferAsRequestWriter.init(transfer), | ||||||
|  |         .initiator = .{ .type = "other" }, | ||||||
|  |     }, .{ .session_id = session_id }); | ||||||
| } | } | ||||||
|  |  | ||||||
| pub fn httpResponseHeaderDone(arena: Allocator, bc: anytype, msg: *const Notification.ResponseHeaderDone) !void { | pub fn httpResponseHeaderDone(arena: Allocator, bc: anytype, msg: *const Notification.ResponseHeaderDone) !void { | ||||||
|   | |||||||
| @@ -122,7 +122,7 @@ fn createIsolatedWorld(cmd: anytype) !void { | |||||||
|  |  | ||||||
|     const world = try bc.createIsolatedWorld(params.worldName, params.grantUniveralAccess); |     const world = try bc.createIsolatedWorld(params.worldName, params.grantUniveralAccess); | ||||||
|     const page = bc.session.currentPage() orelse return error.PageNotLoaded; |     const page = bc.session.currentPage() orelse return error.PageNotLoaded; | ||||||
|     try pageCreated(bc, page); |     try world.createContextAndLoadPolyfills(bc.arena, page); | ||||||
|     const js_context = &world.executor.js_context.?; |     const js_context = &world.executor.js_context.?; | ||||||
|  |  | ||||||
|     // Create the auxdata json for the contextCreated event |     // Create the auxdata json for the contextCreated event | ||||||
| @@ -259,7 +259,7 @@ pub fn pageNavigate(arena: Allocator, bc: anytype, event: *const Notification.Pa | |||||||
|             true, |             true, | ||||||
|         ); |         ); | ||||||
|     } |     } | ||||||
|     if (bc.isolated_world) |*isolated_world| { |     for (bc.isolated_worlds.items) |*isolated_world| { | ||||||
|         const aux_json = try std.fmt.allocPrint(arena, "{{\"isDefault\":false,\"type\":\"isolated\",\"frameId\":\"{s}\"}}", .{target_id}); |         const aux_json = try std.fmt.allocPrint(arena, "{{\"isDefault\":false,\"type\":\"isolated\",\"frameId\":\"{s}\"}}", .{target_id}); | ||||||
|         // Calling contextCreated will assign a new Id to the context and send the contextCreated event |         // Calling contextCreated will assign a new Id to the context and send the contextCreated event | ||||||
|         bc.inspector.contextCreated( |         bc.inspector.contextCreated( | ||||||
| @@ -274,18 +274,14 @@ pub fn pageNavigate(arena: Allocator, bc: anytype, event: *const Notification.Pa | |||||||
|  |  | ||||||
| pub fn pageRemove(bc: anytype) !void { | pub fn pageRemove(bc: anytype) !void { | ||||||
|     // The main page is going to be removed, we need to remove contexts from other worlds first. |     // The main page is going to be removed, we need to remove contexts from other worlds first. | ||||||
|     if (bc.isolated_world) |*isolated_world| { |     for (bc.isolated_worlds.items) |*isolated_world| { | ||||||
|         try isolated_world.removeContext(); |         try isolated_world.removeContext(); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| pub fn pageCreated(bc: anytype, page: *Page) !void { | pub fn pageCreated(bc: anytype, page: *Page) !void { | ||||||
|     if (bc.isolated_world) |*isolated_world| { |     for (bc.isolated_worlds.items) |*isolated_world| { | ||||||
|         // We need to recreate the isolated world context |         try isolated_world.createContextAndLoadPolyfills(bc.arena, page); | ||||||
|         try isolated_world.createContext(page); |  | ||||||
|  |  | ||||||
|         const polyfill = @import("../../browser/polyfill/polyfill.zig"); |  | ||||||
|         try polyfill.preload(bc.arena, &isolated_world.executor.js_context.?); |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -27,6 +27,7 @@ pub fn processMessage(cmd: anytype) !void { | |||||||
|         addBinding, |         addBinding, | ||||||
|         callFunctionOn, |         callFunctionOn, | ||||||
|         releaseObject, |         releaseObject, | ||||||
|  |         getProperties, | ||||||
|     }, cmd.input.action) orelse return error.UnknownMethod; |     }, cmd.input.action) orelse return error.UnknownMethod; | ||||||
|  |  | ||||||
|     switch (action) { |     switch (action) { | ||||||
|   | |||||||
| @@ -79,7 +79,7 @@ fn createBrowserContext(cmd: anytype) !void { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     const bc = cmd.createBrowserContext() catch |err| switch (err) { |     const bc = cmd.createBrowserContext() catch |err| switch (err) { | ||||||
|         error.AlreadyExists => return cmd.sendError(-32000, "Cannot have more than one browser context at a time"), |         error.AlreadyExists => return cmd.sendError(-32000, "Cannot have more than one browser context at a time", .{}), | ||||||
|         else => return err, |         else => return err, | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
| @@ -102,7 +102,7 @@ fn disposeBrowserContext(cmd: anytype) !void { | |||||||
|     })) orelse return error.InvalidParams; |     })) orelse return error.InvalidParams; | ||||||
|  |  | ||||||
|     if (cmd.cdp.disposeBrowserContext(params.browserContextId) == false) { |     if (cmd.cdp.disposeBrowserContext(params.browserContextId) == false) { | ||||||
|         return cmd.sendError(-32602, "No browser context with the given id found"); |         return cmd.sendError(-32602, "No browser context with the given id found", .{}); | ||||||
|     } |     } | ||||||
|     try cmd.sendResult(null, .{}); |     try cmd.sendResult(null, .{}); | ||||||
| } | } | ||||||
| @@ -241,10 +241,10 @@ fn closeTarget(cmd: anytype) !void { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     bc.session.removePage(); |     bc.session.removePage(); | ||||||
|     if (bc.isolated_world) |*world| { |     for (bc.isolated_worlds.items) |*world| { | ||||||
|         world.deinit(); |         world.deinit(); | ||||||
|         bc.isolated_world = null; |  | ||||||
|     } |     } | ||||||
|  |     bc.isolated_worlds.clearRetainingCapacity(); | ||||||
|     bc.target_id = null; |     bc.target_id = null; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Pierre Tachoire
					Pierre Tachoire