diff --git a/lib/TreeBuilder.php b/lib/TreeBuilder.php index d55f30d..f38b64e 100644 --- a/lib/TreeBuilder.php +++ b/lib/TreeBuilder.php @@ -3730,15 +3730,22 @@ class TreeBuilder { # Run these steps: # # Initialize node to be the current node (the bottommost node of the stack). - // We do this below in the loop + // We do this below before the loop # If node's tag name, converted to ASCII lowercase, is not the # same as the tag name of the token, then this is a parse error. // DEVIATION: We only generate the parse error if we don't reach // "Otherwise" below, to avoid reporting the parse error a second // time in HTML content parsing - # Loop: If node is the topmost element in the stack of open elements, then return. (fragment case) $pos = count($this->stack) - 1; - while ($pos > 0 && ($node = $this->stack[$pos])->namespaceURI !== null) { + $node = $this->stack[$pos]; + do { + # Loop: If node is the topmost element in the stack of open elements, then return. (fragment case) + if ($pos === 0) { + if (strtolower($this->stack->currentNodeName) !== $token->name) { + $this->error(ParseError::UNEXPECTED_END_TAG, $token->name); + } + return true; + } # If node's tag name, converted to ASCII lowercase, is the same as the # tag name of the token, pop elements from the stack of open elements until node # has been popped from the stack, and then abort these steps. @@ -3750,11 +3757,10 @@ class TreeBuilder { return true; } # Set node to the previous entry in the stack of open elements. - $pos--; + $node = $this->stack[--$pos]; # If node is not an element in the HTML namespace, return to the step labeled # loop. - // See loop condition above - } + } while ($node->namespaceURI !== null); # Otherwise, process the token according to the rules given in the section # corresponding to the current insertion mode in HTML content. return $this->parseTokenInHTMLContent($token, $this->insertionMode); diff --git a/tests/cases/TestTreeConstructor.php b/tests/cases/TestTreeConstructor.php index cf582fd..ba0405c 100644 --- a/tests/cases/TestTreeConstructor.php +++ b/tests/cases/TestTreeConstructor.php @@ -91,7 +91,7 @@ class TestTreeConstructor extends \PHPUnit\Framework\TestCase { $this->assertEquals($exp, $act, $treeBuilder->debugLog); if ($errors !== false) { // If $errors is false, the test does not include errors when there are in fact errors - $this->assertCount(sizeof($errors), $actualErrors, var_export($actualErrors, true)); + $this->assertCount(sizeof($errors), $actualErrors, var_export($errors, true).var_export($actualErrors, true)); } } @@ -109,6 +109,24 @@ class TestTreeConstructor extends \PHPUnit\Framework\TestCase { } // some tests don't document errors when they should if (!$errors && in_array($data, [ + // math.dat + '
', + '', + '', + '', + '', + '', + '', + // namespace-sensitivity.dat + 'Foo', + // svg.dat + '
', + '', + '', + '', + '
', + '', + '', // template.dat '