Skip to content

Commit 1b4af7d

Browse files
committed
1 parent aae3eb0 commit 1b4af7d

27 files changed

Lines changed: 117 additions & 30 deletions

src/main/java/org/htmlunit/cyberneko/HTMLTagBalancer.java

Lines changed: 42 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1124,7 +1124,6 @@ public void endElement(final QName element, final Augmentations augs) throws XNI
11241124
final boolean isForcedEndElement = forcedEndElement_;
11251125
forcedEndElement_ = false;
11261126

1127-
11281127
// is there anything to do?
11291128
if (fSeenRootElementEnd) {
11301129
notifyDiscardedEndElement(element, augs);
@@ -1205,39 +1204,32 @@ else if (elementCode == HTMLElements.HEAD && !isForcedEndElement) {
12051204

12061205
// empty element
12071206
final int depth = getElementDepth(elem);
1207+
12081208
// no matching tag found
12091209
if (depth == -1) {
12101210
if (elementCode == HTMLElements.P) {
12111211
forceStartElement(element, fEmptyXMLAttributes, synthesizedAugs());
12121212
endElement(element, augs);
1213+
return;
12131214
}
1214-
else if (elementCode == HTMLElements.BR) {
1215+
if (elementCode == HTMLElements.BR) {
12151216
forceStartElement(element, fEmptyXMLAttributes, synthesizedAugs());
1217+
return;
12161218
}
1217-
else if (elementCode == HTMLElements.H1
1218-
|| elementCode == HTMLElements.H2
1219-
|| elementCode == HTMLElements.H3
1220-
|| elementCode == HTMLElements.H4
1221-
|| elementCode == HTMLElements.H5
1222-
|| elementCode == HTMLElements.H6) {
1223-
for (int i = fElementStack.length - 1; i >= 0; i--) {
1219+
1220+
// Headings: if a heading end tag appears but there is no matching open tag,
1221+
// close the nearest open heading (H1..H6).
1222+
if (isHeading(elementCode)) {
1223+
for (int i = fElementStack.length - 1; i >= fragmentContextStackSize_; i--) {
12241224
final Info info = fElementStack.data[i];
1225-
final short infoElemCode = info.element.code;
1226-
if (infoElemCode == HTMLElements.H1
1227-
|| infoElemCode == HTMLElements.H2
1228-
|| infoElemCode == HTMLElements.H3
1229-
|| infoElemCode == HTMLElements.H4
1230-
|| infoElemCode == HTMLElements.H5
1231-
|| infoElemCode == HTMLElements.H6) {
1232-
if (documentHandler_ != null) {
1233-
addBodyIfNeeded(infoElemCode);
1234-
endElement(info.qname, augs);
1235-
return;
1236-
}
1225+
if (isHeading(info.element.code)) {
1226+
closeTopElements(element, fElementStack.length - i, augs);
1227+
return;
12371228
}
12381229
}
12391230
}
1240-
else if (!elem.isEmpty()) {
1231+
1232+
if (!elem.isEmpty()) {
12411233
notifyDiscardedEndElement(element, augs);
12421234
}
12431235
return;
@@ -1259,30 +1251,51 @@ else if (!elem.isEmpty()) {
12591251
}
12601252

12611253
// close children up to appropriate element
1254+
closeTopElements(element, depth, augs);
1255+
}
1256+
1257+
private static boolean isHeading(final short code) {
1258+
return code == HTMLElements.H1
1259+
|| code == HTMLElements.H2
1260+
|| code == HTMLElements.H3
1261+
|| code == HTMLElements.H4
1262+
|| code == HTMLElements.H5
1263+
|| code == HTMLElements.H6;
1264+
}
1265+
1266+
/**
1267+
* Pops and closes the top {@code depth} elements from {@link #fElementStack}, emitting warnings
1268+
* and endElement events exactly like the old inline loop in {@link #endElement(QName, Augmentations)}.
1269+
*
1270+
* @param triggeringElement the end tag that caused this close (used for warnings and for deciding
1271+
* which Augmentations are "real" vs synthesized)
1272+
* @param depth how many stack entries to close (must be > 0)
1273+
* @param augs augmentations from the triggering end tag
1274+
*/
1275+
private void closeTopElements(final QName triggeringElement, final int depth, final Augmentations augs) {
12621276
for (int i = 0; i < depth; i++) {
12631277
final Info info = fElementStack.pop();
1278+
12641279
if (fReportErrors && i < depth - 1) {
1265-
final String ename = element.getRawname();
1280+
final String ename = triggeringElement.getRawname();
12661281
final String iname = info.qname.getRawname();
12671282
fErrorReporter.reportWarning("HTML2007", new Object[]{ename, iname});
12681283
}
1284+
12691285
if (documentHandler_ != null) {
12701286
addBodyIfNeeded(info.element.code);
1271-
// PATCH: Marc-Andr� Morissette
1287+
// PATCH: Marc-André Morissette
12721288
callEndElement(info.qname, i < depth - 1 ? synthesizedAugs() : augs);
12731289
}
12741290
}
12751291
}
12761292

12771293
// re-open inline elements
12781294
protected boolean reopenFormattingElements(final HTMLElements.Element element) {
1279-
final int size = fFormattingStack.length;
1280-
1281-
if (size == 0) {
1295+
if (fFormattingStack.length == 0) {
12821296
return false;
12831297
}
12841298

1285-
int i = 0;
12861299
Info info = fFormattingStack.pop();
12871300
XMLAttributes attributes = info.attributes;
12881301
if (fReportErrors) {
@@ -1295,9 +1308,8 @@ protected boolean reopenFormattingElements(final HTMLElements.Element element) {
12951308
}
12961309

12971310
forceStartElement(info.qname, attributes, synthesizedAugs());
1298-
i++;
12991311

1300-
for ( ; i < size; i++) {
1312+
while(fFormattingStack.length > 0) {
13011313
info = fFormattingStack.pop();
13021314
attributes = info.attributes;
13031315
if (fReportErrors) {
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
try{}catch(u){try{}catch(u){try{}catch(u){try{}catch([0for([0for([0for([4for([2for([1for([1for([0for([]in
2+
E)]in
3+
E)]in
4+
E)]in
5+
E)]in
6+
E)]in
7+
E)]in
8+
E)]in
9+
Et)]){
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
(html
2+
(head
3+
)head
4+
(body
5+
"try{}catch(u){try{}catch(u){try{}catch(u){try{}catch([0for([0for([0for([4for([2for([1for([1for([0for([]in\nE)]in\nE)]in\nE)]in\nE)]in\nE)]in\nE)]in\nE)]in\nEt)]){
6+
)body
7+
)html
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"try{}catch(u){try{}catch(u){try{}catch(u){try{}catch([0for([0for([0for([4for([2for([1for([1for([0for([]in\nE)]in\nE)]in\nE)]in\nE)]in\nE)]in\nE)]in\nE)]in\nEt)]){
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<html><head></head><body>try&lbrace;&rbrace;catch&lpar;u&rpar;&lbrace;try&lbrace;&rbrace;catch&lpar;u&rpar;&lbrace;try&lbrace;&rbrace;catch&lpar;u&rpar;&lbrace;try&lbrace;&rbrace;catch&lpar;&lbrack;0for&lpar;&lbrack;0for&lpar;&lbrack;0for&lpar;&lbrack;4for&lpar;&lbrack;2for&lpar;&lbrack;1for&lpar;&lbrack;1for&lpar;&lbrack;0for&lpar;&lbrack;&rbrack;in
2+
E&rpar;&rbrack;in
3+
E&rpar;&rbrack;in
4+
E&rpar;&rbrack;in
5+
E&rpar;&rbrack;in
6+
E&rpar;&rbrack;in
7+
E&rpar;&rbrack;in
8+
E&rpar;&rbrack;in
9+
Et&rpar;&rbrack;&rpar;&lbrace;</body></html>
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
startDocument [(1,1,0) (1,1,0) false]
2+
startElement (localpart="html",rawname="html",uri="http://www.w3.org/1999/xhtml") [(-1,-1,-1) (-1,-1,-1) true]
3+
startElement (localpart="head",rawname="head",uri="http://www.w3.org/1999/xhtml") [(-1,-1,-1) (-1,-1,-1) true]
4+
endElement (localpart="head",rawname="head",uri="http://www.w3.org/1999/xhtml") [(-1,-1,-1) (-1,-1,-1) true]
5+
startElement (localpart="body",rawname="body",uri="http://www.w3.org/1999/xhtml") [(-1,-1,-1) (-1,-1,-1) true]
6+
characters 'try{}catch(u){try{}catch(u){try{}catch(u){try{}catch([0for([0for([0for([4for([2for([1for([1for([0for([]in
7+
E)]in
8+
E)]in
9+
E)]in
10+
E)]in
11+
E)]in
12+
E)]in
13+
E)]in
14+
Et)]){
15+
'[(1,1,0) (10,1,155) false]
16+
endElement (localpart="body",rawname="body") [(-1,-1,-1) (-1,-1,-1) true]
17+
endElement (localpart="html",rawname="html") [(-1,-1,-1) (-1,-1,-1) true]
18+
endDocument [(10,1,155) (10,1,155) false]
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
try{}catch(u){try{}catch(u){try{}catch(u){try{}catch([0for([0for([0for([4for([2for([1for([1for([0for([]in
2+
E)]in
3+
E)]in
4+
E)]in
5+
E)]in
6+
E)]in
7+
E)]in
8+
E)]in
9+
Et)]){
Binary file not shown.
Binary file not shown.
Binary file not shown.

0 commit comments

Comments
 (0)