Merge from mozilla-central.
authorDavid Anderson <danderson@mozilla.com>
Tue, 28 Feb 2012 12:21:56 -0800
changeset 105912 609a224cd28293bab2c8fe4fd0adf1492b25cd61
parent 105911 0c780caf3eb66016173de53e317152ea16d505db (current diff)
parent 87911 30b4f99a137c72345bb0401fa1970598687d80c7 (diff)
child 105913 251bea6ccff885c50d099b39926f1586b586d45d
push id1075
push uservporof@mozilla.com
push dateThu, 13 Sep 2012 10:46:49 +0000
treeherderfx-team@f39786e8364d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone13.0a1
Merge from mozilla-central.
accessible/src/atk/nsAccessibleWrap.cpp
accessible/src/base/nsAccDocManager.cpp
accessible/src/base/nsTextAttrs.cpp
accessible/src/base/nsTextAttrs.h
b2g/installer/package-manifest.in
browser/components/sessionstore/src/nsSessionStore.js
config/autoconf.mk.in
configure.in
content/base/public/nsContentUtils.h
content/base/src/Makefile.in
content/base/src/nsContentSink.cpp
content/base/src/nsContentUtils.cpp
content/base/src/nsCrossSiteListenerProxy.cpp
content/base/src/nsDOMParser.cpp
content/base/src/nsGenericElement.cpp
content/base/src/nsGenericElement.h
content/base/src/nsObjectLoadingContent.cpp
content/base/src/nsObjectLoadingContent.h
content/base/src/nsParserUtils.cpp
content/base/src/nsParserUtils.h
content/base/src/nsScriptLoader.cpp
content/canvas/src/WebGLContext.cpp
content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
content/canvas/test/webgl/test_webgl_conformance_test_suite.html
content/html/content/src/nsHTMLLinkElement.cpp
content/html/content/src/nsHTMLStyleElement.cpp
content/html/document/src/nsHTMLContentSink.cpp
content/mathml/content/src/nsMathMLElement.cpp
content/xml/content/src/nsXMLProcessingInstruction.cpp
content/xml/content/src/nsXMLStylesheetPI.cpp
content/xml/document/src/nsXMLContentSink.cpp
content/xul/content/src/nsXULElement.cpp
content/xul/document/src/nsXULContentSink.cpp
content/xul/document/src/nsXULDocument.cpp
dom/base/nsGlobalWindow.cpp
dom/plugins/base/nsPluginHost.cpp
dom/plugins/base/nsPluginHost.h
editor/txmgr/tests/TestTXMgr.cpp
embedding/components/webbrowserpersist/src/nsWebBrowserPersist.cpp
embedding/components/webbrowserpersist/src/nsWebBrowserPersist.h
gfx/gl/GLContext.cpp
gfx/gl/GLContext.h
gfx/gl/GLContextProviderEGL.cpp
gfx/layers/d3d10/LayerManagerD3D10.cpp
gfx/layers/d3d10/LayerManagerD3D10.h
gfx/layers/d3d9/LayerManagerD3D9.cpp
gfx/layers/d3d9/LayerManagerD3D9.h
gfx/layers/opengl/LayerManagerOGL.cpp
gfx/layers/opengl/LayerManagerOGL.h
gfx/thebes/gfxPlatform.cpp
gfx/thebes/gfxWindowsPlatform.cpp
image/decoders/nsPNGDecoder.cpp
js/src/MemoryMetrics.cpp
js/src/frontend/BytecodeEmitter.cpp
js/src/frontend/BytecodeEmitter.h
js/src/frontend/Parser.cpp
js/src/gc/Barrier.h
js/src/ion/CodeGenerator.cpp
js/src/jsapi-tests/testDebugger.cpp
js/src/jsapi.cpp
js/src/jsarray.cpp
js/src/jscntxt.cpp
js/src/jscntxt.h
js/src/jsdbgapi.cpp
js/src/jsdbgapi.h
js/src/jsfriendapi.cpp
js/src/jsfun.cpp
js/src/jsfun.h
js/src/jsgc.cpp
js/src/jsgc.h
js/src/jsgcmark.cpp
js/src/jsgcmark.h
js/src/jsinfer.cpp
js/src/jsinterp.cpp
js/src/jsinterp.h
js/src/jsiter.cpp
js/src/jsiter.h
js/src/jsobj.cpp
js/src/jsobj.h
js/src/jsobjinlines.h
js/src/jsproxy.cpp
js/src/jsscript.cpp
js/src/jstypedarray.cpp
js/src/jsval.h
js/src/jsweakmap.cpp
js/src/jswrapper.cpp
js/src/jsxml.cpp
js/src/methodjit/Compiler.cpp
js/src/methodjit/Compiler.h
js/src/methodjit/InvokeHelpers.cpp
js/src/methodjit/MonoIC.cpp
js/src/methodjit/PolyIC.cpp
js/src/methodjit/StubCalls.cpp
js/src/tests/js1_8_5/extensions/jstests.list
js/src/tests/workers.py
js/src/vm/Debugger.cpp
js/src/vm/GlobalObject.cpp
js/src/vm/Stack-inl.h
js/src/vm/Stack.h
js/xpconnect/src/XPCJSRuntime.cpp
layout/build/nsLayoutModule.cpp
layout/reftests/mathml/reftest.list
mobile/android/base/AndroidManifest.xml.in
mobile/android/base/GeckoAppShell.java
mobile/android/base/Makefile.in
mobile/android/base/sync/repositories/android/Authorities.java.in
mobile/android/base/sync/repositories/android/BrowserContract.java
mobile/xul/installer/package-manifest.in
modules/libpref/src/init/all.js
netwerk/base/src/nsSocketTransportService2.cpp
netwerk/protocol/http/SpdySession.cpp
netwerk/protocol/http/SpdySession.h
netwerk/protocol/http/nsHttpHandler.cpp
netwerk/protocol/http/nsHttpHandler.h
parser/html/nsParserUtils.cpp
testing/jetpack/jetpack-location.txt
toolkit/components/aboutmemory/content/aboutMemory.js
toolkit/components/feeds/nsIScriptableUnescapeHTML.idl
toolkit/components/feeds/nsScriptableUnescapeHTML.cpp
toolkit/components/feeds/nsScriptableUnescapeHTML.h
toolkit/components/satchel/nsFormFillController.cpp
toolkit/components/satchel/nsFormFillController.h
toolkit/components/telemetry/TelemetryHistograms.h
toolkit/content/license.html
toolkit/content/widgets/videocontrols.xml
toolkit/mozapps/extensions/XPIProvider.jsm
toolkit/mozapps/update/nsUpdateService.js
widget/android/nsWindow.cpp
widget/windows/GfxInfo.cpp
widget/windows/JumpListBuilder.cpp
widget/windows/JumpListBuilder.h
widget/windows/JumpListItem.cpp
widget/windows/JumpListItem.h
widget/windows/TaskbarPreview.cpp
widget/windows/TaskbarPreview.h
widget/windows/TaskbarPreviewButton.cpp
widget/windows/TaskbarTabPreview.cpp
widget/windows/TaskbarTabPreview.h
widget/windows/TaskbarWindowPreview.cpp
widget/windows/TaskbarWindowPreview.h
widget/windows/WinTaskbar.cpp
widget/windows/WinTaskbar.h
widget/windows/nsAppShell.cpp
widget/windows/nsAppShell.h
widget/windows/nsWindow.cpp
widget/windows/nsWindow.h
widget/xpwidgets/nsBaseWidget.cpp
widget/xpwidgets/nsBaseWidget.h
widget/xpwidgets/nsHTMLFormatConverter.cpp
xpcom/base/nsMemoryReporterManager.cpp
xpcom/idl-parser/xpidl.py
xpcom/tests/TestHarness.h
--- a/accessible/src/atk/nsAccessibleWrap.cpp
+++ b/accessible/src/atk/nsAccessibleWrap.cpp
@@ -866,20 +866,21 @@ refChildCB(AtkObject *aAtkObj, gint aChi
         return nsnull;
 
     AtkObject* childAtkObj = nsAccessibleWrap::GetAtkObject(accChild);
 
     NS_ASSERTION(childAtkObj, "Fail to get AtkObj");
     if (!childAtkObj)
         return nsnull;
     g_object_ref(childAtkObj);
-    
-    //this will addref parent
+
+  if (aAtkObj != childAtkObj->accessible_parent)
     atk_object_set_parent(childAtkObj, aAtkObj);
-    return childAtkObj;
+
+  return childAtkObj;
 }
 
 gint
 getIndexInParentCB(AtkObject *aAtkObj)
 {
     // We don't use nsIAccessible::GetIndexInParent() because
     // for ATK we don't want to include text leaf nodes as children
     nsAccessibleWrap *accWrap = GetAccessibleWrap(aAtkObj);
--- a/accessible/src/base/StyleInfo.cpp
+++ b/accessible/src/base/StyleInfo.cpp
@@ -105,8 +105,21 @@ void
 StyleInfo::Margin(css::Side aSide, nsAString& aValue)
 {
   aValue.Truncate();
 
   nscoord coordVal = mElement->GetPrimaryFrame()->GetUsedMargin().Side(aSide);
   aValue.AppendFloat(nsPresContext::AppUnitsToFloatCSSPixels(coordVal));
   aValue.AppendLiteral("px");
 }
+
+void
+StyleInfo::Format(const nscolor& aValue, nsString& aFormattedValue)
+{
+  // Combine the string like rgb(R, G, B) from nscolor.
+  aFormattedValue.AppendLiteral("rgb(");
+  aFormattedValue.AppendInt(NS_GET_R(aValue));
+  aFormattedValue.AppendLiteral(", ");
+  aFormattedValue.AppendInt(NS_GET_G(aValue));
+  aFormattedValue.AppendLiteral(", ");
+  aFormattedValue.AppendInt(NS_GET_B(aValue));
+  aFormattedValue.Append(')');
+}
--- a/accessible/src/base/StyleInfo.h
+++ b/accessible/src/base/StyleInfo.h
@@ -55,16 +55,18 @@ public:
   void Display(nsAString& aValue);
   void TextAlign(nsAString& aValue);
   void TextIndent(nsAString& aValue);
   void MarginLeft(nsAString& aValue) { Margin(css::eSideLeft, aValue); }
   void MarginRight(nsAString& aValue) { Margin(css::eSideRight, aValue); }
   void MarginTop(nsAString& aValue) { Margin(css::eSideTop, aValue); }
   void MarginBottom(nsAString& aValue) { Margin(css::eSideBottom, aValue); }
 
+  static void Format(const nscolor& aValue, nsString& aFormattedValue);
+
 private:
   StyleInfo() MOZ_DELETE;
   StyleInfo(const StyleInfo&) MOZ_DELETE;
   StyleInfo& operator = (const StyleInfo&) MOZ_DELETE;
 
   void Margin(css::Side aSide, nsAString& aValue);
 
   dom::Element* mElement;
--- a/accessible/src/base/nsAccDocManager.cpp
+++ b/accessible/src/base/nsAccDocManager.cpp
@@ -359,19 +359,19 @@ nsDocAccessible*
 nsAccDocManager::CreateDocOrRootAccessible(nsIDocument *aDocument)
 {
   // Ignore temporary, hiding, resource documents and documents without
   // docshell.
   if (aDocument->IsInitialDocument() || !aDocument->IsVisible() ||
       aDocument->IsResourceDoc() || !aDocument->IsActive())
     return nsnull;
 
-  // Ignore documents without presshell.
-  nsIPresShell *presShell = aDocument->GetShell();
-  if (!presShell)
+  // Ignore documents without presshell and not having root frame.
+  nsIPresShell* presShell = aDocument->GetShell();
+  if (!presShell || !presShell->GetRootFrame())
     return nsnull;
 
   // Do not create document accessible until role content is loaded, otherwise
   // we get accessible document with wrong role.
   nsIContent *rootElm = nsCoreUtils::GetRoleContent(aDocument);
   if (!rootElm)
     return nsnull;
 
--- a/accessible/src/base/nsTextAttrs.cpp
+++ b/accessible/src/base/nsTextAttrs.cpp
@@ -36,22 +36,26 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsTextAttrs.h"
 
 #include "nsAccUtils.h"
 #include "nsCoreUtils.h"
 #include "nsHyperTextAccessibleWrap.h"
+#include "StyleInfo.h"
 
 #include "gfxFont.h"
 #include "gfxUserFontSet.h"
 #include "nsFontMetrics.h"
 #include "nsLayoutUtils.h"
 
+using namespace mozilla;
+using namespace mozilla::a11y;
+
 ////////////////////////////////////////////////////////////////////////////////
 // Constants and structures
 
 /**
  * Item of the gCSSTextAttrsMap map.
  */
 struct nsCSSTextAttrMapItem
 {
@@ -65,17 +69,16 @@ struct nsCSSTextAttrMapItem
  * The map of CSS properties to text attributes.
  */
 const char* const kAnyValue = nsnull;
 const char* const kCopyValue = nsnull;
 
 static nsCSSTextAttrMapItem gCSSTextAttrsMap[] =
 {
   // CSS name            CSS value        Attribute name                                Attribute value
-  { "color",             kAnyValue,       &nsGkAtoms::color,                 kCopyValue },
   { "font-family",       kAnyValue,       &nsGkAtoms::font_family,            kCopyValue },
   { "font-style",        kAnyValue,       &nsGkAtoms::font_style,             kCopyValue },
   { "text-decoration",   "line-through",  &nsGkAtoms::textLineThroughStyle,  "solid" },
   { "text-decoration",   "underline",     &nsGkAtoms::textUnderlineStyle,    "solid" },
   { "vertical-align",    kAnyValue,       &nsGkAtoms::textPosition,          kCopyValue }
 };
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -149,44 +152,44 @@ nsTextAttrsMgr::GetAttributes(nsIPersist
   }
 
   nsTArray<nsITextAttr*> textAttrArray(10);
 
   // "language" text attribute
   nsLangTextAttr langTextAttr(mHyperTextAcc, hyperTextElm, offsetNode);
   textAttrArray.AppendElement(static_cast<nsITextAttr*>(&langTextAttr));
 
-  // "color" text attribute
-  nsCSSTextAttr colorTextAttr(0, hyperTextElm, offsetElm);
-  textAttrArray.AppendElement(static_cast<nsITextAttr*>(&colorTextAttr));
-
   // "font-family" text attribute
-  nsCSSTextAttr fontFamilyTextAttr(1, hyperTextElm, offsetElm);
+  nsCSSTextAttr fontFamilyTextAttr(0, hyperTextElm, offsetElm);
   textAttrArray.AppendElement(static_cast<nsITextAttr*>(&fontFamilyTextAttr));
 
   // "font-style" text attribute
-  nsCSSTextAttr fontStyleTextAttr(2, hyperTextElm, offsetElm);
+  nsCSSTextAttr fontStyleTextAttr(1, hyperTextElm, offsetElm);
   textAttrArray.AppendElement(static_cast<nsITextAttr*>(&fontStyleTextAttr));
 
   // "text-line-through-style" text attribute
-  nsCSSTextAttr lineThroughTextAttr(3, hyperTextElm, offsetElm);
+  nsCSSTextAttr lineThroughTextAttr(2, hyperTextElm, offsetElm);
   textAttrArray.AppendElement(static_cast<nsITextAttr*>(&lineThroughTextAttr));
 
   // "text-underline-style" text attribute
-  nsCSSTextAttr underlineTextAttr(4, hyperTextElm, offsetElm);
+  nsCSSTextAttr underlineTextAttr(3, hyperTextElm, offsetElm);
   textAttrArray.AppendElement(static_cast<nsITextAttr*>(&underlineTextAttr));
 
   // "text-position" text attribute
-  nsCSSTextAttr posTextAttr(5, hyperTextElm, offsetElm);
+  nsCSSTextAttr posTextAttr(4, hyperTextElm, offsetElm);
   textAttrArray.AppendElement(static_cast<nsITextAttr*>(&posTextAttr));
 
   // "background-color" text attribute
   nsBGColorTextAttr bgColorTextAttr(rootFrame, frame);
   textAttrArray.AppendElement(static_cast<nsITextAttr*>(&bgColorTextAttr));
 
+  // "color" text attribute
+  ColorTextAttr colorTextAttr(rootFrame, frame);
+  textAttrArray.AppendElement(static_cast<nsITextAttr*>(&colorTextAttr));
+
   // "font-size" text attribute
   nsFontSizeTextAttr fontSizeTextAttr(rootFrame, frame);
   textAttrArray.AppendElement(static_cast<nsITextAttr*>(&fontSizeTextAttr));
 
   // "font-weight" text attribute
   nsFontWeightTextAttr fontWeightTextAttr(rootFrame, frame);
   textAttrArray.AppendElement(static_cast<nsITextAttr*>(&fontWeightTextAttr));
 
@@ -358,17 +361,17 @@ nsCSSTextAttr::Format(const nsAutoString
   if (attrValue != kCopyValue)
     AppendASCIItoUTF16(attrValue, aFormattedValue);
   else
     aFormattedValue = aValue;
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsBackgroundTextAttr
+// nsBGColorTextAttr
 ////////////////////////////////////////////////////////////////////////////////
 
 nsBGColorTextAttr::nsBGColorTextAttr(nsIFrame *aRootFrame, nsIFrame *aFrame) :
   nsTextAttr<nscolor>(aFrame == nsnull), mRootFrame(aRootFrame)
 {
   mIsRootDefined = GetColor(mRootFrame, &mRootNativeValue);
   if (aFrame)
     mIsDefined = GetColor(aFrame, &mNativeValue);
@@ -382,26 +385,18 @@ nsBGColorTextAttr::GetValueFor(nsIConten
     return false;
 
   return GetColor(frame, aValue);
 }
 
 void
 nsBGColorTextAttr::Format(const nscolor& aValue, nsAString& aFormattedValue)
 {
-  // Combine the string like rgb(R, G, B) from nscolor.
   nsAutoString value;
-  value.AppendLiteral("rgb(");
-  value.AppendInt(NS_GET_R(aValue));
-  value.AppendLiteral(", ");
-  value.AppendInt(NS_GET_G(aValue));
-  value.AppendLiteral(", ");
-  value.AppendInt(NS_GET_B(aValue));
-  value.Append(')');
-
+  StyleInfo::Format(aValue, value);
   aFormattedValue = value;
 }
 
 bool
 nsBGColorTextAttr::GetColor(nsIFrame *aFrame, nscolor *aColor)
 {
   const nsStyleBackground *styleBackground = aFrame->GetStyleBackground();
 
@@ -422,16 +417,53 @@ nsBGColorTextAttr::GetColor(nsIFrame *aF
   if (parentFrame == mRootFrame)
     return false;
 
   return GetColor(parentFrame, aColor);
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
+// ColorTextAttr
+////////////////////////////////////////////////////////////////////////////////
+
+ColorTextAttr::ColorTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) :
+  nsTextAttr<nscolor>(!aFrame)
+{
+  mRootNativeValue = aRootFrame->GetStyleColor()->mColor;
+  mIsRootDefined = true;
+
+  if (aFrame) {
+    mNativeValue = aFrame->GetStyleColor()->mColor;
+    mIsDefined = true;
+  }
+}
+
+bool
+ColorTextAttr::GetValueFor(nsIContent* aContent, nscolor* aValue)
+{
+  nsIFrame* frame = aContent->GetPrimaryFrame();
+  if (frame) {
+    *aValue = frame->GetStyleColor()->mColor;
+    return true;
+  }
+
+  return false;
+}
+
+void
+ColorTextAttr::Format(const nscolor& aValue, nsAString& aFormattedValue)
+{
+  nsAutoString value;
+  StyleInfo::Format(aValue, value);
+  aFormattedValue = value;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
 // nsFontSizeTextAttr
 ////////////////////////////////////////////////////////////////////////////////
 
 nsFontSizeTextAttr::nsFontSizeTextAttr(nsIFrame *aRootFrame, nsIFrame *aFrame) :
   nsTextAttr<nscoord>(aFrame == nsnull)
 {
   mDC = aRootFrame->PresContext()->DeviceContext();
 
--- a/accessible/src/base/nsTextAttrs.h
+++ b/accessible/src/base/nsTextAttrs.h
@@ -303,16 +303,35 @@ protected:
 
 private:
   bool GetColor(nsIFrame *aFrame, nscolor *aColor);
   nsIFrame *mRootFrame;
 };
 
 
 /**
+ * Class is used for the work with 'color' text attribute in nsTextAttrsMgr
+ * class.
+ */
+class ColorTextAttr : public nsTextAttr<nscolor>
+{
+public:
+  ColorTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame);
+
+  // nsITextAttr
+  virtual nsIAtom* GetName() const { return nsGkAtoms::color; }
+
+protected:
+  // nsTextAttr
+  virtual bool GetValueFor(nsIContent* aContent, nscolor* aValue);
+  virtual void Format(const nscolor& aValue, nsAString& aFormattedValue);
+};
+
+
+/**
  * Class is used for the work with "font-size" text attribute in nsTextAttrsMgr
  * class.
  */
 class nsFontSizeTextAttr : public nsTextAttr<nscoord>
 {
 public:
   nsFontSizeTextAttr(nsIFrame *aRootFrame, nsIFrame *aFrame);
 
--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -187,16 +187,17 @@
 @BINPATH@/components/fastfind.xpt
 @BINPATH@/components/feeds.xpt
 #ifdef MOZ_GTK2
 @BINPATH@/components/filepicker.xpt
 #endif
 @BINPATH@/components/find.xpt
 @BINPATH@/components/fuel.xpt
 @BINPATH@/components/gfx.xpt
+@BINPATH@/components/html5.xpt
 @BINPATH@/components/htmlparser.xpt
 @BINPATH@/components/imglib2.xpt
 @BINPATH@/components/imgicon.xpt
 @BINPATH@/components/inspector.xpt
 @BINPATH@/components/intl.xpt
 @BINPATH@/components/jar.xpt
 @BINPATH@/components/jetpack.xpt
 @BINPATH@/components/jsdservice.xpt
--- a/browser/components/sessionstore/src/nsSessionStore.js
+++ b/browser/components/sessionstore/src/nsSessionStore.js
@@ -1676,21 +1676,26 @@ SessionStoreService.prototype = {
       if (groupsData.totalNumber > 1)
         return [false, false];
     }
 
     // Step 2 of processing:
     // If we're still here, then the window is usable. Look at the open tabs in
     // comparison to home pages. If all the tabs are home pages then we'll end
     // up overwriting all of them. Otherwise we'll just close the tabs that
-    // match home pages.
-    let homePages = aWindow.gHomeButton.getHomePage().split("|");
+    // match home pages. Tabs with the about:blank URI will always be
+    // overwritten.
+    let homePages = ["about:blank"];
     let removableTabs = [];
     let tabbrowser = aWindow.gBrowser;
     let normalTabsLen = tabbrowser.tabs.length - tabbrowser._numPinnedTabs;
+    let startupPref = this._prefBranch.getIntPref("startup.page");
+    if (startupPref == 1)
+      homePages = homePages.concat(aWindow.gHomeButton.getHomePage().split("|"));
+
     for (let i = tabbrowser._numPinnedTabs; i < tabbrowser.tabs.length; i++) {
       let tab = tabbrowser.tabs[i];
       if (homePages.indexOf(tab.linkedBrowser.currentURI.spec) != -1) {
         removableTabs.push(tab);
       }
     }
 
     if (tabbrowser.tabs.length == removableTabs.length) {
--- a/browser/config/mozconfigs/linux32/debug
+++ b/browser/config/mozconfigs/linux32/debug
@@ -1,10 +1,11 @@
 ac_add_options --enable-debug
 ac_add_options --enable-trace-malloc
+ac_add_options --enable-signmar
 
 . $topsrcdir/build/unix/mozconfig.linux
 
 # Avoid dependency on libstdc++ 4.5
 ac_add_options --enable-stdcxx-compat
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
--- a/browser/config/mozconfigs/linux32/nightly
+++ b/browser/config/mozconfigs/linux32/nightly
@@ -1,11 +1,12 @@
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
 ac_add_options --enable-update-packaging
 ac_add_options --enable-codesighs
+ac_add_options --enable-signmar
 
 # Nightlies only since this has a cost in performance
 ac_add_options --enable-js-diagnostics
 
 . $topsrcdir/build/unix/mozconfig.linux
 
 # Avoid dependency on libstdc++ 4.5
 ac_add_options --enable-stdcxx-compat
--- a/browser/config/mozconfigs/linux64/debug
+++ b/browser/config/mozconfigs/linux64/debug
@@ -1,10 +1,11 @@
 ac_add_options --enable-debug
 ac_add_options --enable-trace-malloc
+ac_add_options --enable-signmar
 
 . $topsrcdir/build/unix/mozconfig.linux
 
 # Avoid dependency on libstdc++ 4.5
 ac_add_options --enable-stdcxx-compat
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
--- a/browser/config/mozconfigs/linux64/nightly
+++ b/browser/config/mozconfigs/linux64/nightly
@@ -1,11 +1,12 @@
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
 ac_add_options --enable-update-packaging
 ac_add_options --enable-codesighs
+ac_add_options --enable-signmar
 
 # Nightlies only since this has a cost in performance
 ac_add_options --enable-js-diagnostics
 
 . $topsrcdir/build/unix/mozconfig.linux
 
 # Avoid dependency on libstdc++ 4.5
 ac_add_options --enable-stdcxx-compat
--- a/browser/config/mozconfigs/macosx-lion-universal/nightly
+++ b/browser/config/mozconfigs/macosx-lion-universal/nightly
@@ -2,16 +2,17 @@
 
 # Universal builds override the default of browser (bug 575283 comment 29)
 ac_add_options --enable-application=browser
 
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
 ac_add_options --enable-update-packaging
 ac_add_options --enable-codesighs
 ac_add_options --disable-install-strip
+ac_add_options --enable-signmar
 
 # Nightlies only since this has a cost in performance
 ac_add_options --enable-js-diagnostics
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 export MOZ_TELEMETRY_REPORTING=1
--- a/browser/config/mozconfigs/macosx-universal/nightly
+++ b/browser/config/mozconfigs/macosx-universal/nightly
@@ -2,16 +2,17 @@
 
 # Universal builds override the default of browser (bug 575283 comment 29)
 ac_add_options --enable-application=browser
 
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
 ac_add_options --enable-update-packaging
 ac_add_options --enable-codesighs
 ac_add_options --disable-install-strip
+ac_add_options --enable-signmar
 
 # Nightlies only since this has a cost in performance
 ac_add_options --enable-js-diagnostics
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 export MOZ_TELEMETRY_REPORTING=1
--- a/browser/config/mozconfigs/macosx32-lion/debug
+++ b/browser/config/mozconfigs/macosx32-lion/debug
@@ -1,11 +1,12 @@
 . $topsrcdir/build/macosx/mozconfig.leopard
 ac_add_options --enable-debug
 ac_add_options --enable-trace-malloc
+ac_add_options --enable-signmar
 
 # Enable parallel compiling
 mk_add_options MOZ_MAKE_FLAGS="-j12"
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 ac_add_options --with-macbundlename-prefix=Firefox
--- a/browser/config/mozconfigs/macosx32/debug
+++ b/browser/config/mozconfigs/macosx32/debug
@@ -1,11 +1,12 @@
 . $topsrcdir/build/macosx/mozconfig.leopard
 ac_add_options --enable-debug
 ac_add_options --enable-trace-malloc
+ac_add_options --enable-signmar
 
 # Enable parallel compiling
 mk_add_options MOZ_MAKE_FLAGS="-j4"
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 ac_add_options --with-macbundlename-prefix=Firefox
--- a/browser/config/mozconfigs/macosx64-lion/debug
+++ b/browser/config/mozconfigs/macosx64-lion/debug
@@ -1,13 +1,14 @@
 . $topsrcdir/build/macosx/common
 
 ac_add_options --enable-debug
 ac_add_options --enable-trace-malloc
 ac_add_options --enable-accessibility
+ac_add_options --enable-signmar
 
 # Enable parallel compiling
 mk_add_options MOZ_MAKE_FLAGS="-j12"
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 ac_add_options --with-macbundlename-prefix=Firefox
--- a/browser/config/mozconfigs/macosx64/debug
+++ b/browser/config/mozconfigs/macosx64/debug
@@ -1,13 +1,14 @@
 . $topsrcdir/build/macosx/common
 
 ac_add_options --enable-debug
 ac_add_options --enable-trace-malloc
 ac_add_options --enable-accessibility
+ac_add_options --enable-signmar
 
 # Enable parallel compiling
 mk_add_options MOZ_MAKE_FLAGS="-j4"
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 ac_add_options --with-macbundlename-prefix=Firefox
--- a/browser/config/mozconfigs/win32/debug
+++ b/browser/config/mozconfigs/win32/debug
@@ -1,9 +1,10 @@
 ac_add_options --enable-debug
 ac_add_options --enable-trace-malloc
+ac_add_options --enable-signmar
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 mk_add_options MOZ_MAKE_FLAGS=-j1
 
 . $topsrcdir/browser/config/mozconfigs/win32/vs2010-mozconfig
--- a/browser/config/mozconfigs/win32/nightly
+++ b/browser/config/mozconfigs/win32/nightly
@@ -1,14 +1,15 @@
 # for pgo
 mk_add_options PROFILE_GEN_SCRIPT='$(PYTHON) $(MOZ_OBJDIR)/_profile/pgo/profileserver.py'
 
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
 ac_add_options --enable-update-packaging
 ac_add_options --enable-jemalloc
+ac_add_options --enable-signmar
 
 # Nightlies only since this has a cost in performance
 ac_add_options --enable-js-diagnostics
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 export MOZ_TELEMETRY_REPORTING=1
--- a/browser/config/mozconfigs/win64/debug
+++ b/browser/config/mozconfigs/win64/debug
@@ -1,10 +1,11 @@
 ac_add_options --target=x86_64-pc-mingw32
 ac_add_options --host=x86_64-pc-mingw32
 
 ac_add_options --enable-debug
 ac_add_options --enable-trace-malloc
+ac_add_options --enable-signmar
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 mk_add_options MOZ_MAKE_FLAGS=-j1
--- a/browser/config/mozconfigs/win64/nightly
+++ b/browser/config/mozconfigs/win64/nightly
@@ -2,16 +2,17 @@ ac_add_options --target=x86_64-pc-mingw3
 ac_add_options --host=x86_64-pc-mingw32
 
 # for pgo
 mk_add_options PROFILE_GEN_SCRIPT='$(PYTHON) $(MOZ_OBJDIR)/_profile/pgo/profileserver.py'
 
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
 ac_add_options --enable-update-packaging
 ac_add_options --enable-jemalloc
+ac_add_options --enable-signmar
 
 # Nightlies only since this has a cost in performance
 ac_add_options --enable-js-diagnostics
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 export MOZ_TELEMETRY_REPORTING=1
--- a/browser/devtools/scratchpad/scratchpad.js
+++ b/browser/devtools/scratchpad/scratchpad.js
@@ -70,16 +70,18 @@ const DEVTOOLS_CHROME_ENABLED = "devtool
 const BUTTON_POSITION_SAVE = 0;
 const BUTTON_POSITION_CANCEL = 1;
 const BUTTON_POSITION_DONT_SAVE = 2;
 
 /**
  * The scratchpad object handles the Scratchpad window functionality.
  */
 var Scratchpad = {
+  _initialWindowTitle: document.title,
+
   /**
    * The script execution context. This tells Scratchpad in which context the
    * script shall execute.
    *
    * Possible values:
    *   - SCRATCHPAD_CONTEXT_CONTENT to execute code in the context of the current
    *   tab content window object.
    *   - SCRATCHPAD_CONTEXT_BROWSER to execute code in the context of the
@@ -146,50 +148,67 @@ var Scratchpad = {
   /**
    * Set the filename in the scratchpad UI and object
    *
    * @param string aFilename
    *        The new filename
    */
   setFilename: function SP_setFilename(aFilename)
   {
-    document.title = this.filename = aFilename;
+    this.filename = aFilename;
+    this._updateTitle();
+  },
+
+  /**
+   * Update the Scratchpad window title based on the current state.
+   * @private
+   */
+  _updateTitle: function SP__updateTitle()
+  {
+    if (this.filename) {
+      document.title = (this.editor && this.editor.dirty ? "*" : "") +
+                       this.filename;
+    } else {
+      document.title = this._initialWindowTitle;
+    }
   },
 
   /**
    * Get the current state of the scratchpad. Called by the
    * Scratchpad Manager for session storing.
    *
    * @return object
    *        An object with 3 properties: filename, text, and
    *        executionContext.
    */
   getState: function SP_getState()
   {
     return {
       filename: this.filename,
       text: this.getText(),
       executionContext: this.executionContext,
-      saved: this.saved
+      saved: !this.editor.dirty,
     };
   },
 
   /**
    * Set the filename and execution context using the given state. Called
    * when scratchpad is being restored from a previous session.
    *
    * @param object aState
    *        An object with filename and executionContext properties.
    */
   setState: function SP_getState(aState)
   {
     if (aState.filename) {
       this.setFilename(aState.filename);
     }
-    this.saved = aState.saved;
+    if (this.editor) {
+      this.editor.dirty = !aState.saved;
+    }
 
     if (aState.executionContext == SCRATCHPAD_CONTEXT_BROWSER) {
       this.setBrowserContext();
     }
     else {
       this.setContentContext();
     }
   },
@@ -633,17 +652,17 @@ var Scratchpad = {
   openFile: function SP_openFile()
   {
     let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
     fp.init(window, this.strings.GetStringFromName("openFile.title"),
             Ci.nsIFilePicker.modeOpen);
     fp.defaultString = "";
     if (fp.show() != Ci.nsIFilePicker.returnCancel) {
       this.setFilename(fp.file.path);
-      this.importFromFile(fp.file, false, this.onTextSaved.bind(this));
+      this.importFromFile(fp.file, false);
     }
   },
 
   /**
    * Save the textbox content to the currently open file.
    *
    * @param function aCallback
    *        Optional function you want to call when file is saved
@@ -653,17 +672,19 @@ var Scratchpad = {
     if (!this.filename) {
       return this.saveFileAs(aCallback);
     }
 
     let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
     file.initWithPath(this.filename);
 
     this.exportToFile(file, true, false, function(aStatus) {
-      this.onTextSaved();
+      if (Components.isSuccessCode(aStatus)) {
+        this.editor.dirty = false;
+      }
       if (aCallback) {
         aCallback(aStatus);
       }
     });
   },
 
   /**
    * Save the textbox content to a new file.
@@ -676,17 +697,19 @@ var Scratchpad = {
     let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
     fp.init(window, this.strings.GetStringFromName("saveFileAs"),
             Ci.nsIFilePicker.modeSave);
     fp.defaultString = "scratchpad.js";
     if (fp.show() != Ci.nsIFilePicker.returnCancel) {
       this.setFilename(fp.file.path);
 
       this.exportToFile(fp.file, true, false, function(aStatus) {
-        this.onTextSaved();
+        if (Components.isSuccessCode(aStatus)) {
+          this.editor.dirty = false;
+        }
         if (aCallback) {
           aCallback(aStatus);
         }
       });
     }
   },
 
   /**
@@ -778,67 +801,69 @@ var Scratchpad = {
    *
    * @param nsIDOMEvent aEvent
    */
   onLoad: function SP_onLoad(aEvent)
   {
     if (aEvent.target != document) {
       return;
     }
-
     let chrome = Services.prefs.getBoolPref(DEVTOOLS_CHROME_ENABLED);
     if (chrome) {
       let environmentMenu = document.getElementById("sp-environment-menu");
       let errorConsoleCommand = document.getElementById("sp-cmd-errorConsole");
       let chromeContextCommand = document.getElementById("sp-cmd-browserContext");
       environmentMenu.removeAttribute("hidden");
       chromeContextCommand.removeAttribute("disabled");
       errorConsoleCommand.removeAttribute("disabled");
     }
 
+    let state = null;
     let initialText = this.strings.GetStringFromName("scratchpadIntro");
     if ("arguments" in window &&
          window.arguments[0] instanceof Ci.nsIDialogParamBlock) {
-      let state = JSON.parse(window.arguments[0].GetString(0));
+      state = JSON.parse(window.arguments[0].GetString(0));
       this.setState(state);
       initialText = state.text;
     }
 
     this.editor = new SourceEditor();
 
     let config = {
       mode: SourceEditor.MODES.JAVASCRIPT,
       showLineNumbers: true,
       initialText: initialText,
+      contextMenu: "scratchpad-text-popup",
     };
 
     let editorPlaceholder = document.getElementById("scratchpad-editor");
-    this.editor.init(editorPlaceholder, config, this.onEditorLoad.bind(this));
+    this.editor.init(editorPlaceholder, config,
+                     this._onEditorLoad.bind(this, state));
   },
 
   /**
    * The load event handler for the source editor. This method does post-load
    * editor initialization.
+   *
+   * @private
+   * @param object aState
+   *        The initial Scratchpad state object.
    */
-  onEditorLoad: function SP_onEditorLoad()
+  _onEditorLoad: function SP__onEditorLoad(aState)
   {
-    this.editor.addEventListener(SourceEditor.EVENTS.CONTEXT_MENU,
-                                 this.onContextMenu);
+    this.editor.addEventListener(SourceEditor.EVENTS.DIRTY_CHANGED,
+                                 this._onDirtyChanged);
     this.editor.focus();
     this.editor.setCaretOffset(this.editor.getCharCount());
+    if (aState) {
+      this.editor.dirty = !aState.saved;
+    }
 
     this.initialized = true;
 
-    if (this.filename && !this.saved) {
-      this.onTextChanged();
-    }
-    else if (this.filename && this.saved) {
-      this.onTextSaved();
-    }
-
     this._triggerObservers("Ready");
   },
 
   /**
    * Insert text at the current caret location.
    *
    * @param string aText
    *        The text you want to insert.
@@ -846,46 +871,27 @@ var Scratchpad = {
   insertTextAtCaret: function SP_insertTextAtCaret(aText)
   {
     let caretOffset = this.editor.getCaretOffset();
     this.setText(aText, caretOffset, caretOffset);
     this.editor.setCaretOffset(caretOffset + aText.length);
   },
 
   /**
-   * The contextmenu event handler for the source editor. This method opens the
-   * Scratchpad context menu popup at the pointer location.
+   * The Source Editor DirtyChanged event handler. This function updates the
+   * Scratchpad window title to show an asterisk when there are unsaved changes.
    *
+   * @private
+   * @see SourceEditor.EVENTS.DIRTY_CHANGED
    * @param object aEvent
-   *        An event object coming from the SourceEditor. This object needs to
-   *        hold the screenX and screenY properties.
+   *        The DirtyChanged event object.
    */
-  onContextMenu: function SP_onContextMenu(aEvent)
+  _onDirtyChanged: function SP__onDirtyChanged(aEvent)
   {
-    let menu = document.getElementById("scratchpad-text-popup");
-    if (menu.state == "closed") {
-      menu.openPopupAtScreen(aEvent.screenX, aEvent.screenY, true);
-    }
-  },
-
-  /**
-   * The popupshowing event handler for the Edit menu. This method updates the
-   * enabled/disabled state of the Undo and Redo commands, based on the editor
-   * state such that the menu items render correctly for the user when the menu
-   * shows.
-   */
-  onEditPopupShowing: function SP_onEditPopupShowing()
-  {
-    goUpdateGlobalEditMenuItems();
-
-    let undo = document.getElementById("sp-cmd-undo");
-    undo.setAttribute("disabled", !this.editor.canUndo());
-
-    let redo = document.getElementById("sp-cmd-redo");
-    redo.setAttribute("disabled", !this.editor.canRedo());
+    Scratchpad._updateTitle();
   },
 
   /**
    * Undo the last action of the user.
    */
   undo: function SP_undo()
   {
     this.editor.undo();
@@ -895,123 +901,133 @@ var Scratchpad = {
    * Redo the previously undone action.
    */
   redo: function SP_redo()
   {
     this.editor.redo();
   },
 
   /**
-   * This method adds a listener to the editor for text changes. Called when
-   * a scratchpad is saved, opened from file, or restored from a saved file.
-   */
-  onTextSaved: function SP_onTextSaved(aStatus)
-  {
-    if (aStatus && !Components.isSuccessCode(aStatus)) {
-      return;
-    }
-    if (!document || !this.initialized) {
-      return;  // file saved to disk after window has closed
-    }
-    document.title = document.title.replace(/^\*/, "");
-    this.saved = true;
-    this.editor.addEventListener(SourceEditor.EVENTS.TEXT_CHANGED,
-                                 this.onTextChanged);
-  },
-
-  /**
-   * The scratchpad handler for editor text change events. This handler
-   * indicates that there are unsaved changes in the UI.
-   */
-  onTextChanged: function SP_onTextChanged()
-  {
-    document.title = "*" + document.title;
-    Scratchpad.saved = false;
-    Scratchpad.editor.removeEventListener(SourceEditor.EVENTS.TEXT_CHANGED,
-                                          Scratchpad.onTextChanged);
-  },
-
-  /**
    * The Scratchpad window unload event handler. This method unloads/destroys
    * the source editor.
    *
    * @param nsIDOMEvent aEvent
    */
   onUnload: function SP_onUnload(aEvent)
   {
     if (aEvent.target != document) {
       return;
     }
 
     this.resetContext();
-    this.editor.removeEventListener(SourceEditor.EVENTS.CONTEXT_MENU,
-                                    this.onContextMenu);
+    this.editor.removeEventListener(SourceEditor.EVENTS.DIRTY_CHANGED,
+                                    this._onDirtyChanged);
     this.editor.destroy();
     this.editor = null;
     this.initialized = false;
   },
 
   /**
    * Prompt to save scratchpad if it has unsaved changes.
    *
    * @param function aCallback
-   *        Optional function you want to call when file is saved
+   *        Optional function you want to call when file is saved. The callback
+   *        receives three arguments:
+   *          - toClose (boolean) - tells if the window should be closed.
+   *          - saved (boolen) - tells if the file has been saved.
+   *          - status (number) - the file save status result (if the file was
+   *          saved).
    * @return boolean
    *         Whether the window should be closed
    */
   promptSave: function SP_promptSave(aCallback)
   {
-    if (this.filename && !this.saved) {
+    if (this.filename && this.editor.dirty) {
       let ps = Services.prompt;
       let flags = ps.BUTTON_POS_0 * ps.BUTTON_TITLE_SAVE +
                   ps.BUTTON_POS_1 * ps.BUTTON_TITLE_CANCEL +
                   ps.BUTTON_POS_2 * ps.BUTTON_TITLE_DONT_SAVE;
 
       let button = ps.confirmEx(window,
                           this.strings.GetStringFromName("confirmClose.title"),
                           this.strings.GetStringFromName("confirmClose"),
                           flags, null, null, null, null, {});
 
       if (button == BUTTON_POSITION_CANCEL) {
+        if (aCallback) {
+          aCallback(false, false);
+        }
         return false;
       }
+
       if (button == BUTTON_POSITION_SAVE) {
-        this.saveFile(aCallback);
+        this.saveFile(function(aStatus) {
+          if (aCallback) {
+            aCallback(true, true, aStatus);
+          }
+        });
+        return true;
       }
     }
+
+    if (aCallback) {
+      aCallback(true, false);
+    }
     return true;
   },
 
   /**
    * Handler for window close event. Prompts to save scratchpad if
    * there are unsaved changes.
    *
    * @param nsIDOMEvent aEvent
    */
   onClose: function SP_onClose(aEvent)
   {
-    let toClose = this.promptSave();
-    if (!toClose) {
-      aEvent.preventDefault();
+    if (this._skipClosePrompt) {
+      return;
     }
+
+    this.promptSave(function(aShouldClose, aSaved, aStatus) {
+      let shouldClose = aShouldClose;
+      if (aSaved && !Components.isSuccessCode(aStatus)) {
+        shouldClose = false;
+      }
+
+      if (shouldClose) {
+        this._skipClosePrompt = true;
+        window.close();
+      }
+    }.bind(this));
+    aEvent.preventDefault();
   },
 
   /**
    * Close the scratchpad window. Prompts before closing if the scratchpad
    * has unsaved changes.
    *
    * @param function aCallback
    *        Optional function you want to call when file is saved
    */
   close: function SP_close(aCallback)
   {
-    let toClose = this.promptSave(aCallback);
-    if (toClose) {
-      window.close();
-    }
+    this.promptSave(function(aShouldClose, aSaved, aStatus) {
+      let shouldClose = aShouldClose;
+      if (aSaved && !Components.isSuccessCode(aStatus)) {
+        shouldClose = false;
+      }
+
+      if (shouldClose) {
+        this._skipClosePrompt = true;
+        window.close();
+      }
+      if (aCallback) {
+        aCallback();
+      }
+    }.bind(this));
   },
 
   _observers: [],
 
   /**
    * Add an observer for Scratchpad events.
    *
    * The observer implements IScratchpadObserver := {
--- a/browser/devtools/scratchpad/scratchpad.xul
+++ b/browser/devtools/scratchpad/scratchpad.xul
@@ -76,21 +76,21 @@
   <command id="sp-cmd-run" oncommand="Scratchpad.run();"/>
   <command id="sp-cmd-inspect" oncommand="Scratchpad.inspect();"/>
   <command id="sp-cmd-display" oncommand="Scratchpad.display();"/>
   <command id="sp-cmd-contentContext" oncommand="Scratchpad.setContentContext();"/>
   <command id="sp-cmd-browserContext" oncommand="Scratchpad.setBrowserContext();" disabled="true"/>
   <command id="sp-cmd-resetContext" oncommand="Scratchpad.resetContext();"/>
   <command id="sp-cmd-errorConsole" oncommand="Scratchpad.openErrorConsole();" disabled="true"/>
   <command id="sp-cmd-webConsole" oncommand="Scratchpad.openWebConsole();"/>
-  <command id="sp-cmd-undo" oncommand="Scratchpad.undo();" disabled="true"/>
-  <command id="sp-cmd-redo" oncommand="Scratchpad.redo();" disabled="true"/>
   <command id="sp-cmd-documentationLink" oncommand="Scratchpad.openDocumentationPage();"/>
 </commandset>
 
+<keyset id="sourceEditorKeys"/>
+
 <keyset id="sp-keyset">
   <key id="sp-key-window"
        key="&newWindowCmd.commandkey;"
        command="sp-cmd-newWindow"
        modifiers="accel"/>
   <key id="sp-key-open"
        key="&openFileCmd.commandkey;"
        command="sp-cmd-openFile"
@@ -118,19 +118,19 @@
   <key id="key_copy"
        key="&copyCmd.key;"
        modifiers="accel"/>
   <key id="key_paste"
        key="&pasteCmd.key;"
        modifiers="accel"/>
   <key id="key_selectAll" key="&selectAllCmd.key;" modifiers="accel"/>
   <key id="key_undo" key="&undoCmd.key;" modifiers="accel"
-       oncommand="Scratchpad.undo();"/>
+       command="se-cmd-undo"/>
   <key id="key_redo" key="&undoCmd.key;" modifiers="accel,shift"
-       oncommand="Scratchpad.redo();"/>
+       command="se-cmd-redo"/>
   <key id="sp-key-run"
        key="&run.key;"
        command="sp-cmd-run"
        modifiers="accel"/>
   <key id="sp-key-inspect"
        key="&inspect.key;"
        command="sp-cmd-inspect"
        modifiers="accel"/>
@@ -163,20 +163,16 @@
   <key id="key_findAgain"
        keycode="VK_F3"
        command="cmd_findAgain"/>
   <key id="key_findPrevious"
        keycode="VK_F3"
        command="cmd_findPrevious"
        modifiers="shift"/>
 #endif
-  <key id="key_gotoLine"
-       key="&gotoLineCmd.key;"
-       command="cmd_gotoLine"
-       modifiers="accel"/>
   <key id="key_openHelp"
        keycode="VK_F1"
        command="sp-cmd-documentationLink"/>
 </keyset>
 
 
 <menubar id="sp-menubar">
   <menu id="sp-file-menu" label="&fileMenu.label;"
@@ -218,27 +214,27 @@
                 accesskey="&closeCmd.accesskey;"
                 command="sp-cmd-close"/>
     </menupopup>
   </menu>
 
   <menu id="sp-edit-menu" label="&editMenu.label;"
         accesskey="&editMenu.accesskey;">
     <menupopup id="sp-menu_editpopup"
-               onpopupshowing="Scratchpad.onEditPopupShowing()">
+               onpopupshowing="goUpdateGlobalEditMenuItems()">
       <menuitem id="sp-menu-undo"
                 label="&undoCmd.label;"
                 key="key_undo"
                 accesskey="&undoCmd.accesskey;"
-                command="sp-cmd-undo"/>
+                command="se-cmd-undo"/>
       <menuitem id="sp-menu-redo"
                 label="&redoCmd.label;"
                 key="key_redo"
                 accesskey="&redoCmd.accesskey;"
-                command="sp-cmd-redo"/>
+                command="se-cmd-redo"/>
       <menuseparator/>
       <menuitem id="sp-menu-cut"
                 label="&cutCmd.label;"
                 key="key_cut"
                 accesskey="&cutCmd.accesskey;"
                 command="cmd_cut"/>
       <menuitem id="sp-menu-copy"
                 label="&copyCmd.label;"
--- a/browser/devtools/scratchpad/test/browser_scratchpad_bug_653427_confirm_close.js
+++ b/browser/devtools/scratchpad/test/browser_scratchpad_bug_653427_confirm_close.js
@@ -41,94 +41,92 @@ function test()
   testSavedFile();
 
   content.location = "data:text/html,<p>test scratchpad save file prompt on closing";
 }
 
 function testNew()
 {
   openScratchpad(function(win) {
-    win.Scratchpad.close();
-    ok(win.closed, "new scratchpad window should close without prompting")
-    done();
+    win.Scratchpad.close(function() {
+      ok(win.closed, "new scratchpad window should close without prompting")
+      done();
+    });
   }, {noFocus: true});
 }
 
 function testSavedFile()
 {
   openScratchpad(function(win) {
     win.Scratchpad.filename = "test.js";
-    win.Scratchpad.saved = true;
-    win.Scratchpad.close();
-
-    ok(win.closed, "scratchpad from file with no changes should close")
-    done();
+    win.Scratchpad.editor.dirty = false;
+    win.Scratchpad.close(function() {
+      ok(win.closed, "scratchpad from file with no changes should close")
+      done();
+    });
   }, {noFocus: true});
 }
 
 function testUnsaved()
 {
   testUnsavedFileCancel();
   testUnsavedFileSave();
   testUnsavedFileDontSave();
 }
 
 function testUnsavedFileCancel()
 {
   openScratchpad(function(win) {
-    win.Scratchpad.filename = "test.js";
-    win.Scratchpad.saved = false;
+    win.Scratchpad.setFilename("test.js");
+    win.Scratchpad.editor.dirty = true;
 
     promptButton = win.BUTTON_POSITION_CANCEL;
 
-    win.Scratchpad.close();
-
-    ok(!win.closed, "cancelling dialog shouldn't close scratchpad");
-
-    win.close();
-    done();
+    win.Scratchpad.close(function() {
+      ok(!win.closed, "cancelling dialog shouldn't close scratchpad");
+      win.close();
+      done();
+    });
   }, {noFocus: true});
 }
 
 function testUnsavedFileSave()
 {
   openScratchpad(function(win) {
     win.Scratchpad.importFromFile(gFile, true, function(status, content) {
-      win.Scratchpad.filename = gFile.path;
-      win.Scratchpad.onTextSaved();
+      win.Scratchpad.setFilename(gFile.path);
 
       let text = "new text";
       win.Scratchpad.setText(text);
 
       promptButton = win.BUTTON_POSITION_SAVE;
 
       win.Scratchpad.close(function() {
+        ok(win.closed, 'pressing "Save" in dialog should close scratchpad');
         readFile(gFile, function(savedContent) {
           is(savedContent, text, 'prompted "Save" worked when closing scratchpad');
           done();
         });
       });
-
-      ok(win.closed, 'pressing "Save" in dialog should close scratchpad');
     });
   }, {noFocus: true});
 }
 
 function testUnsavedFileDontSave()
 {
   openScratchpad(function(win) {
-    win.Scratchpad.filename = gFile.path;
-    win.Scratchpad.saved = false;
+    win.Scratchpad.setFilename(gFile.path);
+    win.Scratchpad.editor.dirty = true;
 
     promptButton = win.BUTTON_POSITION_DONT_SAVE;
 
-    win.Scratchpad.close();
-
-    ok(win.closed, 'pressing "Don\'t Save" in dialog should close scratchpad');
-    done();
+    win.Scratchpad.close(function() {
+      ok(win.closed, 'pressing "Don\'t Save" in dialog should close scratchpad');
+      done();
+    });
   }, {noFocus: true});
 }
 
 function cleanup()
 {
   Services.prompt = oldPrompt;
   gFile.remove(false);
   gFile = null;
--- a/browser/devtools/scratchpad/test/browser_scratchpad_bug_669612_unsaved.js
+++ b/browser/devtools/scratchpad/test/browser_scratchpad_bug_669612_unsaved.js
@@ -1,74 +1,67 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */  
 
 // only finish() when correct number of tests are done
-const expected = 5;
+const expected = 4;
 var count = 0;
 function done()
 {
   if (++count == expected) {
     finish();
   }
 }
 
 var ScratchpadManager = Scratchpad.ScratchpadManager;
 
 
 function test()
 {
   waitForExplicitFinish();
   
   testListeners();
-  testErrorStatus();
   testRestoreNotFromFile();
   testRestoreFromFileSaved();
   testRestoreFromFileUnsaved();
 
   content.location = "data:text/html,<p>test star* UI for unsaved file changes";
 }
 
 function testListeners()
 {
   openScratchpad(function(aWin, aScratchpad) {
     aScratchpad.setText("new text");
     ok(!isStar(aWin), "no star if scratchpad isn't from a file");
 
-    aScratchpad.onTextSaved();
+    aScratchpad.editor.dirty = false;
     ok(!isStar(aWin), "no star before changing text");
 
+    aScratchpad.setFilename("foo.js");
     aScratchpad.setText("new text2");
     ok(isStar(aWin), "shows star if scratchpad text changes");
 
-    aScratchpad.onTextSaved();
+    aScratchpad.editor.dirty = false;
     ok(!isStar(aWin), "no star if scratchpad was just saved");
 
+    aScratchpad.setText("new text3");
+    ok(isStar(aWin), "shows star if scratchpad has more changes");
+
     aScratchpad.undo();
-    ok(isStar(aWin), "star if scratchpad undo");
+    ok(!isStar(aWin), "no star if scratchpad undo to save point");
+
+    aScratchpad.undo();
+    ok(isStar(aWin), "star if scratchpad undo past save point");
 
     aWin.close();
     done();
   }, {noFocus: true});
 }
 
-function testErrorStatus()
-{
-  openScratchpad(function(aWin, aScratchpad) {
-    aScratchpad.onTextSaved(Components.results.NS_ERROR_FAILURE);
-    aScratchpad.setText("new text");
-    ok(!isStar(aWin), "no star if file save failed");
-
-    aWin.close();
-    done();
-  }, {noFocus: true});
-}
-
-
 function testRestoreNotFromFile()
 {
   let session = [{
     text: "test1",
     executionContext: 1
   }];
 
   let [win] = ScratchpadManager.restoreSession(session);
--- a/browser/devtools/scratchpad/test/browser_scratchpad_ui.js
+++ b/browser/devtools/scratchpad/test/browser_scratchpad_ui.js
@@ -27,18 +27,16 @@ function runTests()
     "sp-menu-save": "saveFile",
     "sp-menu-saveas": "saveFileAs",
     "sp-text-run": "run",
     "sp-text-inspect": "inspect",
     "sp-text-display": "display",
     "sp-text-resetContext": "resetContext",
     "sp-menu-content": "setContentContext",
     "sp-menu-browser": "setBrowserContext",
-    "sp-menu-undo": "undo",
-    "sp-menu-redo": "redo",
   };
 
   let lastMethodCalled = null;
   sp.__noSuchMethod__ = function(aMethodName) {
     lastMethodCalled = aMethodName;
   };
 
   for (let id in methodsAndItems) {
--- a/browser/devtools/sourceeditor/source-editor-orion.jsm
+++ b/browser/devtools/sourceeditor/source-editor-orion.jsm
@@ -141,16 +141,18 @@ function SourceEditor() {
   // Update the SourceEditor defaults from user preferences.
 
   SourceEditor.DEFAULTS.tabSize =
     Services.prefs.getIntPref(SourceEditor.PREFS.TAB_SIZE);
   SourceEditor.DEFAULTS.expandTab =
     Services.prefs.getBoolPref(SourceEditor.PREFS.EXPAND_TAB);
 
   this._onOrionSelection = this._onOrionSelection.bind(this);
+  this._onTextChanged = this._onTextChanged.bind(this);
+  this._onOrionContextMenu = this._onOrionContextMenu.bind(this);
 
   this._eventTarget = {};
   this._eventListenersQueue = [];
   this.ui = new SourceEditorUI(this);
 }
 
 SourceEditor.prototype = {
   _view: null,
@@ -167,16 +169,18 @@ SourceEditor.prototype = {
   _currentLineAnnotation: null,
   _primarySelectionTimeout: null,
   _mode: null,
   _expandTab: null,
   _tabSize: null,
   _iframeWindow: null,
   _eventTarget: null,
   _eventListenersQueue: null,
+  _contextMenu: null,
+  _dirty: false,
 
   /**
    * The Source Editor user interface manager.
    * @type object
    *       An instance of the SourceEditorUI.
    */
   ui: null,
 
@@ -274,17 +278,31 @@ SourceEditor.prototype = {
 
     let onOrionLoad = function() {
       this._view.removeEventListener("Load", onOrionLoad);
       this._onOrionLoad();
     }.bind(this);
 
     this._view.addEventListener("Load", onOrionLoad);
     if (config.highlightCurrentLine || Services.appinfo.OS == "Linux") {
-      this._view.addEventListener("Selection", this._onOrionSelection);
+      this.addEventListener(SourceEditor.EVENTS.SELECTION,
+                            this._onOrionSelection);
+    }
+    this.addEventListener(SourceEditor.EVENTS.TEXT_CHANGED,
+                           this._onTextChanged);
+
+    if (typeof config.contextMenu == "string") {
+      let chromeDocument = this.parentElement.ownerDocument;
+      this._contextMenu = chromeDocument.getElementById(config.contextMenu);
+    } else if (typeof config.contextMenu == "object" ) {
+      this._contextMenu = config._contextMenu;
+    }
+    if (this._contextMenu) {
+      this.addEventListener(SourceEditor.EVENTS.CONTEXT_MENU,
+                            this._onOrionContextMenu);
     }
 
     let KeyBinding = window.require("orion/textview/keyBinding").KeyBinding;
     let TextDND = window.require("orion/textview/textDND").TextDND;
     let Rulers = window.require("orion/textview/rulers");
     let LineNumberRuler = Rulers.LineNumberRuler;
     let AnnotationRuler = Rulers.AnnotationRuler;
     let OverviewRuler = Rulers.OverviewRuler;
@@ -583,16 +601,54 @@ SourceEditor.prototype = {
       }
       this._primarySelectionTimeout =
         window.setTimeout(this._updatePrimarySelection.bind(this),
                           PRIMARY_SELECTION_DELAY);
     }
   },
 
   /**
+   * The TextChanged event handler which tracks the dirty state of the editor.
+   *
+   * @see SourceEditor.EVENTS.TEXT_CHANGED
+   * @see SourceEditor.EVENTS.DIRTY_CHANGED
+   * @see SourceEditor.dirty
+   * @private
+   */
+  _onTextChanged: function SE__onTextChanged()
+  {
+    this._updateDirty();
+  },
+
+  /**
+   * The Orion contextmenu event handler. This method opens the default or
+   * the custom context menu popup at the pointer location.
+   *
+   * @param object aEvent
+   *        The contextmenu event object coming from Orion. This object should
+   *        hold the screenX and screenY properties.
+   */
+  _onOrionContextMenu: function SE__onOrionContextMenu(aEvent)
+  {
+    if (this._contextMenu.state == "closed") {
+      this._contextMenu.openPopupAtScreen(aEvent.screenX || 0,
+                                          aEvent.screenY || 0, true);
+    }
+  },
+
+  /**
+   * Update the dirty state of the editor based on the undo stack.
+   * @private
+   */
+  _updateDirty: function SE__updateDirty()
+  {
+    this.dirty = !this._undoStack.isClean();
+  },
+
+  /**
    * Update the X11 PRIMARY buffer to hold the current selection.
    * @private
    */
   _updatePrimarySelection: function SE__updatePrimarySelection()
   {
     this._primarySelectionTimeout = null;
 
     let text = this.getSelectedText();
@@ -861,28 +917,38 @@ SourceEditor.prototype = {
       this._eventTarget.removeEventListener(aEventType, aCallback);
     } else {
       this._eventListenersQueue.push(["remove", aEventType, aCallback]);
     }
   },
 
   /**
    * Undo a change in the editor.
+   *
+   * @return boolean
+   *         True if there was a change undone, false otherwise.
    */
   undo: function SE_undo()
   {
-    return this._undoStack.undo();
+    let result = this._undoStack.undo();
+    this.ui._onUndoRedo();
+    return result;
   },
 
   /**
    * Redo a change in the editor.
+   *
+   * @return boolean
+   *         True if there was a change redone, false otherwise.
    */
   redo: function SE_redo()
   {
-    return this._undoStack.redo();
+    let result = this._undoStack.redo();
+    this.ui._onUndoRedo();
+    return result;
   },
 
   /**
    * Check if there are changes that can be undone.
    *
    * @return boolean
    *         True if there are changes that can be undone, false otherwise.
    */
@@ -898,21 +964,64 @@ 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
+   * Reset the Undo stack.
    */
   resetUndo: function SE_resetUndo()
   {
     this._undoStack.reset();
+    this._updateDirty();
+    this.ui._onUndoRedo();
+  },
+
+  /**
+   * Set the "dirty" state of the editor. Set this to false when you save the
+   * text being edited. The dirty state will become true once the user makes
+   * changes to the text.
+   *
+   * @param boolean aNewValue
+   *        The new dirty state: true if the text is not saved, false if you
+   *        just saved the text.
+   */
+  set dirty(aNewValue)
+  {
+    if (aNewValue == this._dirty) {
+      return;
+    }
+
+    let event = {
+      type: SourceEditor.EVENTS.DIRTY_CHANGED,
+      oldValue: this._dirty,
+      newValue: aNewValue,
+    };
+
+    this._dirty = aNewValue;
+    if (!this._dirty && !this._undoStack.isClean()) {
+      this._undoStack.markClean();
+    }
+    this._dispatchEvent(event);
+  },
+
+  /**
+   * Get the editor "dirty" state. This tells if the text is considered saved or
+   * not.
+   *
+   * @see SourceEditor.EVENTS.DIRTY_CHANGED
+   * @return boolean
+   *         True if there are changes which are not saved, false otherwise.
+   */
+  get dirty()
+  {
+    return this._dirty;
   },
 
   /**
    * 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()
@@ -1321,20 +1430,32 @@ SourceEditor.prototype = {
   },
 
   /**
    * Destroy/uninitialize the editor.
    */
   destroy: function SE_destroy()
   {
     if (this._config.highlightCurrentLine || Services.appinfo.OS == "Linux") {
-      this._view.removeEventListener("Selection", this._onOrionSelection);
+      this.removeEventListener(SourceEditor.EVENTS.SELECTION,
+                               this._onOrionSelection);
     }
     this._onOrionSelection = null;
 
+    this.removeEventListener(SourceEditor.EVENTS.TEXT_CHANGED,
+                             this._onTextChanged);
+    this._onTextChanged = null;
+
+    if (this._contextMenu) {
+      this.removeEventListener(SourceEditor.EVENTS.CONTEXT_MENU,
+                               this._onOrionContextMenu);
+      this._contextMenu = null;
+    }
+    this._onOrionContextMenu = null;
+
     if (this._primarySelectionTimeout) {
       let window = this.parentElement.ownerDocument.defaultView;
       window.clearTimeout(this._primarySelectionTimeout);
       this._primarySelectionTimeout = null;
     }
 
     this._view.destroy();
     this.ui.destroy();
--- a/browser/devtools/sourceeditor/source-editor-overlay.xul
+++ b/browser/devtools/sourceeditor/source-editor-overlay.xul
@@ -30,18 +30,85 @@
    - 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 ***** -->
-
+<!DOCTYPE overlay SYSTEM "chrome://browser/locale/devtools/sourceeditor.dtd">
 <overlay id="sourceEditorOverlay"
          xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+  <!-- This Source Editor overlay requires the editMenuOverlay.xul to be loaded.
+       The globalOverlay.js script is also required in the XUL document where
+       the source-editor-overlay.xul is loaded. -->
+
   <commandset id="sourceEditorCommands">
     <command id="cmd_find" oncommand="goDoCommand('cmd_find')"/>
     <command id="cmd_findAgain" oncommand="goDoCommand('cmd_findAgain')" disabled="true"/>
     <command id="cmd_findPrevious" oncommand="goDoCommand('cmd_findPrevious')" disabled="true"/>
     <command id="cmd_gotoLine" oncommand="goDoCommand('cmd_gotoLine')"/>
+    <command id="se-cmd-undo" oncommand="goDoCommand('se-cmd-undo')" disabled="true"/>
+    <command id="se-cmd-redo" oncommand="goDoCommand('se-cmd-redo')" disabled="true"/>
   </commandset>
+
+  <keyset id="sourceEditorKeys">
+    <key id="key_gotoLine"
+         key="&gotoLineCmd.key;"
+         command="cmd_gotoLine"
+         modifiers="accel"/>
+  </keyset>
+
+  <menupopup id="sourceEditorContextMenu"
+             onpopupshowing="goUpdateGlobalEditMenuItems()">
+    <menuitem id="se-menu-undo"
+              label="&undoCmd.label;"
+              key="key_undo"
+              accesskey="&undoCmd.accesskey;"
+              command="se-cmd-undo"/>
+    <menuseparator/>
+    <menuitem id="se-menu-cut"
+              label="&cutCmd.label;"
+              key="key_cut"
+              accesskey="&cutCmd.accesskey;"
+              command="cmd_cut"/>
+    <menuitem id="se-menu-copy"
+              label="&copyCmd.label;"
+              key="key_copy"
+              accesskey="&copyCmd.accesskey;"
+              command="cmd_copy"/>
+    <menuitem id="se-menu-paste"
+              label="&pasteCmd.label;"
+              key="key_paste"
+              accesskey="&pasteCmd.accesskey;"
+              command="cmd_paste"/>
+    <menuitem id="se-menu-delete"
+              label="&deleteCmd.label;"
+              key="key_delete"
+              accesskey="&deleteCmd.accesskey;"
+              command="cmd_delete"/>
+    <menuseparator/>
+    <menuitem id="se-menu-selectAll"
+              label="&selectAllCmd.label;"
+              key="key_selectAll"
+              accesskey="&selectAllCmd.accesskey;"
+              command="cmd_selectAll"/>
+    <menuseparator/>
+    <menuitem id="se-menu-find"
+              label="&findCmd.label;"
+              accesskey="&findCmd.accesskey;"
+              key="key_find"
+              command="cmd_find"/>
+    <menuitem id="se-menu-findAgain"
+              label="&findAgainCmd.label;"
+              accesskey="&findAgainCmd.accesskey;"
+              key="key_findAgain"
+              command="cmd_findAgain"/>
+    <menuseparator/>
+    <menuitem id="se-menu-gotoLine"
+              label="&gotoLineCmd.label;"
+              accesskey="&gotoLineCmd.accesskey;"
+              key="key_gotoLine"
+              command="cmd_gotoLine"/>
+  </menupopup>
 </overlay>
--- a/browser/devtools/sourceeditor/source-editor-ui.jsm
+++ b/browser/devtools/sourceeditor/source-editor-ui.jsm
@@ -45,16 +45,17 @@ Cu.import("resource://gre/modules/Servic
 var EXPORTED_SYMBOLS = ["SourceEditorUI"];
 
 /**
  * The Source Editor component user interface.
  */
 function SourceEditorUI(aEditor)
 {
   this.editor = aEditor;
+  this._onDirtyChanged = this._onDirtyChanged.bind(this);
 }
 
 SourceEditorUI.prototype = {
   /**
    * Initialize the user interface. This is called by the SourceEditor.init()
    * method.
    */
   init: function SEU_init()
@@ -67,16 +68,18 @@ SourceEditorUI.prototype = {
    * initialization and it is ready for usage. Currently this code sets up the
    * nsIController.
    */
   onReady: function SEU_onReady()
   {
     if (this._ownerWindow.controllers) {
       this._controller = new SourceEditorController(this.editor);
       this._ownerWindow.controllers.insertControllerAt(0, this._controller);
+      this.editor.addEventListener(this.editor.EVENTS.DIRTY_CHANGED,
+                                   this._onDirtyChanged);
     }
   },
 
   /**
    * The "go to line" command UI. This displays a prompt that allows the user to
    * input the line number to jump to.
    */
   gotoLine: function SEU_gotoLine()
@@ -173,21 +176,49 @@ SourceEditorUI.prototype = {
 
     if (this._ownerWindow.goUpdateCommand) {
       this._ownerWindow.goUpdateCommand("cmd_findAgain");
       this._ownerWindow.goUpdateCommand("cmd_findPrevious");
     }
   },
 
   /**
+   * This is executed after each undo/redo operation.
+   * @private
+   */
+  _onUndoRedo: function SEU__onUndoRedo()
+  {
+    if (this._ownerWindow.goUpdateCommand) {
+      this._ownerWindow.goUpdateCommand("se-cmd-undo");
+      this._ownerWindow.goUpdateCommand("se-cmd-redo");
+    }
+  },
+
+  /**
+   * The DirtyChanged event handler for the editor. This tracks the editor state
+   * changes to make sure the Source Editor overlay Undo/Redo commands are kept
+   * up to date.
+   * @private
+   */
+  _onDirtyChanged: function SEU__onDirtyChanged()
+  {
+    this._onUndoRedo();
+  },
+
+  /**
    * Destroy the SourceEditorUI instance. This is called by the
    * SourceEditor.destroy() method.
    */
   destroy: function SEU_destroy()
   {
+    if (this._ownerWindow.controllers) {
+      this.editor.removeEventListener(this.editor.EVENTS.DIRTY_CHANGED,
+                                      this._onDirtyChanged);
+    }
+
     this._ownerWindow = null;
     this.editor = null;
     this._controller = null;
   },
 };
 
 /**
  * The Source Editor nsIController implements features that need to be available
@@ -215,16 +246,18 @@ SourceEditorController.prototype = {
   {
     let result;
 
     switch (aCommand) {
       case "cmd_find":
       case "cmd_findAgain":
       case "cmd_findPrevious":
       case "cmd_gotoLine":
+      case "se-cmd-undo":
+      case "se-cmd-redo":
         result = true;
         break;
       default:
         result = false;
         break;
     }
 
     return result;
@@ -246,16 +279,22 @@ SourceEditorController.prototype = {
       case "cmd_find":
       case "cmd_gotoLine":
         result = true;
         break;
       case "cmd_findAgain":
       case "cmd_findPrevious":
         result = this._editor.lastFind && this._editor.lastFind.lastFound != -1;
         break;
+      case "se-cmd-undo":
+        result = this._editor.canUndo();
+        break;
+      case "se-cmd-redo":
+        result = this._editor.canRedo();
+        break;
       default:
         result = false;
         break;
     }
 
     return result;
   },
 
@@ -276,13 +315,19 @@ SourceEditorController.prototype = {
         this._editor.ui.findNext();
         break;
       case "cmd_findPrevious":
         this._editor.ui.findPrevious();
         break;
       case "cmd_gotoLine":
         this._editor.ui.gotoLine();
         break;
+      case "se-cmd-undo":
+        this._editor.undo();
+        break;
+      case "se-cmd-redo":
+        this._editor.redo();
+        break;
     }
   },
 
   onEvent: function() { }
 };
--- a/browser/devtools/sourceeditor/source-editor.jsm
+++ b/browser/devtools/sourceeditor/source-editor.jsm
@@ -194,16 +194,32 @@ SourceEditor.DEFAULTS = {
    *   - accel - boolean for the Accel key (Cmd on Macs, Ctrl on Linux/Windows).
    *   - shift - boolean for the Shift key.
    *   - alt - boolean for the Alt key.
    *   - callback - optional function to invoke, if the action is not predefined
    *   in the editor.
    * @type array
    */
   keys: null,
+
+  /**
+   * The editor context menu you want to display when the user right-clicks
+   * within the editor. This property can be:
+   *   - a string that tells the ID of the xul:menupopup you want. This needs to
+   *   be available within the editor parentElement.ownerDocument.
+   *   - an nsIDOMElement object reference pointing to the xul:menupopup you
+   *   want to open when the contextmenu event is fired.
+   *
+   * Set this property to a falsey value to disable the default context menu.
+   *
+   * @see SourceEditor.EVENTS.CONTEXT_MENU for more control over the contextmenu
+   * event.
+   * @type string|nsIDOMElement
+   */
+  contextMenu: "sourceEditorContextMenu",
 };
 
 /**
  * Known editor events you can listen for.
  */
 SourceEditor.EVENTS = {
   /**
    * The contextmenu event is fired when the editor context menu is invoked. The
@@ -211,16 +227,18 @@ SourceEditor.EVENTS = {
    *   - x - the pointer location on the x axis, relative to the document the
    *   user is editing.
    *   - y - the pointer location on the y axis, relative to the document the
    *   user is editing.
    *   - screenX - the pointer location on the x axis, relative to the screen.
    *   This value comes from the DOM contextmenu event.screenX property.
    *   - screenY - the pointer location on the y axis, relative to the screen.
    *   This value comes from the DOM contextmenu event.screenY property.
+   *
+   * @see SourceEditor.DEFAULTS.contextMenu
    */
   CONTEXT_MENU: "ContextMenu",
 
   /**
    * The TextChanged event is fired when the editor content changes. The event
    * object properties:
    *   - start - the character offset in the document where the change has
    *   occured.
@@ -277,16 +295,25 @@ SourceEditor.EVENTS = {
    * a breakpoint is removed - either through API use or through the editor UI.
    * Event object properties:
    *   - added - array that holds the new breakpoints.
    *   - removed - array that holds the breakpoints that have been removed.
    * Each object in the added/removed arrays holds two properties: line and
    * condition.
    */
   BREAKPOINT_CHANGE: "BreakpointChange",
+
+  /**
+   * The DirtyChanged event is fired when the dirty state of the editor is
+   * changed. The dirty state of the editor tells if the are text changes that
+   * have not been saved yet. Event object properties: oldValue and newValue.
+   * Both are booleans telling the old dirty state and the new state,
+   * respectively.
+   */
+  DIRTY_CHANGED: "DirtyChanged",
 };
 
 /**
  * Extend a destination object with properties from a source object.
  *
  * @param object aDestination
  * @param object aSource
  */
@@ -298,16 +325,22 @@ function extend(aDestination, aSource)
     }
   }
 }
 
 /**
  * Add methods common to all components.
  */
 extend(SourceEditor.prototype, {
+  // Expose the static constants on the SourceEditor instances.
+  EVENTS: SourceEditor.EVENTS,
+  MODES: SourceEditor.MODES,
+  THEMES: SourceEditor.THEMES,
+  DEFAULTS: SourceEditor.DEFAULTS,
+
   _lastFind: null,
 
   /**
    * Find a string in the editor.
    *
    * @param string aString
    *        The string you want to search for. If |aString| is not given the
    *        currently selected text is used.
--- a/browser/devtools/sourceeditor/test/Makefile.in
+++ b/browser/devtools/sourceeditor/test/Makefile.in
@@ -53,12 +53,13 @@ include $(topsrcdir)/config/rules.mk
 		browser_bug684546_reset_undo.js \
 		browser_bug695035_middle_click_paste.js \
 		browser_bug687160_line_api.js \
 		browser_bug650345_find.js \
 		browser_bug703692_focus_blur.js \
 		browser_bug725388_mouse_events.js \
 		browser_bug707987_debugger_breakpoints.js \
 		browser_bug712982_line_ruler_click.js \
+		browser_bug700893_dirty_state.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_bug700893_dirty_state.js
@@ -0,0 +1,94 @@
+/* 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";
+
+function test() {
+
+  let temp = {};
+  Cu.import("resource:///modules/source-editor.jsm", temp);
+  let SourceEditor = temp.SourceEditor;
+
+  let component = Services.prefs.getCharPref(SourceEditor.PREFS.COMPONENT);
+  if (component == "textarea") {
+    ok(true, "skip test for bug 700893: only applicable for non-textarea components");
+    return;
+  }
+
+  waitForExplicitFinish();
+
+  let editor;
+
+  const windowUrl = "data:text/xml,<?xml version='1.0'?>" +
+    "<window xmlns='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul'" +
+    " title='test for bug 700893' width='600' height='500'><hbox flex='1'/></window>";
+  const windowFeatures = "chrome,titlebar,toolbar,centerscreen,resizable,dialog=no";
+
+  let 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 hbox = testWin.document.querySelector("hbox");
+    editor = new SourceEditor();
+    editor.init(hbox, {initialText: "foobar"}, editorLoaded);
+  }
+
+  function editorLoaded()
+  {
+    editor.focus();
+
+    is(editor.dirty, false, "editory is not dirty");
+
+    let event = null;
+    let eventHandler = function(aEvent) {
+      event = aEvent;
+    };
+    editor.addEventListener(SourceEditor.EVENTS.DIRTY_CHANGED, eventHandler);
+
+    editor.setText("omg");
+
+    is(editor.dirty, true, "editor is dirty");
+    ok(event, "DirtyChanged event fired")
+    is(event.oldValue, false, "event.oldValue is correct");
+    is(event.newValue, true, "event.newValue is correct");
+
+    event = null;
+    editor.setText("foo 2");
+    ok(!event, "no DirtyChanged event fired");
+
+    editor.dirty = false;
+
+    is(editor.dirty, false, "editor marked as clean");
+    ok(event, "DirtyChanged event fired")
+    is(event.oldValue, true, "event.oldValue is correct");
+    is(event.newValue, false, "event.newValue is correct");
+
+    event = null;
+    editor.setText("foo 3");
+
+    is(editor.dirty, true, "editor is dirty after changes");
+    ok(event, "DirtyChanged event fired")
+    is(event.oldValue, false, "event.oldValue is correct");
+    is(event.newValue, true, "event.newValue is correct");
+
+    editor.undo();
+    is(editor.dirty, false, "editor is not dirty after undo");
+    ok(event, "DirtyChanged event fired")
+    is(event.oldValue, true, "event.oldValue is correct");
+    is(event.newValue, false, "event.newValue is correct");
+
+    editor.removeEventListener(SourceEditor.EVENTS.DIRTY_CHANGED, eventHandler);
+
+    editor.destroy();
+
+    testWin.close();
+    testWin = editor = null;
+
+    waitForFocus(finish, window);
+  }
+}
--- a/browser/devtools/styleeditor/styleeditor.xul
+++ b/browser/devtools/styleeditor/styleeditor.xul
@@ -40,29 +40,39 @@
  %styleEditorDTD;
 ]>
 <?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?>
 <?xml-stylesheet href="chrome://browser/content/splitview.css" type="text/css"?>
 <?xml-stylesheet href="chrome://browser/skin/devtools/common.css" type="text/css"?>
 <?xml-stylesheet href="chrome://browser/skin/devtools/splitview.css" type="text/css"?>
 <?xml-stylesheet href="chrome://browser/content/styleeditor.css" type="text/css"?>
 <?xml-stylesheet href="chrome://browser/skin/devtools/styleeditor.css" type="text/css"?>
+<?xul-overlay href="chrome://global/content/editMenuOverlay.xul"?>
+<?xul-overlay href="chrome://browser/content/source-editor-overlay.xul"?>
 <xul:window xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
         xmlns="http://www.w3.org/1999/xhtml"
         id="style-editor-chrome-window"
         title="&window.title;"
         windowtype="Tools:StyleEditor"
         width="800" height="280"
         persist="screenX screenY width height sizemode">
 <xul:script type="application/javascript" src="chrome://global/content/globalOverlay.js"/>
 
+<xul:popupset id="style-editor-popups">
+  <xul:menupopup id="sourceEditorContextMenu"/>
+</xul:popupset>
+
+<xul:commandset id="editMenuCommands"/>
+<xul:commandset id="sourceEditorCommands"/>
 <xul:commandset id="style-editor-commandset">
   <xul:command id="style-editor-cmd-close" oncommand="window.close();"/>
 </xul:commandset>
 
+<xul:keyset id="editMenuKeys"/>
+<xul:keyset id="sourceEditorKeys"/>
 <xul:keyset id="style-editor-keyset">
   <xul:key id="style-editor-key-close"
            key="&closeCmd.key;"
            command="style-editor-cmd-close"
            modifiers="accel"/>
 </xul:keyset>
 
 <xul:box id="style-editor-chrome" class="splitview-root loading">
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -185,16 +185,17 @@
 @BINPATH@/components/fastfind.xpt
 @BINPATH@/components/feeds.xpt
 #ifdef MOZ_GTK2
 @BINPATH@/components/filepicker.xpt
 #endif
 @BINPATH@/components/find.xpt
 @BINPATH@/components/fuel.xpt
 @BINPATH@/components/gfx.xpt
+@BINPATH@/components/html5.xpt
 @BINPATH@/components/htmlparser.xpt
 @BINPATH@/components/imglib2.xpt
 @BINPATH@/components/imgicon.xpt
 @BINPATH@/components/inspector.xpt
 @BINPATH@/components/intl.xpt
 @BINPATH@/components/jar.xpt
 @BINPATH@/components/jsdservice.xpt
 @BINPATH@/components/jsdebugger.xpt
--- a/browser/installer/removed-files.in
+++ b/browser/installer/removed-files.in
@@ -1186,16 +1186,17 @@ xpicleanup@BIN_SUFFIX@
   components/exthelper.xpt
   components/fastfind.xpt
   components/feeds.xpt
   components/find.xpt
   components/firefox.xpt
   components/fuel.xpt
   components/gfx.xpt
   components/gksvgrenderer.xpt
+  components/html5.xpt
   components/htmlparser.xpt
   components/imgicon.xpt
   components/imglib2.xpt
   components/inspector.xpt
   components/intl.xpt
   components/jar.xpt
   components/jsconsole.xpt
   components/jsdservice.xpt
new file mode 100644
--- /dev/null
+++ b/browser/locales/en-US/chrome/browser/devtools/sourceeditor.dtd
@@ -0,0 +1,32 @@
+<!-- LOCALIZATION NOTE : FILE This file contains the Source Editor component
+  - strings. The source editor component is used within the Scratchpad and
+  - Style Editor tools. -->
+
+<!-- LOCALIZATION NOTE : FILE Do not translate commandkeys -->
+
+<!-- LOCALIZATION NOTE : FILE The correct localization of this file might be to
+  - keep it in English, or another language commonly spoken among web developers.
+  - You want to make that choice consistent across the developer tools.
+  - A good criteria is the language in which you'd find the best
+  - documentation on web development on the web. -->
+
+<!ENTITY undoCmd.label             "Undo">
+<!ENTITY undoCmd.accesskey         "U">
+<!ENTITY cutCmd.label              "Cut">
+<!ENTITY cutCmd.accesskey          "t">
+<!ENTITY copyCmd.label             "Copy">
+<!ENTITY copyCmd.accesskey         "C">
+<!ENTITY pasteCmd.label            "Paste">
+<!ENTITY pasteCmd.accesskey        "P">
+<!ENTITY deleteCmd.label           "Delete">
+<!ENTITY deleteCmd.accesskey       "D">
+<!ENTITY selectAllCmd.label        "Select All">
+<!ENTITY selectAllCmd.accesskey    "A">
+<!ENTITY findCmd.label             "Find…">
+<!ENTITY findCmd.accesskey         "F">
+<!ENTITY findAgainCmd.label        "Find Again…">
+<!ENTITY findAgainCmd.accesskey    "g">
+<!ENTITY gotoLineCmd.label         "Jump to line…">
+<!ENTITY gotoLineCmd.key           "J">
+<!ENTITY gotoLineCmd.accesskey     "J">
+
--- a/browser/locales/jar.mn
+++ b/browser/locales/jar.mn
@@ -25,16 +25,17 @@
     locale/browser/devtools/scratchpad.properties     (%chrome/browser/devtools/scratchpad.properties)
     locale/browser/devtools/scratchpad.dtd            (%chrome/browser/devtools/scratchpad.dtd)
     locale/browser/devtools/styleeditor.properties    (%chrome/browser/devtools/styleeditor.properties)
     locale/browser/devtools/styleeditor.dtd           (%chrome/browser/devtools/styleeditor.dtd)
     locale/browser/devtools/styleinspector.properties (%chrome/browser/devtools/styleinspector.properties)
     locale/browser/devtools/styleinspector.dtd        (%chrome/browser/devtools/styleinspector.dtd)
     locale/browser/devtools/webConsole.dtd            (%chrome/browser/devtools/webConsole.dtd)
     locale/browser/devtools/sourceeditor.properties   (%chrome/browser/devtools/sourceeditor.properties)
+    locale/browser/devtools/sourceeditor.dtd          (%chrome/browser/devtools/sourceeditor.dtd)
     locale/browser/newTab.dtd                      (%chrome/browser/newTab.dtd)
     locale/browser/newTab.properties               (%chrome/browser/newTab.properties)
     locale/browser/openLocation.dtd                (%chrome/browser/openLocation.dtd)
     locale/browser/openLocation.properties         (%chrome/browser/openLocation.properties)
 *   locale/browser/pageInfo.dtd                    (%chrome/browser/pageInfo.dtd)
     locale/browser/pageInfo.properties             (%chrome/browser/pageInfo.properties)
     locale/browser/quitDialog.properties           (%chrome/browser/quitDialog.properties)
 *   locale/browser/safeMode.dtd                    (%chrome/browser/safeMode.dtd)
--- a/browser/themes/gnomestripe/preferences/preferences.css
+++ b/browser/themes/gnomestripe/preferences/preferences.css
@@ -176,13 +176,9 @@ radio[pane=paneSync] {
   list-style-image: url("chrome://mozapps/skin/profile/profileicon.png");
 }
 
 #syncAddDeviceLabel {
   margin-top: 1em;
   margin-bottom: 1em;
 }
 
-#syncEnginesList {
-  height: 10em;
-}
-
 %endif
--- a/browser/themes/pinstripe/preferences/preferences.css
+++ b/browser/themes/pinstripe/preferences/preferences.css
@@ -234,13 +234,9 @@ caption {
   list-style-image: url("chrome://mozapps/skin/profile/profileicon.png");
 }
 
 #syncAddDeviceLabel {
   margin-top: 1em;
   margin-bottom: 1em;
 }
 
-#syncEnginesList {
-  height: 10em;
-}
-
 %endif
--- a/browser/themes/winstripe/preferences/preferences.css
+++ b/browser/themes/winstripe/preferences/preferences.css
@@ -164,15 +164,11 @@ radio[pane=paneSync] {
 
 #accountCaptionImage {
   list-style-image: url("chrome://mozapps/skin/profile/profileicon.png");
 }
 
 #syncAddDeviceLabel {
   margin-top: 1em;
   margin-bottom: 1em;
- }
-
-#syncEnginesList {
-  height: 11em;
 }
 
 %endif
--- a/build/unix/build-toolchain/build-gcc.py
+++ b/build/unix/build-toolchain/build-gcc.py
@@ -94,16 +94,43 @@ def build_linux_headers_aux(inst_dir):
                                "headers_install"])
     shutil.move(linux_source_dir + "/dest", inst_dir)
 
 def build_linux_headers(inst_dir):
     def f():
         build_linux_headers_aux(inst_dir)
     with_env({"PATH" : aux_inst_dir + "/bin:%s" % os.environ["PATH"]}, f)
 
+def build_gcc(stage_dir, is_stage_one):
+    gcc_build_dir = stage_dir + '/gcc'
+    tool_inst_dir = stage_dir + '/inst'
+    lib_inst_dir = stage_dir + '/libinst'
+    gcc_configure_args = ["--prefix=%s" % tool_inst_dir,
+                          "--enable-__cxa_atexit",
+                          "--with-gmp=%s" % lib_inst_dir,
+                          "--with-mpfr=%s" % lib_inst_dir,
+                          "--with-mpc=%s" % lib_inst_dir,
+                          "--enable-languages=c,c++",
+                          "--disable-multilib",
+                          "--disable-bootstrap"]
+    if is_stage_one:
+        # We build the stage1 gcc without shared libraries. Otherwise its
+        # libgcc.so would depend on the system libc.so, which causes problems
+        # when it tries to use that libgcc.so and the libc we are about to
+        # build.
+        gcc_configure_args.append("--disable-shared")
+
+    build_package(gcc_source_dir, gcc_build_dir, gcc_configure_args)
+
+    if is_stage_one:
+        # The glibc build system uses -lgcc_eh, but at least in this setup
+        # libgcc.a has all it needs.
+        d = tool_inst_dir + "/lib/gcc/x86_64-unknown-linux-gnu/4.5.2/"
+        os.symlink(d + "libgcc.a", d + "libgcc_eh.a")
+
 def build_one_stage(env, stage_dir, is_stage_one):
     def f():
         build_one_stage_aux(stage_dir, is_stage_one)
     with_env(env, f)
 
 def build_one_stage_aux(stage_dir, is_stage_one):
     os.mkdir(stage_dir)
 
@@ -124,43 +151,28 @@ def build_one_stage_aux(stage_dir, is_st
 
     tool_inst_dir = stage_dir + '/inst'
     build_linux_headers(tool_inst_dir)
 
     binutils_build_dir = stage_dir + '/binutils'
     build_package(binutils_source_dir, binutils_build_dir,
                   ["--prefix=%s" % tool_inst_dir])
 
-    gcc_build_dir = stage_dir + '/gcc'
-    gcc_configure_args = ["--prefix=%s" % tool_inst_dir,
-                          "--enable-__cxa_atexit",
-                          "--with-gmp=%s" % lib_inst_dir,
-                          "--with-mpfr=%s" % lib_inst_dir,
-                          "--with-mpc=%s" % lib_inst_dir,
-                          "--enable-languages=c,c++",
-                          "--disable-multilib",
-                          "--disable-bootstrap"]
+    # During stage one we have to build gcc first, this glibc doesn't even
+    # build with gcc 4.6. During stage two, we have to build glibc first.
+    # The problem is that libstdc++ is built with xgcc and if glibc has
+    # not been built yet xgcc will use the system one.
     if is_stage_one:
-        # We build the stage1 gcc without shared libraries. Otherwise its
-        # libgcc.so would depend on the system libc.so, which causes problems
-        # when it tries to use that libgcc.so and the libc we are about to
-        # build.
-        gcc_configure_args.append("--disable-shared")
-
-    build_package(gcc_source_dir, gcc_build_dir, gcc_configure_args)
-
-    if is_stage_one:
-        # The glibc build system uses -lgcc_eh, but at least in this setup
-        # libgcc.a has all it needs.
-        d = tool_inst_dir + "/lib/gcc/x86_64-unknown-linux-gnu/4.5.2/"
-        os.symlink(d + "libgcc.a", d + "libgcc_eh.a")
-
-    build_glibc({"CC"  : tool_inst_dir + "/bin/gcc",
-                 "CXX" : tool_inst_dir + "/bin/g++"},
-                stage_dir, tool_inst_dir)
+        build_gcc(stage_dir, is_stage_one)
+        build_glibc({"CC"  : tool_inst_dir + "/bin/gcc",
+                     "CXX" : tool_inst_dir + "/bin/g++"},
+                    stage_dir, tool_inst_dir)
+    else:
+        build_glibc({}, stage_dir, tool_inst_dir)
+        build_gcc(stage_dir, is_stage_one)
 
 def build_tar_package(tar, name, base, directory):
     name = os.path.realpath(name)
     run_in(base, [tar, "-cf", name, "--mtime=2012-01-01", "--owner=root",
                   directory])
 
 ##############################################
 
--- a/config/autoconf.mk.in
+++ b/config/autoconf.mk.in
@@ -138,16 +138,17 @@ ENABLE_TESTS	= @ENABLE_TESTS@
 IBMBIDI = @IBMBIDI@
 MOZ_UNIVERSALCHARDET = @MOZ_UNIVERSALCHARDET@
 ACCESSIBILITY = @ACCESSIBILITY@
 MOZ_BRANDING_DIRECTORY = @MOZ_BRANDING_DIRECTORY@
 XPCOM_USE_LEA = @XPCOM_USE_LEA@
 MOZ_INSTALLER	= @MOZ_INSTALLER@
 MOZ_MAINTENANCE_SERVICE	= @MOZ_MAINTENANCE_SERVICE@
 MOZ_VERIFY_MAR_SIGNATURE	= @MOZ_VERIFY_MAR_SIGNATURE@
+MOZ_ENABLE_SIGNMAR	= @MOZ_ENABLE_SIGNMAR@
 MOZ_UPDATER	= @MOZ_UPDATER@
 MOZ_UPDATE_CHANNEL	= @MOZ_UPDATE_CHANNEL@
 MOZ_UPDATE_PACKAGING	= @MOZ_UPDATE_PACKAGING@
 MOZ_DISABLE_PARENTAL_CONTROLS = @MOZ_DISABLE_PARENTAL_CONTROLS@
 NS_ENABLE_TSF = @NS_ENABLE_TSF@
 MOZ_SPELLCHECK = @MOZ_SPELLCHECK@
 MOZ_ANDROID_HISTORY = @MOZ_ANDROID_HISTORY@
 MOZ_WEBSMS_BACKEND = @MOZ_WEBSMS_BACKEND@
--- a/configure.in
+++ b/configure.in
@@ -313,17 +313,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 -isystem $gonkdir/bionic/libc/include/ -isystem $gonkdir/bionic/libc/kernel/common -isystem $gonkdir/bionic/libc/arch-arm/include -isystem $gonkdir/bionic/libc/kernel/arch-arm -isystem $gonkdir/bionic/libm/include -isystem $gonkdir/frameworks/base/opengl/include -isystem $gonkdir/frameworks/base/native/include -isystem $gonkdir/hardware/libhardware/include -isystem $gonkdir/hardware/libhardware_legacy/include -isystem $gonkdir/system/core/include -isystem $gonkdir/bionic -isystem $gonkdir/frameworks/base/include $STLPORT_CPPFLAGS $CPPFLAGS -isystem $gonkdir/frameworks/base/services/sensorservice"
+    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 -I$gonkdir/frameworks/base/services/sensorservice"
     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
@@ -6495,16 +6495,33 @@ if test -n "$MOZ_VERIFY_MAR_SIGNATURE"; 
   if test "$OS_ARCH" = "WINNT"; then
     AC_DEFINE(MOZ_VERIFY_MAR_SIGNATURE)
   else
     AC_MSG_ERROR([Can only build with --enable-verify-mar with a Windows target])
   fi
 fi
 
 dnl ========================================================
+dnl Enable building the signmar program.
+dnl This option is much different than the --enable-verify-mar option.
+dnl --enable-verify-mar is for enabling the verification check on MAR
+dnl files in the updater.  The --enable-signmar option is for building
+dnl the signmar program.
+dnl ========================================================
+
+MOZ_ARG_ENABLE_BOOL(sign-mar,
+[  --enable-signmar     Enable building the signmar program],
+    MOZ_ENABLE_SIGNMAR=1,
+    MOZ_ENABLE_SIGNMAR= )
+
+if test -n "$MOZ_ENABLE_SIGNMAR"; then
+  AC_DEFINE(MOZ_ENABLE_SIGNMAR)
+fi
+
+dnl ========================================================
 dnl Updater
 dnl ========================================================
 
 MOZ_ARG_DISABLE_BOOL(updater,
 [  --disable-updater       Disable building of updater],
     MOZ_UPDATER=,
     MOZ_UPDATER=1 )
 
@@ -8596,16 +8613,17 @@ AC_SUBST(MOZ_UNIVERSALCHARDET)
 AC_SUBST(ACCESSIBILITY)
 AC_SUBST(MOZ_SPELLCHECK)
 AC_SUBST(MOZ_JAVA_COMPOSITOR)
 AC_SUBST(MOZ_ONLY_TOUCH_EVENTS)
 AC_SUBST(MOZ_USER_DIR)
 AC_SUBST(MOZ_CRASHREPORTER)
 AC_SUBST(MOZ_MAINTENANCE_SERVICE)
 AC_SUBST(MOZ_VERIFY_MAR_SIGNATURE)
+AC_SUBST(MOZ_ENABLE_SIGNMAR)
 AC_SUBST(MOZ_UPDATER)
 AC_SUBST(MOZ_ANGLE)
 AC_SUBST(MOZ_DIRECTX_SDK_PATH)
 AC_SUBST(MOZ_DIRECTX_SDK_CPU_SUFFIX)
 AC_SUBST(MOZ_D3DX9_VERSION)
 AC_SUBST(MOZ_D3DX9_CAB)
 AC_SUBST(MOZ_D3DCOMPILER_CAB)
 AC_SUBST(MOZ_D3DX9_DLL)
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -1139,22 +1139,44 @@ public:
 
   /**
    * Parse a string into a document using the HTML parser.
    * Script elements are marked unexecutable.
    *
    * @param aSourceBuffer the string to parse as an HTML document
    * @param aTargetDocument the document object to parse into. Must not have
    *                        child nodes.
+   * @param aScriptingEnabledForNoscriptParsing whether <noscript> is parsed
+   *                                            as if scripting was enabled
    * @return NS_ERROR_DOM_INVALID_STATE_ERR if a re-entrant attempt to parse
    *         fragments is made, NS_ERROR_OUT_OF_MEMORY if aSourceBuffer is too
    *         long and NS_OK otherwise.
    */
   static nsresult ParseDocumentHTML(const nsAString& aSourceBuffer,
-                                    nsIDocument* aTargetDocument);
+                                    nsIDocument* aTargetDocument,
+                                    bool aScriptingEnabledForNoscriptParsing);
+
+  /**
+   * Converts HTML source to plain text by parsing the source and using the
+   * plain text serializer on the resulting tree.
+   *
+   * @param aSourceBuffer the string to parse as an HTML document
+   * @param aResultBuffer the string where the plain text result appears;
+   *                      may be the same string as aSourceBuffer
+   * @param aFlags Flags from nsIDocumentEncoder.
+   * @param aWrapCol Number of columns after which to line wrap; 0 for no
+   *                 auto-wrapping
+   * @return NS_ERROR_DOM_INVALID_STATE_ERR if a re-entrant attempt to parse
+   *         fragments is made, NS_ERROR_OUT_OF_MEMORY if aSourceBuffer is too
+   *         long and NS_OK otherwise.
+   */
+  static nsresult ConvertToPlainText(const nsAString& aSourceBuffer,
+                                     nsAString& aResultBuffer,
+                                     PRUint32 aFlags,
+                                     PRUint32 aWrapCol);
 
   /**
    * Creates a new XML document, which is marked to be loaded as data.
    *
    * @param aNamespaceURI Namespace for the root element to create and insert in
    *                      the document. Only used if aQualifiedName is not
    *                      empty.
    * @param aQualifiedName Qualified name for the root element to create and
@@ -1936,16 +1958,42 @@ public:
    * comma-separated list of URIs.  Return true if the given URI's prepath is
    * in the list, and false otherwise.
    *
    * Comparisons are case-insensitive, and whitespace between elements of the
    * comma-separated list is ignored.
    */
   static bool URIIsChromeOrInPref(nsIURI *aURI, const char *aPref);
 
+  /**
+   * This will parse aSource, to extract the value of the pseudo attribute
+   * with the name specified in aName. See
+   * http://www.w3.org/TR/xml-stylesheet/#NT-StyleSheetPI for the specification
+   * which is used to parse aSource.
+   *
+   * @param aSource the string to parse
+   * @param aName the name of the attribute to get the value for
+   * @param aValue [out] the value for the attribute with name specified in
+   *                     aAttribute. Empty if the attribute isn't present.
+   * @return true     if the attribute exists and was successfully parsed.
+   *         false if the attribute doesn't exist, or has a malformed
+   *                  value, such as an unknown or unterminated entity.
+   */
+  static bool GetPseudoAttributeValue(const nsString& aSource, nsIAtom *aName,
+                                      nsAString& aValue);
+
+  /**
+   * Returns true if the language name is a version of JavaScript and
+   * false otherwise
+   */
+  static bool IsJavaScriptLanguage(const nsString& aName, PRUint32 *aVerFlags);
+
+  static void SplitMimeType(const nsAString& aValue, nsString& aType,
+                            nsString& aParams);
+
 private:
   static bool InitializeEventTable();
 
   static nsresult EnsureStringBundle(PropertiesFile aFile);
 
   static nsIDOMScriptObjectFactory *GetDOMScriptObjectFactory();
 
   static nsresult HoldScriptObject(PRUint32 aLangID, void* aObject);
--- a/content/base/public/nsIDocumentEncoder.idl
+++ b/content/base/public/nsIDocumentEncoder.idl
@@ -167,17 +167,18 @@ interface nsIDocumentEncoder : nsISuppor
   /**
    * Output the content of noscript elements (only for serializing
    * to plaintext).
    */
   const unsigned long OutputNoScriptContent = (1 << 11);
 
   /**
    * Output the content of noframes elements (only for serializing
-   * to plaintext).
+   * to plaintext). (Used only internally in the plain text serializer;
+   * ignored if passed by the caller.)
    */
   const unsigned long OutputNoFramesContent = (1 << 12);
 
   /**
    * Don't allow any formatting nodes (e.g. <br>, <b>) inside a <pre>.
    * This is used primarily by mail. XHTML/HTML output only.
    */
   const unsigned long OutputNoFormattingInPre = (1 << 13);
--- a/content/base/src/Makefile.in
+++ b/content/base/src/Makefile.in
@@ -122,17 +122,16 @@ CPPSRCS		= \
 		nsMappedAttributes.cpp \
 		nsNameSpaceManager.cpp \
 		nsNoDataProtocolContentPolicy.cpp \
 		nsNodeInfo.cpp \
 		nsNodeInfoManager.cpp \
 		nsNodeIterator.cpp \
 		nsNodeUtils.cpp \
 		nsObjectLoadingContent.cpp \
-		nsParserUtils.cpp \
 		nsPlainTextSerializer.cpp \
 		nsPropertyTable.cpp \
 		nsRange.cpp \
 		nsReferencedElement.cpp \
 		nsScriptElement.cpp \
 		nsScriptLoader.cpp \
 		nsStubDocumentObserver.cpp \
 		nsStubImageDecoderObserver.cpp \
--- a/content/base/src/nsContentSink.cpp
+++ b/content/base/src/nsContentSink.cpp
@@ -75,17 +75,16 @@
 #include "nsIApplicationCacheContainer.h"
 #include "nsIApplicationCacheChannel.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIDOMLoadStatus.h"
 #include "nsICookieService.h"
 #include "nsIPrompt.h"
 #include "nsServiceManagerUtils.h"
 #include "nsContentUtils.h"
-#include "nsParserUtils.h"
 #include "nsCRT.h"
 #include "nsEscape.h"
 #include "nsWeakReference.h"
 #include "nsUnicharUtils.h"
 #include "nsNodeInfoManager.h"
 #include "nsIAppShell.h"
 #include "nsIWidget.h"
 #include "nsWidgetsCID.h"
@@ -707,17 +706,17 @@ nsContentSink::ProcessStyleLink(nsIConte
 {
   if (aAlternate && aTitle.IsEmpty()) {
     // alternates must have title return without error, for now
     return NS_OK;
   }
 
   nsAutoString  mimeType;
   nsAutoString  params;
-  nsParserUtils::SplitMimeType(aType, mimeType, params);
+  nsContentUtils::SplitMimeType(aType, mimeType, params);
 
   // see bug 18817
   if (!mimeType.IsEmpty() && !mimeType.LowerCaseEqualsLiteral("text/css")) {
     // Unknown stylesheet language
     return NS_OK;
   }
 
   nsCOMPtr<nsIURI> url;
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -175,16 +175,17 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_
 #include "BasicLayers.h"
 #include "nsFocusManager.h"
 #include "nsTextEditorState.h"
 #include "nsIPluginHost.h"
 #include "nsICategoryManager.h"
 #include "nsIViewManager.h"
 #include "nsEventStateManager.h"
 #include "nsIDOMHTMLInputElement.h"
+#include "nsParserConstants.h"
 
 #ifdef IBMBIDI
 #include "nsIBidiKeyboard.h"
 #endif
 #include "nsCycleCollectionParticipant.h"
 
 // for ReportToConsole
 #include "nsIStringBundle.h"
@@ -715,16 +716,195 @@ nsContentUtils::URIIsChromeOrInPref(nsIU
     if (whitelistItem.Equals(prePath, nsCaseInsensitiveStringComparator())) {
       return true;
     }
   }
 
   return false;
 }
 
+#define SKIP_WHITESPACE(iter, end_iter, end_res)                 \
+  while ((iter) != (end_iter) && nsCRT::IsAsciiSpace(*(iter))) { \
+    ++(iter);                                                    \
+  }                                                              \
+  if ((iter) == (end_iter)) {                                    \
+    return (end_res);                                            \
+  }
+
+#define SKIP_ATTR_NAME(iter, end_iter)                            \
+  while ((iter) != (end_iter) && !nsCRT::IsAsciiSpace(*(iter)) && \
+         *(iter) != '=') {                                        \
+    ++(iter);                                                     \
+  }
+
+bool
+nsContentUtils::GetPseudoAttributeValue(const nsString& aSource, nsIAtom *aName,
+                                        nsAString& aValue)
+{
+  aValue.Truncate();
+
+  const PRUnichar *start = aSource.get();
+  const PRUnichar *end = start + aSource.Length();
+  const PRUnichar *iter;
+
+  while (start != end) {
+    SKIP_WHITESPACE(start, end, false)
+    iter = start;
+    SKIP_ATTR_NAME(iter, end)
+
+    if (start == iter) {
+      return false;
+    }
+
+    // Remember the attr name.
+    const nsDependentSubstring & attrName = Substring(start, iter);
+
+    // Now check whether this is a valid name="value" pair.
+    start = iter;
+    SKIP_WHITESPACE(start, end, false)
+    if (*start != '=') {
+      // No '=', so this is not a name="value" pair.  We don't know
+      // what it is, and we have no way to handle it.
+      return false;
+    }
+
+    // Have to skip the value.
+    ++start;
+    SKIP_WHITESPACE(start, end, false)
+    PRUnichar q = *start;
+    if (q != kQuote && q != kApostrophe) {
+      // Not a valid quoted value, so bail.
+      return false;
+    }
+
+    ++start;  // Point to the first char of the value.
+    iter = start;
+
+    while (iter != end && *iter != q) {
+      ++iter;
+    }
+
+    if (iter == end) {
+      // Oops, unterminated quoted string.
+      return false;
+    }
+
+    // At this point attrName holds the name of the "attribute" and
+    // the value is between start and iter.
+
+    if (aName->Equals(attrName)) {
+      nsIParserService* parserService = nsContentUtils::GetParserService();
+      NS_ENSURE_TRUE(parserService, false);
+
+      // We'll accumulate as many characters as possible (until we hit either
+      // the end of the string or the beginning of an entity). Chunks will be
+      // delimited by start and chunkEnd.
+      const PRUnichar *chunkEnd = start;
+      while (chunkEnd != iter) {
+        if (*chunkEnd == kLessThan) {
+          aValue.Truncate();
+
+          return false;
+        }
+
+        if (*chunkEnd == kAmpersand) {
+          aValue.Append(start, chunkEnd - start);
+
+          // Point to first character after the ampersand.
+          ++chunkEnd;
+
+          const PRUnichar *afterEntity;
+          PRUnichar result[2];
+          PRUint32 count =
+            parserService->DecodeEntity(chunkEnd, iter, &afterEntity, result);
+          if (count == 0) {
+            aValue.Truncate();
+
+            return false;
+          }
+
+          aValue.Append(result, count);
+
+          // Advance to after the entity and begin a new chunk.
+          start = chunkEnd = afterEntity;
+        }
+        else {
+          ++chunkEnd;
+        }
+      }
+
+      // Append remainder.
+      aValue.Append(start, iter - start);
+
+      return true;
+    }
+
+    // Resume scanning after the end of the attribute value (past the quote
+    // char).
+    start = iter + 1;
+  }
+
+  return false;
+}
+
+bool
+nsContentUtils::IsJavaScriptLanguage(const nsString& aName, PRUint32 *aFlags)
+{
+  JSVersion version = JSVERSION_UNKNOWN;
+
+  if (aName.LowerCaseEqualsLiteral("javascript") ||
+      aName.LowerCaseEqualsLiteral("livescript") ||
+      aName.LowerCaseEqualsLiteral("mocha")) {
+    version = JSVERSION_DEFAULT;
+  } else if (aName.LowerCaseEqualsLiteral("javascript1.0")) {
+    version = JSVERSION_1_0;
+  } else if (aName.LowerCaseEqualsLiteral("javascript1.1")) {
+    version = JSVERSION_1_1;
+  } else if (aName.LowerCaseEqualsLiteral("javascript1.2")) {
+    version = JSVERSION_1_2;
+  } else if (aName.LowerCaseEqualsLiteral("javascript1.3")) {
+    version = JSVERSION_1_3;
+  } else if (aName.LowerCaseEqualsLiteral("javascript1.4")) {
+    version = JSVERSION_1_4;
+  } else if (aName.LowerCaseEqualsLiteral("javascript1.5")) {
+    version = JSVERSION_1_5;
+  } else if (aName.LowerCaseEqualsLiteral("javascript1.6")) {
+    version = JSVERSION_1_6;
+  } else if (aName.LowerCaseEqualsLiteral("javascript1.7")) {
+    version = JSVERSION_1_7;
+  } else if (aName.LowerCaseEqualsLiteral("javascript1.8")) {
+    version = JSVERSION_1_8;
+  }
+
+  if (version == JSVERSION_UNKNOWN) {
+    return false;
+  }
+  *aFlags = version;
+  return true;
+}
+
+void
+nsContentUtils::SplitMimeType(const nsAString& aValue, nsString& aType,
+                              nsString& aParams)
+{
+  aType.Truncate();
+  aParams.Truncate();
+  PRInt32 semiIndex = aValue.FindChar(PRUnichar(';'));
+  if (-1 != semiIndex) {
+    aType = Substring(aValue, 0, semiIndex);
+    aParams = Substring(aValue, semiIndex + 1,
+                       aValue.Length() - (semiIndex + 1));
+    aParams.StripWhitespace();
+  }
+  else {
+    aType = aValue;
+  }
+  aType.StripWhitespace();
+}
+
 /**
  * Access a cached parser service. Don't addref. We need only one
  * reference to it and this class has that one.
  */
 /* static */
 nsIParserService*
 nsContentUtils::GetParserService()
 {
@@ -3742,31 +3922,33 @@ nsContentUtils::ParseFragmentHTML(const 
                                        aQuirks,
                                        aPreventScriptExecution);
   return rv;
 }
 
 /* static */
 nsresult
 nsContentUtils::ParseDocumentHTML(const nsAString& aSourceBuffer,
-                                  nsIDocument* aTargetDocument)
+                                  nsIDocument* aTargetDocument,
+                                  bool aScriptingEnabledForNoscriptParsing)
 {
   if (nsContentUtils::sFragmentParsingActive) {
     NS_NOTREACHED("Re-entrant fragment parsing attempted.");
     return NS_ERROR_DOM_INVALID_STATE_ERR;
   }
   mozilla::AutoRestore<bool> guard(nsContentUtils::sFragmentParsingActive);
   nsContentUtils::sFragmentParsingActive = true;
   if (!sHTMLFragmentParser) {
     NS_ADDREF(sHTMLFragmentParser = new nsHtml5StringParser());
     // Now sHTMLFragmentParser owns the object
   }
   nsresult rv =
     sHTMLFragmentParser->ParseDocument(aSourceBuffer,
-                                       aTargetDocument);
+                                       aTargetDocument,
+                                       aScriptingEnabledForNoscriptParsing);
   return rv;
 }
 
 /* static */
 nsresult
 nsContentUtils::ParseFragmentXML(const nsAString& aSourceBuffer,
                                  nsIDocument* aDocument,
                                  nsTArray<nsString>& aTagStack,
@@ -3807,16 +3989,54 @@ nsContentUtils::ParseFragmentXML(const n
 
   rv = sXMLFragmentSink->FinishFragmentParsing(aReturn);
 
   sXMLFragmentParser->Reset();
 
   return rv;
 }
 
+/* static */
+nsresult
+nsContentUtils::ConvertToPlainText(const nsAString& aSourceBuffer,
+                                   nsAString& aResultBuffer,
+                                   PRUint32 aFlags,
+                                   PRUint32 aWrapCol)
+{
+  nsCOMPtr<nsIURI> uri;
+  NS_NewURI(getter_AddRefs(uri), "about:blank");
+  nsCOMPtr<nsIPrincipal> principal =
+    do_CreateInstance("@mozilla.org/nullprincipal;1");
+  nsCOMPtr<nsIDOMDocument> domDocument;
+  nsresult rv = nsContentUtils::CreateDocument(EmptyString(),
+                                               EmptyString(),
+                                               nsnull,
+                                               uri,
+                                               uri,
+                                               principal,
+                                               nsnull,
+                                               DocumentFlavorHTML,
+                                               getter_AddRefs(domDocument));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCOMPtr<nsIDocument> document = do_QueryInterface(domDocument);
+  rv = nsContentUtils::ParseDocumentHTML(aSourceBuffer, document,
+    !(aFlags & nsIDocumentEncoder::OutputNoScriptContent));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCOMPtr<nsIDocumentEncoder> encoder = do_CreateInstance(
+    "@mozilla.org/layout/documentEncoder;1?type=text/plain");
+
+  rv = encoder->Init(domDocument, NS_LITERAL_STRING("text/plain"), aFlags);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  encoder->SetWrapColumn(aWrapCol);
+
+  return encoder->EncodeToString(aResultBuffer);
+}
 
 /* static */
 nsresult
 nsContentUtils::CreateDocument(const nsAString& aNamespaceURI, 
                                const nsAString& aQualifiedName, 
                                nsIDOMDocumentType* aDoctype,
                                nsIURI* aDocumentURI, nsIURI* aBaseURI,
                                nsIPrincipal* aPrincipal,
--- a/content/base/src/nsCrossSiteListenerProxy.cpp
+++ b/content/base/src/nsCrossSiteListenerProxy.cpp
@@ -43,17 +43,16 @@
 #include "nsIScriptSecurityManager.h"
 #include "nsNetUtil.h"
 #include "nsIParser.h"
 #include "nsParserCIID.h"
 #include "nsICharsetAlias.h"
 #include "nsMimeTypes.h"
 #include "nsIStreamConverterService.h"
 #include "nsStringStream.h"
-#include "nsParserUtils.h"
 #include "nsGkAtoms.h"
 #include "nsWhitespaceTokenizer.h"
 #include "nsIChannelEventSink.h"
 #include "nsIAsyncVerifyRedirectCallback.h"
 #include "nsCharSeparatedTokenizer.h"
 #include "nsAsyncRedirectVerifyHelper.h"
 #include "prclist.h"
 #include "prtime.h"
--- a/content/base/src/nsDOMParser.cpp
+++ b/content/base/src/nsDOMParser.cpp
@@ -97,17 +97,17 @@ nsDOMParser::ParseFromString(const PRUni
   nsresult rv;
 
   if (!nsCRT::strcmp(contentType, "text/html")) {
     nsCOMPtr<nsIDOMDocument> domDocument;
     rv = SetUpDocument(DocumentFlavorHTML, getter_AddRefs(domDocument));
     NS_ENSURE_SUCCESS(rv, rv);
     nsCOMPtr<nsIDocument> document = do_QueryInterface(domDocument);
     nsDependentString sourceBuffer(str);
-    rv = nsContentUtils::ParseDocumentHTML(sourceBuffer, document);
+    rv = nsContentUtils::ParseDocumentHTML(sourceBuffer, document, false);
     NS_ENSURE_SUCCESS(rv, rv);
 
     // Keep the XULXBL state, base URL and principal setting in sync with the
     // XML case
 
     if (nsContentUtils::IsSystemPrincipal(mOriginalPrincipal)) {
       document->ForceEnableXULXBL();
     }
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -2896,16 +2896,24 @@ nsGenericElement::GetAttributeNodeNS(con
                                      const nsAString& aLocalName,
                                      nsIDOMAttr** aReturn)
 {
   NS_ENSURE_ARG_POINTER(aReturn);
   *aReturn = nsnull;
 
   OwnerDoc()->WarnOnceAbout(nsIDocument::eGetAttributeNodeNS);
 
+  return GetAttributeNodeNSInternal(aNamespaceURI, aLocalName, aReturn);
+}
+
+nsresult
+nsGenericElement::GetAttributeNodeNSInternal(const nsAString& aNamespaceURI,
+                                             const nsAString& aLocalName,
+                                             nsIDOMAttr** aReturn)
+{
   nsCOMPtr<nsIDOMNamedNodeMap> map;
   nsresult rv = GetAttributes(getter_AddRefs(map));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIDOMNode> node;
   rv = map->GetNamedItemNS(aNamespaceURI, aLocalName, getter_AddRefs(node));
 
   if (NS_SUCCEEDED(rv) && node) {
@@ -5203,18 +5211,18 @@ nsGenericElement::SetAttrAndNotify(PRInt
   }
 
   if (aFireMutation) {
     nsMutationEvent mutation(true, NS_MUTATION_ATTRMODIFIED);
 
     nsCOMPtr<nsIDOMAttr> attrNode;
     nsAutoString ns;
     nsContentUtils::NameSpaceManager()->GetNameSpaceURI(aNamespaceID, ns);
-    GetAttributeNodeNS(ns, nsDependentAtomString(aName),
-                       getter_AddRefs(attrNode));
+    GetAttributeNodeNSInternal(ns, nsDependentAtomString(aName),
+                               getter_AddRefs(attrNode));
     mutation.mRelatedNode = attrNode;
 
     mutation.mAttrName = aName;
     nsAutoString newValue;
     GetAttr(aNamespaceID, aName, newValue);
     if (!newValue.IsEmpty()) {
       mutation.mNewAttrValue = do_GetAtom(newValue);
     }
@@ -5383,18 +5391,18 @@ nsGenericElement::UnsetAttr(PRInt32 aNam
                                          NS_EVENT_BITS_MUTATION_ATTRMODIFIED,
                                          this);
 
   // Grab the attr node if needed before we remove it from the attr map
   nsCOMPtr<nsIDOMAttr> attrNode;
   if (hasMutationListeners) {
     nsAutoString ns;
     nsContentUtils::NameSpaceManager()->GetNameSpaceURI(aNameSpaceID, ns);
-    GetAttributeNodeNS(ns, nsDependentAtomString(aName),
-                       getter_AddRefs(attrNode));
+    GetAttributeNodeNSInternal(ns, nsDependentAtomString(aName),
+                               getter_AddRefs(attrNode));
   }
 
   // Clear binding to nsIDOMNamedNodeMap
   nsDOMSlots *slots = GetExistingDOMSlots();
   if (slots && slots->mAttributeMap) {
     slots->mAttributeMap->DropAttribute(aNameSpaceID, aName);
   }
 
--- a/content/base/src/nsGenericElement.h
+++ b/content/base/src/nsGenericElement.h
@@ -789,16 +789,20 @@ protected:
 
   nsIFrame* GetStyledFrame();
 
   virtual mozilla::dom::Element* GetNameSpaceElement()
   {
     return this;
   }
 
+  nsresult GetAttributeNodeNSInternal(const nsAString& aNamespaceURI,
+                                      const nsAString& aLocalName,
+                                      nsIDOMAttr** aReturn);
+
 public:
   // Because of a bug in MS C++ compiler nsDOMSlots must be declared public,
   // otherwise nsXULElement::nsXULSlots doesn't compile.
   /**
    * There are a set of DOM- and scripting-specific instance variables
    * that may only be instantiated when a content object is accessed
    * through the DOM. Rather than burn actual slots in the content
    * objects for each of these instance variables, we put them off
--- a/content/base/src/nsObjectLoadingContent.cpp
+++ b/content/base/src/nsObjectLoadingContent.cpp
@@ -551,17 +551,17 @@ nsObjectLoadingContent::nsObjectLoadingC
   , mChannel(nsnull)
   , mType(eType_Loading)
   , mInstantiating(false)
   , mUserDisabled(false)
   , mSuppressed(false)
   , mNetworkCreated(true)
   // If plugins.click_to_play is false, plugins should always play
   , mShouldPlay(!mozilla::Preferences::GetBool("plugins.click_to_play", false))
-  , mSrcStreamLoadInitiated(false)
+  , mSrcStreamLoading(false)
   , mFallbackReason(ePluginOtherState)
 {
 }
 
 nsObjectLoadingContent::~nsObjectLoadingContent()
 {
   DestroyImageLoadingContent();
   if (mFrameLoader) {
@@ -687,18 +687,16 @@ nsObjectLoadingContent::NotifyOwnerDocum
 
 // nsIRequestObserver
 NS_IMETHODIMP
 nsObjectLoadingContent::OnStartRequest(nsIRequest *aRequest,
                                        nsISupports *aContext)
 {
   SAMPLE_LABEL("nsObjectLoadingContent", "OnStartRequest");
 
-  mSrcStreamLoadInitiated = true;
-
   if (aRequest != mChannel || !aRequest) {
     // This is a bit of an edge case - happens when a new load starts before the
     // previous one got here
     return NS_BINDING_ABORTED;
   }
 
   AutoNotifier notifier(this, true);
 
@@ -878,17 +876,17 @@ nsObjectLoadingContent::OnStartRequest(n
         mType = newType;
         notifier.Notify();
       }
       nsCOMPtr<nsIPluginHost> pluginHostCOM(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
       nsPluginHost *pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
       if (!pluginHost) {
         return NS_ERROR_NOT_AVAILABLE;
       }
-      pluginHost->InstantiatePluginForChannel(chan, this, getter_AddRefs(mFinalListener));
+      pluginHost->CreateListenerForChannel(chan, this, getter_AddRefs(mFinalListener));
       break;
     }
     case eType_Loading:
       NS_NOTREACHED("Should not have a loading type here!");
     case eType_Null:
       // Need to fallback here (instead of using the case below), so that we can
       // set mFallbackReason without it being overwritten. This is also why we
       // return early.
@@ -901,30 +899,35 @@ nsObjectLoadingContent::OnStartRequest(n
         mFallbackReason = pluginState;
         FirePluginError(thisContent, pluginState);
       }
       return NS_BINDING_ABORTED;
   }
 
   if (mFinalListener) {
     mType = newType;
+
+    mSrcStreamLoading = true;
     rv = mFinalListener->OnStartRequest(aRequest, aContext);
-    if (NS_FAILED(rv)) {
-#ifdef XP_MACOSX
-      // Shockwave on Mac is special and returns an error here even when it
-      // handles the content
-      if (mContentType.EqualsLiteral("application/x-director")) {
-        rv = NS_OK; // otherwise, the AutoFallback will make us fall back
+    mSrcStreamLoading = false;
+
+    if (NS_SUCCEEDED(rv)) {
+      // Plugins need to set up for NPRuntime.
+      if (mType == eType_Plugin) {
+        NotifyContentObjectWrapper();
+      }
+    } else {
+      // Plugins don't fall back if there is an error here.
+      if (mType == eType_Plugin) {
+        rv = NS_OK; // this is necessary to avoid auto-fallback
         return NS_BINDING_ABORTED;
       }
-#endif
       Fallback(false);
-    } else if (mType == eType_Plugin) {
-      NotifyContentObjectWrapper();
     }
+
     return rv;
   }
 
   Fallback(false);
   return NS_BINDING_ABORTED;
 }
 
 NS_IMETHODIMP
@@ -2106,12 +2109,11 @@ nsObjectLoadingContent::NotifyContentObj
 }
 
 NS_IMETHODIMP
 nsObjectLoadingContent::PlayPlugin()
 {
   if (!nsContentUtils::IsCallerChrome())
     return NS_OK;
 
-  mSrcStreamLoadInitiated = false;
   mShouldPlay = true;
   return LoadObject(mURI, true, mContentType, true);
 }
--- a/content/base/src/nsObjectLoadingContent.h
+++ b/content/base/src/nsObjectLoadingContent.h
@@ -146,17 +146,17 @@ class nsObjectLoadingContent : public ns
       mNetworkCreated = aNetworkCreated;
     }
 
     // Can flush layout.
     nsresult InstantiatePluginInstance(const char* aMimeType, nsIURI* aURI);
 
     void NotifyOwnerDocumentActivityChanged();
 
-    bool SrcStreamLoadInitiated() { return mSrcStreamLoadInitiated; };
+    bool SrcStreamLoading() { return mSrcStreamLoading; };
 
   protected:
     /**
      * Load the object from the given URI.
      * @param aURI       The URI to load.
      * @param aNotify If true, nsIDocumentObserver state change notifications
      *                will be sent as needed.
      * @param aTypeHint  MIME Type hint. Overridden by the server unless this
@@ -396,19 +396,22 @@ class nsObjectLoadingContent : public ns
     // created using NS_FROM_PARSER_NETWORK flag. If the element is modified,
     // it may lose the flag.
     bool                        mNetworkCreated : 1;
 
     // Used to keep track of whether or not a plugin should be played.
     // This is used for click-to-play plugins.
     bool                        mShouldPlay : 1;
 
-    // Used to indicate that a stream for a src/data attribute has been
-    // initiated so that we don't do it twice.
-    bool mSrcStreamLoadInitiated;
+    // Used to track when we might try to instantiate a plugin instance based on
+    // a src data stream being delivered to this object. When this is true we don't
+    // want plugin instance instantiation code to attempt to load src data again or
+    // we'll deliver duplicate streams. Should be cleared when we are not loading
+    // src data.
+    bool mSrcStreamLoading;
 
     // A specific state that caused us to fallback
     PluginSupportState          mFallbackReason;
 
     nsWeakFrame                 mPrintFrame;
 
     nsRefPtr<nsPluginInstanceOwner> mInstanceOwner;
 };
deleted file mode 100644
--- a/content/base/src/nsParserUtils.cpp
+++ /dev/null
@@ -1,236 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** 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 Communicator client code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * 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
- * 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 ***** */
-
-/*
- * Namespace class for some static parsing-related methods.
- */
-
-#include "nsParserUtils.h"
-#include "jsapi.h"
-#include "nsReadableUtils.h"
-#include "nsCRT.h"
-#include "nsContentUtils.h"
-#include "nsIParserService.h"
-#include "nsParserConstants.h"
-
-#define SKIP_WHITESPACE(iter, end_iter, end_res)                 \
-  while ((iter) != (end_iter) && nsCRT::IsAsciiSpace(*(iter))) { \
-    ++(iter);                                                    \
-  }                                                              \
-  if ((iter) == (end_iter)) {                                    \
-    return (end_res);                                            \
-  }
-
-#define SKIP_ATTR_NAME(iter, end_iter)                            \
-  while ((iter) != (end_iter) && !nsCRT::IsAsciiSpace(*(iter)) && \
-         *(iter) != '=') {                                        \
-    ++(iter);                                                     \
-  }
-
-bool
-nsParserUtils::GetQuotedAttributeValue(const nsString& aSource, nsIAtom *aName,
-                                       nsAString& aValue)
-{
-  aValue.Truncate();
-
-  const PRUnichar *start = aSource.get();
-  const PRUnichar *end = start + aSource.Length();
-  const PRUnichar *iter;
-  
-  while (start != end) {
-    SKIP_WHITESPACE(start, end, false)
-    iter = start;
-    SKIP_ATTR_NAME(iter, end)
-
-    if (start == iter) {
-      return false;
-    }
-
-    // Remember the attr name.
-    const nsDependentSubstring & attrName = Substring(start, iter);
-
-    // Now check whether this is a valid name="value" pair.
-    start = iter;
-    SKIP_WHITESPACE(start, end, false)
-    if (*start != '=') {
-      // No '=', so this is not a name="value" pair.  We don't know
-      // what it is, and we have no way to handle it.
-      return false;
-    }
-    
-    // Have to skip the value.
-    ++start;
-    SKIP_WHITESPACE(start, end, false)
-    PRUnichar q = *start;
-    if (q != kQuote && q != kApostrophe) {
-      // Not a valid quoted value, so bail.
-      return false;
-    }
-    
-    ++start;  // Point to the first char of the value.
-    iter = start;
-
-    while (iter != end && *iter != q) {
-      ++iter;
-    }
-
-    if (iter == end) {
-      // Oops, unterminated quoted string.
-      return false;
-    }
-
-    // At this point attrName holds the name of the "attribute" and
-    // the value is between start and iter.
-    
-    if (aName->Equals(attrName)) {
-      nsIParserService* parserService = nsContentUtils::GetParserService();
-      NS_ENSURE_TRUE(parserService, false);
-
-      // We'll accumulate as many characters as possible (until we hit either
-      // the end of the string or the beginning of an entity). Chunks will be
-      // delimited by start and chunkEnd.
-      const PRUnichar *chunkEnd = start;
-      while (chunkEnd != iter) {
-        if (*chunkEnd == kLessThan) {
-          aValue.Truncate();
-
-          return false;
-        }
-
-        if (*chunkEnd == kAmpersand) {
-          aValue.Append(start, chunkEnd - start);
-
-          // Point to first character after the ampersand.
-          ++chunkEnd;
-
-          const PRUnichar *afterEntity;
-          PRUnichar result[2];
-          PRUint32 count =
-            parserService->DecodeEntity(chunkEnd, iter, &afterEntity, result);
-          if (count == 0) {
-            aValue.Truncate();
-
-            return false;
-          }
-
-          aValue.Append(result, count);
-
-          // Advance to after the entity and begin a new chunk.
-          start = chunkEnd = afterEntity;
-        }
-        else {
-          ++chunkEnd;
-        }
-      }
-
-      // Append remainder.
-      aValue.Append(start, iter - start);
-
-      return true;
-    }
-
-    // Resume scanning after the end of the attribute value (past the quote
-    // char).
-    start = iter + 1;
-  }
-
-  return false;
-}
-
-// Returns true if the language name is a version of JavaScript and
-// false otherwise
-bool
-nsParserUtils::IsJavaScriptLanguage(const nsString& aName, PRUint32 *aFlags)
-{
-  JSVersion version = JSVERSION_UNKNOWN;
-
-  if (aName.LowerCaseEqualsLiteral("javascript") ||
-      aName.LowerCaseEqualsLiteral("livescript") ||
-      aName.LowerCaseEqualsLiteral("mocha")) {
-    version = JSVERSION_DEFAULT;
-  }
-  else if (aName.LowerCaseEqualsLiteral("javascript1.0")) {
-    version = JSVERSION_1_0;
-  }
-  else if (aName.LowerCaseEqualsLiteral("javascript1.1")) {
-    version = JSVERSION_1_1;
-  }
-  else if (aName.LowerCaseEqualsLiteral("javascript1.2")) {
-    version = JSVERSION_1_2;
-  }
-  else if (aName.LowerCaseEqualsLiteral("javascript1.3")) {
-    version = JSVERSION_1_3;
-  }
-  else if (aName.LowerCaseEqualsLiteral("javascript1.4")) {
-    version = JSVERSION_1_4;
-  }
-  else if (aName.LowerCaseEqualsLiteral("javascript1.5")) {
-    version = JSVERSION_1_5;
-  }
-  else if (aName.LowerCaseEqualsLiteral("javascript1.6")) {
-    version = JSVERSION_1_6;
-  }
-  else if (aName.LowerCaseEqualsLiteral("javascript1.7")) {
-    version = JSVERSION_1_7;
-  }
-  else if (aName.LowerCaseEqualsLiteral("javascript1.8")) {
-    version = JSVERSION_1_8;
-  }
-  if (version == JSVERSION_UNKNOWN)
-    return false;
-  *aFlags = version;
-  return true;
-}
-
-void
-nsParserUtils::SplitMimeType(const nsAString& aValue, nsString& aType,
-                             nsString& aParams)
-{
-  aType.Truncate();
-  aParams.Truncate();
-  PRInt32 semiIndex = aValue.FindChar(PRUnichar(';'));
-  if (-1 != semiIndex) {
-    aType = Substring(aValue, 0, semiIndex);
-    aParams = Substring(aValue, semiIndex + 1,
-                       aValue.Length() - (semiIndex + 1));
-    aParams.StripWhitespace();
-  }
-  else {
-    aType = aValue;
-  }
-  aType.StripWhitespace();
-}
deleted file mode 100644
--- a/content/base/src/nsParserUtils.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** 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 Communicator client code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * 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
- * 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 ***** */
-
-/*
- * Namespace class for some static parsing-related methods.
- */
-
-#ifndef nsParserUtils_h__
-#define nsParserUtils_h__
-
-#include "nsString.h"
-class nsIAtom;
-
-class nsParserUtils {
-public:
-  /**
-   * This will parse aSource, to extract the value of the pseudo attribute
-   * with the name specified in aName. See
-   * http://www.w3.org/TR/xml-stylesheet/#NT-StyleSheetPI for the specification
-   * which is used to parse aSource.
-   *
-   * @param aSource the string to parse
-   * @param aName the name of the attribute to get the value for
-   * @param aValue [out] the value for the attribute with name specified in
-   *                     aAttribute. Empty if the attribute isn't present.
-   * @return true     if the attribute exists and was successfully parsed.
-   *         false if the attribute doesn't exist, or has a malformed
-   *                  value, such as an unknown or unterminated entity.
-   */
-  static bool
-  GetQuotedAttributeValue(const nsString& aSource, nsIAtom *aName,
-                          nsAString& aValue);
-
-  static bool
-  IsJavaScriptLanguage(const nsString& aName, PRUint32 *aVerFlags);
-
-  static void
-  SplitMimeType(const nsAString& aValue, nsString& aType,
-                nsString& aParams);
-};
-
-#endif // nsParserUtils_h__
-
-
-
--- a/content/base/src/nsScriptLoader.cpp
+++ b/content/base/src/nsScriptLoader.cpp
@@ -39,17 +39,16 @@
 
 /*
  * A class that handles loading and evaluation of <script> elements.
  */
 
 #include "jsapi.h"
 #include "jsfriendapi.h"
 #include "nsScriptLoader.h"
-#include "nsParserUtils.h"
 #include "nsICharsetConverterManager.h"
 #include "nsIUnicodeDecoder.h"
 #include "nsIContent.h"
 #include "mozilla/dom/Element.h"
 #include "nsGkAtoms.h"
 #include "nsNetUtil.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIScriptContext.h"
@@ -504,24 +503,24 @@ nsScriptLoader::ProcessScriptElement(nsI
     }
   } else {
     // no 'type=' element
     // "language" is a deprecated attribute of HTML, so we check it only for
     // HTML script elements.
     if (scriptContent->IsHTML()) {
       scriptContent->GetAttr(kNameSpaceID_None, nsGkAtoms::language, language);
       if (!language.IsEmpty()) {
-        if (nsParserUtils::IsJavaScriptLanguage(language, &version))
+        if (nsContentUtils::IsJavaScriptLanguage(language, &version))
           typeID = nsIProgrammingLanguage::JAVASCRIPT;
         else
           typeID = nsIProgrammingLanguage::UNKNOWN;
         // IE, Opera, etc. do not respect language version, so neither should
         // we at this late date in the browser wars saga.  Note that this change
         // affects HTML but not XUL or SVG (but note also that XUL has its own
-        // code to check nsParserUtils::IsJavaScriptLanguage -- that's probably
+        // code to check nsContentUtils::IsJavaScriptLanguage -- that's probably
         // a separate bug, one we may not be able to fix short of XUL2).  See
         // bug 255895 (https://bugzilla.mozilla.org/show_bug.cgi?id=255895).
         NS_ASSERTION(JSVERSION_DEFAULT == 0,
                      "We rely on all languages having 0 as a version default");
         version = 0;
       }
     }
   }
--- a/content/base/test/TestPlainTextSerializer.cpp
+++ b/content/base/test/TestPlainTextSerializer.cpp
@@ -32,47 +32,28 @@
  * 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 "TestHarness.h"
 
-#include "nsIParser.h"
-#include "nsIHTMLToTextSink.h"
-#include "nsIParser.h"
-#include "nsIContentSink.h"
-#include "nsIParserService.h"
 #include "nsServiceManagerUtils.h"
 #include "nsStringGlue.h"
-#include "nsParserCIID.h"
 #include "nsIDocumentEncoder.h"
 #include "nsCRT.h"
-
-static NS_DEFINE_CID(kCParserCID, NS_PARSER_CID);
+#include "nsIParserUtils.h"
 
 void
 ConvertBufToPlainText(nsString &aConBuf, int aFlag)
 {
-  nsCOMPtr<nsIParser> parser = do_CreateInstance(kCParserCID);
-  if (parser) {
-    nsCOMPtr<nsIContentSink> sink;
-    sink = do_CreateInstance(NS_PLAINTEXTSINK_CONTRACTID);
-    if (sink) {
-      nsCOMPtr<nsIHTMLToTextSink> textSink(do_QueryInterface(sink));
-      if (textSink) {
-        nsAutoString convertedText;
-        textSink->Initialize(&convertedText, aFlag, 72);
-        parser->SetContentSink(sink);
-        parser->Parse(aConBuf, 0, NS_LITERAL_CSTRING("text/html"), true);
-        aConBuf = convertedText;
-      }
-    }
-  }
+  nsCOMPtr<nsIParserUtils> utils =
+    do_GetService(NS_PARSERUTILS_CONTRACTID);
+  utils->ConvertToPlainText(aConBuf, aFlag, 72, aConBuf);
 }
 
 // Test for ASCII with format=flowed; delsp=yes
 nsresult
 TestASCIIWithFlowedDelSp()
 {
   nsString test;
   nsString result;
--- a/content/base/test/chrome/Makefile.in
+++ b/content/base/test/chrome/Makefile.in
@@ -66,15 +66,16 @@ include $(topsrcdir)/config/rules.mk
     test_fileconstructor.xul \
     fileconstructor_file.png \
     test_bug339494.xul \
     test_bug357450.xul \
     test_bug571390.xul \
     test_bug574596.html \
     test_bug683852.xul \
     test_bug599295.html \
+    test_bug650784.html \
     $(NULL)
 
 libs:: $(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
 
 libs:: $(_CHROME_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/chrome/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/content/base/test/chrome/test_bug650784.html
@@ -0,0 +1,43 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=650776
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 650776</title>
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=650776">Mozilla Bug 650776</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 650776 **/
+
+var c = Components.interfaces.nsIDocumentEncoder;
+var s = Components.classes["@mozilla.org/parserutils;1"]
+        .getService(Components.interfaces.nsIParserUtils);
+
+is(s.convertToPlainText("foo", c.OutputLFLineBreak, 0), "foo", "Wrong conversion result 1");
+is(s.convertToPlainText("foo foo foo", c.OutputWrap | c.OutputLFLineBreak, 7), "foo foo\nfoo", "Wrong conversion result 2");
+is(s.convertToPlainText("<body><noscript>b<span>a</span>r</noscript>foo", c.OutputLFLineBreak, 0), "foo", "Wrong conversion result 3");
+is(s.convertToPlainText("<body><noscript>b<span>a</span>r</noscript>foo", c.OutputNoScriptContent, 0), "barfoo", "Wrong conversion result 4");
+is(s.convertToPlainText("foo\u00A0bar", c.OutputPersistNBSP | c.OutputLFLineBreak, 0), "foo\u00A0bar", "Wrong conversion result 5");
+is(s.convertToPlainText("foo\u00A0bar", c.OutputLFLineBreak, 0), "foo bar", "Wrong conversion result 6");
+is(s.convertToPlainText("<body><noframes>bar</noframes>foo", c.OutputLFLineBreak, 0), "foo", "Wrong conversion result 7");
+// OutputNoFramesContent doesn't actually work, because the flag gets overridden by 
+// the browser.frames.enabled pref in all cases.
+is(s.convertToPlainText("<body><noframes>bar</noframes>foo", c.OutputNoFramesContent | c.OutputLFLineBreak, 0), "foo", "Wrong conversion result 8");
+is(s.convertToPlainText("<i>foo</i> <b>bar</b>", c.OutputFormatted | c.OutputLFLineBreak, 0), "/foo/ *bar*\n", "Wrong conversion result 9");
+is(s.convertToPlainText("<p>foo</p> <p>bar</p>", c.OutputLFLineBreak, 0), "foo\n\nbar", "Wrong conversion result 10");
+
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/content/canvas/crashtests/729116.html
@@ -0,0 +1,18 @@
+<html>
+<script language=javascript>
+
+function draw() {
+  var canv = document.getElementById("canv");
+  var ctx = canv.getContext("2d");
+  try {
+    canv.width = 50000;
+  } catch (e) { }
+
+  ctx.clearRect(0, 0, 10, 10);
+}
+
+</script>
+<body onload="draw()">
+<canvas id="canv" width="5" height="5"></canvas>
+</body>
+</html>
--- a/content/canvas/crashtests/crashtests.list
+++ b/content/canvas/crashtests/crashtests.list
@@ -1,5 +1,6 @@
 load 360293-1.html
 load 421715-1.html
 load 553938-1.html
 load 647480.html
 load 0px-size-font-667225.html
+skip-if(cocoaWidget&&layersGPUAccelerated) load 729116.html # bug 731117
--- a/content/canvas/src/WebGLContext.cpp
+++ b/content/canvas/src/WebGLContext.cpp
@@ -357,18 +357,16 @@ WebGLContext::SetDimensions(PRInt32 widt
 
         gl->ClearSafely();
 
         return NS_OK;
     }
 
     /*** end of early success return cases ***/
 
-    ScopedGfxFeatureReporter reporter("WebGL");
-
     // At this point we know that the old context is not going to survive, even though we still don't
     // know if creating the new context will succeed.
     DestroyResourcesAndContext();
 
     // Get some prefs for some preferred/overriden things
     NS_ENSURE_TRUE(Preferences::GetRootBranch(), NS_ERROR_FAILURE);
 
     bool forceOSMesa =
@@ -381,16 +379,18 @@ WebGLContext::SetDimensions(PRInt32 widt
 #endif
     bool forceEnabled =
         Preferences::GetBool("webgl.force-enabled", false);
     bool disabled =
         Preferences::GetBool("webgl.disabled", false);
     bool verbose =
         Preferences::GetBool("webgl.verbose", false);
 
+    ScopedGfxFeatureReporter reporter("WebGL", forceEnabled);
+
     if (disabled)
         return NS_ERROR_FAILURE;
 
     mVerbose = verbose;
 
     // We're going to create an entirely new context.  If our
     // generation is not 0 right now (that is, if this isn't the first
     // context we're creating), we may have to dispatch a context lost
--- a/content/canvas/src/WebGLContextReporter.cpp
+++ b/content/canvas/src/WebGLContextReporter.cpp
@@ -37,17 +37,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "WebGLContext.h"
 #include "nsIMemoryReporter.h"
 
 using namespace mozilla;
 
 
-class WebGLMemoryMultiReporter : public nsIMemoryMultiReporter 
+class WebGLMemoryMultiReporter MOZ_FINAL : public nsIMemoryMultiReporter 
 {
   public:
     NS_DECL_ISUPPORTS
     NS_DECL_NSIMEMORYMULTIREPORTER
 };
 
 NS_IMPL_ISUPPORTS1(WebGLMemoryMultiReporter, nsIMemoryMultiReporter)
 
--- a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
@@ -1301,16 +1301,20 @@ nsCanvasRenderingContext2DAzure::Initial
   // will be set to non-null.
   // In all cases, any usable canvas context will have non-null mTarget.
 
   if (target) {
     mValid = true;
     mTarget = target;
   } else {
     mValid = false;
+    // Create a dummy target in the hopes that it will help us deal with users
+    // calling into us after having changed the size where the size resulted
+    // in an inability to create a correct DrawTarget.
+    mTarget = gfxPlatform::GetPlatform()->CreateOffscreenDrawTarget(IntSize(1, 1), FORMAT_B8G8R8A8);
   }
 
   mResetLayer = true;
 
   // set up the initial canvas defaults
   mStyleStack.Clear();
   mPathBuilder = nsnull;
   mPath = nsnull;
--- a/content/canvas/test/webgl/test_webgl_conformance_test_suite.html
+++ b/content/canvas/test/webgl/test_webgl_conformance_test_suite.html
@@ -37,16 +37,18 @@ var OPTIONS = {
     request.open('GET', url, false);
     request.send(null);
     if (request.readyState != 4) {
       throw error;
     }
     return request.responseText;
   };
 
+SimpleTest.waitForExplicitFinish();
+
 function start() {
 
   var kIsWindows = false;
   var kIsMac = false;
   var kIsLinux = false;
   if (navigator.platform.indexOf("Win") == 0)
     kIsWindows = true;
   else if (navigator.platform.indexOf("Linux") == 0)
@@ -57,16 +59,44 @@ function start() {
   var kIsWindowsVistaOrHigher = false;
   if (kIsWindows) {
     // code borrowed from browser/modules/test/browser_taskbar_preview.js
     netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
     var version = Components.classes["@mozilla.org/system-info;1"]
                             .getService(Components.interfaces.nsIPropertyBag2)
                             .getProperty("version");
     kIsWindowsVistaOrHigher = (parseFloat(version) >= 6.0);
+    // Workaround for Windows 2000 (driver?) which may crash itself.
+    if (parseFloat(version) <= 5.0) {
+      todo(false, "Test disabled on Windows 2000 and older. (To prevent possible system crash.)");
+      SimpleTest.finish();
+      return;
+    }
+  }
+
+  // we currently disable this test on version of Mac OSX older than 10.6,
+  // due to various weird failures, including one making getRenderbufferParameter tests
+  // on DEPTH_STENCIL fail
+  var kDarwinVersion = 0;
+  if (kIsMac) {
+    // code borrowed from browser/modules/test/browser_taskbar_preview.js
+    var is106orHigher = false;
+    netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+    kDarwinVersion = parseFloat(Components.classes["@mozilla.org/system-info;1"]
+                                          .getService(Components.interfaces.nsIPropertyBag2)
+                                          .getProperty("version"));
+    // the next line is correct: Mac OS 10.6 corresponds to Darwin version 10 !
+    // Mac OS 10.5 would be Darwin version 9. the |version| string we've got here
+    // is the Darwin version.
+    is106orHigher = (kDarwinVersion >= 10.0);
+    if (!is106orHigher) {
+      dump("WebGL mochitest disabled on Mac OSX versions older than 10.6\n");
+      SimpleTest.finish();
+      return;
+    }
   }
 
   function getEnv(env) {
     netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
     var envsvc = Components.classes["@mozilla.org/process/environment;1"].getService(Components.interfaces.nsIEnvironment);
     var val = envsvc.get(env);
     if (val == "")
       return null;
@@ -338,47 +368,28 @@ function start() {
                 return reporter.reportFunc(type, msg, success);
             },
             OPTIONS);
         testHarness.setTimeoutDelay(20000); // and make it much higher when running under valgrind.
         window.webglTestHarness = testHarness;
     } else {
         var errmsg = "Can't create a WebGL context";
         reporter.fullResultsNode.textContent = errmsg;
-        ok(false, errmsg);
+        // Workaround for SeaMonkey tinderboxes which don't support WebGL.
+        if (navigator.userAgent.match(/ SeaMonkey\//))
+          todo(false, errmsg + " (This is expected on SeaMonkey (tinderboxes).)");
+        else
+          ok(false, errmsg);
         dump("WebGL mochitest failed: " + errmsg + "\n");
         reporter.finishedTestSuite();
     }
   };
 
-  SimpleTest.waitForExplicitFinish();
   SimpleTest.requestLongerTimeout(3);
 
-  // we currently disable this test on version of Mac OSX older than 10.6,
-  // due to various weird failures, including one making getRenderbufferParameter tests
-  // on DEPTH_STENCIL fail
-  var kDarwinVersion = 0;
-  if (kIsMac) {
-    // code borrowed from browser/modules/test/browser_taskbar_preview.js
-    var is106orHigher = false;
-    netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
-    kDarwinVersion = parseFloat(Components.classes["@mozilla.org/system-info;1"]
-                                          .getService(Components.interfaces.nsIPropertyBag2)
-                                          .getProperty("version"));
-    // the next line is correct: Mac OS 10.6 corresponds to Darwin version 10 !
-    // Mac OS 10.5 would be Darwin version 9. the |version| string we've got here
-    // is the Darwin version.
-    is106orHigher = (kDarwinVersion >= 10.0);
-    if (!is106orHigher) {
-      dump("WebGL mochitest disabled on Mac OSX versions older than 10.6\n");
-      SimpleTest.finish();
-      return;
-    }
-  }
-
   var statusElem = document.getElementById("status");
   var statusTextNode = document.createTextNode('');
   statusElem.appendChild(statusTextNode);
 
   var expectedtofailElem = document.getElementById("expectedtofail");
   var expectedtofailTextNode = document.createTextNode('');
   expectedtofailElem.appendChild(expectedtofailTextNode);
 
@@ -426,17 +437,17 @@ function start() {
 
   var testsSuccessful = [];
 
   runTestSuite();
 }
 
 </script>
 </head>
-<body onload="start()">
+<body onload="start();">
 <p id="display"></p>
 <div id="content" style="display: none">
 
 </div>
 <table border="2px">
   <tr style="height: 500px;">
     <td style="width: 500px;">
       <iframe id="testframe" scrolling="no" width="500px" height="500px"></iframe>
--- a/content/html/content/src/nsHTMLLinkElement.cpp
+++ b/content/html/content/src/nsHTMLLinkElement.cpp
@@ -47,17 +47,16 @@
 #include "nsReadableUtils.h"
 #include "nsUnicharUtils.h"
 #include "nsIURL.h"
 #include "nsNetUtil.h"
 #include "nsIDocument.h"
 #include "nsIDOMEvent.h"
 #include "nsIPrivateDOMEvent.h"
 #include "nsIDOMEventTarget.h"
-#include "nsParserUtils.h"
 #include "nsContentUtils.h"
 #include "nsPIDOMWindow.h"
 #include "nsAsyncDOMEvent.h"
 
 #include "Link.h"
 using namespace mozilla::dom;
 
 class nsHTMLLinkElement : public nsGenericHTMLElement,
@@ -434,17 +433,17 @@ nsHTMLLinkElement::GetStyleSheetInfo(nsA
   }
 
   GetAttr(kNameSpaceID_None, nsGkAtoms::media, aMedia);
   ToLowerCase(aMedia); // HTML4.0 spec is inconsistent, make it case INSENSITIVE
 
   nsAutoString mimeType;
   nsAutoString notUsed;
   GetAttr(kNameSpaceID_None, nsGkAtoms::type, aType);
-  nsParserUtils::SplitMimeType(aType, mimeType, notUsed);
+  nsContentUtils::SplitMimeType(aType, mimeType, notUsed);
   if (!mimeType.IsEmpty() && !mimeType.LowerCaseEqualsLiteral("text/css")) {
     return;
   }
 
   // If we get here we assume that we're loading a css file, so set the
   // type to 'text/css'
   aType.AssignLiteral("text/css");
 
--- a/content/html/content/src/nsHTMLStyleElement.cpp
+++ b/content/html/content/src/nsHTMLStyleElement.cpp
@@ -42,17 +42,16 @@
 #include "nsGkAtoms.h"
 #include "nsStyleConsts.h"
 #include "nsIDOMStyleSheet.h"
 #include "nsIStyleSheet.h"
 #include "nsStyleLinkElement.h"
 #include "nsNetUtil.h"
 #include "nsIDocument.h"
 #include "nsUnicharUtils.h"
-#include "nsParserUtils.h"
 #include "nsThreadUtils.h"
 #include "nsContentUtils.h"
 
 class nsHTMLStyleElement : public nsGenericHTMLElement,
                            public nsIDOMHTMLStyleElement,
                            public nsStyleLinkElement,
                            public nsStubMutationObserver
 {
@@ -342,17 +341,17 @@ nsHTMLStyleElement::GetStyleSheetInfo(ns
 
   GetAttr(kNameSpaceID_None, nsGkAtoms::media, aMedia);
   ToLowerCase(aMedia); // HTML4.0 spec is inconsistent, make it case INSENSITIVE
 
   GetAttr(kNameSpaceID_None, nsGkAtoms::type, aType);
 
   nsAutoString mimeType;
   nsAutoString notUsed;
-  nsParserUtils::SplitMimeType(aType, mimeType, notUsed);
+  nsContentUtils::SplitMimeType(aType, mimeType, notUsed);
   if (!mimeType.IsEmpty() && !mimeType.LowerCaseEqualsLiteral("text/css")) {
     return;
   }
 
   // If we get here we assume that we're loading a css file, so set the
   // type to 'text/css'
   aType.AssignLiteral("text/css");
 }
--- a/content/html/document/src/nsHTMLContentSink.cpp
+++ b/content/html/document/src/nsHTMLContentSink.cpp
@@ -45,17 +45,16 @@
 #include "nsContentSink.h"
 #include "nsCOMPtr.h"
 #include "nsReadableUtils.h"
 #include "nsUnicharUtils.h"
 #include "nsIHTMLContentSink.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIParser.h"
-#include "nsParserUtils.h"
 #include "nsScriptLoader.h"
 #include "nsIURI.h"
 #include "nsNetUtil.h"
 #include "nsIContentViewer.h"
 #include "nsIMarkupDocumentViewer.h"
 #include "nsINodeInfo.h"
 #include "nsHTMLTokens.h"
 #include "nsIAppShell.h"
--- a/content/mathml/content/src/nsMathMLElement.cpp
+++ b/content/mathml/content/src/nsMathMLElement.cpp
@@ -141,16 +141,21 @@ nsMathMLElement::ParseAttribute(PRInt32 
       return aResult.ParseColor(aValue);
     }
   }
 
   return nsMathMLElementBase::ParseAttribute(aNamespaceID, aAttribute,
                                              aValue, aResult);
 }
 
+static nsGenericElement::MappedAttributeEntry sMtableStyles[] = {
+  { &nsGkAtoms::width },
+  { nsnull }
+};
+
 static nsGenericElement::MappedAttributeEntry sTokenStyles[] = {
   { &nsGkAtoms::mathsize_ },
   { &nsGkAtoms::fontsize_ },
   { &nsGkAtoms::color },
   { &nsGkAtoms::fontfamily_ },
   { nsnull }
 };
 
@@ -166,16 +171,20 @@ static nsGenericElement::MappedAttribute
   { &nsGkAtoms::mathcolor_ },
   { &nsGkAtoms::mathbackground_ },
   { nsnull }
 };
 
 bool
 nsMathMLElement::IsAttributeMapped(const nsIAtom* aAttribute) const
 {
+  static const MappedAttributeEntry* const mtableMap[] = {
+    sMtableStyles,
+    sCommonPresStyles
+  };
   static const MappedAttributeEntry* const tokenMap[] = {
     sTokenStyles,
     sCommonPresStyles
   };
   static const MappedAttributeEntry* const mstyleMap[] = {
     sTokenStyles,
     sEnvironmentStyles,
     sCommonPresStyles
@@ -189,16 +198,19 @@ nsMathMLElement::IsAttributeMapped(const
   if (tag == nsGkAtoms::ms_ || tag == nsGkAtoms::mi_ ||
       tag == nsGkAtoms::mn_ || tag == nsGkAtoms::mo_ ||
       tag == nsGkAtoms::mtext_ || tag == nsGkAtoms::mspace_)
     return FindAttributeDependence(aAttribute, tokenMap);
   if (tag == nsGkAtoms::mstyle_ ||
       tag == nsGkAtoms::math)
     return FindAttributeDependence(aAttribute, mstyleMap);
 
+  if (tag == nsGkAtoms::mtable_)
+    return FindAttributeDependence(aAttribute, mtableMap);
+
   if (tag == nsGkAtoms::maction_ ||
       tag == nsGkAtoms::maligngroup_ ||
       tag == nsGkAtoms::malignmark_ ||
       tag == nsGkAtoms::menclose_ ||
       tag == nsGkAtoms::merror_ ||
       tag == nsGkAtoms::mfenced_ ||
       tag == nsGkAtoms::mfrac_ ||
       tag == nsGkAtoms::mover_ ||
@@ -206,17 +218,16 @@ nsMathMLElement::IsAttributeMapped(const
       tag == nsGkAtoms::mphantom_ ||
       tag == nsGkAtoms::mprescripts_ ||
       tag == nsGkAtoms::mroot_ ||
       tag == nsGkAtoms::mrow_ ||
       tag == nsGkAtoms::msqrt_ ||
       tag == nsGkAtoms::msub_ ||
       tag == nsGkAtoms::msubsup_ ||
       tag == nsGkAtoms::msup_ ||
-      tag == nsGkAtoms::mtable_ ||
       tag == nsGkAtoms::mtd_ ||
       tag == nsGkAtoms::mtr_ ||
       tag == nsGkAtoms::munder_ ||
       tag == nsGkAtoms::munderover_ ||
       tag == nsGkAtoms::none) {
     return FindAttributeDependence(aAttribute, commonPresMap);
   }
 
@@ -454,16 +465,29 @@ nsMathMLElement::MapMathMLAttributesInto
     }
     nscolor color;
     nsCSSValue* colorValue = aData->ValueForColor();
     if (value && value->GetColorValue(color) &&
         colorValue->GetUnit() == eCSSUnit_Null) {
       colorValue->SetColorValue(color);
     }
   }
+
+  if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Position)) {
+    // width: value
+    nsCSSValue* width = aData->ValueForWidth();
+    if (width->GetUnit() == eCSSUnit_Null) {
+      const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::width);
+      // This does not handle auto and unitless values
+      if (value && value->Type() == nsAttrValue::eString) {
+        ParseNumericValue(value->GetStringValue(), *width, 0);
+      }
+    }
+  }
+
 }
 
 nsresult
 nsMathMLElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
 {
   nsresult rv = nsGenericElement::PreHandleEvent(aVisitor);
   NS_ENSURE_SUCCESS(rv, rv);
 
--- a/content/xml/content/src/nsXMLProcessingInstruction.cpp
+++ b/content/xml/content/src/nsXMLProcessingInstruction.cpp
@@ -34,18 +34,18 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsGenericElement.h"
 #include "nsGkAtoms.h"
 #include "nsUnicharUtils.h"
 #include "nsXMLProcessingInstruction.h"
-#include "nsParserUtils.h"
 #include "nsContentCreatorFunctions.h"
+#include "nsContentUtils.h"
 
 nsresult
 NS_NewXMLProcessingInstruction(nsIContent** aInstancePtrResult,
                                nsNodeInfoManager *aNodeInfoManager,
                                const nsAString& aTarget,
                                const nsAString& aData)
 {
   NS_PRECONDITION(aNodeInfoManager, "Missing nodeinfo manager");
@@ -124,17 +124,17 @@ nsXMLProcessingInstruction::GetTarget(ns
 }
 
 bool
 nsXMLProcessingInstruction::GetAttrValue(nsIAtom *aName, nsAString& aValue)
 {
   nsAutoString data;
 
   GetData(data);
-  return nsParserUtils::GetQuotedAttributeValue(data, aName, aValue);
+  return nsContentUtils::GetPseudoAttributeValue(data, aName, aValue);
 }
 
 bool
 nsXMLProcessingInstruction::IsNodeOfType(PRUint32 aFlags) const
 {
   return !(aFlags & ~(eCONTENT | ePROCESSING_INSTRUCTION | eDATA_NODE));
 }
 
--- a/content/xml/content/src/nsXMLStylesheetPI.cpp
+++ b/content/xml/content/src/nsXMLStylesheetPI.cpp
@@ -40,17 +40,16 @@
 #include "nsIDOMStyleSheet.h"
 #include "nsIDocument.h"
 #include "nsIStyleSheet.h"
 #include "nsIURI.h"
 #include "nsStyleLinkElement.h"
 #include "nsNetUtil.h"
 #include "nsXMLProcessingInstruction.h"
 #include "nsUnicharUtils.h"
-#include "nsParserUtils.h"
 #include "nsGkAtoms.h"
 #include "nsThreadUtils.h"
 #include "nsContentUtils.h"
 
 class nsXMLStylesheetPI : public nsXMLProcessingInstruction,
                           public nsStyleLinkElement
 {
 public:
@@ -204,37 +203,39 @@ nsXMLStylesheetPI::GetStyleSheetInfo(nsA
   // xml-stylesheet PI is special only in prolog
   if (!nsContentUtils::InProlog(this)) {
     return;
   }
 
   nsAutoString data;
   GetData(data);
 
-  nsParserUtils::GetQuotedAttributeValue(data, nsGkAtoms::title, aTitle);
+  nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::title, aTitle);
 
   nsAutoString alternate;
-  nsParserUtils::GetQuotedAttributeValue(data, nsGkAtoms::alternate, alternate);
+  nsContentUtils::GetPseudoAttributeValue(data,
+                                          nsGkAtoms::alternate,
+                                          alternate);
 
   // if alternate, does it have title?
   if (alternate.EqualsLiteral("yes")) {
     if (aTitle.IsEmpty()) { // alternates must have title
       return;
     }
 
     *aIsAlternate = true;
   }
 
-  nsParserUtils::GetQuotedAttributeValue(data, nsGkAtoms::media, aMedia);
+  nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::media, aMedia);
 
   nsAutoString type;
-  nsParserUtils::GetQuotedAttributeValue(data, nsGkAtoms::type, type);
+  nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::type, type);
 
   nsAutoString mimeType, notUsed;
-  nsParserUtils::SplitMimeType(type, mimeType, notUsed);
+  nsContentUtils::SplitMimeType(type, mimeType, notUsed);
   if (!mimeType.IsEmpty() && !mimeType.LowerCaseEqualsLiteral("text/css")) {
     aType.Assign(type);
     return;
   }
 
   // If we get here we assume that we're loading a css file, so set the
   // type to 'text/css'
   aType.AssignLiteral("text/css");
--- a/content/xml/document/src/nsXMLContentSink.cpp
+++ b/content/xml/document/src/nsXMLContentSink.cpp
@@ -63,17 +63,16 @@
 #include "nsIScriptContext.h"
 #include "nsINameSpaceManager.h"
 #include "nsIServiceManager.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIContentViewer.h"
 #include "prtime.h"
 #include "prlog.h"
 #include "prmem.h"
-#include "nsParserUtils.h"
 #include "nsRect.h"
 #include "nsGenericElement.h"
 #include "nsIWebNavigation.h"
 #include "nsIScriptElement.h"
 #include "nsScriptLoader.h"
 #include "nsStyleLinkElement.h"
 #include "nsIImageLoadingContent.h"
 #include "nsReadableUtils.h"
@@ -260,37 +259,37 @@ CheckXSLTParamPI(nsIDOMProcessingInstruc
 {
   nsAutoString target, data;
   aPi->GetTarget(target);
 
   // Check for namespace declarations
   if (target.EqualsLiteral("xslt-param-namespace")) {
     aPi->GetData(data);
     nsAutoString prefix, namespaceAttr;
-    nsParserUtils::GetQuotedAttributeValue(data, nsGkAtoms::prefix,
-                                           prefix);
+    nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::prefix,
+                                            prefix);
     if (!prefix.IsEmpty() &&
-        nsParserUtils::GetQuotedAttributeValue(data, nsGkAtoms::_namespace,
-                                               namespaceAttr)) {
+        nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::_namespace,
+                                                namespaceAttr)) {
       aProcessor->AddXSLTParamNamespace(prefix, namespaceAttr);
     }
   }
 
   // Check for actual parameters
   else if (target.EqualsLiteral("xslt-param")) {
     aPi->GetData(data);
     nsAutoString name, namespaceAttr, select, value;
-    nsParserUtils::GetQuotedAttributeValue(data, nsGkAtoms::name,
-                                           name);
-    nsParserUtils::GetQuotedAttributeValue(data, nsGkAtoms::_namespace,
-                                           namespaceAttr);
-    if (!nsParserUtils::GetQuotedAttributeValue(data, nsGkAtoms::select, select)) {
+    nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::name,
+                                            name);
+    nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::_namespace,
+                                            namespaceAttr);
+    if (!nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::select, select)) {
       select.SetIsVoid(true);
     }
-    if (!nsParserUtils::GetQuotedAttributeValue(data, nsGkAtoms::value, value)) {
+    if (!nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::value, value)) {
       value.SetIsVoid(true);
     }
     if (!name.IsEmpty()) {
       nsCOMPtr<nsIDOMNode> doc = do_QueryInterface(aDocument);
       aProcessor->AddXSLTParam(name, namespaceAttr, select, value, doc);
     }
   }
 }
@@ -1335,17 +1334,17 @@ nsXMLContentSink::HandleProcessingInstru
       }
 
       return NS_OK;
     }
   }
 
   // If it's not a CSS stylesheet PI...
   nsAutoString type;
-  nsParserUtils::GetQuotedAttributeValue(data, nsGkAtoms::type, type);
+  nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::type, type);
 
   if (mState != eXMLContentSinkState_InProlog ||
       !target.EqualsLiteral("xml-stylesheet") ||
       type.IsEmpty()                          ||
       type.LowerCaseEqualsLiteral("text/css")) {
     return DidProcessATokenImpl();
   }
 
@@ -1363,26 +1362,28 @@ nsXMLContentSink::HandleProcessingInstru
 
 /* static */
 bool
 nsXMLContentSink::ParsePIData(const nsString &aData, nsString &aHref,
                               nsString &aTitle, nsString &aMedia,
                               bool &aIsAlternate)
 {
   // If there was no href, we can't do anything with this PI
-  if (!nsParserUtils::GetQuotedAttributeValue(aData, nsGkAtoms::href, aHref)) {
+  if (!nsContentUtils::GetPseudoAttributeValue(aData, nsGkAtoms::href, aHref)) {
     return false;
   }
 
-  nsParserUtils::GetQuotedAttributeValue(aData, nsGkAtoms::title, aTitle);
+  nsContentUtils::GetPseudoAttributeValue(aData, nsGkAtoms::title, aTitle);
 
-  nsParserUtils::GetQuotedAttributeValue(aData, nsGkAtoms::media, aMedia);
+  nsContentUtils::GetPseudoAttributeValue(aData, nsGkAtoms::media, aMedia);
 
   nsAutoString alternate;
-  nsParserUtils::GetQuotedAttributeValue(aData, nsGkAtoms::alternate, alternate);
+  nsContentUtils::GetPseudoAttributeValue(aData,
+                                          nsGkAtoms::alternate,
+                                          alternate);
 
   aIsAlternate = alternate.EqualsLiteral("yes");
 
   return true;
 }
 
 NS_IMETHODIMP
 nsXMLContentSink::HandleXMLDeclaration(const PRUnichar *aVersion,
--- a/content/xul/content/src/nsXULElement.cpp
+++ b/content/xul/content/src/nsXULElement.cpp
@@ -1363,17 +1363,18 @@ nsXULElement::UnsetAttr(PRInt32 aNameSpa
     bool hasMutationListeners = aNotify &&
         nsContentUtils::HasMutationListeners(this,
             NS_EVENT_BITS_MUTATION_ATTRMODIFIED, this);
 
     nsCOMPtr<nsIDOMAttr> attrNode;
     if (hasMutationListeners) {
         nsAutoString ns;
         nsContentUtils::NameSpaceManager()->GetNameSpaceURI(aNameSpaceID, ns);
-        GetAttributeNodeNS(ns, nsDependentAtomString(aName), getter_AddRefs(attrNode));
+        GetAttributeNodeNSInternal(ns, nsDependentAtomString(aName),
+                                   getter_AddRefs(attrNode));
     }
 
     nsDOMSlots *slots = GetExistingDOMSlots();
     if (slots && slots->mAttributeMap) {
       slots->mAttributeMap->DropAttribute(aNameSpaceID, aName);
     }
 
     // The id-handling code, and in the future possibly other code, need to
--- a/content/xul/document/src/nsXULContentSink.cpp
+++ b/content/xul/document/src/nsXULContentSink.cpp
@@ -69,17 +69,16 @@
 #include "nsIServiceManager.h"
 #include "nsIURL.h"
 #include "nsIViewManager.h"
 #include "nsIXULDocument.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsLayoutCID.h"
 #include "nsNetUtil.h"
 #include "nsRDFCID.h"
-#include "nsParserUtils.h"
 #include "nsXPIDLString.h"
 #include "nsReadableUtils.h"
 #include "nsXULElement.h"
 #include "prlog.h"
 #include "prmem.h"
 #include "nsCRT.h"
 
 #include "nsXULPrototypeDocument.h"     // XXXbe temporary
@@ -1074,17 +1073,17 @@ XULContentSinkImpl::OpenScript(const PRU
               }
           }
       }
       else if (key.EqualsLiteral("language")) {
           // Language is deprecated, and the impl in nsScriptLoader ignores the
           // various version strings anyway.  So we make no attempt to support
           // languages other than JS for language=
           nsAutoString lang(aAttributes[1]);
-          if (nsParserUtils::IsJavaScriptLanguage(lang, &version)) {
+          if (nsContentUtils::IsJavaScriptLanguage(lang, &version)) {
               langID = nsIProgrammingLanguage::JAVASCRIPT;
 
               // Even when JS version < 1.6 is specified, E4X is
               // turned on in XUL.
               version = js::VersionSetXML(JSVersion(version), true);
           }
       }
       aAttributes += 2;
--- a/content/xul/document/src/nsXULDocument.cpp
+++ b/content/xul/document/src/nsXULDocument.cpp
@@ -79,17 +79,16 @@
 #include "nsITimer.h"
 #include "nsIDocShell.h"
 #include "nsGkAtoms.h"
 #include "nsXMLContentSink.h"
 #include "nsXULContentSink.h"
 #include "nsXULContentUtils.h"
 #include "nsIXULOverlayProvider.h"
 #include "nsNetUtil.h"
-#include "nsParserUtils.h"
 #include "nsParserCIID.h"
 #include "nsPIBoxObject.h"
 #include "nsRDFCID.h"
 #include "nsILocalStore.h"
 #include "nsXPIDLString.h"
 #include "nsPIDOMWindow.h"
 #include "nsPIWindowRoot.h"
 #include "nsXULCommandDispatcher.h"
@@ -2540,19 +2539,19 @@ nsXULDocument::InsertXULOverlayPI(const 
     if (NS_FAILED(rv)) return rv;
 
     // xul-overlay PI is special only in prolog
     if (!nsContentUtils::InProlog(aPINode)) {
         return NS_OK;
     }
 
     nsAutoString href;
-    nsParserUtils::GetQuotedAttributeValue(aProtoPI->mData,
-                                           nsGkAtoms::href,
-                                           href);
+    nsContentUtils::GetPseudoAttributeValue(aProtoPI->mData,
+                                            nsGkAtoms::href,
+                                            href);
 
     // If there was no href, we can't do anything with this PI
     if (href.IsEmpty()) {
         return NS_OK;
     }
 
     // Add the overlay to our list of overlays that need to be processed.
     nsCOMPtr<nsIURI> uri;
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -7662,37 +7662,40 @@ void nsGlobalWindow::MaybeUpdateTouchSta
   nsIFocusManager* fm = nsFocusManager::GetFocusManager();
 
   nsCOMPtr<nsIDOMWindow> focusedWindow;
   fm->GetFocusedWindow(getter_AddRefs(focusedWindow));
 
   if(this == focusedWindow) {
     UpdateTouchState();
   }
+
+  if (mMayHaveTouchEventListener) {
+    nsCOMPtr<nsIObserverService> observerService =
+      do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
+
+    if (observerService) {
+      observerService->NotifyObservers(static_cast<nsIDOMWindow*>(this),
+                                       DOM_TOUCH_LISTENER_ADDED,
+                                       nsnull);
+    }
+  }
 }
 
 void nsGlobalWindow::UpdateTouchState()
 {
   FORWARD_TO_INNER_VOID(UpdateTouchState, ());
 
   nsCOMPtr<nsIWidget> mainWidget = GetMainWidget();
-  if (!mainWidget)
+  if (!mainWidget) {
     return;
+  }
 
   if (mMayHaveTouchEventListener) {
     mainWidget->RegisterTouchWindow();
-
-    nsCOMPtr<nsIObserverService> observerService =
-      do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
-
-    if (observerService) {
-      observerService->NotifyObservers(static_cast<nsIDOMWindow*>(this),
-                                       DOM_TOUCH_LISTENER_ADDED,
-                                       nsnull);
-    }
   } else {
     mainWidget->UnregisterTouchWindow();
   }
 }
 
 void
 nsGlobalWindow::EnableDeviceMotionUpdates()
 {
--- a/dom/plugins/base/nsPluginHost.cpp
+++ b/dom/plugins/base/nsPluginHost.cpp
@@ -927,19 +927,19 @@ nsPluginHost::GetPluginTempDir(nsIFile *
     NS_ENSURE_SUCCESS(rv, rv);
 
     tmpDir.swap(sPluginTempDir);
   }
 
   return sPluginTempDir->Clone(aDir);
 }
 
-nsresult nsPluginHost::InstantiatePluginForChannel(nsIChannel* aChannel,
-                                                   nsObjectLoadingContent* aContent,
-                                                   nsIStreamListener** aListener)
+nsresult nsPluginHost::CreateListenerForChannel(nsIChannel* aChannel,
+                                                nsObjectLoadingContent* aContent,
+                                                nsIStreamListener** aListener)
 {
   NS_PRECONDITION(aChannel && aContent,
                   "Invalid arguments to InstantiatePluginForChannel");
   nsCOMPtr<nsIURI> uri;
   nsresult rv = aChannel->GetURI(getter_AddRefs(uri));
   if (NS_FAILED(rv))
     return rv;
 
@@ -1063,17 +1063,17 @@ nsPluginHost::InstantiateEmbeddedPlugin(
       nsCOMPtr<nsIProtocolHandler> handler = do_GetService(contractID.get());
       if (handler)
         bCanHandleInternally = true;
   }
 
   // if we don't have a MIME type at this point, we still have one more chance by
   // opening the stream and seeing if the server hands one back
   if (!aMimeType) {
-    if (bCanHandleInternally && !aContent->SrcStreamLoadInitiated()) {
+    if (bCanHandleInternally && !aContent->SrcStreamLoading()) {
       NewEmbeddedPluginStream(aURL, aContent, nsnull);
     }
     return NS_ERROR_FAILURE;
   }
 
   rv = SetUpPluginInstance(aMimeType, aURL, instanceOwner);
   if (NS_FAILED(rv)) {
     return NS_ERROR_FAILURE;
@@ -1091,17 +1091,17 @@ nsPluginHost::InstantiateEmbeddedPlugin(
     // If we've got a native window, the let the plugin know about it.
     instanceOwner->CallSetWindow();
 
     // create an initial stream with data
     // don't make the stream if it's a java applet or we don't have SRC or DATA attribute
     // no need to check for "data" as it would have been converted to "src"
     const char *value;
     bool havedata = NS_SUCCEEDED(pti->GetAttribute("SRC", &value));
-    if (havedata && !isJava && bCanHandleInternally && !aContent->SrcStreamLoadInitiated()) {
+    if (havedata && !isJava && bCanHandleInternally && !aContent->SrcStreamLoading()) {
       NewEmbeddedPluginStream(aURL, nsnull, instance.get());
     }
   }
 
   // At this point we consider instantiation to be successful. Do not return an error.
   instanceOwner.forget(aOwner);
 
 #ifdef PLUGIN_LOGGING
--- a/dom/plugins/base/nsPluginHost.h
+++ b/dom/plugins/base/nsPluginHost.h
@@ -108,19 +108,19 @@ public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIPLUGINHOST
   NS_DECL_NSIOBSERVER
   NS_DECL_NSITIMERCALLBACK
 
   nsresult Init();
   nsresult Destroy();
   nsresult LoadPlugins();
-  nsresult InstantiatePluginForChannel(nsIChannel* aChannel,
-                                       nsObjectLoadingContent* aContent,
-                                       nsIStreamListener** aListener);
+  nsresult CreateListenerForChannel(nsIChannel* aChannel,
+                                    nsObjectLoadingContent* aContent,
+                                    nsIStreamListener** aListener);
   nsresult SetUpPluginInstance(const char *aMimeType,
                                nsIURI *aURL,
                                nsIPluginInstanceOwner *aOwner);
   nsresult IsPluginEnabledForType(const char* aMimeType);
   nsresult IsPluginEnabledForExtension(const char* aExtension, const char* &aMimeType);
 
   nsresult GetPluginCount(PRUint32* aPluginCount);
   nsresult GetPlugins(PRUint32 aPluginCount, nsIDOMPlugin** aPluginArray);
--- a/dom/src/geolocation/nsGeoPosition.h
+++ b/dom/src/geolocation/nsGeoPosition.h
@@ -81,28 +81,28 @@ public:
 
 ////////////////////////////////////////////////////
 // nsGeoPositionCoords
 ////////////////////////////////////////////////////
 
 /**
  * Simple object that holds a single point in space.
  */
-class nsGeoPositionCoords : public nsIDOMGeoPositionCoords
+class nsGeoPositionCoords MOZ_FINAL : public nsIDOMGeoPositionCoords
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIDOMGEOPOSITIONCOORDS
   
   nsGeoPositionCoords(double aLat, double aLong,
                       double aAlt, double aHError,
                       double aVError, double aHeading,
                       double aSpeed);
+  ~nsGeoPositionCoords();
 private:
-  ~nsGeoPositionCoords();
   const double mLat, mLong, mAlt, mHError, mVError, mHeading, mSpeed;
 };
 
 
 ////////////////////////////////////////////////////
 // nsGeoPosition
 ////////////////////////////////////////////////////
 
--- a/dom/src/geolocation/nsGeoPositionIPCSerialiser.h
+++ b/dom/src/geolocation/nsGeoPositionIPCSerialiser.h
@@ -37,17 +37,17 @@
 #ifndef dom_src_geolocation_IPC_serialiser
 #define dom_src_geolocation_IPC_serialiser
 
 #include "IPC/IPCMessageUtils.h"
 #include "nsGeoPosition.h"
 #include "nsIDOMGeoPosition.h"
 
 typedef nsIDOMGeoPositionAddress  *GeoPositionAddress;
-typedef nsIDOMGeoPositionCoords   *GeoPositionCoords;
+typedef nsGeoPositionCoords       *GeoPositionCoords;
 typedef nsIDOMGeoPosition         *GeoPosition;
 
 namespace IPC {
 
 template <>
 struct ParamTraits<GeoPositionAddress>
 {
   typedef GeoPositionAddress paramType;
@@ -228,17 +228,17 @@ struct ParamTraits<GeoPosition>
     if (isNull) return;
 
     DOMTimeStamp timeStamp;
     aParam->GetTimestamp(&timeStamp);
     WriteParam(aMsg, timeStamp);
 
     nsCOMPtr<nsIDOMGeoPositionCoords> coords;
     aParam->GetCoords(getter_AddRefs(coords));
-    GeoPositionCoords simpleCoords = coords.get();
+    GeoPositionCoords simpleCoords = static_cast<GeoPositionCoords>(coords.get());
     WriteParam(aMsg, simpleCoords);
 
     nsCOMPtr<nsIDOMGeoPositionAddress> address;
     aParam->GetAddress(getter_AddRefs(address));
     GeoPositionAddress simpleAddress = address.get();
     WriteParam(aMsg, simpleAddress);
   }
 
--- a/dom/tests/mochitest/bugs/test_resize_move_windows.html
+++ b/dom/tests/mochitest/bugs/test_resize_move_windows.html
@@ -257,20 +257,22 @@ function checkChangeIsEnabled(aWindow, a
   });
   });
   });
   });
   });
   });
 }
 
+SpecialPowers.pushPrefEnv({"set": [["dom.disable_window_move_resize", false]]}, function() {
 SimpleTest.waitForFocus(function() {
   if (screen.width <= 200 || screen.height <= 200) {
-    todo(false, "The screen is too small to run this test.");
+    todo(false, "The screen needs to be bigger than 200px*200px to run this test.");
     SimpleTest.finish();
+    return;
   }
 
   backValues();
 
   // The current window can't change it's own size and position.
   checkChangeIsDisabled(window, function() {
     // We create a window and check that it can change its own size and position.
     // However, passing size/position parameters to window.open should work.
@@ -313,13 +315,14 @@ SimpleTest.waitForFocus(function() {
               });
             });
           }, w, false);
         });
       })
     }, w, false);
   });
 });
+}); // SpecialPowers.pushPrefEnv()
 
 </script>
 </pre>
 </body>
 </html>
--- a/editor/txmgr/tests/TestTXMgr.cpp
+++ b/editor/txmgr/tests/TestTXMgr.cpp
@@ -787,289 +787,267 @@ quick_test(TestTransactionFactory *facto
   nsresult result;
 
   /*******************************************************************
    *
    * Create a transaction manager implementation:
    *
    *******************************************************************/
 
-  printf("Create transaction manager instance ... ");
-
   nsCOMPtr<nsITransactionManager> mgr =
     do_CreateInstance(NS_TRANSACTIONMANAGER_CONTRACTID, &result);
   if (NS_FAILED(result) || !mgr) {
     printf("ERROR: Failed to create Transaction Manager instance.\n");
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
-  printf("passed\n");
+  passed("Create transaction manager instance");
 
   /*******************************************************************
    *
    * Call DoTransaction() with a null transaction:
    *
    *******************************************************************/
 
-  printf("Call DoTransaction() with null transaction ... ");
   result = mgr->DoTransaction(0);
 
   if (result != NS_ERROR_NULL_POINTER) {
     printf("ERROR: DoTransaction() returned unexpected error. (%d)\n", result);
     return result;
   }
 
-  printf("passed\n");
+  passed("Call DoTransaction() with null transaction");
 
   /*******************************************************************
    *
    * Call UndoTransaction() with an empty undo stack:
    *
    *******************************************************************/
 
-  printf("Call UndoTransaction() with empty undo stack ... ");
   result = mgr->UndoTransaction();
 
   if (NS_FAILED(result)) {
     printf("ERROR: Undo on empty undo stack failed. (%d)\n", result);
     return result;
   }
 
-  printf("passed\n");
+  passed("Call UndoTransaction() with empty undo stack");
 
   /*******************************************************************
    *
    * Call RedoTransaction() with an empty redo stack:
    *
    *******************************************************************/
 
-  printf("Call RedoTransaction() with empty redo stack ... ");
   result = mgr->RedoTransaction();
 
   if (NS_FAILED(result)) {
     printf("ERROR: Redo on empty redo stack failed. (%d)\n", result);
     return result;
   }
 
-  printf("passed\n");
+  passed("Call RedoTransaction() with empty redo stack");
 
   /*******************************************************************
    *
    * Call SetMaxTransactionCount(-1) with empty undo and redo stacks:
    *
    *******************************************************************/
 
-  printf("Call SetMaxTransactionCount(-1) with empty undo and redo stacks ... ");
   result = mgr->SetMaxTransactionCount(-1);
 
   if (NS_FAILED(result)) {
     printf("ERROR: SetMaxTransactionCount(-1) failed. (%d)\n", result);
     return result;
   }
 
-  printf("passed\n");
+  passed("Call SetMaxTransactionCount(-1) with empty undo and redo stacks");
 
   /*******************************************************************
    *
    * Call SetMaxTransactionCount(0) with empty undo and redo stacks:
    *
    *******************************************************************/
 
-  printf("Call SetMaxTransactionCount(0) with empty undo and redo stacks ... ");
   result = mgr->SetMaxTransactionCount(0);
 
   if (NS_FAILED(result)) {
     printf("ERROR: SetMaxTransactionCount(0) failed. (%d)\n", result);
     return result;
   }
 
-  printf("passed\n");
+  passed("Call SetMaxTransactionCount(0) with empty undo and redo stacks");
 
   /*******************************************************************
    *
    * Call SetMaxTransactionCount(10) with empty undo and redo stacks:
    *
    *******************************************************************/
 
-  printf("Call SetMaxTransactionCount(10) with empty undo and redo stacks ... ");
   result = mgr->SetMaxTransactionCount(10);
 
   if (NS_FAILED(result)) {
     printf("ERROR: SetMaxTransactionCount(10) failed. (%d)\n", result);
     return result;
   }
 
-  printf("passed\n");
+  passed("Call SetMaxTransactionCount(10) with empty undo and redo stacks");
 
   /*******************************************************************
    *
    * Call Clear() with empty undo and redo stacks:
    *
    *******************************************************************/
 
-  printf("Call Clear() with empty undo and redo stack ... ");
-
   result = mgr->Clear();
   if (NS_FAILED(result)) {
     printf("ERROR: Clear on empty undo and redo stack failed. (%d)\n", result);
     return result;
   }
 
-  printf("passed\n");
+  passed("Call Clear() with empty undo and redo stack");
 
   PRInt32 numitems;
 
   /*******************************************************************
    *
    * Call GetNumberOfUndoItems() with an empty undo stack:
    *
    *******************************************************************/
 
-  printf("Call GetNumberOfUndoItems() with empty undo stack ... ");
   result = mgr->GetNumberOfUndoItems(&numitems);
 
   if (NS_FAILED(result)) {
     printf("ERROR: GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
            result);
     return result;
   }
 
   if (numitems != 0) {
     printf("ERROR: GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
            numitems, result);
     return NS_ERROR_FAILURE;
   }
 
-  printf("passed\n");
+  passed("Call GetNumberOfUndoItems() with empty undo stack");
 
   /*******************************************************************
    *
    * Call GetNumberOfRedoItems() with an empty redo stack:
    *
    *******************************************************************/
 
-  printf("Call GetNumberOfRedoItems() with empty redo stack ... ");
   result = mgr->GetNumberOfRedoItems(&numitems);
 
   if (NS_FAILED(result)) {
     printf("ERROR: GetNumberOfRedoItems() on empty redo stack failed. (%d)\n",
            result);
     return result;
   }
 
   if (numitems != 0) {
     printf("ERROR: GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
            numitems, result);
     return NS_ERROR_FAILURE;
   }
 
-  printf("passed\n");
+  passed("Call GetNumberOfRedoItems() with empty redo stack");
 
   nsITransaction *tx;
 
   /*******************************************************************
    *
    * Call PeekUndoStack() with an empty undo stack:
    *
    *******************************************************************/
 
-  printf("Call PeekUndoStack() with empty undo stack ... ");
-
   tx = 0;
   result = mgr->PeekUndoStack(&tx);
 
   TEST_TXMGR_IF_RELEASE(tx); // Don't hold onto any references!
 
   if (NS_FAILED(result)) {
     printf("ERROR: PeekUndoStack() on empty undo stack failed. (%d)\n", result);
     return result;
   }
 
   if (tx != 0) {
     printf("ERROR: PeekUndoStack() on empty undo stack failed. (%d)\n", result);
     return NS_ERROR_FAILURE;
   }
 
-  printf("passed\n");
+  passed("Call PeekUndoStack() with empty undo stack");
 
   /*******************************************************************
    *
    * Call PeekRedoStack() with an empty undo stack:
    *
    *******************************************************************/
 
-  printf("Call PeekRedoStack() with empty undo stack ... ");
-
   tx = 0;
   result = mgr->PeekRedoStack(&tx);
 
   TEST_TXMGR_IF_RELEASE(tx); // Don't hold onto any references!
 
   if (NS_FAILED(result)) {
     printf("ERROR: PeekRedoStack() on empty redo stack failed. (%d)\n", result);
     return result;
   }
 
   if (tx != 0) {
     printf("ERROR: PeekRedoStack() on empty redo stack failed. (%d)\n", result);
     return NS_ERROR_FAILURE;
   }
 
-  printf("passed\n");
+  passed("Call PeekRedoStack() with empty undo stack");
 
   /*******************************************************************
    *
    * Call AddListener() with a null listener pointer:
    *
    *******************************************************************/
 
-  printf("Call AddListener() with null listener ... ");
-
   result = mgr->AddListener(0);
 
   if (result != NS_ERROR_NULL_POINTER) {
     printf("ERROR: AddListener() returned unexpected error. (%d)\n", result);
     return result;
   }
 
-  printf("passed\n");
+  passed("Call AddListener() with null listener");
 
   /*******************************************************************
    *
    * Call RemoveListener() with a null listener pointer:
    *
    *******************************************************************/
 
-  printf("Call RemoveListener() with null listener ... ");
-
   result = mgr->RemoveListener(0);
 
   if (result != NS_ERROR_NULL_POINTER) {
     printf("ERROR: RemoveListener() returned unexpected error. (%d)\n", result);
     return result;
   }
 
-  printf("passed\n");
+  passed("Call RemoveListener() with null listener");
 
   PRInt32 i;
   TestTransaction *tximpl;
   nsITransaction *u1, *u2;
   nsITransaction *r1, *r2;
 
   /*******************************************************************
    *
    * Test coalescing by executing a transaction that can merge any
    * command into itself. Then execute 20 transaction. Afterwards,
    * we should still have the first transaction sitting on the undo
    * stack. Then clear the undo and redo stacks.
    *
    *******************************************************************/
 
-  printf("Test coalescing of transactions ... ");
-
   result = mgr->SetMaxTransactionCount(10);
 
   if (NS_FAILED(result)) {
     printf("ERROR: SetMaxTransactionCount(10) failed. (%d)\n", result);
     return result;
   }
 
 
@@ -1206,27 +1184,25 @@ quick_test(TestTransactionFactory *facto
   }
 
   result = mgr->Clear();
   if (NS_FAILED(result)) {
     printf("ERROR: Clear() failed. (%d)\n", result);
     return result;
   }
 
-  printf("passed\n");
+  passed("Test coalescing of transactions");
 
   /*******************************************************************
    *
    * Execute 20 transactions. Afterwards, we should have 10
    * transactions on the undo stack:
    *
    *******************************************************************/
 
-  printf("Execute 20 transactions ... ");
-
   for (i = 1; i <= 20; i++) {
     tximpl = factory->create(mgr, NONE_FLAG);
 
     if (!tximpl) {
       printf("ERROR: Failed to allocate transaction %d.\n", i);
       return NS_ERROR_OUT_OF_MEMORY;
     }
 
@@ -1270,27 +1246,25 @@ quick_test(TestTransactionFactory *facto
   }
 
   if (numitems != 0) {
     printf("ERROR: GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
            numitems, result);
     return NS_ERROR_FAILURE;
   }
 
-  printf("passed\n");
+  passed("Execute 20 transactions");
 
   /*******************************************************************
    *
    * Execute 20 transient transactions. Afterwards, we should still
    * have the same 10 transactions on the undo stack:
    *
    *******************************************************************/
 
-  printf("Execute 20 transient transactions ... ");
-
   u1 = u2 = r1 = r2 = 0;
 
   result = mgr->PeekUndoStack(&u1);
 
   TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
 
   if (NS_FAILED(result)) {
     printf("ERROR: Initial PeekUndoStack() failed. (%d)\n", result);
@@ -1382,27 +1356,25 @@ quick_test(TestTransactionFactory *facto
   }
 
   if (numitems != 0) {
     printf("ERROR: GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
            numitems, result);
     return NS_ERROR_FAILURE;
   }
 
-  printf("passed\n");
+  passed("Execute 20 transient transactions");
 
   /*******************************************************************
    *
    * Undo 4 transactions. Afterwards, we should have 6 transactions
    * on the undo stack, and 4 on the redo stack:
    *
    *******************************************************************/
 
-  printf("Undo 4 transactions ... ");
-
   for (i = 1; i <= 4; i++) {
     result = mgr->UndoTransaction();
     if (NS_FAILED(result)) {
       printf("ERROR: Failed to undo transaction %d. (%d)\n", i, result);
       return result;
     }
   }
 
@@ -1429,27 +1401,25 @@ quick_test(TestTransactionFactory *facto
   }
 
   if (numitems != 4) {
     printf("ERROR: GetNumberOfRedoItems() expected 4 got %d. (%d)\n",
            numitems, result);
     return NS_ERROR_FAILURE;
   }
 
-  printf("passed\n");
+  passed("Undo 4 transactions");
 
   /*******************************************************************
    *
    * Redo 2 transactions. Afterwards, we should have 8 transactions
    * on the undo stack, and 2 on the redo stack:
    *
    *******************************************************************/
 
-  printf("Redo 2 transactions ... ");
-
   for (i = 1; i <= 2; ++i) {
     result = mgr->RedoTransaction();
     if (NS_FAILED(result)) {
       printf("ERROR: Failed to redo transaction %d. (%d)\n", i, result);
       return result;
     }
   }
 
@@ -1476,26 +1446,24 @@ quick_test(TestTransactionFactory *facto
   }
 
   if (numitems != 2) {
     printf("ERROR: GetNumberOfRedoItems() expected 2 got %d. (%d)\n",
            numitems, result);
     return NS_ERROR_FAILURE;
   }
 
-  printf("passed\n");
+  passed("Redo 2 transactions");
 
   /*******************************************************************
    *
    * Execute a new transaction. The redo stack should get pruned!
    *
    *******************************************************************/
 
-  printf("Check if new transactions prune the redo stack ... ");
-
   tximpl = factory->create(mgr, NONE_FLAG);
 
   if (!tximpl) {
     printf("ERROR: Failed to allocate transaction.\n");
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   tx = 0;
@@ -1538,26 +1506,24 @@ quick_test(TestTransactionFactory *facto
   }
 
   if (numitems != 0) {
     printf("ERROR: GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
            numitems, result);
     return NS_ERROR_FAILURE;
   }
 
-  printf("passed\n");
+  passed("Check if new transactions prune the redo stack");
 
   /*******************************************************************
    *
    * Undo 4 transactions then clear the undo and redo stacks.
    *
    *******************************************************************/
 
-  printf("Undo 4 transactions then clear the undo and redo stacks ... ");
-
   for (i = 1; i <= 4; ++i) {
     result = mgr->UndoTransaction();
     if (NS_FAILED(result)) {
       printf("ERROR: Failed to undo transaction %d. (%d)\n", i, result);
       return result;
     }
   }
 
@@ -1619,26 +1585,24 @@ quick_test(TestTransactionFactory *facto
   }
 
   if (numitems != 0) {
     printf("ERROR: GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
            numitems, result);
     return NS_ERROR_FAILURE;
   }
 
-  printf("passed\n");
+  passed("Undo 4 transactions then clear the undo and redo stacks");
 
   /*******************************************************************
    *
    * Execute 5 transactions.
    *
    *******************************************************************/
 
-  printf("Execute 5 transactions ... ");
-
   for (i = 1; i <= 5; i++) {
     tximpl = factory->create(mgr, NONE_FLAG);
 
     if (!tximpl) {
       printf("ERROR: Failed to allocate transaction %d.\n", i);
       return NS_ERROR_OUT_OF_MEMORY;
     }
 
@@ -1682,26 +1646,24 @@ quick_test(TestTransactionFactory *facto
   }
 
   if (numitems != 0) {
     printf("ERROR: GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
            numitems, result);
     return NS_ERROR_FAILURE;
   }
 
-  printf("passed\n");
+  passed("Execute 5 transactions");
 
   /*******************************************************************
    *
    * Test transaction DoTransaction() error:
    *
    *******************************************************************/
 
-  printf("Test transaction DoTransaction() error ... ");
-
   tximpl = factory->create(mgr, THROWS_DO_ERROR_FLAG);
 
   if (!tximpl) {
     printf("ERROR: Failed to allocate transaction.\n");
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   tx = 0;
@@ -1793,26 +1755,24 @@ quick_test(TestTransactionFactory *facto
   }
 
   if (numitems != 0) {
     printf("ERROR: GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
            numitems, result);
     return NS_ERROR_FAILURE;
   }
 
-  printf("passed\n");
+  passed("Test transaction DoTransaction() error");
 
   /*******************************************************************
    *
    * Test transaction UndoTransaction() error:
    *
    *******************************************************************/
 
-  printf("Test transaction UndoTransaction() error ... ");
-
   tximpl = factory->create(mgr, THROWS_UNDO_ERROR_FLAG);
 
   if (!tximpl) {
     printf("ERROR: Failed to allocate transaction.\n");
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   tx = 0;
@@ -1911,26 +1871,24 @@ quick_test(TestTransactionFactory *facto
   }
 
   if (numitems != 0) {
     printf("ERROR: GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
            numitems, result);
     return NS_ERROR_FAILURE;
   }
 
-  printf("passed\n");
+  passed("Test transaction UndoTransaction() error");
 
   /*******************************************************************
    *
    * Test transaction RedoTransaction() error:
    *
    *******************************************************************/
 
-  printf("Test transaction RedoTransaction() error ... ");
-
   tximpl = factory->create(mgr, THROWS_REDO_ERROR_FLAG);
 
   if (!tximpl) {
     printf("ERROR: Failed to allocate transaction.\n");
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   tx = 0;
@@ -2075,28 +2033,26 @@ quick_test(TestTransactionFactory *facto
   }
 
   if (numitems != 2) {
     printf("ERROR: GetNumberOfRedoItems() expected 2 got %d. (%d)\n",
            numitems, result);
     return NS_ERROR_FAILURE;
   }
 
-  printf("passed\n");
+  passed("Test transaction RedoTransaction() error");
 
   /*******************************************************************
    *
    * Make sure that setting the transaction manager's max transaction
    * count to zero, clears both the undo and redo stacks, and executes
    * all new commands without pushing them on the undo stack!
    *
    *******************************************************************/
 
-  printf("Test max transaction count of zero ... ");
-
   result = mgr->SetMaxTransactionCount(0);
 
   if (NS_FAILED(result)) {
     printf("ERROR: SetMaxTransactionCount(0) failed. (%d)\n", result);
     return result;
   }
 
   result = mgr->GetNumberOfUndoItems(&numitems);
@@ -2175,28 +2131,26 @@ quick_test(TestTransactionFactory *facto
 
     if (numitems != 0) {
       printf("ERROR: GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
              numitems, result);
       return NS_ERROR_FAILURE;
     }
   }
 
-  printf("passed\n");
+  passed("Test max transaction count of zero");
 
   /*******************************************************************
    *
    * Make sure that setting the transaction manager's max transaction
    * count to something greater than the number of transactions on
    * both the undo and redo stacks causes no pruning of the stacks:
    *
    *******************************************************************/
 
-  printf("Test SetMaxTransactionCount() greater than num stack items ... ");
-
   result = mgr->SetMaxTransactionCount(-1);
 
   if (NS_FAILED(result)) {
     printf("ERROR: SetMaxTransactionCount(-1) failed. (%d)\n", result);
     return result;
   }
 
   // Push 20 transactions on the undo stack:
@@ -2368,28 +2322,26 @@ quick_test(TestTransactionFactory *facto
   }
 
   if (numitems != 10) {
     printf("ERROR: GetNumberOfRedoItems() expected 10 got %d. (%d)\n",
            numitems, result);
     return NS_ERROR_FAILURE;
   }
 
-  printf("passed\n");
+  passed("Test SetMaxTransactionCount() greater than num stack items");
 
   /*******************************************************************
    *
    * Test undo stack pruning by setting the transaction
    * manager's max transaction count to a number lower than the
    * number of transactions on both the undo and redo stacks:
    *
    *******************************************************************/
 
-  printf("Test SetMaxTransactionCount() pruning undo stack ... ");
-
   u1 = u2 = r1 = r2 = 0;
 
   result = mgr->PeekUndoStack(&u1);
 
   TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
 
   if (NS_FAILED(result)) {
     printf("ERROR: Initial PeekUndoStack() failed. (%d)\n", result);
@@ -2463,28 +2415,26 @@ quick_test(TestTransactionFactory *facto
   }
 
   if (numitems != 10) {
     printf("ERROR: GetNumberOfRedoItems() expected 10 got %d. (%d)\n",
            numitems, result);
     return NS_ERROR_FAILURE;
   }
 
-  printf("passed\n");
+  passed("Test SetMaxTransactionCount() pruning undo stack");
 
   /*******************************************************************
    *
    * Test redo stack pruning by setting the transaction
    * manager's max transaction count to a number lower than the
    * number of transactions on both the undo and redo stacks:
    *
    *******************************************************************/
 
-  printf("Test SetMaxTransactionCount() pruning redo stack ... ");
-
   u1 = u2 = r1 = r2 = 0;
 
   result = mgr->PeekUndoStack(&u1);
 
   TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
 
   if (NS_FAILED(result)) {
     printf("ERROR: Initial PeekUndoStack() failed. (%d)\n", result);
@@ -2558,27 +2508,25 @@ quick_test(TestTransactionFactory *facto
   }
 
   if (numitems != 5) {
     printf("ERROR: GetNumberOfRedoItems() expected 5 got %d. (%d)\n",
            numitems, result);
     return NS_ERROR_FAILURE;
   }
 
-  printf("passed\n");
+  passed("Test SetMaxTransactionCount() pruning redo stack");
 
   /*******************************************************************
    *
    * Release the transaction manager. Any transactions on the undo
    * and redo stack should automatically be released:
    *
    *******************************************************************/
 
-  printf("Release the transaction manager ... ");
-
   result = mgr->SetMaxTransactionCount(-1);
 
   if (NS_FAILED(result)) {
     printf("ERROR: SetMaxTransactionCount(-1) failed. (%d)\n", result);
     return result;
   }
 
   // Push 20 transactions on the undo stack:
@@ -2673,35 +2621,33 @@ quick_test(TestTransactionFactory *facto
   }
 
   result = mgr->Clear();
   if (NS_FAILED(result)) {
     printf("ERROR: Clear() failed. (%d)\n", result);
     return result;
   }
 
-  printf("passed\n");
+  passed("Release the transaction manager");
 
   /*******************************************************************
    *
    * Make sure number of transactions created matches number of
    * transactions destroyed!
    *
    *******************************************************************/
 
-  printf("Number of transactions created and destroyed match ... ");
-
   if (sConstructorCount != sDestructorCount) {
     printf("ERROR: Transaction constructor count (%d) != destructor count (%d).\n",
            sConstructorCount, sDestructorCount);
     return NS_ERROR_FAILURE;
   }
 
-  printf("passed\n");
-  printf("%d transactions processed during quick test.\n", sConstructorCount);
+  passed("Number of transactions created and destroyed match");
+  passed("%d transactions processed during quick test", sConstructorCount);
 
   return NS_OK;
 }
 
 nsresult
 simple_test()
 {
   /*******************************************************************
@@ -2769,38 +2715,34 @@ quick_batch_test(TestTransactionFactory 
   nsresult result;
 
   /*******************************************************************
    *
    * Create a transaction manager implementation:
    *
    *******************************************************************/
 
-  printf("Create transaction manager instance ... ");
-
   nsCOMPtr<nsITransactionManager> mgr =
     do_CreateInstance(NS_TRANSACTIONMANAGER_CONTRACTID, &result);
   if (NS_FAILED(result) || !mgr) {
     printf("ERROR: Failed to create Transaction Manager instance.\n");
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
-  printf("passed\n");
+  passed("Create transaction manager instance");
 
   PRInt32 numitems;
 
   /*******************************************************************
    *
    * Make sure an unbalanced call to EndBatch() with empty undo stack
    * throws an error!
    *
    *******************************************************************/
 
-  printf("Test unbalanced EndBatch() with empty undo stack ... ");
-
   result = mgr->GetNumberOfUndoItems(&numitems);
 
   if (NS_FAILED(result)) {
     printf("ERROR: GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
            result);
     return result;
   }
 
@@ -2826,28 +2768,25 @@ quick_batch_test(TestTransactionFactory 
   }
 
   if (numitems != 0) {
     printf("ERROR: GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
            numitems, result);
     return NS_ERROR_FAILURE;
   }
 
-  printf("passed\n");
-
+  passed("Test unbalanced EndBatch() with empty undo stack");
 
   /*******************************************************************
    *
    * Make sure that an empty batch is not added to the undo stack
    * when it is closed.
    *
    *******************************************************************/
 
-  printf("Test empty batch ... ");
-
   result = mgr->GetNumberOfUndoItems(&numitems);
 
   if (NS_FAILED(result)) {
     printf("ERROR: GetNumberOfUndoItems() on empty undo stack failed. (%d)\n",
            result);
     return result;
   }
 
@@ -2894,31 +2833,29 @@ quick_batch_test(TestTransactionFactory 
   }
 
   if (numitems != 0) {
     printf("ERROR: GetNumberOfUndoItems() expected 0 got %d. (%d)\n",
            numitems, result);
     return NS_ERROR_FAILURE;
   }
 
-  printf("passed\n");
+  passed("Test empty batch");
 
   PRInt32 i;
   TestTransaction *tximpl;
   nsITransaction *tx;
 
   /*******************************************************************
    *
    * Execute 20 transactions. Afterwards, we should have 1
    * transaction on the undo stack:
    *
    *******************************************************************/
 
-  printf("Execute 20 batched transactions ... ");
-
   result = mgr->BeginBatch();
 
   if (NS_FAILED(result)) {
     printf("ERROR: BeginBatch() failed. (%d)\n", result);
     return result;
   }
 
   for (i = 1; i <= 20; i++) {
@@ -2976,30 +2913,28 @@ quick_batch_test(TestTransactionFactory 
   }
 
   if (numitems != 1) {
     printf("ERROR: GetNumberOfUndoItems() expected 1 got %d. (%d)\n",
            numitems, result);
     return NS_ERROR_FAILURE;
   }
 
-  printf("passed\n");
+  passed("Execute 20 batched transactions");
 
   nsITransaction *u1, *u2;
   nsITransaction *r1, *r2;
 
   /*******************************************************************
    *
    * Execute 20 transient transactions. Afterwards, we should still
    * have the same transaction on the undo stack:
    *
    *******************************************************************/
 
-  printf("Execute 20 batched transient transactions ... ");
-
   u1 = u2 = r1 = r2 = 0;
 
   result = mgr->PeekUndoStack(&u1);
 
   TEST_TXMGR_IF_RELEASE(u1); // Don't hold onto any references!
 
   if (NS_FAILED(result)) {
     printf("ERROR: Initial PeekUndoStack() failed. (%d)\n", result);
@@ -3105,27 +3040,25 @@ quick_batch_test(TestTransactionFactory 
   }
 
   if (numitems != 0) {
     printf("ERROR: GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
            numitems, result);
     return NS_ERROR_FAILURE;
   }
 
-  printf("passed\n");
+  passed("Execute 20 batched transient transactions");
 
   /*******************************************************************
    *
    * Test nested batching. Afterwards, we should have 2 transactions
    * on the undo stack:
    *
    *******************************************************************/
 
-  printf("Test nested batched transactions ... ");
-
   result = mgr->BeginBatch();
 
   if (NS_FAILED(result)) {
     printf("ERROR: BeginBatch() failed. (%d)\n", result);
     return result;
   }
 
   tximpl = factory->create(mgr, NONE_FLAG);
@@ -3280,27 +3213,25 @@ quick_batch_test(TestTransactionFactory 
   }
 
   if (numitems != 2) {
     printf("ERROR: GetNumberOfUndoItems() expected 2 got %d. (%d)\n",
            numitems, result);
     return NS_ERROR_FAILURE;
   }
 
-  printf("passed\n");
+  passed("Test nested batched transactions");
 
   /*******************************************************************
    *
    * Undo 2 batch transactions. Afterwards, we should have 0
    * transactions on the undo stack and 2 on the redo stack.
    *
    *******************************************************************/
 
-  printf("Undo 2 batch transactions ... ");
-
   for (i = 1; i <= 2; ++i) {
     result = mgr->UndoTransaction();
     if (NS_FAILED(result)) {
       printf("ERROR: Failed to undo transaction %d. (%d)\n", i, result);
       return result;
     }
   }
 
@@ -3327,28 +3258,25 @@ quick_batch_test(TestTransactionFactory 
   }
 
   if (numitems != 2) {
     printf("ERROR: GetNumberOfRedoItems() expected 2 got %d. (%d)\n",
            numitems, result);
     return NS_ERROR_FAILURE;
   }
 
-  printf("passed\n");
+  passed("Undo 2 batch transactions");
 
   /*******************************************************************
    *
    * Redo 2 batch transactions. Afterwards, we should have 2
    * transactions on the undo stack and 0 on the redo stack.
    *
    *******************************************************************/
 
-
-  printf("Redo 2 batch transactions ... ");
-
   for (i = 1; i <= 2; ++i) {
     result = mgr->RedoTransaction();
     if (NS_FAILED(result)) {
       printf("ERROR: Failed to undo transaction %d. (%d)\n", i, result);
       return result;
     }
   }
 
@@ -3375,27 +3303,25 @@ quick_batch_test(TestTransactionFactory 
   }
 
   if (numitems != 0) {
     printf("ERROR: GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
            numitems, result);
     return NS_ERROR_FAILURE;
   }
 
-  printf("passed\n");
+  passed("Redo 2 batch transactions");
 
   /*******************************************************************
    *
    * Call undo. Afterwards, we should have 1 transaction
    * on the undo stack, and 1 on the redo stack:
    *
    *******************************************************************/
 
-  printf("Undo a batched transaction that was redone ... ");
-
   result = mgr->UndoTransaction();
 
   if (NS_FAILED(result)) {
     printf("ERROR: Failed to undo transaction. (%d)\n", result);
     return result;
   }
 
   result = mgr->GetNumberOfUndoItems(&numitems);
@@ -3421,27 +3347,25 @@ quick_batch_test(TestTransactionFactory 
   }
 
   if (numitems != 1) {
     printf("ERROR: GetNumberOfRedoItems() expected 1 got %d. (%d)\n",
            numitems, result);
     return NS_ERROR_FAILURE;
   }
 
-  printf("passed\n");
+  passed("Undo a batched transaction that was redone");
 
   /*******************************************************************
    *
    * Make sure an unbalanced call to EndBatch() throws an error and
    * doesn't affect the undo and redo stacks!
    *
    *******************************************************************/
 
-  printf("Test effect of unbalanced EndBatch() on undo and redo stacks ... ");
-
   result = mgr->EndBatch();
 
   if (result != NS_ERROR_FAILURE) {
     printf("ERROR: EndBatch() returned unexpected status. (%d)\n", result);
     return result;
   }
 
   result = mgr->GetNumberOfUndoItems(&numitems);
@@ -3467,28 +3391,26 @@ quick_batch_test(TestTransactionFactory 
   }
 
   if (numitems != 1) {
     printf("ERROR: GetNumberOfRedoItems() expected 1 got %d. (%d)\n",
            numitems, result);
     return NS_ERROR_FAILURE;
   }
 
-  printf("passed\n");
+  passed("Test effect of unbalanced EndBatch() on undo and redo stacks");
 
   /*******************************************************************
    *
    * Make sure that an empty batch is not added to the undo stack
    * when it is closed, and that it does not affect the undo and redo
    * stacks.
    *
    *******************************************************************/
 
-  printf("Test effect of empty batch on undo and redo stacks ... ");
-
   result = mgr->BeginBatch();
 
   if (NS_FAILED(result)) {
     printf("ERROR: BeginBatch() failed. (%d)\n", result);
     return result;
   }
 
   result = mgr->GetNumberOfUndoItems(&numitems);
@@ -3549,28 +3471,24 @@ quick_batch_test(TestTransactionFactory 
   }
 
   if (numitems != 1) {
     printf("ERROR: GetNumberOfRedoItems() expected 1 got %d. (%d)\n",
            numitems, result);
     return NS_ERROR_FAILURE;
   }
 
-
-  printf("passed\n");
-
+  passed("Test effect of empty batch on undo and redo stacks");
 
   /*******************************************************************
    *
    * Execute a new transaction. The redo stack should get pruned!
    *
    *******************************************************************/
 
-  printf("Check if new batched transactions prune the redo stack ... ");
-
   result = mgr->BeginBatch();
 
   if (NS_FAILED(result)) {
     printf("ERROR: BeginBatch() failed. (%d)\n", result);
     return result;
   }
 
   for (i = 1; i <= 20; i++) {
@@ -3656,26 +3574,24 @@ quick_batch_test(TestTransactionFactory 
   }
 
   if (numitems != 0) {
     printf("ERROR: GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
            numitems, result);
     return NS_ERROR_FAILURE;
   }
 
-  printf("passed\n");
+  passed("Check if new batched transactions prune the redo stack");
 
   /*******************************************************************
    *
    * Call undo.
    *
    *******************************************************************/
 
-  printf("Call undo ... ");
-
   // Move a transaction over to the redo stack, so that we have one
   // transaction on the undo stack, and one on the redo stack!
 
   result = mgr->UndoTransaction();
 
   if (NS_FAILED(result)) {
     printf("ERROR: Failed to undo transaction. (%d)\n", result);
     return result;
@@ -3704,27 +3620,24 @@ quick_batch_test(TestTransactionFactory 
   }
 
   if (numitems != 1) {
     printf("ERROR: GetNumberOfRedoItems() expected 1 got %d. (%d)\n",
            numitems, result);
     return NS_ERROR_FAILURE;
   }
 
-  printf("passed\n");
+  passed("Call undo");
 
   /*******************************************************************
    *
    * Test transaction DoTransaction() error:
    *
    *******************************************************************/
 
-  printf("Test transaction DoTransaction() error ... ");
-
-
   tximpl = factory->create(mgr, THROWS_DO_ERROR_FLAG);
 
   if (!tximpl) {
     printf("ERROR: Failed to allocate transaction.\n");
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   tx     = 0;
@@ -3830,26 +3743,24 @@ quick_batch_test(TestTransactionFactory 
   }
 
   if (numitems != 1) {
     printf("ERROR: GetNumberOfRedoItems() expected 1 got %d. (%d)\n",
            numitems, result);
     return NS_ERROR_FAILURE;
   }
 
-  printf("passed\n");
+  passed("Test transaction DoTransaction() error");
 
   /*******************************************************************
    *
    * Test transaction UndoTransaction() error:
    *
    *******************************************************************/
 
-  printf("Test transaction UndoTransaction() error ... ");
-
   tximpl = factory->create(mgr, THROWS_UNDO_ERROR_FLAG);
 
   if (!tximpl) {
     printf("ERROR: Failed to allocate transaction.\n");
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   tx     = 0;
@@ -3962,26 +3873,24 @@ quick_batch_test(TestTransactionFactory 
   }
 
   if (numitems != 0) {
     printf("ERROR: GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
            numitems, result);
     return NS_ERROR_FAILURE;
   }
 
-  printf("passed\n");
+  passed("Test transaction UndoTransaction() error");
 
   /*******************************************************************
    *
    * Test transaction RedoTransaction() error:
    *
    *******************************************************************/
 
-  printf("Test transaction RedoTransaction() error ... ");
-
   tximpl = factory->create(mgr, THROWS_REDO_ERROR_FLAG);
 
   if (!tximpl) {
     printf("ERROR: Failed to allocate transaction.\n");
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   tx     = 0;
@@ -4140,28 +4049,26 @@ quick_batch_test(TestTransactionFactory 
   }
 
   if (numitems != 2) {
     printf("ERROR: GetNumberOfRedoItems() expected 2 got %d. (%d)\n",
            numitems, result);
     return NS_ERROR_FAILURE;
   }
 
-  printf("passed\n");
+  passed("Test transaction RedoTransaction() error");
 
   /*******************************************************************
    *
    * Make sure that setting the transaction manager's max transaction
    * count to zero, clears both the undo and redo stacks, and executes
    * all new commands without pushing them on the undo stack!
    *
    *******************************************************************/
 
-  printf("Test max transaction count of zero ... ");
-
   result = mgr->SetMaxTransactionCount(0);
 
   if (NS_FAILED(result)) {
     printf("ERROR: SetMaxTransactionCount(0) failed. (%d)\n", result);
     return result;
   }
 
   result = mgr->GetNumberOfUndoItems(&numitems);
@@ -4254,27 +4161,25 @@ quick_batch_test(TestTransactionFactory 
 
     if (numitems != 0) {
       printf("ERROR: GetNumberOfRedoItems() expected 0 got %d. (%d)\n",
              numitems, result);
       return NS_ERROR_FAILURE;
     }
   }
 
-  printf("passed\n");
+  passed("Test max transaction count of zero");
 
   /*******************************************************************
    *
    * Release the transaction manager. Any transactions on the undo
    * and redo stack should automatically be released:
    *
    *******************************************************************/
 
-  printf("Release the transaction manager ... ");
-
   result = mgr->SetMaxTransactionCount(-1);
 
   if (NS_FAILED(result)) {
     printf("ERROR: SetMaxTransactionCount(0) failed. (%d)\n", result);
     return result;
   }
 
   // Push 20 transactions on the undo stack:
@@ -4383,35 +4288,33 @@ quick_batch_test(TestTransactionFactory 
   }
 
   result = mgr->Clear();
   if (NS_FAILED(result)) {
     printf("ERROR: Clear() failed. (%d)\n", result);
     return result;
   }
 
-  printf("passed\n");
+  passed("Release the transaction manager");
 
   /*******************************************************************
    *
    * Make sure number of transactions created matches number of
    * transactions destroyed!
    *
    *******************************************************************/
 
-  printf("Number of transactions created and destroyed match ... ");
-
   if (sConstructorCount != sDestructorCount) {
     printf("ERROR: Transaction constructor count (%d) != destructor count (%d).\n",
            sConstructorCount, sDestructorCount);
     return NS_ERROR_FAILURE;
   }
 
-  printf("passed\n");
-  printf("%d transactions processed during quick batch test.\n",
+  passed("Number of transactions created and destroyed match");
+  passed("%d transactions processed during quick batch test",
          sConstructorCount);
 
   return NS_OK;
 }
 
 nsresult
 simple_batch_test()
 {
@@ -4576,31 +4479,31 @@ stress_test(TestTransactionFactory *fact
       }
     }
 
     // Trivial feedback not to let the user think the test is stuck.
     if (NS_UNLIKELY(j % 100 == 0))
       printf("%i ", j);
   } // for, iterations.
 
+  printf("passed\n");
+
   result = mgr->Clear();
   if (NS_FAILED(result)) {
     printf("ERROR: Clear() failed. (%d)\n", result);
     return result;
   }
 
   if (sConstructorCount != sDestructorCount) {
     printf("ERROR: Transaction constructor count (%d) != destructor count (%d).\n",
            sConstructorCount, sDestructorCount);
     return NS_ERROR_FAILURE;
   }
 
-  printf("passed\n");
-
-  printf("%d transactions processed during stress test.\n", sConstructorCount);
+  passed("%d transactions processed during stress test", sConstructorCount);
 
   return NS_OK;
 }
 
 nsresult
 simple_stress_test()
 {
   /*******************************************************************
--- a/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.cpp
+++ b/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.cpp
@@ -80,16 +80,17 @@
 #include "nsIDOMNamedNodeMap.h"
 #include "nsIDOMNodeList.h"
 #include "nsIWebProgressListener.h"
 #include "nsIAuthPrompt.h"
 #include "nsIPrompt.h"
 #include "nsISHEntry.h"
 #include "nsIWebPageDescriptor.h"
 #include "nsIFormControl.h"
+#include "nsContentUtils.h"
 
 #include "nsIDOMNodeFilter.h"
 #include "nsIDOMProcessingInstruction.h"
 #include "nsIDOMHTMLBodyElement.h"
 #include "nsIDOMHTMLTableElement.h"
 #include "nsIDOMHTMLTableRowElement.h"
 #include "nsIDOMHTMLTableCellElement.h"
 #include "nsIDOMHTMLAnchorElement.h"
@@ -2599,108 +2600,54 @@ nsWebBrowserPersist::EnumCleanupUploadLi
     {
         channel->Cancel(NS_BINDING_ABORTED);
     }
     UploadData *data = (UploadData *) aData;
     delete data; // Delete data associated with key
     return true;
 }
 
-
-bool
-nsWebBrowserPersist::GetQuotedAttributeValue(
-    const nsAString &aSource, const nsAString &aAttribute, nsAString &aValue)
-{  
-    // NOTE: This code was lifted verbatim from nsParserUtils.cpp
-    aValue.Truncate();
-    nsAString::const_iterator start, end;
-    aSource.BeginReading(start);
-    aSource.EndReading(end);
-    nsAString::const_iterator iter(end);
-
-    while (start != end) {
-        if (FindInReadable(aAttribute, start, iter))
-        {
-            // walk past any whitespace
-            while (iter != end && nsCRT::IsAsciiSpace(*iter))
-            {
-                ++iter;
-            }
-
-            if (iter == end)
-                break;
-            
-            // valid name="value" pair?
-            if (*iter != '=')
-            {
-                start = iter;
-                iter = end;
-                continue;
-            }
-            // move past the =
-            ++iter;
-
-            while (iter != end && nsCRT::IsAsciiSpace(*iter))
-            {
-                ++iter;
-            }
-
-            if (iter == end)
-                break;
-
-            PRUnichar q = *iter;
-            if (q != '"' && q != '\'')
-            {
-                start = iter;
-                iter = end;
-                continue;
-            }
-
-            // point to the first char of the value
-            ++iter;
-            start = iter;
-            if (FindCharInReadable(q, iter, end))
-            {
-                aValue = Substring(start, iter);
-                return true;
-            }
-
-            // we've run out of string.  Just return...
-            break;
-         }
-    }
-    return false;
-}
-
 nsresult nsWebBrowserPersist::FixupXMLStyleSheetLink(nsIDOMProcessingInstruction *aPI, const nsAString &aHref)
 {
     NS_ENSURE_ARG_POINTER(aPI);
     nsresult rv = NS_OK;
 
     nsAutoString data;
     rv = aPI->GetData(data);
     NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
 
     nsAutoString href;
-    GetQuotedAttributeValue(data, NS_LITERAL_STRING("href"), href);
+    nsContentUtils::GetPseudoAttributeValue(data,
+                                            nsGkAtoms::href,
+                                            href);
 
     // Construct and set a new data value for the xml-stylesheet
     if (!aHref.IsEmpty() && !href.IsEmpty())
     {
         nsAutoString alternate;
         nsAutoString charset;
         nsAutoString title;
         nsAutoString type;
         nsAutoString media;
 
-        GetQuotedAttributeValue(data, NS_LITERAL_STRING("alternate"), alternate);
-        GetQuotedAttributeValue(data, NS_LITERAL_STRING("charset"), charset);
-        GetQuotedAttributeValue(data, NS_LITERAL_STRING("title"), title);
-        GetQuotedAttributeValue(data, NS_LITERAL_STRING("type"), type);
-        GetQuotedAttributeValue(data, NS_LITERAL_STRING("media"), media);
+        nsContentUtils::GetPseudoAttributeValue(data,
+                                                nsGkAtoms::alternate,
+                                                alternate);
+        nsContentUtils::GetPseudoAttributeValue(data,
+                                                nsGkAtoms::charset,
+                                                charset);
+        nsContentUtils::GetPseudoAttributeValue(data,
+                                                nsGkAtoms::title,
+                                                title);
+        nsContentUtils::GetPseudoAttributeValue(data,
+                                                nsGkAtoms::type,
+                                                type);
+        nsContentUtils::GetPseudoAttributeValue(data,
+                                                nsGkAtoms::media,
+                                                media);
 
         NS_NAMED_LITERAL_STRING(kCloseAttr, "\" ");
         nsAutoString newData;
         newData += NS_LITERAL_STRING("href=\"") + aHref + kCloseAttr;
         if (!title.IsEmpty())
         {
             newData += NS_LITERAL_STRING("title=\"") + title + kCloseAttr;
         }
@@ -2731,17 +2678,17 @@ nsresult nsWebBrowserPersist::GetXMLStyl
 {
     NS_ENSURE_ARG_POINTER(aPI);
 
     nsresult rv = NS_OK;
     nsAutoString data;
     rv = aPI->GetData(data);
     NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
 
-    GetQuotedAttributeValue(data, NS_LITERAL_STRING("href"), aHref);
+    nsContentUtils::GetPseudoAttributeValue(data, nsGkAtoms::href, aHref);
 
     return NS_OK;
 }
 
 nsresult nsWebBrowserPersist::OnWalkDOMNode(nsIDOMNode *aNode)
 {
     // Fixup xml-stylesheet processing instructions
     nsCOMPtr<nsIDOMProcessingInstruction> nodeAsPI = do_QueryInterface(aNode);
--- a/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.h
+++ b/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.h
@@ -147,18 +147,16 @@ private:
         URIData **aData = nsnull);
     nsresult StoreURIAttribute(
         nsIDOMNode *aNode, const char *aAttribute,
         bool aNeedsPersisting = true,
         URIData **aData = nsnull)
     {
         return StoreURIAttributeNS(aNode, "", aAttribute, aNeedsPersisting, aData);
     }
-    bool GetQuotedAttributeValue(
-    const nsAString &aSource, const nsAString &aAttribute, nsAString &aValue);
     bool DocumentEncoderExists(const PRUnichar *aContentType);
 
     nsresult GetNodeToFixup(nsIDOMNode *aNodeIn, nsIDOMNode **aNodeOut);
     nsresult FixupURI(nsAString &aURI);
     nsresult FixupNodeAttributeNS(nsIDOMNode *aNode, const char *aNamespaceURI, const char *aAttribute);
     nsresult FixupNodeAttribute(nsIDOMNode *aNode, const char *aAttribute)
     {
         return FixupNodeAttributeNS(aNode, "", aAttribute);
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -55,18 +55,17 @@
 #include "gfxUtils.h"
 
 #include "mozilla/Util.h" // for DebugOnly
 
 namespace mozilla {
 namespace gl {
 
 #ifdef DEBUG
-// see comment near declaration in GLContext.h. Should be thread-local.
-GLContext* GLContext::sCurrentGLContext = nsnull;
+PRUintn GLContext::sCurrentGLContextTLS = -1;
 #endif
 
 PRUint32 GLContext::sDebugMode = 0;
 
 // define this here since it's global to GLContextProvider, not any
 // specific implementation
 const ContextFormat ContextFormat::BasicRGBA32Format(ContextFormat::BasicRGBA32);
 
--- a/gfx/gl/GLContext.h
+++ b/gfx/gl/GLContext.h
@@ -597,19 +597,25 @@ public:
         ContextTypeEGL,
         ContextTypeOSMesa
     };
 
     virtual GLContextType GetContextType() { return ContextTypeUnknown; }
 
     virtual bool MakeCurrentImpl(bool aForce = false) = 0;
 
+#ifdef DEBUG
+    static void StaticInit() {
+        PR_NewThreadPrivateIndex(&sCurrentGLContextTLS, NULL);
+    }
+#endif
+
     bool MakeCurrent(bool aForce = false) {
 #ifdef DEBUG
-        sCurrentGLContext = this;
+        PR_SetThreadPrivate(sCurrentGLContextTLS, this);
 #endif
         return MakeCurrentImpl(aForce);
     }
 
     bool IsContextLost() { return mContextLost; }
 
     virtual bool SetupLookupFunction() = 0;
 
@@ -1500,20 +1506,22 @@ public:
 protected:
 
     ContextFormat mCreationFormat;
     nsRefPtr<GLContext> mSharedContext;
 
     GLContextSymbols mSymbols;
 
 #ifdef DEBUG
-    // this should be thread-local, but that is slightly annoying to implement because on Mac
-    // we don't have any __thread-like keyword. So for now, MOZ_GL_DEBUG assumes (and asserts)
-    // that only the main thread is doing OpenGL calls.
-    static THEBES_API GLContext* sCurrentGLContext;
+    // GLDebugMode will check that we don't send call
+    // to a GLContext that isn't current on the current
+    // thread.
+    // Store the current context when binding to thread local
+    // storage to support DebugMode on an arbitrary thread.
+    static PRUintn sCurrentGLContextTLS;
 #endif
 
     void UpdateActualFormat();
     ContextFormat mActualFormat;
 
     gfxIntSize mOffscreenSize;
     gfxIntSize mOffscreenActualSize;
     GLuint mOffscreenTexture;
@@ -1627,31 +1635,26 @@ public:
 
 protected:
     GLenum mGLError;
 
 public:
 
     void BeforeGLCall(const char* glFunction) {
         if (DebugMode()) {
-            // since the static member variable sCurrentGLContext is not thread-local as it should,
-            // we have to assert that we're in the main thread. Note that sCurrentGLContext is only used
-            // for the OpenGL debug mode.
-            if (!NS_IsMainThread()) {
-                NS_ERROR("OpenGL call from non-main thread. While this is fine in itself, "
-                         "the OpenGL debug mode, which is currently enabled, doesn't support this. "
-                         "It needs to be patched by making GLContext::sCurrentGLContext be thread-local.\n");
-                NS_ABORT();
-            }
+            GLContext *currentGLContext = NULL;
+
+            currentGLContext = (GLContext*)PR_GetThreadPrivate(sCurrentGLContextTLS);
+
             if (DebugMode() & DebugTrace)
                 printf_stderr("[gl:%p] > %s\n", this, glFunction);
-            if (this != sCurrentGLContext) {
+            if (this != currentGLContext) {
                 printf_stderr("Fatal: %s called on non-current context %p. "
                               "The current context for this thread is %p.\n",
-                               glFunction, this, sCurrentGLContext);
+                               glFunction, this, currentGLContext);
                 NS_ABORT();
             }
         }
     }
 
     void AfterGLCall(const char* glFunction) {
         if (DebugMode()) {
             // calling fFinish() immediately after every GL call makes sure that if this GL command crashes,
--- a/gfx/gl/GLContextProviderEGL.cpp
+++ b/gfx/gl/GLContextProviderEGL.cpp
@@ -262,25 +262,16 @@ is_power_of_two(int v)
 
 #define AFTER_GL_CALL do {           \
     AfterGLCall(MOZ_FUNCTION_NAME);  \
 } while (0)
 
 static void BeforeGLCall(const char* glFunction)
 {
     if (GLContext::DebugMode()) {
-        // since the static member variable sCurrentGLContext is not thread-local as it should,
-        // we have to assert that we're in the main thread. Note that sCurrentGLContext is only used
-        // for the OpenGL debug mode.
-        if (!NS_IsMainThread()) {
-            NS_ERROR("OpenGL call from non-main thread. While this is fine in itself, "
-                     "the OpenGL debug mode, which is currently enabled, doesn't support this. "
-                     "It needs to be patched by making GLContext::sCurrentGLContext be thread-local.\n");
-            NS_ABORT();
-        }
         if (GLContext::DebugMode() & GLContext::DebugTrace)
             printf_stderr("[egl] > %s\n", glFunction);
     }
 }
 
 static void AfterGLCall(const char* glFunction)
 {
     if (GLContext::DebugMode() & GLContext::DebugTrace) {
--- a/gfx/layers/d3d10/LayerManagerD3D10.cpp
+++ b/gfx/layers/d3d10/LayerManagerD3D10.cpp
@@ -120,19 +120,19 @@ LayerManagerD3D10::~LayerManagerD3D10()
       delete attachments;
     }
   }
 
   Destroy();
 }
 
 bool
-LayerManagerD3D10::Initialize()
+LayerManagerD3D10::Initialize(bool force)
 {
-  ScopedGfxFeatureReporter reporter("D3D10 Layers");
+  ScopedGfxFeatureReporter reporter("D3D10 Layers", force);
 
   HRESULT hr;
 
   /* Create an Nv3DVUtils instance */
   if (!mNv3DVUtils) {
     mNv3DVUtils = new Nv3DVUtils();
     if (!mNv3DVUtils) {
       NS_WARNING("Could not create a new instance of Nv3DVUtils.\n");
--- a/gfx/layers/d3d10/LayerManagerD3D10.h
+++ b/gfx/layers/d3d10/LayerManagerD3D10.h
@@ -95,17 +95,17 @@ public:
   /*
    * Initializes the layer manager, this is when the layer manager will
    * actually access the device and attempt to create the swap chain used
    * to draw to the window. If this method fails the device cannot be used.
    * This function is not threadsafe.
    *
    * \return True is initialization was succesful, false when it was not.
    */
-  bool Initialize();
+  bool Initialize(bool force = false);
 
   /*
    * LayerManager implementation.
    */
   virtual void Destroy();
 
   virtual ShadowLayerForwarder* AsShadowForwarder()
   { return this; }
--- a/gfx/layers/d3d9/LayerManagerD3D9.cpp
+++ b/gfx/layers/d3d9/LayerManagerD3D9.cpp
@@ -65,19 +65,19 @@ LayerManagerD3D9::LayerManagerD3D9(nsIWi
 }
 
 LayerManagerD3D9::~LayerManagerD3D9()
 {
   Destroy();
 }
 
 bool
-LayerManagerD3D9::Initialize()
+LayerManagerD3D9::Initialize(bool force)
 {
-  ScopedGfxFeatureReporter reporter("D3D9 Layers");
+  ScopedGfxFeatureReporter reporter("D3D9 Layers", force);
 
   /* XXX: this preference and blacklist code should move out of the layer manager */
   bool forceAccelerate =
     Preferences::GetBool("layers.acceleration.force-enabled", false);
 
   nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
   if (gfxInfo) {
     PRInt32 status;
--- a/gfx/layers/d3d9/LayerManagerD3D9.h
+++ b/gfx/layers/d3d9/LayerManagerD3D9.h
@@ -98,17 +98,17 @@ public:
   /*
    * Initializes the layer manager, this is when the layer manager will
    * actually access the device and attempt to create the swap chain used
    * to draw to the window. If this method fails the device cannot be used.
    * This function is not threadsafe.
    *
    * \return True is initialization was succesful, false when it was not.
    */
-  bool Initialize();
+  bool Initialize(bool force = false);
 
   /*
    * Sets the clipping region for this layer manager. This is important on
    * windows because using OGL we no longer have GDI's native clipping. Therefor
    * widget must tell us what part of the screen is being invalidated,
    * and we should clip to this.
    *
    * \param aClippingRegion Region to clip to. Setting an empty region
--- a/gfx/layers/opengl/LayerManagerOGL.cpp
+++ b/gfx/layers/opengl/LayerManagerOGL.cpp
@@ -166,19 +166,19 @@ LayerManagerOGL::CreateContext()
 
   if (!context) {
     NS_WARNING("Failed to create LayerManagerOGL context");
   }
   return context.forget();
 }
 
 bool
-LayerManagerOGL::Initialize(nsRefPtr<GLContext> aContext)
+LayerManagerOGL::Initialize(nsRefPtr<GLContext> aContext, bool force)
 {
-  ScopedGfxFeatureReporter reporter("GL Layers");
+  ScopedGfxFeatureReporter reporter("GL Layers", force);
 
   // Do not allow double intiailization
   NS_ABORT_IF_FALSE(mGLContext == nsnull, "Don't reiniailize layer managers");
 
   if (!aContext)
     return false;
 
   mGLContext = aContext;
--- a/gfx/layers/opengl/LayerManagerOGL.h
+++ b/gfx/layers/opengl/LayerManagerOGL.h
@@ -101,21 +101,21 @@ public:
   /**
    * Initializes the layer manager with a given GLContext. If aContext is null
    * then the layer manager will try to create one for the associated widget.
    *
    * \param aContext an existing GL context to use. Can be created with CreateContext()
    *
    * \return True is initialization was succesful, false when it was not.
    */
-  bool Initialize() {
-    return Initialize(CreateContext());
+  bool Initialize(bool force = false) {
+    return Initialize(CreateContext(), force);
   }
 
-  bool Initialize(nsRefPtr<GLContext> aContext);
+  bool Initialize(nsRefPtr<GLContext> aContext, bool force = false);
 
   /**
    * Sets the clipping region for this layer manager. This is important on 
    * windows because using OGL we no longer have GDI's native clipping. Therefor
    * widget must tell us what part of the screen is being invalidated,
    * and we should clip to this.
    *
    * \param aClippingRegion Region to clip to. Setting an empty region
--- a/gfx/src/gfxCrashReporterUtils.cpp
+++ b/gfx/src/gfxCrashReporterUtils.cpp
@@ -98,20 +98,19 @@ ScopedGfxFeatureReporter::WriteAppNote(c
     if (NS_FAILED(rv)) {
       observer = nsnull;
       return;
     }
     gFeaturesAlreadyReported = new nsTArray<nsCString>;
   }
 
   nsCAutoString featureString;
-  featureString.AppendPrintf("%s%c%c",
+  featureString.AppendPrintf("%s%c ",
                              mFeature,
-                             statusChar,
-                             statusChar == '?' ? ' ' : '\n');
+                             statusChar);
 
   if (!gFeaturesAlreadyReported->Contains(featureString)) {
     gFeaturesAlreadyReported->AppendElement(featureString);
     CrashReporter::AppendAppNotesToCrashReport(featureString);
   }
 }
 
 } // end namespace mozilla
--- a/gfx/src/gfxCrashReporterUtils.h
+++ b/gfx/src/gfxCrashReporterUtils.h
@@ -48,19 +48,20 @@ namespace mozilla {
   *
   * This ScopedGfxFeatureReporter class is designed to be fool-proof to use in functions that
   * have many exit points. We don't want to encourage having function with many exit points.
   * It just happens that our graphics features initialization functions are like that.
   */
 class NS_GFX ScopedGfxFeatureReporter
 {
 public:
-  ScopedGfxFeatureReporter(const char *aFeature) : mFeature(aFeature), mStatusChar('-')
+  ScopedGfxFeatureReporter(const char *aFeature, bool force = false)
+    : mFeature(aFeature), mStatusChar('-')
   {
-    WriteAppNote('?');
+    WriteAppNote(force ? '!' : '?');
   }
   ~ScopedGfxFeatureReporter() {
     WriteAppNote(mStatusChar);
   }
   void SetSuccessful() { mStatusChar = '+'; }
 
 protected:
   const char *mFeature;
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -293,16 +293,20 @@ gfxPlatform::Init()
 #elif defined(XP_OS2)
     gPlatform = new gfxOS2Platform;
 #elif defined(ANDROID)
     gPlatform = new gfxAndroidPlatform;
 #else
     #error "No gfxPlatform implementation available"
 #endif
 
+#ifdef DEBUG
+    mozilla::gl::GLContext::StaticInit();
+#endif
+
     nsresult rv;
 
 #if defined(XP_MACOSX) || defined(XP_WIN) || defined(ANDROID) // temporary, until this is implemented on others
     rv = gfxPlatformFontList::Init();
     if (NS_FAILED(rv)) {
         NS_RUNTIMEABORT("Could not initialize gfxPlatformFontList");
     }
 #endif
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -496,17 +496,17 @@ gfxWindowsPlatform::VerifyD2DDevice(bool
         ID3D10Device1 *device = cairo_d2d_device_get_device(mD2DDevice);
 
         if (SUCCEEDED(device->GetDeviceRemovedReason())) {
             return;
         }
         mD2DDevice = nsnull;
     }
 
-    mozilla::ScopedGfxFeatureReporter reporter("D2D");
+    mozilla::ScopedGfxFeatureReporter reporter("D2D", aAttemptForce);
 
     HMODULE d3d10module = LoadLibraryA("d3d10_1.dll");
     D3D10CreateDevice1Func createD3DDevice = (D3D10CreateDevice1Func)
         GetProcAddress(d3d10module, "D3D10CreateDevice1");
     nsRefPtr<ID3D10Device1> device;
 
     if (createD3DDevice) {
         HMODULE dxgiModule = LoadLibraryA("dxgi.dll");
--- a/js/public/MemoryMetrics.h
+++ b/js/public/MemoryMetrics.h
@@ -123,16 +123,17 @@ struct RuntimeStats
                  DestroyNameCallback destroyNameCb)
       : runtimeObject(0)
       , runtimeAtomsTable(0)
       , runtimeContexts(0)
       , runtimeNormal(0)
       , runtimeTemporary(0)
       , runtimeRegexpCode(0)
       , runtimeStackCommitted(0)
+      , runtimeGCMarker(0)
       , gcHeapChunkTotal(0)
       , gcHeapChunkCleanUnused(0)
       , gcHeapChunkDirtyUnused(0)
       , gcHeapChunkCleanDecommitted(0)
       , gcHeapChunkDirtyDecommitted(0)
       , gcHeapArenaUnused(0)
       , gcHeapChunkAdmin(0)
       , gcHeapUnusedPercentage(0)
@@ -154,16 +155,17 @@ struct RuntimeStats
 
     size_t runtimeObject;
     size_t runtimeAtomsTable;
     size_t runtimeContexts;
     size_t runtimeNormal;
     size_t runtimeTemporary;
     size_t runtimeRegexpCode;
     size_t runtimeStackCommitted;
+    size_t runtimeGCMarker;
     size_t gcHeapChunkTotal;
     size_t gcHeapChunkCleanUnused;
     size_t gcHeapChunkDirtyUnused;
     size_t gcHeapChunkCleanDecommitted;
     size_t gcHeapChunkDirtyDecommitted;
     size_t gcHeapArenaUnused;
     size_t gcHeapChunkAdmin;
     size_t gcHeapUnusedPercentage;
--- a/js/public/Vector.h
+++ b/js/public/Vector.h
@@ -494,16 +494,27 @@ class Vector : private AllocPolicy
      */
     bool insert(T *p, const T &val);
 
     /*
      * Removes the element |t|, which must fall in the bounds [begin, end),
      * shifting existing elements from |t + 1| onward one position lower.
      */
     void erase(T *t);
+
+    /*
+     * Measure the size of the Vector's heap-allocated storage.
+     */
+    size_t sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf) const;
+
+    /* 
+     * Like sizeOfExcludingThis, but also measures the size of the Vector
+     * object (which must be heap-allocated) itself.
+     */
+    size_t sizeOfIncludingThis(JSMallocSizeOfFun mallocSizeOf) const;
 };
 
 /* This does the re-entrancy check plus several other sanity checks. */
 #define REENTRANCY_GUARD_ET_AL \
     ReentrancyGuard g(*this); \
     JS_ASSERT_IF(usingInlineStorage(), mCapacity == sInlineCapacity); \
     JS_ASSERT(reserved() <= mCapacity); \
     JS_ASSERT(mLength <= reserved()); \
@@ -991,15 +1002,29 @@ Vector<T,N,AP>::replaceRawBuffer(T *p, s
         mLength = length;
         mCapacity = length;
     }
 #ifdef DEBUG
     mReserved = length;
 #endif
 }
 
+template <class T, size_t N, class AP>
+inline size_t
+Vector<T,N,AP>::sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf) const
+{
+    return usingInlineStorage() ? 0 : mallocSizeOf(beginNoCheck());
+}
+
+template <class T, size_t N, class AP>
+inline size_t
+Vector<T,N,AP>::sizeOfIncludingThis(JSMallocSizeOfFun mallocSizeOf) const
+{
+    return mallocSizeOf(this) + sizeOfExcludingThis(mallocSizeOf);
+}
+
 }  /* namespace js */
 
 #ifdef _MSC_VER
 #pragma warning(pop)
 #endif
 
 #endif /* jsvector_h_ */
--- a/js/src/MemoryMetrics.cpp
+++ b/js/src/MemoryMetrics.cpp
@@ -218,20 +218,19 @@ CollectRuntimeStats(JSRuntime *rt, Runti
         IterateChunks(cx, rtStats, StatsChunkCallback);
 
         rtStats->runtimeObject = rtStats->mallocSizeOf(rt);
 
         rt->sizeOfExcludingThis(rtStats->mallocSizeOf,
                                 &rtStats->runtimeNormal,
                                 &rtStats->runtimeTemporary,
                                 &rtStats->runtimeRegexpCode,
-                                &rtStats->runtimeStackCommitted);
+                                &rtStats->runtimeStackCommitted,
+                                &rtStats->runtimeGCMarker);
 
-        // Nb: we use sizeOfExcludingThis() because atomState.atoms is within
-        // JSRuntime, and so counted when JSRuntime is counted.
         rtStats->runtimeAtomsTable =
             rt->atomState.atoms.sizeOfExcludingThis(rtStats->mallocSizeOf);
 
         JSContext *acx, *iter = NULL;
         while ((acx = JS_ContextIteratorUnlocked(rt, &iter)) != NULL)
             rtStats->runtimeContexts += acx->sizeOfIncludingThis(rtStats->mallocSizeOf);
     }
 
@@ -342,17 +341,18 @@ GetExplicitNonHeapForRuntime(JSRuntime *
 
         // explicit/runtime/regexp-code
         // explicit/runtime/stack-committed
         size_t regexpCode, stackCommitted;
         rt->sizeOfExcludingThis(mallocSizeOf,
                                 NULL,
                                 NULL,
                                 &regexpCode,
-                                &stackCommitted);
+                                &stackCommitted,
+                                NULL);
 
         *amount += regexpCode;
         *amount += stackCommitted;
     }
 
     JS_DestroyContextNoGC(cx);
 
     return true;
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -238,16 +238,18 @@ UpdateDecomposeLength(BytecodeEmitter *b
     uintN end = bce->offset();
     JS_ASSERT(uintN(end - start) < 256);
     bce->code(start)[-1] = end - start;
 }
 
 ptrdiff_t
 frontend::Emit1(JSContext *cx, BytecodeEmitter *bce, JSOp op)
 {
+    JS_ASSERT_IF(op == JSOP_ARGUMENTS, !bce->mayOverwriteArguments());
+
     ptrdiff_t offset = EmitCheck(cx, bce, 1);
 
     if (offset >= 0) {
         *bce->current->next++ = (jsbytecode)op;
         UpdateDepth(cx, bce, offset);
     }
     return offset;
 }
@@ -978,16 +980,24 @@ EmitSlotObjectOp(JSContext *cx, JSOp op,
 
     jsbytecode *pc = bce->code(off);
     SET_SLOTNO(pc, slot);
     pc += SLOTNO_LEN;
     SET_UINT32_INDEX(pc, index);
     return true;
 }
 
+static bool
+EmitArguments(JSContext *cx, BytecodeEmitter *bce)
+{
+    if (!bce->mayOverwriteArguments())
+        return Emit1(cx, bce, JSOP_ARGUMENTS) >= 0;
+    return EmitAtomOp(cx, cx->runtime->atomState.argumentsAtom, JSOP_NAME, bce);
+}
+
 bool
 BytecodeEmitter::shouldNoteClosedName(ParseNode *pn)
 {
     return !callsEval() && pn->isDefn() && pn->isClosed();
 }
 
 /*
  * Adjust the slot for a block local to account for the number of variables
@@ -1828,17 +1838,20 @@ EmitNameOp(JSContext *cx, BytecodeEmitte
             op = JSOP_CALLFCSLOT;
             break;
           default:
             JS_ASSERT(op == JSOP_ARGUMENTS || op == JSOP_CALLEE);
             break;
         }
     }
 
-    if (op == JSOP_ARGUMENTS || op == JSOP_CALLEE) {
+    if (op == JSOP_ARGUMENTS) {
+        if (!EmitArguments(cx, bce))
+            return JS_FALSE;
+    } else if (op == JSOP_CALLEE) {
         if (Emit1(cx, bce, op) < 0)
             return JS_FALSE;
     } else {
         if (!pn->pn_cookie.isFree()) {
             JS_ASSERT(JOF_OPTYPE(op) != JOF_ATOM);
             EMIT_UINT16_IMM_OP(op, pn->pn_cookie.asInteger());
         } else {
             if (!EmitAtomOp(cx, pn, op, bce))
@@ -3589,17 +3602,17 @@ EmitVariables(JSContext *cx, BytecodeEmi
                                  (pn->isOp(JSOP_DEFCONST))
                                  ? SRC_DECL_CONST
                                  : (pn->isOp(JSOP_DEFVAR))
                                  ? SRC_DECL_VAR
                                  : SRC_DECL_LET) < 0) {
             return JS_FALSE;
         }
         if (op == JSOP_ARGUMENTS) {
-            if (Emit1(cx, bce, op) < 0)
+            if (!EmitArguments(cx, bce))
                 return JS_FALSE;
         } else if (!pn2->pn_cookie.isFree()) {
             EMIT_UINT16_IMM_OP(op, atomIndex);
         } else {
             if (!EmitIndexOp(cx, op, atomIndex, bce))
                 return false;
         }
 
@@ -3700,17 +3713,17 @@ EmitAssignment(JSContext *cx, BytecodeEm
     if (op != JSOP_NOP) {
         JS_ASSERT(rhs);
         switch (lhs->getKind()) {
           case PNK_NAME:
             if (lhs->isConst()) {
                 if (lhs->isOp(JSOP_CALLEE)) {
                     if (Emit1(cx, bce, JSOP_CALLEE) < 0)
                         return false;
-                } else if (lhs->isOp(JSOP_NAME)) {
+                } else if (lhs->isOp(JSOP_NAME) || lhs->isOp(JSOP_GETGNAME)) {
                     if (!EmitIndex32(cx, lhs->getOp(), atomIndex, bce))
                         return false;
                 } else {
                     JS_ASSERT(JOF_OPTYPE(lhs->getOp()) != JOF_ATOM);
                     EMIT_UINT16_IMM_OP(lhs->getOp(), atomIndex);
                 }
             } else if (lhs->isOp(JSOP_SETNAME)) {
                 if (Emit1(cx, bce, JSOP_DUP) < 0)
--- a/js/src/frontend/BytecodeEmitter.h
+++ b/js/src/frontend/BytecodeEmitter.h
@@ -163,31 +163,30 @@ struct StmtInfo {
 
 #define TCF_COMPILING           0x01 /* TreeContext is BytecodeEmitter */
 #define TCF_IN_FUNCTION         0x02 /* parsing inside function body */
 #define TCF_RETURN_EXPR         0x04 /* function has 'return expr;' */
 #define TCF_RETURN_VOID         0x08 /* function has 'return;' */
 #define TCF_IN_FOR_INIT         0x10 /* parsing init expr of for; exclude 'in' */
 #define TCF_FUN_SETS_OUTER_NAME 0x20 /* function set outer name (lexical or free) */
 #define TCF_FUN_PARAM_ARGUMENTS 0x40 /* function has parameter named arguments */
-#define TCF_FUN_USES_ARGUMENTS  0x80 /* function uses arguments except as a
+#define TCF_FUN_LOCAL_ARGUMENTS 0x80 /* function has local named arguments */
+#define TCF_FUN_USES_ARGUMENTS 0x100 /* function uses arguments except as a
                                         parameter name */
-#define TCF_FUN_HEAVYWEIGHT    0x100 /* function needs Call object per call */
-#define TCF_FUN_IS_GENERATOR   0x200 /* parsed yield statement in function */
-#define TCF_FUN_USES_OWN_NAME  0x400 /* named function expression that uses its
+#define TCF_FUN_HEAVYWEIGHT    0x200 /* function needs Call object per call */
+#define TCF_FUN_IS_GENERATOR   0x400 /* parsed yield statement in function */
+#define TCF_FUN_USES_OWN_NAME  0x800 /* named function expression that uses its
                                         own name */
-#define TCF_HAS_FUNCTION_STMT  0x800 /* block contains a function statement */
-#define TCF_GENEXP_LAMBDA     0x1000 /* flag lambda from generator expression */
-#define TCF_COMPILE_N_GO      0x2000 /* compile-and-go mode of script, can
+#define TCF_HAS_FUNCTION_STMT 0x1000 /* block contains a function statement */
+#define TCF_GENEXP_LAMBDA     0x2000 /* flag lambda from generator expression */
+#define TCF_COMPILE_N_GO      0x4000 /* compile-and-go mode of script, can
                                         optimize name references based on scope
                                         chain */
-#define TCF_NO_SCRIPT_RVAL    0x4000 /* API caller does not want result value
+#define TCF_NO_SCRIPT_RVAL    0x8000 /* API caller does not want result value
                                         from global script */
-/* bit 0x8000 is unused */
-
 /*
  * Set when parsing a declaration-like destructuring pattern.  This
  * flag causes PrimaryExpr to create PN_NAME parse nodes for variable
  * references which are not hooked into any definition's use chain,
  * added to any tree context's AtomList, etc. etc.  CheckDestructuring
  * will do that work later.
  *
  * The comments atop CheckDestructuring explain the distinction
@@ -268,16 +267,17 @@ struct StmtInfo {
 #define TCF_RETURN_FLAGS        (TCF_RETURN_EXPR | TCF_RETURN_VOID)
 
 /*
  * Sticky deoptimization flags to propagate from FunctionBody.
  */
 #define TCF_FUN_FLAGS           (TCF_FUN_SETS_OUTER_NAME |                    \
                                  TCF_FUN_USES_ARGUMENTS  |                    \
                                  TCF_FUN_PARAM_ARGUMENTS |                    \
+                                 TCF_FUN_LOCAL_ARGUMENTS |                    \
                                  TCF_FUN_HEAVYWEIGHT     |                    \
                                  TCF_FUN_IS_GENERATOR    |                    \
                                  TCF_FUN_USES_OWN_NAME   |                    \
                                  TCF_FUN_CALLS_EVAL      |                    \
                                  TCF_FUN_MIGHT_ALIAS_LOCALS |                 \
                                  TCF_FUN_MUTATES_PARAMETER |                  \
                                  TCF_STRICT_MODE_CODE    |                    \
                                  TCF_FUN_EXTENSIBLE_SCOPE)
@@ -429,16 +429,25 @@ struct TreeContext {                /* t
         flags |= TCF_FUN_MUTATES_PARAMETER;
     }
 
     bool mutatesParameter() const {
         JS_ASSERT(inFunction());
         return flags & TCF_FUN_MUTATES_PARAMETER;
     }
 
+    bool mayOverwriteArguments() const {
+        JS_ASSERT(inFunction());
+        JS_ASSERT_IF(inStrictMode(),
+                     !(flags & (TCF_FUN_PARAM_ARGUMENTS | TCF_FUN_LOCAL_ARGUMENTS)));
+        return !inStrictMode() &&
+               (callsEval() ||
+                flags & (TCF_FUN_PARAM_ARGUMENTS | TCF_FUN_LOCAL_ARGUMENTS));
+    }
+
     void noteArgumentsNameUse(ParseNode *node) {
         JS_ASSERT(inFunction());
         JS_ASSERT(node->isKind(PNK_NAME));
         JS_ASSERT(node->pn_atom == parser->context->runtime->atomState.argumentsAtom);
         countArgumentsUse(node);
         flags |= TCF_FUN_USES_ARGUMENTS;
         if (funbox)
             funbox->node->pn_dflags |= PND_FUNARG;
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -2426,17 +2426,17 @@ NoteLValue(JSContext *cx, ParseNode *pn,
      * depending on code strictness.  Assignment to arguments is a syntax error
      * in strict mode and thus cannot happen.  Outside strict mode, we optimize
      * away assignment to the function name.  For assignment to function name
      * to fail in strict mode, we must have a binding for it in the scope
      * chain; we ensure this happens by making such functions heavyweight.
      */
     JSAtom *lname = pn->pn_atom;
     if (lname == cx->runtime->atomState.argumentsAtom) {
-        tc->flags |= TCF_FUN_HEAVYWEIGHT;
+        tc->flags |= (TCF_FUN_HEAVYWEIGHT | TCF_FUN_LOCAL_ARGUMENTS);
         tc->countArgumentsUse(pn);
     } else if (tc->inFunction() && lname == tc->fun()->atom) {
         tc->flags |= TCF_FUN_HEAVYWEIGHT;
     }
 }
 
 #if JS_HAS_DESTRUCTURING
 
@@ -2448,17 +2448,17 @@ BindDestructuringVar(JSContext *cx, Bind
     /*
      * Destructuring is a form of assignment, so just as for an initialized
      * simple variable, we must check for assignment to 'arguments' and flag
      * the enclosing function (if any) as heavyweight.
      */
     JS_ASSERT(pn->isKind(PNK_NAME));
     atom = pn->pn_atom;
     if (atom == cx->runtime->atomState.argumentsAtom)
-        tc->flags |= TCF_FUN_HEAVYWEIGHT;
+        tc->flags |= (TCF_FUN_HEAVYWEIGHT | TCF_FUN_LOCAL_ARGUMENTS);
 
     data->pn = pn;
     if (!data->binder(cx, data, atom, tc))
         return JS_FALSE;
 
     /*
      * Select the appropriate name-setting opcode, respecting eager selection
      * done by the data->binder function.
@@ -4419,17 +4419,17 @@ Parser::variables(ParseNodeKind kind, St
             NoteLValue(context, pn2, tc, data.fresh ? PND_INITIALIZED : PND_ASSIGNED);
 
             /* The declarator's position must include the initializer. */
             pn2->pn_pos.end = init->pn_pos.end;
 
             if (tc->inFunction() && name == context->runtime->atomState.argumentsAtom) {
                 tc->noteArgumentsNameUse(pn2);
                 if (!blockObj)
-                    tc->flags |= TCF_FUN_HEAVYWEIGHT;
+                    tc->flags |= (TCF_FUN_HEAVYWEIGHT | TCF_FUN_LOCAL_ARGUMENTS);
             }
         }
     } while (tokenStream.matchToken(TOK_COMMA));
 
     pn->pn_pos.end = pn->last()->pn_pos.end;
     return pn;
 }
 
--- a/js/src/frontend/TokenStream.cpp
+++ b/js/src/frontend/TokenStream.cpp
@@ -173,18 +173,18 @@ TokenStream::init(const jschar *base, si
     version = v;
     xml = VersionHasXML(v);
 
     userbuf.init(base, length);
     linebase = base;
     prevLinebase = NULL;
     sourceMap = NULL;
 
-    JSSourceHandler listener = cx->debugHooks->sourceHandler;
-    void *listenerData = cx->debugHooks->sourceHandlerData;
+    JSSourceHandler listener = cx->runtime->debugHooks.sourceHandler;
+    void *listenerData = cx->runtime->debugHooks.sourceHandlerData;
 
     if (listener)
         listener(fn, ln, base, length, &listenerTSData, listenerData);
 
     /*
      * This table holds all the token kinds that satisfy these properties:
      * - A single char long.
      * - Cannot be a prefix of any longer token (eg. '+' is excluded because
@@ -516,18 +516,18 @@ TokenStream::reportCompileErrorNumberVA(
      * uncaught exception report.
      */
     if (!js_ErrorToException(cx, message, &report, NULL, NULL)) {
         /*
          * If debugErrorHook is present then we give it a chance to veto
          * sending the error on to the regular error reporter.
          */
         bool reportError = true;
-        if (JSDebugErrorHook hook = cx->debugHooks->debugErrorHook)
-            reportError = hook(cx, message, &report, cx->debugHooks->debugErrorHookData);
+        if (JSDebugErrorHook hook = cx->runtime->debugHooks.debugErrorHook)
+            reportError = hook(cx, message, &report, cx->runtime->debugHooks.debugErrorHookData);
 
         /* Report the error */
         if (reportError && cx->errorReporter)
             cx->errorReporter(cx, message, &report);
     }
 
   out:
     if (linebytes)
--- a/js/src/gc/Barrier-inl.h
+++ b/js/src/gc/Barrier-inl.h
@@ -41,58 +41,69 @@
 
 #include "gc/Barrier.h"
 
 #ifndef jsgc_barrier_inl_h___
 #define jsgc_barrier_inl_h___
 
 namespace js {
 
-static JS_ALWAYS_INLINE void
-ClearValueRange(JSCompartment *comp, HeapValue *vec, uintN len, bool useHoles)
+inline void
+EncapsulatedValue::writeBarrierPre(const Value &value)
 {
-    if (useHoles) {
-        for (uintN i = 0; i < len; i++)
-            vec[i].set(comp, MagicValue(JS_ARRAY_HOLE));
-    } else {
-        for (uintN i = 0; i < len; i++)
-            vec[i].set(comp, UndefinedValue());
+#ifdef JSGC_INCREMENTAL
+    if (value.isMarkable()) {
+        js::gc::Cell *cell = (js::gc::Cell *)value.toGCThing();
+        writeBarrierPre(cell->compartment(), value);
     }
+#endif
 }
 
-static JS_ALWAYS_INLINE void
-InitValueRange(HeapValue *vec, uintN len, bool useHoles)
+inline void
+EncapsulatedValue::writeBarrierPre(JSCompartment *comp, const Value &value)
 {
-    if (useHoles) {
-        for (uintN i = 0; i < len; i++)
-            vec[i].init(MagicValue(JS_ARRAY_HOLE));
-    } else {
-        for (uintN i = 0; i < len; i++)
-            vec[i].init(UndefinedValue());
+#ifdef JSGC_INCREMENTAL
+    if (comp->needsBarrier()) {
+        Value tmp(value);
+        js::gc::MarkValueUnbarriered(comp->barrierTracer(), &tmp, "write barrier");
+        JS_ASSERT(tmp == value);
     }
+#endif
 }
 
-static JS_ALWAYS_INLINE void
-DestroyValueRange(HeapValue *vec, uintN len)
+inline void
+EncapsulatedValue::pre()
+{
+    writeBarrierPre(value);
+}
+
+inline void
+EncapsulatedValue::pre(JSCompartment *comp)
 {
-    for (uintN i = 0; i < len; i++)
-        vec[i].~HeapValue();
+    writeBarrierPre(comp, value);
+}
+
+inline
+HeapValue::HeapValue()
+    : EncapsulatedValue(UndefinedValue())
+{
+    post();
 }
 
 inline
 HeapValue::HeapValue(const Value &v)
-    : value(v)
+    : EncapsulatedValue(v)
 {
     JS_ASSERT(!IsPoisonedValue(v));
     post();
 }
 
 inline
 HeapValue::HeapValue(const HeapValue &v)
-    : value(v.value)
+    : EncapsulatedValue(v.value)
 {
     JS_ASSERT(!IsPoisonedValue(v.value));
     post();
 }
 
 inline
 HeapValue::~HeapValue()
 {
@@ -109,71 +120,16 @@ HeapValue::init(const Value &v)
 
 inline void
 HeapValue::init(JSCompartment *comp, const Value &v)
 {
     value = v;
     post(comp);
 }
 
-inline void
-HeapValue::writeBarrierPre(const Value &value)
-{
-#ifdef JSGC_INCREMENTAL
-    if (value.isMarkable()) {
-        js::gc::Cell *cell = (js::gc::Cell *)value.toGCThing();
-        writeBarrierPre(cell->compartment(), value);
-    }
-#endif
-}
-
-inline void
-HeapValue::writeBarrierPost(const Value &value, void *addr)
-{
-}
-
-inline void
-HeapValue::writeBarrierPre(JSCompartment *comp, const Value &value)
-{
-#ifdef JSGC_INCREMENTAL
-    if (comp->needsBarrier()) {
-        Value tmp(value);
-        js::gc::MarkValueUnbarriered(comp->barrierTracer(), &tmp, "write barrier");
-        JS_ASSERT(tmp == value);
-    }
-#endif
-}
-
-inline void
-HeapValue::writeBarrierPost(JSCompartment *comp, const Value &value, void *addr)
-{
-}
-
-inline void
-HeapValue::pre()
-{
-    writeBarrierPre(value);
-}
-
-inline void
-HeapValue::post()
-{
-}
-
-inline void
-HeapValue::pre(JSCompartment *comp)
-{
-    writeBarrierPre(comp, value);
-}
-
-inline void
-HeapValue::post(JSCompartment *comp)
-{
-}
-
 inline HeapValue &
 HeapValue::operator=(const Value &v)
 {
     pre();
     JS_ASSERT(!IsPoisonedValue(v));
     value = v;
     post();
     return *this;
@@ -201,16 +157,119 @@ HeapValue::set(JSCompartment *comp, cons
 #endif
 
     pre(comp);
     JS_ASSERT(!IsPoisonedValue(v));
     value = v;
     post(comp);
 }
 
+inline void
+HeapValue::writeBarrierPost(const Value &value, void *addr)
+{
+}
+
+inline void
+HeapValue::writeBarrierPost(JSCompartment *comp, const Value &value, void *addr)
+{
+}
+
+inline void
+HeapValue::post()
+{
+}
+
+inline void
+HeapValue::post(JSCompartment *comp)
+{
+}
+
+inline
+HeapSlot::HeapSlot(JSObject *obj, uint32_t slot, const Value &v)
+    : EncapsulatedValue(v)
+{
+    JS_ASSERT(!IsPoisonedValue(v));
+    post(obj, slot);
+}
+
+inline
+HeapSlot::HeapSlot(JSObject *obj, uint32_t slot, const HeapSlot &s)
+    : EncapsulatedValue(s.value)
+{
+    JS_ASSERT(!IsPoisonedValue(s.value));
+    post(obj, slot);
+}
+
+inline
+HeapSlot::~HeapSlot()
+{
+    pre();
+}
+
+inline void
+HeapSlot::init(JSObject *obj, uint32_t slot, const Value &v)
+{
+    value = v;
+    post(obj, slot);
+}
+
+inline void
+HeapSlot::init(JSCompartment *comp, JSObject *obj, uint32_t slot, const Value &v)
+{
+    value = v;
+    post(comp, obj, slot);
+}
+
+inline void
+HeapSlot::set(JSObject *obj, uint32_t slot, const Value &v)
+{
+    JS_ASSERT_IF(!obj->isArray(), &obj->getSlotRef(slot) == this);
+    JS_ASSERT_IF(obj->isDenseArray(), &obj->getDenseArrayElement(slot) == (const Value *)this);
+
+    pre();
+    JS_ASSERT(!IsPoisonedValue(v));
+    value = v;
+    post(obj, slot);
+}
+
+inline void
+HeapSlot::set(JSCompartment *comp, JSObject *obj, uint32_t slot, const Value &v)
+{
+    JS_ASSERT_IF(!obj->isArray(), &const_cast<JSObject *>(obj)->getSlotRef(slot) == this);
+    JS_ASSERT_IF(obj->isDenseArray(), &obj->getDenseArrayElement(slot) == (const Value *)this);
+    JS_ASSERT(obj->compartment() == comp);
+
+    pre(comp);
+    JS_ASSERT(!IsPoisonedValue(v));
+    value = v;
+    post(comp, obj, slot);
+}
+
+inline void
+HeapSlot::writeBarrierPost(JSObject *obj, uint32_t slot)
+{
+}
+
+inline void
+HeapSlot::writeBarrierPost(JSCompartment *comp, JSObject *obj, uint32_t slotno)
+{
+}
+
+inline void
+HeapSlot::post(JSObject *owner, uint32_t slot)
+{
+    HeapSlot::writeBarrierPost(owner, slot);
+}
+
+inline void
+HeapSlot::post(JSCompartment *comp, JSObject *owner, uint32_t slot)
+{
+    HeapSlot::writeBarrierPost(comp, owner, slot);
+}
+
 inline
 HeapId::HeapId(jsid id)
     : value(id)
 {
     JS_ASSERT(!IsPoisonedId(id));
     post();
 }
 
--- a/js/src/gc/Barrier.h
+++ b/js/src/gc/Barrier.h
@@ -294,41 +294,34 @@ struct HeapPtrHasher
     static HashNumber hash(Lookup obj) { return DefaultHasher<T *>::hash(obj); }
     static bool match(const Key &k, Lookup l) { return k.get() == l; }
 };
 
 /* Specialized hashing policy for HeapPtrs. */
 template <class T>
 struct DefaultHasher< HeapPtr<T> >: HeapPtrHasher<T> { };
 
-class HeapValue
+class EncapsulatedValue
 {
+  protected:
     Value value;
 
+    /*
+     * Ensure that EncapsulatedValue is not constructable, except by our
+     * implementations.
+     */
+    EncapsulatedValue() MOZ_DELETE;
+    EncapsulatedValue(const EncapsulatedValue &v) MOZ_DELETE;
+    EncapsulatedValue &operator=(const Value &v) MOZ_DELETE;
+    EncapsulatedValue &operator=(const EncapsulatedValue &v) MOZ_DELETE;
+
+    EncapsulatedValue(const Value &v) : value(v) {}
+    ~EncapsulatedValue() {}
+
   public:
-    explicit HeapValue() : value(UndefinedValue()) {}
-    explicit inline HeapValue(const Value &v);
-    explicit inline HeapValue(const HeapValue &v);
-
-    inline ~HeapValue();
-
-    inline void init(const Value &v);
-    inline void init(JSCompartment *comp, const Value &v);
-
-    inline HeapValue &operator=(const Value &v);
-    inline HeapValue &operator=(const HeapValue &v);
-
-    /*
-     * This is a faster version of operator=. Normally, operator= has to
-     * determine the compartment of the value before it can decide whether to do
-     * the barrier. If you already know the compartment, it's faster to pass it
-     * in.
-     */
-    inline void set(JSCompartment *comp, const Value &v);
-
     const Value &get() const { return value; }
     Value *unsafeGet() { return &value; }
     operator const Value &() const { return value; }
 
     bool isUndefined() const { return value.isUndefined(); }
     bool isNull() const { return value.isNull(); }
     bool isBoolean() const { return value.isBoolean(); }
     bool isTrue() const { return value.isTrue(); }
@@ -355,48 +348,103 @@ class HeapValue
 
     uint64_t asRawBits() const { return value.asRawBits(); }
 
 #ifdef DEBUG
     JSWhyMagic whyMagic() const { return value.whyMagic(); }
 #endif
 
     static inline void writeBarrierPre(const Value &v);
-    static inline void writeBarrierPost(const Value &v, void *addr);
+    static inline void writeBarrierPre(JSCompartment *comp, const Value &v);
+
+  protected:
+    inline void pre();
+    inline void pre(JSCompartment *comp);
+};
+
+class HeapValue : public EncapsulatedValue
+{
+  public:
+    explicit inline HeapValue();
+    explicit inline HeapValue(const Value &v);
+    explicit inline HeapValue(const HeapValue &v);
+    inline ~HeapValue();
 
-    static inline void writeBarrierPre(JSCompartment *comp, const Value &v);
+    inline void init(const Value &v);
+    inline void init(JSCompartment *comp, const Value &v);
+
+    inline HeapValue &operator=(const Value &v);
+    inline HeapValue &operator=(const HeapValue &v);
+
+    /*
+     * This is a faster version of operator=. Normally, operator= has to
+     * determine the compartment of the value before it can decide whether to do
+     * the barrier. If you already know the compartment, it's faster to pass it
+     * in.
+     */
+    inline void set(JSCompartment *comp, const Value &v);
+
+    static inline void writeBarrierPost(const Value &v, void *addr);
     static inline void writeBarrierPost(JSCompartment *comp, const Value &v, void *addr);
 
   private:
-    inline void pre();
     inline void post();
+    inline void post(JSCompartment *comp);
+};
+
+class HeapSlot : public EncapsulatedValue
+{
+    /*
+     * Operator= is not valid for HeapSlot because is must take the object and
+     * slot offset to provide to the post/generational barrier.
+     */
+    inline HeapSlot &operator=(const Value &v) MOZ_DELETE;
+    inline HeapSlot &operator=(const HeapValue &v) MOZ_DELETE;
+    inline HeapSlot &operator=(const HeapSlot &v) MOZ_DELETE;
 
-    inline void pre(JSCompartment *comp);
-    inline void post(JSCompartment *comp);
+  public:
+    explicit inline HeapSlot() MOZ_DELETE;
+    explicit inline HeapSlot(JSObject *obj, uint32_t slot, const Value &v);
+    explicit inline HeapSlot(JSObject *obj, uint32_t slot, const HeapSlot &v);
+    inline ~HeapSlot();
+
+    inline void init(JSObject *owner, uint32_t slot, const Value &v);
+    inline void init(JSCompartment *comp, JSObject *owner, uint32_t slot, const Value &v);
+
+    inline void set(JSObject *owner, uint32_t slot, const Value &v);
+    inline void set(JSCompartment *comp, JSObject *owner, uint32_t slot, const Value &v);
+
+    static inline void writeBarrierPost(JSObject *obj, uint32_t slot);
+    static inline void writeBarrierPost(JSCompartment *comp, JSObject *obj, uint32_t slotno);
+
+  private:
+    inline void post(JSObject *owner, uint32_t slot);
+    inline void post(JSCompartment *comp, JSObject *owner, uint32_t slot);
 };
 
 static inline const Value *
-Valueify(const HeapValue *array)
+Valueify(const EncapsulatedValue *array)
 {
-    JS_ASSERT(sizeof(HeapValue) == sizeof(Value));
+    JS_STATIC_ASSERT(sizeof(HeapValue) == sizeof(Value));
+    JS_STATIC_ASSERT(sizeof(HeapSlot) == sizeof(Value));
     return (const Value *)array;
 }
 
-class HeapValueArray
+class HeapSlotArray
 {
-    HeapValue *array;
+    HeapSlot *array;
 
   public:
-    HeapValueArray(HeapValue *array) : array(array) {}
+    HeapSlotArray(HeapSlot *array) : array(array) {}
 
     operator const Value *() const { return Valueify(array); }
-    operator HeapValue *() const { return array; }
+    operator HeapSlot *() const { return array; }
 
-    HeapValueArray operator +(int offset) const { return HeapValueArray(array + offset); }
-    HeapValueArray operator +(uint32_t offset) const { return HeapValueArray(array + offset); }
+    HeapSlotArray operator +(int offset) const { return HeapSlotArray(array + offset); }
+    HeapSlotArray operator +(uint32_t offset) const { return HeapSlotArray(array + offset); }
 };
 
 class HeapId
 {
     jsid value;
 
   public:
     explicit HeapId() : value(JSID_VOID) {}
--- a/js/src/ion/CodeGenerator.cpp
+++ b/js/src/ion/CodeGenerator.cpp
@@ -1532,17 +1532,17 @@ CodeGenerator::visitCallIteratorMore(LCa
 
     return true;
 }
 
 bool
 CodeGenerator::visitCallIteratorEnd(LCallIteratorEnd *lir)
 {
     typedef bool (*pf)(JSContext *, JSObject *);
-    static const VMFunction Info = FunctionInfo<pf>(js_CloseIterator);
+    static const VMFunction Info = FunctionInfo<pf>(CloseIterator);
 
     const Register objReg = ToRegister(lir->getOperand(0));
 
     pushArg(objReg);
     return callVM(Info, lir);
 }
 
 bool
@@ -1940,17 +1940,17 @@ CodeGenerator::visitOutOfLineBindNameCac
     if (!callVM(BindNameCacheInfo, ins))
         return false;
 
     masm.storeCallResult(output);
     restoreLive(ins);
 
     masm.jump(ool->rejoin());
     return true;
-};
+}
 
 ConstantOrRegister
 CodeGenerator::getSetPropertyValue(LInstruction *ins)
 {
     if (ins->getOperand(1)->isConstant()) {
         JS_ASSERT(ins->isSetPropertyCacheT());
         return ConstantOrRegister(*ins->getOperand(1)->toConstant());
     }
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/testOverwrittenArgumentsWithUndefined.js
@@ -0,0 +1,24 @@
+function f() {
+    var a = arguments;
+    eval("assertEq(arguments[0], 42)");
+    eval("assertEq(arguments, a)");
+    arguments = undefined;
+    eval("assertEq(arguments, undefined)");
+    arguments = a;
+    eval("assertEq(arguments[0], 42)");
+    eval("assertEq(arguments, a)");
+}
+f(42);
+
+function f(z) {
+    var a = arguments;
+    eval("assertEq(arguments[0], 42)");
+    eval("assertEq(arguments, a)");
+    arguments = undefined;
+    eval("assertEq(arguments, undefined)");
+    z = 17;
+    eval("assertEq(a[0], 17)");
+    a[0] = 'ponies';
+    eval("assertEq(z, 'ponies')");
+}
+f(42);
--- a/js/src/jsapi-tests/testDebugger.cpp
+++ b/js/src/jsapi-tests/testDebugger.cpp
@@ -105,45 +105,43 @@ BEGIN_TEST(testDebugger_getThisStrict)
 }
 END_TEST(testDebugger_getThisStrict)
 
 bool called = false;
 
 static JSTrapStatus
 ThrowHook(JSContext *cx, JSScript *, jsbytecode *, jsval *rval, void *closure)
 {
+    JS_ASSERT(!closure);
     called = true;
 
     JSObject *global = JS_GetGlobalForScopeChain(cx);
 
     char text[] = "new Error()";
     jsval _;
     JS_EvaluateScript(cx, global, text, strlen(text), "", 0, &_);
 
     return JSTRAP_CONTINUE;
 }
 
 BEGIN_TEST(testDebugger_throwHook)
 {
     uint32_t newopts = JS_GetOptions(cx) | JSOPTION_METHODJIT | JSOPTION_METHODJIT_ALWAYS;
     uint32_t oldopts = JS_SetOptions(cx, newopts);
 
-    JSDebugHooks hooks = { 0 };
-    hooks.throwHook = ThrowHook;
-    JSDebugHooks *old = JS_SetContextDebugHooks(cx, &hooks);
+    CHECK(JS_SetThrowHook(rt, ThrowHook, NULL));
     EXEC("function foo() { throw 3 };\n"
          "for (var i = 0; i < 10; ++i) { \n"
          "  var x = <tag></tag>;\n"
          "  try {\n"
          "    foo(); \n"
          "  } catch(e) {}\n"
          "}\n");
     CHECK(called);
-
-    JS_SetContextDebugHooks(cx, old);
+    CHECK(JS_SetThrowHook(rt, NULL, NULL));
     JS_SetOptions(cx, oldopts);
     return true;
 }
 END_TEST(testDebugger_throwHook)
 
 BEGIN_TEST(testDebugger_debuggerObjectVsDebugMode)
 {
     CHECK(JS_DefineDebuggerObject(cx, global));
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -804,17 +804,17 @@ JSRuntime::JSRuntime()
     ionStackLimit(0),
     ionActivation(NULL),
     ionReturnOverride_(MagicValue(JS_ARG_POISON))
 {
     /* Initialize infallibly first, so we can goto bad and JS_DestroyRuntime. */
     JS_INIT_CLIST(&contextList);
     JS_INIT_CLIST(&debuggerList);
 
-    PodZero(&globalDebugHooks);
+    PodZero(&debugHooks);
     PodZero(&atomState);
 
 #if JS_STACK_GROWTH_DIRECTION > 0
     nativeStackLimit = UINTPTR_MAX;
 #endif
 }
 
 bool
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -1189,17 +1189,17 @@ array_deleteSpecial(JSContext *cx, JSObj
 }
 
 static void
 array_trace(JSTracer *trc, JSObject *obj)
 {
     JS_ASSERT(obj->isDenseArray());
 
     uint32_t initLength = obj->getDenseArrayInitializedLength();
-    MarkValueRange(trc, initLength, obj->getDenseArrayElements(), "element");
+    MarkSlotRange(trc, initLength, obj->getDenseArrayElements(), "element");
 }
 
 static JSBool
 array_fix(JSContext *cx, JSObject *obj, bool *success, AutoIdVector *props)
 {
     JS_ASSERT(obj->isDenseArray());
 
     /*
@@ -1372,29 +1372,30 @@ JSObject::makeDenseArraySlow(JSContext *
     gc::AllocKind kind = getAllocKind();
     Shape *shape = EmptyShape::getInitialShape(cx, &SlowArrayClass, getProto(),
                                                oldShape->getObjectParent(), kind);
     if (!shape)
         return false;
     this->shape_ = shape;
 
     /* Take ownership of the dense elements, reset to an empty dense array. */
-    HeapValue *elems = elements;
+    HeapSlot *elems = elements;
     elements = emptyObjectElements;
 
     /* Root all values in the array during conversion. */
     AutoValueArray autoArray(cx, (Value *) elems, arrayInitialized);
 
     /*
      * Begin with the length property to share more of the property tree.
      * The getter/setter here will directly access the object's private value.
      */
     if (!AddLengthProperty(cx, this)) {
         this->shape_ = oldShape;
-        cx->free_(getElementsHeader());
+        if (elements != emptyObjectElements)
+            cx->free_(getElementsHeader());
         elements = elems;
         return false;
     }
 
     /*
      * Create new properties pointing to existing elements. Pack the array to
      * remove holes, so that shapes use successive slots (as for other objects).
      */
--- a/js/src/jsarrayinlines.h
+++ b/js/src/jsarrayinlines.h
@@ -59,17 +59,22 @@ JSObject::ensureDenseArrayInitializedLen
      * for a write.
      */
     JS_ASSERT(index + extra <= getDenseArrayCapacity());
     uint32_t &initlen = getElementsHeader()->initializedLength;
     if (initlen < index)
         markDenseArrayNotPacked(cx);
 
     if (initlen < index + extra) {
-        js::InitValueRange(elements + initlen, index + extra - initlen, true);
+        JSCompartment *comp = compartment();
+        size_t offset = initlen;
+        for (js::HeapSlot *sp = elements + initlen;
+             sp != elements + (index + extra);
+             sp++, offset++)
+            sp->init(comp, this, offset, js::MagicValue(JS_ARRAY_HOLE));
         initlen = index + extra;
     }
 }
 
 inline JSObject::EnsureDenseResult
 JSObject::ensureDenseArrayElements(JSContext *cx, uintN index, uintN extra)
 {
     JS_ASSERT(isDenseArray());
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -91,17 +91,17 @@
 #include "jscompartment.h"
 #include "jsobjinlines.h"
 
 using namespace js;
 using namespace js::gc;
 
 void
 JSRuntime::sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf, size_t *normal, size_t *temporary,
-                               size_t *regexpCode, size_t *stackCommitted)
+                               size_t *regexpCode, size_t *stackCommitted, size_t *gcMarkerSize)
 {
     if (normal)
         *normal = mallocSizeOf(dtoaState);
 
     if (temporary)
         *temporary = tempLifoAlloc.sizeOfExcludingThis(mallocSizeOf);
 
     if (regexpCode) {
@@ -109,16 +109,19 @@ JSRuntime::sizeOfExcludingThis(JSMallocS
         if (execAlloc_)
             execAlloc_->sizeOfCode(&method, &regexp, &unused);
         JS_ASSERT(method == 0);     /* this execAlloc is only used for regexp code */
         *regexpCode = regexp + unused;
     }
 
     if (stackCommitted)
         *stackCommitted = stackSpace.sizeOfCommitted();
+
+    if (gcMarkerSize)
+        *gcMarkerSize = gcMarker.sizeOfExcludingThis(mallocSizeOf);
 }
 
 JS_FRIEND_API(void)
 JSRuntime::triggerOperationCallback()
 {
     /*
      * Use JS_ATOMIC_SET in the hope that it ensures the write will become
      * immediately visible to other processors polling the flag.
@@ -352,21 +355,19 @@ ReportError(JSContext *cx, const char *m
      * If an exception was raised, then we call the debugErrorHook
      * (if present) to give it a chance to see the error before it
      * propagates out of scope.  This is needed for compatibility
      * with the old scheme.
      */
     if (!JS_IsRunning(cx) ||
         !js_ErrorToException(cx, message, reportp, callback, userRef)) {
         js_ReportErrorAgain(cx, message, reportp);
-    } else if (cx->debugHooks->debugErrorHook && cx->errorReporter) {
-        JSDebugErrorHook hook = cx->debugHooks->debugErrorHook;
-        /* test local in case debugErrorHook changed on another thread */
-        if (hook)
-            hook(cx, message, reportp, cx->debugHooks->debugErrorHookData);
+    } else if (JSDebugErrorHook hook = cx->runtime->debugHooks.debugErrorHook) {
+        if (cx->errorReporter)
+            hook(cx, message, reportp, cx->runtime->debugHooks.debugErrorHookData);
     }
 }
 
 /*
  * The given JSErrorReport object have been zeroed and must not outlive
  * cx->fp() (otherwise report->originPrincipals may become invalid).
  */
 static void
@@ -415,19 +416,19 @@ js_ReportOutOfMemory(JSContext *cx)
     /*
      * If debugErrorHook is present then we give it a chance to veto sending
      * the error on to the regular ErrorReporter. We also clear a pending
      * exception if any now so the hooks can replace the out-of-memory error
      * by a script-catchable exception.
      */
     cx->clearPendingException();
     if (onError) {
-        JSDebugErrorHook hook = cx->debugHooks->debugErrorHook;
+        JSDebugErrorHook hook = cx->runtime->debugHooks.debugErrorHook;
         if (hook &&
-            !hook(cx, msg, &report, cx->debugHooks->debugErrorHookData)) {
+            !hook(cx, msg, &report, cx->runtime->debugHooks.debugErrorHookData)) {
             onError = NULL;
         }
     }
 
     if (onError) {
         AutoAtomicIncrement incr(&cx->runtime->inOOMReport);
         onError(cx, msg, &report);
     }
@@ -747,22 +748,19 @@ js_ReportErrorAgain(JSContext *cx, const
         return;
     onError = cx->errorReporter;
 
     /*
      * If debugErrorHook is present then we give it a chance to veto
      * sending the error on to the regular ErrorReporter.
      */
     if (onError) {
-        JSDebugErrorHook hook = cx->debugHooks->debugErrorHook;
-        if (hook &&
-            !hook(cx, cx->lastMessage, reportp,
-                  cx->debugHooks->debugErrorHookData)) {
+        JSDebugErrorHook hook = cx->runtime->debugHooks.debugErrorHook;
+        if (hook && !hook(cx, cx->lastMessage, reportp, cx->runtime->debugHooks.debugErrorHookData))
             onError = NULL;
-        }
     }
     if (onError)
         onError(cx, cx->lastMessage, reportp);
 }
 
 void
 js_ReportIsNotDefined(JSContext *cx, const char *name)
 {
@@ -977,17 +975,16 @@ JSContext::JSContext(JSRuntime *rt)
     errorReporter(NULL),
     operationCallback(NULL),
     data(NULL),
     data2(NULL),
 #ifdef JS_THREADSAFE
     outstandingRequests(0),
 #endif
     autoGCRooters(NULL),
-    debugHooks(&rt->globalDebugHooks),
     securityCallbacks(NULL),
     resolveFlags(0),
     rngSeed(0),
     iterValue(MagicValue(JS_NO_ITER_VALUE)),
 #ifdef JS_METHODJIT
     methodJitEnabled(false),
 #endif
     inferenceEnabled(false),
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -474,17 +474,17 @@ struct JSRuntime : js::RuntimeFriendFiel
     /* List of active contexts sharing this runtime. */
     JSCList             contextList;
 
     bool hasContexts() const {
         return !JS_CLIST_IS_EMPTY(&contextList);
     }
 
     /* Per runtime debug hooks -- see jsprvtd.h and jsdbgapi.h. */
-    JSDebugHooks        globalDebugHooks;
+    JSDebugHooks        debugHooks;
 
     /* If true, new compartments are initially in debug mode. */
     bool                debugMode;
 
     /* If true, new scripts must be created with PC counter information. */
     bool                profilingScripts;
 
     /* Had an out-of-memory error which did not populate an exception. */
@@ -726,17 +726,17 @@ struct JSRuntime : js::RuntimeFriendFiel
     JS_FRIEND_API(void) triggerOperationCallback();
 
     void setJitHardening(bool enabled);
     bool getJitHardening() const {
         return jitHardening;
     }
 
     void sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf, size_t *normal, size_t *temporary,
-                             size_t *regexpCode, size_t *stackCommitted);
+                             size_t *regexpCode, size_t *stackCommitted, size_t *gcMarker);
 
     void purge(JSContext *cx);
 };
 
 /* Common macros to access thread-local caches in JSRuntime. */
 #define JS_PROPERTY_CACHE(cx)   (cx->runtime->propertyCache)
 
 #define JS_KEEP_ATOMS(rt)   (rt)->gcKeepAtoms++;
@@ -751,18 +751,16 @@ struct JSRuntime : js::RuntimeFriendFiel
 struct JSArgumentFormatMap {
     const char          *format;
     size_t              length;
     JSArgumentFormatter formatter;
     JSArgumentFormatMap *next;
 };
 #endif
 
-extern const JSDebugHooks js_NullDebugHooks;  /* defined in jsdbgapi.cpp */
-
 namespace js {
 
 template <typename T> class Root;
 class CheckRoot;
 
 struct AutoResolving;
 
 static inline bool
@@ -1052,19 +1050,16 @@ struct JSContext : js::ContextFriendFiel
      * location as holding a relocatable pointer, but have no other effect on
      * GC behavior.
      */
     js::CheckRoot *checkGCRooters;
 #endif
 
 #endif /* JSGC_ROOT_ANALYSIS */
 
-    /* Debug hooks associated with the current context. */
-    const JSDebugHooks  *debugHooks;
-
     /* Security callbacks that override any defined on the runtime. */
     JSSecurityCallbacks *securityCallbacks;
 
     /* Stored here to avoid passing it around as a parameter. */
     uintN               resolveFlags;
 
     /* Random number generator state, used by jsmath.cpp. */
     int64_t             rngSeed;
--- a/js/src/jsdbgapi.cpp
+++ b/js/src/jsdbgapi.cpp
@@ -108,21 +108,21 @@ JS_SetRuntimeDebugMode(JSRuntime *rt, JS
 namespace js {
 
 JSTrapStatus
 ScriptDebugPrologue(JSContext *cx, StackFrame *fp)
 {
     JS_ASSERT(fp == cx->fp());
 
     if (fp->isFramePushedByExecute()) {
-        if (JSInterpreterHook hook = cx->debugHooks->executeHook)
-            fp->setHookData(hook(cx, Jsvalify(fp), true, 0, cx->debugHooks->executeHookData));
+        if (JSInterpreterHook hook = cx->runtime->debugHooks.executeHook)
+            fp->setHookData(hook(cx, Jsvalify(fp), true, 0, cx->runtime->debugHooks.executeHookData));
     } else {
-        if (JSInterpreterHook hook = cx->debugHooks->callHook)
-            fp->setHookData(hook(cx, Jsvalify(fp), true, 0, cx->debugHooks->callHookData));
+        if (JSInterpreterHook hook = cx->runtime->debugHooks.callHook)
+            fp->setHookData(hook(cx, Jsvalify(fp), true, 0, cx->runtime->debugHooks.callHookData));
     }
 
     Value rval;
     JSTrapStatus status = Debugger::onEnterFrame(cx, &rval);
     switch (status) {
       case JSTRAP_CONTINUE:
         break;
       case JSTRAP_THROW:
@@ -143,20 +143,20 @@ ScriptDebugPrologue(JSContext *cx, Stack
 bool
 ScriptDebugEpilogue(JSContext *cx, StackFrame *fp, bool okArg)
 {
     JS_ASSERT(fp == cx->fp());
     JSBool ok = okArg;
 
     if (void *hookData = fp->maybeHookData()) {
         if (fp->isFramePushedByExecute()) {
-            if (JSInterpreterHook hook = cx->debugHooks->executeHook)
+            if (JSInterpreterHook hook = cx->runtime->debugHooks.executeHook)
                 hook(cx, Jsvalify(fp), false, &ok, hookData);
         } else {
-            if (JSInterpreterHook hook = cx->debugHooks->callHook)
+            if (JSInterpreterHook hook = cx->runtime->debugHooks.callHook)
                 hook(cx, Jsvalify(fp), false, &ok, hookData);
         }
     }
     Debugger::onLeaveFrame(cx);
 
     return ok;
 }
 
@@ -233,30 +233,30 @@ JS_PUBLIC_API(void)
 JS_ClearAllTrapsForCompartment(JSContext *cx)
 {
     cx->compartment->clearTraps(cx);
 }
 
 JS_PUBLIC_API(JSBool)
 JS_SetInterrupt(JSRuntime *rt, JSInterruptHook hook, void *closure)
 {
-    rt->globalDebugHooks.interruptHook = hook;
-    rt->globalDebugHooks.interruptHookData = closure;
+    rt->debugHooks.interruptHook = hook;
+    rt->debugHooks.interruptHookData = closure;
     return JS_TRUE;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_ClearInterrupt(JSRuntime *rt, JSInterruptHook *hoop, void **closurep)
 {
     if (hoop)
-        *hoop = rt->globalDebugHooks.interruptHook;
+        *hoop = rt->debugHooks.interruptHook;
     if (closurep)
-        *closurep = rt->globalDebugHooks.interruptHookData;
-    rt->globalDebugHooks.interruptHook = 0;
-    rt->globalDebugHooks.interruptHookData = 0;
+        *closurep = rt->debugHooks.interruptHookData;
+    rt->debugHooks.interruptHook = 0;
+    rt->debugHooks.interruptHookData = 0;
     return JS_TRUE;
 }
 
 /************************************************************************/
 
 JS_PUBLIC_API(JSBool)
 JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsid id,
                  JSWatchPointHandler handler, JSObject *closure)
@@ -584,17 +584,17 @@ JS_GetFrameCallObject(JSContext *cx, JSS
     if (!ac.enter())
         return NULL;
 
     /*
      * XXX ill-defined: null return here means error was reported, unlike a
      *     null returned above or in the #else
      */
     if (!fp->hasCallObj() && fp->isNonEvalFunctionFrame())
-        return CreateFunCallObject(cx, fp);
+        return CallObject::createForFunction(cx, fp);
     return &fp->callObj();
 }
 
 JS_PUBLIC_API(JSBool)
 JS_GetFrameThis(JSContext *cx, JSStackFrame *fpArg, jsval *thisv)
 {
     StackFrame *fp = Valueify(fpArg);
     if (fp->isDummyFrame())
@@ -723,26 +723,26 @@ JS_GetScriptVersion(JSContext *cx, JSScr
     return VersionNumber(script->getVersion());
 }
 
 /***************************************************************************/
 
 JS_PUBLIC_API(void)
 JS_SetNewScriptHook(JSRuntime *rt, JSNewScriptHook hook, void *callerdata)
 {
-    rt->globalDebugHooks.newScriptHook = hook;
-    rt->globalDebugHooks.newScriptHookData = callerdata;
+    rt->debugHooks.newScriptHook = hook;
+    rt->debugHooks.newScriptHookData = callerdata;
 }
 
 JS_PUBLIC_API(void)
 JS_SetDestroyScriptHook(JSRuntime *rt, JSDestroyScriptHook hook,
                         void *callerdata)
 {
-    rt->globalDebugHooks.destroyScriptHook = hook;
-    rt->globalDebugHooks.destroyScriptHookData = callerdata;
+    rt->debugHooks.destroyScriptHook = hook;
+    rt->debugHooks.destroyScriptHookData = callerdata;
 }
 
 /***************************************************************************/
 
 JS_PUBLIC_API(JSBool)
 JS_EvaluateUCInStackFrame(JSContext *cx, JSStackFrame *fpArg,
                           const jschar *chars, uintN length,
                           const char *filename, uintN lineno,
@@ -839,20 +839,20 @@ JS_GetPropertyDesc(JSContext *cx, JSObje
 
     if (wasThrowing)
         cx->setPendingException(lastException);
 
     pd->flags |= (shape->enumerable() ? JSPD_ENUMERATE : 0)
               |  (!shape->writable()  ? JSPD_READONLY  : 0)
               |  (!shape->configurable() ? JSPD_PERMANENT : 0);
     pd->spare = 0;
-    if (shape->getter() == GetCallArg) {
+    if (shape->getter() == CallObject::getArgOp) {
         pd->slot = shape->shortid();
         pd->flags |= JSPD_ARGUMENT;
-    } else if (shape->getter() == GetCallVar) {
+    } else if (shape->getter() == CallObject::getVarOp) {
         pd->slot = shape->shortid();
         pd->flags |= JSPD_VARIABLE;
     } else {
         pd->slot = 0;
     }
     pd->alias = JSVAL_VOID;
 
     return JS_TRUE;
@@ -923,58 +923,58 @@ JS_PutPropertyDescArray(JSContext *cx, J
     cx->free_(pd);
 }
 
 /************************************************************************/
 
 JS_PUBLIC_API(JSBool)
 JS_SetDebuggerHandler(JSRuntime *rt, JSDebuggerHandler handler, void *closure)
 {
-    rt->globalDebugHooks.debuggerHandler = handler;
-    rt->globalDebugHooks.debuggerHandlerData = closure;
+    rt->debugHooks.debuggerHandler = handler;
+    rt->debugHooks.debuggerHandlerData = closure;
     return JS_TRUE;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_SetSourceHandler(JSRuntime *rt, JSSourceHandler handler, void *closure)
 {
-    rt->globalDebugHooks.sourceHandler = handler;
-    rt->globalDebugHooks.sourceHandlerData = closure;
+    rt->debugHooks.sourceHandler = handler;
+    rt->debugHooks.sourceHandlerData = closure;
     return JS_TRUE;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_SetExecuteHook(JSRuntime *rt, JSInterpreterHook hook, void *closure)
 {
-    rt->globalDebugHooks.executeHook = hook;
-    rt->globalDebugHooks.executeHookData = closure;
+    rt->debugHooks.executeHook = hook;
+    rt->debugHooks.executeHookData = closure;
     return JS_TRUE;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_SetCallHook(JSRuntime *rt, JSInterpreterHook hook, void *closure)
 {
-    rt->globalDebugHooks.callHook = hook;
-    rt->globalDebugHooks.callHookData = closure;
+    rt->debugHooks.callHook = hook;
+    rt->debugHooks.callHookData = closure;
     return JS_TRUE;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_SetThrowHook(JSRuntime *rt, JSThrowHook hook, void *closure)
 {
-    rt->globalDebugHooks.throwHook = hook;
-    rt->globalDebugHooks.throwHookData = closure;
+    rt->debugHooks.throwHook = hook;
+    rt->debugHooks.throwHookData = closure;
     return JS_TRUE;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_SetDebugErrorHook(JSRuntime *rt, JSDebugErrorHook hook, void *closure)
 {
-    rt->globalDebugHooks.debugErrorHook = hook;
-    rt->globalDebugHooks.debugErrorHookData = closure;
+    rt->debugHooks.debugErrorHook = hook;
+    rt->debugHooks.debugErrorHookData = closure;
     return JS_TRUE;
 }
 
 /************************************************************************/
 
 JS_PUBLIC_API(size_t)
 JS_GetObjectTotalSize(JSContext *cx, JSObject *obj)
 {
@@ -1081,35 +1081,17 @@ JS_FRIEND_API(void)
 js_RevertVersion(JSContext *cx)
 {
     cx->clearVersionOverride();
 }
 
 JS_PUBLIC_API(const JSDebugHooks *)
 JS_GetGlobalDebugHooks(JSRuntime *rt)
 {
-    return &rt->globalDebugHooks;
-}
-
-const JSDebugHooks js_NullDebugHooks = {};
-
-JS_PUBLIC_API(JSDebugHooks *)
-JS_SetContextDebugHooks(JSContext *cx, const JSDebugHooks *hooks)
-{
-    JS_ASSERT(hooks);
-
-    JSDebugHooks *old = const_cast<JSDebugHooks *>(cx->debugHooks);
-    cx->debugHooks = hooks;
-    return old;
-}
-
-JS_PUBLIC_API(JSDebugHooks *)
-JS_ClearContextDebugHooks(JSContext *cx)
-{
-    return JS_SetContextDebugHooks(cx, &js_NullDebugHooks);
+    return &rt->debugHooks;
 }
 
 /************************************************************************/
 
 /* Profiling-related API */
 
 /* Thread-unsafe error management */
 
--- a/js/src/jsdbgapi.h
+++ b/js/src/jsdbgapi.h
@@ -472,23 +472,16 @@ JS_MakeSystemObject(JSContext *cx, JSObj
 /************************************************************************/
 
 extern JS_FRIEND_API(void)
 js_RevertVersion(JSContext *cx);
 
 extern JS_PUBLIC_API(const JSDebugHooks *)
 JS_GetGlobalDebugHooks(JSRuntime *rt);
 
-extern JS_PUBLIC_API(JSDebugHooks *)
-JS_SetContextDebugHooks(JSContext *cx, const JSDebugHooks *hooks);
-
-/* Disable debug hooks for this context. */
-extern JS_PUBLIC_API(JSDebugHooks *)
-JS_ClearContextDebugHooks(JSContext *cx);
-
 /**
  * Start any profilers that are available and have been configured on for this
  * platform. This is NOT thread safe.
  *
  * The profileName is used by some profilers to describe the current profiling
  * run. It may be used for part of the filename of the output, but the
  * specifics depend on the profiler. Many profilers will ignore it. Passing in
  * NULL is legal; some profilers may use it to output to stdout or similar.
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -586,27 +586,27 @@ VersionSetXML(JSVersion version, bool en
 {
     return enable ? JSVersion(uint32_t(version) | VersionFlags::HAS_XML)
                   : JSVersion(uint32_t(version) & ~VersionFlags::HAS_XML);
 }
 
 JS_FRIEND_API(bool)
 CanCallContextDebugHandler(JSContext *cx)
 {
-    return cx->debugHooks && cx->debugHooks->debuggerHandler;
+    return !!cx->runtime->debugHooks.debuggerHandler;
 }
 
 JS_FRIEND_API(JSTrapStatus)
 CallContextDebugHandler(JSContext *cx, JSScript *script, jsbytecode *bc, Value *rval)
 {
-    if (!CanCallContextDebugHandler(cx))
+    if (!cx->runtime->debugHooks.debuggerHandler)
         return JSTRAP_RETURN;
 
-    return cx->debugHooks->debuggerHandler(cx, script, bc, rval,
-                                           cx->debugHooks->debuggerHandlerData);
+    return cx->runtime->debugHooks.debuggerHandler(cx, script, bc, rval,
+                                                   cx->runtime->debugHooks.debuggerHandlerData);
 }
 
 #ifdef JS_THREADSAFE
 void *
 GetOwnerThread(const JSContext *cx)
 {
     return cx->runtime->ownerThread();
 }
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -96,31 +96,16 @@
 #include "vm/ScopeObject-inl.h"
 #include "vm/Stack-inl.h"
 
 using namespace mozilla;
 using namespace js;
 using namespace js::gc;
 using namespace js::types;
 
-JSBool
-js_GetArgsValue(JSContext *cx, StackFrame *fp, Value *vp)
-{
-    JSObject *argsobj;
-    if (fp->hasOverriddenArgs()) {
-        JS_ASSERT(fp->hasCallObj());
-        return fp->callObj().getProperty(cx, cx->runtime->atomState.argumentsAtom, vp);
-    }
-    argsobj = js_GetArgsObject(cx, fp);
-    if (!argsobj)
-        return JS_FALSE;
-    vp->setObject(*argsobj);
-    return JS_TRUE;
-}
-
 js::ArgumentsObject *
 ArgumentsObject::create(JSContext *cx, uint32_t argc, JSObject &callee)
 {
     JS_ASSERT(argc <= StackSpace::ARGS_LENGTH_MAX);
 
     JSObject *proto = callee.global().getOrCreateObjectPrototype(cx);
     if (!proto)
         return NULL;
@@ -143,17 +128,18 @@ ArgumentsObject::create(JSContext *cx, u
         return NULL;
 
     ArgumentsData *data = (ArgumentsData *)
         cx->malloc_(offsetof(ArgumentsData, slots) + argc * sizeof(Value));
     if (!data)
         return NULL;
 
     data->callee.init(ObjectValue(callee));
-    InitValueRange(data->slots, argc, false);
+    for (HeapValue *vp = data->slots; vp != data->slots + argc; vp++)
+        vp->init(UndefinedValue());
 
     /* We have everything needed to fill in the object, so make the object. */
     JSObject *obj = JSObject::create(cx, FINALIZE_KIND, emptyArgumentsShape, type, NULL);
     if (!obj)
         return NULL;
 
     ArgumentsObject &argsobj = obj->asArguments();
 
@@ -177,17 +163,17 @@ struct STATIC_SKIP_INFERENCE PutArg
         JS_ASSERT(dst->isMagic(JS_ARGS_HOLE) || dst->isUndefined());
         if (!dst->isMagic(JS_ARGS_HOLE))
             dst->set(compartment, *src);
         ++dst;
         return true;
     }
 };
 
-JSObject *
+ArgumentsObject *
 js_GetArgsObject(JSContext *cx, StackFrame *fp)
 {
     /*
      * Arguments and Call objects are owned by the enclosing non-eval function
      * frame, thus any eval frames must be skipped before testing hasArgsObj.
      */
     JS_ASSERT(fp->isFunctionFrame());
     while (fp->isEvalInFunction())
@@ -608,360 +594,16 @@ Class js::StrictArgumentsObjectClass = {
         NULL,       /* outerObject */
         NULL,       /* innerObject */
         JS_ElementIteratorStub,
         NULL,       /* unused      */
         false,      /* isWrappedNative */
     }
 };
 
-namespace js {
-
-CallObject *
-CreateFunCallObject(JSContext *cx, StackFrame *fp)
-{
-    JS_ASSERT(fp->isNonEvalFunctionFrame());
-    JS_ASSERT(!fp->hasCallObj());
-
-    JSObject *scopeChain = &fp->scopeChain();
-    JS_ASSERT_IF(scopeChain->isWith() || scopeChain->isBlock() || scopeChain->isCall(),
-                 scopeChain->getPrivate() != fp);
-
-    /*
-     * For a named function expression Call's parent points to an environment
-     * object holding function's name.
-     */
-    if (JSAtom *lambdaName = CallObjectLambdaName(fp->fun())) {
-        scopeChain = DeclEnvObject::create(cx, fp);
-        if (!scopeChain)
-            return NULL;
-
-        if (!DefineNativeProperty(cx, scopeChain, ATOM_TO_JSID(lambdaName),
-                                  ObjectValue(fp->callee()), NULL, NULL,
-                                  JSPROP_PERMANENT | JSPROP_READONLY, 0, 0)) {
-            return NULL;
-        }
-    }
-
-    CallObject *callobj = CallObject::create(cx, fp->script(), *scopeChain, &fp->callee());
-    if (!callobj)
-        return NULL;
-
-    callobj->setStackFrame(fp);
-    fp->setScopeChainWithOwnCallObj(*callobj);
-    return callobj;
-}
-
-CallObject *
-CreateEvalCallObject(JSContext *cx, StackFrame *fp)
-{
-    CallObject *callobj = CallObject::create(cx, fp->script(), fp->scopeChain(), NULL);
-    if (!callobj)
-        return NULL;
-
-    callobj->setStackFrame(fp);
-    fp->setScopeChainWithOwnCallObj(*callobj);
-    return callobj;
-}
-
-} // namespace js
-
-void
-js_PutCallObject(StackFrame *fp)
-{
-    CallObject &callobj = fp->callObj().asCall();
-    JS_ASSERT(callobj.maybeStackFrame() == fp);
-    JS_ASSERT_IF(fp->isEvalFrame(), fp->isStrictEvalFrame());
-    JS_ASSERT(fp->isEvalFrame() == callobj.isForEval());
-
-    /* Get the arguments object to snapshot fp's actual argument values. */
-    if (fp->hasArgsObj()) {
-        if (!fp->hasOverriddenArgs())
-            callobj.initArguments(ObjectValue(fp->argsObj()));
-        js_PutArgsObject(fp);
-    }
-
-    JSScript *script = fp->script();
-    Bindings &bindings = script->bindings;
-
-    if (callobj.isForEval()) {
-        JS_ASSERT(script->strictModeCode);
-        JS_ASSERT(bindings.countArgs() == 0);
-
-        /* This could be optimized as below, but keep it simple for now. */
-        callobj.copyValues(0, NULL, bindings.countVars(), fp->slots());
-    } else {
-        JSFunction *fun = fp->fun();
-        JS_ASSERT(script == callobj.getCalleeFunction()->script());
-        JS_ASSERT(script == fun->script());
-
-        uintN n = bindings.countArgsAndVars();
-        if (n > 0) {
-            uint32_t nvars = bindings.countVars();
-            uint32_t nargs = bindings.countArgs();
-            JS_ASSERT(fun->nargs == nargs);
-            JS_ASSERT(nvars + nargs == n);
-
-            JSScript *script = fun->script();
-            if (script->usesEval
-#ifdef JS_METHODJIT
-                || script->debugMode
-#endif
-                ) {
-                callobj.copyValues(nargs, fp->formalArgs(), nvars, fp->slots());
-            } else {
-                /*
-                 * For each arg & var that is closed over, copy it from the stack
-                 * into the call object. We use initArg/VarUnchecked because,
-                 * when you call a getter on a call object, js_NativeGetInline
-                 * caches the return value in the slot, so we can't assert that
-                 * it's undefined.
-                 */
-                uint32_t nclosed = script->nClosedArgs;
-                for (uint32_t i = 0; i < nclosed; i++) {
-                    uint32_t e = script->getClosedArg(i);
-#ifdef JS_GC_ZEAL
-                    callobj.setArg(e, fp->formalArg(e));
-#else
-                    callobj.initArgUnchecked(e, fp->formalArg(e));
-#endif
-                }
-
-                nclosed = script->nClosedVars;
-                for (uint32_t i = 0; i < nclosed; i++) {
-                    uint32_t e = script->getClosedVar(i);
-#ifdef JS_GC_ZEAL
-                    callobj.setVar(e, fp->slots()[e]);
-#else
-                    callobj.initVarUnchecked(e, fp->slots()[e]);
-#endif
-                }
-            }
-
-            /*
-             * Update the args and vars for the active call if this is an outer
-             * function in a script nesting.
-             */
-            types::TypeScriptNesting *nesting = script->nesting();
-            if (nesting && script->isOuterFunction) {
-                nesting->argArray = callobj.argArray();
-                nesting->varArray = callobj.varArray();
-            }
-        }
-
-        /* Clear private pointers to fp, which is about to go away. */
-        if (js_IsNamedLambda(fun)) {
-            JSObject &env = callobj.enclosingScope();
-            JS_ASSERT(env.asDeclEnv().maybeStackFrame() == fp);
-            env.setPrivate(NULL);
-        }
-    }
-
-    callobj.setStackFrame(NULL);
-}
-
-namespace js {
-
-static JSBool
-GetCallArguments(JSContext *cx, JSObject *obj, jsid id, Value *vp)
-{
-    CallObject &callobj = obj->asCall();
-
-    StackFrame *fp = callobj.maybeStackFrame();
-    if (fp && !fp->hasOverriddenArgs()) {
-        JSObject *argsobj = js_GetArgsObject(cx, fp);
-        if (!argsobj)
-            return false;
-        vp->setObject(*argsobj);
-    } else {
-        *vp = callobj.getArguments();
-    }
-    return true;
-}
-
-static JSBool
-SetCallArguments(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
-{
-    CallObject &callobj = obj->asCall();
-
-    if (StackFrame *fp = callobj.maybeStackFrame())
-        fp->setOverriddenArgs();
-    callobj.setArguments(*vp);
-    return true;
-}
-
-JSBool
-GetCallArg(JSContext *cx, JSObject *obj, jsid id, Value *vp)
-{
-    CallObject &callobj = obj->asCall();
-    JS_ASSERT((int16_t) JSID_TO_INT(id) == JSID_TO_INT(id));
-    uintN i = (uint16_t) JSID_TO_INT(id);
-
-    if (StackFrame *fp = callobj.maybeStackFrame())
-        *vp = fp->formalArg(i);
-    else
-        *vp = callobj.arg(i);
-    return true;
-}
-
-JSBool
-SetCallArg(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
-{
-    CallObject &callobj = obj->asCall();
-    JS_ASSERT((int16_t) JSID_TO_INT(id) == JSID_TO_INT(id));
-    uintN i = (uint16_t) JSID_TO_INT(id);
-
-    if (StackFrame *fp = callobj.maybeStackFrame())
-        fp->formalArg(i) = *vp;
-    else
-        callobj.setArg(i, *vp);
-
-    JSFunction *fun = callobj.getCalleeFunction();
-    JSScript *script = fun->script();
-    if (!script->ensureHasTypes(cx))
-        return false;
-
-    TypeScript::SetArgument(cx, script, i, *vp);
-
-    return true;
-}
-
-JSBool
-GetCallUpvar(JSContext *cx, JSObject *obj, jsid id, Value *vp)
-{
-    CallObject &callobj = obj->asCall();
-    JS_ASSERT((int16_t) JSID_TO_INT(id) == JSID_TO_INT(id));
-    uintN i = (uint16_t) JSID_TO_INT(id);
-
-    *vp = callobj.getCallee()->toFunction()->getFlatClosureUpvar(i);
-    return true;
-}
-
-JSBool
-SetCallUpvar(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
-{
-    CallObject &callobj = obj->asCall();
-    JS_ASSERT((int16_t) JSID_TO_INT(id) == JSID_TO_INT(id));
-    uintN i = (uint16_t) JSID_TO_INT(id);
-
-    callobj.getCallee()->toFunction()->setFlatClosureUpvar(i, *vp);
-    return true;
-}
-
-JSBool
-GetCallVar(JSContext *cx, JSObject *obj, jsid id, Value *vp)
-{
-    CallObject &callobj = obj->asCall();
-    JS_ASSERT((int16_t) JSID_TO_INT(id) == JSID_TO_INT(id));
-    uintN i = (uint16_t) JSID_TO_INT(id);
-
-    if (StackFrame *fp = callobj.maybeStackFrame())
-        *vp = fp->varSlot(i);
-    else
-        *vp = callobj.var(i);
-    return true;
-}
-
-JSBool
-SetCallVar(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
-{
-    CallObject &callobj = obj->asCall();
-
-    JS_ASSERT((int16_t) JSID_TO_INT(id) == JSID_TO_INT(id));
-    uintN i = (uint16_t) JSID_TO_INT(id);
-
-    if (StackFrame *fp = callobj.maybeStackFrame())
-        fp->varSlot(i) = *vp;
-    else
-        callobj.setVar(i, *vp);
-
-    JSFunction *fun = callobj.getCalleeFunction();
-    JSScript *script = fun->script();
-    if (!script->ensureHasTypes(cx))
-        return false;
-
-    TypeScript::SetLocal(cx, script, i, *vp);
-
-    return true;
-}
-
-} // namespace js
-
-static JSBool
-call_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags, JSObject **objp)
-{
-    JS_ASSERT(!obj->getProto());
-
-    if (!JSID_IS_ATOM(id))
-        return true;
-
-    JSObject *callee = obj->asCall().getCallee();
-#ifdef DEBUG
-    if (callee) {
-        JSScript *script = callee->toFunction()->script();
-        JS_ASSERT(!script->bindings.hasBinding(cx, JSID_TO_ATOM(id)));
-    }
-#endif
-
-    /*
-     * Resolve arguments so that we never store a particular Call object's
-     * arguments object reference in a Call prototype's |arguments| slot.
-     *
-     * Include JSPROP_ENUMERATE for consistency with all other Call object
-     * properties; see js::Bindings::add and js::Interpret's JSOP_DEFFUN
-     * rebinding-Call-property logic.
-     */
-    if (callee && id == ATOM_TO_JSID(cx->runtime->atomState.argumentsAtom)) {
-        if (!DefineNativeProperty(cx, obj, id, UndefinedValue(),
-                                  GetCallArguments, SetCallArguments,
-                                  JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_ENUMERATE,
-                                  0, 0, DNP_DONT_PURGE)) {
-            return false;
-        }
-        *objp = obj;
-        return true;
-    }
-
-    /* Control flow reaches here only if id was not resolved. */
-    return true;
-}
-
-static void
-call_trace(JSTracer *trc, JSObject *obj)
-{
-    JS_ASSERT(obj->isCall());
-
-    /* Mark any generator frame, as for arguments objects. */
-#if JS_HAS_GENERATORS
-    StackFrame *fp = (StackFrame *) obj->getPrivate();
-    if (fp && fp->isFloatingGenerator())
-        MarkObject(trc, &js_FloatingFrameToGenerator(fp)->obj, "generator object");
-#endif
-}
-
-JS_PUBLIC_DATA(Class) js::CallClass = {
-    "Call",
-    JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS |
-    JSCLASS_HAS_RESERVED_SLOTS(CallObject::RESERVED_SLOTS) |
-    JSCLASS_NEW_RESOLVE | JSCLASS_IS_ANONYMOUS,
-    JS_PropertyStub,         /* addProperty */
-    JS_PropertyStub,         /* delProperty */
-    JS_PropertyStub,         /* getProperty */
-    JS_StrictPropertyStub,   /* setProperty */
-    JS_EnumerateStub,
-    (JSResolveOp)call_resolve,
-    NULL,                    /* convert: Leave it NULL so we notice if calls ever escape */
-    NULL,                    /* finalize */
-    NULL,                    /* checkAccess */
-    NULL,                    /* call        */
-    NULL,                    /* construct   */
-    NULL,                    /* hasInstance */
-    call_trace
-};
-
 bool
 StackFrame::getValidCalleeObject(JSContext *cx, Value *vp)
 {
     if (!isFunctionFrame()) {
         vp->setNull();
         return true;
     }
 
--- a/js/src/jsfun.h
+++ b/js/src/jsfun.h
@@ -357,40 +357,16 @@ js_ValueToCallableObject(JSContext *cx, 
 extern void
 js_ReportIsNotFunction(JSContext *cx, const js::Value *vp, uintN flags);
 
 extern void
 js_PutCallObject(js::StackFrame *fp);
 
 namespace js {
 
-CallObject *
-CreateFunCallObject(JSContext *cx, StackFrame *fp);
-
-CallObject *
-CreateEvalCallObject(JSContext *cx, StackFrame *fp);
-
-extern JSBool
-GetCallArg(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
-
-extern JSBool
-GetCallVar(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
-
-extern JSBool
-GetCallUpvar(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
-
-extern JSBool
-SetCallArg(JSContext *cx, JSObject *obj, jsid id, JSBool strict, js::Value *vp);
-
-extern JSBool
-SetCallVar(JSContext *cx, JSObject *obj, jsid id, JSBool strict, js::Value *vp);
-
-extern JSBool
-SetCallUpvar(JSContext *cx, JSObject *obj, jsid id, JSBool strict, js::Value *vp);
-
 /*
  * Function extended with reserved slots for use by various kinds of functions.
  * Most functions do not have these extensions, but enough are that efficient
  * storage is required (no malloc'ed reserved slots).
  */
 class FunctionExtended : public JSFunction
 {
     friend struct JSFunction;
@@ -410,30 +386,27 @@ JSFunction::toExtended()
 
 inline const js::FunctionExtended *
 JSFunction::toExtended() const
 {
     JS_ASSERT(isExtended());
     return static_cast<const js::FunctionExtended *>(this);
 }
 
-extern JSBool
-js_GetArgsValue(JSContext *cx, js::StackFrame *fp, js::Value *vp);
-
 /*
  * Get the arguments object for the given frame.  If the frame is strict mode
  * code, its current arguments will be copied into the arguments object.
  *
  * NB: Callers *must* get the arguments object before any parameters are
  *     mutated when the frame is strict mode code!  The emitter ensures this
  *     occurs for strict mode functions containing syntax which might mutate a
  *     named parameter by synthesizing an arguments access at the start of the
  *     function.
  */
-extern JSObject *
+extern js::ArgumentsObject *
 js_GetArgsObject(JSContext *cx, js::StackFrame *fp);
 
 extern void
 js_PutArgsObject(js::StackFrame *fp);
 
 inline bool
 js_IsNamedLambda(JSFunction *fun) { return (fun->flags & JSFUN_LAMBDA) && fun->atom; }
 
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -2157,16 +2157,23 @@ GCMarker::appendGrayRoot(void *thing, JS
 
 void
 GCMarker::GrayCallback(JSTracer *trc, void **thingp, JSGCTraceKind kind)
 {
     GCMarker *gcmarker = static_cast<GCMarker *>(trc);
     gcmarker->appendGrayRoot(*thingp, kind);
 }
 
+size_t
+GCMarker::sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf) const
+{
+    return stack.sizeOfExcludingThis(mallocSizeOf) +
+           grayRoots.sizeOfExcludingThis(mallocSizeOf);
+}
+
 void
 SetMarkStackLimit(JSRuntime *rt, size_t limit)
 {
     JS_ASSERT(!rt->gcRunning);
     rt->gcMarker.setSizeLimit(limit);
     for (CompartmentsIter c(rt); !c.done(); c.next())
         c->barrierMarker_.setSizeLimit(limit);
 }
@@ -3130,37 +3137,45 @@ ValidateIncrementalMarking(JSContext *cx
     typedef HashMap<Chunk *, uintptr_t *, GCChunkHasher, SystemAllocPolicy> BitmapMap;
     BitmapMap map;
     if (!map.init())
         return;
 
     JSRuntime *rt = cx->runtime;
     FullGCMarker *gcmarker = &rt->gcMarker;
 
-    /* Save existing mark bits */
+    /* Save existing mark bits. */
     for (GCChunkSet::Range r(rt->gcChunkSet.all()); !r.empty(); r.popFront()) {
         ChunkBitmap *bitmap = &r.front()->bitmap;
         uintptr_t *entry = (uintptr_t *)js_malloc(sizeof(bitmap->bitmap));
         if (!entry)
             return;
 
         memcpy(entry, bitmap->bitmap, sizeof(bitmap->bitmap));
         if (!map.putNew(r.front(), entry))
             return;
     }
 
+    /* Save the existing weakmaps. */
+    WeakMapVector weakmaps;
+    if (!WeakMapBase::saveWeakMapList(rt, weakmaps))
+        return;
+
     /*
      * After this point, the function should run to completion, so we shouldn't
      * do anything fallible.
      */
 
     /* Re-do all the marking, but non-incrementally. */
     js::gc::State state = rt->gcIncrementalState;
     rt->gcIncrementalState = NO_INCREMENTAL;
 
+    /* As we're re-doing marking, we need to reset the weak map list. */
+    WeakMapBase::resetWeakMapList(rt);
+
     JS_ASSERT(gcmarker->isDrained());
     gcmarker->reset();
 
     for (GCChunkSet::Range r(rt->gcChunkSet.all()); !r.empty(); r.popFront())
         r.front()->bitmap.clear();
 
     MarkRuntime(gcmarker, true);
     SliceBudget budget;
@@ -3198,16 +3213,20 @@ ValidateIncrementalMarking(JSContext *cx
                 JS_ASSERT_IF(bitmap->isMarked(cell, BLACK), incBitmap.isMarked(cell, BLACK));
                 thing += Arena::thingSize(kind);
             }
         }
 
         memcpy(bitmap->bitmap, incBitmap.bitmap, sizeof(incBitmap.bitmap));
     }
 
+    /* Restore the weak map list. */
+    WeakMapBase::resetWeakMapList(rt);
+    WeakMapBase::restoreWeakMapList(rt, weakmaps);
+
     rt->gcIncrementalState = state;
 }
 #endif
 
 static void
 SweepPhase(JSContext *cx, JSGCInvocationKind gckind)
 {
     JSRuntime *rt = cx->runtime;
--- a/js/src/jsgc.h
+++ b/js/src/jsgc.h
@@ -1691,16 +1691,24 @@ struct MarkStack {
             if (!newStack)
                 return false;
         }
         stack = newStack;
         tos = stack + tosIndex;
         limit = newStack + newcap;
         return true;
     }
+
+    size_t sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf) const {
+        size_t n = 0;
+        if (stack != ballast)
+            n += mallocSizeOf(stack);
+        n += mallocSizeOf(ballast);
+        return n;
+    }
 };
 
 /*
  * This class records how much work has been done in a given GC slice, so that
  * we can return before pausing for too long. Some slices are allowed to run for
  * unlimited time, and others are bounded. To reduce the number of gettimeofday
  * calls, we only check the time every 1000 operations.
  */
@@ -1833,16 +1841,18 @@ struct GCMarker : public JSTracer {
      */
     bool hasBufferedGrayRoots() const;
     void startBufferingGrayRoots();
     void endBufferingGrayRoots();
     void markBufferedGrayRoots();
 
     static void GrayCallback(JSTracer *trc, void **thing, JSGCTraceKind kind);
 
+    size_t sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf) const;
+
     MarkStack<uintptr_t> stack;
 
   private:
 #ifdef DEBUG
     void checkCompartment(void *p);
 #else
     void checkCompartment(void *p) {}
 #endif
--- a/js/src/jsgcmark.cpp
+++ b/js/src/jsgcmark.cpp
@@ -357,16 +357,51 @@ MarkValueRootRange(JSTracer *trc, size_t
 {
     JS_ROOT_MARKING_ASSERT(trc);
     for (size_t i = 0; i < len; ++i) {
         JS_SET_TRACING_INDEX(trc, name, i);
         MarkValueInternal(trc, &vec[i]);
     }
 }
 
+/*** Slot Marking ***/
+
+void
+MarkSlot(JSTracer *trc, HeapSlot *s, const char *name)
+{
+    JS_SET_TRACING_NAME(trc, name);
+    MarkValueInternal(trc, s->unsafeGet());
+}
+
+void
+MarkSlotRange(JSTracer *trc, size_t len, HeapSlot *vec, const char *name)
+{
+    for (size_t i = 0; i < len; ++i) {
+        JS_SET_TRACING_INDEX(trc, name, i);
+        MarkValueInternal(trc, vec[i].unsafeGet());
+    }
+}
+
+void
+MarkCrossCompartmentSlot(JSTracer *trc, HeapSlot *s, const char *name)
+{
+    if (s->isMarkable()) {
+        Cell *cell = (Cell *)s->toGCThing();
+        JSRuntime *rt = trc->runtime;
+        if (rt->gcCurrentCompartment && cell->compartment() != rt->gcCurrentCompartment)
+            return;
+
+        /* In case we're called from a write barrier. */
+        if (rt->gcIncrementalCompartment && cell->compartment() != rt->gcIncrementalCompartment)
+            return;
+
+        MarkSlot(trc, s, name);
+    }
+}
+
 /*** Special Marking ***/
 
 /*
  * The unioned HeapPtr stored in script->globalObj needs special treatment to
  * typecheck correctly.
  */
 static void
 MarkObject(JSTracer *trc, const HeapPtr<GlobalObject, JSScript *> &thing, const char *name)
@@ -377,33 +412,16 @@ MarkObject(JSTracer *trc, const HeapPtr<
 
 void
 MarkValueUnbarriered(JSTracer *trc, Value *v, const char *name)
 {
     JS_SET_TRACING_NAME(trc, name);
     MarkValueInternal(trc, v);
 }
 
-void
-MarkCrossCompartmentValue(JSTracer *trc, HeapValue *v, const char *name)
-{
-    if (v->isMarkable()) {
-        Cell *cell = (Cell *)v->toGCThing();
-        JSRuntime *rt = trc->runtime;
-        if (rt->gcCurrentCompartment && cell->compartment() != rt->gcCurrentCompartment)
-            return;
-
-        /* In case we're called from a write barrier. */
-        if (rt->gcIncrementalCompartment && cell->compartment() != rt->gcIncrementalCompartment)
-            return;
-
-        MarkValue(trc, v, name);
-    }
-}
-
 /*** Push Mark Stack ***/
 
 #define JS_COMPARTMENT_ASSERT(rt, thing)                                 \
     JS_ASSERT_IF((rt)->gcCurrentCompartment,                             \
                  (thing)->compartment() == (rt)->gcCurrentCompartment);
 
 #define JS_COMPARTMENT_ASSERT_STR(rt, thing)                             \
     JS_ASSERT_IF((rt)->gcCurrentCompartment,                             \
@@ -946,31 +964,31 @@ PushArena(GCMarker *gcmarker, ArenaHeade
 #endif
     }
 }
 
 } /* namespace gc */
 
 using namespace js::gc;
 
-struct ValueArrayLayout
+struct SlotArrayLayout
 {
     union {
-        HeapValue *end;
+        HeapSlot *end;
         js::Class *clasp;
     };
     union {
-        HeapValue *start;
+        HeapSlot *start;
         uintptr_t index;
     };
     JSObject *obj;
 
     static void staticAsserts() {
         /* This should have the same layout as three mark stack items. */
-        JS_STATIC_ASSERT(sizeof(ValueArrayLayout) == 3 * sizeof(uintptr_t));
+        JS_STATIC_ASSERT(sizeof(SlotArrayLayout) == 3 * sizeof(uintptr_t));
     }
 };
 
 /*
  * During incremental GC, we return from drainMarkStack without having processed
  * the entire stack. At that point, JS code can run and reallocate slot arrays
  * that are stored on the stack. To prevent this from happening, we replace all
  * ValueArrayTag stack items with SavedValueArrayTag. In the latter, slots
@@ -983,26 +1001,26 @@ struct ValueArrayLayout
  */
 void
 GCMarker::saveValueRanges()
 {
     for (uintptr_t *p = stack.tos; p > stack.stack; ) {
         uintptr_t tag = *--p & StackTagMask;
         if (tag == ValueArrayTag) {
             p -= 2;
-            ValueArrayLayout *arr = reinterpret_cast<ValueArrayLayout *>(p);
+            SlotArrayLayout *arr = reinterpret_cast<SlotArrayLayout *>(p);
             JSObject *obj = arr->obj;
 
             if (obj->getClass() == &ArrayClass) {
-                HeapValue *vp = obj->getDenseArrayElements();
+                HeapSlot *vp = obj->getDenseArrayElements();
                 JS_ASSERT(arr->start >= vp &&
                           arr->end == vp + obj->getDenseArrayInitializedLength());
                 arr->index = arr->start - vp;
             } else {
-                HeapValue *vp = obj->fixedSlots();
+                HeapSlot *vp = obj->fixedSlots();
                 unsigned nfixed = obj->numFixedSlots();
                 if (arr->start >= vp && arr->start < vp + nfixed) {
                     JS_ASSERT(arr->end == vp + Min(nfixed, obj->slotSpan()));
                     arr->index = arr->start - vp;
                 } else {
                     JS_ASSERT(arr->start >= obj->slots &&
                               arr->end == obj->slots + obj->slotSpan() - nfixed);
                     arr->index = (arr->start - obj->slots) + nfixed;
@@ -1025,26 +1043,26 @@ GCMarker::restoreValueArray(JSObject *ob
     JS_ASSERT(obj->getClass() == clasp ||
               (clasp == &ArrayClass && obj->getClass() == &SlowArrayClass));
 
     if (clasp == &ArrayClass) {
         if (obj->getClass() != &ArrayClass)
             return false;
 
         uint32_t initlen = obj->getDenseArrayInitializedLength();
-        HeapValue *vp = obj->getDenseArrayElements();
+        HeapSlot *vp = obj->getDenseArrayElements();
         if (start < initlen) {
             *vpp = vp + start;
             *endp = vp + initlen;
         } else {
             /* The object shrunk, in which case no scanning is needed. */
             *vpp = *endp = vp;
         }
     } else {
-        HeapValue *vp = obj->fixedSlots();
+        HeapSlot *vp = obj->fixedSlots();
         unsigned nfixed = obj->numFixedSlots();
         unsigned nslots = obj->slotSpan();
         if (start < nfixed) {
             *vpp = vp + start;
             *endp = vp + Min(nfixed, nslots);
         } else if (start < nslots) {
             *vpp = obj->slots + start - nfixed;
             *endp = obj->slots + nslots - nfixed;
@@ -1061,33 +1079,33 @@ GCMarker::restoreValueArray(JSObject *ob
 inline void
 GCMarker::processMarkStackTop(SliceBudget &budget)
 {
     /*
      * The function uses explicit goto and implements the scanning of the
      * object directly. It allows to eliminate the tail recursion and
      * significantly improve the marking performance, see bug 641025.
      */
-    HeapValue *vp, *end;
+    HeapSlot *vp, *end;
     JSObject *obj;
 
     uintptr_t addr = stack.pop();
     uintptr_t tag = addr & StackTagMask;
     addr &= ~StackTagMask;
 
     if (tag == ValueArrayTag) {
         JS_STATIC_ASSERT(ValueArrayTag == 0);
         JS_ASSERT(!(addr & Cell::CellMask));
         obj = reinterpret_cast<JSObject *>(addr);
         uintptr_t addr2 = stack.pop();
         uintptr_t addr3 = stack.pop();
         JS_ASSERT(addr2 <= addr3);
         JS_ASSERT((addr3 - addr2) % sizeof(Value) == 0);
-        vp = reinterpret_cast<HeapValue *>(addr2);
-        end = reinterpret_cast<HeapValue *>(addr3);
+        vp = reinterpret_cast<HeapSlot *>(addr2);
+        end = reinterpret_cast<HeapSlot *>(addr3);
         goto scan_value_array;
     }
 
     if (tag == ObjectTag) {
         obj = reinterpret_cast<JSObject *>(addr);
         JS_COMPARTMENT_ASSERT(runtime, obj);
         goto scan_obj;
     }
--- a/js/src/jsgcmark.h
+++ b/js/src/jsgcmark.h
@@ -115,28 +115,36 @@ void
 MarkValueRootRange(JSTracer *trc, size_t len, Value *vec, const char *name);
 
 inline void
 MarkValueRootRange(JSTracer *trc, Value *begin, Value *end, const char *name)
 {
     MarkValueRootRange(trc, end - begin, begin, name);
 }
 
-/*** Special Cases ***/
+/*** Slot Marking ***/
 
-/* Direct value access used by the write barriers and the methodjit */
 void
-MarkValueUnbarriered(JSTracer *trc, Value *v, const char *name);
+MarkSlot(JSTracer *trc, HeapSlot *s, const char *name);
+
+void
+MarkSlotRange(JSTracer *trc, size_t len, HeapSlot *vec, const char *name);
 
 /*
  * Mark a value that may be in a different compartment from the compartment
  * being GC'd. (Although it won't be marked if it's in the wrong compartment.)
  */
 void
-MarkCrossCompartmentValue(JSTracer *trc, HeapValue *v, const char *name);
+MarkCrossCompartmentSlot(JSTracer *trc, HeapSlot *s, const char *name);
+
+/*** Special Cases ***/
+
+/* Direct value access used by the write barriers and the methodjit. */
+void
+MarkValueUnbarriered(JSTracer *trc, Value *v, const char *name);
 
 /*
  * MarkChildren<JSObject> is exposed solely for preWriteBarrier on
  * JSObject::TradeGuts. It should not be considered external interface.
  */
 void
 MarkChildren(JSTracer *trc, JSObject *obj);
 
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -1684,20 +1684,18 @@ types::MarkArgumentsCreated(JSContext *c
         StackFrame *fp = iter.fp();
         if (fp->isScriptFrame() && fp->script() == script) {
             /*
              * Check locals and stack slots, assignment to individual arguments
              * is treated as an escape on the arguments.
              */
             Value *sp = fp->base() + analysis->getCode(iter.pc()).stackDepth;
             for (Value *vp = fp->slots(); vp < sp; vp++) {
-                if (vp->isParticularMagic(JS_LAZY_ARGUMENTS)) {
-                    if (!js_GetArgsValue(cx, fp, vp))
-                        vp->setNull();
-                }
+                if (vp->isParticularMagic(JS_LAZY_ARGUMENTS))
+                    *vp = ObjectOrNullValue(js_GetArgsObject(cx, fp));
             }
         }
     }
 }
 
 static inline void
 ObjectStateChange(JSContext *cx, TypeObject *object, bool markingUnknown, bool force)
 {
@@ -2416,16 +2414,21 @@ ScriptAnalysis::addTypeBarrier(JSContext
 
     InferSpew(ISpewOps, "typeBarrier: #%u:%05u: %sT%p%s %s",
               script->id(), pc - script->code,
               InferSpewColor(target), target, InferSpewColorReset(),
               TypeString(type));
 
     barrier = cx->typeLifoAlloc().new_<TypeBarrier>(target, type, (JSObject *) NULL, JSID_VOID);
 
+    if (!barrier) {
+        cx->compartment->types.setPendingNukeTypes(cx);
+        return;
+    }
+
     barrier->next = code.typeBarriers;
     code.typeBarriers = barrier;
 }
 
 void
 ScriptAnalysis::addSingletonTypeBarrier(JSContext *cx, const jsbytecode *pc, TypeSet *target, JSObject *singleton, jsid singletonId)
 {
     JS_ASSERT(singletonId == MakeTypeId(cx, singletonId) && !JSID_IS_VOID(singletonId));
@@ -2442,16 +2445,21 @@ ScriptAnalysis::addSingletonTypeBarrier(
     InferSpew(ISpewOps, "singletonTypeBarrier: #%u:%05u: %sT%p%s %p %s",
               script->id(), pc - script->code,
               InferSpewColor(target), target, InferSpewColorReset(),
               (void *) singleton, TypeIdString(singletonId));
 
     TypeBarrier *barrier = cx->typeLifoAlloc().new_<TypeBarrier>(target, Type::UndefinedType(),
                               singleton, singletonId);
 
+    if (!barrier) {
+        cx->compartment->types.setPendingNukeTypes(cx);
+        return;
+    }
+
     barrier->next = code.typeBarriers;
     code.typeBarriers = barrier;
 }
 
 void
 TypeCompartment::print(JSContext *cx, bool force)
 {
     JSCompartment *compartment = this->compartment();
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -156,17 +156,17 @@ js::GetScopeChain(JSContext *cx, StackFr
      * make sure there's a call object at the current head of the scope chain,
      * if this frame is a call frame.
      *
      * Also, identify the innermost compiler-allocated block we needn't clone.
      */
     JSObject *limitBlock, *limitClone;
     if (fp->isNonEvalFunctionFrame() && !fp->hasCallObj()) {
         JS_ASSERT_IF(fp->scopeChain().isClonedBlock(), fp->scopeChain().getPrivate() != fp);
-        if (!CreateFunCallObject(cx, fp))
+        if (!CallObject::createForFunction(cx, fp))
             return NULL;
 
         /* We know we must clone everything on blockChain. */
         limitBlock = limitClone = NULL;
     } else {
         /*
          * scopeChain includes all blocks whose static scope we're within that
          * have already been cloned.  Find the innermost such block.  Its
@@ -650,17 +650,17 @@ js::ExecuteKernel(JSContext *cx, JSScrip
     if (!cx->stack.pushExecuteFrame(cx, script, thisv, scopeChain, type, evalInFrame, &efg))
         return false;
 
     if (!script->ensureRanAnalysis(cx, &scopeChain))
         return false;
 
     /* Give strict mode eval its own fresh lexical environment. */
     StackFrame *fp = efg.fp();
-    if (fp->isStrictEvalFrame() && !CreateEvalCallObject(cx, fp))
+    if (fp->isStrictEvalFrame() && !CallObject::createForStrictEval(cx, fp))
         return false;
 
     Probes::startExecution(cx, script);
 
     TypeScript::SetThis(cx, script, fp->thisValue());
 
     AutoPreserveEnumerators preserve(cx);
     JSBool ok = RunScript(cx, script, fp);
@@ -1471,17 +1471,17 @@ js::Interpret(JSContext *cx, StackFrame 
         if (script->pcCounters)                                               \
             ENABLE_INTERRUPTS();                                              \
         JS_ASSERT_IF(interpMode == JSINTERP_SKIP_TRAP,                        \
                      script->hasAnyBreakpointsOrStepMode());                  \
     JS_END_MACRO
 
 #define CHECK_INTERRUPT_HANDLER()                                             \
     JS_BEGIN_MACRO                                                            \
-        if (cx->debugHooks->interruptHook)                                    \
+        if (cx->runtime->debugHooks.interruptHook)                            \
             ENABLE_INTERRUPTS();                                              \
     JS_END_MACRO
 
     /* Repoint cx->regs to a local variable for faster access. */
     FrameRegs regs = cx->regs();
     PreserveRegsGuard interpGuard(cx, regs);
 
     /*
@@ -1618,22 +1618,22 @@ js::Interpret(JSContext *cx, StackFrame 
         }
 
         if (script->pcCounters) {
             OpcodeCounts counts = script->getCounts(regs.pc);
             counts.get(OpcodeCounts::BASE_INTERP)++;
             moreInterrupts = true;
         }
 
-        JSInterruptHook hook = cx->debugHooks->interruptHook;
+        JSInterruptHook hook = cx->runtime->debugHooks.interruptHook;
         if (hook || script->stepModeEnabled()) {
             Value rval;
             JSTrapStatus status = JSTRAP_CONTINUE;
             if (hook)
-                status = hook(cx, script, regs.pc, &rval, cx->debugHooks->interruptHookData);
+                status = hook(cx, script, regs.pc, &rval, cx->runtime->debugHooks.interruptHookData);
             if (status == JSTRAP_CONTINUE && script->stepModeEnabled())
                 status = Debugger::onSingleStep(cx, &rval);
             switch (status) {
               case JSTRAP_ERROR:
                 goto error;
               case JSTRAP_CONTINUE:
                 break;
               case JSTRAP_RETURN:
@@ -2021,17 +2021,17 @@ BEGIN_CASE(JSOP_IN)
     regs.sp[-1].setBoolean(cond);
 }
 END_CASE(JSOP_IN)
 
 BEGIN_CASE(JSOP_ITER)
 {
     JS_ASSERT(regs.sp > regs.fp()->base());
     uint8_t flags = GET_UINT8(regs.pc);
-    if (!js_ValueToIterator(cx, flags, &regs.sp[-1]))
+    if (!ValueToIterator(cx, flags, &regs.sp[-1]))
         goto error;
     CHECK_INTERRUPT_HANDLER();
     JS_ASSERT(!regs.sp[-1].isPrimitive());
 }
 END_CASE(JSOP_ITER)
 
 BEGIN_CASE(JSOP_MOREITER)
 {
@@ -2055,17 +2055,17 @@ BEGIN_CASE(JSOP_ITERNEXT)
     if (!IteratorNext(cx, &itervp->toObject(), &regs.sp[-1]))
         goto error;
 }
 END_CASE(JSOP_ITERNEXT)
 
 BEGIN_CASE(JSOP_ENDITER)
 {
     JS_ASSERT(regs.sp - 1 >= regs.fp()->base());
-    bool ok = !!js_CloseIterator(cx, &regs.sp[-1].toObject());
+    bool ok = CloseIterator(cx, &regs.sp[-1].toObject());
     regs.sp--;
     if (!ok)
         goto error;
 }
 END_CASE(JSOP_ENDITER)
 
 BEGIN_CASE(JSOP_DUP)
 {
@@ -3063,24 +3063,28 @@ END_VARLEN_CASE
 
 BEGIN_CASE(JSOP_ARGUMENTS)
 {
     Value rval;
     if (cx->typeInferenceEnabled() && !script->strictModeCode) {
         if (!script->ensureRanInference(cx))
             goto error;
         if (script->createdArgs) {
-            if (!js_GetArgsValue(cx, regs.fp(), &rval))
+            ArgumentsObject *arguments = js_GetArgsObject(cx, regs.fp());
+            if (!arguments)
                 goto error;
+            rval = ObjectValue(*arguments);
         } else {
             rval = MagicValue(JS_LAZY_ARGUMENTS);
         }
     } else {
-        if (!js_GetArgsValue(cx, regs.fp(), &rval))
+        ArgumentsObject *arguments = js_GetArgsObject(cx, regs.fp());
+        if (!arguments)
             goto error;
+        rval = ObjectValue(*arguments);
     }
     PUSH_COPY(rval);
 }
 END_CASE(JSOP_ARGUMENTS)
 
 BEGIN_CASE(JSOP_GETARG)
 BEGIN_CASE(JSOP_CALLARG)
     PUSH_COPY(regs.fp()->formalArg(GET_ARGNO(regs.pc)));
@@ -3716,18 +3720,18 @@ BEGIN_CASE(JSOP_INSTANCEOF)
     regs.sp[-1].setBoolean(cond);
 }
 END_CASE(JSOP_INSTANCEOF)
 
 BEGIN_CASE(JSOP_DEBUGGER)
 {
     JSTrapStatus st = JSTRAP_CONTINUE;
     Value rval;
-    if (JSDebuggerHandler handler = cx->debugHooks->debuggerHandler)
-        st = handler(cx, script, regs.pc, &rval, cx->debugHooks->debuggerHandlerData);
+    if (JSDebuggerHandler handler = cx->runtime->debugHooks.debuggerHandler)
+        st = handler(cx, script, regs.pc, &rval, cx->runtime->debugHooks.debuggerHandlerData);
     if (st == JSTRAP_CONTINUE)
         st = Debugger::onDebuggerStatement(cx, &rval);
     switch (st) {
       case JSTRAP_ERROR:
         goto error;
       case JSTRAP_CONTINUE:
         break;
       case JSTRAP_RETURN:
@@ -4276,23 +4280,23 @@ END_CASE(JSOP_ARRAYPUSH)
         JSThrowHook handler;
         JSTryNote *tn, *tnlimit;
         uint32_t offset;
 
         /* Restore atoms local in case we will resume. */
         atoms = script->atoms;
 
         /* Call debugger throw hook if set. */
-        if (cx->debugHooks->throwHook || !cx->compartment->getDebuggees().empty()) {
+        if (cx->runtime->debugHooks.throwHook || !cx->compartment->getDebuggees().empty()) {
             Value rval;
             JSTrapStatus st = Debugger::onExceptionUnwind(cx, &rval);
             if (st == JSTRAP_CONTINUE) {
-                handler = cx->debugHooks->throwHook;
+                handler = cx->runtime->debugHooks.throwHook;
                 if (handler)
-                    st = handler(cx, script, regs.pc, &rval, cx->debugHooks->throwHookData);
+                    st = handler(cx, script, regs.pc, &rval, cx->runtime->debugHooks.throwHookData);
             }
 
             switch (st) {
               case JSTRAP_ERROR:
                 cx->clearPendingException();
                 goto error;
               case JSTRAP_RETURN:
                 cx->clearPendingException();
@@ -4379,23 +4383,20 @@ END_CASE(JSOP_ARRAYPUSH)
                 PUSH_COPY(cx->getPendingException());
                 cx->clearPendingException();
                 len = 0;
                 DO_NEXT_OP(len);
 
               case JSTRY_ITER: {
                 /* This is similar to JSOP_ENDITER in the interpreter loop. */
                 JS_ASSERT(JSOp(*regs.pc) == JSOP_ENDITER);
-                Value v = cx->getPendingException();
-                cx->clearPendingException();
-                bool ok = js_CloseIterator(cx, &regs.sp[-1].toObject());
+                bool ok = UnwindIteratorForException(cx, &regs.sp[-1].toObject());
                 regs.sp -= 1;
                 if (!ok)
                     goto error;
-                cx->setPendingException(v);
               }
            }
         } while (++tn != tnlimit);
 
       no_catch:
         /*
          * Propagate the exception or error to the caller unless the exception
          * is an asynchronous return from a generator.
--- a/js/src/jsinterp.h
+++ b/js/src/jsinterp.h
@@ -347,17 +347,16 @@ Debug_SetValueRangeToCrashOnTouch(Value 
 
 static JS_ALWAYS_INLINE void
 Debug_SetValueRangeToCrashOnTouch(HeapValue *vec, size_t len)
 {
 #ifdef DEBUG
     Debug_SetValueRangeToCrashOnTouch((Value *) vec, len);
 #endif
 }
-
 JSObject*
 NewInitArray(JSContext *cx, uint32_t count, types::TypeObject *type);
 
 bool
 Throw(JSContext *cx, const Value &v);
 
 bool
 GetProperty(JSContext *cx, const Value &value, PropertyName *name, Value *vp);
@@ -397,11 +396,27 @@ DivValues(JSContext *cx, const Value &lh
 
 bool
 ModValues(JSContext *cx, const Value &lhs, const Value &rhs, Value *res);
 
 template <bool strict>
 bool
 SetProperty(JSContext *cx, JSObject *obj, JSAtom *atom, Value value);
 
+static JS_ALWAYS_INLINE void
+Debug_SetSlotRangeToCrashOnTouch(HeapSlot *vec, size_t len)
+{
+#ifdef DEBUG
+    Debug_SetValueRangeToCrashOnTouch((Value *) vec, len);
+#endif
+}
+
+static JS_ALWAYS_INLINE void
+Debug_SetSlotRangeToCrashOnTouch(HeapSlot *begin, HeapSlot *end)
+{
+#ifdef DEBUG
+    Debug_SetValueRangeToCrashOnTouch((Value *) begin, end - begin);
+#endif
+}
+
 }  /* namespace js */
 
 #endif /* jsinterp_h___ */
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -833,17 +833,17 @@ iterator_iterator(JSContext *cx, JSObjec
 
 static JSBool
 Iterator(JSContext *cx, uintN argc, Value *vp)
 {
     Value *argv = JS_ARGV(cx, vp);
     bool keyonly = argc >= 2 ? js_ValueToBoolean(argv[1]) : false;
     uintN flags = JSITER_OWNONLY | (keyonly ? 0 : (JSITER_FOREACH | JSITER_KEYVALUE));
     *vp = argc >= 1 ? argv[0] : UndefinedValue();
-    return js_ValueToIterator(cx, flags, vp);
+    return ValueToIterator(cx, flags, vp);
 }
 
 JSBool
 js_ThrowStopIteration(JSContext *cx)
 {
     Value v;
 
     JS_ASSERT(!JS_IsExceptionPending(cx));
@@ -875,22 +875,29 @@ iterator_next(JSContext *cx, uintN argc,
 
 #define JSPROP_ROPERM   (JSPROP_READONLY | JSPROP_PERMANENT)
 
 static JSFunctionSpec iterator_methods[] = {
     JS_FN(js_next_str,      iterator_next,  0,JSPROP_ROPERM),
     JS_FS_END
 };
 
+#if JS_HAS_GENERATORS
+static JSBool
+CloseGenerator(JSContext *cx, JSObject *genobj);
+#endif
+
+namespace js {
+
 /*
  * Call ToObject(v).__iterator__(keyonly) if ToObject(v).__iterator__ exists.
  * Otherwise construct the default iterator.
  */
-JS_FRIEND_API(JSBool)
-js_ValueToIterator(JSContext *cx, uintN flags, Value *vp)
+JSBool
+ValueToIterator(JSContext *cx, uintN flags, Value *vp)
 {
     /* JSITER_KEYVALUE must always come with JSITER_FOREACH */
     JS_ASSERT_IF(flags & JSITER_KEYVALUE, flags & JSITER_FOREACH);
 
     /*
      * Make sure the more/next state machine doesn't get stuck. A value might be
      * left in iterValue when a trace is left due to an operation time-out after
      * JSOP_MOREITER but before the value is picked up by FOR*.
@@ -918,23 +925,18 @@ js_ValueToIterator(JSContext *cx, uintN 
             if (!obj)
                 return false;
         }
     }
 
     return GetIterator(cx, obj, flags, vp);
 }
 
-#if JS_HAS_GENERATORS
-static JSBool
-CloseGenerator(JSContext *cx, JSObject *genobj);
-#endif
-
-JS_FRIEND_API(bool)
-js_CloseIterator(JSContext *cx, JSObject *obj)
+bool
+CloseIterator(JSContext *cx, JSObject *obj)
 {
     cx->iterValue.setMagic(JS_NO_ITER_VALUE);
 
     if (obj->isIterator()) {
         /* Remove enumerators from the active list, which is a stack. */
         NativeIterator *ni = obj->getNativeIterator();
 
         if (ni->flags & JSITER_ENUMERATE) {
@@ -954,16 +956,29 @@ js_CloseIterator(JSContext *cx, JSObject
 #if JS_HAS_GENERATORS
     else if (obj->isGenerator()) {
         return CloseGenerator(cx, obj);
     }
 #endif
     return JS_TRUE;
 }
 
+bool
+UnwindIteratorForException(JSContext *cx, JSObject *obj)
+{
+    Value v = cx->getPendingException();
+    cx->clearPendingException();
+    if (!CloseIterator(cx, obj))
+        return false;
+    cx->setPendingException(v);
+    return true;
+}
+
+} // namespace js
+
 /*
  * Suppress enumeration of deleted properties. This function must be called
  * when a property is deleted and there might be active enumerators.
  *
  * We maintain a list of active non-escaping for-in enumerators. To suppress
  * a property, we check whether each active enumerator contains the (obj, id)
  * pair and has not yet enumerated |id|. If so, and |id| is the next property,
  * we simply advance the cursor. Otherwise, we delete |id| from the list.
--- a/js/src/jsiter.h
+++ b/js/src/jsiter.h
@@ -179,29 +179,32 @@ VectorToValueIterator(JSContext *cx, JSO
 
 /*
  * Creates either a key or value iterator, depending on flags. For a value
  * iterator, performs value-lookup to convert the given list of jsids.
  */
 bool
 EnumeratedIdVectorToIterator(JSContext *cx, JSObject *obj, uintN flags, js::AutoIdVector &props, js::Value *vp);
 
-}
-
 /*
  * Convert the value stored in *vp to its iteration object. The flags should
  * contain JSITER_ENUMERATE if js_ValueToIterator is called when enumerating
  * for-in semantics are required, and when the caller can guarantee that the
  * iterator will never be exposed to scripts.
  */
-extern JS_FRIEND_API(JSBool)
-js_ValueToIterator(JSContext *cx, uintN flags, js::Value *vp);
+extern JSBool
+ValueToIterator(JSContext *cx, uintN flags, js::Value *vp);
 
-extern JS_FRIEND_API(bool)
-js_CloseIterator(JSContext *cx, JSObject *iterObj);
+extern bool
+CloseIterator(JSContext *cx, JSObject *iterObj);
+
+extern bool
+UnwindIteratorForException(JSContext *cx, JSObject *obj);
+
+}
 
 extern bool
 js_SuppressDeletedProperty(JSContext *cx, JSObject *obj, jsid id);
 
 extern bool
 js_SuppressDeletedElement(JSContext *cx, JSObject *obj, uint32_t index);
 
 extern bool
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -2748,17 +2748,17 @@ NewObject(JSContext *cx, Class *clasp, t
 
     RootTypeObject typeRoot(cx, &type);
 
     RootedVarShape shape(cx);
     shape = EmptyShape::getInitialShape(cx, clasp, type->proto, parent, kind);
     if (!shape)
         return NULL;
 
-    HeapValue *slots;
+    HeapSlot *slots;
     if (!PreallocateObjectDynamicSlots(cx, shape, &slots))
         return NULL;