fix: [#1888] Replaces inefficient loops for clearing children #1889
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Fixes #1888
This PR introduces a fast path for clearing all children from a parent node in
O(n)
time and wires it into hot code paths (innerHTML
,textContent
,replaceChildren
,ShadowRoot.setHTMLUnsafe
, andDocument.open
). It also optimizes cleanup inNode#[PropertySymbol.cloneNode]
using the same technique. The change preserves observable behavior andMutationObserver
semantics while significantly reducing time and allocations for large subtree clears.Motivation
Several core DOM APIs in happy-dom clear a node by repeatedly calling
removeChild(childNodes[0])
in a loop. Each removal from index 0 shifts the array, leading toO(n^2)
behavior and extra GC pressure for large trees. This PR replaces those loops with a single-pass algorithm.Design overview
New utility:
ParentNodeUtility.clearChildren(parent)
NodeList
reference identity by truncating arrays (length = 0
) rather than reassigning them.elementArray
in one step.childList
MutationRecord
s that the previous loops emitted, matchingpreviousSibling
andnextSibling
expectations.Node#[PropertySymbol.cloneNode]
cleanupwhile (childNodes.length) removeChild(childNodes[0])
pattern with a local fast-detach that snapshots children, truncates arrays (length = 0
), and then clears parent links/cache and dispatches disconnects per child.