Bug 742414 & Bug 731234 - Highlight script end tag correctly in View Source and avoid crashing when doing so. r=smaug.
authorHenri Sivonen <hsivonen@iki.fi>
Tue, 17 Apr 2012 14:53:52 +0300
changeset 91851 fdc8a3e8c956d48b0e7ed5812aa1122d464da46c
parent 91850 913f7811c0681b7485a61044502a1877f3c96006
child 91852 372d32e0ea61376eb4c20443a2e3794345617195
push id22480
push useremorley@mozilla.com
push dateWed, 18 Apr 2012 00:48:48 +0000
treeherdermozilla-central@93dfd98900ad [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs742414, 731234
milestone14.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 742414 & Bug 731234 - Highlight script end tag correctly in View Source and avoid crashing when doing so. r=smaug.
parser/html/nsHtml5Highlighter.cpp
parser/html/nsHtml5Highlighter.h
parser/htmlparser/tests/crashtests/742414-1.html
parser/htmlparser/tests/crashtests/crashtests.list
parser/htmlparser/tests/reftest/bug482921-1-ref.html
parser/htmlparser/tests/reftest/bug482921-1.html
parser/htmlparser/tests/reftest/bug731234-1-ref.html
parser/htmlparser/tests/reftest/bug731234-1.html
parser/htmlparser/tests/reftest/reftest.list
--- a/parser/html/nsHtml5Highlighter.cpp
+++ b/parser/html/nsHtml5Highlighter.cpp
@@ -158,19 +158,17 @@ nsHtml5Highlighter::Transition(PRInt32 a
       // We can transition on < and on &. Either way, we don't yet know the
       // role of the token, so open a span without class.
       if (aState == NS_HTML5TOKENIZER_CONSUME_CHARACTER_REFERENCE) {
         StartSpan();
         // Start another span for highlighting the ampersand
         StartSpan();
         mAmpersand = CurrentNode();
       } else {
-        EndCharacters();
-        StartSpan();
-        mCurrentRun = CurrentNode();
+        EndCharactersAndStartMarkupRun();
       }
       break;
     case NS_HTML5TOKENIZER_TAG_OPEN:
       switch (aState) {
         case NS_HTML5TOKENIZER_TAG_NAME:
           StartSpan(sStartTag);
           break;
         case NS_HTML5TOKENIZER_DATA:
@@ -408,26 +406,27 @@ nsHtml5Highlighter::Transition(PRInt32 a
         default:
           FinishTag();
           break;
       }
       break;
     case NS_HTML5TOKENIZER_SCRIPT_DATA_LESS_THAN_SIGN:
     case NS_HTML5TOKENIZER_SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN:
       if (aState == NS_HTML5TOKENIZER_NON_DATA_END_TAG_NAME) {
+        FlushCurrent();
+        StartSpan(); // don't know if it is "end-tag" yet :-(
         break;
       }
       FinishTag();
       break;
     case NS_HTML5TOKENIZER_SCRIPT_DATA_ESCAPED_DASH_DASH:
     case NS_HTML5TOKENIZER_SCRIPT_DATA_ESCAPED:
     case NS_HTML5TOKENIZER_SCRIPT_DATA_ESCAPED_DASH:
       if (aState == NS_HTML5TOKENIZER_SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN) {
-        EndCharacters();
-        StartSpan();
+        EndCharactersAndStartMarkupRun();
       }
       break;
       // Lots of double escape states omitted, because they don't highlight.
       // Likewise, only doctype states that can emit the doctype are of
       // interest. Otherwise, the transition out of bogus comment deals.
     case NS_HTML5TOKENIZER_BEFORE_DOCTYPE_NAME:
     case NS_HTML5TOKENIZER_DOCTYPE_NAME:
     case NS_HTML5TOKENIZER_AFTER_DOCTYPE_NAME:
@@ -550,22 +549,25 @@ nsHtml5Highlighter::StartCharacters()
   NS_PRECONDITION(!mInCharacters, "Already in characters!");
   FlushChars();
   Push(nsGkAtoms::span, nsnull);
   mCurrentRun = CurrentNode();
   mInCharacters = true;
 }
 
 void
-nsHtml5Highlighter::EndCharacters()
+nsHtml5Highlighter::EndCharactersAndStartMarkupRun()
 {
   NS_PRECONDITION(mInCharacters, "Not in characters!");
   FlushChars();
   Pop();
   mInCharacters = false;
+  // Now start markup run
+  StartSpan();
+  mCurrentRun = CurrentNode();
 }
 
 void
 nsHtml5Highlighter::StartA()
 {
   FlushChars();
   Push(nsGkAtoms::a, nsnull);
   AddClass(sAttributeValue);
--- a/parser/html/nsHtml5Highlighter.h
+++ b/parser/html/nsHtml5Highlighter.h
@@ -199,17 +199,17 @@ class nsHtml5Highlighter
     /**
      * Starts a wrapper around a run of characters.
      */
     void StartCharacters();
 
     /**
      * Ends a wrapper around a run of characters.
      */
-    void EndCharacters();
+    void EndCharactersAndStartMarkupRun();
 
     /**
      * Starts an <a>.
      */
     void StartA();
 
     /**
      * Flushes characters up to but not including the current one.
new file mode 100644
--- /dev/null
+++ b/parser/htmlparser/tests/crashtests/742414-1.html
@@ -0,0 +1,4 @@
+<script></script
+><script></script
+><script></script
+>
--- a/parser/htmlparser/tests/crashtests/crashtests.list
+++ b/parser/htmlparser/tests/crashtests/crashtests.list
@@ -45,8 +45,9 @@ load 536097-1.html
 load 563514-1.html
 load 574884-1.html
 load 574884-2.html
 load 591330-1.html
 load 650501-1.xhtml
 load 696651-1.html
 load view-source:699347-1.xml
 load 721313-1.html
+load view-source:742414-1.html
--- a/parser/htmlparser/tests/reftest/bug482921-1-ref.html
+++ b/parser/htmlparser/tests/reftest/bug482921-1-ref.html
@@ -2,17 +2,17 @@
 <span id></span><span>&lt;<span class="start-tag">html</span>&gt;</span>
 <span id></span><span>&lt;<span class="start-tag">head</span>&gt;</span>
 <span id></span><span>&lt;<span class="start-tag">title</span>&gt;</span><span>Title</span><span>&lt;/<span class="end-tag">title</span>&gt;</span>
 <span id></span><span>&lt;<span class="start-tag">script</span>&gt;</span>
 <span id></span>var lt = "&lt;";
 <span id></span>&lt;!--
 <span id></span>var s = "&lt;script&gt;foo&lt;/script&gt;";
 <span id></span>--&gt;
-<span id></span><span class="end-tag">&lt;/script&gt;</span><span></span><span class="comment">&lt;!-- Not quite optimal highlight there. --&gt;</span>
+<span id></span><span>&lt;/<span class="end-tag">script</span>&gt;</span><span></span><span class="comment">&lt;!-- Comment. --&gt;</span>
 <span id></span><span>&lt;<span class="start-tag">style</span>&gt;</span>
 <span id></span>/* &lt;/foo&gt; */
 <span id></span><span>&lt;/<span class="end-tag">style</span>&gt;</span>
 <span id></span><span>&lt;/<span class="end-tag">head</span>&gt;</span>
 <span id></span><span>&lt;<span class="start-tag">body</span>&gt;</span>
 <span id></span><span>&lt;<span class="start-tag">p</span>&gt;</span><span>Entity: <span class="entity"><span>&amp;</span>amp; </span></span><span>&lt;/<span class="end-tag">p</span>&gt;</span>
 <span id></span><span>&lt;<span class="start-tag">iframe</span>&gt;</span>&lt;img&gt;<span>&lt;/<span class="end-tag">iframe</span>&gt;</span>
 <span id></span><span>&lt;<span class="start-tag">noscript</span>&gt;</span>&lt;p&gt;Not para&lt;/p&gt;<span>&lt;/<span class="end-tag">noscript</span>&gt;</span>
--- a/parser/htmlparser/tests/reftest/bug482921-1.html
+++ b/parser/htmlparser/tests/reftest/bug482921-1.html
@@ -2,17 +2,17 @@
 <html>
 <head>
 <title>Title</title>
 <script>
 var lt = "<";
 <!--
 var s = "<script>foo</script>";
 -->
-</script><!-- Not quite optimal highlight there. -->
+</script><!-- Comment. -->
 <style>
 /* </foo> */
 </style>
 </head>
 <body>
 <p>Entity: &amp; </p>
 <iframe><img></iframe>
 <noscript><p>Not para</p></noscript>
new file mode 100644
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug731234-1-ref.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html><html><head><title></title><link rel="stylesheet" type="text/css" href="resource://gre-resources/viewsource.css"></head><body id="viewsource" class="wrap"><pre id><span class="doctype">&lt;!DOCTYPE html&gt;</span><span>
+<span id></span></span><span>&lt;<span class="start-tag">body</span>&gt;</span><span>
+<span id></span></span><span>&lt;<span class="start-tag">script</span>&gt;</span><span></span><span>&lt;/<span class="end-tag">script</span>&gt;</span><span>X
+<span id></span></span><span>&lt;<span class="start-tag">script</span>&gt;</span><span></span><span>&lt;/<span class="end-tag">script</span> &gt;</span><span>X
+<span id></span></span><span>&lt;<span class="start-tag">script</span>&gt;</span><span></span><span>&lt;/<span class="end-tag">script</span>
+<span id></span>&gt;</span><span>X
+<span id></span></span><span>&lt;<span class="start-tag">script</span>&gt;</span><span></span><span title="End tag had attributes." class="error">&lt;/<span class="end-tag">script</span> <span class="attribute-name">foo</span>&gt;</span><span>X
+<span id></span></span><span>&lt;<span class="start-tag">script</span>&gt;</span><span></span><span title="End tag had attributes." class="error">&lt;/<span class="end-tag">script</span> <span class="attribute-name">foo</span>=<a class="attribute-value">bar</a>&gt;</span><span>X
+<span id></span></span><span>&lt;<span class="start-tag">script</span>&gt;</span><span></span><span title="End tag had attributes." class="error">&lt;/<span class="end-tag">script</span> <span class="attribute-name">foo</span>="<a class="attribute-value">bar</a>"&gt;</span><span>X
+<span id></span></span><span>&lt;<span class="start-tag">script</span>&gt;</span><span></span><span>&lt;!</span><span>--</span><span>&lt;/<span class="end-tag">script</span>&gt;</span><span>X
+<span id></span></span><span>&lt;<span class="start-tag">script</span>&gt;</span><span></span><span>&lt;!</span><span>-- </span><span>&lt;/<span class="end-tag">script</span>&gt;</span><span>X
+<span id></span></span><span>&lt;<span class="start-tag">script</span>&gt;</span><span></span><span>&lt;!</span><span>-- </span><span>&lt;/<span class="end-tag">script</span> &gt;</span><span>X
+<span id></span></span><span>&lt;<span class="start-tag">script</span>&gt;</span><span></span><span>&lt;!</span><span>-- </span><span>&lt;/<span class="end-tag">script</span>
+<span id></span>&gt;</span><span>X
+<span id></span></span><span>&lt;<span class="start-tag">script</span>&gt;</span><span></span><span>&lt;!</span><span>-- </span><span title="End tag had attributes." class="error">&lt;/<span class="end-tag">script</span> <span class="attribute-name">foo</span>&gt;</span><span>X
+<span id></span></span><span>&lt;<span class="start-tag">script</span>&gt;</span><span></span><span>&lt;!</span><span>-- </span><span title="End tag had attributes." class="error">&lt;/<span class="end-tag">script</span> <span class="attribute-name">foo</span>=<a class="attribute-value">bar</a>&gt;</span><span>X
+<span id></span></span><span>&lt;<span class="start-tag">script</span>&gt;</span><span></span><span>&lt;!</span><span>-- </span><span title="End tag had attributes." class="error">&lt;/<span class="end-tag">script</span> <span class="attribute-name">foo</span>="<a class="attribute-value">bar</a>"&gt;</span><span>X
+<span id></span></span><span>&lt;<span class="start-tag">script</span>&gt;</span><span></span><span>&lt;!</span><span>-- -</span><span>&lt;/<span class="end-tag">script</span>&gt;</span><span>X
+<span id></span></span><span>&lt;<span class="start-tag">script</span>&gt;</span><span></span><span>&lt;!</span><span>-- --</span><span>&lt;/<span class="end-tag">script</span>&gt;</span><span>X
+<span id></span></span><span>&lt;<span class="start-tag">script</span>&gt;</span><span></span><span>&lt;!</span><span>-- --&gt;</span><span>&lt;/<span class="end-tag">script</span>&gt;</span><span>X
+<span id></span></span><span>&lt;<span class="start-tag">script</span>&gt;</span><span></span><span>&lt;!</span><span>--</span><span>&lt;s</span><span>cript&gt; &lt;/script&gt; </span><span>&lt;/<span class="end-tag">script</span>&gt;</span><span>X
+<span id></span></span><span>&lt;<span class="start-tag">script</span>&gt;</span><span></span><span>&lt;!</span><span>--</span><span>&lt;s</span><span>cript&gt; &lt;/script&gt; --&gt;</span><span>&lt;/<span class="end-tag">script</span>&gt;</span><span>X
+<span id></span></span><span>&lt;<span class="start-tag">script</span>&gt;</span><span></span><span>&lt;!</span><span>--</span><span>&lt;s</span><span>cript &lt;/script&gt; --&gt;</span><span>&lt;/<span class="end-tag">script</span>&gt;</span><span>X
+<span id></span></span><span>&lt;<span class="start-tag">script</span>&gt;</span><span></span><span>&lt;!</span><span>--</span><span>&lt;s</span><span>cript&gt; &lt;/script  &gt; --&gt;</span><span>&lt;/<span class="end-tag">script</span>&gt;</span><span>X
+<span id></span></span><span>&lt;<span class="start-tag">script</span>&gt;</span><span></span><span>&lt;!</span><span>--</span><span>&lt;s</span><span>cript&gt; &lt;/script  foo&gt; --&gt;</span><span>&lt;/<span class="end-tag">script</span>&gt;</span><span>X
+<span id></span></span><span>&lt;<span class="start-tag">script</span>&gt;</span><span></span><span>&lt;!</span><span>--</span><span>&lt;s</span><span>cript&gt; &lt;/script  foo=bar&gt; --&gt;</span><span>&lt;/<span class="end-tag">script</span>&gt;</span><span>X
+<span id></span></span><span>&lt;<span class="start-tag">script</span>&gt;</span><span></span><span>&lt;!</span><span>--</span><span>&lt;s</span><span>cript&gt; &lt;/script  foo="bar"&gt; --&gt;</span><span>&lt;/<span class="end-tag">script</span>&gt;</span><span>X
+<span id></span></span>
+</pre>
+<!-- View source CSS matches the <pre id> and <span id> elements and produces line numbers. -->
new file mode 100644
--- /dev/null
+++ b/parser/htmlparser/tests/reftest/bug731234-1.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<body>
+<script></script>X
+<script></script >X
+<script></script
+>X
+<script></script foo>X
+<script></script foo=bar>X
+<script></script foo="bar">X
+<script><!--</script>X
+<script><!-- </script>X
+<script><!-- </script >X
+<script><!-- </script
+>X
+<script><!-- </script foo>X
+<script><!-- </script foo=bar>X
+<script><!-- </script foo="bar">X
+<script><!-- -</script>X
+<script><!-- --</script>X
+<script><!-- --></script>X
+<script><!--<script> </script> </script>X
+<script><!--<script> </script> --></script>X
+<script><!--<script </script> --></script>X
+<script><!--<script> </script  > --></script>X
+<script><!--<script> </script  foo> --></script>X
+<script><!--<script> </script  foo=bar> --></script>X
+<script><!--<script> </script  foo="bar"> --></script>X
--- a/parser/htmlparser/tests/reftest/reftest.list
+++ b/parser/htmlparser/tests/reftest/reftest.list
@@ -14,8 +14,9 @@ fails-if(/^Windows\x20NT\x206\.1/.test(h
 == bug659763-4.html bug659763-4-ref.html
 == bug659763-5.html bug659763-5-ref.html
 == bug659763-6.html bug659763-6-ref.html
 == view-source:bug673094-1.html view-source:bug673094-1-ref.html
 == bug696651-1.html bug696651-1-ref.html
 == bug696651-2.html bug696651-2-ref.html
 == view-source:bug700260-1.html view-source:bug700260-1-ref.html
 == view-source:bug704667-1.html bug704667-1-ref.html
+== view-source:bug731234-1.html bug731234-1-ref.html