From 396e52631b4aed2cede4f11ea926f30752677131 Mon Sep 17 00:00:00 2001 From: Dustin Wilson Date: Tue, 2 Nov 2021 15:17:03 -0500 Subject: [PATCH] Starting to fill out Document --- README.md | 4 +- lib/Document.php | 55 +++++- lib/Element.php | 41 +++++ lib/InnerNode/Document.php | 10 +- lib/InnerNode/{NodeMap.php => NodeCache.php} | 2 +- lib/InnerNode/Reflection.php | 9 +- lib/Node.php | 1 - tests/cases/TestDocument.php | 33 +++- tests/cases/TestNode.php | 176 +++++++++---------- 9 files changed, 221 insertions(+), 110 deletions(-) rename lib/InnerNode/{NodeMap.php => NodeCache.php} (98%) diff --git a/README.md b/README.md index c8d97a5..9efc0bc 100644 --- a/README.md +++ b/README.md @@ -39,9 +39,9 @@ Coming soon $d->loadHTML('Ook

Ook!

'); ``` -## Differences from Specification ## +## Limitations & Differences from Specification ## -The primary aim of this library is accuracy. However, due either to limitations imposed by PHP's DOM or by assumptions made by the specification that aren't applicable to a PHP library some changes have needed to be made. These are as follows: +The primary aim of this library is accuracy. However, due either to limitations imposed by PHP's DOM, by assumptions made by the specification that aren't applicable to a PHP library, or simply because of impractability some changes have needed to be made. These are as follows: 1. Any mention of scripting or anything necessary because of scripting (such as the `ElementCreationOptions` options dictionary on `Document::createElement`) will not be implemented. 2. The specification is written entirely with browsers in mind and aren't concerned with the DOM's being used outside of the browser. In browser there is always a document created by parsing serialized markup, and the DOM spec always assumes such. This is impossible in the way this PHP library is intended to be used. The default when creating a new `Document` is to set its content type to "application/xml". This isn't ideal when creating an HTML document entirely through the DOM, so this implementation will instead default to "text/html" unless using `XMLDocument`. diff --git a/lib/Document.php b/lib/Document.php index 12aba8c..983fca9 100644 --- a/lib/Document.php +++ b/lib/Document.php @@ -31,7 +31,7 @@ class Document extends Node { protected function __get_body(): ?Element { $documentElement = $this->innerNode->documentElement; - if ($documentElement === null || !$documentElement->hasChildNodes()) { + if ($documentElement === null) { return null; } @@ -39,11 +39,13 @@ class Document extends Node { # that is either a body element or a frameset element, or null if there is no # such element. $n = $documentElement->firstChild; - do { - if ($n instanceof \DOMElement && $n->namespaceURI === null && ($n->nodeName === 'body' || $n->nodeName === 'frameset')) { - return $n->ownerDocument->getWrapperNode($n); - } - } while ($n = $n->nextSibling); + if ($n !== null) { + do { + if ($n instanceof \DOMElement && $n->namespaceURI === null && ($n->nodeName === 'body' || $n->nodeName === 'frameset')) { + return $n->ownerDocument->getWrapperNode($n); + } + } while ($n = $n->nextSibling); + } return null; } @@ -64,6 +66,11 @@ class Document extends Node { return $this->_contentType; } + protected function __get_doctype(): DocumentType { + // PHP's DOM does this correctly already. + return $this->innerNode->getWrapperNode($this->innerNode->doctype); + } + protected function __get_documentElement(): ?Element { return $this->innerNode->getWrapperNode($this->innerNode->documentElement); } @@ -97,6 +104,42 @@ class Document extends Node { } + public function adoptNode(Node &$node): Node { + # The adoptNode(node) method steps are: + # + # 1. If node is a document, then throw a "NotSupportedError" DOMException. + if ($node instanceof Document) { + throw new DOMException(DOMException::NOT_SUPPORTED); + } + + # 2. If node is a shadow root, then throw a "HierarchyRequestError" DOMException. + // DEVIATION: There is no scripting in this implementation + + # 3. If node is a DocumentFragment node whose host is non-null, then return. + // DEVIATION: One can't just return here? + if ($node instanceof DocumentFragment) { + $host = Reflection::getProtectedProperty($node, 'host'); + if ($host === null || $host->get() === null) { + return $node; + } + } + + # 4. Adopt node into this. + $newNode = $this->importNode($node, true); + + $parent = $node->parentNode; + if ($parent !== null) { + $parent->removeChild($node); + } + + // Remove node from the inner document's node cache. + Reflection::getProtectedProperty($this->getInnerNode($node)->ownerDocument, 'nodeCache')->delete($node); + + # 5. Return node. + $node = $newNode; + return $node; + } + public function createAttribute(string $localName): Attr { # The createAttribute(localName) method steps are: # diff --git a/lib/Element.php b/lib/Element.php index da65cbe..9c970fb 100644 --- a/lib/Element.php +++ b/lib/Element.php @@ -22,7 +22,20 @@ class Element extends Node { return Reflection::createFromProtectedConstructor(__NAMESPACE__ . '\\NamedNodeMap', $this, ($this instanceof Document) ? $this->innerNode : $this->innerNode->ownerDocument, $this->innerNode->attributes); } + protected function __get_id(): string { + # The id attribute must reflect the "id" content attribute. + # Return the result of running get an attribute value given this and name. + return $this->getAttribute('id') ?? ''; + } + + protected function __set_id(string $value): string { + # The id attribute must reflect the "id" content attribute. + # Set an attribute value for this using name and the given value. + return $this->setAttribute('id', $value); + } + protected function __get_localName(): ?string { + // PHP's DOM does this correctly already. return $this->innerNode->localName; } @@ -37,14 +50,35 @@ class Element extends Node { } protected function __get_prefix(): ?string { + // PHP's DOM does this correctly already. return $this->innerNode->prefix; } + protected function __get_tagName(): string { + // PHP's DOM does this correctly already. + return $this->innerNode->tagName; + } + protected function __construct(\DOMElement $element) { parent::__construct($element); } + + public function getAttributeNames(): array { + # The getAttributeNames() method steps are to return the qualified names of the + # attributes in this’s attribute list, in order; otherwise a new list. + $list = []; + $attributes = $this->innerNode->attributes; + if ($attributes !== null) { + foreach ($attributes as $attr) { + $list[] = $attr->nodeName; + } + } + + return $list; + } + public function getAttributeNode(string $qualifiedName): ?Attr { # The getAttributeNode(qualifiedName) method steps are to return the result of # getting an attribute given qualifiedName and this. @@ -81,6 +115,13 @@ class Element extends Node { return ($attr !== false) ? $this->innerNode->ownerDocument->getWrapperNode($attr) : null; } + public function hasAttributes(): bool { + # The hasAttributes() method steps are to return false if this’s attribute list + # is empty; otherwise true. + // PHP's DOM does this correctly already. + return $this->innerNode->hasAttributes(); + } + public function hasAttribute(string $qualifiedName): bool { # The hasAttribute(qualifiedName) method steps are: # diff --git a/lib/InnerNode/Document.php b/lib/InnerNode/Document.php index 193e8fa..7a7809b 100644 --- a/lib/InnerNode/Document.php +++ b/lib/InnerNode/Document.php @@ -25,7 +25,7 @@ class Document extends \DOMDocument { public const NAME_PRODUCTION_REGEX = '/^[:A-Z_a-z\x{C0}-\x{D6}\x{D8}-\x{F6}\x{F8}-\x{2FF}\x{370}-\x{37D}\x{37F}-\x{1FFF}\x{200C}-\x{200D}\x{2070}-\x{218F}\x{2C00}-\x{2FEF}\x{3001}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFFD}\x{10000}-\x{EFFFF}][:A-Z_a-z\x{C0}-\x{D6}\x{D8}-\x{F6}\x{F8}-\x{2FF}\x{370}-\x{37D}\x{37F}-\x{1FFF}\x{200C}-\x{200D}\x{2070}-\x{218F}\x{2C00}-\x{2FEF}\x{3001}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFFD}\x{10000}-\x{EFFFF}-\.0-9\x{B7}\x{0300}-\x{036F}\x{203F}-\x{2040}]*$/Su'; public const QNAME_PRODUCTION_REGEX = '/^([A-Z_a-z\x{C0}-\x{D6}\x{D8}-\x{F6}\x{F8}-\x{2FF}\x{370}-\x{37D}\x{37F}-\x{1FFF}\x{200C}-\x{200D}\x{2070}-\x{218F}\x{2C00}-\x{2FEF}\x{3001}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFFD}\x{10000}-\x{EFFFF}][A-Z_a-z\x{C0}-\x{D6}\x{D8}-\x{F6}\x{F8}-\x{2FF}\x{370}-\x{37D}\x{37F}-\x{1FFF}\x{200C}-\x{200D}\x{2070}-\x{218F}\x{2C00}-\x{2FEF}\x{3001}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFFD}\x{10000}-\x{EFFFF}-\.0-9\x{B7}\x{0300}-\x{036F}\x{203F}-\x{2040}]*:)?[A-Z_a-z\x{C0}-\x{D6}\x{D8}-\x{F6}\x{F8}-\x{2FF}\x{370}-\x{37D}\x{37F}-\x{1FFF}\x{200C}-\x{200D}\x{2070}-\x{218F}\x{2C00}-\x{2FEF}\x{3001}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFFD}\x{10000}-\x{EFFFF}][A-Z_a-z\x{C0}-\x{D6}\x{D8}-\x{F6}\x{F8}-\x{2FF}\x{370}-\x{37D}\x{37F}-\x{1FFF}\x{200C}-\x{200D}\x{2070}-\x{218F}\x{2C00}-\x{2FEF}\x{3001}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFFD}\x{10000}-\x{EFFFF}-\.0-9\x{B7}\x{0300}-\x{036F}\x{203F}-\x{2040}]*$/Su'; - protected NodeMap $nodeMap; + protected NodeCache $nodeCache; protected \WeakReference $_wrapperNode; protected function __get_wrapperNode(): WrapperNode { @@ -39,7 +39,7 @@ class Document extends \DOMDocument { parent::__construct(); parent::registerNodeClass('DOMDocument', self::class); - $this->nodeMap = new NodeMap(); + $this->nodeCache = new NodeCache(); // Use a weak reference here to prevent a circular reference $this->_wrapperNode = \WeakReference::create($wrapperNode); @@ -50,7 +50,7 @@ class Document extends \DOMDocument { public function getInnerNode(WrapperNode $node): ?\DOMNode { - return $this->nodeMap->get($node); + return Reflection::getProtectedProperty($node, 'innerNode'); } public function getWrapperNode(?\DOMNode $node = null): ?WrapperNode { @@ -64,7 +64,7 @@ class Document extends \DOMDocument { } // If the wrapper node already exists then return that. - if ($wrapperNode = $this->nodeMap->get($node)) { + if ($wrapperNode = $this->nodeCache->get($node)) { return $wrapperNode; } @@ -109,7 +109,7 @@ class Document extends \DOMDocument { Reflection::setProtectedProperties($wrapperNode, [ '_ownerDocument' => $this->_wrapperNode ]); } - $this->nodeMap->set($wrapperNode, $node); + $this->nodeCache->set($wrapperNode, $node); return $wrapperNode; } } diff --git a/lib/InnerNode/NodeMap.php b/lib/InnerNode/NodeCache.php similarity index 98% rename from lib/InnerNode/NodeMap.php rename to lib/InnerNode/NodeCache.php index bf07888..98f1c29 100644 --- a/lib/InnerNode/NodeMap.php +++ b/lib/InnerNode/NodeCache.php @@ -10,7 +10,7 @@ namespace MensBeam\HTML\DOM\InnerNode; use MensBeam\HTML\DOM\Node as WrapperNode; -class NodeMap { +class NodeCache { protected $wrapperArray = []; protected $innerArray = []; diff --git a/lib/InnerNode/Reflection.php b/lib/InnerNode/Reflection.php index 52c75de..e137a32 100644 --- a/lib/InnerNode/Reflection.php +++ b/lib/InnerNode/Reflection.php @@ -8,7 +8,14 @@ declare(strict_types=1); namespace MensBeam\HTML\DOM\InnerNode; - +/** + * Class which uses reflection to gain access to protected constructors and + * properties. We are well aware of the negative conotations around using + * Reflection. The specification itself is written in a manner that expects + * C++-style friend classes which PHP lacks, so it first comes out of necessity. + * Any other use of it comes down to speed optimizations (such as gaining access + * to Node::innerNode). + */ class Reflection { public static function createFromProtectedConstructor(string $className, ...$arguments): mixed { $reflector = new \ReflectionClass($className); diff --git a/lib/Node.php b/lib/Node.php index e8a2180..ddb28fa 100644 --- a/lib/Node.php +++ b/lib/Node.php @@ -1311,7 +1311,6 @@ abstract class Node { } } - public function __toString() { return $this->ownerDocument->serialize($this); } diff --git a/tests/cases/TestDocument.php b/tests/cases/TestDocument.php index 8adcfc2..ebf5351 100644 --- a/tests/cases/TestDocument.php +++ b/tests/cases/TestDocument.php @@ -32,23 +32,44 @@ class TestDocument extends \PHPUnit\Framework\TestCase { * @covers \MensBeam\HTML\DOM\Node::preInsertionValidity * @covers \MensBeam\HTML\DOM\InnerNode\Document::__construct * @covers \MensBeam\HTML\DOM\InnerNode\Document::getWrapperNode - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::get - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::has - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::key - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::set + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::get + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::has + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::key + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::set * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::createFromProtectedConstructor * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::getProtectedProperty */ public function testProperty_body() { $d = new Document(); + + // Document::body without document element + $this->assertNull($d->body); + $d->appendChild($d->createElement('html')); - // Node::body without body + // Document::body without body $this->assertNull($d->body); $body = $d->documentElement->appendChild($d->createElement('body')); - // Node::body with body + // Document::body with body $this->assertSame($body, $d->body); } + + /** + * @covers \MensBeam\HTML\DOM\Document::__get_charset + * @covers \MensBeam\HTML\DOM\Document::__get_inputEncoding + */ + public function testProperty_charset() { + $d = new Document(''); + $this->assertSame('GBK', $d->charset); + $this->assertSame('GBK', $d->inputEncoding); + } + + /** @covers \MensBeam\HTML\DOM\Document::__get_documentURI */ + public function testProperty_documentURI() { + $d = new Document(); + $d->loadFile('https://google.com'); + $this->assertSame('https://google.com', $d->documentURI); + } } \ No newline at end of file diff --git a/tests/cases/TestNode.php b/tests/cases/TestNode.php index 64af0aa..69b0360 100644 --- a/tests/cases/TestNode.php +++ b/tests/cases/TestNode.php @@ -68,10 +68,10 @@ class TestNode extends \PHPUnit\Framework\TestCase { * @covers \MensBeam\HTML\DOM\InnerNode\Document::__construct * @covers \MensBeam\HTML\DOM\InnerNode\Document::__get_wrapperNode * @covers \MensBeam\HTML\DOM\InnerNode\Document::getWrapperNode - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::get - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::has - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::key - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::set + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::get + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::has + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::key + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::set * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::createFromProtectedConstructor * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::getProtectedProperty * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::setProtectedProperties @@ -157,10 +157,10 @@ class TestNode extends \PHPUnit\Framework\TestCase { * @covers \MensBeam\HTML\DOM\InnerNode\Document::__construct * @covers \MensBeam\HTML\DOM\InnerNode\Document::__get_wrapperNode * @covers \MensBeam\HTML\DOM\InnerNode\Document::getWrapperNode - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::get - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::has - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::key - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::set + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::get + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::has + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::key + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::set * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::createFromProtectedConstructor * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::getProtectedProperty */ @@ -239,10 +239,10 @@ class TestNode extends \PHPUnit\Framework\TestCase { * @covers \MensBeam\HTML\DOM\Node::preInsertionValidity * @covers \MensBeam\HTML\DOM\InnerNode\Document::__construct * @covers \MensBeam\HTML\DOM\InnerNode\Document::getWrapperNode - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::get - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::has - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::key - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::set + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::get + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::has + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::key + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::set * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::createFromProtectedConstructor * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::getProtectedProperty */ @@ -282,10 +282,10 @@ class TestNode extends \PHPUnit\Framework\TestCase { * @covers \MensBeam\HTML\DOM\InnerNode\Document::__get_wrapperNode * @covers \MensBeam\HTML\DOM\InnerNode\Document::getInnerNode * @covers \MensBeam\HTML\DOM\InnerNode\Document::getWrapperNode - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::get - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::has - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::key - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::set + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::get + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::has + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::key + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::set * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::createFromProtectedConstructor * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::getProtectedProperty * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::setProtectedProperties @@ -326,10 +326,10 @@ class TestNode extends \PHPUnit\Framework\TestCase { * @covers \MensBeam\HTML\DOM\Text::__construct * @covers \MensBeam\HTML\DOM\InnerNode\Document::__construct * @covers \MensBeam\HTML\DOM\InnerNode\Document::getWrapperNode - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::get - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::has - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::key - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::set + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::get + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::has + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::key + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::set * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::createFromProtectedConstructor * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::getProtectedProperty * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::setProtectedProperties @@ -382,10 +382,10 @@ class TestNode extends \PHPUnit\Framework\TestCase { * @covers \MensBeam\HTML\DOM\InnerNode\Document::__construct * @covers \MensBeam\HTML\DOM\InnerNode\Document::__get_wrapperNode * @covers \MensBeam\HTML\DOM\InnerNode\Document::getWrapperNode - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::get - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::has - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::key - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::set + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::get + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::has + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::key + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::set * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::createFromProtectedConstructor * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::getProtectedProperty */ @@ -432,10 +432,10 @@ class TestNode extends \PHPUnit\Framework\TestCase { * @covers \MensBeam\HTML\DOM\InnerNode\Document::__construct * @covers \MensBeam\HTML\DOM\InnerNode\Document::__get_wrapperNode * @covers \MensBeam\HTML\DOM\InnerNode\Document::getWrapperNode - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::get - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::has - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::key - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::set + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::get + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::has + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::key + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::set * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::createFromProtectedConstructor * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::getProtectedProperty * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::setProtectedProperties @@ -535,10 +535,10 @@ class TestNode extends \PHPUnit\Framework\TestCase { * @covers \MensBeam\HTML\DOM\InnerNode\Document::__construct * @covers \MensBeam\HTML\DOM\InnerNode\Document::__get_wrapperNode * @covers \MensBeam\HTML\DOM\InnerNode\Document::getWrapperNode - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::get - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::has - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::key - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::set + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::get + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::has + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::key + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::set * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::createFromProtectedConstructor * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::getProtectedProperty * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::setProtectedProperties @@ -598,10 +598,10 @@ class TestNode extends \PHPUnit\Framework\TestCase { * @covers \MensBeam\HTML\DOM\InnerNode\Document::__construct * @covers \MensBeam\HTML\DOM\InnerNode\Document::__get_wrapperNode * @covers \MensBeam\HTML\DOM\InnerNode\Document::getWrapperNode - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::get - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::has - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::key - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::set + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::get + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::has + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::key + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::set * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::createFromProtectedConstructor * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::getProtectedProperty */ @@ -634,10 +634,10 @@ class TestNode extends \PHPUnit\Framework\TestCase { * @covers \MensBeam\HTML\DOM\Text::__construct * @covers \MensBeam\HTML\DOM\InnerNode\Document::__construct * @covers \MensBeam\HTML\DOM\InnerNode\Document::getWrapperNode - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::get - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::has - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::key - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::set + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::get + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::has + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::key + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::set * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::createFromProtectedConstructor * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::getProtectedProperty */ @@ -944,10 +944,10 @@ class TestNode extends \PHPUnit\Framework\TestCase { * @covers \MensBeam\HTML\DOM\Text::__construct * @covers \MensBeam\HTML\DOM\InnerNode\Document::__construct * @covers \MensBeam\HTML\DOM\InnerNode\Document::getWrapperNode - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::get - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::has - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::key - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::set + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::get + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::has + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::key + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::set * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::createFromProtectedConstructor * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::getProtectedProperty */ @@ -987,10 +987,10 @@ class TestNode extends \PHPUnit\Framework\TestCase { * @covers \MensBeam\HTML\DOM\Node::preInsertionValidity * @covers \MensBeam\HTML\DOM\InnerNode\Document::__construct * @covers \MensBeam\HTML\DOM\InnerNode\Document::getWrapperNode - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::get - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::has - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::key - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::set + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::get + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::has + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::key + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::set * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::createFromProtectedConstructor * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::getProtectedProperty */ @@ -1025,10 +1025,10 @@ class TestNode extends \PHPUnit\Framework\TestCase { * @covers \MensBeam\HTML\DOM\InnerNode\Document::__construct * @covers \MensBeam\HTML\DOM\InnerNode\Document::__get_wrapperNode * @covers \MensBeam\HTML\DOM\InnerNode\Document::getWrapperNode - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::get - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::has - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::key - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::set + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::get + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::has + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::key + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::set * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::createFromProtectedConstructor * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::getProtectedProperty */ @@ -1059,10 +1059,10 @@ class TestNode extends \PHPUnit\Framework\TestCase { * @covers \MensBeam\HTML\DOM\Text::__construct * @covers \MensBeam\HTML\DOM\InnerNode\Document::__construct * @covers \MensBeam\HTML\DOM\InnerNode\Document::getWrapperNode - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::get - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::has - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::key - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::set + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::get + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::has + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::key + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::set * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::createFromProtectedConstructor * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::getProtectedProperty */ @@ -1106,10 +1106,10 @@ class TestNode extends \PHPUnit\Framework\TestCase { * @covers \MensBeam\HTML\DOM\Text::__construct * @covers \MensBeam\HTML\DOM\InnerNode\Document::__construct * @covers \MensBeam\HTML\DOM\InnerNode\Document::getWrapperNode - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::get - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::has - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::key - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::set + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::get + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::has + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::key + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::set * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::createFromProtectedConstructor * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::getProtectedProperty * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::setProtectedProperties @@ -1154,10 +1154,10 @@ class TestNode extends \PHPUnit\Framework\TestCase { * @covers \MensBeam\HTML\DOM\Text::__construct * @covers \MensBeam\HTML\DOM\InnerNode\Document::__construct * @covers \MensBeam\HTML\DOM\InnerNode\Document::getWrapperNode - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::get - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::has - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::key - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::set + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::get + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::has + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::key + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::set * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::createFromProtectedConstructor * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::getProtectedProperty * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::setProtectedProperties @@ -1211,10 +1211,10 @@ class TestNode extends \PHPUnit\Framework\TestCase { * @covers \MensBeam\HTML\DOM\Text::__construct * @covers \MensBeam\HTML\DOM\InnerNode\Document::__construct * @covers \MensBeam\HTML\DOM\InnerNode\Document::getWrapperNode - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::get - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::has - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::key - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::set + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::get + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::has + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::key + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::set * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::createFromProtectedConstructor * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::getProtectedProperty * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::setProtectedProperties @@ -1292,10 +1292,10 @@ class TestNode extends \PHPUnit\Framework\TestCase { * @covers \MensBeam\HTML\DOM\Text::__construct * @covers \MensBeam\HTML\DOM\InnerNode\Document::__construct * @covers \MensBeam\HTML\DOM\InnerNode\Document::getWrapperNode - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::get - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::has - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::key - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::set + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::get + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::has + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::key + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::set * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::createFromProtectedConstructor * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::getProtectedProperty * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::setProtectedProperties @@ -1353,10 +1353,10 @@ class TestNode extends \PHPUnit\Framework\TestCase { * @covers \MensBeam\HTML\DOM\Text::__construct * @covers \MensBeam\HTML\DOM\InnerNode\Document::__construct * @covers \MensBeam\HTML\DOM\InnerNode\Document::getWrapperNode - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::get - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::has - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::key - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::set + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::get + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::has + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::key + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::set * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::createFromProtectedConstructor * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::getProtectedProperty * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::setProtectedProperties @@ -1442,10 +1442,10 @@ class TestNode extends \PHPUnit\Framework\TestCase { * @covers \MensBeam\HTML\DOM\InnerNode\Document::__construct * @covers \MensBeam\HTML\DOM\InnerNode\Document::__get_wrapperNode * @covers \MensBeam\HTML\DOM\InnerNode\Document::getWrapperNode - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::get - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::has - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::key - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::set + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::get + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::has + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::key + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::set * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::createFromProtectedConstructor * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::getProtectedProperty * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::setProtectedProperties @@ -1508,10 +1508,10 @@ class TestNode extends \PHPUnit\Framework\TestCase { * @covers \MensBeam\HTML\DOM\InnerNode\Document::__construct * @covers \MensBeam\HTML\DOM\InnerNode\Document::__get_wrapperNode * @covers \MensBeam\HTML\DOM\InnerNode\Document::getWrapperNode - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::get - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::has - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::key - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::set + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::get + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::has + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::key + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::set * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::createFromProtectedConstructor * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::getProtectedProperty * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::setProtectedProperties @@ -1592,10 +1592,10 @@ class TestNode extends \PHPUnit\Framework\TestCase { * @covers \MensBeam\HTML\DOM\Text::__construct * @covers \MensBeam\HTML\DOM\InnerNode\Document::__construct * @covers \MensBeam\HTML\DOM\InnerNode\Document::getWrapperNode - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::get - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::has - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::key - * @covers \MensBeam\HTML\DOM\InnerNode\NodeMap::set + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::get + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::has + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::key + * @covers \MensBeam\HTML\DOM\InnerNode\NodeCache::set * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::createFromProtectedConstructor * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::getProtectedProperty * @covers \MensBeam\HTML\DOM\InnerNode\Reflection::setProtectedProperties