mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 00:47:45 +00:00
LibWeb: Fix infinite loop in ChildNode's before() and after()
The loop that was supposed to check the chain of previous or next siblings had a logic mistake where it would never traverse the chain, so we would get stuck looking at the immediate sibling forever.
This commit is contained in:
parent
ad843b6e4a
commit
35f359c51c
5 changed files with 47 additions and 11 deletions
|
@ -0,0 +1,5 @@
|
||||||
|
<DIV id="one" >
|
||||||
|
<DIV id="two" >
|
||||||
|
<DIV id="two" >
|
||||||
|
<DIV id="one" >
|
||||||
|
PASS (didn't crash)
|
|
@ -0,0 +1,5 @@
|
||||||
|
<DIV id="one" >
|
||||||
|
<DIV id="two" >
|
||||||
|
<DIV id="two" >
|
||||||
|
<DIV id="one" >
|
||||||
|
PASS (didn't crash)
|
|
@ -0,0 +1,13 @@
|
||||||
|
<script src="../include.js"></script>
|
||||||
|
<div id="one"></div><div id="two"></div><script>
|
||||||
|
test(() => {
|
||||||
|
let one = document.getElementById("one");
|
||||||
|
let two = document.getElementById("two");
|
||||||
|
one.after(two);
|
||||||
|
printElement(one);
|
||||||
|
printElement(one.nextSibling);
|
||||||
|
printElement(two);
|
||||||
|
printElement(two.previousSibling);
|
||||||
|
println("PASS (didn't crash)");
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -0,0 +1,13 @@
|
||||||
|
<script src="../include.js"></script>
|
||||||
|
<div id="one"></div><div id="two"></div><script>
|
||||||
|
test(() => {
|
||||||
|
let one = document.getElementById("one");
|
||||||
|
let two = document.getElementById("two");
|
||||||
|
two.before(one);
|
||||||
|
printElement(one);
|
||||||
|
printElement(one.nextSibling);
|
||||||
|
printElement(two);
|
||||||
|
printElement(two.previousSibling);
|
||||||
|
println("PASS (didn't crash)");
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -58,7 +58,7 @@ public:
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
// 3. Let viableNextSibling be this’s first following sibling not in nodes; otherwise null.
|
// 3. Let viableNextSibling be this’s first following sibling not in nodes; otherwise null.
|
||||||
auto viable_next_sibling = viable_nest_sibling_for_insertion(nodes);
|
auto viable_next_sibling = viable_next_sibling_for_insertion(nodes);
|
||||||
|
|
||||||
// 4. Let node be the result of converting nodes into a node, given nodes and this’s node document.
|
// 4. Let node be the result of converting nodes into a node, given nodes and this’s node document.
|
||||||
auto node_to_insert = TRY(convert_nodes_to_single_node(nodes, node->document()));
|
auto node_to_insert = TRY(convert_nodes_to_single_node(nodes, node->document()));
|
||||||
|
@ -82,7 +82,7 @@ public:
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
// 3. Let viableNextSibling be this’s first following sibling not in nodes; otherwise null.
|
// 3. Let viableNextSibling be this’s first following sibling not in nodes; otherwise null.
|
||||||
auto viable_next_sibling = viable_nest_sibling_for_insertion(nodes);
|
auto viable_next_sibling = viable_next_sibling_for_insertion(nodes);
|
||||||
|
|
||||||
// 4. Let node be the result of converting nodes into a node, given nodes and this’s node document.
|
// 4. Let node be the result of converting nodes into a node, given nodes and this’s node document.
|
||||||
auto node_to_insert = TRY(convert_nodes_to_single_node(nodes, node->document()));
|
auto node_to_insert = TRY(convert_nodes_to_single_node(nodes, node->document()));
|
||||||
|
@ -121,47 +121,47 @@ private:
|
||||||
{
|
{
|
||||||
auto* node = static_cast<NodeType*>(this);
|
auto* node = static_cast<NodeType*>(this);
|
||||||
|
|
||||||
while (auto* previous_sibling = node->previous_sibling()) {
|
for (auto* sibling = node->previous_sibling(); sibling; sibling = sibling->previous_sibling()) {
|
||||||
bool contained_in_nodes = false;
|
bool contained_in_nodes = false;
|
||||||
|
|
||||||
for (auto const& node_or_string : nodes) {
|
for (auto const& node_or_string : nodes) {
|
||||||
if (!node_or_string.template has<JS::Handle<Node>>())
|
if (!node_or_string.template has<JS::Handle<Node>>())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto node_in_vector = node_or_string.template get<JS::Handle<Node>>();
|
auto const& node_in_vector = node_or_string.template get<JS::Handle<Node>>();
|
||||||
if (node_in_vector.cell() == previous_sibling) {
|
if (node_in_vector.cell() == sibling) {
|
||||||
contained_in_nodes = true;
|
contained_in_nodes = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!contained_in_nodes)
|
if (!contained_in_nodes)
|
||||||
return previous_sibling;
|
return sibling;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
JS::GCPtr<Node> viable_nest_sibling_for_insertion(Vector<Variant<JS::Handle<Node>, String>> const& nodes)
|
JS::GCPtr<Node> viable_next_sibling_for_insertion(Vector<Variant<JS::Handle<Node>, String>> const& nodes)
|
||||||
{
|
{
|
||||||
auto* node = static_cast<NodeType*>(this);
|
auto* node = static_cast<NodeType*>(this);
|
||||||
|
|
||||||
while (auto* next_sibling = node->next_sibling()) {
|
for (auto* sibling = node->next_sibling(); sibling; sibling = sibling->next_sibling()) {
|
||||||
bool contained_in_nodes = false;
|
bool contained_in_nodes = false;
|
||||||
|
|
||||||
for (auto const& node_or_string : nodes) {
|
for (auto const& node_or_string : nodes) {
|
||||||
if (!node_or_string.template has<JS::Handle<Node>>())
|
if (!node_or_string.template has<JS::Handle<Node>>())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto& node_in_vector = node_or_string.template get<JS::Handle<Node>>();
|
auto const& node_in_vector = node_or_string.template get<JS::Handle<Node>>();
|
||||||
if (node_in_vector.cell() == next_sibling) {
|
if (node_in_vector.cell() == sibling) {
|
||||||
contained_in_nodes = true;
|
contained_in_nodes = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!contained_in_nodes)
|
if (!contained_in_nodes)
|
||||||
return next_sibling;
|
return sibling;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue