Backed out changesets b242651c3c1b (bug 229827), b36eaac9ecf8, and 40f38a8aa660 (bug 663291) for mochitest-3/4 failures.
authorRyan VanderMeulen <ryanvm@gmail.com>
Fri, 16 Nov 2012 16:59:38 -0500
changeset 113555 20fcf80a5242a056503b6427f1e98d80c42f2132
parent 113554 84384977f87b5ae9427848ddaeb3cfe60b8832fd
child 113556 bf81463952c79f4793f217f8645c12491f0a42b3
push id18230
push userryanvm@gmail.com
push dateFri, 16 Nov 2012 22:03:01 +0000
treeherdermozilla-inbound@20fcf80a5242 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs229827, 663291
milestone19.0a1
backs outb242651c3c1bdd23318560331fd3ffb0e95a8a7a
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
Backed out changesets b242651c3c1b (bug 229827), b36eaac9ecf8, and 40f38a8aa660 (bug 663291) for mochitest-3/4 failures. CLOSED TREE
content/base/test/file_bug708620-2.html
content/base/test/file_bug708620.html
content/base/test/test_bug513194.html
content/base/test/test_bug631615.html
content/base/test/test_bug708620.html
content/events/test/test_bug489671.html
dom/workers/test/errorPropagation_iframe.html
dom/workers/test/test_errorPropagation.html
layout/style/ErrorReporter.cpp
layout/style/nsCSSScanner.cpp
layout/style/nsRuleNode.cpp
layout/style/nsStyleUtil.cpp
layout/style/nsStyleUtil.h
layout/style/test/Makefile.in
layout/style/test/property_database.js
layout/style/test/test_parser_diagnostics_unprintables.html
parser/htmlparser/tests/mochitest/Makefile.in
parser/htmlparser/tests/mochitest/test_bug672453.html
testing/mochitest/tests/SimpleTest/SimpleTest.js
testing/specialpowers/content/specialpowers.js
testing/specialpowers/content/specialpowersAPI.js
--- a/content/base/test/file_bug708620-2.html
+++ b/content/base/test/file_bug708620-2.html
@@ -1,4 +1,5 @@
 <!DOCTYPE html>
 <meta charset=utf-8>
 <title>Non-UTF form target</title>
 <body onload="parent.finish();">
+
--- a/content/base/test/file_bug708620.html
+++ b/content/base/test/file_bug708620.html
@@ -1,7 +1,8 @@
-<!doctype html>
+<!DOCTYPE html>
 <meta charset=windows-1252>
 <title>Non-UTF form</title>
 <body onload="document.forms[0].submit();">
 <form action="file_bug708620-2.html">
 <input name=foo value=bar>
 </form>
+
--- a/content/base/test/test_bug513194.html
+++ b/content/base/test/test_bug513194.html
@@ -1,27 +1,72 @@
-<!doctype html>
+<!DOCTYPE HTML>
 <html>
 <!--
 https://bugzilla.mozilla.org/show_bug.cgi?id=513194
 -->
 <head>
   <meta charset="utf-8">
   <title>Test for Bug 513194</title>
-  <script src="/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" href="/tests/SimpleTest/test.css">
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 <body>
-<a target="_blank"
-   href="https://bugzilla.mozilla.org/show_bug.cgi?id=631615"
-   >Mozilla Bug 513194</a>
-<script>
-// The use of document.write is deliberate.  We are testing for the
-// HTML parser to call the CSS parser once and only once when it
-// encounters a new <style> element.
-SimpleTest.runTestExpectingConsoleMessages(
-  function () { document.write("<style>qux { foo : bar; }<\/style>") },
-  [{ errorMessage: /Unknown property/ }]
-);
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+  netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+
+  const Cc = Components.classes;
+  const Ci = Components.interfaces;
+  const Cr = Components.results;
+
+  var consoleService =
+    Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService);
+
+  var consoleListener = {
+    seenError: false,
+
+    observe: function(message) {
+      netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+
+      if (this.seenError) {
+        ok(false, "Seen too many errors!");
+      }
+      
+      this.seenError = true;
+
+      ok(message.message.indexOf("Unknown property") > -1,
+         "Wrong message");
+    },
+    
+    finish: function() {
+      ok(this.seenError , "Didn't get message.");
+      SimpleTest.finish();
+    },
+
+    QueryInterface: function(iid) {
+      netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+      if (iid.equals(Ci.nsIConsoleListener) ||
+          iid.equals(Ci.nsISupports)) {
+        return this;
+      }
+      throw Cr.NS_NOINTERFACE;
+    }
+  };
+
+  consoleService.reset();
+  consoleService.registerListener(consoleListener);
+  SimpleTest.waitForExplicitFinish();
+
+  document.write("<style>qux { foo: bar; }<\/style>");
+
+  function done() {
+    netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+    consoleListener.finish();
+    consoleService.unregisterListener(consoleListener);
+  }
+  setTimeout(done, 0);
 </script>
+</pre>
 </body>
 </html>
 
--- a/content/base/test/test_bug631615.html
+++ b/content/base/test/test_bug631615.html
@@ -1,38 +1,95 @@
-<!doctype html>
+<!DOCTYPE HTML>
 <html>
 <!--
 https://bugzilla.mozilla.org/show_bug.cgi?id=631615
 -->
 <head>
   <meta charset="utf-8">
   <title>Test for Bug 631615</title>
-  <script src="/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" href="/tests/SimpleTest/test.css">
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
 <body>
-<a target="_blank"
-   href="https://bugzilla.mozilla.org/show_bug.cgi?id=631615"
-   >Mozilla Bug 631615</a>
-<pre id="monitor"></pre>
-<script>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=631615">Mozilla Bug 631615</a>
+<pre id="monitor">
+</pre>
+<script type="application/javascript">
+
+netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+const Cr = Components.results;
+
+var consoleService =
+  Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService);
+
+var messageCount = 0;
+var monitor = document.getElementById("monitor");
+
+var listener = {
+  observe: function(message) {
+    netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+
+    if (message.message === "sentinel") {
+      is(messageCount, 0, "should have been no console messages");
+      removeListener();
+      SimpleTest.finish();
+    } else {
+      messageCount++;
+      var err = "" + messageCount + ": " + message.message + "\n";
+      monitor.appendChild(document.createTextNode(err));
+    }
+  },
+
+  QueryInterface: function(iid) {
+    netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+    if (iid.equals(Ci.nsIConsoleListener) ||
+        iid.equals(Ci.nsISupports)) {
+      return this;
+    }
+    throw Cr.NS_NOINTERFACE;
+  }
+};
+
+function addListener() {
+  netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+  consoleService.reset();
+  consoleService.registerListener(listener);
+}
+
+function removeListener() {
+  netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+  consoleService.unregisterListener(listener);
+}
+
+function postSentinel() {
+  netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+  consoleService.logStringMessage("sentinel");
+}
+
+SimpleTest.waitForExplicitFinish();
+
 function doTest() {
-  var monitor = document.getElementById("monitor");
   var html = document.documentElement;
   var results;
   var matches = html.matchesSelector || html.mozMatchesSelector;
 
+  addListener();
   try {
     results = "return: " +
       matches.call(html, "[test!='']:sizzle") + "\n";
   } catch (e) {
     results = "throws: " + e + "\n";
   }
 
   monitor.appendChild(document.createTextNode(results));
   is(results.slice(0, 6), "throws", "looking for an exception");
-}
 
-SimpleTest.runTestExpectingConsoleMessages(doTest, []);
+  postSentinel();
+}
+doTest();
+
 </script>
 </body>
 </html>
--- a/content/base/test/test_bug708620.html
+++ b/content/base/test/test_bug708620.html
@@ -1,41 +1,66 @@
-<!doctype html>
+<!DOCTYPE HTML>
 <html>
 <!--
 https://bugzilla.mozilla.org/show_bug.cgi?id=708620
 -->
 <head>
   <meta charset="utf-8">
   <title>Test for Bug 708620</title>
-  <script src="/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" href="/tests/SimpleTest/test.css">
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
-<body>
-<a target="_blank"
-   href="https://bugzilla.mozilla.org/show_bug.cgi?id=708620"
-   >Mozilla Bug 708620</a>
-<iframe></iframe>
-<script>
+<body onload="start();">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=708620">Mozilla Bug 708620</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  <iframe></iframe>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
 /** Test for Bug 708620 **/
 
 SimpleTest.waitForExplicitFinish();
-SimpleTest.monitorConsole(SimpleTest.finish, [
-  { errorMessage: "A form was submitted in the windows-1252 encoding "+
-                  "which cannot encode all Unicode characters, so user "+
-                  "input may get corrupted. To avoid this problem, the "+
-                  "page should be changed so that the form is submitted "+
-                  "in the UTF-8 encoding either by changing the encoding "+
-                  "of the page itself to UTF-8 or by specifying "+
-                  "accept-charset=utf-8 on the form element.",
-    isWarning: true }
-]);
+
+var tests = [
+  "file_bug708620.html"
+];
+
+function resolveURL(relative) {
+  var a = document.createElement('a');
+  a.href = relative;
+  return a.href;
+}
+
+var resolvedURL = resolveURL(tests[0]);
 
-window.onload = function () {
-  document.getElementsByTagName("iframe")[0].src = "file_bug708620.html";
+var expectedErrors = [
+  '[JavaScript Warning: "A form was submitted in the windows-1252 encoding which cannot encode all Unicode characters, so user input may get corrupted. To avoid this problem, the page should be changed so that the form is submitted in the UTF-8 encoding either by changing the encoding of the page itself to UTF-8 or by specifying accept-charset=utf-8 on the form element." {file: "' + resolvedURL + '" line: 1}]'
+];
+
+function consoleError(msg, fileName) {
+  // Ignore messages not generated by the test
+  if (fileName !== resolvedURL) {
+    return;
+  }
+  var expected = expectedErrors.shift();
+  is(msg, expected, "Not the right error message");
+}
+
+SpecialPowers.addErrorConsoleListener(consoleError);
+
+function start() {
+  var url = tests.shift();
+  document.getElementsByTagName("iframe")[0].src = url;
 }
 
 function finish() {
-  SimpleTest.endMonitorConsole();
+    is(expectedErrors.length, 0, "The error supply was not exhausted");
+    SpecialPowers.removeErrorConsoleListener(consoleError);
+    SimpleTest.finish();
 }
+
 </script>
+</pre>
 </body>
 </html>
--- a/content/events/test/test_bug489671.html
+++ b/content/events/test/test_bug489671.html
@@ -1,55 +1,98 @@
-<!doctype html>
+<!DOCTYPE HTML>
 <html>
 <!--
 https://bugzilla.mozilla.org/show_bug.cgi?id=489671
 -->
 <head>
   <meta charset="utf-8">
   <title>Test for Bug 489671</title>
-  <script src="/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" href="/tests/SimpleTest/test.css">
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
 <body>
-<a target="_blank"
-   href="https://bugzilla.mozilla.org/show_bug.cgi?id=489671"
-   >Mozilla Bug 489671</a>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=489671">Mozilla Bug 489671</a>
 <p id="display" onclick="throw 'Got click'"></p>
-<script>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 489671 **/
+netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+const Cr = Components.results;
+
+var listener = {
+  observe: function(message) {
+    netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+
+    is(message.QueryInterface(Ci.nsIScriptError).errorMessage,
+       "uncaught exception: Got click");
+    SimpleTest.executeSoon(nextTest);
+  },
+
+  QueryInterface: function(iid) {
+    netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+    if (iid.equals(Ci.nsIConsoleListener) ||
+        iid.equals(Ci.nsISupports)) {
+      return this;
+    }
+    throw Cr.NS_NOINTERFACE;
+  }
+};
+
+
+function addListener() {
+  netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+  var consoleService =
+    Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService);
+  consoleService.reset();
+  consoleService.registerListener(listener);
+}
+
+function removeListener() {
+  netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+  var consoleService =
+    Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService);
+  consoleService.unregisterListener(listener);
+}
+
+SimpleTest.waitForExplicitFinish();
+
+addListener();
 // override window.onerror so it won't see our exceptions
 window.onerror = function() {}
 
 var testNum = 0;
-function doTest() {
+function nextTest() {
   switch(testNum++) {
     case 0:
       var event = document.createEvent("MouseEvents");
       event.initMouseEvent("click", true, true, document.defaultView,
                            0, 0, 0, 0, 0, false, false, false, false, 0, null);
       $("display").dispatchEvent(event);
       break;
     case 1:
       var script = document.createElement("script");
       script.textContent = "throw 'Got click'";
       document.body.appendChild(script);
       break;
     case 2:
       window.setTimeout("throw 'Got click'", 0);
       break;
     case 3:
-      SimpleTest.endMonitorConsole();
-      return;
+      removeListener();
+      SimpleTest.finish();
+      break;
   }
-  SimpleTest.executeSoon(doTest);
 }
 
-SimpleTest.waitForExplicitFinish();
-SimpleTest.monitorConsole(SimpleTest.finish, [
-  { errorMessage: "uncaught exception: Got click" },
-  { errorMessage: "uncaught exception: Got click" },
-  { errorMessage: "uncaught exception: Got click" }
-]);
+nextTest();
 
-doTest();
 </script>
+</pre>
 </body>
 </html>
--- a/dom/workers/test/errorPropagation_iframe.html
+++ b/dom/workers/test/errorPropagation_iframe.html
@@ -13,18 +13,18 @@
         var seenWindowError;
         window.onerror = function(message, filename, lineno) {
           if (!seenWindowError) {
             seenWindowError = true;
             messageCallback({
               type: "window",
               data: { message: message, filename: filename, lineno: lineno }
             });
+            return true;
           }
-          return false;
         };
 
         worker = new Worker("errorPropagation_worker.js");
 
         worker.onmessage = function(event) {
           messageCallback(event.data);
         };
 
--- a/dom/workers/test/test_errorPropagation.html
+++ b/dom/workers/test/test_errorPropagation.html
@@ -31,50 +31,36 @@
         if (event.type == "scope") {
           scopeErrorCount++;
         }
         else if (event.type == "worker") {
           workerErrorCount++;
         }
         else if (event.type == "window") {
           windowErrorCount++;
-          workerFrame.stop();
-          // do this via executeSoon to give the workers a chance to
-          // be cleaned up
-          SimpleTest.executeSoon(SimpleTest.endMonitorConsole);
         }
         else {
           ok(false, "Bad event type: " + event.type);
         }
 
         is(event.data.message, errorMessage, "Correct message event.message");
         is(event.data.filename, errorFilename,
            "Correct message event.filename");
         is(event.data.lineno, errorLineno, "Correct message event.lineno");
-      }
 
-      function finish() {
-        is(scopeErrorCount, workerCount, "Good number of scope errors");
-        is(workerErrorCount, workerCount, "Good number of worker errors");
-        is(windowErrorCount, 1, "Good number of window errors");
-        SimpleTest.finish();
+        if (windowErrorCount == 1) {
+          is(scopeErrorCount, workerCount, "Good number of scope errors");
+          is(workerErrorCount, workerCount, "Good number of worker errors");
+          workerFrame.stop();
+          SimpleTest.finish();
+        }
       }
 
       function workerFrameLoaded() {
         workerFrame = document.getElementById("workerFrame").contentWindow;
-
-        SimpleTest.monitorConsole(finish, [
-          { 'isScriptError': true,
-            'isWarning': false,
-            'isException': false,
-            'sourceName': errorFilename,
-            'lineNumber': errorLineno,
-            'errorMessage': errorMessage }
-        ]);
-
         workerFrame.start(workerCount, messageListener);
       }
 
       SimpleTest.waitForExplicitFinish();
     </script>
   </body>
 </html>
 
--- a/layout/style/ErrorReporter.cpp
+++ b/layout/style/ErrorReporter.cpp
@@ -12,17 +12,16 @@
 #include "nsCSSScanner.h"
 #include "nsCSSStyleSheet.h"
 #include "nsIConsoleService.h"
 #include "nsIDocument.h"
 #include "nsIFactory.h"
 #include "nsIScriptError.h"
 #include "nsIServiceManager.h"
 #include "nsIStringBundle.h"
-#include "nsStyleUtil.h"
 #include "nsThreadUtils.h"
 
 #ifdef CSS_REPORT_PARSE_ERRORS
 
 using mozilla::Preferences;
 namespace services = mozilla::services;
 
 namespace {
@@ -248,20 +247,17 @@ ErrorReporter::ReportUnexpected(const ch
 }
 
 void
 ErrorReporter::ReportUnexpected(const char *aMessage,
                                 const nsString &aParam)
 {
   if (!ShouldReportErrors()) return;
 
-  nsAutoString qparam;
-  nsStyleUtil::AppendEscapedCSSIdent(aParam, qparam);
-  const PRUnichar *params[1] = { qparam.get() };
-
+  const PRUnichar *params[1] = { aParam.get() };
   nsAutoString str;
   sStringBundle->FormatStringFromName(NS_ConvertASCIItoUTF16(aMessage).get(),
                                       params, ArrayLength(params),
                                       getter_Copies(str));
   AddToError(str);
 }
 
 void
--- a/layout/style/nsCSSScanner.cpp
+++ b/layout/style/nsCSSScanner.cpp
@@ -4,17 +4,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 
 /* tokenization of CSS style sheets */
 
 #include <math.h> // must be first due to symbol conflicts
 
 #include "nsCSSScanner.h"
-#include "nsStyleUtil.h"
 #include "mozilla/css/ErrorReporter.h"
 #include "mozilla/Likely.h"
 #include "mozilla/Util.h"
 
 using mozilla::ArrayLength;
 
 static const uint8_t IS_HEX_DIGIT  = 0x01;
 static const uint8_t START_IDENT   = 0x02;
@@ -140,111 +139,93 @@ nsCSSToken::nsCSSToken()
 {
   mType = eCSSToken_Symbol;
 }
 
 void
 nsCSSToken::AppendToString(nsString& aBuffer) const
 {
   switch (mType) {
+    case eCSSToken_AtKeyword:
+      aBuffer.Append(PRUnichar('@')); // fall through intentional
     case eCSSToken_Ident:
-      nsStyleUtil::AppendEscapedCSSIdent(mIdent, aBuffer);
-      break;
-
-    case eCSSToken_AtKeyword:
-      aBuffer.Append('@');
-      nsStyleUtil::AppendEscapedCSSIdent(mIdent, aBuffer);
+    case eCSSToken_WhiteSpace:
+    case eCSSToken_Function:
+    case eCSSToken_HTMLComment:
+    case eCSSToken_URange:
+      aBuffer.Append(mIdent);
+      if (mType == eCSSToken_Function)
+        aBuffer.Append(PRUnichar('('));
       break;
-
-    case eCSSToken_ID:
-    case eCSSToken_Ref:
-      aBuffer.Append('#');
-      nsStyleUtil::AppendEscapedCSSIdent(mIdent, aBuffer);
-      break;
-
-    case eCSSToken_Function:
-      nsStyleUtil::AppendEscapedCSSIdent(mIdent, aBuffer);
-      aBuffer.Append('(');
-      break;
-
     case eCSSToken_URL:
     case eCSSToken_Bad_URL:
       aBuffer.AppendLiteral("url(");
       if (mSymbol != PRUnichar(0)) {
-        nsStyleUtil::AppendEscapedCSSString(mIdent, aBuffer, mSymbol);
-      } else {
-        aBuffer.Append(mIdent);
+        aBuffer.Append(mSymbol);
+      }
+      aBuffer.Append(mIdent);
+      if (mSymbol != PRUnichar(0)) {
+        aBuffer.Append(mSymbol);
       }
       if (mType == eCSSToken_URL) {
         aBuffer.Append(PRUnichar(')'));
       }
       break;
-
     case eCSSToken_Number:
       if (mIntegerValid) {
         aBuffer.AppendInt(mInteger, 10);
-      } else {
+      }
+      else {
         aBuffer.AppendFloat(mNumber);
       }
       break;
-
     case eCSSToken_Percentage:
       NS_ASSERTION(!mIntegerValid, "How did a percentage token get this set?");
       aBuffer.AppendFloat(mNumber * 100.0f);
       aBuffer.Append(PRUnichar('%'));
       break;
-
     case eCSSToken_Dimension:
       if (mIntegerValid) {
         aBuffer.AppendInt(mInteger, 10);
-      } else {
+      }
+      else {
         aBuffer.AppendFloat(mNumber);
       }
-      nsStyleUtil::AppendEscapedCSSIdent(mIdent, aBuffer);
+      aBuffer.Append(mIdent);
       break;
-
-    case eCSSToken_Bad_String:
-      nsStyleUtil::AppendEscapedCSSString(mIdent, aBuffer, mSymbol);
-      // remove the trailing quote character
-      aBuffer.Truncate(aBuffer.Length() - 1);
-      break;
-
     case eCSSToken_String:
-      nsStyleUtil::AppendEscapedCSSString(mIdent, aBuffer, mSymbol);
-      break;
-
+      aBuffer.Append(mSymbol);
+      aBuffer.Append(mIdent); // fall through intentional
     case eCSSToken_Symbol:
       aBuffer.Append(mSymbol);
       break;
-
-    case eCSSToken_WhiteSpace:
-      aBuffer.Append(' ');
-      break;
-
-    case eCSSToken_HTMLComment:
-    case eCSSToken_URange:
+    case eCSSToken_ID:
+    case eCSSToken_Ref:
+      aBuffer.Append(PRUnichar('#'));
       aBuffer.Append(mIdent);
       break;
-
     case eCSSToken_Includes:
       aBuffer.AppendLiteral("~=");
       break;
     case eCSSToken_Dashmatch:
       aBuffer.AppendLiteral("|=");
       break;
     case eCSSToken_Beginsmatch:
       aBuffer.AppendLiteral("^=");
       break;
     case eCSSToken_Endsmatch:
       aBuffer.AppendLiteral("$=");
       break;
     case eCSSToken_Containsmatch:
       aBuffer.AppendLiteral("*=");
       break;
-
+    case eCSSToken_Bad_String:
+      aBuffer.Append(mSymbol);
+      aBuffer.Append(mIdent);
+      break;
     default:
       NS_ERROR("invalid token type");
       break;
   }
 }
 
 nsCSSScanner::nsCSSScanner(const nsAString& aBuffer, uint32_t aLineNumber)
   : mReadPointer(aBuffer.BeginReading())
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -367,19 +367,18 @@ static nscoord CalcLengthWith(const nsCS
     aStyleFont ? aStyleFont : aStyleContext->GetStyleFont();
   if (aFontSize == -1) {
     // XXX Should this be styleFont->mSize instead to avoid taking minfontsize
     // prefs into account?
     aFontSize = styleFont->mFont.size;
   }
   switch (aValue.GetUnit()) {
     case eCSSUnit_EM: {
-      // CSS2.1 specifies that this unit scales to the computed font
-      // size, not the em-width in the font metrics, despite the name.
       return ScaleCoord(aValue, float(aFontSize));
+      // XXX scale against font metrics height instead?
     }
     case eCSSUnit_XHeight: {
       nsRefPtr<nsFontMetrics> fm =
         GetMetricsFor(aPresContext, aStyleContext, styleFont,
                       aFontSize, aUseUserFontSet);
       return ScaleCoord(aValue, float(fm->XHeight()));
     }
     case eCSSUnit_Char: {
--- a/layout/style/nsStyleUtil.cpp
+++ b/layout/style/nsStyleUtil.cpp
@@ -50,99 +50,103 @@ bool nsStyleUtil::DashMatchCompare(const
     }
     else {
       result = StringBeginsWith(aAttributeValue, aSelectorValue, aComparator);
     }
   }
   return result;
 }
 
-void nsStyleUtil::AppendEscapedCSSString(const nsAString& aString,
-                                         nsAString& aReturn,
-                                         PRUnichar quoteChar)
+void nsStyleUtil::AppendEscapedCSSString(const nsString& aString,
+                                         nsAString& aReturn)
 {
-  NS_PRECONDITION(quoteChar == '\'' || quoteChar == '"',
-                  "CSS strings must be quoted with ' or \"");
-  aReturn.Append(quoteChar);
+  aReturn.Append(PRUnichar('"'));
 
-  const PRUnichar* in = aString.BeginReading();
-  const PRUnichar* const end = aString.EndReading();
-  for (; in != end; in++) {
-    if (*in < 0x20 || (*in >= 0x7F && *in < 0xA0)) {
-      // Escape U+0000 through U+001F and U+007F through U+009F numerically.
-      aReturn.AppendPrintf("\\%hX ", *in);
-    } else {
-      if (*in == '"' || *in == '\'' || *in == '\\') {
-        // Escape backslash and quote characters symbolically.
-        // It's not technically necessary to escape the quote
-        // character that isn't being used to delimit the string,
-        // but we do it anyway because that makes testing simpler.
-        aReturn.Append(PRUnichar('\\'));
-      }
-      aReturn.Append(*in);
+  const nsString::char_type* in = aString.get();
+  const nsString::char_type* const end = in + aString.Length();
+  for (; in != end; in++)
+  {
+    if (*in < 0x20)
+    {
+     // Escape all characters below 0x20 numerically.
+   
+     /*
+      This is the buffer into which snprintf should write. As the hex. value is,
+      for numbers below 0x20, max. 2 characters long, we don't need more than 5
+      characters ("\XX "+NUL).
+     */
+     PRUnichar buf[5];
+     nsTextFormatter::snprintf(buf, ArrayLength(buf), NS_LITERAL_STRING("\\%hX ").get(), *in);
+     aReturn.Append(buf);
+   
+    } else switch (*in) {
+      // Special characters which should be escaped: Quotes and backslash
+      case '\\':
+      case '\"':
+      case '\'':
+       aReturn.Append(PRUnichar('\\'));
+      // And now, after the eventual escaping character, the actual one.
+      default:
+       aReturn.Append(PRUnichar(*in));
     }
   }
 
-  aReturn.Append(quoteChar);
+  aReturn.Append(PRUnichar('"'));
 }
 
 /* static */ void
-nsStyleUtil::AppendEscapedCSSIdent(const nsAString& aIdent, nsAString& aReturn)
+nsStyleUtil::AppendEscapedCSSIdent(const nsString& aIdent, nsAString& aReturn)
 {
   // The relevant parts of the CSS grammar are:
   //   ident    [-]?{nmstart}{nmchar}*
   //   nmstart  [_a-z]|{nonascii}|{escape}
   //   nmchar   [_a-z0-9-]|{nonascii}|{escape}
   //   nonascii [^\0-\177]
   //   escape   {unicode}|\\[^\n\r\f0-9a-f]
   //   unicode  \\[0-9a-f]{1,6}(\r\n|[ \n\r\t\f])?
   // from http://www.w3.org/TR/CSS21/syndata.html#tokenization
 
-  const PRUnichar* in = aIdent.BeginReading();
-  const PRUnichar* const end = aIdent.EndReading();
+  const nsString::char_type* in = aIdent.get();
+  const nsString::char_type* const end = in + aIdent.Length();
 
-  if (in == end)
-    return;
-
-  // A leading dash does not need to be escaped as long as it is not the
-  // *only* character in the identifier.
-  if (in + 1 != end && *in == '-') {
+  // Deal with the leading dash separately so we don't need to
+  // unnecessarily escape digits.
+  if (in != end && *in == '-') {
     aReturn.Append(PRUnichar('-'));
     ++in;
   }
 
-  // Escape a digit at the start (including after a dash),
-  // numerically.  If we didn't escape it numerically, it would get
-  // interpreted as a numeric escape for the wrong character.
-  // A second dash immediately after a leading dash must also be
-  // escaped, but this may be done symbolically.
-  if (in != end && (*in == '-' ||
-                    ('0' <= *in && *in <= '9'))) {
-    if (*in == '-') {
-      aReturn.Append(PRUnichar('\\'));
-      aReturn.Append(PRUnichar('-'));
+  bool first = true;
+  for (; in != end; ++in, first = false)
+  {
+    if (*in < 0x20 || (first && '0' <= *in && *in <= '9'))
+    {
+      // Escape all characters below 0x20, and digits at the start
+      // (including after a dash), numerically.  If we didn't escape
+      // digits numerically, they'd get interpreted as a numeric escape
+      // for the wrong character.
+
+      /*
+       This is the buffer into which snprintf should write. As the hex.
+       value is, for numbers below 0x7F, max. 2 characters long, we
+       don't need more than 5 characters ("\XX "+NUL).
+      */
+      PRUnichar buf[5];
+      nsTextFormatter::snprintf(buf, ArrayLength(buf),
+                                NS_LITERAL_STRING("\\%hX ").get(), *in);
+      aReturn.Append(buf);
     } else {
-      aReturn.AppendPrintf("\\%hX ", *in);
-    }
-    ++in;
-  }
-
-  for (; in != end; ++in) {
-    PRUnichar ch = *in;
-    if (ch < 0x20 || (0x7F <= ch && ch < 0xA0)) {
-      // Escape U+0000 through U+001F and U+007F through U+009F numerically.
-      aReturn.AppendPrintf("\\%hX ", *in);
-    } else {
-      // Escape ASCII non-identifier printables as a backslash plus
-      // the character.
-      if (ch < 0x7F &&
-          ch != '_' && ch != '-' &&
-          (ch < '0' || '9' < ch) &&
-          (ch < 'A' || 'Z' < ch) &&
-          (ch < 'a' || 'z' < ch)) {
+      PRUnichar ch = *in;
+      if (!((ch == PRUnichar('_')) ||
+            (PRUnichar('A') <= ch && ch <= PRUnichar('Z')) ||
+            (PRUnichar('a') <= ch && ch <= PRUnichar('z')) ||
+            PRUnichar(0x80) <= ch ||
+            (!first && ch == PRUnichar('-')) ||
+            (PRUnichar('0') <= ch && ch <= PRUnichar('9')))) {
+        // Character needs to be escaped
         aReturn.Append(PRUnichar('\\'));
       }
       aReturn.Append(ch);
     }
   }
 }
 
 /* static */ void
--- a/layout/style/nsStyleUtil.h
+++ b/layout/style/nsStyleUtil.h
@@ -20,27 +20,24 @@ class nsIContent;
 
 // Style utility functions
 class nsStyleUtil {
 public:
 
  static bool DashMatchCompare(const nsAString& aAttributeValue,
                                 const nsAString& aSelectorValue,
                                 const nsStringComparator& aComparator);
-
-  // Append a quoted (with 'quoteChar') and escaped version of aString
-  // to aResult.  'quoteChar' must be ' or ".
-  static void AppendEscapedCSSString(const nsAString& aString,
-                                     nsAString& aResult,
-                                     PRUnichar quoteChar = '"');
-
+                                
+  // Append a quoted (with "") and escaped version of aString to aResult.
+  static void AppendEscapedCSSString(const nsString& aString,
+                                     nsAString& aResult);
   // Append the identifier given by |aIdent| to |aResult|, with
   // appropriate escaping so that it can be reparsed to the same
   // identifier.
-  static void AppendEscapedCSSIdent(const nsAString& aIdent,
+  static void AppendEscapedCSSIdent(const nsString& aIdent,
                                     nsAString& aResult);
 
   // Append a bitmask-valued property's value(s) (space-separated) to aResult.
   static void AppendBitmaskCSSValue(nsCSSProperty aProperty,
                                     int32_t aMaskedValue,
                                     int32_t aFirstMask,
                                     int32_t aLastMask,
                                     nsAString& aResult);
--- a/layout/style/test/Makefile.in
+++ b/layout/style/test/Makefile.in
@@ -113,17 +113,16 @@ MOCHITEST_FILES =	test_acid3_test46.html
 		test_media_queries_dynamic_xbl.html \
 		test_media_query_list.html \
 		test_moz_device_pixel_ratio.html \
 		test_namespace_rule.html \
 		test_of_type_selectors.xhtml \
 		test_parse_ident.html \
 		test_parse_rule.html \
 		test_parse_url.html \
-		test_parser_diagnostics_unprintables.html \
 		test_pixel_lengths.html \
 		test_pointer-events.html \
 		test_property_database.html \
 		test_priority_preservation.html \
 		test_property_syntax_errors.html \
 		test_rem_unit.html \
 		test_rule_serialization.html \
 		test_rules_out_of_sheets.html \
--- a/layout/style/test/property_database.js
+++ b/layout/style/test/property_database.js
@@ -2310,25 +2310,25 @@ var gCSSProperties = {
 		other_values: [ '""', "''", '"hello"', "url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==)", "url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==')", 'url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==")', 'counter(foo)', 'counter(bar, upper-roman)', 'counters(foo, ".")', "counters(bar, '-', lower-greek)", "'-' counter(foo) '.'", "attr(title)", "open-quote", "close-quote", "no-open-quote", "no-close-quote", "close-quote attr(title) counters(foo, '.', upper-alpha)", "counter(foo, none)", "counters(bar, '.', none)", "attr(\\32)", "attr(\\2)", "attr(-\\2)", "attr(-\\32)", "counter(\\2)", "counters(\\32, '.')", "counter(-\\32, upper-roman)", "counters(-\\2, '-', lower-greek)", "counter(\\()", "counters(a\\+b, '.')", "counter(\\}, upper-alpha)", "-moz-alt-content" ],
 		invalid_values: [ 'counters(foo)', 'counter(foo, ".")', 'attr("title")', "attr('title')", "attr(2)", "attr(-2)", "counter(2)", "counters(-2, '.')", "-moz-alt-content 'foo'", "'foo' -moz-alt-content" ]
 	},
 	"counter-increment": {
 		domProp: "counterIncrement",
 		inherited: false,
 		type: CSS_TYPE_LONGHAND,
 		initial_values: [ "none" ],
-		other_values: [ "foo 1", "bar", "foo 3 bar baz 2", "\\32  1", "-\\32  1", "-c 1", "\\32 1", "-\\32 1", "\\2  1", "-\\2  1", "-c 1", "\\2 1", "-\\2 1", "-\\7f \\9e 1" ],
+		other_values: [ "foo 1", "bar", "foo 3 bar baz 2", "\\32  1", "-\\32  1", "-c 1", "\\32 1", "-\\32 1", "\\2  1", "-\\2  1", "-c 1", "\\2 1", "-\\2 1" ],
 		invalid_values: []
 	},
 	"counter-reset": {
 		domProp: "counterReset",
 		inherited: false,
 		type: CSS_TYPE_LONGHAND,
 		initial_values: [ "none" ],
-		other_values: [ "foo 1", "bar", "foo 3 bar baz 2", "\\32  1", "-\\32  1", "-c 1", "\\32 1", "-\\32 1", "\\2  1", "-\\2  1", "-c 1", "\\2 1", "-\\2 1", "-\\7f \\9e 1" ],
+		other_values: [ "foo 1", "bar", "foo 3 bar baz 2", "\\32  1", "-\\32  1", "-c 1", "\\32 1", "-\\32 1", "\\2  1", "-\\2  1", "-c 1", "\\2 1", "-\\2 1" ],
 		invalid_values: []
 	},
 	"cursor": {
 		domProp: "cursor",
 		inherited: true,
 		type: CSS_TYPE_LONGHAND,
 		initial_values: [ "auto" ],
 		other_values: [ "crosshair", "default", "pointer", "move", "e-resize", "ne-resize", "nw-resize", "n-resize", "se-resize", "sw-resize", "s-resize", "w-resize", "text", "wait", "help", "progress", "copy", "alias", "context-menu", "cell", "not-allowed", "col-resize", "row-resize", "no-drop", "vertical-text", "all-scroll", "nesw-resize", "nwse-resize", "ns-resize", "ew-resize", "none", "-moz-grab", "-moz-grabbing", "-moz-zoom-in", "-moz-zoom-out", "url(foo.png), move", "url(foo.png) 5 7, move", "url(foo.png) 12 3, url(bar.png), no-drop", "url(foo.png), url(bar.png) 7 2, wait", "url(foo.png) 3 2, url(bar.png) 7 9, pointer" ],
deleted file mode 100644
--- a/layout/style/test/test_parser_diagnostics_unprintables.html
+++ /dev/null
@@ -1,219 +0,0 @@
-<!doctype html>
-<html>
-<head>
-  <meta charset="utf-8">
-  <title>Test for CSS parser diagnostics escaping unprintable
-         characters correctly</title>
-  <script src="/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" href="/tests/SimpleTest/test.css">
-</head>
-<body>
-<a target="_blank"
-   href="https://bugzilla.mozilla.org/show_bug.cgi?id=229827"
->Mozilla Bug 229827</a>
-<style id="testbench"></style>
-<script type="application/javascript;version=1.8">
-// This test has intimate knowledge of how to get the CSS parser to
-// emit diagnostics that contain text under control of the user.
-// That's not the point of the test, though; the point is only that
-// *that text* is properly escaped.
-
-// There is one "pattern" for each code path through the error reporter
-// that might need to escape some kind of user-supplied text.
-// Each "pattern" is tested once with each of the "substitution"s below:
-// <t>, <i>, and <s> are replaced by the t:, i:, and s: fields of
-// each substitution object in turn.
-const patterns = [
-  // REPORT_UNEXPECTED_P (only ever used in contexts where identifier-like
-  // escaping is appropriate)
-  { i: "<t>|x{}",                 o: "prefix '<i>'" },
-  // REPORT_UNEXPECTED_TOKEN with:
-  // _Ident
-  { i: "@namespace fnord <t>;",    o: "within @namespace: '<i>'" },
-  // _Ref
-  { i: "@namespace fnord #<t>;",   o: "within @namespace: '#<i>'" },
-  // _Function
-  { i: "@namespace fnord <t>();",  o: "within @namespace: '<i>('" },
-  // _Dimension
-  { i: "@namespace fnord 14<t>;",  o: "within @namespace: '14<i>'" },
-  // _AtKeyword
-  { i: "x{@<t>: }",        o: "declaration but found '@<i>'." },
-  // _String
-  { i: "x{ '<t>'}" ,       o: "declaration but found ''<s>''." },
-  // _Bad_String
-  { i: "x{ '<t>\n}",      o: "declaration but found ''<s>'." },
-  // _URL
-  { i: "x{ url('<t>')}",   o: "declaration but found 'url('<s>')'." },
-  // _Bad_URL
-  { i: "x{ url('<t>'.)}" , o: "declaration but found 'url('<s>''." }
-];
-
-// Blocks of characters to test, and how they should be escaped when
-// they appear in identifiers and string constants.
-const substitutions = [
-  // ASCII printables that _can_ normally appear in identifiers,
-  // so should of course _not_ be escaped.
-  { t: "-_0123456789",               i: "-_0123456789",
-                                     s: "-_0123456789" },
-  { t: "abcdefghijklmnopqrstuvwxyz", i: "abcdefghijklmnopqrstuvwxyz",
-                                     s: "abcdefghijklmnopqrstuvwxyz" },
-  { t: "ABCDEFGHIJKLMNOPQRSTUVWXYZ", i: "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
-                                     s: "ABCDEFGHIJKLMNOPQRSTUVWXYZ" },
-
-  // ASCII printables that are not normally valid as the first character
-  // of an identifier, or the character immediately after a leading dash,
-  // but can be forced into that position with escapes.
-  { t: "\\-",    i: "\\-",    s: "-"  },
-  { t: "\\30 ",  i: "\\30 ",  s: "0"  },
-  { t: "\\31 ",  i: "\\31 ",  s: "1"  },
-  { t: "\\32 ",  i: "\\32 ",  s: "2"  },
-  { t: "\\33 ",  i: "\\33 ",  s: "3"  },
-  { t: "\\34 ",  i: "\\34 ",  s: "4"  },
-  { t: "\\35 ",  i: "\\35 ",  s: "5"  },
-  { t: "\\36 ",  i: "\\36 ",  s: "6"  },
-  { t: "\\37 ",  i: "\\37 ",  s: "7"  },
-  { t: "\\38 ",  i: "\\38 ",  s: "8"  },
-  { t: "\\39 ",  i: "\\39 ",  s: "9"  },
-  { t: "-\\-",   i: "-\\-",   s: "--" },
-  { t: "-\\30 ", i: "-\\30 ", s: "-0" },
-  { t: "-\\31 ", i: "-\\31 ", s: "-1" },
-  { t: "-\\32 ", i: "-\\32 ", s: "-2" },
-  { t: "-\\33 ", i: "-\\33 ", s: "-3" },
-  { t: "-\\34 ", i: "-\\34 ", s: "-4" },
-  { t: "-\\35 ", i: "-\\35 ", s: "-5" },
-  { t: "-\\36 ", i: "-\\36 ", s: "-6" },
-  { t: "-\\37 ", i: "-\\37 ", s: "-7" },
-  { t: "-\\38 ", i: "-\\38 ", s: "-8" },
-  { t: "-\\39 ", i: "-\\39 ", s: "-9" },
-
-  // ASCII printables that must be escaped in identifiers.
-  // Most of these should not be escaped in strings.
-  { t: "\\!\\\"\\#\\$",   i: "\\!\\\"\\#\\$",   s: "!\\\"#$" },
-  { t: "\\%\\&\\'\\(",    i: "\\%\\&\\'\\(",    s: "%&\\'(" },
-  { t: "\\)\\*\\+\\,",    i: "\\)\\*\\+\\,",    s: ")*+," },
-  { t: "\\.\\/\\:\\;",    i: "\\.\\/\\:\\;",    s: "./:;" },
-  { t: "\\<\\=\\>\\?",    i: "\\<\\=\\>\\?",    s: "<=>?", },
-  { t: "\\@\\[\\\\\\]",   i: "\\@\\[\\\\\\]",   s: "@[\\\\]" },
-  { t: "\\^\\`\\{\\}\\~", i: "\\^\\`\\{\\}\\~", s: "^`{}~" },
-
-  // U+0000 - U+0020 (C0 controls, space)
-  // U+000A LINE FEED, U+000C FORM FEED, and U+000D CARRIAGE RETURN
-  // cannot be put into a CSS token as escaped literal characters, so
-  // we do them with hex escapes instead.
-  { t: "\\\x00\\\x01\\\x02\\\x03",       i: "\\0 \\1 \\2 \\3 ",
-                                         s: "\\0 \\1 \\2 \\3 " },
-  { t: "\\\x04\\\x05\\\x06\\\x07",       i: "\\4 \\5 \\6 \\7 ",
-                                         s: "\\4 \\5 \\6 \\7 " },
-  { t: "\\\x08\\\x09\\000A\\\x0B",       i: "\\8 \\9 \\A \\B ",
-                                         s: "\\8 \\9 \\A \\B " },
-  { t: "\\000C\\000D\\\x0E\\\x0F",       i: "\\C \\D \\E \\F ",
-                                         s: "\\C \\D \\E \\F " },
-  { t: "\\\x10\\\x11\\\x12\\\x13",       i: "\\10 \\11 \\12 \\13 ",
-                                         s: "\\10 \\11 \\12 \\13 " },
-  { t: "\\\x14\\\x15\\\x16\\\x17",       i: "\\14 \\15 \\16 \\17 ",
-                                         s: "\\14 \\15 \\16 \\17 " },
-  { t: "\\\x18\\\x19\\\x1A\\\x1B",       i: "\\18 \\19 \\1A \\1B ",
-                                         s: "\\18 \\19 \\1A \\1B " },
-  { t: "\\\x1C\\\x1D\\\x1E\\\x1F\\ ",    i: "\\1C \\1D \\1E \\1F \\ ",
-                                         s: "\\1C \\1D \\1E \\1F  " },
-
-  // U+007F (DELETE) and U+0080 - U+009F (C1 controls)
-  { t: "\\\x7f\\\x80\\\x81\\\x82",       i: "\\7F \\80 \\81 \\82 ",
-                                         s: "\\7F \\80 \\81 \\82 " },
-  { t: "\\\x83\\\x84\\\x85\\\x86",       i: "\\83 \\84 \\85 \\86 ",
-                                         s: "\\83 \\84 \\85 \\86 " },
-  { t: "\\\x87\\\x88\\\x89\\\x8A",       i: "\\87 \\88 \\89 \\8A ",
-                                         s: "\\87 \\88 \\89 \\8A " },
-  { t: "\\\x8B\\\x8C\\\x8D\\\x8E",       i: "\\8B \\8C \\8D \\8E ",
-                                         s: "\\8B \\8C \\8D \\8E " },
-  { t: "\\\x8F\\\x90\\\x91\\\x92",       i: "\\8F \\90 \\91 \\92 ",
-                                         s: "\\8F \\90 \\91 \\92 " },
-  { t: "\\\x93\\\x94\\\x95\\\x96",       i: "\\93 \\94 \\95 \\96 ",
-                                         s: "\\93 \\94 \\95 \\96 " },
-  { t: "\\\x97\\\x98\\\x99\\\x9A",       i: "\\97 \\98 \\99 \\9A ",
-                                         s: "\\97 \\98 \\99 \\9A " },
-  { t: "\\\x9B\\\x9C\\\x9D\\\x9E\\\x9F", i: "\\9B \\9C \\9D \\9E \\9F ",
-                                         s: "\\9B \\9C \\9D \\9E \\9F " },
-
-  // CSS doesn't bother with the full Unicode rules for identifiers,
-  // instead declaring that any code point greater than or equal to
-  // U+00A0 is a valid identifier character.  Test a small handful
-  // of both basic and astral plane characters.
-
-  // Arabic (caution to editors: there is a possibly-invisible U+200E
-  // LEFT-TO-RIGHT MARK in each string, just before the close quote)
-  { t: "أبجدهوزحطيكلمنسعفصقرشتثخذضظغ‎",
-    i: "أبجدهوزحطيكلمنسعفصقرشتثخذضظغ‎",
-    s: "أبجدهوزحطيكلمنسعفصقرشتثخذضظغ‎" },
-
-  // Box drawing
-  { t: "─│┌┐└┘├┤┬┴┼╭╮╯╰╴╵╶╷",
-    i: "─│┌┐└┘├┤┬┴┼╭╮╯╰╴╵╶╷",
-    s: "─│┌┐└┘├┤┬┴┼╭╮╯╰╴╵╶╷" },
-
-  // CJK Unified Ideographs
-  { t: "一丁丂七丄丅丆万丈三上下丌不与丏",
-    i: "一丁丂七丄丅丆万丈三上下丌不与丏",
-    s: "一丁丂七丄丅丆万丈三上下丌不与丏" },
-
-  // CJK Unified Ideographs Extension B (astral)
-  { t: "𠀀𠀁𠀂𠀃𠀄𠀅𠀆𠀇𠀈𠀉𠀊𠀋𠀌𠀍𠀎𠀏",
-    i: "𠀀𠀁𠀂𠀃𠀄𠀅𠀆𠀇𠀈𠀉𠀊𠀋𠀌𠀍𠀎𠀏",
-    s: "𠀀𠀁𠀂𠀃𠀄𠀅𠀆𠀇𠀈𠀉𠀊𠀋𠀌𠀍𠀎𠀏" },
-
-  // Devanagari
-  { t: "कखगघङचछजझञटठडढणतथदधनपफबभमयरलळवशषसह",
-    i: "कखगघङचछजझञटठडढणतथदधनपफबभमयरलळवशषसह",
-    s: "कखगघङचछजझञटठडढणतथदधनपफबभमयरलळवशषसह" },
-
-  // Emoticons (astral)
-  { t: "😁😂😃😄😅😆😇😈😉😊😋😌😍😎😏😐",
-    i: "😁😂😃😄😅😆😇😈😉😊😋😌😍😎😏😐",
-    s: "😁😂😃😄😅😆😇😈😉😊😋😌😍😎😏😐" },
-
-  // Greek
-  { t: "αβγδεζηθικλμνξοπρςστυφχψω",
-    i: "αβγδεζηθικλμνξοπρςστυφχψω",
-    s: "αβγδεζηθικλμνξοπρςστυφχψω" }
-];
-
-const npatterns = patterns.length;
-const nsubstitutions = substitutions.length;
-
-function quotemeta(str) {
-  return str.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
-}
-function subst(str, sub) {
-  return str.replace("<t>", sub.t)
-    .replace("<i>", sub.i)
-    .replace("<s>", sub.s);
-}
-
-var curpat = 0;
-var cursubst = -1;
-var testbench = document.getElementById("testbench");
-
-function nextTest() {
-  cursubst++;
-  if (cursubst == nsubstitutions) {
-    curpat++;
-    cursubst = 0;
-  }
-  if (curpat == npatterns) {
-    SimpleTest.finish();
-    return;
-  }
-
-  let css = subst(patterns[curpat].i, substitutions[cursubst]);
-  let msg = quotemeta(subst(patterns[curpat].o, substitutions[cursubst]));
-
-  SimpleTest.expectConsoleMessages(function () { testbench.innerHTML = css },
-                                   [{ errorMessage: new RegExp(msg) }],
-                                   nextTest);
-}
-
-SimpleTest.waitForExplicitFinish();
-nextTest();
-</script>
-</body>
-</html>
--- a/parser/htmlparser/tests/mochitest/Makefile.in
+++ b/parser/htmlparser/tests/mochitest/Makefile.in
@@ -58,17 +58,16 @@ MOCHITEST_FILES =	parser_datreader.js \
 		test_bug613662.xhtml \
 		test_bug639362.html \
 		test_bug642908.html \
 		file_bug642908.sjs \
 		test_bug645115.html \
 		test_bug655682.html \
 		file_bug655682.sjs \
 		test_bug667533.html \
-		test_bug672453.html \
 		file_bug672453_not_declared.html \
 		file_bug672453_late_meta.html \
 		file_bug672453_meta_restart.html \
 		file_bug672453_meta_unsupported.html \
 		file_bug672453_http_unsupported.html \
 		file_bug672453_http_unsupported.html^headers^ \
 		file_bug672453_bomless_utf16.html \
 		file_bug672453_meta_utf16.html \
@@ -99,9 +98,12 @@ endif
 # Disabled test due to orange on Linux
 #		test_bug568470.html \
 #		file_bug568470.sjs \
 #		file_bug568470-script.sjs \
 
 # Disable test due to frequent orange on Mac
 #		test_bug534293.html \
 
+# Disabled due to frequent orange (bug 739354)
+#		test_bug672453.html \
+
 include $(topsrcdir)/config/rules.mk
--- a/parser/htmlparser/tests/mochitest/test_bug672453.html
+++ b/parser/htmlparser/tests/mochitest/test_bug672453.html
@@ -1,94 +1,68 @@
-<!doctype html>
+<!DOCTYPE HTML>
 <html>
 <!--
 https://bugzilla.mozilla.org/show_bug.cgi?id=672453
 -->
 <head>
   <meta charset="utf-8">
   <title>Test for Bug 672453</title>
-  <script src="/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" href="/tests/SimpleTest/test.css">
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
 <body>
-<a target="_blank"
-   href="https://bugzilla.mozilla.org/show_bug.cgi?id=672453"
-   >Mozilla Bug 672453</a>
-<iframe></iframe>
-<script>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=672453">Mozilla Bug 672453</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+<iframe onload="runNextTest();"></iframe>  
+</div>
+<pre id="test">
+<script type="application/javascript">
+
 /** Test for Bug 672453 **/
 
+SimpleTest.waitForExplicitFinish();
+
 var tests = [
   "file_bug672453_not_declared.html",
   "file_bug672453_late_meta.html",
   "file_bug672453_meta_restart.html",
   "file_bug672453_meta_unsupported.html",
   "file_bug672453_http_unsupported.html",
   "file_bug672453_bomless_utf16.html",
   "file_bug672453_meta_utf16.html",
   "file_bug672453_meta_non_superset.html"
 ];
 
 var expectedErrors = [
-  { errorMessage: "The character encoding of a framed document was not declared. The document may appear different if viewed without the document framing it.",
-    sourceName: "http://mochi.test:8888/tests/parser/htmlparser/tests/mochitest/file_bug672453_not_declared.html",
-    lineNumber: 0,
-    isWarning: true,
-    isException: false },
-  { errorMessage: "The character encoding declaration of the framed HTML document was not found when prescanning the first 1024 bytes of the file. When viewed without the document framing it, the page will reload automatically. The encoding declaration needs to be moved to be within the first 1024 bytes of the file.",
-    sourceName: "http://mochi.test:8888/tests/parser/htmlparser/tests/mochitest/file_bug672453_late_meta.html",
-    lineNumber: 1028,
-    isWarning: true,
-    isException: false },
-  { errorMessage: "The page was reloaded, because the character encoding declaration of the HTML document was not found when prescanning the first 1024 bytes of the file. The encoding declaration needs to be moved to be within the first 1024 bytes of the file.",
-    sourceName: "http://mochi.test:8888/tests/parser/htmlparser/tests/mochitest/file_bug672453_meta_restart.html",
-    lineNumber: 1028,
-    isWarning: true,
-    isException: false },
-  { errorMessage: "An unsupported character encoding was declared for the HTML document using a meta tag. The declaration was ignored.",
-    sourceName: "http://mochi.test:8888/tests/parser/htmlparser/tests/mochitest/file_bug672453_meta_unsupported.html",
-    lineNumber: 1,
-    isWarning: false,
-    isException: false },
-  { errorMessage: "An unsupported character encoding was declared on the transfer protocol level. The declaration was ignored.",
-    sourceName: "http://mochi.test:8888/tests/parser/htmlparser/tests/mochitest/file_bug672453_http_unsupported.html",
-    lineNumber: 0,
-    isWarning: false,
-    isException: false },
-  { errorMessage: "Detected UTF-16-encoded Basic Latin-only text without a byte order mark and without a transfer protocol-level declaration. Encoding this content in UTF-16 is inefficient and the character encoding should have been declared in any case.",
-    sourceName: "http://mochi.test:8888/tests/parser/htmlparser/tests/mochitest/file_bug672453_bomless_utf16.html",
-    lineNumber: 0,
-    isWarning: false,
-    isException: false },
-  { errorMessage: "A meta tag was used to declare the character encoding as UTF-16. This was interpreted as an UTF-8 declaration instead.",
-    sourceName: "http://mochi.test:8888/tests/parser/htmlparser/tests/mochitest/file_bug672453_meta_utf16.html",
-    lineNumber: 1,
-    isWarning: false,
-    isException: false },
-  { errorMessage: "A meta tag was used to declare a character encoding the does not encode the Basic Latin range roughly like US-ASCII. The declaration was ignored.",
-    sourceName: "http://mochi.test:8888/tests/parser/htmlparser/tests/mochitest/file_bug672453_meta_non_superset.html",
-    lineNumber: 1,
-    isWarning: false,
-    isException: false }
+  '[JavaScript Warning: "The character encoding of a framed document was not declared. The document may appear different if viewed without the document framing it." {file: "http://mochi.test:8888/tests/parser/htmlparser/tests/mochitest/file_bug672453_not_declared.html" line: 0}]',
+  '[JavaScript Warning: "The character encoding declaration of the framed HTML document was not found when prescanning the first 1024 bytes of the file. When viewed without the document framing it, the page will reload automatically. The encoding declaration needs to be moved to be within the first 1024 bytes of the file." {file: "http://mochi.test:8888/tests/parser/htmlparser/tests/mochitest/file_bug672453_late_meta.html" line: 1028}]',
+  '[JavaScript Warning: "The page was reloaded, because the character encoding declaration of the HTML document was not found when prescanning the first 1024 bytes of the file. The encoding declaration needs to be moved to be within the first 1024 bytes of the file." {file: "http://mochi.test:8888/tests/parser/htmlparser/tests/mochitest/file_bug672453_meta_restart.html" line: 1028}]',
+  '[JavaScript Error: "An unsupported character encoding was declared for the HTML document using a meta tag. The declaration was ignored." {file: "http://mochi.test:8888/tests/parser/htmlparser/tests/mochitest/file_bug672453_meta_unsupported.html" line: 1}]',
+  '[JavaScript Error: "An unsupported character encoding was declared on the transfer protocol level. The declaration was ignored." {file: "http://mochi.test:8888/tests/parser/htmlparser/tests/mochitest/file_bug672453_http_unsupported.html" line: 0}]',
+  '[JavaScript Error: "Detected UTF-16-encoded Basic Latin-only text without a byte order mark and without a transfer protocol-level declaration. Encoding this content in UTF-16 is inefficient and the character encoding should have been declared in any case." {file: "http://mochi.test:8888/tests/parser/htmlparser/tests/mochitest/file_bug672453_bomless_utf16.html" line: 0}]',
+  '[JavaScript Error: "A meta tag was used to declare the character encoding as UTF-16. This was interpreted as an UTF-8 declaration instead." {file: "http://mochi.test:8888/tests/parser/htmlparser/tests/mochitest/file_bug672453_meta_utf16.html" line: 1}]',
+  '[JavaScript Error: "A meta tag was used to declare a character encoding the does not encode the Basic Latin range roughly like US-ASCII. The declaration was ignored." {file: "http://mochi.test:8888/tests/parser/htmlparser/tests/mochitest/file_bug672453_meta_non_superset.html" line: 1}]'
 ];
 
-SimpleTest.waitForExplicitFinish();
+function consoleError(msg) {
+  var expected = expectedErrors.shift();
+  is(msg, expected, "Not the right error message");
+}
 
-window.onload = function() {
-  var iframe = document.getElementsByTagName("iframe")[0];
+SpecialPowers.addErrorConsoleListener(consoleError);
 
-  function runNextTest() {
-    var url = tests.shift();
-    if (!url) {
-      SimpleTest.endMonitorConsole();
-      return;
-    }
-    iframe.src = url;
+function runNextTest() {
+  var url = tests.shift();
+  if (!url) {
+    is(expectedErrors.length, 0, "The error supply was not exhausted");
+    SpecialPowers.removeErrorConsoleListener(consoleError);
+    SimpleTest.finish();
+    return;
   }
-  iframe.onload = runNextTest;
+  document.getElementsByTagName("iframe")[0].src = url;
+}
 
-  SimpleTest.monitorConsole(SimpleTest.finish, expectedErrors);
-  runNextTest();
-}
 </script>
+</pre>
 </body>
 </html>
--- a/testing/mochitest/tests/SimpleTest/SimpleTest.js
+++ b/testing/mochitest/tests/SimpleTest/SimpleTest.js
@@ -689,99 +689,16 @@ SimpleTest.finish = function () {
         /* We're running in an iframe, and the parent has a TestRunner */
         parentRunner.testFinished(SimpleTest._tests);
     } else {
         SimpleTest.showReport();
     }
 };
 
 /**
- * Monitor console output from now until endMonitorConsole is called.
- *
- * Expect to receive as many console messages as there are elements of
- * |msgs|, an array; each element is an object which may have any
- * number of the following properties:
- *   message, errorMessage, sourceName, sourceLine, category:
- *     string or regexp
- *   lineNumber, columnNumber: number
- *   isScriptError, isWarning, isException, isStrict: boolean
- * Strings, numbers, and booleans must compare equal to the named
- * property of the Nth console message.  Regexps must match.  Any
- * fields present in the message but not in the pattern object are ignored.
- *
- * After endMonitorConsole is called, |continuation| will be called
- * asynchronously.  (Normally, you will want to pass |SimpleTest.finish| here.)
- *
- * It is incorrect to use this function in a test which has not called
- * SimpleTest.waitForExplicitFinish.
- */
-SimpleTest.monitorConsole = function (continuation, msgs) {
-  if (SimpleTest._stopOnLoad) {
-    ok(false, "Console monitoring requires use of waitForExplicitFinish.");
-  }
-
-  var counter = 0;
-  function listener(msg) {
-    if (msg.message === "SENTINEL" && !msg.isScriptError) {
-      is(counter, msgs.length, "monitorConsole | number of messages");
-      SimpleTest.executeSoon(continuation);
-    } else if (counter >= msgs.length) {
-      ok(false, "monitorConsole | extra message | " + JSON.stringify(msg));
-    } else {
-      var pat = msgs[counter];
-      for (k in pat) {
-        ok(k in msg, "monitorConsole | [" + counter + "]." + k + " present");
-        if (k in msg) {
-          if (pat[k] instanceof RegExp && typeof(msg[k]) === 'string') {
-            ok(pat[k].test(msg[k]),
-               "monitorConsole | [" + counter + "]." + k + " value - " +
-               msg[k].quote() + " contains /" + pat[k].source + "/");
-          } else {
-            ise(msg[k], pat[k],
-                "monitorConsole | [" + counter + "]." + k + " value");
-          }
-        }
-      }
-      counter++;
-    }
-  }
-  SpecialPowers.registerConsoleListener(listener);
-};
-
-/**
- * Stop monitoring console output.
- */
-SimpleTest.endMonitorConsole = function () {
-  SpecialPowers.postConsoleSentinel();
-};
-
-/**
- * Run |testfn| synchronously, and monitor its console output.
- *
- * |msgs| is handled as described above for monitorConsole.
- *
- * After |testfn| returns, console monitoring will stop, and
- * |continuation| will be called asynchronously.
- */
-SimpleTest.expectConsoleMessages = function (testfn, msgs, continuation) {
-  SimpleTest.monitorConsole(continuation, msgs);
-  testfn();
-  SimpleTest.executeSoon(SimpleTest.endMonitorConsole);
-};
-
-/**
- * Wrapper around |expectConsoleMessages| for the case where the test has
- * only one |testfn| to run.
- */
-SimpleTest.runTestExpectingConsoleMessages = function(testfn, msgs) {
-  SimpleTest.waitForExplicitFinish();
-  SimpleTest.expectConsoleMessages(testfn, msgs, SimpleTest.finish);
-};
-
-/**
  * Indicates to the test framework that the current test expects one or
  * more crashes (from plugins or IPC documents), and that the minidumps from
  * those crashes should be removed.
  */
 SimpleTest.expectChildProcessCrash = function () {
     if (parentRunner) {
         parentRunner.expectChildProcessCrash();
     }
--- a/testing/specialpowers/content/specialpowers.js
+++ b/testing/specialpowers/content/specialpowers.js
@@ -6,33 +6,32 @@
  */
 
 function SpecialPowers(window) {
   this.window = Components.utils.getWeakReference(window);
   this._encounteredCrashDumpFiles = [];
   this._unexpectedCrashDumpFiles = { };
   this._crashDumpDir = null;
   this.DOMWindowUtils = bindDOMWindowUtils(window);
-  Object.defineProperty(this, 'Components', {
-      configurable: true, enumerable: true, get: function() {
-          var win = this.window.get();
-          if (!win)
-              return null;
-          return getRawComponents(win);
-      }});
+  Object.defineProperty(this, 'Components', { configurable: true, enumerable: true,
+                                              get: function() { var win = this.window.get();
+                                                                if (!win)
+                                                                  return null;
+                                                                return getRawComponents(win); } });
   this._pongHandlers = [];
   this._messageListener = this._messageReceived.bind(this);
   addMessageListener("SPPingService", this._messageListener);
+  this._consoleListeners = [];
 }
 
 SpecialPowers.prototype = new SpecialPowersAPI();
 
 SpecialPowers.prototype.toString = function() { return "[SpecialPowers]"; };
 SpecialPowers.prototype.sanityCheck = function() { return "foo"; };
-
+ 
 // This gets filled in in the constructor.
 SpecialPowers.prototype.DOMWindowUtils = undefined;
 SpecialPowers.prototype.Components = undefined;
 
 SpecialPowers.prototype._sendSyncMessage = function(msgname, msg) {
   return sendSyncMessage(msgname, msg);
 };
 
--- a/testing/specialpowers/content/specialpowersAPI.js
+++ b/testing/specialpowers/content/specialpowersAPI.js
@@ -4,23 +4,22 @@
 /* This code is loaded in every child process that is started by mochitest in
  * order to be used as a replacement for UniversalXPConnect
  */
 
 var Ci = Components.interfaces;
 var Cc = Components.classes;
 var Cu = Components.utils;
 
-Cu.import("resource://specialpowers/MockFilePicker.jsm");
-Cu.import("resource://specialpowers/MockPermissionPrompt.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Components.utils.import("resource://specialpowers/MockFilePicker.jsm");
+Components.utils.import("resource://specialpowers/MockPermissionPrompt.jsm");
+Components.utils.import("resource://gre/modules/Services.jsm");
+Components.utils.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
 
-function SpecialPowersAPI() {
+function SpecialPowersAPI() { 
   this._consoleListeners = [];
   this._encounteredCrashDumpFiles = [];
   this._unexpectedCrashDumpFiles = { };
   this._crashDumpDir = null;
   this._mfl = null;
   this._prefEnvUndoStack = [];
   this._pendingPrefs = [];
   this._applyingPrefs = false;
@@ -375,68 +374,16 @@ SpecialPowersHandler.prototype.fix = fun
 // Per the ES5 spec this is a derived trap, but it's fundamental in spidermonkey
 // for some reason. See bug 665198.
 SpecialPowersHandler.prototype.enumerate = function() {
   var t = this;
   var filt = function(name) { return t.getPropertyDescriptor(name).enumerable; };
   return this.getPropertyNames().filter(filt);
 };
 
-// SPConsoleListener reflects nsIConsoleMessage objects into JS in a
-// tidy, XPCOM-hiding way.  Messages that are nsIScriptError objects
-// have their properties exposed in detail.  It also auto-unregisters
-// itself when it receives a "sentinel" message.
-function SPConsoleListener(callback) {
-  this.callback = callback;
-}
-
-SPConsoleListener.prototype = {
-  observe: function(msg) {
-    let m = { message: msg.message,
-              errorMessage: null,
-              sourceName: null,
-              sourceLine: null,
-              lineNumber: null,
-              columnNumber: null,
-              category: null,
-              windowID: null,
-              isScriptError: false,
-              isWarning: false,
-              isException: false,
-              isStrict: false };
-    if (msg instanceof Ci.nsIScriptError) {
-      m.errorMessage  = msg.errorMessage;
-      m.sourceName    = msg.sourceName;
-      m.sourceLine    = msg.sourceLine;
-      m.lineNumber    = msg.lineNumber;
-      m.columnNumber  = msg.columnNumber;
-      m.category      = msg.category;
-      m.windowID      = msg.outerWindowID;
-      m.isScriptError = true;
-      m.isWarning     = ((msg.flags & Ci.nsIScriptError.warningFlag) === 1);
-      m.isException   = ((msg.flags & Ci.nsIScriptError.exceptionFlag) === 1);
-      m.isStrict      = ((msg.flags & Ci.nsIScriptError.strictFlag) === 1);
-    }
-
-    // expose all props of 'm' as read-only
-    let expose = {};
-    for (let prop in m)
-      expose[prop] = 'r';
-    m.__exposedProps__ = expose;
-    Object.freeze(m);
-
-    this.callback.call(undefined, m);
-
-    if (!m.isScriptError && m.message === "SENTINEL")
-      Services.console.unregisterListener(this);
-  },
-
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsIConsoleListener])
-};
-
 SpecialPowersAPI.prototype = {
 
   /*
    * Privileged object wrapping API
    *
    * Usage:
    *   var wrapper = SpecialPowers.wrap(obj);
    *   wrapper.privilegedMethod(); wrapper.privilegedProperty;
@@ -797,36 +744,36 @@ SpecialPowersAPI.prototype = {
     if (aIid) {
       msg = {'op':'set','prefName':aPrefName, 'prefType': aPrefType, 'prefValue': [aIid,aValue]};
     } else {
       msg = {'op':'set', 'prefName': aPrefName, 'prefType': aPrefType, 'prefValue': aValue};
     }
     return(this._sendSyncMessage('SPPrefService', msg)[0]);
   },
 
-  _getDocShell: function(window) {
-    return window.QueryInterface(Ci.nsIInterfaceRequestor)
-                 .getInterface(Ci.nsIWebNavigation)
-                 .QueryInterface(Ci.nsIDocShell);
-  },
-  _getMUDV: function(window) {
-    return this._getDocShell(window).contentViewer
-               .QueryInterface(Ci.nsIMarkupDocumentViewer);
-  },
   //XXX: these APIs really ought to be removed, they're not e10s-safe.
   // (also they're pretty Firefox-specific)
   _getTopChromeWindow: function(window) {
     return window.QueryInterface(Ci.nsIInterfaceRequestor)
                  .getInterface(Ci.nsIWebNavigation)
                  .QueryInterface(Ci.nsIDocShellTreeItem)
                  .rootTreeItem
                  .QueryInterface(Ci.nsIInterfaceRequestor)
                  .getInterface(Ci.nsIDOMWindow)
                  .QueryInterface(Ci.nsIDOMChromeWindow);
   },
+  _getDocShell: function(window) {
+    return window.QueryInterface(Ci.nsIInterfaceRequestor)
+                 .getInterface(Ci.nsIWebNavigation)
+                 .QueryInterface(Ci.nsIDocShell);
+  },
+  _getMUDV: function(window) {
+    return this._getDocShell(window).contentViewer
+               .QueryInterface(Ci.nsIMarkupDocumentViewer);
+  },
   _getAutoCompletePopup: function(window) {
     return this._getTopChromeWindow(window).document
                                            .getElementById("PopupAutoComplete");
   },
   addAutoCompletePopupEventListener: function(window, listener) {
     this._getAutoCompletePopup(window).addEventListener("popupshowing",
                                                         listener,
                                                         false);
@@ -848,40 +795,54 @@ SpecialPowersAPI.prototype = {
   detachFormFillControllerFrom: function(window) {
     this.getFormFillController().detachFromBrowser(this._getDocShell(window));
   },
   isBackButtonEnabled: function(window) {
     return !this._getTopChromeWindow(window).document
                                       .getElementById("Browser:Back")
                                       .hasAttribute("disabled");
   },
-  //XXX end of problematic APIs
 
   addChromeEventListener: function(type, listener, capture, allowUntrusted) {
     addEventListener(type, listener, capture, allowUntrusted);
   },
   removeChromeEventListener: function(type, listener, capture) {
     removeEventListener(type, listener, capture);
   },
 
-  // Note: each call to registerConsoleListener MUST be paired with a
-  // call to postConsoleSentinel; when the callback receives the
-  // sentinel it will unregister itself (_after_ calling the
-  // callback).  SimpleTest.expectConsoleMessages does this for you.
-  // If you register more than one console listener, a call to
-  // postConsoleSentinel will zap all of them.
-  registerConsoleListener: function(callback) {
-    let listener = new SPConsoleListener(callback);
-    Services.console.registerListener(listener);
+  addErrorConsoleListener: function(listener) {
+    var consoleListener = {
+      userListener: listener,
+      observe: function(consoleMessage) {
+        var fileName;
+        try {
+          fileName = consoleMessage.QueryInterface(Ci.nsIScriptError)
+                                   .sourceName;
+        } catch (e) {
+        }
+        this.userListener(consoleMessage.message, fileName);
+      }
+    };
+
+    Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService)
+                                       .registerListener(consoleListener);
+
+    this._consoleListeners.push(consoleListener);
   },
-  postConsoleSentinel: function() {
-    Services.console.logStringMessage("SENTINEL");
-  },
-  resetConsole: function() {
-    Services.console.reset();
+
+  removeErrorConsoleListener: function(listener) {
+    for (var index in this._consoleListeners) {
+      var consoleListener = this._consoleListeners[index];
+      if (consoleListener.userListener == listener) {
+        Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService)
+                                           .unregisterListener(consoleListener);
+        this._consoleListeners = this._consoleListeners.splice(index, 1);
+        break;
+      }
+    }
   },
 
   getMaxLineBoxWidth: function(window) {
     return this._getMUDV(window).maxLineBoxWidth;
   },
 
   setMaxLineBoxWidth: function(window, width) {
     this._getMUDV(window).changeMaxLineBoxWidth(width);
@@ -933,21 +894,21 @@ SpecialPowersAPI.prototype = {
     return this.snapshotWindow.apply(this, args);
   },
 
   gc: function() {
     this.DOMWindowUtils.garbageCollect();
   },
 
   forceGC: function() {
-    Cu.forceGC();
+    Components.utils.forceGC();
   },
 
   forceCC: function() {
-    Cu.forceCC();
+    Components.utils.forceCC();
   },
 
   exactGC: function(win, callback) {
     var self = this;
     let count = 0;
 
     function doPreciseGCandCC() {
       function scheduledGCCallback() {
@@ -955,24 +916,24 @@ SpecialPowersAPI.prototype = {
 
         if (++count < 2) {
           doPreciseGCandCC();
         } else {
           callback();
         }
       }
 
-      Cu.schedulePreciseGC(scheduledGCCallback);
+      Components.utils.schedulePreciseGC(scheduledGCCallback);
     }
 
     doPreciseGCandCC();
   },
 
   setGCZeal: function(zeal) {
-    Cu.setGCZeal(zeal);
+    Components.utils.setGCZeal(zeal);
   },
 
   isMainProcess: function() {
     try {
       return Cc["@mozilla.org/xre/app-info;1"].
                getService(Ci.nsIXULRuntime).
                processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
     } catch (e) { }
@@ -1236,17 +1197,17 @@ SpecialPowersAPI.prototype = {
       // It's an URL.
       url = Cc["@mozilla.org/network/io-service;1"]
               .getService(Ci.nsIIOService)
               .newURI(arg, null, null)
               .spec;
     } else if (arg.manifestURL) {
       // It's a thing representing an app.
       let tmp = {};
-      Cu.import("resource://gre/modules/Webapps.jsm", tmp);
+      Components.utils.import("resource://gre/modules/Webapps.jsm", tmp);
 
       let app = tmp.DOMApplicationRegistry.getAppByManifestURL(arg.manifestURL);
       if (!app) {
         throw "No app for this manifest!";
       }
 
       appId = app.localId;
       url = app.origin;