Skip to content

Commit 4ec5a04

Browse files
authored
Merge pull request #8 from nanto/fix-infinite-loop-in-replace
Fix infinite loop when calling replace method with a fragment
2 parents aa4a191 + bc6f640 commit 4ec5a04

File tree

2 files changed

+119
-7
lines changed

2 files changed

+119
-7
lines changed

DOM.xs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2111,13 +2111,10 @@ CODE:
21112111
if (html5_dom_is_fragment(new_node)) {
21122112
myhtml_tree_node_t *fragment_child = myhtml_node_child(new_node);
21132113
while (fragment_child) {
2114-
myhtml_tree_node_t *fragment_child = myhtml_node_child(new_node);
2115-
while (fragment_child) {
2116-
myhtml_tree_node_t *next = myhtml_node_next(fragment_child);
2117-
myhtml_tree_node_remove(fragment_child);
2118-
myhtml_tree_node_insert_before(old_node, fragment_child);
2119-
fragment_child = next;
2120-
}
2114+
myhtml_tree_node_t *next = myhtml_node_next(fragment_child);
2115+
myhtml_tree_node_remove(fragment_child);
2116+
myhtml_tree_node_insert_before(old_node, fragment_child);
2117+
fragment_child = next;
21212118
}
21222119
} else {
21232120
myhtml_tree_node_remove(new_node);

t/0-api.t

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -924,6 +924,121 @@ for my $test (@$test_manipulations) {
924924
}
925925
}
926926

927+
# DOM node insertion manipulations with fragment
928+
my $test_manipulations_with_fragment = [
929+
{
930+
method => 'append',
931+
on_parent => 1,
932+
return => 'self',
933+
check_offset => 5,
934+
},
935+
{
936+
method => 'appendChild',
937+
on_parent => 1,
938+
return => 'added',
939+
check_offset => 5,
940+
},
941+
{
942+
method => 'prepend',
943+
on_parent => 1,
944+
return => 'self',
945+
check_offset => 0,
946+
},
947+
{
948+
method => 'prependChild',
949+
on_parent => 1,
950+
return => 'added',
951+
check_offset => 0,
952+
},
953+
{
954+
method => 'replace',
955+
return => 'self',
956+
check_offset => 2,
957+
replace => 1,
958+
},
959+
{
960+
method => 'replaceChild',
961+
on_parent => 1,
962+
with_child => 1,
963+
return => 'removed',
964+
check_offset => 2,
965+
replace => 1,
966+
},
967+
{
968+
method => 'before',
969+
return => 'self',
970+
check_offset => 2,
971+
},
972+
{
973+
method => 'insertBefore',
974+
on_parent => 1,
975+
with_child => 1,
976+
return => 'added',
977+
check_offset => 2,
978+
},
979+
{
980+
method => 'after',
981+
return => 'self',
982+
check_offset => 3,
983+
},
984+
{
985+
method => 'insertAfter',
986+
on_parent => 1,
987+
with_child => 1,
988+
return => 'added',
989+
check_offset => 3,
990+
},
991+
];
992+
993+
for my $test (@$test_manipulations_with_fragment) {
994+
my $tree = HTML5::DOM->new->parse('
995+
<ul>
996+
<li>UNIX</li>
997+
<li>Linux</li>
998+
<li id="child">OSX</li>
999+
<li>Windows</li>
1000+
<li>FreeBSD</li>
1001+
</ul>
1002+
');
1003+
1004+
my $arg = $tree->parseFragment('
1005+
<li>NetBSD</li>
1006+
<li>OpenBSD</li>
1007+
', 'ul');
1008+
my $arg_child1 = $arg->firstElementChild;
1009+
my $arg_child2 = $arg->lastElementChild;
1010+
1011+
my $method = $test->{method};
1012+
my $child = $tree->at('#child');
1013+
my $parent = $child->parent;
1014+
my $test_el = $test->{on_parent} ? $parent : $child;
1015+
1016+
my $result;
1017+
if ($test->{with_child}) {
1018+
$result = $test_el->$method($arg, $child);
1019+
} else {
1020+
$result = $test_el->$method($arg);
1021+
}
1022+
1023+
if ($test->{return} eq 'self') {
1024+
ok($result == $test_el, "$method with fragment: check return (self)");
1025+
} elsif ($test->{return} eq 'added') {
1026+
ok($result == $arg, "$method with fragment: check return (added)");
1027+
} elsif ($test->{return} eq 'removed') {
1028+
ok($result == $child, "$method with fragment: check return (removed)");
1029+
}
1030+
1031+
my $check_offset1 = $test->{check_offset};
1032+
my $check_offset2 = $check_offset1 + 1;
1033+
my $child_count = $test->{replace} ? 6 : 7;
1034+
my $children = $parent->children;
1035+
ok($children->item($check_offset1) == $arg_child1, "$method with fragment: check position 1");
1036+
ok($children->item($check_offset2) == $arg_child2, "$method with fragment: check position 2");
1037+
ok($children->length == $child_count, "$method with fragment: check child count");
1038+
1039+
ok($arg->childNodes->length == 0, "$method with fragment: check child count of arg");
1040+
}
1041+
9271042
#####################################
9281043
# HTML5::DOM::DocType
9291044
#####################################

0 commit comments

Comments
 (0)