|
56 | 56 | #include <LibWeb/DOM/Attr.h> |
57 | 57 | #include <LibWeb/DOM/DOMTokenList.h> |
58 | 58 | #include <LibWeb/DOM/Document.h> |
| 59 | +#include <LibWeb/DOM/DocumentFragment.h> |
59 | 60 | #include <LibWeb/DOM/Element.h> |
60 | 61 | #include <LibWeb/DOM/ElementFactory.h> |
61 | 62 | #include <LibWeb/DOM/HTMLCollection.h> |
@@ -1534,27 +1535,29 @@ WebIDL::ExceptionOr<void> Element::set_inner_html(TrustedTypes::TrustedHTMLOrStr |
1534 | 1535 | TrustedTypes::InjectionSink::Element_innerHTML, |
1535 | 1536 | TrustedTypes::Script.to_string())); |
1536 | 1537 |
|
1537 | | - // 2. Let context be this. |
1538 | | - DOM::Node* context = this; |
| 1538 | + // 2. Let target be this. |
| 1539 | + Variant<GC::Ref<Element>, GC::Ref<DocumentFragment>> target = GC::Ref { *this }; |
1539 | 1540 |
|
1540 | | - // 3. Let fragment be the result of invoking the fragment parsing algorithm steps with context and compliantString. |
1541 | | - auto fragment = TRY(as<Element>(*context).parse_fragment(compliant_string.to_utf8_but_should_be_ported_to_utf16())); |
1542 | | - |
1543 | | - // 4. If context is a template element, then set context to the template element's template contents (a DocumentFragment). |
1544 | | - auto* template_element = as_if<HTML::HTMLTemplateElement>(*context); |
| 1541 | + // 3. If target is a template element, then set target to the template element's template contents (a DocumentFragment). |
| 1542 | + auto* template_element = as_if<HTML::HTMLTemplateElement>(*this); |
1545 | 1543 | if (template_element) |
1546 | | - context = template_element->content(); |
| 1544 | + target = template_element->content(); |
| 1545 | + |
| 1546 | + // 4. Let fragment be the result of invoking the fragment parsing algorithm steps with target and compliantString. |
| 1547 | + auto fragment = TRY(parse_fragment(target, compliant_string.to_utf8_but_should_be_ported_to_utf16())); |
1547 | 1548 |
|
1548 | | - // 5. Replace all with fragment within context. |
1549 | | - context->replace_all(fragment); |
| 1549 | + // 5. Replace all with fragment within target. |
| 1550 | + target.visit([&](auto node) { |
| 1551 | + node->replace_all(fragment); |
| 1552 | + }); |
1550 | 1553 |
|
1551 | 1554 | // NOTE: We don't invalidate style & layout for <template> elements since they don't affect rendering. |
1552 | 1555 | if (!template_element) { |
1553 | | - context->set_needs_style_update(true); |
| 1556 | + set_needs_style_update(true); |
1554 | 1557 |
|
1555 | | - if (context->is_connected()) { |
| 1558 | + if (is_connected()) { |
1556 | 1559 | // NOTE: Since the DOM has changed, we have to rebuild the layout tree. |
1557 | | - context->set_needs_layout_tree_update(true, DOM::SetNeedsLayoutTreeUpdateReason::ElementSetInnerHTML); |
| 1560 | + set_needs_layout_tree_update(true, DOM::SetNeedsLayoutTreeUpdateReason::ElementSetInnerHTML); |
1558 | 1561 | } |
1559 | 1562 | } |
1560 | 1563 |
|
@@ -2661,32 +2664,18 @@ bool Element::is_actually_disabled() const |
2661 | 2664 | } |
2662 | 2665 |
|
2663 | 2666 | // https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#fragment-parsing-algorithm-steps |
2664 | | -WebIDL::ExceptionOr<GC::Ref<DOM::DocumentFragment>> Element::parse_fragment(StringView markup, HTML::ParserScriptingMode scripting_mode) |
| 2667 | +WebIDL::ExceptionOr<GC::Ref<DOM::DocumentFragment>> Element::parse_fragment(Variant<GC::Ref<Element>, GC::Ref<DocumentFragment>> target, StringView markup, HTML::ParserScriptingMode scripting_mode) |
2665 | 2668 | { |
2666 | 2669 | // 1. Assert: scriptingMode is either Inert or Fragment. |
2667 | 2670 | VERIFY(scripting_mode == HTML::ParserScriptingMode::Inert || scripting_mode == HTML::ParserScriptingMode::Fragment); |
2668 | 2671 |
|
2669 | | - // 2. Let newChildren be null. |
2670 | | - Vector<GC::Root<Node>> new_children; |
2671 | | - |
2672 | | - // 3. If context's node document is an XML document, then set newChildren to the result of invoking the XML fragment parsing algorithm given context and markup. |
2673 | | - if (document().is_xml_document()) { |
2674 | | - new_children = TRY(XMLFragmentParser::parse_xml_fragment(*this, markup)); |
2675 | | - } |
2676 | | - // 4. Otherwise, set newChildren to the result of invoking the HTML fragment parsing algorithm given context, markup, false, and scriptingMode. |
2677 | | - else { |
2678 | | - new_children = TRY(HTML::HTMLParser::parse_html_fragment(*this, markup, HTML::HTMLParser::AllowDeclarativeShadowRoots::No, scripting_mode)); |
2679 | | - } |
2680 | | - |
2681 | | - // 5. Let fragment be a new DocumentFragment whose node document is context's node document. |
2682 | | - auto fragment = realm().create<DOM::DocumentFragment>(document()); |
2683 | | - |
2684 | | - // 6. For each node of newChildren, in tree order: append node to fragment. |
2685 | | - for (auto& child : new_children) |
2686 | | - TRY(fragment->append_child(*child)); |
| 2672 | + // 2. If target's node document is an XML document, then return the result of invoking the XML fragment parsing |
| 2673 | + // algorithm given target and markup. |
| 2674 | + if (target.visit([](auto node) { return node->document().is_xml_document(); })) |
| 2675 | + return XMLFragmentParser::parse_xml_fragment(target, markup); |
2687 | 2676 |
|
2688 | | - // 7. Return fragment. |
2689 | | - return fragment; |
| 2677 | + // 3. Return the result of invoking the HTML fragment parsing algorithm given context, markup, false, and scriptingMode. |
| 2678 | + return HTML::HTMLParser::parse_html_fragment(target, markup, HTML::HTMLParser::AllowDeclarativeShadowRoots::No, scripting_mode); |
2690 | 2679 | } |
2691 | 2680 |
|
2692 | 2681 | // https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#dom-element-outerhtml |
@@ -2723,7 +2712,7 @@ WebIDL::ExceptionOr<void> Element::set_outer_html(TrustedTypes::TrustedHTMLOrStr |
2723 | 2712 | parent = TRY(create_element(document(), HTML::TagNames::body, Namespace::HTML)); |
2724 | 2713 |
|
2725 | 2714 | // 6. Let fragment be the result of invoking the fragment parsing algorithm steps given parent and compliantString. |
2726 | | - auto fragment = TRY(as<Element>(*parent).parse_fragment(compliant_string.to_utf8_but_should_be_ported_to_utf16())); |
| 2715 | + auto fragment = TRY(Element::parse_fragment(GC::Ref { as<Element>(*parent) }, compliant_string.to_utf8_but_should_be_ported_to_utf16())); |
2727 | 2716 |
|
2728 | 2717 | // 6. Replace this with fragment within this's parent. |
2729 | 2718 | TRY(this->parent()->replace_child(fragment, *this)); |
@@ -2784,7 +2773,7 @@ WebIDL::ExceptionOr<void> Element::insert_adjacent_html(String const& position, |
2784 | 2773 | } |
2785 | 2774 |
|
2786 | 2775 | // 5. Let fragment be the result of invoking the fragment parsing algorithm steps with context and compliantString. |
2787 | | - auto fragment = TRY(as<Element>(*context).parse_fragment(compliant_string.to_utf8_but_should_be_ported_to_utf16())); |
| 2776 | + auto fragment = TRY(Element::parse_fragment(GC::Ref { as<Element>(*context) }, compliant_string.to_utf8_but_should_be_ported_to_utf16())); |
2788 | 2777 |
|
2789 | 2778 | // 6. Use the first matching item from this list: |
2790 | 2779 |
|
@@ -4888,12 +4877,12 @@ WebIDL::ExceptionOr<void> Element::set_html_unsafe(TrustedTypes::TrustedHTMLOrSt |
4888 | 4877 | TrustedTypes::Script.to_string())); |
4889 | 4878 |
|
4890 | 4879 | // 2. Let target be this's template contents if this is a template element; otherwise this. |
4891 | | - DOM::Node* target = this; |
| 4880 | + Variant<GC::Ref<DOM::Element>, GC::Ref<DOM::DocumentFragment>> target = GC::Ref { *this }; |
4892 | 4881 | if (is<HTML::HTMLTemplateElement>(*this)) |
4893 | | - target = as<HTML::HTMLTemplateElement>(*this).content().ptr(); |
| 4882 | + target = as<HTML::HTMLTemplateElement>(*this).content(); |
4894 | 4883 |
|
4895 | 4884 | // 3. Unsafe set HTML given target, this, and compliantHTML. |
4896 | | - TRY(target->unsafely_set_html(*this, compliant_html.to_utf8_but_should_be_ported_to_utf16())); |
| 4885 | + TRY(unsafely_set_html(target, compliant_html.to_utf8_but_should_be_ported_to_utf16())); |
4897 | 4886 |
|
4898 | 4887 | return {}; |
4899 | 4888 | } |
|
0 commit comments