mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-07-31 09:46:05 -04:00
cleanup: Mechanical move various frame.parse* method
Follows the observer, user_input, etc.. pattern and relocates various `Frame.parse*` methods into Frame.parse.* functions. Goal is just to keep Frame neat.
This commit is contained in:
@@ -73,6 +73,7 @@ const milliTimestamp = @import("../datetime.zig").milliTimestamp;
|
||||
|
||||
const GlobalEventHandlersLookup = @import("webapi/global_event_handlers.zig").Lookup;
|
||||
|
||||
pub const parse = @import("frame/parse.zig");
|
||||
pub const preload = @import("frame/preload.zig");
|
||||
pub const observers = @import("frame/observers.zig");
|
||||
pub const user_input = @import("frame/user_input.zig");
|
||||
@@ -2867,113 +2868,6 @@ pub fn updateRangesForNodeRemoval(self: *Frame, parent: *Node, child: *Node, chi
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: optimize and cleanup, this is called a lot (e.g., innerHTML = '')
|
||||
pub fn parseHtmlAsChildren(self: *Frame, node: *Node, html: []const u8) !void {
|
||||
return self.parseHtmlAsChildrenInner(node, html, .{});
|
||||
}
|
||||
|
||||
// setHTMLUnsafe variant: parse a fragment that may contain declarative shadow node
|
||||
pub fn parseHtmlUnsafeAsChildren(self: *Frame, node: *Node, html: []const u8) !void {
|
||||
return self.parseHtmlAsChildrenInner(node, html, .{ .allow_declarative_shadow = true });
|
||||
}
|
||||
|
||||
// Range.createContextualFragment variant: unlike innerHTML et al., its scripts
|
||||
// are run when the fragment is inserted into a document.
|
||||
pub fn parseContextualFragment(self: *Frame, node: *Node, html: []const u8) !void {
|
||||
return self.parseHtmlAsChildrenInner(node, html, .{ .scripts_runnable = true });
|
||||
}
|
||||
|
||||
const FragmentParseOpts = struct {
|
||||
scripts_runnable: bool = false,
|
||||
allow_declarative_shadow: bool = false,
|
||||
};
|
||||
|
||||
fn parseHtmlAsChildrenInner(self: *Frame, node: *Node, html: []const u8, opts: FragmentParseOpts) !void {
|
||||
const previous_parse_mode = self._parse_mode;
|
||||
self._parse_mode = .fragment;
|
||||
defer self._parse_mode = previous_parse_mode;
|
||||
|
||||
// The html5ever wrapper-unwrap below rebinds children without going
|
||||
// through the insertion path, so recompute slot assignments for any
|
||||
// shadow tree this fragment landed in (idempotent; signals only on diff).
|
||||
defer if (self._element_shadow_roots.count() != 0) {
|
||||
const root = node.getRootNode(.{});
|
||||
if (root.is(ShadowRoot) != null) {
|
||||
slotting.assignSlottablesForTree(root, self);
|
||||
}
|
||||
if (node.is(Element)) |el| {
|
||||
if (self._element_shadow_roots.get(el)) |shadow_root| {
|
||||
slotting.assignSlottablesForTree(shadow_root.asNode(), self);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const previous_scripts_runnable = self._fragment_scripts_runnable;
|
||||
self._fragment_scripts_runnable = opts.scripts_runnable;
|
||||
defer self._fragment_scripts_runnable = previous_scripts_runnable;
|
||||
|
||||
var parser = Parser.init(self.call_arena, node, self, .{ .allow_declarative_shadow = opts.allow_declarative_shadow });
|
||||
parser.parseFragment(html);
|
||||
if (parser.terminated) {
|
||||
return error.ExecutionTerminated;
|
||||
}
|
||||
|
||||
// html5ever wraps fragment output in an <html> element; unwrap so its
|
||||
// children land directly on `node`. See https://github.com/servo/html5ever/issues/583.
|
||||
// Because of custom element callbacks, the structure might not be what
|
||||
// we expect, and nodes might be altogether removed. We deal with this in a
|
||||
// few different places, but always the same way: leave it as-is.
|
||||
const children = node._children orelse return;
|
||||
const first = Node.linkToNode(children.first.?);
|
||||
if (first.is(Element.Html.Html) == null) {
|
||||
return;
|
||||
}
|
||||
node._children = first._children;
|
||||
|
||||
// No mutation records for the unwrapped children either; see the comment
|
||||
// about fragment parses in _insertNodeRelative.
|
||||
var it = node.childrenIterator();
|
||||
while (it.next()) |child| {
|
||||
child._parent = node;
|
||||
}
|
||||
}
|
||||
|
||||
// Build a detached XMLDocument from `xml` (DOMParser.parseFromString and
|
||||
// XMLHttpRequest.responseXML). Returns null when the input isn't well-formed
|
||||
// XML. The parse borrows the fragment parse-mode so frame-side hooks triggered
|
||||
// from `Build.created` / `nodeIsReady` (external stylesheet fetches, script
|
||||
// execution, mutation-observer fan-out, default-script injection) treat the
|
||||
// parsed nodes as detached and skip side effects on the live document.
|
||||
pub fn parseXmlDocument(self: *Frame, xml: []const u8) !?*Document.XMLDocument {
|
||||
const arena = try self.getArena(.medium, "Frame.parseXmlDocument");
|
||||
defer self.releaseArena(arena);
|
||||
|
||||
const previous_parse_mode = self._parse_mode;
|
||||
self._parse_mode = .fragment;
|
||||
defer self._parse_mode = previous_parse_mode;
|
||||
|
||||
const doc = try self._factory.document(Document.XMLDocument{ ._proto = undefined });
|
||||
const doc_node = doc.asNode();
|
||||
var parser = Parser.init(arena, doc_node, self, .{});
|
||||
parser.parseXML(xml);
|
||||
if (parser.terminated) {
|
||||
return error.ExecutionTerminated;
|
||||
}
|
||||
|
||||
if (parser.err != null or doc_node.firstChild() == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// If first node is a `ProcessingInstruction` (e.g. the <?xml?>
|
||||
// declaration), skip it.
|
||||
const first_child = doc_node.firstChild().?;
|
||||
if (first_child.getNodeType() == 7) {
|
||||
_ = try doc_node.removeChild(first_child, self);
|
||||
}
|
||||
|
||||
return doc;
|
||||
}
|
||||
|
||||
// Runs the "ready" work for an inserted node and, when it's an element with
|
||||
// children, for its descendants in tree order: appending a subtree
|
||||
// containing scripts must execute them all, after the whole insertion.
|
||||
|
||||
@@ -282,7 +282,7 @@ fn testForms(html: []const u8) ![]FormInfo {
|
||||
|
||||
const doc = frame.window._document;
|
||||
const div = try doc.createElement("div", null, frame);
|
||||
try frame.parseHtmlAsChildren(div.asNode(), html);
|
||||
try Frame.parse.htmlAsChildren(frame, div.asNode(), html);
|
||||
|
||||
return collectForms(frame.call_arena, div.asNode(), frame);
|
||||
}
|
||||
|
||||
129
src/browser/frame/parse.zig
Normal file
129
src/browser/frame/parse.zig
Normal file
@@ -0,0 +1,129 @@
|
||||
// Copyright (C) 2023-2026 Lightpanda (Selecy SAS)
|
||||
//
|
||||
// Francis Bouvier <francis@lightpanda.io>
|
||||
// Pierre Tachoire <pierre@lightpanda.io>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as
|
||||
// published by the Free Software Foundation, either version 3 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const Frame = @import("../Frame.zig");
|
||||
const Parser = @import("../parser/Parser.zig");
|
||||
|
||||
const Node = @import("../webapi/Node.zig");
|
||||
const Element = @import("../webapi/Element.zig");
|
||||
const Document = @import("../webapi/Document.zig");
|
||||
const ShadowRoot = @import("../webapi/ShadowRoot.zig");
|
||||
const slotting = @import("../webapi/element/slotting.zig");
|
||||
|
||||
pub fn htmlAsChildren(frame: *Frame, node: *Node, html: []const u8) !void {
|
||||
return htmlAsChildrenInner(frame, node, html, .{});
|
||||
}
|
||||
|
||||
// setHTMLUnsafe variant: parse a fragment that may contain declarative shadow node
|
||||
pub fn htmlUnsafeAsChildren(frame: *Frame, node: *Node, html: []const u8) !void {
|
||||
return htmlAsChildrenInner(frame, node, html, .{ .allow_declarative_shadow = true });
|
||||
}
|
||||
|
||||
// Range.createContextualFragment variant: unlike innerHTML et al., its scripts
|
||||
// are run when the fragment is inserted into a document.
|
||||
pub fn contextualFragment(frame: *Frame, node: *Node, html: []const u8) !void {
|
||||
return htmlAsChildrenInner(frame, node, html, .{ .scripts_runnable = true });
|
||||
}
|
||||
|
||||
const FragmentParseOpts = struct {
|
||||
scripts_runnable: bool = false,
|
||||
allow_declarative_shadow: bool = false,
|
||||
};
|
||||
|
||||
fn htmlAsChildrenInner(frame: *Frame, node: *Node, html: []const u8, opts: FragmentParseOpts) !void {
|
||||
const previous_parse_mode = frame._parse_mode;
|
||||
frame._parse_mode = .fragment;
|
||||
defer frame._parse_mode = previous_parse_mode;
|
||||
|
||||
// The html5ever wrapper-unwrap below rebinds children without going
|
||||
// through the insertion path, so recompute slot assignments for any
|
||||
// shadow tree this fragment landed in (idempotent; signals only on diff).
|
||||
defer if (frame._element_shadow_roots.count() != 0) {
|
||||
const root = node.getRootNode(.{});
|
||||
if (root.is(ShadowRoot) != null) {
|
||||
slotting.assignSlottablesForTree(root, frame);
|
||||
}
|
||||
if (node.is(Element)) |el| {
|
||||
if (frame._element_shadow_roots.get(el)) |shadow_root| {
|
||||
slotting.assignSlottablesForTree(shadow_root.asNode(), frame);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const previous_scripts_runnable = frame._fragment_scripts_runnable;
|
||||
frame._fragment_scripts_runnable = opts.scripts_runnable;
|
||||
defer frame._fragment_scripts_runnable = previous_scripts_runnable;
|
||||
|
||||
var parser = Parser.init(frame.call_arena, node, frame, .{ .allow_declarative_shadow = opts.allow_declarative_shadow });
|
||||
parser.parseFragment(html);
|
||||
if (parser.terminated) {
|
||||
return error.ExecutionTerminated;
|
||||
}
|
||||
|
||||
// html5ever wraps fragment output in an <html> element; unwrap so its
|
||||
// children land directly on `node`. See https://github.com/servo/html5ever/issues/583.
|
||||
// Because of custom element callbacks, the structure might not be what
|
||||
// we expect, and nodes might be altogether removed. We deal with this in a
|
||||
// few different places, but always the same way: leave it as-is.
|
||||
const children = node._children orelse return;
|
||||
const first = Node.linkToNode(children.first.?);
|
||||
if (first.is(Element.Html.Html) == null) {
|
||||
return;
|
||||
}
|
||||
node._children = first._children;
|
||||
|
||||
// No mutation records for the unwrapped children either; see the comment
|
||||
// about fragment parses in _insertNodeRelative.
|
||||
var it = node.childrenIterator();
|
||||
while (it.next()) |child| {
|
||||
child._parent = node;
|
||||
}
|
||||
}
|
||||
|
||||
// Build a detached XMLDocument from `xml` (DOMParser.parseFromString and
|
||||
// XMLHttpRequest.responseXML). Returns null when the input isn't well-formed
|
||||
// XML.
|
||||
pub fn xmlDocument(frame: *Frame, xml: []const u8) !?*Document.XMLDocument {
|
||||
const arena = try frame.getArena(.medium, "parse.xmlDocument");
|
||||
defer frame.releaseArena(arena);
|
||||
|
||||
const previous_parse_mode = frame._parse_mode;
|
||||
frame._parse_mode = .fragment;
|
||||
defer frame._parse_mode = previous_parse_mode;
|
||||
|
||||
const doc = try frame._factory.document(Document.XMLDocument{ ._proto = undefined });
|
||||
const doc_node = doc.asNode();
|
||||
var parser = Parser.init(arena, doc_node, frame, .{});
|
||||
parser.parseXML(xml);
|
||||
if (parser.terminated) {
|
||||
return error.ExecutionTerminated;
|
||||
}
|
||||
|
||||
if (parser.err != null or doc_node.firstChild() == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// If first node is a `ProcessingInstruction` (e.g. the <?xml?>
|
||||
// declaration), skip it.
|
||||
const first_child = doc_node.firstChild().?;
|
||||
if (first_child.getNodeType() == 7) {
|
||||
_ = try doc_node.removeChild(first_child, frame);
|
||||
}
|
||||
|
||||
return doc;
|
||||
}
|
||||
@@ -501,7 +501,7 @@ fn testInteractive(html: []const u8) ![]InteractiveElement {
|
||||
|
||||
const doc = frame.window._document;
|
||||
const div = try doc.createElement("div", null, frame);
|
||||
try frame.parseHtmlAsChildren(div.asNode(), html);
|
||||
try Frame.parse.htmlAsChildren(frame, div.asNode(), html);
|
||||
|
||||
return collectInteractiveElements(div.asNode(), frame.call_arena, frame);
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ fn testLinks(html: []const u8) ![]Link {
|
||||
|
||||
const doc = frame.window._document;
|
||||
const div = try doc.createElement("div", null, frame);
|
||||
try frame.parseHtmlAsChildren(div.asNode(), html);
|
||||
try Frame.parse.htmlAsChildren(frame, div.asNode(), html);
|
||||
|
||||
return collectLinks(frame.call_arena, div.asNode(), frame);
|
||||
}
|
||||
|
||||
@@ -599,7 +599,7 @@ fn testMarkdownHTML(html: []const u8, expected: []const u8) !void {
|
||||
const doc = frame.window._document;
|
||||
|
||||
const div = try doc.createElement("div", null, frame);
|
||||
try frame.parseHtmlAsChildren(div.asNode(), html);
|
||||
try Frame.parse.htmlAsChildren(frame, div.asNode(), html);
|
||||
|
||||
var aw: std.Io.Writer.Allocating = .init(testing.allocator);
|
||||
defer aw.deinit();
|
||||
@@ -800,7 +800,7 @@ test "browser.markdown: resolve links" {
|
||||
|
||||
const doc = frame.window._document;
|
||||
const div = try doc.createElement("div", null, frame);
|
||||
try frame.parseHtmlAsChildren(div.asNode(),
|
||||
try Frame.parse.htmlAsChildren(frame, div.asNode(),
|
||||
\\<a href="b">Link</a>
|
||||
\\<img src="../c.png" alt="Img">
|
||||
\\<a href="/my page">Space</a>
|
||||
@@ -839,7 +839,7 @@ test "browser.markdown: max_bytes leaves output untouched when under cap" {
|
||||
|
||||
const doc = frame.window._document;
|
||||
const div = try doc.createElement("div", null, frame);
|
||||
try frame.parseHtmlAsChildren(div.asNode(), "<p>Short</p>");
|
||||
try Frame.parse.htmlAsChildren(frame, div.asNode(), "<p>Short</p>");
|
||||
|
||||
var aw: std.Io.Writer.Allocating = .init(testing.allocator);
|
||||
defer aw.deinit();
|
||||
@@ -855,7 +855,7 @@ test "browser.markdown: max_bytes truncates with marker" {
|
||||
|
||||
const doc = frame.window._document;
|
||||
const div = try doc.createElement("div", null, frame);
|
||||
try frame.parseHtmlAsChildren(div.asNode(), "<p>" ++ ("AAAA " ** 100) ++ "</p>");
|
||||
try Frame.parse.htmlAsChildren(frame, div.asNode(), "<p>" ++ ("AAAA " ** 100) ++ "</p>");
|
||||
|
||||
var aw: std.Io.Writer.Allocating = .init(testing.allocator);
|
||||
defer aw.deinit();
|
||||
@@ -878,11 +878,11 @@ fn testMarkdownShadow(light: []const u8, shadow: []const u8, expected: []const u
|
||||
|
||||
const host = try doc.createElement("div", null, frame);
|
||||
if (light.len > 0) {
|
||||
try frame.parseHtmlAsChildren(host.asNode(), light);
|
||||
try Frame.parse.htmlAsChildren(frame, host.asNode(), light);
|
||||
}
|
||||
|
||||
const sr = try host.attachShadow(.{ .mode = .open }, frame);
|
||||
try frame.parseHtmlAsChildren(sr.asNode(), shadow);
|
||||
try Frame.parse.htmlAsChildren(frame, sr.asNode(), shadow);
|
||||
|
||||
var aw: std.Io.Writer.Allocating = .init(testing.allocator);
|
||||
defer aw.deinit();
|
||||
|
||||
@@ -494,7 +494,7 @@ fn testStructuredData(html: []const u8) !StructuredData {
|
||||
|
||||
const doc = frame.window._document;
|
||||
const div = try doc.createElement("div", null, frame);
|
||||
try frame.parseHtmlAsChildren(div.asNode(), html);
|
||||
try Frame.parse.htmlAsChildren(frame, div.asNode(), html);
|
||||
|
||||
return collectStructuredData(div.asNode(), frame.call_arena, frame);
|
||||
}
|
||||
@@ -714,7 +714,7 @@ test "structured_data: link headers from response" {
|
||||
|
||||
const doc = frame.window._document;
|
||||
const div = try doc.createElement("div", null, frame);
|
||||
try frame.parseHtmlAsChildren(div.asNode(), "<title>Example</title>");
|
||||
try Frame.parse.htmlAsChildren(frame, div.asNode(), "<title>Example</title>");
|
||||
|
||||
const data = try collectStructuredData(div.asNode(), frame.call_arena, frame);
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<body>
|
||||
<script src="../testing.js"></script>
|
||||
|
||||
<!-- Frame.parseHtmlAsChildren extracts children from the temporary
|
||||
<!-- Frame.parse.htmlAsChildren extracts children from the temporary
|
||||
<html> element the fragment parser leaves at the top of the parse
|
||||
result. A custom element's connectedCallback fires synchronously
|
||||
during that parse, so it can reach two levels up (this.parentNode is
|
||||
|
||||
@@ -55,7 +55,7 @@ pub fn parseFromString(
|
||||
defer frame.releaseArena(arena);
|
||||
|
||||
// DOMParser builds a detached Document. Borrow the same fragment
|
||||
// parse-mode that `parseHtmlAsChildren` uses so frame-side hooks
|
||||
// parse-mode that `Frame.parse` uses so frame-side hooks
|
||||
// triggered from `Build.created` / `nodeIsReady` (external
|
||||
// stylesheet fetches, script execution, mutation-observer fan-out,
|
||||
// default-script injection) treat the parsed nodes as detached and
|
||||
@@ -89,9 +89,9 @@ pub fn parseFromString(
|
||||
return doc.asDocument();
|
||||
},
|
||||
else => {
|
||||
const doc = (try frame.parseXmlDocument(html)) orelse blk: {
|
||||
const doc = (try Frame.parse.xmlDocument(frame, html)) orelse blk: {
|
||||
// Return a document with a <parsererror> element per spec.
|
||||
break :blk (try frame.parseXmlDocument("<parsererror xmlns=\"http://www.mozilla.org/newlayout/xml/parsererror.xml\">error</parsererror>")).?;
|
||||
break :blk (try Frame.parse.xmlDocument(frame, "<parsererror xmlns=\"http://www.mozilla.org/newlayout/xml/parsererror.xml\">error</parsererror>")).?;
|
||||
};
|
||||
return doc.asDocument();
|
||||
},
|
||||
|
||||
@@ -484,7 +484,7 @@ pub fn setOuterHTML(self: *Element, html: []const u8, frame: *Frame) !void {
|
||||
var fragment: ?*Node = null;
|
||||
if (html.len > 0) {
|
||||
const frag = (try Node.DocumentFragment.init(frame)).asNode();
|
||||
try frame.parseHtmlAsChildren(frag, html);
|
||||
try Frame.parse.htmlAsChildren(frame, frag, html);
|
||||
fragment = frag;
|
||||
}
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ pub fn setBody(self: *HTMLDocument, html: []const u8, frame: *Frame) !void {
|
||||
// parsing strips any <html>/<body>/<head> wrappers the author included.
|
||||
const new_body_node = try Frame.node_factory.createElementNS(frame, .html, "body", null);
|
||||
if (html.len > 0) {
|
||||
try frame.parseHtmlAsChildren(new_body_node, html);
|
||||
try Frame.parse.htmlAsChildren(frame, new_body_node, html);
|
||||
}
|
||||
|
||||
const document_node = document_element.asNode();
|
||||
|
||||
@@ -1557,9 +1557,9 @@ pub fn setHTML(self: *Node, html: []const u8, allow_declarative_shadow: bool, fr
|
||||
|
||||
if (html.len > 0) {
|
||||
if (allow_declarative_shadow) {
|
||||
try frame.parseHtmlUnsafeAsChildren(self, html);
|
||||
try Frame.parse.htmlUnsafeAsChildren(frame, self, html);
|
||||
} else {
|
||||
try frame.parseHtmlAsChildren(self, html);
|
||||
try Frame.parse.htmlAsChildren(frame, self, html);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -703,7 +703,7 @@ pub fn createContextualFragment(self: *const Range, html: []const u8, frame: *Fr
|
||||
else
|
||||
try Frame.node_factory.createElementNS(frame, .html, "div", null);
|
||||
|
||||
try frame.parseContextualFragment(temp_node, html);
|
||||
try Frame.parse.contextualFragment(frame, temp_node, html);
|
||||
|
||||
// Move all parsed children to the fragment
|
||||
// Keep removing first child until temp element is empty
|
||||
|
||||
@@ -290,7 +290,7 @@ pub fn insertAdjacentHTML(
|
||||
) !void {
|
||||
const DocumentFragment = @import("../DocumentFragment.zig");
|
||||
const fragment = (try DocumentFragment.init(frame)).asNode();
|
||||
try frame.parseHtmlAsChildren(fragment, html);
|
||||
try Frame.parse.htmlAsChildren(frame, fragment, html);
|
||||
|
||||
const target_node, const prev_node = try self.asNode().findAdjacentNodes(position, .html);
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ const Transfer = @import("../../../network/HttpClient.zig").Transfer;
|
||||
const URL = @import("../../URL.zig");
|
||||
const Mime = @import("../../Mime.zig");
|
||||
const Page = @import("../../Page.zig");
|
||||
const Frame = @import("../../Frame.zig");
|
||||
|
||||
const Node = @import("../Node.zig");
|
||||
const Event = @import("../Event.zig");
|
||||
@@ -438,14 +439,14 @@ pub fn getResponse(self: *XMLHttpRequest, exec: *const Execution) !?Response {
|
||||
.frame => |frame| {
|
||||
const final: Mime = self._override_mime orelse self._response_mime orelse .{ .content_type = .text_xml };
|
||||
if (final.isXML()) {
|
||||
const document = (try frame.parseXmlDocument(data)) orelse return null;
|
||||
const document = (try Frame.parse.xmlDocument(frame, data)) orelse return null;
|
||||
break :blk .{ .document = document.asDocument() };
|
||||
}
|
||||
if (!final.isHTML()) {
|
||||
return null;
|
||||
}
|
||||
const document = try exec._factory.node(Node.Document{ ._proto = undefined, ._type = .generic });
|
||||
try frame.parseHtmlAsChildren(document.asNode(), data);
|
||||
try Frame.parse.htmlAsChildren(frame, document.asNode(), data);
|
||||
break :blk .{ .document = document };
|
||||
},
|
||||
.worker => return error.NotSupportedInWorker,
|
||||
@@ -487,7 +488,7 @@ pub fn getResponseXML(self: *XMLHttpRequest, exec: *const Execution) !?*Node.Doc
|
||||
|
||||
switch (exec.js.global) {
|
||||
.frame => |frame| {
|
||||
const xml_document = (try frame.parseXmlDocument(self._response_data.items)) orelse return null;
|
||||
const xml_document = (try Frame.parse.xmlDocument(frame, self._response_data.items)) orelse return null;
|
||||
const document = xml_document.asDocument();
|
||||
self._response_xml = document;
|
||||
return document;
|
||||
|
||||
Reference in New Issue
Block a user