Category
bug · php-src-strict · DOM ID map · pillar 4
Problem
When an element with setIdAttribute('id', true) is removed via replaceChild() and the replacement reuses the same id value, Zend/libxml leaves getElementById() as null even after calling setIdAttribute on the (now attached) replacement. VM returns the replacement element. Distinct from closed #23999 (detached setIdAttribute before insert — that path is green). Probed 2026-07-30 vs Zend 8.2.32.
| Repro |
Zend 8.2.32 |
VM (2026-07-30) |
replaceChild removes id-mapped a; new c has same id; setIdAttribute after insert; getElementById('x') |
null |
c |
Control: replace with a fresh id then setIdAttribute |
finds node |
finds node (OK) |
php-src reference
PHP implementation target
ext/dom/ ID-map helpers — on replace/remove, clear the old id slot such that re-setIdAttribute of the same string on the replacement matches Zend (including the null outcome if that is libxml’s observable); PHP-in-PHP only
Repro
./script/docker-exec.sh -- bash -lc '
php test/repro/maintainer_gap_dom_getelementbyid_replacechild_same_id.php
php bin/vm.php test/repro/maintainer_gap_dom_getelementbyid_replacechild_same_id.php
'
Inline:
$d = new DOMDocument();
$d->loadXML('<r><a id="x"/><b id="y"/></r>');
$a = $d->documentElement->firstChild;
$a->setIdAttribute('id', true);
$b = $a->nextSibling;
$b->setIdAttribute('id', true);
$new = $d->createElement('c');
$new->setAttribute('id', 'x');
$d->documentElement->replaceChild($new, $a);
$new->setIdAttribute('id', true);
echo ($d->getElementById('x')->nodeName ?? 'null'), "\n";
// Zend: null VM: c
Done when
Category
bug· php-src-strict · DOM ID map · pillar 4Problem
When an element with
setIdAttribute('id', true)is removed viareplaceChild()and the replacement reuses the sameidvalue, Zend/libxml leavesgetElementById()asnulleven after callingsetIdAttributeon the (now attached) replacement. VM returns the replacement element. Distinct from closed #23999 (detachedsetIdAttributebefore insert — that path is green). Probed 2026-07-30 vs Zend 8.2.32.a; newchas sameid;setIdAttributeafter insert;getElementById('x')nullcsetIdAttributephp-src reference
ext/dom/node.c—dom_node_replace_child/ ID-map unlinkext/dom/document.c—getElementById/ element ID hashtableext/dom/element.c—setIdAttributePHP implementation target
ext/dom/ID-map helpers — on replace/remove, clear the old id slot such that re-setIdAttributeof the same string on the replacement matches Zend (including the null outcome if that is libxml’s observable); PHP-in-PHP onlyRepro
Inline:
Done when
replaceChild+setIdAttribute→getElementByIdmatches Zend on VM (+ JIT/AOT when in scope).phpt+ keeptest/repro/maintainer_gap_dom_getelementbyid_replacechild_same_id.php