diff --git a/src/browser/Frame.zig b/src/browser/Frame.zig index 16a03f23f..4e3a6de81 100644 --- a/src/browser/Frame.zig +++ b/src/browser/Frame.zig @@ -211,6 +211,12 @@ _customized_builtin_disconnected_callback_invoked: std.AutoHashMapUnmanaged(*Ele // The constructor can access this to get the element being upgraded. _upgrading_element: ?*Node = null, +// Set when materializing the fragment parser's context element. The element +// is never inserted into the tree so if its a custom element ,we must not run +// its constructor (else we'll end up in an endless loop if the constructor +// sets this.innerHTML = '...', which happens). +_skip_custom_element_upgrade: bool = false, + // List of custom elements that were created before their definition was registered _undefined_custom_elements: std.ArrayList(*Element.Html.Custom) = .{}, diff --git a/src/browser/frame/node_factory.zig b/src/browser/frame/node_factory.zig index 95dd36ec9..b93d4a36a 100644 --- a/src/browser/frame/node_factory.zig +++ b/src/browser/frame/node_factory.zig @@ -829,6 +829,12 @@ pub fn createElementNS(frame: *Frame, namespace: Element.Namespace, name: []cons ._definition = definition, }); + // Fragment-parse context element. It will not be inserted and + // we should not run the custom element's constructor. + if (frame._skip_custom_element_upgrade) { + return node; + } + const def = definition orelse { const element = node.as(Element); const custom = element.is(Element.Html.Custom).?; diff --git a/src/browser/parser/Parser.zig b/src/browser/parser/Parser.zig index 700dc5377..159dbe372 100644 --- a/src/browser/parser/Parser.zig +++ b/src/browser/parser/Parser.zig @@ -272,6 +272,7 @@ pub fn parseFragment(self: *Parser, html: []const u8) void { &self.container, self, createElementCallback, + createContextElementCallback, getDataCallback, appendCallback, parseErrorCallback, @@ -439,6 +440,25 @@ fn createXMLElementCallback(ctx: *anyopaque, data: *anyopaque, qname: h5e.QualNa return _createElementCallbackWithDefaultnamespace(ctx, data, qname, attributes, .xml); } +// html5ever_parse_fragment materializes the fragment's context element through +// this dedicated callback, never through createElementCallback. The context +// element is a throwaway: html5ever only queries its name (and, for a +//