Merge mozilla-central and inbound
authorEd Morley <emorley@mozilla.com>
Wed, 19 Jun 2013 15:51:08 +0100
changeset 135638 c908cc1206b52fa77e54e0dab8b2f19ee3af3c83
parent 135595 c12150cfdfef0afcba76233da774e5f64eadc06f (current diff)
parent 135637 62f26a2bab83dc5cd8f5eff0a32e751e2205ebc5 (diff)
child 135639 9d7ab37cf1d3a96ab1419865f18750a9f05011e5
push id24847
push userkwierso@gmail.com
push dateWed, 19 Jun 2013 23:38:15 +0000
treeherdermozilla-central@8ea92aeab783 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone24.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge mozilla-central and inbound
content/html/content/src/nsHTMLFormElement.cpp
content/html/content/src/nsHTMLFormElement.h
--- a/browser/base/content/test/Makefile.in
+++ b/browser/base/content/test/Makefile.in
@@ -54,31 +54,31 @@ endif
 #
 # browser_sanitizeDialog_treeView.js is disabled until the tree view is added
 # back to the clear recent history dialog (sanitize.xul), if it ever is (bug
 # 480169)
 
 # browser_drag.js is disabled, as it needs to be updated for the new behavior from bug 320638.
 
 # browser_bug321000.js is disabled because newline handling is shaky (bug 592528)
+# browser_bug386835.js is disabled for intermittent failures (bug 880226)
 
 _BROWSER_FILES = \
                  head.js \
                  browser_typeAheadFind.js \
                  browser_keywordSearch.js \
                  browser_keywordSearch_postData.js \
                  POSTSearchEngine.xml \
                  print_postdata.sjs \
                  browser_alltabslistener.js \
                  browser_bug304198.js \
                  title_test.svg \
                  browser_bug329212.js \
                  browser_bug356571.js \
                  browser_bug380960.js \
-                 browser_bug386835.js \
                  browser_bug405137.js \
                  browser_bug406216.js \
                  browser_bug409481.js \
                  browser_bug409624.js \
                  browser_bug413915.js \
                  browser_bug416661.js \
                  browser_bug417483.js \
                  browser_bug419612.js \
--- a/browser/components/sessionstore/test/Makefile.in
+++ b/browser/components/sessionstore/test/Makefile.in
@@ -10,16 +10,17 @@ relativesrcdir  = @relativesrcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 # browser_506482.js is disabled because of frequent failures (bug 538672)
 # browser_526613.js is disabled because of frequent failures (bug 534489)
 # browser_589246.js is disabled for leaking browser windows (bug 752467)
 # browser_580512.js is disabled for leaking browser windows (bug 752467)
 # browser_capabilities.js is disabled for using resources outside of the build network (bug 882575)
+# browser_707862.js & browser_705597.js are disabled whilst waiting for review (bug 861700 & bug 883592)
 
 MOCHITEST_BROWSER_FILES = \
 	head.js \
 	browser_attributes.js \
 	browser_dying_cache.js \
 	browser_form_restore_events.js \
 	browser_form_restore_events_sample.html \
 	browser_formdata_format.js \
@@ -127,18 +128,16 @@ MOCHITEST_BROWSER_FILES = \
 	browser_662743_sample.html \
 	browser_662812.js \
 	browser_665702-state_session.js \
 	browser_682507.js \
 	browser_687710.js \
 	browser_687710_2.js \
 	browser_694378.js \
 	browser_701377.js \
-	browser_705597.js \
-	browser_707862.js \
 	browser_739531.js \
 	browser_739531_sample.html \
 	browser_739805.js \
 	browser_819510_perwindowpb.js \
 	browser_833286_atomic_backup.js \
 	$(filter disabled-for-intermittent-failures--bug-766044, browser_459906_empty.html) \
 	$(filter disabled-for-intermittent-failures--bug-766044, browser_459906_sample.html) \
 	$(filter disabled-for-intermittent-failures--bug-765389, browser_461743_sample.html) \
--- a/build/unix/stdc++compat/Makefile.in
+++ b/build/unix/stdc++compat/Makefile.in
@@ -5,17 +5,16 @@
 DEPTH		= @DEPTH@
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 LIBRARY_NAME	= stdc++compat
-DISABLED_HOST_LIBRARY_NAME = host_stdc++compat
 FORCE_STATIC_LIB= 1
 STL_FLAGS =
 NO_EXPAND_LIBS = 1
 NO_PROFILE_GUIDED_OPTIMIZE = 1
 
   $(NULL)
 
 HOST_CPPSRCS = $(CPPSRCS)
--- a/caps/include/nsScriptSecurityManager.h
+++ b/caps/include/nsScriptSecurityManager.h
@@ -369,17 +369,17 @@ private:
     nsScriptSecurityManager();
     virtual ~nsScriptSecurityManager();
 
     bool SubjectIsPrivileged();
 
     static JSBool
     CheckObjectAccess(JSContext *cx, JSHandleObject obj,
                       JSHandleId id, JSAccessMode mode,
-                      JSMutableHandleValue vp);
+                      JS::MutableHandle<JS::Value> vp);
     
     // Decides, based on CSP, whether or not eval() and stuff can be executed.
     static JSBool
     ContentSecurityPolicyPermitsJSAction(JSContext *cx);
 
     // Returns null if a principal cannot be found; generally callers
     // should error out at that point.
     static nsIPrincipal* doGetObjectPrincipal(JS::Handle<JSObject*> obj);
--- a/caps/src/nsScriptSecurityManager.cpp
+++ b/caps/src/nsScriptSecurityManager.cpp
@@ -481,17 +481,17 @@ nsScriptSecurityManager::ContentSecurity
 
     return evalOK;
 }
 
 
 JSBool
 nsScriptSecurityManager::CheckObjectAccess(JSContext *cx, JSHandleObject obj,
                                            JSHandleId id, JSAccessMode mode,
-                                           JSMutableHandleValue vp)
+                                           JS::MutableHandle<JS::Value> vp)
 {
     // Get the security manager
     nsScriptSecurityManager *ssm =
         nsScriptSecurityManager::GetScriptSecurityManager();
 
     NS_ASSERTION(ssm, "Failed to get security manager service");
     if (!ssm)
         return JS_FALSE;
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -12,16 +12,17 @@ endif
 
 # Integrate with mozbuild-generated make files. We first verify that no
 # variables provided by the automatically generated .mk files are
 # present. If they are, this is a violation of the separation of
 # responsibility between Makefile.in and mozbuild files.
 _MOZBUILD_EXTERNAL_VARIABLES := \
   DIRS \
   HOST_CSRCS \
+  HOST_LIBRARY_NAME \
   MODULE \
   PARALLEL_DIRS \
   TEST_DIRS \
   TIERS \
   TOOL_DIRS \
   XPIDL_MODULE \
   $(NULL)
 
--- a/content/base/public/nsContentCID.h
+++ b/content/base/public/nsContentCID.h
@@ -38,26 +38,16 @@
 // {e7ba1480-1dea-11d3-830f-00104bed045e}
 #define NS_TEXT_ENCODER_CID \
 { 0xe7ba1480, 0x1dea, 0x11d3, {0x83, 0x0f, 0x00, 0x10, 0x4b, 0xed, 0x04, 0x5e} }
 
  // {7f915b01-98fc-11d4-8eb0-a803f80ff1bc}
 #define NS_HTMLCOPY_TEXT_ENCODER_CID \
 { 0x7f915b01, 0x98fc, 0x11d4, { 0x8e, 0xb0, 0xa8, 0x03, 0xf8, 0x0f, 0xf1, 0xbc } }
 
-#define NS_HTMLIMAGEELEMENT_CID                   \
-{ /* d6008c40-4dad-11d2-b328-00805f8a3859 */      \
- 0xd6008c40, 0x4dad, 0x11d2,                      \
- {0xb3, 0x28, 0x00, 0x80, 0x5f, 0x8a, 0x38, 0x59}}
-
-#define NS_HTMLOPTIONELEMENT_CID                  \
-{ /* a6cf90f5-15b3-11d2-932e-00805f8add32 */      \
- 0xa6cf90f5, 0x15b3, 0x11d2,                      \
- {0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32}}
-
 #define NS_NAMESPACEMANAGER_CID                   \
 { /* d9783472-8fe9-11d2-9d3c-0060088f9ff7 */      \
  0xd9783472, 0x8fe9, 0x11d2,                      \
  {0x9d, 0x3c, 0x00, 0x60, 0x08, 0x8f, 0x9f, 0xf7}}
 
 #define NS_CONTENTITERATOR_CID \
 {/* {a6cf90e3-15b3-11d2-932e-00805f8add32}*/ \
  0xa6cf90e3, 0x15b3, 0x11d2, {0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32 } }
--- a/content/base/public/nsINode.h
+++ b/content/base/public/nsINode.h
@@ -272,17 +272,17 @@ public:
   // Among the sub-classes that inherit (directly or indirectly) from nsINode,
   // measurement of the following members may be added later if DMD finds it is
   // worthwhile:
   // - nsGenericHTMLElement:  mForm, mFieldSet
   // - nsGenericHTMLFrameElement: mFrameLoader (bug 672539)
   // - HTMLBodyElement:       mContentStyleRule
   // - HTMLDataListElement:   mOptions
   // - HTMLFieldSetElement:   mElements, mDependentElements, mFirstLegend
-  // - nsHTMLFormElement:     many!
+  // - HTMLFormElement:       many!
   // - HTMLFrameSetElement:   mRowSpecs, mColSpecs
   // - HTMLInputElement:      mInputData, mFiles, mFileList, mStaticDocfileList
   // - nsHTMLMapElement:      mAreas
   // - HTMLMediaElement:      many!
   // - nsHTMLOutputElement:   mDefaultValue, mTokenList
   // - nsHTMLRowElement:      mCells
   // - nsHTMLSelectElement:   mOptions, mRestoreState
   // - nsHTMLTableElement:    mTBodies, mRows, mTableInheritedAttributes
--- a/content/base/src/nsFormData.cpp
+++ b/content/base/src/nsFormData.cpp
@@ -1,17 +1,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsFormData.h"
 #include "nsIVariant.h"
 #include "nsIInputStream.h"
 #include "nsIDOMFile.h"
-#include "nsHTMLFormElement.h"
+#include "mozilla/dom/HTMLFormElement.h"
 #include "mozilla/dom/FormDataBinding.h"
 #include "nsContentUtils.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 nsFormData::nsFormData(nsISupports* aOwner)
   : nsFormSubmission(NS_LITERAL_CSTRING("UTF-8"), nullptr)
@@ -104,23 +104,23 @@ nsFormData::Append(const nsAString& aNam
 /* virtual */ JSObject*
 nsFormData::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
 {
   return FormDataBinding::Wrap(aCx, aScope, this);
 }
 
 /* static */ already_AddRefed<nsFormData>
 nsFormData::Constructor(const GlobalObject& aGlobal,
-                        const Optional<nsHTMLFormElement*>& aFormElement,
+                        const Optional<NonNull<HTMLFormElement> >& aFormElement,
                         ErrorResult& aRv)
 {
   nsRefPtr<nsFormData> formData = new nsFormData(aGlobal.Get());
   if (aFormElement.WasPassed()) {
-    MOZ_ASSERT(aFormElement.Value());
-    aRv = aFormElement.Value()->WalkFormElements(formData);
+    // TODO: this should ...Value().WalkFromElements(formData); - Bug 883827
+    aRv = aFormElement.Value().get()->WalkFormElements(formData);
   }
   return formData.forget();
 }
 
 // -------------------------------------------------------------------------
 // nsIXHRSendable
 
 NS_IMETHODIMP
--- a/content/base/src/nsFormData.h
+++ b/content/base/src/nsFormData.h
@@ -9,23 +9,23 @@
 #include "nsIDOMFormData.h"
 #include "nsIXMLHttpRequest.h"
 #include "nsFormSubmission.h"
 #include "nsWrapperCache.h"
 #include "nsTArray.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/dom/BindingDeclarations.h"
 
-class nsHTMLFormElement;
 class nsIDOMFile;
 
 namespace mozilla {
 class ErrorResult;
 
 namespace dom {
+class HTMLFormElement;
 class GlobalObject;
 } // namespace dom
 } // namespace mozilla
 
 class nsFormData : public nsIDOMFormData,
                    public nsIXHRSendable,
                    public nsFormSubmission,
                    public nsWrapperCache
@@ -47,17 +47,17 @@ public:
   // WebIDL
   nsISupports*
   GetParentObject() const
   {
     return mOwner;
   }
   static already_AddRefed<nsFormData>
   Constructor(const mozilla::dom::GlobalObject& aGlobal,
-              const mozilla::dom::Optional<nsHTMLFormElement*>& aFormElement,
+              const mozilla::dom::Optional<mozilla::dom::NonNull<mozilla::dom::HTMLFormElement> >& aFormElement,
               mozilla::ErrorResult& aRv);
   void Append(const nsAString& aName, const nsAString& aValue);
   void Append(const nsAString& aName, nsIDOMBlob* aBlob,
               const mozilla::dom::Optional<nsAString>& aFilename);
 
   // nsFormSubmission
   virtual nsresult GetEncodedSubmission(nsIURI* aURI,
                                         nsIInputStream** aPostDataStream) MOZ_OVERRIDE;
--- a/content/base/src/nsFrameLoader.cpp
+++ b/content/base/src/nsFrameLoader.cpp
@@ -293,17 +293,17 @@ nsFrameLoader::nsFrameLoader(Element* aO
   ResetPermissionManagerStatus();
 }
 
 nsFrameLoader*
 nsFrameLoader::Create(Element* aOwner, bool aNetworkCreated)
 {
   NS_ENSURE_TRUE(aOwner, nullptr);
   nsIDocument* doc = aOwner->OwnerDoc();
-  NS_ENSURE_TRUE(!doc->GetDisplayDocument() &&
+  NS_ENSURE_TRUE(!doc->IsResourceDoc() &&
                  ((!doc->IsLoadedAsData() && aOwner->GetCurrentDoc()) ||
                    doc->IsStaticDocument()),
                  nullptr);
 
   return new nsFrameLoader(aOwner, aNetworkCreated);
 }
 
 NS_IMETHODIMP
@@ -1787,17 +1787,17 @@ nsresult
 nsFrameLoader::GetWindowDimensions(nsRect& aRect)
 {
   // Need to get outer window position here
   nsIDocument* doc = mOwnerContent->GetDocument();
   if (!doc) {
     return NS_ERROR_FAILURE;
   }
 
-  if (doc->GetDisplayDocument()) {
+  if (doc->IsResourceDoc()) {
     return NS_ERROR_FAILURE;
   }
 
   nsCOMPtr<nsIWebNavigation> parentAsWebNav =
     do_GetInterface(doc->GetScriptGlobalObject());
 
   if (!parentAsWebNav) {
     return NS_ERROR_FAILURE;
@@ -1962,17 +1962,17 @@ nsFrameLoader::TryRemoteBrowser()
 {
   NS_ASSERTION(!mRemoteBrowser, "TryRemoteBrowser called with a remote browser already?");
 
   nsIDocument* doc = mOwnerContent->GetDocument();
   if (!doc) {
     return false;
   }
 
-  if (doc->GetDisplayDocument()) {
+  if (doc->IsResourceDoc()) {
     // Don't allow subframe loads in external reference documents
     return false;
   }
 
   nsCOMPtr<nsIWebNavigation> parentAsWebNav =
     do_GetInterface(doc->GetScriptGlobalObject());
 
   if (!parentAsWebNav) {
--- a/content/base/src/nsObjectLoadingContent.cpp
+++ b/content/base/src/nsObjectLoadingContent.cpp
@@ -1056,18 +1056,50 @@ NS_IMETHODIMP
 nsObjectLoadingContent::GetContentTypeForMIMEType(const nsACString& aMIMEType,
                                                   uint32_t* aType)
 {
   *aType = GetTypeOfContent(PromiseFlatCString(aMIMEType));
   return NS_OK;
 }
 
 // nsIInterfaceRequestor
+// We use a shim class to implement this so that JS consumers still
+// see an interface requestor even though WebIDL bindings don't expose
+// that stuff.
+class ObjectInterfaceRequestorShim MOZ_FINAL : public nsIInterfaceRequestor,
+                                               public nsIChannelEventSink
+{
+public:
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(ObjectInterfaceRequestorShim,
+                                           nsIInterfaceRequestor)
+  NS_DECL_NSIINTERFACEREQUESTOR
+  NS_FORWARD_NSICHANNELEVENTSINK(mContent->)
+
+  ObjectInterfaceRequestorShim(nsIChannelEventSink* aContent)
+    : mContent(aContent)
+  {}
+
+protected:
+  nsRefPtr<nsIChannelEventSink> mContent;
+};
+
+NS_IMPL_CYCLE_COLLECTION_1(ObjectInterfaceRequestorShim, mContent)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ObjectInterfaceRequestorShim)
+  NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
+  NS_INTERFACE_MAP_ENTRY(nsIChannelEventSink)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInterfaceRequestor)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(ObjectInterfaceRequestorShim)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(ObjectInterfaceRequestorShim)
+
 NS_IMETHODIMP
-nsObjectLoadingContent::GetInterface(const nsIID & aIID, void **aResult)
+ObjectInterfaceRequestorShim::GetInterface(const nsIID & aIID, void **aResult)
 {
   if (aIID.Equals(NS_GET_IID(nsIChannelEventSink))) {
     nsIChannelEventSink* sink = this;
     *aResult = sink;
     NS_ADDREF(sink);
     return NS_OK;
   }
   return NS_NOINTERFACE;
@@ -2074,17 +2106,19 @@ nsObjectLoadingContent::OpenChannel()
   nsCOMPtr<nsIContentSecurityPolicy> csp;
   rv = doc->NodePrincipal()->GetCsp(getter_AddRefs(csp));
   NS_ENSURE_SUCCESS(rv, rv);
   if (csp) {
     channelPolicy = do_CreateInstance("@mozilla.org/nschannelpolicy;1");
     channelPolicy->SetContentSecurityPolicy(csp);
     channelPolicy->SetLoadType(nsIContentPolicy::TYPE_OBJECT);
   }
-  rv = NS_NewChannel(getter_AddRefs(chan), mURI, nullptr, group, this,
+  nsRefPtr<ObjectInterfaceRequestorShim> shim =
+    new ObjectInterfaceRequestorShim(this);
+  rv = NS_NewChannel(getter_AddRefs(chan), mURI, nullptr, group, shim,
                      nsIChannel::LOAD_CALL_CONTENT_SNIFFERS |
                      nsIChannel::LOAD_CLASSIFY_URI,
                      channelPolicy);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Referrer
   nsCOMPtr<nsIHttpChannel> httpChan(do_QueryInterface(chan));
   if (httpChan) {
--- a/content/base/src/nsObjectLoadingContent.h
+++ b/content/base/src/nsObjectLoadingContent.h
@@ -11,17 +11,16 @@
  */
 
 #ifndef NSOBJECTLOADINGCONTENT_H_
 #define NSOBJECTLOADINGCONTENT_H_
 
 #include "mozilla/Attributes.h"
 #include "nsImageLoadingContent.h"
 #include "nsIStreamListener.h"
-#include "nsIInterfaceRequestor.h"
 #include "nsIChannelEventSink.h"
 #include "nsIObjectLoadingContent.h"
 #include "nsIRunnable.h"
 #include "nsPluginInstanceOwner.h"
 #include "nsIThreadInternal.h"
 #include "nsIFrame.h"
 #include "nsIFrameLoader.h"
 
@@ -31,17 +30,16 @@ class AutoSetInstantiatingToFalse;
 class nsObjectFrame;
 class nsFrameLoader;
 class nsXULElement;
 
 class nsObjectLoadingContent : public nsImageLoadingContent
                              , public nsIStreamListener
                              , public nsIFrameLoaderOwner
                              , public nsIObjectLoadingContent
-                             , public nsIInterfaceRequestor
                              , public nsIChannelEventSink
 {
   friend class AutoSetInstantiatingToFalse;
   friend class AutoSetLoadingToFalse;
   friend class CheckPluginStopEvent;
   friend class nsStopPluginRunnable;
   friend class nsAsyncInstantiateEvent;
 
@@ -95,17 +93,16 @@ class nsObjectLoadingContent : public ns
 
     nsObjectLoadingContent();
     virtual ~nsObjectLoadingContent();
 
     NS_DECL_NSIREQUESTOBSERVER
     NS_DECL_NSISTREAMLISTENER
     NS_DECL_NSIFRAMELOADEROWNER
     NS_DECL_NSIOBJECTLOADINGCONTENT
-    NS_DECL_NSIINTERFACEREQUESTOR
     NS_DECL_NSICHANNELEVENTSINK
 
     /**
      * Object state. This is a bitmask of NS_EVENT_STATEs epresenting the
      * current state of the object.
      */
     nsEventStates ObjectState() const;
 
--- a/content/events/src/nsIMEStateManager.cpp
+++ b/content/events/src/nsIMEStateManager.cpp
@@ -26,17 +26,17 @@
 #include "nsISelectionListener.h"
 #include "nsISelectionController.h"
 #include "nsIMutationObserver.h"
 #include "nsContentEventHandler.h"
 #include "nsIObserverService.h"
 #include "mozilla/Services.h"
 #include "nsIFormControl.h"
 #include "nsIForm.h"
-#include "nsHTMLFormElement.h"
+#include "mozilla/dom/HTMLFormElement.h"
 #include "mozilla/Attributes.h"
 #include "nsEventDispatcher.h"
 #include "TextComposition.h"
 #include "mozilla/Preferences.h"
 #include "nsAsyncDOMEvent.h"
 
 using namespace mozilla;
 using namespace mozilla::widget;
@@ -482,17 +482,17 @@ nsIMEStateManager::SetIMEState(const IME
       mozilla::dom::Element* formElement = control->GetFormElement();
       nsCOMPtr<nsIForm> form;
       if (control) {
         // is this a form and does it have a default submit element?
         if ((form = do_QueryInterface(formElement)) && form->GetDefaultSubmitElement()) {
           willSubmit = true;
         // is this an html form and does it only have a single text input element?
         } else if (formElement && formElement->Tag() == nsGkAtoms::form && formElement->IsHTML() &&
-                   static_cast<nsHTMLFormElement*>(formElement)->HasSingleTextControl()) {
+                   static_cast<dom::HTMLFormElement*>(formElement)->HasSingleTextControl()) {
           willSubmit = true;
         }
       }
       context.mActionHint.Assign(willSubmit ? control->GetType() == NS_FORM_INPUT_SEARCH
                                                 ? NS_LITERAL_STRING("search")
                                                 : NS_LITERAL_STRING("go")
                                             : formElement
                                                 ? NS_LITERAL_STRING("next")
--- a/content/html/content/src/HTMLButtonElement.cpp
+++ b/content/html/content/src/HTMLButtonElement.cpp
@@ -24,17 +24,17 @@
 #include "nsIDocument.h"
 #include "nsGUIEvent.h"
 #include "nsUnicharUtils.h"
 #include "nsLayoutUtils.h"
 #include "nsEventDispatcher.h"
 #include "nsPresState.h"
 #include "nsError.h"
 #include "nsFocusManager.h"
-#include "nsHTMLFormElement.h"
+#include "mozilla/dom/HTMLFormElement.h"
 #include "mozAutoDocUpdate.h"
 
 #define NS_IN_SUBMIT_CLICK      (1 << 0)
 #define NS_OUTER_ACTIVATE_EVENT (1 << 1)
 
 NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(Button)
 
 namespace mozilla {
@@ -366,17 +366,17 @@ HTMLButtonElement::PostHandleEvent(nsEve
                           mForm->HasAttr(kNameSpaceID_None, nsGkAtoms::novalidate) ||
                           // We know the element is a submit control, if this check is moved,
                           // make sure formnovalidate is used only if it's a submit control.
                           HasAttr(kNameSpaceID_None, nsGkAtoms::formnovalidate) ||
                           mForm->CheckValidFormSubmission())) {
           // TODO: removing this code and have the submit event sent by the form
           // see bug 592124.
           // Hold a strong ref while dispatching
-          nsRefPtr<nsHTMLFormElement> form(mForm);
+          nsRefPtr<HTMLFormElement> form(mForm);
           presShell->HandleDOMEventWithTarget(mForm, &event, &status);
           aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
         }
       }
     }
   } else if ((aVisitor.mItemFlags & NS_IN_SUBMIT_CLICK) && mForm) {
     // Tell the form to flush a possible pending submission.
     // the reason is that the script returned false (the event was
--- a/content/html/content/src/HTMLFieldSetElement.h
+++ b/content/html/content/src/HTMLFieldSetElement.h
@@ -5,17 +5,17 @@
 
 #ifndef mozilla_dom_HTMLFieldSetElement_h
 #define mozilla_dom_HTMLFieldSetElement_h
 
 #include "mozilla/Attributes.h"
 #include "nsGenericHTMLElement.h"
 #include "nsIDOMHTMLFieldSetElement.h"
 #include "nsIConstraintValidation.h"
-#include "nsHTMLFormElement.h"
+#include "mozilla/dom/HTMLFormElement.h"
 #include "mozilla/dom/ValidityState.h"
 
 namespace mozilla {
 namespace dom {
 
 class HTMLFieldSetElement : public nsGenericHTMLFormElement,
                             public nsIDOMHTMLFieldSetElement,
                             public nsIConstraintValidation
rename from content/html/content/src/nsHTMLFormElement.cpp
rename to content/html/content/src/HTMLFormElement.cpp
--- a/content/html/content/src/nsHTMLFormElement.cpp
+++ b/content/html/content/src/HTMLFormElement.cpp
@@ -1,13 +1,15 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#include "nsHTMLFormElement.h"
+
+#include "mozilla/dom/HTMLFormElement.h"
+#include "mozilla/dom/HTMLFormElementBinding.h"
 #include "nsIHTMLDocument.h"
 #include "nsEventStateManager.h"
 #include "nsEventStates.h"
 #include "nsGkAtoms.h"
 #include "nsStyleConsts.h"
 #include "nsPresContext.h"
 #include "nsIDocument.h"
 #include "nsIFormControlFrame.h"
@@ -52,43 +54,63 @@
 #include "nsIDOMHTMLButtonElement.h"
 #include "mozilla/dom/HTMLCollectionBinding.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "nsSandboxFlags.h"
 
 // images
 #include "mozilla/dom/HTMLImageElement.h"
 
-using namespace mozilla::dom;
+DOMCI_NODE_DATA(HTMLFormElement, mozilla::dom::HTMLFormElement)
+
+// construction, destruction
+nsGenericHTMLElement*
+NS_NewHTMLFormElement(already_AddRefed<nsINodeInfo> aNodeInfo,
+                      mozilla::dom::FromParser aFromParser)
+{
+  mozilla::dom::HTMLFormElement* it = new mozilla::dom::HTMLFormElement(aNodeInfo);
+
+  nsresult rv = it->Init();
+
+  if (NS_FAILED(rv)) {
+    delete it;
+    return nullptr;
+  }
+
+  return it;
+}
+
+namespace mozilla {
+namespace dom {
 
 static const int NS_FORM_CONTROL_LIST_HASHTABLE_SIZE = 16;
 
 static const uint8_t NS_FORM_AUTOCOMPLETE_ON  = 1;
 static const uint8_t NS_FORM_AUTOCOMPLETE_OFF = 0;
 
 static const nsAttrValue::EnumTable kFormAutocompleteTable[] = {
   { "on",  NS_FORM_AUTOCOMPLETE_ON },
   { "off", NS_FORM_AUTOCOMPLETE_OFF },
   { 0 }
 };
 // Default autocomplete value is 'on'.
 static const nsAttrValue::EnumTable* kFormDefaultAutocomplete = &kFormAutocompleteTable[0];
 
-// nsHTMLFormElement
-
-bool nsHTMLFormElement::gFirstFormSubmitted = false;
-bool nsHTMLFormElement::gPasswordManagerInitialized = false;
+// HTMLFormElement
+
+bool HTMLFormElement::gFirstFormSubmitted = false;
+bool HTMLFormElement::gPasswordManagerInitialized = false;
 
 
 // nsFormControlList
 class nsFormControlList : public nsIHTMLCollection,
                           public nsWrapperCache
 {
 public:
-  nsFormControlList(nsHTMLFormElement* aForm);
+  nsFormControlList(HTMLFormElement* aForm);
   virtual ~nsFormControlList();
 
   nsresult Init();
 
   void DropFormReference();
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
@@ -129,17 +151,17 @@ public:
 
   // nsWrapperCache
   virtual JSObject* WrapObject(JSContext *cx,
                                JS::Handle<JSObject*> scope) MOZ_OVERRIDE
   {
     return HTMLCollectionBinding::Wrap(cx, scope, this);
   }
 
-  nsHTMLFormElement* mForm;  // WEAK - the form owns me
+  HTMLFormElement* mForm;  // WEAK - the form owns me
 
   nsTArray<nsGenericHTMLFormElement*> mElements;  // Holds WEAK references - bug 36639
 
   // This array holds on to all form controls that are not contained
   // in mElements (form.elements in JS, see ShouldBeInFormControl()).
   // This is needed to properly clean up the bi-directional references
   // (both weak and strong) between the form and its form controls.
 
@@ -204,36 +226,19 @@ ShouldBeInElements(nsIFormControl* aForm
   // form.elements array
   //
   // NS_FORM_INPUT_IMAGE
   // NS_FORM_LABEL
 
   return false;
 }
 
-// nsHTMLFormElement implementation
-
-// construction, destruction
-nsGenericHTMLElement*
-NS_NewHTMLFormElement(already_AddRefed<nsINodeInfo> aNodeInfo,
-                      FromParser aFromParser)
-{
-  nsHTMLFormElement* it = new nsHTMLFormElement(aNodeInfo);
-
-  nsresult rv = it->Init();
-
-  if (NS_FAILED(rv)) {
-    delete it;
-    return nullptr;
-  }
-
-  return it;
-}
-
-nsHTMLFormElement::nsHTMLFormElement(already_AddRefed<nsINodeInfo> aNodeInfo)
+// HTMLFormElement implementation
+
+HTMLFormElement::HTMLFormElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsGenericHTMLElement(aNodeInfo),
     mGeneratingSubmit(false),
     mGeneratingReset(false),
     mIsSubmitting(false),
     mDeferSubmission(false),
     mNotifiedObservers(false),
     mNotifiedObserversResult(false),
     mSubmitPopupState(openAbused),
@@ -243,29 +248,31 @@ nsHTMLFormElement::nsHTMLFormElement(alr
     mDefaultSubmitElement(nullptr),
     mFirstSubmitInElements(nullptr),
     mFirstSubmitNotInElements(nullptr),
     mInvalidElementsCount(0),
     mEverTriedInvalidSubmit(false)
 {
   mImageNameLookupTable.Init(NS_FORM_CONTROL_LIST_HASHTABLE_SIZE);
   mPastNameLookupTable.Init(NS_FORM_CONTROL_LIST_HASHTABLE_SIZE);
+
+  SetIsDOMBinding();
 }
 
-nsHTMLFormElement::~nsHTMLFormElement()
+HTMLFormElement::~HTMLFormElement()
 {
   if (mControls) {
     mControls->DropFormReference();
   }
 
   Clear();
 }
 
 nsresult
-nsHTMLFormElement::Init()
+HTMLFormElement::Init()
 {
   mControls = new nsFormControlList(this);
   if (!mControls) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   nsresult rv = mControls->Init();
   
@@ -291,64 +298,77 @@ ElementTraverser(const nsAString& key, n
 {
   nsCycleCollectionTraversalCallback *cb = 
     static_cast<nsCycleCollectionTraversalCallback*>(userArg);
  
   cb->NoteXPCOMChild(element);
   return PL_DHASH_NEXT;
 }
 
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsHTMLFormElement,
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLFormElement,
                                                   nsGenericHTMLElement)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mControls)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mImageNameLookupTable)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPastNameLookupTable)
   tmp->mSelectedRadioButtons.EnumerateRead(ElementTraverser, &cb);
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsHTMLFormElement,
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLFormElement,
                                                 nsGenericHTMLElement)
   tmp->Clear();
+  ++tmp->mExpandoAndGeneration.generation;
+  tmp->mExpandoAndGeneration.expando = JS::UndefinedValue();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
-NS_IMPL_ADDREF_INHERITED(nsHTMLFormElement, Element)
-NS_IMPL_RELEASE_INHERITED(nsHTMLFormElement, Element)
-
-
-DOMCI_NODE_DATA(HTMLFormElement, nsHTMLFormElement)
-
-// QueryInterface implementation for nsHTMLFormElement
-NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsHTMLFormElement)
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(HTMLFormElement,
+                                               nsGenericHTMLElement)
+  if (tmp->PreservingWrapper()) {
+    NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK(mExpandoAndGeneration.expando);
+  }
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
+
+NS_IMPL_ADDREF_INHERITED(HTMLFormElement, Element)
+NS_IMPL_RELEASE_INHERITED(HTMLFormElement, Element)
+
+
+// QueryInterface implementation for HTMLFormElement
+NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(HTMLFormElement)
   NS_HTML_CONTENT_INTERFACES(nsGenericHTMLElement)
-  NS_INTERFACE_TABLE_INHERITED4(nsHTMLFormElement,
+  NS_INTERFACE_TABLE_INHERITED4(HTMLFormElement,
                                 nsIDOMHTMLFormElement,
                                 nsIForm,
                                 nsIWebProgressListener,
                                 nsIRadioGroupContainer)
   NS_INTERFACE_TABLE_TO_MAP_SEGUE
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(HTMLFormElement)
 NS_ELEMENT_INTERFACE_MAP_END
 
 
 // nsIDOMHTMLFormElement
 
-NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsHTMLFormElement)
+NS_IMPL_ELEMENT_CLONE_WITH_INIT(HTMLFormElement)
+
+nsIHTMLCollection*
+HTMLFormElement::Elements()
+{
+  return mControls;
+}
 
 NS_IMETHODIMP
-nsHTMLFormElement::GetElements(nsIDOMHTMLCollection** aElements)
+HTMLFormElement::GetElements(nsIDOMHTMLCollection** aElements)
 {
-  *aElements = mControls;
+  *aElements = Elements();
   NS_ADDREF(*aElements);
   return NS_OK;
 }
 
 nsresult
-nsHTMLFormElement::SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
-                           nsIAtom* aPrefix, const nsAString& aValue,
-                           bool aNotify)
+HTMLFormElement::SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
+                         nsIAtom* aPrefix, const nsAString& aValue,
+                         bool aNotify)
 {
   if ((aName == nsGkAtoms::action || aName == nsGkAtoms::target) &&
       aNameSpaceID == kNameSpaceID_None) {
     if (mPendingSubmission) {
       // aha, there is a pending submission that means we're in
       // the script and we need to flush it. let's tell it
       // that the event was ignored to force the flush.
       // the second argument is not playing a role at all.
@@ -360,18 +380,18 @@ nsHTMLFormElement::SetAttr(int32_t aName
     ForgetCurrentSubmission();
     mNotifiedObservers = notifiedObservers;
   }
   return nsGenericHTMLElement::SetAttr(aNameSpaceID, aName, aPrefix, aValue,
                                        aNotify);
 }
 
 nsresult
-nsHTMLFormElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
-                                const nsAttrValue* aValue, bool aNotify)
+HTMLFormElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
+                              const nsAttrValue* aValue, bool aNotify)
 {
   if (aName == nsGkAtoms::novalidate && aNameSpaceID == kNameSpaceID_None) {
     // Update all form elements states because they might be [no longer]
     // affected by :-moz-ui-valid or :-moz-ui-invalid.
     for (uint32_t i = 0, length = mControls->mElements.Length();
          i < length; ++i) {
       mControls->mElements[i]->UpdateState(true);
     }
@@ -380,67 +400,73 @@ nsHTMLFormElement::AfterSetAttr(int32_t 
          i < length; ++i) {
       mControls->mNotInElements[i]->UpdateState(true);
     }
   }
 
   return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue, aNotify);
 }
 
-NS_IMPL_STRING_ATTR(nsHTMLFormElement, AcceptCharset, acceptcharset)
-NS_IMPL_ACTION_ATTR(nsHTMLFormElement, Action, action)
-NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLFormElement, Autocomplete, autocomplete,
+NS_IMPL_STRING_ATTR(HTMLFormElement, AcceptCharset, acceptcharset)
+NS_IMPL_ACTION_ATTR(HTMLFormElement, Action, action)
+NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(HTMLFormElement, Autocomplete, autocomplete,
                                 kFormDefaultAutocomplete->tag)
-NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLFormElement, Enctype, enctype,
+NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(HTMLFormElement, Enctype, enctype,
                                 kFormDefaultEnctype->tag)
-NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLFormElement, Method, method,
+NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(HTMLFormElement, Method, method,
                                 kFormDefaultMethod->tag)
-NS_IMPL_BOOL_ATTR(nsHTMLFormElement, NoValidate, novalidate)
-NS_IMPL_STRING_ATTR(nsHTMLFormElement, Name, name)
-NS_IMPL_STRING_ATTR(nsHTMLFormElement, Target, target)
-
-NS_IMETHODIMP
-nsHTMLFormElement::Submit()
+NS_IMPL_BOOL_ATTR(HTMLFormElement, NoValidate, novalidate)
+NS_IMPL_STRING_ATTR(HTMLFormElement, Name, name)
+NS_IMPL_STRING_ATTR(HTMLFormElement, Target, target)
+
+void
+HTMLFormElement::Submit(ErrorResult& aRv)
 {
   // Send the submit event
-  nsresult rv = NS_OK;
   nsRefPtr<nsPresContext> presContext = GetPresContext();
   if (mPendingSubmission) {
     // aha, we have a pending submission that was not flushed
     // (this happens when form.submit() is called twice)
     // we have to delete it and build a new one since values
     // might have changed inbetween (we emulate IE here, that's all)
     mPendingSubmission = nullptr;
   }
 
-  rv = DoSubmitOrReset(nullptr, NS_FORM_SUBMIT);
-  return rv;
+  aRv = DoSubmitOrReset(nullptr, NS_FORM_SUBMIT);
 }
 
 NS_IMETHODIMP
-nsHTMLFormElement::Reset()
+HTMLFormElement::Submit()
+{
+  ErrorResult rv;
+  Submit(rv);
+  return rv.ErrorCode();
+}
+
+NS_IMETHODIMP
+HTMLFormElement::Reset()
 {
   nsFormEvent event(true, NS_FORM_RESET);
   nsEventDispatcher::Dispatch(static_cast<nsIContent*>(this), nullptr,
                               &event);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsHTMLFormElement::CheckValidity(bool* retVal)
+HTMLFormElement::CheckValidity(bool* retVal)
 {
-  *retVal = CheckFormValidity(nullptr);
+  *retVal = CheckValidity();
   return NS_OK;
 }
 
 bool
-nsHTMLFormElement::ParseAttribute(int32_t aNamespaceID,
-                                  nsIAtom* aAttribute,
-                                  const nsAString& aValue,
-                                  nsAttrValue& aResult)
+HTMLFormElement::ParseAttribute(int32_t aNamespaceID,
+                                nsIAtom* aAttribute,
+                                const nsAString& aValue,
+                                nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     if (aAttribute == nsGkAtoms::method) {
       return aResult.ParseEnumValue(aValue, kFormMethodTable, false);
     }
     if (aAttribute == nsGkAtoms::enctype) {
       return aResult.ParseEnumValue(aValue, kFormEnctypeTable, false);
     }
@@ -449,19 +475,19 @@ nsHTMLFormElement::ParseAttribute(int32_
     }
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
 nsresult
-nsHTMLFormElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers)
+HTMLFormElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
+                            nsIContent* aBindingParent,
+                            bool aCompileEventHandlers)
 {
   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
                                                  aBindingParent,
                                                  aCompileEventHandlers);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIHTMLDocument> htmlDoc(do_QueryInterface(aDocument));
   if (htmlDoc) {
@@ -563,17 +589,17 @@ CollectOrphans(nsINode* aRemovalRoot,
       nsCOMPtr<nsIDOMHTMLFormElement> form = node->GetForm();
       NS_ASSERTION(form == aThisForm, "How did that happen?");
     }
 #endif /* DEBUG */
   }
 }
 
 void
-nsHTMLFormElement::UnbindFromTree(bool aDeep, bool aNullParent)
+HTMLFormElement::UnbindFromTree(bool aDeep, bool aNullParent)
 {
   nsCOMPtr<nsIHTMLDocument> oldDocument = do_QueryInterface(GetCurrentDoc());
 
   // Mark all of our controls as maybe being orphans
   MarkOrphans(mControls->mElements);
   MarkOrphans(mControls->mNotInElements);
   MarkOrphans(mImageElements);
 
@@ -607,17 +633,17 @@ nsHTMLFormElement::UnbindFromTree(bool a
 
   if (oldDocument) {
     oldDocument->RemovedForm();
   }
   ForgetCurrentSubmission();
 }
 
 nsresult
-nsHTMLFormElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
+HTMLFormElement::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
 {
   aVisitor.mWantsWillHandleEvent = true;
   if (aVisitor.mEvent->originalTarget == static_cast<nsIContent*>(this)) {
     uint32_t msg = aVisitor.mEvent->message;
     if (msg == NS_FORM_SUBMIT) {
       if (mGeneratingSubmit) {
         aVisitor.mCanHandle = false;
         return NS_OK;
@@ -636,32 +662,32 @@ nsHTMLFormElement::PreHandleEvent(nsEven
       }
       mGeneratingReset = true;
     }
   }
   return nsGenericHTMLElement::PreHandleEvent(aVisitor);
 }
 
 nsresult
-nsHTMLFormElement::WillHandleEvent(nsEventChainPostVisitor& aVisitor)
+HTMLFormElement::WillHandleEvent(nsEventChainPostVisitor& aVisitor)
 {
   // If this is the bubble stage and there is a nested form below us which
   // received a submit event we do *not* want to handle the submit event
   // for this form too.
   if ((aVisitor.mEvent->message == NS_FORM_SUBMIT ||
        aVisitor.mEvent->message == NS_FORM_RESET) &&
       aVisitor.mEvent->mFlags.mInBubblingPhase &&
       aVisitor.mEvent->originalTarget != static_cast<nsIContent*>(this)) {
     aVisitor.mEvent->mFlags.mPropagationStopped = true;
   }
   return NS_OK;
 }
 
 nsresult
-nsHTMLFormElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
+HTMLFormElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
 {
   if (aVisitor.mEvent->originalTarget == static_cast<nsIContent*>(this)) {
     uint32_t msg = aVisitor.mEvent->message;
     if (msg == NS_FORM_SUBMIT) {
       // let the form know not to defer subsequent submissions
       mDeferSubmission = false;
     }
 
@@ -698,18 +724,18 @@ nsHTMLFormElement::PostHandleEvent(nsEve
     else if (msg == NS_FORM_RESET) {
       mGeneratingReset = false;
     }
   }
   return NS_OK;
 }
 
 nsresult
-nsHTMLFormElement::DoSubmitOrReset(nsEvent* aEvent,
-                                   int32_t aMessage)
+HTMLFormElement::DoSubmitOrReset(nsEvent* aEvent,
+                                 int32_t aMessage)
 {
   // Make sure the presentation is up-to-date
   nsIDocument* doc = GetCurrentDoc();
   if (doc) {
     doc->FlushPendingNotifications(Flush_ContentAndNotify);
   }
 
   // JBK Don't get form frames anymore - bug 34297
@@ -728,17 +754,17 @@ nsHTMLFormElement::DoSubmitOrReset(nsEve
     return DoSubmit(aEvent);
   }
 
   MOZ_ASSERT(false);
   return NS_OK;
 }
 
 nsresult
-nsHTMLFormElement::DoReset()
+HTMLFormElement::DoReset()
 {
   // JBK walk the elements[] array instead of form frame controls - bug 34297
   uint32_t numElements = GetElementCount();
   for (uint32_t elementX = 0; elementX < numElements; ++elementX) {
     // Hold strong ref in case the reset does something weird
     nsCOMPtr<nsIFormControl> controlNode = GetElementAt(elementX);
     if (controlNode) {
       controlNode->Reset();
@@ -750,17 +776,17 @@ nsHTMLFormElement::DoReset()
 
 #define NS_ENSURE_SUBMIT_SUCCESS(rv)                                          \
   if (NS_FAILED(rv)) {                                                        \
     ForgetCurrentSubmission();                                                \
     return rv;                                                                \
   }
 
 nsresult
-nsHTMLFormElement::DoSubmit(nsEvent* aEvent)
+HTMLFormElement::DoSubmit(nsEvent* aEvent)
 {
   NS_ASSERTION(GetCurrentDoc(), "Should never get here without a current doc");
 
   if (mIsSubmitting) {
     NS_WARNING("Preventing double form submission");
     // XXX Should this return an error?
     return NS_OK;
   }
@@ -804,18 +830,18 @@ nsHTMLFormElement::DoSubmit(nsEvent* aEv
   
   // 
   // perform the submission
   //
   return SubmitSubmission(submission); 
 }
 
 nsresult
-nsHTMLFormElement::BuildSubmission(nsFormSubmission** aFormSubmission, 
-                                   nsEvent* aEvent)
+HTMLFormElement::BuildSubmission(nsFormSubmission** aFormSubmission, 
+                                 nsEvent* aEvent)
 {
   NS_ASSERTION(!mPendingSubmission, "tried to build two submissions!");
 
   // Get the originating frame (failure is non-fatal)
   nsGenericHTMLElement* originatingElement = nullptr;
   if (aEvent) {
     if (NS_FORM_EVENT == aEvent->eventStructType) {
       nsIContent* originator = ((nsFormEvent *)aEvent)->originator;
@@ -842,17 +868,17 @@ nsHTMLFormElement::BuildSubmission(nsFor
   //
   rv = WalkFormElements(*aFormSubmission);
   NS_ENSURE_SUBMIT_SUCCESS(rv);
 
   return NS_OK;
 }
 
 nsresult
-nsHTMLFormElement::SubmitSubmission(nsFormSubmission* aFormSubmission)
+HTMLFormElement::SubmitSubmission(nsFormSubmission* aFormSubmission)
 {
   nsresult rv;
   nsIContent* originatingElement = aFormSubmission->GetOriginatingElement();
 
   //
   // Get the action and target
   //
   nsCOMPtr<nsIURI> actionURI;
@@ -976,19 +1002,19 @@ nsHTMLFormElement::SubmitSubmission(nsFo
   } else {
     ForgetCurrentSubmission();
   }
 
   return rv;
 }
 
 nsresult
-nsHTMLFormElement::NotifySubmitObservers(nsIURI* aActionURL,
-                                         bool* aCancelSubmit,
-                                         bool    aEarlyNotify)
+HTMLFormElement::NotifySubmitObservers(nsIURI* aActionURL,
+                                       bool* aCancelSubmit,
+                                       bool    aEarlyNotify)
 {
   // If this is the first form, bring alive the first form submit
   // category observers
   if (!gFirstFormSubmitted) {
     gFirstFormSubmitted = true;
     NS_CreateServicesFromCategory(NS_FIRST_FORMSUBMIT_CATEGORY,
                                   nullptr,
                                   NS_FIRST_FORMSUBMIT_CATEGORY);
@@ -1035,17 +1061,17 @@ nsHTMLFormElement::NotifySubmitObservers
     }
   }
 
   return rv;
 }
 
 
 nsresult
-nsHTMLFormElement::WalkFormElements(nsFormSubmission* aFormSubmission)
+HTMLFormElement::WalkFormElements(nsFormSubmission* aFormSubmission)
 {
   nsTArray<nsGenericHTMLFormElement*> sortedControls;
   nsresult rv = mControls->GetSortedControls(sortedControls);
   NS_ENSURE_SUCCESS(rv, rv);
 
   uint32_t len = sortedControls.Length();
 
   // Hold a reference to the elements so they can't be deleted while
@@ -1068,25 +1094,33 @@ nsHTMLFormElement::WalkFormElements(nsFo
   }
 
   return NS_OK;
 }
 
 // nsIForm
 
 NS_IMETHODIMP_(uint32_t)
-nsHTMLFormElement::GetElementCount() const 
+HTMLFormElement::GetElementCount() const 
 {
   uint32_t count = 0;
   mControls->GetLength(&count); 
   return count;
 }
 
+Element*
+HTMLFormElement::IndexedGetter(uint32_t aIndex, bool &aFound)
+{
+  Element* element = mControls->mElements.SafeElementAt(aIndex, nullptr);
+  aFound = element != nullptr;
+  return element;
+}
+
 NS_IMETHODIMP_(nsIFormControl*)
-nsHTMLFormElement::GetElementAt(int32_t aIndex) const
+HTMLFormElement::GetElementAt(int32_t aIndex) const
 {
   return mControls->mElements.SafeElementAt(aIndex, nullptr);
 }
 
 /**
  * Compares the position of aControl1 and aControl2 in the document
  * @param aControl1 First control to compare.
  * @param aControl2 Second control to compare.
@@ -1149,17 +1183,17 @@ AssertDocumentOrder(const nsTArray<nsGen
                                               aForm) < 0,
                    "Form controls not ordered correctly");
     }
   }
 }
 #endif
 
 void
-nsHTMLFormElement::PostPasswordEvent()
+HTMLFormElement::PostPasswordEvent()
 {
   // Don't fire another add event if we have a pending add event.
   if (mFormPasswordEvent.get()) {
     return;
   }
 
   nsRefPtr<FormPasswordEvent> event =
     new FormPasswordEvent(this, NS_LITERAL_STRING("DOMFormHasPassword"));
@@ -1167,17 +1201,17 @@ nsHTMLFormElement::PostPasswordEvent()
   event->PostDOMEvent();
 }
 
 // This function return true if the element, once appended, is the last one in
 // the array.
 template<typename ElementType>
 static bool
 AddElementToList(nsTArray<ElementType*>& aList, ElementType* aChild,
-                 nsHTMLFormElement* aForm)
+                 HTMLFormElement* aForm)
 {
   NS_ASSERTION(aList.IndexOf(aChild) == aList.NoIndex,
                "aChild already in aList");
 
   uint32_t count = aList.Length();
   ElementType* element;
   bool lastElement = false;
 
@@ -1214,18 +1248,18 @@ AddElementToList(nsTArray<ElementType*>&
     // WEAK - don't addref
     aList.InsertElementAt(low, aChild);
   }
 
   return lastElement;
 }
 
 nsresult
-nsHTMLFormElement::AddElement(nsGenericHTMLFormElement* aChild,
-                              bool aUpdateValidity, bool aNotify)
+HTMLFormElement::AddElement(nsGenericHTMLFormElement* aChild,
+                            bool aUpdateValidity, bool aNotify)
 {
   // If an element has a @form, we can assume it *might* be able to not have
   // a parent and still be in the form.
   NS_ASSERTION(aChild->HasAttr(kNameSpaceID_None, nsGkAtoms::form) ||
                aChild->GetParent(),
                "Form control should have a parent");
 
   // Determine whether to add the new element to the elements or
@@ -1319,26 +1353,26 @@ nsHTMLFormElement::AddElement(nsGenericH
       static_cast<HTMLInputElement*>(aChild);
     radio->AddedToRadioGroup();
   }
 
   return NS_OK;
 }
 
 nsresult
-nsHTMLFormElement::AddElementToTable(nsGenericHTMLFormElement* aChild,
-                                     const nsAString& aName)
+HTMLFormElement::AddElementToTable(nsGenericHTMLFormElement* aChild,
+                                   const nsAString& aName)
 {
   return mControls->AddElementToTable(aChild, aName);  
 }
 
 
 nsresult
-nsHTMLFormElement::RemoveElement(nsGenericHTMLFormElement* aChild,
-                                 bool aUpdateValidity)
+HTMLFormElement::RemoveElement(nsGenericHTMLFormElement* aChild,
+                               bool aUpdateValidity)
 {
   //
   // Remove it from the radio group if it's a radio button
   //
   nsresult rv = NS_OK;
   if (aChild->GetType() == NS_FORM_INPUT_RADIO) {
     nsRefPtr<HTMLInputElement> radio =
       static_cast<HTMLInputElement*>(aChild);
@@ -1396,17 +1430,17 @@ nsHTMLFormElement::RemoveElement(nsGener
       UpdateValidity(true);
     }
   }
 
   return rv;
 }
 
 void
-nsHTMLFormElement::HandleDefaultSubmitRemoval()
+HTMLFormElement::HandleDefaultSubmitRemoval()
 {
   if (mDefaultSubmitElement) {
     // Already got reset somehow; nothing else to do here
     return;
   }
 
   if (!mFirstSubmitNotInElements) {
     mDefaultSubmitElement = mFirstSubmitInElements;
@@ -1427,30 +1461,31 @@ nsHTMLFormElement::HandleDefaultSubmitRe
                    "What happened here?");
 
   // Notify about change if needed.
   if (mDefaultSubmitElement) {
     mDefaultSubmitElement->UpdateState(true);
   }
 }
 
-static nsresult
-RemoveElementFromTableInternal(
+nsresult
+HTMLFormElement::RemoveElementFromTableInternal(
   nsInterfaceHashtable<nsStringHashKey,nsISupports>& aTable,
   nsIContent* aChild, const nsAString& aName)
 {
   nsCOMPtr<nsISupports> supports;
 
   if (!aTable.Get(aName, getter_AddRefs(supports)))
     return NS_OK;
 
   // Single element in the hash, just remove it if it's the one
   // we're trying to remove...
   if (supports == aChild) {
     aTable.Remove(aName);
+    ++mExpandoAndGeneration.generation;
     return NS_OK;
   }
 
   nsCOMPtr<nsIContent> content(do_QueryInterface(supports));
   if (content) {
     return NS_OK;
   }
 
@@ -1464,16 +1499,17 @@ RemoveElementFromTableInternal(
 
   uint32_t length = 0;
   list->GetLength(&length);
 
   if (!length) {
     // If the list is empty we remove if from our hash, this shouldn't
     // happen tho
     aTable.Remove(aName);
+    ++mExpandoAndGeneration.generation;
   } else if (length == 1) {
     // Only one element left, replace the list in the hash with the
     // single element.
     nsIContent* node = list->Item(0);
     if (node) {
       aTable.Put(aName, node);
     }
   }
@@ -1485,68 +1521,92 @@ static PLDHashOperator
 RemovePastNames(const nsAString& aName,
                 nsCOMPtr<nsISupports>& aData,
                 void* aClosure)
 {
   return aClosure == aData ? PL_DHASH_REMOVE : PL_DHASH_NEXT;
 }
 
 nsresult
-nsHTMLFormElement::RemoveElementFromTable(nsGenericHTMLFormElement* aElement,
-                                          const nsAString& aName,
-                                          RemoveElementReason aRemoveReason)
+HTMLFormElement::RemoveElementFromTable(nsGenericHTMLFormElement* aElement,
+                                        const nsAString& aName,
+                                        RemoveElementReason aRemoveReason)
 {
   // If the element is being removed from the form, we have to remove it from
   // the past names map.
   if (aRemoveReason == ElementRemoved) {
+    uint32_t oldCount = mPastNameLookupTable.Count();
     mPastNameLookupTable.Enumerate(RemovePastNames, aElement);
+    if (oldCount != mPastNameLookupTable.Count()) {
+      ++mExpandoAndGeneration.generation;
+    }
   }
 
   return mControls->RemoveElementFromTable(aElement, aName);
 }
 
 already_AddRefed<nsISupports>
-nsHTMLFormElement::FindNamedItem(const nsAString& aName,
-                                 nsWrapperCache** aCache)
+HTMLFormElement::NamedGetter(const nsAString& aName, bool &aFound)
 {
+  aFound = true;
+
   nsCOMPtr<nsISupports> result = DoResolveName(aName, true);
   if (result) {
-    // FIXME Get the wrapper cache from DoResolveName.
-    *aCache = nullptr;
     AddToPastNamesMap(aName, result);
     return result.forget();
   }
 
   result = mImageNameLookupTable.GetWeak(aName);
   if (result) {
-    *aCache = nullptr;
     AddToPastNamesMap(aName, result);
     return result.forget();
   }
 
   result = mPastNameLookupTable.GetWeak(aName);
   if (result) {
+    return result.forget();
+  }
+
+  aFound = false;
+  return nullptr;
+}
+
+void
+HTMLFormElement::GetSupportedNames(nsTArray<nsString >& aRetval)
+{
+  // TODO https://www.w3.org/Bugs/Public/show_bug.cgi?id=22320
+}
+
+already_AddRefed<nsISupports>
+HTMLFormElement::FindNamedItem(const nsAString& aName,
+                               nsWrapperCache** aCache)
+{
+  // FIXME Get the wrapper cache from DoResolveName.
+
+  bool found;
+  nsCOMPtr<nsISupports> result = NamedGetter(aName, found);
+  if (result) {
     *aCache = nullptr;
     return result.forget();
   }
 
   return nullptr;
 }
 
 already_AddRefed<nsISupports>
-nsHTMLFormElement::DoResolveName(const nsAString& aName,
-                                 bool aFlushContent)
+HTMLFormElement::DoResolveName(const nsAString& aName,
+                               bool aFlushContent)
 {
   nsCOMPtr<nsISupports> result =
     mControls->NamedItemInternal(aName, aFlushContent);
   return result.forget();
 }
 
 void
-nsHTMLFormElement::OnSubmitClickBegin(nsIContent* aOriginatingElement)
+HTMLFormElement::OnSubmitClickBegin(nsIContent* aOriginatingElement)
 {
   mDeferSubmission = true;
 
   // Prepare to run NotifySubmitObservers early before the
   // scripts on the page get to modify the form data, possibly
   // throwing off any password manager. (bug 257781)
   nsCOMPtr<nsIURI> actionURI;
   nsresult rv;
@@ -1564,36 +1624,36 @@ nsHTMLFormElement::OnSubmitClickBegin(ns
     if (NS_SUCCEEDED(rv)) {
       mNotifiedObservers = true;
       mNotifiedObserversResult = cancelSubmit;
     }
   }
 }
 
 void
-nsHTMLFormElement::OnSubmitClickEnd()
+HTMLFormElement::OnSubmitClickEnd()
 {
   mDeferSubmission = false;
 }
 
 void
-nsHTMLFormElement::FlushPendingSubmission()
+HTMLFormElement::FlushPendingSubmission()
 {
   if (mPendingSubmission) {
     // Transfer owning reference so that the submissioin doesn't get deleted
     // if we reenter
     nsAutoPtr<nsFormSubmission> submission = mPendingSubmission;
 
     SubmitSubmission(submission);
   }
 }
 
 nsresult
-nsHTMLFormElement::GetActionURL(nsIURI** aActionURL,
-                                nsIContent* aOriginatingElement)
+HTMLFormElement::GetActionURL(nsIURI** aActionURL,
+                              nsIContent* aOriginatingElement)
 {
   nsresult rv = NS_OK;
 
   *aActionURL = nullptr;
 
   //
   // Grab the URL string
   //
@@ -1688,27 +1748,27 @@ nsHTMLFormElement::GetActionURL(nsIURI**
   //
   *aActionURL = actionURL;
   NS_ADDREF(*aActionURL);
 
   return rv;
 }
 
 NS_IMETHODIMP_(nsIFormControl*)
-nsHTMLFormElement::GetDefaultSubmitElement() const
+HTMLFormElement::GetDefaultSubmitElement() const
 {
   NS_PRECONDITION(mDefaultSubmitElement == mFirstSubmitInElements ||
                   mDefaultSubmitElement == mFirstSubmitNotInElements,
                   "What happened here?");
   
   return mDefaultSubmitElement;
 }
 
 bool
-nsHTMLFormElement::IsDefaultSubmitElement(const nsIFormControl* aControl) const
+HTMLFormElement::IsDefaultSubmitElement(const nsIFormControl* aControl) const
 {
   NS_PRECONDITION(aControl, "Unexpected call");
 
   if (aControl == mDefaultSubmitElement) {
     // Yes, it is
     return true;
   }
 
@@ -1733,65 +1793,69 @@ nsHTMLFormElement::IsDefaultSubmitElemen
   nsIFormControl* defaultSubmit =
     CompareFormControlPosition(mFirstSubmitInElements,
                                mFirstSubmitNotInElements, this) < 0 ?
       mFirstSubmitInElements : mFirstSubmitNotInElements;
   return aControl == defaultSubmit;
 }
 
 bool
-nsHTMLFormElement::HasSingleTextControl() const
+HTMLFormElement::HasSingleTextControl() const
 {
   // Input text controls are always in the elements list.
   uint32_t numTextControlsFound = 0;
   uint32_t length = mControls->mElements.Length();
   for (uint32_t i = 0; i < length && numTextControlsFound < 2; ++i) {
     if (mControls->mElements[i]->IsSingleLineTextControl(false)) {
       numTextControlsFound++;
     }
   }
   return numTextControlsFound == 1;
 }
 
 NS_IMETHODIMP
-nsHTMLFormElement::GetEncoding(nsAString& aEncoding)
+HTMLFormElement::GetEncoding(nsAString& aEncoding)
 {
   return GetEnctype(aEncoding);
 }
  
 NS_IMETHODIMP
-nsHTMLFormElement::SetEncoding(const nsAString& aEncoding)
+HTMLFormElement::SetEncoding(const nsAString& aEncoding)
 {
   return SetEnctype(aEncoding);
 }
 
+int32_t
+HTMLFormElement::Length()
+{
+  return mControls->Length();
+}
+
 NS_IMETHODIMP    
-nsHTMLFormElement::GetLength(int32_t* aLength)
+HTMLFormElement::GetLength(int32_t* aLength)
 {
-  uint32_t length;
-  nsresult rv = mControls->GetLength(&length);
-  *aLength = length;
-  return rv;
+  *aLength = Length();
+  return NS_OK;
 }
 
 void
-nsHTMLFormElement::ForgetCurrentSubmission()
+HTMLFormElement::ForgetCurrentSubmission()
 {
   mNotifiedObservers = false;
   mIsSubmitting = false;
   mSubmittingRequest = nullptr;
   nsCOMPtr<nsIWebProgress> webProgress = do_QueryReferent(mWebProgress);
   if (webProgress) {
     webProgress->RemoveProgressListener(this);
   }
   mWebProgress = nullptr;
 }
 
 bool
-nsHTMLFormElement::CheckFormValidity(nsIMutableArray* aInvalidElements) const
+HTMLFormElement::CheckFormValidity(nsIMutableArray* aInvalidElements) const
 {
   bool ret = true;
 
   nsTArray<nsGenericHTMLFormElement*> sortedControls;
   if (NS_FAILED(mControls->GetSortedControls(sortedControls))) {
     return false;
   }
 
@@ -1828,17 +1892,17 @@ nsHTMLFormElement::CheckFormValidity(nsI
   for (uint32_t i = 0; i < len; ++i) {
     static_cast<nsGenericHTMLElement*>(sortedControls[i])->Release();
   }
 
   return ret;
 }
 
 bool
-nsHTMLFormElement::CheckValidFormSubmission()
+HTMLFormElement::CheckValidFormSubmission()
 {
   /**
    * Check for form validity: do not submit a form if there are unhandled
    * invalid controls in the form.
    * This should not be done if the form has been submitted with .submit().
    *
    * NOTE: for the moment, we are also checking that there is an observer for
    * NS_INVALIDFORMSUBMIT_SUBJECT so it will prevent blocking form submission
@@ -1943,17 +2007,17 @@ nsHTMLFormElement::CheckValidFormSubmiss
     NS_WARNING("There is no observer for \"invalidformsubmit\". \
 One should be implemented!");
   }
 
   return true;
 }
 
 void
-nsHTMLFormElement::UpdateValidity(bool aElementValidity)
+HTMLFormElement::UpdateValidity(bool aElementValidity)
 {
   if (aElementValidity) {
     --mInvalidElementsCount;
   } else {
     ++mInvalidElementsCount;
   }
 
   NS_ASSERTION(mInvalidElementsCount >= 0, "Something went seriously wrong!");
@@ -1993,99 +2057,99 @@ nsHTMLFormElement::UpdateValidity(bool a
     }
   }
 
   UpdateState(true);
 }
 
 // nsIWebProgressListener
 NS_IMETHODIMP
-nsHTMLFormElement::OnStateChange(nsIWebProgress* aWebProgress,
-                                 nsIRequest* aRequest,
-                                 uint32_t aStateFlags,
-                                 nsresult aStatus)
+HTMLFormElement::OnStateChange(nsIWebProgress* aWebProgress,
+                               nsIRequest* aRequest,
+                               uint32_t aStateFlags,
+                               nsresult aStatus)
 {
   // If STATE_STOP is never fired for any reason (redirect?  Failed state
   // change?) the form element will leak.  It will be kept around by the
   // nsIWebProgressListener (assuming it keeps a strong pointer).  We will
   // consequently leak the request.
   if (aRequest == mSubmittingRequest &&
       aStateFlags & nsIWebProgressListener::STATE_STOP) {
     ForgetCurrentSubmission();
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsHTMLFormElement::OnProgressChange(nsIWebProgress* aWebProgress,
-                                    nsIRequest* aRequest,
-                                    int32_t aCurSelfProgress,
-                                    int32_t aMaxSelfProgress,
-                                    int32_t aCurTotalProgress,
-                                    int32_t aMaxTotalProgress)
+HTMLFormElement::OnProgressChange(nsIWebProgress* aWebProgress,
+                                  nsIRequest* aRequest,
+                                  int32_t aCurSelfProgress,
+                                  int32_t aMaxSelfProgress,
+                                  int32_t aCurTotalProgress,
+                                  int32_t aMaxTotalProgress)
 {
   NS_NOTREACHED("notification excluded in AddProgressListener(...)");
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsHTMLFormElement::OnLocationChange(nsIWebProgress* aWebProgress,
-                                    nsIRequest* aRequest,
-                                    nsIURI* location,
-                                    uint32_t aFlags)
+HTMLFormElement::OnLocationChange(nsIWebProgress* aWebProgress,
+                                  nsIRequest* aRequest,
+                                  nsIURI* location,
+                                  uint32_t aFlags)
 {
   NS_NOTREACHED("notification excluded in AddProgressListener(...)");
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsHTMLFormElement::OnStatusChange(nsIWebProgress* aWebProgress,
-                                  nsIRequest* aRequest,
-                                  nsresult aStatus,
-                                  const PRUnichar* aMessage)
+HTMLFormElement::OnStatusChange(nsIWebProgress* aWebProgress,
+                                nsIRequest* aRequest,
+                                nsresult aStatus,
+                                const PRUnichar* aMessage)
 {
   NS_NOTREACHED("notification excluded in AddProgressListener(...)");
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsHTMLFormElement::OnSecurityChange(nsIWebProgress* aWebProgress,
-                                    nsIRequest* aRequest,
-                                    uint32_t state)
+HTMLFormElement::OnSecurityChange(nsIWebProgress* aWebProgress,
+                                  nsIRequest* aRequest,
+                                  uint32_t state)
 {
   NS_NOTREACHED("notification excluded in AddProgressListener(...)");
   return NS_OK;
 }
 
 NS_IMETHODIMP_(int32_t)
-nsHTMLFormElement::IndexOfControl(nsIFormControl* aControl)
+HTMLFormElement::IndexOfControl(nsIFormControl* aControl)
 {
   int32_t index = 0;
   return mControls->IndexOfControl(aControl, &index) == NS_OK ? index : 0;
 }
 
 void
-nsHTMLFormElement::SetCurrentRadioButton(const nsAString& aName,
-                                         nsIDOMHTMLInputElement* aRadio)
+HTMLFormElement::SetCurrentRadioButton(const nsAString& aName,
+                                       nsIDOMHTMLInputElement* aRadio)
 {
   mSelectedRadioButtons.Put(aName, aRadio);
 }
 
 nsIDOMHTMLInputElement*
-nsHTMLFormElement::GetCurrentRadioButton(const nsAString& aName)
+HTMLFormElement::GetCurrentRadioButton(const nsAString& aName)
 {
   return mSelectedRadioButtons.GetWeak(aName);
 }
 
 NS_IMETHODIMP
-nsHTMLFormElement::GetNextRadioButton(const nsAString& aName,
-                                      const bool aPrevious,
-                                      nsIDOMHTMLInputElement*  aFocusedRadio,
-                                      nsIDOMHTMLInputElement** aRadioOut)
+HTMLFormElement::GetNextRadioButton(const nsAString& aName,
+                                    const bool aPrevious,
+                                    nsIDOMHTMLInputElement*  aFocusedRadio,
+                                    nsIDOMHTMLInputElement** aRadioOut)
 {
   // Return the radio button relative to the focused radio button.
   // If no radio is focused, get the radio relative to the selected one.
   *aRadioOut = nullptr;
 
   nsCOMPtr<nsIDOMHTMLInputElement> currentRadio;
   if (aFocusedRadio) {
     currentRadio = aFocusedRadio;
@@ -2135,19 +2199,19 @@ nsHTMLFormElement::GetNextRadioButton(co
     radio->GetDisabled(&disabled);
   } while (disabled && radio != currentRadio);
 
   NS_IF_ADDREF(*aRadioOut = radio);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsHTMLFormElement::WalkRadioGroup(const nsAString& aName,
-                                  nsIRadioVisitor* aVisitor,
-                                  bool aFlushContent)
+HTMLFormElement::WalkRadioGroup(const nsAString& aName,
+                                nsIRadioVisitor* aVisitor,
+                                bool aFlushContent)
 {
   if (aName.IsEmpty()) {
     //
     // XXX If the name is empty, it's not stored in the control list.  There
     // *must* be a more efficient way to do this.
     //
     nsCOMPtr<nsIFormControl> control;
     uint32_t len = GetElementCount();
@@ -2195,31 +2259,31 @@ nsHTMLFormElement::WalkRadioGroup(const 
         !aVisitor->Visit(formControl)) {
       break;
     }
   }
   return NS_OK;
 }
 
 void
-nsHTMLFormElement::AddToRadioGroup(const nsAString& aName,
-                                   nsIFormControl* aRadio)
+HTMLFormElement::AddToRadioGroup(const nsAString& aName,
+                                 nsIFormControl* aRadio)
 {
   nsCOMPtr<nsIContent> element = do_QueryInterface(aRadio);
   NS_ASSERTION(element, "radio controls have to be content elements!");
 
   if (element->HasAttr(kNameSpaceID_None, nsGkAtoms::required)) {
     mRequiredRadioButtonCounts.Put(aName,
                                    mRequiredRadioButtonCounts.Get(aName)+1);
   }
 }
 
 void
-nsHTMLFormElement::RemoveFromRadioGroup(const nsAString& aName,
-                                        nsIFormControl* aRadio)
+HTMLFormElement::RemoveFromRadioGroup(const nsAString& aName,
+                                      nsIFormControl* aRadio)
 {
   nsCOMPtr<nsIContent> element = do_QueryInterface(aRadio);
   NS_ASSERTION(element, "radio controls have to be content elements!");
 
   if (element->HasAttr(kNameSpaceID_None, nsGkAtoms::required)) {
     uint32_t requiredNb = mRequiredRadioButtonCounts.Get(aName);
     NS_ASSERTION(requiredNb >= 1,
                  "At least one radio button has to be required!");
@@ -2228,24 +2292,24 @@ nsHTMLFormElement::RemoveFromRadioGroup(
       mRequiredRadioButtonCounts.Remove(aName);
     } else {
       mRequiredRadioButtonCounts.Put(aName, requiredNb-1);
     }
   }
 }
 
 uint32_t
-nsHTMLFormElement::GetRequiredRadioCount(const nsAString& aName) const
+HTMLFormElement::GetRequiredRadioCount(const nsAString& aName) const
 {
   return mRequiredRadioButtonCounts.Get(aName);
 }
 
 void
-nsHTMLFormElement::RadioRequiredChanged(const nsAString& aName,
-                                        nsIFormControl* aRadio)
+HTMLFormElement::RadioRequiredChanged(const nsAString& aName,
+                                      nsIFormControl* aRadio)
 {
   nsCOMPtr<nsIContent> element = do_QueryInterface(aRadio);
   NS_ASSERTION(element, "radio controls have to be content elements!");
 
   if (element->HasAttr(kNameSpaceID_None, nsGkAtoms::required)) {
     mRequiredRadioButtonCounts.Put(aName,
                                    mRequiredRadioButtonCounts.Get(aName)+1);
   } else {
@@ -2256,57 +2320,57 @@ nsHTMLFormElement::RadioRequiredChanged(
       mRequiredRadioButtonCounts.Remove(aName);
     } else {
       mRequiredRadioButtonCounts.Put(aName, requiredNb-1);
     }
   }
 }
 
 bool
-nsHTMLFormElement::GetValueMissingState(const nsAString& aName) const
+HTMLFormElement::GetValueMissingState(const nsAString& aName) const
 {
   return mValueMissingRadioGroups.Get(aName);
 }
 
 void
-nsHTMLFormElement::SetValueMissingState(const nsAString& aName, bool aValue)
+HTMLFormElement::SetValueMissingState(const nsAString& aName, bool aValue)
 {
   mValueMissingRadioGroups.Put(aName, aValue);
 }
 
 nsEventStates
-nsHTMLFormElement::IntrinsicState() const
+HTMLFormElement::IntrinsicState() const
 {
   nsEventStates state = nsGenericHTMLElement::IntrinsicState();
 
   if (mInvalidElementsCount) {
     state |= NS_EVENT_STATE_INVALID;
   } else {
       state |= NS_EVENT_STATE_VALID;
   }
 
   return state;
 }
 
 void
-nsHTMLFormElement::Clear()
+HTMLFormElement::Clear()
 {
   for (int32_t i = mImageElements.Length() - 1; i >= 0; i--) {
     mImageElements[i]->ClearForm(false);
   }
   mImageElements.Clear();
   mImageNameLookupTable.Clear();
   mPastNameLookupTable.Clear();
 }
 
 //----------------------------------------------------------------------
 // nsFormControlList implementation, this could go away if there were
 // a lightweight collection implementation somewhere
 
-nsFormControlList::nsFormControlList(nsHTMLFormElement* aForm) :
+nsFormControlList::nsFormControlList(HTMLFormElement* aForm) :
   mForm(aForm),
   // Initialize the elements list to have an initial capacity
   // of 8 to reduce allocations on small forms.
   mElements(8)
 {
   SetIsDOMBinding();
 }
 
@@ -2449,43 +2513,44 @@ nsFormControlList::NamedItemInternal(con
 {
   if (aFlushContent) {
     FlushPendingNotifications();
   }
 
   return mNameLookupTable.GetWeak(aName);
 }
 
-static nsresult
-AddElementToTableInternal(
+nsresult
+HTMLFormElement::AddElementToTableInternal(
   nsInterfaceHashtable<nsStringHashKey,nsISupports>& aTable,
-  nsIContent* aChild, const nsAString& aName, nsHTMLFormElement* aForm)
+  nsIContent* aChild, const nsAString& aName)
 {
   nsCOMPtr<nsISupports> supports;
   aTable.Get(aName, getter_AddRefs(supports));
 
   if (!supports) {
     // No entry found, add the element
     aTable.Put(aName, aChild);
+    ++mExpandoAndGeneration.generation;
   } else {
     // Found something in the hash, check its type
     nsCOMPtr<nsIContent> content = do_QueryInterface(supports);
 
     if (content) {
       // Check if the new content is the same as the one we found in the
       // hash, if it is then we leave it in the hash as it is, this will
       // happen if a form control has both a name and an id with the same
       // value
       if (content == aChild) {
         return NS_OK;
       }
 
       // Found an element, create a list, add the element to the list and put
       // the list in the hash
-      nsSimpleContentList *list = new nsSimpleContentList(aForm);
+      nsSimpleContentList *list = new nsSimpleContentList(this);
 
       // If an element has a @form, we can assume it *might* be able to not have
       // a parent and still be in the form.
       NS_ASSERTION(content->HasAttr(kNameSpaceID_None, nsGkAtoms::form) ||
                    content->GetParent(), "Item in list without parent");
 
       // Determine the ordering between the new and old element.
       bool newFirst = nsContentUtils::PositionIsBefore(aChild, content);
@@ -2551,17 +2616,17 @@ AddElementToTableInternal(
 nsresult
 nsFormControlList::AddElementToTable(nsGenericHTMLFormElement* aChild,
                                      const nsAString& aName)
 {
   if (!ShouldBeInElements(aChild)) {
     return NS_OK;
   }
 
-  return AddElementToTableInternal(mNameLookupTable, aChild, aName, mForm);
+  return mForm->AddElementToTableInternal(mNameLookupTable, aChild, aName);
 }
 
 nsresult
 nsFormControlList::IndexOfControl(nsIFormControl* aControl,
                                   int32_t* aIndex)
 {
   // Note -- not a DOM method; callers should handle flushing themselves
   
@@ -2575,17 +2640,17 @@ nsFormControlList::IndexOfControl(nsIFor
 nsresult
 nsFormControlList::RemoveElementFromTable(nsGenericHTMLFormElement* aChild,
                                           const nsAString& aName)
 {
   if (!ShouldBeInElements(aChild)) {
     return NS_OK;
   }
 
-  return RemoveElementFromTableInternal(mNameLookupTable, aChild, aName);
+  return mForm->RemoveElementFromTableInternal(mNameLookupTable, aChild, aName);
 }
 
 nsresult
 nsFormControlList::GetSortedControls(nsTArray<nsGenericHTMLFormElement*>& aControls) const
 {
 #ifdef DEBUG
   AssertDocumentOrder(mElements, mForm);
   AssertDocumentOrder(mNotInElements, mForm);
@@ -2701,58 +2766,66 @@ nsFormControlList::GetSupportedNames(nsT
   FlushPendingNotifications();
   // Just enumerate mNameLookupTable.  This won't guarantee order, but
   // that's OK, because the HTML5 spec doesn't define an order for
   // this enumeration.
   mNameLookupTable.EnumerateRead(CollectNames, &aNames);
 }
 
 nsresult
-nsHTMLFormElement::AddImageElement(HTMLImageElement* aChild)
+HTMLFormElement::AddImageElement(HTMLImageElement* aChild)
 {
   AddElementToList(mImageElements, aChild, this);
   return NS_OK;
 }
 
 nsresult
-nsHTMLFormElement::AddImageElementToTable(HTMLImageElement* aChild,
-                                          const nsAString& aName)
+HTMLFormElement::AddImageElementToTable(HTMLImageElement* aChild,
+                                        const nsAString& aName)
 {
-  return AddElementToTableInternal(mImageNameLookupTable, aChild, aName, this);
+  return AddElementToTableInternal(mImageNameLookupTable, aChild, aName);
 }
 
 nsresult
-nsHTMLFormElement::RemoveImageElement(HTMLImageElement* aChild)
+HTMLFormElement::RemoveImageElement(HTMLImageElement* aChild)
 {
   uint32_t index = mImageElements.IndexOf(aChild);
   NS_ENSURE_STATE(index != mImageElements.NoIndex);
 
   mImageElements.RemoveElementAt(index);
   return NS_OK;
 }
 
 nsresult
-nsHTMLFormElement::RemoveImageElementFromTable(HTMLImageElement* aElement,
-                                               const nsAString& aName,
-                                               RemoveElementReason aRemoveReason)
+HTMLFormElement::RemoveImageElementFromTable(HTMLImageElement* aElement,
+                                             const nsAString& aName,
+                                             RemoveElementReason aRemoveReason)
 {
   // If the element is being removed from the form, we have to remove it from
   // the past names map.
   if (aRemoveReason == ElementRemoved) {
     mPastNameLookupTable.Enumerate(RemovePastNames, aElement);
   }
 
   return RemoveElementFromTableInternal(mImageNameLookupTable, aElement, aName);
 }
 
 void
-nsHTMLFormElement::AddToPastNamesMap(const nsAString& aName,
-                                     nsISupports* aChild)
+HTMLFormElement::AddToPastNamesMap(const nsAString& aName,
+                                   nsISupports* aChild)
 {
   // If candidates contains exactly one node. Add a mapping from name to the
   // node in candidates in the form element's past names map, replacing the
   // previous entry with the same name, if any.
   nsCOMPtr<nsIContent> node = do_QueryInterface(aChild);
   if (node) {
     mPastNameLookupTable.Put(aName, aChild);
   }
 }
-
+ 
+JSObject*
+HTMLFormElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aScope)
+{
+  return HTMLFormElementBinding::Wrap(aCx, aScope, this);
+}
+
+} // namespace dom
+} // namespace mozilla
rename from content/html/content/src/nsHTMLFormElement.h
rename to content/html/content/src/HTMLFormElement.h
--- a/content/html/content/src/nsHTMLFormElement.h
+++ b/content/html/content/src/HTMLFormElement.h
@@ -1,15 +1,15 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef nsHTMLFormElement_h__
-#define nsHTMLFormElement_h__
+#ifndef mozilla_dom_HTMLFormElement_h
+#define mozilla_dom_HTMLFormElement_h
 
 #include "mozilla/Attributes.h"
 #include "nsCOMPtr.h"
 #include "nsIForm.h"
 #include "nsIFormControl.h"
 #include "nsFormSubmission.h"
 #include "nsGenericHTMLElement.h"
 #include "nsIDOMHTMLFormElement.h"
@@ -23,35 +23,41 @@
 
 // Including 'windows.h' will #define GetClassInfo to something else.
 #ifdef XP_WIN
 #ifdef GetClassInfo
 #undef GetClassInfo
 #endif
 #endif
 
-class nsFormControlList;
 class nsIMutableArray;
 class nsIURI;
 
 namespace mozilla {
 namespace dom {
 class HTMLImageElement;
 }
 }
 
-class nsHTMLFormElement : public nsGenericHTMLElement,
-                          public nsIDOMHTMLFormElement,
-                          public nsIWebProgressListener,
-                          public nsIForm,
-                          public nsIRadioGroupContainer
+namespace mozilla {
+namespace dom {
+
+class nsFormControlList;
+
+class HTMLFormElement : public nsGenericHTMLElement,
+                        public nsIDOMHTMLFormElement,
+                        public nsIWebProgressListener,
+                        public nsIForm,
+                        public nsIRadioGroupContainer
 {
+  friend class nsFormControlList;
+
 public:
-  nsHTMLFormElement(already_AddRefed<nsINodeInfo> aNodeInfo);
-  virtual ~nsHTMLFormElement();
+  HTMLFormElement(already_AddRefed<nsINodeInfo> aNodeInfo);
+  virtual ~HTMLFormElement();
 
   nsresult Init();
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIDOMNode
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
@@ -122,18 +128,18 @@ public:
   /**
    * Forget all information about the current submission (and the fact that we
    * are currently submitting at all).
    */
   void ForgetCurrentSubmission();
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;
 
-  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsHTMLFormElement,
-                                           nsGenericHTMLElement)
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(HTMLFormElement,
+                                                         nsGenericHTMLElement)
 
   /**
    * Remove an element from this form's list of elements
    *
    * @param aElement the element to remove
    * @param aUpdateValidity If true, updates the form validity.
    * @return NS_OK if the element was successfully removed.
    */
@@ -306,82 +312,182 @@ public:
 
   /**
    * Implements form[name]. Returns form controls in this form with the correct
    * value of the name attribute.
    */
   already_AddRefed<nsISupports>
   FindNamedItem(const nsAString& aName, nsWrapperCache** aCache);
 
+  // WebIDL
+
+  void GetAcceptCharset(DOMString& aValue)
+  {
+    GetHTMLAttr(nsGkAtoms::acceptcharset, aValue);
+  }
+
+  void SetAcceptCharset(const nsAString& aValue, ErrorResult& aRv)
+  {
+    SetHTMLAttr(nsGkAtoms::acceptcharset, aValue, aRv);
+  }
+
+  // XPCOM GetAction() is OK
+  void SetAction(const nsAString& aValue, ErrorResult& aRv)
+  {
+    SetHTMLAttr(nsGkAtoms::action, aValue, aRv);
+  }
+
+  // XPCOM GetAutocomplete() is OK
+  void SetAutocomplete(const nsAString& aValue, ErrorResult& aRv)
+  {
+    SetHTMLAttr(nsGkAtoms::autocomplete, aValue, aRv);
+  }
+
+  // XPCOM GetEnctype() is OK
+  void SetEnctype(const nsAString& aValue, ErrorResult& aRv)
+  {
+    SetHTMLAttr(nsGkAtoms::enctype, aValue, aRv);
+  }
+
+  // XPCOM GetEncoding() is OK
+  void SetEncoding(const nsAString& aValue, ErrorResult& aRv)
+  {
+    SetEnctype(aValue, aRv);
+  }
+
+  // XPCOM GetMethod() is OK
+  void SetMethod(const nsAString& aValue, ErrorResult& aRv)
+  {
+    SetHTMLAttr(nsGkAtoms::method, aValue, aRv);
+  }
+
+  void GetName(DOMString& aValue)
+  {
+    GetHTMLAttr(nsGkAtoms::name, aValue);
+  }
+
+  void SetName(const nsAString& aValue, ErrorResult& aRv)
+  {
+    SetHTMLAttr(nsGkAtoms::name, aValue, aRv);
+  }
+
+  bool NoValidate() const
+  {
+    return GetBoolAttr(nsGkAtoms::novalidate);
+  }
+
+  void SetNoValidate(bool aValue, ErrorResult& aRv)
+  {
+    SetHTMLBoolAttr(nsGkAtoms::novalidate, aValue, aRv);
+  }
+
+  void GetTarget(DOMString& aValue)
+  {
+    GetHTMLAttr(nsGkAtoms::target, aValue);
+  }
+
+  void SetTarget(const nsAString& aValue, ErrorResult& aRv)
+  {
+    SetHTMLAttr(nsGkAtoms::target, aValue, aRv);
+  }
+
+  // it's only out-of-line because the class definition is not available in the
+  // header
+  nsIHTMLCollection* Elements();
+
+  int32_t Length();
+
+  void Submit(ErrorResult& aRv);
+
+  // XPCOM Reset() is OK
+
+  bool CheckValidity()
+  {
+    return CheckFormValidity(nullptr);
+  }
+
+  Element*
+  IndexedGetter(uint32_t aIndex, bool &aFound);
+
+  already_AddRefed<nsISupports>
+  NamedGetter(const nsAString& aName, bool &aFound);
+
+  void GetSupportedNames(nsTArray<nsString >& aRetval);
+
+  js::ExpandoAndGeneration mExpandoAndGeneration;
+
 protected:
+  virtual JSObject* WrapNode(JSContext* aCx,
+                             JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
+
   void PostPasswordEvent();
   void EventHandled() { mFormPasswordEvent = nullptr; }
 
   class FormPasswordEvent : public nsAsyncDOMEvent
   {
   public:
-    FormPasswordEvent(nsHTMLFormElement* aEventNode,
+    FormPasswordEvent(HTMLFormElement* aEventNode,
                       const nsAString& aEventType)
       : nsAsyncDOMEvent(aEventNode, aEventType, true, true)
     {}
 
     NS_IMETHOD Run() MOZ_OVERRIDE
     {
-      static_cast<nsHTMLFormElement*>(mEventNode.get())->EventHandled();
+      static_cast<HTMLFormElement*>(mEventNode.get())->EventHandled();
       return nsAsyncDOMEvent::Run();
     }
   };
 
   nsRefPtr<FormPasswordEvent> mFormPasswordEvent;
 
   class RemoveElementRunnable;
   friend class RemoveElementRunnable;
 
   class RemoveElementRunnable : public nsRunnable {
   public:
-    RemoveElementRunnable(nsHTMLFormElement* aForm)
+    RemoveElementRunnable(HTMLFormElement* aForm)
       : mForm(aForm)
     {}
 
     NS_IMETHOD Run() MOZ_OVERRIDE {
       mForm->HandleDefaultSubmitRemoval();
       return NS_OK;
     }
 
   private:
-    nsRefPtr<nsHTMLFormElement> mForm;
+    nsRefPtr<HTMLFormElement> mForm;
   };
 
   nsresult DoSubmitOrReset(nsEvent* aEvent,
                            int32_t aMessage);
   nsresult DoReset();
 
   // Async callback to handle removal of our default submit
   void HandleDefaultSubmitRemoval();
 
   //
   // Submit Helpers
   //
   //
   /**
-   * Attempt to submit (submission might be deferred) 
+   * Attempt to submit (submission might be deferred)
    * (called by DoSubmitOrReset)
    *
    * @param aPresContext the presentation context
    * @param aEvent the DOM event that was passed to us for the submit
    */
   nsresult DoSubmit(nsEvent* aEvent);
 
   /**
    * Prepare the submission object (called by DoSubmit)
    *
    * @param aFormSubmission the submission object
    * @param aEvent the DOM event that was passed to us for the submit
    */
-  nsresult BuildSubmission(nsFormSubmission** aFormSubmission, 
+  nsresult BuildSubmission(nsFormSubmission** aFormSubmission,
                            nsEvent* aEvent);
   /**
    * Perform the submission (called by DoSubmit and FlushPendingSubmission)
    *
    * @param aFormSubmission the submission object
    */
   nsresult SubmitSubmission(nsFormSubmission* aFormSubmission);
 
@@ -421,16 +527,26 @@ protected:
   bool CheckFormValidity(nsIMutableArray* aInvalidElements) const;
 
   // Clear the mImageNameLookupTable and mImageElements.
   void Clear();
 
   // Insert a element into the past names map.
   void AddToPastNamesMap(const nsAString& aName, nsISupports* aChild);
 
+  nsresult
+  AddElementToTableInternal(
+    nsInterfaceHashtable<nsStringHashKey,nsISupports>& aTable,
+    nsIContent* aChild, const nsAString& aName);
+
+  nsresult
+  RemoveElementFromTableInternal(
+    nsInterfaceHashtable<nsStringHashKey,nsISupports>& aTable,
+    nsIContent* aChild, const nsAString& aName);
+
 public:
   /**
    * Flush a possible pending submission. If there was a scripted submission
    * triggered by a button or image, the submission was defered. This method
    * forces the pending submission to be submitted. (happens when the handler
    * returns false or there is an action/target change in the script)
    */
   void FlushPendingSubmission();
@@ -514,9 +630,12 @@ protected:
 
 protected:
   /** Detection of first form to notify observers */
   static bool gFirstFormSubmitted;
   /** Detection of first password input to initialize the password manager */
   static bool gPasswordManagerInitialized;
 };
 
-#endif // nsHTMLFormElement_h__
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_HTMLFormElement_h
--- a/content/html/content/src/HTMLImageElement.cpp
+++ b/content/html/content/src/HTMLImageElement.cpp
@@ -20,53 +20,33 @@
 #include "nsNetUtil.h"
 #include "nsContentUtils.h"
 #include "nsIFrame.h"
 #include "nsNodeInfoManager.h"
 #include "nsGUIEvent.h"
 #include "nsContentPolicyUtils.h"
 #include "nsIDOMWindow.h"
 #include "nsFocusManager.h"
-#include "nsHTMLFormElement.h"
+#include "mozilla/dom/HTMLFormElement.h"
 
 #include "imgIContainer.h"
 #include "imgILoader.h"
 #include "imgINotificationObserver.h"
 #include "imgRequestProxy.h"
 
 #include "nsILoadGroup.h"
 
 #include "nsRuleData.h"
 
 #include "nsIDOMHTMLMapElement.h"
 #include "nsEventDispatcher.h"
 
 #include "nsLayoutUtils.h"
 
-nsGenericHTMLElement*
-NS_NewHTMLImageElement(already_AddRefed<nsINodeInfo> aNodeInfo,
-                       mozilla::dom::FromParser aFromParser)
-{
-  /*
-   * HTMLImageElement's will be created without a nsINodeInfo passed in
-   * if someone says "var img = new Image();" in JavaScript, in a case like
-   * that we request the nsINodeInfo from the document's nodeinfo list.
-   */
-  nsCOMPtr<nsINodeInfo> nodeInfo(aNodeInfo);
-  if (!nodeInfo) {
-    nsCOMPtr<nsIDocument> doc = nsContentUtils::GetDocumentFromCaller();
-    NS_ENSURE_TRUE(doc, nullptr);
-
-    nodeInfo = doc->NodeInfoManager()->GetNodeInfo(nsGkAtoms::img, nullptr,
-                                                   kNameSpaceID_XHTML,
-                                                   nsIDOMNode::ELEMENT_NODE);
-  }
-
-  return new mozilla::dom::HTMLImageElement(nodeInfo.forget());
-}
+NS_IMPL_NS_NEW_HTML_ELEMENT(Image)
 
 namespace mozilla {
 namespace dom {
 
 HTMLImageElement::HTMLImageElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsGenericHTMLElement(aNodeInfo)
   , mForm(nullptr)
 {
@@ -307,17 +287,17 @@ HTMLImageElement::BeforeSetAttr(int32_t 
   if (aNameSpaceID == kNameSpaceID_None && mForm &&
       (aName == nsGkAtoms::name || aName == nsGkAtoms::id)) {
     // remove the image from the hashtable as needed
     nsAutoString tmp;
     GetAttr(kNameSpaceID_None, aName, tmp);
 
     if (!tmp.IsEmpty()) {
       mForm->RemoveImageElementFromTable(this, tmp,
-                                         nsHTMLFormElement::AttributeUpdated);
+                                         HTMLFormElement::AttributeUpdated);
     }
   }
 
   return nsGenericHTMLElement::BeforeSetAttr(aNameSpaceID, aName,
                                              aValue, aNotify);
 }
 
 nsresult
@@ -669,17 +649,17 @@ HTMLImageElement::GetForm() const
 
 void
 HTMLImageElement::SetForm(nsIDOMHTMLFormElement* aForm)
 {
   NS_PRECONDITION(aForm, "Don't pass null here");
   NS_ASSERTION(!mForm,
                "We don't support switching from one non-null form to another.");
 
-  mForm = static_cast<nsHTMLFormElement*>(aForm);
+  mForm = static_cast<HTMLFormElement*>(aForm);
 }
 
 void
 HTMLImageElement::ClearForm(bool aRemoveFromForm)
 {
   NS_ASSERTION((mForm != nullptr) == HasFlag(ADDED_TO_FORM),
                "Form control should have had flag set correctly");
 
@@ -691,22 +671,22 @@ HTMLImageElement::ClearForm(bool aRemove
     nsAutoString nameVal, idVal;
     GetAttr(kNameSpaceID_None, nsGkAtoms::name, nameVal);
     GetAttr(kNameSpaceID_None, nsGkAtoms::id, idVal);
 
     mForm->RemoveImageElement(this);
 
     if (!nameVal.IsEmpty()) {
       mForm->RemoveImageElementFromTable(this, nameVal,
-                                         nsHTMLFormElement::ElementRemoved);
+                                         HTMLFormElement::ElementRemoved);
     }
 
     if (!idVal.IsEmpty()) {
       mForm->RemoveImageElementFromTable(this, idVal,
-                                         nsHTMLFormElement::ElementRemoved);
+                                         HTMLFormElement::ElementRemoved);
     }
   }
 
   UnsetFlags(ADDED_TO_FORM);
   mForm = nullptr;
 }
 
 } // namespace dom
--- a/content/html/content/src/HTMLImageElement.h
+++ b/content/html/content/src/HTMLImageElement.h
@@ -192,15 +192,15 @@ protected:
                                  const nsAttrValueOrString* aValue,
                                  bool aNotify) MOZ_OVERRIDE;
 
   virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
                                 const nsAttrValue* aValue, bool aNotify) MOZ_OVERRIDE;
 
   // This is a weak reference that this element and the HTMLFormElement
   // cooperate in maintaining.
-  nsHTMLFormElement* mForm;
+  HTMLFormElement* mForm;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif /* mozilla_dom_HTMLImageElement_h */
--- a/content/html/content/src/HTMLInputElement.cpp
+++ b/content/html/content/src/HTMLInputElement.cpp
@@ -2319,17 +2319,17 @@ HTMLInputElement::MaybeSubmitForm(nsPres
     shell->HandleDOMEventWithTarget(submitContent, &event, &status);
   } else if (mForm->HasSingleTextControl() &&
              (mForm->HasAttr(kNameSpaceID_None, nsGkAtoms::novalidate) ||
               mForm->CheckValidFormSubmission())) {
     // TODO: removing this code and have the submit event sent by the form,
     // bug 592124.
     // If there's only one text control, just submit the form
     // Hold strong ref across the event
-    nsRefPtr<nsHTMLFormElement> form = mForm;
+    nsRefPtr<mozilla::dom::HTMLFormElement> form = mForm;
     nsFormEvent event(true, NS_FORM_SUBMIT);
     nsEventStatus status = nsEventStatus_eIgnore;
     shell->HandleDOMEventWithTarget(mForm, &event, &status);
   }
 
   return NS_OK;
 }
 
@@ -3160,17 +3160,17 @@ HTMLInputElement::PostHandleEvent(nsEven
             // form, see bug 592124.
             if (presShell && (event.message != NS_FORM_SUBMIT ||
                               mForm->HasAttr(kNameSpaceID_None, nsGkAtoms::novalidate) ||
                               // We know the element is a submit control, if this check is moved,
                               // make sure formnovalidate is used only if it's a submit control.
                               HasAttr(kNameSpaceID_None, nsGkAtoms::formnovalidate) ||
                               mForm->CheckValidFormSubmission())) {
               // Hold a strong ref while dispatching
-              nsRefPtr<nsHTMLFormElement> form(mForm);
+              nsRefPtr<mozilla::dom::HTMLFormElement> form(mForm);
               presShell->HandleDOMEventWithTarget(mForm, &event, &status);
               aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
             }
           }
           break;
 
         default:
           break;
--- a/content/html/content/src/HTMLInputElement.h
+++ b/content/html/content/src/HTMLInputElement.h
@@ -12,17 +12,17 @@
 #include "nsIDOMHTMLInputElement.h"
 #include "nsITextControlElement.h"
 #include "nsIPhonetic.h"
 #include "nsIDOMNSEditableElement.h"
 #include "nsTextEditorState.h"
 #include "nsCOMPtr.h"
 #include "nsIConstraintValidation.h"
 #include "nsDOMFile.h"
-#include "nsHTMLFormElement.h" // for ShouldShowInvalidUI()
+#include "mozilla/dom/HTMLFormElement.h" // for ShouldShowInvalidUI()
 #include "nsIFile.h"
 #include "nsIFilePicker.h"
 #include "nsIContentPrefService2.h"
 #include "mozilla/Decimal.h"
 
 class nsDOMFileList;
 class nsIFilePicker;
 class nsIRadioGroupContainer;
--- a/content/html/content/src/HTMLLegendElement.cpp
+++ b/content/html/content/src/HTMLLegendElement.cpp
@@ -159,22 +159,22 @@ void
 HTMLLegendElement::PerformAccesskey(bool aKeyCausesActivation,
                                     bool aIsTrustedEvent)
 {
   // just use the same behaviour as the focus method
   ErrorResult rv;
   Focus(rv);
 }
 
-already_AddRefed<nsHTMLFormElement>
+already_AddRefed<HTMLFormElement>
 HTMLLegendElement::GetForm()
 {
   Element* form = GetFormElement();
   MOZ_ASSERT_IF(form, form->IsHTML(nsGkAtoms::form));
-  nsRefPtr<nsHTMLFormElement> ret = static_cast<nsHTMLFormElement*>(form);
+  nsRefPtr<HTMLFormElement> ret = static_cast<HTMLFormElement*>(form);
   return ret.forget();
 }
 
 JSObject*
 HTMLLegendElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aScope)
 {
   return HTMLLegendElementBinding::Wrap(aCx, aScope, this);
 }
--- a/content/html/content/src/HTMLLegendElement.h
+++ b/content/html/content/src/HTMLLegendElement.h
@@ -4,17 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_HTMLLegendElement_h
 #define mozilla_dom_HTMLLegendElement_h
 
 #include "mozilla/Attributes.h"
 #include "nsIDOMHTMLLegendElement.h"
 #include "nsGenericHTMLElement.h"
-#include "nsHTMLFormElement.h"
+#include "mozilla/dom/HTMLFormElement.h"
 
 namespace mozilla {
 namespace dom {
 
 class HTMLLegendElement : public nsGenericHTMLElement,
                           public nsIDOMHTMLLegendElement
 {
 public:
@@ -80,17 +80,17 @@ public:
   }
 
   virtual nsIDOMNode* AsDOMNode() MOZ_OVERRIDE { return this; }
 
   /**
    * WebIDL Interface
    */
 
-  already_AddRefed<nsHTMLFormElement> GetForm();
+  already_AddRefed<HTMLFormElement> GetForm();
 
   // The XPCOM GetAlign is OK for us
   void SetAlign(const nsAString& aAlign, ErrorResult& aError)
   {
     SetHTMLAttr(nsGkAtoms::align, aAlign, aError);
   }
 
   nsINode* GetParentObject() {
--- a/content/html/content/src/HTMLObjectElement.cpp
+++ b/content/html/content/src/HTMLObjectElement.cpp
@@ -75,26 +75,25 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_IN
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mValidity)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_ADDREF_INHERITED(HTMLObjectElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLObjectElement, Element)
 
 NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(HTMLObjectElement)
   NS_HTML_CONTENT_INTERFACES(nsGenericHTMLFormElement)
-  NS_INTERFACE_TABLE_INHERITED11(HTMLObjectElement,
+  NS_INTERFACE_TABLE_INHERITED10(HTMLObjectElement,
                                  nsIDOMHTMLObjectElement,
                                  imgINotificationObserver,
                                  nsIRequestObserver,
                                  nsIStreamListener,
                                  nsIFrameLoaderOwner,
                                  nsIObjectLoadingContent,
                                  nsIImageLoadingContent,
                                  imgIOnloadBlocker,
-                                 nsIInterfaceRequestor,
                                  nsIChannelEventSink,
                                  nsIConstraintValidation)
   NS_INTERFACE_TABLE_TO_MAP_SEGUE
 NS_ELEMENT_INTERFACE_MAP_END
 
 NS_IMPL_ELEMENT_CLONE(HTMLObjectElement)
 
 // nsIConstraintValidation
--- a/content/html/content/src/HTMLOptionElement.cpp
+++ b/content/html/content/src/HTMLOptionElement.cpp
@@ -27,37 +27,17 @@
 #include "nsContentCreatorFunctions.h"
 #include "mozAutoDocUpdate.h"
 #include "nsTextNode.h"
 
 /**
  * Implementation of &lt;option&gt;
  */
 
-nsGenericHTMLElement*
-NS_NewHTMLOptionElement(already_AddRefed<nsINodeInfo> aNodeInfo,
-                        mozilla::dom::FromParser aFromParser)
-{
-  /*
-   * HTMLOptionElement's will be created without a nsINodeInfo passed in
-   * if someone says "var opt = new Option();" in JavaScript, in a case like
-   * that we request the nsINodeInfo from the document's nodeinfo list.
-   */
-  nsCOMPtr<nsINodeInfo> nodeInfo(aNodeInfo);
-  if (!nodeInfo) {
-    nsCOMPtr<nsIDocument> doc = nsContentUtils::GetDocumentFromCaller();
-    NS_ENSURE_TRUE(doc, nullptr);
-
-    nodeInfo = doc->NodeInfoManager()->GetNodeInfo(nsGkAtoms::option, nullptr,
-                                                   kNameSpaceID_XHTML,
-                                                   nsIDOMNode::ELEMENT_NODE);
-  }
-
-  return new mozilla::dom::HTMLOptionElement(nodeInfo.forget());
-}
+NS_IMPL_NS_NEW_HTML_ELEMENT(Option)
 
 namespace mozilla {
 namespace dom {
 
 HTMLOptionElement::HTMLOptionElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsGenericHTMLElement(aNodeInfo),
     mSelectedChanged(false),
     mIsSelected(false),
@@ -94,17 +74,17 @@ NS_IMPL_ELEMENT_CLONE(HTMLOptionElement)
 
 NS_IMETHODIMP
 HTMLOptionElement::GetForm(nsIDOMHTMLFormElement** aForm)
 {
   NS_IF_ADDREF(*aForm = GetForm());
   return NS_OK;
 }
 
-nsHTMLFormElement*
+mozilla::dom::HTMLFormElement*
 HTMLOptionElement::GetForm()
 {
   HTMLSelectElement* selectControl = GetSelect();
   return selectControl ? selectControl->GetForm() : nullptr;
 }
 
 void
 HTMLOptionElement::SetSelectedInternal(bool aValue, bool aNotify)
--- a/content/html/content/src/HTMLOptionElement.h
+++ b/content/html/content/src/HTMLOptionElement.h
@@ -6,17 +6,17 @@
 
 #ifndef mozilla_dom_HTMLOptionElement_h__
 #define mozilla_dom_HTMLOptionElement_h__
 
 #include "mozilla/Attributes.h"
 #include "nsGenericHTMLElement.h"
 #include "nsIDOMHTMLOptionElement.h"
 #include "nsIJSNativeInitializer.h"
-#include "nsHTMLFormElement.h"
+#include "mozilla/dom/HTMLFormElement.h"
 
 namespace mozilla {
 namespace dom {
 
 class HTMLSelectElement;
 
 class HTMLOptionElement : public nsGenericHTMLElement,
                           public nsIDOMHTMLOptionElement
@@ -86,17 +86,17 @@ public:
     return GetBoolAttr(nsGkAtoms::disabled);
   }
 
   void SetDisabled(bool aValue, ErrorResult& aRv)
   {
     SetHTMLBoolAttr(nsGkAtoms::disabled, aValue, aRv);
   }
 
-  nsHTMLFormElement* GetForm();
+  HTMLFormElement* GetForm();
 
   // The XPCOM GetLabel is OK for us
   void SetLabel(const nsAString& aLabel, ErrorResult& aError)
   {
     SetHTMLAttr(nsGkAtoms::label, aLabel, aError);
   }
 
   // The XPCOM DefaultSelected is OK for us
--- a/content/html/content/src/HTMLOutputElement.cpp
+++ b/content/html/content/src/HTMLOutputElement.cpp
@@ -5,17 +5,17 @@
 
 #include "mozilla/dom/HTMLOutputElement.h"
 
 #include "mozilla/dom/HTMLOutputElementBinding.h"
 #include "nsFormSubmission.h"
 #include "nsDOMSettableTokenList.h"
 #include "nsEventStates.h"
 #include "mozAutoDocUpdate.h"
-#include "nsHTMLFormElement.h"
+#include "mozilla/dom/HTMLFormElement.h"
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(Output)
 
 namespace mozilla {
 namespace dom {
 
 HTMLOutputElement::HTMLOutputElement(already_AddRefed<nsINodeInfo> aNodeInfo)
   : nsGenericHTMLFormElement(aNodeInfo)
--- a/content/html/content/src/HTMLSelectElement.h
+++ b/content/html/content/src/HTMLSelectElement.h
@@ -11,17 +11,17 @@
 #include "nsIConstraintValidation.h"
 
 #include "mozilla/dom/BindingDeclarations.h"
 #include "mozilla/dom/HTMLOptionsCollection.h"
 #include "mozilla/ErrorResult.h"
 #include "nsCheapSets.h"
 #include "nsCOMPtr.h"
 #include "nsError.h"
-#include "nsHTMLFormElement.h"
+#include "mozilla/dom/HTMLFormElement.h"
 
 class nsIDOMHTMLOptionElement;
 class nsISelectControlFrame;
 class nsPresState;
 
 namespace mozilla {
 namespace dom {
 
@@ -145,17 +145,17 @@ public:
   bool Disabled() const
   {
     return GetBoolAttr(nsGkAtoms::disabled);
   }
   void SetDisabled(bool aVal, ErrorResult& aRv)
   {
     SetHTMLBoolAttr(nsGkAtoms::disabled, aVal, aRv);
   }
-  nsHTMLFormElement* GetForm() const
+  HTMLFormElement* GetForm() const
   {
     return nsGenericHTMLFormElement::GetForm();
   }
   bool Multiple() const
   {
     return GetBoolAttr(nsGkAtoms::multiple);
   }
   void SetMultiple(bool aVal, ErrorResult& aRv)
--- a/content/html/content/src/HTMLSharedObjectElement.cpp
+++ b/content/html/content/src/HTMLSharedObjectElement.cpp
@@ -88,25 +88,24 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_ADDREF_INHERITED(HTMLSharedObjectElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLSharedObjectElement, Element)
 
 NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(HTMLSharedObjectElement)
   NS_HTML_CONTENT_INTERFACES_AMBIGUOUS(nsGenericHTMLElement,
                                        nsIDOMHTMLAppletElement)
-  NS_INTERFACE_TABLE_INHERITED9(HTMLSharedObjectElement,
+  NS_INTERFACE_TABLE_INHERITED8(HTMLSharedObjectElement,
                                 nsIRequestObserver,
                                 nsIStreamListener,
                                 nsIFrameLoaderOwner,
                                 nsIObjectLoadingContent,
                                 imgINotificationObserver,
                                 nsIImageLoadingContent,
                                 imgIOnloadBlocker,
-                                nsIInterfaceRequestor,
                                 nsIChannelEventSink)
   NS_INTERFACE_TABLE_TO_MAP_SEGUE
   NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLAppletElement, applet)
   NS_INTERFACE_MAP_ENTRY_IF_TAG(nsIDOMHTMLEmbedElement, embed)
 NS_ELEMENT_INTERFACE_MAP_END
 
 NS_IMPL_ELEMENT_CLONE(HTMLSharedObjectElement)
 
--- a/content/html/content/src/HTMLTextAreaElement.h
+++ b/content/html/content/src/HTMLTextAreaElement.h
@@ -11,17 +11,17 @@
 #include "nsIDOMHTMLTextAreaElement.h"
 #include "nsITextControlElement.h"
 #include "nsIDOMNSEditableElement.h"
 #include "nsCOMPtr.h"
 #include "nsGenericHTMLElement.h"
 #include "nsEventStates.h"
 #include "nsStubMutationObserver.h"
 #include "nsIConstraintValidation.h"
-#include "nsHTMLFormElement.h"
+#include "mozilla/dom/HTMLFormElement.h"
 #include "nsGkAtoms.h"
 
 #include "nsTextEditorState.h"
 
 class nsFormSubmission;
 class nsIControllers;
 class nsIDocument;
 class nsPresContext;
--- a/content/html/content/src/moz.build
+++ b/content/html/content/src/moz.build
@@ -19,16 +19,17 @@ EXPORTS.mozilla.dom += [
     'HTMLBRElement.h',
     'HTMLBodyElement.h',
     'HTMLButtonElement.h',
     'HTMLDataElement.h',
     'HTMLDataListElement.h',
     'HTMLDivElement.h',
     'HTMLFieldSetElement.h',
     'HTMLFontElement.h',
+    'HTMLFormElement.h',
     'HTMLFrameElement.h',
     'HTMLFrameSetElement.h',
     'HTMLHRElement.h',
     'HTMLHeadingElement.h',
     'HTMLIFrameElement.h',
     'HTMLImageElement.h',
     'HTMLInputElement.h',
     'HTMLLIElement.h',
@@ -142,14 +143,14 @@ CPP_SOURCES += [
     'UndoManager.cpp',
     'ValidityState.cpp',
     'nsClientRect.cpp',
     'nsDOMStringMap.cpp',
     'nsFormSubmission.cpp',
     'nsGenericHTMLElement.cpp',
     'nsGenericHTMLFrameElement.cpp',
     'nsHTMLDNSPrefetch.cpp',
-    'nsHTMLFormElement.cpp',
+    'HTMLFormElement.cpp',
     'nsIConstraintValidation.cpp',
     'nsRadioVisitor.cpp',
     'nsTextEditorState.cpp',
 ]
 
--- a/content/html/content/src/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -59,17 +59,17 @@
 #include "nsGkAtoms.h"
 #include "nsEventStateManager.h"
 #include "nsIDOMEvent.h"
 #include "nsDOMCSSDeclaration.h"
 #include "nsITextControlFrame.h"
 #include "nsIForm.h"
 #include "nsIFormControl.h"
 #include "nsIDOMHTMLFormElement.h"
-#include "nsHTMLFormElement.h"
+#include "mozilla/dom/HTMLFormElement.h"
 #include "nsFocusManager.h"
 #include "nsAttrValueOrString.h"
 
 #include "nsMutationEvent.h"
 #include "nsDOMStringMap.h"
 
 #include "nsIEditor.h"
 #include "nsIEditorIMESupport.h"
@@ -646,18 +646,18 @@ nsGenericHTMLElement::UnbindFromTree(boo
     if (htmlDocument) {
       htmlDocument->ChangeContentEditableCount(this, -1);
     }
   }
 
   nsStyledElement::UnbindFromTree(aDeep, aNullParent);
 }
 
-nsHTMLFormElement*
-nsGenericHTMLElement::FindAncestorForm(nsHTMLFormElement* aCurrentForm)
+HTMLFormElement*
+nsGenericHTMLElement::FindAncestorForm(HTMLFormElement* aCurrentForm)
 {
   NS_ASSERTION(!HasAttr(kNameSpaceID_None, nsGkAtoms::form),
                "FindAncestorForm should not be called if @form is set!");
 
   // Make sure we don't end up finding a form that's anonymous from
   // our point of view.
   nsIContent* bindingParent = GetBindingParent();
 
@@ -672,17 +672,17 @@ nsGenericHTMLElement::FindAncestorForm(n
         // anonymous.  Check for this the hard way.
         for (nsIContent* child = this; child != content;
              child = child->GetParent()) {
           NS_ASSERTION(child->GetParent()->IndexOf(child) != -1,
                        "Walked too far?");
         }
       }
 #endif
-      return static_cast<nsHTMLFormElement*>(content);
+      return static_cast<HTMLFormElement*>(content);
     }
 
     nsIContent *prevContent = content;
     content = prevContent->GetParent();
 
     if (!content && aCurrentForm) {
       // We got to the root of the subtree we're in, and we're being removed
       // from the DOM (the only time we get into this method with a non-null
@@ -2153,17 +2153,17 @@ nsGenericHTMLFormElement::SaveSubtreeSta
 void
 nsGenericHTMLFormElement::SetForm(nsIDOMHTMLFormElement* aForm)
 {
   NS_PRECONDITION(aForm, "Don't pass null here");
   NS_ASSERTION(!mForm,
                "We don't support switching from one non-null form to another.");
 
   // keep a *weak* ref to the form here
-  mForm = static_cast<nsHTMLFormElement*>(aForm);
+  mForm = static_cast<HTMLFormElement*>(aForm);
 }
 
 void
 nsGenericHTMLFormElement::ClearForm(bool aRemoveFromForm)
 {
   NS_ASSERTION((mForm != nullptr) == HasFlag(ADDED_TO_FORM),
                "Form control should have had flag set correctly");
 
@@ -2175,22 +2175,22 @@ nsGenericHTMLFormElement::ClearForm(bool
     nsAutoString nameVal, idVal;
     GetAttr(kNameSpaceID_None, nsGkAtoms::name, nameVal);
     GetAttr(kNameSpaceID_None, nsGkAtoms::id, idVal);
 
     mForm->RemoveElement(this, true);
 
     if (!nameVal.IsEmpty()) {
       mForm->RemoveElementFromTable(this, nameVal,
-                                    nsHTMLFormElement::ElementRemoved);
+                                    HTMLFormElement::ElementRemoved);
     }
 
     if (!idVal.IsEmpty()) {
       mForm->RemoveElementFromTable(this, idVal,
-                                    nsHTMLFormElement::ElementRemoved);
+                                    HTMLFormElement::ElementRemoved);
     }
   }
 
   UnsetFlags(ADDED_TO_FORM);
   mForm = nullptr;
 }
 
 Element*
@@ -2312,33 +2312,33 @@ nsGenericHTMLFormElement::BeforeSetAttr(
 
     // remove the control from the hashtable as needed
 
     if (mForm && (aName == nsGkAtoms::name || aName == nsGkAtoms::id)) {
       GetAttr(kNameSpaceID_None, aName, tmp);
 
       if (!tmp.IsEmpty()) {
         mForm->RemoveElementFromTable(this, tmp,
-                                      nsHTMLFormElement::AttributeUpdated);
+                                      HTMLFormElement::AttributeUpdated);
       }
     }
 
     if (mForm && aName == nsGkAtoms::type) {
       GetAttr(kNameSpaceID_None, nsGkAtoms::name, tmp);
 
       if (!tmp.IsEmpty()) {
         mForm->RemoveElementFromTable(this, tmp,
-                                      nsHTMLFormElement::AttributeUpdated);
+                                      HTMLFormElement::AttributeUpdated);
       }
 
       GetAttr(kNameSpaceID_None, nsGkAtoms::id, tmp);
 
       if (!tmp.IsEmpty()) {
         mForm->RemoveElementFromTable(this, tmp,
-                                      nsHTMLFormElement::AttributeUpdated);
+                                      HTMLFormElement::AttributeUpdated);
       }
 
       mForm->RemoveElement(this, false);
 
       // Removing the element from the form can make it not be the default
       // control anymore.  Go ahead and notify on that change, though we might
       // end up readding and becoming the default control again in
       // AfterSetAttr.
@@ -2650,17 +2650,17 @@ nsGenericHTMLFormElement::UpdateFormOwne
                   "aFormIdElement shouldn't be set if aBindToTree is true!");
 
   bool needStateUpdate = false;
   if (!aBindToTree) {
     needStateUpdate = mForm && mForm->IsDefaultSubmitElement(this);
     ClearForm(true);
   }
 
-  nsHTMLFormElement *oldForm = mForm;
+  HTMLFormElement *oldForm = mForm;
 
   if (!mForm) {
     // If @form is set, we have to use that to find the form.
     nsAutoString formId;
     if (GetAttr(kNameSpaceID_None, nsGkAtoms::form, formId)) {
       if (!formId.IsEmpty()) {
         Element* element = nullptr;
 
@@ -2673,17 +2673,17 @@ nsGenericHTMLFormElement::UpdateFormOwne
         NS_ASSERTION(GetCurrentDoc(), "The element should be in a document "
                                       "when UpdateFormOwner is called!");
         NS_ASSERTION(!GetCurrentDoc() ||
                      element == GetCurrentDoc()->GetElementById(formId),
                      "element should be equals to the current element "
                      "associated with the id in @form!");
 
         if (element && element->IsHTML(nsGkAtoms::form)) {
-          mForm = static_cast<nsHTMLFormElement*>(element);
+          mForm = static_cast<HTMLFormElement*>(element);
         }
       }
      } else {
       // We now have a parent, so we may have picked up an ancestor form.  Search
       // for it.  Note that if mForm is already set we don't want to do this,
       // because that means someone (probably the content sink) has already set
       // it to the right value.  Also note that even if being bound here didn't
       // change our parent, we still need to search, since our parent chain
--- a/content/html/content/src/nsGenericHTMLElement.h
+++ b/content/html/content/src/nsGenericHTMLElement.h
@@ -28,23 +28,23 @@ class nsIDOMCSSStyleDeclaration;
 class nsIURI;
 class nsIFormControlFrame;
 class nsIForm;
 class nsPresState;
 class nsILayoutHistoryState;
 class nsIEditor;
 struct nsRect;
 struct nsSize;
-class nsHTMLFormElement;
 class nsIDOMHTMLMenuElement;
 class nsIDOMHTMLCollection;
 class nsDOMSettableTokenList;
 
 namespace mozilla {
 namespace dom{
+class HTMLFormElement;
 class HTMLPropertiesCollection;
 class HTMLMenuElement;
 }
 }
 
 typedef nsMappedAttributeElement nsGenericHTMLElementBase;
 
 /**
@@ -661,17 +661,18 @@ public:
    * Find an ancestor of this content node which is a form (could be null)
    * @param aCurrentForm the current form for this node.  If this is
    *        non-null, and no ancestor form is found, and the current form is in
    *        a connected subtree with the node, the current form will be
    *        returned.  This is needed to handle cases when HTML elements have a
    *        current form that they're not descendants of.
    * @note This method should not be called if the element has a form attribute.
    */
-  nsHTMLFormElement* FindAncestorForm(nsHTMLFormElement* aCurrentForm = nullptr);
+  mozilla::dom::HTMLFormElement*
+  FindAncestorForm(mozilla::dom::HTMLFormElement* aCurrentForm = nullptr);
 
   virtual void RecompileScriptEventListeners() MOZ_OVERRIDE;
 
   /**
    * See if the document being tested has nav-quirks mode enabled.
    * @param doc the document
    */
   static bool InNavQuirksMode(nsIDocument* aDoc);
@@ -1082,17 +1083,17 @@ public:
 
   nsINode* GetParentObject() const;
 
   virtual bool IsNodeOfType(uint32_t aFlags) const MOZ_OVERRIDE;
   virtual void SaveSubtreeState() MOZ_OVERRIDE;
 
   // nsIFormControl
   virtual mozilla::dom::Element* GetFormElement() MOZ_OVERRIDE;
-  nsHTMLFormElement* GetForm() const
+  mozilla::dom::HTMLFormElement* GetForm() const
   {
     return mForm;
   }
   virtual void SetForm(nsIDOMHTMLFormElement* aForm) MOZ_OVERRIDE;
   virtual void ClearForm(bool aRemoveFromForm) MOZ_OVERRIDE;
 
   nsresult GetForm(nsIDOMHTMLFormElement** aForm);
 
@@ -1216,17 +1217,17 @@ protected:
     eActiveWindow
   };
 
   // Get our focus state.  If this returns eInactiveWindow, it will set this
   // element as the focused element for that window.
   FocusTristate FocusState();
 
   /** The form that contains this control */
-  nsHTMLFormElement* mForm;
+  mozilla::dom::HTMLFormElement* mForm;
 
   /* This is a pointer to our closest fieldset parent if any */
   mozilla::dom::HTMLFieldSetElement* mFieldSet;
 };
 
 //----------------------------------------------------------------------
 
 /**
--- a/content/html/content/src/nsIConstraintValidation.cpp
+++ b/content/html/content/src/nsIConstraintValidation.cpp
@@ -2,17 +2,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsIConstraintValidation.h"
 
 #include "nsAString.h"
 #include "nsGenericHTMLElement.h"
-#include "nsHTMLFormElement.h"
+#include "mozilla/dom/HTMLFormElement.h"
 #include "mozilla/dom/ValidityState.h"
 #include "nsIFormControl.h"
 #include "nsContentUtils.h"
 
 const uint16_t nsIConstraintValidation::sContentSpecifiedMaxLengthMessage = 256;
 
 nsIConstraintValidation::nsIConstraintValidation()
   : mValidityBitField(0)
@@ -131,18 +131,18 @@ nsIConstraintValidation::SetValidityStat
     mValidityBitField &= ~aState;
   }
 
   // Inform the form element if our validity has changed.
   if (previousValidity != IsValid() && IsCandidateForConstraintValidation()) {
     nsCOMPtr<nsIFormControl> formCtrl = do_QueryInterface(this);
     NS_ASSERTION(formCtrl, "This interface should be used by form elements!");
 
-    nsHTMLFormElement* form =
-      static_cast<nsHTMLFormElement*>(formCtrl->GetFormElement());
+    mozilla::dom::HTMLFormElement* form =
+      static_cast<mozilla::dom::HTMLFormElement*>(formCtrl->GetFormElement());
     if (form) {
       form->UpdateValidity(IsValid());
     }
   }
 }
 
 void
 nsIConstraintValidation::SetCustomValidity(const nsAString& aError)
@@ -159,18 +159,18 @@ nsIConstraintValidation::SetBarredFromCo
   mBarredFromConstraintValidation = aBarred;
 
   // Inform the form element if our status regarding constraint validation
   // is going to change.
   if (!IsValid() && previousBarred != mBarredFromConstraintValidation) {
     nsCOMPtr<nsIFormControl> formCtrl = do_QueryInterface(this);
     NS_ASSERTION(formCtrl, "This interface should be used by form elements!");
 
-    nsHTMLFormElement* form =
-      static_cast<nsHTMLFormElement*>(formCtrl->GetFormElement());
+    mozilla::dom::HTMLFormElement* form =
+      static_cast<mozilla::dom::HTMLFormElement*>(formCtrl->GetFormElement());
     if (form) {
       // If the element is going to be barred from constraint validation,
       // we can inform the form that we are now valid.
       // Otherwise, we are now invalid.
       form->UpdateValidity(aBarred);
     }
   }
 }
--- a/content/html/content/test/reflect.js
+++ b/content/html/content/test/reflect.js
@@ -53,40 +53,28 @@ function reflectString(aParameters)
   element.setAttribute(contentAttr, null);
   is(element.getAttribute(contentAttr), "null",
      "null should have been stringified to 'null' for '" + contentAttr + "'");
   is(element[idlAttr], "null",
       "null should have been stringified to 'null' for '" + idlAttr + "'");
   element.removeAttribute(contentAttr);
 
   element[idlAttr] = null;
-  // TODO: remove this ugly hack when null stringification will work as expected.
-  var todoAttrs = {
-    form: [ "acceptCharset", "name", "target" ],
-  };
-  if (!(element.localName in todoAttrs) || todoAttrs[element.localName].indexOf(idlAttr) == -1) {
-    if (treatNullAs == "EmptyString") {
-      is(element.getAttribute(contentAttr), "",
-         "null should have been stringified to '' for '" + contentAttr + "'");
-      is(element[idlAttr], "",
-         "null should have been stringified to '' for '" + idlAttr + "'");
-    } else {
-      is(element.getAttribute(contentAttr), "null",
-         "null should have been stringified to 'null' for '" + contentAttr + "'");
-      is(element[idlAttr], "null",
-         "null should have been stringified to 'null' for '" + contentAttr + "'");
-    }
-    element.removeAttribute(contentAttr);
+  if (treatNullAs == "EmptyString") {
+    is(element.getAttribute(contentAttr), "",
+       "null should have been stringified to '' for '" + contentAttr + "'");
+    is(element[idlAttr], "",
+       "null should have been stringified to '' for '" + idlAttr + "'");
   } else {
-    todo_is(element.getAttribute(contentAttr), "null",
+    is(element.getAttribute(contentAttr), "null",
        "null should have been stringified to 'null' for '" + contentAttr + "'");
-    todo_is(element[idlAttr], "null",
+    is(element[idlAttr], "null",
        "null should have been stringified to 'null' for '" + contentAttr + "'");
-    element.removeAttribute(contentAttr);
   }
+  element.removeAttribute(contentAttr);
 
   // Tests various strings.
   var stringsToTest = [
     // [ test value, expected result ]
     [ "", "" ],
     [ "null", "null" ],
     [ "undefined", "undefined" ],
     [ "foo", "foo" ],
--- a/content/html/content/test/test_bug389797.html
+++ b/content/html/content/test/test_bug389797.html
@@ -67,18 +67,17 @@ function HTML_TAG(aTagName, aImplClass) 
     for (i = 0; i < arguments[3].length; ++i) {
       interfacesNonClassinfo[aTagName].push(arguments[3][i]);
     }
   }
 }
 
 const objectIfaces = [
     "imgINotificationObserver", "nsIRequestObserver", "nsIStreamListener",
-    "nsIFrameLoaderOwner", "nsIObjectLoadingContent", "nsIInterfaceRequestor",
-    "nsIChannelEventSink"
+    "nsIFrameLoaderOwner", "nsIObjectLoadingContent", "nsIChannelEventSink"
   ];
 
 var objectIfaces2 = [];
 for (var iface of objectIfaces) {
   objectIfaces2.push(iface);
 }
 objectIfaces2.push("nsIImageLoadingContent");
 
--- a/content/html/content/test/test_bug879319.html
+++ b/content/html/content/test/test_bug879319.html
@@ -47,19 +47,19 @@ ok("tmp1" in form.elements, "tmp1 is in 
 ok(!("tmp0" in form.elements), "tmp0 is not in form.elements");
 ok(!("foo0" in form.elements), "foo0 is not in form.elements");
 is(form.tmp0, input0, "Form.tmp0 == input0");
 is(form.tmp1, input0, "Form.tmp1 == input0");
 is(form.foo0, input0, "Form.foo0 is still here");
 
 input0.setAttribute("form", "");
 ok(!("foo0" in form.elements), "foo0 is not in form.elements");
-todo_is(form.foo0, undefined, "Form.foo0 should not still be here");
-todo_is(form.tmp0, undefined, "Form.tmp0 should not still be here");
-todo_is(form.tmp1, undefined, "Form.tmp1 should not still be here");
+is(form.foo0, undefined, "Form.foo0 should not still be here");
+is(form.tmp0, undefined, "Form.tmp0 should not still be here");
+is(form.tmp1, undefined, "Form.tmp1 should not still be here");
 
 var input1 = document.getElementById("input1");
 ok(input1, "input1 exists");
 is(form.foo1, input1, "Form.foo1 should exist");
 
 ok("foo1" in form.elements, "foo1 in form.elements");
 is(input1.form, form, "input1.form is form");
 
@@ -68,24 +68,25 @@ ok("foo0" in form.elements, "foo0 is in 
 is(form.foo0, input1, "Form.foo0 should be input1");
 is(form.foo1, input1, "Form.foo1 should be input1");
 
 var input2 = document.getElementById("input2");
 ok(input2, "input2 exists");
 is(form.foo2, input2, "Form.foo2 should exist");
 input2.parentNode.removeChild(input2);
 ok(!("foo2" in form.elements), "foo2 is not in form.elements");
-todo_is(form.foo2, undefined, "Form.foo2 should not longer be there");
+is(form.foo2, undefined, "Form.foo2 should not longer be there");
 
 var img0 = document.getElementById("img0");
 ok(img0, "img0 exists");
 is(form.bar0, img0, "Form.bar0 should exist");
 
 img0.setAttribute("name", "old_bar0");
+is(form.old_bar0, img0, "Form.bar0 is still here");
 is(form.bar0, img0, "Form.bar0 is still here");
 
 img0.parentNode.removeChild(img0);
-todo_is(form.bar0, undefined, "Form.bar0 should not be here");
+is(form.bar0, undefined, "Form.bar0 should not be here");
 
 </script>
 </pre>
 </body>
 </html>
--- a/content/media/AudioNodeStream.h
+++ b/content/media/AudioNodeStream.h
@@ -103,16 +103,22 @@ public:
   bool IsAudioParamStream() const
   {
     return mAudioParamStream;
   }
   const OutputChunks& LastChunks() const
   {
     return mLastChunks;
   }
+  virtual bool MainThreadNeedsUpdates() const MOZ_OVERRIDE
+  {
+    // Only source and external streams need updates on the main thread.
+    return (mKind == MediaStreamGraph::SOURCE_STREAM && mFinished) ||
+           mKind == MediaStreamGraph::EXTERNAL_STREAM;
+  }
 
   // Any thread
   AudioNodeEngine* Engine() { return mEngine; }
   TrackRate SampleRate() const { return mSampleRate; }
 
 protected:
   void FinishOutput();
 
--- a/content/media/MediaStreamGraph.cpp
+++ b/content/media/MediaStreamGraph.cpp
@@ -888,28 +888,34 @@ MediaStreamGraphImpl::PlayVideo(MediaStr
   }
 }
 
 void
 MediaStreamGraphImpl::PrepareUpdatesToMainThreadState(bool aFinalUpdate)
 {
   mMonitor.AssertCurrentThreadOwns();
 
+  mStreamUpdates.SetCapacity(mStreamUpdates.Length() + mStreams.Length());
   for (uint32_t i = 0; i < mStreams.Length(); ++i) {
     MediaStream* stream = mStreams[i];
+    if (!stream->MainThreadNeedsUpdates()) {
+      continue;
+    }
     StreamUpdate* update = mStreamUpdates.AppendElement();
     update->mGraphUpdateIndex = stream->mGraphUpdateIndices.GetAt(mCurrentTime);
     update->mStream = stream;
     update->mNextMainThreadCurrentTime =
       GraphTimeToStreamTime(stream, mCurrentTime);
     update->mNextMainThreadFinished =
       stream->mFinished &&
       StreamTimeToGraphTime(stream, stream->GetBufferEnd()) <= mCurrentTime;
   }
-  mUpdateRunnables.MoveElementsFrom(mPendingUpdateRunnables);
+  if (!mPendingUpdateRunnables.IsEmpty()) {
+    mUpdateRunnables.MoveElementsFrom(mPendingUpdateRunnables);
+  }
 
   // Don't send the message to the main thread if it's not going to have
   // any work to do.
   if (aFinalUpdate ||
       !mUpdateRunnables.IsEmpty() ||
       !mCurrentTaskMessageQueue.IsEmpty() ||
       !mStreamUpdates.IsEmpty()) {
     EnsureStableStateEventPosted();
--- a/content/media/MediaStreamGraph.h
+++ b/content/media/MediaStreamGraph.h
@@ -438,16 +438,22 @@ public:
   void ApplyTrackDisabling(TrackID aTrackID, MediaSegment* aSegment);
 
   DOMMediaStream* GetWrapper()
   {
     NS_ASSERTION(NS_IsMainThread(), "Only use DOMMediaStream on main thread");
     return mWrapper;
   }
 
+  // Return true if the main thread needs to observe updates from this stream.
+  virtual bool MainThreadNeedsUpdates() const
+  {
+    return true;
+  }
+
 protected:
   virtual void AdvanceTimeVaryingValuesToCurrentTime(GraphTime aCurrentTime, GraphTime aBlockedTime)
   {
     mBufferStartTime += aBlockedTime;
     mGraphUpdateIndices.InsertTimeAtStart(aBlockedTime);
     mGraphUpdateIndices.AdvanceCurrentTime(aCurrentTime);
     mExplicitBlockerCount.AdvanceCurrentTime(aCurrentTime);
 
@@ -932,17 +938,17 @@ public:
    * tracks, whichever is greater.
    * TODO at some point we will probably need to add API to select
    * particular tracks of each input stream.
    */
   ProcessedMediaStream* CreateTrackUnionStream(DOMMediaStream* aWrapper);
   // Internal AudioNodeStreams can only pass their output to another
   // AudioNode, whereas external AudioNodeStreams can pass their output
   // to an nsAudioStream for playback.
-  enum AudioNodeStreamKind { INTERNAL_STREAM, EXTERNAL_STREAM };
+  enum AudioNodeStreamKind { SOURCE_STREAM, INTERNAL_STREAM, EXTERNAL_STREAM };
   /**
    * Create a stream that will process audio for an AudioNode.
    * Takes ownership of aEngine.  aSampleRate is the sampling rate used
    * for the stream.  If 0 is passed, the sampling rate of the engine's
    * node will get used.
    */
   AudioNodeStream* CreateAudioNodeStream(AudioNodeEngine* aEngine,
                                          AudioNodeStreamKind aKind,
--- a/content/media/webaudio/AudioBufferSourceNode.cpp
+++ b/content/media/webaudio/AudioBufferSourceNode.cpp
@@ -433,17 +433,17 @@ AudioBufferSourceNode::AudioBufferSource
   , mDuration(std::numeric_limits<double>::min())
   , mPlaybackRate(new AudioParam(this, SendPlaybackRateToStream, 1.0f))
   , mLoop(false)
   , mStartCalled(false)
   , mStopped(false)
 {
   mStream = aContext->Graph()->CreateAudioNodeStream(
       new AudioBufferSourceNodeEngine(this, aContext->Destination()),
-      MediaStreamGraph::INTERNAL_STREAM);
+      MediaStreamGraph::SOURCE_STREAM);
   mStream->AddMainThreadListener(this);
 }
 
 AudioBufferSourceNode::~AudioBufferSourceNode()
 {
   if (Context()) {
     Context()->UnregisterAudioBufferSourceNode(this);
   }
--- a/content/xbl/src/nsXBLDocumentInfo.cpp
+++ b/content/xbl/src/nsXBLDocumentInfo.cpp
@@ -114,33 +114,33 @@ nsXBLDocGlobalObject::doCheckAccess(JSCo
 
   nsresult rv = ssm->CheckPropertyAccess(cx, base, JS_GetClass(base)->name,
                                          id, accessType);
   return NS_SUCCEEDED(rv);
 }
 
 static JSBool
 nsXBLDocGlobalObject_getProperty(JSContext *cx, JSHandleObject obj,
-                                 JSHandleId id, JSMutableHandleValue vp)
+                                 JSHandleId id, JS::MutableHandle<JS::Value> vp)
 {
   return nsXBLDocGlobalObject::
     doCheckAccess(cx, obj, id, nsIXPCSecurityManager::ACCESS_GET_PROPERTY);
 }
 
 static JSBool
 nsXBLDocGlobalObject_setProperty(JSContext *cx, JSHandleObject obj,
-                                 JSHandleId id, JSBool strict, JSMutableHandleValue vp)
+                                 JSHandleId id, JSBool strict, JS::MutableHandle<JS::Value> vp)
 {
   return nsXBLDocGlobalObject::
     doCheckAccess(cx, obj, id, nsIXPCSecurityManager::ACCESS_SET_PROPERTY);
 }
 
 static JSBool
 nsXBLDocGlobalObject_checkAccess(JSContext *cx, JSHandleObject obj, JSHandleId id,
-                                 JSAccessMode mode, JSMutableHandleValue vp)
+                                 JSAccessMode mode, JS::MutableHandle<JS::Value> vp)
 {
   uint32_t translated;
   if (mode & JSACC_WRITE) {
     translated = nsIXPCSecurityManager::ACCESS_SET_PROPERTY;
   } else {
     translated = nsIXPCSecurityManager::ACCESS_GET_PROPERTY;
   }
 
--- a/content/xbl/src/nsXBLMaybeCompiled.h
+++ b/content/xbl/src/nsXBLMaybeCompiled.h
@@ -60,26 +60,26 @@ private:
     // An pointer that represents the function before being compiled, with
     // BIT_UNCOMPILED set.
     uintptr_t mUncompiled;
 
     // The JS object for the compiled result.
     JSObject* mCompiled;
   };
 
-  friend class js::RootMethods<nsXBLMaybeCompiled<UncompiledT> >;
+  friend class js::GCMethods<nsXBLMaybeCompiled<UncompiledT> >;
 };
 
 /* Add support for JS::Heap<nsXBLMaybeCompiled>. */
 namespace js {
 
 template <class UncompiledT>
-struct RootMethods<nsXBLMaybeCompiled<UncompiledT> > : public RootMethods<JSObject *>
+struct GCMethods<nsXBLMaybeCompiled<UncompiledT> > : public GCMethods<JSObject *>
 {
-  typedef struct RootMethods<JSObject *> Base;
+  typedef struct GCMethods<JSObject *> Base;
 
   static nsXBLMaybeCompiled<UncompiledT> initial() { return nsXBLMaybeCompiled<UncompiledT>(); }
 
   static bool poisoned(nsXBLMaybeCompiled<UncompiledT> function)
   {
     return function.IsCompiled() && Base::poisoned(function.GetJSFunction());
   }
 
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -12144,17 +12144,17 @@ nsDocShell::OnLinkClickSync(nsIContent *
   }
 
   if (!IsOKToLoadURI(aURI)) {
     return NS_OK;
   }
 
   // XXX When the linking node was HTMLFormElement, it is synchronous event.
   //     That is, the caller of this method is not |OnLinkClickEvent::Run()|
-  //     but |nsHTMLFormElement::SubmitSubmission(...)|.
+  //     but |HTMLFormElement::SubmitSubmission(...)|.
   if (nsGkAtoms::form == aContent->Tag() && ShouldBlockLoadingForBackButton()) {
     return NS_OK;
   }
 
   if (aContent->IsEditable()) {
     return NS_OK;
   }
 
--- a/dom/apps/src/OfflineCacheInstaller.jsm
+++ b/dom/apps/src/OfflineCacheInstaller.jsm
@@ -73,17 +73,17 @@ function storeCache(applicationCache, ur
       applicationCache.markEntry(url, itemType);
       cacheEntry.close();
     }
   });
 }
 
 function readFile(aFile, aCallback) {
   let channel = NetUtil.newChannel(aFile);
-  channel.contentType = "pain/text";
+  channel.contentType = "plain/text";
   NetUtil.asyncFetch(channel, function(aStream, aResult) {
     if (!Components.isSuccessCode(aResult)) {
       Cu.reportError("OfflineCacheInstaller: Could not read file " + aFile.path);
       if (aCallback)
         aCallback(null);
       return;
     }
 
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -521,17 +521,17 @@ static nsDOMClassInfoData sClassInfoData
 #undef MOZ_GENERATED_EVENT_LIST
 
   NS_DEFINE_CLASSINFO_DATA(DeviceAcceleration, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(DeviceRotationRate, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   // HTML element classes
-  NS_DEFINE_CLASSINFO_DATA(HTMLFormElement, nsHTMLFormElementSH,
+  NS_DEFINE_CLASSINFO_DATA(HTMLFormElement, HTMLFormElementSH,
                            ELEMENT_SCRIPTABLE_FLAGS |
                            nsIXPCScriptable::WANT_GETPROPERTY |
                            nsIXPCScriptable::WANT_NEWENUMERATE)
 
   // CSS classes
   NS_DEFINE_CLASSINFO_DATA(CSSStyleRule, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(CSSCharsetRule, nsDOMGenericSH,
@@ -2647,17 +2647,17 @@ static JSClass sGlobalScopePolluterClass
   JS_ConvertStub,
   nullptr
 };
 
 
 // static
 JSBool
 nsWindowSH::GlobalScopePolluterGetProperty(JSContext *cx, JSHandleObject obj,
-                                           JSHandleId id, JSMutableHandleValue vp)
+                                           JSHandleId id, JS::MutableHandle<JS::Value> vp)
 {
   // Someone is accessing a element by referencing its name/id in the
   // global scope, do a security check to make sure that's ok.
 
   nsresult rv =
     sSecMan->CheckPropertyAccess(cx, ::JS_GetGlobalForObject(cx, obj),
                                  "Window", id,
                                  nsIXPCSecurityManager::ACCESS_GET_PROPERTY);
@@ -2670,17 +2670,17 @@ nsWindowSH::GlobalScopePolluterGetProper
   }
 
   return JS_TRUE;
 }
 
 // Gets a subframe.
 static JSBool
 ChildWindowGetter(JSContext *cx, JSHandleObject obj, JSHandleId id,
-                  JSMutableHandleValue vp)
+                  JS::MutableHandle<JS::Value> vp)
 {
   MOZ_ASSERT(JSID_IS_STRING(id));
   // Grab the native DOM window.
   vp.setUndefined();
   nsCOMPtr<nsISupports> winSupports =
     do_QueryInterface(nsDOMClassInfo::XPConnect()->GetNativeOfWrapper(cx, obj));
   if (!winSupports)
     return true;
@@ -3153,17 +3153,17 @@ static const IDBConstant sIDBConstants[]
   { IDBConstant::IDBRequest,     "LOADING",           "pending" },
   { IDBConstant::IDBRequest,     "DONE",              "done" },
   { IDBConstant::IDBTransaction, "READ_ONLY",         "readonly" },
   { IDBConstant::IDBTransaction, "READ_WRITE",        "readwrite" },
   { IDBConstant::IDBTransaction, "VERSION_CHANGE",    "versionchange" },
 };
 
 static JSBool
-IDBConstantGetter(JSContext *cx, JSHandleObject obj, JSHandleId id, JSMutableHandleValue vp)
+IDBConstantGetter(JSContext *cx, JSHandleObject obj, JSHandleId id, JS::MutableHandle<JS::Value> vp)
 {
   JSString *idstr = JSID_TO_STRING(id);
   unsigned index;
   for (index = 0; index < mozilla::ArrayLength(sIDBConstants); index++) {
     JSBool match;
     if (!JS_StringEqualsAscii(cx, idstr, sIDBConstants[index].name, &match)) {
       return JS_FALSE;
     }
@@ -4290,30 +4290,30 @@ LocationSetterGuts(JSContext *cx, JSObje
   NS_ENSURE_TRUE(depStr.init(cx, val), NS_ERROR_UNEXPECTED);
 
   return location->SetHref(depStr);
 }
 
 template<class Interface>
 static JSBool
 LocationSetter(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict,
-               JSMutableHandleValue vp)
+               JS::MutableHandle<JS::Value> vp)
 {
   nsresult rv = LocationSetterGuts<Interface>(cx, obj, vp.address());
   if (NS_FAILED(rv)) {
     xpc::Throw(cx, rv);
     return JS_FALSE;
   }
 
   return JS_TRUE;
 }
 
 static JSBool
 LocationSetterUnwrapper(JSContext *cx, JSHandleObject obj_, JSHandleId id, JSBool strict,
-                        JSMutableHandleValue vp)
+                        JS::MutableHandle<JS::Value> vp)
 {
   JS::RootedObject obj(cx, obj_);
 
   JSObject *wrapped = XPCWrapper::UnsafeUnwrapSecurityWrapper(obj);
   if (wrapped) {
     obj = wrapped;
   }
 
@@ -5696,17 +5696,17 @@ nsHTMLDocumentSH::GetDocumentAllNodeList
     return JS_FALSE;
   }
 
   return *nodeList != nullptr;
 }
 
 JSBool
 nsHTMLDocumentSH::DocumentAllGetProperty(JSContext *cx, JSHandleObject obj_,
-                                         JSHandleId id, JSMutableHandleValue vp)
+                                         JSHandleId id, JS::MutableHandle<JS::Value> vp)
 {
   JS::Rooted<JSObject*> obj(cx, obj_);
 
   // document.all.item and .namedItem get their value in the
   // newResolve hook, so nothing to do for those properties here. And
   // we need to return early to prevent <div id="item"> from shadowing
   // document.all.item(), etc.
   if (nsDOMClassInfo::sItem_id == id || nsDOMClassInfo::sNamedItem_id == id) {
@@ -5886,63 +5886,63 @@ nsHTMLDocumentSH::CallToGetPropMapper(JS
 
   return ::JS_GetUCProperty(cx, self, chars, length, vp);
 }
 
 
 // HTMLFormElement helper
 
 NS_IMETHODIMP
-nsHTMLFormElementSH::NewResolve(nsIXPConnectWrappedNative *wrapper,
-                                JSContext *cx, JSObject *aObj, jsid aId,
-                                uint32_t flags, JSObject **objp,
-                                bool *_retval)
+HTMLFormElementSH::NewResolve(nsIXPConnectWrappedNative *wrapper,
+                              JSContext *cx, JSObject *aObj, jsid aId,
+                              uint32_t flags, JSObject **objp,
+                              bool *_retval)
 {
   JS::Rooted<JSObject*> obj(cx, aObj);
   JS::Rooted<jsid> id(cx, aId);
   // For native wrappers, do not resolve random names on form
   if ((!(JSRESOLVE_ASSIGNING & flags)) && JSID_IS_STRING(id) &&
       (!ObjectIsNativeWrapper(cx, obj) ||
        xpc::WrapperFactory::XrayWrapperNotShadowing(obj, id))) {
     nsCOMPtr<nsIForm> form(do_QueryWrappedNative(wrapper, obj));
 
     nsDependentJSString name(id);
     nsWrapperCache* cache;
     nsCOMPtr<nsISupports> result =
-      static_cast<nsHTMLFormElement*>(form.get())->FindNamedItem(name, &cache);
+      static_cast<HTMLFormElement*>(form.get())->FindNamedItem(name, &cache);
 
     if (result) {
       *_retval = ::JS_DefinePropertyById(cx, obj, id, JSVAL_VOID, nullptr,
                                          nullptr, JSPROP_ENUMERATE);
 
       *objp = obj;
 
       return *_retval ? NS_OK : NS_ERROR_FAILURE;
     }
   }
 
   return nsElementSH::NewResolve(wrapper, cx, obj, id, flags, objp, _retval);
 }
 
 
 NS_IMETHODIMP
-nsHTMLFormElementSH::GetProperty(nsIXPConnectWrappedNative *wrapper,
-                                 JSContext *cx, JSObject *aObj, jsid aId,
-                                 jsval *vp, bool *_retval)
+HTMLFormElementSH::GetProperty(nsIXPConnectWrappedNative *wrapper,
+                               JSContext *cx, JSObject *aObj, jsid aId,
+                               jsval *vp, bool *_retval)
 {
   JS::Rooted<JSObject*> obj(cx, aObj);
   JS::Rooted<jsid> id(cx, aId);
   nsCOMPtr<nsIForm> form(do_QueryWrappedNative(wrapper, obj));
 
   if (JSID_IS_STRING(id)) {
     // For native wrappers, do not get random names on form
     nsDependentJSString name(id);
     nsWrapperCache* cache;
     nsCOMPtr<nsISupports> result =
-      static_cast<nsHTMLFormElement*>(form.get())->FindNamedItem(name, &cache);
+      static_cast<HTMLFormElement*>(form.get())->FindNamedItem(name, &cache);
 
     if (result) {
       // Wrap result, result can be either an element or a list of
       // elements
       nsresult rv = WrapNative(cx, obj, result, cache, true, vp);
       return NS_FAILED(rv) ? rv : NS_SUCCESS_I_DID_SOMETHING;
     }
   } else {
@@ -5960,20 +5960,20 @@ nsHTMLFormElementSH::GetProperty(nsIXPCo
       }
     }
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsHTMLFormElementSH::NewEnumerate(nsIXPConnectWrappedNative *wrapper,
-                                  JSContext *cx, JSObject *obj,
-                                  uint32_t enum_op, jsval *statep,
-                                  jsid *idp, bool *_retval)
+HTMLFormElementSH::NewEnumerate(nsIXPConnectWrappedNative *wrapper,
+                                JSContext *cx, JSObject *obj,
+                                uint32_t enum_op, jsval *statep,
+                                jsid *idp, bool *_retval)
 {
   switch (enum_op) {
   case JSENUMERATE_INIT:
   case JSENUMERATE_INIT_ALL:
     {
       nsCOMPtr<nsIForm> form(do_QueryWrappedNative(wrapper, obj));
 
       if (!form) {
--- a/dom/base/nsDOMClassInfo.h
+++ b/dom/base/nsDOMClassInfo.h
@@ -367,17 +367,17 @@ public:
                       JSObject *obj) MOZ_OVERRIDE;
   NS_IMETHOD OuterObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
                          JSObject * obj, JSObject * *_retval) MOZ_OVERRIDE;
 
   static JSBool GlobalScopePolluterNewResolve(JSContext *cx, JSHandleObject obj,
                                               JSHandleId id, unsigned flags,
                                               JS::MutableHandle<JSObject*> objp);
   static JSBool GlobalScopePolluterGetProperty(JSContext *cx, JSHandleObject obj,
-                                               JSHandleId id, JSMutableHandleValue vp);
+                                               JSHandleId id, JS::MutableHandle<JS::Value> vp);
   static JSBool InvalidateGlobalScopePolluter(JSContext *cx,
                                               JS::Handle<JSObject*> obj);
   static nsresult InstallGlobalScopePolluter(JSContext *cx,
                                              JS::Handle<JSObject*> obj);
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsWindowSH(aData);
   }
@@ -597,34 +597,34 @@ extern JSClass sHTMLDocumentAllClass;
 class nsHTMLDocumentSH
 {
 protected:
   static JSBool GetDocumentAllNodeList(JSContext *cx, JS::Handle<JSObject*> obj,
                                        nsDocument *doc,
                                        nsContentList **nodeList);
 public:
   static JSBool DocumentAllGetProperty(JSContext *cx, JSHandleObject obj, JSHandleId id,
-                                       JSMutableHandleValue vp);
+                                       JS::MutableHandle<JS::Value> vp);
   static JSBool DocumentAllNewResolve(JSContext *cx, JSHandleObject obj, JSHandleId id,
                                       unsigned flags, JS::MutableHandle<JSObject*> objp);
   static void ReleaseDocument(JSFreeOp *fop, JSObject *obj);
   static JSBool CallToGetPropMapper(JSContext *cx, unsigned argc, jsval *vp);
 };
 
 
 // HTMLFormElement helper
 
-class nsHTMLFormElementSH : public nsElementSH
+class HTMLFormElementSH : public nsElementSH
 {
 protected:
-  nsHTMLFormElementSH(nsDOMClassInfoData* aData) : nsElementSH(aData)
+  HTMLFormElementSH(nsDOMClassInfoData* aData) : nsElementSH(aData)
   {
   }
 
-  virtual ~nsHTMLFormElementSH()
+  virtual ~HTMLFormElementSH()
   {
   }
 
 public:
   NS_IMETHOD NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                         JSObject *obj, jsid id, uint32_t flags,
                         JSObject **objp, bool *_retval) MOZ_OVERRIDE;
   NS_IMETHOD GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
@@ -633,17 +633,17 @@ public:
 
   NS_IMETHOD NewEnumerate(nsIXPConnectWrappedNative *wrapper,
                           JSContext *cx, JSObject *obj,
                           uint32_t enum_op, jsval *statep,
                           jsid *idp, bool *_retval) MOZ_OVERRIDE;
 
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
-    return new nsHTMLFormElementSH(aData);
+    return new HTMLFormElementSH(aData);
   }
 };
 
 
 // Plugin helper
 
 class nsPluginSH : public nsNamedArraySH
 {
--- a/dom/bindings/BindingDeclarations.h
+++ b/dom/bindings/BindingDeclarations.h
@@ -423,16 +423,82 @@ private:
   // Forbid copy-construction and assignment
   Optional(const Optional& other) MOZ_DELETE;
   const Optional &operator=(const Optional &other) MOZ_DELETE;
 
   bool mPassed;
   const nsAString* mStr;
 };
 
+template<class T>
+class NonNull
+{
+public:
+  NonNull()
+#ifdef DEBUG
+    : inited(false)
+#endif
+  {}
+
+  operator T&() {
+    MOZ_ASSERT(inited);
+    MOZ_ASSERT(ptr, "NonNull<T> was set to null");
+    return *ptr;
+  }
+
+  operator const T&() const {
+    MOZ_ASSERT(inited);
+    MOZ_ASSERT(ptr, "NonNull<T> was set to null");
+    return *ptr;
+  }
+
+  void operator=(T* t) {
+    ptr = t;
+    MOZ_ASSERT(ptr);
+#ifdef DEBUG
+    inited = true;
+#endif
+  }
+
+  template<typename U>
+  void operator=(U* t) {
+    ptr = t->ToAStringPtr();
+    MOZ_ASSERT(ptr);
+#ifdef DEBUG
+    inited = true;
+#endif
+  }
+
+  T** Slot() {
+#ifdef DEBUG
+    inited = true;
+#endif
+    return &ptr;
+  }
+
+  T* Ptr() {
+    MOZ_ASSERT(inited);
+    MOZ_ASSERT(ptr, "NonNull<T> was set to null");
+    return ptr;
+  }
+
+  // Make us work with smart-ptr helpers that expect a get()
+  T* get() const {
+    MOZ_ASSERT(inited);
+    MOZ_ASSERT(ptr);
+    return ptr;
+  }
+
+protected:
+  T* ptr;
+#ifdef DEBUG
+  bool inited;
+#endif
+};
+
 // Class for representing sequences in arguments.  We use a non-auto array
 // because that allows us to use sequences of sequences and the like.  This
 // needs to be fallible because web content controls the length of the array,
 // and can easily try to create very large lengths.
 template<typename T>
 class Sequence : public FallibleTArray<T>
 {
 public:
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -1750,17 +1750,17 @@ InterfaceHasInstance(JSContext* cx, JS::
     }
   }
 
   *bp = false;
   return true;
 }
 
 JSBool
-InterfaceHasInstance(JSContext* cx, JSHandleObject obj, JSMutableHandleValue vp,
+InterfaceHasInstance(JSContext* cx, JSHandleObject obj, JS::MutableHandle<JS::Value> vp,
                      JSBool* bp)
 {
   if (!vp.isObject()) {
     *bp = false;
     return true;
   }
 
   JS::Rooted<JSObject*> instanceObject(cx, &vp.toObject());
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -1346,75 +1346,16 @@ GetPropertyOnPrototype(JSContext* cx, JS
                        JS::Value* vp);
 
 bool
 HasPropertyOnPrototype(JSContext* cx, JS::Handle<JSObject*> proxy,
                        DOMProxyHandler* handler,
                        JS::Handle<jsid> id);
 
 template<class T>
-class NonNull
-{
-public:
-  NonNull()
-#ifdef DEBUG
-    : inited(false)
-#endif
-  {}
-
-  operator T&() {
-    MOZ_ASSERT(inited);
-    MOZ_ASSERT(ptr, "NonNull<T> was set to null");
-    return *ptr;
-  }
-
-  operator const T&() const {
-    MOZ_ASSERT(inited);
-    MOZ_ASSERT(ptr, "NonNull<T> was set to null");
-    return *ptr;
-  }
-
-  void operator=(T* t) {
-    ptr = t;
-    MOZ_ASSERT(ptr);
-#ifdef DEBUG
-    inited = true;
-#endif
-  }
-
-  template<typename U>
-  void operator=(U* t) {
-    ptr = t->ToAStringPtr();
-    MOZ_ASSERT(ptr);
-#ifdef DEBUG
-    inited = true;
-#endif
-  }
-
-  T* Ptr() {
-    MOZ_ASSERT(inited);
-    MOZ_ASSERT(ptr, "NonNull<T> was set to null");
-    return ptr;
-  }
-
-  // Make us work with smart-ptr helpers that expect a get()
-  T* get() const {
-    MOZ_ASSERT(inited);
-    MOZ_ASSERT(ptr);
-    return ptr;
-  }
-
-protected:
-  T* ptr;
-#ifdef DEBUG
-  bool inited;
-#endif
-};
-
-template<class T>
 class OwningNonNull
 {
 public:
   OwningNonNull()
 #ifdef DEBUG
     : inited(false)
 #endif
   {}
@@ -2024,17 +1965,17 @@ ReparentWrapper(JSContext* aCx, JS::Hand
  *
  * instance should not be a security wrapper.
  */
 JSBool
 InterfaceHasInstance(JSContext* cx, JS::Handle<JSObject*> obj,
                      JS::Handle<JSObject*> instance,
                      JSBool* bp);
 JSBool
-InterfaceHasInstance(JSContext* cx, JSHandleObject obj, JSMutableHandleValue vp,
+InterfaceHasInstance(JSContext* cx, JSHandleObject obj, JS::MutableHandle<JS::Value> vp,
                      JSBool* bp);
 
 // Helper for lenient getters/setters to report to console.  If this
 // returns false, we couldn't even get a global.
 bool
 ReportLenientThisUnwrappingFailure(JSContext* cx, JS::Handle<JSObject*> obj);
 
 inline JSObject*
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -1601,24 +1601,16 @@ def addExternalIface(iface, nativeType=N
     }
     if not nativeType is None:
         domInterface['nativeType'] = nativeType
     if not headerFile is None:
         domInterface['headerFile'] = headerFile
     domInterface['notflattened'] = notflattened
     DOMInterfaces[iface] = domInterface
 
-# If you add one of these, you need to make sure nsDOMQS.h has the relevant
-# macros added for it
-def addExternalHTMLElement(element):
-   nativeElement = 'ns' + element
-   addExternalIface(element, nativeType=nativeElement,
-                    headerFile=nativeElement + '.h')
-
-addExternalHTMLElement('HTMLFormElement')
 addExternalIface('ActivityOptions', nativeType='nsIDOMMozActivityOptions',
                  headerFile='nsIDOMActivityOptions.h')
 addExternalIface('Counter')
 addExternalIface('CSSRule')
 addExternalIface('DeviceAcceleration', headerFile='nsIDOMDeviceMotionEvent.h', notflattened=True)
 addExternalIface('DeviceRotationRate', headerFile='nsIDOMDeviceMotionEvent.h', notflattened=True)
 addExternalIface('mozIDOMApplication', nativeType='mozIDOMApplication', headerFile='nsIDOMApplicationRegistry.h')
 addExternalIface('CSSRuleList')
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -926,17 +926,17 @@ class CGAbstractClassHook(CGAbstractStat
         assert(False)
 
 class CGAddPropertyHook(CGAbstractClassHook):
     """
     A hook for addProperty, used to preserve our wrapper from GC.
     """
     def __init__(self, descriptor):
         args = [Argument('JSContext*', 'cx'), Argument('JSHandleObject', 'obj'),
-                Argument('JSHandleId', 'id'), Argument('JSMutableHandleValue', 'vp')]
+                Argument('JSHandleId', 'id'), Argument('JS::MutableHandle<JS::Value>', 'vp')]
         CGAbstractClassHook.__init__(self, descriptor, ADDPROPERTY_HOOK_NAME,
                                      'JSBool', args)
 
     def generate_code(self):
         assert not self.descriptor.workers and self.descriptor.wrapperCache
         if self.descriptor.nativeOwnership == 'nsisupports':
             preserveArgs = "reinterpret_cast<nsISupports*>(self), self"
         else:
@@ -1183,17 +1183,17 @@ class CGNamedConstructors(CGThing):
         namedConstructors = CGWrapper(CGIndenter(namedConstructors),
                                       pre="static const NamedConstructor namedConstructors[] = {\n",
                                       post="\n};\n")
         return nativePropertyHooks + namedConstructors.define()
 
 class CGClassHasInstanceHook(CGAbstractStaticMethod):
     def __init__(self, descriptor):
         args = [Argument('JSContext*', 'cx'), Argument('JSHandleObject', 'obj'),
-                Argument('JSMutableHandleValue', 'vp'), Argument('JSBool*', 'bp')]
+                Argument('JS::MutableHandle<JS::Value>', 'vp'), Argument('JSBool*', 'bp')]
         CGAbstractStaticMethod.__init__(self, descriptor, HASINSTANCE_HOOK_NAME,
                                         'JSBool', args)
 
     def define(self):
         if not NeedsGeneratedHasInstance(self.descriptor):
             return ""
         return CGAbstractStaticMethod.define(self)
 
--- a/dom/plugins/base/nsJSNPRuntime.cpp
+++ b/dom/plugins/base/nsJSNPRuntime.cpp
@@ -104,38 +104,38 @@ NPClass nsJSObjWrapper::sJSObjWrapperNPC
     nsJSObjWrapper::NP_GetProperty,
     nsJSObjWrapper::NP_SetProperty,
     nsJSObjWrapper::NP_RemoveProperty,
     nsJSObjWrapper::NP_Enumerate,
     nsJSObjWrapper::NP_Construct
   };
 
 static JSBool
-NPObjWrapper_AddProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, JSMutableHandleValue vp);
+NPObjWrapper_AddProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, JS::MutableHandle<JS::Value> vp);
 
 static JSBool
 NPObjWrapper_DelProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool *succeeded);
 
 static JSBool
 NPObjWrapper_SetProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict,
-                         JSMutableHandleValue vp);
+                         JS::MutableHandle<JS::Value> vp);
 
 static JSBool
-NPObjWrapper_GetProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, JSMutableHandleValue vp);
+NPObjWrapper_GetProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, JS::MutableHandle<JS::Value> vp);
 
 static JSBool
 NPObjWrapper_newEnumerate(JSContext *cx, JSHandleObject obj, JSIterateOp enum_op,
                           JS::Value *statep, jsid *idp);
 
 static JSBool
 NPObjWrapper_NewResolve(JSContext *cx, JSHandleObject obj, JSHandleId id, unsigned flags,
                         JS::MutableHandle<JSObject*> objp);
 
 static JSBool
-NPObjWrapper_Convert(JSContext *cx, JSHandleObject obj, JSType type, JSMutableHandleValue vp);
+NPObjWrapper_Convert(JSContext *cx, JSHandleObject obj, JSType type, JS::MutableHandle<JS::Value> vp);
 
 static void
 NPObjWrapper_Finalize(JSFreeOp *fop, JSObject *obj);
 
 static JSBool
 NPObjWrapper_Call(JSContext *cx, unsigned argc, JS::Value *vp);
 
 static JSBool
@@ -166,17 +166,17 @@ JSClass sNPObjectJSWrapperClass =
 typedef struct NPObjectMemberPrivate {
     JSObject *npobjWrapper;
     JS::Value fieldValue;
     NPIdentifier methodName;
     NPP   npp;
 } NPObjectMemberPrivate;
 
 static JSBool
-NPObjectMember_Convert(JSContext *cx, JSHandleObject obj, JSType type, JSMutableHandleValue vp);
+NPObjectMember_Convert(JSContext *cx, JSHandleObject obj, JSType type, JS::MutableHandle<JS::Value> vp);
 
 static void
 NPObjectMember_Finalize(JSFreeOp *fop, JSObject *obj);
 
 static JSBool
 NPObjectMember_Call(JSContext *cx, unsigned argc, JS::Value *vp);
 
 static void
@@ -1103,17 +1103,17 @@ GetNPObject(JSContext *cx, JSObject *obj
 
   return (NPObject *)::JS_GetPrivate(obj);
 }
 
 
 // Does not actually add a property because this is always followed by a
 // SetProperty call.
 static JSBool
-NPObjWrapper_AddProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, JSMutableHandleValue vp)
+NPObjWrapper_AddProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, JS::MutableHandle<JS::Value> vp)
 {
   NPObject *npobj = GetNPObject(cx, obj);
 
   if (!npobj || !npobj->_class || !npobj->_class->hasProperty ||
       !npobj->_class->hasMethod) {
     ThrowJSException(cx, "Bad NPObject as private data!");
 
     return JS_FALSE;
@@ -1178,17 +1178,17 @@ NPObjWrapper_DelProperty(JSContext *cx, 
   if (!npobj->_class->removeProperty(npobj, identifier))
     *succeeded = false;
 
   return ReportExceptionIfPending(cx);
 }
 
 static JSBool
 NPObjWrapper_SetProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict,
-                         JSMutableHandleValue vp)
+                         JS::MutableHandle<JS::Value> vp)
 {
   NPObject *npobj = GetNPObject(cx, obj);
 
   if (!npobj || !npobj->_class || !npobj->_class->hasProperty ||
       !npobj->_class->setProperty) {
     ThrowJSException(cx, "Bad NPObject as private data!");
 
     return JS_FALSE;
@@ -1237,17 +1237,17 @@ NPObjWrapper_SetProperty(JSContext *cx, 
 
     return JS_FALSE;
   }
 
   return JS_TRUE;
 }
 
 static JSBool
-NPObjWrapper_GetProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, JSMutableHandleValue vp)
+NPObjWrapper_GetProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, JS::MutableHandle<JS::Value> vp)
 {
   NPObject *npobj = GetNPObject(cx, obj);
 
   if (!npobj || !npobj->_class || !npobj->_class->hasProperty ||
       !npobj->_class->hasMethod || !npobj->_class->getProperty) {
     ThrowJSException(cx, "Bad NPObject as private data!");
 
     return JS_FALSE;
@@ -1601,17 +1601,17 @@ NPObjWrapper_NewResolve(JSContext *cx, J
     return fnc != nullptr;
   }
 
   // no property or method
   return JS_TRUE;
 }
 
 static JSBool
-NPObjWrapper_Convert(JSContext *cx, JSHandleObject obj, JSType hint, JSMutableHandleValue vp)
+NPObjWrapper_Convert(JSContext *cx, JSHandleObject obj, JSType hint, JS::MutableHandle<JS::Value> vp)
 {
   JS_ASSERT(hint == JSTYPE_NUMBER || hint == JSTYPE_STRING || hint == JSTYPE_VOID);
 
   // Plugins do not simply use JS_ConvertStub, and the default [[DefaultValue]]
   // behavior, because that behavior involves calling toString or valueOf on
   // objects which weren't designed to accommodate this.  Usually this wouldn't
   // be a problem, because the absence of either property, or the presence of
   // either property with a value that isn't callable, will cause that property
@@ -2021,17 +2021,17 @@ CreateNPObjectMember(NPP npp, JSContext 
   memberPrivate->npp = npp;
 
   ::JS_RemoveValueRoot(cx, vp);
 
   return JS_TRUE;
 }
 
 static JSBool
-NPObjectMember_Convert(JSContext *cx, JSHandleObject obj, JSType type, JSMutableHandleValue vp)
+NPObjectMember_Convert(JSContext *cx, JSHandleObject obj, JSType type, JS::MutableHandle<JS::Value> vp)
 {
   NPObjectMemberPrivate *memberPrivate =
     (NPObjectMemberPrivate *)::JS_GetInstancePrivate(cx, obj,
                                                      &sNPObjectMemberClass,
                                                      nullptr);
   if (!memberPrivate) {
     NS_ERROR("no Ambiguous Member Private data!");
     return JS_FALSE;
--- a/dom/webidl/FormData.webidl
+++ b/dom/webidl/FormData.webidl
@@ -2,15 +2,13 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  *
  * The origin of this IDL file is
  * http://xhr.spec.whatwg.org
  */
 
-interface HTMLFormElement;
-
 [Constructor(optional HTMLFormElement form)]
 interface FormData {
   void append(DOMString name, Blob value, optional DOMString filename);
   void append(DOMString name, DOMString value);
-};
\ No newline at end of file
+};
new file mode 100644
--- /dev/null
+++ b/dom/webidl/HTMLFormElement.webidl
@@ -0,0 +1,48 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * The origin of this IDL file is
+ * http://www.whatwg.org/specs/web-apps/current-work/#htmlformelement
+ *
+ * © Copyright 2004-2011 Apple Computer, Inc., Mozilla Foundation, and
+ * Opera Software ASA. You are granted a license to use, reproduce
+ * and create derivative works of this document.
+ */
+
+[OverrideBuiltins]
+interface HTMLFormElement : HTMLElement {
+           [Pure, SetterThrows]
+           attribute DOMString acceptCharset;
+           [Pure, SetterThrows]
+           attribute DOMString action;
+           [Pure, SetterThrows]
+           attribute DOMString autocomplete;
+           [Pure, SetterThrows]
+           attribute DOMString enctype;
+           [Pure, SetterThrows]
+           attribute DOMString encoding;
+           [Pure, SetterThrows]
+           attribute DOMString method;
+           [Pure, SetterThrows]
+           attribute DOMString name;
+           [Pure, SetterThrows]
+           attribute boolean noValidate;
+           [Pure, SetterThrows]
+           attribute DOMString target;
+
+  [Constant]
+  readonly attribute HTMLCollection elements;
+  [Pure]
+  readonly attribute long length;
+
+  getter Element (unsigned long index);
+  // TODO this should be: getter (RadioNodeList or HTMLInputElement or HTMLImageElement) (DOMString name);
+  getter nsISupports (DOMString name);
+
+  [Throws]
+  void submit();
+  void reset();
+  boolean checkValidity();
+};
--- a/dom/webidl/WebIDL.mk
+++ b/dom/webidl/WebIDL.mk
@@ -104,16 +104,17 @@ webidl_files = \
   HTMLDirectoryElement.webidl \
   HTMLDivElement.webidl \
   HTMLDListElement.webidl \
   HTMLDocument.webidl \
   HTMLElement.webidl \
   HTMLEmbedElement.webidl \
   HTMLFieldSetElement.webidl \
   HTMLFontElement.webidl \
+  HTMLFormElement.webidl \
   HTMLFrameElement.webidl \
   HTMLFrameSetElement.webidl \
   HTMLHeadElement.webidl \
   HTMLHeadingElement.webidl \
   HTMLHRElement.webidl \
   HTMLHtmlElement.webidl \
   HTMLIFrameElement.webidl \
   HTMLImageElement.webidl \
--- a/dom/workers/Events.cpp
+++ b/dom/workers/Events.cpp
@@ -215,33 +215,33 @@ private:
   static void
   Finalize(JSFreeOp* aFop, JSObject* aObj)
   {
     JS_ASSERT(IsThisClass(JS_GetClass(aObj)));
     delete GetJSPrivateSafeish<Event>(aObj);
   }
 
   static JSBool
-  GetProperty(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JSMutableHandleValue aVp)
+  GetProperty(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JS::MutableHandle<JS::Value> aVp)
   {
     JS_ASSERT(JSID_IS_INT(aIdval));
 
     int32_t slot = JSID_TO_INT(aIdval);
 
     const char* name = sProperties[slot - SLOT_FIRST].name;
     if (!GetInstancePrivate(aCx, aObj, name)) {
       return false;
     }
 
     aVp.set(JS_GetReservedSlot(aObj, slot));
     return true;
   }
 
   static JSBool
-  GetConstant(JSContext* aCx, JSHandleObject aObj, JSHandleId idval, JSMutableHandleValue aVp)
+  GetConstant(JSContext* aCx, JSHandleObject aObj, JSHandleId idval, JS::MutableHandle<JS::Value> aVp)
   {
     JS_ASSERT(JSID_IS_INT(idval));
     JS_ASSERT(JSID_TO_INT(idval) >= CAPTURING_PHASE &&
               JSID_TO_INT(idval) <= BUBBLING_PHASE);
 
     aVp.set(INT_TO_JSVAL(JSID_TO_INT(idval)));
     return true;
   }
@@ -500,17 +500,17 @@ private:
   Finalize(JSFreeOp* aFop, JSObject* aObj)
   {
     JS_ASSERT(IsThisClass(JS_GetClass(aObj)));
     MessageEvent* priv = GetJSPrivateSafeish<MessageEvent>(aObj);
     delete priv;
   }
 
   static JSBool
-  GetProperty(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JSMutableHandleValue aVp)
+  GetProperty(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JS::MutableHandle<JS::Value> aVp)
   {
     JS_ASSERT(JSID_IS_INT(aIdval));
 
     int32_t slot = JSID_TO_INT(aIdval);
 
     JS_ASSERT(slot >= SLOT_data && slot < SLOT_COUNT);
 
     const char* name = sProperties[slot - SLOT_FIRST].name;
@@ -707,17 +707,17 @@ private:
   static void
   Finalize(JSFreeOp* aFop, JSObject* aObj)
   {
     JS_ASSERT(IsThisClass(JS_GetClass(aObj)));
     delete GetJSPrivateSafeish<ErrorEvent>(aObj);
   }
 
   static JSBool
-  GetProperty(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JSMutableHandleValue aVp)
+  GetProperty(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JS::MutableHandle<JS::Value> aVp)
   {
     JS_ASSERT(JSID_IS_INT(aIdval));
 
     int32_t slot = JSID_TO_INT(aIdval);
 
     JS_ASSERT(slot >= SLOT_message && slot < SLOT_COUNT);
 
     const char* name = sProperties[slot - SLOT_FIRST].name;
@@ -886,17 +886,17 @@ private:
   static void
   Finalize(JSFreeOp* aFop, JSObject* aObj)
   {
     JS_ASSERT(JS_GetClass(aObj) == &sClass);
     delete GetJSPrivateSafeish<ProgressEvent>(aObj);
   }
 
   static JSBool
-  GetProperty(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JSMutableHandleValue aVp)
+  GetProperty(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JS::MutableHandle<JS::Value> aVp)
   {
     JS_ASSERT(JSID_IS_INT(aIdval));
 
     int32_t slot = JSID_TO_INT(aIdval);
 
     JS_ASSERT(slot >= SLOT_lengthComputable && slot < SLOT_COUNT);
 
     const char* name = sProperties[slot - SLOT_FIRST].name;
--- a/dom/workers/Exceptions.cpp
+++ b/dom/workers/Exceptions.cpp
@@ -121,17 +121,17 @@ private:
       return false;
     }
 
     JS_SET_RVAL(aCx, aVp, STRING_TO_JSVAL(out));
     return true;
   }
 
   static JSBool
-  GetProperty(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JSMutableHandleValue aVp)
+  GetProperty(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JS::MutableHandle<JS::Value> aVp)
   {
     JS_ASSERT(JSID_IS_INT(aIdval));
 
     int32_t slot = JSID_TO_INT(aIdval);
 
     JSClass* classPtr = JS_GetClass(aObj);
 
     if (classPtr != &sClass || !GetJSPrivateSafeish<DOMException>(aObj)) {
@@ -141,17 +141,17 @@ private:
       return false;
     }
 
     aVp.set(JS_GetReservedSlot(aObj, slot));
     return true;
   }
 
   static JSBool
-  GetConstant(JSContext* aCx, JSHandleObject aObj, JSHandleId idval, JSMutableHandleValue aVp)
+  GetConstant(JSContext* aCx, JSHandleObject aObj, JSHandleId idval, JS::MutableHandle<JS::Value> aVp)
   {
     JS_ASSERT(JSID_IS_INT(idval));
     aVp.set(INT_TO_JSVAL(JSID_TO_INT(idval)));
     return true;
   }
 };
 
 JSClass DOMException::sClass = {
--- a/dom/workers/File.cpp
+++ b/dom/workers/File.cpp
@@ -108,17 +108,17 @@ private:
   {
     JS_ASSERT(JS_GetClass(aObj) == &sClass);
 
     nsIDOMBlob* blob = GetPrivate(aObj);
     NS_IF_RELEASE(blob);
   }
 
   static JSBool
-  GetSize(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JSMutableHandleValue aVp)
+  GetSize(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JS::MutableHandle<JS::Value> aVp)
   {
     nsIDOMBlob* blob = GetInstancePrivate(aCx, aObj, "size");
     if (!blob) {
       return false;
     }
 
     uint64_t size;
     if (NS_FAILED(blob->GetSize(&size))) {
@@ -127,17 +127,17 @@ private:
     }
 
     aVp.set(JS_NumberValue(double(size)));
 
     return true;
   }
 
   static JSBool
-  GetType(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JSMutableHandleValue aVp)
+  GetType(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JS::MutableHandle<JS::Value> aVp)
   {
     nsIDOMBlob* blob = GetInstancePrivate(aCx, aObj, "type");
     if (!blob) {
       return false;
     }
 
     nsString type;
     if (NS_FAILED(blob->GetType(type))) {
@@ -297,17 +297,17 @@ private:
   {
     JS_ASSERT(JS_GetClass(aObj) == &sClass);
 
     nsIDOMFile* file = GetPrivate(aObj);
     NS_IF_RELEASE(file);
   }
 
   static JSBool
-  GetMozFullPath(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JSMutableHandleValue aVp)
+  GetMozFullPath(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JS::MutableHandle<JS::Value> aVp)
   {
     nsIDOMFile* file = GetInstancePrivate(aCx, aObj, "mozFullPath");
     if (!file) {
       return false;
     }
 
     nsString fullPath;
 
@@ -323,17 +323,17 @@ private:
       return false;
     }
 
     aVp.set(STRING_TO_JSVAL(jsFullPath));
     return true;
   }
 
   static JSBool
-  GetName(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JSMutableHandleValue aVp)
+  GetName(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JS::MutableHandle<JS::Value> aVp)
   {
     nsIDOMFile* file = GetInstancePrivate(aCx, aObj, "name");
     if (!file) {
       return false;
     }
 
     nsString name;
     if (NS_FAILED(file->GetName(name))) {
@@ -345,17 +345,17 @@ private:
       return false;
     }
 
     aVp.set(STRING_TO_JSVAL(jsName));
     return true;
   }
 
   static JSBool
-  GetLastModifiedDate(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JSMutableHandleValue aVp)
+  GetLastModifiedDate(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JS::MutableHandle<JS::Value> aVp)
   {
     nsIDOMFile* file = GetInstancePrivate(aCx, aObj, "lastModifiedDate");
     if (!file) {
       return false;
     }
 
     JS::Rooted<JS::Value> value(aCx);
     if (NS_FAILED(file->GetLastModifiedDate(aCx, value.address()))) {
--- a/dom/workers/ImageData.cpp
+++ b/dom/workers/ImageData.cpp
@@ -110,17 +110,17 @@ private:
   static void
   Finalize(JSFreeOp* aFop, JSObject* aObj)
   {
     MOZ_ASSERT(JS_GetClass(aObj) == &sClass);
     delete static_cast<ImageData*>(JS_GetPrivate(aObj));
   }
 
   static JSBool
-  GetProperty(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JSMutableHandleValue aVp)
+  GetProperty(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JS::MutableHandle<JS::Value> aVp)
   {
     JSClass* classPtr = JS_GetClass(aObj);
     if (classPtr != &sClass) {
       JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL,
                            JSMSG_INCOMPATIBLE_PROTO, sClass.name, "GetProperty",
                            classPtr->name);
       return false;
     }
--- a/dom/workers/Location.cpp
+++ b/dom/workers/Location.cpp
@@ -124,17 +124,17 @@ private:
 
     jsval href = JS_GetReservedSlot(obj, SLOT_href);
 
     JS_SET_RVAL(aCx, aVp, href);
     return true;
   }
 
   static JSBool
-  GetProperty(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JSMutableHandleValue aVp)
+  GetProperty(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JS::MutableHandle<JS::Value> aVp)
   {
     JSClass* classPtr = JS_GetClass(aObj);
     if (classPtr != &sClass) {
       JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL,
                            JSMSG_INCOMPATIBLE_PROTO, sClass.name, "GetProperty",
                            classPtr->name);
       return false;
     }
--- a/dom/workers/Navigator.cpp
+++ b/dom/workers/Navigator.cpp
@@ -112,17 +112,17 @@ private:
   static void
   Finalize(JSFreeOp* aFop, JSObject* aObj)
   {
     JS_ASSERT(JS_GetClass(aObj) == &sClass);
     delete static_cast<Navigator*>(JS_GetPrivate(aObj));
   }
 
   static JSBool
-  GetProperty(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JSMutableHandleValue aVp)
+  GetProperty(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JS::MutableHandle<JS::Value> aVp)
   {
     JSClass* classPtr = JS_GetClass(aObj);
     if (classPtr != &sClass) {
       JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL,
                            JSMSG_INCOMPATIBLE_PROTO, sClass.name, "GetProperty",
                            classPtr->name);
       return false;
     }
--- a/dom/workers/Worker.cpp
+++ b/dom/workers/Worker.cpp
@@ -170,17 +170,17 @@ protected:
 private:
   // No instance of this class should ever be created so these are explicitly
   // left without an implementation to prevent linking in case someone tries to
   // make one.
   Worker();
   ~Worker();
 
   static JSBool
-  GetEventListener(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JSMutableHandleValue aVp)
+  GetEventListener(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JS::MutableHandle<JS::Value> aVp)
   {
     JS_ASSERT(JSID_IS_INT(aIdval));
     JS_ASSERT(JSID_TO_INT(aIdval) >= 0 && JSID_TO_INT(aIdval) < STRING_COUNT);
 
     const char* name = sEventStrings[JSID_TO_INT(aIdval)];
     WorkerPrivate* worker = GetInstancePrivate(aCx, aObj, name);
     if (!worker) {
       return !JS_IsExceptionPending(aCx);
@@ -195,17 +195,17 @@ private:
     }
 
     aVp.set(listener ? OBJECT_TO_JSVAL(listener) : JSVAL_NULL);
     return true;
   }
 
   static JSBool
   SetEventListener(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JSBool aStrict,
-                   JSMutableHandleValue aVp)
+                   JS::MutableHandle<JS::Value> aVp)
   {
     JS_ASSERT(JSID_IS_INT(aIdval));
     JS_ASSERT(JSID_TO_INT(aIdval) >= 0 && JSID_TO_INT(aIdval) < STRING_COUNT);
 
     const char* name = sEventStrings[JSID_TO_INT(aIdval)];
     WorkerPrivate* worker = GetInstancePrivate(aCx, aObj, name);
     if (!worker) {
       return !JS_IsExceptionPending(aCx);
--- a/dom/workers/WorkerScope.cpp
+++ b/dom/workers/WorkerScope.cpp
@@ -137,17 +137,17 @@ protected:
   virtual void
   _finalize(JSFreeOp* aFop) MOZ_OVERRIDE
   {
     EventTarget::_finalize(aFop);
   }
 
 private:
   static JSBool
-  GetEventListener(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JSMutableHandleValue aVp)
+  GetEventListener(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JS::MutableHandle<JS::Value> aVp)
   {
     JS_ASSERT(JSID_IS_INT(aIdval));
     JS_ASSERT(JSID_TO_INT(aIdval) >= 0 && JSID_TO_INT(aIdval) < STRING_COUNT);
 
     const char* name = sEventStrings[JSID_TO_INT(aIdval)];
     WorkerGlobalScope* scope = GetInstancePrivate(aCx, aObj, name);
     if (!scope) {
       return false;
@@ -164,17 +164,17 @@ private:
     }
 
     aVp.set(listener ? OBJECT_TO_JSVAL(listener) : JSVAL_NULL);
     return true;
   }
 
   static JSBool
   SetEventListener(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JSBool aStrict,
-                   JSMutableHandleValue aVp)
+                   JS::MutableHandle<JS::Value> aVp)
   {
     JS_ASSERT(JSID_IS_INT(aIdval));
     JS_ASSERT(JSID_TO_INT(aIdval) >= 0 && JSID_TO_INT(aIdval) < STRING_COUNT);
 
     const char* name = sEventStrings[JSID_TO_INT(aIdval)];
     WorkerGlobalScope* scope = GetInstancePrivate(aCx, aObj, name);
     if (!scope) {
       return false;
@@ -204,28 +204,28 @@ private:
   Construct(JSContext* aCx, unsigned aArgc, jsval* aVp)
   {
     JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL, JSMSG_WRONG_CONSTRUCTOR,
                          sClass.name);
     return false;
   }
 
   static JSBool
-  GetSelf(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JSMutableHandleValue aVp)
+  GetSelf(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JS::MutableHandle<JS::Value> aVp)
   {
     if (!GetInstancePrivate(aCx, aObj, "self")) {
       return false;
     }
 
     aVp.set(OBJECT_TO_JSVAL(aObj));
     return true;
   }
 
   static JSBool
-  GetLocation(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JSMutableHandleValue aVp)
+  GetLocation(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JS::MutableHandle<JS::Value> aVp)
   {
     WorkerGlobalScope* scope =
       GetInstancePrivate(aCx, aObj, sProperties[SLOT_location].name);
     if (!scope) {
       return false;
     }
 
     if (JSVAL_IS_VOID(scope->mSlots[SLOT_location])) {
@@ -304,17 +304,17 @@ private:
         !JS_CallFunctionName(aCx, event, "preventDefault", 0, NULL, rval.address())) {
       return false;
     }
 
     return true;
   }
 
   static JSBool
-  GetOnErrorListener(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JSMutableHandleValue aVp)
+  GetOnErrorListener(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JS::MutableHandle<JS::Value> aVp)
   {
     const char* name = sEventStrings[STRING_onerror];
     WorkerGlobalScope* scope = GetInstancePrivate(aCx, aObj, name);
     if (!scope) {
       return false;
     }
 
     ErrorResult rv;
@@ -336,17 +336,17 @@ private:
 
     JS_ASSERT(!JSVAL_IS_PRIMITIVE(aVp));
 
     return true;
   }
 
   static JSBool
   SetOnErrorListener(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval,
-                     JSBool aStrict, JSMutableHandleValue aVp)
+                     JSBool aStrict, JS::MutableHandle<JS::Value> aVp)
   {
     const char* name = sEventStrings[STRING_onerror];
     WorkerGlobalScope* scope = GetInstancePrivate(aCx, aObj, name);
     if (!scope) {
       return false;
     }
 
     if (JSVAL_IS_PRIMITIVE(aVp)) {
@@ -378,17 +378,17 @@ private:
       JS_ReportError(aCx, "Failed to set event listener!");
       return false;
     }
 
     return true;
   }
 
   static JSBool
-  GetNavigator(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JSMutableHandleValue aVp)
+  GetNavigator(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JS::MutableHandle<JS::Value> aVp)
   {
     WorkerGlobalScope* scope =
       GetInstancePrivate(aCx, aObj, sProperties[SLOT_navigator].name);
     if (!scope) {
       return false;
     }
 
     if (JSVAL_IS_VOID(scope->mSlots[SLOT_navigator])) {
@@ -727,17 +727,17 @@ protected:
     MOZ_COUNT_DTOR(mozilla::dom::workers::DedicatedWorkerGlobalScope);
   }
 
 private:
   using EventTarget::GetEventListener;
   using EventTarget::SetEventListener;
 
   static JSBool
-  GetEventListener(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JSMutableHandleValue aVp)
+  GetEventListener(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JS::MutableHandle<JS::Value> aVp)
   {
     JS_ASSERT(JSID_IS_INT(aIdval));
     JS_ASSERT(JSID_TO_INT(aIdval) >= 0 && JSID_TO_INT(aIdval) < STRING_COUNT);
 
     const char* name = sEventStrings[JSID_TO_INT(aIdval)];
     DedicatedWorkerGlobalScope* scope = GetInstancePrivate(aCx, aObj, name);
     if (!scope) {
       return false;
@@ -754,17 +754,17 @@ private:
     }
 
     aVp.set(listener ? OBJECT_TO_JSVAL(listener) : JSVAL_NULL);
     return true;
   }
 
   static JSBool
   SetEventListener(JSContext* aCx, JSHandleObject aObj, JSHandleId aIdval, JSBool aStrict,
-                   JSMutableHandleValue aVp)
+                   JS::MutableHandle<JS::Value> aVp)
   {
     JS_ASSERT(JSID_IS_INT(aIdval));
     JS_ASSERT(JSID_TO_INT(aIdval) >= 0 && JSID_TO_INT(aIdval) < STRING_COUNT);
 
     const char* name = sEventStrings[JSID_TO_INT(aIdval)];
     DedicatedWorkerGlobalScope* scope = GetInstancePrivate(aCx, aObj, name);
     if (!scope) {
       return false;
--- a/gfx/2d/SourceSurfaceD2DTarget.cpp
+++ b/gfx/2d/SourceSurfaceD2DTarget.cpp
@@ -94,16 +94,21 @@ SourceSurfaceD2DTarget::GetSRView()
 void
 SourceSurfaceD2DTarget::DrawTargetWillChange()
 {
   RefPtr<ID3D10Texture2D> oldTexture = mTexture;
 
   D3D10_TEXTURE2D_DESC desc;
   mTexture->GetDesc(&desc);
 
+  // Our original texture might implement the keyed mutex flag. We shouldn't
+  // need that here. We actually specifically don't want it since we don't lock
+  // our texture for usage!
+  desc.MiscFlags = 0;
+
   // Get a copy of the surface data so the content at snapshot time was saved.
   Factory::GetDirect3D10Device()->CreateTexture2D(&desc, nullptr, byRef(mTexture));
   Factory::GetDirect3D10Device()->CopyResource(mTexture, oldTexture);
 
   mBitmap = nullptr;
 
   DrawTargetD2D::mVRAMUsageSS += desc.Width * desc.Height * BytesPerPixel(mFormat);
   mOwnsCopy = true;
--- a/gfx/layers/ipc/PGrallocBuffer.ipdl
+++ b/gfx/layers/ipc/PGrallocBuffer.ipdl
@@ -14,17 +14,16 @@ namespace layers {
 
 /**
  * This is a trivial protocol that's used to track gralloc buffers
  * across thread contexts.  A live PGrallocBuffer actor always
  * corresponds 1:1 to a pre-shared gralloc buffer (sharing is done by
  * the PGrallocBuffer constructor).
  */
 async protocol PGrallocBuffer {
-  // FIXME: Bug 783451: shouldn't be managed by PCompositor or PImageContainer
   manager PImageBridge or PLayerTransaction;
 
   /** Gralloc buffers can be "owned" by either parent or child. */
 both:
   async __delete__();
 };
 
 } // namespace layers
--- a/ipc/chromium/src/base/pickle.cc
+++ b/ipc/chromium/src/base/pickle.cc
@@ -1,58 +1,133 @@
 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "base/pickle.h"
 
+#include "mozilla/Endian.h"
+#include "mozilla/TypeTraits.h"
+#include "mozilla/Util.h"
+
 #include <stdlib.h>
 
 #include <limits>
 #include <string>
 
 //------------------------------------------------------------------------------
 
+MOZ_STATIC_ASSERT(MOZ_ALIGNOF(Pickle::memberAlignmentType) >= MOZ_ALIGNOF(uint32_t),
+		  "Insufficient alignment");
+
 // static
 const int Pickle::kPayloadUnit = 64;
 
 // We mark a read only pickle with a special capacity_.
 static const uint32_t kCapacityReadOnly = (uint32_t) -1;
 
 static const char kBytePaddingMarker = char(0xbf);
 
-// Payload is uint32_t aligned.
+namespace {
+
+// We want to copy data to our payload as efficiently as possible.
+// memcpy fits the bill for copying, but not all compilers or
+// architectures support inlining memcpy from void*, which has unknown
+// static alignment.  However, we know that all the members of our
+// payload will be aligned on memberAlignmentType boundaries.  We
+// therefore use that knowledge to construct a copier that will copy
+// efficiently (via standard C++ assignment mechanisms) if the datatype
+// needs that alignment or less, and memcpy otherwise.  (The compiler
+// may still inline memcpy, of course.)
+
+template<typename T, size_t size, bool hasSufficientAlignment>
+struct Copier
+{
+  static void Copy(T* dest, void** iter) {
+    memcpy(dest, *iter, sizeof(T));
+  }
+};
+
+// Copying 64-bit quantities happens often enough and can easily be made
+// worthwhile on 32-bit platforms, so handle it specially.  Only do it
+// if 64-bit types aren't sufficiently aligned; the alignment
+// requirements for them vary between 32-bit platforms.
+#ifndef HAVE_64BIT_OS
+template<typename T>
+struct Copier<T, sizeof(uint64_t), false>
+{
+  static void Copy(T* dest, void** iter) {
+#if MOZ_LITTLE_ENDIAN
+    static const int loIndex = 0, hiIndex = 1;
+#else
+    static const int loIndex = 1, hiIndex = 0;
+#endif
+    MOZ_STATIC_ASSERT(MOZ_ALIGNOF(uint32_t*) == MOZ_ALIGNOF(void*),
+		      "Pointers have different alignments");
+    uint32_t* src = *reinterpret_cast<uint32_t**>(iter);
+    uint32_t* uint32dest = reinterpret_cast<uint32_t*>(dest);
+    uint32dest[loIndex] = src[loIndex];
+    uint32dest[hiIndex] = src[hiIndex];
+  }
+};
+#endif
+
+template<typename T, size_t size>
+struct Copier<T, size, true>
+{
+  static void Copy(T* dest, void** iter) {
+    // The reinterpret_cast is only safe if two conditions hold:
+    // (1) If the alignment of T* is the same as void*;
+    // (2) The alignment of the data in *iter is at least as
+    //     big as MOZ_ALIGNOF(T).
+    // Check the first condition, as the second condition is already
+    // known to be true, or we wouldn't be here.
+    MOZ_STATIC_ASSERT(MOZ_ALIGNOF(T*) == MOZ_ALIGNOF(void*),
+		      "Pointers have different alignments");
+    *dest = *(*reinterpret_cast<T**>(iter));
+  }
+};
+
+template<typename T>
+void CopyFromIter(T* dest, void** iter) {
+  MOZ_STATIC_ASSERT(mozilla::IsPod<T>::value, "Copied type must be a POD type");
+  Copier<T, sizeof(T), (MOZ_ALIGNOF(T) <= sizeof(Pickle::memberAlignmentType))>::Copy(dest, iter);
+}
+
+} // anonymous namespace
+
+// Payload is sizeof(Pickle::memberAlignmentType) aligned.
 
 Pickle::Pickle()
     : header_(NULL),
       header_size_(sizeof(Header)),
       capacity_(0),
       variable_buffer_offset_(0) {
   Resize(kPayloadUnit);
   header_->payload_size = 0;
 }
 
 Pickle::Pickle(int header_size)
     : header_(NULL),
-      header_size_(AlignInt(header_size, sizeof(uint32_t))),
+      header_size_(AlignInt(header_size)),
       capacity_(0),
       variable_buffer_offset_(0) {
-  DCHECK(static_cast<uint32_t>(header_size) >= sizeof(Header));
+  DCHECK(static_cast<memberAlignmentType>(header_size) >= sizeof(Header));
   DCHECK(header_size <= kPayloadUnit);
   Resize(kPayloadUnit);
   header_->payload_size = 0;
 }
 
 Pickle::Pickle(const char* data, int data_len)
     : header_(reinterpret_cast<Header*>(const_cast<char*>(data))),
       header_size_(data_len - header_->payload_size),
       capacity_(kCapacityReadOnly),
       variable_buffer_offset_(0) {
   DCHECK(header_size_ >= sizeof(Header));
-  DCHECK(header_size_ == AlignInt(header_size_, sizeof(uint32_t)));
+  DCHECK(header_size_ == AlignInt(header_size_));
 }
 
 Pickle::Pickle(const Pickle& other)
     : header_(NULL),
       header_size_(other.header_size_),
       capacity_(0),
       variable_buffer_offset_(other.variable_buffer_offset_) {
   uint32_t payload_size = header_size_ + other.header_->payload_size;
@@ -93,67 +168,62 @@ bool Pickle::ReadBool(void** iter, bool*
 bool Pickle::ReadInt16(void** iter, int16_t* result) const {
   DCHECK(iter);
   if (!*iter)
     *iter = const_cast<char*>(payload());
 
   if (!IteratorHasRoomFor(*iter, sizeof(*result)))
     return false;
 
-  memcpy(result, *iter, sizeof(*result));
+  CopyFromIter(result, iter);
 
   UpdateIter(iter, sizeof(*result));
   return true;
 }
 
 bool Pickle::ReadUInt16(void** iter, uint16_t* result) const {
   DCHECK(iter);
   if (!*iter)
     *iter = const_cast<char*>(payload());
 
   if (!IteratorHasRoomFor(*iter, sizeof(*result)))
     return false;
 
-  memcpy(result, *iter, sizeof(*result));
+  CopyFromIter(result, iter);
 
   UpdateIter(iter, sizeof(*result));
   return true;
 }
 
 bool Pickle::ReadInt(void** iter, int* result) const {
   DCHECK(iter);
   if (!*iter)
     *iter = const_cast<char*>(payload());
 
   if (!IteratorHasRoomFor(*iter, sizeof(*result)))
     return false;
 
-  // TODO(jar) bug 1129285: Pickle should be cleaned up, and not dependent on
-  // alignment.
-  // Next line is otherwise the same as: memcpy(result, *iter, sizeof(*result));
-  *result = *reinterpret_cast<int*>(*iter);
+  CopyFromIter(result, iter);
 
   UpdateIter(iter, sizeof(*result));
   return true;
 }
 
 // Always written as a 64-bit value since the size for this type can
 // differ between architectures.
 bool Pickle::ReadLong(void** iter, long* result) const {
   DCHECK(iter);
   if (!*iter)
     *iter = const_cast<char*>(payload());
 
   int64_t bigResult = 0;
   if (!IteratorHasRoomFor(*iter, sizeof(bigResult)))
     return false;
 
-  // TODO(jar) bug 1129285: Pickle should be cleaned up, and not dependent on
-  // alignment.
-  memcpy(&bigResult, *iter, sizeof(bigResult));
+  CopyFromIter(&bigResult, iter);
   DCHECK(bigResult <= LONG_MAX && bigResult >= LONG_MIN);
   *result = static_cast<long>(bigResult);
 
   UpdateIter(iter, sizeof(bigResult));
   return true;
 }
 
 // Always written as a 64-bit value since the size for this type can
@@ -162,19 +232,17 @@ bool Pickle::ReadULong(void** iter, unsi
   DCHECK(iter);
   if (!*iter)
     *iter = const_cast<char*>(payload());
 
   uint64_t bigResult = 0;
   if (!IteratorHasRoomFor(*iter, sizeof(bigResult)))
     return false;
 
-  // TODO(jar) bug 1129285: Pickle should be cleaned up, and not dependent on
-  // alignment.
-  memcpy(&bigResult, *iter, sizeof(bigResult));
+  CopyFromIter(&bigResult, iter);
   DCHECK(bigResult <= ULONG_MAX);
   *result = static_cast<unsigned long>(bigResult);
 
   UpdateIter(iter, sizeof(bigResult));
   return true;
 }
 
 bool Pickle::ReadLength(void** iter, int* result) const {
@@ -189,124 +257,122 @@ bool Pickle::ReadSize(void** iter, size_
   DCHECK(iter);
   if (!*iter)
     *iter = const_cast<char*>(payload());
 
   uint64_t bigResult = 0;
   if (!IteratorHasRoomFor(*iter, sizeof(bigResult)))
     return false;
 
-  // TODO(jar) bug 1129285: Pickle should be cleaned up, and not dependent on
-  // alignment.
-  memcpy(&bigResult, *iter, sizeof(bigResult));
+  CopyFromIter(&bigResult, iter);
   DCHECK(bigResult <= std::numeric_limits<size_t>::max());
   *result = static_cast<size_t>(bigResult);
 
   UpdateIter(iter, sizeof(bigResult));
   return true;
 }
 
 bool Pickle::ReadInt32(void** iter, int32_t* result) const {
   DCHECK(iter);
   if (!*iter)
     *iter = const_cast<char*>(payload());
 
   if (!IteratorHasRoomFor(*iter, sizeof(*result)))
     return false;
 
-  memcpy(result, *iter, sizeof(*result));
+  CopyFromIter(result, iter);
 
   UpdateIter(iter, sizeof(*result));
   return true;
 }
 
 bool Pickle::ReadUInt32(void** iter, uint32_t* result) const {
   DCHECK(iter);
   if (!*iter)
     *iter = const_cast<char*>(payload());
 
   if (!IteratorHasRoomFor(*iter, sizeof(*result)))
     return false;
 
-  memcpy(result, *iter, sizeof(*result));
+  CopyFromIter(result, iter);
 
   UpdateIter(iter, sizeof(*result));
   return true;
 }
 
 bool Pickle::ReadInt64(void** iter, int64_t* result) const {
   DCHECK(iter);
   if (!*iter)
     *iter = const_cast<char*>(payload());
 
   if (!IteratorHasRoomFor(*iter, sizeof(*result)))
     return false;
 
-  memcpy(result, *iter, sizeof(*result));
+  CopyFromIter(result, iter);
 
   UpdateIter(iter, sizeof(*result));
   return true;
 }
 
 bool Pickle::ReadUInt64(void** iter, uint64_t* result) const {
   DCHECK(iter);
   if (!*iter)
     *iter = const_cast<char*>(payload());
 
   if (!IteratorHasRoomFor(*iter, sizeof(*result)))
     return false;
 
-  memcpy(result, *iter, sizeof(*result));
+  CopyFromIter(result, iter);
 
   UpdateIter(iter, sizeof(*result));
   return true;
 }
 
 bool Pickle::ReadDouble(void** iter, double* result) const {
   DCHECK(iter);
   if (!*iter)
     *iter = const_cast<char*>(payload());
 
   if (!IteratorHasRoomFor(*iter, sizeof(*result)))
     return false;
 
-  memcpy(result, *iter, sizeof(*result));
+  CopyFromIter(result, iter);
 
   UpdateIter(iter, sizeof(*result));
   return true;
 }
 
 // Always written as a 64-bit value since the size for this type can
 // differ between architectures.
 bool Pickle::ReadIntPtr(void** iter, intptr_t* result) const {
   DCHECK(iter);
   if (!*iter)
     *iter = const_cast<char*>(payload());
 
   int64_t bigResult = 0;
   if (!IteratorHasRoomFor(*iter, sizeof(bigResult)))
     return false;
 
-  memcpy(&bigResult, *iter, sizeof(bigResult));
+  CopyFromIter(&bigResult, iter);
   DCHECK(bigResult <= std::numeric_limits<intptr_t>::max() && bigResult >= std::numeric_limits<intptr_t>::min());
   *result = static_cast<intptr_t>(bigResult);
 
   UpdateIter(iter, sizeof(bigResult));
   return true;
 }
 
 bool Pickle::ReadUnsignedChar(void** iter, unsigned char* result) const {
   DCHECK(iter);
   if (!*iter)
     *iter = const_cast<char*>(payload());
 
   if (!IteratorHasRoomFor(*iter, sizeof(*result)))
     return false;
 
-  memcpy(result, *iter, sizeof(*result));
+  CopyFromIter(result, iter);
 
   UpdateIter(iter, sizeof(*result));
   return true;
 }
 
 bool Pickle::ReadString(void** iter, std::string* result) const {
   DCHECK(iter);
   if (!*iter)
@@ -406,19 +472,19 @@ bool Pickle::ReadData(void** iter, const
 
   return ReadBytes(iter, data, *length);
 }
 
 char* Pickle::BeginWrite(uint32_t length, uint32_t alignment) {
   DCHECK(alignment % 4 == 0) << "Must be at least 32-bit aligned!";
 
   // write at an alignment-aligned offset from the beginning of the header
-  uint32_t offset = AlignInt(header_->payload_size, sizeof(uint32_t));
+  uint32_t offset = AlignInt(header_->payload_size);
   uint32_t padding = (header_size_ + offset) %  alignment;
-  uint32_t new_size = offset + padding + AlignInt(length, sizeof(uint32_t));
+  uint32_t new_size = offset + padding + AlignInt(length);
   uint32_t needed_size = header_size_ + new_size;
 
   if (needed_size > capacity_ && !Resize(std::max(capacity_ * 2, needed_size)))
     return NULL;
 
   DCHECK(intptr_t(header_) % alignment == 0);
 
 #ifdef ARCH_CPU_64_BITS
@@ -436,18 +502,19 @@ char* Pickle::BeginWrite(uint32_t length
 
   header_->payload_size = new_size;
   return buffer;
 }
 
 void Pickle::EndWrite(char* dest, int length) {
   // Zero-pad to keep tools like purify from complaining about uninitialized
   // memory.
-  if (length % sizeof(uint32_t))
-    memset(dest + length, 0, sizeof(uint32_t) - (length % sizeof(uint32_t)));
+  if (length % sizeof(memberAlignmentType))
+    memset(dest + length, 0,
+	   sizeof(memberAlignmentType) - (length % sizeof(memberAlignmentType)));
 }
 
 bool Pickle::WriteBytes(const void* data, int data_len, uint32_t alignment) {
   DCHECK(capacity_ != kCapacityReadOnly) << "oops: pickle is readonly";
   DCHECK(alignment == 4 || alignment == 8);
   DCHECK(intptr_t(header_) % alignment == 0);
 
   char* dest = BeginWrite(data_len, alignment);
@@ -489,17 +556,17 @@ bool Pickle::WriteData(const char* data,
 
 char* Pickle::BeginWriteData(int length) {
   DCHECK_EQ(variable_buffer_offset_, 0U) <<
     "There can only be one variable buffer in a Pickle";
 
   if (!WriteInt(length))
     return NULL;
 
-  char *data_ptr = BeginWrite(length, sizeof(uint32_t));
+  char *data_ptr = BeginWrite(length, sizeof(memberAlignmentType));
   if (!data_ptr)
     return NULL;
 
   variable_buffer_offset_ =
       data_ptr - reinterpret_cast<char*>(header_) - sizeof(int);
 
   // EndWrite doesn't necessarily have to be called after the write operation,
   // so we call it here to pad out what the caller will eventually write.
@@ -520,33 +587,33 @@ void Pickle::TrimWriteData(int new_lengt
   }
 
   // Update the payload size and variable buffer size
   header_->payload_size -= (*cur_length - new_length);
   *cur_length = new_length;
 }
 
 bool Pickle::Resize(uint32_t new_capacity) {
-  new_capacity = AlignInt(new_capacity, kPayloadUnit);
+  new_capacity = ConstantAligner<kPayloadUnit>::align(new_capacity);
 
   void* p = realloc(header_, new_capacity);
   if (!p)
     return false;
 
   header_ = reinterpret_cast<Header*>(p);
   capacity_ = new_capacity;
   return true;
 }
 
 // static
 const char* Pickle::FindNext(uint32_t header_size,
                              const char* start,
                              const char* end) {
-  DCHECK(header_size == AlignInt(header_size, sizeof(uint32_t)));
-  DCHECK(header_size <= static_cast<uint32_t>(kPayloadUnit));
+  DCHECK(header_size == AlignInt(header_size));
+  DCHECK(header_size <= static_cast<memberAlignmentType>(kPayloadUnit));
 
   const Header* hdr = reinterpret_cast<const Header*>(start);
   const char* payload_base = start + header_size;
   const char* payload_end = payload_base + hdr->payload_size;
   if (payload_end < payload_base)
     return NULL;
 
   return (payload_end > end) ? NULL : payload_end;
--- a/ipc/chromium/src/base/pickle.h
+++ b/ipc/chromium/src/base/pickle.h
@@ -79,17 +79,17 @@ class Pickle {
   bool ReadDouble(void** iter, double* result) const;
   bool ReadIntPtr(void** iter, intptr_t* result) const;
   bool ReadUnsignedChar(void** iter, unsigned char* result) const;
   bool ReadString(void** iter, std::string* result) const;
   bool ReadWString(void** iter, std::wstring* result) const;
   bool ReadString16(void** iter, string16* result) const;
   bool ReadData(void** iter, const char** data, int* length) const;
   bool ReadBytes(void** iter, const char** data, int length,
-                 uint32_t alignment = sizeof(uint32_t)) const;
+                 uint32_t alignment = sizeof(memberAlignmentType)) const;
 
   // Safer version of ReadInt() checks for the result not being negative.
   // Use it for reading the object sizes.
   bool ReadLength(void** iter, int* result) const;
 
   // Methods for adding to the payload of the Pickle.  These values are
   // appended to the end of the Pickle's payload.  When reading values from a
   // Pickle, it is important to read them in the order in which they were added
@@ -144,17 +144,17 @@ class Pickle {
   bool WriteUnsignedChar(unsigned char value) {
     return WriteBytes(&value, sizeof(value));
   }
   bool WriteString(const std::string& value);
   bool WriteWString(const std::wstring& value);
   bool WriteString16(const string16& value);
   bool WriteData(const char* data, int length);
   bool WriteBytes(const void* data, int data_len,
-                  uint32_t alignment = sizeof(uint32_t));
+                  uint32_t alignment = sizeof(memberAlignmentType));
 
   // Same as WriteData, but allows the caller to write directly into the
   // Pickle. This saves a copy in cases where the data is not already
   // available in a buffer. The caller should take care to not write more
   // than the length it declares it will. Use ReadData to get the data.
   // Returns NULL on failure.
   //
   // The returned pointer will only be valid until the next write operation
@@ -201,16 +201,18 @@ class Pickle {
   bool IteratorHasRoomFor(const void* iter, int len) const {
     if ((len < 0) || (iter < header_) || iter > end_of_payload())
       return false;
     const char* end_of_region = reinterpret_cast<const char*>(iter) + len;
     // Watch out for overflow in pointer calculation, which wraps.
     return (iter <= end_of_region) && (end_of_region <= end_of_payload());
   }
 
+  typedef uint32_t memberAlignmentType;
+
  protected:
   uint32_t payload_size() const { return header_->payload_size; }
 
   char* payload() {
     return reinterpret_cast<char*>(header_) + header_size_;
   }
   const char* payload() const {
     return reinterpret_cast<const char*>(header_) + header_size_;
@@ -241,26 +243,35 @@ class Pickle {
   void EndWrite(char* dest, int length);
 
   // Resize the capacity, note that the input value should include the size of
   // the header: new_capacity = sizeof(Header) + desired_payload_capacity.
   // A realloc() failure will cause a Resize failure... and caller should check
   // the return result for true (i.e., successful resizing).
   bool Resize(uint32_t new_capacity);
 
-  // Aligns 'i' by rounding it up to the next multiple of 'alignment'
-  static uint32_t AlignInt(uint32_t i, int alignment) {
-    return i + (alignment - (i % alignment)) % alignment;
+  // Round 'bytes' up to the next multiple of 'alignment'.  'alignment' must be
+  // a power of 2.
+  template<uint32_t alignment> struct ConstantAligner {
+    static uint32_t align(int bytes) {
+      MOZ_STATIC_ASSERT((alignment & (alignment - 1)) == 0,
+			"alignment must be a power of two");
+      return (bytes + (alignment - 1)) & ~static_cast<uint32_t>(alignment - 1);
+    }
+  };
+
+  static uint32_t AlignInt(int bytes) {
+    return ConstantAligner<sizeof(memberAlignmentType)>::align(bytes);
   }
 
   // Moves the iterator by the given number of bytes, making sure it is aligned.
   // Pointer (iterator) is NOT aligned, but the change in the pointer
-  // is guaranteed to be a multiple of sizeof(uint32_t).
+  // is guaranteed to be a multiple of sizeof(memberAlignmentType).
   static void UpdateIter(void** iter, int bytes) {
-    *iter = static_cast<char*>(*iter) + AlignInt(bytes, sizeof(uint32_t));
+    *iter = static_cast<char*>(*iter) + AlignInt(bytes);
   }
 
   // Find the end of the pickled data that starts at range_start.  Returns NULL
   // if the entire Pickle is not found in the given data range.
   static const char* FindNext(uint32_t header_size,
                               const char* range_start,
                               const char* range_end);
 
new file mode 100644
--- /dev/null
+++ b/ipc/ipdl/test/cxx/PTestIndirectProtocolParam.ipdlh
@@ -0,0 +1,15 @@
+include protocol PTestIndirectProtocolParamSecond;
+
+namespace mozilla {
+namespace _ipdltest {
+
+struct IndirectParamStruct {
+    PTestIndirectProtocolParamSecond actor;
+};
+
+union IndirectParamUnion {
+    IndirectParamStruct;
+};
+
+}
+}
new file mode 100644
--- /dev/null
+++ b/ipc/ipdl/test/cxx/PTestIndirectProtocolParamFirst.ipdl
@@ -0,0 +1,19 @@
+include protocol PTestIndirectProtocolParamManage;
+// FIXME/bug 792908 protocol PTestIndirectProtocolParamSecond is
+// already included in PTestIndirectProtocolParam.ipdlh
+include protocol PTestIndirectProtocolParamSecond;
+include PTestIndirectProtocolParam;
+
+namespace mozilla {
+namespace _ipdltest {
+
+sync protocol PTestIndirectProtocolParamFirst {
+    manager PTestIndirectProtocolParamManage;
+parent:
+    sync Test(IndirectParamUnion actor);
+both:
+    __delete__();
+};
+
+}
+}
new file mode 100644
--- /dev/null
+++ b/ipc/ipdl/test/cxx/PTestIndirectProtocolParamManage.ipdl
@@ -0,0 +1,17 @@
+include protocol PTestIndirectProtocolParamFirst;
+include protocol PTestIndirectProtocolParamSecond;
+
+namespace mozilla {
+namespace _ipdltest {
+
+sync protocol PTestIndirectProtocolParamManage {
+    manages PTestIndirectProtocolParamFirst;
+    manages PTestIndirectProtocolParamSecond;
+both:
+    PTestIndirectProtocolParamFirst();
+    PTestIndirectProtocolParamSecond();
+    __delete__();
+};
+
+}
+}
new file mode 100644
--- /dev/null
+++ b/ipc/ipdl/test/cxx/PTestIndirectProtocolParamSecond.ipdl
@@ -0,0 +1,13 @@
+include protocol PTestIndirectProtocolParamManage;
+
+namespace mozilla {
+namespace _ipdltest {
+
+sync protocol PTestIndirectProtocolParamSecond {
+    manager PTestIndirectProtocolParamManage;
+both:
+    __delete__();
+};
+
+}
+}
--- a/ipc/ipdl/test/cxx/ipdl.mk
+++ b/ipc/ipdl/test/cxx/ipdl.mk
@@ -45,9 +45,13 @@ IPDLSRCS =					\
   PTestShutdownSubsub.ipdl			\
   PTestStackHooks.ipdl				\
   PTestSyncError.ipdl                           \
   PTestSyncHang.ipdl                            \
   PTestSyncWakeup.ipdl				\
   PTestSysVShmem.ipdl				\
   PTestBadActor.ipdl                            \
   PTestBadActorSub.ipdl                         \
+  PTestIndirectProtocolParam.ipdlh	        \
+  PTestIndirectProtocolParamManage.ipdl         \
+  PTestIndirectProtocolParamFirst.ipdl	        \
+  PTestIndirectProtocolParamSecond.ipdl	        \
   $(NULL)
--- a/js/ipc/ObjectWrapperParent.cpp
+++ b/js/ipc/ObjectWrapperParent.cpp
@@ -383,17 +383,17 @@ jsval_to_nsString(JSContext* cx, jsid fr
         *to = chars;
         return true;
     }
     return false;
 }
 
 /*static*/ JSBool
 ObjectWrapperParent::CPOW_AddProperty(JSContext *cx, JSHandleObject obj, JSHandleId id,
-                                      JSMutableHandleValue vp)
+                                      MutableHandleValue vp)
 {
     CPOW_LOG(("Calling CPOW_AddProperty (%s)...",
               JSVAL_TO_CSTR(cx, id)));
 
     ObjectWrapperParent* self = Unwrap(cx, obj);
     if (!self)
         return with_error(cx, JS_FALSE, "Unwrapping failed in CPOW_AddProperty");
 
@@ -410,17 +410,17 @@ ObjectWrapperParent::CPOW_AddProperty(JS
     return (self->Manager()->RequestRunToCompletion() &&
             self->CallAddProperty(in_id,
                                   aco.StatusPtr()) &&
             aco.Ok());
 }
 
 /*static*/ JSBool
 ObjectWrapperParent::CPOW_GetProperty(JSContext *cx, JSHandleObject obj, JSHandleId id,
-                                      JSMutableHandleValue vp)
+                                      MutableHandleValue vp)
 {
     CPOW_LOG(("Calling CPOW_GetProperty (%s)...",
               JSVAL_TO_CSTR(cx, id)));
 
     ObjectWrapperParent* self = Unwrap(cx, obj);
     if (!self)
         return with_error(cx, JS_FALSE, "Unwrapping failed in CPOW_GetProperty");
 
@@ -437,17 +437,17 @@ ObjectWrapperParent::CPOW_GetProperty(JS
             self->CallGetProperty(in_id,
                                   aco.StatusPtr(), &out_v) &&
             aco.Ok() &&
             self->jsval_from_JSVariant(cx, out_v, vp.address()));
 }
 
 /*static*/ JSBool
 ObjectWrapperParent::CPOW_SetProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, 
-                                      JSBool strict, JSMutableHandleValue vp)
+                                      JSBool strict, MutableHandleValue vp)
 {
     CPOW_LOG(("Calling CPOW_SetProperty (%s)...",
               JSVAL_TO_CSTR(cx, id)));
 
     ObjectWrapperParent* self = Unwrap(cx, obj);
     if (!self)
         return with_error(cx, JS_FALSE, "Unwrapping failed in CPOW_SetProperty");
 
@@ -609,17 +609,17 @@ ObjectWrapperParent::CPOW_NewResolve(JSC
         JS_DefinePropertyById(cx, obj2, id, JSVAL_VOID, NULL, NULL,
                               JSPROP_ENUMERATE);
     }
     return JS_TRUE;
 }
 
 /*static*/ JSBool
 ObjectWrapperParent::CPOW_Convert(JSContext *cx, JSHandleObject obj, JSType type,
-                                  JSMutableHandleValue vp)
+                                  MutableHandleValue vp)
 {
     CPOW_LOG(("Calling CPOW_Convert (to %s)...",
               JS_GetTypeName(cx, type)));
 
     ObjectWrapperParent* self = Unwrap(cx, obj);
     if (!self)
         return with_error(cx, JS_FALSE, "Unwrapping failed in CPOW_Convert");
 
@@ -703,17 +703,17 @@ ObjectWrapperParent::CPOW_Construct(JSCo
 
     return (constructor->Manager()->RequestRunToCompletion() &&
             constructor->CallConstruct(in_argv, aco.StatusPtr(), &out_powp) &&
             aco.Ok() &&
             jsval_from_PObjectWrapperParent(cx, out_powp, vp));
 }
 
 /*static*/ JSBool
-ObjectWrapperParent::CPOW_HasInstance(JSContext *cx, JSHandleObject obj, JSMutableHandleValue v,
+ObjectWrapperParent::CPOW_HasInstance(JSContext *cx, JSHandleObject obj, MutableHandleValue v,
                                       JSBool *bp)
 {
     CPOW_LOG(("Calling CPOW_HasInstance..."));
 
     *bp = JS_FALSE;
 
     ObjectWrapperParent* self = Unwrap(cx, obj);
     if (!self)
--- a/js/ipc/ObjectWrapperParent.h
+++ b/js/ipc/ObjectWrapperParent.h
@@ -54,52 +54,52 @@ protected:
 
     ContextWrapperParent* Manager();
 
 private:
 
     mutable JSObject* mObj;
 
     static JSBool
-    CPOW_AddProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, JSMutableHandleValue vp);
+    CPOW_AddProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, JS::MutableHandleValue vp);
 
     static JSBool
     CPOW_DelProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool *succeeded);
 
     static JSBool
-    CPOW_GetProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, JSMutableHandleValue vp);
+    CPOW_GetProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, JS::MutableHandleValue vp);
     
     static JSBool
-    CPOW_SetProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, JSMutableHandleValue vp);
+    CPOW_SetProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, JS::MutableHandleValue vp);
 
     JSBool NewEnumerateInit(JSContext* cx, jsval* statep, jsid* idp);
     JSBool NewEnumerateNext(JSContext* cx, jsval* statep, jsid* idp);
     JSBool NewEnumerateDestroy(JSContext* cx, jsval state);
     static JSBool
     CPOW_NewEnumerate(JSContext *cx, JSHandleObject obj, JSIterateOp enum_op,
                       jsval *statep, jsid *idp);
 
     static JSBool
     CPOW_NewResolve(JSContext *cx, JSHandleObject obj, JSHandleId id, unsigned flags,
                     JS::MutableHandleObject objp);
 
     static JSBool
-    CPOW_Convert(JSContext *cx, JSHandleObject obj, JSType type, JSMutableHandleValue vp);
+    CPOW_Convert(JSContext *cx, JSHandleObject obj, JSType type, JS::MutableHandleValue vp);
 
     static void
     CPOW_Finalize(js::FreeOp* fop, JSObject* obj);
 
     static JSBool
     CPOW_Call(JSContext* cx, unsigned argc, jsval* vp);
 
     static JSBool
     CPOW_Construct(JSContext *cx, unsigned argc, jsval *vp);
 
     static JSBool
-    CPOW_HasInstance(JSContext *cx, JSHandleObject obj, JSMutableHandleValue vp, JSBool *bp);
+    CPOW_HasInstance(JSContext *cx, JSHandleObject obj, JS::MutableHandleValue vp, JSBool *bp);
 
     static bool jsval_to_JSVariant(JSContext* cx, jsval from, JSVariant* to);
     static bool jsval_from_JSVariant(JSContext* cx, const JSVariant& from,
                                      jsval* to);
     static bool boolean_from_JSVariant(JSContext* cx, const JSVariant& from,
                                        JSBool* to);
     static bool
     JSObject_to_PObjectWrapperParent(JSContext* cx, JSObject* from, PObjectWrapperParent** to);
--- a/js/public/RootingAPI.h
+++ b/js/public/RootingAPI.h
@@ -97,17 +97,17 @@
  */
 
 namespace js {
 
 class Module;
 class ScriptSourceObject;
 
 template <typename T>
-struct RootMethods {};
+struct GCMethods {};
 
 template <typename T>
 class RootedBase {};
 
 template <typename T>
 class HandleBase {};
 
 template <typename T>
@@ -176,23 +176,23 @@ struct JS_PUBLIC_API(NullPtr)
  */
 template <typename T>
 class Heap : public js::HeapBase<T>
 {
   public:
     Heap() {
         MOZ_STATIC_ASSERT(sizeof(T) == sizeof(Heap<T>),
                           "Heap<T> must be binary compatible with T.");
-        init(js::RootMethods<T>::initial());
+        init(js::GCMethods<T>::initial());
     }
     explicit Heap(T p) { init(p); }
     explicit Heap(const Heap<T> &p) { init(p.ptr); }
 
     ~Heap() {
-        if (js::RootMethods<T>::needsPostBarrier(ptr))
+        if (js::GCMethods<T>::needsPostBarrier(ptr))
             relocate();
     }
 
     bool operator!=(const T &other) const { return ptr != other; }
     bool operator==(const T &other) const { return ptr == other; }
 
     operator T() const { return ptr; }
     T operator->() const { return ptr; }
@@ -202,46 +202,46 @@ class Heap : public js::HeapBase<T>
     T *unsafeGet() { return &ptr; }
 
     Heap<T> &operator=(T p) {
         set(p);
         return *this;
     }
 
     void set(T newPtr) {
-        JS_ASSERT(!js::RootMethods<T>::poisoned(newPtr));
-        if (js::RootMethods<T>::needsPostBarrier(newPtr)) {
+        JS_ASSERT(!js::GCMethods<T>::poisoned(newPtr));
+        if (js::GCMethods<T>::needsPostBarrier(newPtr)) {
             ptr = newPtr;
             post();
-        } else if (js::RootMethods<T>::needsPostBarrier(ptr)) {
+        } else if (js::GCMethods<T>::needsPostBarrier(ptr)) {
             relocate();  /* Called before overwriting ptr. */
             ptr = newPtr;
         } else {
             ptr = newPtr;
         }
     }
 
   private:
     void init(T newPtr) {
-        JS_ASSERT(!js::RootMethods<T>::poisoned(newPtr));
+        JS_ASSERT(!js::GCMethods<T>::poisoned(newPtr));
         ptr = newPtr;
-        if (js::RootMethods<T>::needsPostBarrier(ptr))
+        if (js::GCMethods<T>::needsPostBarrier(ptr))
             post();
     }
 
     void post() {
 #ifdef JSGC_GENERATIONAL
-        JS_ASSERT(js::RootMethods<T>::needsPostBarrier(ptr));
-        js::RootMethods<T>::postBarrier(&ptr);
+        JS_ASSERT(js::GCMethods<T>::needsPostBarrier(ptr));
+        js::GCMethods<T>::postBarrier(&ptr);
 #endif
     }
 
     void relocate() {
 #ifdef JSGC_GENERATIONAL
-        js::RootMethods<T>::relocate(&ptr);
+        js::GCMethods<T>::relocate(&ptr);
 #endif
     }
 
     T ptr;
 };
 
 /*
  * Reference to a T that has been rooted elsewhere. This is most useful
@@ -358,17 +358,17 @@ typedef Handle<Value>                   
  */
 template <typename T>
 class MOZ_STACK_CLASS MutableHandle : public js::MutableHandleBase<T>
 {
   public:
     inline MutableHandle(Rooted<T> *root);
 
     void set(T v) {
-        JS_ASSERT(!js::RootMethods<T>::poisoned(v));
+        JS_ASSERT(!js::GCMethods<T>::poisoned(v));
         *ptr = v;
     }
 
     /*
      * This may be called only if the location of the T is guaranteed
      * to be marked (for some reason other than being a Rooted),
      * e.g., if it is guaranteed to be reachable from an implicit root.
      *
@@ -476,17 +476,17 @@ class InternalHandle<T*>
  */
 template <typename T>
 struct RootKind<T *>
 {
     static ThingRootKind rootKind() { return T::rootKind(); }
 };
 
 template <typename T>
-struct RootMethods<T *>
+struct GCMethods<T *>
 {
     static T *initial() { return NULL; }
     static ThingRootKind kind() { return RootKind<T *>::rootKind(); }
     static bool poisoned(T *v) { return JS::IsPoisonedPtr(v); }
     static bool needsPostBarrier(T *v) { return v; }
 #ifdef JSGC_GENERATIONAL
     static void postBarrier(T **vp) {
         JS::HeapCellPostBarrier(reinterpret_cast<js::gc::Cell **>(vp));
@@ -523,49 +523,49 @@ class MOZ_STACK_CLASS Rooted : public js
 #if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
         commonInit(pt->thingGCRooters);
 #endif
     }
 
   public:
     Rooted(JSContext *cx
            MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
-      : ptr(js::RootMethods<T>::initial())
+      : ptr(js::GCMethods<T>::initial())
     {
         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
         init(cx);
     }
 
     Rooted(JSContext *cx, T initial
            MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
       : ptr(initial)
     {
         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
         init(cx);
     }
 
     Rooted(js::PerThreadData *pt
            MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
-      : ptr(js::RootMethods<T>::initial())
+      : ptr(js::GCMethods<T>::initial())
     {
         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
         init(js::PerThreadDataFriendFields::get(pt));
     }
 
     Rooted(js::PerThreadData *pt, T initial
            MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
       : ptr(initial)
     {
         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
         init(js::PerThreadDataFriendFields::get(pt));
     }
 
     Rooted(JSRuntime *rt
            MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
-      : ptr(js::RootMethods<T>::initial())
+      : ptr(js::GCMethods<T>::initial())
     {
         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
         init(js::PerThreadDataFriendFields::getMainThread(rt));
     }
 
     Rooted(JSRuntime *rt, T initial
            MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
       : ptr(initial)
@@ -592,43 +592,43 @@ class MOZ_STACK_CLASS Rooted : public js
     operator const T&() const { return ptr; }
     T operator->() const { return ptr; }
     T *address() { return &ptr; }
     const T *address() const { return &ptr; }
     T &get() { return ptr; }
     const T &get() const { return ptr; }
 
     T &operator=(T value) {
-        JS_ASSERT(!js::RootMethods<T>::poisoned(value));
+        JS_ASSERT(!js::GCMethods<T>::poisoned(value));
         ptr = value;
         return ptr;
     }
 
     T &operator=(const Rooted &value) {
         ptr = value;
         return ptr;
     }
 
     void set(T value) {
-        JS_ASSERT(!js::RootMethods<T>::poisoned(value));
+        JS_ASSERT(!js::GCMethods<T>::poisoned(value));
         ptr = value;
     }
 
     bool operator!=(const T &other) const { return ptr != other; }
     bool operator==(const T &other) const { return ptr == other; }
 
   private:
     void commonInit(Rooted<void*> **thingGCRooters) {
 #if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
-        js::ThingRootKind kind = js::RootMethods<T>::kind();
+        js::ThingRootKind kind = js::GCMethods<T>::kind();
         this->stack = &thingGCRooters[kind];
         this->prev = *stack;
         *stack = reinterpret_cast<Rooted<void*>*>(this);
 
-        JS_ASSERT(!js::RootMethods<T>::poisoned(ptr));
+        JS_ASSERT(!js::GCMethods<T>::poisoned(ptr));
 #endif
     }
 
 #if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
     Rooted<void*> **stack, *prev;
 #endif
 
 #if defined(DEBUG) && defined(JS_GC_ZEAL) && defined(JSGC_ROOT_ANALYSIS) && !defined(JS_THREADSAFE)
@@ -743,17 +743,17 @@ class SkipRoot
 
 /* Interface substitute for Rooted<T> which does not root the variable's memory. */
 template <typename T>
 class FakeRooted : public RootedBase<T>
 {
   public:
     FakeRooted(JSContext *cx
                 MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
-      : ptr(RootMethods<T>::initial())
+      : ptr(GCMethods<T>::initial())
     {
         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
     }
 
     FakeRooted(JSContext *cx, T initial
                 MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
       : ptr(initial)
     {
@@ -763,17 +763,17 @@ class FakeRooted : public RootedBase<T>
     operator T() const { return ptr; }
     T operator->() const { return ptr; }
     T *address() { return &ptr; }
     const T *address() const { return &ptr; }
     T &get() { return ptr; }
     const T &get() const { return ptr; }
 
     T &operator=(T value) {
-        JS_ASSERT(!RootMethods<T>::poisoned(value));
+        JS_ASSERT(!GCMethods<T>::poisoned(value));
         ptr = value;
         return ptr;
     }
 
     bool operator!=(const T &other) const { return ptr != other; }
     bool operator==(const T &other) const { return ptr == other; }
 
   private:
@@ -793,17 +793,17 @@ class FakeMutableHandle : public js::Mut
         ptr = t;
     }
 
     FakeMutableHandle(FakeRooted<T> *root) {
         ptr = root->address();
     }
 
     void set(T v) {
-        JS_ASSERT(!js::RootMethods<T>::poisoned(v));
+        JS_ASSERT(!js::GCMethods<T>::poisoned(v));
         *ptr = v;
     }
 
     T *address() const { return ptr; }
     T get() const { return *ptr; }
 
     operator T() const { return get(); }
     T operator->() const { return get(); }
--- a/js/public/Value.h
+++ b/js/public/Value.h
@@ -1396,24 +1396,24 @@ SameType(const Value &lhs, const Value &
 namespace JS {
 JS_PUBLIC_API(void) HeapValuePostBarrier(Value *valuep);
 JS_PUBLIC_API(void) HeapValueRelocate(Value *valuep);
 }
 #endif
 
 namespace js {
 
-template <> struct RootMethods<const JS::Value>
+template <> struct GCMethods<const JS::Value>
 {
     static JS::Value initial() { return JS::UndefinedValue(); }
     static ThingRootKind kind() { return THING_ROOT_VALUE; }
     static bool poisoned(const JS::Value &v) { return JS::IsPoisonedValue(v); }
 };
 
-template <> struct RootMethods<JS::Value>
+template <> struct GCMethods<JS::Value>
 {
     static JS::Value initial() { return JS::UndefinedValue(); }
     static ThingRootKind kind() { return THING_ROOT_VALUE; }
     static bool poisoned(const JS::Value &v) { return JS::IsPoisonedValue(v); }
     static bool needsPostBarrier(const JS::Value &v) { return v.isMarkable(); }
 #ifdef JSGC_GENERATIONAL
     static void postBarrier(JS::Value *v) { JS::HeapValuePostBarrier(v); }
     static void relocate(JS::Value *v) { JS::HeapValueRelocate(v); }
--- a/js/src/config/rules.mk
+++ b/js/src/config/rules.mk
@@ -12,16 +12,17 @@ endif
 
 # Integrate with mozbuild-generated make files. We first verify that no
 # variables provided by the automatically generated .mk files are
 # present. If they are, this is a violation of the separation of
 # responsibility between Makefile.in and mozbuild files.
 _MOZBUILD_EXTERNAL_VARIABLES := \
   DIRS \
   HOST_CSRCS \
+  HOST_LIBRARY_NAME \
   MODULE \
   PARALLEL_DIRS \
   TEST_DIRS \
   TIERS \
   TOOL_DIRS \
   XPIDL_MODULE \
   $(NULL)
 
--- a/js/src/ctypes/CTypes.cpp
+++ b/js/src/ctypes/CTypes.cpp
@@ -169,17 +169,17 @@ namespace CType {
   static JSBool NameGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval,
     MutableHandleValue vp);
   static JSBool SizeGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval,
     MutableHandleValue vp);
   static JSBool PtrGetter(JSContext* cx, JSHandleObject obj, JSHandleId idval, MutableHandleValue vp);
   static JSBool CreateArray(JSContext* cx, unsigned argc, jsval* vp);
   static JSBool ToString(JSContext* cx, unsigned argc, jsval* vp);
   static JSBool ToSource(JSContext* cx, unsigned argc, jsval* vp);
-  static JSBool HasInstance(JSContext* cx, JSHandleObject obj, JSMutableHandleValue v, JSBool* bp);
+  static JSBool HasInstance(JSContext* cx, JSHandleObject obj, MutableHandleValue v, JSBool* bp);
 
 
   /*
    * Get the global "ctypes" object.
    *
    * |obj| must be a CType object.
    *
    * This function never returns NULL.
@@ -3742,17 +3742,17 @@ CType::ToSource(JSContext* cx, unsigned 
   if (!result)
     return JS_FALSE;
 
   args.rval().setString(result);
   return JS_TRUE;
 }
 
 JSBool
-CType::HasInstance(JSContext* cx, JSHandleObject obj, JSMutableHandleValue v, JSBool* bp)
+CType::HasInstance(JSContext* cx, JSHandleObject obj, MutableHandleValue v, JSBool* bp)
 {
   JS_ASSERT(CType::IsCType(obj));
 
   jsval slot = JS_GetReservedSlot(obj, SLOT_PROTO);
   JS::Rooted<JSObject*> prototype(cx, &slot.toObject());
   JS_ASSERT(prototype);
   JS_ASSERT(CData::IsCDataProto(prototype));
 
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -6498,20 +6498,19 @@ template <>
 ParseNode *
 Parser<FullParseHandler>::newRegExp(const jschar *buf, size_t length, RegExpFlag flags)
 {
     ParseNode *pn = NullaryNode::create(PNK_REGEXP, &handler);
     if (!pn)
         return NULL;
 
     const StableCharPtr chars(buf, length);
-    RegExpStatics *res = context->regExpStatics();
 
     Rooted<RegExpObject*> reobj(context);
-    if (context->hasfp())
+    if (RegExpStatics *res = context->regExpStatics())
         reobj = RegExpObject::create(context, res, chars.get(), length, flags, &tokenStream);
     else
         reobj = RegExpObject::createNoStatics(context, chars.get(), length, flags, &tokenStream);
 
     if (!reobj)
         return NULL;
 
     pn->pn_objbox = newObjectBox(reobj);
@@ -6523,20 +6522,19 @@ Parser<FullParseHandler>::newRegExp(cons
 }
 
 template <>
 SyntaxParseHandler::Node
 Parser<SyntaxParseHandler>::newRegExp(const jschar *buf, size_t length, RegExpFlag flags)
 {
     // Create the regexp even when doing a syntax parse, to check the regexp's syntax.
     const StableCharPtr chars(buf, length);
-    RegExpStatics *res = context->regExpStatics();
 
     RegExpObject *reobj;
-    if (context->hasfp())
+    if (RegExpStatics *res = context->regExpStatics())
         reobj = RegExpObject::create(context, res, chars.get(), length, flags, &tokenStream);
     else
         reobj = RegExpObject::createNoStatics(context, chars.get(), length, flags, &tokenStream);
 
     return reobj ? SyntaxParseHandler::NodeGeneric : SyntaxParseHandler::NodeFailure;
 }
 
 template <typename ParseHandler>
--- a/js/src/ion/BaselineBailouts.cpp
+++ b/js/src/ion/BaselineBailouts.cpp
@@ -1210,17 +1210,17 @@ ion::FinishBailoutToBaseline(BaselineBai
     if (topFrame->scopeChain() && !EnsureHasScopeObjects(cx, topFrame))
         return false;
 
     // Create arguments objects for bailed out frames, to maintain the invariant
     // that script->needsArgsObj() implies frame->hasArgsObj().
     RootedScript innerScript(cx, NULL);
     RootedScript outerScript(cx, NULL);
 
-    JS_ASSERT(cx->mainThread().currentlyRunningInJit());
+    JS_ASSERT(cx->currentlyRunningInJit());
     IonFrameIterator iter(cx->mainThread().ionTop);
 
     uint32_t frameno = 0;
     while (frameno < numFrames) {
         JS_ASSERT(!iter.isOptimizedJS());
 
         if (iter.isBaselineJS()) {
             BaselineFrame *frame = iter.baselineFrame();
--- a/js/src/ion/BaselineIC.cpp
+++ b/js/src/ion/BaselineIC.cpp
@@ -671,17 +671,17 @@ ICStubCompiler::emitPostWriteBarrierSlot
 #endif // JSGC_GENERATIONAL
 
 //
 // UseCount_Fallback
 //
 static bool
 IsTopFrameConstructing(JSContext *cx)
 {
-    JS_ASSERT(cx->mainThread().currentlyRunningInJit());
+    JS_ASSERT(cx->currentlyRunningInJit());
     JitActivationIterator activations(cx->runtime());
     IonFrameIterator iter(activations);
     JS_ASSERT(iter.type() == IonFrame_Exit);
 
     ++iter;
     JS_ASSERT(iter.type() == IonFrame_BaselineStub);
 
     ++iter;
--- a/js/src/ion/BaselineJIT.cpp
+++ b/js/src/ion/BaselineJIT.cpp
@@ -122,28 +122,27 @@ EnterBaseline(JSContext *cx, StackFrame 
         fp->setRunningInJit();
 
         // Pass the scope chain for global and eval frames.
         JSObject *scopeChain = NULL;
         if (!fp->isNonEvalFunctionFrame())
             scopeChain = fp->scopeChain();
 
         // For OSR, pass the number of locals + stack values.
-        uint32_t numStackValues = osr ? fp->script()->nfixed + cx->regs().stackDepth() : 0;
+        uint32_t numStackValues = osr ? fp->script()->nfixed + cx->stack.regs().stackDepth() : 0;
         JS_ASSERT_IF(osr, !IsJSDEnabled(cx));
 
         AutoFlushInhibitor afi(cx->compartment()->ionCompartment());
         // Single transition point from Interpreter to Baseline.
         enter(jitcode, maxArgc, maxArgv, osr ? fp : NULL, calleeToken, scopeChain, numStackValues,
               result.address());
 
         fp->clearRunningInJit();
     }
 
-    JS_ASSERT(fp == cx->fp());
     JS_ASSERT(!cx->runtime()->hasIonReturnOverride());
 
     // The trampoline wrote the return value but did not set the HAS_RVAL flag.
     fp->setReturnValue(result);
 
     // Ion callers wrap primitive constructor return.
     if (!result.isMagic() && fp->isConstructing() && fp->returnValue().isPrimitive())
         fp->setReturnValue(ObjectValue(fp->constructorThis()));
@@ -242,17 +241,17 @@ ion::CanEnterBaselineJIT(JSContext *cx, 
 
     if (script->hasBaselineScript())
         return Method_Compiled;
 
     // Check script use count. However, always eagerly compile scripts if JSD
     // is enabled, so that we don't have to OSR and don't have to update the
     // frame pointer stored in JSD's frames list.
     if (IsJSDEnabled(cx)) {
-        if (JSOp(*cx->regs().pc) == JSOP_LOOPENTRY) // No OSR.
+        if (JSOp(*cx->stack.regs().pc) == JSOP_LOOPENTRY) // No OSR.
             return Method_Skipped;
     } else if (script->incUseCount() <= js_IonOptions.baselineUsesBeforeCompile) {
         return Method_Skipped;
     }
 
     if (script->isCallsiteClone) {
         // Ensure the original function is compiled too, so that bailouts from
         // Ion code have a BaselineScript to resume into.
--- a/js/src/ion/Ion.cpp
+++ b/js/src/ion/Ion.cpp
@@ -1851,17 +1851,16 @@ EnterIon(JSContext *cx, StackFrame *fp, 
 
         // Single transition point from Interpreter to Ion.
         enter(jitcode, maxArgc, maxArgv, fp, calleeToken, /* scopeChain = */ NULL, 0,
               result.address());
 
         fp->clearRunningInJit();
     }
 
-    JS_ASSERT(fp == cx->fp());
     JS_ASSERT(!cx->runtime()->hasIonReturnOverride());
 
     // The trampoline wrote the return value but did not set the HAS_RVAL flag.
     fp->setReturnValue(result);
 
     // Ion callers wrap primitive constructor return.
     if (!result.isMagic() && fp->isConstructing() && fp->returnValue().isPrimitive())
         fp->setReturnValue(ObjectValue(fp->constructorThis()));
--- a/js/src/ion/IonCaches.cpp
+++ b/js/src/ion/IonCaches.cpp
@@ -931,17 +931,17 @@ GenerateCallGetter(JSContext *cx, IonScr
             Address(StackPointer, IonOOLNativeGetterExitFrameLayout::offsetOfResult()),
             JSReturnOperand);
     } else {
         Register argObjReg       = argUintNReg;
         Register argIdReg        = regSet.takeGeneral();
 
         PropertyOp target = shape->getterOp();
         JS_ASSERT(target);
-        // JSPropertyOp: JSBool fn(JSContext *cx, JSHandleObject obj, JSHandleId id, JSMutableHandleValue vp)
+        // JSPropertyOp: JSBool fn(JSContext *cx, JSHandleObject obj, JSHandleId id, MutableHandleValue vp)
 
         // Push args on stack first so we can take pointers to make handles.
         masm.Push(UndefinedValue());
         masm.movePtr(StackPointer, argVpReg);
 
         // push canonical jsid from shape instead of propertyname.
         RootedId propId(cx);
         if (!shape->getUserId(cx, &propId))
@@ -1841,17 +1841,17 @@ SetPropertyIC::attachSetterCall(JSContex
 
     Label success, exception;
 
     attacher.pushStubCodePointer(masm);
 
     StrictPropertyOp target = shape->setterOp();
     JS_ASSERT(target);
     // JSStrictPropertyOp: JSBool fn(JSContext *cx, JSHandleObject obj,
-    //                               JSHandleId id, JSBool strict, JSMutableHandleValue vp);
+    //                               JSHandleId id, JSBool strict, MutableHandleValue vp);
 
     // Push args on stack first so we can take pointers to make handles.
     if (value().constant())
         masm.Push(value().value());
     else
         masm.Push(value().reg());
     masm.movePtr(StackPointer, argVpReg);
 
--- a/js/src/ion/arm/IonFrames-arm.h
+++ b/js/src/ion/arm/IonFrames-arm.h
@@ -345,17 +345,17 @@ class IonOOLPropertyOpExitFrameLayout
     IonExitFrameLayout exit_;
 
     // Object for JSHandleObject
     JSObject *obj_;
 
     // id for JSHandleId
     jsid id_;
 
-    // space for JSMutableHandleValue result
+    // space for MutableHandleValue result
     // use two uint32_t so compiler doesn't align.
     uint32_t vp0_;
     uint32_t vp1_;
 
     // pointer to root the stub's IonCode
     IonCode *stubCode_;
 
   public:
@@ -393,17 +393,17 @@ class IonOOLProxyGetExitFrameLayout
     JSObject *proxy_;
 
     // Object for JSHandleObject
     JSObject *receiver_;
 
     // id for JSHandleId
     jsid id_;
 
-    // space for JSMutableHandleValue result
+    // space for MutableHandleValue result
     // use two uint32_t so compiler doesn't align.
     uint32_t vp0_;
     uint32_t vp1_;
 
     // pointer to root the stub's IonCode
     IonCode *stubCode_;
 
   public:
--- a/js/src/ion/shared/IonFrames-x86-shared.h
+++ b/js/src/ion/shared/IonFrames-x86-shared.h
@@ -309,17 +309,17 @@ class IonOOLPropertyOpExitFrameLayout
     IonExitFrameLayout exit_;
 
     // Object for JSHandleObject
     JSObject *obj_;
 
     // id for JSHandleId
     jsid id_;
 
-    // space for JSMutableHandleValue result
+    // space for MutableHandleValue result
     // use two uint32_t so compiler doesn't align.
     uint32_t vp0_;
     uint32_t vp1_;
 
     // pointer to root the stub's IonCode
     IonCode *stubCode_;
 
   public:
@@ -357,17 +357,17 @@ class IonOOLProxyGetExitFrameLayout
     JSObject *proxy_;
 
     // Object for JSHandleObject
     JSObject *receiver_;
 
     // id for JSHandleId
     jsid id_;
 
-    // space for JSMutableHandleValue result
+    // space for MutableHandleValue result
     // use two uint32_t so compiler doesn't align.
     uint32_t vp0_;
     uint32_t vp1_;
 
     // pointer to root the stub's IonCode
     IonCode *stubCode_;
 
   public:
--- a/js/src/jsanalyze.cpp
+++ b/js/src/jsanalyze.cpp
@@ -409,22 +409,22 @@ ScriptAnalysis::analyzeBytecode(JSContex
           case JSOP_GETELEM:
           case JSOP_CALLELEM:
             numPropertyReads_++;
             break;
 
           case JSOP_THROW:
           case JSOP_EXCEPTION:
           case JSOP_DEBUGGER:
-          case JSOP_FUNCALL:
             isIonInlineable = false;
             break;
 
           /* Additional opcodes which can be both compiled both normally and inline. */
           case JSOP_ARGUMENTS:
+          case JSOP_FUNCALL:
           case JSOP_FUNAPPLY:
           case JSOP_CALLEE:
           case JSOP_NOP:
           case JSOP_UNDEFINED:
           case JSOP_GOTO:
           case JSOP_DEFAULT:
           case JSOP_IFEQ:
           case JSOP_IFNE:
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -3204,23 +3204,23 @@ JS_DefaultValue(JSContext *cx, JSObject 
     if (!JSObject::defaultValue(cx, obj, hint, &value))
         return false;
 
     *vp = value;
     return true;
 }
 
 JS_PUBLIC_API(JSBool)
-JS_PropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, JSMutableHandleValue vp)
+JS_PropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, MutableHandleValue vp)
 {
     return JS_TRUE;
 }
 
 JS_PUBLIC_API(JSBool)
-JS_StrictPropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, JSMutableHandleValue vp)
+JS_StrictPropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, MutableHandleValue vp)
 {
     return JS_TRUE;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_DeletePropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool *succeeded)
 {
     *succeeded = true;
@@ -3235,17 +3235,17 @@ JS_EnumerateStub(JSContext *cx, JSHandle
 
 JS_PUBLIC_API(JSBool)
 JS_ResolveStub(JSContext *cx, JSHandleObject obj, JSHandleId id)
 {
     return JS_TRUE;
 }
 
 JS_PUBLIC_API(JSBool)
-JS_ConvertStub(JSContext *cx, JSHandleObject obj, JSType type, JSMutableHandleValue vp)
+JS_ConvertStub(JSContext *cx, JSHandleObject obj, JSType type, MutableHandleValue vp)
 {
     JS_ASSERT(type != JSTYPE_OBJECT && type != JSTYPE_FUNCTION);
     JS_ASSERT(obj);
     return DefaultValue(cx, obj, type, vp);
 }
 
 JS_PUBLIC_API(JSObject *)
 JS_InitClass(JSContext *cx, JSObject *objArg, JSObject *parent_protoArg,
@@ -5960,17 +5960,17 @@ JS_PUBLIC_API(void)
 JS_TriggerOperationCallback(JSRuntime *rt)
 {
     rt->triggerOperationCallback();
 }
 
 JS_PUBLIC_API(JSBool)
 JS_IsRunning(JSContext *cx)
 {
-    return cx->hasfp();
+    return cx->currentlyRunning();
 }
 
 JS_PUBLIC_API(JSBool)
 JS_SaveFrameChain(JSContext *cx)
 {
     AssertHeapIsIdleOrIterating(cx);
     CHECK_REQUEST(cx);
     return cx->saveFrameChain();
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -713,39 +713,35 @@ CallNonGenericMethod(JSContext *cx, IsAc
 
 /************************************************************************/
 
 typedef JS::Handle<JSObject*> JSHandleObject;
 typedef JS::Handle<JSString*> JSHandleString;
 typedef JS::Handle<JS::Value> JSHandleValue;
 typedef JS::Handle<jsid> JSHandleId;
 
-typedef JS::MutableHandle<JSFunction*> JSMutableHandleFunction;
-typedef JS::MutableHandle<JSString*>   JSMutableHandleString;
-typedef JS::MutableHandle<JS::Value>   JSMutableHandleValue;
-
 /* JSClass operation signatures. */
 
 /*
  * Add or get a property named by id in obj.  Note the jsid id type -- id may
  * be a string (Unicode property identifier) or an int (element index).  The
  * *vp out parameter, on success, is the new property value after the action.
  */
 typedef JSBool
-(* JSPropertyOp)(JSContext *cx, JSHandleObject obj, JSHandleId id, JSMutableHandleValue vp);
+(* JSPropertyOp)(JSContext *cx, JSHandleObject obj, JSHandleId id, JS::MutableHandle<JS::Value> vp);
 
 /*
  * Set a property named by id in obj, treating the assignment as strict
  * mode code if strict is true. Note the jsid id type -- id may be a string
  * (Unicode property identifier) or an int (element index). The *vp out
  * parameter, on success, is the new property value after the
  * set.
  */
 typedef JSBool
-(* JSStrictPropertyOp)(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, JSMutableHandleValue vp);
+(* JSStrictPropertyOp)(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, JS::MutableHandle<JS::Value> vp);
 
 /*
  * Delete a property named by id in obj.
  *
  * If an error occurred, return false as per normal JSAPI error practice.
  *
  * If no error occurred, but the deletion attempt wasn't allowed (perhaps
  * because the property was non-configurable), set *succeeded to false and
@@ -789,17 +785,17 @@ typedef JSBool
  *    call to this function when enum_op was JSENUMERATE_INIT or
  *    JSENUMERATE_INIT_ALL.
  *
  * The return value is used to indicate success, with a value of JS_FALSE
  * indicating failure.
  */
 typedef JSBool
 (* JSNewEnumerateOp)(JSContext *cx, JSHandleObject obj, JSIterateOp enum_op,
-                     JSMutableHandleValue statep, JS::MutableHandleId idp);
+                     JS::MutableHandle<JS::Value> statep, JS::MutableHandleId idp);
 
 /*
  * The old-style JSClass.enumerate op should define all lazy properties not
  * yet reflected in obj.
  */
 typedef JSBool
 (* JSEnumerateOp)(JSContext *cx, JSHandleObject obj);
 
@@ -834,17 +830,17 @@ typedef JSBool
 (* JSNewResolveOp)(JSContext *cx, JSHandleObject obj, JSHandleId id, unsigned flags,
                    JS::MutableHandleObject objp);
 
 /*
  * Convert obj to the given type, returning true with the resulting value in
  * *vp on success, and returning false on error or exception.
  */
 typedef JSBool
-(* JSConvertOp)(JSContext *cx, JSHandleObject obj, JSType type, JSMutableHandleValue vp);
+(* JSConvertOp)(JSContext *cx, JSHandleObject obj, JSType type, JS::MutableHandle<JS::Value> vp);
 
 typedef struct JSFreeOp JSFreeOp;
 
 struct JSFreeOp {
   private:
     JSRuntime   *runtime_;
 
   protected:
@@ -877,25 +873,25 @@ struct JSStringFinalizer {
 /*
  * JSClass.checkAccess type: check whether obj[id] may be accessed per mode,
  * returning false on error/exception, true on success with obj[id]'s last-got
  * value in *vp, and its attributes in *attrsp.  As for JSPropertyOp above, id
  * is either a string or an int jsval.
  */
 typedef JSBool
 (* JSCheckAccessOp)(JSContext *cx, JSHandleObject obj, JSHandleId id, JSAccessMode mode,
-                    JSMutableHandleValue vp);
+                    JS::MutableHandle<JS::Value> vp);
 
 /*
  * Check whether v is an instance of obj.  Return false on error or exception,
  * true on success with JS_TRUE in *bp if v is an instance of obj, JS_FALSE in
  * *bp otherwise.
  */
 typedef JSBool
-(* JSHasInstanceOp)(JSContext *cx, JSHandleObject obj, JSMutableHandleValue vp, JSBool *bp);
+(* JSHasInstanceOp)(JSContext *cx, JSHandleObject obj, JS::MutableHandle<JS::Value> vp, JSBool *bp);
 
 /*
  * Function type for trace operation of the class called to enumerate all
  * traceable things reachable from obj's private data structure. For each such
  * thing, a trace implementation must call one of the JS_Call*Tracer variants
  * on the thing.
  *
  * JSTraceOp implementation can assume that no other threads mutates object
@@ -1025,27 +1021,27 @@ typedef struct JSErrorFormatString {
     int16_t exnType;
 } JSErrorFormatString;
 
 typedef const JSErrorFormatString *
 (* JSErrorCallback)(void *userRef, const char *locale,
                     const unsigned errorNumber);
 
 typedef JSBool
-(* JSLocaleToUpperCase)(JSContext *cx, JSHandleString src, JSMutableHandleValue rval);
+(* JSLocaleToUpperCase)(JSContext *cx, JSHandleString src, JS::MutableHandle<JS::Value> rval);
 
 typedef JSBool
-(* JSLocaleToLowerCase)(JSContext *cx, JSHandleString src, JSMutableHandleValue rval);
+(* JSLocaleToLowerCase)(JSContext *cx, JSHandleString src, JS::MutableHandle<JS::Value> rval);
 
 typedef JSBool
 (* JSLocaleCompare)(JSContext *cx, JSHandleString src1, JSHandleString src2,
-                    JSMutableHandleValue rval);
+                    JS::MutableHandle<JS::Value> rval);
 
 typedef JSBool
-(* JSLocaleToUnicode)(JSContext *cx, const char *src, JSMutableHandleValue rval);
+(* JSLocaleToUnicode)(JSContext *cx, const char *src, JS::MutableHandle<JS::Value> rval);
 
 /*
  * Security protocol types.
  */
 
 typedef void
 (* JSDestroyPrincipalsOp)(JSPrincipals *principals);
 
@@ -1781,17 +1777,17 @@ IsPoisonedId(jsid iden)
         return JS::IsPoisonedPtr(JSID_TO_OBJECT(iden));
     return false;
 }
 
 } /* namespace JS */
 
 namespace js {
 
-template <> struct RootMethods<jsid>
+template <> struct GCMethods<jsid>
 {
     static jsid initial() { return JSID_VOID; }
     static ThingRootKind kind() { return THING_ROOT_ID; }
     static bool poisoned(jsid id) { return JS::IsPoisonedId(id); }
     static bool needsPostBarrier(jsid id) { return false; }
 #ifdef JSGC_GENERATIONAL
     static void postBarrier(jsid *idp) {}
     static void relocate(jsid *idp) {}
@@ -2859,17 +2855,17 @@ struct JSClass {
  * member initial value.  The "original ... value" verbiage is there because
  * in ECMA-262, global properties naming class objects are read/write and
  * deleteable, for the most part.
  *
  * Implementing this efficiently requires that global objects have classes
  * with the following flags. Failure to use JSCLASS_GLOBAL_FLAGS was
  * prevously allowed, but is now an ES5 violation and thus unsupported.
  */
-#define JSCLASS_GLOBAL_SLOT_COUNT      (JSProto_LIMIT * 3 + 26)
+#define JSCLASS_GLOBAL_SLOT_COUNT      (JSProto_LIMIT * 3 + 25)
 #define JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(n)                                    \
     (JSCLASS_IS_GLOBAL | JSCLASS_HAS_RESERVED_SLOTS(JSCLASS_GLOBAL_SLOT_COUNT + (n)))
 #define JSCLASS_GLOBAL_FLAGS                                                  \
     JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(0)
 #define JSCLASS_HAS_GLOBAL_FLAG_AND_SLOTS(clasp)                              \
   (((clasp)->flags & JSCLASS_IS_GLOBAL)                                       \
    && JSCLASS_RESERVED_SLOTS(clasp) >= JSCLASS_GLOBAL_SLOT_COUNT)
 
@@ -2962,32 +2958,32 @@ JS_IdToValue(JSContext *cx, jsid id, jsv
  * the specified object, computing a primitive default value for the object.
  * The hint must be JSTYPE_STRING, JSTYPE_NUMBER, or JSTYPE_VOID (no hint).  On
  * success the resulting value is stored in *vp.
  */
 extern JS_PUBLIC_API(JSBool)
 JS_DefaultValue(JSContext *cx, JSObject *obj, JSType hint, jsval *vp);
 
 extern JS_PUBLIC_API(JSBool)
-JS_PropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, JSMutableHandleValue vp);
+JS_PropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, JS::MutableHandle<JS::Value> vp);
 
 extern JS_PUBLIC_API(JSBool)
-JS_StrictPropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, JSMutableHandleValue vp);
+JS_StrictPropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, JS::MutableHandle<JS::Value> vp);
 
 extern JS_PUBLIC_API(JSBool)
 JS_DeletePropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool *succeeded);
 
 extern JS_PUBLIC_API(JSBool)
 JS_EnumerateStub(JSContext *cx, JSHandleObject obj);
 
 extern JS_PUBLIC_API(JSBool)
 JS_ResolveStub(JSContext *cx, JSHandleObject obj, JSHandleId id);
 
 extern JS_PUBLIC_API(JSBool)
-JS_ConvertStub(JSContext *cx, JSHandleObject obj, JSType type, JSMutableHandleValue vp);
+JS_ConvertStub(JSContext *cx, JSHandleObject obj, JSType type, JS::MutableHandle<JS::Value> vp);
 
 struct JSConstDoubleSpec {
     double          dval;
     const char      *name;
     uint8_t         flags;
     uint8_t         spare[3];
 };
 
@@ -3338,17 +3334,17 @@ class PropertyDescriptorOperations
     void setSetterObject(JSObject *obj) { desc()->setter = reinterpret_cast<JSStrictPropertyOp>(obj); }
 };
 
 } /* namespace JS */
 
 namespace js {
 
 template <>
-struct RootMethods<JSPropertyDescriptor> {
+struct GCMethods<JSPropertyDescriptor> {
     static JSPropertyDescriptor initial() { return JSPropertyDescriptor(); }
     static ThingRootKind kind() { return THING_ROOT_PROPERTY_DESCRIPTOR; }
     static bool poisoned(const JSPropertyDescriptor &desc) {
         return (desc.obj && JS::IsPoisonedPtr(desc.obj)) ||
                (desc.attrs & JSPROP_GETTER && desc.getter && JS::IsPoisonedPtr(desc.getter)) ||
                (desc.attrs & JSPROP_SETTER && desc.setter && JS::IsPoisonedPtr(desc.setter)) ||
                (desc.value.isGCThing() && JS::IsPoisonedPtr(desc.value.toGCThing()));
     }
--- a/js/src/jsbool.cpp
+++ b/js/src/jsbool.cpp
@@ -166,18 +166,16 @@ js_InitBooleanClass(JSContext *cx, Handl
 
     RootedValue value(cx, ObjectValue(*valueOf));
     if (!JSObject::defineProperty(cx, booleanProto, valueOfName, value,
                                   JS_PropertyStub, JS_StrictPropertyStub, 0))
     {
         return NULL;
     }
 
-    global->setBooleanValueOf(valueOf);
-
     if (!DefineConstructorAndPrototype(cx, global, JSProto_Boolean, ctor, booleanProto))
         return NULL;
 
     return booleanProto;
 }
 
 JSString *
 js_BooleanToString(JSContext *cx, JSBool b)
@@ -190,21 +188,21 @@ js::ToBooleanSlow(const Value &v)
 {
     if (v.isString())
         return v.toString()->length() != 0;
 
     JS_ASSERT(v.isObject());
     return !EmulatesUndefined(&v.toObject());
 }
 
+/*
+ * This slow path is only ever taken for Boolean objects from other
+ * compartments. The only caller of the fast path, JSON's PreprocessValue,
+ * makes sure of that.
+ */
 bool
-js::BooleanGetPrimitiveValueSlow(JSContext *cx, HandleObject obj, Value *vp)
+js::BooleanGetPrimitiveValueSlow(HandleObject wrappedBool, JSContext *cx)
 {
-    InvokeArgsGuard ag;
-    if (!cx->stack.pushInvokeArgs(cx, 0, &ag))
-        return false;
-    ag.setCallee(cx->compartment()->maybeGlobal()->booleanValueOf());
-    ag.setThis(ObjectValue(*obj));
-    if (!Invoke(cx, ag))
-        return false;
-    *vp = ag.rval();
-    return true;
+    JS_ASSERT(wrappedBool->isCrossCompartmentWrapper());
+    JSObject *obj = Wrapper::wrappedObject(wrappedBool);
+    JS_ASSERT(obj);
+    return obj->asBoolean().unbox();
 }
--- a/js/src/jsbool.h
+++ b/js/src/jsbool.h
@@ -16,13 +16,13 @@ extern JSObject *
 js_InitBooleanClass(JSContext *cx, js::HandleObject obj);
 
 extern JSString *
 js_BooleanToString(JSContext *cx, JSBool b);
 
 namespace js {
 
 inline bool
-BooleanGetPrimitiveValue(JSContext *cx, HandleObject obj, Value *vp);
+BooleanGetPrimitiveValue(HandleObject obj, JSContext *cx);
 
 } /* namespace js */
 
 #endif /* jsbool_h___ */
--- a/js/src/jsboolinlines.h
+++ b/js/src/jsboolinlines.h
@@ -11,27 +11,26 @@
 #include "mozilla/Likely.h"
 
 #include "js/RootingAPI.h"
 
 #include "vm/BooleanObject-inl.h"
 
 namespace js {
 
-bool BooleanGetPrimitiveValueSlow(JSContext *, HandleObject, Value *);
+bool
+BooleanGetPrimitiveValueSlow(HandleObject, JSContext *);
 
 inline bool
-BooleanGetPrimitiveValue(JSContext *cx, HandleObject obj, Value *vp)
+BooleanGetPrimitiveValue(HandleObject obj, JSContext *cx)
 {
-    if (obj->isBoolean()) {
-        *vp = BooleanValue(obj->asBoolean().unbox());
-        return true;
-    }
+    if (obj->isBoolean())
+        return obj->asBoolean().unbox();
 
-    return BooleanGetPrimitiveValueSlow(cx, obj, vp);
+    return BooleanGetPrimitiveValueSlow(obj, cx);
 }
 
 inline bool
 EmulatesUndefined(JSObject *obj)
 {
     JSObject *actual = MOZ_LIKELY(!obj->isWrapper()) ? obj : UncheckedUnwrap(obj);
     bool emulatesUndefined = actual->getClass()->emulatesUndefined();
     MOZ_ASSERT_IF(emulatesUndefined, obj->type()->flags & types::OBJECT_FLAG_EMULATES_UNDEFINED);
--- a/js/src/jsclass.h
+++ b/js/src/jsclass.h
@@ -382,17 +382,17 @@ IsObjectWithClass(const Value &v, ESClas
 inline bool
 IsPoisonedSpecialId(js::SpecialId iden)
 {
     if (iden.isObject())
         return IsPoisonedPtr(iden.toObject());
     return false;
 }
 
-template <> struct RootMethods<SpecialId>
+template <> struct GCMethods<SpecialId>
 {
     static SpecialId initial() { return SpecialId(); }
     static ThingRootKind kind() { return THING_ROOT_ID; }
     static bool poisoned(SpecialId id) { return IsPoisonedSpecialId(id); }
 };
 
 }  /* namespace js */
 
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -1294,16 +1294,30 @@ JSContext::restoreFrameChain()
 
     if (Activation *act = mainThread().activation())
         act->restoreFrameChain();
 
     if (isExceptionPending())
         wrapPendingException();
 }
 
+bool
+JSContext::currentlyRunning() const
+{
+    for (ActivationIterator iter(runtime()); !iter.done(); ++iter) {
+        if (iter.activation()->cx() == this) {
+            if (iter.activation()->hasSavedFrameChain())
+                return false;
+            return true;
+        }
+    }
+
+    return false;
+}
+
 void
 JSRuntime::setGCMaxMallocBytes(size_t value)
 {
     /*
      * For compatibility treat any value that exceeds PTRDIFF_T_MAX to
      * mean that value.
      */
     gcMaxMallocBytes = (ptrdiff_t(value) >= 0) ? value : size_t(-1) >> 1;
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -516,22 +516,16 @@ class PerThreadData : public js::PerThre
     }
     js::AsmJSActivation *asmJSActivationStackFromOwnerThread() const {
         return asmJSActivationStack_;
     }
 
     js::Activation *activation() const {
         return activation_;
     }
-    bool currentlyRunningInInterpreter() const {
-        return activation_->isInterpreter();
-    }
-    bool currentlyRunningInJit() const {
-        return activation_->isJit();
-    }
 
     /*
      * When this flag is non-zero, any attempt to GC will be skipped. It is used
      * to suppress GC when reporting an OOM (see js_ReportOutOfMemory) and in
      * debugging facilities that cannot tolerate a GC and would rather OOM
      * immediately, such as utilities exposed to GDB. Setting this flag is
      * extremely dangerous and should only be used when in an OOM situation or
      * in non-exposed debugging facilities.
@@ -1522,17 +1516,17 @@ struct JSContext : js::ContextFriendFiel
     JSRuntime *runtime() const { return runtime_; }
     JSCompartment *compartment() const { return compartment_; }
 
     inline JS::Zone *zone() const {
         JS_ASSERT_IF(!compartment(), !zone_);
         JS_ASSERT_IF(compartment(), js::GetCompartmentZone(compartment()) == zone_);
         return zone_;
     }
-    js::PerThreadData &mainThread() { return runtime()->mainThread; }
+    js::PerThreadData &mainThread() const { return runtime()->mainThread; }
 
   private:
     /* See JSContext::findVersion. */
     JSVersion           defaultVersion;      /* script compilation version */
     JSVersion           versionOverride;     /* supercedes defaultVersion when valid */
     bool                hasVersionOverride;
 
     /* Exception state -- the exception member is a GC root by definition. */
@@ -1612,23 +1606,16 @@ struct JSContext : js::ContextFriendFiel
     js::ContextStack    stack;
 
     /*
      * Current global. This is only safe to use within the scope of the
      * AutoCompartment from which it's called.
      */
     inline js::Handle<js::GlobalObject*> global() const;
 
-    /* ContextStack convenience functions */
-    inline bool hasfp() const               { return stack.hasfp(); }
-    inline js::StackFrame* fp() const       { return stack.fp(); }
-    inline js::StackFrame* maybefp() const  { return stack.maybefp(); }
-    inline js::FrameRegs& regs() const      { return stack.regs(); }
-    inline js::FrameRegs* maybeRegs() const { return stack.maybeRegs(); }
-
     /* Wrap cx->exception for the current compartment. */
     void wrapPendingException();
 
     /* State for object and array toSource conversion. */
     js::ObjectSet       cycleDetectorSet;
 
     /* Per-context optional error reporter. */
     JSErrorReporter     errorReporter;
@@ -1728,16 +1715,32 @@ struct JSContext : js::ContextFriendFiel
     js::Value           iterValue;
 
     bool jitIsBroken;
 
     inline bool typeInferenceEnabled() const;
 
     void updateJITEnabled();
 
+    /* Whether this context has JS frames on the stack. */
+    bool currentlyRunning() const;
+
+    bool currentlyRunningInInterpreter() const {
+        return mainThread().activation()->isInterpreter();
+    }
+    bool currentlyRunningInJit() const {
+        return mainThread().activation()->isJit();
+    }
+    js::StackFrame *interpreterFrame() const {
+        return mainThread().activation()->asInterpreter()->current();
+    }
+    js::FrameRegs &interpreterRegs() const {
+        return mainThread().activation()->asInterpreter()->regs();
+    }
+
 #ifdef MOZ_TRACE_JSCALLS
     /* Function entry/exit debugging callback. */
     JSFunctionCallback    functionCallback;
 
     void doFunctionCallback(const JSFunction *fun,
                             const JSScript *scr,
                             int entering) const
     {
--- a/js/src/jscntxtinlines.h
+++ b/js/src/jscntxtinlines.h
@@ -121,21 +121,21 @@ NewObjectCache::newObjectFromHit(JSConte
     }
 
     return NULL;
 }
 
 struct PreserveRegsGuard
 {
     PreserveRegsGuard(JSContext *cx, FrameRegs &regs)
-      : prevContextRegs(cx->maybeRegs()), cx(cx), regs_(regs) {
+      : prevContextRegs(cx->stack.maybeRegs()), cx(cx), regs_(regs) {
         cx->stack.repointRegs(&regs_);
     }
     ~PreserveRegsGuard() {
-        JS_ASSERT(cx->maybeRegs() == &regs_);
+        JS_ASSERT(cx->stack.maybeRegs() == &regs_);
         *prevContextRegs = regs_;
         cx->stack.repointRegs(prevContextRegs);
     }
 
     FrameRegs *prevContextRegs;
 
   private:
     JSContext *cx;
@@ -453,17 +453,17 @@ CallSetter(JSContext *cx, HandleObject o
     return CallJSPropertyOpSetter(cx, op, obj, nid, strict, vp);
 }
 
 }  /* namespace js */
 
 inline bool
 JSContext::canSetDefaultVersion() const
 {
-    return !stack.hasfp() && !hasVersionOverride;
+    return !currentlyRunning() && !hasVersionOverride;
 }
 
 inline void
 JSContext::overrideVersion(JSVersion newVersion)
 {
     JS_ASSERT(!canSetDefaultVersion());
     versionOverride = newVersion;
     hasVersionOverride = true;
@@ -513,17 +513,17 @@ JSContext::setDefaultCompartmentObject(J
 
     if (!hasEnteredCompartment()) {
         /*
          * If JSAPI callers want to JS_SetGlobalObject while code is running,
          * they must have entered a compartment (otherwise there will be no
          * final leaveCompartment call to set the context's compartment back to
          * defaultCompartmentObject->compartment()).
          */
-        JS_ASSERT(!hasfp());
+        JS_ASSERT(!currentlyRunning());
         setCompartment(obj ? obj->compartment() : NULL);
         if (throwing)
             wrapPendingException();
     }
 }
 
 inline void
 JSContext::setDefaultCompartmentObjectIfUnset(JSObject *obj)
--- a/js/src/jsdbgapi.cpp
+++ b/js/src/jsdbgapi.cpp
@@ -71,17 +71,17 @@ IsTopFrameConstructing(JSContext *cx, Ab
     ScriptFrameIter iter(cx);
     JS_ASSERT(iter.abstractFramePtr() == frame);
     return iter.isConstructing();
 }
 
 JSTrapStatus
 js::ScriptDebugPrologue(JSContext *cx, AbstractFramePtr frame)
 {
-    JS_ASSERT_IF(frame.isStackFrame(), frame.asStackFrame() == cx->fp());
+    JS_ASSERT_IF(frame.isStackFrame(), frame.asStackFrame() == cx->interpreterFrame());
 
     if (!frame.script()->selfHosted) {
         if (frame.isFramePushedByExecute()) {
             if (JSInterpreterHook hook = cx->runtime()->debugHooks.executeHook)
                 frame.setHookData(hook(cx, Jsvalify(frame), IsTopFrameConstructing(cx, frame),
                                        true, 0, cx->runtime()->debugHooks.executeHookData));
         } else {
             if (JSInterpreterHook hook = cx->runtime()->debugHooks.callHook)
@@ -108,17 +108,18 @@ js::ScriptDebugPrologue(JSContext *cx, A
         JS_NOT_REACHED("bad Debugger::onEnterFrame JSTrapStatus value");
     }
     return status;
 }
 
 bool
 js::ScriptDebugEpilogue(JSContext *cx, AbstractFramePtr frame, bool okArg)
 {
-    JS_ASSERT_IF(frame.isStackFrame(), frame.asStackFrame() == cx->fp());
+    JS_ASSERT_IF(frame.isStackFrame(), frame.asStackFrame() == cx->interpreterFrame());
+
     JSBool ok = okArg;
 
     // We don't add hook data for self-hosted scripts, so we don't need to check for them, here.
     if (void *hookData = frame.maybeHookData()) {
         if (frame.isFramePushedByExecute()) {
             if (JSInterpreterHook hook = cx->runtime()->debugHooks.executeHook)
                 hook(cx, Jsvalify(frame), IsTopFrameConstructing(cx, frame), false, &ok, hookData);
         } else {
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -399,24 +399,24 @@ JS_FRIEND_API(bool)
 js::IsOriginalScriptFunction(JSFunction *fun)
 {
     return fun->nonLazyScript()->function() == fun;
 }
 
 JS_FRIEND_API(JSScript *)
 js::GetOutermostEnclosingFunctionOfScriptedCaller(JSContext *cx)
 {
-    if (!cx->hasfp())
+    ScriptFrameIter iter(cx);
+    if (iter.done())
         return NULL;
 
-    StackFrame *fp = cx->fp();
-    if (!fp->isFunctionFrame())
+    if (!iter.isFunctionFrame())
         return NULL;
 
-    RootedFunction scriptedCaller(cx, fp->fun());
+    RootedFunction scriptedCaller(cx, iter.callee());
     RootedScript outermost(cx, scriptedCaller->nonLazyScript());
     for (StaticScopeIter i(cx, scriptedCaller); !i.done(); i++) {
         if (i.type() == StaticScopeIter::FUNCTION)
             outermost = i.funScript();
     }
     return outermost;
 }
 
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -120,17 +120,17 @@ JS_ObjectToOuterObject(JSContext *cx, JS
 
 extern JS_FRIEND_API(JSObject *)
 JS_CloneObject(JSContext *cx, JSObject *obj, JSObject *proto, JSObject *parent);
 
 extern JS_FRIEND_API(JSString *)
 JS_BasicObjectToString(JSContext *cx, JSHandleObject obj);
 
 extern JS_FRIEND_API(JSBool)
-js_GetterOnlyPropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, JSMutableHandleValue vp);
+js_GetterOnlyPropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, JS::MutableHandleValue vp);
 
 JS_FRIEND_API(void)
 js_ReportOverRecursed(JSContext *maybecx);
 
 #ifdef DEBUG
 
 /*
  * Routines to print out values during debugging.  These are FRIEND_API to help
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -879,17 +879,17 @@ js_fun_apply(JSContext *cx, unsigned arg
          * function and read actuals out of the frame.
          */
         /* Steps 4-6. */
 
 #ifdef JS_ION
         // We do not want to use ScriptFrameIter to abstract here because this
         // is supposed to be a fast path as opposed to ScriptFrameIter which is
         // doing complex logic to settle on the next frame twice.
-        if (cx->mainThread().currentlyRunningInJit()) {
+        if (cx->currentlyRunningInJit()) {
             ion::JitActivationIterator activations(cx->runtime());
             ion::IonFrameIterator frame(activations);
             if (frame.isNative()) {
                 // Stop on the next Ion JS Frame.
                 ++frame;
                 if (frame.isOptimizedJS()) {
                     ion::InlineFrameIterator iter(cx, &frame);
 
@@ -924,17 +924,17 @@ js_fun_apply(JSContext *cx, unsigned arg
                 JS_ASSERT(frame.isBaselineJS());
 
                 if (!PushBaselineFunApplyArguments(cx, frame, args, vp))
                     return false;
             }
         } else
 #endif
         {
-            StackFrame *fp = cx->fp();
+            StackFrame *fp = cx->interpreterFrame();
             unsigned length = fp->numActualArgs();
             JS_ASSERT(length <= StackSpace::ARGS_LENGTH_MAX);
 
             if (!cx->stack.pushInvokeArgs(cx, length, &args))
                 return false;
 
             /* Push fval, obj, and aobj's elements as args. */
             args.setCallee(fval);
--- a/js/src/jsinfer.h
+++ b/js/src/jsinfer.h
@@ -44,24 +44,24 @@ class TaggedProto
 };
 
 template <>
 struct RootKind<TaggedProto>
 {
     static ThingRootKind rootKind() { return THING_ROOT_OBJECT; }
 };
 
-template <> struct RootMethods<const TaggedProto>
+template <> struct GCMethods<const TaggedProto>
 {
     static TaggedProto initial() { return TaggedProto(); }
     static ThingRootKind kind() { return THING_ROOT_OBJECT; }
     static bool poisoned(const TaggedProto &v) { return IsPoisonedPtr(v.raw()); }
 };
 
-template <> struct RootMethods<TaggedProto>
+template <> struct GCMethods<TaggedProto>
 {
     static TaggedProto initial() { return TaggedProto(); }
     static ThingRootKind kind() { return THING_ROOT_OBJECT; }
     static bool poisoned(const TaggedProto &v) { return IsPoisonedPtr(v.raw()); }
 };
 
 template<class Outer>
 class TaggedProtoOperations
--- a/js/src/jsinferinlines.h
+++ b/js/src/jsinferinlines.h
@@ -1800,28 +1800,28 @@ js::analyze::ScriptAnalysis::addPushedTy
 {
     js::types::TypeSet *pushed = pushedTypes(offset, which);
     pushed->addType(cx, type);
 }
 
 namespace js {
 
 template <>
-struct RootMethods<const types::Type>
+struct GCMethods<const types::Type>
 {
     static types::Type initial() { return types::Type::UnknownType(); }
     static ThingRootKind kind() { return THING_ROOT_TYPE; }
     static bool poisoned(const types::Type &v) {
         return (v.isTypeObject() && IsPoisonedPtr(v.typeObject()))
             || (v.isSingleObject() && IsPoisonedPtr(v.singleObject()));
     }
 };
 
 template <>
-struct RootMethods<types::Type>
+struct GCMethods<types::Type>
 {
     static types::Type initial() { return types::Type::UnknownType(); }
     static ThingRootKind kind() { return THING_ROOT_TYPE; }
     static bool poisoned(const types::Type &v) {
         return (v.isTypeObject() && IsPoisonedPtr(v.typeObject()))
             || (v.isSingleObject() && IsPoisonedPtr(v.singleObject()));
     }
 };
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -1411,19 +1411,18 @@ Class js::GeneratorClass = {
  * Called from the JSOP_GENERATOR case in the interpreter, with fp referring
  * to the frame by which the generator function was activated.  Create a new
  * JSGenerator object, which contains its own StackFrame that we populate
  * from *fp.  We know that upon return, the JSOP_GENERATOR opcode will return
  * from the activation in fp, so we can steal away fp->callobj and fp->argsobj
  * if they are non-null.
  */
 JSObject *
-js_NewGenerator(JSContext *cx)
+js_NewGenerator(JSContext *cx, const FrameRegs &stackRegs)
 {
-    FrameRegs &stackRegs = cx->regs();
     JS_ASSERT(stackRegs.stackDepth() == 0);
     StackFrame *stackfp = stackRegs.fp();
 
     Rooted<GlobalObject*> global(cx, &stackfp->global());
     RootedObject obj(cx);
     {
         JSObject *proto = global->getOrCreateGeneratorPrototype(cx);
         if (!proto)
@@ -1544,17 +1543,17 @@ SendToGenerator(JSContext *cx, JSGenerat
 
         /*
          * Don't change the state until after the frame is successfully pushed
          * or else we might fail to scan some generator values.
          */
         gen->state = futureState;
 
         StackFrame *fp = gfg.fp();
-        gen->regs = cx->regs();
+        gen->regs = cx->stack.regs();
 
         cx->enterGenerator(gen);   /* OOM check above. */
         ok = RunScript(cx, fp);
         cx->leaveGenerator(gen);
     }
 
     if (gen->fp->isYielding()) {
         /*
--- a/js/src/jsiter.h
+++ b/js/src/jsiter.h
@@ -341,17 +341,17 @@ struct JSGenerator
     JSGeneratorState    state;
     js::FrameRegs       regs;
     JSGenerator         *prevGenerator;
     js::StackFrame      *fp;
     js::HeapValue       stackSnapshot[1];
 };
 
 extern JSObject *
-js_NewGenerator(JSContext *cx);
+js_NewGenerator(JSContext *cx, const js::FrameRegs &regs);
 
 namespace js {
 
 bool
 GeneratorHasMarkableFrame(JSGenerator *gen);
 
 } /* namespace js */
 #endif
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -4698,17 +4698,17 @@ js::DefaultValue(JSContext *cx, HandleOb
     RootedValue val(cx, ObjectValue(*obj));
     js_ReportValueError2(cx, JSMSG_CANT_CONVERT_TO, JSDVG_SEARCH_STACK, val, str,
                          (hint == JSTYPE_VOID) ? "primitive type" : TypeStrings[hint]);
     return false;
 }
 
 JS_FRIEND_API(JSBool)
 JS_EnumerateState(JSContext *cx, JSHandleObject obj, JSIterateOp enum_op,
-                  JSMutableHandleValue statep, JS::MutableHandleId idp)
+                  MutableHandleValue statep, JS::MutableHandleId idp)
 {
     /* If the class has a custom JSCLASS_NEW_ENUMERATE hook, call it. */
     Class *clasp = obj->getClass();
     JSEnumerateOp enumerate = clasp->enumerate;
     if (clasp->flags & JSCLASS_NEW_ENUMERATE) {
         JS_ASSERT(enumerate != JS_EnumerateStub);
         return ((JSNewEnumerateOp) enumerate)(cx, obj, enum_op, statep, idp);
     }
@@ -4988,17 +4988,17 @@ js_ReportGetterOnlyAssignment(JSContext 
     return JS_ReportErrorFlagsAndNumber(cx,
                                         JSREPORT_WARNING | JSREPORT_STRICT |
                                         JSREPORT_STRICT_MODE_ERROR,
                                         js_GetErrorMessage, NULL,
                                         JSMSG_GETTER_ONLY);
 }
 
 JS_FRIEND_API(JSBool)
-js_GetterOnlyPropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, JSMutableHandleValue vp)
+js_GetterOnlyPropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, MutableHandleValue vp)
 {
     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_GETTER_ONLY);
     return JS_FALSE;
 }
 
 #ifdef DEBUG
 
 /*
--- a/js/src/json.cpp
+++ b/js/src/json.cpp
@@ -273,19 +273,17 @@ PreprocessValue(JSContext *cx, HandleObj
                 return false;
             vp.set(NumberValue(d));
         } else if (ObjectClassIs(obj, ESClass_String, cx)) {
             JSString *str = ToStringSlow<CanGC>(cx, vp);
             if (!str)
                 return false;
             vp.set(StringValue(str));
         } else if (ObjectClassIs(obj, ESClass_Boolean, cx)) {
-            if (!BooleanGetPrimitiveValue(cx, obj, vp.address()))
-                return false;
-            JS_ASSERT(vp.get().isBoolean());
+            vp.setBoolean(BooleanGetPrimitiveValue(obj, cx));
         }
     }
 
     return true;
 }
 
 /*
  * Determines whether a value which has passed by ES5 150.2.3 Str steps 1-4's
--- a/js/src/jsopcode.cpp
+++ b/js/src/jsopcode.cpp
@@ -406,18 +406,19 @@ js_Disassemble(JSContext *cx, HandleScri
 
 JS_FRIEND_API(JSBool)
 js_DumpPC(JSContext *cx)
 {
     js::gc::AutoSuppressGC suppressGC(cx);
     Sprinter sprinter(cx);
     if (!sprinter.init())
         return JS_FALSE;
-    RootedScript script(cx, cx->fp()->script());
-    JSBool ok = js_DisassembleAtPC(cx, script, true, cx->regs().pc, false, &sprinter);
+    ScriptFrameIter iter(cx);
+    RootedScript script(cx, iter.script());
+    JSBool ok = js_DisassembleAtPC(cx, script, true, iter.pc(), false, &sprinter);
     fprintf(stdout, "%s", sprinter.string());
     return ok;
 }
 
 JS_FRIEND_API(JSBool)
 js_DumpScript(JSContext *cx, JSScript *scriptArg)
 {
     js::gc::AutoSuppressGC suppressGC(cx);
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -169,17 +169,17 @@ Bindings::clone(JSContext *cx, InternalB
      */
     if (!initWithTemporaryStorage(cx, self, src.numArgs(), src.numVars(), src.bindingArray()))
         return false;
     self->switchToScriptStorage(dstPackedBindings);
     return true;
 }
 
 /* static */ Bindings
-RootMethods<Bindings>::initial()
+GCMethods<Bindings>::initial()
 {
     return Bindings();
 }
 
 template<XDRMode mode>
 static bool
 XDRScriptBindings(XDRState<mode> *xdr, LifoAllocScope &las, unsigned numArgs, unsigned numVars,
                   HandleScript script)
@@ -2233,22 +2233,16 @@ js_GetScriptLineExtent(JSScript *script)
     }
 
     if (maxLineNo > lineno)
         lineno = maxLineNo;
 
     return 1 + lineno - script->lineno;
 }
 
-unsigned
-js::CurrentLine(JSContext *cx)
-{
-    return PCToLineNumber(cx->fp()->script(), cx->regs().pc);
-}
-
 void
 js::CurrentScriptFileLineOriginSlow(JSContext *cx, const char **file, unsigned *linenop,
                                     JSPrincipals **origin)
 {
     NonBuiltinScriptFrameIter iter(cx);
 
     if (iter.done()) {
         *file = NULL;
--- a/js/src/jsscript.h
+++ b/js/src/jsscript.h
@@ -206,17 +206,17 @@ class Bindings
 
     /* Return whether this scope has any aliased bindings. */
     bool hasAnyAliasedBindings() const { return !callObjShape_->isEmptyShape(); }
 
     void trace(JSTracer *trc);
 };
 
 template <>
-struct RootMethods<Bindings> {
+struct GCMethods<Bindings> {
     static Bindings initial();
     static ThingRootKind kind() { return THING_ROOT_BINDINGS; }
     static bool poisoned(const Bindings &bindings) {
         return IsPoisonedPtr(static_cast<Shape *>(bindings.callObjShape()));
     }
 };
 
 class ScriptCounts
@@ -1448,19 +1448,16 @@ namespace js {
 
 extern unsigned
 PCToLineNumber(JSScript *script, jsbytecode *pc, unsigned *columnp = NULL);
 
 extern unsigned
 PCToLineNumber(unsigned startLine, jssrcnote *notes, jsbytecode *code, jsbytecode *pc,
                unsigned *columnp = NULL);
 
-extern unsigned
-CurrentLine(JSContext *cx);
-
 /*
  * This function returns the file and line number of the script currently
  * executing on cx. If there is no current script executing on cx (e.g., a
  * native called directly through JSAPI (e.g., by setTimeout)), NULL and 0 are
  * returned as the file and line. Additionally, this function avoids the full
  * linear scan to compute line number when the caller guarnatees that the
  * script compilation occurs at a JSOP_EVAL.
  */
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -2594,18 +2594,16 @@ EvalInFrame(JSContext *cx, unsigned argc
 
     uint32_t upCount = JSVAL_TO_INT(argv[0]);
     RootedString str(cx, JSVAL_TO_STRING(argv[1]));
 
     bool saveCurrent = (argc >= 3 && JSVAL_IS_BOOLEAN(argv[2]))
                         ? !!(JSVAL_TO_BOOLEAN(argv[2]))
                         : false;
 
-    JS_ASSERT(cx->hasfp());
-
     /* This is a copy of CheckDebugMode. */
     if (!JS_GetDebugMode(cx)) {
         JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, js_GetErrorMessage,
                                      NULL, JSMSG_NEED_DEBUG_MODE);
         return false;
     }
 
     /* Debug-mode currently disables Ion compilation. */
--- a/js/src/vm/GlobalObject-inl.h
+++ b/js/src/vm/GlobalObject-inl.h
@@ -54,23 +54,16 @@ GlobalObject::setOriginalEval(JSObject *
 void
 GlobalObject::setCreateArrayFromBufferHelper(uint32_t slot, Handle<JSFunction*> fun)
 {
     JS_ASSERT(getSlotRef(slot).isUndefined());
     setSlot(slot, ObjectValue(*fun));
 }
 
 void
-GlobalObject::setBooleanValueOf(Handle<JSFunction*> valueOfFun)
-{
-    JS_ASSERT(getSlotRef(BOOLEAN_VALUEOF).isUndefined());
-    setSlot(BOOLEAN_VALUEOF, ObjectValue(*valueOfFun));
-}
-
-void
 GlobalObject::setCreateDataViewForThis(Handle<JSFunction*> fun)
 {
     JS_ASSERT(getSlotRef(CREATE_DATAVIEW_FOR_THIS).isUndefined());
     setSlot(CREATE_DATAVIEW_FOR_THIS, ObjectValue(*fun));
 }
 
 template<>
 inline void
--- a/js/src/vm/GlobalObject.h
+++ b/js/src/vm/GlobalObject.h
@@ -61,18 +61,17 @@ class GlobalObject : public JSObject
 {
     /*
      * Count of slots to store built-in constructors, prototypes, and initial
      * visible properties for the constructors.
      */
     static const unsigned STANDARD_CLASS_SLOTS  = JSProto_LIMIT * 3;
 
     /* Various function values needed by the engine. */
-    static const unsigned BOOLEAN_VALUEOF         = STANDARD_CLASS_SLOTS;
-    static const unsigned EVAL                    = BOOLEAN_VALUEOF + 1;
+    static const unsigned EVAL                    = STANDARD_CLASS_SLOTS;
     static const unsigned CREATE_DATAVIEW_FOR_THIS = EVAL + 1;
     static const unsigned THROWTYPEERROR          = CREATE_DATAVIEW_FOR_THIS + 1;
     static const unsigned PROTO_GETTER            = THROWTYPEERROR + 1;
 
     /*
      * Instances of the internal createArrayFromBuffer function used by the
      * typed array code, one per typed array element type.
      */
@@ -189,17 +188,16 @@ class GlobalObject : public JSObject
         JS_ASSERT(FROM_BUFFER_UINT8 <= slot && slot <= FROM_BUFFER_UINT8CLAMPED);
         return getSlot(slot);
     }
 
     inline void setCreateArrayFromBufferHelper(uint32_t slot, Handle<JSFunction*> fun);
 
   public:
     /* XXX Privatize me! */
-    inline void setBooleanValueOf(Handle<JSFunction*> valueOfFun);
     inline void setCreateDataViewForThis(Handle<JSFunction*> fun);
 
     template<typename T>
     inline void setCreateArrayFromBuffer(Handle<JSFunction*> fun);
 
   public:
     static GlobalObject *create(JSContext *cx, Class *clasp);
 
@@ -393,21 +391,16 @@ class GlobalObject : public JSObject
 
     inline RegExpStatics *getRegExpStatics() const;
 
     JSObject *getThrowTypeError() const {
         JS_ASSERT(functionObjectClassesInitialized());
         return &getSlot(THROWTYPEERROR).toObject();
     }
 
-    Value booleanValueOf() const {
-        JS_ASSERT(booleanClassInitialized());
-        return getSlot(BOOLEAN_VALUEOF);
-    }
-
     Value createDataViewForThis() const {
         JS_ASSERT(dataViewClassInitialized());
         return getSlot(CREATE_DATAVIEW_FOR_THIS);
     }
 
     template<typename T>
     inline Value createArrayFromBuffer() const;
 
--- a/js/src/vm/Interpreter-inl.h
+++ b/js/src/vm/Interpreter-inl.h
@@ -120,41 +120,32 @@ IsOptimizedArguments(AbstractFramePtr fr
     return vp->isMagic(JS_OPTIMIZED_ARGUMENTS);
 }
 
 /*
  * One optimized consumer of MagicValue(JS_OPTIMIZED_ARGUMENTS) is f.apply.
  * However, this speculation must be guarded before calling 'apply' in case it
  * is not the builtin Function.prototype.apply.
  */
-static bool
+static inline bool
 GuardFunApplyArgumentsOptimization(JSContext *cx, AbstractFramePtr frame, HandleValue callee,
                                    Value *args, uint32_t argc)
 {
     if (argc == 2 && IsOptimizedArguments(frame, &args[1])) {
         if (!IsNativeFunction(callee, js_fun_apply)) {
             RootedScript script(cx, frame.script());
             if (!JSScript::argumentsOptimizationFailed(cx, script))
                 return false;
             args[1] = ObjectValue(frame.argsObj());
         }
     }
 
     return true;
 }
 
-static inline bool
-GuardFunApplyArgumentsOptimization(JSContext *cx)
-{
-    FrameRegs &regs = cx->regs();
-    CallArgs args = CallArgsFromSp(GET_ARGC(regs.pc), regs.sp);
-    return GuardFunApplyArgumentsOptimization(cx, cx->fp(), args.calleev(), args.array(),
-                                              args.length());
-}
-
 /*
  * Return an object on which we should look for the properties of |value|.
  * This helps us implement the custom [[Get]] method that ES5's GetValue
  * algorithm uses for primitive values, without actually constructing the
  * temporary object that the specification does.
  *
  * For objects, return the object itself. For string, boolean, and number
  * primitive values, return the appropriate constructor's prototype. For
@@ -592,17 +583,17 @@ ToIdOperation(JSContext *cx, HandleScrip
 }
 
 static JS_ALWAYS_INLINE bool
 GetObjectElementOperation(JSContext *cx, JSOp op, JSObject *objArg, bool wasObject,
                           HandleValue rref, MutableHandleValue res)
 {
     do {
         // Don't call GetPcScript (needed for analysis) from inside Ion since it's expensive.
-        bool analyze = cx->mainThread().currentlyRunningInInterpreter();
+        bool analyze = cx->currentlyRunningInInterpreter();
 
         uint32_t index;
         if (IsDefinitelyIndex(rref, &index)) {
             if (analyze && !objArg->isNative() && !objArg->isTypedArray()) {
                 JSScript *script = NULL;
                 jsbytecode *pc = NULL;
                 types::TypeScript::GetPcScript(cx, &script, &pc);
 
@@ -725,22 +716,16 @@ GetElementOperation(JSContext *cx, JSOp 
             str = cx->runtime()->staticStrings.getUnitStringForElement(cx, str, index);
             if (!str)
                 return false;
             res.setString(str);
             return true;
         }
     }
 
-    bool done = false;
-    if (!GetElemOptimizedArguments(cx, cx->fp(), lref, rref, res, &done))
-        return false;
-    if (done)
-        return true;
-
     bool isObject = lref.isObject();
     JSObject *obj = ToObjectFromStack(cx, lref);
     if (!obj)
         return false;
     return GetObjectElementOperation(cx, op, obj, isObject, rref, res);
 }
 
 static JS_ALWAYS_INLINE bool
@@ -753,17 +738,17 @@ SetObjectElementOperation(JSContext *cx,
     if (obj->isNative() && JSID_IS_INT(id)) {
         uint32_t length = obj->getDenseInitializedLength();
         int32_t i = JSID_TO_INT(id);
         if ((uint32_t)i >= length) {
             // In an Ion activation, GetPcScript won't work.  For non-baseline activations,
             // that's ok, because optimized ion doesn't generate analysis info.  However,
             // baseline must generate this information, so it passes the script and pc in
             // as arguments.
-            if (script || cx->mainThread().currentlyRunningInInterpreter()) {
+            if (script || cx->currentlyRunningInInterpreter()) {
                 JS_ASSERT(!!script == !!pc);
                 if (!script)
                     types::TypeScript::GetPcScript(cx, script.address(), &pc);
 
                 if (script->hasAnalysis())
                     script->analysis()->getCode(pc).arrayWriteHole = true;
             }
         }
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -78,30 +78,29 @@ CallThisObjectHook(JSContext *cx, Handle
  * influences performance. The JS_NEVER_INLINE is a temporary workaround until
  * we can remove the conservative scanner. See bug 849526 for more info.
  */
 #if defined(__clang__) && defined(JS_CPU_X86)
 static JS_NEVER_INLINE bool
 #else
 static bool
 #endif
-ToBooleanOp(JSContext *cx)
+ToBooleanOp(const FrameRegs &regs)
 {
-    return ToBoolean(cx->regs().sp[-1]);
+    return ToBoolean(regs.sp[-1]);
 }
 
 template <bool Eq>
 #if defined(__clang__) && defined(JS_CPU_X86)
 static JS_NEVER_INLINE bool
 #else
 static bool
 #endif
-LooseEqualityOp(JSContext *cx)
+LooseEqualityOp(JSContext *cx, FrameRegs &regs)
 {
-    FrameRegs &regs = cx->regs();
     Value rval = regs.sp[-1];
     Value lval = regs.sp[-2];
     bool cond;
     if (!LooselyEqual(cx, lval, rval, &cond))
         return false;
     cond = (cond == Eq);
     regs.sp--;
     regs.sp[-1].setBoolean(cond);
@@ -249,24 +248,24 @@ NoSuchMethod(JSContext *cx, unsigned arg
     JSBool ok = Invoke(cx, args);
     vp[0] = args.rval();
     return ok;
 }
 
 #endif /* JS_HAS_NO_SUCH_METHOD */
 
 inline bool
-GetPropertyOperation(JSContext *cx, HandleScript script, jsbytecode *pc, MutableHandleValue lval,
-                     MutableHandleValue vp)
+GetPropertyOperation(JSContext *cx, StackFrame *fp, HandleScript script, jsbytecode *pc,
+                     MutableHandleValue lval, MutableHandleValue vp)
 {
     JSOp op = JSOp(*pc);
 
     if (op == JSOP_LENGTH) {
-        if (IsOptimizedArguments(cx->fp(), lval.address())) {
-            vp.setInt32(cx->fp()->numActualArgs());
+        if (IsOptimizedArguments(fp, lval.address())) {
+            vp.setInt32(fp->numActualArgs());
             return true;
         }
 
         if (GetLengthProperty(lval, vp))
             return true;
     }
 
     JSObject *obj = ToObjectFromStack(cx, lval);
@@ -348,20 +347,20 @@ js::ValueToCallable(JSContext *cx, const
 }
 
 static JS_NEVER_INLINE bool
 Interpret(JSContext *cx, StackFrame *entryFrame);
 
 bool
 js::RunScript(JSContext *cx, StackFrame *fp)
 {
-    JS_ASSERT(fp == cx->fp());
+    JS_ASSERT(fp == cx->stack.fp());
     RootedScript script(cx, fp->script());
 
-    JS_ASSERT_IF(!fp->isGeneratorFrame(), cx->regs().pc == script->code);
+    JS_ASSERT_IF(!fp->isGeneratorFrame(), cx->stack.regs().pc == script->code);
     JS_ASSERT_IF(fp->isEvalFrame(), script->isActiveEval);
 
     JS_CHECK_RECURSION(cx, return false);
 
     // Check to see if useNewType flag should be set for this frame.
     if (fp->isFunctionFrame() && fp->isConstructing() && !fp->isGeneratorFrame() &&
         cx->typeInferenceEnabled())
     {
@@ -374,20 +373,20 @@ js::RunScript(JSContext *cx, StackFrame 
         }
     }
 
 #ifdef DEBUG
     struct CheckStackBalance {
         JSContext *cx;
         StackFrame *fp;
         CheckStackBalance(JSContext *cx)
-          : cx(cx), fp(cx->fp())
+          : cx(cx), fp(cx->stack.fp())
         {}
         ~CheckStackBalance() {
-            JS_ASSERT(fp == cx->fp());
+            JS_ASSERT(fp == cx->stack.fp());
         }
     } check(cx);
 #endif
 
     SPSEntryMarker marker(cx->runtime());
 
 #ifdef JS_ION
     if (ion::IsEnabled(cx)) {
@@ -803,48 +802,42 @@ js::TypeOfValue(JSContext *cx, const Val
     return JSTYPE_BOOLEAN;
 }
 
 /*
  * Enter the new with scope using an object at sp[-1] and associate the depth
  * of the with block with sp + stackIndex.
  */
 static bool
-EnterWith(JSContext *cx, int stackIndex)
+EnterWith(JSContext *cx, AbstractFramePtr frame, HandleValue val, uint32_t stackDepth)
 {
-    StackFrame *fp = cx->fp();
-    Value *sp = cx->regs().sp;
-    JS_ASSERT(stackIndex < 0);
-    JS_ASSERT(int(cx->regs().stackDepth()) + stackIndex >= 0);
-
     RootedObject obj(cx);
-    if (sp[-1].isObject()) {
-        obj = &sp[-1].toObject();
+    if (val.isObject()) {
+        obj = &val.toObject();
     } else {
-        obj = js_ValueToNonNullObject(cx, sp[-1]);
+        obj = js_ValueToNonNullObject(cx, val);
         if (!obj)
             return false;
-        sp[-1].setObject(*obj);
     }
 
-    WithObject *withobj = WithObject::create(cx, obj, fp->scopeChain(),
-                                             cx->regs().stackDepth() + stackIndex);
+    RootedObject scopeChain(cx, frame.scopeChain());
+    WithObject *withobj = WithObject::create(cx, obj, scopeChain, stackDepth);
     if (!withobj)
         return false;
 
-    fp->pushOnScopeChain(*withobj);
+    frame.pushOnScopeChain(*withobj);
     return true;
 }
 
 /* Unwind block and scope chains to match the given depth. */
 void
 js::UnwindScope(JSContext *cx, AbstractFramePtr frame, uint32_t stackDepth)
 {
-    JS_ASSERT_IF(frame.isStackFrame(), cx->fp() == frame.asStackFrame());
-    JS_ASSERT_IF(frame.isStackFrame(), stackDepth <= cx->regs().stackDepth());
+    JS_ASSERT_IF(frame.isStackFrame(), cx->stack.fp() == frame.asStackFrame());
+    JS_ASSERT_IF(frame.isStackFrame(), stackDepth <= cx->stack.regs().stackDepth());
 
     for (ScopeIter si(frame, cx); !si.done(); ++si) {
         switch (si.type()) {
           case ScopeIter::Block:
             if (si.staticBlock().stackDepth() < stackDepth)
                 return;
             frame.popBlock(cx);
             break;
@@ -1104,17 +1097,17 @@ Interpret(JSContext *cx, StackFrame *ent
 #define SET_SCRIPT(s)                                                         \
     JS_BEGIN_MACRO                                                            \
         script = (s);                                                         \
         if (script->hasAnyBreakpointsOrStepMode() || script->hasScriptCounts) \
             interrupts.enable();                                              \
     JS_END_MACRO
 
     /* Repoint cx->regs to a local variable for faster access. */
-    FrameRegs regs = cx->regs();
+    FrameRegs regs = cx->stack.regs();
     PreserveRegsGuard interpGuard(cx, regs);
 
     /*
      * Help Debugger find frames running scripts that it has put in
      * single-step mode.
      */
     InterpreterFrames interpreterFrame(cx, &regs, interrupts);
 
@@ -1405,29 +1398,34 @@ BEGIN_CASE(JSOP_POPN)
 END_CASE(JSOP_POPN)
 
 BEGIN_CASE(JSOP_SETRVAL)
 BEGIN_CASE(JSOP_POPV)
     POP_RETURN_VALUE();
 END_CASE(JSOP_POPV)
 
 BEGIN_CASE(JSOP_ENTERWITH)
-    if (!EnterWith(cx, -1))
+{
+    RootedValue &val = rootValue0;
+    val = regs.sp[-1];
+
+    if (!EnterWith(cx, regs.fp(), val, regs.stackDepth() - 1))
         goto error;
 
     /*
      * We must ensure that different "with" blocks have different stack depth
      * associated with them. This allows the try handler search to properly
      * recover the scope chain. Thus we must keep the stack at least at the
      * current level.
      *
      * We set sp[-1] to the current "with" object to help asserting the
      * enter/leave balance in [leavewith].
      */
     regs.sp[-1].setObject(*regs.fp()->scopeChain());
+}
 END_CASE(JSOP_ENTERWITH)
 
 BEGIN_CASE(JSOP_LEAVEWITH)
     JS_ASSERT(regs.sp[-1].toObject() == *regs.fp()->scopeChain());
     regs.fp()->popWith(cx);
     regs.sp--;
 END_CASE(JSOP_LEAVEWITH)
 
@@ -1492,49 +1490,49 @@ BEGIN_CASE(JSOP_GOTO)
 {
     len = GET_JUMP_OFFSET(regs.pc);
     BRANCH(len);
 }
 END_CASE(JSOP_GOTO)
 
 BEGIN_CASE(JSOP_IFEQ)
 {
-    bool cond = ToBooleanOp(cx);
+    bool cond = ToBooleanOp(regs);
     regs.sp--;
     if (cond == false) {
         len = GET_JUMP_OFFSET(regs.pc);
         BRANCH(len);
     }
 }
 END_CASE(JSOP_IFEQ)
 
 BEGIN_CASE(JSOP_IFNE)
 {
-    bool cond = ToBooleanOp(cx);
+    bool cond = ToBooleanOp(regs);
     regs.sp--;
     if (cond != false) {
         len = GET_JUMP_OFFSET(regs.pc);
         BRANCH(len);
     }
 }
 END_CASE(JSOP_IFNE)
 
 BEGIN_CASE(JSOP_OR)
 {
-    bool cond = ToBooleanOp(cx);
+    bool cond = ToBooleanOp(regs);
     if (cond == true) {
         len = GET_JUMP_OFFSET(regs.pc);
         DO_NEXT_OP(len);
     }
 }
 END_CASE(JSOP_OR)
 
 BEGIN_CASE(JSOP_AND)
 {
-    bool cond = ToBooleanOp(cx);
+    bool cond = ToBooleanOp(regs);
     if (cond == false) {
         len = GET_JUMP_OFFSET(regs.pc);
         DO_NEXT_OP(len);
     }
 }
 END_CASE(JSOP_AND)
 
 #define FETCH_ELEMENT_ID(n, id)                                               \
@@ -1750,22 +1748,22 @@ END_CASE(JSOP_BITXOR)
 
 BEGIN_CASE(JSOP_BITAND)
     BITWISE_OP(&);
 END_CASE(JSOP_BITAND)
 
 #undef BITWISE_OP
 
 BEGIN_CASE(JSOP_EQ)
-    if (!LooseEqualityOp<true>(cx))
+    if (!LooseEqualityOp<true>(cx, regs))
         goto error;
 END_CASE(JSOP_EQ)
 
 BEGIN_CASE(JSOP_NE)
-    if (!LooseEqualityOp<false>(cx))
+    if (!LooseEqualityOp<false>(cx, regs))
         goto error;
 END_CASE(JSOP_NE)
 
 #define STRICT_EQUALITY_OP(OP, COND)                                          \
     JS_BEGIN_MACRO                                                            \
         const Value &rref = regs.sp[-1];                                      \
         const Value &lref = regs.sp[-2];                                      \
         bool equal;                                                           \
@@ -1940,17 +1938,17 @@ BEGIN_CASE(JSOP_MOD)
     if (!ModOperation(cx, script, regs.pc, lval, rval, &regs.sp[-2]))
         goto error;
     regs.sp--;
 }
 END_CASE(JSOP_MOD)
 
 BEGIN_CASE(JSOP_NOT)
 {
-    bool cond = ToBooleanOp(cx);
+    bool cond = ToBooleanOp(regs);
     regs.sp--;
     PUSH_BOOLEAN(!cond);
 }
 END_CASE(JSOP_NOT)
 
 BEGIN_CASE(JSOP_BITNOT)
 {
     int32_t i;
@@ -2080,18 +2078,19 @@ BEGIN_CASE(JSOP_THIS)
     PUSH_COPY(regs.fp()->thisValue());
 END_CASE(JSOP_THIS)
 
 BEGIN_CASE(JSOP_GETPROP)
 BEGIN_CASE(JSOP_GETXPROP)
 BEGIN_CASE(JSOP_LENGTH)
 BEGIN_CASE(JSOP_CALLPROP)
 {
+
     MutableHandleValue lval = MutableHandleValue::fromMarkedLocation(&regs.sp[-1]);
-    if (!GetPropertyOperation(cx, script, regs.pc, lval, lval))
+    if (!GetPropertyOperation(cx, regs.fp(), script, regs.pc, lval, lval))
         goto error;
 
     TypeScript::Monitor(cx, script, regs.pc, lval);
     assertSameCompartmentDebugOnly(cx, lval);
 }
 END_CASE(JSOP_GETPROP)
 
 BEGIN_CASE(JSOP_SETINTRINSIC)
@@ -2135,20 +2134,27 @@ BEGIN_CASE(JSOP_SETPROP)
 }
 END_CASE(JSOP_SETPROP)
 
 BEGIN_CASE(JSOP_GETELEM)
 BEGIN_CASE(JSOP_CALLELEM)
 {
     MutableHandleValue lval = MutableHandleValue::fromMarkedLocation(&regs.sp[-2]);
     HandleValue rval = HandleValue::fromMarkedLocation(&regs.sp[-1]);
-
     MutableHandleValue res = MutableHandleValue::fromMarkedLocation(&regs.sp[-2]);
-    if (!GetElementOperation(cx, op, lval, rval, res))
+
+    bool done = false;
+    if (!GetElemOptimizedArguments(cx, regs.fp(), lval, rval, res, &done))
         goto error;
+
+    if (!done) {
+        if (!GetElementOperation(cx, op, lval, rval, res))
+            goto error;
+    }
+
     TypeScript::Monitor(cx, script, regs.pc, res);
     regs.sp--;
 }
 END_CASE(JSOP_GETELEM)
 
 BEGIN_CASE(JSOP_SETELEM)
 {
     RootedObject &obj = rootObject0;
@@ -2190,19 +2196,23 @@ BEGIN_CASE(JSOP_EVAL)
             goto error;
     }
     regs.sp = args.spAfterCall();
     TypeScript::Monitor(cx, script, regs.pc, regs.sp[-1]);
 }
 END_CASE(JSOP_EVAL)
 
 BEGIN_CASE(JSOP_FUNAPPLY)
-    if (!GuardFunApplyArgumentsOptimization(cx))
+{
+    CallArgs args = CallArgsFromSp(GET_ARGC(regs.pc), regs.sp);
+    if (!GuardFunApplyArgumentsOptimization(cx, regs.fp(), args.calleev(), args.array(),
+                                            args.length()))
         goto error;
     /* FALL THROUGH */
+}
 
 BEGIN_CASE(JSOP_NEW)
 BEGIN_CASE(JSOP_CALL)
 BEGIN_CASE(JSOP_FUNCALL)
 {
     if (regs.fp()->hasPushedSPSFrame())
         cx->runtime()->spsProfiler.updatePC(script, regs.pc);
     JS_ASSERT(regs.stackDepth() >= 2 + GET_ARGC(regs.pc));
@@ -2988,17 +2998,17 @@ BEGIN_CASE(JSOP_LEAVEBLOCKEXPR)
 END_CASE(JSOP_LEAVEBLOCK)
 
 #if JS_HAS_GENERATORS
 BEGIN_CASE(JSOP_GENERATOR)
 {
     JS_ASSERT(!cx->isExceptionPending());
     regs.fp()->initGeneratorFrame();
     regs.pc += JSOP_GENERATOR_LENGTH;
-    JSObject *obj = js_NewGenerator(cx);
+    JSObject *obj = js_NewGenerator(cx, regs);
     if (!obj)
         goto error;
     regs.fp()->setReturnValue(ObjectValue(*obj));
     regs.fp()->setYielding();
     interpReturnOK = true;
     if (entryFrame != regs.fp())
         goto inline_return;
     goto exit;
@@ -3041,17 +3051,17 @@ END_CASE(JSOP_ARRAYPUSH)
                                  JSMSG_BAD_BYTECODE, numBuf);
             goto error;
           }
 
         } /* switch (op) */
     } /* for (;;) */
 
   error:
-    JS_ASSERT(&cx->regs() == &regs);
+    JS_ASSERT(&cx->stack.regs() == &regs);
     JS_ASSERT(uint32_t(regs.pc - script->code) < script->length);
 
     if (cx->isExceptionPending()) {
         /* Call debugger throw hooks. */
         if (cx->compartment()->debugMode()) {
             JSTrapStatus status = DebugExceptionUnwind(cx, regs.fp(), regs.pc);
             switch (status) {
               case JSTRAP_ERROR:
@@ -3068,17 +3078,17 @@ END_CASE(JSOP_ARRAYPUSH)
               default:
                 JS_NOT_REACHED("Invalid trap status");
             }
         }
 
         for (TryNoteIter tni(cx, regs); !tni.done(); ++tni) {
             JSTryNote *tn = *tni;
 
-            UnwindScope(cx, cx->fp(), tn->stackDepth);
+            UnwindScope(cx, regs.fp(), tn->stackDepth);
 
             /*
              * Set pc to the first bytecode after the the try note to point
              * to the beginning of catch or finally or to [enditer] closing
              * the for-in loop.
              */
             regs.pc = (script)->main() + tn->start + tn->length;
             regs.sp = regs.spForStackDepth(tn->stackDepth);
@@ -3143,17 +3153,17 @@ END_CASE(JSOP_ARRAYPUSH)
         }
 #endif
     } else {
         UnwindForUncatchableException(cx, regs);
         interpReturnOK = false;
     }
 
   forced_return:
-    UnwindScope(cx, cx->fp(), 0);
+    UnwindScope(cx, regs.fp(), 0);
     regs.setToEndOfScript();
 
     if (entryFrame != regs.fp())
         goto inline_return;
 
   exit:
     if (cx->compartment()->debugMode())
         interpReturnOK = ScriptDebugEpilogue(cx, regs.fp(), interpReturnOK);
@@ -3243,21 +3253,25 @@ js::Lambda(JSContext *cx, HandleFunction
 {
     RootedObject clone(cx, CloneFunctionObjectIfNotSingleton(cx, fun, parent, TenuredObject));
     if (!clone)
         return NULL;
 
     if (fun->isArrow()) {
         // Note that this will assert if called from Ion code. Ion can't yet
         // emit code for a bound arrow function (bug 851913).
-        AbstractFramePtr frame = cx->fp();
+        AbstractFramePtr frame;
+        if (cx->currentlyRunningInInterpreter()) {
+            frame = cx->interpreterFrame();
+        } else {
 #ifdef JS_ION
-        if (cx->mainThread().currentlyRunningInJit())
+            JS_ASSERT(cx->currentlyRunningInJit());
             frame = ion::GetTopBaselineFrame(cx);
 #endif
+        }
 
         if (!ComputeThis(cx, frame))
             return NULL;
 
         RootedValue thisval(cx, frame.thisValue());
         clone = js_fun_bind(cx, clone, thisval, NULL, 0);
         if (!clone)
             return NULL;
@@ -3283,18 +3297,17 @@ js::DefFunOperation(JSContext *cx, Handl
      */
     RootedFunction fun(cx, funArg);
     if (fun->isNative() || fun->environment() != scopeChain) {
         fun = CloneFunctionObjectIfNotSingleton(cx, fun, scopeChain, TenuredObject);
         if (!fun)
             return false;
     } else {
         JS_ASSERT(script->compileAndGo);
-        JS_ASSERT_IF(cx->mainThread().currentlyRunningInInterpreter(),
-                     cx->fp()->isGlobalFrame() || cx->fp()->isEvalInFunction());
+        JS_ASSERT(!script->function());
     }
 
     /*
      * We define the function as a property of the variable object and not the
      * current scope chain even for the case of function expression statements
      * and functions defined by eval inside let or with blocks.
      */
     RootedObject parent(cx, scopeChain);
--- a/js/src/vm/ObjectImpl.h
+++ b/js/src/vm/ObjectImpl.h
@@ -1625,17 +1625,17 @@ DefineElement(JSContext *cx, Handle<Obje
 extern bool
 SetElement(JSContext *cx, Handle<ObjectImpl*> obj, Handle<ObjectImpl*> receiver, uint32_t index,
            const Value &v, unsigned resolveFlags, bool *succeeded);
 
 extern bool
 HasElement(JSContext *cx, Handle<ObjectImpl*> obj, uint32_t index, unsigned resolveFlags,
            bool *found);
 
-template <> struct RootMethods<PropertyId>
+template <> struct GCMethods<PropertyId>
 {
     static PropertyId initial() { return PropertyId(); }
     static ThingRootKind kind() { return THING_ROOT_PROPERTY_ID; }
     static bool poisoned(PropertyId propid) { return IsPoisonedId(propid.asId()); }
 };
 
 } /* namespace js */
 
--- a/js/src/vm/ScopeObject.cpp
+++ b/js/src/vm/ScopeObject.cpp
@@ -282,18 +282,18 @@ CallObject::createForFunction(JSContext 
 
     return callobj;
 }
 
 CallObject *
 CallObject::createForStrictEval(JSContext *cx, AbstractFramePtr frame)
 {
     JS_ASSERT(frame.isStrictEvalFrame());
-    JS_ASSERT_IF(frame.isStackFrame(), cx->fp() == frame.asStackFrame());
-    JS_ASSERT_IF(frame.isStackFrame(), cx->regs().pc == frame.script()->code);
+    JS_ASSERT_IF(frame.isStackFrame(), cx->interpreterFrame() == frame.asStackFrame());
+    JS_ASSERT_IF(frame.isStackFrame(), cx->interpreterRegs().pc == frame.script()->code);
 
     RootedFunction callee(cx);
     RootedScript script(cx, frame.script());
     RootedObject scopeChain(cx, frame.scopeChain());
     return create(cx, script, scopeChain, callee);
 }
 
 Class CallObject::class_ = {
--- a/js/src/vm/Stack-inl.h
+++ b/js/src/vm/Stack-inl.h
@@ -69,17 +69,17 @@ StackFrame::compartment() const
     JS_ASSERT(scopeChain()->compartment() == script()->compartment());
     return scopeChain()->compartment();
 }
 
 inline void
 StackFrame::initPrev(JSContext *cx)
 {
     JS_ASSERT(flags_ & HAS_PREVPC);
-    if (FrameRegs *regs = cx->maybeRegs()) {
+    if (FrameRegs *regs = cx->stack.maybeRegs()) {
         prev_ = regs->fp();
         prevpc_ = regs->pc;
         JS_ASSERT(uint32_t(prevpc_ - prev_->script()->code) < prev_->script()->length);
     } else {
         prev_ = NULL;
 #ifdef DEBUG
         prevpc_ = (jsbytecode *)0xbadc;
 #endif
@@ -448,16 +448,30 @@ AbstractFramePtr::scopeChain() const
         return asStackFrame()->scopeChain();
 #ifdef JS_ION
     return asBaselineFrame()->scopeChain();
 #else
     JS_NOT_REACHED("Invalid frame");
 #endif
 }
 
+inline void
+AbstractFramePtr::pushOnScopeChain(ScopeObject &scope)
+{
+    if (isStackFrame()) {
+        asStackFrame()->pushOnScopeChain(scope);
+        return;
+    }
+#ifdef JS_ION
+    asBaselineFrame()->pushOnScopeChain(scope);
+#else
+    JS_NOT_REACHED("Invalid frame");
+#endif
+}
+
 inline CallObject &
 AbstractFramePtr::callObj() const
 {
     if (isStackFrame())
         return asStackFrame()->callObj();
 #ifdef JS_ION
     return asBaselineFrame()->callObj();
 #else
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -283,17 +283,17 @@ StackFrame::initFunctionScopeObjects(JSC
 }
 
 bool
 StackFrame::prologue(JSContext *cx)
 {
     RootedScript script(cx, this->script());
 
     JS_ASSERT(!isGeneratorFrame());
-    JS_ASSERT(cx->regs().pc == script->code);
+    JS_ASSERT(cx->interpreterRegs().pc == script->code);
 
     if (isEvalFrame()) {
         if (script->strict) {
             CallObject *callobj = CallObject::createForStrictEval(cx, this);
             if (!callobj)
                 return false;
             pushOnScopeChain(*callobj);
             flags_ |= HAS_CALL_OBJ;
@@ -800,17 +800,17 @@ ContextStack::onTop() const
  * Additionally, to minimize calls to ensureSpace, ensureOnTop ensures that
  * there is space for nvars slots on top of the stack.
  */
 Value *
 ContextStack::ensureOnTop(JSContext *cx, MaybeReportError report, unsigned nvars,
                           MaybeExtend extend, bool *pushedSeg)
 {
     Value *firstUnused = space().firstUnused();
-    FrameRegs *regs = cx->maybeRegs();
+    FrameRegs *regs = cx->stack.maybeRegs();
 
     if (onTop() && extend) {
         if (!space().ensureSpace(cx, report, firstUnused, nvars))
             return NULL;
         return firstUnused;
     }
 
     if (!space().ensureSpace(cx, report, firstUnused, VALUES_PER_STACK_SEGMENT + nvars))
@@ -1767,18 +1767,18 @@ ScriptFrameIter::numFrameSlots() const
         ion::BaselineFrame *frame = data_.ionFrames_.baselineFrame();
         return frame->numValueSlots() - data_.ionFrames_.script()->nfixed;
 #else
         break;
 #endif
       }
       case SCRIPTED:
         JS_ASSERT(data_.cx_);
-        JS_ASSERT(data_.cx_->regs().spForStackDepth(0) == interpFrame()->base());
-        return data_.cx_->regs().sp - interpFrame()->base();
+        JS_ASSERT(data_.cx_->stack.regs().spForStackDepth(0) == interpFrame()->base());
+        return data_.cx_->stack.regs().sp - interpFrame()->base();
     }
     JS_NOT_REACHED("Unexpected state");
     return 0;
 }
 
 Value
 ScriptFrameIter::frameSlotValue(size_t index) const
 {
--- a/js/src/vm/Stack.h
+++ b/js/src/vm/Stack.h
@@ -178,16 +178,18 @@ class AbstractFramePtr
 
     operator bool() const { return !!ptr_; }
 
     inline JSGenerator *maybeSuspendedGenerator(JSRuntime *rt) const;
 
     inline JSObject *scopeChain() const;
     inline CallObject &callObj() const;
     inline bool initFunctionScopeObjects(JSContext *cx);
+    inline void pushOnScopeChain(ScopeObject &scope);
+
     inline JSCompartment *compartment() const;
 
     inline StaticBlockObject *maybeBlockChain() const;
     inline bool hasCallObj() const;
     inline bool isGeneratorFrame() const;
     inline bool isYielding() const;
     inline bool isFunctionFrame() const;
     inline bool isGlobalFrame() const;
@@ -1600,16 +1602,19 @@ class InterpreterActivation : public Act
 
         current_ = frame->prev();
         JS_ASSERT(current_);
     }
     StackFrame *current() const {
         JS_ASSERT(current_);
         return current_;
     }
+    FrameRegs &regs() const {
+        return regs_;
+    }
 };
 
 // Iterates over a runtime's activation list.
 class ActivationIterator
 {
     uint8_t *jitTop_;
 
   protected:
--- a/js/src/vm/String.h
+++ b/js/src/vm/String.h
@@ -614,17 +614,17 @@ class Rooted<JSStableString *>
     JSStableString ** address() { return reinterpret_cast<JSStableString **>(rooter.addr()); }
     JSStableString * const * address() const {
         return reinterpret_cast<JSStableString * const *>(rooter.addr());
     }
     JSStableString * get() const { return static_cast<JSStableString *>(rooter.string()); }
 
     Rooted & operator =(JSStableString *value)
     {
-        JS_ASSERT(!js::RootMethods<JSStableString *>::poisoned(value));
+        JS_ASSERT(!js::GCMethods<JSStableString *>::poisoned(value));
         rooter.setString(value);
         return *this;
     }
 
     Rooted & operator =(const Rooted &value)
     {
         rooter.setString(value.get());
         return *this;
--- a/js/xpconnect/shell/xpcshell.cpp
+++ b/js/xpconnect/shell/xpcshell.cpp
@@ -79,16 +79,17 @@
 #include <unistd.h>     /* for isatty() */
 #endif
 
 #ifdef MOZ_CRASHREPORTER
 #include "nsICrashReporter.h"
 #endif
 
 using namespace mozilla;
+using namespace JS;
 
 class XPCShellDirProvider : public nsIDirectoryServiceProvider2
 {
 public:
     NS_DECL_ISUPPORTS_INHERITED
     NS_DECL_NSIDIRECTORYSERVICEPROVIDER
     NS_DECL_NSIDIRECTORYSERVICEPROVIDER2
 
@@ -140,17 +141,17 @@ int gExitCode = 0;
 JSBool gQuitting = false;
 static JSBool reportWarnings = true;
 static JSBool compileOnly = false;
 
 JSPrincipals *gJSPrincipals = nullptr;
 nsAutoString *gWorkingDirectory = nullptr;
 
 static JSBool
-GetLocationProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, JSMutableHandleValue vp)
+GetLocationProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, MutableHandleValue vp)
 {
 #if !defined(XP_WIN) && !defined(XP_UNIX)
     //XXX: your platform should really implement this
     return false;
 #else
     JSScript *script;
     JS_DescribeScriptedCaller(cx, &script, NULL);
     const char *filename = JS_GetScriptFilename(cx, script);
@@ -846,17 +847,17 @@ static const JSFunctionSpec glob_functio
 
 JSClass global_class = {
     "global", 0,
     JS_PropertyStub,  JS_DeletePropertyStub,  JS_PropertyStub,  JS_StrictPropertyStub,
     JS_EnumerateStub, JS_ResolveStub,   JS_ConvertStub,   nullptr
 };
 
 static JSBool
-env_setProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, JSMutableHandleValue vp)
+env_setProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, MutableHandleValue vp)
 {
 /* XXX porting may be easy, but these don't seem to supply setenv by default */
 #if !defined XP_OS2 && !defined SOLARIS
     JSString *valstr;
     JS::Rooted<JSString*> idstr(cx);
     int rv;
 
     jsval idval;
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -2955,17 +2955,17 @@ sandbox_finalize(JSFreeOp *fop, JSObject
         static_cast<nsIScriptObjectPrincipal *>(xpc_GetJSPrivate(obj));
     MOZ_ASSERT(sop);
     static_cast<SandboxPrivate *>(sop)->ForgetGlobalObject();
     NS_IF_RELEASE(sop);
     DestroyProtoAndIfaceCache(obj);
 }
 
 static JSBool
-sandbox_convert(JSContext *cx, JSHandleObject obj, JSType type, JSMutableHandleValue vp)
+sandbox_convert(JSContext *cx, JSHandleObject obj, JSType type, MutableHandleValue vp)
 {
     if (type == JSTYPE_OBJECT) {
         vp.set(OBJECT_TO_JSVAL(obj));
         return true;
     }
 
     return JS_ConvertStub(cx, obj, type, vp);
 }
@@ -3121,19 +3121,19 @@ bool BindPropertyOp(JSContext *cx, Op &o
     if (!func)
         return false;
     op = JS_DATA_TO_FUNC_PTR(Op, func.get());
     desc->attrs |= attrFlag;
     return true;
 }
 
 extern JSBool
-XPC_WN_Helper_GetProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, JSMutableHandleValue vp);
+XPC_WN_Helper_GetProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, MutableHandleValue vp);
 extern JSBool
-XPC_WN_Helper_SetProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, JSMutableHandleValue vp);
+XPC_WN_Helper_SetProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, MutableHandleValue vp);
 
 bool
 xpc::SandboxProxyHandler::getPropertyDescriptor(JSContext *cx,
                                                 JS::Handle<JSObject*> proxy,
                                                 JS::Handle<jsid> id,
                                                 PropertyDescriptor *desc,
                                                 unsigned flags)
 {
@@ -4823,17 +4823,17 @@ nsXPCComponents::SetProperty(nsIXPConnec
         return NS_ERROR_FAILURE;
     }
 
     return NS_ERROR_XPC_CANT_MODIFY_PROP_ON_WN;
 }
 
 static JSBool
 ContentComponentsGetterOp(JSContext *cx, JSHandleObject obj, JSHandleId id,
-                          JSMutableHandleValue vp)
+                          MutableHandleValue vp)
 {
     // If chrome is accessing the Components object of content, allow.
     MOZ_ASSERT(nsContentUtils::GetCurrentJSContext() == cx);
     if (nsContentUtils::IsCallerChrome())
         return true;
 
     // If the caller is XBL, this is ok.
     if (nsContentUtils::IsCallerXBL())
--- a/js/xpconnect/src/XPCLocale.cpp
+++ b/js/xpconnect/src/XPCLocale.cpp
@@ -17,16 +17,18 @@
 #include "nsIPlatformCharset.h"
 #include "nsILocaleService.h"
 #include "nsICollation.h"
 #include "nsIServiceManager.h"
 #include "nsUnicharUtils.h"
 
 #include "xpcpublic.h"
 
+using namespace JS;
+
 /**
  * JS locale callbacks implemented by XPCOM modules.  These are theoretically
  * safe for use on multiple threads.  Unfortunately, the intl code underlying
  * these XPCOM modules doesn't yet support this, so in practice
  * XPCLocaleCallbacks are limited to the main thread.
  */
 struct XPCLocaleCallbacks : public JSLocaleCallbacks
 {
@@ -67,42 +69,42 @@ struct XPCLocaleCallbacks : public JSLoc
     MOZ_ASSERT(lc->localeToUnicode == LocaleToUnicode);
 
     XPCLocaleCallbacks* ths = static_cast<XPCLocaleCallbacks*>(lc);
     ths->AssertThreadSafety();
     return ths;
   }
 
   static JSBool
-  LocaleToUpperCase(JSContext *cx, JSHandleString src, JSMutableHandleValue rval)
+  LocaleToUpperCase(JSContext *cx, JSHandleString src, MutableHandleValue rval)
   {
     return ChangeCase(cx, src, rval, ToUpperCase);
   }
 
   static JSBool
-  LocaleToLowerCase(JSContext *cx, JSHandleString src, JSMutableHandleValue rval)
+  LocaleToLowerCase(JSContext *cx, JSHandleString src, MutableHandleValue rval)
   {
     return ChangeCase(cx, src, rval, ToLowerCase);
   }
 
   static JSBool
-  LocaleToUnicode(JSContext* cx, const char* src, JSMutableHandleValue rval)
+  LocaleToUnicode(JSContext* cx, const char* src, MutableHandleValue rval)
   {
     return This(JS_GetRuntime(cx))->ToUnicode(cx, src, rval);
   }
 
   static JSBool
-  LocaleCompare(JSContext *cx, JSHandleString src1, JSHandleString src2, JSMutableHandleValue rval)
+  LocaleCompare(JSContext *cx, JSHandleString src1, JSHandleString src2, MutableHandleValue rval)
   {
     return This(JS_GetRuntime(cx))->Compare(cx, src1, src2, rval);
   }
 
 private:
   static JSBool
-  ChangeCase(JSContext* cx, JSHandleString src, JSMutableHandleValue rval,
+  ChangeCase(JSContext* cx, JSHandleString src, MutableHandleValue rval,
              void(*changeCaseFnc)(const nsAString&, nsAString&))
   {
     nsDependentJSString depStr;
     if (!depStr.init(cx, src)) {
       return false;
     }
 
     nsAutoString result;
@@ -114,17 +116,17 @@ private:
       return false;
     }
 
     rval.set(STRING_TO_JSVAL(ucstr));
     return true;
   }
 
   JSBool
-  Compare(JSContext *cx, JSHandleString src1, JSHandleString src2, JSMutableHandleValue rval)
+  Compare(JSContext *cx, JSHandleString src1, JSHandleString src2, MutableHandleValue rval)
   {
     nsresult rv;
 
     if (!mCollation) {
       nsCOMPtr<nsILocaleService> localeService =
         do_GetService(NS_LOCALESERVICE_CONTRACTID, &rv);
 
       if (NS_SUCCEEDED(rv)) {
@@ -161,17 +163,17 @@ private:
       return false;
     }
 
     rval.set(INT_TO_JSVAL(result));
     return true;
   }
 
   JSBool
-  ToUnicode(JSContext* cx, const char* src, JSMutableHandleValue rval)
+  ToUnicode(JSContext* cx, const char* src, MutableHandleValue rval)
   {
     nsresult rv;
 
     if (!mDecoder) {
       // use app default locale
       nsCOMPtr<nsILocaleService> localeService =
         do_GetService(NS_LOCALESERVICE_CONTRACTID, &rv);
       if (NS_SUCCEEDED(rv)) {
--- a/js/xpconnect/src/XPCQuickStubs.cpp
+++ b/js/xpconnect/src/XPCQuickStubs.cpp
@@ -390,17 +390,17 @@ void
 xpc_qsThrowBadSetterValue(JSContext *cx, nsresult rv, JSObject *obj,
                           uint16_t name_index)
 {
     xpc_qsThrowBadSetterValue(cx, rv, obj, xpc_qsStringTable + name_index);
 }
 
 JSBool
 xpc_qsGetterOnlyPropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict,
-                             JSMutableHandleValue vp)
+                             MutableHandleValue vp)
 {
     return JS_ReportErrorFlagsAndNumber(cx,
                                         JSREPORT_WARNING | JSREPORT_STRICT |
                                         JSREPORT_STRICT_MODE_ERROR,
                                         js_GetErrorMessage, NULL,
                                         JSMSG_GETTER_ONLY);
 }
 
--- a/js/xpconnect/src/XPCQuickStubs.h
+++ b/js/xpconnect/src/XPCQuickStubs.h
@@ -126,17 +126,17 @@ void
 xpc_qsThrowBadSetterValue(JSContext *cx, nsresult rv, JSObject *obj,
                           const char* propName);
 void
 xpc_qsThrowBadSetterValue(JSContext *cx, nsresult rv, JSObject *obj,
                           uint16_t name_index);
 
 
 JSBool
-xpc_qsGetterOnlyPropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, JSMutableHandleValue vp);
+xpc_qsGetterOnlyPropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, JS::MutableHandleValue vp);
 
 JSBool
 xpc_qsGetterOnlyNativeStub(JSContext *cx, unsigned argc, jsval *vp);
 
 /* Functions for converting values between COM and JS. */
 
 inline JSBool
 xpc_qsInt64ToJsval(JSContext *cx, int64_t i, jsval *rv)
@@ -564,29 +564,29 @@ xpc_qsSameResult(int32_t result1, int32_
 
 #define XPC_QS_ASSERT_CONTEXT_OK(cx) xpc_qsAssertContextOK(cx)
 #else
 #define XPC_QS_ASSERT_CONTEXT_OK(cx) ((void) 0)
 #endif
 
 // Apply |op| to |obj|, |id|, and |vp|. If |op| is a setter, treat the assignment as lenient.
 template<typename Op>
-inline JSBool ApplyPropertyOp(JSContext *cx, Op op, JSHandleObject obj, JSHandleId id, JSMutableHandleValue vp);
+inline JSBool ApplyPropertyOp(JSContext *cx, Op op, JSHandleObject obj, JSHandleId id, JS::MutableHandleValue vp);
 
 template<>
 inline JSBool
-ApplyPropertyOp<JSPropertyOp>(JSContext *cx, JSPropertyOp op, JSHandleObject obj, JSHandleId id, JSMutableHandleValue vp)
+ApplyPropertyOp<JSPropertyOp>(JSContext *cx, JSPropertyOp op, JSHandleObject obj, JSHandleId id, JS::MutableHandleValue vp)
 {
     return op(cx, obj, id, vp);
 }
 
 template<>
 inline JSBool
 ApplyPropertyOp<JSStrictPropertyOp>(JSContext *cx, JSStrictPropertyOp op, JSHandleObject obj,
-                                    JSHandleId id, JSMutableHandleValue vp)
+                                    JSHandleId id, JS::MutableHandleValue vp)
 {
     return op(cx, obj, id, true, vp);
 }
 
 template<typename Op>
 JSBool
 PropertyOpForwarder(JSContext *cx, unsigned argc, jsval *vp)
 {
--- a/js/xpconnect/src/XPCWrappedNativeJSOps.cpp
+++ b/js/xpconnect/src/XPCWrappedNativeJSOps.cpp
@@ -425,59 +425,59 @@ DefinePropertyIfFound(XPCCallContext& cc
     return JS_DefinePropertyById(ccx, obj, id, JSVAL_VOID, getter, setter,
                                  propFlags);
 }
 
 /***************************************************************************/
 /***************************************************************************/
 
 static JSBool
-XPC_WN_OnlyIWrite_AddPropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, JSMutableHandleValue vp)
+XPC_WN_OnlyIWrite_AddPropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, MutableHandleValue vp)
 {
     XPCCallContext ccx(JS_CALLER, cx, obj, NullPtr(), id);
     XPCWrappedNative* wrapper = ccx.GetWrapper();
     THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
 
     // Allow only XPConnect to add/set the property
     if (ccx.GetResolveName() == id)
         return true;
 
     return Throw(NS_ERROR_XPC_CANT_MODIFY_PROP_ON_WN, cx);
 }
 
 static JSBool
 XPC_WN_OnlyIWrite_SetPropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict,
-                                  JSMutableHandleValue vp)
+                                  MutableHandleValue vp)
 {
     return XPC_WN_OnlyIWrite_AddPropertyStub(cx, obj, id, vp);
 }
 
 static JSBool
 XPC_WN_CannotModifyPropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id,
-                                JSMutableHandleValue vp)
+                                MutableHandleValue vp)
 {
     return Throw(NS_ERROR_XPC_CANT_MODIFY_PROP_ON_WN, cx);
 }
 
 static JSBool
 XPC_WN_CantDeletePropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id,
                               JSBool *succeeded)
 {
     return Throw(NS_ERROR_XPC_CANT_MODIFY_PROP_ON_WN, cx);
 }
 
 static JSBool
 XPC_WN_CannotModifyStrictPropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict,
-                                      JSMutableHandleValue vp)
+                                      MutableHandleValue vp)
 {
     return XPC_WN_CannotModifyPropertyStub(cx, obj, id, vp);
 }
 
 static JSBool
-XPC_WN_Shared_Convert(JSContext *cx, JSHandleObject obj, JSType type, JSMutableHandleValue vp)
+XPC_WN_Shared_Convert(JSContext *cx, JSHandleObject obj, JSType type, MutableHandleValue vp)
 {
     if (type == JSTYPE_OBJECT) {
         vp.set(OBJECT_TO_JSVAL(obj));
         return true;
     }
 
     XPCCallContext ccx(JS_CALLER, cx, obj);
     XPCWrappedNative* wrapper = ccx.GetWrapper();
@@ -751,30 +751,30 @@ XPCWrappedNativeJSClass XPC_WN_NoHelper_
   },
   0 // interfacesBitmap
 };
 
 
 /***************************************************************************/
 
 static JSBool
-XPC_WN_MaybeResolvingPropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, JSMutableHandleValue vp)
+XPC_WN_MaybeResolvingPropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, MutableHandleValue vp)
 {
     XPCCallContext ccx(JS_CALLER, cx, obj);
     XPCWrappedNative* wrapper = ccx.GetWrapper();
     THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
 
     if (ccx.GetResolvingWrapper() == wrapper)
         return true;
     return Throw(NS_ERROR_XPC_CANT_MODIFY_PROP_ON_WN, cx);
 }
 
 static JSBool
 XPC_WN_MaybeResolvingStrictPropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict,
-                                        JSMutableHandleValue vp)
+                                        MutableHandleValue vp)
 {
     return XPC_WN_MaybeResolvingPropertyStub(cx, obj, id, vp);
 }
 
 static JSBool
 XPC_WN_MaybeResolvingDeletePropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool *succeeded)
 {
     XPCCallContext ccx(JS_CALLER, cx, obj);
@@ -805,17 +805,17 @@ XPC_WN_MaybeResolvingDeletePropertyStub(
 
 #define POST_HELPER_STUB                                                      \
     if (NS_FAILED(rv))                                                        \
         return Throw(rv, cx);                                                 \
     return retval;
 
 static JSBool
 XPC_WN_Helper_AddProperty(JSContext *cx, JSHandleObject obj, JSHandleId id,
-                          JSMutableHandleValue vp)
+                          MutableHandleValue vp)
 {
     PRE_HELPER_STUB
     AddProperty(wrapper, cx, obj, id, vp.address(), &retval);
     POST_HELPER_STUB
 }
 
 static JSBool
 XPC_WN_Helper_DelProperty(JSContext *cx, JSHandleObject obj, JSHandleId id,
@@ -823,43 +823,43 @@ XPC_WN_Helper_DelProperty(JSContext *cx,
 {
     PRE_HELPER_STUB
     DelProperty(wrapper, cx, obj, id, &retval);
     POST_HELPER_STUB
 }
 
 JSBool
 XPC_WN_Helper_GetProperty(JSContext *cx, JSHandleObject obj, JSHandleId id,
-                          JSMutableHandleValue vp)
+                          MutableHandleValue vp)
 {
     PRE_HELPER_STUB
     GetProperty(wrapper, cx, obj, id, vp.address(), &retval);
     POST_HELPER_STUB
 }
 
 JSBool
 XPC_WN_Helper_SetProperty(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict,
-                          JSMutableHandleValue vp)
+                          MutableHandleValue vp)
 {
     PRE_HELPER_STUB
     SetProperty(wrapper, cx, obj, id, vp.address(), &retval);
     POST_HELPER_STUB
 }
 
 static JSBool
-XPC_WN_Helper_Convert(JSContext *cx, JSHandleObject obj, JSType type, JSMutableHandleValue vp)
+XPC_WN_Helper_Convert(JSContext *cx, JSHandleObject obj, JSType type, MutableHandleValue vp)
 {
     PRE_HELPER_STUB
     Convert(wrapper, cx, obj, type, vp.address(), &retval);
     POST_HELPER_STUB
 }
 
 static JSBool
 XPC_WN_Helper_CheckAccess(JSContext *cx, JSHandleObject obj, JSHandleId id,
-                          JSAccessMode mode, JSMutableHandleValue vp)
+                          JSAccessMode mode, MutableHandleValue vp)
 {
     PRE_HELPER_STUB
     CheckAccess(wrapper, cx, obj, id, mode, vp.address(), &retval);
     POST_HELPER_STUB
 }
 
 static JSBool
 XPC_WN_Helper_Call(JSContext *cx, unsigned argc, jsval *vp)
@@ -896,17 +896,17 @@ XPC_WN_Helper_Construct(JSContext *cx, u
     MOZ_ASSERT(obj == ccx.GetFlattenedJSObject());
 
     PRE_HELPER_STUB
     Construct(wrapper, cx, obj, args, &retval);
     POST_HELPER_STUB
 }
 
 static JSBool
-XPC_WN_Helper_HasInstance(JSContext *cx, JSHandleObject obj, JSMutableHandleValue valp, JSBool *bp)
+XPC_WN_Helper_HasInstance(JSContext *cx, JSHandleObject obj, MutableHandleValue valp, JSBool *bp)
 {
     bool retval2;
     PRE_HELPER_STUB
     HasInstance(wrapper, cx, obj, valp, &retval2, &retval);
     *bp = retval2;
     POST_HELPER_STUB
 }
 
@@ -1030,17 +1030,17 @@ XPC_WN_Helper_NewResolve(JSContext *cx, 
         if ( DONT_ENUM_STATICS )
             use enumerate stub - don't use this JSOp thing at all
         else
             do shared enumerate - don't use this JSOp thing at all
 */
 
 JSBool
 XPC_WN_JSOp_Enumerate(JSContext *cx, JSHandleObject obj, JSIterateOp enum_op,
-                      JSMutableHandleValue statep, MutableHandleId idp)
+                      MutableHandleValue statep, MutableHandleId idp)
 {
     js::Class *clazz = js::GetObjectClass(obj);
     if (!IS_WN_CLASS(clazz) || clazz == &XPC_WN_NoHelper_JSClass.base) {
         // obj must be a prototype object or a wrapper w/o a
         // helper. Short circuit this call to the default
         // implementation.
 
         return JS_EnumerateState(cx, obj, enum_op, statep, idp);
@@ -1525,17 +1525,17 @@ js::Class XPC_WN_ModsAllowed_NoCall_Prot
     JS_NULL_CLASS_EXT,
     XPC_WN_NoCall_ObjectOps
 };
 
 /***************************************************************************/
 
 static JSBool
 XPC_WN_OnlyIWrite_Proto_AddPropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id,
-                                        JSMutableHandleValue vp)
+                                        MutableHandleValue vp)
 {
     NS_ASSERTION(js::GetObjectClass(obj) == &XPC_WN_NoMods_WithCall_Proto_JSClass ||
                  js::GetObjectClass(obj) == &XPC_WN_NoMods_NoCall_Proto_JSClass,
                  "bad proto");
 
     XPCWrappedNativeProto* self =
         (XPCWrappedNativeProto*) xpc_GetJSPrivate(obj);
     if (!self)
@@ -1549,17 +1549,17 @@ XPC_WN_OnlyIWrite_Proto_AddPropertyStub(
     if (ccx.GetResolveName() == id)
         return true;
 
     return Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO, cx);
 }
 
 static JSBool
 XPC_WN_OnlyIWrite_Proto_SetPropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict,
-                                        JSMutableHandleValue vp)
+                                        MutableHandleValue vp)
 {
     return XPC_WN_OnlyIWrite_Proto_AddPropertyStub(cx, obj, id, vp);
 }
 
 static JSBool
 XPC_WN_NoMods_Proto_Resolve(JSContext *cx, JSHandleObject obj, JSHandleId id)
 {
     NS_ASSERTION(js::GetObjectClass(obj) == &XPC_WN_NoMods_WithCall_Proto_JSClass ||
--- a/js/xpconnect/src/dom_quickstubs.qsconf
+++ b/js/xpconnect/src/dom_quickstubs.qsconf
@@ -55,24 +55,16 @@ members = [
 
     'nsIDOMProgressEvent.lengthComputable',
     'nsIDOMProgressEvent.loaded',
     'nsIDOMProgressEvent.total',
     #XXX Can't quickstub initProgressEvent because it has long long parameters.
 
     'nsIDOMTouchList.*',
 
-    # dom/interfaces/html
-    'nsIDOMHTMLFormElement.elements',
-    'nsIDOMHTMLFormElement.name',
-    'nsIDOMHTMLFormElement.submit',
-    'nsIDOMHTMLFormElement.length',
-    'nsIDOMHTMLFormElement.target',
-    'nsIDOMHTMLFormElement.action',
-
     # dom/interfaces/storage
     'nsIDOMToString.toString',
     'nsIDOMStorage.setItem',
     'nsIDOMStorage.length',
     'nsIDOMStorage.getItem',
     'nsIDOMStorage.key',
     'nsIDOMStorage.removeItem',
     'nsIDOMStorage.clear',
--- a/js/xpconnect/src/nsDOMQS.h
+++ b/js/xpconnect/src/nsDOMQS.h
@@ -3,17 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsDOMQS_h__
 #define nsDOMQS_h__
 
 #include "nsDOMClassInfoID.h"
 #include "nsGenericHTMLElement.h"
 #include "mozilla/dom/HTMLCanvasElement.h"
-#include "nsHTMLFormElement.h"
+#include "mozilla/dom/HTMLFormElement.h"
 #include "mozilla/dom/HTMLImageElement.h"
 #include "mozilla/dom/HTMLOptionElement.h"
 #include "HTMLOptGroupElement.h"
 #include "mozilla/dom/HTMLVideoElement.h"
 #include "nsHTMLDocument.h"
 #include "nsICSSDeclaration.h"
 #include "nsSVGElement.h"
 #include "nsDOMEvent.h"
@@ -226,17 +226,17 @@ UnwrapArg<_clazz>(JSContext *cx, jsval v
 {                                                                             \
     return xpc_qsUnwrapArg<_clazz>(cx, v, ppArg, ppArgRef, vp);               \
 }                                                                             \
                                                                               \
 } /* namespace dom */                                                         \
 } /* namespace mozilla */
 
 DEFINE_UNWRAP_CAST_HTML(canvas, mozilla::dom::HTMLCanvasElement)
-DEFINE_UNWRAP_CAST_HTML(form, nsHTMLFormElement)
+DEFINE_UNWRAP_CAST_HTML(form, mozilla::dom::HTMLFormElement)
 DEFINE_UNWRAP_CAST_HTML(img, mozilla::dom::HTMLImageElement)
 DEFINE_UNWRAP_CAST_HTML(optgroup, mozilla::dom::HTMLOptGroupElement)
 DEFINE_UNWRAP_CAST_HTML(option, mozilla::dom::HTMLOptionElement)
 DEFINE_UNWRAP_CAST_HTML(video, mozilla::dom::HTMLVideoElement)
 
 inline nsISupports*
 ToSupports(nsContentList *p)
 {
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -1197,17 +1197,17 @@ extern js::Class XPC_WN_NoHelper_Proto_J
 extern JSBool
 XPC_WN_CallMethod(JSContext *cx, unsigned argc, jsval *vp);
 
 extern JSBool
 XPC_WN_GetterSetter(JSContext *cx, unsigned argc, jsval *vp);
 
 extern JSBool
 XPC_WN_JSOp_Enumerate(JSContext *cx, JSHandleObject obj, JSIterateOp enum_op,
-                      JSMutableHandleValue statep, JS::MutableHandleId idp);
+                      JS::MutableHandleValue statep, JS::MutableHandleId idp);
 
 extern JSObject*
 XPC_WN_JSOp_ThisObject(JSContext *cx, JSHandleObject obj);
 
 // Macros to initialize Object or Function like XPC_WN classes
 #define XPC_WN_WithCall_ObjectOps                                             \
     {                                                                         \
         nullptr, /* lookupGeneric */                                          \
--- a/js/xpconnect/wrappers/XrayWrapper.h
+++ b/js/xpconnect/wrappers/XrayWrapper.h
@@ -17,19 +17,19 @@
 // we pull them out of the Wrapper inheritance hierarchy and create a
 // little world around them.
 
 class XPCWrappedNative;
 
 namespace xpc {
 
 JSBool
-holder_get(JSContext *cx, JSHandleObject holder, JSHandleId id, JSMutableHandleValue vp);
+holder_get(JSContext *cx, JSHandleObject holder, JSHandleId id, JS::MutableHandleValue vp);
 JSBool
-holder_set(JSContext *cx, JSHandleObject holder, JSHandleId id, JSBool strict, JSMutableHandleValue vp);
+holder_set(JSContext *cx, JSHandleObject holder, JSHandleId id, JSBool strict, JS::MutableHandleValue vp);
 
 namespace XrayUtils {
 
 extern JSClass HolderClass;
 
 bool CloneExpandoChain(JSContext *cx, JSObject *src, JSObject *dst);
 
 bool
--- a/layout/build/nsLayoutModule.cpp
+++ b/layout/build/nsLayoutModule.cpp
@@ -11,17 +11,16 @@
 #include "nsContentCID.h"
 #include "nsContentDLF.h"
 #include "nsContentPolicyUtils.h"
 #include "nsDataDocumentContentPolicy.h"
 #include "nsNoDataProtocolContentPolicy.h"
 #include "nsDOMCID.h"
 #include "nsHTMLContentSerializer.h"
 #include "nsHTMLParts.h"
-#include "nsGenericHTMLElement.h"
 #include "nsIComponentManager.h"
 #include "nsIContentIterator.h"
 #include "nsIContentSerializer.h"
 #include "nsIContentViewer.h"
 #include "nsIController.h"
 #include "nsIControllers.h"
 #include "nsIDOMDOMImplementation.h"
 #include "nsIDocument.h"
@@ -543,18 +542,16 @@ MAKE_CTOR(CreateContentViewer,          
 MAKE_CTOR(CreateHTMLDocument,             nsIDocument,                 NS_NewHTMLDocument)
 MAKE_CTOR(CreateXMLDocument,              nsIDocument,                 NS_NewXMLDocument)
 MAKE_CTOR(CreateSVGDocument,              nsIDocument,                 NS_NewSVGDocument)
 MAKE_CTOR(CreateImageDocument,            nsIDocument,                 NS_NewImageDocument)
 MAKE_CTOR(CreateDOMSelection,             nsISelection,                NS_NewDomSelection)
 MAKE_CTOR2(CreateContentIterator,         nsIContentIterator,          NS_NewContentIterator)
 MAKE_CTOR2(CreatePreContentIterator,      nsIContentIterator,          NS_NewPreContentIterator)
 MAKE_CTOR2(CreateSubtreeIterator,         nsIContentIterator,          NS_NewContentSubtreeIterator)
-// CreateHTMLImgElement, see below
-// CreateHTMLOptionElement, see below
 MAKE_CTOR(CreateTextEncoder,              nsIDocumentEncoder,          NS_NewTextEncoder)
 MAKE_CTOR(CreateHTMLCopyTextEncoder,      nsIDocumentEncoder,          NS_NewHTMLCopyTextEncoder)
 MAKE_CTOR(CreateXMLContentSerializer,     nsIContentSerializer,        NS_NewXMLContentSerializer)
 MAKE_CTOR(CreateHTMLContentSerializer,    nsIContentSerializer,        NS_NewHTMLContentSerializer)
 MAKE_CTOR(CreateXHTMLContentSerializer,   nsIContentSerializer,        NS_NewXHTMLContentSerializer)
 MAKE_CTOR(CreatePlainTextSerializer,      nsIContentSerializer,        NS_NewPlainTextSerializer)
 MAKE_CTOR(CreateContentPolicy,            nsIContentPolicy,            NS_NewContentPolicy)
 #ifdef MOZ_XUL
@@ -601,52 +598,16 @@ static nsresult                         
         rv = NS_ERROR_OUT_OF_MEMORY;                                          \
         return rv;                                                            \
     }                                                                         \
     rv = inst->QueryInterface(aIID, aResult);                                 \
                                                                               \
     return rv;                                                                \
 }                                                                             \
 
-static nsresult
-CreateHTMLImgElement(nsISupports* aOuter, REFNSIID aIID, void** aResult)
-{
-  *aResult = nullptr;
-  if (aOuter)
-    return NS_ERROR_NO_AGGREGATION;
-  // Note! NS_NewHTMLImageElement is special cased to handle a null nodeinfo
-  nsCOMPtr<nsINodeInfo> ni;
-  nsIContent* inst = NS_NewHTMLImageElement(ni.forget());
-  nsresult rv = NS_ERROR_OUT_OF_MEMORY;
-  if (inst) {
-    NS_ADDREF(inst);
-    rv = inst->QueryInterface(aIID, aResult);
-    NS_RELEASE(inst);
-  }
-  return rv;
-}
-
-static nsresult
-CreateHTMLOptionElement(nsISupports* aOuter, REFNSIID aIID, void** aResult)
-{
-  *aResult = nullptr;
-  if (aOuter)
-    return NS_ERROR_NO_AGGREGATION;
-  // Note! NS_NewHTMLOptionElement is special cased to handle a null nodeinfo
-  nsCOMPtr<nsINodeInfo> ni;
-  nsIContent* inst = NS_NewHTMLOptionElement(ni.forget());
-  nsresult rv = NS_ERROR_OUT_OF_MEMORY;
-  if (inst) {
-    NS_ADDREF(inst);
-    rv = inst->QueryInterface(aIID, aResult);
-    NS_RELEASE(inst);
-  }
-  return rv;
-}
-
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsDOMScriptObjectFactory)
 
 #define NS_GEOLOCATION_CID \
   { 0x1E1C3FF, 0x94A, 0xD048, { 0x44, 0xB4, 0x62, 0xD2, 0x9C, 0x7B, 0x4F, 0x39 } }
 
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(Geolocation, Init)
 
 #define NS_GEOLOCATION_SERVICE_CID \
@@ -725,18 +686,16 @@ NS_DEFINE_NAMED_CID(NS_CONTENT_VIEWER_CI
 NS_DEFINE_NAMED_CID(NS_HTMLDOCUMENT_CID);
 NS_DEFINE_NAMED_CID(NS_XMLDOCUMENT_CID);
 NS_DEFINE_NAMED_CID(NS_SVGDOCUMENT_CID);
 NS_DEFINE_NAMED_CID(NS_IMAGEDOCUMENT_CID);
 NS_DEFINE_NAMED_CID(NS_DOMSELECTION_CID);
 NS_DEFINE_NAMED_CID(NS_CONTENTITERATOR_CID);
 NS_DEFINE_NAMED_CID(NS_PRECONTENTITERATOR_CID);
 NS_DEFINE_NAMED_CID(NS_SUBTREEITERATOR_CID);
-NS_DEFINE_NAMED_CID(NS_HTMLIMAGEELEMENT_CID);
-NS_DEFINE_NAMED_CID(NS_HTMLOPTIONELEMENT_CID);
 NS_DEFINE_NAMED_CID(NS_CANVASRENDERINGCONTEXTWEBGL_CID);
 NS_DEFINE_NAMED_CID(NS_TEXT_ENCODER_CID);
 NS_DEFINE_NAMED_CID(NS_HTMLCOPY_TEXT_ENCODER_CID);
 NS_DEFINE_NAMED_CID(NS_XMLCONTENTSERIALIZER_CID);
 NS_DEFINE_NAMED_CID(NS_XHTMLCONTENTSERIALIZER_CID);
 NS_DEFINE_NAMED_CID(NS_HTMLCONTENTSERIALIZER_CID);
 NS_DEFINE_NAMED_CID(NS_PLAINTEXTSERIALIZER_CID);
 NS_DEFINE_NAMED_CID(NS_PARSERUTILS_CID);
@@ -1015,18 +974,16 @@ static const mozilla::Module::CIDEntry k
   { &kNS_HTMLDOCUMENT_CID, false, NULL, CreateHTMLDocument },
   { &kNS_XMLDOCUMENT_CID, false, NULL, CreateXMLDocument },
   { &kNS_SVGDOCUMENT_CID, false, NULL, CreateSVGDocument },
   { &kNS_IMAGEDOCUMENT_CID, false, NULL, CreateImageDocument },
   { &kNS_DOMSELECTION_CID, false, NULL, CreateDOMSelection },
   { &kNS_CONTENTITERATOR_CID, false, NULL, CreateContentIterator },
   { &kNS_PRECONTENTITERATOR_CID, false, NULL, CreatePreContentIterator },
   { &kNS_SUBTREEITERATOR_CID, false, NULL, CreateSubtreeIterator },
-  { &kNS_HTMLIMAGEELEMENT_CID, false, NULL, CreateHTMLImgElement },
-  { &kNS_HTMLOPTIONELEMENT_CID, false, NULL, CreateHTMLOptionElement },
   { &kNS_CANVASRENDERINGCONTEXTWEBGL_CID, false, NULL, CreateCanvasRenderingContextWebGL },
   { &kNS_TEXT_ENCODER_CID, false, NULL, CreateTextEncoder },
   { &kNS_HTMLCOPY_TEXT_ENCODER_CID, false, NULL, CreateHTMLCopyTextEncoder },
   { &kNS_XMLCONTENTSERIALIZER_CID, false, NULL, CreateXMLContentSerializer },
   { &kNS_HTMLCONTENTSERIALIZER_CID, false, NULL, CreateHTMLContentSerializer },
   { &kNS_XHTMLCONTENTSERIALIZER_CID, false, NULL, CreateXHTMLContentSerializer },
   { &kNS_PLAINTEXTSERIALIZER_CID, false, NULL, CreatePlainTextSerializer },
   { &kNS_PARSERUTILS_CID, false, NULL, nsParserUtilsConstructor },
@@ -1165,18 +1122,16 @@ static const mozilla::Module::ContractID
   { "@mozilla.org/inspector/dom-utils;1", &kIN_DOMUTILS_CID },
   { NS_NAMESPACEMANAGER_CONTRACTID, &kNS_NAMESPACEMANAGER_CID },
   { "@mozilla.org/xml/xml-document;1", &kNS_XMLDOCUMENT_CID },
   { "@mozilla.org/svg/svg-document;1", &kNS_SVGDOCUMENT_CID },
   { "@mozilla.org/content/dom-selection;1", &kNS_DOMSELECTION_CID },
   { "@mozilla.org/content/post-content-iterator;1", &kNS_CONTENTITERATOR_CID },
   { "@mozilla.org/content/pre-content-iterator;1", &kNS_PRECONTENTITERATOR_CID },
   { "@mozilla.org/content/subtree-content-iterator;1", &kNS_SUBTREEITERATOR_CID },
-  { "@mozilla.org/content/element/html;1?name=img", &kNS_HTMLIMAGEELEMENT_CID },
-  { "@mozilla.org/content/element/html;1?name=option", &kNS_HTMLOPTIONELEMENT_CID },
   { "@mozilla.org/content/canvas-rendering-context;1?id=moz-webgl", &kNS_CANVASRENDERINGCONTEXTWEBGL_CID },
   { "@mozilla.org/content/canvas-rendering-context;1?id=experimental-webgl", &kNS_CANVASRENDERINGCONTEXTWEBGL_CID },
 #ifdef MOZ_PHOENIX // Not MOZ_FENNEC or MOZ_B2G yet.
   { "@mozilla.org/content/canvas-rendering-context;1?id=webgl", &kNS_CANVASRENDERINGCONTEXTWEBGL_CID },
 #endif
   { NS_DOC_ENCODER_CONTRACTID_BASE "text/xml", &kNS_TEXT_ENCODER_CID },
   { NS_DOC_ENCODER_CONTRACTID_BASE "application/xml", &kNS_TEXT_ENCODER_CID },
   { NS_DOC_ENCODER_CONTRACTID_BASE "application/xhtml+xml", &kNS_TEXT_ENCODER_CID },
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -4878,17 +4878,17 @@ nsIFrame::IsInvalid(nsRect& aRect)
 void
 nsIFrame::SchedulePaint(uint32_t aFlags)
 {
   nsIFrame *displayRoot = nsLayoutUtils::GetDisplayRootFrame(this);
   nsPresContext *pres = displayRoot->PresContext()->GetRootPresContext();
 
   // No need to schedule a paint for an external document since they aren't
   // painted directly.
-  if (!pres || (pres->Document() && pres->Document()->GetDisplayDocument())) {
+  if (!pres || (pres->Document() && pres->Document()->IsResourceDoc())) {
     return;
   }
   
   pres->PresShell()->ScheduleViewManagerFlush();
   if (!(aFlags & PAINT_COMPOSITE_ONLY)) {
     displayRoot->AddStateBits(NS_FRAME_UPDATE_LAYER_TREE);
   }
   nsIPresShell* shell = PresContext()->PresShell();
--- a/media/libopus/include/opus_defines.h
+++ b/media/libopus/include/opus_defines.h
@@ -67,24 +67,24 @@ extern "C" {
 #define OPUS_INVALID_STATE    -6
 /** Memory allocation has failed @hideinitializer*/
 #define OPUS_ALLOC_FAIL       -7
 /**@}*/
 
 /** @cond OPUS_INTERNAL_DOC */
 /**Export control for opus functions */
 
-#if defined(__GNUC__) && defined(OPUS_BUILD)
-# define OPUS_EXPORT __attribute__ ((visibility ("default")))
-#elif defined(WIN32)
+#if defined(WIN32)
 # ifdef OPUS_BUILD
 #   define OPUS_EXPORT __declspec(dllexport)
 # else
 #   define OPUS_EXPORT __declspec(dllimport)
 # endif
+#elif defined(__GNUC__) && defined(OPUS_BUILD)
+# define OPUS_EXPORT __attribute__ ((visibility ("default")))
 #else
 # define OPUS_EXPORT
 #endif
 
 /** These are the actual Encoder CTL ID numbers.
   * They should not be used directly by applications. */
 #define OPUS_SET_APPLICATION_REQUEST         4000
 #define OPUS_GET_APPLICATION_REQUEST         4001
new file mode 100644
--- /dev/null
+++ b/media/libopus/mingw.patch
@@ -0,0 +1,28 @@
+commit 986fb3ec557aa7aeb8788360224708ffa2955072
+Author: Jacek Caban <jacek@codeweavers.com>
+Date:   Wed Jun 12 17:30:47 2013 +0200
+
+    Use __declspec(dllexport) on mingw build.
+
+diff --git a/media/libopus/include/opus_defines.h b/media/libopus/include/opus_defines.h
+index db6b3b7..b64049b 100644
+--- a/media/libopus/include/opus_defines.h
++++ b/media/libopus/include/opus_defines.h
+@@ -72,14 +72,14 @@ extern "C" {
+ /** @cond OPUS_INTERNAL_DOC */
+ /**Export control for opus functions */
+ 
+-#if defined(__GNUC__) && defined(OPUS_BUILD)
+-# define OPUS_EXPORT __attribute__ ((visibility ("default")))
+-#elif defined(WIN32)
++#if defined(WIN32)
+ # ifdef OPUS_BUILD
+ #   define OPUS_EXPORT __declspec(dllexport)
+ # else
+ #   define OPUS_EXPORT __declspec(dllimport)
+ # endif
++#elif defined(__GNUC__) && defined(OPUS_BUILD)
++# define OPUS_EXPORT __attribute__ ((visibility ("default")))
+ #else
+ # define OPUS_EXPORT
+ #endif
--- a/media/libopus/update.sh
+++ b/media/libopus/update.sh
@@ -60,8 +60,9 @@ echo "copied from revision ${version}"
 # update README revision
 sed -e "s/^The git tag\/revision used was .*/The git tag\/revision used was ${version}./" \
     ${TARGET}/README_MOZILLA > ${TARGET}/README_MOZILLA+ && \
     mv ${TARGET}/README_MOZILLA+ ${TARGET}/README_MOZILLA
 
 # apply outstanding local patches
 patch -p3 < bug776661.patch
 patch -p1 < padding.patch
+patch -p3 < mingw.patch
--- a/modules/libbz2/src/Makefile.in
+++ b/modules/libbz2/src/Makefile.in
@@ -7,17 +7,16 @@
 DEPTH		= @DEPTH@
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 LIBRARY_NAME	= bz2
-DISABLED_HOST_LIBRARY_NAME = hostbz2
 FORCE_STATIC_LIB= 1
 ifeq ($(OS_ARCH),WINNT)
 USE_STATIC_LIBS = 1
 endif
 
 # This is defined by the bzip2-1.0.3 Makefile.  It appears to be used to
 # configure GLIBC to support large files.  This isn't something we care about
 # at this stage, since we're only interested in the streaming API, but we
--- a/modules/libmar/src/Makefile.in
+++ b/modules/libmar/src/Makefile.in
@@ -7,17 +7,16 @@
 DEPTH		= @DEPTH@
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 LIBRARY_NAME	= mar
-DISABLED_HOST_LIBRARY_NAME = hostmar
 FORCE_STATIC_LIB = 1
 ifeq ($(OS_ARCH),WINNT)
 USE_STATIC_LIBS = 1
 endif
 
 # This makefile just builds support for reading archives.
 
 CSRCS = \
--- a/netwerk/dns/nsDNSService2.cpp
+++ b/netwerk/dns/nsDNSService2.cpp
@@ -250,30 +250,34 @@ public:
 
     nsDNSAsyncRequest(nsHostResolver   *res,
                       const nsACString &host,
                       nsIDNSListener   *listener,
                       uint16_t          flags,
                       uint16_t          af)
         : mResolver(res)
         , mHost(host)
-        , mListener(listener)
+        // Sometimes aListener is a main-thread only object like XPCWrappedJS, and
+        // sometimes it's a threadsafe object like nsSocketTransport. Use a main-
+        // thread pointer holder, but disable strict enforcement of thread invariants.
+        // The AddRef implementation of XPCWrappedJS will assert if we go wrong here.
+        , mListener(new nsMainThreadPtrHolder<nsIDNSListener>(listener, false))
         , mFlags(flags)
         , mAF(af) {}
     ~nsDNSAsyncRequest() {}
 
     void OnLookupComplete(nsHostResolver *, nsHostRecord *, nsresult);
     // Returns TRUE if the DNS listener arg is the same as the member listener
     // Used in Cancellations to remove DNS requests associated with a
     // particular hostname and nsIDNSListener
     bool EqualsAsyncListener(nsIDNSListener *aListener);
 
     nsRefPtr<nsHostResolver> mResolver;
     nsCString                mHost; // hostname we're resolving
-    nsCOMPtr<nsIDNSListener> mListener;
+    nsMainThreadPtrHandle<nsIDNSListener> mListener;
     uint16_t                 mFlags;
     uint16_t                 mAF;
 };
 
 void
 nsDNSAsyncRequest::OnLookupComplete(nsHostResolver *resolver,
                                     nsHostRecord   *hostRecord,
                                     nsresult        status)
@@ -287,17 +291,16 @@ nsDNSAsyncRequest::OnLookupComplete(nsHo
         rec = new nsDNSRecord(hostRecord);
         if (!rec)
             status = NS_ERROR_OUT_OF_MEMORY;
     }
 
     MOZ_EVENT_TRACER_DONE(this, "net::dns::lookup");
 
     mListener->OnLookupComplete(this, rec, status);
-    mListener = nullptr;
 
     // release the reference to ourselves that was added before we were
     // handed off to the host resolver.
     NS_RELEASE_THIS();
 }
 
 bool
 nsDNSAsyncRequest::EqualsAsyncListener(nsIDNSListener *aListener)
--- a/services/sync/modules/engines/forms.js
+++ b/services/sync/modules/engines/forms.js
@@ -262,17 +262,17 @@ FormTracker.prototype = {
 
   _enabled: false,
   observe: function observe(subject, topic, data) {
     switch (topic) {
       case "weave:engine:start-tracking":
         if (!this._enabled) {
           Svc.Obs.add("form-notifier", this);
           Svc.Obs.add("satchel-storage-changed", this);
-          // nsHTMLFormElement doesn't use the normal observer/observe
+          // HTMLFormElement doesn't use the normal observer/observe
           // pattern and looks up nsIFormSubmitObservers to .notify()
           // them so add manually to observers
           Cc["@mozilla.org/observer-service;1"]
             .getService(Ci.nsIObserverService)
             .addObserver(this, "earlyformsubmit", true);
           this._enabled = true;
         }
         break;
--- a/toolkit/crashreporter/google-breakpad/src/common/Makefile.in
+++ b/toolkit/crashreporter/google-breakpad/src/common/Makefile.in
@@ -8,17 +8,16 @@ srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 LIBRARY_NAME	= breakpad_common_s
 MSVC_ENABLE_PGO := 1
 ifneq (WINNT,$(OS_TARGET))
 ifdef MOZ_CRASHREPORTER
-DISABLED_HOST_LIBRARY_NAME = host_breakpad_common_s
 endif
 endif
 
 LOCAL_INCLUDES 	= -I$(srcdir)/..
 
 ifneq (WINNT,$(OS_TARGET))
 ifdef MOZ_CRASHREPORTER
 HOST_CPPSRCS = \
--- a/toolkit/crashreporter/google-breakpad/src/common/dwarf/Makefile.in
+++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf/Makefile.in
@@ -5,17 +5,16 @@
 DEPTH		= @DEPTH@
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 ifdef MOZ_CRASHREPORTER
-DISABLED_HOST_LIBRARY_NAME = host_breakpad_dwarf_s
 
 LOCAL_INCLUDES 	= -I$(srcdir)/../..
 
 HOST_CPPSRCS = \
   bytereader.cc \
   dwarf2diehandler.cc \
   dwarf2reader.cc \
   functioninfo.cc \
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/Makefile.in
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/Makefile.in
@@ -6,17 +6,16 @@ DEPTH		= @DEPTH@
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 LIBRARY_NAME	= breakpad_linux_common_s
 ifdef MOZ_CRASHREPORTER
-DISABLED_HOST_LIBRARY_NAME = host_breakpad_linux_common_s
 endif
 
 LOCAL_INCLUDES = \
   -I$(topsrcdir)/toolkit/crashreporter/google-breakpad/src \
   $(NULL)
 
 ifneq (Android,$(OS_TARGET))
 else
--- a/toolkit/crashreporter/google-breakpad/src/common/mac/Makefile.in
+++ b/toolkit/crashreporter/google-breakpad/src/common/mac/Makefile.in
@@ -5,17 +5,16 @@
 DEPTH		= @DEPTH@
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 LIBRARY_NAME	= breakpad_mac_common_s
-DISABLED_HOST_LIBRARY_NAME = host_breakpad_mac_common_s
 
 LOCAL_INCLUDES 	= -I$(srcdir)/../..
 
 # This is a little weird, but we're building a host and a target lib here.
 # The host lib is used for dump_syms, and the target lib for the
 # crash reporter client.  Therefore, we don't need all the srcs in both.
 CMSRCS = \
   HTTPMultipartUpload.m \
--- a/toolkit/crashreporter/google-breakpad/src/common/solaris/Makefile.in
+++ b/toolkit/crashreporter/google-breakpad/src/common/solaris/Makefile.in
@@ -5,17 +5,16 @@
 DEPTH		= @DEPTH@
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 LIBRARY_NAME	= breakpad_solaris_common_s
-DISABLED_HOST_LIBRARY_NAME = host_breakpad_solaris_common_s
 
 LOCAL_INCLUDES 	= -I$(srcdir)/../..
 
 # not compiling http_upload.cc currently
 # since it depends on libcurl
 HOST_CPPSRCS = \
   dump_symbols.cc \
   file_id.cc \
--- a/toolkit/library/Makefile.in
+++ b/toolkit/library/Makefile.in
@@ -645,21 +645,23 @@ ifeq (Linux,$(OS_ARCH))
 # the build directory.
 PP_TARGETS += LIBXUL_AUTOLOAD
 LIBXUL_AUTOLOAD = libxul.so-gdb.py.in
 LIBXUL_AUTOLOAD_FLAGS := -Dtopsrcdir=$(abspath $(topsrcdir))
 endif
 
 ifdef MAKE_FRAMEWORK
 EFFECTIVE_LIB_PREFIX=
+EFFECTIVE_LIB_SUFFIX=
 else
 EFFECTIVE_LIB_PREFIX=$(DLL_PREFIX)
+EFFECTIVE_LIB_SUFFIX=$(DLL_SUFFIX)
 endif
 
-GTEST_LIB = $(EFFECTIVE_LIB_PREFIX)gtest/$(EFFECTIVE_LIB_PREFIX)$(LIBRARY_NAME).$(DLL_SUFFIX)
+GTEST_LIB = $(EFFECTIVE_LIB_PREFIX)gtest/$(EFFECTIVE_LIB_PREFIX)$(LIBRARY_NAME)$(EFFECTIVE_LIB_SUFFIX)
 EXTRA_MDDEPEND_FILES = $(GTEST_LIB).pp
 
 include $(topsrcdir)/config/rules.mk
 
 export:: $(RDF_UTIL_SRC_CPPSRCS) $(INTL_UNICHARUTIL_UTIL_CPPSRCS)
 	$(INSTALL) $^ .
 
 # need widget/windows for resource.h (included from widget.rc)