|
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> |
@@ -1539,27 +1540,29 @@ WebIDL::ExceptionOr<void> Element::set_inner_html(TrustedTypes::TrustedHTMLOrStr |
1539 | 1540 | TrustedTypes::InjectionSink::Element_innerHTML, |
1540 | 1541 | TrustedTypes::Script.to_string())); |
1541 | 1542 |
|
1542 | | - // 2. Let context be this. |
1543 | | - DOM::Node* context = this; |
| 1543 | + // 2. Let target be this. |
| 1544 | + Variant<GC::Ref<Element>, GC::Ref<DocumentFragment>> target = GC::Ref { *this }; |
1544 | 1545 |
|
1545 | | - // 3. Let fragment be the result of invoking the fragment parsing algorithm steps with context and compliantString. |
1546 | | - auto fragment = TRY(as<Element>(*context).parse_fragment(compliant_string.utf16_view())); |
1547 | | - |
1548 | | - // 4. If context is a template element, then set context to the template element's template contents (a DocumentFragment). |
1549 | | - auto* template_element = as_if<HTML::HTMLTemplateElement>(*context); |
| 1546 | + // 3. If target is a template element, then set target to the template element's template contents (a DocumentFragment). |
| 1547 | + auto* template_element = as_if<HTML::HTMLTemplateElement>(*this); |
1550 | 1548 | if (template_element) |
1551 | | - context = template_element->content(); |
| 1549 | + target = template_element->content(); |
| 1550 | + |
| 1551 | + // 4. Let fragment be the result of invoking the fragment parsing algorithm steps with target and compliantString. |
| 1552 | + auto fragment = TRY(parse_fragment(target, compliant_string.utf16_view())); |
1552 | 1553 |
|
1553 | | - // 5. Replace all with fragment within context. |
1554 | | - context->replace_all(fragment); |
| 1554 | + // 5. Replace all with fragment within target. |
| 1555 | + target.visit([&](auto node) { |
| 1556 | + node->replace_all(fragment); |
| 1557 | + }); |
1555 | 1558 |
|
1556 | 1559 | // NOTE: We don't invalidate style & layout for <template> elements since they don't affect rendering. |
1557 | 1560 | if (!template_element) { |
1558 | | - context->set_needs_style_update(true); |
| 1561 | + set_needs_style_update(true); |
1559 | 1562 |
|
1560 | | - if (context->is_connected()) { |
| 1563 | + if (is_connected()) { |
1561 | 1564 | // NOTE: Since the DOM has changed, we have to rebuild the layout tree. |
1562 | | - context->set_needs_layout_tree_update(true, DOM::SetNeedsLayoutTreeUpdateReason::ElementSetInnerHTML); |
| 1565 | + set_needs_layout_tree_update(true, DOM::SetNeedsLayoutTreeUpdateReason::ElementSetInnerHTML); |
1563 | 1566 | } |
1564 | 1567 | } |
1565 | 1568 |
|
@@ -2666,32 +2669,18 @@ bool Element::is_actually_disabled() const |
2666 | 2669 | } |
2667 | 2670 |
|
2668 | 2671 | // https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#fragment-parsing-algorithm-steps |
2669 | | -WebIDL::ExceptionOr<GC::Ref<DOM::DocumentFragment>> Element::parse_fragment(Utf16View markup, HTML::ParserScriptingMode scripting_mode) |
| 2672 | +WebIDL::ExceptionOr<GC::Ref<DOM::DocumentFragment>> Element::parse_fragment(Variant<GC::Ref<Element>, GC::Ref<DocumentFragment>> target, Utf16View markup, HTML::ParserScriptingMode scripting_mode) |
2670 | 2673 | { |
2671 | 2674 | // 1. Assert: scriptingMode is either Inert or Fragment. |
2672 | 2675 | VERIFY(scripting_mode == HTML::ParserScriptingMode::Inert || scripting_mode == HTML::ParserScriptingMode::Fragment); |
2673 | 2676 |
|
2674 | | - // 2. Let newChildren be null. |
2675 | | - Vector<GC::Root<Node>> new_children; |
2676 | | - |
2677 | | - // 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. |
2678 | | - if (document().is_xml_document()) { |
2679 | | - new_children = TRY(XMLFragmentParser::parse_xml_fragment(*this, markup)); |
2680 | | - } |
2681 | | - // 4. Otherwise, set newChildren to the result of invoking the HTML fragment parsing algorithm given context, markup, false, and scriptingMode. |
2682 | | - else { |
2683 | | - new_children = TRY(HTML::HTMLParser::parse_html_fragment(*this, markup, HTML::HTMLParser::AllowDeclarativeShadowRoots::No, scripting_mode)); |
2684 | | - } |
2685 | | - |
2686 | | - // 5. Let fragment be a new DocumentFragment whose node document is context's node document. |
2687 | | - auto fragment = realm().create<DOM::DocumentFragment>(document()); |
2688 | | - |
2689 | | - // 6. For each node of newChildren, in tree order: append node to fragment. |
2690 | | - for (auto& child : new_children) |
2691 | | - TRY(fragment->append_child(*child)); |
| 2677 | + // 2. If target's node document is an XML document, then return the result of invoking the XML fragment parsing |
| 2678 | + // algorithm given target and markup. |
| 2679 | + if (target.visit([](auto node) { return node->document().is_xml_document(); })) |
| 2680 | + return XMLFragmentParser::parse_xml_fragment(target, markup); |
2692 | 2681 |
|
2693 | | - // 7. Return fragment. |
2694 | | - return fragment; |
| 2682 | + // 3. Return the result of invoking the HTML fragment parsing algorithm given context, markup, false, and scriptingMode. |
| 2683 | + return HTML::HTMLParser::parse_html_fragment(target, markup, HTML::HTMLParser::AllowDeclarativeShadowRoots::No, scripting_mode); |
2695 | 2684 | } |
2696 | 2685 |
|
2697 | 2686 | // https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#dom-element-outerhtml |
@@ -2728,7 +2717,7 @@ WebIDL::ExceptionOr<void> Element::set_outer_html(TrustedTypes::TrustedHTMLOrStr |
2728 | 2717 | parent = TRY(create_element(document(), HTML::TagNames::body, Namespace::HTML)); |
2729 | 2718 |
|
2730 | 2719 | // 6. Let fragment be the result of invoking the fragment parsing algorithm steps given parent and compliantString. |
2731 | | - auto fragment = TRY(as<Element>(*parent).parse_fragment(compliant_string.utf16_view())); |
| 2720 | + auto fragment = TRY(Element::parse_fragment(GC::Ref { as<Element>(*parent) }, compliant_string.utf16_view())); |
2732 | 2721 |
|
2733 | 2722 | // 6. Replace this with fragment within this's parent. |
2734 | 2723 | TRY(this->parent()->replace_child(fragment, *this)); |
@@ -2789,7 +2778,7 @@ WebIDL::ExceptionOr<void> Element::insert_adjacent_html(String const& position, |
2789 | 2778 | } |
2790 | 2779 |
|
2791 | 2780 | // 5. Let fragment be the result of invoking the fragment parsing algorithm steps with context and compliantString. |
2792 | | - auto fragment = TRY(as<Element>(*context).parse_fragment(compliant_string.utf16_view())); |
| 2781 | + auto fragment = TRY(Element::parse_fragment(GC::Ref { as<Element>(*context) }, compliant_string.utf16_view())); |
2793 | 2782 |
|
2794 | 2783 | // 6. Use the first matching item from this list: |
2795 | 2784 |
|
@@ -4893,12 +4882,12 @@ WebIDL::ExceptionOr<void> Element::set_html_unsafe(TrustedTypes::TrustedHTMLOrSt |
4893 | 4882 | TrustedTypes::Script.to_string())); |
4894 | 4883 |
|
4895 | 4884 | // 2. Let target be this's template contents if this is a template element; otherwise this. |
4896 | | - DOM::Node* target = this; |
| 4885 | + Variant<GC::Ref<DOM::Element>, GC::Ref<DOM::DocumentFragment>> target = GC::Ref { *this }; |
4897 | 4886 | if (is<HTML::HTMLTemplateElement>(*this)) |
4898 | | - target = as<HTML::HTMLTemplateElement>(*this).content().ptr(); |
| 4887 | + target = as<HTML::HTMLTemplateElement>(*this).content(); |
4899 | 4888 |
|
4900 | 4889 | // 3. Unsafe set HTML given target, this, and compliantHTML. |
4901 | | - TRY(target->unsafely_set_html(*this, compliant_html.utf16_view())); |
| 4890 | + TRY(unsafely_set_html(target, compliant_html.utf16_view())); |
4902 | 4891 |
|
4903 | 4892 | return {}; |
4904 | 4893 | } |
|
0 commit comments