mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-10-29 15:13:28 +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