Skip to content

Commit e3cc9e4

Browse files
committed
simplify id/name index building by using only one recursive loop
1 parent 01b1665 commit e3cc9e4

2 files changed

Lines changed: 43 additions & 22 deletions

File tree

src/changes/changes.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88

99
<body>
1010
<release version="5.0.0" date="April 31, 2026" description="jdk17, Firefox 149, Chrome 147, Bugfixes">
11-
<action type="update" dev="rbri">
12-
Upgrade Apache commons-io to 2.22.0.
11+
<action type="update" dev="Ronny Shapiro">
12+
Defer building the HtmlPage id/name lookup index until first read.
1313
</action>
1414
<action type="fix" dev="rbri">
1515
Input type image returns false for willValidate.

src/main/java/org/htmlunit/html/HtmlPage.java

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1856,48 +1856,60 @@ void addMappedElement(final DomElement element, final boolean recurse) {
18561856
return;
18571857
}
18581858
if (isAncestorOf(element)) {
1859-
addElement(idMap_, element, DomElement.ID_ATTRIBUTE, recurse);
1860-
addElement(nameMap_, element, DomElement.NAME_ATTRIBUTE, recurse);
1859+
addElement(element, recurse);
18611860
}
18621861
}
18631862

18641863
private void ensureMappedElementsBuilt() {
18651864
if (mappedElementsBuilt_) {
18661865
return;
18671866
}
1867+
18681868
final DomElement root = getDocumentElement();
18691869
if (root != null) {
1870-
addElement(idMap_, root, DomElement.ID_ATTRIBUTE, true);
1871-
addElement(nameMap_, root, DomElement.NAME_ATTRIBUTE, true);
1870+
addElement(root, true);
18721871
}
1872+
18731873
// Flip the flag only after the maps are populated, so a partial
18741874
// failure mid-walk leaves us with built_=false and the next read
18751875
// tries again rather than seeing a half-populated index.
18761876
mappedElementsBuilt_ = true;
18771877
}
18781878

1879-
private void addElement(final Map<String, MappedElementIndexEntry> map, final DomElement element,
1880-
final String attribute, final boolean recurse) {
1881-
final String value = element.getAttribute(attribute);
1879+
private void addElement(final DomElement element, final boolean recurse) {
1880+
final String idValue = element.getAttribute(DomElement.ID_ATTRIBUTE);
1881+
if (ATTRIBUTE_NOT_DEFINED != idValue) {
1882+
MappedElementIndexEntry elements = idMap_.get(idValue);
1883+
if (elements == null) {
1884+
elements = new MappedElementIndexEntry();
1885+
elements.add(element);
1886+
idMap_.put(idValue, elements);
1887+
}
1888+
else {
1889+
elements.add(element);
1890+
}
1891+
}
18821892

1883-
if (ATTRIBUTE_NOT_DEFINED != value) {
1884-
MappedElementIndexEntry elements = map.get(value);
1893+
final String nameValue = element.getAttribute(DomElement.NAME_ATTRIBUTE);
1894+
if (ATTRIBUTE_NOT_DEFINED != nameValue) {
1895+
MappedElementIndexEntry elements = nameMap_.get(nameValue);
18851896
if (elements == null) {
18861897
elements = new MappedElementIndexEntry();
18871898
elements.add(element);
1888-
map.put(value, elements);
1899+
nameMap_.put(nameValue, elements);
18891900
}
18901901
else {
18911902
elements.add(element);
18921903
}
18931904
}
1905+
18941906
if (recurse) {
18951907
// poor man's approach - we don't use getChildElements()
18961908
// to avoid a bunch of object constructions
18971909
DomNode nextChild = element.getFirstChild();
18981910
while (nextChild != null) {
18991911
if (nextChild instanceof DomElement domElement) {
1900-
addElement(map, domElement, attribute, true);
1912+
addElement(domElement, true);
19011913
}
19021914
nextChild = nextChild.getNextSibling();
19031915
}
@@ -1916,27 +1928,36 @@ void removeMappedElement(final DomElement element, final boolean recurse, final
19161928
return;
19171929
}
19181930
if (descendant || isAncestorOf(element)) {
1919-
removeElement(idMap_, element, DomElement.ID_ATTRIBUTE, recurse);
1920-
removeElement(nameMap_, element, DomElement.NAME_ATTRIBUTE, recurse);
1931+
removeElement(element, recurse);
19211932
}
19221933
}
19231934

1924-
private void removeElement(final Map<String, MappedElementIndexEntry> map, final DomElement element,
1925-
final String attribute, final boolean recurse) {
1926-
final String value = element.getAttribute(attribute);
1935+
private void removeElement(final DomElement element, final boolean recurse) {
1936+
final String idValue = element.getAttribute(DomElement.ID_ATTRIBUTE);
1937+
if (ATTRIBUTE_NOT_DEFINED != idValue) {
1938+
final MappedElementIndexEntry elements = idMap_.remove(idValue);
1939+
if (elements != null) {
1940+
elements.remove(element);
1941+
if (!elements.elements_.isEmpty()) {
1942+
idMap_.put(idValue, elements);
1943+
}
1944+
}
1945+
}
19271946

1928-
if (ATTRIBUTE_NOT_DEFINED != value) {
1929-
final MappedElementIndexEntry elements = map.remove(value);
1947+
final String nameValue = element.getAttribute(DomElement.NAME_ATTRIBUTE);
1948+
if (ATTRIBUTE_NOT_DEFINED != nameValue) {
1949+
final MappedElementIndexEntry elements = nameMap_.remove(nameValue);
19301950
if (elements != null) {
19311951
elements.remove(element);
19321952
if (!elements.elements_.isEmpty()) {
1933-
map.put(value, elements);
1953+
nameMap_.put(nameValue, elements);
19341954
}
19351955
}
19361956
}
1957+
19371958
if (recurse) {
19381959
for (final DomElement child : element.getChildElements()) {
1939-
removeElement(map, child, attribute, true);
1960+
removeElement(child, true);
19401961
}
19411962
}
19421963
}

0 commit comments

Comments
 (0)