|
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> |
@@ -1523,27 +1524,29 @@ WebIDL::ExceptionOr<void> Element::set_inner_html(TrustedTypes::TrustedHTMLOrStr |
1523 | 1524 | TrustedTypes::InjectionSink::Element_innerHTML, |
1524 | 1525 | TrustedTypes::Script.to_string())); |
1525 | 1526 |
|
1526 | | - // 2. Let context be this. |
1527 | | - DOM::Node* context = this; |
| 1527 | + // 2. Let target be this. |
| 1528 | + Variant<GC::Ref<Element>, GC::Ref<DocumentFragment>> target = GC::Ref { *this }; |
1528 | 1529 |
|
1529 | | - // 3. Let fragment be the result of invoking the fragment parsing algorithm steps with context and compliantString. |
1530 | | - auto fragment = TRY(as<Element>(*context).parse_fragment(compliant_string.utf16_view())); |
1531 | | - |
1532 | | - // 4. If context is a template element, then set context to the template element's template contents (a DocumentFragment). |
1533 | | - auto* template_element = as_if<HTML::HTMLTemplateElement>(*context); |
| 1530 | + // 3. If target is a template element, then set target to the template element's template contents (a DocumentFragment). |
| 1531 | + auto* template_element = as_if<HTML::HTMLTemplateElement>(*this); |
1534 | 1532 | if (template_element) |
1535 | | - context = template_element->content(); |
| 1533 | + target = template_element->content(); |
| 1534 | + |
| 1535 | + // 4. Let fragment be the result of invoking the fragment parsing algorithm steps with target and compliantString. |
| 1536 | + auto fragment = TRY(parse_fragment(target, compliant_string.utf16_view())); |
1536 | 1537 |
|
1537 | | - // 5. Replace all with fragment within context. |
1538 | | - context->replace_all(fragment); |
| 1538 | + // 5. Replace all with fragment within target. |
| 1539 | + target.visit([&](auto node) { |
| 1540 | + node->replace_all(fragment); |
| 1541 | + }); |
1539 | 1542 |
|
1540 | 1543 | // NOTE: We don't invalidate style & layout for <template> elements since they don't affect rendering. |
1541 | 1544 | if (!template_element) { |
1542 | | - context->set_needs_style_update(true); |
| 1545 | + set_needs_style_update(true); |
1543 | 1546 |
|
1544 | | - if (context->is_connected()) { |
| 1547 | + if (is_connected()) { |
1545 | 1548 | // NOTE: Since the DOM has changed, we have to rebuild the layout tree. |
1546 | | - context->set_needs_layout_tree_update(true, DOM::SetNeedsLayoutTreeUpdateReason::ElementSetInnerHTML); |
| 1549 | + set_needs_layout_tree_update(true, DOM::SetNeedsLayoutTreeUpdateReason::ElementSetInnerHTML); |
1547 | 1550 | } |
1548 | 1551 | } |
1549 | 1552 |
|
@@ -2650,32 +2653,18 @@ bool Element::is_actually_disabled() const |
2650 | 2653 | } |
2651 | 2654 |
|
2652 | 2655 | // https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#fragment-parsing-algorithm-steps |
2653 | | -WebIDL::ExceptionOr<GC::Ref<DOM::DocumentFragment>> Element::parse_fragment(Utf16View markup, HTML::ParserScriptingMode scripting_mode) |
| 2656 | +WebIDL::ExceptionOr<GC::Ref<DOM::DocumentFragment>> Element::parse_fragment(Variant<GC::Ref<Element>, GC::Ref<DocumentFragment>> target, Utf16View markup, HTML::ParserScriptingMode scripting_mode) |
2654 | 2657 | { |
2655 | 2658 | // 1. Assert: scriptingMode is either Inert or Fragment. |
2656 | 2659 | VERIFY(scripting_mode == HTML::ParserScriptingMode::Inert || scripting_mode == HTML::ParserScriptingMode::Fragment); |
2657 | 2660 |
|
2658 | | - // 2. Let newChildren be null. |
2659 | | - Vector<GC::Root<Node>> new_children; |
2660 | | - |
2661 | | - // 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. |
2662 | | - if (document().is_xml_document()) { |
2663 | | - new_children = TRY(XMLFragmentParser::parse_xml_fragment(*this, markup)); |
2664 | | - } |
2665 | | - // 4. Otherwise, set newChildren to the result of invoking the HTML fragment parsing algorithm given context, markup, false, and scriptingMode. |
2666 | | - else { |
2667 | | - new_children = TRY(HTML::HTMLParser::parse_html_fragment(*this, markup, HTML::HTMLParser::AllowDeclarativeShadowRoots::No, scripting_mode)); |
2668 | | - } |
2669 | | - |
2670 | | - // 5. Let fragment be a new DocumentFragment whose node document is context's node document. |
2671 | | - auto fragment = realm().create<DOM::DocumentFragment>(document()); |
2672 | | - |
2673 | | - // 6. For each node of newChildren, in tree order: append node to fragment. |
2674 | | - for (auto& child : new_children) |
2675 | | - TRY(fragment->append_child(*child)); |
| 2661 | + // 2. If target's node document is an XML document, then return the result of invoking the XML fragment parsing |
| 2662 | + // algorithm given target and markup. |
| 2663 | + if (target.visit([](auto node) { return node->document().is_xml_document(); })) |
| 2664 | + return XMLFragmentParser::parse_xml_fragment(target, markup); |
2676 | 2665 |
|
2677 | | - // 7. Return fragment. |
2678 | | - return fragment; |
| 2666 | + // 3. Return the result of invoking the HTML fragment parsing algorithm given context, markup, false, and scriptingMode. |
| 2667 | + return HTML::HTMLParser::parse_html_fragment(target, markup, HTML::HTMLParser::AllowDeclarativeShadowRoots::No, scripting_mode); |
2679 | 2668 | } |
2680 | 2669 |
|
2681 | 2670 | // https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#dom-element-outerhtml |
@@ -2712,7 +2701,7 @@ WebIDL::ExceptionOr<void> Element::set_outer_html(TrustedTypes::TrustedHTMLOrStr |
2712 | 2701 | parent = TRY(create_element(document(), HTML::TagNames::body, Namespace::HTML)); |
2713 | 2702 |
|
2714 | 2703 | // 6. Let fragment be the result of invoking the fragment parsing algorithm steps given parent and compliantString. |
2715 | | - auto fragment = TRY(as<Element>(*parent).parse_fragment(compliant_string.utf16_view())); |
| 2704 | + auto fragment = TRY(Element::parse_fragment(GC::Ref { as<Element>(*parent) }, compliant_string.utf16_view())); |
2716 | 2705 |
|
2717 | 2706 | // 6. Replace this with fragment within this's parent. |
2718 | 2707 | TRY(this->parent()->replace_child(fragment, *this)); |
@@ -2773,7 +2762,7 @@ WebIDL::ExceptionOr<void> Element::insert_adjacent_html(String const& position, |
2773 | 2762 | } |
2774 | 2763 |
|
2775 | 2764 | // 5. Let fragment be the result of invoking the fragment parsing algorithm steps with context and compliantString. |
2776 | | - auto fragment = TRY(as<Element>(*context).parse_fragment(compliant_string.utf16_view())); |
| 2765 | + auto fragment = TRY(Element::parse_fragment(GC::Ref { as<Element>(*context) }, compliant_string.utf16_view())); |
2777 | 2766 |
|
2778 | 2767 | // 6. Use the first matching item from this list: |
2779 | 2768 |
|
@@ -4877,12 +4866,12 @@ WebIDL::ExceptionOr<void> Element::set_html_unsafe(TrustedTypes::TrustedHTMLOrSt |
4877 | 4866 | TrustedTypes::Script.to_string())); |
4878 | 4867 |
|
4879 | 4868 | // 2. Let target be this's template contents if this is a template element; otherwise this. |
4880 | | - DOM::Node* target = this; |
| 4869 | + Variant<GC::Ref<DOM::Element>, GC::Ref<DOM::DocumentFragment>> target = GC::Ref { *this }; |
4881 | 4870 | if (is<HTML::HTMLTemplateElement>(*this)) |
4882 | | - target = as<HTML::HTMLTemplateElement>(*this).content().ptr(); |
| 4871 | + target = as<HTML::HTMLTemplateElement>(*this).content(); |
4883 | 4872 |
|
4884 | 4873 | // 3. Unsafe set HTML given target, this, and compliantHTML. |
4885 | | - TRY(target->unsafely_set_html(*this, compliant_html.utf16_view())); |
| 4874 | + TRY(unsafely_set_html(target, compliant_html.utf16_view())); |
4886 | 4875 |
|
4887 | 4876 | return {}; |
4888 | 4877 | } |
|
0 commit comments