From 5a5e3a6ec3858dd66cbc105f5e98ecfd3d363914 Mon Sep 17 00:00:00 2001 From: Luke Wilde Date: Sat, 29 Jan 2022 21:44:41 +0000 Subject: [PATCH] LibWeb: Implement ChildNode.after --- .../Libraries/LibWeb/DOM/CharacterData.idl | 1 + Userland/Libraries/LibWeb/DOM/ChildNode.h | 55 +++++++++++++++++++ .../Libraries/LibWeb/DOM/DocumentType.idl | 1 + Userland/Libraries/LibWeb/DOM/Element.idl | 1 + 4 files changed, 58 insertions(+) diff --git a/Userland/Libraries/LibWeb/DOM/CharacterData.idl b/Userland/Libraries/LibWeb/DOM/CharacterData.idl index a577a8c9e2..7d859fa8ce 100644 --- a/Userland/Libraries/LibWeb/DOM/CharacterData.idl +++ b/Userland/Libraries/LibWeb/DOM/CharacterData.idl @@ -8,6 +8,7 @@ interface CharacterData : Node { // FIXME: These should come from a ChildNode mixin [CEReactions, Unscopable] undefined before((Node or DOMString)... nodes); + [CEReactions, Unscopable] undefined after((Node or DOMString)... nodes); [CEReactions, Unscopable, ImplementedAs=remove_binding] undefined remove(); }; diff --git a/Userland/Libraries/LibWeb/DOM/ChildNode.h b/Userland/Libraries/LibWeb/DOM/ChildNode.h index 7c8414a3ee..2eb70e4696 100644 --- a/Userland/Libraries/LibWeb/DOM/ChildNode.h +++ b/Userland/Libraries/LibWeb/DOM/ChildNode.h @@ -51,6 +51,36 @@ public: return {}; } + // https://dom.spec.whatwg.org/#dom-childnode-after + ExceptionOr after(Vector, String>> const& nodes) + { + auto* node = static_cast(this); + + // 1. Let parent be this’s parent. + auto* parent = node->parent(); + + // 2. If parent is null, then return. + if (!parent) + return {}; + + // 3. Let viableNextSibling be this’s first following sibling not in nodes; otherwise null. + auto viable_next_sibling = viable_nest_sibling_for_insertion(nodes); + + // 4. Let node be the result of converting nodes into a node, given nodes and this’s node document. + auto node_or_exception = convert_nodes_to_single_node(nodes, node->document()); + if (node_or_exception.is_exception()) + return node_or_exception.exception(); + + auto node_to_insert = node_or_exception.release_value(); + + // 5. Pre-insert node into parent before viableNextSibling. + auto result = parent->pre_insert(node_to_insert, viable_next_sibling); + if (result.is_exception()) + return result.exception(); + + return {}; + } + // https://dom.spec.whatwg.org/#dom-childnode-remove void remove_binding() { @@ -92,6 +122,31 @@ private: return nullptr; } + + RefPtr viable_nest_sibling_for_insertion(Vector, String>> const& nodes) const + { + auto* node = static_cast(this); + + while (auto* next_sibling = node->next_sibling()) { + bool contained_in_nodes = false; + + for (auto const& node_or_string : nodes) { + if (!node_or_string.template has>()) + continue; + + auto node_in_vector = node_or_string.template get>(); + if (node_in_vector.ptr() == next_sibling) { + contained_in_nodes = true; + break; + } + } + + if (!contained_in_nodes) + return next_sibling; + } + + return nullptr; + } }; } diff --git a/Userland/Libraries/LibWeb/DOM/DocumentType.idl b/Userland/Libraries/LibWeb/DOM/DocumentType.idl index fa3ec8697e..0bfa494bca 100644 --- a/Userland/Libraries/LibWeb/DOM/DocumentType.idl +++ b/Userland/Libraries/LibWeb/DOM/DocumentType.idl @@ -6,6 +6,7 @@ interface DocumentType : Node { // FIXME: These should come from a ChildNode mixin [CEReactions, Unscopable] undefined before((Node or DOMString)... nodes); + [CEReactions, Unscopable] undefined after((Node or DOMString)... nodes); [CEReactions, Unscopable, ImplementedAs=remove_binding] undefined remove(); }; diff --git a/Userland/Libraries/LibWeb/DOM/Element.idl b/Userland/Libraries/LibWeb/DOM/Element.idl index 91a0e56d2b..ea82f8113c 100644 --- a/Userland/Libraries/LibWeb/DOM/Element.idl +++ b/Userland/Libraries/LibWeb/DOM/Element.idl @@ -56,6 +56,7 @@ interface Element : Node { // FIXME: These should come from a ChildNode mixin [CEReactions, Unscopable] undefined before((Node or DOMString)... nodes); + [CEReactions, Unscopable] undefined after((Node or DOMString)... nodes); [CEReactions, Unscopable, ImplementedAs=remove_binding] undefined remove(); };