Merge from mozilla-central.
authorDavid Anderson <danderson@mozilla.com>
Thu, 22 Dec 2011 11:50:00 -0800
changeset 112312 74c7f055b86b0abc20216c27b4ba67dfbd07d312
parent 112311 f99cd892afdcb56e758f8cfdbcd58b1e3eb723ad (current diff)
parent 86061 c5b90ea7e475e362314174aeb8cbfdf0c7391572 (diff)
child 112313 860845757cc8d0ba4206104688eff443aba17014
push id239
push userakeybl@mozilla.com
push dateThu, 03 Jan 2013 21:54:43 +0000
treeherdermozilla-release@3a7b66445659 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone12.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
Merge from mozilla-central.
accessible/src/atk/nsAccessibleWrap.cpp
browser/devtools/webconsole/HUDService.jsm
browser/devtools/webconsole/test/Makefile.in
browser/devtools/webconsole/test/browser_webconsole_bug_583816_tab_focus.js
config/system-headers
configure.in
content/base/src/nsAttrAndChildArray.h
content/base/src/nsContentUtils.cpp
content/base/src/nsDocument.cpp
content/base/src/nsEventSource.cpp
content/base/src/nsScriptLoader.cpp
content/base/src/nsWebSocket.cpp
content/canvas/src/CustomQS_Canvas2D.h
content/events/src/nsEventStateManager.cpp
content/html/content/public/nsHTMLMediaElement.h
content/html/content/src/nsHTMLMediaElement.cpp
content/html/document/src/nsHTMLContentSink.cpp
content/xml/document/src/nsXMLDocument.cpp
content/xslt/src/xslt/txMozillaXMLOutput.cpp
dom/base/nsDOMClassInfo.cpp
dom/base/nsGlobalWindow.cpp
dom/base/nsIScriptContext.h
dom/base/nsJSEnvironment.cpp
dom/base/nsJSEnvironment.h
dom/indexedDB/IndexedDatabaseManager.cpp
dom/locales/en-US/chrome/dom/dom.properties
dom/src/jsurl/nsJSProtocolHandler.cpp
dom/workers/WorkerPrivate.cpp
editor/libeditor/base/nsEditorEventListener.cpp
extensions/cookie/nsPermissionManager.cpp
extensions/cookie/nsPermissionManager.h
image/src/Decoder.cpp
js/src/Makefile.in
js/src/config/system-headers
js/src/frontend/BytecodeEmitter.cpp
js/src/jscompartment.h
js/src/jsdbgapi.cpp
js/src/jsfriendapi.h
js/src/jsfun.cpp
js/src/jsobj.cpp
js/src/jsobj.h
js/src/jsobjinlines.h
js/src/methodjit/Compiler.cpp
js/src/shell/js.cpp
js/xpconnect/loader/mozJSComponentLoader.cpp
js/xpconnect/src/XPCComponents.cpp
js/xpconnect/src/XPCWrappedJSClass.cpp
js/xpconnect/src/XPCWrappedNativeJSOps.cpp
js/xpconnect/src/xpcprivate.h
layout/base/nsCSSFrameConstructor.cpp
layout/base/nsCSSFrameConstructor.h
layout/base/nsDocumentViewer.cpp
layout/base/nsLayoutUtils.cpp
layout/base/nsPresContext.cpp
layout/base/nsStyleChangeList.h
layout/generic/nsBlockFrame.cpp
layout/generic/nsContainerFrame.cpp
layout/generic/nsFrame.cpp
layout/generic/nsFrameSelection.h
layout/generic/nsGfxScrollFrame.cpp
layout/generic/nsImageFrame.cpp
layout/generic/nsLineLayout.cpp
layout/generic/nsObjectFrame.cpp
layout/generic/nsPlaceholderFrame.cpp
layout/generic/nsSelection.cpp
layout/generic/nsTextFrameThebes.cpp
layout/mathml/mathml.css
layout/mathml/nsIMathMLFrame.h
layout/mathml/nsMathMLChar.cpp
layout/mathml/nsMathMLChar.h
layout/mathml/nsMathMLContainerFrame.cpp
layout/mathml/nsMathMLContainerFrame.h
layout/mathml/nsMathMLFrame.cpp
layout/mathml/nsMathMLFrame.h
layout/mathml/nsMathMLOperators.cpp
layout/mathml/nsMathMLOperators.h
layout/mathml/nsMathMLTokenFrame.cpp
layout/mathml/nsMathMLmencloseFrame.cpp
layout/mathml/nsMathMLmfencedFrame.cpp
layout/mathml/nsMathMLmfracFrame.cpp
layout/mathml/nsMathMLmmultiscriptsFrame.cpp
layout/mathml/nsMathMLmoFrame.cpp
layout/mathml/nsMathMLmpaddedFrame.cpp
layout/mathml/nsMathMLmpaddedFrame.h
layout/mathml/nsMathMLmsubFrame.cpp
layout/mathml/nsMathMLmsubsupFrame.cpp
layout/mathml/nsMathMLmsupFrame.cpp
layout/printing/nsPrintData.h
layout/printing/nsPrintEngine.h
layout/printing/nsPrintObject.h
layout/reftests/mathml/reftest.list
layout/reftests/scrolling/reftest.list
layout/style/Declaration.h
layout/style/StyleRule.h
layout/style/nsCSSParser.h
layout/style/nsCSSRules.cpp
layout/style/nsCSSRules.h
layout/style/nsCSSScanner.cpp
layout/style/nsCSSStyleSheet.h
layout/style/nsCSSValue.h
layout/style/nsFontFaceLoader.cpp
layout/style/nsHTMLCSSStyleSheet.h
layout/style/nsHTMLStyleSheet.h
layout/style/nsRuleNode.cpp
layout/style/nsStyleAnimation.cpp
layout/style/nsStyleSet.h
layout/style/nsStyleStruct.h
layout/tables/nsCellMap.cpp
layout/tables/nsTableFrame.cpp
layout/tools/reftest/reftest.js
layout/tools/reftest/remotereftest.py
layout/tools/reftest/runreftest.py
layout/xul/base/src/grid/nsGridRowLeafLayout.cpp
layout/xul/base/src/nsPopupSetFrame.cpp
layout/xul/base/src/nsXULTooltipListener.h
mfbt/Util.h
mobile/android/base/AndroidManifest.xml.in
mobile/android/base/GeckoApp.java
mobile/android/base/GeckoAppShell.java
mobile/android/base/Makefile.in
mobile/android/base/resources/drawable-land-v14/address_bar_texture.png
mobile/android/base/resources/drawable-land-v14/address_bar_url_bg.9.png
mobile/android/base/resources/drawable-land-v14/address_bar_url_outline.9.png
mobile/android/base/resources/drawable-land-v14/tabs_normal.png
mobile/android/base/resources/drawable-land-v14/tabs_pressed.png
mobile/android/base/resources/drawable-port-v14/address_bar_texture.png
mobile/android/base/resources/drawable-port-v14/address_bar_url_bg.9.png
mobile/android/base/resources/drawable-port-v14/address_bar_url_outline.9.png
mobile/android/base/resources/drawable-port-v14/tabs_normal.png
mobile/android/base/resources/drawable-port-v14/tabs_pressed.png
mobile/android/base/resources/drawable/awesomebar_tab_focus.xml
mobile/android/base/resources/drawable/awesomebar_tab_focus_selected.xml
mobile/android/themes/core/gingerbread/images/aboutBackground.jpg
mobile/android/themes/core/header.css
mobile/android/themes/core/honeycomb/images/aboutBackground.jpg
mobile/android/themes/core/images/aboutBackground.jpg
mobile/xul/themes/core/gingerbread/browser.css
modules/libjar/nsZipArchive.h
netwerk/base/src/nsSocketTransport2.cpp
netwerk/protocol/http/nsHttpConnection.cpp
other-licenses/android/APKOpen.cpp
parser/htmlparser/src/nsExpatDriver.cpp
security/manager/ssl/src/nsNSSIOLayer.cpp
security/manager/ssl/src/nsRecentBadCerts.h
services/sync/version.txt
testing/jetpack/jetpack-location.txt
toolkit/mozapps/extensions/XPIProvider.jsm
toolkit/mozapps/extensions/content/extensions.js
widget/src/android/AndroidJNI.cpp
widget/src/android/nsWindow.cpp
widget/src/android/nsWindow.h
widget/src/cocoa/nsCocoaWindow.mm
widget/src/windows/nsFilePicker.cpp
widget/src/xpwidgets/PuppetWidget.cpp
xpcom/base/nsAutoRef.h
xpcom/ds/nsAtomTable.cpp
xpcom/glue/nsCOMArray.h
xpcom/glue/nsStringAPI.h
xpcom/glue/nsTArray-inl.h
xpcom/glue/nsTArray.h
xpcom/io/nsUnicharInputStream.cpp
xpcom/string/public/nsReadableUtils.h
xpcom/string/public/nsTString.h
xpcom/string/src/nsReadableUtils.cpp
--- a/accessible/src/atk/nsAccessibleWrap.cpp
+++ b/accessible/src/atk/nsAccessibleWrap.cpp
@@ -1370,18 +1370,19 @@ nsAccessibleWrap::FireAtkTextChangedEven
 
     PRInt32 start = event->GetStartOffset();
     PRUint32 length = event->GetLength();
     bool isInserted = event->IsTextInserted();
     bool isFromUserInput = aEvent->IsFromUserInput();
     char* signal_name = nsnull;
 
   if (gAvailableAtkSignals == eUnknown)
-    gAvailableAtkSignals = g_signal_lookup("text-insert", ATK_TYPE_TEXT) ?
-      eHaveNewAtkTextSignals : eNoNewAtkSignals;
+    gAvailableAtkSignals =
+      g_signal_lookup("text-insert", G_OBJECT_TYPE(aObject)) ?
+        eHaveNewAtkTextSignals : eNoNewAtkSignals;
 
   if (gAvailableAtkSignals == eNoNewAtkSignals) {
     // XXX remove this code and the gHaveNewTextSignals check when we can
     // stop supporting old atk since it doesn't really work anyway
     // see bug 619002
     signal_name = g_strconcat(isInserted ? "text_changed::insert" :
                               "text_changed::delete",
                               isFromUserInput ? "" : kNonUserInputEvent, NULL);
--- a/browser/devtools/scratchpad/scratchpad.js
+++ b/browser/devtools/scratchpad/scratchpad.js
@@ -19,16 +19,17 @@
  * Portions created by the Initial Developer are Copyright (C) 2011
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Rob Campbell <robcee@mozilla.com> (original author)
  *   Erik Vold <erikvvold@gmail.com>
  *   David Dahl <ddahl@mozilla.com>
  *   Mihai Sucan <mihai.sucan@gmail.com>
+ *   Kenny Heaton <kennyheaton@gmail.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -331,17 +332,17 @@ var Scratchpad = {
                                 "Scratchpad", 1);
     }
     catch (ex) {
       this.openWebConsole();
 
       let contentWindow = this.gBrowser.selectedBrowser.contentWindow;
 
       let scriptError = Cc["@mozilla.org/scripterror;1"].
-                        createInstance(Ci.nsIScriptError2);
+                        createInstance(Ci.nsIScriptError);
 
       scriptError.initWithWindowID(ex.message + "\n" + ex.stack, ex.fileName,
                                    "", ex.lineNumber, 0, scriptError.errorFlag,
                                    "content javascript",
                                    this.getInnerWindowId(contentWindow));
 
       Services.console.logMessage(scriptError);
 
@@ -578,16 +579,17 @@ var Scratchpad = {
     let self = this;
     NetUtil.asyncFetch(channel, function(aInputStream, aStatus) {
       let content = null;
 
       if (Components.isSuccessCode(aStatus)) {
         content = NetUtil.readInputStreamToString(aInputStream,
                                                   aInputStream.available());
         self.setText(content);
+        self.editor.resetUndo();
       }
       else if (!aSilentError) {
         window.alert(self.strings.GetStringFromName("openFile.failed"));
       }
 
       if (aCallback) {
         aCallback.call(self, aStatus, content);
       }
--- a/browser/devtools/scratchpad/test/Makefile.in
+++ b/browser/devtools/scratchpad/test/Makefile.in
@@ -55,11 +55,12 @@ include $(topsrcdir)/config/rules.mk
 		browser_scratchpad_bug_660560_tab.js \
 		browser_scratchpad_open.js \
 		browser_scratchpad_restore.js \
 		browser_scratchpad_bug_679467_falsy.js \
 		browser_scratchpad_bug_699130_edit_ui_updates.js \
 		browser_scratchpad_bug_669612_unsaved.js \
 		head.js \
 		browser_scratchpad_bug_653427_confirm_close.js \
+		browser_scratchpad_bug684546_reset_undo.js \
 
 libs:: $(_BROWSER_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/browser/devtools/scratchpad/test/browser_scratchpad_bug684546_reset_undo.js
@@ -0,0 +1,155 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+Cu.import("resource://gre/modules/NetUtil.jsm");
+Cu.import("resource://gre/modules/FileUtils.jsm");
+
+// Reference to the Scratchpad chrome window object.
+let gScratchpadWindow;
+
+// Reference to the Scratchpad object.
+let gScratchpad;
+
+// Reference to the temporary nsIFile we will work with.
+let gFileA;
+let gFileB;
+
+// The temporary file content.
+let gFileAContent = "// File A ** Hello World!";
+let gFileBContent = "// File B ** Goodbye All";
+
+// Help track if one or both files are saved
+let gFirstFileSaved = false;
+
+function test()
+{
+  waitForExplicitFinish();
+
+  gBrowser.selectedTab = gBrowser.addTab();
+  gBrowser.selectedBrowser.addEventListener("load", function browserLoad() {
+    gBrowser.selectedBrowser.removeEventListener("load", browserLoad, true);
+    openScratchpad(runTests);
+  }, true);
+
+  content.location = "data:text/html,<p>test that undo get's reset after file load in Scratchpad";
+}
+
+function runTests()
+{
+  gScratchpad = gScratchpadWindow.Scratchpad;
+
+  // Create a temporary file.
+  gFileA = FileUtils.getFile("TmpD", ["fileAForBug684546.tmp"]);
+  gFileA.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
+
+  gFileB = FileUtils.getFile("TmpD", ["fileBForBug684546.tmp"]);
+  gFileB.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
+
+  // Write the temporary file.
+  let foutA = Cc["@mozilla.org/network/file-output-stream;1"].
+             createInstance(Ci.nsIFileOutputStream);
+  foutA.init(gFileA.QueryInterface(Ci.nsILocalFile), 0x02 | 0x08 | 0x20,
+            0644, foutA.DEFER_OPEN);
+
+  let foutB = Cc["@mozilla.org/network/file-output-stream;1"].
+             createInstance(Ci.nsIFileOutputStream);
+  foutB.init(gFileB.QueryInterface(Ci.nsILocalFile), 0x02 | 0x08 | 0x20,
+            0644, foutB.DEFER_OPEN);
+
+  let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].
+                  createInstance(Ci.nsIScriptableUnicodeConverter);
+  converter.charset = "UTF-8";
+  let fileContentStreamA = converter.convertToInputStream(gFileAContent);
+  let fileContentStreamB = converter.convertToInputStream(gFileBContent);
+
+  NetUtil.asyncCopy(fileContentStreamA, foutA, tempFileSaved);
+  NetUtil.asyncCopy(fileContentStreamB, foutB, tempFileSaved);
+}
+
+function tempFileSaved(aStatus)
+{
+  let success = Components.isSuccessCode(aStatus);
+
+  ok(success, "a temporary file was saved successfully");
+
+  if (!success)
+  {
+    finish();
+    return;
+  }
+
+  if (gFirstFileSaved && success)
+  {
+    ok((gFirstFileSaved && success), "Both files loaded");
+    // Import the file A into Scratchpad.
+    gScratchpad.importFromFile(gFileA.QueryInterface(Ci.nsILocalFile),  true,
+                              fileAImported);
+  }
+  gFirstFileSaved = success;
+}
+
+function fileAImported(aStatus, aFileContent)
+{
+  ok(Components.isSuccessCode(aStatus),
+     "the temporary file A was imported successfully with Scratchpad");
+
+  is(aFileContent, gFileAContent, "received data is correct");
+
+  is(gScratchpad.getText(), gFileAContent, "the editor content is correct");
+
+  gScratchpad.setText("new text", gScratchpad.getText().length);
+
+  is(gScratchpad.getText(), gFileAContent + "new text", "text updated correctly");
+  gScratchpad.undo();
+  is(gScratchpad.getText(), gFileAContent, "undo works");
+  gScratchpad.redo();
+  is(gScratchpad.getText(), gFileAContent + "new text", "redo works");
+
+  // Import the file B into Scratchpad.
+  gScratchpad.importFromFile(gFileB.QueryInterface(Ci.nsILocalFile),  true,
+                            fileBImported);
+}
+
+function fileBImported(aStatus, aFileContent)
+{
+  ok(Components.isSuccessCode(aStatus),
+     "the temporary file B was imported successfully with Scratchpad");
+
+  is(aFileContent, gFileBContent, "received data is correct");
+
+  is(gScratchpad.getText(), gFileBContent, "the editor content is correct");
+
+  ok(!gScratchpad.editor.canUndo(), "editor cannot undo after load");
+
+  gScratchpad.undo();
+  is(gScratchpad.getText(), gFileBContent,
+      "the editor content is still correct after undo");
+
+  gScratchpad.setText("new text", gScratchpad.getText().length);
+  is(gScratchpad.getText(), gFileBContent + "new text", "text updated correctly");
+
+  gScratchpad.undo();
+  is(gScratchpad.getText(), gFileBContent, "undo works");
+  ok(!gScratchpad.editor.canUndo(), "editor cannot undo after load (again)");
+
+  gScratchpad.redo();
+  is(gScratchpad.getText(), gFileBContent + "new text", "redo works");
+
+  // Done!
+  finish();
+}
+
+registerCleanupFunction(function() {
+  if (gFileA && gFileA.exists())
+  {
+    gFileA.remove(false);
+    gFileA = null;
+  }
+  if (gFileB && gFileB.exists())
+  {
+    gFileB.remove(false);
+    gFileB = null;
+  }
+  gScratchpad = null;
+});
--- a/browser/devtools/sourceeditor/source-editor-orion.jsm
+++ b/browser/devtools/sourceeditor/source-editor-orion.jsm
@@ -16,16 +16,17 @@
  *
  * The Initial Developer of the Original Code is
  * The Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2011
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Mihai Sucan <mihai.sucan@gmail.com> (original author)
+ *   Kenny Heaton <kennyheaton@gmail.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -549,16 +550,24 @@ SourceEditor.prototype = {
    *         True if there are changes that can be repeated, false otherwise.
    */
   canRedo: function SE_canRedo()
   {
     return this._undoStack.canRedo();
   },
 
   /**
+   * Reset the Undo stack
+   */
+  resetUndo: function SE_resetUndo()
+  {
+    this._undoStack.reset();
+  },
+
+  /**
    * Start a compound change in the editor. Compound changes are grouped into
    * only one change that you can undo later, after you invoke
    * endCompoundChange().
    */
   startCompoundChange: function SE_startCompoundChange()
   {
     this._undoStack.startCompoundChange();
   },
--- a/browser/devtools/sourceeditor/source-editor-textarea.jsm
+++ b/browser/devtools/sourceeditor/source-editor-textarea.jsm
@@ -16,16 +16,17 @@
  *
  * The Initial Developer of the Original Code is
  * The Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2011
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Mihai Sucan <mihai.sucan@gmail.com> (original author)
+ *   Kenny Heaton <kennyheaton@gmail.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -143,18 +144,17 @@ SourceEditor.prototype = {
 
     // Mimic the mode change.
     this.setMode(aConfig.mode || SourceEditor.DEFAULTS.MODE);
 
     this._editor.transactionManager.maxTransactionCount =
       aConfig.undoLimit || SourceEditor.DEFAULTS.UNDO_LIMIT;
 
     // Make sure that the transactions stack is clean.
-    this._editor.transactionManager.clear();
-    this._editor.resetModificationCount();
+    this.resetUndo();
 
     // Add the edit action listener so we can fire the SourceEditor TextChanged
     // events.
     this._editActionListener = new EditActionListener(this);
     this._editor.addEditActionListener(this._editActionListener);
 
     this._lineDelimiter = win.navigator.platform.indexOf("Win") > -1 ?
                           "\r\n" : "\n";
@@ -402,16 +402,25 @@ SourceEditor.prototype = {
   {
     let isEnabled = {};
     let canRedo = {};
     this._editor.canRedo(isEnabled, canRedo);
     return canRedo.value;
   },
 
   /**
+   * Reset the Undo stack
+   */
+  resetUndo: function SE_resetUndo()
+  {
+    this._editor.transactionManager.clear();
+    this._editor.resetModificationCount();
+  },
+
+  /**
    * Start a compound change in the editor. Compound changes are grouped into
    * only one change that you can undo later, after you invoke
    * endCompoundChange().
    */
   startCompoundChange: function SE_startCompoundChange()
   {
     this._editor.beginTransaction();
   },
--- a/browser/devtools/sourceeditor/test/Makefile.in
+++ b/browser/devtools/sourceeditor/test/Makefile.in
@@ -45,14 +45,15 @@ include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _BROWSER_TEST_FILES = \
 		browser_sourceeditor_initialization.js \
 		browser_bug684862_paste_html.js \
 		browser_bug687573_vscroll.js \
 		browser_bug687568_pagescroll.js \
 		browser_bug687580_drag_and_drop.js \
+		browser_bug684546_reset_undo.js \
 		browser_bug695035_middle_click_paste.js \
 		browser_bug687160_line_api.js \
 		head.js \
 
 libs:: $(_BROWSER_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/browser/devtools/sourceeditor/test/browser_bug684546_reset_undo.js
@@ -0,0 +1,70 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+Cu.import("resource:///modules/source-editor.jsm");
+
+let testWin;
+let editor;
+
+function test()
+{
+  waitForExplicitFinish();
+
+  const windowUrl = "data:application/vnd.mozilla.xul+xml,<?xml version='1.0'?>" +
+    "<window xmlns='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul'" +
+    " title='test for bug 684546 - reset undo' width='300' height='500'>" +
+    "<box flex='1'/></window>";
+  const windowFeatures = "chrome,titlebar,toolbar,centerscreen,resizable,dialog=no";
+
+  testWin = Services.ww.openWindow(null, windowUrl, "_blank", windowFeatures, null);
+  testWin.addEventListener("load", function onWindowLoad() {
+    testWin.removeEventListener("load", onWindowLoad, false);
+    waitForFocus(initEditor, testWin);
+  }, false);
+}
+
+function initEditor()
+{
+  let box = testWin.document.querySelector("box");
+
+  editor = new SourceEditor();
+  editor.init(box, {}, editorLoaded);
+}
+
+function editorLoaded()
+{
+  editor.setText("First");
+  editor.setText("Second", 5);
+  is(editor.getText(), "FirstSecond", "text set correctly.");
+  editor.undo();
+  is(editor.getText(), "First", "undo works.");
+  editor.redo();
+  is(editor.getText(), "FirstSecond", "redo works.");
+  editor.resetUndo();
+  ok(!editor.canUndo(), "canUndo() is correct");
+  ok(!editor.canRedo(), "canRedo() is correct");
+  editor.undo();
+  is(editor.getText(), "FirstSecond", "reset undo works correctly");
+  editor.setText("Third", 11);
+  is(editor.getText(), "FirstSecondThird", "text set correctly");
+  editor.undo();
+  is(editor.getText(), "FirstSecond", "undo works after reset");
+  editor.redo();
+  is(editor.getText(), "FirstSecondThird", "redo works after reset");
+  editor.resetUndo();
+  ok(!editor.canUndo(), "canUndo() is correct (again)");
+  ok(!editor.canRedo(), "canRedo() is correct (again)");
+  editor.undo();
+  is(editor.getText(), "FirstSecondThird", "reset undo still works correctly");
+
+  finish();
+}
+
+registerCleanupFunction(function() {
+  editor.destroy();
+  testWin.close();
+  testWin = editor = null;
+});
--- a/browser/devtools/tilt/Tilt.jsm
+++ b/browser/devtools/tilt/Tilt.jsm
@@ -133,16 +133,17 @@ Tilt.prototype = {
     if (!this.visualizers[aId]) {
       return;
     }
 
     this.visualizers[aId].removeOverlay();
     this.visualizers[aId].cleanup();
     this.visualizers[aId] = null;
 
+    this.chromeWindow.gBrowser.selectedBrowser.contentWindow.focus();
     Services.obs.notifyObservers(null, TILT_NOTIFICATIONS.DESTROYED, null);
   },
 
   /**
    * Handles any supplementary post-initialization work, done immediately
    * after a TILT_NOTIFICATIONS.INITIALIZED notification.
    */
   _whenInitialized: function T__whenInitialized()
--- a/browser/devtools/tilt/TiltVisualizer.jsm
+++ b/browser/devtools/tilt/TiltVisualizer.jsm
@@ -60,21 +60,21 @@ const INVISIBLE_ELEMENTS = {
 
 const STACK_THICKNESS = 15;
 const WIREFRAME_COLOR = [0, 0, 0, 0.25];
 const INITIAL_TRANSITION_DURATION = 100;
 const INITIAL_Z_TRANSLATION = 400;
 
 const MOUSE_CLICK_THRESHOLD = 10;
 const ARCBALL_SENSITIVITY = 0.3;
-const ARCBALL_ZOOM_STEP = 0.1;
 const ARCBALL_ROTATION_STEP = 0.15;
 const ARCBALL_TRANSLATION_STEP = 35;
-const ARCBALL_SCROLL_MIN = -3000;
-const ARCBALL_SCROLL_MAX = 500;
+const ARCBALL_ZOOM_STEP = 0.1;
+const ARCBALL_ZOOM_MIN = -3000;
+const ARCBALL_ZOOM_MAX = 500;
 
 const TILT_CRAFTER = "resource:///modules/devtools/TiltWorkerCrafter.js";
 const TILT_PICKER = "resource:///modules/devtools/TiltWorkerPicker.js";
 
 Cu.import("resource:///modules/devtools/TiltGL.jsm");
 Cu.import("resource:///modules/devtools/TiltMath.jsm");
 Cu.import("resource:///modules/devtools/TiltUtils.jsm");
 Cu.import("resource:///modules/devtools/TiltVisualizerStyle.jsm");
@@ -101,17 +101,17 @@ function TiltVisualizer(aProperties)
   /**
    * The canvas element used for rendering the visualization.
    */
   this.canvas = TiltUtils.DOM.initCanvas(aProperties.parentNode, {
     focusable: true,
     append: true
   });
 
-  /*
+  /**
    * Visualization logic and drawing loop.
    */
   this.presenter = new TiltVisualizer.Presenter(this.canvas,
     aProperties.contentWindow,
     aProperties.requestAnimationFrame,
     aProperties.inspectorUI,
     aProperties.onError || null,
     aProperties.onLoad || null);
@@ -180,16 +180,17 @@ TiltVisualizer.prototype = {
  */
 TiltVisualizer.Presenter = function TV_Presenter(
   aCanvas, aContentWindow, aRequestAnimationFrame, aInspectorUI,
   onError, onLoad)
 {
   this.canvas = aCanvas;
   this.contentWindow = aContentWindow;
   this.inspectorUI = aInspectorUI;
+  this.tiltUI = aInspectorUI.chromeWin.Tilt;
 
   /**
    * Create the renderer, containing useful functions for easy drawing.
    */
   this.renderer = new TiltGL.Renderer(aCanvas, onError, onLoad);
 
   /**
    * A custom shader used for drawing the visualization mesh.
@@ -967,17 +968,17 @@ TiltVisualizer.Controller.prototype = {
   /**
    * Called when the mouse wheel is used.
    */
   onMozScroll: function TVC_onMozScroll(e)
   {
     e.preventDefault();
     e.stopPropagation();
 
-    this.arcball.mouseScroll(e.detail);
+    this.arcball.zoom(e.detail);
   },
 
   /**
    * Called when a key is pressed.
    */
   onKeyDown: function TVC_onKeyDown(e)
   {
     let code = e.keyCode || e.which;
@@ -995,16 +996,20 @@ TiltVisualizer.Controller.prototype = {
   onKeyUp: function TVC_onKeyUp(e)
   {
     let code = e.keyCode || e.which;
 
     if (code >= e.DOM_VK_LEFT && code <= e.DOM_VK_DOWN) {
       e.preventDefault();
       e.stopPropagation();
     }
+    if (code === e.DOM_VK_ESCAPE) {
+      this.presenter.tiltUI.destroy(this.presenter.tiltUI.currentWindowId);
+      return;
+    }
     this.arcball.keyUp(code);
   },
 
   /**
    * Called when the content window of the current browser is resized.
    */
   onResize: function TVC_onResize(e)
   {
@@ -1070,22 +1075,17 @@ TiltVisualizer.Arcball = function TV_Arc
 {
   /**
    * Values retaining the current horizontal and vertical mouse coordinates.
    */
   this._mousePress = vec3.create();
   this._mouseRelease = vec3.create();
   this._mouseMove = vec3.create();
   this._mouseLerp = vec3.create();
-
-  /**
-   * Other mouse flags: current pressed mouse button and the scroll amount.
-   */
   this._mouseButton = -1;
-  this._scrollValue = 0;
 
   /**
    * Object retaining the current pressed key codes.
    */
   this._keyCode = {};
 
   /**
    * The vectors representing the mouse coordinates mapped on the arcball
@@ -1104,16 +1104,17 @@ TiltVisualizer.Arcball = function TV_Arc
   this._currentRot = quat4.create(aInitialRot);
 
   /**
    * The current camera translation coordinates.
    */
   this._lastTrans = vec3.create();
   this._deltaTrans = vec3.create();
   this._currentTrans = vec3.create(aInitialTrans);
+  this._zoomAmount = 0;
 
   /**
    * Additional rotation and translation vectors.
    */
   this._addKeyRot = vec3.create();
   this._addKeyTrans = vec3.create();
   this._deltaKeyRot = quat4.create();
   this._deltaKeyTrans = vec3.create();
@@ -1212,21 +1213,21 @@ TiltVisualizer.Arcball.prototype = {
       currentTrans[0] = lastTrans[0] + deltaTrans[0];
       currentTrans[1] = lastTrans[1] + deltaTrans[1];
     } else {
       // save the current panning to stack translations
       lastTrans[0] = currentTrans[0];
       lastTrans[1] = currentTrans[1];
     }
 
-    let scrollValue = this._scrollValue;
+    let zoomAmount = this._zoomAmount;
     let keyCode = this._keyCode;
 
     // mouse wheel handles zooming
-    deltaTrans[2] = (scrollValue - currentTrans[2]) * ARCBALL_ZOOM_STEP;
+    deltaTrans[2] = (zoomAmount - currentTrans[2]) * ARCBALL_ZOOM_STEP;
     currentTrans[2] += deltaTrans[2];
 
     let addKeyRot = this._addKeyRot;
     let addKeyTrans = this._addKeyTrans;
     let deltaKeyRot = this._deltaKeyRot;
     let deltaKeyTrans = this._deltaKeyTrans;
 
     // handle additional rotation and translation by the keyboard
@@ -1249,16 +1250,29 @@ TiltVisualizer.Arcball.prototype = {
       addKeyTrans[0] += ARCBALL_SENSITIVITY * ARCBALL_TRANSLATION_STEP;
     }
     if (keyCode[Ci.nsIDOMKeyEvent.DOM_VK_UP]) {
       addKeyTrans[1] -= ARCBALL_SENSITIVITY * ARCBALL_TRANSLATION_STEP;
     }
     if (keyCode[Ci.nsIDOMKeyEvent.DOM_VK_DOWN]) {
       addKeyTrans[1] += ARCBALL_SENSITIVITY * ARCBALL_TRANSLATION_STEP;
     }
+    if (keyCode[Ci.nsIDOMKeyEvent.DOM_VK_I] ||
+        keyCode[Ci.nsIDOMKeyEvent.DOM_VK_ADD] ||
+        keyCode[Ci.nsIDOMKeyEvent.DOM_VK_EQUALS]) {
+      this.zoom(-ARCBALL_TRANSLATION_STEP);
+    }
+    if (keyCode[Ci.nsIDOMKeyEvent.DOM_VK_O] ||
+        keyCode[Ci.nsIDOMKeyEvent.DOM_VK_SUBTRACT]) {
+      this.zoom(ARCBALL_TRANSLATION_STEP);
+    }
+    if (keyCode[Ci.nsIDOMKeyEvent.DOM_VK_R] ||
+        keyCode[Ci.nsIDOMKeyEvent.DOM_VK_0]) {
+      this._zoomAmount = 0;
+    }
 
     // update the delta key rotations and translations
     deltaKeyRot[0] +=
       (addKeyRot[0] - deltaKeyRot[0]) * ARCBALL_SENSITIVITY;
     deltaKeyRot[1] +=
       (addKeyRot[1] - deltaKeyRot[1]) * ARCBALL_SENSITIVITY;
 
     deltaKeyTrans[0] +=
@@ -1359,26 +1373,27 @@ TiltVisualizer.Arcball.prototype = {
    */
   mouseOut: function TVA_mouseOut()
   {
     // if the mouse leaves the parent bounds, stop the animation
     this._mouseButton = -1;
   },
 
   /**
-   * Function handling the mouseScroll event.
-   * Call this when the mouse wheel was scrolled.
+   * Function handling the arcball zoom amount.
+   * Call this, for example, when the mouse wheel was scrolled or zoom keys
+   * were pressed.
    *
-   * @param {Number} aScroll
-   *                 the mouse wheel direction and speed
+   * @param {Number} aZoom
+   *                 the zoom direction and speed
    */
-  mouseScroll: function TVA_mouseScroll(aScroll)
+  zoom: function TVA_zoom(aZoom)
   {
-    this._scrollValue = TiltMath.clamp(this._scrollValue - aScroll,
-      ARCBALL_SCROLL_MIN, ARCBALL_SCROLL_MAX);
+    this._zoomAmount = TiltMath.clamp(this._zoomAmount - aZoom,
+      ARCBALL_ZOOM_MIN, ARCBALL_ZOOM_MAX);
   },
 
   /**
    * Function handling the keyDown event.
    * Call this when a key was pressed.
    *
    * @param {Number} aCode
    *                 the code corresponding to the key pressed
--- a/browser/devtools/tilt/test/Makefile.in
+++ b/browser/devtools/tilt/test/Makefile.in
@@ -45,16 +45,17 @@ include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _BROWSER_TEST_FILES = \
 	head.js \
 	browser_tilt_01_lazy_getter.js \
 	browser_tilt_02_notifications.js \
 	browser_tilt_03_tab_switch.js \
 	browser_tilt_04_initialization.js \
+	browser_tilt_05_destruction-esc.js \
 	browser_tilt_05_destruction.js \
 	browser_tilt_arcball.js \
 	browser_tilt_gl01.js \
 	browser_tilt_gl02.js \
 	browser_tilt_gl03.js \
 	browser_tilt_gl04.js \
 	browser_tilt_gl05.js \
 	browser_tilt_gl06.js \
--- a/browser/devtools/tilt/test/browser_tilt_04_initialization.js
+++ b/browser/devtools/tilt/test/browser_tilt_04_initialization.js
@@ -15,39 +15,48 @@ function test() {
     info("Skipping initialization test because WebGL isn't supported.");
     return;
   }
 
   waitForExplicitFinish();
 
   createTab(function() {
     let id = TiltUtils.getWindowId(gBrowser.selectedBrowser.contentWindow);
+    let initialActiveElement;
 
     is(id, Tilt.currentWindowId,
       "The unique window identifiers should match for the same window.");
 
     createTilt({
       onInspectorOpen: function() {
+        initialActiveElement = document.activeElement;
+
         is(Tilt.visualizers[id], null,
           "A instance of the visualizer shouldn't be initialized yet.");
 
         is(typeof TiltVisualizer.Prefs.enabled, "boolean",
           "The 'enabled' pref should have been loaded by now.");
         is(typeof TiltVisualizer.Prefs.forceEnabled, "boolean",
           "The 'force-enabled' pref should have been loaded by now.");
       },
-      onTiltOpen: function()
+      onTiltOpen: function(instance)
       {
+        is(document.activeElement, instance.presenter.canvas,
+          "The visualizer canvas should be focused on initialization.");
+
         ok(Tilt.visualizers[id] instanceof TiltVisualizer,
           "A new instance of the visualizer wasn't created properly.");
         ok(Tilt.visualizers[id].isInitialized(),
           "The new instance of the visualizer wasn't initialized properly.");
       },
       onTiltClose: function()
       {
+        is(document.activeElement, initialActiveElement,
+          "The focus wasn't correctly given back to the initial element.");
+
         is(Tilt.visualizers[id], null,
           "The current instance of the visualizer wasn't destroyed properly.");
       },
       onEnd: function()
       {
         gBrowser.removeCurrentTab();
         finish();
       }
new file mode 100644
--- /dev/null
+++ b/browser/devtools/tilt/test/browser_tilt_05_destruction-esc.js
@@ -0,0 +1,41 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/*global ok, is, info, waitForExplicitFinish, finish, gBrowser */
+/*global isTiltEnabled, isWebGLSupported, createTab, createTilt */
+/*global Services, EventUtils, Tilt, TiltUtils, InspectorUI, TILT_DESTROYED */
+"use strict";
+
+function test() {
+  if (!isTiltEnabled()) {
+    info("Skipping destruction test because Tilt isn't enabled.");
+    return;
+  }
+  if (!isWebGLSupported()) {
+    info("Skipping destruction test because WebGL isn't supported.");
+    return;
+  }
+
+  waitForExplicitFinish();
+
+  createTab(function() {
+    createTilt({
+      onTiltOpen: function()
+      {
+        Services.obs.addObserver(cleanup, TILT_DESTROYED, false);
+        EventUtils.sendKey("ESCAPE");
+      }
+    });
+  });
+}
+
+function cleanup() {
+  let id = TiltUtils.getWindowId(gBrowser.selectedBrowser.contentWindow);
+
+  is(Tilt.visualizers[id], null,
+    "The current instance of the visualizer wasn't destroyed properly.");
+
+  Services.obs.removeObserver(cleanup, TILT_DESTROYED);
+  gBrowser.removeCurrentTab();
+  finish();
+}
--- a/browser/devtools/tilt/test/browser_tilt_arcball.js
+++ b/browser/devtools/tilt/test/browser_tilt_arcball.js
@@ -1,12 +1,13 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 /*global ok, is, isApproxVec, vec3, quat4, TiltVisualizer */
+/*global Cc, Ci, Cu */
 "use strict";
 
 function cloneUpdate(update) {
   return {
     rotation: quat4.create(update.rotation),
     translation: vec3.create(update.translation)
   };
 }
@@ -194,23 +195,23 @@ function test() {
       -0.17157875001430511, 0.04261413961648941,
       -0.08445467799901962, -0.9806182980537415],
       translation: [0, 0, -6.125794887542725] },
     { rotation: [
       -0.17158031463623047, 0.04261442646384239,
       -0.08445550501346588, -0.980617880821228],
       translation: [0, 0, -6.5132155418396] }];
 
-  arcball3.mouseScroll(10);
+  arcball3.zoom(10);
   for (let i3 = 0; i3 < 10; i3++) {
     stack3.push(cloneUpdate(arcball3.update()));
   }
 
   ok(isExpectedUpdate(stack3, expect3),
-    "Mouse scroll events didn't create the expected transformation results.");
+    "Mouse zoom events didn't create the expected transformation results.");
 
   let stack4 = [];
   let expect4 = [
     { rotation: [
       -0.17158135771751404, 0.04261462762951851,
       -0.08445606380701065, -0.9806176424026489],
       translation: [0, 0, -6.861894130706787] },
     { rotation: [
@@ -245,24 +246,24 @@ function test() {
       -0.17158377170562744, 0.04261511191725731,
       -0.08445732295513153, -0.980617105960846],
       translation: [0, 0, -8.649148941040039] },
     { rotation: [
       -0.17158380150794983, 0.04261511191725731,
       -0.08445733785629272, -0.980617105960846],
       translation: [0, 0, -8.784234046936035] }];
 
-  arcball3.keyDown(65);
-  arcball3.keyDown(68);
-  arcball3.keyDown(87);
-  arcball3.keyDown(83);
-  arcball3.keyDown(37);
-  arcball3.keyDown(39);
-  arcball3.keyDown(38);
-  arcball3.keyDown(40);
+  arcball3.keyDown(Ci.nsIDOMKeyEvent.DOM_VK_A);
+  arcball3.keyDown(Ci.nsIDOMKeyEvent.DOM_VK_D);
+  arcball3.keyDown(Ci.nsIDOMKeyEvent.DOM_VK_W);
+  arcball3.keyDown(Ci.nsIDOMKeyEvent.DOM_VK_S);
+  arcball3.keyDown(Ci.nsIDOMKeyEvent.DOM_VK_LEFT);
+  arcball3.keyDown(Ci.nsIDOMKeyEvent.DOM_VK_RIGHT);
+  arcball3.keyDown(Ci.nsIDOMKeyEvent.DOM_VK_UP);
+  arcball3.keyDown(Ci.nsIDOMKeyEvent.DOM_VK_DOWN);
   for (let i4 = 0; i4 < 10; i4++) {
     stack4.push(cloneUpdate(arcball3.update()));
   }
 
   ok(isExpectedUpdate(stack4, expect4),
     "Key down events didn't create the expected transformation results.");
 
   let stack5 = [];
@@ -303,31 +304,196 @@ function test() {
       -0.17158392071723938, 0.0426151417195797,
       -0.0844573974609375, -0.980617105960846],
       translation: [0, 0, -9.528986930847168] },
     { rotation: [
       -0.17158392071723938, 0.0426151417195797,
       -0.0844573974609375, -0.980617105960846],
       translation: [0, 0, -9.576087951660156] }];
 
-  arcball3.keyUp(65);
-  arcball3.keyUp(68);
-  arcball3.keyUp(87);
-  arcball3.keyUp(83);
-  arcball3.keyUp(37);
-  arcball3.keyUp(39);
-  arcball3.keyUp(38);
-  arcball3.keyUp(40);
+  arcball3.keyUp(Ci.nsIDOMKeyEvent.DOM_VK_A);
+  arcball3.keyUp(Ci.nsIDOMKeyEvent.DOM_VK_D);
+  arcball3.keyUp(Ci.nsIDOMKeyEvent.DOM_VK_W);
+  arcball3.keyUp(Ci.nsIDOMKeyEvent.DOM_VK_S);
+  arcball3.keyUp(Ci.nsIDOMKeyEvent.DOM_VK_LEFT);
+  arcball3.keyUp(Ci.nsIDOMKeyEvent.DOM_VK_RIGHT);
+  arcball3.keyUp(Ci.nsIDOMKeyEvent.DOM_VK_UP);
+  arcball3.keyUp(Ci.nsIDOMKeyEvent.DOM_VK_DOWN);
   for (let i5 = 0; i5 < 10; i5++) {
     stack5.push(cloneUpdate(arcball3.update()));
   }
 
   ok(isExpectedUpdate(stack5, expect5),
     "Key up events didn't create the expected transformation results.");
 
+  let stack6 = [];
+  let expect6 = [
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, -9.618478775024414] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, -6.156630992889404] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 0.4590320587158203] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 9.913128852844238] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 21.921815872192383] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 36.22963333129883] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 52.60667037963867] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 70.84600067138672] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 90.76139831542969] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 112.18525695800781] }];
+
+  arcball3.keyDown(Ci.nsIDOMKeyEvent.DOM_VK_I);
+  arcball3.keyDown(Ci.nsIDOMKeyEvent.DOM_VK_ADD);
+  arcball3.keyDown(Ci.nsIDOMKeyEvent.DOM_VK_EQUALS);
+  for (let i6 = 0; i6 < 10; i6++) {
+    stack6.push(cloneUpdate(arcball3.update()));
+  }
+  arcball3.keyUp(Ci.nsIDOMKeyEvent.DOM_VK_I);
+  arcball3.keyUp(Ci.nsIDOMKeyEvent.DOM_VK_ADD);
+  arcball3.keyUp(Ci.nsIDOMKeyEvent.DOM_VK_EQUALS);
+
+  ok(isExpectedUpdate(stack6, expect6),
+    "Key zoom in events didn't create the expected transformation results.");
+
+  let stack7 = [];
+  let expect7 = [
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 134.96673583984375] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 151.97006225585938] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 163.77305603027344] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 170.895751953125] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 173.80618286132812] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 172.92556762695312] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 168.6330108642578] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 161.26971435546875] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 151.1427459716797] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 138.52847290039062] }];
+
+  arcball3.keyDown(Ci.nsIDOMKeyEvent.DOM_VK_O);
+  arcball3.keyDown(Ci.nsIDOMKeyEvent.DOM_VK_SUBTRACT);
+  for (let i7 = 0; i7 < 10; i7++) {
+    stack7.push(cloneUpdate(arcball3.update()));
+  }
+  arcball3.keyUp(Ci.nsIDOMKeyEvent.DOM_VK_O);
+  arcball3.keyUp(Ci.nsIDOMKeyEvent.DOM_VK_SUBTRACT);
+
+  ok(isExpectedUpdate(stack7, expect7),
+    "Key zoom out events didn't create the expected transformation results.");
+
+  let stack8 = [];
+  let expect8 = [
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 123.67562866210938] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 111.30806732177734] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 100.17726135253906] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 90.15953826904297] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 81.14358520507812] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 73.02922821044922] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 65.72630310058594] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 59.15367126464844] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 53.238304138183594] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 47.91447448730469] }];
+
+  arcball3.keyDown(Ci.nsIDOMKeyEvent.DOM_VK_R);
+  arcball3.keyDown(Ci.nsIDOMKeyEvent.DOM_VK_0);
+  for (let i8 = 0; i8 < 10; i8++) {
+    stack8.push(cloneUpdate(arcball3.update()));
+  }
+  arcball3.keyUp(Ci.nsIDOMKeyEvent.DOM_VK_R);
+  arcball3.keyUp(Ci.nsIDOMKeyEvent.DOM_VK_0);
+
+  ok(isExpectedUpdate(stack8, expect8),
+    "Key zoom reset events didn't create the expected transformation results.");
+
+
   arcball3.resize(123, 456);
   is(arcball3.width, 123,
     "The arcball width wasn't updated correctly.");
   is(arcball3.height, 456,
     "The arcball height wasn't updated correctly.");
   is(arcball3.radius, 123,
     "The arcball radius wasn't implicitly updated correctly.");
 }
--- a/browser/devtools/tilt/test/browser_tilt_visualizer.js
+++ b/browser/devtools/tilt/test/browser_tilt_visualizer.js
@@ -17,16 +17,17 @@ function test() {
 
   let webGLError = false;
   let webGLLoad = false;
 
   let visualizer = new TiltVisualizer({
     parentNode: gBrowser.selectedBrowser.parentNode,
     contentWindow: gBrowser.selectedBrowser.contentWindow,
     requestAnimationFrame: window.mozRequestAnimationFrame,
+    inspectorUI: window.InspectorUI,
 
     onError: function onWebGLError()
     {
       webGLError = true;
     },
 
     onLoad: function onWebGLLoad()
     {
--- a/browser/devtools/tilt/test/head.js
+++ b/browser/devtools/tilt/test/head.js
@@ -45,19 +45,17 @@ const TILT_ENABLED = Services.prefs.getB
 const INSP_ENABLED = Services.prefs.getBoolPref("devtools.inspector.enabled");
 
 
 function isTiltEnabled() {
   return TILT_ENABLED && INSP_ENABLED;
 }
 
 function isWebGLSupported() {
-  return TiltGL.isWebGLSupported() &&
-         TiltGL.create3DContext(
-           document.createElementNS("http://www.w3.org/1999/xhtml", "canvas"));
+  return TiltGL.isWebGLSupported() && TiltGL.create3DContext(createCanvas());
 }
 
 function isApprox(num1, num2) {
   return Math.abs(num1 - num2) < EPSILON;
 }
 
 function isApproxVec(vec1, vec2) {
   if (vec1.length !== vec2.length) {
@@ -68,19 +66,17 @@ function isApproxVec(vec1, vec2) {
       return false;
     }
   }
   return true;
 }
 
 
 function createCanvas() {
-  return gBrowser.parentNode
-                 .ownerDocument
-                 .createElementNS("http://www.w3.org/1999/xhtml", "canvas");
+  return document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
 }
 
 
 function createTab(callback, location) {
   let tab = gBrowser.selectedTab = gBrowser.addTab();
 
   gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
     gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
@@ -108,17 +104,17 @@ function createTilt(callbacks, close) {
     });
   }
 
   function onTiltOpen() {
     Services.obs.removeObserver(onTiltOpen, TILT_INITIALIZED);
 
     executeSoon(function() {
       if ("function" === typeof callbacks.onTiltOpen) {
-        callbacks.onTiltOpen();
+        callbacks.onTiltOpen(Tilt.visualizers[Tilt.currentWindowId]);
       }
       if (close) {
         Services.obs.addObserver(onTiltClose, TILT_DESTROYED, false);
         Tilt.destroy(Tilt.currentWindowId);
       }
     });
   }
 
--- a/browser/devtools/webconsole/HUDService.jsm
+++ b/browser/devtools/webconsole/HUDService.jsm
@@ -5258,16 +5258,20 @@ JSTerm.prototype = {
 
       case Ci.nsIDOMKeyEvent.DOM_VK_TAB:
         // Generate a completion and accept the first proposed value.
         if (this.complete(this.COMPLETE_HINT_ONLY) &&
             this.lastCompletion &&
             this.acceptProposedCompletion()) {
           aEvent.preventDefault();
         }
+        else {
+          this.updateCompleteNode(HUDService.getStr("Autocomplete.blank"));
+          aEvent.preventDefault();
+        }
         break;
 
       default:
         break;
     }
   },
 
   /**
@@ -6518,17 +6522,16 @@ HUDConsoleObserver = {
   observe: function HCO_observe(aSubject, aTopic, aData)
   {
     if (aTopic == "xpcom-shutdown") {
       this.uninit();
       return;
     }
 
     if (!(aSubject instanceof Ci.nsIScriptError) ||
-        !(aSubject instanceof Ci.nsIScriptError2) ||
         !aSubject.outerWindowID) {
       return;
     }
 
     switch (aSubject.category) {
       // We ignore chrome-originating errors as we only
       // care about content.
       case "XPConnect JavaScript":
--- a/browser/devtools/webconsole/test/Makefile.in
+++ b/browser/devtools/webconsole/test/Makefile.in
@@ -83,17 +83,17 @@ include $(topsrcdir)/config/rules.mk
 	browser_webconsole_property_provider.js \
 	browser_webconsole_registries.js \
 	browser_webconsole_bug_587617_output_copy.js \
 	browser_webconsole_bug_585237_line_limit.js \
 	browser_webconsole_bug_581231_close_button.js \
 	browser_webconsole_bug_582201_duplicate_errors.js \
 	browser_webconsole_bug_580454_timestamp_l10n.js \
 	browser_webconsole_netlogging.js \
-	browser_webconsole_bug_583816_tab_focus.js \
+	browser_webconsole_bug_583816_No_input_and_Tab_key_pressed.js \
 	browser_webconsole_bug_594477_clickable_output.js \
 	browser_webconsole_bug_589162_css_filter.js \
 	browser_webconsole_bug_597103_deactivateHUDForContext_unfocused_window.js \
 	browser_webconsole_bug_595350_multiple_windows_and_tabs.js \
 	browser_webconsole_bug_594497_history_arrow_keys.js \
 	browser_webconsole_bug_588342_document_focus.js \
 	browser_webconsole_bug_595934_message_categories.js \
 	browser_webconsole_bug_601352_scroll.js \
new file mode 100644
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_583816_No_input_and_Tab_key_pressed.js
@@ -0,0 +1,70 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Web Console test suite.
+ *
+ * The Initial Developer of the Original Code is
+ * The Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Mihai Sucan <mihai.sucan@gmail.com>
+ *   Jignesh Kakadiya <jigneshhk1992@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test//browser/test-console.html";
+
+function test() {
+  addTab(TEST_URI);
+  browser.addEventListener("DOMContentLoaded", testCompletion, false);
+}
+
+function testCompletion() {
+  browser.removeEventListener("DOMContentLoaded", testCompletion, false);
+
+  openConsole();
+
+  var jsterm = HUDService.getHudByWindow(content).jsterm;
+  var input = jsterm.inputNode;
+
+  jsterm.setInputValue("");
+  EventUtils.synthesizeKey("VK_TAB", {});
+  is(jsterm.completeNode.value, "<- no result", "<- no result - matched");
+  is(input.value, "", "inputnode is empty - matched")
+  is(input.getAttribute("focused"), "true", "input is still focused");
+
+  //Any thing which is not in property autocompleter
+  jsterm.setInputValue("window.Bug583816");
+  EventUtils.synthesizeKey("VK_TAB", {});
+  is(jsterm.completeNode.value, "                <- no result", "completenode content - matched");
+  is(input.value, "window.Bug583816", "inputnode content - matched");
+  is(input.getAttribute("focused"), "true", "input is still focused");
+
+  jsterm = input = null;
+  finishTest();
+}
deleted file mode 100644
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_583816_tab_focus.js
+++ /dev/null
@@ -1,61 +0,0 @@
-/* vim:set ts=2 sw=2 sts=2 et: */
-/* ***** BEGIN LICENSE BLOCK *****
- * Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/
- *
- * Contributor(s):
- *  Mihai Șucan <mihai.sucan@gmail.com>
- *
- * ***** END LICENSE BLOCK ***** */
-
-const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test//test-console.html";
-
-let HUD, inputNode;
-
-function tabLoad(aEvent) {
-  browser.removeEventListener(aEvent.type, arguments.callee, true);
-
-  waitForFocus(function() {
-    openConsole();
-
-    HUD = HUDService.getHudByWindow(content);
-
-    inputNode = HUD.jsterm.inputNode;
-
-    inputNode.focus();
-    executeSoon(function() {
-      is(inputNode.getAttribute("focused"), "true", "inputNode is focused");
-      HUD.jsterm.setInputValue("doc");
-      inputNode.addEventListener("keyup", firstTab, false);
-      EventUtils.synthesizeKey("VK_TAB", {});
-    });
-  }, content);
-}
-
-function firstTab(aEvent) {
-  this.removeEventListener(aEvent.type, arguments.callee, false);
-
-  is(inputNode.getAttribute("focused"), "true", "inputNode is still focused");
-  isnot(this.value, "doc", "input autocompleted");
-
-  HUD.jsterm.setInputValue("foobarbaz" + Date.now());
-
-  EventUtils.synthesizeKey("VK_TAB", {});
-
-  executeSoon(secondTab);
-}
-
-function secondTab() {
-  isnot(inputNode.getAttribute("focused"), "true",
-          "inputNode is no longer focused");
-
-  HUD = inputNode = null;
-  HUDService.deactivateHUDForContext(gBrowser.selectedTab);
-  executeSoon(finish);
-}
-
-function test() {
-  addTab(TEST_URI);
-  browser.addEventListener("load", tabLoad, true);
-}
-
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_603750_websocket.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_603750_websocket.js
@@ -16,18 +16,17 @@ let errors = 0;
 let lastWindowId = 0;
 let oldPref_ws;
 
 let TestObserver = {
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]),
 
   observe: function test_observe(aSubject)
   {
-    if (!(aSubject instanceof Ci.nsIScriptError) ||
-        !(aSubject instanceof Ci.nsIScriptError2)) {
+    if (!(aSubject instanceof Ci.nsIScriptError)) {
       return;
     }
 
     is(aSubject.category, "Web Socket", "received a Web Socket error");
     isnot(aSubject.sourceName.indexOf("test-bug-603750-websocket.js"), -1,
           "sourceName is correct");
 
     if (++errors == 2) {
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -214,16 +214,17 @@
 @BINPATH@/components/necko.xpt
 @BINPATH@/components/loginmgr.xpt
 @BINPATH@/components/parentalcontrols.xpt
 @BINPATH@/components/places.xpt
 @BINPATH@/components/plugin.xpt
 @BINPATH@/components/pref.xpt
 @BINPATH@/components/prefetch.xpt
 @BINPATH@/components/profile.xpt
+@BINPATH@/components/profiler.xpt
 @BINPATH@/components/proxyObject.xpt
 @BINPATH@/components/rdf.xpt
 @BINPATH@/components/satchel.xpt
 @BINPATH@/components/saxparser.xpt
 @BINPATH@/components/sessionstore.xpt
 @BINPATH@/components/services-crypto-component.xpt
 @BINPATH@/components/shellservice.xpt
 @BINPATH@/components/shistory.xpt
--- a/browser/locales/en-US/chrome/browser/devtools/webconsole.properties
+++ b/browser/locales/en-US/chrome/browser/devtools/webconsole.properties
@@ -166,9 +166,14 @@ stacktrace.outputMessage=Stack trace fro
 # %S=name of timer
 timerStarted=%S: timer started
 
 # LOCALIZATION NOTE (timeEnd):
 # This string is used to display the result of the console.timeEnd() call.
 # %1$S=name of timer, %2$S=number of milliseconds
 timeEnd=%1$S: %2$Sms
 
+# LOCALIZATION NOTE (Autocomplete.blank):
+# This string is used when inputnode string containing anchor doesn't
+# doesn't matches to any property in the content.
+Autocomplete.blank=  <- no result
+
 maxTimersExceeded=The maximum allowed number of timers in this page was exceeded.
--- a/build/binary-location.mk
+++ b/build/binary-location.mk
@@ -35,17 +35,17 @@
 # 
 # ***** END LICENSE BLOCK *****
 
 # finds the location of the browser and puts it in the variable $(browser_path)
 
 ifneq (,$(filter OS2 WINNT,$(OS_ARCH)))
 PROGRAM = $(MOZ_APP_NAME)$(BIN_SUFFIX)
 else
-ifeq ($(MOZ_BUILD_APP),mobile)
+ifeq ($(MOZ_BUILD_APP),mobile/xul)
 PROGRAM = $(MOZ_APP_NAME)$(BIN_SUFFIX)
 else
 PROGRAM = $(MOZ_APP_NAME)-bin$(BIN_SUFFIX)
 endif
 endif
 
 TARGET_DIST = $(TARGET_DEPTH)/dist
 
--- a/config/system-headers
+++ b/config/system-headers
@@ -526,16 +526,17 @@ netinet/in_systm.h
 netinet/tcp.h
 new
 newexe.h
 new.h
 nl_types.h
 NodeInfo.h
 nss.h
 nssilock.h
+nsswitch.h
 objbase.h
 objidl.h
 Objsafe.h
 ojiapitests.h
 ole2.h
 oleidl.h
 OpenGL/OpenGL.h
 OpenTptInternet.h
@@ -745,16 +746,17 @@ sys/stack.h
 sys/statfs.h
 sys/stat.h
 sys/statvfs.h
 sys/syscall.h
 sys/sysctl.h
 sys/sysinfo.h
 sys/sysmp.h
 sys/syssgi.h
+sys/system_properties.h
 sys/systeminfo.h
 sys/timeb.h
 sys/time.h
 sys/times.h
 sys/ttycom.h
 sys/types.h
 sys/ucontext.h
 sys/uio.h
--- a/configure.in
+++ b/configure.in
@@ -308,17 +308,17 @@ if test -n "$gonkdir" ; then
     LD="$gonk_toolchain"/bin/"$android_tool_prefix"-ld
     AR="$gonk_toolchain"/bin/"$android_tool_prefix"-ar
     RANLIB="$gonk_toolchain"/bin/"$android_tool_prefix"-ranlib
     STRIP="$gonk_toolchain"/bin/"$android_tool_prefix"-strip
 
     STLPORT_CPPFLAGS="-I$gonkdir/ndk/sources/cxx-stl/stlport/stlport/"
     STLPORT_LIBS="-lstlport"
 
-    CPPFLAGS="-DANDROID -I$gonkdir/bionic/libc/include/ -I$gonkdir/bionic/libc/kernel/common -I$gonkdir/bionic/libc/arch-arm/include -I$gonkdir/bionic/libc/kernel/arch-arm -I$gonkdir/bionic/libm/include -I$gonkdir/frameworks/base/opengl/include -I$gonkdir/frameworks/base/native/include -I$gonkdir/hardware/libhardware/include -I$gonkdir/system/core/include -I$gonkdir/bionic -I$gonkdir/frameworks/base/include $STLPORT_CPPFLAGS $CPPFLAGS"
+    CPPFLAGS="-DANDROID -I$gonkdir/bionic/libc/include/ -I$gonkdir/bionic/libc/kernel/common -I$gonkdir/bionic/libc/arch-arm/include -I$gonkdir/bionic/libc/kernel/arch-arm -I$gonkdir/bionic/libm/include -I$gonkdir/frameworks/base/opengl/include -I$gonkdir/frameworks/base/native/include -I$gonkdir/hardware/libhardware/include -I$gonkdir/hardware/libhardware_legacy/include -I$gonkdir/system/core/include -I$gonkdir/bionic -I$gonkdir/frameworks/base/include $STLPORT_CPPFLAGS $CPPFLAGS"
     CFLAGS="-mandroid -fno-short-enums -fno-exceptions $CFLAGS"
     CXXFLAGS="-mandroid -fno-short-enums -fno-exceptions $CXXFLAGS"
     LIBS="$LIBS $STLPORT_LIBS"
 
     dnl Add -llog by default, since we use it all over the place.
     LDFLAGS="-mandroid -L$gonkdir/out/target/product/$GONK_PRODUCT/obj/lib -Wl,-rpath-link=$gonkdir/out/target/product/$GONK_PRODUCT/obj/lib --sysroot=$gonkdir/out/target/product/$GONK_PRODUCT/obj/ -llog $LDFLAGS"
 
     dnl prevent cross compile section from using these flags as host flags
--- a/content/base/src/nsAttrAndChildArray.h
+++ b/content/base/src/nsAttrAndChildArray.h
@@ -39,16 +39,18 @@
 /*
  * Storage of the children and attributes of a DOM node; storage for
  * the two is unified to minimize footprint.
  */
 
 #ifndef nsAttrAndChildArray_h___
 #define nsAttrAndChildArray_h___
 
+#include "mozilla/Attributes.h"
+
 #include "nscore.h"
 #include "nsAttrName.h"
 #include "nsAttrValue.h"
 
 class nsINode;
 class nsIContent;
 class nsMappedAttributes;
 class nsHTMLStyleSheet;
@@ -131,18 +133,18 @@ public:
   {
     return AttrSlotCount() < ATTRCHILD_ARRAY_MAX_ATTR_COUNT ||
            !AttrSlotIsTaken(ATTRCHILD_ARRAY_MAX_ATTR_COUNT - 1);
   }
 
   PRInt64 SizeOf() const;
 
 private:
-  nsAttrAndChildArray(const nsAttrAndChildArray& aOther); // Not to be implemented
-  nsAttrAndChildArray& operator=(const nsAttrAndChildArray& aOther); // Not to be implemented
+  nsAttrAndChildArray(const nsAttrAndChildArray& aOther) MOZ_DELETE;
+  nsAttrAndChildArray& operator=(const nsAttrAndChildArray& aOther) MOZ_DELETE;
 
   void Clear();
 
   PRUint32 NonMappedAttrCount() const;
   PRUint32 MappedAttrCount() const;
 
   nsresult GetModifiableMapped(nsMappedAttributeElement* aContent,
                                nsHTMLStyleSheet* aSheet,
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -2826,30 +2826,29 @@ nsContentUtils::ReportToConsole(PRUint32
     rv = GetLocalizedString(aFile, aMessageName, errorText);
   }
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCAutoString spec;
   if (aURI)
     aURI->GetSpec(spec);
 
-  nsCOMPtr<nsIScriptError2> errorObject =
+  nsCOMPtr<nsIScriptError> errorObject =
       do_CreateInstance(NS_SCRIPTERROR_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = errorObject->InitWithWindowID(errorText.get(),
                                      NS_ConvertUTF8toUTF16(spec).get(), // file name
                                      aSourceLine.get(),
                                      aLineNumber, aColumnNumber,
                                      aErrorFlags, aCategory,
                                      innerWindowID);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsCOMPtr<nsIScriptError> logError = do_QueryInterface(errorObject);
-  return sConsoleService->LogMessage(logError);
+  return sConsoleService->LogMessage(errorObject);
 }
 
 bool
 nsContentUtils::IsChromeDoc(nsIDocument *aDocument)
 {
   if (!aDocument) {
     return false;
   }
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -1397,21 +1397,19 @@ nsDOMImplementation::CreateDocumentType(
 
   nsresult rv = nsContentUtils::CheckQName(aQualifiedName);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIAtom> name = do_GetAtom(aQualifiedName);
   NS_ENSURE_TRUE(name, NS_ERROR_OUT_OF_MEMORY);
 
   // Indicate that there is no internal subset (not just an empty one)
-  nsAutoString voidString;
-  voidString.SetIsVoid(true);
   return NS_NewDOMDocumentType(aReturn, mOwner->NodeInfoManager(),
                                name, aPublicId,
-                               aSystemId, voidString);
+                               aSystemId, NullString());
 }
 
 NS_IMETHODIMP
 nsDOMImplementation::CreateDocument(const nsAString& aNamespaceURI,
                                     const nsAString& aQualifiedName,
                                     nsIDOMDocumentType* aDoctype,
                                     nsIDOMDocument** aReturn)
 {
@@ -1456,24 +1454,22 @@ NS_IMETHODIMP
 nsDOMImplementation::CreateHTMLDocument(const nsAString& aTitle,
                                         nsIDOMDocument** aReturn)
 {
   *aReturn = nsnull;
   NS_ENSURE_STATE(mOwner);
 
   nsCOMPtr<nsIDOMDocumentType> doctype;
   // Indicate that there is no internal subset (not just an empty one)
-  nsAutoString voidString;
-  voidString.SetIsVoid(true);
   nsresult rv = NS_NewDOMDocumentType(getter_AddRefs(doctype),
                                       mOwner->NodeInfoManager(),
                                       nsGkAtoms::html, // aName
                                       EmptyString(), // aPublicId
                                       EmptyString(), // aSystemId
-                                      voidString); // aInternalSubset
+                                      NullString()); // aInternalSubset
   NS_ENSURE_SUCCESS(rv, rv);
 
 
   nsCOMPtr<nsIScriptGlobalObject> scriptHandlingObject =
     do_QueryReferent(mScriptObject);
 
   NS_ENSURE_STATE(!mScriptObject || scriptHandlingObject);
                                                        
--- a/content/base/src/nsEventSource.cpp
+++ b/content/base/src/nsEventSource.cpp
@@ -1086,41 +1086,41 @@ nsEventSource::PrintErrorOnConsole(const
   nsresult rv =
     bundleService->CreateBundle(aBundleURI, getter_AddRefs(strBundle));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIConsoleService> console(
     do_GetService(NS_CONSOLESERVICE_CONTRACTID, &rv));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsCOMPtr<nsIScriptError2> errObj(
+  nsCOMPtr<nsIScriptError> errObj(
     do_CreateInstance(NS_SCRIPTERROR_CONTRACTID, &rv));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Localize the error message
   nsXPIDLString message;
   if (aFormatStrings) {
     rv = strBundle->FormatStringFromName(aError, aFormatStrings,
                                          aFormatStringsLen,
                                          getter_Copies(message));
   } else {
     rv = strBundle->GetStringFromName(aError, getter_Copies(message));
   }
   NS_ENSURE_SUCCESS(rv, rv);
 
-  errObj->InitWithWindowID(message.get(),
-                           mScriptFile.get(),
-                           nsnull,
-                           mScriptLine, 0,
-                           nsIScriptError::errorFlag,
-                           "Event Source", mInnerWindowID);
+  rv = errObj->InitWithWindowID(message.get(),
+                                mScriptFile.get(),
+                                nsnull,
+                                mScriptLine, 0,
+                                nsIScriptError::errorFlag,
+                                "Event Source", mInnerWindowID);
+  NS_ENSURE_SUCCESS(rv, rv);
 
   // print the error message directly to the JS console
-  nsCOMPtr<nsIScriptError> logError = do_QueryInterface(errObj);
-  rv = console->LogMessage(logError);
+  rv = console->LogMessage(errObj);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
 nsresult
 nsEventSource::ConsoleError()
 {
--- a/content/base/src/nsScriptLoader.cpp
+++ b/content/base/src/nsScriptLoader.cpp
@@ -115,17 +115,17 @@ public:
   }
 
   nsCOMPtr<nsIScriptElement> mElement;
   bool mLoading;             // Are we still waiting for a load to complete?
   bool mIsInline;            // Is the script inline or loaded?
   nsString mScriptText;              // Holds script for loaded scripts
   PRUint32 mJSVersion;
   nsCOMPtr<nsIURI> mURI;
-  nsCOMPtr<nsIURI> mFinalURI;
+  nsCOMPtr<nsIPrincipal> mOriginPrincipal;
   PRInt32 mLineNo;
 };
 
 // The nsScriptLoadRequest is passed as the context to necko, and thus
 // it needs to be threadsafe. Necko won't do anything with this
 // context, but it will AddRef and Release it on other threads.
 NS_IMPL_THREADSAFE_ISUPPORTS0(nsScriptLoadRequest)
 
@@ -877,33 +877,34 @@ nsScriptLoader::EvaluateScript(nsScriptL
   // Make sure context is a strong reference since we access it after
   // we've executed a script, which may cause all other references to
   // the context to go away.
   nsCOMPtr<nsIScriptContext> context = globalObject->GetScriptContext(stid);
   if (!context) {
     return NS_ERROR_FAILURE;
   }
 
-  nsIURI* uri = aRequest->mFinalURI ? aRequest->mFinalURI : aRequest->mURI;
-
   bool oldProcessingScriptTag = context->GetProcessingScriptTag();
   context->SetProcessingScriptTag(true);
 
   // Update our current script.
   nsCOMPtr<nsIScriptElement> oldCurrent = mCurrentScript;
   mCurrentScript = aRequest->mElement;
 
+  // It's very important to use aRequest->mURI, not the final URI of the channel
+  // aRequest ended up getting script data from, as the script filename.
   nsCAutoString url;
-  nsContentUtils::GetWrapperSafeScriptFilename(mDocument, uri, url);
+  nsContentUtils::GetWrapperSafeScriptFilename(mDocument, aRequest->mURI, url);
 
   bool isUndefined;
   rv = context->EvaluateString(aScript, globalObject->GetGlobalJSObject(),
-                          mDocument->NodePrincipal(), url.get(),
-                          aRequest->mLineNo, aRequest->mJSVersion, nsnull,
-                          &isUndefined);
+                               mDocument->NodePrincipal(),
+                               aRequest->mOriginPrincipal,
+                               url.get(), aRequest->mLineNo,
+                               aRequest->mJSVersion, nsnull, &isUndefined);
 
   // Put the old script back in case it wants to do anything else.
   mCurrentScript = oldCurrent;
 
   JSContext *cx = nsnull; // Initialize this to keep GCC happy.
   if (stid == nsIProgrammingLanguage::JAVASCRIPT) {
     cx = context->GetNativeContext();
     ::JS_BeginRequest(cx);
@@ -1208,17 +1209,20 @@ nsScriptLoader::PrepareLoadedRequest(nsS
     bool requestSucceeded;
     rv = httpChannel->GetRequestSucceeded(&requestSucceeded);
     if (NS_SUCCEEDED(rv) && !requestSucceeded) {
       return NS_ERROR_NOT_AVAILABLE;
     }
   }
 
   nsCOMPtr<nsIChannel> channel = do_QueryInterface(req);
-  NS_GetFinalChannelURI(channel, getter_AddRefs(aRequest->mFinalURI));
+  rv = nsContentUtils::GetSecurityManager()->
+    GetChannelPrincipal(channel, getter_AddRefs(aRequest->mOriginPrincipal));
+  NS_ENSURE_SUCCESS(rv, rv);
+
   if (aStringLen) {
     // Check the charset attribute to determine script charset.
     nsAutoString hintCharset;
     if (!aRequest->IsPreload()) {
       aRequest->mElement->GetScriptCharset(hintCharset);
     } else {
       nsTArray<PreloadInfo>::index_type i =
         mPreloads.IndexOf(aRequest, 0, PreloadRequestComparator());
--- a/content/base/src/nsWebSocket.cpp
+++ b/content/base/src/nsWebSocket.cpp
@@ -122,40 +122,40 @@ nsWebSocket::PrintErrorOnConsole(const c
   nsCOMPtr<nsIStringBundle> strBundle;
   rv = bundleService->CreateBundle(aBundleURI, getter_AddRefs(strBundle));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIConsoleService> console(
     do_GetService(NS_CONSOLESERVICE_CONTRACTID, &rv));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsCOMPtr<nsIScriptError2> errorObject(
+  nsCOMPtr<nsIScriptError> errorObject(
     do_CreateInstance(NS_SCRIPTERROR_CONTRACTID, &rv));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Localize the error message
   nsXPIDLString message;
   if (aFormatStrings) {
     rv = strBundle->FormatStringFromName(aError, aFormatStrings,
                                          aFormatStringsLen,
                                          getter_Copies(message));
   } else {
     rv = strBundle->GetStringFromName(aError, getter_Copies(message));
   }
   NS_ENSURE_SUCCESS(rv, rv);
 
-  errorObject->InitWithWindowID(message.get(),
-                                NS_ConvertUTF8toUTF16(mScriptFile).get(),
-                                nsnull, mScriptLine, 0,
-                                nsIScriptError::errorFlag, "Web Socket",
-                                mInnerWindowID);
+  rv = errorObject->InitWithWindowID(message.get(),
+                                     NS_ConvertUTF8toUTF16(mScriptFile).get(),
+                                     nsnull, mScriptLine, 0,
+                                     nsIScriptError::errorFlag, "Web Socket",
+                                     mInnerWindowID);
+  NS_ENSURE_SUCCESS(rv, rv);
 
   // print the error message directly to the JS console
-  nsCOMPtr<nsIScriptError> logError(do_QueryInterface(errorObject));
-  rv = console->LogMessage(logError);
+  rv = console->LogMessage(errorObject);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
 // when this is called the browser side wants no more part of it
 nsresult
 nsWebSocket::CloseConnection()
--- a/content/base/test/test_bug461735.html
+++ b/content/base/test/test_bug461735.html
@@ -14,30 +14,34 @@ https://bugzilla.mozilla.org/show_bug.cg
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script type="application/javascript">
 var errorFired = false;
 window.onerror = function(message, uri, line) {
   is(message, "Script error.", "Should have empty error message");
-  is(uri, "", "Should have empty error location URI");
+  is(uri,
+     "http://mochi.test:8888/tests/content/base/test/bug461735-redirect1.sjs",
+     "Should have pre-redirect error location URI");
   is(line, 0, "Shouldn't have a line here");
   errorFired = true;
 }
 </script>
 <script src="bug461735-redirect1.sjs"></script>
 <script>
   is(errorFired, true, "Should have error in redirected different origin script");
   errorFired = false;
 </script>
 <script type="application/javascript">
 window.onerror = function(message, uri, line) {
   is(message, "c is not defined", "Should have correct error message");
-  is(uri, "http://mochi.test:8888/tests/content/base/test/bug461735-post-redirect.js", "Unexpected error location URI");
+  is(uri,
+     "http://mochi.test:8888/tests/content/base/test/bug461735-redirect2.sjs",
+     "Unexpected error location URI");
   is(line, 3, "Should have a line here");
   errorFired = true;
 }
 </script>
 <script src="bug461735-redirect2.sjs"></script>
 <script>
   is(errorFired, true, "Should have error in same origin script");
 </script>
--- a/content/base/test/test_createHTMLDocument.html
+++ b/content/base/test/test_createHTMLDocument.html
@@ -19,16 +19,17 @@ function checkDoc(title, expectedtitle, 
   var doc = document.implementation.createHTMLDocument(title);
   is(doc.readyState, "complete");
   is(doc.compatMode, "CSS1Compat");
   // Opera doesn't have a doctype: DSK-311092
   ok(doc.doctype, "Need a doctype");
   is(doc.doctype.name, "html");
   is(doc.doctype.publicId, "");
   is(doc.doctype.systemId, "");
+  is(doc.doctype.internalSubset, null, "internalSubset should be null!");
   isElement(doc.documentElement, "html");
   isElement(doc.documentElement.firstChild, "head");
   is(doc.documentElement.firstChild.childNodes.length, 1);
   isElement(doc.documentElement.firstChild.firstChild, "title");
   // Doesn't always work out in WebKit.
   ok(doc.documentElement.firstChild.firstChild.firstChild, "Need a text node.");
   is(doc.documentElement.firstChild.firstChild.firstChild.data, expectedtitle);
   isElement(doc.documentElement.lastChild, "body");
--- a/content/canvas/src/CustomQS_Canvas2D.h
+++ b/content/canvas/src/CustomQS_Canvas2D.h
@@ -72,20 +72,17 @@ Canvas2D_SetStyleHelper(JSContext *cx, J
         nsISupports *arg0;
         xpc_qsSelfRef arg0ref;
         rv = xpc_qsUnwrapArg<nsISupports>(cx, *vp, &arg0, &arg0ref.ptr, vp);
         if (NS_FAILED(rv)) {
             xpc_qsThrowBadSetterValue(cx, rv, JSVAL_TO_OBJECT(*tvr.jsval_addr()), id);
             return JS_FALSE;
         }
 
-        nsString voidStr;
-        voidStr.SetIsVoid(true);
-
-        rv = (self->*setfunc)(voidStr, arg0);
+        rv = (self->*setfunc)(NullString(), arg0);
     }
 
     if (NS_FAILED(rv))
         return xpc_qsThrowGetterSetterFailed(cx, rv, JSVAL_TO_OBJECT(*tvr.jsval_addr()), id);
 
     return JS_TRUE;
 }
 
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -4503,16 +4503,41 @@ nsEventStateManager::UpdateAncestorState
     }
     Element* element = aStartNode->AsElement();
     DoStateChange(element, aState, aAddState);
     Element* labelTarget = GetLabelTarget(element);
     if (labelTarget) {
       DoStateChange(labelTarget, aState, aAddState);
     }
   }
+
+  if (aAddState) {
+    // We might be in a situation where a node was in hover both
+    // because it was hovered and because the label for it was
+    // hovered, and while we stopped hovering the node the label is
+    // still hovered.  Or we might have had two nested labels for the
+    // same node, and while one is no longer hovered the other still
+    // is.  In that situation, the label that's still hovered will be
+    // aStopBefore or some ancestor of it, and the call we just made
+    // to UpdateAncestorState with aAddState = false would have
+    // removed the hover state from the node.  But the node should
+    // still be in hover state.  To handle this situation we need to
+    // keep walking up the tree and any time we find a label mark its
+    // corresponding node as still in our state.
+    for ( ; aStartNode; aStartNode = aStartNode->GetParent()) {
+      if (!aStartNode->IsElement()) {
+        continue;
+      }
+
+      Element* labelTarget = GetLabelTarget(aStartNode->AsElement());
+      if (labelTarget && !labelTarget->State().HasState(aState)) {
+        DoStateChange(labelTarget, aState, true);
+      }
+    }
+  }
 }
 
 bool
 nsEventStateManager::SetContentState(nsIContent *aContent, nsEventStates aState)
 {
   // We manage 4 states here: ACTIVE, HOVER, DRAGOVER, URLTARGET
   // The input must be exactly one of them.
   NS_PRECONDITION(aState == NS_EVENT_STATE_ACTIVE ||
--- a/content/events/test/test_bug656379-2.html
+++ b/content/events/test/test_bug656379-2.html
@@ -4,47 +4,68 @@
 https://bugzilla.mozilla.org/show_bug.cgi?id=656379
 -->
 <head>
   <title>Test for Bug 656379</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
   <style>
-    button:hover { color: green; }
+    input[type="button"]:hover { color: green; }
   </style>
 </head>
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=656379">Mozilla Bug 656379</a>
 <p id="display">
   <label for="button1" id="label1">Label 1</label>
-  <button id="button1">Button 1</button>
-  <label><span id="label2">Label 2</span><button id="button2">Button 2</button></label>
+  <input type="button" id="button1" value="Button 1">
+  <label>
+    <span id="label2">Label 2</span>
+    <input type="button" id="button2" value="Button 2">
+  </label>
 </p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script type="application/javascript;version=1.8">
 
 /** Test for Bug 656379 **/
 SimpleTest.waitForExplicitFinish();
 function tests() {
   synthesizeMouseAtCenter($("label1"), { type: "mousemove" });
   yield;
   is($("button1").mozMatchesSelector(":hover"), true,
-     "Button 1 should be hovered");
+     "Button 1 should be hovered after mousemove over label1");
+  is($("label1").mozMatchesSelector(":hover"), true,
+     "Label 1 should be hovered after mousemove over label1");
   is($("button2").mozMatchesSelector(":hover"), false,
-     "Button 2 should not be hovered");
+     "Button 2 should not be hovered after mousemove over label1");
+  is($("label2").mozMatchesSelector(":hover"), false,
+     "Label 2 should not be hovered after mousemove over label1");
+  synthesizeMouseAtCenter($("button2"), { type: "mousemove" });
+  yield;
+  is($("button1").mozMatchesSelector(":hover"), false,
+     "Button 1 should not be hovered after mousemove over button2");
+  is($("label1").mozMatchesSelector(":hover"), false,
+     "Label 1 should not be hovered after mousemove over button2");
+  is($("button2").mozMatchesSelector(":hover"), true,
+     "Button 2 should be hovered after mousemove over button2");
+  is($("label2").mozMatchesSelector(":hover"), false,
+     "Label 2 should not be hovered after mousemove over label2");
   synthesizeMouseAtCenter($("label2"), { type: "mousemove" });
   yield;
   is($("button1").mozMatchesSelector(":hover"), false,
-     "Button 1 should not be hovered");
+     "Button 1 should not be hovered after mousemove over label2");
+  is($("label1").mozMatchesSelector(":hover"), false,
+     "Label 1 should not be hovered after mousemove over label2");
   is($("button2").mozMatchesSelector(":hover"), true,
-     "Button 2 should be hovered");
+     "Button 2 should be hovered after mousemove over label2");
+  is($("label2").mozMatchesSelector(":hover"), true,
+     "Label 2 should be hovered after mousemove over label2");
   SimpleTest.finish();
 }
 
 function executeTests() {
   var testYielder = tests();
   function execNext() {
     try {
       testYielder.next();
--- a/content/html/content/public/nsHTMLMediaElement.h
+++ b/content/html/content/public/nsHTMLMediaElement.h
@@ -351,16 +351,26 @@ public:
    * increasing during playback.
    */
   void FireTimeUpdate(bool aPeriodic);
 
 protected:
   class MediaLoadListener;
 
   /**
+   * Logs a warning message to the web console to report various failures.
+   * aMsg is the localized message identifier, aParams is the parameters to
+   * be substituted into the localized message, and aParamCount is the number
+   * of parameters in aParams.
+   */
+  void ReportLoadError(const char* aMsg,
+                       const PRUnichar** aParams = nsnull,
+                       PRUint32 aParamCount = 0);
+
+  /**
    * Changes mHasPlayedOrSeeked to aValue. If mHasPlayedOrSeeked changes
    * we'll force a reflow so that the video frame gets reflowed to reflect
    * the poster hiding or showing immediately.
    */
   void SetPlayedOrSeeked(bool aValue);
 
   /**
    * Create a decoder for the given aMIMEType. Returns null if we
--- a/content/html/content/src/nsHTMLMediaElement.cpp
+++ b/content/html/content/src/nsHTMLMediaElement.cpp
@@ -85,16 +85,18 @@
 #include "nsIAsyncVerifyRedirectCallback.h"
 #include "nsIAppShell.h"
 #include "nsWidgetsCID.h"
 
 #include "nsIPrivateDOMEvent.h"
 #include "nsIDOMNotifyAudioAvailableEvent.h"
 #include "nsMediaFragmentURIParser.h"
 #include "nsURIHashKey.h"
+#include "nsContentUtils.h"
+#include "nsIScriptError.h"
 
 #ifdef MOZ_OGG
 #include "nsOggDecoder.h"
 #endif
 #ifdef MOZ_WAVE
 #include "nsWaveDecoder.h"
 #endif
 #ifdef MOZ_WEBM
@@ -277,16 +279,30 @@ nsHTMLMediaElement::MediaLoadListener::O
 {
   nsContentUtils::UnregisterShutdownObserver(this);
 
   // Clear mElement to break cycle so we don't leak on shutdown
   mElement = nsnull;
   return NS_OK;
 }
 
+void nsHTMLMediaElement::ReportLoadError(const char* aMsg,
+                                         const PRUnichar** aParams,
+                                         PRUint32 aParamCount)
+{
+  nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
+                                  "Media",
+                                  OwnerDoc(),
+                                  nsContentUtils::eDOM_PROPERTIES,
+                                  aMsg,
+                                  aParams,
+                                  aParamCount);
+}
+
+
 NS_IMETHODIMP nsHTMLMediaElement::MediaLoadListener::OnStartRequest(nsIRequest* aRequest, nsISupports* aContext)
 {
   nsContentUtils::UnregisterShutdownObserver(this);
 
   // The element is only needed until we've had a chance to call
   // InitializeDecoderForChannel. So make sure mElement is cleared here.
   nsRefPtr<nsHTMLMediaElement> element;
   element.swap(mElement);
@@ -303,16 +319,31 @@ NS_IMETHODIMP nsHTMLMediaElement::MediaL
   nsresult rv = aRequest->GetStatus(&status);
   NS_ENSURE_SUCCESS(rv, rv);
   if (NS_FAILED(status)) {
     if (element)
       element->NotifyLoadError();
     return status;
   }
 
+  nsCOMPtr<nsIHttpChannel> hc = do_QueryInterface(aRequest);
+  bool succeeded;
+  if (hc && NS_SUCCEEDED(hc->GetRequestSucceeded(&succeeded)) && !succeeded) {
+    element->NotifyLoadError();
+    PRUint32 responseStatus = 0;
+    hc->GetResponseStatus(&responseStatus);
+    nsAutoString code;
+    code.AppendInt(responseStatus);
+    nsAutoString src;
+    element->GetCurrentSrc(src);
+    const PRUnichar* params[] = { code.get(), src.get() };
+    element->ReportLoadError("MediaLoadHttpError", params, ArrayLength(params));
+    return NS_BINDING_ABORTED;
+  }
+
   nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
   if (channel &&
       element &&
       NS_SUCCEEDED(rv = element->InitializeDecoderForChannel(channel, getter_AddRefs(mNextListener))) &&
       mNextListener) {
     rv = mNextListener->OnStartRequest(aRequest, aContext);
   } else {
     // If InitializeDecoderForChannel() returned an error, fire a network
@@ -659,16 +690,19 @@ void nsHTMLMediaElement::SelectResource(
         return;
       }
 
       rv = LoadResource();
       if (NS_SUCCEEDED(rv)) {
         mIsRunningSelectResource = false;
         return;
       }
+    } else {
+      const PRUnichar* params[] = { src.get() };
+      ReportLoadError("MediaLoadInvalidURI", params, ArrayLength(params));
     }
     NoSupportedMediaSourceError();
   } else {
     // Otherwise, the source elements will be used.
     mIsLoadingFromSourceChildren = true;
     LoadFromSourceChildren();
   }
   mIsRunningSelectResource = false;
@@ -717,40 +751,46 @@ void nsHTMLMediaElement::LoadFromSourceC
   while (true) {
     nsIContent* child = GetNextSource();
     if (!child) {
       // Exhausted candidates, wait for more candidates to be appended to
       // the media element.
       mLoadWaitStatus = WAITING_FOR_SOURCE;
       mNetworkState = nsIDOMHTMLMediaElement::NETWORK_NO_SOURCE;
       ChangeDelayLoadStatus(false);
+      ReportLoadError("MediaLoadExhaustedCandidates");
       return;
     }
 
     // Must have src attribute.
     nsAutoString src;
     if (!child->GetAttr(kNameSpaceID_None, nsGkAtoms::src, src)) {
+      ReportLoadError("MediaLoadSourceMissingSrc");
       DispatchAsyncSourceError(child);
       continue;
     }
 
     // If we have a type attribute, it must be a supported type.
     nsAutoString type;
     if (child->GetAttr(kNameSpaceID_None, nsGkAtoms::type, type) &&
         GetCanPlay(type) == CANPLAY_NO) {
       DispatchAsyncSourceError(child);
+      const PRUnichar* params[] = { type.get(), src.get() };
+      ReportLoadError("MediaLoadUnsupportedType", params, ArrayLength(params));
       continue;
     }
     LOG(PR_LOG_DEBUG, ("%p Trying load from <source>=%s type=%s", this,
       NS_ConvertUTF16toUTF8(src).get(), NS_ConvertUTF16toUTF8(type).get()));
 
     nsCOMPtr<nsIURI> uri;
     NewURIFromString(src, getter_AddRefs(uri));
     if (!uri) {
       DispatchAsyncSourceError(child);
+      const PRUnichar* params[] = { src.get() };
+      ReportLoadError("MediaLoadInvalidURI", params, ArrayLength(params));
       continue;
     }
 
     mLoadingSrc = uri;
     NS_ASSERTION(mNetworkState == nsIDOMHTMLMediaElement::NETWORK_LOADING,
                  "Network state should be loading");
 
     if (mPreloadAction == nsHTMLMediaElement::PRELOAD_NONE) {
@@ -1946,16 +1986,21 @@ nsresult nsHTMLMediaElement::InitializeD
 {
   NS_ASSERTION(mLoadingSrc, "mLoadingSrc must already be set");
 
   nsCAutoString mimeType;
   aChannel->GetContentType(mimeType);
 
   nsRefPtr<nsMediaDecoder> decoder = CreateDecoder(mimeType);
   if (!decoder) {
+    nsAutoString src;
+    GetCurrentSrc(src);
+    NS_ConvertUTF8toUTF16 mimeUTF16(mimeType);
+    const PRUnichar* params[] = { mimeUTF16.get(), src.get() };
+    ReportLoadError("MediaLoadUnsupportedMimeType", params, ArrayLength(params));
     return NS_ERROR_FAILURE;
   }
 
   LOG(PR_LOG_DEBUG, ("%p Created decoder %p for type %s", this, decoder.get(), mimeType.get()));
 
   mNetworkState = nsIDOMHTMLMediaElement::NETWORK_LOADING;
 
   nsMediaStream* stream = nsMediaStream::Create(decoder, aChannel);
@@ -2115,16 +2160,21 @@ void nsHTMLMediaElement::ResourceLoaded(
 
 void nsHTMLMediaElement::NetworkError()
 {
   Error(nsIDOMMediaError::MEDIA_ERR_NETWORK);
 }
 
 void nsHTMLMediaElement::DecodeError()
 {
+  nsAutoString src;
+  GetCurrentSrc(src);
+  const PRUnichar* params[] = { src.get() };
+  ReportLoadError("MediaLoadDecodeError", params, ArrayLength(params));
+
   if (mDecoder) {
     RemoveMediaElementFromURITable();
     mDecoder->Shutdown();
     mDecoder = nsnull;
   }
   mLoadingSrc = nsnull;
   if (mIsLoadingFromSourceChildren) {
     mError = nsnull;
--- a/content/html/document/src/nsHTMLContentSink.cpp
+++ b/content/html/document/src/nsHTMLContentSink.cpp
@@ -2448,21 +2448,19 @@ HTMLContentSink::AddDocTypeDecl(const ns
     }
 
     nsCOMPtr<nsIAtom> nameAtom = do_GetAtom(name);
     if (!nameAtom) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
 
     // Indicate that there is no internal subset (not just an empty one)
-    nsAutoString voidString;
-    voidString.SetIsVoid(true);
     rv = NS_NewDOMDocumentType(getter_AddRefs(docType),
                                mDocument->NodeInfoManager(), nameAtom,
-                               publicId, systemId, voidString);
+                               publicId, systemId, NullString());
     NS_ENSURE_SUCCESS(rv, rv);
 
     if (oldDocType) {
       // If we already have a doctype we replace the old one.
       nsCOMPtr<nsIDOMNode> tmpNode;
       rv = doc->ReplaceChild(oldDocType, docType, getter_AddRefs(tmpNode));
     } else {
       // If we don't already have one we insert it as the first child,
--- a/content/xml/document/src/nsXMLDocument.cpp
+++ b/content/xml/document/src/nsXMLDocument.cpp
@@ -396,34 +396,33 @@ nsXMLDocument::Load(const nsAString& aUr
     if (NS_FAILED(uri->SchemeIs("chrome", &isChrome)) || !isChrome) {
       nsCAutoString spec;
       if (mDocumentURI)
         mDocumentURI->GetSpec(spec);
 
       nsAutoString error;
       error.AssignLiteral("Cross site loading using document.load is no "
                           "longer supported. Use XMLHttpRequest instead.");
-      nsCOMPtr<nsIScriptError2> errorObject =
+      nsCOMPtr<nsIScriptError> errorObject =
           do_CreateInstance(NS_SCRIPTERROR_CONTRACTID, &rv);
       NS_ENSURE_SUCCESS(rv, rv);
 
       rv = errorObject->InitWithWindowID(error.get(), NS_ConvertUTF8toUTF16(spec).get(),
                                          nsnull, 0, 0, nsIScriptError::warningFlag,
                                          "DOM",
                                          callingDoc ?
                                            callingDoc->InnerWindowID() :
                                            this->InnerWindowID());
 
       NS_ENSURE_SUCCESS(rv, rv);
 
       nsCOMPtr<nsIConsoleService> consoleService =
         do_GetService(NS_CONSOLESERVICE_CONTRACTID);
-      nsCOMPtr<nsIScriptError> logError = do_QueryInterface(errorObject);
-      if (consoleService && logError) {
-        consoleService->LogMessage(logError);
+      if (consoleService) {
+        consoleService->LogMessage(errorObject);
       }
 
       return NS_ERROR_DOM_SECURITY_ERR;
     }
   }
 
   // Partial Reset, need to restore principal for security reasons and
   // event listener manager so that load listeners etc. will
--- a/content/xslt/src/xslt/txMozillaXMLOutput.cpp
+++ b/content/xslt/src/xslt/txMozillaXMLOutput.cpp
@@ -931,24 +931,22 @@ txMozillaXMLOutput::createResultDocument
         nsresult rv = nsContentUtils::CheckQName(qName);
         if (NS_SUCCEEDED(rv)) {
             nsCOMPtr<nsIAtom> doctypeName = do_GetAtom(qName);
             if (!doctypeName) {
                 return NS_ERROR_OUT_OF_MEMORY;
             }
 
             // Indicate that there is no internal subset (not just an empty one)
-            nsAutoString voidString;
-            voidString.SetIsVoid(true);
             rv = NS_NewDOMDocumentType(getter_AddRefs(documentType),
                                        mNodeInfoManager,
                                        doctypeName,
                                        mOutputFormat.mPublicId,
                                        mOutputFormat.mSystemId,
-                                       voidString);
+                                       NullString());
             NS_ENSURE_SUCCESS(rv, rv);
 
             nsCOMPtr<nsIContent> docType = do_QueryInterface(documentType);
             rv = mDocument->AppendChildTo(docType, true);
             NS_ENSURE_SUCCESS(rv, rv);
         }
     }
 
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -1723,17 +1723,17 @@ PrintWarningOnConsole(JSContext *cx, con
   }
 
   nsCOMPtr<nsIConsoleService> consoleService
     (do_GetService(NS_CONSOLESERVICE_CONTRACTID));
   if (!consoleService) {
     return;
   }
 
-  nsCOMPtr<nsIScriptError2> scriptError =
+  nsCOMPtr<nsIScriptError> scriptError =
     do_CreateInstance(NS_SCRIPTERROR_CONTRACTID);
   if (!scriptError) {
     return;
   }
 
   JSStackFrame *fp, *iterator = nsnull;
   fp = ::JS_FrameIterator(cx, &iterator);
   PRUint32 lineno = 0;
@@ -1756,19 +1756,18 @@ PrintWarningOnConsole(JSContext *cx, con
                                               sourcefile.get(),
                                               EmptyString().get(),
                                               lineno,
                                               0, // column for error is not available
                                               nsIScriptError::warningFlag,
                                               "DOM:HTML",
                                               nsJSUtils::GetCurrentlyRunningCodeInnerWindowID(cx));
 
-  if (NS_SUCCEEDED(rv)){
-    nsCOMPtr<nsIScriptError> logError = do_QueryInterface(scriptError);
-    consoleService->LogMessage(logError);
+  if (NS_SUCCEEDED(rv)) {
+    consoleService->LogMessage(scriptError);
   }
 }
 
 static inline JSString *
 IdToString(JSContext *cx, jsid id)
 {
   if (JSID_IS_STRING(id))
     return JSID_TO_STRING(id);
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -9256,17 +9256,18 @@ nsGlobalWindow::RunTimeout(nsTimeout *aT
       const char *filename = nsnull;
       PRUint32 lineNo = 0;
       handler->GetLocation(&filename, &lineNo);
 
       NS_TIME_FUNCTION_MARK("(file: %s, line: %d)", filename, lineNo);
 
       bool is_undefined;
       scx->EvaluateString(nsDependentString(script), FastGetGlobalJSObject(),
-                          timeout->mPrincipal, filename, lineNo,
+                          timeout->mPrincipal, timeout->mPrincipal,
+                          filename, lineNo,
                           handler->GetScriptVersion(), nsnull,
                           &is_undefined);
     } else {
       // Let the script handler know about the "secret" final argument that
       // indicates timeout lateness in milliseconds
       TimeDuration lateness = now - timeout->mWhen;
 
       handler->SetLateness(lateness.ToMilliseconds());
--- a/dom/base/nsIScriptContext.h
+++ b/dom/base/nsIScriptContext.h
@@ -69,18 +69,18 @@ public:
 
   virtual nsIScriptObjectPrincipal* GetObjectPrincipal() = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIScriptContextPrincipal,
                               NS_ISCRIPTCONTEXTPRINCIPAL_IID)
 
 #define NS_ISCRIPTCONTEXT_IID \
-{ 0xb36103bd, 0x304e, 0x4ef2, \
-  { 0x81, 0x12, 0x83, 0x42, 0xe5, 0xbd, 0xf3, 0xd4 } }
+{ 0xf3840057, 0x4fe5, 0x4f92, \
+ { 0xa3, 0xb8, 0x27, 0xd7, 0x44, 0x6f, 0x72, 0x4d } }
 
 /* This MUST match JSVERSION_DEFAULT.  This version stuff if we don't
    know what language we have is a little silly... */
 #define SCRIPTVERSION_DEFAULT JSVERSION_DEFAULT
 
 /**
  * It is used by the application to initialize a runtime and run scripts.
  * A script runtime would implement this interface.
@@ -94,32 +94,35 @@ public:
   virtual PRUint32 GetScriptTypeID() = 0;
 
   /**
    * Compile and execute a script.
    *
    * @param aScript a string representing the script to be executed
    * @param aScopeObject a script object for the scope to execute in, or
    *                     nsnull to use a default scope
-   * @param aPrincipal the principal that produced the script
+   * @param aPrincipal the principal the script should be evaluated with
+   * @param aOriginPrincipal the principal the script originates from.  If null,
+   *                         aPrincipal is used.
    * @param aURL the URL or filename for error messages
    * @param aLineNo the starting line number of the script for error messages
    * @param aVersion the script language version to use when executing
    * @param aRetValue the result of executing the script, or null for no result.
    *        If this is a JS context, it's the caller's responsibility to
    *        preserve aRetValue from GC across this call
    * @param aIsUndefined true if the result of executing the script is the
    *                     undefined value
    *
    * @return NS_OK if the script was valid and got executed
    *
    **/
   virtual nsresult EvaluateString(const nsAString& aScript,
                                   JSObject* aScopeObject,
                                   nsIPrincipal *aPrincipal,
+                                  nsIPrincipal *aOriginPrincipal,
                                   const char *aURL,
                                   PRUint32 aLineNo,
                                   PRUint32 aVersion,
                                   nsAString *aRetValue,
                                   bool* aIsUndefined) = 0;
 
   virtual nsresult EvaluateStringWithValue(const nsAString& aScript,
                                            JSObject* aScopeObject,
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -84,16 +84,18 @@
 #include "nsIObjectInputStream.h"
 #include "nsIObjectOutputStream.h"
 #include "nsDOMScriptObjectHolder.h"
 #include "prmem.h"
 #include "WrapperFactory.h"
 #include "nsGlobalWindow.h"
 #include "nsScriptNameSpaceManager.h"
 
+#include "nsJSPrincipals.h"
+
 #ifdef XP_MACOSX
 // AssertMacros.h defines 'check' and conflicts with AccessCheck.h
 #undef check
 #endif
 #include "AccessCheck.h"
 
 #ifdef MOZ_JSDEBUGGER
 #include "jsdIDebuggerService.h"
@@ -278,23 +280,25 @@ NS_HandleScriptError(nsIScriptGlobalObje
   }
   return called;
 }
 
 class ScriptErrorEvent : public nsRunnable
 {
 public:
   ScriptErrorEvent(nsIScriptGlobalObject* aScriptGlobal,
+                   nsIPrincipal* aScriptOriginPrincipal,
                    PRUint32 aLineNr, PRUint32 aColumn, PRUint32 aFlags,
                    const nsAString& aErrorMsg,
                    const nsAString& aFileName,
                    const nsAString& aSourceLine,
                    bool aDispatchEvent,
                    PRUint64 aInnerWindowID)
-  : mScriptGlobal(aScriptGlobal), mLineNr(aLineNr), mColumn(aColumn),
+    : mScriptGlobal(aScriptGlobal), mOriginPrincipal(aScriptOriginPrincipal),
+      mLineNr(aLineNr), mColumn(aColumn),
     mFlags(aFlags), mErrorMsg(aErrorMsg), mFileName(aFileName),
     mSourceLine(aSourceLine), mDispatchEvent(aDispatchEvent),
     mInnerWindowID(aInnerWindowID)
   {}
 
   NS_IMETHOD Run()
   {
     nsEventStatus status = nsEventStatus_eIgnore;
@@ -315,45 +319,32 @@ public:
 
           errorevent.fileName = mFileName.get();
 
           nsCOMPtr<nsIScriptObjectPrincipal> sop(do_QueryInterface(win));
           NS_ENSURE_STATE(sop);
           nsIPrincipal* p = sop->GetPrincipal();
           NS_ENSURE_STATE(p);
 
-          bool sameOrigin = mFileName.IsVoid();
+          bool sameOrigin = !mOriginPrincipal;
 
           if (p && !sameOrigin) {
-            nsCOMPtr<nsIURI> errorURI;
-            NS_NewURI(getter_AddRefs(errorURI), mFileName);
-            if (errorURI) {
-              // FIXME: Once error reports contain the origin of the
-              // error (principals) we should change this to do the
-              // security check based on the principals and not
-              // URIs. See bug 387476.
-              sameOrigin = NS_SUCCEEDED(p->CheckMayLoad(errorURI, false));
+            if (NS_FAILED(p->Subsumes(mOriginPrincipal, &sameOrigin))) {
+              sameOrigin = false;
             }
           }
 
           NS_NAMED_LITERAL_STRING(xoriginMsg, "Script error.");
           if (sameOrigin) {
             errorevent.errorMsg = mErrorMsg.get();
             errorevent.lineNr = mLineNr;
           } else {
             NS_WARNING("Not same origin error!");
             errorevent.errorMsg = xoriginMsg.get();
             errorevent.lineNr = 0;
-            // FIXME: once the principal of the script is not tied to
-            // the filename, we can stop using the post-redirect
-            // filename if we want and remove this line.  Note that
-            // apparently we can't handle null filenames in the error
-            // event dispatching code.
-            static PRUnichar nullFilename[] = { PRUnichar(0) };
-            errorevent.fileName = nullFilename;
           }
 
           nsEventDispatcher::Dispatch(win, presContext, &errorevent, nsnull,
                                       &status);
         }
 
         sHandlingScriptError = false;
       }
@@ -375,43 +366,36 @@ public:
                      "nsIScriptObjectPrincipal");
         nsCOMPtr<nsIPrincipal> systemPrincipal;
         sSecurityManager->GetSystemPrincipal(getter_AddRefs(systemPrincipal));
         const char * category =
           scriptPrincipal->GetPrincipal() == systemPrincipal
           ? "chrome javascript"
           : "content javascript";
 
-        nsCOMPtr<nsIScriptError2> error2(do_QueryInterface(errorObject));
-        if (error2) {
-          rv = error2->InitWithWindowID(mErrorMsg.get(), mFileName.get(),
-                                        mSourceLine.get(),
-                                        mLineNr, mColumn, mFlags,
-                                        category, mInnerWindowID);
-        } else {
-          rv = errorObject->Init(mErrorMsg.get(), mFileName.get(),
-                                 mSourceLine.get(),
-                                 mLineNr, mColumn, mFlags,
-                                 category);
-        }
+        rv = errorObject->InitWithWindowID(mErrorMsg.get(), mFileName.get(),
+                                           mSourceLine.get(),
+                                           mLineNr, mColumn, mFlags,
+                                           category, mInnerWindowID);
 
         if (NS_SUCCEEDED(rv)) {
           nsCOMPtr<nsIConsoleService> consoleService =
             do_GetService(NS_CONSOLESERVICE_CONTRACTID, &rv);
           if (NS_SUCCEEDED(rv)) {
             consoleService->LogMessage(errorObject);
           }
         }
       }
     }
     return NS_OK;
   }
 
 
   nsCOMPtr<nsIScriptGlobalObject> mScriptGlobal;
+  nsCOMPtr<nsIPrincipal>          mOriginPrincipal;
   PRUint32                        mLineNr;
   PRUint32                        mColumn;
   PRUint32                        mFlags;
   nsString                        mErrorMsg;
   nsString                        mFileName;
   nsString                        mSourceLine;
   bool                            mDispatchEvent;
   PRUint64                        mInnerWindowID;
@@ -497,18 +481,21 @@ NS_ScriptErrorReporter(JSContext *cx,
       nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(globalObject);
       PRUint64 innerWindowID = 0;
       if (win) {
         nsCOMPtr<nsPIDOMWindow> innerWin = win->GetCurrentInnerWindow();
         if (innerWin) {
           innerWindowID = innerWin->WindowID();
         }
       }
+      JSPrincipals *prin = report->originPrincipals;
+      nsIPrincipal *principal =
+        prin ? static_cast<nsJSPrincipals*>(prin)->nsIPrincipalPtr : nsnull;
       nsContentUtils::AddScriptRunner(
-        new ScriptErrorEvent(globalObject, report->lineno,
+        new ScriptErrorEvent(globalObject, principal, report->lineno,
                              report->uctokenptr - report->uclinebuf,
                              report->flags, msg, fileName, sourceLine,
                              report->errorNumber != JSMSG_OUT_OF_MEMORY,
                              innerWindowID));
     }
   }
 
 #ifdef DEBUG
@@ -1384,16 +1371,17 @@ nsJSContext::GetObjectPrincipal()
   nsCOMPtr<nsIScriptObjectPrincipal> prin = do_QueryInterface(GetGlobalObject());
   return prin;
 }
 
 nsresult
 nsJSContext::EvaluateString(const nsAString& aScript,
                             JSObject* aScopeObject,
                             nsIPrincipal *aPrincipal,
+                            nsIPrincipal *aOriginPrincipal,
                             const char *aURL,
                             PRUint32 aLineNo,
                             PRUint32 aVersion,
                             nsAString *aRetValue,
                             bool* aIsUndefined)
 {
   NS_TIME_FUNCTION_MIN_FMT(1.0, "%s (line %d) (url: %s, line: %d)", MOZ_FUNCTION_NAME,
                            __LINE__, aURL, aLineNo);
@@ -1431,34 +1419,47 @@ nsJSContext::EvaluateString(const nsAStr
     if (!objPrincipal)
       return NS_ERROR_FAILURE;
     principal = objPrincipal->GetPrincipal();
     if (!principal)
       return NS_ERROR_FAILURE;
     principal->GetJSPrincipals(mContext, &jsprin);
   }
 
+  JSPrincipals *originJSprin;
+  if (aOriginPrincipal) {
+    aOriginPrincipal->GetJSPrincipals(mContext, &originJSprin);
+  } else {
+    originJSprin = nsnull;
+  }
+
   // From here on, we must JSPRINCIPALS_DROP(jsprin) before returning...
 
   bool ok = false;
 
   nsresult rv = sSecurityManager->CanExecuteScripts(mContext, principal, &ok);
   if (NS_FAILED(rv)) {
     JSPRINCIPALS_DROP(mContext, jsprin);
+    if (originJSprin) {
+      JSPRINCIPALS_DROP(mContext, originJSprin);
+    }
     return NS_ERROR_FAILURE;
   }
 
   // Push our JSContext on the current thread's context stack so JS called
   // from native code via XPConnect uses the right context.  Do this whether
   // or not the SecurityManager said "ok", in order to simplify control flow
   // below where we pop before returning.
   nsCOMPtr<nsIJSContextStack> stack =
            do_GetService("@mozilla.org/js/xpc/ContextStack;1", &rv);
   if (NS_FAILED(rv) || NS_FAILED(stack->Push(mContext))) {
     JSPRINCIPALS_DROP(mContext, jsprin);
+    if (originJSprin) {
+      JSPRINCIPALS_DROP(mContext, originJSprin);
+    }
     return NS_ERROR_FAILURE;
   }
 
   // The result of evaluation, used only if there were no errors.  This need
   // not be a GC root currently, provided we run the GC only from the
   // operation callback or from ScriptEvaluated.
   jsval val = JSVAL_VOID;
   jsval* vp = aRetValue ? &val : NULL;
@@ -1474,35 +1475,41 @@ nsJSContext::EvaluateString(const nsAStr
   // Since the caller is responsible for parsing the version strings, we just
   // check it isn't JSVERSION_UNKNOWN.
   if (ok && JSVersion(aVersion) != JSVERSION_UNKNOWN) {
     JSAutoRequest ar(mContext);
     JSAutoEnterCompartment ac;
     if (!ac.enter(mContext, aScopeObject)) {
       stack->Pop(nsnull);
       JSPRINCIPALS_DROP(mContext, jsprin);
+      if (originJSprin) {
+        JSPRINCIPALS_DROP(mContext, originJSprin);
+      }
       return NS_ERROR_FAILURE;
     }
 
-    ok = JS_EvaluateUCScriptForPrincipalsVersion(
-      mContext, aScopeObject, jsprin,
+    ok = JS_EvaluateUCScriptForPrincipalsVersionOrigin(
+      mContext, aScopeObject, jsprin, originJSprin,
       static_cast<const jschar*>(PromiseFlatString(aScript).get()),
       aScript.Length(), aURL, aLineNo, vp, JSVersion(aVersion));
 
     if (!ok) {
       // Tell XPConnect about any pending exceptions. This is needed
       // to avoid dropping JS exceptions in case we got here through
       // nested calls through XPConnect.
 
       ReportPendingException();
     }
   }
 
   // Whew!  Finally done with these manually ref-counted things.
   JSPRINCIPALS_DROP(mContext, jsprin);
+  if (originJSprin) {
+    JSPRINCIPALS_DROP(mContext, originJSprin);
+  }
 
   // If all went well, convert val to a string if one is wanted.
   if (ok) {
     JSAutoRequest ar(mContext);
     JSAutoEnterCompartment ac;
     if (!ac.enter(mContext, aScopeObject)) {
       stack->Pop(nsnull);
     }
--- a/dom/base/nsJSEnvironment.h
+++ b/dom/base/nsJSEnvironment.h
@@ -70,16 +70,17 @@ public:
   virtual nsIScriptObjectPrincipal* GetObjectPrincipal();
 
   virtual PRUint32 GetScriptTypeID()
     { return nsIProgrammingLanguage::JAVASCRIPT; }
 
   virtual nsresult EvaluateString(const nsAString& aScript,
                                   JSObject* aScopeObject,
                                   nsIPrincipal *principal,
+                                  nsIPrincipal *originPrincipal,
                                   const char *aURL,
                                   PRUint32 aLineNo,
                                   PRUint32 aVersion,
                                   nsAString *aRetValue,
                                   bool* aIsUndefined);
   virtual nsresult EvaluateStringWithValue(const nsAString& aScript,
                                            JSObject* aScopeObject,
                                            nsIPrincipal* aPrincipal,
--- a/dom/indexedDB/IndexedDatabaseManager.cpp
+++ b/dom/indexedDB/IndexedDatabaseManager.cpp
@@ -729,22 +729,19 @@ IndexedDatabaseManager::EnsureOriginIsIn
 
     nsCOMPtr<nsIFile> fileManagerDirectory;
     rv = directory->Clone(getter_AddRefs(fileManagerDirectory));
     NS_ENSURE_SUCCESS(rv, rv);
 
     rv = fileManagerDirectory->Append(dbBaseFilename);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    nsString voidString;
-    voidString.SetIsVoid(true);
-
     nsCOMPtr<mozIStorageConnection> connection;
     rv = OpenDatabaseHelper::CreateDatabaseConnection(
-      voidString, file, fileManagerDirectory, getter_AddRefs(connection));
+      NullString(), file, fileManagerDirectory, getter_AddRefs(connection));
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsCOMPtr<mozIStorageStatement> stmt;
     rv = connection->CreateStatement(NS_LITERAL_CSTRING(
       "SELECT name "
       "FROM database"
     ), getter_AddRefs(stmt));
     NS_ENSURE_SUCCESS(rv, rv);
--- a/dom/locales/en-US/chrome/dom/dom.properties
+++ b/dom/locales/en-US/chrome/dom/dom.properties
@@ -131,8 +131,20 @@ FullScreenDeniedNotFocusedTab=Request fo
 RemovedFullScreenElement=Exited full-screen because full-screen element was removed from document.
 FocusedWindowedPluginWhileFullScreen=Exited full-screen because windowed plugin was focused.
 HTMLMultipartXHRWarning=HTML parsing in XMLHttpRequest is not supported for multipart responses.
 HTMLSyncXHRWarning=HTML parsing in XMLHttpRequest is not supported in the synchronous mode.
 InvalidRedirectChannelWarning=Unable to redirect to %S because the channel doesn't implement nsIWritablePropertyBag2.
 ResponseTypeSyncXHRWarning=Use of XMLHttpRequest's responseType attribute is no longer supported in the synchronous mode in window context.
 WithCredentialsSyncXHRWarning=Use of XMLHttpRequest's withCredentials attribute is no longer supported in the synchronous mode in window context.
 JSONCharsetWarning=An attempt was made to declare a non-UTF-8 encoding for JSON retrieved using XMLHttpRequest. Only UTF-8 is supported for decoding JSON.
+MediaLoadExhaustedCandidates=All candidate resources failed to load. Media load paused.
+MediaLoadSourceMissingSrc=<source> element has no "src" attribute. Media resource load failed.
+# LOCALIZATION NOTE: %1$S is the Http error code the server returned (e.g. 404, 500, etc), %2$S is the URL of the media resource which failed to load.
+MediaLoadHttpError=HTTP load failed with status %1$S. Load of media resource %2$S failed.
+# LOCALIZATION NOTE: %S is the URL of the media resource which failed to load.
+MediaLoadInvalidURI=Invalid URI. Load of media resource %S failed.
+# LOCALIZATION NOTE: %1$S is the media resource's format/codec type (basically equivalent to the file type, e.g. MP4,AVI,WMV,MOV etc), %2$S is the URL of the media resource which failed to load.
+MediaLoadUnsupportedType=Specified "type" of "%1$S" is not supported. Load of media resource %2$S failed.
+# LOCALIZATION NOTE: %1$S is the MIME type HTTP header being sent by the web server, %2$S is the URL of the media resource which failed to load.
+MediaLoadUnsupportedMimeType=HTTP "Content-Type" of "%1$S" is not supported. Load of media resource %2$S failed.
+# LOCALIZATION NOTE: %S is the URL of the media resource which failed to load because of error in decoding.
+MediaLoadDecodeError=Media resource %S could not be decoded.
--- a/dom/src/jsurl/nsJSProtocolHandler.cpp
+++ b/dom/src/jsurl/nsJSProtocolHandler.cpp
@@ -355,16 +355,17 @@ nsresult nsJSThunk::EvaluateScript(nsICh
 
         stack->Pop(nsnull);
     } else {
         // No need to use the sandbox, evaluate the script directly in
         // the given scope.
         rv = scriptContext->EvaluateString(NS_ConvertUTF8toUTF16(script),
                                            globalJSObject, // obj
                                            principal,
+                                           principal,
                                            mURL.get(),     // url
                                            1,              // line no
                                            nsnull,
                                            &result,
                                            &isUndefined);
 
         // If there's an error on cx as a result of that call, report
         // it now -- either we're just running under the event loop,
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -1104,46 +1104,41 @@ public:
       nsRefPtr<ReportErrorRunnable> runnable =
         new ReportErrorRunnable(aWorkerPrivate, aMessage, aFilename, aLine,
                                 aLineNumber, aColumnNumber, aFlags,
                                 aErrorNumber);
       return runnable->Dispatch(aCx);
     }
 
     // Otherwise log an error to the error console.
-    nsCOMPtr<nsIScriptError2> scriptError =
+    nsCOMPtr<nsIScriptError> scriptError =
       do_CreateInstance(NS_SCRIPTERROR_CONTRACTID);
-    NS_WARN_IF_FALSE(scriptError, "Faild to create script error!");
-
-    nsCOMPtr<nsIConsoleMessage> consoleMessage;
+    NS_WARN_IF_FALSE(scriptError, "Failed to create script error!");
 
     if (scriptError) {
-      if (NS_SUCCEEDED(scriptError->InitWithWindowID(aMessage.get(),
-                                                     aFilename.get(),
-                                                     aLine.get(), aLineNumber,
-                                                     aColumnNumber, aFlags,
-                                                     "Web Worker",
-                                                     aInnerWindowId))) {
-        consoleMessage = do_QueryInterface(scriptError);
-        NS_ASSERTION(consoleMessage, "This should never fail!");
-      }
-      else {
+      if (NS_FAILED(scriptError->InitWithWindowID(aMessage.get(),
+                                                  aFilename.get(),
+                                                  aLine.get(), aLineNumber,
+                                                  aColumnNumber, aFlags,
+                                                  "Web Worker",
+                                                  aInnerWindowId))) {
         NS_WARNING("Failed to init script error!");
+        scriptError = nsnull;
       }
     }
 
     nsCOMPtr<nsIConsoleService> consoleService =
       do_GetService(NS_CONSOLESERVICE_CONTRACTID);
-    NS_WARN_IF_FALSE(consoleService, "Faild to get console service!");
+    NS_WARN_IF_FALSE(consoleService, "Failed to get console service!");
 
     bool logged = false;
 
     if (consoleService) {
-      if (consoleMessage) {
-        if (NS_SUCCEEDED(consoleService->LogMessage(consoleMessage))) {
+      if (scriptError) {
+        if (NS_SUCCEEDED(consoleService->LogMessage(scriptError))) {
           logged = true;
         }
         else {
           NS_WARNING("Failed to log script error!");
         }
       }
       else if (NS_SUCCEEDED(consoleService->LogStringMessage(aMessage.get()))) {
         logged = true;
--- a/editor/libeditor/base/nsEditorEventListener.cpp
+++ b/editor/libeditor/base/nsEditorEventListener.cpp
@@ -152,17 +152,16 @@ nsEditorEventListener::InstallToEditor()
   elmP->AddEventListenerByType(this,
                                NS_LITERAL_STRING("keyup"),
                                NS_EVENT_FLAG_BUBBLE |
                                NS_EVENT_FLAG_SYSTEM_EVENT);
 #endif
   elmP->AddEventListenerByType(this,
                                NS_LITERAL_STRING("keypress"),
                                NS_EVENT_FLAG_BUBBLE |
-                               NS_PRIV_EVENT_UNTRUSTED_PERMITTED |
                                NS_EVENT_FLAG_SYSTEM_EVENT);
   // See bug 455215, we cannot use the standard dragstart event yet
   elmP->AddEventListenerByType(this,
                                NS_LITERAL_STRING("draggesture"),
                                NS_EVENT_FLAG_BUBBLE |
                                NS_EVENT_FLAG_SYSTEM_EVENT);
   elmP->AddEventListenerByType(this,
                                NS_LITERAL_STRING("dragenter"),
--- a/editor/libeditor/html/tests/Makefile.in
+++ b/editor/libeditor/html/tests/Makefile.in
@@ -90,16 +90,17 @@ include $(topsrcdir)/config/rules.mk
 		test_bug674770-2.html \
 		test_bug674861.html \
 		test_bug676401.html \
 		test_bug677752.html \
 		test_bug697842.html \
 		test_CF_HTML_clipboard.html \
 		test_contenteditable_focus.html \
 		test_htmleditor_keyevent_handling.html \
+		test_keypress_untrusted_event.html \
 		test_select_all_without_body.html \
 		file_select_all_without_body.html \
 		test_root_element_replacement.html \
 		$(NULL)
 
 ifneq (mobile,$(MOZ_BUILD_APP))
 _TEST_FILES +=  test_spellcheck_pref.html \
 		$(NULL)
new file mode 100644
--- /dev/null
+++ b/editor/libeditor/html/tests/test_keypress_untrusted_event.html
@@ -0,0 +1,99 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=622245
+-->
+<head>
+  <title>Test for untrusted keypress events</title>
+  <script type="application/javascript" src="/MochiKit/packed.js"></script>
+  <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=622245">Mozilla Bug 622245</a>
+<p id="display"></p>
+<div id="content">
+<input id="i"><br>
+<textarea id="t"></textarea><br>
+<div id="d" contenteditable style="min-height: 1em;"></div>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 674770 **/
+SimpleTest.waitForExplicitFinish();
+
+var input = document.getElementById("i");
+var textarea = document.getElementById("t");
+var div = document.getElementById("d");
+
+addLoadEvent(function() {
+  input.focus();
+
+  SimpleTest.executeSoon(function() {
+    input.addEventListener("keypress",
+      function(aEvent) {
+        input.removeEventListener("keypress", arguments.callee, false);
+        is(aEvent.target, input,
+           "The keypress event target isn't the input element");
+
+        SimpleTest.executeSoon(function() {
+          is(input.value, "",
+             "Did keypress event cause modifying the input element?");
+          textarea.focus();
+          SimpleTest.executeSoon(runTextareaTest);
+        });
+      }, false);
+    var keypress = document.createEvent("KeyboardEvent");
+    keypress.initKeyEvent("keypress", true, true, document.defaultView,
+                          false, false, false, false, 0, "a".charCodeAt(0));
+    input.dispatchEvent(keypress);
+  });
+});
+
+function runTextareaTest()
+{
+  textarea.addEventListener("keypress",
+    function(aEvent) {
+      textarea.removeEventListener("keypress", arguments.callee, false);
+      is(aEvent.target, textarea,
+         "The keypress event target isn't the textarea element");
+
+      SimpleTest.executeSoon(function() {
+        is(textarea.value, "",
+           "Did keypress event cause modifying the textarea element?");
+        div.focus();
+        SimpleTest.executeSoon(runContentediableTest);
+      });
+    }, false);
+  var keypress = document.createEvent("KeyboardEvent");
+  keypress.initKeyEvent("keypress", true, true, document.defaultView,
+                        false, false, false, false, 0, "b".charCodeAt(0));
+  textarea.dispatchEvent(keypress);
+}
+
+function runContentediableTest()
+{
+  div.addEventListener("keypress",
+    function(aEvent) {
+      div.removeEventListener("keypress", arguments.callee, false);
+      is(aEvent.target, div,
+         "The keypress event target isn't the div element");
+
+      SimpleTest.executeSoon(function() {
+        is(div.innerHTML, "",
+           "Did keypress event cause modifying the div element?");
+
+        SimpleTest.finish();
+      });
+    }, false);
+  var keypress = document.createEvent("KeyboardEvent");
+  keypress.initKeyEvent("keypress", true, true, document.defaultView,
+                        false, false, false, false, 0, "c".charCodeAt(0));
+  div.dispatchEvent(keypress);
+}
+
+</script>
+</pre>
+</body>
+</html>
--- a/extensions/cookie/nsPermissionManager.cpp
+++ b/extensions/cookie/nsPermissionManager.cpp
@@ -615,29 +615,40 @@ nsPermissionManager::RemoveAll()
 {
   ENSURE_NOT_CHILD_PROCESS;
 
   nsresult rv = RemoveAllInternal();
   NotifyObservers(nsnull, NS_LITERAL_STRING("cleared").get());
   return rv;
 }
 
+void
+nsPermissionManager::CloseDB()
+{
+  // Null the statements, this will finalize them.
+  mStmtInsert = nsnull;
+  mStmtDelete = nsnull;
+  mStmtUpdate = nsnull;
+  if (mDBConn) {
+    mozilla::DebugOnly<nsresult> rv = mDBConn->Close();
+    MOZ_ASSERT(NS_SUCCEEDED(rv));
+    mDBConn = nsnull;
+  }
+}
+
 nsresult
 nsPermissionManager::RemoveAllInternal()
 {
   RemoveAllFromMemory();
 
   // clear the db
   if (mDBConn) {
     nsresult rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING("DELETE FROM moz_hosts"));
     if (NS_FAILED(rv)) {
-      mStmtInsert = nsnull;
-      mStmtDelete = nsnull;
-      mStmtUpdate = nsnull;
-      mDBConn = nsnull;
+      CloseDB();
       rv = InitDB(true);
       return rv;
     }
   }
 
   return NS_OK;
 }
 
@@ -787,22 +798,17 @@ NS_IMETHODIMP nsPermissionManager::Obser
     // The profile is about to change,
     // or is going away because the application is shutting down.
     if (!nsCRT::strcmp(someData, NS_LITERAL_STRING("shutdown-cleanse").get())) {
       // clear the permissions file
       RemoveAllInternal();
     } else {
       RemoveAllFromMemory();
     }
-    if (mDBConn) {
-      // Null the statements, this will finalize them.
-      mStmtInsert = nsnull;
-      mStmtDelete = nsnull;
-      mStmtUpdate = nsnull;
-    }
+    CloseDB();
   }
   else if (!nsCRT::strcmp(aTopic, "profile-do-change")) {
     // the profile has already changed; init the db from the new location
     InitDB(false);
   }
 
   return NS_OK;
 }
--- a/extensions/cookie/nsPermissionManager.h
+++ b/extensions/cookie/nsPermissionManager.h
@@ -217,16 +217,20 @@ private:
   nsresult Read();
   void     NotifyObserversWithPermission(const nsACString &aHost,
                                          const nsCString  &aType,
                                          PRUint32          aPermission,
                                          PRUint32          aExpireType,
                                          PRInt64           aExpireTime,
                                          const PRUnichar  *aData);
   void     NotifyObservers(nsIPermission *aPermission, const PRUnichar *aData);
+
+  // Finalize all statements, close the DB and null it.
+  void     CloseDB();
+
   nsresult RemoveAllInternal();
   nsresult RemoveAllFromMemory();
   nsresult NormalizeToACE(nsCString &aHost);
   nsresult GetHost(nsIURI *aURI, nsACString &aResult);
   static void UpdateDB(OperationType         aOp,
                        mozIStorageStatement* aStmt,
                        PRInt64               aID,
                        const nsACString     &aHost,
--- a/gfx/thebes/gfxQuartzNativeDrawing.h
+++ b/gfx/thebes/gfxQuartzNativeDrawing.h
@@ -33,16 +33,18 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef _GFXQUARTZNATIVEDRAWING_H_
 #define _GFXQUARTZNATIVEDRAWING_H_
 
+#include "mozilla/Attributes.h"
+
 #include "gfxContext.h"
 #include "gfxQuartzSurface.h"
 
 class THEBES_API gfxQuartzNativeDrawing {
 public:
 
     /* Create native Quartz drawing for a rectangle bounded by
      * nativeRect.
@@ -66,18 +68,18 @@ public:
      * for drawing after that time, the result is undefined. */
     CGContextRef BeginNativeDrawing();
 
     /* Marks the end of native drawing */
     void EndNativeDrawing();
 
 private:
     // don't allow copying via construction or assignment
-    gfxQuartzNativeDrawing(const gfxQuartzNativeDrawing&);
-    const gfxQuartzNativeDrawing& operator=(const gfxQuartzNativeDrawing&);
+    gfxQuartzNativeDrawing(const gfxQuartzNativeDrawing&) MOZ_DELETE;
+    const gfxQuartzNativeDrawing& operator=(const gfxQuartzNativeDrawing&) MOZ_DELETE;
 
     // Final destination context
     nsRefPtr<gfxContext> mContext;
     // context that draws to mQuartzSurface; can be different from mContext
     // if mContext is not drawing to Quartz
     nsRefPtr<gfxContext> mSurfaceContext;
     gfxRect mNativeRect;
 
--- a/hal/Hal.h
+++ b/hal/Hal.h
@@ -66,17 +66,17 @@ class nsIDOMWindow;
 
 namespace mozilla {
 
 namespace hal {
 
 class WindowIdentifier;
 
 extern PRLogModuleInfo *sHalLog;
-#define HAL_LOG(msg) PR_LOG(sHalLog, PR_LOG_DEBUG, msg)
+#define HAL_LOG(msg) PR_LOG(mozilla::hal::sHalLog, PR_LOG_DEBUG, msg)
 
 } // namespace hal
 
 namespace MOZ_HAL_NAMESPACE {
 
 /**
  * Turn the default vibrator device on/off per the pattern specified
  * by |pattern|.  Each element in the pattern is the number of
--- a/hal/Makefile.in
+++ b/hal/Makefile.in
@@ -36,16 +36,17 @@
 # ***** END LICENSE BLOCK *****
 
 DEPTH       = ..
 topsrcdir   = @top_srcdir@
 srcdir      = @srcdir@
 VPATH       = \
   $(srcdir) \
   $(srcdir)/android \
+  $(srcdir)/gonk \
   $(srcdir)/fallback \
   $(srcdir)/sandbox \
   $(srcdir)/linux \
   $(srcdir)/windows \
   $(NULL)
 
 include $(DEPTH)/config/autoconf.mk
 
@@ -65,16 +66,18 @@ EXPORTS_mozilla = \
 CPPSRCS = \
   Hal.cpp \
   SandboxHal.cpp \
   WindowIdentifier.cpp \
   $(NULL)
 
 ifeq (android,$(MOZ_WIDGET_TOOLKIT))
 CPPSRCS += AndroidHal.cpp
+else ifeq (gonk,$(MOZ_WIDGET_TOOLKIT))
+CPPSRCS += GonkHal.cpp
 else ifeq (Linux,$(OS_TARGET))
 CPPSRCS += LinuxHal.cpp
 ifdef MOZ_ENABLE_DBUS
 CPPSRCS += UPowerClient.cpp
 endif
 else ifeq (WINNT,$(OS_TARGET))
 CPPSRCS += WindowsHal.cpp WindowsBattery.cpp
 else
new file mode 100644
--- /dev/null
+++ b/hal/gonk/GonkHal.cpp
@@ -0,0 +1,417 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et ft=cpp : */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at:
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Code.
+ *
+ * The Initial Developer of the Original Code is
+ *   The Mozilla Foundation
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Chris Jones <jones.chris.g@gmail.com>
+ *   Michael Wu <mwu@mozilla.com>
+ *   Justin Lebar <justin.lebar@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "hardware_legacy/uevent.h"
+#include "Hal.h"
+#include "mozilla/dom/battery/Constants.h"
+#include "mozilla/FileUtils.h"
+#include "nsAlgorithm.h"
+#include "nsThreadUtils.h"
+#include "mozilla/Monitor.h"
+#include "mozilla/Services.h"
+#include "mozilla/FileUtils.h"
+#include "nsThreadUtils.h"
+#include "nsIRunnable.h"
+#include "nsIThread.h"
+#include "nsIObserver.h"
+#include "nsIObserverService.h"
+#include "hardware_legacy/vibrator.h"
+#include <stdio.h>
+#include <math.h>
+#include <fcntl.h>
+#include <errno.h>
+
+using mozilla::hal::WindowIdentifier;
+
+namespace mozilla {
+namespace hal_impl {
+
+namespace {
+
+/**
+ * This runnable runs for the lifetime of the program, once started.  It's
+ * responsible for "playing" vibration patterns.
+ */
+class VibratorRunnable
+  : public nsIRunnable
+  , public nsIObserver
+{
+public:
+  VibratorRunnable()
+    : mMonitor("VibratorRunnable")
+    , mIndex(0)
+    , mShuttingDown(false)
+  {
+    nsCOMPtr<nsIObserverService> os = services::GetObserverService();
+    if (!os) {
+      NS_WARNING("Could not get observer service!");
+      return;
+    }
+
+    os->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, /* weak ref */ true);
+  } 
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIRUNNABLE
+  NS_DECL_NSIOBSERVER
+
+  // Run on the main thread, not the vibrator thread.
+  void Vibrate(const nsTArray<uint32> &pattern);
+  void CancelVibrate();
+
+private:
+  Monitor mMonitor;
+
+  // The currently-playing pattern.
+  nsTArray<uint32> mPattern;
+
+  // The index we're at in the currently-playing pattern.  If mIndex >=
+  // mPattern.Length(), then we're not currently playing anything.
+  uint32 mIndex;
+
+  // Set to true in our shutdown observer.  When this is true, we kill the
+  // vibrator thread.
+  bool mShuttingDown;
+};
+
+NS_IMPL_ISUPPORTS2(VibratorRunnable, nsIRunnable, nsIObserver);
+
+NS_IMETHODIMP
+VibratorRunnable::Run()
+{
+  MonitorAutoLock lock(mMonitor);
+
+  // We currently assume that mMonitor.Wait(X) waits for X milliseconds.  But in
+  // reality, the kernel might not switch to this thread for some time after the
+  // wait expires.  So there's potential for some inaccuracy here.
+  //
+  // This doesn't worry me too much.  Note that we don't even start vibrating
+  // immediately when VibratorRunnable::Vibrate is called -- we go through a
+  // condvar onto another thread.  Better just to be chill about small errors in
+  // the timing here.
+
+  while (!mShuttingDown) {
+    if (mIndex < mPattern.Length()) {
+      uint32 duration = mPattern[mIndex];
+      if (mIndex % 2 == 0) {
+        vibrator_on(duration);
+      }
+      mIndex++;
+      mMonitor.Wait(PR_MillisecondsToInterval(duration));
+    }
+    else {
+      mMonitor.Wait();
+    }
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+VibratorRunnable::Observe(nsISupports *subject, const char *topic,
+                          const PRUnichar *data)
+{
+  MOZ_ASSERT(strcmp(topic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0);
+  MonitorAutoLock lock(mMonitor);
+  mShuttingDown = true;
+  mMonitor.Notify();
+  return NS_OK;
+}
+
+void
+VibratorRunnable::Vibrate(const nsTArray<uint32> &pattern)
+{
+  MonitorAutoLock lock(mMonitor);
+  mPattern = pattern;
+  mIndex = 0;
+  mMonitor.Notify();
+}
+
+void
+VibratorRunnable::CancelVibrate()
+{
+  MonitorAutoLock lock(mMonitor);
+  mPattern.Clear();
+  mPattern.AppendElement(0);
+  mIndex = 0;
+  mMonitor.Notify();
+}
+
+VibratorRunnable *sVibratorRunnable = NULL;
+
+void
+EnsureVibratorThreadInitialized()
+{
+  if (sVibratorRunnable) {
+    return;
+  }
+
+  nsRefPtr<VibratorRunnable> runnable = new VibratorRunnable();
+  sVibratorRunnable = runnable;
+  nsCOMPtr<nsIThread> thread;
+  NS_NewThread(getter_AddRefs(thread), sVibratorRunnable);
+}
+
+} // anonymous namespace
+
+void
+Vibrate(const nsTArray<uint32> &pattern, const hal::WindowIdentifier &)
+{
+  EnsureVibratorThreadInitialized();
+  sVibratorRunnable->Vibrate(pattern);
+}
+
+void
+CancelVibrate(const hal::WindowIdentifier &)
+{
+  EnsureVibratorThreadInitialized();
+  sVibratorRunnable->CancelVibrate();
+}
+
+namespace {
+
+class BatteryUpdater : public nsRunnable {
+public:
+  NS_IMETHOD Run()
+  {
+    hal::BatteryInformation info;
+    hal_impl::GetCurrentBatteryInformation(&info);
+    hal::NotifyBatteryChange(info);
+    return NS_OK;
+  }
+};
+
+class UEventWatcher : public nsRunnable {
+public:
+  UEventWatcher()
+    : mUpdater(new BatteryUpdater())
+    , mRunning(false)
+  {
+  }
+
+  NS_IMETHOD Run()
+  {
+    while (mRunning) {
+      char buf[1024];
+      int count = uevent_next_event(buf, sizeof(buf) - 1);
+      if (!count) {
+        NS_WARNING("uevent_next_event() returned 0!");
+        continue;
+      }
+
+      buf[sizeof(buf) - 1] = 0;
+      if (strstr(buf, "battery"))
+        NS_DispatchToMainThread(mUpdater);
+    }
+    return NS_OK;
+  }
+
+  bool mRunning;
+
+private:
+  nsRefPtr<BatteryUpdater> mUpdater;
+};
+
+} // anonymous namespace
+
+static bool sUEventInitialized = false;
+static UEventWatcher *sWatcher = NULL;
+static nsIThread *sWatcherThread = NULL;
+
+void
+EnableBatteryNotifications()
+{
+  if (!sUEventInitialized)
+    sUEventInitialized = uevent_init();
+  if (!sUEventInitialized) {
+    NS_WARNING("uevent_init() failed!");
+    return;
+  }
+
+  if (!sWatcher)
+    sWatcher = new UEventWatcher();
+  NS_ADDREF(sWatcher);
+
+  sWatcher->mRunning = true;
+  nsresult rv = NS_NewThread(&sWatcherThread, sWatcher);
+  if (NS_FAILED(rv))
+    NS_WARNING("Failed to get new thread for uevent watching");
+}
+
+void
+DisableBatteryNotifications()
+{
+  sWatcher->mRunning = false;
+  sWatcherThread->Shutdown();
+  NS_IF_RELEASE(sWatcherThread);
+  delete sWatcher;
+}
+
+void
+GetCurrentBatteryInformation(hal::BatteryInformation *aBatteryInfo)
+{
+  FILE *capacityFile = fopen("/sys/class/power_supply/battery/capacity", "r");
+  double capacity = dom::battery::kDefaultLevel * 100;
+  if (capacityFile) {
+    fscanf(capacityFile, "%lf", &capacity);
+    fclose(capacityFile);
+  }
+
+  FILE *chargingFile = fopen("/sys/class/power_supply/battery/charging_source", "r");
+  int chargingSrc = 1;
+  if (chargingFile) {
+    fscanf(chargingFile, "%d", &chargingSrc);
+    fclose(chargingFile);
+  }
+
+  aBatteryInfo->level() = capacity / 100;
+  aBatteryInfo->charging() = chargingSrc == 1;
+  aBatteryInfo->remainingTime() = dom::battery::kUnknownRemainingTime;
+}
+
+namespace {
+
+/**
+ * RAII class to help us remember to close file descriptors.
+ */
+const char *screenEnabledFilename = "/sys/power/state";
+const char *screenBrightnessFilename = "/sys/class/backlight/pwm-backlight/brightness";
+
+template<ssize_t n>
+bool ReadFromFile(const char *filename, char (&buf)[n])
+{
+  int fd = open(filename, O_RDONLY);
+  ScopedClose autoClose(fd);
+  if (fd < 0) {
+    HAL_LOG(("Unable to open file %s.", filename));
+    return false;
+  }
+
+  ssize_t numRead = read(fd, buf, n);
+  if (numRead < 0) {
+    HAL_LOG(("Error reading from file %s.", filename));
+    return false;
+  }
+
+  buf[PR_MIN(numRead, n - 1)] = '\0';
+  return true;
+}
+
+void WriteToFile(const char *filename, const char *toWrite)
+{
+  int fd = open(filename, O_WRONLY);
+  ScopedClose autoClose(fd);
+  if (fd < 0) {
+    HAL_LOG(("Unable to open file %s.", filename));
+    return;
+  }
+
+  if (write(fd, toWrite, strlen(toWrite)) < 0) {
+    HAL_LOG(("Unable to write to file %s.", filename));
+    return;
+  }
+}
+
+// We can write to screenEnabledFilename to enable/disable the screen, but when
+// we read, we always get "mem"!  So we have to keep track ourselves whether
+// the screen is on or not.
+bool sScreenEnabled = true;
+
+} // anonymous namespace
+
+bool
+GetScreenEnabled()
+{
+  return sScreenEnabled;
+}
+
+void
+SetScreenEnabled(bool enabled)
+{
+  WriteToFile(screenEnabledFilename, enabled ? "on" : "mem");
+  sScreenEnabled = enabled;
+}
+
+double
+GetScreenBrightness()
+{
+  char buf[32];
+  ReadFromFile(screenBrightnessFilename, buf);
+
+  errno = 0;
+  unsigned long val = strtoul(buf, NULL, 10);
+  if (errno) {
+    HAL_LOG(("Cannot parse contents of %s; expected an unsigned "
+             "int, but contains \"%s\".",
+             screenBrightnessFilename, buf));
+    return 1;
+  }
+
+  if (val > 255) {
+    HAL_LOG(("Got out-of-range brightness %d, truncating to 1.0", val));
+    val = 255;
+  }
+
+  return val / 255.0;
+}
+
+void
+SetScreenBrightness(double brightness)
+{
+  // Don't use De Morgan's law to push the ! into this expression; we want to
+  // catch NaN too.
+  if (!(0 <= brightness && brightness <= 1)) {
+    HAL_LOG(("SetScreenBrightness: Dropping illegal brightness %f.",
+             brightness));
+    return;
+  }
+
+  // Convert the value in [0, 1] to an int between 0 and 255, then write to a
+  // string.
+  int val = static_cast<int>(round(brightness * 255));
+  char str[4];
+  DebugOnly<int> numChars = snprintf(str, sizeof(str), "%d", val);
+  MOZ_ASSERT(numChars < static_cast<int>(sizeof(str)));
+
+  WriteToFile(screenBrightnessFilename, str);
+}
+
+} // hal_impl
+} // mozilla
--- a/image/src/Decoder.cpp
+++ b/image/src/Decoder.cpp
@@ -125,33 +125,31 @@ Decoder::Finish()
 
   // If PostDecodeDone() has not been called, we need to sent teardown
   // notifications.
   if (!IsSizeDecode() && !mDecodeDone) {
 
     // Log data errors to the error console
     nsCOMPtr<nsIConsoleService> consoleService =
       do_GetService(NS_CONSOLESERVICE_CONTRACTID);
-    nsCOMPtr<nsIScriptError2> errorObject =
+    nsCOMPtr<nsIScriptError> errorObject =
       do_CreateInstance(NS_SCRIPTERROR_CONTRACTID);
 
     if (consoleService && errorObject && !HasDecoderError()) {
       nsAutoString msg(NS_LITERAL_STRING("Image corrupt or truncated: ") +
                        NS_ConvertASCIItoUTF16(mImage.GetURIString()));
 
-      errorObject->InitWithWindowID
-        (msg.get(),
-         NS_ConvertUTF8toUTF16(mImage.GetURIString()).get(),
-         nsnull,
-         0, 0, nsIScriptError::errorFlag,
-         "Image", mImage.InnerWindowID()
-         );
-  
-      nsCOMPtr<nsIScriptError> error = do_QueryInterface(errorObject);
-      consoleService->LogMessage(error);
+      if (NS_SUCCEEDED(errorObject->InitWithWindowID(
+                         msg.get(),
+                         NS_ConvertUTF8toUTF16(mImage.GetURIString()).get(),
+                         nsnull, 0, 0, nsIScriptError::errorFlag,
+                         "Image", mImage.InnerWindowID()
+                       ))) {
+        consoleService->LogMessage(errorObject);
+      }
     }
 
     // If we only have a data error, see if things are worth salvaging
     bool salvage = !HasDecoderError() && mImage.GetNumFrames();
 
     // If we're salvaging, say we finished decoding
     if (salvage)
       mImage.DecodingComplete();
--- a/intl/uconv/util/ubase.h
+++ b/intl/uconv/util/ubase.h
@@ -32,26 +32,14 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 #ifndef ubase_h__
 #define ubase_h__
 
-#ifdef _WIN32
-#ifndef NS_WIN32 
-#define NS_WIN32 1
-#endif
-#endif
-
-#if defined(__unix)
-#ifndef NS_UNIX 
-#define NS_UNIX 1
-#endif
-#endif
-
 #include "prtypes.h"
 
 #define PRIVATE 
 #define MODULE_PRIVATE
 
 #endif
--- a/js/public/Utility.h
+++ b/js/public/Utility.h
@@ -35,16 +35,18 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef js_utility_h__
 #define js_utility_h__
 
+#include "mozilla/Assertions.h"
+
 #include <stdlib.h>
 #include <string.h>
 
 #include "jstypes.h"
 
 #ifdef __cplusplus
 
 /* The public JS engine namespace. */
@@ -66,67 +68,34 @@ using namespace mozilla;
 JS_BEGIN_EXTERN_C
 
 /*
  * Pattern used to overwrite freed memory. If you are accessing an object with
  * this pattern, you probably have a dangling pointer.
  */
 #define JS_FREE_PATTERN 0xDA
 
-/* JS_ASSERT */
+#define JS_ASSERT(expr)           MOZ_ASSERT(expr)
+#define JS_ASSERT_IF(cond, expr)  MOZ_ASSERT_IF((cond), (expr))
+#define JS_NOT_REACHED(reason)    MOZ_NOT_REACHED(reason)
+#define JS_ALWAYS_TRUE(expr)      MOZ_ALWAYS_TRUE(expr)
+#define JS_ALWAYS_FALSE(expr)     MOZ_ALWAYS_FALSE(expr)
+
 #ifdef DEBUG
-# define JS_ASSERT(expr)                                                      \
-    ((expr) ? (void)0 : JS_Assert(#expr, __FILE__, __LINE__))
-# define JS_ASSERT_IF(cond, expr)                                             \
-    ((!(cond) || (expr)) ? (void)0 : JS_Assert(#expr, __FILE__, __LINE__))
-# define JS_NOT_REACHED(reason)                                               \
-    JS_Assert(reason, __FILE__, __LINE__)
-# define JS_ALWAYS_TRUE(expr) JS_ASSERT(expr)
-# define JS_ALWAYS_FALSE(expr) JS_ASSERT(!(expr))
 # ifdef JS_THREADSAFE
 #  define JS_THREADSAFE_ASSERT(expr) JS_ASSERT(expr)
 # else
 #  define JS_THREADSAFE_ASSERT(expr) ((void) 0)
 # endif
 #else
-# define JS_ASSERT(expr)         ((void) 0)
-# define JS_ASSERT_IF(cond,expr) ((void) 0)
-# define JS_NOT_REACHED(reason)
-# define JS_ALWAYS_TRUE(expr)    ((void) (expr))
-# define JS_ALWAYS_FALSE(expr)    ((void) (expr))
 # define JS_THREADSAFE_ASSERT(expr) ((void) 0)
 #endif
 
-/*
- * JS_STATIC_ASSERT
- *
- * A compile-time assert. "cond" must be a constant expression. The macro can
- * be used only in places where an "extern" declaration is allowed.
- */
-#ifdef __SUNPRO_CC
-/*
- * Sun Studio C++ compiler has a bug
- * "sizeof expression not accepted as size of array parameter"
- * It happens when js_static_assert() function is declared inside functions.
- * The bug number is 6688515. It is not public yet.
- * Therefore, for Sun Studio, declare js_static_assert as an array instead.
- */
-# define JS_STATIC_ASSERT(cond) extern char js_static_assert[(cond) ? 1 : -1]
-#else
-# ifdef __COUNTER__
-#  define JS_STATIC_ASSERT_GLUE1(x,y) x##y
-#  define JS_STATIC_ASSERT_GLUE(x,y) JS_STATIC_ASSERT_GLUE1(x,y)
-#  define JS_STATIC_ASSERT(cond)                                            \
-        typedef int JS_STATIC_ASSERT_GLUE(js_static_assert, __COUNTER__)[(cond) ? 1 : -1]
-# else
-#  define JS_STATIC_ASSERT(cond) extern void js_static_assert(int arg[(cond) ? 1 : -1])
-# endif
-#endif
-
-#define JS_STATIC_ASSERT_IF(cond, expr) JS_STATIC_ASSERT(!(cond) || (expr))
+#define JS_STATIC_ASSERT(cond)           MOZ_STATIC_ASSERT(cond, "JS_STATIC_ASSERT")
+#define JS_STATIC_ASSERT_IF(cond, expr)  MOZ_STATIC_ASSERT_IF(cond, expr, "JS_STATIC_ASSERT_IF")
 
 /*
  * Abort the process in a non-graceful manner. This will cause a core file,
  * call to the debugger or other moral equivalent as well as causing the
  * entire process to stop.
  */
 extern JS_PUBLIC_API(void) JS_Abort(void);
 
--- a/js/public/Vector.h
+++ b/js/public/Vector.h
@@ -36,16 +36,18 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef jsvector_h_
 #define jsvector_h_
 
+#include "mozilla/Attributes.h"
+
 #include "TemplateLib.h"
 #include "Utility.h"
 
 /* Silence dire "bugs in previous versions of MSVC have been fixed" warnings */
 #ifdef _MSC_VER
 #pragma warning(push)
 #pragma warning(disable:4345)
 #endif
@@ -269,18 +271,18 @@ class Vector : private AllocPolicy
 
     AlignedStorage<sInlineBytes> storage;
 
 #ifdef DEBUG
     friend class ReentrancyGuard;
     bool entered;
 #endif
 
-    Vector(const Vector &);
-    Vector &operator=(const Vector &);
+    Vector(const Vector &) MOZ_DELETE;
+    Vector &operator=(const Vector &) MOZ_DELETE;
 
     /* private accessors */
 
     bool usingInlineStorage() const {
         return mBegin == (T *)storage.addr();
     }
 
     T *beginNoCheck() const {
--- a/js/src/config/system-headers
+++ b/js/src/config/system-headers
@@ -526,16 +526,17 @@ netinet/in_systm.h
 netinet/tcp.h
 new
 newexe.h
 new.h
 nl_types.h
 NodeInfo.h
 nss.h
 nssilock.h
+nsswitch.h
 objbase.h
 objidl.h
 Objsafe.h
 ojiapitests.h
 ole2.h
 oleidl.h
 OpenGL/OpenGL.h
 OpenTptInternet.h
@@ -745,16 +746,17 @@ sys/stack.h
 sys/statfs.h
 sys/stat.h
 sys/statvfs.h
 sys/syscall.h
 sys/sysctl.h
 sys/sysinfo.h
 sys/sysmp.h
 sys/syssgi.h
+sys/system_properties.h
 sys/systeminfo.h
 sys/timeb.h
 sys/time.h
 sys/times.h
 sys/ttycom.h
 sys/types.h
 sys/ucontext.h
 sys/uio.h
--- a/js/src/ds/LifoAlloc.cpp
+++ b/js/src/ds/LifoAlloc.cpp
@@ -92,17 +92,20 @@ BumpChunk::canAllocUnaligned(size_t n)
 void *
 BumpChunk::tryAllocUnaligned(size_t n)
 {
     char *oldBump = bump;
     char *newBump = bump + n;
     if (newBump > limit)
         return NULL;
 
-    JS_ASSERT(canAllocUnaligned(n));
+    if (JS_UNLIKELY(newBump < oldBump))
+        return NULL;
+
+    JS_ASSERT(canAllocUnaligned(n)); /* Ensure consistency between "can" and "try". */
     setBump(newBump);
     return oldBump;
 }
 
 } /* namespace detail */
 } /* namespace js */
 
 void
--- a/js/src/ds/LifoAlloc.h
+++ b/js/src/ds/LifoAlloc.h
@@ -36,16 +36,18 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef LifoAlloc_h__
 #define LifoAlloc_h__
 
+#include "mozilla/Attributes.h"
+
 /*
  * This data structure supports stacky LIFO allocation (mark/release and
  * LifoAllocScope). It does not maintain one contiguous segment; instead, it
  * maintains a bunch of linked memory segments. In order to prevent malloc/free
  * thrashing, unused segments are deallocated when garbage collection occurs.
  */
 
 #include "jsutil.h"
@@ -176,18 +178,18 @@ class LifoAlloc
 {
     typedef detail::BumpChunk BumpChunk;
 
     BumpChunk   *first;
     BumpChunk   *latest;
     size_t      markCount;
     size_t      defaultChunkSize_;
 
-    void operator=(const LifoAlloc &);
-    LifoAlloc(const LifoAlloc &);
+    void operator=(const LifoAlloc &) MOZ_DELETE;
+    LifoAlloc(const LifoAlloc &) MOZ_DELETE;
 
     /* 
      * Return a BumpChunk that can perform an allocation of at least size |n|
      * and add it to the chain appropriately.
      *
      * Side effect: if retval is non-null, |first| and |latest| are initialized
      * appropriately.
      */
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -1776,18 +1776,18 @@ LookupCompileTimeConstant(JSContext *cx,
                 if (shape) {
                     /*
                      * We're compiling code that will be executed immediately,
                      * not re-executed against a different scope chain and/or
                      * variable object.  Therefore we can get constant values
                      * from our variable object here.
                      */
                     if (!shape->writable() && !shape->configurable() &&
-                        shape->hasDefaultGetter() && obj->containsSlot(shape->slot())) {
-                        *constp = obj->getSlot(shape->slot());
+                        shape->hasDefaultGetter() && shape->hasSlot()) {
+                        *constp = obj->nativeGetSlot(shape->slot());
                     }
                 }
 
                 if (shape)
                     break;
             }
         }
     } while (bce->parent && (bce = bce->parent->asBytecodeEmitter()));
--- a/js/src/jscompartment.h
+++ b/js/src/jscompartment.h
@@ -35,16 +35,18 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef jscompartment_h___
 #define jscompartment_h___
 
+#include "mozilla/Attributes.h"
+
 #include "jsclist.h"
 #include "jscntxt.h"
 #include "jsfun.h"
 #include "jsgc.h"
 #include "jsgcstats.h"
 #include "jsobj.h"
 #include "jsscope.h"
 #include "vm/GlobalObject.h"
@@ -481,19 +483,18 @@ class AutoCompartment
   public:
     AutoCompartment(JSContext *cx, JSObject *target);
     ~AutoCompartment();
 
     bool enter();
     void leave();
 
   private:
-    // Prohibit copying.
-    AutoCompartment(const AutoCompartment &);
-    AutoCompartment & operator=(const AutoCompartment &);
+    AutoCompartment(const AutoCompartment &) MOZ_DELETE;
+    AutoCompartment & operator=(const AutoCompartment &) MOZ_DELETE;
 };
 
 /*
  * Use this to change the behavior of an AutoCompartment slightly on error. If
  * the exception happens to be an Error object, copy it to the origin compartment
  * instead of wrapping it.
  */
 class ErrorCopier
--- a/js/src/jsdbgapi.cpp
+++ b/js/src/jsdbgapi.cpp
@@ -861,25 +861,16 @@ JS_GetPropertyDesc(JSContext *cx, JSObje
     } else if (shape->getter() == GetCallVar) {
         pd->slot = shape->shortid();
         pd->flags |= JSPD_VARIABLE;
     } else {
         pd->slot = 0;
     }
     pd->alias = JSVAL_VOID;
 
-    if (obj->containsSlot(shape->slot())) {
-        for (Shape::Range r = obj->lastProperty()->all(); !r.empty(); r.popFront()) {
-            const Shape &aprop = r.front();
-            if (&aprop != shape && aprop.slot() == shape->slot()) {
-                pd->alias = IdToJsval(aprop.propid());
-                break;
-            }
-        }
-    }
     return JS_TRUE;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_GetPropertyDescArray(JSContext *cx, JSObject *obj, JSPropertyDescArray *pda)
 {
     assertSameCompartment(cx, obj);
     Class *clasp = obj->getClass();
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -301,16 +301,17 @@ extern JS_FRIEND_DATA(js::Class) DeclEnv
 extern JS_FRIEND_DATA(js::Class) FunctionClass;
 extern JS_FRIEND_DATA(js::Class) FunctionProxyClass;
 extern JS_FRIEND_DATA(js::Class) NamespaceClass;
 extern JS_FRIEND_DATA(js::Class) OuterWindowProxyClass;
 extern JS_FRIEND_DATA(js::Class) ObjectProxyClass;
 extern JS_FRIEND_DATA(js::Class) QNameClass;
 extern JS_FRIEND_DATA(js::Class) ScriptClass;
 extern JS_FRIEND_DATA(js::Class) XMLClass;
+extern JS_FRIEND_DATA(js::Class) ObjectClass;
 
 inline js::Class *
 GetObjectClass(const JSObject *obj)
 {
     return reinterpret_cast<const shadow::Object*>(obj)->shape->base->clasp;
 }
 
 inline JSClass *
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -2194,27 +2194,29 @@ js_CloneFunctionObject(JSContext *cx, JS
 
     JSObject *cloneobj = NewObjectWithClassProto(cx, &FunctionClass, NULL, SkipScopeParent(parent), kind);
     if (!cloneobj)
         return NULL;
     JSFunction *clone = static_cast<JSFunction *>(cloneobj);
 
     clone->nargs = fun->nargs;
     clone->flags = fun->flags & ~JSFUN_EXTENDED;
-    clone->u = fun->toFunction()->u;
+    if (fun->isInterpreted()) {
+        clone->initScript(fun->script());
+        clone->initEnvironment(parent);
+    } else {
+        clone->u.n = fun->u.n;
+    }
     clone->atom = fun->atom;
 
     if (kind == JSFunction::ExtendedFinalizeKind) {
         clone->flags |= JSFUN_EXTENDED;
         clone->initializeExtended();
     }
 
-    if (clone->isInterpreted())
-        clone->setEnvironment(parent);
-
     if (cx->compartment == fun->compartment()) {
         /*
          * We can use the same type as the original function provided that (a)
          * its prototype is correct, and (b) its type is not a singleton. The
          * first case will hold in all compileAndGo code, and the second case
          * will have been caught by CloneFunctionObject coming from function
          * definitions or read barriers, so will not get here.
          */
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -5029,17 +5029,17 @@ js_FindClassObject(JSContext *cx, JSObje
     }
 
     JS_ASSERT(obj->isNative());
     if (!LookupPropertyWithFlags(cx, obj, id, JSRESOLVE_CLASSNAME, &pobj, &prop))
         return false;
     Value v = UndefinedValue();
     if (prop && pobj->isNative()) {
         shape = (Shape *) prop;
-        if (pobj->containsSlot(shape->slot())) {
+        if (shape->hasSlot()) {
             v = pobj->nativeGetSlot(shape->slot());
             if (v.isPrimitive())
                 v.setUndefined();
         }
     }
     *vp = v;
     return true;
 }
@@ -5286,17 +5286,17 @@ static inline bool
 CallAddPropertyHook(JSContext *cx, Class *clasp, JSObject *obj, const Shape *shape, Value *vp)
 {
     if (clasp->addProperty != JS_PropertyStub) {
         Value nominal = *vp;
 
         if (!CallJSPropertyOp(cx, clasp->addProperty, obj, shape->propid(), vp))
             return false;
         if (*vp != nominal) {
-            if (obj->containsSlot(shape->slot()))
+            if (shape->hasSlot())
                 obj->nativeSetSlotWithType(cx, shape, *vp);
         }
     }
     return true;
 }
 
 namespace js {
 
@@ -5416,17 +5416,17 @@ DefineNativeProperty(JSContext *cx, JSOb
 
         shape = obj->putProperty(cx, id, getter, setter, SHAPE_INVALID_SLOT,
                                  attrs, flags, shortid);
         if (!shape)
             return NULL;
     }
 
     /* Store valueCopy before calling addProperty, in case the latter GC's. */
-    if (shape->hasSlot() && obj->containsSlot(shape->slot()))
+    if (shape->hasSlot())
         obj->nativeSetSlot(shape->slot(), valueCopy);
 
     /* XXXbe called with lock held */
     if (!CallAddPropertyHook(cx, clasp, obj, shape, &valueCopy)) {
         obj->removeProperty(cx, id);
         return NULL;
     }
 
@@ -5851,17 +5851,16 @@ JSBool
 js_NativeSet(JSContext *cx, JSObject *obj, const Shape *shape, bool added, bool strict, Value *vp)
 {
     AddTypePropertyId(cx, obj, shape->propid(), *vp);
 
     JS_ASSERT(obj->isNative());
 
     if (shape->hasSlot()) {
         uint32_t slot = shape->slot();
-        JS_ASSERT(obj->containsSlot(slot));
 
         /* If shape has a stub setter, just store *vp. */
         if (shape->hasDefaultSetter()) {
             if (!added) {
                 if (shape->isMethod() && !obj->methodShapeChange(cx, *shape))
                     return false;
             }
             obj->nativeSetSlot(slot, *vp);
@@ -6333,17 +6332,17 @@ js_SetPropertyHelper(JSContext *cx, JSOb
         if (!shape)
             return JS_FALSE;
 
         /*
          * Initialize the new property value (passed to setter) to undefined.
          * Note that we store before calling addProperty, to match the order
          * in DefineNativeProperty.
          */
-        if (obj->containsSlot(shape->slot()))
+        if (shape->hasSlot())
             obj->nativeSetSlot(shape->slot(), UndefinedValue());
 
         /* XXXbe called with obj locked */
         if (!CallAddPropertyHook(cx, clasp, obj, shape, vp)) {
             obj->removeProperty(cx, id);
             return JS_FALSE;
         }
         added = true;
@@ -6460,22 +6459,17 @@ js_DeleteProperty(JSContext *cx, JSObjec
     shape = (Shape *)prop;
     if (!shape->configurable()) {
         if (strict)
             return obj->reportNotConfigurable(cx, id);
         rval->setBoolean(false);
         return true;
     }
 
-    if (!CallJSPropertyOp(cx, obj->getClass()->delProperty, obj, shape->getUserId(), rval))
-        return false;
-    if (rval->isFalse())
-        return true;
-
-    if (shape->hasSlot() && obj->containsSlot(shape->slot())) {
+    if (shape->hasSlot()) {
         const Value &v = obj->nativeGetSlot(shape->slot());
         GCPoke(cx, v);
 
         /*
          * Delete is rare enough that we can take the hit of checking for an
          * active cloned method function object that must be homed to a callee
          * slot on the active stack frame before this delete completes, in case
          * someone saved the clone and checks it against foo.caller for a foo
@@ -6499,16 +6493,21 @@ js_DeleteProperty(JSContext *cx, JSObjec
                             break;
                         }
                     } while ((tmp = tmp->getProto()) != NULL);
                 }
             }
         }
     }
 
+    if (!CallJSPropertyOp(cx, obj->getClass()->delProperty, obj, shape->getUserId(), rval))
+        return false;
+    if (rval->isFalse())
+        return true;
+
     return obj->removeProperty(cx, id) && js_SuppressDeletedProperty(cx, obj, id);
 }
 
 JSBool
 js_DeleteElement(JSContext *cx, JSObject *obj, uint32_t index, Value *rval, JSBool strict)
 {
     jsid id;
     if (!IndexToId(cx, index, &id))
@@ -6518,17 +6517,16 @@ js_DeleteElement(JSContext *cx, JSObject
 
 namespace js {
 
 bool
 HasDataProperty(JSContext *cx, JSObject *obj, jsid methodid, Value *vp)
 {
     if (const Shape *shape = obj->nativeLookup(cx, methodid)) {
         if (shape->hasDefaultGetterOrIsMethod() && shape->hasSlot()) {
-            JS_ASSERT(obj->containsSlot(shape->slot()));
             *vp = obj->nativeGetSlot(shape->slot());
             return true;
         }
     }
 
     return false;
 }
 
@@ -6962,20 +6960,18 @@ js_PrintObjectSlotName(JSTracer *trc, ch
     JS_ASSERT(trc->debugPrinter == js_PrintObjectSlotName);
 
     JSObject *obj = (JSObject *)trc->debugPrintArg;
     uint32_t slot = uint32_t(trc->debugPrintIndex);
 
     const Shape *shape;
     if (obj->isNative()) {
         shape = obj->lastProperty();
-        while (shape->previous() && shape->maybeSlot() != slot)
+        while (shape && (!shape->hasSlot() || shape->slot() != slot))
             shape = shape->previous();
-        if (shape->maybeSlot() != slot)
-            shape = NULL;
     } else {
         shape = NULL;
     }
 
     if (!shape) {
         const char *slotname = NULL;
         if (obj->isGlobal()) {
 #define JS_PROTO(name,code,init)                                              \
@@ -7022,18 +7018,18 @@ js_ClearNative(JSContext *cx, JSObject *
     }
 
     /* Set all remaining writable plain data properties to undefined. */
     for (Shape::Range r(obj->lastProperty()->all()); !r.empty(); r.popFront()) {
         const Shape *shape = &r.front();
         if (shape->isDataDescriptor() &&
             shape->writable() &&
             shape->hasDefaultSetter() &&
-            obj->containsSlot(shape->maybeSlot())) {
-            obj->setSlot(shape->slot(), UndefinedValue());
+            shape->hasSlot()) {
+            obj->nativeSetSlot(shape->slot(), UndefinedValue());
         }
     }
     return true;
 }
 
 bool
 js_GetReservedSlot(JSContext *cx, JSObject *obj, uint32_t slot, Value *vp)
 {
@@ -7290,17 +7286,17 @@ DumpProperty(JSObject *obj, const Shape 
         dumpString(JSID_TO_STRING(id));
     else if (JSID_IS_INT(id))
         fprintf(stderr, "%d", (int) JSID_TO_INT(id));
     else
         fprintf(stderr, "unknown jsid %p", (void *) JSID_BITS(id));
 
     uint32_t slot = shape.hasSlot() ? shape.maybeSlot() : SHAPE_INVALID_SLOT;
     fprintf(stderr, ": slot %d", slot);
-    if (obj->containsSlot(slot)) {
+    if (shape.hasSlot()) {
         fprintf(stderr, " = ");
         dumpValue(obj->getSlot(slot));
     } else if (slot != SHAPE_INVALID_SLOT) {
         fprintf(stderr, " (INVALID!)");
     }
     fprintf(stderr, "\n");
 }
 
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -706,18 +706,16 @@ struct JSObject : js::gc::Cell
      * ensure there are enough slots in this object. If |valid|, then the slots
      * being overwritten hold valid data and must be invalidated for the write
      * barrier.
      */
     void copySlotRange(size_t start, const js::Value *vector, size_t length, bool valid);
 
     inline uint32_t slotSpan() const;
 
-    inline bool containsSlot(uint32_t slot) const;
-
     void rollbackProperties(JSContext *cx, uint32_t slotSpan);
 
 #ifdef DEBUG
     enum SentinelAllowed {
         SENTINEL_NOT_ALLOWED,
         SENTINEL_ALLOWED
     };
 
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -1137,35 +1137,29 @@ JSObject::principals(JSContext *cx)
 inline uint32_t
 JSObject::slotSpan() const
 {
     if (inDictionaryMode())
         return lastProperty()->base()->slotSpan();
     return lastProperty()->slotSpan();
 }
 
-inline bool
-JSObject::containsSlot(uint32_t slot) const
-{
-    return slot < slotSpan();
-}
-
 inline js::HeapValue &
 JSObject::nativeGetSlotRef(uintN slot)
 {
     JS_ASSERT(isNative());
-    JS_ASSERT(containsSlot(slot));
+    JS_ASSERT(slot < slotSpan());
     return getSlotRef(slot);
 }
 
 inline const js::Value &
 JSObject::nativeGetSlot(uintN slot) const
 {
     JS_ASSERT(isNative());
-    JS_ASSERT(containsSlot(slot));
+    JS_ASSERT(slot < slotSpan());
     return getSlot(slot);
 }
 
 inline JSFunction *
 JSObject::nativeGetMethod(const js::Shape *shape) const
 {
     /*
      * For method shapes, this object must have an uncloned function object in
@@ -1179,17 +1173,17 @@ JSObject::nativeGetMethod(const js::Shap
 
     return static_cast<JSFunction *>(&nativeGetSlot(shape->slot()).toObject());
 }
 
 inline void
 JSObject::nativeSetSlot(uintN slot, const js::Value &value)
 {
     JS_ASSERT(isNative());
-    JS_ASSERT(containsSlot(slot));
+    JS_ASSERT(slot < slotSpan());
     return setSlot(slot, value);
 }
 
 inline void
 JSObject::nativeSetSlotWithType(JSContext *cx, const js::Shape *shape, const js::Value &value)
 {
     nativeSetSlot(shape->slot(), value);
     js::types::AddTypePropertyId(cx, this, shape->propid(), value);
--- a/js/src/jsxdrapi.cpp
+++ b/js/src/jsxdrapi.cpp
@@ -690,16 +690,19 @@ JS_XDRFunctionObject(JSXDRState *xdr, JS
 {
     XDRScriptState fstate(xdr);
 
     if (xdr->mode == JSXDR_ENCODE) {
         JSFunction* fun = (*objp)->toFunction();
         fstate.filename = fun->script()->filename;
     }
 
+    if (!JS_XDRCStringOrNull(xdr, (char **) &fstate.filename))
+        return false;
+
     return js_XDRFunctionObject(xdr, objp);
 }
 
 JS_PUBLIC_API(JSBool)
 JS_XDRScript(JSXDRState *xdr, JSScript **scriptp)
 {
     JS_ASSERT(!xdr->state);
 
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -541,20 +541,16 @@ mjit::Compiler::performCompilation(JITSc
 
 #ifdef JS_METHODJIT_SPEW
     prof.stop();
     JaegerSpew(JSpew_Prof, "compilation took %d us\n", prof.time_us());
 #endif
 
     JaegerSpew(JSpew_Scripts, "successfully compiled (code \"%p\") (size \"%u\")\n",
                (*jitp)->code.m_code.executableAddress(), unsigned((*jitp)->code.m_size));
-
-    if (!*jitp)
-        return Compile_Abort;
-
     return Compile_Okay;
 }
 
 #undef CHECK_STATUS
 
 mjit::Compiler::ActiveFrame::ActiveFrame(JSContext *cx)
     : parent(NULL), parentPC(NULL), script(NULL), jumpMap(NULL),
       inlineIndex(UINT32_MAX), varTypes(NULL), needReturnValue(false),
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -2647,17 +2647,17 @@ ConvertArgs(JSContext *cx, uintN argc, j
             b, c, (char)c, i, u, j);
     ToStringHelper obj2string(cx, obj2);
     ToStringHelper valueString(cx, v);
     JSAutoByteString strBytes;
     if (str)
         strBytes.encode(cx, str);
     JSString *tmpstr = JS_DecompileFunction(cx, fun, 4);
     JSAutoByteString func;
-    if (!tmpstr || !func.encode(cx, tmpstr));
+    if (!tmpstr || !func.encode(cx, tmpstr))
         ReportException(cx);
     fprintf(gOutFile,
             "d %g, I %g, S %s, W %s, obj %s, fun %s\n"
             "v %s, re %g, im %g\n",
             d, I, !!strBytes ? strBytes.ptr() : "", EscapeWideString(w),
             obj2string.getBytes(),
             fun ? (!!func ? func.ptr() : "error decompiling fun") : "",
             valueString.getBytes(), re, im);
--- a/js/src/tests/ecma_5/RegExp/jstests.list
+++ b/js/src/tests/ecma_5/RegExp/jstests.list
@@ -4,11 +4,12 @@ script 15.10.5-01.js
 script 15.10.7.5-01.js
 script empty-lookahead.js
 script exec.js
 script exec-lastIndex-ToInteger.js
 script regress-576828.js
 script regress-613820-1.js
 script regress-613820-2.js
 script regress-613820-3.js
+script regress-429241.js
 silentfail skip-if(!xulRuntime.shell&&(Android||xulRuntime.OS=="WINNT")) script regress-617935.js
 script instance-property-storage-introspection.js
 script regexp-space-character-class.js
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_5/RegExp/regress-429241.js
@@ -0,0 +1,233 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is JavaScript Engine testing utilities.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   <x00000000@freenet.de>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+var gTestfile = 'regress-429241.js';
+var BUGNUMBER = 429241;
+var summary = '\\x or \\u followed by too few hex digits';
+var r;
+
+reportCompare(
+  "x",
+  (r = /[\x]+/.exec("\\x\0")) && r[0],
+  "Section 1"
+);
+
+reportCompare(
+  "xy",
+  (r = /[\xy]+/.exec("\\xy\0")) && r[0],
+  "Section 2"
+);
+
+reportCompare(
+  "x0",
+  (r = /[\x0]+/.exec("\\x0\0")) && r[0],
+  "Section 3"
+);
+
+reportCompare(
+  "x0y",
+  (r = /[\x0y]+/.exec("\\x0y\0")) && r[0],
+  "Section 4"
+);
+
+reportCompare(
+  "\0",
+  (r = /[\x00]+/.exec("\\x\0")) && r[0],
+  "Section 5"
+);
+
+reportCompare(
+  "0\0",
+  (r = /[\x000]+/.exec("0\0")) && r[0],
+  "Section 6"
+);
+
+reportCompare(
+  "x",
+  (r = /^\x$/.exec("x")) && r[0],
+  "Section 7"
+);
+
+reportCompare(
+  "xy",
+  (r = /^\xy$/.exec("xy")) && r[0],
+  "Section 8"
+);
+
+reportCompare(
+  "x0",
+  (r = /^\x0$/.exec("x0")) && r[0],
+  "Section 9"
+);
+
+reportCompare(
+  "x0y",
+  (r = /^\x0y$/.exec("x0y")) && r[0],
+  "Section 10"
+);
+
+reportCompare(
+  null,
+  /^\x00$/.exec("\0" + "0"),
+  "Section 11"
+);
+
+reportCompare(
+  "\0" + "0",
+  (r = /^\x000$/.exec("\0" + "0")) && r[0],
+  "Section 12"
+);
+
+reportCompare(
+  "u",
+  (r = /[\u]+/.exec("\\u\0")) && r[0],
+  "Section 13"
+);
+
+reportCompare(
+  "uy",
+  (r = /[\uy]+/.exec("\\uy\0")) && r[0],
+  "Section 14"
+);
+
+reportCompare(
+  "u0",
+  (r = /[\u0]+/.exec("\\u0\0")) && r[0],
+  "Section 15"
+);
+
+reportCompare(
+  "u0",
+  (r = /[\u00]+/.exec("\\u0\0")) && r[0],
+  "Section 16"
+);
+
+reportCompare(
+  "u0",
+  (r = /[\u000]+/.exec("\\u0\0")) && r[0],
+  "Section 17"
+);
+
+reportCompare(
+  "u0y",
+  (r = /[\u0y]+/.exec("\\u0y\0")) && r[0],
+  "Section 18"
+);
+
+reportCompare(
+  "u0y",
+  (r = /[\u00y]+/.exec("\\u0y\0")) && r[0],
+  "Section 19"
+);
+
+reportCompare(
+  "u0y",
+  (r = /[\u000y]+/.exec("\\u0y\0")) && r[0],
+  "Section 20"
+);
+
+reportCompare(
+  "\0",
+  (r = /[\u0000]+/.exec("\\u\0")) && r[0],
+  "Section 21"
+);
+
+reportCompare(
+  "0\0",
+  (r = /[\u00000]+/.exec("0\0")) && r[0],
+  "Section 22"
+);
+
+reportCompare(
+  "u",
+  (r = /^\u$/.exec("u")) && r[0],
+  "Section 23"
+);
+
+reportCompare(
+  "uy",
+  (r = /^\uy$/.exec("uy")) && r[0],
+  "Section 24"
+);
+
+reportCompare(
+  "u0",
+  (r = /^\u0$/.exec("u0")) && r[0],
+  "Section 25"
+);
+
+reportCompare(
+  "u00",
+  (r = /^\u00$/.exec("u00")) && r[0],
+  "Section 26"
+);
+
+reportCompare(
+  "u000",
+  (r = /^\u000$/.exec("u000")) && r[0],
+  "Section 27"
+);
+
+reportCompare(
+  "u0y",
+  (r = /^\u0y$/.exec("u0y")) && r[0],
+  "Section 28"
+);
+
+reportCompare(
+  "u00y",
+  (r = /^\u00y$/.exec("u00y")) && r[0],
+  "Section 29"
+);
+
+reportCompare(
+  "u000y",
+  (r = /^\u000y$/.exec("u000y")) && r[0],
+  "Section 30"
+);
+
+reportCompare(
+  null,
+  /^\u0000$/.exec("\0" + "0"),
+  "Section 31"
+);
+
+reportCompare(
+  "\0" + "0",
+  (r = /^\u00000$/.exec("\0" + "0")) && r[0],
+  "Section 32"
+);
--- a/js/src/tests/js1_5/Regress/jstests.list
+++ b/js/src/tests/js1_5/Regress/jstests.list
@@ -144,17 +144,17 @@ script regress-321874.js
 script regress-321971.js
 script regress-322430.js
 script regress-323314-1.js
 script regress-325925.js
 script regress-326453.js
 script regress-326467.js
 script regress-328012.js
 script regress-328664.js
-script regress-328897.js
+fails-if(browserIsRemote) script regress-328897.js
 script regress-329383.js
 skip-if(Android) script regress-329530.js
 skip-if(Android) script regress-330352.js
 script regress-330951.js
 script regress-334807-01.js
 script regress-334807-02.js
 script regress-334807-03.js
 script regress-334807-04.js
--- a/js/src/tests/js1_5/Regress/regress-328897.js
+++ b/js/src/tests/js1_5/Regress/regress-328897.js
@@ -46,17 +46,17 @@ printBugNumber(BUGNUMBER);
 printStatus (summary);
  
 if (typeof window == 'undefined')
 {
   reportCompare(expect, actual, summary);
 }
 else
 {
-  expect = /(Script error.|uncaught exception: Permission denied to get property UnnamedClass.classes)/;
+  expect = /(Script error.|Permission denied for <file:\/\/> to get property XPCComponents.classes)/;
 
   window._onerror = window.onerror;
   window.onerror = (function (msg, page, line) { 
       actual = msg; 
       gDelayTestDriverEnd = false;
       jsTestDriverEnd();
       reportMatch(expect, actual, summary);
     });
--- a/js/src/tests/manifest.py
+++ b/js/src/tests/manifest.py
@@ -5,39 +5,42 @@
 import os, re, sys
 from subprocess import *
 
 from tests import TestCase
 
 
 def split_path_into_dirs(path):
     dirs = [path]
-   
+
     while True:
         path, tail = os.path.split(path)
         if not tail:
             break
         dirs.append(path)
     return dirs
 
 class XULInfo:
     def __init__(self, abi, os, isdebug):
         self.abi = abi
         self.os = os
         self.isdebug = isdebug
+        self.browserIsRemote = False
 
     def as_js(self):
         """Return JS that when executed sets up variables so that JS expression
         predicates on XUL build info evaluate properly."""
 
-        return 'var xulRuntime = { OS: "%s", XPCOMABI: "%s", shell: true }; var isDebugBuild=%s; var Android=%s;' % (
+        return ('var xulRuntime = { OS: "%s", XPCOMABI: "%s", shell: true };' +
+                'var isDebugBuild=%s; var Android=%s; var browserIsRemote=%s') % (
             self.os,
             self.abi,
             str(self.isdebug).lower(),
-            str(self.os == "Android").lower())
+            str(self.os == "Android").lower(),
+            str(self.browserIsRemote).lower())
 
     @classmethod
     def create(cls, jsdir):
         """Create a XULInfo based on the current platform's characteristics."""
 
         # Our strategy is to find the autoconf.mk generated for the build and
         # read the values from there.
 
--- a/js/src/vm/Debugger.h
+++ b/js/src/vm/Debugger.h
@@ -37,16 +37,18 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef Debugger_h__
 #define Debugger_h__
 
+#include "mozilla/Attributes.h"
+
 #include "jsapi.h"
 #include "jsclist.h"
 #include "jscntxt.h"
 #include "jscompartment.h"
 #include "jsgc.h"
 #include "jsweakmap.h"
 #include "jswrapper.h"
 
@@ -343,19 +345,18 @@ class Debugger {
     /*
      * Return the Debugger.Script object for |script|, or create a new one if
      * needed. The context |cx| must be in the debugger compartment; |script|
      * must be a script in a debuggee compartment.
      */
     JSObject *wrapScript(JSContext *cx, JSScript *script);
 
   private:
-    /* Prohibit copying. */
-    Debugger(const Debugger &);
-    Debugger & operator=(const Debugger &);
+    Debugger(const Debugger &) MOZ_DELETE;
+    Debugger & operator=(const Debugger &) MOZ_DELETE;
 };
 
 class BreakpointSite {
     friend class Breakpoint;
     friend struct ::JSCompartment;
     friend struct ::JSScript;
     friend class Debugger;
 
--- a/js/xpconnect/idl/nsIScriptError.idl
+++ b/js/xpconnect/idl/nsIScriptError.idl
@@ -38,17 +38,17 @@
 /*
  * nsIConsoleMessage subclass for representing JavaScript errors and warnings.
  */
 
 
 #include "nsISupports.idl"
 #include "nsIConsoleMessage.idl"
 
-[scriptable, uuid(537ff844-c325-4047-92f5-e1c292d108bc)]
+[scriptable, uuid(c6dd877a-87b6-47cc-968d-90f4514ec65f)]
 interface nsIScriptError : nsIConsoleMessage
 {
     /** pseudo-flag for default case */
     const unsigned long errorFlag = 0x0;
 
     /** message is warning */
     const unsigned long warningFlag = 0x1;
 
@@ -85,52 +85,45 @@ interface nsIScriptError : nsIConsoleMes
        The time (in milliseconds from the Epoch) that the script error instance
        was initialised, and thus the time when the error occurred.
        Currently used to display date and time of the message in Error console.
        The timestamp is initialized as JS_now/1000 so that it can be
        compared to Date.now in Javascript.
      */
     readonly attribute long long timeStamp;
 
+    /* Get the window id this was initialized with.  Zero will be
+       returned if init() was used instead of initWithWindowID(). */
+    readonly attribute unsigned long long outerWindowID;
+
+    /* Get the inner window id this was initialized with.  Zero will be
+       returned if init() was used instead of initWithWindowID(). */
+    readonly attribute unsigned long long innerWindowID;
+
     void init(in wstring message,
               in wstring sourceName,
               in wstring sourceLine,
               in PRUint32 lineNumber,
               in PRUint32 columnNumber,
               in PRUint32 flags,
               in string category);
 
-    AUTF8String toString();
-};
-
-/**
- * An interface that nsIScriptError objects can implement to allow
- * them to be initialized with a window id.
- */
-[scriptable, uuid(444c5e66-a85d-4a3b-83ce-4c71882b09a3)]
-interface nsIScriptError2 : nsISupports {
-    /* Get the window id this was initialized with.  Zero will be
-       returned if init() was used instead of initWithWindowID(). */
-    readonly attribute unsigned long long outerWindowID;
-
-    /* Get the inner window id this was initialized with.  Zero will be
-       returned if init() was used instead of initWithWindowID(). */
-    readonly attribute unsigned long long innerWindowID;
-
     /* This should be called instead of nsIScriptError.init to
        initialize with a window id.  The window id should be for the
        inner window associated with this error. */
     void initWithWindowID(in wstring message,
                           in wstring sourceName,
                           in wstring sourceLine,
                           in PRUint32 lineNumber,
                           in PRUint32 columnNumber,
                           in PRUint32 flags,
                           in string category,
                           in unsigned long long innerWindowID);
+
+    AUTF8String toString();
 };
 
 %{ C++
 #define NS_SCRIPTERROR_CLASSNAME "Script Error"
 
 #define NS_SCRIPTERROR_CID \
 { 0xe38e53b9, 0x5bb0, 0x456a, { 0xb5, 0x53, 0x57, 0x93, 0x70, 0xcb, 0x15, 0x67 }}
 
--- a/js/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/xpconnect/loader/mozJSComponentLoader.cpp
@@ -36,16 +36,18 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
+#include "mozilla/Attributes.h"
+
 #ifdef MOZ_LOGGING
 #define FORCE_PR_LOG
 #endif
 
 #include <stdarg.h>
 
 #include "prlog.h"
 #ifdef ANDROID
@@ -314,34 +316,34 @@ public:
 
 private:
     JSContext* mContext;
     intN       mContextThread;
     nsIThreadJSContextStack* mContextStack;
     char*      mBuf;
 
     // prevent copying and assignment
-    JSCLContextHelper(const JSCLContextHelper &); // not implemented
-    const JSCLContextHelper& operator=(const JSCLContextHelper &); // not implemented
+    JSCLContextHelper(const JSCLContextHelper &) MOZ_DELETE;
+    const JSCLContextHelper& operator=(const JSCLContextHelper &) MOZ_DELETE;
 };
 
 
 class JSCLAutoErrorReporterSetter
 {
 public:
     JSCLAutoErrorReporterSetter(JSContext* cx, JSErrorReporter reporter)
         {mContext = cx; mOldReporter = JS_SetErrorReporter(cx, reporter);}
     ~JSCLAutoErrorReporterSetter()
         {JS_SetErrorReporter(mContext, mOldReporter);}
 private:
     JSContext* mContext;
     JSErrorReporter mOldReporter;
-    // prevent copying and assignment
-    JSCLAutoErrorReporterSetter(const JSCLAutoErrorReporterSetter &); // not implemented
-    const JSCLAutoErrorReporterSetter& operator=(const JSCLAutoErrorReporterSetter &); // not implemented
+
+    JSCLAutoErrorReporterSetter(const JSCLAutoErrorReporterSetter &) MOZ_DELETE;
+    const JSCLAutoErrorReporterSetter& operator=(const JSCLAutoErrorReporterSetter &) MOZ_DELETE;
 };
 
 static nsresult
 ReportOnCaller(JSContext *callerContext,
                const char *format, ...) {
     if (!callerContext) {
         return NS_ERROR_FAILURE;
     }
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -2687,17 +2687,17 @@ nsXPCComponents_Utils::LookupMethod(cons
 /* void reportError (); */
 NS_IMETHODIMP
 nsXPCComponents_Utils::ReportError(const JS::Value &error, JSContext *cx)
 {
     // This function shall never fail! Silently eat any failure conditions.
 
     nsCOMPtr<nsIConsoleService> console(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
 
-    nsCOMPtr<nsIScriptError2> scripterr(do_CreateInstance(NS_SCRIPTERROR_CONTRACTID));
+    nsCOMPtr<nsIScriptError> scripterr(do_CreateInstance(NS_SCRIPTERROR_CONTRACTID));
 
     if (!scripterr || !console)
         return NS_OK;
 
     JSAutoRequest ar(cx);
 
     const PRUint64 innerWindowID = nsJSUtils::GetCurrentlyRunningCodeInnerWindowID(cx);
 
@@ -2710,18 +2710,17 @@ nsXPCComponents_Utils::ReportError(const
         PRUint32 column = err->uctokenptr - err->uclinebuf;
 
         nsresult rv = scripterr->InitWithWindowID(
                 static_cast<const PRUnichar*>(err->ucmessage), fileUni.get(),
                 static_cast<const PRUnichar*>(err->uclinebuf), err->lineno,
                 column, err->flags, "XPConnect JavaScript", innerWindowID);
         NS_ENSURE_SUCCESS(rv, NS_OK);
 
-        nsCOMPtr<nsIScriptError> logError = do_QueryInterface(scripterr);
-        console->LogMessage(logError);
+        console->LogMessage(scripterr);
         return NS_OK;
     }
 
     // It's not a JS Error object, so we synthesize as best we're able.
     JSString *msgstr = JS_ValueToString(cx, error);
     if (!msgstr) {
         return NS_OK;
     }
@@ -2743,18 +2742,17 @@ nsXPCComponents_Utils::ReportError(const
         return NS_OK;
 
     nsresult rv = scripterr->InitWithWindowID(
             reinterpret_cast<const PRUnichar *>(msgchars),
             NS_ConvertUTF8toUTF16(fileName).get(),
             nsnull, lineNo, 0, 0, "XPConnect JavaScript", innerWindowID);
     NS_ENSURE_SUCCESS(rv, NS_OK);
 
-    nsCOMPtr<nsIScriptError> logError = do_QueryInterface(scripterr);
-    console->LogMessage(logError);
+    console->LogMessage(scripterr);
     return NS_OK;
 }
 
 #include "nsIScriptSecurityManager.h"
 #include "nsIURI.h"
 #include "nsNetUtil.h"
 const char kScriptSecurityManagerContractID[] = NS_SCRIPTSECURITYMANAGER_CONTRACTID;
 
--- a/js/xpconnect/src/XPCWrappedJSClass.cpp
+++ b/js/xpconnect/src/XPCWrappedJSClass.cpp
@@ -1128,24 +1128,22 @@ nsXPCWrappedJSClass::CheckForException(X
                                 if (location) {
                                     // Get line number w/o checking; 0 is ok.
                                     location->GetLineNumber(&lineNumber);
 
                                     // get a filename.
                                     rv = location->GetFilename(getter_Copies(sourceName));
                                 }
 
-                                nsCOMPtr<nsIScriptError2> scriptError2 =
-                                    do_QueryInterface(scriptError);
-                                rv = scriptError2->InitWithWindowID(newMessage.get(),
-                                                                    NS_ConvertASCIItoUTF16(sourceName).get(),
-                                                                    nsnull,
-                                                                    lineNumber, 0, 0,
-                                                                    "XPConnect JavaScript",
-                                                                    nsJSUtils::GetCurrentlyRunningCodeInnerWindowID(cx));
+                                rv = scriptError->InitWithWindowID(newMessage.get(),
+                                                                   NS_ConvertASCIItoUTF16(sourceName).get(),
+                                                                   nsnull,
+                                                                   lineNumber, 0, 0,
+                                                                   "XPConnect JavaScript",
+                                                                   nsJSUtils::GetCurrentlyRunningCodeInnerWindowID(cx));
                                 if (NS_FAILED(rv))
                                     scriptError = nsnull;
                             }
                         }
                     }
                     if (nsnull != scriptError)
                         consoleService->LogMessage(scriptError);
                 }
--- a/js/xpconnect/src/XPCWrappedNativeJSOps.cpp
+++ b/js/xpconnect/src/XPCWrappedNativeJSOps.cpp
@@ -623,17 +623,22 @@ XPC_WN_NoHelper_Finalize(JSContext *cx, 
 
     if (IS_SLIM_WRAPPER_OBJECT(obj)) {
         SLIM_LOG(("----- %i finalized slim wrapper (%p, %p)\n",
                   ++sFinalizedSlimWrappers, obj, p));
 
         nsWrapperCache* cache;
         CallQueryInterface(p, &cache);
         cache->ClearWrapper();
-        NS_RELEASE(p);
+
+        XPCJSRuntime *rt = nsXPConnect::GetRuntimeInstance();
+        if(rt)
+            rt->DeferredRelease(p);
+        else
+            NS_RELEASE(p);
         return;
     }
 
     static_cast<XPCWrappedNative*>(p)->FlatJSObjectFinalized(cx);
 }
 
 static void
 TraceScopeJSObjects(JSTracer *trc, XPCWrappedNativeScope* scope)
--- a/js/xpconnect/src/nsScriptError.cpp
+++ b/js/xpconnect/src/nsScriptError.cpp
@@ -41,18 +41,17 @@
  * nsIScriptError implementation.  Defined here, lacking a JS-specific
  * place to put XPCOM things.
  */
 
 #include "xpcprivate.h"
 #include "nsGlobalWindow.h"
 #include "nsPIDOMWindow.h"
 
-NS_IMPL_THREADSAFE_ISUPPORTS3(nsScriptError, nsIConsoleMessage, nsIScriptError,
-                              nsIScriptError2)
+NS_IMPL_THREADSAFE_ISUPPORTS2(nsScriptError, nsIConsoleMessage, nsIScriptError)
 
 nsScriptError::nsScriptError()
     :  mMessage(),
        mSourceName(),
        mLineNumber(0),
        mSourceLine(),
        mColumnNumber(0),
        mFlags(0),
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -41,16 +41,18 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 /* All the XPConnect private declarations - only include locally. */
 
 #ifndef xpcprivate_h___
 #define xpcprivate_h___
 
+#include "mozilla/Attributes.h"
+
 #include <string.h>
 #include <stdlib.h>
 #include <stdarg.h>
 #include <math.h>
 #include "xpcpublic.h"
 #include "jsapi.h"
 #include "jsdhash.h"
 #include "jsprf.h"
@@ -3931,29 +3933,27 @@ xpc_DumpJSObject(JSObject* obj);
 
 extern JSBool
 xpc_InstallJSDebuggerKeywordHandler(JSRuntime* rt);
 
 /***************************************************************************/
 
 // Definition of nsScriptError, defined here because we lack a place to put
 // XPCOM objects associated with the JavaScript engine.
-class nsScriptError : public nsIScriptError,
-                      public nsIScriptError2 {
+class nsScriptError : public nsIScriptError {
 public:
     nsScriptError();
 
     virtual ~nsScriptError();
 
   // TODO - do something reasonable on getting null from these babies.
 
     NS_DECL_ISUPPORTS
     NS_DECL_NSICONSOLEMESSAGE
     NS_DECL_NSISCRIPTERROR
-    NS_DECL_NSISCRIPTERROR2
 
 private:
     nsString mMessage;
     nsString mSourceName;
     PRUint32 mLineNumber;
     nsString mSourceLine;
     PRUint32 mColumnNumber;
     PRUint32 mFlags;
@@ -4021,18 +4021,18 @@ private:
     JSExceptionState* mState;
     bool mErrorReporterSet;
     bool mEvaluated;
     jsword mContextHasThread;
     JSAutoEnterCompartment mEnterCompartment;
     MOZILLA_DECL_USE_GUARD_OBJECT_NOTIFIER
 
     // No copying or assignment allowed
-    AutoScriptEvaluate(const AutoScriptEvaluate &);
-    AutoScriptEvaluate & operator =(const AutoScriptEvaluate &);
+    AutoScriptEvaluate(const AutoScriptEvaluate &) MOZ_DELETE;
+    AutoScriptEvaluate & operator =(const AutoScriptEvaluate &) MOZ_DELETE;
 };
 
 /***************************************************************************/
 class NS_STACK_CLASS AutoResolveName
 {
 public:
     AutoResolveName(XPCCallContext& ccx, jsid name
                     MOZILLA_GUARD_OBJECT_NOTIFIER_PARAM)
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -3522,17 +3522,17 @@ nsCSSFrameConstructor::FindHTMLData(Elem
     SIMPLE_TAG_CHAIN(embed, nsCSSFrameConstructor::FindObjectData),
     COMPLEX_TAG_CREATE(fieldset,
                        &nsCSSFrameConstructor::ConstructFieldSetFrame),
     { &nsGkAtoms::legend,
       FCDATA_DECL(FCDATA_ALLOW_BLOCK_STYLES, NS_NewLegendFrame) },
     SIMPLE_TAG_CREATE(frameset, NS_NewHTMLFramesetFrame),
     SIMPLE_TAG_CREATE(iframe, NS_NewSubDocumentFrame),
     COMPLEX_TAG_CREATE(button, &nsCSSFrameConstructor::ConstructButtonFrame),
-    SIMPLE_TAG_CREATE(canvas, NS_NewHTMLCanvasFrame),
+    SIMPLE_TAG_CHAIN(canvas, nsCSSFrameConstructor::FindCanvasData),
 #if defined(MOZ_MEDIA)
     SIMPLE_TAG_CREATE(video, NS_NewHTMLVideoFrame),
     SIMPLE_TAG_CREATE(audio, NS_NewHTMLVideoFrame),
 #endif
     SIMPLE_TAG_CREATE(progress, NS_NewProgressFrame)
   };
 
   return FindDataByTag(aTag, aElement, aStyleContext, sHTMLData,
@@ -3633,16 +3633,30 @@ nsCSSFrameConstructor::FindObjectData(El
                       NS_NewSubDocumentFrame)
     // Nothing for TYPE_NULL so we'll construct frames by display there
   };
 
   return FindDataByInt((PRInt32)type, aElement, aStyleContext,
                        sObjectData, ArrayLength(sObjectData));
 }
 
+/* static */
+const nsCSSFrameConstructor::FrameConstructionData*
+nsCSSFrameConstructor::FindCanvasData(Element* aElement,
+                                      nsStyleContext* aStyleContext)
+{
+  if (!aElement->OwnerDoc()->IsScriptEnabled()) {
+    return nsnull;
+  }
+
+  static const FrameConstructionData sCanvasData =
+    SIMPLE_FCDATA(NS_NewHTMLCanvasFrame);
+  return &sCanvasData;
+}
+
 nsresult
 nsCSSFrameConstructor::ConstructFrameFromItemInternal(FrameConstructionItem& aItem,
                                                       nsFrameConstructorState& aState,
                                                       nsIFrame* aParentFrame,
                                                       nsFrameItems& aFrameItems)
 {
   const FrameConstructionData* data = aItem.mFCData;
   NS_ASSERTION(data, "Must have frame construction data");
--- a/layout/base/nsCSSFrameConstructor.h
+++ b/layout/base/nsCSSFrameConstructor.h
@@ -38,16 +38,18 @@
 /*
  * construction of a frame tree that is nearly isomorphic to the content
  * tree and updating of that tree in response to dynamic changes
  */
 
 #ifndef nsCSSFrameConstructor_h___
 #define nsCSSFrameConstructor_h___
 
+#include "mozilla/Attributes.h"
+
 #include "nsCOMPtr.h"
 #include "nsILayoutHistoryState.h"
 #include "nsIXBLService.h"
 #include "nsQuoteList.h"
 #include "nsCounterManager.h"
 #include "nsHashKeys.h"
 #include "nsThreadUtils.h"
 #include "nsPageContentFrame.h"
@@ -97,20 +99,19 @@ public:
   static nsIXBLService * GetXBLService();
   static void ReleaseGlobals() { NS_IF_RELEASE(gXBLService); }
 
   // get the alternate text for a content node
   static void GetAlternateTextFor(nsIContent*    aContent,
                                   nsIAtom*       aTag,  // content object's tag
                                   nsXPIDLString& aAltText);
 
-private: 
-  // These are not supported and are not implemented! 
-  nsCSSFrameConstructor(const nsCSSFrameConstructor& aCopy); 
-  nsCSSFrameConstructor& operator=(const nsCSSFrameConstructor& aCopy); 
+private:
+  nsCSSFrameConstructor(const nsCSSFrameConstructor& aCopy) MOZ_DELETE;
+  nsCSSFrameConstructor& operator=(const nsCSSFrameConstructor& aCopy) MOZ_DELETE;
 
 public:
   // XXXbz this method needs to actually return errors!
   nsresult ConstructRootFrame(nsIFrame** aNewFrame);
 
   nsresult ReconstructDocElementHierarchy();
 
   // Create frames for content nodes that are marked as needing frames. This
@@ -1196,16 +1197,18 @@ private:
   static const FrameConstructionData*
     FindImgData(Element* aElement, nsStyleContext* aStyleContext);
   static const FrameConstructionData*
     FindImgControlData(Element* aElement, nsStyleContext* aStyleContext);
   static const FrameConstructionData*
     FindInputData(Element* aElement, nsStyleContext* aStyleContext);
   static const FrameConstructionData*
     FindObjectData(Element* aElement, nsStyleContext* aStyleContext);
+  static const FrameConstructionData*
+    FindCanvasData(Element* aElement, nsStyleContext* aStyleContext);
 
   /* Construct a frame from the given FrameConstructionItem.  This function
      will handle adding the frame to frame lists, processing children, setting
      the frame as the primary frame for the item's content, and so forth.
 
      @param aItem the FrameConstructionItem to use.
      @param aState the frame construction state to use.
      @param aParentFrame the frame to set as the parent of the
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -3766,23 +3766,19 @@ DocumentViewerImpl::PrintPreviewNavigate
   // If it is "End" then just do a "goto" to the last page
   if (aType == nsIWebBrowserPrint::PRINTPREVIEW_END) {
     aType    = nsIWebBrowserPrint::PRINTPREVIEW_GOTO_PAGENUM;
     aPageNum = pageCount;
   }
 
   // Now, locate the current page we are on and
   // and the page of the page number
-  nscoord gap = 0;
   nsIFrame* pageFrame = seqFrame->GetFirstPrincipalChild();
   while (pageFrame != nsnull) {
     nsRect pageRect = pageFrame->GetRect();
-    if (pageNum == 1) {
-      gap = pageRect.y;
-    }
     if (pageRect.Contains(pageRect.x, pt.y)) {
       currentPage = pageFrame;
     }
     if (pageNum == aPageNum) {
       fndPageFrame = pageFrame;
       break;
     }
     pageNum++;
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -4222,17 +4222,17 @@ nsLayoutUtils::GetFontFacesForFrames(nsI
   if (aFrame->GetType() == nsGkAtoms::textFrame) {
     return GetFontFacesForText(aFrame, 0, PR_INT32_MAX, false,
                                aFontFaceList);
   }
 
   while (aFrame) {
     nsIFrame::ChildListID childLists[] = { nsIFrame::kPrincipalList,
                                            nsIFrame::kPopupList };
-    for (int i = 0; i < ArrayLength(childLists); ++i) {
+    for (size_t i = 0; i < ArrayLength(childLists); ++i) {
       nsFrameList children(aFrame->GetChildList(childLists[i]));
       for (nsFrameList::Enumerator e(children); !e.AtEnd(); e.Next()) {
         nsIFrame* child = e.get();
         if (child->GetPrevContinuation()) {
           continue;
         }
         child = nsPlaceholderFrame::GetRealFrameFor(child);
         nsresult rv = GetFontFacesForFrames(child, aFontFaceList);
@@ -4501,29 +4501,34 @@ nsReflowFrameRunnable::Run()
  * width of the device**, the fonts satisfy our minima.
  */
 static nscoord
 MinimumFontSizeFor(nsPresContext* aPresContext, nscoord aContainerWidth)
 {
   if (sFontSizeInflationEmPerLine == 0 && sFontSizeInflationMinTwips == 0) {
     return 0;
   }
+
+  // Clamp the container width to the device dimensions
+  nscoord iFrameWidth = aPresContext->GetVisibleArea().width;
+  nscoord effectiveContainerWidth = NS_MIN(iFrameWidth, aContainerWidth);
+
   nscoord byLine = 0, byInch = 0;
   if (sFontSizeInflationEmPerLine != 0) {
-    byLine = aContainerWidth / sFontSizeInflationEmPerLine;
+    byLine = effectiveContainerWidth / sFontSizeInflationEmPerLine;
   }
   if (sFontSizeInflationMinTwips != 0) {
     // REVIEW: Is this giving us app units and sizes *not* counting
     // viewport scaling?
     nsDeviceContext *dx = aPresContext->DeviceContext();
     nsRect clientRect;
     dx->GetClientRect(clientRect); // FIXME: GetClientRect looks expensive
     float deviceWidthInches =
       float(clientRect.width) / float(dx->AppUnitsPerPhysicalInch());
-    byInch = NSToCoordRound(aContainerWidth /
+    byInch = NSToCoordRound(effectiveContainerWidth /
                             (deviceWidthInches * 1440 /
                              sFontSizeInflationMinTwips ));
   }
   return NS_MAX(byLine, byInch);
 }
 
 /* static */ float
 nsLayoutUtils::FontSizeInflationInner(const nsIFrame *aFrame,
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -486,32 +486,34 @@ nsPresContext::GetFontPreferences()
   PRInt32 size = Preferences::GetInt(pref.get());
   if (unit == eUnit_px) {
     mMinimumFontSizePref = CSSPixelsToAppUnits(size);
   }
   else if (unit == eUnit_pt) {
     mMinimumFontSizePref = CSSPointsToAppUnits(size);
   }
 
+  nsFont* fontTypes[] = {
+    &mDefaultVariableFont,
+    &mDefaultFixedFont,
+    &mDefaultSerifFont,
+    &mDefaultSansSerifFont,
+    &mDefaultMonospaceFont,
+    &mDefaultCursiveFont,
+    &mDefaultFantasyFont
+  };
+  PR_STATIC_ASSERT(NS_ARRAY_LENGTH(fontTypes) == eDefaultFont_COUNT);
+
   // get attributes specific to each generic font
   nsCAutoString generic_dot_langGroup;
-  for (PRInt32 eType = eDefaultFont_Variable; eType < eDefaultFont_COUNT; ++eType) {
+  for (PRUint32 eType = 0; eType < ArrayLength(fontTypes); ++eType) {
     generic_dot_langGroup.Assign(kGenericFont[eType]);
     generic_dot_langGroup.Append(langGroup);
 
-    nsFont* font;
-    switch (eType) {
-      case eDefaultFont_Variable:  font = &mDefaultVariableFont;  break;
-      case eDefaultFont_Fixed:     font = &mDefaultFixedFont;     break;
-      case eDefaultFont_Serif:     font = &mDefaultSerifFont;     break;
-      case eDefaultFont_SansSerif: font = &mDefaultSansSerifFont; break;
-      case eDefaultFont_Monospace: font = &mDefaultMonospaceFont; break;
-      case eDefaultFont_Cursive:   font = &mDefaultCursiveFont;   break;
-      case eDefaultFont_Fantasy:   font = &mDefaultFantasyFont;   break;
-    }
+    nsFont* font = fontTypes[eType];
 
     // set the default variable font (the other fonts are seen as 'generic' fonts
     // in GFX and will be queried there when hunting for alternative fonts)
     if (eType == eDefaultFont_Variable) {
       MAKE_FONT_PREF_KEY(pref, "font.name", generic_dot_langGroup);
 
       nsAdoptingString value = Preferences::GetString(pref.get());
       if (!value.IsEmpty()) {
--- a/layout/base/nsStyleChangeList.h
+++ b/layout/base/nsStyleChangeList.h
@@ -38,16 +38,18 @@
 /*
  * a list of the recomputation that needs to be done in response to a
  * style change
  */
 
 #ifndef nsStyleChangeList_h___
 #define nsStyleChangeList_h___
 
+#include "mozilla/Attributes.h"
+
 #include "nsError.h"
 #include "nsChangeHint.h"
 
 class nsIFrame;
 class nsIContent;
 
 // XXX would all platforms support putting this inside the list?
 struct nsStyleChangeData {
@@ -90,13 +92,13 @@ protected:
   bool                operator==(const nsStyleChangeList& aOther) const;
 
   nsStyleChangeData*  mArray;
   PRInt32             mArraySize;
   PRInt32             mCount;
   nsStyleChangeData   mBuffer[kStyleChangeBufferSize];
 
 private:
-  nsStyleChangeList(const nsStyleChangeList&); // not implemented
+  nsStyleChangeList(const nsStyleChangeList&) MOZ_DELETE;
 };
 
 
 #endif /* nsStyleChangeList_h___ */
--- a/layout/base/tests/TestPoisonArea.cpp
+++ b/layout/base/tests/TestPoisonArea.cpp
@@ -614,16 +614,17 @@ TestPage(const char *pagelabel, uintptr_
     } else if (pid == 0) {
       volatile unsigned char scratch;
       switch (test) {
       case 0: scratch = *(volatile unsigned char *)opaddr; break;
       case 1: JumpTo(opaddr); break;
       case 2: *(volatile unsigned char *)opaddr = 0; break;
       default: abort();
       }
+      (void)scratch;
       _exit(0);
     } else {
       int status;
       if (waitpid(pid, &status, 0) != pid) {
         printf("ERROR | %s %s | wait=%s\n", oplabel, pagelabel,
                LastErrMsg());
         exit(2);
       }
new file mode 100644
new file mode 100644
new file mode 100644
new file mode 100644
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/font-inflation/container-with-clamping-innerFrame-ref.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML>
+<style>
+	div { background: yellow }
+	div { font-size: 20px; line-height: 1.0; width: 450px }
+</style>
+<!--
+Without the patch for bug 707855, we have a 450px container, and the minimum font size
+at 15em per line is 30px. This means we map 0px-45px into 30px-45px, so 12px gets mapped
+to 34px.
+
+With the patch, then we have a 240px container, so the minimum font size
+at 15 em per line is 16px. So, we map 0px-24px into 16px-24px, so 12px gets
+mapped to 20px.
+-->
+<div>Test to see if too large of a container causes a giant escalation of the font size when font inflation is enabled.</div>
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/font-inflation/container-with-clamping-innerFrame.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML>
+<style>
+	div { background: yellow }
+	div { font-size: 12px; line-height: 1.0; width: 450px }
+</style>
+<!--
+Without the patch for bug 707855, we have a 450px container, and the minimum font size
+at 15em per line is 30px. This means we map 0px-45px into 30px-45px, so 12px gets mapped
+to 34px.
+
+With the patch, then we have a 240px container, so the minimum font size
+at 15 em per line is 16px. So, we map 0px-24px into 16px-24px, so 12px gets
+mapped to 20px.
+-->
+<div>Test to see if too large of a container causes a giant escalation of the font size when font inflation is enabled.</div>
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/font-inflation/container-with-clamping-ref.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<style>
+div { background: yellow }
+div { font-size: 12px; line-height: 1.0; width: 1200px }
+</style>
+<!--
+Without the patch for bug 707855, we have a 450px container, and the minimum font size
+at 15em per line is 30px. This means we map 0px-45px into 30px-45px, so 12px gets mapped
+to 34px.
+
+With the patch, then we have a 240px container, so the minimum font size
+at 15 em per line is 16px. So, we map 0px-24px into 16px-24px, so 12px gets
+mapped to 20px.
+-->
+<iframe src="container-with-clamping-innerFrame-ref.html" width="240" height="400">
+</iframe>
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/font-inflation/container-with-clamping.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML>
+<!--
+Without the patch for bug 707855, we have a 450px container, and the minimum font size
+at 15em per line is 30px. This means we map 0px-45px into 30px-45px, so 12px gets mapped
+to 34px.
+
+With the patch, then we have a 240px container, so the minimum font size
+at 15 em per line is 16px. So, we map 0px-24px into 16px-24px, so 12px gets
+mapped to 20px.
+-->
+<iframe src="container-with-clamping-innerFrame.html" width="240" height="400">
+</iframe>
--- a/layout/base/tests/test_font_inflation_reftests.html
+++ b/layout/base/tests/test_font_inflation_reftests.html
@@ -40,16 +40,17 @@ var gTests = [
   "== input-text-1.html input-text-1-ref.html",
   "== input-text-2.html input-text-2-ref.html",
   "== input-text-3.html input-text-3-ref.html",
   "== textarea-1.html textarea-1-ref.html",
   "== textarea-2.html textarea-2-ref.html",
   "== textarea-3.html textarea-3-ref.html",
   "== css-transform-1.html css-transform-1-ref.html",
   "== css-transform-2.html css-transform-2-ref.html",
+  "== container-with-clamping.html container-with-clamping-ref.html",
 ];
 
 // Maintain a reference count of how many things we're waiting for until
 // we can say the tests are done.
 var gDelayCount = 0;
 function AddFinishDependency()
   { ++gDelayCount; }
 function RemoveFinishDependency()
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -405,17 +405,17 @@ nsBlockFrame::List(FILE* out, PRInt32 aI
 
   if (nsnull != mContent) {
     fprintf(out, " [content=%p]", static_cast<void*>(mContent));
   }
 
   // Output the rect and state
   fprintf(out, " {%d,%d,%d,%d}", mRect.x, mRect.y, mRect.width, mRect.height);
   if (0 != mState) {
-    fprintf(out, " [state=%016llx]", mState);
+    fprintf(out, " [state=%016llx]", (unsigned long long)mState);
   }
   nsBlockFrame* f = const_cast<nsBlockFrame*>(this);
   if (f->HasOverflowAreas()) {
     nsRect overflowArea = f->GetVisualOverflowRect();
     fprintf(out, " [vis-overflow=%d,%d,%d,%d]", overflowArea.x, overflowArea.y,
             overflowArea.width, overflowArea.height);
     overflowArea = f->GetScrollableOverflowRect();
     fprintf(out, " [scr-overflow=%d,%d,%d,%d]", overflowArea.x, overflowArea.y,
@@ -7072,27 +7072,23 @@ nsBlockFrame::VerifyLines(bool aFinalChe
   }
   if (mLines.empty()) {
     return;
   }
 
   // Add up the counts on each line. Also validate that IsFirstLine is
   // set properly.
   PRInt32 count = 0;
-  bool seenBlock = false;
   line_iterator line, line_end;
   for (line = begin_lines(), line_end = end_lines();
        line != line_end;
        ++line) {
     if (aFinalCheckOK) {
       NS_ABORT_IF_FALSE(line->GetChildCount(), "empty line");
       if (line->IsBlock()) {
-        seenBlock = true;
-      }
-      if (line->IsBlock()) {
         NS_ASSERTION(1 == line->GetChildCount(), "bad first line");
       }
     }
     count += line->GetChildCount();
   }
 
   // Then count the frames
   PRInt32 frameCount = 0;
--- a/layout/generic/nsContainerFrame.cpp
+++ b/layout/generic/nsContainerFrame.cpp
@@ -1738,17 +1738,17 @@ nsContainerFrame::List(FILE* out, PRInt3
     fprintf(out, " IBSplitSpecialSibling=%p", IBsibling);
   }
   void* IBprevsibling = Properties().Get(IBSplitSpecialPrevSibling());
   if (IBprevsibling) {
     fprintf(out, " IBSplitSpecialPrevSibling=%p", IBprevsibling);
   }
   fprintf(out, " {%d,%d,%d,%d}", mRect.x, mRect.y, mRect.width, mRect.height);
   if (0 != mState) {
-    fprintf(out, " [state=%016llx]", mState);
+    fprintf(out, " [state=%016llx]", (unsigned long long)mState);
   }
   fprintf(out, " [content=%p]", static_cast<void*>(mContent));
   nsContainerFrame* f = const_cast<nsContainerFrame*>(this);
   if (f->HasOverflowAreas()) {
     nsRect overflowArea = f->GetVisualOverflowRect();
     fprintf(out, " [vis-overflow=%d,%d,%d,%d]", overflowArea.x, overflowArea.y,
             overflowArea.width, overflowArea.height);
     overflowArea = f->GetScrollableOverflowRect();
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -37,16 +37,17 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 /* base class of all rendering objects */
 
+#include "mozilla/Attributes.h"
 #include "mozilla/Util.h"
 
 #include "nsCOMPtr.h"
 #include "nsFrame.h"
 #include "nsFrameList.h"
 #include "nsPlaceholderFrame.h"
 #include "nsLineLayout.h"
 #include "nsIContent.h"
@@ -5049,17 +5050,17 @@ nsFrame::List(FILE* out, PRInt32 aIndent
 #ifdef DEBUG_waterson
   fprintf(out, " [parent=%p]", static_cast<void*>(mParent));
 #endif
   if (HasView()) {
     fprintf(out, " [view=%p]", static_cast<void*>(GetView()));
   }
   fprintf(out, " {%d,%d,%d,%d}", mRect.x, mRect.y, mRect.width, mRect.height);
   if (0 != mState) {
-    fprintf(out, " [state=%016llx]", mState);
+    fprintf(out, " [state=%016llx]", (unsigned long long)mState);
   }
   nsIFrame* prevInFlow = GetPrevInFlow();
   nsIFrame* nextInFlow = GetNextInFlow();
   if (nsnull != prevInFlow) {
     fprintf(out, " prev-in-flow=%p", static_cast<void*>(prevInFlow));
   }
   if (nsnull != nextInFlow) {
     fprintf(out, " next-in-flow=%p", static_cast<void*>(nextInFlow));
@@ -5271,17 +5272,17 @@ nsFrame::DumpRegressionData(nsPresContex
 {
   IndentBy(out, aIndent);
   fprintf(out, "<frame va=\"%ld\" type=\"", PRUptrdiff(this));
   nsAutoString name;
   GetFrameName(name);
   XMLQuote(name);
   fputs(NS_LossyConvertUTF16toASCII(name).get(), out);
   fprintf(out, "\" state=\"%016llx\" parent=\"%ld\">\n",
-          GetDebugStateBits(), PRUptrdiff(mParent));
+          (unsigned long long)GetDebugStateBits(), PRUptrdiff(mParent));
 
   aIndent++;
   DumpBaseRegressionData(aPresContext, out, aIndent);
   aIndent--;
 
   IndentBy(out, aIndent);
   fprintf(out, "</frame>\n");
 
@@ -8069,17 +8070,17 @@ struct DR_FrameTypeInfo
       }
    }
 
   nsIAtom*    mType;
   char        mNameAbbrev[16];
   char        mName[32];
   nsTArray<DR_Rule*> mRules;
 private:
-  DR_FrameTypeInfo& operator=(const DR_FrameTypeInfo&); // NOT USED
+  DR_FrameTypeInfo& operator=(const DR_FrameTypeInfo&) MOZ_DELETE;
 };
 
 DR_FrameTypeInfo::DR_FrameTypeInfo(nsIAtom* aFrameType, 
                                    const char* aFrameNameAbbrev, 
                                    const char* aFrameName)
 {
   mType = aFrameType;
   PL_strncpyz(mNameAbbrev, aFrameNameAbbrev, sizeof(mNameAbbrev));
--- a/layout/generic/nsFrameSelection.h
+++ b/layout/generic/nsFrameSelection.h
@@ -33,16 +33,18 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsFrameSelection_h___
 #define nsFrameSelection_h___
 
+#include "mozilla/Attributes.h"
+
 #include "nsIFrame.h"
 #include "nsIContent.h"
 #include "nsISelectionController.h"
 #include "nsITableLayout.h"
 #include "nsITableCellLayout.h"
 #include "nsIDOMElement.h"
 #include "nsGUIEvent.h"
 #include "nsIRange.h"
@@ -205,17 +207,17 @@ class nsTypedSelection;
 class nsIScrollableFrame;
 
 /**
  * Methods which are marked with *unsafe* should be handled with special care.
  * They may cause nsFrameSelection to be deleted, if strong pointer isn't used,
  * or they may cause other objects to be deleted.
  */
 
-class nsFrameSelection : public nsISupports {
+class nsFrameSelection MOZ_FINAL : public nsISupports {
 public:
   enum HINT { HINTLEFT = 0, HINTRIGHT = 1};  //end of this line or beginning of next
   /*interfaces for addref and release and queryinterface*/
   
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(nsFrameSelection)
 
   /** Init will initialize the frame selector with the necessary pres shell to 
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -839,25 +839,23 @@ nsHTMLScrollFrame::Reflow(nsPresContext*
   // sanity check: ensure that if we have no scrollbar, we treat it
   // as hidden.
   if (!mInner.mVScrollbarBox || mInner.mNeverHasVerticalScrollbar)
     state.mStyles.mVertical = NS_STYLE_OVERFLOW_HIDDEN;
   if (!mInner.mHScrollbarBox || mInner.mNeverHasHorizontalScrollbar)
     state.mStyles.mHorizontal = NS_STYLE_OVERFLOW_HIDDEN;
 
   //------------ Handle Incremental Reflow -----------------
-  bool reflowContents = true; // XXX Ignored
   bool reflowHScrollbar = true;
   bool reflowVScrollbar = true;
   bool reflowScrollCorner = true;
   if (!aReflowState.ShouldReflowAllKids()) {
     #define NEEDS_REFLOW(frame_) \
       ((frame_) && NS_SUBTREE_DIRTY(frame_))
 
-    reflowContents = NEEDS_REFLOW(mInner.mScrolledFrame);
     reflowHScrollbar = NEEDS_REFLOW(mInner.mHScrollbarBox);
     reflowVScrollbar = NEEDS_REFLOW(mInner.mVScrollbarBox);
     reflowScrollCorner = NEEDS_REFLOW(mInner.mScrollCornerBox) ||
                          NEEDS_REFLOW(mInner.mResizerBox);
 
     #undef NEEDS_REFLOW
   }
 
@@ -1633,17 +1631,18 @@ CanScrollWithBlitting(nsIFrame* aFrame)
 
   for (nsIFrame* f = aFrame; f;
        f = nsLayoutUtils::GetCrossDocParentFrame(f)) {
     if (nsSVGIntegrationUtils::UsingEffectsForFrame(f) ||
         f->IsFrameOfType(nsIFrame::eSVG)) {
       return false;
     }
     nsIScrollableFrame* sf = do_QueryFrame(f);
-    if (sf && nsLayoutUtils::HasNonZeroCorner(f->GetStyleBorder()->mBorderRadius))
+    if ((sf || f->IsFrameOfType(nsIFrame::eReplaced)) &&
+        nsLayoutUtils::HasNonZeroCorner(f->GetStyleBorder()->mBorderRadius))
       return false;
     if (nsLayoutUtils::IsPopup(f))
       break;
   }
   return true;
 }
 
 static void
--- a/layout/generic/nsImageFrame.cpp
+++ b/layout/generic/nsImageFrame.cpp
@@ -1679,17 +1679,17 @@ nsImageFrame::List(FILE* out, PRInt32 aI
 #ifdef DEBUG_waterson
   fprintf(out, " [parent=%p]", mParent);
 #endif
   if (HasView()) {
     fprintf(out, " [view=%p]", (void*)GetView());
   }
   fprintf(out, " {%d,%d,%d,%d}", mRect.x, mRect.y, mRect.width, mRect.height);
   if (0 != mState) {
-    fprintf(out, " [state=%016llx]", mState);
+    fprintf(out, " [state=%016llx]", (unsigned long long)mState);
   }
   fprintf(out, " [content=%p]", (void*)mContent);
   fprintf(out, " [sc=%p]", static_cast<void*>(mStyleContext));
 
   // output the img src url
   nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mContent);
   if (imageLoader) {
     nsCOMPtr<imgIRequest> currentRequest;
--- a/layout/generic/nsLineLayout.cpp
+++ b/layout/generic/nsLineLayout.cpp
@@ -1796,30 +1796,27 @@ nsLineLayout::VerticalAlignFrames(PerSpa
     // sanity check (see bug 105168, non-reproducible crashes from null frame)
     NS_ASSERTION(frame, "null frame in PerFrameData - something is very very bad");
     if (!frame) {
       return;
     }
 
     // Compute the logical height of the frame
     nscoord logicalHeight;
-    nscoord topLeading;
     PerSpanData* frameSpan = pfd->mSpan;
     if (frameSpan) {
       // For span frames the logical-height and top-leading was
       // pre-computed when the span was reflowed.
       logicalHeight = frameSpan->mLogicalHeight;
-      topLeading = frameSpan->mTopLeading;
     }
     else {
       // For other elements the logical height is the same as the
       // frames height plus its margins.
       logicalHeight = pfd->mBounds.height + pfd->mMargin.top +
         pfd->mMargin.bottom;
-      topLeading = 0;
     }
 
     // Get vertical-align property
     const nsStyleCoord& verticalAlign =
       frame->GetStyleTextReset()->mVerticalAlign;
 #ifdef NOISY_VERTICAL_ALIGN
     printf("  [frame]");
     nsFrame::ListTag(stdout, frame);
@@ -2037,17 +2034,17 @@ nsLineLayout::VerticalAlignFrames(PerSpa
         }
         if (yTop < minY) minY = yTop;
         if (yBottom > maxY) maxY = yBottom;
 #ifdef NOISY_VERTICAL_ALIGN
         printf("     [frame]raw: a=%d h=%d bp=%d,%d logical: h=%d leading=%d y=%d minY=%d maxY=%d\n",
                pfd->mAscent, pfd->mBounds.height,
                pfd->mBorderPadding.top, pfd->mBorderPadding.bottom,
                logicalHeight,
-               pfd->mSpan ? topLeading : 0,
+               frameSpan ? frameSpan->mTopLeading : 0,
                pfd->mBounds.y, minY, maxY);
 #endif
       }
       if (psd != mRootSpan) {
         frame->SetRect(pfd->mBounds);
       }
     }
     pfd = pfd->mNext;
--- a/layout/generic/nsObjectFrame.cpp
+++ b/layout/generic/nsObjectFrame.cpp
@@ -1415,16 +1415,18 @@ nsObjectFrame::PrintPlugin(nsRenderingCo
   ::DisposeGWorld(gWorld);
 
   nativeDraw.EndNativeDrawing();
 #elif defined(XP_UNIX)
 
   /* XXX this just flat-out doesn't work in a thebes world --
    * RenderEPS is a no-op.  So don't bother to do any work here.
    */
+  (void)window;
+  (void)npprint;
 
 #elif defined(XP_OS2)
   void *hps = GetPSFromRC(aRenderingContext);
   if (!hps)
     return;
 
   npprint.print.embedPrint.platformPrint = hps;
   npprint.print.embedPrint.window = window;
--- a/layout/generic/nsPlaceholderFrame.cpp
+++ b/layout/generic/nsPlaceholderFrame.cpp
@@ -255,17 +255,17 @@ nsPlaceholderFrame::List(FILE* out, PRIn
 #ifdef DEBUG_waterson
   fprintf(out, " [parent=%p]", static_cast<void*>(mParent));
 #endif
   if (HasView()) {
     fprintf(out, " [view=%p]", (void*)GetView());
   }
   fprintf(out, " {%d,%d,%d,%d}", mRect.x, mRect.y, mRect.width, mRect.height);
   if (0 != mState) {
-    fprintf(out, " [state=%016llx]", mState);
+    fprintf(out, " [state=%016llx]", (unsigned long long)mState);
   }
   nsIFrame* prevInFlow = GetPrevInFlow();
   nsIFrame* nextInFlow = GetNextInFlow();
   if (nsnull != prevInFlow) {
     fprintf(out, " prev-in-flow=%p", static_cast<void*>(prevInFlow));
   }
   if (nsnull != nextInFlow) {
     fprintf(out, " next-in-flow=%p", static_cast<void*>(nextInFlow));
--- a/layout/generic/nsSelection.cpp
+++ b/layout/generic/nsSelection.cpp
@@ -4686,20 +4686,18 @@ nsTypedSelection::StopAutoScrollTimer()
   return NS_OK; 
 }
 
 nsresult
 nsTypedSelection::DoAutoScroll(nsIFrame *aFrame, nsPoint& aPoint)
 {
   NS_PRECONDITION(aFrame, "Need a frame");
 
-  nsresult result = NS_OK;
-
   if (mAutoScrollTimer)
-    result = mAutoScrollTimer->Stop();
+    (void)mAutoScrollTimer->Stop();
 
   nsPresContext* presContext = aFrame->PresContext();
   nsRootPresContext* rootPC = presContext->GetRootPresContext();
   if (!rootPC)
     return NS_OK;
   nsIFrame* rootmostFrame = rootPC->PresShell()->FrameManager()->GetRootFrame();
   // Get the point relative to the root most frame because the scroll we are
   // about to do will change the coordinates of aFrame.
--- a/layout/generic/nsTextFrameThebes.cpp
+++ b/layout/generic/nsTextFrameThebes.cpp
@@ -1750,17 +1750,16 @@ static const nsTextFrameUtils::Compressi
 gfxTextRun*
 BuildTextRunsScanner::BuildTextRunForFrames(void* aTextBuffer)
 {
   gfxSkipCharsBuilder builder;
 
   const void* textPtr = aTextBuffer;
   bool anySmallcapsStyle = false;
   bool anyTextTransformStyle = false;
-  PRInt32 endOfLastContent = 0;
   PRUint32 textFlags = nsTextFrameUtils::TEXT_NO_BREAKS;
 
   if (mCurrentRunContextInfo & nsTextFrameUtils::INCOMING_WHITESPACE) {
     textFlags |= nsTextFrameUtils::TEXT_INCOMING_WHITESPACE;
   }
   if (mCurrentRunContextInfo & nsTextFrameUtils::INCOMING_ARABICCHAR) {
     textFlags |= gfxTextRunWordCache::TEXT_INCOMING_ARABICCHAR;
   }
@@ -1869,18 +1868,16 @@ BuildTextRunsScanner::BuildTextRunForFra
             bufStart, compression, &mNextRunContextInfo, &builder, &analysisFlags);
         aTextBuffer = end;
       }
     }
     textFlags |= analysisFlags;
 
     currentTransformedTextOffset =
       (static_cast<const PRUint8*>(aTextBuffer) - static_cast<const PRUint8*>(textPtr)) >> mDoubleByteText;
-
-    endOfLastContent = contentEnd;
   }
 
   // Check for out-of-memory in gfxSkipCharsBuilder
   if (!builder.IsOK()) {
     DestroyUserData(userDataToDestroy);
     return nsnull;
   }
 
@@ -7048,17 +7045,17 @@ nsTextFrame::Reflow(nsPresContext*      
 #ifdef ACCESSIBILITY
 /**
  * Notifies accessibility about text reflow. Used by nsTextFrame::ReflowText.
  */
 class NS_STACK_CLASS ReflowTextA11yNotifier
 {
 public:
   ReflowTextA11yNotifier(nsPresContext* aPresContext, nsIContent* aContent) :
-    mPresContext(aPresContext), mContent(aContent)
+    mContent(aContent), mPresContext(aPresContext)
   {
   }
   ~ReflowTextA11yNotifier()
   {
     nsAccessibilityService* accService = nsIPresShell::AccService();
     if (accService) {
       accService->UpdateText(mPresContext->PresShell(), mContent);
     }
@@ -7942,17 +7939,17 @@ nsTextFrame::List(FILE* out, PRInt32 aIn
     fprintf(out, " prev-continuation=%p", static_cast<void*>(prevContinuation));
   }
   if (nsnull != mNextContinuation) {
     fprintf(out, " next-continuation=%p", static_cast<void*>(mNextContinuation));
   }
 
   // Output the rect and state
   fprintf(out, " {%d,%d,%d,%d}", mRect.x, mRect.y, mRect.width, mRect.height);
-  fprintf(out, " [state=%016llx]", mState);
+  fprintf(out, " [state=%016llx]", (unsigned long long)mState);
   if (IsSelected()) {
     fprintf(out, " SELECTED");
   }
   fprintf(out, " [content=%p]", static_cast<void*>(mContent));
   if (HasOverflowAreas()) {
     nsRect overflowArea = GetVisualOverflowRect();
     fprintf(out, " [vis-overflow=%d,%d,%d,%d]",
             overflowArea.x, overflowArea.y,
--- a/layout/mathml/mathfont.properties
+++ b/layout/mathml/mathfont.properties
@@ -114,18 +114,18 @@ mathvariant.monospace = A\ud835\ude70B\u
 
 operator.\u0021.postfix = lspace:1 rspace:0 # !
 operator.\u0021\u0021.postfix = lspace:1 rspace:0 # !!
 operator.\u0021\u003D.infix = lspace:4 rspace:4 # !=
 operator.\u0025.infix = lspace:3 rspace:3 # percent sign
 operator.\u0026.postfix = lspace:0 rspace:0 # &amp;
 operator.\u0026\u0026.infix = lspace:4 rspace:4 # &amp;&amp;
 operator.\u0027.postfix = lspace:0 rspace:0 accent # '
-operator.\u0028.prefix = lspace:0 rspace:0 stretchy fence symmetric direction:vertical # (
-operator.\u0029.postfix = lspace:0 rspace:0 stretchy fence symmetric direction:vertical # )
+operator.\u0028.prefix = lspace:0 rspace:0 stretchy fence symmetric direction:vertical mirrorable # (
+operator.\u0029.postfix = lspace:0 rspace:0 stretchy fence symmetric direction:vertical mirrorable # )
 operator.\u002A.infix = lspace:3 rspace:3 # *
 operator.\u002A\u002A.infix = lspace:1 rspace:1 # **
 operator.\u002A\u003D.infix = lspace:4 rspace:4 # *=
 operator.\u002B.infix = lspace:4 rspace:4 # +
 operator.\u002B.prefix = lspace:0 rspace:1 # +
 operator.\u002B\u002B.postfix = lspace:0 rspace:0 # ++
 operator.\u002B\u003D.infix = lspace:4 rspace:4 # +=
 operator.\u002C.infix = lspace:0 rspace:3 separator # ,
@@ -147,35 +147,35 @@ operator.\u003C.infix = lspace:5 rspace:
 operator.\u003C\u003D.infix = lspace:5 rspace:5 # &lt;=
 operator.\u003C\u003E.infix = lspace:1 rspace:1 # &lt;>
 operator.\u003D.infix = lspace:5 rspace:5 # =
 operator.\u003D\u003D.infix = lspace:4 rspace:4 # ==
 operator.\u003E.infix = lspace:5 rspace:5 # >
 operator.\u003E\u003D.infix = lspace:5 rspace:5 # >=
 operator.\u003F.infix = lspace:1 rspace:1 # ?
 operator.\u0040.infix = lspace:1 rspace:1 # @
-operator.\u005B.prefix = lspace:0 rspace:0 stretchy fence symmetric direction:vertical # [
+operator.\u005B.prefix = lspace:0 rspace:0 stretchy fence symmetric direction:vertical mirrorable # [
 operator.\u005C.infix = lspace:0 rspace:0 # reverse solidus
-operator.\u005D.postfix = lspace:0 rspace:0 stretchy fence symmetric direction:vertical # ]
+operator.\u005D.postfix = lspace:0 rspace:0 stretchy fence symmetric direction:vertical mirrorable # ]
 operator.\u005E.postfix = lspace:0 rspace:0 stretchy accent direction:horizontal # &Hat; circumflex accent
 operator.\u005E.infix = lspace:1 rspace:1 direction:horizontal # ^
 operator.\u005F.postfix = lspace:0 rspace:0 stretchy accent direction:horizontal # _ low line
 operator.\u005F.infix = lspace:1 rspace:1 stretchy direction:horizontal # _ low line
 operator.\u0060.postfix = lspace:0 rspace:0 accent # &DiacriticalGrave;
-operator.\u007B.prefix = lspace:0 rspace:0 stretchy fence symmetric direction:vertical # {
+operator.\u007B.prefix = lspace:0 rspace:0 stretchy fence symmetric direction:vertical mirrorable # {
 operator.\u007C.infix = lspace:2 rspace:2 stretchy fence symmetric direction:vertical # &VerticalLine; |
 operator.\u007C.prefix = lspace:0 rspace:0 stretchy fence symmetric direction:vertical # |
 operator.\u007C.postfix = lspace:0 rspace:0 stretchy fence symmetric direction:vertical # |
 operator.\u007C\u007C.infix = lspace:2 rspace:2 stretchy fence symmetric direction:vertical # ||
 operator.\u007C\u007C.prefix = lspace:0 rspace:0 stretchy fence symmetric direction:vertical # multiple character operator: ||
 operator.\u007C\u007C.postfix = lspace:0 rspace:0 stretchy fence symmetric direction:vertical # multiple character operator: ||
 operator.\u007C\u007C\u007C.infix = lspace:2 rspace:2 stretchy fence symmetric direction:vertical # multiple character operator: |||
 operator.\u007C\u007C\u007C.prefix = lspace:0 rspace:0 stretchy fence symmetric direction:vertical # multiple character operator: |||
 operator.\u007C\u007C\u007C.postfix = lspace:0 rspace:0 stretchy fence symmetric direction:vertical # multiple character operator: |||
-operator.\u007D.postfix = lspace:0 rspace:0 stretchy fence symmetric direction:vertical # }
+operator.\u007D.postfix = lspace:0 rspace:0 stretchy fence symmetric direction:vertical mirrorable # }
 operator.\u007E.postfix = lspace:0 rspace:0 stretchy accent direction:horizontal # ~ tilde
 operator.\u00A8.postfix = lspace:0 rspace:0 accent # &DoubleDot;
 operator.\u00AC.prefix = lspace:2 rspace:1 # not sign
 operator.\u00AF.postfix = lspace:0 rspace:0 stretchy accent direction:horizontal # &OverBar;
 operator.\u00B0.postfix = lspace:0 rspace:0 # degree sign
 operator.\u00B1.infix = lspace:4 rspace:4 # &PlusMinus;
 operator.\u00B1.prefix = lspace:0 rspace:1 # &PlusMinus;
 operator.\u00B4.postfix = lspace:0 rspace:0 accent # &DiacriticalAcute;
@@ -336,49 +336,49 @@ operator.\u2208.infix = lspace:5 rspace:
 operator.\u2209.infix = lspace:5 rspace:5 # &NotElement;
 operator.\u220A.infix = lspace:5 rspace:5 # small element of
 operator.\u220B.infix = lspace:5 rspace:5 # &SuchThat; &ReverseElement;
 operator.\u220C.infix = lspace:5 rspace:5 # &NotReverseElement;
 operator.\u220D.infix = lspace:5 rspace:5 # small contains as member
 operator.\u220E.infix = lspace:3 rspace:3 # end of proof
 operator.\u220F.prefix = lspace:1 rspace:2 largeop movablelimits symmetric direction:vertical # &Product;
 operator.\u2210.prefix = lspace:1 rspace:2 largeop movablelimits symmetric direction:vertical # &Coproduct;
-operator.\u2211.prefix = lspace:1 rspace:2 largeop movablelimits symmetric direction:vertical # &Sum;
+operator.\u2211.prefix = lspace:1 rspace:2 largeop movablelimits symmetric direction:vertical mirrorable # &Sum;
 operator.\u2212.infix = lspace:4 rspace:4 # official Unicode minus sign
 operator.\u2212.prefix = lspace:0 rspace:1 # official Unicode minus sign
 operator.\u2213.infix = lspace:4 rspace:4 # &MinusPlus;
 operator.\u2213.prefix = lspace:0 rspace:1 # &MinusPlus;
 operator.\u2214.infix = lspace:4 rspace:4 # dot plus
 operator.\u2215.infix = lspace:4 rspace:4 stretchy direction:vertical # division slash
 operator.\u2216.infix = lspace:4 rspace:4 direction:vertical # set minus
 operator.\u2217.infix = lspace:4 rspace:4 # asterisk operator
 operator.\u2218.infix = lspace:4 rspace:4 # &SmallCircle;
 operator.\u2219.infix = lspace:4 rspace:4 # bullet operator
-operator.\u221A.prefix = lspace:1 rspace:1 stretchy direction:vertical # &Sqrt;
+operator.\u221A.prefix = lspace:1 rspace:1 stretchy direction:vertical mirrorable # &Sqrt;
 operator.\u221B.prefix = lspace:1 rspace:1 # cube root
 operator.\u221C.prefix = lspace:1 rspace:1 # fourth root
 operator.\u221D.infix = lspace:5 rspace:5 # &Proportional;
 operator.\u221F.infix = lspace:5 rspace:5 # right angle
 operator.\u2220.prefix = lspace:0 rspace:0 # angle
 operator.\u2221.prefix = lspace:0 rspace:0 # measured angle
 operator.\u2222.prefix = lspace:0 rspace:0 # spherical angle
 operator.\u2223.infix = lspace:5 rspace:5 direction:vertical # divides
 operator.\u2224.infix = lspace:5 rspace:5 # &NotVerticalBar;
 operator.\u2225.infix = lspace:5 rspace:5 direction:vertical # parallel to
 operator.\u2226.infix = lspace:5 rspace:5 # &NotDoubleVerticalBar;
 operator.\u2227.infix = lspace:4 rspace:4 # &wedge;
 operator.\u2228.infix = lspace:4 rspace:4 # &vee;
 operator.\u2229.infix = lspace:4 rspace:4 # &cap;
 operator.\u222A.infix = lspace:4 rspace:4 # &cup;
-operator.\u222B.prefix = lspace:0 rspace:1 largeop symmetric direction:vertical integral # &Integral;
-operator.\u222C.prefix = lspace:0 rspace:1 largeop symmetric direction:vertical integral # double integral
-operator.\u222D.prefix = lspace:0 rspace:1 largeop symmetric direction:vertical integral # triple integral
-operator.\u222E.prefix = lspace:0 rspace:1 largeop symmetric direction:vertical integral # &ContourIntegral;
-operator.\u222F.prefix = lspace:0 rspace:1 largeop symmetric direction:vertical integral # &DoubleContourIntegral;
-operator.\u2230.prefix = lspace:0 rspace:1 largeop symmetric direction:vertical integral # volume integral
+operator.\u222B.prefix = lspace:0 rspace:1 largeop symmetric direction:vertical integral mirrorable # &Integral;
+operator.\u222C.prefix = lspace:0 rspace:1 largeop symmetric direction:vertical integral mirrorable # double integral
+operator.\u222D.prefix = lspace:0 rspace:1 largeop symmetric direction:vertical integral mirrorable # triple integral
+operator.\u222E.prefix = lspace:0 rspace:1 largeop symmetric direction:vertical integral mirrorable # &ContourIntegral;
+operator.\u222F.prefix = lspace:0 rspace:1 largeop symmetric direction:vertical integral mirrorable # &DoubleContourIntegral;
+operator.\u2230.prefix = lspace:0 rspace:1 largeop symmetric direction:vertical integral mirrorable # volume integral
 operator.\u2231.prefix = lspace:0 rspace:1 largeop symmetric direction:vertical integral # clockwise integral
 operator.\u2232.prefix = lspace:0 rspace:1 largeop symmetric direction:vertical integral # &ClockwiseContourIntegral;
 operator.\u2233.prefix = lspace:0 rspace:1 largeop symmetric direction:vertical integral # &CounterClockwiseContourIntegral;
 operator.\u2234.infix = lspace:5 rspace:5 # &Therefore;
 operator.\u2235.infix = lspace:5 rspace:5 # &Because;
 operator.\u2236.infix = lspace:5 rspace:5 # ratio
 operator.\u2237.infix = lspace:5 rspace:5 # &Colon; &Proportion;
 operator.\u2238.infix = lspace:4 rspace:4 # dot minus
@@ -933,34 +933,34 @@ operator.\u2A02.prefix = lspace:1 rspace
 operator.\u2A03.prefix = lspace:1 rspace:2 largeop movablelimits symmetric # n-ary union operator with dot
 operator.\u2A04.prefix = lspace:1 rspace:2 largeop movablelimits symmetric direction:vertical # &biguplus;
 operator.\u2A05.prefix = lspace:1 rspace:2 largeop movablelimits symmetric # n-ary square intersection operator
 operator.\u2A06.prefix = lspace:1 rspace:2 largeop movablelimits symmetric direction:vertical # &bigsqcup;
 operator.\u2A07.prefix = lspace:1 rspace:2 largeop movablelimits symmetric # two logical and operator
 operator.\u2A08.prefix = lspace:1 rspace:2 largeop movablelimits symmetric # two logical or operator
 operator.\u2A09.prefix = lspace:1 rspace:2 largeop movablelimits symmetric # n-ary times operator
 operator.\u2A0A.prefix = lspace:1 rspace:2 largeop movablelimits symmetric # modulo two sum
-operator.\u2A0B.prefix = lspace:1 rspace:2 largeop symmetric direction:vertical integral # summation with integral
-operator.\u2A0C.prefix = lspace:0 rspace:1 largeop symmetric direction:vertical integral # quadruple integral operator
-operator.\u2A0D.prefix = lspace:1 rspace:2 largeop symmetric direction:vertical integral # finite part integral
-operator.\u2A0E.prefix = lspace:1 rspace:2 largeop symmetric direction:vertical integral # integral with double stroke
-operator.\u2A0F.prefix = lspace:1 rspace:2 largeop symmetric direction:vertical integral # integral average with slash
-operator.\u2A10.prefix = lspace:1 rspace:2 largeop movablelimits symmetric direction:vertical integral # circulation function
+operator.\u2A0B.prefix = lspace:1 rspace:2 largeop symmetric direction:vertical integral mirrorable # summation with integral
+operator.\u2A0C.prefix = lspace:0 rspace:1 largeop symmetric direction:vertical integral mirrorable # quadruple integral operator
+operator.\u2A0D.prefix = lspace:1 rspace:2 largeop symmetric direction:vertical integral mirrorable # finite part integral
+operator.\u2A0E.prefix = lspace:1 rspace:2 largeop symmetric direction:vertical integral mirrorable # integral with double stroke
+operator.\u2A0F.prefix = lspace:1 rspace:2 largeop symmetric direction:vertical integral mirrorable # integral average with slash
+operator.\u2A10.prefix = lspace:1 rspace:2 largeop movablelimits symmetric direction:vertical integral mirrorable # circulation function
 operator.\u2A11.prefix = lspace:1 rspace:2 largeop movablelimits symmetric direction:vertical integral # anticlockwise integration
-operator.\u2A12.prefix = lspace:1 rspace:2 largeop movablelimits symmetric direction:vertical integral # line integration with rectangular path around pole
-operator.\u2A13.prefix = lspace:1 rspace:2 largeop movablelimits symmetric direction:vertical integral # line integration with semicircular path around pole
-operator.\u2A14.prefix = lspace:1 rspace:2 largeop movablelimits symmetric direction:vertical integral # line integration not including the pole
-operator.\u2A15.prefix = lspace:1 rspace:2 largeop symmetric direction:vertical integral # integral around a point operator
-operator.\u2A16.prefix = lspace:1 rspace:2 largeop symmetric direction:vertical integral # quaternion integral operator
+operator.\u2A12.prefix = lspace:1 rspace:2 largeop movablelimits symmetric direction:vertical integral mirrorable # line integration with rectangular path around pole
+operator.\u2A13.prefix = lspace:1 rspace:2 largeop movablelimits symmetric direction:vertical integral mirrorable # line integration with semicircular path around pole
+operator.\u2A14.prefix = lspace:1 rspace:2 largeop movablelimits symmetric direction:vertical integral mirrorable # line integration not including the pole
+operator.\u2A15.prefix = lspace:1 rspace:2 largeop symmetric direction:vertical integral mirrorable # integral around a point operator
+operator.\u2A16.prefix = lspace:1 rspace:2 largeop symmetric direction:vertical integral mirrorable # quaternion integral operator
 operator.\u2A17.prefix = lspace:1 rspace:2 largeop symmetric direction:vertical integral # integral with leftwards arrow with hook
-operator.\u2A18.prefix = lspace:1 rspace:2 largeop symmetric direction:vertical integral # integral with times sign
-operator.\u2A19.prefix = lspace:1 rspace:2 largeop symmetric direction:vertical integral # integral with intersection
-operator.\u2A1A.prefix = lspace:1 rspace:2 largeop symmetric direction:vertical integral # integral with union
-operator.\u2A1B.prefix = lspace:1 rspace:2 largeop symmetric direction:vertical integral # integral with overbar
-operator.\u2A1C.prefix = lspace:1 rspace:2 largeop symmetric direction:vertical integral # integral with underbar
+operator.\u2A18.prefix = lspace:1 rspace:2 largeop symmetric direction:vertical integral mirrorable # integral with times sign
+operator.\u2A19.prefix = lspace:1 rspace:2 largeop symmetric direction:vertical integral mirrorable # integral with intersection
+operator.\u2A1A.prefix = lspace:1 rspace:2 largeop symmetric direction:vertical integral mirrorable # integral with union
+operator.\u2A1B.prefix = lspace:1 rspace:2 largeop symmetric direction:vertical integral mirrorable # integral with overbar
+operator.\u2A1C.prefix = lspace:1 rspace:2 largeop symmetric direction:vertical integral mirrorable # integral with underbar
 operator.\u2A1D.infix = lspace:3 rspace:3 # join
 operator.\u2A1E.infix = lspace:3 rspace:3 # large left triangle operator
 operator.\u2A1F.infix = lspace:3 rspace:3 # z notation schema composition
 operator.\u2A20.infix = lspace:3 rspace:3 # z notation schema piping
 operator.\u2A21.infix = lspace:3 rspace:3 # z notation schema projection
 operator.\u2A22.infix = lspace:4 rspace:4 # plus sign with small circle above
 operator.\u2A23.infix = lspace:4 rspace:4 # plus sign with circumflex accent above
 operator.\u2A24.infix = lspace:4 rspace:4 # plus sign with tilde above
--- a/layout/mathml/mathml.css
+++ b/layout/mathml/mathml.css
@@ -462,8 +462,22 @@ semantics > :not(:first-child) {
 /* all other cases can be described using regular CSS, so we do it this way because it's
    more efficient and less code */
 mroot > :not(:first-child) { -moz-script-level:+2; }
 
 msub > :not(:first-child),
 msup > :not(:first-child),
 msubsup > :not(:first-child),
 mmultiscripts > :not(:first-child) { -moz-script-level:+1; }
+
+/*****************************************/
+/* Controlling directionality            */
+/*****************************************/
+
+math[dir="rtl"], mstyle[dir="rtl"], mrow[dir="rtl"],
+mi[dir="rtl"], mn[dir="rtl"], mo[dir="rtl"], mtext[dir="rtl"], ms[dir="rtl"] {
+    direction: rtl;
+}
+
+math[dir="ltr"], mstyle[dir="ltr"], mrow[dir="ltr"],
+mi[dir="ltr"], mn[dir="ltr"], mo[dir="ltr"], mtext[dir="ltr"], ms[dir="ltr"] {
+    direction: ltr;
+}
--- a/layout/mathml/nsIMathMLFrame.h
+++ b/layout/mathml/nsIMathMLFrame.h
@@ -250,25 +250,25 @@ struct nsEmbellishData {
 
   // stretchy direction that the nsMathMLChar owned by the core <mo> supports
   nsStretchDirection direction;
 
   // spacing that may come from <mo> depending on its 'form'. Since
   // the 'form' may also depend on the position of the outermost
   // embellished ancestor, the set up of these values may require
   // looking up the position of our ancestors.
-  nscoord leftSpace;
-  nscoord rightSpace;
+  nscoord leadingSpace;
+  nscoord trailingSpace;
 
   nsEmbellishData() {
     flags = 0;
     coreFrame = nsnull;
     direction = NS_STRETCH_DIRECTION_UNSUPPORTED;
-    leftSpace = 0;
-    rightSpace = 0;
+    leadingSpace = 0;
+    trailingSpace = 0;
   }
 };
 
 // struct used by a container frame to modulate its presentation.
 // By convention, the data that we keep in this struct can change depending
 // on any of our ancestors and/or descendants. If a data can be resolved
 // solely from the embellished hierarchy, and it remains immutable once
 // resolved, we put it in |nsEmbellishData|. If it can be affected by other
@@ -325,16 +325,19 @@ struct nsPresentationData {
 // This bit is set if the frame has the explicit attribute
 // displaystyle="true" or "false". It is only relevant to <mstyle> and <mtable>
 // because they are the only tags where the attribute is allowed by the spec.
 #define NS_MATHML_EXPLICIT_DISPLAYSTYLE               0x00000020U
 
 // This bit is set if the frame is "space-like", as defined by the spec.
 #define NS_MATHML_SPACE_LIKE                          0x00000040U
 
+// This bit is set if the directionality of the frame is right-to-left
+#define NS_MATHML_RTL                                 0x00000080U
+
 // This bit is set when the frame cannot be formatted due to an
 // error (e.g., invalid markup such as a <msup> without an overscript).
 // When set, a visual feedback will be provided to the user.
 #define NS_MATHML_ERROR                               0x80000000U
 
 // a bit used for debug
 #define NS_MATHML_STRETCH_DONE                        0x20000000U
 
@@ -359,16 +362,19 @@ struct nsPresentationData {
   (NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY == ((_flags) & NS_MATHML_STRETCH_ALL_CHILDREN_HORIZONTALLY))
 
 #define NS_MATHML_HAS_EXPLICIT_DISPLAYSTYLE(_flags) \
   (NS_MATHML_EXPLICIT_DISPLAYSTYLE == ((_flags) & NS_MATHML_EXPLICIT_DISPLAYSTYLE))
 
 #define NS_MATHML_IS_SPACE_LIKE(_flags) \
   (NS_MATHML_SPACE_LIKE == ((_flags) & NS_MATHML_SPACE_LIKE))
 
+#define NS_MATHML_IS_RTL(_flags) \
+  (NS_MATHML_RTL == ((_flags) & NS_MATHML_RTL))
+
 #define NS_MATHML_HAS_ERROR(_flags) \
   (NS_MATHML_ERROR == ((_flags) & NS_MATHML_ERROR))
 
 #define NS_MATHML_STRETCH_WAS_DONE(_flags) \
   (NS_MATHML_STRETCH_DONE == ((_flags) & NS_MATHML_STRETCH_DONE))
 
 #define NS_MATHML_PAINT_BOUNDING_METRICS(_flags) \
   (NS_MATHML_SHOW_BOUNDING_METRICS == ((_flags) & NS_MATHML_SHOW_BOUNDING_METRICS))
--- a/layout/mathml/nsMathMLChar.cpp
+++ b/layout/mathml/nsMathMLChar.cpp
@@ -1698,24 +1698,26 @@ nsMathMLChar::StretchInternal(nsPresCont
 }
 
 nsresult
 nsMathMLChar::Stretch(nsPresContext*           aPresContext,
                       nsRenderingContext&     aRenderingContext,
                       nsStretchDirection       aStretchDirection,
                       const nsBoundingMetrics& aContainerSize,
                       nsBoundingMetrics&       aDesiredStretchSize,
-                      PRUint32                 aStretchHint)
+                      PRUint32                 aStretchHint,
+                      bool                     aRTL)
 {
   NS_ASSERTION(!(aStretchHint &
                  ~(NS_STRETCH_VARIABLE_MASK | NS_STRETCH_LARGEOP |
                    NS_STRETCH_INTEGRAL)),
                "Unexpected stretch flags");
 
   mDrawNormal = true;
+  mMirrored = aRTL && nsMathMLOperators::IsMirrorableOperator(mData);
   mScaleY = mScaleX = 1.0;
   mDirection = aStretchDirection;
   nsresult rv =
     StretchInternal(aPresContext, aRenderingContext, mDirection,
                     aContainerSize, aDesiredStretchSize, aStretchHint);
 
   // Record the metrics
   mBoundingMetrics = aDesiredStretchSize;
@@ -1791,20 +1793,21 @@ nsMathMLChar::ComposeChildren(nsPresCont
   }
   nscoord dx = 0, dy = 0;
   for (i = 0, child = mSibling; child; child = child->mSibling, i++) {
     // child chars should just inherit our values - which may change between calls...
     child->mData = mData;
     child->mDirection = mDirection;
     child->mStyleContext = mStyleContext;
     child->mGlyphTable = aGlyphTable; // the child is associated to this table
+    child->mMirrored = mMirrored;
     // there goes the Stretch() ...
     nsBoundingMetrics childSize;
     nsresult rv = child->Stretch(aPresContext, aRenderingContext, mDirection,
-                                 splitSize, childSize, aStretchHint);
+                                 splitSize, childSize, aStretchHint, mMirrored);
     // check if something went wrong or the child couldn't fit in the alloted space
     if (NS_FAILED(rv) || (NS_STRETCH_DIRECTION_UNSUPPORTED == child->mDirection)) {
       delete mSibling; // don't leave a dangling list behind ...
       mSibling = nsnull;
       return NS_ERROR_FAILURE;
     }
     child->SetRect(nsRect(dx, dy, childSize.width, childSize.ascent+childSize.descent));
     if (0 == i)
@@ -2023,18 +2026,23 @@ nsMathMLChar::Display(nsDisplayListBuild
         nsDisplayMathMLCharForeground(aBuilder, aForFrame, this,
                                       aSelectedRect && !aSelectedRect->IsEmpty()));
 }
 
 void
 nsMathMLChar::ApplyTransforms(nsRenderingContext& aRenderingContext, nsRect &r)
 {
   // apply the transforms
-  aRenderingContext.Translate(r.TopLeft());
-  aRenderingContext.Scale(mScaleX, mScaleY);
+  if (mMirrored) {
+    aRenderingContext.Translate(r.TopRight());
+    aRenderingContext.Scale(-mScaleX, mScaleY);
+  } else {
+    aRenderingContext.Translate(r.TopLeft());
+    aRenderingContext.Scale(mScaleX, mScaleY);
+  }
 
   // update the bounding rectangle.
   r.x = r.y = 0;
   r.width /= mScaleX;
   r.height /= mScaleY;
 }
 
 void
--- a/layout/mathml/nsMathMLChar.h
+++ b/layout/mathml/nsMathMLChar.h
@@ -107,16 +107,17 @@ public:
   nsMathMLChar(nsMathMLChar* aParent = nsnull) {
     MOZ_COUNT_CTOR(nsMathMLChar);
     mStyleContext = nsnull;
     mSibling = nsnull;
     mParent = aParent;
     mUnscaledAscent = 0;
     mScaleX = mScaleY = 1.0;
     mDrawNormal = true;
+    mMirrored = false;
   }
 
   ~nsMathMLChar() { // not a virtual destructor: this class is not intended to be subclassed
     MOZ_COUNT_DTOR(nsMathMLChar);
     // there is only one style context owned by the "root" char
     // and it may be used by child chars as well
     if (!mParent && mStyleContext) { // only the "root" need to release it
       mStyleContext->Release();
@@ -141,17 +142,18 @@ public:
   // @param aContainerSize - IN - suggested size for the stretched char
   // @param aDesiredStretchSize - OUT - the size that the char wants
   nsresult
   Stretch(nsPresContext*           aPresContext,
           nsRenderingContext&     aRenderingContext,
           nsStretchDirection       aStretchDirection,
           const nsBoundingMetrics& aContainerSize,
           nsBoundingMetrics&       aDesiredStretchSize,
-          PRUint32                 aStretchHint = NS_STRETCH_NORMAL);
+          PRUint32                 aStretchHint,
+          bool                     aRTL);
 
   void
   SetData(nsPresContext* aPresContext,
           nsString&       aData);
 
   void
   GetData(nsString& aData) {
     aData = mData;
@@ -253,16 +255,18 @@ private:
   // from the family in the nsStyleContext.
   nsString           mFamily;
   // mUnscaledAscent is the actual ascent of the char.
   nscoord            mUnscaledAscent;
   // mScaleX, mScaleY are the factors by which we scale the char.
   float              mScaleX, mScaleY;
   // mDrawNormal indicates whether we use special glyphs or not.
   bool               mDrawNormal;
+  // mMirrored indicates whether the character is mirrored. 
+  bool               mMirrored;
 
   class StretchEnumContext;
   friend class StretchEnumContext;
 
   // helper methods
   nsresult
   StretchInternal(nsPresContext*           aPresContext,
                   nsRenderingContext&     aRenderingContext,
--- a/layout/mathml/nsMathMLContainerFrame.cpp
+++ b/layout/mathml/nsMathMLContainerFrame.cpp
@@ -440,21 +440,23 @@ nsMathMLContainerFrame::Stretch(nsRender
         // (need to test coreFrame since <mfrac> resets other things)
         if (parentData.coreFrame != mEmbellishData.coreFrame) {
           // (we fetch values from the core since they may use units that depend
           // on style data, and style changes could have occurred in the core since
           // our last visit there)
           nsEmbellishData coreData;
           GetEmbellishDataFrom(mEmbellishData.coreFrame, coreData);
 
-          mBoundingMetrics.width += coreData.leftSpace + coreData.rightSpace;
+          mBoundingMetrics.width +=
+            coreData.leadingSpace + coreData.trailingSpace;
           aDesiredStretchSize.width = mBoundingMetrics.width;
           aDesiredStretchSize.mBoundingMetrics.width = mBoundingMetrics.width;
 
-          nscoord dx = coreData.leftSpace;
+          nscoord dx = (NS_MATHML_IS_RTL(mPresentationData.flags) ?
+                        coreData.trailingSpace : coreData.leadingSpace);
           if (dx != 0) {
             mBoundingMetrics.leftBearing += dx;
             mBoundingMetrics.rightBearing += dx;
             aDesiredStretchSize.mBoundingMetrics.leftBearing += dx;
             aDesiredStretchSize.mBoundingMetrics.rightBearing += dx;
 
             nsIFrame* childFrame = mFrames.FirstChild();
             while (childFrame) {
@@ -1188,38 +1190,44 @@ static nscoord GetThinSpace(const nsStyl
 {
   return NSToCoordRound(float(aStyleFont->mFont.size)*float(3) / float(18));
 }
 
 class nsMathMLContainerFrame::RowChildFrameIterator {
 public:
   explicit RowChildFrameIterator(nsMathMLContainerFrame* aParentFrame) :
     mParentFrame(aParentFrame),
-    mChildFrame(aParentFrame->mFrames.FirstChild()),
     mX(0),
     mCarrySpace(0),
-    mFromFrameType(eMathMLFrameType_UNKNOWN)
+    mFromFrameType(eMathMLFrameType_UNKNOWN),
+    mRTL(NS_MATHML_IS_RTL(aParentFrame->mPresentationData.flags))
   {
+    if (!mRTL) {
+      mChildFrame = aParentFrame->mFrames.FirstChild();
+    } else {
+      mChildFrame = aParentFrame->mFrames.LastChild();
+    }
+
     if (!mChildFrame)
       return;
 
     InitMetricsForChild();
-    // Remove left correction in <msqrt> because the sqrt glyph itself is
-    // there first.
-    if (mParentFrame->GetContent()->Tag() == nsGkAtoms::msqrt_) {
-      mX = 0;
-    }
   }
 
   RowChildFrameIterator& operator++()
   {
     // add child size + italic correction
     mX += mSize.mBoundingMetrics.width + mItalicCorrection;
 
-    mChildFrame = mChildFrame->GetNextSibling();
+    if (!mRTL) {
+      mChildFrame = mChildFrame->GetNextSibling();
+    } else {
+      mChildFrame = mChildFrame->GetPrevSibling();
+    }
+
     if (!mChildFrame)
       return *this;
 
     eMathMLFrameType prevFrameType = mChildFrameType;
     InitMetricsForChild();
 
     // add inter frame spacing
     const nsStyleFont* font = mParentFrame->GetStyleFont();
@@ -1246,26 +1254,39 @@ private:
   nsHTMLReflowMetrics mSize;
   nscoord mX;
 
   nscoord mItalicCorrection;
   eMathMLFrameType mChildFrameType;
   PRInt32 mCarrySpace;
   eMathMLFrameType mFromFrameType;
 
+  bool mRTL;
+
   void InitMetricsForChild()
   {
     GetReflowAndBoundingMetricsFor(mChildFrame, mSize, mSize.mBoundingMetrics,
                                    &mChildFrameType);
-    nscoord leftCorrection;
-    GetItalicCorrection(mSize.mBoundingMetrics, leftCorrection,
-                        mItalicCorrection);
+    nscoord leftCorrection, rightCorrection;
+    GetItalicCorrection(mSize.mBoundingMetrics,
+                        leftCorrection, rightCorrection);
+    if (!mChildFrame->GetPrevSibling() &&
+        mParentFrame->GetContent()->Tag() == nsGkAtoms::msqrt_) {
+      // Remove leading correction in <msqrt> because the sqrt glyph itself is
+      // there first.
+      if (!mRTL) {
+        leftCorrection = 0;
+      } else {
+        rightCorrection = 0;
+      }
+    }
     // add left correction -- this fixes the problem of the italic 'f'
     // e.g., <mo>q</mo> <mi>f</mi> <mo>I</mo> 
     mX += leftCorrection;
+    mItalicCorrection = rightCorrection;
   }
 };
 
 /* virtual */ nsresult
 nsMathMLContainerFrame::Place(nsRenderingContext& aRenderingContext,
                               bool                 aPlaceOrigin,
                               nsHTMLReflowMetrics& aDesiredSize)
 {
@@ -1504,18 +1525,18 @@ nsMathMLContainerFrame::TransmitAutomati
   }
 
   if (childFrame || !embellishedOpFound) {
     // The element is not embellished operator
     mPresentationData.baseFrame = nsnull;
     mEmbellishData.flags = 0;
     mEmbellishData.coreFrame = nsnull;
     mEmbellishData.direction = NS_STRETCH_DIRECTION_UNSUPPORTED;
-    mEmbellishData.leftSpace = 0;
-    mEmbellishData.rightSpace = 0;
+    mEmbellishData.leadingSpace = 0;
+    mEmbellishData.trailingSpace = 0;
   }
 
   if (childFrame || embellishedOpFound) {
     // The element is not space-like
     mPresentationData.flags &= ~NS_MATHML_SPACE_LIKE;
   }
 
   return NS_OK;
--- a/layout/mathml/nsMathMLContainerFrame.h
+++ b/layout/mathml/nsMathMLContainerFrame.h
@@ -188,16 +188,24 @@ public:
   //        to re-layout its children using ReLayoutChildren(mParent);
   //        Therefore, there is an overhead here in that our siblings are re-laid
   //        too (e.g., this happens with <mstyle>, <munder>, <mover>, <munderover>). 
   NS_IMETHOD
   AttributeChanged(PRInt32         aNameSpaceID,
                    nsIAtom*        aAttribute,
                    PRInt32         aModType);
 
+  // helper function to apply mirroring to a horizontal coordinate, if needed.
+  nscoord
+  MirrorIfRTL(nscoord aParentWidth, nscoord aChildWidth, nscoord aChildLeading)
+  {
+    return (NS_MATHML_IS_RTL(mPresentationData.flags) ?
+            aParentWidth - aChildWidth - aChildLeading : aChildLeading);
+  }
+
   // --------------------------------------------------------------------------
   // Additional methods 
 
 protected:
   /* Place :
    * This method is used to measure or position child frames and other
    * elements.  It may be called any number of times with aPlaceOrigin
    * false to measure, and the final call of the Reflow process before
--- a/layout/mathml/nsMathMLFrame.cpp
+++ b/layout/mathml/nsMathMLFrame.cpp
@@ -16,16 +16,17 @@
  *
  * The Initial Developer of the Original Code is
  * The University Of Queensland.
  * Portions created by the Initial Developer are Copyright (C) 1999
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Roger B. Sidje <rbs@maths.uq.edu.au>
+ *   Frederic Wang <fred.wang@free.fr>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either of the GNU General Public License Version 2 or later (the "GPL"),
  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -83,48 +84,86 @@ nsMathMLFrame::FindAttrDisplaystyle(nsIC
   case 1:
     aPresentationData.flags |= NS_MATHML_DISPLAYSTYLE;
     aPresentationData.flags |= NS_MATHML_EXPLICIT_DISPLAYSTYLE;
     break;
   }
   // no reset if the attr isn't found. so be sure to call it on inherited flags
 }
 
+// snippet of code used by the tags where the dir attribute is allowed.
+/* static */ void
+nsMathMLFrame::FindAttrDirectionality(nsIContent*         aContent,
+                                      nsPresentationData& aPresentationData)
+{
+  NS_ASSERTION(aContent->Tag() == nsGkAtoms::math ||
+               aContent->Tag() == nsGkAtoms::mrow_ ||
+               aContent->Tag() == nsGkAtoms::mstyle_ ||
+               aContent->Tag() == nsGkAtoms::mi_ ||
+               aContent->Tag() == nsGkAtoms::mn_ ||
+               aContent->Tag() == nsGkAtoms::mo_ ||
+               aContent->Tag() == nsGkAtoms::mtext_ ||
+               aContent->Tag() == nsGkAtoms::ms_, "bad caller");
+
+  static nsIContent::AttrValuesArray strings[] =
+    {&nsGkAtoms::ltr, &nsGkAtoms::rtl, nsnull};
+
+  // see if the explicit dir attribute is there
+  switch (aContent->FindAttrValueIn(kNameSpaceID_None,
+                                    nsGkAtoms::dir, strings, eCaseMatters))
+    {
+    case 0:
+      aPresentationData.flags &= ~NS_MATHML_RTL;
+      break;
+    case 1:
+      aPresentationData.flags |= NS_MATHML_RTL;
+      break;
+    }
+  // no reset if the attr isn't found. so be sure to call it on inherited flags
+}
+
 NS_IMETHODIMP
 nsMathMLFrame::InheritAutomaticData(nsIFrame* aParent) 
 {
   mEmbellishData.flags = 0;
   mEmbellishData.coreFrame = nsnull;
   mEmbellishData.direction = NS_STRETCH_DIRECTION_UNSUPPORTED;
-  mEmbellishData.leftSpace = 0;
-  mEmbellishData.rightSpace = 0;
+  mEmbellishData.leadingSpace = 0;
+  mEmbellishData.trailingSpace = 0;
 
   mPresentationData.flags = 0;
   mPresentationData.baseFrame = nsnull;
   mPresentationData.mstyle = nsnull;
 
   // by default, just inherit the display of our parent
   nsPresentationData parentData;
   GetPresentationDataFrom(aParent, parentData);
   mPresentationData.mstyle = parentData.mstyle;
   if (NS_MATHML_IS_DISPLAYSTYLE(parentData.flags)) {
     mPresentationData.flags |= NS_MATHML_DISPLAYSTYLE;
   }
+  if (NS_MATHML_IS_RTL(parentData.flags)) {
+    mPresentationData.flags |= NS_MATHML_RTL;
+  }
 
 #if defined(NS_DEBUG) && defined(SHOW_BOUNDING_BOX)
   mPresentationData.flags |= NS_MATHML_SHOW_BOUNDING_METRICS;
 #endif
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsMathMLFrame::UpdatePresentationData(PRUint32        aFlagsValues,
                                       PRUint32        aWhichFlags)
 {
+  NS_ASSERTION(NS_MATHML_IS_DISPLAYSTYLE(aWhichFlags) ||
+               NS_MATHML_IS_COMPRESSED(aWhichFlags),
+               "aWhichFlags should only be displaystyle or compression flag"); 
+
   // update flags that are relevant to this call
   if (NS_MATHML_IS_DISPLAYSTYLE(aWhichFlags)) {
     // updating the displaystyle flag is allowed
     if (NS_MATHML_IS_DISPLAYSTYLE(aFlagsValues)) {
       mPresentationData.flags |= NS_MATHML_DISPLAYSTYLE;
     }
     else {
       mPresentationData.flags &= ~NS_MATHML_DISPLAYSTYLE;
@@ -167,18 +206,18 @@ nsMathMLFrame::ResolveMathMLCharStyle(ns
 /* static */ void
 nsMathMLFrame::GetEmbellishDataFrom(nsIFrame*        aFrame,
                                     nsEmbellishData& aEmbellishData)
 {
   // initialize OUT params
   aEmbellishData.flags = 0;
   aEmbellishData.coreFrame = nsnull;
   aEmbellishData.direction = NS_STRETCH_DIRECTION_UNSUPPORTED;
-  aEmbellishData.leftSpace = 0;
-  aEmbellishData.rightSpace = 0;
+  aEmbellishData.leadingSpace = 0;
+  aEmbellishData.trailingSpace = 0;
 
   if (aFrame && aFrame->IsFrameOfType(nsIFrame::eMathML)) {
     nsIMathMLFrame* mathMLFrame = do_QueryFrame(aFrame);
     if (mathMLFrame) {
       mathMLFrame->GetEmbellishData(aEmbellishData);
     }
   }
 }
@@ -216,16 +255,17 @@ nsMathMLFrame::GetPresentationDataFrom(n
       break;
 
     if (content->Tag() == nsGkAtoms::math) {
       const nsStyleDisplay* display = frame->GetStyleDisplay();
       if (display->mDisplay == NS_STYLE_DISPLAY_BLOCK) {
         aPresentationData.flags |= NS_MATHML_DISPLAYSTYLE;
       }
       FindAttrDisplaystyle(content, aPresentationData);
+      FindAttrDirectionality(content, aPresentationData);
       aPresentationData.mstyle = frame->GetFirstContinuation();
       break;
     }
     frame = frame->GetParent();
   }
   NS_WARN_IF_FALSE(frame && frame->GetContent(),
                    "bad MathML markup - could not find the top <math> element");
 }
--- a/layout/mathml/nsMathMLFrame.h
+++ b/layout/mathml/nsMathMLFrame.h
@@ -16,16 +16,17 @@
  *
  * The Initial Developer of the Original Code is
  * The University Of Queensland.
  * Portions created by the Initial Developer are Copyright (C) 1999
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Roger B. Sidje <rbs@maths.uq.edu.au>
+ *   Frederic Wang <fred.wang@free.fr>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either of the GNU General Public License Version 2 or later (the "GPL"),
  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -163,16 +164,21 @@ public:
                           nsPresentationData& aPresentationData,
                           bool                aClimbTree = true);
 
   // helper used by <mstyle> and <mtable> to see if they have a displaystyle attribute 
   static void
   FindAttrDisplaystyle(nsIContent*         aContent,
                        nsPresentationData& aPresentationData);
 
+  // helper used to see if an element has a dir attribute 
+  static void
+  FindAttrDirectionality(nsIContent*         aContent,
+                         nsPresentationData& aPresentationData);
+
   // helper to check if a content has an attribute. If content is nsnull or if
   // the attribute is not there, check if the attribute is on the mstyle hierarchy
   // @return true     --if attribute exists
   //         false --if attribute doesn't exist
   static bool
   GetAttribute(nsIContent* aContent,
                nsIFrame*   aMathMLmstyleFrame,          
                nsIAtom*    aAttributeAtom,
--- a/layout/mathml/nsMathMLOperators.cpp
+++ b/layout/mathml/nsMathMLOperators.cpp
@@ -49,26 +49,26 @@
 #include "nsCRT.h"
 
 #include "nsMathMLOperators.h"
 
 // operator dictionary entry
 struct OperatorData {
   OperatorData(void)
     : mFlags(0),
-      mLeftSpace(0.0f),
-      mRightSpace(0.0f)
+      mLeadingSpace(0.0f),
+      mTrailingSpace(0.0f)
   {
   }
 
   // member data
   nsString        mStr;
   nsOperatorFlags mFlags;
-  float           mLeftSpace;   // unit is em
-  float           mRightSpace;  // unit is em
+  float           mLeadingSpace;   // unit is em
+  float           mTrailingSpace;  // unit is em
 };
 
 static PRInt32         gTableRefCount = 0;
 static PRUint32        gOperatorCount = 0;
 static OperatorData*   gOperatorArray = nsnull;
 static nsHashtable*    gOperatorTable = nsnull;
 static bool            gInitialized   = false;
 static nsTArray<nsString>*      gInvariantCharArray    = nsnull;
@@ -112,16 +112,18 @@ SetBooleanProperty(OperatorData* aOperat
   else if (aName.EqualsLiteral("separator"))
     aOperatorData->mFlags |=  NS_MATHML_OPERATOR_SEPARATOR;
   else if (aName.EqualsLiteral("movablelimits"))
     aOperatorData->mFlags |= NS_MATHML_OPERATOR_MOVABLELIMITS;
   else if (aName.EqualsLiteral("symmetric"))
     aOperatorData->mFlags |= NS_MATHML_OPERATOR_SYMMETRIC;
   else if (aName.EqualsLiteral("integral"))
     aOperatorData->mFlags |= NS_MATHML_OPERATOR_INTEGRAL;
+  else if (aName.EqualsLiteral("mirrorable"))
+    aOperatorData->mFlags |= NS_MATHML_OPERATOR_MIRRORABLE;
 }
 
 static void
 SetProperty(OperatorData* aOperatorData,
             nsString      aName,
             nsString      aValue)
 {
   if (aName.IsEmpty() || aValue.IsEmpty())
@@ -134,32 +136,32 @@ SetProperty(OperatorData* aOperatorData,
 
   if (aName.EqualsLiteral("direction")) {
     if (aValue.EqualsLiteral("vertical"))
       aOperatorData->mFlags |= NS_MATHML_OPERATOR_DIRECTION_VERTICAL;
     else if (aValue.EqualsLiteral("horizontal"))
       aOperatorData->mFlags |= NS_MATHML_OPERATOR_DIRECTION_HORIZONTAL;
     else return; // invalid value
   } else {
-    bool isLeftSpace;
+    bool isLeadingSpace;
     if (aName.EqualsLiteral("lspace"))
-      isLeftSpace = true;
+      isLeadingSpace = true;
     else if (aName.EqualsLiteral("rspace"))
-      isLeftSpace = false;
+      isLeadingSpace = false;
     else return;  // input is not applicable
 
     // aValue is assumed to be a digit from 0 to 7
     PRInt32 error = 0;
     float space = aValue.ToFloat(&error) / 18.0;
     if (error) return;
 
-    if (isLeftSpace)
-      aOperatorData->mLeftSpace = space;
+    if (isLeadingSpace)
+      aOperatorData->mLeadingSpace = space;
     else
-      aOperatorData->mRightSpace = space;
+      aOperatorData->mTrailingSpace = space;
   }
 }
 
 static bool
 SetOperator(OperatorData*   aOperatorData,
             nsOperatorFlags aForm,
             const nsCString& aOperator,
             nsString&        aAttributes)
@@ -404,24 +406,24 @@ GetOperatorData(const nsString& aOperato
   nsStringKey hkey(key);
   return (OperatorData*)gOperatorTable->Get(&hkey);
 }
 
 bool
 nsMathMLOperators::LookupOperator(const nsString&       aOperator,
                                   const nsOperatorFlags aForm,
                                   nsOperatorFlags*      aFlags,
-                                  float*                aLeftSpace,
-                                  float*                aRightSpace)
+                                  float*                aLeadingSpace,
+                                  float*                aTrailingSpace)
 {
   if (!gInitialized) {
     InitGlobals();
   }
   if (gOperatorTable) {
-    NS_ASSERTION(aFlags && aLeftSpace && aRightSpace, "bad usage");
+    NS_ASSERTION(aFlags && aLeadingSpace && aTrailingSpace, "bad usage");
     NS_ASSERTION(aForm > 0 && aForm < 4, "*** invalid call ***");
 
     // The MathML REC says:
     // If the operator does not occur in the dictionary with the specified form,
     // the renderer should use one of the forms which is available there, in the
     // order of preference: infix, postfix, prefix.
 
     OperatorData* found;
@@ -436,67 +438,67 @@ nsMathMLOperators::LookupOperator(const 
           if (form != NS_MATHML_OPERATOR_FORM_PREFIX) {
             found = GetOperatorData(aOperator, NS_MATHML_OPERATOR_FORM_PREFIX);
           }
         }
       }
     }
     if (found) {
       NS_ASSERTION(found->mStr.Equals(aOperator), "bad setup");
-      *aLeftSpace = found->mLeftSpace;
-      *aRightSpace = found->mRightSpace;
+      *aLeadingSpace = found->mLeadingSpace;
+      *aTrailingSpace = found->mTrailingSpace;
       *aFlags &= ~NS_MATHML_OPERATOR_FORM; // clear the form bits
       *aFlags |= found->mFlags; // just add bits without overwriting
       return true;
     }
   }
   return false;
 }
 
 void
 nsMathMLOperators::LookupOperators(const nsString&       aOperator,
                                    nsOperatorFlags*      aFlags,
-                                   float*                aLeftSpace,
-                                   float*                aRightSpace)
+                                   float*                aLeadingSpace,
+                                   float*                aTrailingSpace)
 {
   if (!gInitialized) {
     InitGlobals();
   }
 
   aFlags[NS_MATHML_OPERATOR_FORM_INFIX] = 0;
-  aLeftSpace[NS_MATHML_OPERATOR_FORM_INFIX] = 0.0f;
-  aRightSpace[NS_MATHML_OPERATOR_FORM_INFIX] = 0.0f;
+  aLeadingSpace[NS_MATHML_OPERATOR_FORM_INFIX] = 0.0f;
+  aTrailingSpace[NS_MATHML_OPERATOR_FORM_INFIX] = 0.0f;
 
   aFlags[NS_MATHML_OPERATOR_FORM_POSTFIX] = 0;
-  aLeftSpace[NS_MATHML_OPERATOR_FORM_POSTFIX] = 0.0f;
-  aRightSpace[NS_MATHML_OPERATOR_FORM_POSTFIX] = 0.0f;
+  aLeadingSpace[NS_MATHML_OPERATOR_FORM_POSTFIX] = 0.0f;
+  aTrailingSpace[NS_MATHML_OPERATOR_FORM_POSTFIX] = 0.0f;
 
   aFlags[NS_MATHML_OPERATOR_FORM_PREFIX] = 0;
-  aLeftSpace[NS_MATHML_OPERATOR_FORM_PREFIX] = 0.0f;
-  aRightSpace[NS_MATHML_OPERATOR_FORM_PREFIX] = 0.0f;
+  aLeadingSpace[NS_MATHML_OPERATOR_FORM_PREFIX] = 0.0f;
+  aTrailingSpace[NS_MATHML_OPERATOR_FORM_PREFIX] = 0.0f;
 
   if (gOperatorTable) {
     OperatorData* found;
     found = GetOperatorData(aOperator, NS_MATHML_OPERATOR_FORM_INFIX);
     if (found) {
       aFlags[NS_MATHML_OPERATOR_FORM_INFIX] = found->mFlags;
-      aLeftSpace[NS_MATHML_OPERATOR_FORM_INFIX] = found->mLeftSpace;
-      aRightSpace[NS_MATHML_OPERATOR_FORM_INFIX] = found->mRightSpace;
+      aLeadingSpace[NS_MATHML_OPERATOR_FORM_INFIX] = found->mLeadingSpace;
+      aTrailingSpace[NS_MATHML_OPERATOR_FORM_INFIX] = found->mTrailingSpace;
     }
     found = GetOperatorData(aOperator, NS_MATHML_OPERATOR_FORM_POSTFIX);
     if (found) {
       aFlags[NS_MATHML_OPERATOR_FORM_POSTFIX] = found->mFlags;
-      aLeftSpace[NS_MATHML_OPERATOR_FORM_POSTFIX] = found->mLeftSpace;
-      aRightSpace[NS_MATHML_OPERATOR_FORM_POSTFIX] = found->mRightSpace;
+      aLeadingSpace[NS_MATHML_OPERATOR_FORM_POSTFIX] = found->mLeadingSpace;
+      aTrailingSpace[NS_MATHML_OPERATOR_FORM_POSTFIX] = found->mTrailingSpace;
     }
     found = GetOperatorData(aOperator, NS_MATHML_OPERATOR_FORM_PREFIX);
     if (found) {
       aFlags[NS_MATHML_OPERATOR_FORM_PREFIX] = found->mFlags;
-      aLeftSpace[NS_MATHML_OPERATOR_FORM_PREFIX] = found->mLeftSpace;
-      aRightSpace[NS_MATHML_OPERATOR_FORM_PREFIX] = found->mRightSpace;
+      aLeadingSpace[NS_MATHML_OPERATOR_FORM_PREFIX] = found->mLeadingSpace;
+      aTrailingSpace[NS_MATHML_OPERATOR_FORM_PREFIX] = found->mTrailingSpace;
     }
   }
 }
 
 bool
 nsMathMLOperators::IsMutableOperator(const nsString& aOperator)
 {
   if (!gInitialized) {
@@ -510,16 +512,30 @@ nsMathMLOperators::IsMutableOperator(con
   nsOperatorFlags allFlags =
     flags[NS_MATHML_OPERATOR_FORM_INFIX] |
     flags[NS_MATHML_OPERATOR_FORM_POSTFIX] |
     flags[NS_MATHML_OPERATOR_FORM_PREFIX];
   return NS_MATHML_OPERATOR_IS_STRETCHY(allFlags) ||
          NS_MATHML_OPERATOR_IS_LARGEOP(allFlags);
 }
 
+/* static */ bool
+nsMathMLOperators::IsMirrorableOperator(const nsString& aOperator)
+{
+  // LookupOperator will search infix, postfix and prefix forms of aOperator and
+  // return the first form found. It is assumed that all these forms have same
+  // mirrorability.
+  nsOperatorFlags flags = 0;
+  float dummy;
+  nsMathMLOperators::LookupOperator(aOperator,
+                                    NS_MATHML_OPERATOR_FORM_INFIX,
+                                    &flags, &dummy, &dummy);
+  return NS_MATHML_OPERATOR_IS_MIRRORABLE(flags);
+}
+
 /* static */ nsStretchDirection
 nsMathMLOperators::GetStretchyDirection(const nsString& aOperator)
 {
   // LookupOperator will search infix, postfix and prefix forms of aOperator and
   // return the first form found. It is assumed that all these forms have same
   // direction.
   nsOperatorFlags flags = 0;
   float dummy;
--- a/layout/mathml/nsMathMLOperators.h
+++ b/layout/mathml/nsMathMLOperators.h
@@ -76,22 +76,23 @@ enum {
   NS_MATHML_OPERATOR_STRETCHY           = 1<<4,
   NS_MATHML_OPERATOR_FENCE              = 1<<5,
   NS_MATHML_OPERATOR_ACCENT             = 1<<6,
   NS_MATHML_OPERATOR_LARGEOP            = 1<<7,
   NS_MATHML_OPERATOR_SEPARATOR          = 1<<8,
   NS_MATHML_OPERATOR_MOVABLELIMITS      = 1<<9,
   NS_MATHML_OPERATOR_SYMMETRIC          = 1<<10,
   NS_MATHML_OPERATOR_INTEGRAL           = 1<<11,
+  NS_MATHML_OPERATOR_MIRRORABLE         = 1<<12,
 
   // Additional bits not stored in the dictionary
-  NS_MATHML_OPERATOR_MINSIZE_ABSOLUTE   = 1<<12,
-  NS_MATHML_OPERATOR_MAXSIZE_ABSOLUTE   = 1<<13,
-  NS_MATHML_OPERATOR_LEFTSPACE_ATTR     = 1<<14,
-  NS_MATHML_OPERATOR_RIGHTSPACE_ATTR    = 1<<15
+  NS_MATHML_OPERATOR_MINSIZE_ABSOLUTE   = 1<<13,
+  NS_MATHML_OPERATOR_MAXSIZE_ABSOLUTE   = 1<<14,
+  NS_MATHML_OPERATOR_LSPACE_ATTR     = 1<<15,
+  NS_MATHML_OPERATOR_RSPACE_ATTR    = 1<<16
 };
 
 #define NS_MATHML_OPERATOR_SIZE_INFINITY NS_IEEEPositiveInfinity()
 
 // Style invariant characters (chars have their own intrinsic predefined style)
 enum eMATHVARIANT {
   eMATHVARIANT_NONE = -1,
   eMATHVARIANT_normal = 0,
@@ -124,36 +125,41 @@ public:
   // If the operator is not found under the supplied form but is found under a 
   // different form, the method returns true as well. The caller can test the
   // output parameter aFlags to know exactly under which form the operator was
   // found in the Operator Dictionary.
   static bool
   LookupOperator(const nsString&       aOperator,
                  const nsOperatorFlags aForm,
                  nsOperatorFlags*      aFlags,
-                 float*                aLeftSpace,
-                 float*                aRightSpace);
+                 float*                aLeadingSpace,
+                 float*                aTrailingSpace);
 
    // LookupOperators:
    // Helper to return all the forms under which an operator is listed in the
    // Operator Dictionary. The caller must pass arrays of size 4, and use 
-   // aFlags[NS_MATHML_OPERATOR_FORM_{INFIX|POSTFIX|PREFIX}], aLeftSpace[], etc,
-   // to access the attributes of the operator under a particular form. If the
-   // operator wasn't found under a form, its entry aFlags[form] is set to zero.
+   // aFlags[NS_MATHML_OPERATOR_FORM_{INFIX|POSTFIX|PREFIX}],
+   // aLeadingSpace[], etc, to access the attributes of the operator under a
+   // particular form. If the operator wasn't found under a form, its entry
+   // aFlags[form] is set to zero.
    static void
    LookupOperators(const nsString&       aOperator,
                    nsOperatorFlags*      aFlags,
-                   float*                aLeftSpace,
-                   float*                aRightSpace);
+                   float*                aLeadingSpace,
+                   float*                aTrailingSpace);
 
   // IsMutableOperator:
   // Return true if the operator exists and is stretchy or largeop
   static bool
   IsMutableOperator(const nsString& aOperator);
 
+  // Helper functions used by the nsMathMLChar class.
+  static bool
+  IsMirrorableOperator(const nsString& aOperator);
+
   // Helper function used by the nsMathMLChar class.
   static nsStretchDirection GetStretchyDirection(const nsString& aOperator);
 
   // Return the variant type of one Unicode Mathematical Alphanumeric Symbol
   // character (which may be represented by a surrogate pair), or return
   // eMATHVARIANT_NONE if aChar is not such a character.
   static eMATHVARIANT LookupInvariantChar(const nsAString& aChar);
 
@@ -224,21 +230,24 @@ public:
   (NS_MATHML_OPERATOR_MOVABLELIMITS == ((_flags) & NS_MATHML_OPERATOR_MOVABLELIMITS))
 
 #define NS_MATHML_OPERATOR_IS_SYMMETRIC(_flags) \
   (NS_MATHML_OPERATOR_SYMMETRIC == ((_flags) & NS_MATHML_OPERATOR_SYMMETRIC))
 
 #define NS_MATHML_OPERATOR_IS_INTEGRAL(_flags) \
   (NS_MATHML_OPERATOR_INTEGRAL == ((_flags) & NS_MATHML_OPERATOR_INTEGRAL))
 
+#define NS_MATHML_OPERATOR_IS_MIRRORABLE(_flags) \
+  (NS_MATHML_OPERATOR_MIRRORABLE == ((_flags) & NS_MATHML_OPERATOR_MIRRORABLE))
+
 #define NS_MATHML_OPERATOR_MINSIZE_IS_ABSOLUTE(_flags) \
   (NS_MATHML_OPERATOR_MINSIZE_ABSOLUTE == ((_flags) & NS_MATHML_OPERATOR_MINSIZE_ABSOLUTE))
 
 #define NS_MATHML_OPERATOR_MAXSIZE_IS_ABSOLUTE(_flags) \
   (NS_MATHML_OPERATOR_MAXSIZE_ABSOLUTE == ((_flags) & NS_MATHML_OPERATOR_MAXSIZE_ABSOLUTE))
 
-#define NS_MATHML_OPERATOR_HAS_LEFTSPACE_ATTR(_flags) \
-  (NS_MATHML_OPERATOR_LEFTSPACE_ATTR == ((_flags) & NS_MATHML_OPERATOR_LEFTSPACE_ATTR))
+#define NS_MATHML_OPERATOR_HAS_LSPACE_ATTR(_flags) \
+  (NS_MATHML_OPERATOR_LSPACE_ATTR == ((_flags) & NS_MATHML_OPERATOR_LSPACE_ATTR))
 
-#define NS_MATHML_OPERATOR_HAS_RIGHTSPACE_ATTR(_flags) \
-  (NS_MATHML_OPERATOR_RIGHTSPACE_ATTR == ((_flags) & NS_MATHML_OPERATOR_RIGHTSPACE_ATTR))
+#define NS_MATHML_OPERATOR_HAS_RSPACE_ATTR(_flags) \
+  (NS_MATHML_OPERATOR_RSPACE_ATTR == ((_flags) & NS_MATHML_OPERATOR_RSPACE_ATTR))
 
 #endif /* nsMathMLOperators_h___ */
--- a/layout/mathml/nsMathMLTokenFrame.cpp
+++ b/layout/mathml/nsMathMLTokenFrame.cpp
@@ -17,16 +17,17 @@
  * The Initial Developer of the Original Code is
  * The University of Queensland.
  * Portions created by the Initial Developer are Copyright (C) 1999
  * the Initial Developer. All Rights Reserved.
  * 
  * Contributor(s): 
  *   Roger B. Sidje <rbs@maths.uq.edu.au>
  *   Karl Tomlinson <karlt+@karlt.net>, Mozilla Corporation
+ *   Frederic Wang <fred.wang@free.fr>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -59,16 +60,21 @@ nsMathMLTokenFrame::~nsMathMLTokenFrame(
 }
 
 NS_IMETHODIMP
 nsMathMLTokenFrame::InheritAutomaticData(nsIFrame* aParent)
 {
   // let the base class get the default from our parent
   nsMathMLContainerFrame::InheritAutomaticData(aParent);
 
+  if (mContent->Tag() != nsGkAtoms::mspace_) {
+    // see if the directionality attribute is there
+    nsMathMLFrame::FindAttrDirectionality(mContent, mPresentationData);
+  }
+
   ProcessTextData();
 
   return NS_OK;
 }
 
 eMathMLFrameType
 nsMathMLTokenFrame::GetMathMLFrameType()
 {
--- a/layout/mathml/nsMathMLmencloseFrame.cpp
+++ b/layout/mathml/nsMathMLmencloseFrame.cpp
@@ -236,17 +236,18 @@ nsMathMLmencloseFrame::BuildDisplayList(
   mencloseRect.x = mencloseRect.y = 0;
 
   if (IsToDraw(NOTATION_RADICAL)) {
     rv = mMathMLChar[mRadicalCharIndex].Display(aBuilder, this, aLists);
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsRect rect;
     mMathMLChar[mRadicalCharIndex].GetRect(rect);
-    rect.MoveBy(rect.width, 0);
+    rect.MoveBy(NS_MATHML_IS_RTL(mPresentationData.flags) ?
+                -mContentWidth : rect.width, 0);
     rect.SizeTo(mContentWidth, mRuleThickness);
     rv = DisplayBar(aBuilder, this, rect, aLists);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   if (IsToDraw(NOTATION_LONGDIV)) {
     rv = mMathMLChar[mLongDivCharIndex].Display(aBuilder, this, aLists);
     NS_ENSURE_SUCCESS(rv, rv);
@@ -491,17 +492,17 @@ nsMathMLmencloseFrame::PlaceInternal(nsR
       nsBoundingMetrics contSize = bmBase;
       contSize.ascent = mRuleThickness;
       contSize.descent = bmBase.ascent + bmBase.descent + psi;
 
       // height(longdiv) should be >= height(base) + psi + mRuleThickness
       mMathMLChar[mLongDivCharIndex].Stretch(PresContext(), aRenderingContext,
                                              NS_STRETCH_DIRECTION_VERTICAL,
                                              contSize, bmLongdivChar,
-                                             NS_STRETCH_LARGER);
+                                             NS_STRETCH_LARGER, false);
       mMathMLChar[mLongDivCharIndex].GetBoundingMetrics(bmLongdivChar);
 
       // Update horizontal parameters
       dx_left = NS_MAX(dx_left, bmLongdivChar.width);
 
       // Update vertical parameters
       longdivAscent = bmBase.ascent + psi + mRuleThickness;
       longdivDescent = NS_MAX(bmBase.descent,
@@ -513,38 +514,42 @@ nsMathMLmencloseFrame::PlaceInternal(nsR
       mBoundingMetrics.descent = NS_MAX(mBoundingMetrics.descent,
                                         longdivDescent);
     }
   }
 
   ///////////////
   // radical notation:
   if (IsToDraw(NOTATION_RADICAL)) {
+    nscoord *dx_leading =
+      NS_MATHML_IS_RTL(mPresentationData.flags) ? &dx_right : &dx_left;
+    
     if (aWidthOnly) {
       nscoord radical_width = mMathMLChar[mRadicalCharIndex].
         GetMaxWidth(PresContext(), aRenderingContext);
       
       // Update horizontal parameters
-      dx_left = NS_MAX(dx_left, radical_width);
+      *dx_leading = NS_MAX(*dx_leading, radical_width);
     } else {
       // Stretch the radical symbol to the appropriate height if it is not
       // big enough.
       nsBoundingMetrics contSize = bmBase;
       contSize.ascent = mRuleThickness;
       contSize.descent = bmBase.ascent + bmBase.descent + psi;
 
       // height(radical) should be >= height(base) + psi + mRuleThickness
       mMathMLChar[mRadicalCharIndex].Stretch(PresContext(), aRenderingContext,
                                              NS_STRETCH_DIRECTION_VERTICAL,
                                              contSize, bmRadicalChar,
-                                             NS_STRETCH_LARGER);
+                                             NS_STRETCH_LARGER,
+                                             NS_MATHML_IS_RTL(mPresentationData.flags));
       mMathMLChar[mRadicalCharIndex].GetBoundingMetrics(bmRadicalChar);
 
       // Update horizontal parameters
-      dx_left = NS_MAX(dx_left, bmRadicalChar.width);
+      *dx_leading = NS_MAX(*dx_leading, bmRadicalChar.width);
 
       // Update vertical parameters
       radicalAscent = bmBase.ascent + psi + mRuleThickness;
       radicalDescent = NS_MAX(bmBase.descent,
                               (bmRadicalChar.ascent + bmRadicalChar.descent -
                                radicalAscent));
 
       mBoundingMetrics.ascent = NS_MAX(mBoundingMetrics.ascent,
@@ -648,24 +653,27 @@ nsMathMLmencloseFrame::PlaceInternal(nsR
       mMathMLChar[mLongDivCharIndex].SetRect(nsRect(dx_left -
                                                     bmLongdivChar.width,
                                                     aDesiredSize.ascent -
                                                     longdivAscent,
                                                     bmLongdivChar.width,
                                                     bmLongdivChar.ascent +
                                                     bmLongdivChar.descent));
 
-    if (IsToDraw(NOTATION_RADICAL))
-      mMathMLChar[mRadicalCharIndex].SetRect(nsRect(dx_left -
-                                                    bmRadicalChar.width,
+    if (IsToDraw(NOTATION_RADICAL)) {
+      nscoord dx = NS_MATHML_IS_RTL(mPresentationData.flags) ?
+        dx_left + bmBase.width : dx_left - bmRadicalChar.width;
+
+      mMathMLChar[mRadicalCharIndex].SetRect(nsRect(dx,
                                                     aDesiredSize.ascent -
                                                     radicalAscent,
                                                     bmRadicalChar.width,
                                                     bmRadicalChar.ascent +
                                                     bmRadicalChar.descent));
+    }
 
     mContentWidth = bmBase.width;
 
     //////////////////
     // Finish reflowing child frames
     PositionRowChildFrames(dx_left, aDesiredSize.ascent);
   }
 
--- a/layout/mathml/nsMathMLmfencedFrame.cpp
+++ b/layout/mathml/nsMathMLmfencedFrame.cpp
@@ -352,74 +352,94 @@ nsMathMLmfencedFrame::Reflow(nsPresConte
   // adjust the origin of children.
 
   // we need to center around the axis
   nscoord delta = NS_MAX(containerSize.ascent - axisHeight, 
                          containerSize.descent + axisHeight);
   containerSize.ascent = delta + axisHeight;
   containerSize.descent = delta - axisHeight;
 
+  bool isRTL = NS_MATHML_IS_RTL(mPresentationData.flags);
+
   /////////////////
   // opening fence ...
   ReflowChar(aPresContext, *aReflowState.rendContext, mOpenChar,
              NS_MATHML_OPERATOR_FORM_PREFIX, font->mScriptLevel, 
-             axisHeight, leading, em, containerSize, ascent, descent);
+             axisHeight, leading, em, containerSize, ascent, descent, isRTL);
   /////////////////
   // separators ...
   for (i = 0; i < mSeparatorsCount; i++) {
     ReflowChar(aPresContext, *aReflowState.rendContext, &mSeparatorsChar[i],
                NS_MATHML_OPERATOR_FORM_INFIX, font->mScriptLevel,
-               axisHeight, leading, em, containerSize, ascent, descent);
+               axisHeight, leading, em, containerSize, ascent, descent, isRTL);
   }
   /////////////////
   // closing fence ...
   ReflowChar(aPresContext, *aReflowState.rendContext, mCloseChar,
              NS_MATHML_OPERATOR_FORM_POSTFIX, font->mScriptLevel,
-             axisHeight, leading, em, containerSize, ascent, descent);
+             axisHeight, leading, em, containerSize, ascent, descent, isRTL);
 
   //////////////////
   // Adjust the origins of each child.
   // and update our bounding metrics
 
   i = 0;
   nscoord dx = 0;
   nsBoundingMetrics bm;
   bool firstTime = true;
-  if (mOpenChar) {
-    PlaceChar(mOpenChar, ascent, bm, dx);
+  nsMathMLChar *leftChar, *rightChar;
+  if (isRTL) {
+    leftChar = mCloseChar;
+    rightChar = mOpenChar;
+  } else {
+    leftChar = mOpenChar;
+    rightChar = mCloseChar;
+  }
+
+  if (leftChar) {
+    PlaceChar(leftChar, ascent, bm, dx);
     aDesiredSize.mBoundingMetrics = bm;
     firstTime = false;
   }
 
-  childFrame = firstChild;
+  if (isRTL) {
+    childFrame = this->GetLastChild(nsIFrame::kPrincipalList);
+  } else {
+    childFrame = firstChild;
+  }
   while (childFrame) {
     nsHTMLReflowMetrics childSize;
     GetReflowAndBoundingMetricsFor(childFrame, childSize, bm);
     if (firstTime) {
       firstTime = false;
       aDesiredSize.mBoundingMetrics  = bm;
     }
     else  
       aDesiredSize.mBoundingMetrics += bm;
 
     FinishReflowChild(childFrame, aPresContext, nsnull, childSize, 
                       dx, ascent - childSize.ascent, 0);
     dx += childSize.width;
 
     if (i < mSeparatorsCount) {
-      PlaceChar(&mSeparatorsChar[i], ascent, bm, dx);
+      PlaceChar(&mSeparatorsChar[isRTL ? mSeparatorsCount - 1 - i : i],
+                ascent, bm, dx);
       aDesiredSize.mBoundingMetrics += bm;
     }
     i++;
 
-    childFrame = childFrame->GetNextSibling();
+    if (isRTL) {
+      childFrame = childFrame->GetPrevSibling();
+    } else {
+      childFrame = childFrame->GetNextSibling();
+    }
   }
 
-  if (mCloseChar) {
-    PlaceChar(mCloseChar, ascent, bm, dx);
+  if (rightChar) {
+    PlaceChar(rightChar, ascent, bm, dx);
     if (firstTime)
       aDesiredSize.mBoundingMetrics  = bm;
     else  
       aDesiredSize.mBoundingMetrics += bm;
   }
 
   aDesiredSize.width = aDesiredSize.mBoundingMetrics.width;
   aDesiredSize.height = ascent + descent;
@@ -475,28 +495,30 @@ nsMathMLmfencedFrame::ReflowChar(nsPresC
                                  nsMathMLChar*        aMathMLChar,
                                  nsOperatorFlags      aForm,
                                  PRInt32              aScriptLevel,
                                  nscoord              axisHeight,
                                  nscoord              leading,
                                  nscoord              em,
                                  nsBoundingMetrics&   aContainerSize,
                                  nscoord&             aAscent,
-                                 nscoord&             aDescent)
+                                 nscoord&             aDescent,
+                                 bool                 aRTL)
 {
   if (aMathMLChar && 0 < aMathMLChar->Length()) {
     nscoord leftSpace;
     nscoord rightSpace;
     GetCharSpacing(aMathMLChar, aForm, aScriptLevel, em, leftSpace, rightSpace);
 
     // stretch the char to the appropriate height if it is not big enough.
     nsBoundingMetrics charSize;
     nsresult res = aMathMLChar->Stretch(aPresContext, aRenderingContext,
                                         NS_STRETCH_DIRECTION_VERTICAL,
-                                        aContainerSize, charSize);
+                                        aContainerSize, charSize,
+                                        NS_STRETCH_NORMAL, aRTL);
 
     if (NS_STRETCH_DIRECTION_UNSUPPORTED != aMathMLChar->GetStretchDirection()) {
       // has changed... so center the char around the axis
       nscoord height = charSize.ascent + charSize.descent;
       charSize.ascent = height/2 + axisHeight;
       charSize.descent = height - charSize.ascent;
     }
     else {
--- a/layout/mathml/nsMathMLmfencedFrame.h
+++ b/layout/mathml/nsMathMLmfencedFrame.h
@@ -100,17 +100,18 @@ public:
              nsMathMLChar*        aMathMLChar,
              nsOperatorFlags      aForm,
              PRInt32              aScriptLevel,
              nscoord              axisHeight,
              nscoord              leading,
              nscoord              em,
              nsBoundingMetrics&   aContainerSize,
              nscoord&             aAscent,
-             nscoord&             aDescent);
+             nscoord&             aDescent,
+             bool                 aRTL);
 
   static void
   PlaceChar(nsMathMLChar*      aMathMLChar,
             nscoord            aDesiredSize,
             nsBoundingMetrics& bm,
             nscoord&           dx);
 
 protected:
--- a/layout/mathml/nsMathMLmfracFrame.cpp
+++ b/layout/mathml/nsMathMLmfracFrame.cpp
@@ -267,18 +267,22 @@ nsMathMLmfracFrame::PlaceInternal(nsRend
   if (!mIsBevelled) {
     mLineRect.height = mLineThickness;
     
     // by default, leave at least one-pixel padding at either end, or use
     // lspace & rspace that may come from <mo> if we are an embellished
     // container (we fetch values from the core since they may use units that
     // depend on style data, and style changes could have occurred in the
     // core since our last visit there)
-    nscoord leftSpace = NS_MAX(onePixel, coreData.leftSpace);
-    nscoord rightSpace = NS_MAX(onePixel, coreData.rightSpace);
+    nscoord leftSpace = NS_MAX(onePixel,
+                               NS_MATHML_IS_RTL(mPresentationData.flags) ?
+                               coreData.trailingSpace : coreData.leadingSpace);
+    nscoord rightSpace = NS_MAX(onePixel,
+                                NS_MATHML_IS_RTL(mPresentationData.flags) ?
+                                coreData.leadingSpace : coreData.trailingSpace);
 
     //////////////////
     // Get shifts
     nscoord numShift = 0;
     nscoord denShift = 0;
 
     // Rule 15b, App. G, TeXbook
     nscoord numShift1, numShift2, numShift3;
@@ -417,18 +421,18 @@ nsMathMLmfracFrame::PlaceInternal(nsRend
     nscoord em = fm->EmHeight();
     nscoord slashMaxWidthConstant = 2 * em;
 
     // For large line thicknesses the minimum slash height is limited to the
     // largest expected height of a fraction
     nscoord slashMinHeight = slashRatio *
       NS_MIN(2 * mLineThickness, slashMaxWidthConstant);
 
-    nscoord leftSpace = NS_MAX(padding, coreData.leftSpace);
-    nscoord rightSpace = NS_MAX(padding, coreData.rightSpace);
+    nscoord leadingSpace = NS_MAX(padding, coreData.leadingSpace);
+    nscoord trailingSpace = NS_MAX(padding, coreData.trailingSpace);
     nscoord delta;
     
     //           ___________
     //          |           |    /
     //         {|-NUMERATOR-|   /
     //         {|___________|  S
     //         {               L
     // numShift{               A
@@ -479,45 +483,58 @@ nsMathMLmfracFrame::PlaceInternal(nsRend
     } else {
       mLineRect.width = mLineThickness +
         NS_MIN(slashMaxWidthConstant,
                (mBoundingMetrics.ascent + mBoundingMetrics.descent) /
                slashRatio);
     }
 
     // Set horizontal bounding metrics
-    mBoundingMetrics.leftBearing = leftSpace + bmNum.leftBearing;
-    mBoundingMetrics.rightBearing =
-      leftSpace + bmNum.width + mLineRect.width + bmDen.rightBearing;
+    if (NS_MATHML_IS_RTL(mPresentationData.flags)) {
+      mBoundingMetrics.leftBearing = trailingSpace + bmDen.leftBearing;
+      mBoundingMetrics.rightBearing = trailingSpace + bmDen.width + mLineRect.width + bmNum.rightBearing;
+    } else {
+      mBoundingMetrics.leftBearing = leadingSpace + bmNum.leftBearing;
+      mBoundingMetrics.rightBearing = leadingSpace + bmNum.width + mLineRect.width + bmDen.rightBearing;
+    }
     mBoundingMetrics.width =
-      leftSpace + bmNum.width + mLineRect.width + bmDen.width + rightSpace;
+      leadingSpace + bmNum.width + mLineRect.width + bmDen.width +
+      trailingSpace;
 
     // Set aDesiredSize
     aDesiredSize.ascent = mBoundingMetrics.ascent + padding;
     aDesiredSize.height =
       mBoundingMetrics.ascent + mBoundingMetrics.descent + 2 * padding;
     aDesiredSize.width = mBoundingMetrics.width;
     aDesiredSize.mBoundingMetrics = mBoundingMetrics;
 
     mReference.x = 0;
     mReference.y = aDesiredSize.ascent;
     
     if (aPlaceOrigin) {
-      FinishReflowChild(frameNum, presContext, nsnull, sizeNum,
-                        leftSpace,
-                        aDesiredSize.ascent - numShift - sizeNum.ascent, 0);
+      nscoord dx, dy;
+
+      // place numerator
+      dx = MirrorIfRTL(aDesiredSize.width, sizeNum.width,
+                       leadingSpace);
+      dy = aDesiredSize.ascent - numShift - sizeNum.ascent;
+      FinishReflowChild(frameNum, presContext, nsnull, sizeNum, dx, dy, 0);
 
-      mLineRect.SetRect(leftSpace + bmNum.width,
-                        aDesiredSize.ascent - mBoundingMetrics.ascent,
-                        mLineRect.width,
-                        aDesiredSize.height - 2 * padding);
+      // place the fraction bar
+      dx = MirrorIfRTL(aDesiredSize.width, mLineRect.width,
+                       leadingSpace + bmNum.width);
+      dy = aDesiredSize.ascent - mBoundingMetrics.ascent;
+      mLineRect.SetRect(dx, dy,
+                        mLineRect.width, aDesiredSize.height - 2 * padding);
 
-      FinishReflowChild(frameDen, presContext, nsnull, sizeDen,
-                        leftSpace + bmNum.width + mLineRect.width,
-                        aDesiredSize.ascent + denShift - sizeDen.ascent, 0);
+      // place denominator
+      dx = MirrorIfRTL(aDesiredSize.width, sizeDen.width,
+                       leadingSpace + bmNum.width + mLineRect.width);
+      dy = aDesiredSize.ascent + denShift - sizeDen.ascent;
+      FinishReflowChild(frameDen, presContext, nsnull, sizeDen, dx, dy, 0);
     }
 
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
@@ -544,59 +561,71 @@ nsMathMLmfracFrame::UpdatePresentationDa
     UpdatePresentationDataFromChildAt(aFirstIndex, aLastIndex,
                                       aFlagsValues, aFlagsToUpdate);
 }
 
 class nsDisplayMathMLSlash : public nsDisplayItem {
 public:
   nsDisplayMathMLSlash(nsDisplayListBuilder* aBuilder,
                        nsIFrame* aFrame, const nsRect& aRect,
-                       nscoord aThickness)
-    : nsDisplayItem(aBuilder, aFrame), mRect(aRect), mThickness(aThickness) {
+                       nscoord aThickness, bool aRTL)
+    : nsDisplayItem(aBuilder, aFrame), mRect(aRect), mThickness(aThickness),
+      mRTL(aRTL) {
     MOZ_COUNT_CTOR(nsDisplayMathMLSlash);
   }
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayMathMLSlash() {
     MOZ_COUNT_DTOR(nsDisplayMathMLSlash);
   }
 #endif
 
   virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx);
   NS_DISPLAY_DECL_NAME("MathMLSlash", TYPE_MATHML_SLASH)
 
 private:
   nsRect    mRect;
   nscoord   mThickness;
+  bool      mRTL;
 };
 
 void nsDisplayMathMLSlash::Paint(nsDisplayListBuilder* aBuilder,
                                  nsRenderingContext* aCtx)
 {
   // get the gfxRect
   nsPresContext* presContext = mFrame->PresContext();
   gfxRect rect = presContext->AppUnitsToGfxUnits(mRect + ToReferenceFrame());
   
   // paint with the current text color
   aCtx->SetColor(mFrame->GetVisitedDependentColor(eCSSProperty_color));
  
   // draw the slash as a parallelogram 
   gfxContext *gfxCtx = aCtx->ThebesContext();
   gfxPoint delta = gfxPoint(presContext->AppUnitsToGfxUnits(mThickness), 0);
   gfxCtx->NewPath();
-  gfxCtx->MoveTo(rect.BottomLeft());
-  gfxCtx->LineTo(rect.BottomLeft() + delta);
-  gfxCtx->LineTo(rect.TopRight());
-  gfxCtx->LineTo(rect.TopRight() - delta);
+
+  if (mRTL) {
+    gfxCtx->MoveTo(rect.TopLeft());
+    gfxCtx->LineTo(rect.TopLeft() + delta);
+    gfxCtx->LineTo(rect.BottomRight());
+    gfxCtx->LineTo(rect.BottomRight() - delta);
+  } else {
+    gfxCtx->MoveTo(rect.BottomLeft());
+    gfxCtx->LineTo(rect.BottomLeft() + delta);
+    gfxCtx->LineTo(rect.TopRight());
+    gfxCtx->LineTo(rect.TopRight() - delta);
+  }
+
   gfxCtx->ClosePath();
   gfxCtx->Fill();
 }
 
 nsresult
 nsMathMLmfracFrame::DisplaySlash(nsDisplayListBuilder* aBuilder,
                                  nsIFrame* aFrame, const nsRect& aRect,
                                  nscoord aThickness,
                                  const nsDisplayListSet& aLists) {
   if (!aFrame->GetStyleVisibility()->IsVisible() || aRect.IsEmpty())
     return NS_OK;
-  
+
   return aLists.Content()->AppendNewToTop(new (aBuilder)
-      nsDisplayMathMLSlash(aBuilder, aFrame, aRect, aThickness));
+      nsDisplayMathMLSlash(aBuilder, aFrame, aRect, aThickness,
+                           NS_MATHML_IS_RTL(mPresentationData.flags)));
 }
--- a/layout/mathml/nsMathMLmmultiscriptsFrame.cpp
+++ b/layout/mathml/nsMathMLmmultiscriptsFrame.cpp
@@ -412,17 +412,21 @@ nsMathMLmmultiscriptsFrame::Place(nsRend
 
     count = 0;
     childFrame = mprescriptsFrame;
     do {
       if (!childFrame) { // end of prescripts,
         // place the base ...
         childFrame = baseFrame;
         dy = aDesiredSize.ascent - baseSize.ascent;
-        FinishReflowChild (baseFrame, PresContext(), nsnull, baseSize, dx, dy, 0);
+        FinishReflowChild (baseFrame, PresContext(), nsnull, baseSize,
+                           MirrorIfRTL(aDesiredSize.width,
+                                       baseSize.width,
+                                       dx),
+                           dy, 0);
         dx += bmBase.width + italicCorrection;
       }
       else if (mprescriptsFrame != childFrame) {
         // process each sup/sub pair
         if (0 == count) {
           subScriptFrame = childFrame;
           count = 1;
         }
@@ -435,23 +439,31 @@ nsMathMLmmultiscriptsFrame::Place(nsRend
           GetReflowAndBoundingMetricsFor(subScriptFrame, subScriptSize, bmSubScript);
           GetReflowAndBoundingMetricsFor(supScriptFrame, supScriptSize, bmSupScript);
 
           // center w.r.t. largest width
           width = NS_MAX(subScriptSize.width, supScriptSize.width);
 
           dy = aDesiredSize.ascent - subScriptSize.ascent +
             maxSubScriptShift;
-          FinishReflowChild (subScriptFrame, PresContext(), nsnull, subScriptSize,
-                             dx + (width-subScriptSize.width)/2, dy, 0);
+          FinishReflowChild (subScriptFrame, PresContext(), nsnull,
+                             subScriptSize,
+                             MirrorIfRTL(aDesiredSize.width,
+                                         subScriptSize.width,
+                                         dx + (width-subScriptSize.width)/2),
+                             dy, 0);
 
           dy = aDesiredSize.ascent - supScriptSize.ascent -
             maxSupScriptShift;
-          FinishReflowChild (supScriptFrame, PresContext(), nsnull, supScriptSize,
-                             dx + (width-supScriptSize.width)/2, dy, 0);
+          FinishReflowChild (supScriptFrame, PresContext(), nsnull,
+                             supScriptSize,
+                             MirrorIfRTL(aDesiredSize.width,
+                                         supScriptSize.width,
+                                         dx + (width-supScriptSize.width)/2),
+                             dy, 0);
 
           dx += width + scriptSpace;
         }
       }
       childFrame = childFrame->GetNextSibling();
     } while (mprescriptsFrame != childFrame);
   }
 
--- a/layout/mathml/nsMathMLmoFrame.cpp
+++ b/layout/mathml/nsMathMLmoFrame.cpp
@@ -261,18 +261,18 @@ nsMathMLmoFrame::ProcessOperatorData()
   if (!mEmbellishData.coreFrame) {
     // i.e., we haven't been here before, the default form is infix
     form = NS_MATHML_OPERATOR_FORM_INFIX;
 
     // reset everything so that we don't keep outdated values around
     // in case of dynamic changes
     mEmbellishData.flags = 0;
     mEmbellishData.coreFrame = nsnull;
-    mEmbellishData.leftSpace = 0;
-    mEmbellishData.rightSpace = 0;
+    mEmbellishData.leadingSpace = 0;
+    mEmbellishData.trailingSpace = 0;
     if (mMathMLChar.Length() != 1)
       mEmbellishData.direction = NS_STRETCH_DIRECTION_UNSUPPORTED;  
     // else... retain the native direction obtained in ProcessTextData()
 
     if (!mFrames.FirstChild()) {
       return;
     }
 
@@ -385,86 +385,86 @@ nsMathMLmoFrame::ProcessOperatorData()
     if (found && (lspace || rspace)) {
       // cache the default values of lspace & rspace that we get from the dictionary.
       // since these values are relative to the 'em' unit, convert to twips now
       nscoord em;
       nsRefPtr<nsFontMetrics> fm;
       nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm));
       GetEmHeight(fm, em);
 
-      mEmbellishData.leftSpace = NSToCoordRound(lspace * em);
-      mEmbellishData.rightSpace = NSToCoordRound(rspace * em);
+      mEmbellishData.leadingSpace = NSToCoordRound(lspace * em);
+      mEmbellishData.trailingSpace = NSToCoordRound(rspace * em);
 
       // tuning if we don't want too much extra space when we are a script.
       // (with its fonts, TeX sets lspace=0 & rspace=0 as soon as scriptlevel>0.
       // Our fonts can be anything, so...)
       if (GetStyleFont()->mScriptLevel > 0) {
         if (NS_MATHML_OPERATOR_EMBELLISH_IS_ISOLATED(mFlags)) {
           // could be an isolated accent or script, e.g., x^{+}, just zero out
-          mEmbellishData.leftSpace = 0;
-          mEmbellishData.rightSpace  = 0;
+          mEmbellishData.leadingSpace = 0;
+          mEmbellishData.trailingSpace  = 0;
         }
         else if (!NS_MATHML_OPERATOR_HAS_EMBELLISH_ANCESTOR(mFlags)) {
-          mEmbellishData.leftSpace /= 2;
-          mEmbellishData.rightSpace  /= 2;
+          mEmbellishData.leadingSpace /= 2;
+          mEmbellishData.trailingSpace  /= 2;
         }
       }
     }
   }
 
   // If we are an accent without explicit lspace="." or rspace=".",
-  // we will ignore our default left/right space
+  // we will ignore our default leading/trailing space
 
   // lspace = number h-unit | namedspace
-  nscoord leftSpace = mEmbellishData.leftSpace;
+  nscoord leadingSpace = mEmbellishData.leadingSpace;
   GetAttribute(mContent, mPresentationData.mstyle, nsGkAtoms::lspace_,
                value);
   if (!value.IsEmpty()) {
     nsCSSValue cssValue;
     if (ParseNumericValue(value, cssValue) ||
         ParseNamedSpaceValue(mPresentationData.mstyle, value, cssValue))
     {
       if ((eCSSUnit_Number == cssValue.GetUnit()) && !cssValue.GetFloatValue())
-        leftSpace = 0;
+        leadingSpace = 0;
       else if (cssValue.IsLengthUnit())
-        leftSpace = CalcLength(presContext, mStyleContext, cssValue);
-      mFlags |= NS_MATHML_OPERATOR_LEFTSPACE_ATTR;
+        leadingSpace = CalcLength(presContext, mStyleContext, cssValue);
+      mFlags |= NS_MATHML_OPERATOR_LSPACE_ATTR;
     }
   }
 
   // rspace = number h-unit | namedspace
-  nscoord rightSpace = mEmbellishData.rightSpace;
+  nscoord trailingSpace = mEmbellishData.trailingSpace;
   GetAttribute(mContent, mPresentationData.mstyle, nsGkAtoms::rspace_,
                value);
   if (!value.IsEmpty()) {
     nsCSSValue cssValue;
     if (ParseNumericValue(value, cssValue) ||
         ParseNamedSpaceValue(mPresentationData.mstyle, value, cssValue))
     {
       if ((eCSSUnit_Number == cssValue.GetUnit()) && !cssValue.GetFloatValue())
-        rightSpace = 0;
+        trailingSpace = 0;
       else if (cssValue.IsLengthUnit())
-        rightSpace = CalcLength(presContext, mStyleContext, cssValue);
-      mFlags |= NS_MATHML_OPERATOR_RIGHTSPACE_ATTR;
+        trailingSpace = CalcLength(presContext, mStyleContext, cssValue);
+      mFlags |= NS_MATHML_OPERATOR_RSPACE_ATTR;
     }
   }
 
   // little extra tuning to round lspace & rspace to at least a pixel so that
   // operators don't look as if they are colliding with their operands
-  if (leftSpace || rightSpace) {
+  if (leadingSpace || trailingSpace) {
     nscoord onePixel = nsPresContext::CSSPixelsToAppUnits(1);
-    if (leftSpace && leftSpace < onePixel)
-      leftSpace = onePixel;
-    if (rightSpace && rightSpace < onePixel)
-      rightSpace = onePixel;
+    if (leadingSpace && leadingSpace < onePixel)
+      leadingSpace = onePixel;
+    if (trailingSpace && trailingSpace < onePixel)
+      trailingSpace = onePixel;
   }
 
   // the values that we get from our attributes override the dictionary
-  mEmbellishData.leftSpace = leftSpace;
-  mEmbellishData.rightSpace = rightSpace;
+  mEmbellishData.leadingSpace = leadingSpace;
+  mEmbellishData.trailingSpace = trailingSpace;
 
   // Now see if there are user-defined attributes that override the dictionary.
   // XXX If an attribute can be forced to be true when it is false in the
   // dictionary, then the following code has to change...
 
   // For each attribute overriden by the user, turn off its bit flag.
   // symmetric|movablelimits|separator|largeop|accent|fence|stretchy|form
   // special: accent and movablelimits are handled above,
@@ -755,17 +755,20 @@ nsMathMLmoFrame::Stretch(nsRenderingCont
           container.descent = aContainerSize.descent;
           container.ascent = height - container.descent;
         }
       }
     }
 
     // let the MathMLChar stretch itself...
     nsresult res = mMathMLChar.Stretch(PresContext(), aRenderingContext,
-                                       aStretchDirection, container, charSize, stretchHint);
+                                       aStretchDirection, container, charSize,
+                                       stretchHint,
+                                       NS_MATHML_IS_RTL(mPresentationData.
+                                                        flags));
     if (NS_FAILED(res)) {
       // gracefully handle cases where stretching the char failed (i.e., GetBoundingMetrics failed)
       // clear our 'form' to behave as if the operator wasn't in the dictionary
       mFlags &= ~NS_MATHML_OPERATOR_FORM;
       useMathMLChar = false;
     }
   }
 
@@ -866,46 +869,49 @@ nsMathMLmoFrame::Stretch(nsRenderingCont
   // Before we leave... there is a last item in the check-list:
   // If our parent is not embellished, it means we are the outermost embellished
   // container and so we put the spacing, otherwise we don't include the spacing,
   // the outermost embellished container will take care of it.
 
   if (!NS_MATHML_OPERATOR_HAS_EMBELLISH_ANCESTOR(mFlags)) {
 
     // Account the spacing if we are not an accent with explicit attributes
-    nscoord leftSpace = mEmbellishData.leftSpace;
-    if (isAccent && !NS_MATHML_OPERATOR_HAS_LEFTSPACE_ATTR(mFlags)) {
-      leftSpace = 0;
+    nscoord leadingSpace = mEmbellishData.leadingSpace;
+    if (isAccent && !NS_MATHML_OPERATOR_HAS_LSPACE_ATTR(mFlags)) {
+      leadingSpace = 0;
     }
-    nscoord rightSpace = mEmbellishData.rightSpace;
-    if (isAccent && !NS_MATHML_OPERATOR_HAS_RIGHTSPACE_ATTR(mFlags)) {
-      rightSpace = 0;
+    nscoord trailingSpace = mEmbellishData.trailingSpace;
+    if (isAccent && !NS_MATHML_OPERATOR_HAS_RSPACE_ATTR(mFlags)) {
+      trailingSpace = 0;
     }
 
-    mBoundingMetrics.width += leftSpace + rightSpace;
+    mBoundingMetrics.width += leadingSpace + trailingSpace;
     aDesiredStretchSize.width = mBoundingMetrics.width;
     aDesiredStretchSize.mBoundingMetrics.width = mBoundingMetrics.width;
 
-    if (leftSpace) {
+    nscoord dx = (NS_MATHML_IS_RTL(mPresentationData.flags) ?
+                  trailingSpace : leadingSpace);
+    if (dx) {
       // adjust the offsets
-      mBoundingMetrics.leftBearing += leftSpace;
-      mBoundingMetrics.rightBearing += leftSpace;
-      aDesiredStretchSize.mBoundingMetrics.leftBearing += leftSpace;
-      aDesiredStretchSize.mBoundingMetrics.rightBearing += leftSpace;
+      mBoundingMetrics.leftBearing += dx;
+      mBoundingMetrics.rightBearing += dx;
+      aDesiredStretchSize.mBoundingMetrics.leftBearing += dx;
+      aDesiredStretchSize.mBoundingMetrics.rightBearing += dx;
 
       if (useMathMLChar) {
         nsRect rect;
         mMathMLChar.GetRect(rect);
-        mMathMLChar.SetRect(nsRect(rect.x + leftSpace, rect.y, rect.width, rect.height));
+        mMathMLChar.SetRect(nsRect(rect.x + dx, rect.y,
+                                   rect.width, rect.height));
       }
       else {
         nsIFrame* childFrame = firstChild;
         while (childFrame) {
-          childFrame->SetPosition(childFrame->GetPosition()
-				  + nsPoint(leftSpace, 0));
+          childFrame->SetPosition(childFrame->GetPosition() +
+                                  nsPoint(dx, 0));
           childFrame = childFrame->GetNextSibling();
         }
       }
     }
   }
 
   // Finished with these:
   ClearSavedChildMetrics();
@@ -1006,20 +1012,20 @@ nsMathMLmoFrame::GetIntrinsicWidth(nsRen
       GetMaxWidth(PresContext(), *aRenderingContext,
                   stretchHint, mMaxSize,
                   NS_MATHML_OPERATOR_MAXSIZE_IS_ABSOLUTE(mFlags));
   }
   else {
     width = nsMathMLTokenFrame::GetIntrinsicWidth(aRenderingContext);
   }
 
-  // leftSpace and rightSpace are actually applied to the outermost
+  // leadingSpace and trailingSpace are actually applied to the outermost
   // embellished container but for determining total intrinsic width it should
   // be safe to include it for the core here instead.
-  width += mEmbellishData.leftSpace + mEmbellishData.rightSpace;
+  width += mEmbellishData.leadingSpace + mEmbellishData.trailingSpace;
 
   return width;
 }
 
 NS_IMETHODIMP
 nsMathMLmoFrame::AttributeChanged(PRInt32         aNameSpaceID,
                                   nsIAtom*        aAttribute,
                                   PRInt32         aModType)
--- a/layout/mathml/nsMathMLmpaddedFrame.cpp
+++ b/layout/mathml/nsMathMLmpaddedFrame.cpp
@@ -128,20 +128,21 @@ nsMathMLmpaddedFrame::ProcessAttributes(
   // depth
   mDepthSign = NS_MATHML_SIGN_INVALID;
   GetAttribute(mContent, nsnull, nsGkAtoms::depth_, value);
   if (!value.IsEmpty()) {
     ParseAttribute(value, mDepthSign, mDepth, mDepthPseudoUnit);
   }
 
   // lspace
-  mLeftSpaceSign = NS_MATHML_SIGN_INVALID;
+  mLeadingSpaceSign = NS_MATHML_SIGN_INVALID;
   GetAttribute(mContent, nsnull, nsGkAtoms::lspace_, value);
   if (!value.IsEmpty()) {
-    ParseAttribute(value, mLeftSpaceSign, mLeftSpace, mLeftSpacePseudoUnit);
+    ParseAttribute(value, mLeadingSpaceSign, mLeadingSpace,
+                   mLeadingSpacePseudoUnit);
   }
 
   // voffset
   mVerticalOffsetSign = NS_MATHML_SIGN_INVALID;
   GetAttribute(mContent, nsnull, nsGkAtoms::voffset_, value);
   if (!value.IsEmpty()) {
     ParseAttribute(value, mVerticalOffsetSign, mVerticalOffset, 
                    mVerticalOffsetPseudoUnit);
@@ -375,40 +376,46 @@ nsMathMLmpaddedFrame::Place(nsRenderingC
     nsMathMLContainerFrame::Place(aRenderingContext, false, aDesiredSize);
   if (NS_MATHML_HAS_ERROR(mPresentationData.flags) || NS_FAILED(rv)) {
     DidReflowChildren(GetFirstPrincipalChild());
     return rv;
   }
 
   nscoord height = mBoundingMetrics.ascent;
   nscoord depth  = mBoundingMetrics.descent;
-  // In MathML2 (http://www.w3.org/TR/MathML2/chapter3.html#presm.mpadded),
-  // lspace is "the amount of space between the left edge of a bounding box
-  // and the start of the rendering of its contents' bounding box" and the
-  // default is zero.
+  // The REC says:
+  //
+  // "The lspace attribute ('leading' space) specifies the horizontal location
+  // of the positioning point of the child content with respect to the
+  // positioning point of the mpadded element. By default they coincide, and
+  // therefore absolute values for lspace have the same effect as relative
+  // values."
   //
-  // In MathML3 draft
-  // http://www.w3.org/TR/2007/WD-MathML3-20070427/chapter3.html#id.3.3.6.2,
-  // lspace is "the amount of space between the left edge of the bounding box
-  // and the positioning poin [sic] of the mpadded element" and the default is
-  // "same as content".
+  // "MathML renderers should ensure that, except for the effects of the
+  // attributes, the relative spacing between the contents of the mpadded
+  // element and surrounding MathML elements would not be modified by replacing
+  // an mpadded element with an mrow element with the same content, even if
+  // linebreaking occurs within the mpadded element."
   //
-  // In both cases, "MathML renderers should ensure that, except for the
-  // effects of the attributes, relative spacing between the contents of
-  // mpadded and surrounding MathML elements is not modified by replacing an
-  // mpadded element with an mrow element with the same content."
+  // (http://www.w3.org/TR/MathML/chapter3.html#presm.mpadded)
+  // 
+  // "In those discussions, the terms leading and trailing are used to specify
+  // a side of an object when which side to use depends on the directionality;
+  // ie. leading means left in LTR but right in RTL."
+  // (http://www.w3.org/TR/MathML/chapter3.html#presm.bidi.math)
   nscoord lspace = 0;
-  // In MATHML3, "width" will be the bounding box width and "advancewidth" will
+  // In MathML3, "width" will be the bounding box width and "advancewidth" will
   // refer "to the horizontal distance between the positioning point of the
   // mpadded and the positioning point for the following content".  MathML2
   // doesn't make the distinction.
   nscoord width  = mBoundingMetrics.width;
   nscoord voffset = 0;
 
   PRInt32 pseudoUnit;
+  nscoord initialWidth = width;
 
   // update width
   pseudoUnit = (mWidthPseudoUnit == NS_MATHML_PSEUDO_UNIT_ITSELF)
              ? NS_MATHML_PSEUDO_UNIT_WIDTH : mWidthPseudoUnit;
   UpdateValue(mWidthSign, pseudoUnit, mWidth,
               mBoundingMetrics, width);
   width = NS_MAX(0, width);
 
@@ -422,48 +429,53 @@ nsMathMLmpaddedFrame::Place(nsRenderingC
   // update "depth" (this is the descent in the terminology of the REC)
   pseudoUnit = (mDepthPseudoUnit == NS_MATHML_PSEUDO_UNIT_ITSELF)
              ? NS_MATHML_PSEUDO_UNIT_DEPTH : mDepthPseudoUnit;
   UpdateValue(mDepthSign, pseudoUnit, mDepth,
               mBoundingMetrics, depth);
   depth = NS_MAX(0, depth);
 
   // update lspace
-  if (mLeftSpacePseudoUnit != NS_MATHML_PSEUDO_UNIT_ITSELF) {
-    pseudoUnit = mLeftSpacePseudoUnit;
-    UpdateValue(mLeftSpaceSign, pseudoUnit, mLeftSpace,
+  if (mLeadingSpacePseudoUnit != NS_MATHML_PSEUDO_UNIT_ITSELF) {
+    pseudoUnit = mLeadingSpacePseudoUnit;
+    UpdateValue(mLeadingSpaceSign, pseudoUnit, mLeadingSpace,
                 mBoundingMetrics, lspace);
   }
 
   // update voffset
   if (mVerticalOffsetPseudoUnit != NS_MATHML_PSEUDO_UNIT_ITSELF) {
     pseudoUnit = mVerticalOffsetPseudoUnit;
     UpdateValue(mVerticalOffsetSign, pseudoUnit, mVerticalOffset,
                 mBoundingMetrics, voffset);
   }
   // do the padding now that we have everything
   // The idea here is to maintain the invariant that <mpadded>...</mpadded> (i.e.,
   // with no attributes) looks the same as <mrow>...</mrow>. But when there are
   // attributes, tweak our metrics and move children to achieve the desired visual
   // effects.
 
-  if (mLeftSpaceSign != NS_MATHML_SIGN_INVALID) { // there was padding on the left
-    // dismiss the left italic correction now (so that our parent won't correct us)
+  if ((NS_MATHML_IS_RTL(mPresentationData.flags) ?
+       mWidthSign : mLeadingSpaceSign) != NS_MATHML_SIGN_INVALID) {
+    // there was padding on the left. dismiss the left italic correction now
+    // (so that our parent won't correct us)
     mBoundingMetrics.leftBearing = 0;
   }
 
-  if (mWidthSign != NS_MATHML_SIGN_INVALID) { // there was padding on the right
-    // dismiss the right italic correction now (so that our parent won't correct us)
+  if ((NS_MATHML_IS_RTL(mPresentationData.flags) ?
+       mLeadingSpaceSign : mWidthSign) != NS_MATHML_SIGN_INVALID) {
+    // there was padding on the right. dismiss the right italic correction now
+    // (so that our parent won't correct us)
     mBoundingMetrics.width = width;
     mBoundingMetrics.rightBearing = mBoundingMetrics.width;
   }
 
   nscoord dy = height - mBoundingMetrics.ascent;
-  nscoord dx = lspace;
-
+  nscoord dx = NS_MATHML_IS_RTL(mPresentationData.flags) ?
+    width - initialWidth - lspace : lspace;
+    
   aDesiredSize.ascent += dy;
   aDesiredSize.width = mBoundingMetrics.width;
   aDesiredSize.height += dy + depth - mBoundingMetrics.descent;
   mBoundingMetrics.ascent = height;
   mBoundingMetrics.descent = depth;
   aDesiredSize.mBoundingMetrics = mBoundingMetrics;
 
   mReference.x = 0;
--- a/layout/mathml/nsMathMLmpaddedFrame.h
+++ b/layout/mathml/nsMathMLmpaddedFrame.h
@@ -78,29 +78,29 @@ protected:
   virtual ~nsMathMLmpaddedFrame();
   
   virtual PRIntn GetSkipSides() const { return 0; }
 
 private:
   nsCSSValue mWidth;
   nsCSSValue mHeight;
   nsCSSValue mDepth;
-  nsCSSValue mLeftSpace;
+  nsCSSValue mLeadingSpace;
   nsCSSValue mVerticalOffset;
 
   PRInt32    mWidthSign;
   PRInt32    mHeightSign;
   PRInt32    mDepthSign;
-  PRInt32    mLeftSpaceSign;
+  PRInt32    mLeadingSpaceSign;
   PRInt32    mVerticalOffsetSign;
 
   PRInt32    mWidthPseudoUnit;
   PRInt32    mHeightPseudoUnit;
   PRInt32    mDepthPseudoUnit;
-  PRInt32    mLeftSpacePseudoUnit;
+  PRInt32    mLeadingSpacePseudoUnit;
   PRInt32    mVerticalOffsetPseudoUnit;
 
   // helpers to process the attributes
   void
   ProcessAttributes();
 
   static bool
   ParseAttribute(nsString&   aString,
--- a/layout/mathml/nsMathMLmrootFrame.cpp
+++ b/layout/mathml/nsMathMLmrootFrame.cpp
@@ -306,17 +306,18 @@ nsMathMLmrootFrame::Reflow(nsPresContext
   contSize.descent = bmBase.ascent + bmBase.descent + psi;
   contSize.ascent = ruleThickness;
 
   // height(radical) should be >= height(base) + psi + ruleThickness
   nsBoundingMetrics radicalSize;
   mSqrChar.Stretch(aPresContext, renderingContext,
                    NS_STRETCH_DIRECTION_VERTICAL, 
                    contSize, radicalSize,
-                   NS_STRETCH_LARGER);
+                   NS_STRETCH_LARGER,
+                   NS_MATHML_IS_RTL(mPresentationData.flags));
   // radicalSize have changed at this point, and should match with
   // the bounding metrics of the char
   mSqrChar.GetBoundingMetrics(bmSqr);
 
   // Update the desired size for the container (like msqrt, index is not yet included)
   // the baseline will be that of the base.
   mBoundingMetrics.ascent = bmBase.ascent + psi + ruleThickness;
   mBoundingMetrics.descent = 
@@ -351,45 +352,51 @@ nsMathMLmrootFrame::Reflow(nsPresContext
     nscoord descent = aDesiredSize.height - aDesiredSize.ascent;
     aDesiredSize.ascent = mBoundingMetrics.ascent + leading;
     aDesiredSize.height = aDesiredSize.ascent + descent;
   }
 
   nscoord dxIndex, dxSqr;
   GetRadicalXOffsets(bmIndex.width, bmSqr.width, fm, &dxIndex, &dxSqr);
 
-  // place the index
-  nscoord dx = dxIndex;
-  nscoord dy = aDesiredSize.ascent - (indexRaisedAscent + indexSize.ascent - bmIndex.ascent);
-  FinishReflowChild(indexFrame, aPresContext, nsnull, indexSize, dx, dy, 0);
-
-  // place the radical symbol and the radical bar
-  dx = dxSqr;
-  dy = indexClearance + leading; // leave a leading at the top
-  mSqrChar.SetRect(nsRect(dx, dy, bmSqr.width, bmSqr.ascent + bmSqr.descent));
-  dx += bmSqr.width;
-  mBarRect.SetRect(dx, dy, bmBase.width, ruleThickness);
-
-  // place the base
-  dy = aDesiredSize.ascent - baseSize.ascent;
-  FinishReflowChild(baseFrame, aPresContext, nsnull, baseSize, dx, dy, 0);
-
-  mReference.x = 0;
-  mReference.y = aDesiredSize.ascent;
-
-  mBoundingMetrics.width = dx + bmBase.width;
+  mBoundingMetrics.width = dxSqr + bmSqr.width + bmBase.width;
   mBoundingMetrics.leftBearing = 
     NS_MIN(dxIndex + bmIndex.leftBearing, dxSqr + bmSqr.leftBearing);
-  mBoundingMetrics.rightBearing = dx +
+  mBoundingMetrics.rightBearing = dxSqr + bmSqr.width +
     NS_MAX(bmBase.width, bmBase.rightBearing);
 
   aDesiredSize.width = mBoundingMetrics.width;
   aDesiredSize.mBoundingMetrics = mBoundingMetrics;
   GatherAndStoreOverflow(&aDesiredSize);
 
+  // place the index
+  nscoord dx = dxIndex;
+  nscoord dy = aDesiredSize.ascent - (indexRaisedAscent + indexSize.ascent - bmIndex.ascent);
+  FinishReflowChild(indexFrame, aPresContext, nsnull, indexSize,
+                    MirrorIfRTL(aDesiredSize.width, indexSize.width, dx),
+                    dy, 0);
+
+  // place the radical symbol and the radical bar
+  dx = dxSqr;
+  dy = indexClearance + leading; // leave a leading at the top
+  mSqrChar.SetRect(nsRect(MirrorIfRTL(aDesiredSize.width, bmSqr.width, dx),
+                          dy, bmSqr.width, bmSqr.ascent + bmSqr.descent));
+  dx += bmSqr.width;
+  mBarRect.SetRect(MirrorIfRTL(aDesiredSize.width, bmBase.width, dx),
+                   dy, bmBase.width, ruleThickness);
+
+  // place the base
+  dy = aDesiredSize.ascent - baseSize.ascent;
+  FinishReflowChild(baseFrame, aPresContext, nsnull, baseSize,
+                    MirrorIfRTL(aDesiredSize.width, baseSize.width, dx),
+                    dy, 0);
+
+  mReference.x = 0;
+  mReference.y = aDesiredSize.ascent;
+
   aStatus = NS_FRAME_COMPLETE;
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
   return NS_OK;
 }
 
 /* virtual */ nscoord
 nsMathMLmrootFrame::GetIntrinsicWidth(nsRenderingContext* aRenderingContext)
 {
--- a/layout/mathml/nsMathMLmrowFrame.cpp
+++ b/layout/mathml/nsMathMLmrowFrame.cpp
@@ -17,16 +17,17 @@
  * The Initial Developer of the Original Code is
  * The University Of Queensland.
  * Portions created by the Initial Developer are Copyright (C) 1999
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Roger B. Sidje <rbs@maths.uq.edu.au>
  *   David J. Fiddes <D.J.Fiddes@hw.ac.uk>
+ *   Frederic Wang <fred.wang@free.fr>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either of the GNU General Public License Version 2 or later (the "GPL"),
  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -64,16 +65,21 @@ nsMathMLmrowFrame::~nsMathMLmrowFrame()
 NS_IMETHODIMP
 nsMathMLmrowFrame::InheritAutomaticData(nsIFrame* aParent)
 {
   // let the base class get the default from our parent
   nsMathMLContainerFrame::InheritAutomaticData(aParent);
 
   mPresentationData.flags |= NS_MATHML_STRETCH_ALL_CHILDREN_VERTICALLY;
 
+  if (mContent->Tag() == nsGkAtoms::mrow_) {
+    // see if the directionality attribute is there
+    nsMathMLFrame::FindAttrDirectionality(mContent, mPresentationData);
+  }
+
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsMathMLmrowFrame::AttributeChanged(PRInt32  aNameSpaceID,
                                     nsIAtom* aAttribute,
                                     PRInt32  aModType)
 {
--- a/layout/mathml/nsMathMLmstyleFrame.cpp
+++ b/layout/mathml/nsMathMLmstyleFrame.cpp
@@ -17,16 +17,17 @@
  * The Initial Developer of the Original Code is
  * The University Of Queensland.
  * Portions created by the Initial Developer are Copyright (C) 1999
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Roger B. Sidje <rbs@maths.uq.edu.au>
  *   David J. Fiddes <D.J.Fiddes@hw.ac.uk>
+ *   Frederic Wang <fred.wang@free.fr>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either of the GNU General Public License Version 2 or later (the "GPL"),
  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -71,16 +72,19 @@ nsMathMLmstyleFrame::InheritAutomaticDat
 
   // sync with our current state
   mPresentationData.flags |= NS_MATHML_STRETCH_ALL_CHILDREN_VERTICALLY;
   mPresentationData.mstyle = this;
 
   // see if the displaystyle attribute is there
   nsMathMLFrame::FindAttrDisplaystyle(mContent, mPresentationData);
 
+  // see if the directionality attribute is there
+  nsMathMLFrame::FindAttrDirectionality(mContent, mPresentationData);
+
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsMathMLmstyleFrame::TransmitAutomaticData()
 {
   return TransmitAutomaticDataForMrowLikeElement();
 }
--- a/layout/mathml/nsMathMLmsubFrame.cpp
+++ b/layout/mathml/nsMathMLmsubFrame.cpp
@@ -198,18 +198,20 @@ nsMathMLmsubFrame::PlaceSubScript (nsPre
   aDesiredSize.width = boundingMetrics.width;
   aDesiredSize.mBoundingMetrics = boundingMetrics;
 
   aFrame->SetReference(nsPoint(0, aDesiredSize.ascent));
 
   if (aPlaceOrigin) {
     nscoord dx, dy;
     // now place the base ...
-    dx = 0; dy = aDesiredSize.ascent - baseSize.ascent;
+    dx = aFrame->MirrorIfRTL(aDesiredSize.width, baseSize.width, 0);
+    dy = aDesiredSize.ascent - baseSize.ascent;
     FinishReflowChild (baseFrame, aPresContext, nsnull, baseSize, dx, dy, 0);
     // ... and subscript
-    dx = bmBase.width; 
+    dx = aFrame->MirrorIfRTL(aDesiredSize.width, subScriptSize.width,
+                             bmBase.width);
     dy = aDesiredSize.ascent - (subScriptSize.ascent - actualSubScriptShift);
     FinishReflowChild (subScriptFrame, aPresContext, nsnull, subScriptSize, dx, dy, 0);
   }
 
   return NS_OK;
 }
--- a/layout/mathml/nsMathMLmsubsupFrame.cpp
+++ b/layout/mathml/nsMathMLmsubsupFrame.cpp
@@ -331,25 +331,28 @@ nsMathMLmsubsupFrame::PlaceSubSupScript(
   aDesiredSize.width = boundingMetrics.width;
   aDesiredSize.mBoundingMetrics = boundingMetrics;
 
   aFrame->SetReference(nsPoint(0, aDesiredSize.ascent));
 
   if (aPlaceOrigin) {
     nscoord dx, dy;
     // now place the base ...
-    dx = 0; dy = aDesiredSize.ascent - baseSize.ascent;
+    dx = aFrame->MirrorIfRTL(aDesiredSize.width, baseSize.width, 0);
+    dy = aDesiredSize.ascent - baseSize.ascent;
     FinishReflowChild(baseFrame, aPresContext, nsnull,
                       baseSize, dx, dy, 0);
     // ... and subscript
-    dx = bmBase.width;
+    dx = aFrame->MirrorIfRTL(aDesiredSize.width, subScriptSize.width,
+                             bmBase.width);
     dy = aDesiredSize.ascent - (subScriptSize.ascent - subScriptShift);
     FinishReflowChild(subScriptFrame, aPresContext, nsnull,
                       subScriptSize, dx, dy, 0);
     // ... and the superscript
-    dx = bmBase.width + italicCorrection;
+    dx = aFrame->MirrorIfRTL(aDesiredSize.width, supScriptSize.width,
+                             bmBase.width + italicCorrection);
     dy = aDesiredSize.ascent - (supScriptSize.ascent + supScriptShift);
     FinishReflowChild(supScriptFrame, aPresContext, nsnull,
                       supScriptSize, dx, dy, 0);
   }
 
   return NS_OK;
 }
--- a/layout/mathml/nsMathMLmsupFrame.cpp
+++ b/layout/mathml/nsMathMLmsupFrame.cpp
@@ -236,18 +236,20 @@ nsMathMLmsupFrame::PlaceSuperScript(nsPr
   aDesiredSize.width = boundingMetrics.width;
   aDesiredSize.mBoundingMetrics = boundingMetrics;
 
   aFrame->SetReference(nsPoint(0, aDesiredSize.ascent));
 
   if (aPlaceOrigin) {
     nscoord dx, dy;
     // now place the base ...
-    dx = 0; dy = aDesiredSize.ascent - baseSize.ascent;
+    dx = aFrame->MirrorIfRTL(aDesiredSize.width, baseSize.width, 0);
+    dy = aDesiredSize.ascent - baseSize.ascent;
     FinishReflowChild (baseFrame, aPresContext, nsnull, baseSize, dx, dy, 0);
     // ... and supscript
-    dx = bmBase.width + italicCorrection;
+    dx = aFrame->MirrorIfRTL(aDesiredSize.width, supScriptSize.width,
+                             bmBase.width + italicCorrection);
     dy = aDesiredSize.ascent - (supScriptSize.ascent + actualSupScriptShift);
     FinishReflowChild (supScriptFrame, aPresContext, nsnull, supScriptSize, dx, dy, 0);
   }
 
   return NS_OK;
 }
--- a/layout/printing/nsPrintData.h
+++ b/layout/printing/nsPrintData.h
@@ -29,19 +29,22 @@
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
+
 #ifndef nsPrintData_h___
 #define nsPrintData_h___
 
+#include "mozilla/Attributes.h"
+
 // Interfaces
 #include "nsIDOMWindow.h"
 #include "nsDeviceContext.h"
 #include "nsIPrintProgressParams.h"
 #include "nsIPrintOptions.h"
 #include "nsTArray.h"
 #include "nsCOMArray.h"
 #include "nsAutoPtr.h"
@@ -118,15 +121,15 @@ public:
   float                       mOrigDCScale;
 
   nsCOMPtr<nsIPrintSettings>  mPrintSettings;
   nsPrintPreviewListener*     mPPEventListeners;
 
   PRUnichar*            mBrandName; //  needed as a substitute name for a document
 
 private:
-  nsPrintData(); //not implemented
-  nsPrintData& operator=(const nsPrintData& aOther); // not implemented
+  nsPrintData() MOZ_DELETE;
+  nsPrintData& operator=(const nsPrintData& aOther) MOZ_DELETE;
 
 };
 
 #endif /* nsPrintData_h___ */
 
--- a/layout/printing/nsPrintEngine.h
+++ b/layout/printing/nsPrintEngine.h
@@ -32,16 +32,18 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 #ifndef nsPrintEngine_h___
 #define nsPrintEngine_h___
 
+#include "mozilla/Attributes.h"
+
 #include "nsCOMPtr.h"
 
 #include "nsPrintObject.h"
 #include "nsPrintData.h"
 #include "nsFrameList.h"
 
 // Interfaces
 #include "nsIDocument.h"
@@ -293,13 +295,12 @@ protected:
   nsPrintData*            mPrtPreview;
   nsPrintData*            mOldPrtPreview;
 
   nsCOMPtr<nsIDocument>   mDocument;
 
   FILE* mDebugFile;
 
 private:
-  nsPrintEngine& operator=(const nsPrintEngine& aOther); // not implemented
-
+  nsPrintEngine& operator=(const nsPrintEngine& aOther) MOZ_DELETE;
 };
 
 #endif /* nsPrintEngine_h___ */
--- a/layout/printing/nsPrintObject.h
+++ b/layout/printing/nsPrintObject.h
@@ -32,16 +32,18 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 #ifndef nsPrintObject_h___
 #define nsPrintObject_h___
 
+#include "mozilla/Attributes.h"
+
 // Interfaces
 #include "nsCOMPtr.h"
 #include "nsIContent.h"
 #include "nsIPresShell.h"
 #include "nsStyleSet.h"
 #include "nsIViewManager.h"
 #include "nsIDocShell.h"
 #include "nsIDocument.h"
@@ -89,16 +91,15 @@ public:
   bool             mSharedPresShell;
   bool             mInvisible;        // Indicates PO is set to not visible by CSS
   bool             mPrintPreview;
   bool             mDidCreateDocShell;
   float            mShrinkRatio;
   float            mZoomRatio;
 
 private:
-  nsPrintObject& operator=(const nsPrintObject& aOther); // not implemented
-
+  nsPrintObject& operator=(const nsPrintObject& aOther) MOZ_DELETE;
 };
 
 
 
 #endif /* nsPrintObject_h___ */
 
new file mode 100644
--- /dev/null
+++ b/layout/reftests/mathml/dir-1-ref.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html>
+  <head><title>Test dir=rtl</title></head>
+  <body>
+    <p>
+      math:
+      <math>
+        <mspace width="25px" height="25px" mathbackground="blue"/>
+        <mspace width="25px" height="25px" mathbackground="green"/>
+        <mspace width="25px" height="25px" mathbackground="red"/>
+      </math>
+    </p>
+
+    <p>
+      mrow:
+      <math>
+        <mrow>
+          <mspace width="25px" height="25px" mathbackground="blue"/>
+          <mspace width="25px" height="25px" mathbackground="green"/>
+          <mspace width="25px" height="25px" mathbackground="red"/>
+        </mrow>
+      </math>
+    </p>
+
+    <p>
+      mstyle:
+      <math>
+        <mstyle>
+          <mspace width="25px" height="25px" mathbackground="blue"/>
+          <mspace width="25px" height="25px" mathbackground="green"/>
+          <mspace width="25px" height="25px" mathbackground="red"/>
+        </mstyle>
+      </math>
+    </p>
+
+    <p>
+      mpadded lspace="25px" width="150px":
+      <math>
+        <mspace width="1px" height="25px" mathbackground="black"/>
+        <mpadded lspace="50px" width="150px">
+          <mspace width="25px" height="25px" mathbackground="blue"/>
+          <mspace width="25px" height="25px" mathbackground="green"/>
+          <mspace width="25px" height="25px" mathbackground="red"/>
+        </mpadded>
+        <mspace width="1px" height="25px" mathbackground="black"/>
+      </math>
+    </p>
+
+    <p>
+      mfenced open="A" close="D" separators="BC":
+      <math>
+        <mfenced open="D" close="A" separators="CB">
+          <mtext>c</mtext>
+          <mtext>b</mtext>
+          <mtext>a</mtext>
+        </mfenced>
+      </math>
+    </p>
+
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/mathml/dir-1.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html>
+  <head><title>Test dir=rtl</title></head>
+  <body>
+    <p>
+      math:
+      <math dir="rtl">
+        <mspace width="25px" height="25px" mathbackground="red"/>
+        <mspace width="25px" height="25px" mathbackground="green"/>
+        <mspace width="25px" height="25px" mathbackground="blue"/>
+      </math>
+    </p>
+
+    <p>
+      mrow:
+      <math>
+        <mrow dir="rtl">
+          <mspace width="25px" height="25px" mathbackground="red"/>
+          <mspace width="25px" height="25px" mathbackground="green"/>
+          <mspace width="25px" height="25px" mathbackground="blue"/>
+        </mrow>
+      </math>
+    </p>
+
+    <p>
+      mstyle:
+      <math>
+        <mstyle dir="rtl">
+          <mspace width="25px" height="25px" mathbackground="red"/>
+          <mspace width="25px" height="25px" mathbackground="green"/>
+          <mspace width="25px" height="25px" mathbackground="blue"/>
+        </mstyle>
+      </math>
+    </p>
+
+    <p>
+      mpadded lspace="25px" width="150px":
+      <math dir="rtl">
+        <mspace width="1px" height="25px" mathbackground="black"/>
+        <mpadded lspace="25px" width="150px">
+          <mspace width="25px" height="25px" mathbackground="red"/>
+          <mspace width="25px" height="25px" mathbackground="green"/>
+          <mspace width="25px" height="25px" mathbackground="blue"/>
+        </mpadded>
+        <mspace width="1px" height="25px" mathbackground="black"/>
+      </math>
+    </p>
+
+    <p>
+      mfenced open="A" close="D" separators="BC":
+      <math dir="rtl">
+        <mfenced open="A" close="D" separators="BC">
+          <mtext>a</mtext>
+          <mtext>b</mtext>
+          <mtext>c</mtext>
+        </mfenced>
+      </math>
+    </p>
+
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/mathml/dir-2-ref.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html>
+<html>
+  <head><title>Test dir=rtl</title></head>
+  <body>
+    <p>
+      mfrac (numalign=left):
+      <math>
+        <mfrac numalign="left">
+          <mspace width="25px" height="25px" mathbackground="red"/>
+          <mspace width="75px" height="25px" mathbackground="green"/>
+        </mfrac>
+      </math>
+    </p>
+
+    <p>
+      mfrac (numalign=right):
+      <math>
+        <mfrac numalign="right">
+          <mspace width="25px" height="25px" mathbackground="red"/>
+          <mspace width="75px" height="25px" mathbackground="green"/>
+        </mfrac>
+      </math>
+    </p>
+
+    <p>
+      menclose:
+      <math>
+        <menclose>
+          <mspace width="25px" height="25px" mathbackground="blue"/>
+          <mspace width="25px" height="25px" mathbackground="green"/>
+          <mspace width="25px" height="25px" mathbackground="red"/>
+        </menclose>
+      </math>
+    </p>
+
+    <p>
+      menclose notation="left":
+      <math>
+        <menclose notation="left">
+          <mspace width="25px" height="25px" mathbackground="blue"/>
+          <mspace width="25px" height="25px" mathbackground="green"/>
+          <mspace width="25px" height="25px" mathbackground="red"/>
+        </menclose>
+      </math>
+    </p>
+
+    <p>
+      menclose notation="right":
+      <math>
+        <menclose notation="right">
+          <mspace width="25px" height="25px" mathbackground="blue"/>
+          <mspace width="25px" height="25px" mathbackground="green"/>
+          <mspace width="25px" height="25px" mathbackground="red"/>
+        </menclose>
+      </math>
+    </p>
+
+    <p>
+      menclose notation="updiagonalstrike":
+      <math>
+        <menclose notation="updiagonalstrike">
+          <mspace width="25px" height="25px" mathbackground="blue"/>
+          <mspace width="25px" height="25px" mathbackground="green"/>
+          <mspace width="25px" height="25px" mathbackground="red"/>
+        </menclose>
+      </math>
+    </p>
+
+    <p>
+      menclose notation="downdiagonalstrike":
+      <math>
+        <menclose notation="downdiagonalstrike">
+          <mspace width="25px" height="25px" mathbackground="blue"/>
+          <mspace width="25px" height="25px" mathbackground="green"/>
+          <mspace width="25px" height="25px" mathbackground="red"/>
+        </menclose>
+      </math>
+    </p>
+
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/mathml/dir-2.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html>
+<html>
+  <head><title>Test dir=rtl</title></head>
+  <body>
+    <p>
+      mfrac (numalign=left):
+      <math dir="rtl">
+        <mfrac numalign="left">
+          <mspace width="25px" height="25px" mathbackground="red"/>
+          <mspace width="75px" height="25px" mathbackground="green"/>
+        </mfrac>
+      </math>
+    </p>
+
+    <p>
+      mfrac (numalign=right):
+      <math dir="rtl">
+        <mfrac numalign="right">
+          <mspace width="25px" height="25px" mathbackground="red"/>
+          <mspace width="75px" height="25px" mathbackground="green"/>
+        </mfrac>
+      </math>
+    </p>
+
+    <p>
+      menclose:
+      <math dir="rtl">
+        <menclose>
+          <mspace width="25px" height="25px" mathbackground="red"/>
+          <mspace width="25px" height="25px" mathbackground="green"/>
+          <mspace width="25px" height="25px" mathbackground="blue"/>
+        </menclose>
+      </math>
+    </p>
+
+    <p>
+      menclose notation="left":
+      <math dir="rtl">
+        <menclose notation="left">
+          <mspace width="25px" height="25px" mathbackground="red"/>
+          <mspace width="25px" height="25px" mathbackground="green"/>
+          <mspace width="25px" height="25px" mathbackground="blue"/>
+        </menclose>
+      </math>
+    </p>
+
+    <p>
+      menclose notation="right":
+      <math dir="rtl">
+        <menclose notation="right">
+          <mspace width="25px" height="25px" mathbackground="red"/>
+          <mspace width="25px" height="25px" mathbackground="green"/>
+          <mspace width="25px" height="25px" mathbackground="blue"/>
+        </menclose>
+      </math>
+    </p>
+
+    <p>
+      menclose notation="updiagonalstrike":
+      <math dir="rtl">
+        <menclose notation="updiagonalstrike">
+          <mspace width="25px" height="25px" mathbackground="red"/>
+          <mspace width="25px" height="25px" mathbackground="green"/>
+          <mspace width="25px" height="25px" mathbackground="blue"/>
+        </menclose>
+      </math>
+    </p>
+
+    <p>
+      menclose notation="downdiagonalstrike":
+      <math dir="rtl">
+        <menclose notation="downdiagonalstrike">
+          <mspace width="25px" height="25px" mathbackground="red"/>
+          <mspace width="25px" height="25px" mathbackground="green"/>
+          <mspace width="25px" height="25px" mathbackground="blue"/>
+        </menclose>
+      </math>
+    </p>
+
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/mathml/dir-3-ref.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+  <head><title>Test dir=rtl</title></head>
+  <body style="background: white;">
+
+    <div style="position: absolute; top: 5px; left: 5px;">
+      <div style="width: 30px; height: 500px; background: black;"></div>
+    </div>
+
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/mathml/dir-3.html
@@ -0,0 +1,114 @@
+<!DOCTYPE html>
+<html>
+  <head><title>Test dir=rtl</title></head>
+  <body style="background: white;">
+
+    <!-- The visible part of the formulas below should be covered by the
+         black rectangle when dir=rtl -->
+
+    <div style="position: absolute; top: 5px; left: 5px;">
+      <!-- msup -->
+      <math dir="rtl">
+        <msup>
+          <mspace width="20px" height="20px"/>
+          <mspace width="20px" height="20px" mathbackground="red"/>
+        </msup>
+      </math><br/>
+      <!-- msub -->
+      <math dir="rtl">
+        <msub>
+          <mspace width="20px" height="20px"/>
+          <mspace width="20px" height="20px" mathbackground="orange"/>
+        </msub>
+      </math><br/>
+      <!-- msubsup -->
+      <math dir="rtl">
+        <msubsup>
+          <mspace width="20px" height="20px"/>
+          <mspace width="20px" height="20px" mathbackground="green"/>
+          <mspace width="20px" height="20px" mathbackground="blue"/>
+        </msubsup>
+      </math><br/>
+      <!-- mmultiscripts -->
+      <math dir="rtl">
+        <mmultiscripts>
+          <mspace/>
+          <mspace width="20px" height="20px" mathbackground="cyan"/>
+          <mspace width="20px" height="20px" mathbackground="yellow"/>
+          <mprescripts/>
+          <mspace width="20px" height="20px"/>
+          <mspace width="20px" height="20px"/>
+        </mmultiscripts>
+      </math><br/>
+      <!-- munder (mo with movablelimits=true and displaystyle=false) -->
+      <math dir="rtl">
+        <munder>
+          <mpadded width="20px">
+            <mphantom>
+              <mo movablelimits="true" displaystyle="false">|</mo>
+            </mphantom>
+          </mpadded>
+          <mspace width="20px" height="20px" mathbackground="magenta"/>
+        </munder>
+      </math><br/>
+      <!-- mover (mo with movablelimits=true and displaystyle=false) -->
+      <math dir="rtl">
+        <mover>
+          <mpadded width="20px">
+            <mphantom>
+              <mo movablelimits="true" displaystyle="false">|</mo>
+            </mphantom>
+          </mpadded>
+          <mspace width="20px" height="20px" mathbackground="cyan"/>
+        </mover>
+      </math><br/>
+      <!-- munderover (mo with movablelimits=true and displaystyle=false) -->
+      <math dir="rtl">
+        <munderover>
+          <mpadded width="20px">
+            <mphantom>
+              <mo movablelimits="true" displaystyle="false">|</mo>
+            </mphantom>
+          </mpadded>
+          <mspace width="20px" height="20px" mathbackground="yellow"/>
+          <mspace width="20px" height="20px" mathbackground="grey"/>
+        </munderover>
+      </math>
+      <!-- mfrac (bevelled=true) -->
+      <math dir="rtl">
+        <mstyle mathcolor="white">
+          <mfrac bevelled="true">
+            <mspace width="20px" height="20px"/>
+            <mspace width="20px" height="20px" mathbackground="red"/>
+          </mfrac>
+        </mstyle>
+      </math><br/>
+      <!-- mroot -->
+      <math dir="rtl">
+        <mstyle mathcolor="white">
+          <mroot>
+            <mspace width="20px" height="20px" mathbackground="orange"/>
+            <mspace width="20px" height="20px"/>
+          </mroot>
+        </mstyle>
+      </math>
+      <!-- msqrt -->
+      <math dir="rtl">
+        <mstyle mathcolor="white">
+          <msqrt>
+            <!-- Here, we assume that (width of radical + width of mspace)
+                 is greater than the width of the black rectangle (i.e.
+                 width of radical > 30 - 25 = 5px), so the test fails if the
+                 radical is placed on the left. -->
+            <mspace width="25px" height="20px" mathbackground="grey"/>
+          </msqrt>
+        </mstyle>
+      </math>
+    </div>
+
+    <div style="position: absolute; top: 5px; left: 5px;">
+      <div style="width: 30px; height: 500px; background: black;"></div>
+    </div>
+
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/mathml/dir-4-ref.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+  <head><title>Test dir=rtl</title></head>
+  <body style="background: white;">
+
+    <div style="position: absolute;
+                top: 5px; left: 5px; width: 100px; height: 100px;
+                text-align: center; background: black;">
+      <div style="position: absolute;
+                  width: 35px; height: 100px; background: red;"></div>
+      <div style="position: absolute; left: 40px;
+                  width: 20px; height: 100px; background: blue;"></div>
+      <div style="position: absolute; left: 60px; width: 40px; height: 100px;
+                  background: green;"></div>
+    </div>
+
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/mathml/dir-4.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+  <head><title>Test dir=rtl</title></head>
+  <body style="background: white;">
+
+    <!-- menclose notation=radical -->
+
+    <div style="position: absolute;
+                top: 5px; left: 5px; width: 100px; height: 100px;
+                text-align: center; background: black;">
+      <math dir="rtl">
+        <mstyle mathcolor="yellow">
+          <!-- left and right notation make the menclose symmetric -->
+          <menclose notation="radical left right">
+            <mspace width="20px" height="20px"/>
+          </menclose>
+        </mstyle>
+      </math>
+    </div>
+
+    <div style="position: absolute;
+                top: 5px; left: 5px; width: 100px; height: 100px;">
+      <!-- hide the left part of the menclose. A 5px band is not covered, where
+           the radical may be seen if it is wrongly placed on the left instead.
+        -->
+      <div style="position: absolute;
+                  width: 35px; height: 100px; background: red;"></div>
+      <!-- hide the middle part of the menclose -->
+      <div style="position: absolute; left: 40px;
+                  width: 20px; height: 100px; background: blue;"></div>
+      <!-- hide the right part of the menclose -->
+      <div style="position: absolute; left: 60px; width: 40px; height: 100px;
+                  background: green;"></div>
+    </div>
+
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/mathml/dir-5-ref.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+  <head><title>Test dir=rtl</title></head>
+  <body>
+
+    <div style="position: absolute;
+                top: 5px; left: 5px; width: 200px; height: 200px;">
+      <div style="position: absolute; width: 40px; height: 200px;
+                  left: 0px; background: red;"></div>
+      <div style="position: absolute; width: 40px; height: 200px;
+                  left: 40px; background: green;"></div>
+      <div style="position: absolute; width: 40px; height: 200px;
+                  left: 80px; background: magenta;"></div>
+      <div style="position: absolute; width: 40px; height: 200px;
+                  left: 120px; background: blue;"></div>
+      <div style="position: absolute; width: 40px; height: 200px;
+                  left: 160px; background: yellow;"></div>
+    </div>
+
+    <div style="position: absolute;
+                top: 5px; left: 5px; width: 200px; height: 200px;">