html: properly handle end script tag in fragment mode

Change-Id: I10af60ce9aa6ffc2f2bc330026f9e4bc5cb30bb7
Reviewed-on: https://go-review.googlesource.com/c/net/+/781892
Auto-Submit: Roland Shoemaker <roland@golang.org>
Reviewed-by: Nicholas Husin <nsh@golang.org>
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Nicholas Husin <husin@google.com>
diff --git a/html/parse_test.go b/html/parse_test.go
index d47a6cd..4dad767 100644
--- a/html/parse_test.go
+++ b/html/parse_test.go
@@ -246,7 +246,6 @@
 
 func TestParser(t *testing.T) {
 	skipTests := map[string]bool{
-		"testdata/html5lib-tests/tree-construction/tests4.dat/8":    true, // strange script case
 		"testdata/html5lib-tests/tree-construction/webkit02.dat/22": true, // xml attribute sort & replace
 	}
 
diff --git a/html/token.go b/html/token.go
index 09b0e7e..83fcf96 100644
--- a/html/token.go
+++ b/html/token.go
@@ -1300,9 +1300,22 @@
 		attrNames: make(map[string]bool),
 	}
 	if contextTag != "" {
+		// Per the "Parsing HTML Fragments" portion of the spec:
+		//    For performance reasons, an implementation that does not report errors
+		//    and that uses the actual state machine described in this specification
+		//    directly could use the PLAINTEXT state instead of the RAWTEXT and script
+		//    data states where those are mentioned in the list above. Except for
+		//    rules regarding parse errors, they are equivalent, since there is no
+		//    appropriate end tag token in the fragment case, yet they involve far
+		//    fewer state transitions.
+		//
+		// As such we just set everything to plaintext, which makes some complex parsing
+		// cases somewhat simpler.
 		switch s := strings.ToLower(contextTag); s {
-		case "iframe", "noembed", "noframes", "noscript", "plaintext", "script", "style", "title", "textarea", "xmp":
+		case "title", "textarea":
 			z.rawTag = s
+		case "style", "xmp", "iframe", "noembed", "noframes", "script", "noscript", "plaintext":
+			z.rawTag = "plaintext"
 		}
 	}
 	return z