diff --git a/src/browser/Frame.zig b/src/browser/Frame.zig index d537c2df6..9a8165081 100644 --- a/src/browser/Frame.zig +++ b/src/browser/Frame.zig @@ -3295,10 +3295,13 @@ fn nodeIsReady(self: *Frame, comptime from_parser: bool, node: *Node) !void { // Scripts, iframes, links and styles activate on becoming connected; // appending them to a detached parent does nothing (they run/load later // if the subtree gets inserted into the document). - if (comptime from_parser == false) { - switch (node._type) { - .element => if (!node.isConnected()) return, - else => {}, + if (node._type == .element) { + if (comptime from_parser) { + if (node.getDocument(self)._frame == null) { + return; + } + } else if (!node.isConnected()) { + return; } } diff --git a/src/browser/frame/node_factory.zig b/src/browser/frame/node_factory.zig index edd716983..8774c7d07 100644 --- a/src/browser/frame/node_factory.zig +++ b/src/browser/frame/node_factory.zig @@ -38,7 +38,7 @@ const String = lp.String; const IFrame = Element.Html.IFrame; pub fn createElementNS(document: *const Node.Document, namespace: Element.Namespace, name: []const u8, attribute_iterator: anytype) !*Node { - const from_parser = @TypeOf(attribute_iterator) == Parser.AttributeIterator; + const from_parser = @TypeOf(attribute_iterator) == Parser.AttributeIterator or @TypeOf(attribute_iterator) == Parser.RebuiltAttributes; const from_clone = @TypeOf(attribute_iterator) == *Element.Attribute.List or @TypeOf(attribute_iterator) == *const Element.Attribute.List; const frame = frameOf(document); @@ -849,6 +849,7 @@ pub fn createElementNS(document: *const Node.Document, namespace: Element.Namesp const node = try createHtmlElementT(document, Element.Html.Custom, namespace, attribute_iterator, .{ ._tag_name = tag_name, ._definition = definition, + ._upgrade_candidate = creation == .construct, }); if (creation == .construct) { try realm._undefined_custom_elements.append(realm.arena, node.as(Element).is(Element.Html.Custom).?); @@ -1070,7 +1071,7 @@ fn createHtmlElementT(document: *const Node.Document, comptime E: type, namespac const node = element.asNode(); if (@hasDecl(E, "Build") and @hasDecl(E.Build, "created")) { - if (comptime @TypeOf(attribute_iterator) == Parser.AttributeIterator and @hasDecl(E.Build, "parser_created_on_insert")) { + if (comptime (@TypeOf(attribute_iterator) == Parser.AttributeIterator or @TypeOf(attribute_iterator) == Parser.RebuiltAttributes) and @hasDecl(E.Build, "parser_created_on_insert")) { // The element wants its parent, it'll do this work when inserted. return node; } @@ -1120,6 +1121,13 @@ fn populateElementAttributes(frame: *Frame, element: *Element, list: anytype) !v return; } + if (@TypeOf(list) == Parser.RebuiltAttributes) { + // from the parser, rebuilding an element in another document + try element._attributes.cloneFrom(list.list, frame); + element.noteStyleAttribute(); + return; + } + // from the parser if (@TypeOf(list) == @TypeOf(null)) { return; diff --git a/src/browser/parser/Parser.zig b/src/browser/parser/Parser.zig index 747b569b9..286b2d7cb 100644 --- a/src/browser/parser/Parser.zig +++ b/src/browser/parser/Parser.zig @@ -42,6 +42,17 @@ pub const ParsedNode = struct { // html5ever should never ask us for this data on a non-element, and we'll // assert that, with this optional, to make sure our assumption is correct. data: ?*anyopaque, + + // Set once html5ever has put the node in the tree or given it children. + // Until then the node is unobservable and its document is only a guess. + placed: bool = false, +}; + +// Attributes of an element the parser rebuilds (see settleDocument): the ones +// html5ever gave the original, read back from it. node_factory treats this +// like AttributeIterator, i.e. as a creation by the parser. +pub const RebuiltAttributes = struct { + list: *const Element.Attribute.List, }; // html5ever's tokenizer flushes the script-data character buffer on every '<' @@ -63,6 +74,13 @@ err: ?Error, arena: Allocator, container: ParsedNode, document: *Node.Document, +// The document new nodes are created in. The spec creates an element for a +// token in its intended parent's document, and a