Commit 8f66d7dc authored by Andrew Balholm's avatar Andrew Balholm Committed by Nigel Tao

exp/html: adjust inSelectIM to match spec

Simplify the flow of control.

Handle EOF, null bytes, <html>, <input>, <keygen>, <textarea>, <script>.

Pass 5 more tests.

R=golang-dev, rsc, nigeltao
CC=golang-dev
https://golang.org/cl/6220062
parent c4ea1c95
...@@ -69,6 +69,7 @@ const ( ...@@ -69,6 +69,7 @@ const (
tableScope tableScope
tableRowScope tableRowScope
tableBodyScope tableBodyScope
selectScope
) )
// popUntil pops the stack of open elements at the highest element whose tag // popUntil pops the stack of open elements at the highest element whose tag
...@@ -123,6 +124,10 @@ func (p *parser) indexOfElementInScope(s scope, matchTags ...string) int { ...@@ -123,6 +124,10 @@ func (p *parser) indexOfElementInScope(s scope, matchTags ...string) int {
if tag == "html" || tag == "table" { if tag == "html" || tag == "table" {
return -1 return -1
} }
case selectScope:
if tag != "optgroup" && tag != "option" {
return -1
}
default: default:
panic("unreachable") panic("unreachable")
} }
...@@ -1500,16 +1505,16 @@ func inCellIM(p *parser) bool { ...@@ -1500,16 +1505,16 @@ func inCellIM(p *parser) bool {
// Section 12.2.5.4.16. // Section 12.2.5.4.16.
func inSelectIM(p *parser) bool { func inSelectIM(p *parser) bool {
endSelect := false
switch p.tok.Type { switch p.tok.Type {
case ErrorToken: case ErrorToken:
// TODO. // Stop parsing.
return true
case TextToken: case TextToken:
p.addText(p.tok.Data) p.addText(strings.Replace(p.tok.Data, "\x00", "", -1))
case StartTagToken: case StartTagToken:
switch p.tok.Data { switch p.tok.Data {
case "html": case "html":
// TODO. return inBodyIM(p)
case "option": case "option":
if p.top().Data == "option" { if p.top().Data == "option" {
p.oe.pop() p.oe.pop()
...@@ -1524,13 +1529,17 @@ func inSelectIM(p *parser) bool { ...@@ -1524,13 +1529,17 @@ func inSelectIM(p *parser) bool {
} }
p.addElement(p.tok.Data, p.tok.Attr) p.addElement(p.tok.Data, p.tok.Attr)
case "select": case "select":
endSelect = true p.tok.Type = EndTagToken
return false
case "input", "keygen", "textarea": case "input", "keygen", "textarea":
// TODO. if p.elementInScope(selectScope, "select") {
case "script": p.parseImpliedToken(EndTagToken, "select", nil)
// TODO. return false
default: }
// Ignore the token. // Ignore the token.
return true
case "script":
return inHeadIM(p)
} }
case EndTagToken: case EndTagToken:
switch p.tok.Data { switch p.tok.Data {
...@@ -1547,19 +1556,20 @@ func inSelectIM(p *parser) bool { ...@@ -1547,19 +1556,20 @@ func inSelectIM(p *parser) bool {
p.oe = p.oe[:i] p.oe = p.oe[:i]
} }
case "select": case "select":
endSelect = true if p.popUntil(selectScope, "select") {
default: p.resetInsertionMode()
// Ignore the token. }
} }
case CommentToken: case CommentToken:
p.doc.Add(&Node{ p.doc.Add(&Node{
Type: CommentNode, Type: CommentNode,
Data: p.tok.Data, Data: p.tok.Data,
}) })
case DoctypeToken:
// Ignore the token.
return true
} }
if endSelect {
p.endSelect()
}
return true return true
} }
...@@ -1570,7 +1580,7 @@ func inSelectInTableIM(p *parser) bool { ...@@ -1570,7 +1580,7 @@ func inSelectInTableIM(p *parser) bool {
switch p.tok.Data { switch p.tok.Data {
case "caption", "table", "tbody", "tfoot", "thead", "tr", "td", "th": case "caption", "table", "tbody", "tfoot", "thead", "tr", "td", "th":
if p.tok.Type == StartTagToken || p.elementInScope(tableScope, p.tok.Data) { if p.tok.Type == StartTagToken || p.elementInScope(tableScope, p.tok.Data) {
p.endSelect() p.parseImpliedToken(EndTagToken, "select", nil)
return false return false
} else { } else {
// Ignore the token. // Ignore the token.
...@@ -1581,19 +1591,6 @@ func inSelectInTableIM(p *parser) bool { ...@@ -1581,19 +1591,6 @@ func inSelectInTableIM(p *parser) bool {
return inSelectIM(p) return inSelectIM(p)
} }
func (p *parser) endSelect() {
for i := len(p.oe) - 1; i >= 0; i-- {
switch p.oe[i].Data {
case "option", "optgroup":
continue
case "select":
p.oe = p.oe[:i]
p.resetInsertionMode()
}
return
}
}
// Section 12.2.5.4.18. // Section 12.2.5.4.18.
func afterBodyIM(p *parser) bool { func afterBodyIM(p *parser) bool {
switch p.tok.Type { switch p.tok.Type {
......
...@@ -9,9 +9,9 @@ PASS "<!doctype html><table><tr><style></script></style>abc" ...@@ -9,9 +9,9 @@ PASS "<!doctype html><table><tr><style></script></style>abc"
PASS "<!doctype html><table><tr><script></style></script>abc" PASS "<!doctype html><table><tr><script></style></script>abc"
PASS "<!doctype html><table><caption><style></script></style>abc" PASS "<!doctype html><table><caption><style></script></style>abc"
PASS "<!doctype html><table><td><style></script></style>abc" PASS "<!doctype html><table><td><style></script></style>abc"
FAIL "<!doctype html><select><script></style></script>abc" PASS "<!doctype html><select><script></style></script>abc"
FAIL "<!doctype html><table><select><script></style></script>abc" PASS "<!doctype html><table><select><script></style></script>abc"
FAIL "<!doctype html><table><tr><select><script></style></script>abc" PASS "<!doctype html><table><tr><select><script></style></script>abc"
PASS "<!doctype html><frameset></frameset><noframes>abc" PASS "<!doctype html><frameset></frameset><noframes>abc"
PASS "<!doctype html><frameset></frameset><noframes>abc</noframes><!--abc-->" PASS "<!doctype html><frameset></frameset><noframes>abc</noframes><!--abc-->"
PASS "<!doctype html><frameset></frameset></html><noframes>abc" PASS "<!doctype html><frameset></frameset></html><noframes>abc"
......
...@@ -10,7 +10,7 @@ PASS "<!doctype html><table><style> <tr>x </style> </table>" ...@@ -10,7 +10,7 @@ PASS "<!doctype html><table><style> <tr>x </style> </table>"
PASS "<!doctype html><table><TBODY><script> <tr>x </script> </table>" PASS "<!doctype html><table><TBODY><script> <tr>x </script> </table>"
PASS "<!doctype html><p><applet><p>X</p></applet>" PASS "<!doctype html><p><applet><p>X</p></applet>"
PASS "<!doctype html><listing>\nX</listing>" PASS "<!doctype html><listing>\nX</listing>"
FAIL "<!doctype html><select><input>X" PASS "<!doctype html><select><input>X"
PASS "<!doctype html><select><select>X" PASS "<!doctype html><select><select>X"
PASS "<!doctype html><table><input type=hidDEN></table>" PASS "<!doctype html><table><input type=hidDEN></table>"
PASS "<!doctype html><table>X<input type=hidDEN></table>" PASS "<!doctype html><table>X<input type=hidDEN></table>"
...@@ -27,4 +27,4 @@ PASS "<table><tr><td><code></code> </table>" ...@@ -27,4 +27,4 @@ PASS "<table><tr><td><code></code> </table>"
PASS "<table><b><tr><td>aaa</td></tr>bbb</table>ccc" PASS "<table><b><tr><td>aaa</td></tr>bbb</table>ccc"
PASS "A<table><tr> B</tr> B</table>" PASS "A<table><tr> B</tr> B</table>"
FAIL "A<table><tr> B</tr> </em>C</table>" FAIL "A<table><tr> B</tr> </em>C</table>"
FAIL "<select><keygen>" PASS "<select><keygen>"
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment