Merge m-c to fx-team
authorWes Kocher <wkocher@mozilla.com>
Wed, 25 Sep 2013 21:25:47 -0700
changeset 162597 160ec7af5cb95369a0d5338ae035999f89563ee6
parent 162596 1c5e6b8ebbde8f18b96ae5b2929820e3b6f0d18c (current diff)
parent 162551 e85b0372cece1bb73a37bd89a8c053971021c835 (diff)
child 162598 153254a69c0007f36df73777d06bc257809110ba
push id3066
push userakeybl@mozilla.com
push dateMon, 09 Dec 2013 19:58:46 +0000
treeherdermozilla-beta@a31a0dce83aa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone27.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 m-c to fx-team
dom/imptests/failures/html/html/dom/elements/global-attributes/Makefile.in
dom/imptests/failures/html/html/dom/elements/global-attributes/test_document-dir.html.json
dom/imptests/failures/html/old-tests/submission/Opera/microdata/Makefile.in
dom/imptests/failures/html/old-tests/submission/Opera/microdata/moz.build
dom/imptests/failures/html/old-tests/submission/Opera/microdata/test_001.html.json
dom/imptests/failures/webapps/DOMCore/tests/approved/Makefile.in
dom/imptests/failures/webapps/DOMCore/tests/approved/moz.build
dom/imptests/failures/webapps/DOMCore/tests/approved/test_Node-properties.html.json
dom/imptests/failures/webapps/DOMCore/tests/approved/test_Range-cloneContents.html.json
dom/imptests/failures/webapps/DOMCore/tests/approved/test_Range-cloneRange.html.json
dom/imptests/failures/webapps/DOMCore/tests/approved/test_Range-collapse.html.json
dom/imptests/failures/webapps/DOMCore/tests/approved/test_Range-commonAncestorContainer.html.json
dom/imptests/failures/webapps/DOMCore/tests/approved/test_Range-compareBoundaryPoints.html.json
dom/imptests/failures/webapps/DOMCore/tests/approved/test_Range-comparePoint.html.json
dom/imptests/failures/webapps/DOMCore/tests/approved/test_Range-deleteContents.html.json
dom/imptests/failures/webapps/DOMCore/tests/approved/test_Range-extractContents.html.json
dom/imptests/failures/webapps/DOMCore/tests/approved/test_Range-intersectsNode.html.json
dom/imptests/failures/webapps/DOMCore/tests/approved/test_Range-isPointInRange.html.json
dom/imptests/failures/webapps/DOMCore/tests/approved/test_Range-mutations.html.json
dom/imptests/failures/webapps/DOMCore/tests/approved/test_Range-set.html.json
dom/imptests/failures/webapps/DOMCore/tests/approved/test_exceptions.html.json
dom/imptests/failures/webapps/DOMCore/tests/approved/test_interfaces.html.json
dom/imptests/failures/webapps/DOMCore/tests/submissions/Ms2ger/moz.build
dom/imptests/failures/webapps/DOMCore/tests/submissions/Ms2ger/test_DOMImplementation-createDocument.html.json
dom/imptests/failures/webapps/DOMCore/tests/submissions/Ms2ger/test_Document-createElementNS.html.json
dom/imptests/failures/webapps/DOMCore/tests/submissions/Ms2ger/test_Document-getElementsByTagName.html.json
dom/imptests/failures/webapps/DOMCore/tests/submissions/Ms2ger/test_Node-isEqualNode.xhtml.json
dom/imptests/failures/webapps/DOMCore/tests/submissions/Ms2ger/test_Node-replaceChild.html.json
dom/imptests/failures/webapps/DOMCore/tests/submissions/Ms2ger/test_NodeFilter-constants.html.json
dom/imptests/failures/webapps/DOMCore/tests/submissions/Ms2ger/test_Range-intersectsNode.html.json
dom/imptests/failures/webapps/DOMCore/tests/submissions/Ms2ger/test_attributes.html.json
dom/imptests/failures/webapps/DOMCore/tests/submissions/Ms2ger/test_case.html.json
dom/imptests/failures/webapps/DOMCore/tests/submissions/Ms2ger/test_historical.html.json
dom/imptests/failures/webapps/DOMCore/tests/submissions/Opera/moz.build
dom/imptests/failures/webapps/DOMCore/tests/submissions/Opera/test_getElementsByClassName-10.xml.json
dom/imptests/failures/webapps/DOMCore/tests/submissions/Opera/test_getElementsByClassName-11.xml.json
dom/imptests/html/html/dom/elements/global-attributes/test_dataset-instanceof.html
dom/imptests/html/old-tests/submission/Opera/microdata/Makefile.in
dom/imptests/html/old-tests/submission/Opera/microdata/moz.build
dom/imptests/html/old-tests/submission/Opera/microdata/test_001.html
dom/imptests/webapps/DOMCore/tests/approved/Makefile.in
dom/imptests/webapps/DOMCore/tests/approved/Range-test-iframe.html
dom/imptests/webapps/DOMCore/tests/approved/common.js
dom/imptests/webapps/DOMCore/tests/approved/moz.build
dom/imptests/webapps/DOMCore/tests/approved/test_Node-compareDocumentPosition.html
dom/imptests/webapps/DOMCore/tests/approved/test_Node-contains.html
dom/imptests/webapps/DOMCore/tests/approved/test_Node-properties.html
dom/imptests/webapps/DOMCore/tests/approved/test_Range-cloneContents.html
dom/imptests/webapps/DOMCore/tests/approved/test_Range-cloneRange.html
dom/imptests/webapps/DOMCore/tests/approved/test_Range-collapse.html
dom/imptests/webapps/DOMCore/tests/approved/test_Range-commonAncestorContainer.html
dom/imptests/webapps/DOMCore/tests/approved/test_Range-compareBoundaryPoints.html
dom/imptests/webapps/DOMCore/tests/approved/test_Range-comparePoint.html
dom/imptests/webapps/DOMCore/tests/approved/test_Range-deleteContents.html
dom/imptests/webapps/DOMCore/tests/approved/test_Range-extractContents.html
dom/imptests/webapps/DOMCore/tests/approved/test_Range-insertNode.html
dom/imptests/webapps/DOMCore/tests/approved/test_Range-intersectsNode.html
dom/imptests/webapps/DOMCore/tests/approved/test_Range-isPointInRange.html
dom/imptests/webapps/DOMCore/tests/approved/test_Range-mutations.html
dom/imptests/webapps/DOMCore/tests/approved/test_Range-selectNode.html
dom/imptests/webapps/DOMCore/tests/approved/test_Range-set.html
dom/imptests/webapps/DOMCore/tests/approved/test_Range-surroundContents.html
dom/imptests/webapps/DOMCore/tests/approved/test_exceptions.html
dom/imptests/webapps/DOMCore/tests/approved/test_interfaces.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/ChildNode-remove.js
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/Document-createProcessingInstruction.js
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/attributes.js
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/case.js
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/constants.js
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/creators.js
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/moz.build
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/productions.js
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_CharacterData-appendData.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_CharacterData-deleteData.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_CharacterData-insertData.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_CharacterData-remove.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_CharacterData-replaceData.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_DOMException-constants.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_DOMImplementation-createDocument.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_DOMImplementation-createDocumentType.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_DOMImplementation-createHTMLDocument.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_DOMImplementation-hasFeature.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Document-adoptNode.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Document-createComment.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Document-createElement.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Document-createElementNS.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Document-createEvent.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Document-createProcessingInstruction-literal-1.xhtml
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Document-createProcessingInstruction-literal-2.xhtml
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Document-createProcessingInstruction.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Document-createProcessingInstruction.xhtml
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Document-createTreeWalker.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Document-getElementById.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Document-getElementsByTagName.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Document-getElementsByTagNameNS.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Document-importNode.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_DocumentType-remove.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Element-children.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Element-getElementsByClassName.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Element-remove.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Element-removeAttributeNS.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Element-tagName.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Event-constants.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Event-constructors.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Event-defaultPrevented.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Event-initEvent.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Event-type.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_EventTarget-dispatchEvent.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Node-appendChild.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Node-cloneNode.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Node-constants.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Node-contains.xml
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Node-insertBefore.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Node-isEqualNode.xhtml
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Node-lookupPrefix.xhtml
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Node-nodeName.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Node-nodeName.xhtml
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Node-normalize.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Node-parentElement.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Node-parentNode.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Node-removeChild.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Node-replaceChild.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_NodeFilter-constants.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Range-attributes.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Range-commonAncestorContainer.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Range-comparePoint.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Range-detach.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Range-intersectsNode-binding.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_attributes.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_case.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_historical.html
dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_interfaces.html
dom/imptests/webapps/DOMCore/tests/submissions/Opera/moz.build
dom/imptests/webapps/DOMCore/tests/submissions/Opera/test_getElementsByClassName-01.htm
dom/imptests/webapps/DOMCore/tests/submissions/Opera/test_getElementsByClassName-02.htm
dom/imptests/webapps/DOMCore/tests/submissions/Opera/test_getElementsByClassName-03.htm
dom/imptests/webapps/DOMCore/tests/submissions/Opera/test_getElementsByClassName-04.htm
dom/imptests/webapps/DOMCore/tests/submissions/Opera/test_getElementsByClassName-05.htm
dom/imptests/webapps/DOMCore/tests/submissions/Opera/test_getElementsByClassName-06.htm
dom/imptests/webapps/DOMCore/tests/submissions/Opera/test_getElementsByClassName-07.htm
dom/imptests/webapps/DOMCore/tests/submissions/Opera/test_getElementsByClassName-08.htm
dom/imptests/webapps/DOMCore/tests/submissions/Opera/test_getElementsByClassName-09.htm
dom/imptests/webapps/DOMCore/tests/submissions/Opera/test_getElementsByClassName-10.xml
dom/imptests/webapps/DOMCore/tests/submissions/Opera/test_getElementsByClassName-11.xml
dom/imptests/webapps/DOMCore/tests/submissions/Opera/test_getElementsByClassName-12.htm
dom/imptests/webapps/DOMCore/tests/submissions/Opera/test_getElementsByClassName-13.htm
dom/imptests/webapps/DOMCore/tests/submissions/Opera/test_getElementsByClassName-14.htm
dom/imptests/webapps/DOMCore/tests/submissions/Opera/test_getElementsByClassName-15.htm
dom/imptests/webapps/DOMCore/tests/submissions/Opera/test_getElementsByClassName-16.htm
dom/imptests/webapps/DOMCore/tests/submissions/Opera/test_getElementsByClassName-17.htm
dom/imptests/webapps/DOMCore/tests/submissions/Opera/test_getElementsByClassName-18.htm
tools/profiler/android-signal-defs.h
--- a/b2g/components/MozKeyboard.js
+++ b/b2g/components/MozKeyboard.js
@@ -372,17 +372,19 @@ MozInputMethod.prototype = {
           // XXX Bug 904339 could receive 'text' event twice
           this.setInputContext(json);
         }
         else {
           this.setInputContext(null);
         }
         break;
       case 'Keyboard:SelectionChange':
-        this._inputcontext.updateSelectionContext(json);
+        if (this.inputcontext) {
+          this._inputcontext.updateSelectionContext(json);
+        }
         break;
       case 'Keyboard:GetContext:Result:OK':
         this.setInputContext(json);
         break;
       case 'Keyboard:LayoutsChange':
         this._layouts = json;
         break;
     }
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,4 +1,4 @@
 {
-    "revision": "df1654f408ae9ff3bdb276ad2e243bfecfd47087", 
+    "revision": "f22c641c064abac5388209008dd81ba01ec6821e", 
     "repo_path": "/integration/gaia-central"
 }
--- a/browser/config/mozconfigs/win32/common-opt
+++ b/browser/config/mozconfigs/win32/common-opt
@@ -1,16 +1,22 @@
 # This file is sourced by the nightly, beta, and release mozconfigs.
 
 . "$topsrcdir/browser/config/mozconfigs/common"
 
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
 ac_add_options --enable-update-packaging
 ac_add_options --enable-jemalloc
-ac_add_options --with-google-api-keyfile=/e/builds/gapi.data
+if [ -f /c/builds/gapi.data ]; then
+  _gapi_keyfile=/c/builds/gapi.data
+else
+  _gapi_keyfile=/e/builds/gapi.data
+fi
+ac_add_options --with-google-api-keyfile=${_gapi_keyfile}
+
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 export MOZ_TELEMETRY_REPORTING=1
 
 if test -z "${_PYMAKE}"; then
   mk_add_options MOZ_MAKE_FLAGS=-j1
--- a/browser/config/mozconfigs/win64/common-opt
+++ b/browser/config/mozconfigs/win64/common-opt
@@ -1,16 +1,21 @@
 # This file is sourced by the nightly, beta, and release mozconfigs.
 
 . "$topsrcdir/browser/config/mozconfigs/common"
 
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
 ac_add_options --enable-update-packaging
 ac_add_options --enable-jemalloc
-ac_add_options --with-google-api-keyfile=/e/builds/gapi.data
+if [ -f /c/builds/gapi.data ]; then
+  _gapi_keyfile=/c/builds/gapi.data
+else
+  _gapi_keyfile=/e/builds/gapi.data
+fi
+ac_add_options --with-google-api-keyfile=${_gapi_keyfile}
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 export MOZ_TELEMETRY_REPORTING=1
 
 if test -z "${_PYMAKE}"; then
   mk_add_options MOZ_MAKE_FLAGS=-j1
new file mode 100644
--- /dev/null
+++ b/build/docs/Vagrantfile
@@ -0,0 +1,10 @@
+# -*- mode: ruby -*-
+# vi: set ft=ruby :
+
+# We intentionally use the old config format because Mozilla's Jenkins
+# server doesn't run a modern Vagrant.
+Vagrant::Config.run do |config|
+  config.vm.box = "precise64"
+  config.vm.box_url = "http://files.vagrantup.com/precise64.box"
+  config.vm.share_folder("gecko", "/gecko", "../..")
+end
--- a/content/base/src/nsFrameMessageManager.cpp
+++ b/content/base/src/nsFrameMessageManager.cpp
@@ -752,17 +752,17 @@ nsFrameMessageManager::ReceiveMessage(ns
   AutoSafeJSContext ctx;
 
   if (mListeners.Length()) {
     nsCOMPtr<nsIAtom> name = do_GetAtom(aMessage);
     MMListenerRemover lr(this);
 
     for (uint32_t i = 0; i < mListeners.Length(); ++i) {
       // Remove mListeners[i] if it's an expired weak listener.
-      nsCOMPtr<nsIMessageListener> weakListener;
+      nsCOMPtr<nsISupports> weakListener;
       if (mListeners[i].mWeakListener) {
         weakListener = do_QueryReferent(mListeners[i].mWeakListener);
         if (!weakListener) {
           mListeners.RemoveElementAt(i--);
           continue;
         }
       }
 
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -2534,16 +2534,33 @@ nsDOMWindowUtils::GetOuterWindowWithId(u
                                   "GetWindowWithOuterIdWarning");
 
   *aWindow = nsGlobalWindow::GetOuterWindowWithId(aWindowID);
   NS_IF_ADDREF(*aWindow);
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsDOMWindowUtils::GetContainerElement(nsIDOMElement** aResult)
+{
+  if (!nsContentUtils::IsCallerChrome()) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
+  nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
+  NS_ENSURE_STATE(window);
+
+  nsCOMPtr<nsIDOMElement> element =
+    do_QueryInterface(window->GetFrameElementInternal());
+
+  element.forget(aResult);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsDOMWindowUtils::WrapDOMFile(nsIFile *aFile,
                               nsIDOMFile **aDOMFile)
 {
   if (!nsContentUtils::IsCallerChrome()) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
   if (!aFile) {
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -1373,29 +1373,22 @@ InitIds(JSContext* cx, const Prefable<Sp
   } while ((++prefableSpecs)->specs);
 
   return true;
 }
 
 bool
 QueryInterface(JSContext* cx, unsigned argc, JS::Value* vp);
 
-template <class T, bool isISupports=IsBaseOf<nsISupports, T>::value>
+template <class T>
 struct
 WantsQueryInterface
 {
-  static bool Enabled(JSContext* aCx, JSObject* aGlobal)
-  {
-    return false;
-  }
-};
-template <class T>
-struct
-WantsQueryInterface<T, true>
-{
+  static_assert(IsBaseOf<nsISupports, T>::value,
+                "QueryInterface can't work without an nsISupports.");
   static bool Enabled(JSContext* aCx, JSObject* aGlobal)
   {
     return NS_IsMainThread() && IsChromeOrXBL(aCx, aGlobal);
   }
 };
 
 bool
 ThrowingConstructor(JSContext* cx, unsigned argc, JS::Value* vp);
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -25,18 +25,16 @@
 #                interface's prototype object).  Always False for callback
 #                interfaces.  Defaults to True otherwise.
 #   * workers - Indicates whether the descriptor is intended to be used for
 #               worker threads (defaults to false).
 #   * customTrace - The native class will use a custom trace hook (defaults to
 #                   true for workers, false otherwise).
 #   * customFinalize - The native class will use a custom finalize hook
 #                      (defaults to true for workers, false otherwise).
-#   * wantsQI - Indicates whether the interface should have a QueryInterface
-#               method available to chrome.
 #   * notflattened - The native type does not have nsIClassInfo, so when
 #                    wrapping it the right IID needs to be passed in.
 #   * register - True if this binding should be registered.  Defaults to true.
 #   * binaryNames - Dict for mapping method and attribute names to different
 #                   names when calling the native methods (defaults to an empty
 #                   dict). The keys are the property names as they appear in the
 #                   .webidl file and the values are the names as they should be
 #                   in the WebIDL.
@@ -313,17 +311,16 @@ DOMInterfaces = {
     'skipGen': True
 }],
 
 'DocumentFragment': {
     'resultNotAddRefed': [ 'querySelector' ]
 },
 
 'DOMException': {
-    'wantsQI': False,
     'binaryNames': {
         'message': 'messageMoz',
     },
 },
 
 'DOMSettableTokenList': {
     'nativeType': 'nsDOMSettableTokenList',
 },
@@ -390,17 +387,16 @@ DOMInterfaces = {
 },
 {
     'workers': True,
     'concrete': False
 }],
 
 'Exception': {
     'headerFile': 'mozilla/dom/DOMException.h',
-    'wantsQI': False,
     'binaryNames': {
         'message': 'messageMoz',
     },
 },
 
 'FileHandle': {
     'nativeType': 'mozilla::dom::file::FileHandle'
 },
@@ -655,17 +651,16 @@ DOMInterfaces = {
 },
 {
     'workers': True,
 }],
 
 'ImageData': [
 {
     'wrapperCache': False,
-    'wantsQI': False,
 }],
 
 'InputStream': [
 {
     'nativeType': 'nsIInputStream',
     'notflattened': True
 },
 {
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -1457,16 +1457,51 @@ class MethodDefiner(PropertyDefiner):
             methods = [m for m in descriptor.interface.members if
                        m.isMethod() and m.isStatic() == static and
                        not m.isIdentifierLess()]
         else:
             methods = []
         self.chrome = []
         self.regular = []
         for m in methods:
+            if m.identifier.name == 'queryInterface':
+                if self.descriptor.workers:
+                    continue
+                if m.isStatic():
+                    raise TypeError("Legacy queryInterface member shouldn't be static")
+                signatures = m.signatures()
+                def argTypeIsIID(arg):
+                    return arg.type.inner.isExternal() and arg.type.inner.identifier.name == 'IID'
+                if len(signatures) > 1 or len(signatures[0][1]) > 1 or not argTypeIsIID(signatures[0][1][0]):
+                    raise TypeError("There should be only one queryInterface method with 1 argument of type IID")
+                # Make sure to not stick QueryInterface on abstract interfaces that
+                # have hasXPConnectImpls (like EventTarget).  So only put it on
+                # interfaces that are concrete and all of whose ancestors are abstract.
+                def allAncestorsAbstract(iface):
+                    if not iface.parent:
+                        return True
+                    desc = self.descriptor.getDescriptor(iface.parent.identifier.name)
+                    if desc.concrete:
+                        return False
+                    return allAncestorsAbstract(iface.parent)
+                if (not self.descriptor.interface.hasInterfacePrototypeObject() or
+                    not self.descriptor.concrete or
+                    not allAncestorsAbstract(self.descriptor.interface)):
+                    raise TypeError("QueryInterface is only supported on "
+                                    "interfaces that are concrete and all "
+                                    "of whose ancestors are abstract: " +
+                                    self.descriptor.name)
+                condition = "WantsQueryInterface<%s>::Enabled" % descriptor.nativeType
+                self.regular.append({"name": 'QueryInterface',
+                                     "methodInfo": False,
+                                     "length": 1,
+                                     "flags": "0",
+                                     "condition": MemberCondition(None, condition) })
+                continue
+
             method = { "name": m.identifier.name,
                        "methodInfo": not m.isStatic(),
                        "length": methodLength(m),
                        "flags": "JSPROP_ENUMERATE",
                        "condition": PropertyDefiner.getControllingCondition(m) }
             if isChromeOnly(m):
                 self.chrome.append(method)
             else:
@@ -1476,24 +1511,16 @@ class MethodDefiner(PropertyDefiner):
         if any(m.isGetter() and m.isIndexed() for m in methods):
             self.regular.append({"name": 'iterator',
                                  "methodInfo": False,
                                  "nativeName": "JS_ArrayIterator",
                                  "length": 0,
                                  "flags": "JSPROP_ENUMERATE",
                                  "condition": MemberCondition(None, None) })
 
-        if not static and descriptor.wantsQI():
-            condition = "WantsQueryInterface<%s>::Enabled" % descriptor.nativeType
-            self.regular.append({"name": 'QueryInterface',
-                                 "methodInfo": False,
-                                 "length": 1,
-                                 "flags": "0",
-                                 "condition": MemberCondition(None, condition) })
-
         if not static:
             stringifier = descriptor.operations['Stringifier']
             if stringifier:
                 toStringDesc = { "name": "toString",
                                  "nativeName": stringifier.identifier.name,
                                  "length": 0,
                                  "flags": "JSPROP_ENUMERATE",
                                  "condition": PropertyDefiner.getControllingCondition(stringifier) }
@@ -7855,16 +7882,18 @@ class CGDescriptor(CGThing):
         # These are set to true if at least one non-static
         # method/getter/setter or jsonifier exist on the interface.
         (hasMethod, hasGetter, hasLenientGetter, hasSetter, hasJsonifier,
             hasLenientSetter) = False, False, False, False, False, False
         for n in descriptor.interface.namedConstructors:
             cgThings.append(CGClassConstructor(descriptor, n,
                                                NamedConstructorName(n)))
         for m in descriptor.interface.members:
+            if m.isMethod() and m.identifier.name == 'queryInterface':
+                continue
             if (m.isMethod() and m == descriptor.operations['Jsonifier']):
                 hasJsonifier = True
                 hasMethod = True
                 jsonifierMethod = m
             elif (m.isMethod() and
                   (not m.isIdentifierLess() or m == descriptor.operations['Stringifier'])):
                 if m.isStatic():
                     assert descriptor.interface.hasInterfaceObject
--- a/dom/bindings/Configuration.py
+++ b/dom/bindings/Configuration.py
@@ -351,18 +351,16 @@ class Descriptor(DescriptorProvider):
         else:
             self.nativeOwnership = desc.get('nativeOwnership', 'refcounted')
             if not self.nativeOwnership in ['owned', 'refcounted']:
                 raise TypeError("Descriptor for %s has unrecognized value (%s) "
                                 "for nativeOwnership" %
                                 (self.interface.identifier.name, self.nativeOwnership))
         self.customTrace = desc.get('customTrace', self.workers)
         self.customFinalize = desc.get('customFinalize', self.workers)
-        if desc.get('wantsQI', None) != None:
-            self._wantsQI = desc.get('wantsQI', None)
         self.wrapperCache = (not self.interface.isCallback() and
                              (self.nativeOwnership == 'worker' or
                               (self.nativeOwnership != 'owned' and
                                desc.get('wrapperCache', True))))
 
         def make_name(name):
             return name + "_workers" if self.workers else name
         self.name = make_name(interface.identifier.name)
@@ -472,36 +470,16 @@ class Descriptor(DescriptorProvider):
         static methods or attributes.
         """
         return (self.interface.isExternal() or self.concrete or
             self.interface.getExtendedAttribute("PrefControlled") or
             self.interface.hasInterfacePrototypeObject() or
             any((m.isAttr() or m.isMethod()) and m.isStatic() for m
                 in self.interface.members))
 
-    def wantsQI(self):
-        # If it was specified explicitly use that.
-        if hasattr(self, '_wantsQI'):
-            return self._wantsQI
-
-        # Make sure to not stick QueryInterface on abstract interfaces that
-        # have hasXPConnectImpls (like EventTarget).  So only put it on
-        # interfaces that are concrete and all of whose ancestors are abstract.
-        def allAncestorsAbstract(iface):
-            if not iface.parent:
-                return True
-            desc = self.getDescriptor(iface.parent.identifier.name)
-            if desc.concrete:
-                return False
-            return allAncestorsAbstract(iface.parent)
-        return (not self.workers and
-                self.interface.hasInterfacePrototypeObject() and
-                self.concrete and
-                allAncestorsAbstract(self.interface))
-
 # Some utility methods
 def getTypesFromDescriptor(descriptor):
     """
     Get all argument and return types for all members of the descriptor
     """
     members = [m for m in descriptor.interface.members]
     if descriptor.interface.ctor():
         members.append(descriptor.interface.ctor())
new file mode 100644
--- /dev/null
+++ b/dom/imptests/failures/html/dom/Makefile.in
@@ -0,0 +1,6 @@
+# THIS FILE IS AUTOGENERATED BY parseFailures.py - DO NOT EDIT
+
+MOCHITEST_FILES := \
+  test_historical.html.json \
+  test_interfaces.html.json \
+  $(NULL)
new file mode 100644
--- /dev/null
+++ b/dom/imptests/failures/html/dom/collections/Makefile.in
@@ -0,0 +1,5 @@
+# THIS FILE IS AUTOGENERATED BY parseFailures.py - DO NOT EDIT
+
+MOCHITEST_FILES := \
+  test_HTMLCollection-empty-name.html.json \
+  $(NULL)
new file mode 100644
--- /dev/null
+++ b/dom/imptests/failures/html/dom/collections/moz.build
@@ -0,0 +1,4 @@
+# THIS FILE IS AUTOGENERATED BY parseFailures.py - DO NOT EDIT
+
+DIRS += [
+]
new file mode 100644
--- /dev/null
+++ b/dom/imptests/failures/html/dom/collections/test_HTMLCollection-empty-name.html.json
@@ -0,0 +1,9 @@
+{
+  "Empty string as a name for Document.getElementsByTagName": true,
+  "Empty string as a name for Element.getElementsByTagName": true,
+  "Empty string as a name for Document.getElementsByTagNameNS": true,
+  "Empty string as a name for Element.getElementsByTagNameNS": true,
+  "Empty string as a name for Document.getElementsByClassName": true,
+  "Empty string as a name for Element.getElementsByClassName": true,
+  "Empty string as a name for Element.children": true
+}
new file mode 100644
--- /dev/null
+++ b/dom/imptests/failures/html/dom/errors/Makefile.in
@@ -0,0 +1,5 @@
+# THIS FILE IS AUTOGENERATED BY parseFailures.py - DO NOT EDIT
+
+MOCHITEST_FILES := \
+  test_exceptions.html.json \
+  $(NULL)
new file mode 100644
--- /dev/null
+++ b/dom/imptests/failures/html/dom/errors/moz.build
@@ -0,0 +1,4 @@
+# THIS FILE IS AUTOGENERATED BY parseFailures.py - DO NOT EDIT
+
+DIRS += [
+]
rename from dom/imptests/failures/webapps/DOMCore/tests/approved/test_exceptions.html.json
rename to dom/imptests/failures/html/dom/errors/test_exceptions.html.json
new file mode 100644
--- /dev/null
+++ b/dom/imptests/failures/html/dom/moz.build
@@ -0,0 +1,4 @@
+# THIS FILE IS AUTOGENERATED BY parseFailures.py - DO NOT EDIT
+
+DIRS += [
+]
new file mode 100644
--- /dev/null
+++ b/dom/imptests/failures/html/dom/nodes/Makefile.in
@@ -0,0 +1,14 @@
+# THIS FILE IS AUTOGENERATED BY parseFailures.py - DO NOT EDIT
+
+MOCHITEST_FILES := \
+  test_Document-createElement-namespace.html.json \
+  test_Document-createElementNS.html.json \
+  test_Document-createEvent.html.json \
+  test_Document-getElementsByTagName.html.json \
+  test_Node-isEqualNode.xhtml.json \
+  test_Node-properties.html.json \
+  test_attributes.html.json \
+  test_case.html.json \
+  test_getElementsByClassName-10.xml.json \
+  test_getElementsByClassName-11.xml.json \
+  $(NULL)
new file mode 100644
--- /dev/null
+++ b/dom/imptests/failures/html/dom/nodes/moz.build
@@ -0,0 +1,4 @@
+# THIS FILE IS AUTOGENERATED BY parseFailures.py - DO NOT EDIT
+
+DIRS += [
+]
new file mode 100644
--- /dev/null
+++ b/dom/imptests/failures/html/dom/nodes/test_Document-createElement-namespace.html.json
@@ -0,0 +1,12 @@
+{
+  "Created element's namespace in empty.xml": true,
+  "Created element's namespace in xhtml.xml": true,
+  "Created element's namespace in svg.xml": true,
+  "Created element's namespace in mathml.xml": true,
+  "Created element's namespace in minimal_html.xml": true,
+  "Created element's namespace in xhtml_ns_removed.xml": true,
+  "Created element's namespace in xhtml_ns_changed.xml": true,
+  "Created element's namespace in bare_xhtml.xml": true,
+  "Created element's namespace in bare_svg.xml": true,
+  "Created element's namespace in bare_mathml.xml": true
+}
rename from dom/imptests/failures/webapps/DOMCore/tests/submissions/Ms2ger/test_Document-createElementNS.html.json
rename to dom/imptests/failures/html/dom/nodes/test_Document-createElementNS.html.json
new file mode 100644
--- /dev/null
+++ b/dom/imptests/failures/html/dom/nodes/test_Document-createEvent.html.json
@@ -0,0 +1,26 @@
+{
+  "createEvent('CustomEvent') should be initialized correctly.": true,
+  "createEvent('customevent') should be initialized correctly.": true,
+  "createEvent('CUSTOMEVENT') should be initialized correctly.": true,
+  "createEvent('Event') should be initialized correctly.": true,
+  "createEvent('event') should be initialized correctly.": true,
+  "createEvent('EVENT') should be initialized correctly.": true,
+  "createEvent('Events') should be initialized correctly.": true,
+  "createEvent('events') should be initialized correctly.": true,
+  "createEvent('EVENTS') should be initialized correctly.": true,
+  "createEvent('HTMLEvents') should be initialized correctly.": true,
+  "createEvent('htmlevents') should be initialized correctly.": true,
+  "createEvent('HTMLEVENTS') should be initialized correctly.": true,
+  "createEvent('MouseEvent') should be initialized correctly.": true,
+  "createEvent('mouseevent') should be initialized correctly.": true,
+  "createEvent('MOUSEEVENT') should be initialized correctly.": true,
+  "createEvent('MouseEvents') should be initialized correctly.": true,
+  "createEvent('mouseevents') should be initialized correctly.": true,
+  "createEvent('MOUSEEVENTS') should be initialized correctly.": true,
+  "createEvent('UIEvent') should be initialized correctly.": true,
+  "createEvent('uievent') should be initialized correctly.": true,
+  "createEvent('UIEVENT') should be initialized correctly.": true,
+  "createEvent('UIEvents') should be initialized correctly.": true,
+  "createEvent('uievents') should be initialized correctly.": true,
+  "createEvent('UIEVENTS') should be initialized correctly.": true
+}
rename from dom/imptests/failures/webapps/DOMCore/tests/submissions/Ms2ger/test_Document-getElementsByTagName.html.json
rename to dom/imptests/failures/html/dom/nodes/test_Document-getElementsByTagName.html.json
rename from dom/imptests/failures/webapps/DOMCore/tests/submissions/Ms2ger/test_Node-isEqualNode.xhtml.json
rename to dom/imptests/failures/html/dom/nodes/test_Node-isEqualNode.xhtml.json
rename from dom/imptests/failures/webapps/DOMCore/tests/approved/test_Node-properties.html.json
rename to dom/imptests/failures/html/dom/nodes/test_Node-properties.html.json
rename from dom/imptests/failures/webapps/DOMCore/tests/submissions/Ms2ger/test_attributes.html.json
rename to dom/imptests/failures/html/dom/nodes/test_attributes.html.json
rename from dom/imptests/failures/webapps/DOMCore/tests/submissions/Ms2ger/test_case.html.json
rename to dom/imptests/failures/html/dom/nodes/test_case.html.json
rename from dom/imptests/failures/webapps/DOMCore/tests/submissions/Opera/test_getElementsByClassName-10.xml.json
rename to dom/imptests/failures/html/dom/nodes/test_getElementsByClassName-10.xml.json
rename from dom/imptests/failures/webapps/DOMCore/tests/submissions/Opera/test_getElementsByClassName-11.xml.json
rename to dom/imptests/failures/html/dom/nodes/test_getElementsByClassName-11.xml.json
new file mode 100644
--- /dev/null
+++ b/dom/imptests/failures/html/dom/ranges/moz.build
@@ -0,0 +1,4 @@
+# THIS FILE IS AUTOGENERATED BY parseFailures.py - DO NOT EDIT
+
+DIRS += [
+]
rename from dom/imptests/failures/webapps/DOMCore/tests/approved/test_Range-cloneContents.html.json
rename to dom/imptests/failures/html/dom/ranges/test_Range-cloneContents.html.json
rename from dom/imptests/failures/webapps/DOMCore/tests/approved/test_Range-cloneRange.html.json
rename to dom/imptests/failures/html/dom/ranges/test_Range-cloneRange.html.json
rename from dom/imptests/failures/webapps/DOMCore/tests/approved/test_Range-collapse.html.json
rename to dom/imptests/failures/html/dom/ranges/test_Range-collapse.html.json
rename from dom/imptests/failures/webapps/DOMCore/tests/approved/test_Range-commonAncestorContainer.html.json
rename to dom/imptests/failures/html/dom/ranges/test_Range-commonAncestorContainer.html.json
rename from dom/imptests/failures/webapps/DOMCore/tests/approved/test_Range-compareBoundaryPoints.html.json
rename to dom/imptests/failures/html/dom/ranges/test_Range-compareBoundaryPoints.html.json
rename from dom/imptests/failures/webapps/DOMCore/tests/approved/test_Range-comparePoint.html.json
rename to dom/imptests/failures/html/dom/ranges/test_Range-comparePoint.html.json
rename from dom/imptests/failures/webapps/DOMCore/tests/approved/test_Range-deleteContents.html.json
rename to dom/imptests/failures/html/dom/ranges/test_Range-deleteContents.html.json
rename from dom/imptests/failures/webapps/DOMCore/tests/approved/test_Range-extractContents.html.json
rename to dom/imptests/failures/html/dom/ranges/test_Range-extractContents.html.json
rename from dom/imptests/failures/webapps/DOMCore/tests/approved/test_Range-intersectsNode.html.json
rename to dom/imptests/failures/html/dom/ranges/test_Range-intersectsNode.html.json
rename from dom/imptests/failures/webapps/DOMCore/tests/approved/test_Range-isPointInRange.html.json
rename to dom/imptests/failures/html/dom/ranges/test_Range-isPointInRange.html.json
rename from dom/imptests/failures/webapps/DOMCore/tests/approved/test_Range-set.html.json
rename to dom/imptests/failures/html/dom/ranges/test_Range-set.html.json
rename from dom/imptests/failures/webapps/DOMCore/tests/submissions/Ms2ger/test_historical.html.json
rename to dom/imptests/failures/html/dom/test_historical.html.json
rename from dom/imptests/failures/webapps/DOMCore/tests/approved/test_interfaces.html.json
rename to dom/imptests/failures/html/dom/test_interfaces.html.json
--- a/dom/imptests/failures/webapps/DOMCore/tests/approved/test_interfaces.html.json
+++ b/dom/imptests/failures/html/dom/test_interfaces.html.json
@@ -1,88 +1,51 @@
 {
-  "DOMException exception: existence and properties of exception interface object": true,
   "DOMException exception: existence and properties of exception interface prototype object": true,
   "DOMException exception: existence and properties of exception interface prototype object's \"name\" property": true,
-  "DOMException exception: existence and properties of exception interface prototype object's \"constructor\" property": true,
-  "DOMException exception: constant INDEX_SIZE_ERR on exception interface prototype object": true,
-  "DOMException exception: constant DOMSTRING_SIZE_ERR on exception interface prototype object": true,
-  "DOMException exception: constant HIERARCHY_REQUEST_ERR on exception interface prototype object": true,
-  "DOMException exception: constant WRONG_DOCUMENT_ERR on exception interface prototype object": true,
-  "DOMException exception: constant INVALID_CHARACTER_ERR on exception interface prototype object": true,
-  "DOMException exception: constant NO_DATA_ALLOWED_ERR on exception interface prototype object": true,
-  "DOMException exception: constant NO_MODIFICATION_ALLOWED_ERR on exception interface prototype object": true,
-  "DOMException exception: constant NOT_FOUND_ERR on exception interface prototype object": true,
-  "DOMException exception: constant NOT_SUPPORTED_ERR on exception interface prototype object": true,
-  "DOMException exception: constant INUSE_ATTRIBUTE_ERR on exception interface prototype object": true,
-  "DOMException exception: constant INVALID_STATE_ERR on exception interface prototype object": true,
-  "DOMException exception: constant SYNTAX_ERR on exception interface prototype object": true,
-  "DOMException exception: constant INVALID_MODIFICATION_ERR on exception interface prototype object": true,
-  "DOMException exception: constant NAMESPACE_ERR on exception interface prototype object": true,
-  "DOMException exception: constant INVALID_ACCESS_ERR on exception interface prototype object": true,
-  "DOMException exception: constant VALIDATION_ERR on exception interface prototype object": true,
-  "DOMException exception: constant TYPE_MISMATCH_ERR on exception interface prototype object": true,
-  "DOMException exception: constant SECURITY_ERR on exception interface prototype object": true,
-  "DOMException exception: constant NETWORK_ERR on exception interface prototype object": true,
-  "DOMException exception: constant ABORT_ERR on exception interface prototype object": true,
-  "DOMException exception: constant URL_MISMATCH_ERR on exception interface prototype object": true,
-  "DOMException exception: constant QUOTA_EXCEEDED_ERR on exception interface prototype object": true,
-  "DOMException exception: constant TIMEOUT_ERR on exception interface prototype object": true,
-  "DOMException exception: constant INVALID_NODE_TYPE_ERR on exception interface prototype object": true,
-  "DOMException exception: constant DATA_CLONE_ERR on exception interface prototype object": true,
-  "DOMException exception: field code on exception interface prototype object": true,
   "Event interface: document.createEvent(\"Event\") must have own property \"isTrusted\"": true,
   "Event interface: document.createEvent(\"Event\") must inherit property \"timeStamp\" with the proper type (15)": true,
   "Event interface: new Event(\"foo\") must have own property \"isTrusted\"": true,
   "Event interface: new Event(\"foo\") must inherit property \"timeStamp\" with the proper type (15)": true,
   "CustomEvent interface: existence and properties of interface object": true,
   "Event interface: new CustomEvent(\"foo\") must have own property \"isTrusted\"": true,
   "Event interface: new CustomEvent(\"foo\") must inherit property \"timeStamp\" with the proper type (15)": true,
+  "EventListener interface: existence and properties of interface prototype object": true,
+  "EventListener interface: existence and properties of interface prototype object's \"constructor\" property": true,
+  "EventListener interface: operation handleEvent(Event)": true,
   "MutationObserver interface: operation observe(Node,MutationObserverInit)": true,
-  "Document interface: attribute children": true,
-  "Document interface: attribute firstElementChild": true,
-  "Document interface: attribute lastElementChild": true,
-  "Document interface: attribute childElementCount": true,
+  "Node interface: existence and properties of interface object": true,
+  "Document interface: existence and properties of interface object": true,
   "Document interface: operation prepend(union)": true,
   "Document interface: operation append(union)": true,
-  "Document interface: xmlDoc must inherit property \"children\" with the proper type (24)": true,
-  "Document interface: xmlDoc must inherit property \"firstElementChild\" with the proper type (25)": true,
-  "Document interface: xmlDoc must inherit property \"lastElementChild\" with the proper type (26)": true,
-  "Document interface: xmlDoc must inherit property \"childElementCount\" with the proper type (27)": true,
+  "XMLDocument interface: existence and properties of interface object": true,
   "Document interface: xmlDoc must inherit property \"prepend\" with the proper type (28)": true,
   "Document interface: calling prepend(union) on xmlDoc with too few arguments must throw TypeError": true,
   "Document interface: xmlDoc must inherit property \"append\" with the proper type (29)": true,
   "Document interface: calling append(union) on xmlDoc with too few arguments must throw TypeError": true,
-  "DocumentFragment interface: attribute children": true,
-  "DocumentFragment interface: attribute firstElementChild": true,
-  "DocumentFragment interface: attribute lastElementChild": true,
-  "DocumentFragment interface: attribute childElementCount": true,
+  "DOMImplementation interface: operation createDocument(DOMString,DOMString,DocumentType)": true,
+  "DOMImplementation interface: calling createDocument(DOMString,DOMString,DocumentType) on document.implementation with too few arguments must throw TypeError": true,
+  "DocumentFragment interface: existence and properties of interface object": true,
   "DocumentFragment interface: operation prepend(union)": true,
   "DocumentFragment interface: operation append(union)": true,
-  "DocumentFragment interface: document.createDocumentFragment() must inherit property \"children\" with the proper type (0)": true,
-  "DocumentFragment interface: document.createDocumentFragment() must inherit property \"firstElementChild\" with the proper type (1)": true,
-  "DocumentFragment interface: document.createDocumentFragment() must inherit property \"lastElementChild\" with the proper type (2)": true,
-  "DocumentFragment interface: document.createDocumentFragment() must inherit property \"childElementCount\" with the proper type (3)": true,
   "DocumentFragment interface: document.createDocumentFragment() must inherit property \"prepend\" with the proper type (4)": true,
   "DocumentFragment interface: calling prepend(union) on document.createDocumentFragment() with too few arguments must throw TypeError": true,
   "DocumentFragment interface: document.createDocumentFragment() must inherit property \"append\" with the proper type (5)": true,
   "DocumentFragment interface: calling append(union) on document.createDocumentFragment() with too few arguments must throw TypeError": true,
-  "DocumentType interface: attribute previousElementSibling": true,
-  "DocumentType interface: attribute nextElementSibling": true,
+  "DocumentType interface: existence and properties of interface object": true,
   "DocumentType interface: operation before(union)": true,
   "DocumentType interface: operation after(union)": true,
   "DocumentType interface: operation replace(union)": true,
-  "DocumentType interface: document.doctype must inherit property \"previousElementSibling\" with the proper type (3)": true,
-  "DocumentType interface: document.doctype must inherit property \"nextElementSibling\" with the proper type (4)": true,
   "DocumentType interface: document.doctype must inherit property \"before\" with the proper type (5)": true,
   "DocumentType interface: calling before(union) on document.doctype with too few arguments must throw TypeError": true,
   "DocumentType interface: document.doctype must inherit property \"after\" with the proper type (6)": true,
   "DocumentType interface: calling after(union) on document.doctype with too few arguments must throw TypeError": true,
   "DocumentType interface: document.doctype must inherit property \"replace\" with the proper type (7)": true,
   "DocumentType interface: calling replace(union) on document.doctype with too few arguments must throw TypeError": true,
+  "Element interface: existence and properties of interface object": true,
   "Element interface: attribute namespaceURI": true,
   "Element interface: attribute prefix": true,
   "Element interface: attribute localName": true,
   "Element interface: attribute className": true,
   "Element interface: operation prepend(union)": true,
   "Element interface: operation append(union)": true,
   "Element interface: operation before(union)": true,
   "Element interface: operation after(union)": true,
@@ -93,53 +56,43 @@
   "Element interface: element must inherit property \"append\" with the proper type (24)": true,
   "Element interface: calling append(union) on element with too few arguments must throw TypeError": true,
   "Element interface: element must inherit property \"before\" with the proper type (27)": true,
   "Element interface: calling before(union) on element with too few arguments must throw TypeError": true,
   "Element interface: element must inherit property \"after\" with the proper type (28)": true,
   "Element interface: calling after(union) on element with too few arguments must throw TypeError": true,
   "Element interface: element must inherit property \"replace\" with the proper type (29)": true,
   "Element interface: calling replace(union) on element with too few arguments must throw TypeError": true,
+  "Attr interface: existence and properties of interface object": true,
   "Attr interface: existence and properties of interface prototype object": true,
-  "CharacterData interface: attribute previousElementSibling": true,
-  "CharacterData interface: attribute nextElementSibling": true,
+  "CharacterData interface: existence and properties of interface object": true,
   "CharacterData interface: operation before(union)": true,
   "CharacterData interface: operation after(union)": true,
   "CharacterData interface: operation replace(union)": true,
-  "CharacterData interface: document.createTextNode(\"abc\") must inherit property \"previousElementSibling\" with the proper type (7)": true,
-  "CharacterData interface: document.createTextNode(\"abc\") must inherit property \"nextElementSibling\" with the proper type (8)": true,
+  "Text interface: existence and properties of interface object": true,
   "CharacterData interface: document.createTextNode(\"abc\") must inherit property \"before\" with the proper type (9)": true,
   "CharacterData interface: calling before(union) on document.createTextNode(\"abc\") with too few arguments must throw TypeError": true,
   "CharacterData interface: document.createTextNode(\"abc\") must inherit property \"after\" with the proper type (10)": true,
   "CharacterData interface: calling after(union) on document.createTextNode(\"abc\") with too few arguments must throw TypeError": true,
   "CharacterData interface: document.createTextNode(\"abc\") must inherit property \"replace\" with the proper type (11)": true,
   "CharacterData interface: calling replace(union) on document.createTextNode(\"abc\") with too few arguments must throw TypeError": true,
-  "CharacterData interface: xmlDoc.createProcessingInstruction(\"abc\", \"def\") must inherit property \"previousElementSibling\" with the proper type (7)": true,
-  "CharacterData interface: xmlDoc.createProcessingInstruction(\"abc\", \"def\") must inherit property \"nextElementSibling\" with the proper type (8)": true,
+  "ProcessingInstruction interface: existence and properties of interface object": true,
   "CharacterData interface: xmlDoc.createProcessingInstruction(\"abc\", \"def\") must inherit property \"before\" with the proper type (9)": true,
   "CharacterData interface: calling before(union) on xmlDoc.createProcessingInstruction(\"abc\", \"def\") with too few arguments must throw TypeError": true,
   "CharacterData interface: xmlDoc.createProcessingInstruction(\"abc\", \"def\") must inherit property \"after\" with the proper type (10)": true,
   "CharacterData interface: calling after(union) on xmlDoc.createProcessingInstruction(\"abc\", \"def\") with too few arguments must throw TypeError": true,
   "CharacterData interface: xmlDoc.createProcessingInstruction(\"abc\", \"def\") must inherit property \"replace\" with the proper type (11)": true,
   "CharacterData interface: calling replace(union) on xmlDoc.createProcessingInstruction(\"abc\", \"def\") with too few arguments must throw TypeError": true,
-  "CharacterData interface: document.createComment(\"abc\") must inherit property \"previousElementSibling\" with the proper type (7)": true,
-  "CharacterData interface: document.createComment(\"abc\") must inherit property \"nextElementSibling\" with the proper type (8)": true,
+  "Comment interface: existence and properties of interface object": true,
   "CharacterData interface: document.createComment(\"abc\") must inherit property \"before\" with the proper type (9)": true,
   "CharacterData interface: calling before(union) on document.createComment(\"abc\") with too few arguments must throw TypeError": true,
   "CharacterData interface: document.createComment(\"abc\") must inherit property \"after\" with the proper type (10)": true,
   "CharacterData interface: calling after(union) on document.createComment(\"abc\") with too few arguments must throw TypeError": true,
   "CharacterData interface: document.createComment(\"abc\") must inherit property \"replace\" with the proper type (11)": true,
   "CharacterData interface: calling replace(union) on document.createComment(\"abc\") with too few arguments must throw TypeError": true,
-  "Node interface: existence and properties of interface object": true,
-  "Document interface: existence and properties of interface object": true,
-  "XMLDocument interface: existence and properties of interface object": true,
-  "DocumentFragment interface: existence and properties of interface object": true,
-  "DocumentType interface: existence and properties of interface object": true,
-  "Element interface: existence and properties of interface object": true,
-  "Attr interface: existence and properties of interface object": true,
-  "CharacterData interface: existence and properties of interface object": true,
-  "Text interface: existence and properties of interface object": true,
-  "ProcessingInstruction interface: existence and properties of interface object": true,
-  "Comment interface: existence and properties of interface object": true,
-  "DOMSettableTokenList interface: existence and properties of interface object": true,
   "NodeFilter interface: existence and properties of interface object": true,
-  "NodeList interface: existence and properties of interface prototype object": true
+  "NodeList interface: existence and properties of interface prototype object": true,
+  "DOMTokenList interface: operation add(DOMString)": true,
+  "DOMTokenList interface: operation remove(DOMString)": true,
+  "DOMTokenList interface: calling add(DOMString) on document.body.classList with too few arguments must throw TypeError": true,
+  "DOMTokenList interface: calling remove(DOMString) on document.body.classList with too few arguments must throw TypeError": true,
+  "DOMSettableTokenList interface: existence and properties of interface object": true
 }
deleted file mode 100644
--- a/dom/imptests/failures/html/html/dom/elements/global-attributes/Makefile.in
+++ /dev/null
@@ -1,5 +0,0 @@
-# THIS FILE IS AUTOGENERATED BY parseFailures.py - DO NOT EDIT
-
-MOCHITEST_FILES := \
-  test_document-dir.html.json \
-  $(NULL)
deleted file mode 100644
--- a/dom/imptests/failures/html/html/dom/elements/global-attributes/test_document-dir.html.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-  "Setting the idl attribute to the empty sting": true
-}
rename from dom/imptests/failures/html/old-tests/submission/Opera/microdata/Makefile.in
rename to dom/imptests/failures/html/microdata/microdata-dom-api/Makefile.in
rename from dom/imptests/failures/html/old-tests/submission/Opera/microdata/moz.build
rename to dom/imptests/failures/html/microdata/microdata-dom-api/moz.build
rename from dom/imptests/failures/html/old-tests/submission/Opera/microdata/test_001.html.json
rename to dom/imptests/failures/html/microdata/microdata-dom-api/test_001.html.json
deleted file mode 100644
--- a/dom/imptests/failures/webapps/DOMCore/tests/approved/Makefile.in
+++ /dev/null
@@ -1,18 +0,0 @@
-# THIS FILE IS AUTOGENERATED BY parseFailures.py - DO NOT EDIT
-
-MOCHITEST_FILES := \
-  test_Node-properties.html.json \
-  test_Range-cloneContents.html.json \
-  test_Range-cloneRange.html.json \
-  test_Range-collapse.html.json \
-  test_Range-commonAncestorContainer.html.json \
-  test_Range-compareBoundaryPoints.html.json \
-  test_Range-comparePoint.html.json \
-  test_Range-deleteContents.html.json \
-  test_Range-extractContents.html.json \
-  test_Range-intersectsNode.html.json \
-  test_Range-isPointInRange.html.json \
-  test_Range-set.html.json \
-  test_exceptions.html.json \
-  test_interfaces.html.json \
-  $(NULL)
deleted file mode 100644
--- a/dom/imptests/failures/webapps/DOMCore/tests/approved/moz.build
+++ /dev/null
@@ -1,5 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# THIS FILE IS AUTOGENERATED BY parseFailures.py - DO NOT EDIT
-
-DIRS += [
-]
deleted file mode 100644
--- a/dom/imptests/failures/webapps/DOMCore/tests/approved/test_Range-mutations.html.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-  "paras[0].firstChild.splitText(1), with unselected range on paras[0] from 0 to 1": true,
-  "paras[0].firstChild.splitText(1), with selected range on paras[0] from 0 to 1": true,
-  "paras[0].firstChild.splitText(1), with unselected range collapsed at (paras[0], 1)": true,
-  "paras[0].firstChild.splitText(1), with selected range collapsed at (paras[0], 1)": true,
-  "paras[0].firstChild.splitText(1), with unselected range from (paras[0].firstChild, 1) to (paras[0], 1)": true,
-  "paras[0].firstChild.splitText(1), with selected range from (paras[0].firstChild, 1) to (paras[0], 1)": true,
-  "paras[0].firstChild.splitText(2), with unselected range from (paras[0].firstChild, 1) to (paras[0], 1)": true,
-  "paras[0].firstChild.splitText(2), with selected range from (paras[0].firstChild, 1) to (paras[0], 1)": true,
-  "paras[0].firstChild.splitText(3), with unselected range from (paras[0].firstChild, 1) to (paras[0], 1)": true,
-  "paras[0].firstChild.splitText(3), with selected range from (paras[0].firstChild, 1) to (paras[0], 1)": true
-}
--- a/dom/imptests/failures/webapps/DOMCore/tests/submissions/Ms2ger/Makefile.in
+++ b/dom/imptests/failures/webapps/DOMCore/tests/submissions/Ms2ger/Makefile.in
@@ -1,10 +0,0 @@
-# THIS FILE IS AUTOGENERATED BY parseFailures.py - DO NOT EDIT
-
-MOCHITEST_FILES := \
-  test_Document-createElementNS.html.json \
-  test_Document-getElementsByTagName.html.json \
-  test_Node-isEqualNode.xhtml.json \
-  test_attributes.html.json \
-  test_case.html.json \
-  test_historical.html.json \
-  $(NULL)
deleted file mode 100644
--- a/dom/imptests/failures/webapps/DOMCore/tests/submissions/Ms2ger/moz.build
+++ /dev/null
@@ -1,5 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# THIS FILE IS AUTOGENERATED BY parseFailures.py - DO NOT EDIT
-
-DIRS += [
-]
deleted file mode 100644
--- a/dom/imptests/failures/webapps/DOMCore/tests/submissions/Ms2ger/test_DOMImplementation-createDocument.html.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-  "createDocument test 91: null,null,DocumentType node,\"WRONG_DOCUMENT_ERR\"": true,
-  "createDocument test 92: null,null,DocumentType node,\"WRONG_DOCUMENT_ERR\"": true,
-  "createDocument test 94: null,null,DocumentType node,\"WRONG_DOCUMENT_ERR\"": true
-}
deleted file mode 100644
--- a/dom/imptests/failures/webapps/DOMCore/tests/submissions/Ms2ger/test_Node-replaceChild.html.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-  "If the context node is not a node that can contain children, a NotFoundError exception should be thrown": true
-}
deleted file mode 100644
--- a/dom/imptests/failures/webapps/DOMCore/tests/submissions/Ms2ger/test_NodeFilter-constants.html.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-  "Constants for acceptNode on NodeFilter prototype object.": true,
-  "Constants for whatToShow on NodeFilter prototype object.": true
-}
deleted file mode 100644
--- a/dom/imptests/failures/webapps/DOMCore/tests/submissions/Ms2ger/test_Range-intersectsNode.html.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-  "Range.intersectsNode": true,
-  "Range.intersectsNode 1": true,
-  "Range.intersectsNode 2": true
-}
--- a/dom/imptests/failures/webapps/DOMCore/tests/submissions/Opera/Makefile.in
+++ b/dom/imptests/failures/webapps/DOMCore/tests/submissions/Opera/Makefile.in
@@ -1,6 +0,0 @@
-# THIS FILE IS AUTOGENERATED BY parseFailures.py - DO NOT EDIT
-
-MOCHITEST_FILES := \
-  test_getElementsByClassName-10.xml.json \
-  test_getElementsByClassName-11.xml.json \
-  $(NULL)
deleted file mode 100644
--- a/dom/imptests/failures/webapps/DOMCore/tests/submissions/Opera/moz.build
+++ /dev/null
@@ -1,5 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# THIS FILE IS AUTOGENERATED BY parseFailures.py - DO NOT EDIT
-
-DIRS += [
-]
--- a/dom/imptests/html.mozbuild
+++ b/dom/imptests/html.mozbuild
@@ -1,11 +1,20 @@
 # THIS FILE IS AUTOGENERATED BY importTestsuite.py - DO NOT EDIT
 
 DIRS += [
+    'html/dom',
+    'html/dom/collections',
+    'html/dom/errors',
+    'html/dom/events',
+    'html/dom/nodes',
+    'html/dom/nodes/Document-createElement-namespace-tests',
+    'html/dom/ranges',
+    'html/dom/traversal',
+    'html/dom/traversal/unfinished',
     'html/domxpath',
     'html/html/browsers/browsing-the-web/read-media',
     'html/html/browsers/the-window-object',
     'html/html/browsers/the-window-object/named-access-on-the-window-object',
     'html/html/dom/documents/dta',
     'html/html/dom/documents/dta/doc.gEBN',
     'html/html/dom/elements/global-attributes',
     'html/html/editing/the-hidden-attribute',
@@ -17,12 +26,12 @@ DIRS += [
     'html/html/semantics/scripting-1/the-script-element',
     'html/html/semantics/tabular-data/the-table-element',
     'html/html/semantics/text-level-semantics/the-time-element',
     'html/html/webappapis/atob',
     'html/html/webappapis/scripting/events',
     'html/html/webappapis/scripting/processing-model-2',
     'html/html/webappapis/timers',
     'html/js/builtins',
-    'html/old-tests/submission/Opera/microdata',
+    'html/microdata/microdata-dom-api',
     'html/typedarrays',
     'html/webgl',
 ]
--- a/dom/imptests/html.txt
+++ b/dom/imptests/html.txt
@@ -1,9 +1,10 @@
 git|git://github.com/w3c/web-platform-tests.git|html
+dom
 domxpath
 html/browsers/browsing-the-web/read-media
 html/browsers/the-window-object
 html/dom/documents/dom-tree-accessors
 html/dom/elements/global-attributes
 html/editing/the-hidden-attribute
 html/obsolete/requirements-for-implementations/other-elements-attributes-and-apis
 html/semantics/document-metadata/the-title-element
@@ -13,11 +14,11 @@ html/semantics/forms/the-select-element
 html/semantics/scripting-1/the-script-element
 html/semantics/tabular-data/the-table-element
 html/semantics/text-level-semantics/the-time-element
 html/webappapis/atob
 html/webappapis/scripting/events
 html/webappapis/scripting/processing-model-2
 html/webappapis/timers
 js/builtins
-old-tests/submission/Opera/microdata
+microdata/microdata-dom-api
 typedarrays
 webgl
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/Makefile.in
@@ -0,0 +1,9 @@
+# THIS FILE IS AUTOGENERATED BY importTestsuite.py - DO NOT EDIT
+
+MOCHITEST_FILES := \
+  test_historical.html \
+  test_interface-objects.html \
+  test_interfaces.html \
+  common.js \
+  constants.js \
+  $(NULL)
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/collections/Makefile.in
@@ -0,0 +1,5 @@
+# THIS FILE IS AUTOGENERATED BY importTestsuite.py - DO NOT EDIT
+
+MOCHITEST_FILES := \
+  test_HTMLCollection-empty-name.html \
+  $(NULL)
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/collections/moz.build
@@ -0,0 +1,4 @@
+# THIS FILE IS AUTOGENERATED BY importTestsuite.py - DO NOT EDIT
+
+DIRS += [
+]
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/collections/test_HTMLCollection-empty-name.html
@@ -0,0 +1,65 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>HTMLCollection and empty names</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<div id=test>
+<div class=a id></div>
+<div class=a name></div>
+<a class=a name></a>
+</div>
+<script>
+test(function() {
+  var c = document.getElementsByTagName("*");
+  assert_false("" in c, "Empty string should not be in the collection.");
+  assert_equals(c[""], undefined, "Named getter should return undefined for empty string.");
+  assert_equals(c.namedItem(""), null, "namedItem should return null for empty string.");
+}, "Empty string as a name for Document.getElementsByTagName");
+
+test(function() {
+  var div = document.getElementById("test");
+  var c = div.getElementsByTagName("*");
+  assert_false("" in c, "Empty string should not be in the collection.");
+  assert_equals(c[""], undefined, "Named getter should return undefined for empty string.");
+  assert_equals(c.namedItem(""), null, "namedItem should return null for empty string.");
+}, "Empty string as a name for Element.getElementsByTagName");
+
+test(function() {
+  var c = document.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "a");
+  assert_false("" in c, "Empty string should not be in the collection.");
+  assert_equals(c[""], undefined, "Named getter should return undefined for empty string.");
+  assert_equals(c.namedItem(""), null, "namedItem should return null for empty string.");
+}, "Empty string as a name for Document.getElementsByTagNameNS");
+
+test(function() {
+  var div = document.getElementById("test");
+  var c = div.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "a");
+  assert_false("" in c, "Empty string should not be in the collection.");
+  assert_equals(c[""], undefined, "Named getter should return undefined for empty string.");
+  assert_equals(c.namedItem(""), null, "namedItem should return null for empty string.");
+}, "Empty string as a name for Element.getElementsByTagNameNS");
+
+test(function() {
+  var c = document.getElementsByClassName("a");
+  assert_false("" in c, "Empty string should not be in the collection.");
+  assert_equals(c[""], undefined, "Named getter should return undefined for empty string.");
+  assert_equals(c.namedItem(""), null, "namedItem should return null for empty string.");
+}, "Empty string as a name for Document.getElementsByClassName");
+
+test(function() {
+  var div = document.getElementById("test");
+  var c = div.getElementsByClassName("a");
+  assert_false("" in c, "Empty string should not be in the collection.");
+  assert_equals(c[""], undefined, "Named getter should return undefined for empty string.");
+  assert_equals(c.namedItem(""), null, "namedItem should return null for empty string.");
+}, "Empty string as a name for Element.getElementsByClassName");
+
+test(function() {
+  var div = document.getElementById("test");
+  var c = div.children;
+  assert_false("" in c, "Empty string should not be in the collection.");
+  assert_equals(c[""], undefined, "Named getter should return undefined for empty string.");
+  assert_equals(c.namedItem(""), null, "namedItem should return null for empty string.");
+}, "Empty string as a name for Element.children");
+</script>
rename from dom/imptests/webapps/DOMCore/tests/approved/common.js
rename to dom/imptests/html/dom/common.js
--- a/dom/imptests/webapps/DOMCore/tests/approved/common.js
+++ b/dom/imptests/html/dom/common.js
@@ -9,17 +9,17 @@ var selection;
 var testDiv, paras, detachedDiv, detachedPara1, detachedPara2,
 	foreignDoc, foreignPara1, foreignPara2, xmlDoc, xmlElement,
 	detachedXmlElement, detachedTextNode, foreignTextNode,
 	detachedForeignTextNode, xmlTextNode, detachedXmlTextNode,
 	processingInstruction, detachedProcessingInstruction, comment,
 	detachedComment, foreignComment, detachedForeignComment, xmlComment,
 	detachedXmlComment, docfrag, foreignDocfrag, xmlDocfrag, doctype,
 	foreignDoctype, xmlDoctype;
-var testRanges, testPoints, testNodes;
+var testRangesShort, testRanges, testPoints, testNodesShort, testNodes;
 
 function setupRangeTests() {
 	selection = getSelection();
 	testDiv = document.querySelector("#test");
 	if (testDiv) {
 		testDiv.parentNode.removeChild(testDiv);
 	}
 	testDiv = document.createElement("div");
@@ -116,85 +116,86 @@ function setupRangeTests() {
 	foreignComment = foreignDoc.createComment('"Commenter" and "commentator" mean different things.  I\'ve seen non-native speakers trip up on this.');
 	foreignDoc.appendChild(foreignComment);
 	foreignTextNode = foreignDoc.createTextNode("I admit that I harbor doubts about whether we really need so many things to test, but it's too late to stop now.");
 	foreignDoc.body.appendChild(foreignTextNode);
 
 	doctype = document.doctype;
 	foreignDoctype = foreignDoc.doctype;
 
-	testRanges = [
+	testRangesShort = [
 		// Various ranges within the text node children of different
 		// paragraphs.  All should be valid.
 		"[paras[0].firstChild, 0, paras[0].firstChild, 0]",
 		"[paras[0].firstChild, 0, paras[0].firstChild, 1]",
 		"[paras[0].firstChild, 2, paras[0].firstChild, 8]",
 		"[paras[0].firstChild, 2, paras[0].firstChild, 9]",
 		"[paras[1].firstChild, 0, paras[1].firstChild, 0]",
-		"[paras[1].firstChild, 0, paras[1].firstChild, 1]",
-		"[paras[1].firstChild, 2, paras[1].firstChild, 8]",
 		"[paras[1].firstChild, 2, paras[1].firstChild, 9]",
 		"[detachedPara1.firstChild, 0, detachedPara1.firstChild, 0]",
-		"[detachedPara1.firstChild, 0, detachedPara1.firstChild, 1]",
 		"[detachedPara1.firstChild, 2, detachedPara1.firstChild, 8]",
 		"[foreignPara1.firstChild, 0, foreignPara1.firstChild, 0]",
-		"[foreignPara1.firstChild, 0, foreignPara1.firstChild, 1]",
 		"[foreignPara1.firstChild, 2, foreignPara1.firstChild, 8]",
 		// Now try testing some elements, not just text nodes.
 		"[document.documentElement, 0, document.documentElement, 1]",
 		"[document.documentElement, 0, document.documentElement, 2]",
 		"[document.documentElement, 1, document.documentElement, 2]",
 		"[document.head, 1, document.head, 1]",
 		"[document.body, 4, document.body, 5]",
 		"[foreignDoc.documentElement, 0, foreignDoc.documentElement, 1]",
-		"[foreignDoc.head, 1, foreignDoc.head, 1]",
-		"[foreignDoc.body, 0, foreignDoc.body, 0]",
-		"[paras[0], 0, paras[0], 0]",
 		"[paras[0], 0, paras[0], 1]",
-		"[detachedPara1, 0, detachedPara1, 0]",
 		"[detachedPara1, 0, detachedPara1, 1]",
 		// Now try some ranges that span elements.
 		"[paras[0].firstChild, 0, paras[1].firstChild, 0]",
 		"[paras[0].firstChild, 0, paras[1].firstChild, 8]",
 		"[paras[0].firstChild, 3, paras[3], 1]",
 		// How about something that spans a node and its descendant?
 		"[paras[0], 0, paras[0].firstChild, 7]",
 		"[testDiv, 2, paras[4], 1]",
+		// Then a few more interesting things just for good measure.
+		"[document, 0, document, 1]",
+		"[document, 0, document, 2]",
+		"[comment, 2, comment, 3]",
+		"[testDiv, 0, comment, 5]",
+		"[foreignDoc, 1, foreignComment, 2]",
+		"[foreignDoc.body, 0, foreignTextNode, 36]",
+		"[xmlDoc, 1, xmlComment, 0]",
+		"[detachedTextNode, 0, detachedTextNode, 8]",
+		"[detachedForeignTextNode, 0, detachedForeignTextNode, 8]",
+		"[detachedXmlTextNode, 0, detachedXmlTextNode, 8]",
+		"[detachedComment, 3, detachedComment, 4]",
+		"[detachedForeignComment, 0, detachedForeignComment, 1]",
+		"[detachedXmlComment, 2, detachedXmlComment, 6]",
+		"[docfrag, 0, docfrag, 0]",
+	];
+
+	testRanges = testRangesShort.concat([
+		"[paras[1].firstChild, 0, paras[1].firstChild, 1]",
+		"[paras[1].firstChild, 2, paras[1].firstChild, 8]",
+		"[detachedPara1.firstChild, 0, detachedPara1.firstChild, 1]",
+		"[foreignPara1.firstChild, 0, foreignPara1.firstChild, 1]",
+		"[foreignDoc.head, 1, foreignDoc.head, 1]",
+		"[foreignDoc.body, 0, foreignDoc.body, 0]",
+		"[paras[0], 0, paras[0], 0]",
+		"[detachedPara1, 0, detachedPara1, 0]",
 		"[testDiv, 1, paras[2].firstChild, 5]",
 		"[document.documentElement, 1, document.body, 0]",
 		"[foreignDoc.documentElement, 1, foreignDoc.body, 0]",
-		// Then a few more interesting things just for good measure.
-		"[document, 0, document, 1]",
-		"[document, 0, document, 2]",
 		"[document, 1, document, 2]",
-		"[comment, 2, comment, 3]",
-		"[testDiv, 0, comment, 5]",
 		"[paras[2].firstChild, 4, comment, 2]",
 		"[paras[3], 1, comment, 8]",
 		"[foreignDoc, 0, foreignDoc, 0]",
-		"[foreignDoc, 1, foreignComment, 2]",
-		"[foreignDoc.body, 0, foreignTextNode, 36]",
 		"[xmlDoc, 0, xmlDoc, 0]",
-		// Opera 11 crashes if you extractContents() a range that ends at offset
-		// zero in a comment.  Comment out this line to run the tests successfully.
-		"[xmlDoc, 1, xmlComment, 0]",
-		"[detachedTextNode, 0, detachedTextNode, 8]",
 		"[detachedForeignTextNode, 7, detachedForeignTextNode, 7]",
-		"[detachedForeignTextNode, 0, detachedForeignTextNode, 8]",
 		"[detachedXmlTextNode, 7, detachedXmlTextNode, 7]",
-		"[detachedXmlTextNode, 0, detachedXmlTextNode, 8]",
-		"[detachedComment, 3, detachedComment, 4]",
 		"[detachedComment, 5, detachedComment, 5]",
-		"[detachedForeignComment, 0, detachedForeignComment, 1]",
 		"[detachedForeignComment, 4, detachedForeignComment, 4]",
-		"[detachedXmlComment, 2, detachedXmlComment, 6]",
-		"[docfrag, 0, docfrag, 0]",
 		"[foreignDocfrag, 0, foreignDocfrag, 0]",
 		"[xmlDocfrag, 0, xmlDocfrag, 0]",
-	];
+	]);
 
 	testPoints = [
 		// Various positions within the page, some invalid.  Remember that
 		// paras[0] is visible, and paras[1] is display: none.
 		"[paras[0].firstChild, -1]",
 		"[paras[0].firstChild, 0]",
 		"[paras[0].firstChild, 1]",
 		"[paras[0].firstChild, 2]",
@@ -281,55 +282,58 @@ function setupRangeTests() {
 		"[xmlDocfrag, 0]",
 		"[doctype, 0]",
 		"[doctype, -17]",
 		"[doctype, 1]",
 		"[foreignDoctype, 0]",
 		"[xmlDoctype, 0]",
 	];
 
-	testNodes = [
+	testNodesShort = [
 		"paras[0]",
 		"paras[0].firstChild",
-		"paras[1]",
 		"paras[1].firstChild",
 		"foreignPara1",
 		"foreignPara1.firstChild",
 		"detachedPara1",
 		"detachedPara1.firstChild",
-		"detachedPara2",
-		"detachedPara2.firstChild",
-		"testDiv",
 		"document",
 		"detachedDiv",
 		"foreignDoc",
 		"foreignPara2",
 		"xmlDoc",
 		"xmlElement",
-		"detachedXmlElement",
 		"detachedTextNode",
 		"foreignTextNode",
-		"detachedForeignTextNode",
-		"xmlTextNode",
-		"detachedXmlTextNode",
 		"processingInstruction",
 		"detachedProcessingInstruction",
 		"comment",
 		"detachedComment",
+		"docfrag",
+		"doctype",
+		"foreignDoctype",
+	];
+
+	testNodes = testNodesShort.concat([
+		"paras[1]",
+		"detachedPara2",
+		"detachedPara2.firstChild",
+		"testDiv",
+		"detachedXmlElement",
+		"detachedForeignTextNode",
+		"xmlTextNode",
+		"detachedXmlTextNode",
+		"xmlComment",
 		"foreignComment",
 		"detachedForeignComment",
-		"xmlComment",
 		"detachedXmlComment",
-		"docfrag",
 		"foreignDocfrag",
 		"xmlDocfrag",
-		"doctype",
-		"foreignDoctype",
 		"xmlDoctype",
-	];
+	]);
 }
 if ("setup" in window) {
 	setup(setupRangeTests);
 } else {
 	// Presumably we're running from within an iframe or something
 	setupRangeTests();
 }
 
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/constants.js
rename to dom/imptests/html/dom/constants.js
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/errors/Makefile.in
@@ -0,0 +1,6 @@
+# THIS FILE IS AUTOGENERATED BY importTestsuite.py - DO NOT EDIT
+
+MOCHITEST_FILES := \
+  test_DOMException-constants.html \
+  test_exceptions.html \
+  $(NULL)
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/errors/moz.build
@@ -0,0 +1,4 @@
+# THIS FILE IS AUTOGENERATED BY importTestsuite.py - DO NOT EDIT
+
+DIRS += [
+]
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_DOMException-constants.html
rename to dom/imptests/html/dom/errors/test_DOMException-constants.html
rename from dom/imptests/webapps/DOMCore/tests/approved/test_exceptions.html
rename to dom/imptests/html/dom/errors/test_exceptions.html
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/events/Makefile.in
@@ -0,0 +1,14 @@
+# THIS FILE IS AUTOGENERATED BY importTestsuite.py - DO NOT EDIT
+
+MOCHITEST_FILES := \
+  test_Event-constants.html \
+  test_Event-constructors.html \
+  test_Event-defaultPrevented.html \
+  test_Event-initEvent.html \
+  test_Event-propagation.html \
+  test_EventTarget-addEventListener.html \
+  test_EventTarget-dispatchEvent.html \
+  test_EventTarget-removeEventListener.html \
+  test_Event-type.html \
+  test_ProgressEvent.html \
+  $(NULL)
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/events/moz.build
@@ -0,0 +1,4 @@
+# THIS FILE IS AUTOGENERATED BY importTestsuite.py - DO NOT EDIT
+
+DIRS += [
+]
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Event-constants.html
rename to dom/imptests/html/dom/events/test_Event-constants.html
--- a/dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Event-constants.html
+++ b/dom/imptests/html/dom/events/test_Event-constants.html
@@ -1,13 +1,13 @@
 <!doctype html>
 <title>Event constants</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="constants.js"></script>
+<script src="../constants.js"></script>
 <div id="log"></div>
 <script>
 var objects = [
   [Event, "Event interface object"],
   [Event.prototype, "Event prototype object"],
   [document.createEvent("Event"), "Event object"],
   [document.createEvent("CustomEvent"), "CustomEvent object"]
 ]
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Event-constructors.html
rename to dom/imptests/html/dom/events/test_Event-constructors.html
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Event-defaultPrevented.html
rename to dom/imptests/html/dom/events/test_Event-defaultPrevented.html
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Event-initEvent.html
rename to dom/imptests/html/dom/events/test_Event-initEvent.html
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/events/test_Event-propagation.html
@@ -0,0 +1,35 @@
+<!doctype html>
+<title>Event propagation tests</title>
+<link rel=author title="Aryeh Gregor" href=ayg@aryeh.name>
+<div id=log></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+"use strict";
+
+function testPropagationFlag(ev, expected, desc) {
+	test(function() {
+		var called = false;
+		var callback = function() { called = true };
+		document.head.addEventListener("foo", callback);
+		document.head.dispatchEvent(ev);
+		assert_equals(called, expected, "Propagation flag");
+		document.head.removeEventListener("foo", callback);
+	}, desc);
+}
+
+var ev = document.createEvent("Event");
+ev.initEvent("foo", true, false);
+testPropagationFlag(ev, true, "Newly-created Event");
+ev.stopPropagation();
+testPropagationFlag(ev, false, "After stopPropagation()");
+ev.initEvent("foo", true, false);
+testPropagationFlag(ev, true, "Reinitialized after stopPropagation()");
+
+var ev = document.createEvent("Event");
+ev.initEvent("foo", true, false);
+ev.stopImmediatePropagation();
+testPropagationFlag(ev, false, "After stopImmediatePropagation()");
+ev.initEvent("foo", true, false);
+testPropagationFlag(ev, true, "Reinitialized after stopImmediatePropagation()");
+</script>
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Event-type.html
rename to dom/imptests/html/dom/events/test_Event-type.html
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/events/test_EventTarget-addEventListener.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>EventTarget.addEventListener</title>
+<link rel="author" title="Ms2ger" href="mailto:Ms2ger@gmail.com">
+<link rel="help" href="http://dom.spec.whatwg.org/#dom-eventtarget-addeventlistener">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+// Step 1.
+test(function() {
+  assert_equals(document.addEventListener("x", null, false), undefined);
+  assert_equals(document.addEventListener("x", null, true), undefined);
+  assert_equals(document.addEventListener("x", null), undefined);
+}, "Adding a null event listener should succeed");
+</script>
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_EventTarget-dispatchEvent.html
rename to dom/imptests/html/dom/events/test_EventTarget-dispatchEvent.html
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/events/test_EventTarget-removeEventListener.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>EventTarget.removeEventListener</title>
+<link rel="author" title="Ms2ger" href="mailto:Ms2ger@gmail.com">
+<link rel="help" href="http://dom.spec.whatwg.org/#dom-eventtarget-removeeventlistener">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+// Step 1.
+test(function() {
+  assert_equals(document.removeEventListener("x", null, false), undefined);
+  assert_equals(document.removeEventListener("x", null, true), undefined);
+  assert_equals(document.removeEventListener("x", null), undefined);
+}, "removing a null event listener should succeed");
+</script>
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/events/test_ProgressEvent.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<title>ProgressEvent constructor</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function() {
+  var ev = new ProgressEvent("test")
+  assert_equals(ev.type, "test")
+  assert_equals(ev.target, null)
+  assert_equals(ev.currentTarget, null)
+  assert_equals(ev.eventPhase, Event.NONE)
+  assert_equals(ev.bubbles, false)
+  assert_equals(ev.cancelable, false)
+  assert_equals(ev.defaultPrevented, false)
+  assert_equals(ev.isTrusted, false)
+  assert_true(ev.timeStamp > 0)
+  assert_true("initEvent" in ev)
+}, "Default event values.")
+test(function() {
+  assert_throws("NotSupportedError", function() {
+    document.createEvent("ProgressEvent")
+  })
+}, "document.createEvent() should not work with ProgressEvent.")
+</script>
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/moz.build
@@ -0,0 +1,4 @@
+# THIS FILE IS AUTOGENERATED BY importTestsuite.py - DO NOT EDIT
+
+DIRS += [
+]
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/ChildNode-remove.js
rename to dom/imptests/html/dom/nodes/ChildNode-remove.js
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/nodes/Document-createElement-namespace-tests/Makefile.in
@@ -0,0 +1,45 @@
+# THIS FILE IS AUTOGENERATED BY importTestsuite.py - DO NOT EDIT
+
+MOCHITEST_FILES := \
+  bare_mathml.html \
+  bare_mathml.svg \
+  bare_mathml.xhtml \
+  bare_mathml.xml \
+  bare_svg.html \
+  bare_svg.svg \
+  bare_svg.xhtml \
+  bare_svg.xml \
+  bare_xhtml.html \
+  bare_xhtml.svg \
+  bare_xhtml.xhtml \
+  bare_xhtml.xml \
+  empty.html \
+  empty.svg \
+  empty.xhtml \
+  empty.xml \
+  generate.py \
+  mathml.html \
+  mathml.svg \
+  mathml.xhtml \
+  mathml.xml \
+  minimal_html.html \
+  minimal_html.svg \
+  minimal_html.xhtml \
+  minimal_html.xml \
+  svg.html \
+  svg.svg \
+  svg.xhtml \
+  svg.xml \
+  xhtml.html \
+  xhtml_ns_changed.html \
+  xhtml_ns_changed.svg \
+  xhtml_ns_changed.xhtml \
+  xhtml_ns_changed.xml \
+  xhtml_ns_removed.html \
+  xhtml_ns_removed.svg \
+  xhtml_ns_removed.xhtml \
+  xhtml_ns_removed.xml \
+  xhtml.svg \
+  xhtml.xhtml \
+  xhtml.xml \
+  $(NULL)
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/nodes/Document-createElement-namespace-tests/bare_mathml.html
@@ -0,0 +1,1 @@
+<math></math>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/nodes/Document-createElement-namespace-tests/bare_mathml.svg
@@ -0,0 +1,1 @@
+<math></math>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/nodes/Document-createElement-namespace-tests/bare_mathml.xhtml
@@ -0,0 +1,1 @@
+<math></math>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/nodes/Document-createElement-namespace-tests/bare_mathml.xml
@@ -0,0 +1,1 @@
+<math></math>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/nodes/Document-createElement-namespace-tests/bare_svg.html
@@ -0,0 +1,1 @@
+<svg></svg>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/nodes/Document-createElement-namespace-tests/bare_svg.svg
@@ -0,0 +1,1 @@
+<svg></svg>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/nodes/Document-createElement-namespace-tests/bare_svg.xhtml
@@ -0,0 +1,1 @@
+<svg></svg>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/nodes/Document-createElement-namespace-tests/bare_svg.xml
@@ -0,0 +1,1 @@
+<svg></svg>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/nodes/Document-createElement-namespace-tests/bare_xhtml.html
@@ -0,0 +1,1 @@
+<html></html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/nodes/Document-createElement-namespace-tests/bare_xhtml.svg
@@ -0,0 +1,1 @@
+<html></html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/nodes/Document-createElement-namespace-tests/bare_xhtml.xhtml
@@ -0,0 +1,1 @@
+<html></html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/nodes/Document-createElement-namespace-tests/bare_xhtml.xml
@@ -0,0 +1,1 @@
+<html></html>
\ No newline at end of file
new file mode 100644
new file mode 100644
new file mode 100644
new file mode 100644
new file mode 100755
--- /dev/null
+++ b/dom/imptests/html/dom/nodes/Document-createElement-namespace-tests/generate.py
@@ -0,0 +1,77 @@
+#!/usr/bin/python
+import os
+import sys
+
+THIS_NAME = "generate.py"
+
+# Note: these lists must be kept in sync with the lists in
+# Document-createElement-namespace.html, and this script must be run whenever
+# the lists are updated.  (We could keep the lists in a shared JSON file, but
+# seems like too much effort.)
+FILES = (
+    ("empty", ""),
+    ("minimal_html", "<!doctype html><title></title>"),
+
+    ("xhtml", '<html xmlns="http://www.w3.org/1999/xhtml"></html>'),
+    ("svg", '<svg xmlns="http://www.w3.org/2000/svg"></svg>'),
+    ("mathml", '<mathml xmlns="http://www.w3.org/1998/Math/MathML"></mathml>'),
+
+    ("bare_xhtml", "<html></html>"),
+    ("bare_svg", "<svg></svg>"),
+    ("bare_mathml", "<math></math>"),
+
+    ("xhtml_ns_removed", """\
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head><script>
+    var newRoot = document.createElementNS(null, "html");
+    document.removeChild(document.documentElement);
+    document.appendChild(newRoot);
+  </script></head>
+</html>
+"""),
+    ("xhtml_ns_changed", """\
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head><script>
+    var newRoot = document.createElementNS("http://www.w3.org/2000/svg", "abc");
+    document.removeChild(document.documentElement);
+    document.appendChild(newRoot);
+  </script></head>
+</html>
+"""),
+)
+
+EXTENSIONS = (
+    "html",
+    "xhtml",
+    "xml",
+    "svg",
+    # Was not able to get server MIME type working properly :(
+    #"mml",
+)
+
+def __main__():
+    if len(sys.argv) > 1:
+        print "No arguments expected, aborting"
+        return
+
+    if not os.access(THIS_NAME, os.F_OK):
+        print "Must be run from the directory of " + THIS_NAME + ", aborting"
+        return
+
+    for name in os.listdir("."):
+        if name == THIS_NAME:
+            continue
+        os.remove(name)
+
+    manifest = open("MANIFEST", "w")
+
+    for name, contents in FILES:
+        for extension in EXTENSIONS:
+            f = open(name + "." + extension, "w")
+            f.write(contents)
+            f.close()
+            manifest.write("support " + name + "." + extension + "\n")
+
+    manifest.close()
+
+__main__()
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/nodes/Document-createElement-namespace-tests/mathml.html
@@ -0,0 +1,1 @@
+<mathml xmlns="http://www.w3.org/1998/Math/MathML"></mathml>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/nodes/Document-createElement-namespace-tests/mathml.svg
@@ -0,0 +1,1 @@
+<mathml xmlns="http://www.w3.org/1998/Math/MathML"></mathml>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/nodes/Document-createElement-namespace-tests/mathml.xhtml
@@ -0,0 +1,1 @@
+<mathml xmlns="http://www.w3.org/1998/Math/MathML"></mathml>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/nodes/Document-createElement-namespace-tests/mathml.xml
@@ -0,0 +1,1 @@
+<mathml xmlns="http://www.w3.org/1998/Math/MathML"></mathml>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/nodes/Document-createElement-namespace-tests/minimal_html.html
@@ -0,0 +1,1 @@
+<!doctype html><title></title>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/nodes/Document-createElement-namespace-tests/minimal_html.svg
@@ -0,0 +1,1 @@
+<!doctype html><title></title>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/nodes/Document-createElement-namespace-tests/minimal_html.xhtml
@@ -0,0 +1,1 @@
+<!doctype html><title></title>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/nodes/Document-createElement-namespace-tests/minimal_html.xml
@@ -0,0 +1,1 @@
+<!doctype html><title></title>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/nodes/Document-createElement-namespace-tests/moz.build
@@ -0,0 +1,4 @@
+# THIS FILE IS AUTOGENERATED BY importTestsuite.py - DO NOT EDIT
+
+DIRS += [
+]
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/nodes/Document-createElement-namespace-tests/svg.html
@@ -0,0 +1,1 @@
+<svg xmlns="http://www.w3.org/2000/svg"></svg>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/nodes/Document-createElement-namespace-tests/svg.svg
@@ -0,0 +1,1 @@
+<svg xmlns="http://www.w3.org/2000/svg"></svg>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/nodes/Document-createElement-namespace-tests/svg.xhtml
@@ -0,0 +1,1 @@
+<svg xmlns="http://www.w3.org/2000/svg"></svg>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/nodes/Document-createElement-namespace-tests/svg.xml
@@ -0,0 +1,1 @@
+<svg xmlns="http://www.w3.org/2000/svg"></svg>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/nodes/Document-createElement-namespace-tests/xhtml.html
@@ -0,0 +1,1 @@
+<html xmlns="http://www.w3.org/1999/xhtml"></html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/nodes/Document-createElement-namespace-tests/xhtml.svg
@@ -0,0 +1,1 @@
+<html xmlns="http://www.w3.org/1999/xhtml"></html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/nodes/Document-createElement-namespace-tests/xhtml.xhtml
@@ -0,0 +1,1 @@
+<html xmlns="http://www.w3.org/1999/xhtml"></html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/nodes/Document-createElement-namespace-tests/xhtml.xml
@@ -0,0 +1,1 @@
+<html xmlns="http://www.w3.org/1999/xhtml"></html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_changed.html
@@ -0,0 +1,7 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head><script>
+    var newRoot = document.createElementNS("http://www.w3.org/2000/svg", "abc");
+    document.removeChild(document.documentElement);
+    document.appendChild(newRoot);
+  </script></head>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_changed.svg
@@ -0,0 +1,7 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head><script>
+    var newRoot = document.createElementNS("http://www.w3.org/2000/svg", "abc");
+    document.removeChild(document.documentElement);
+    document.appendChild(newRoot);
+  </script></head>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_changed.xhtml
@@ -0,0 +1,7 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head><script>
+    var newRoot = document.createElementNS("http://www.w3.org/2000/svg", "abc");
+    document.removeChild(document.documentElement);
+    document.appendChild(newRoot);
+  </script></head>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_changed.xml
@@ -0,0 +1,7 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head><script>
+    var newRoot = document.createElementNS("http://www.w3.org/2000/svg", "abc");
+    document.removeChild(document.documentElement);
+    document.appendChild(newRoot);
+  </script></head>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_removed.html
@@ -0,0 +1,7 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head><script>
+    var newRoot = document.createElementNS(null, "html");
+    document.removeChild(document.documentElement);
+    document.appendChild(newRoot);
+  </script></head>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_removed.svg
@@ -0,0 +1,7 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head><script>
+    var newRoot = document.createElementNS(null, "html");
+    document.removeChild(document.documentElement);
+    document.appendChild(newRoot);
+  </script></head>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_removed.xhtml
@@ -0,0 +1,7 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head><script>
+    var newRoot = document.createElementNS(null, "html");
+    document.removeChild(document.documentElement);
+    document.appendChild(newRoot);
+  </script></head>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_removed.xml
@@ -0,0 +1,7 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head><script>
+    var newRoot = document.createElementNS(null, "html");
+    document.removeChild(document.documentElement);
+    document.appendChild(newRoot);
+  </script></head>
+</html>
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/Document-createProcessingInstruction.js
rename to dom/imptests/html/dom/nodes/Document-createProcessingInstruction.js
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/nodes/Makefile.in
@@ -0,0 +1,78 @@
+# THIS FILE IS AUTOGENERATED BY importTestsuite.py - DO NOT EDIT
+
+MOCHITEST_FILES := \
+  test_attributes.html \
+  test_case.html \
+  test_CharacterData-appendData.html \
+  test_CharacterData-deleteData.html \
+  test_CharacterData-insertData.html \
+  test_CharacterData-remove.html \
+  test_CharacterData-replaceData.html \
+  test_Document-adoptNode.html \
+  test_Document-createComment.html \
+  test_Document-createElement.html \
+  test_Document-createElement-namespace.html \
+  test_Document-createElementNS.html \
+  test_Document-createEvent.html \
+  test_Document-createProcessingInstruction.html \
+  test_Document-createProcessingInstruction-literal-1.xhtml \
+  test_Document-createProcessingInstruction-literal-2.xhtml \
+  test_Document-createProcessingInstruction.xhtml \
+  test_Document-createTreeWalker.html \
+  test_Document-getElementById.html \
+  test_Document-getElementsByTagName.html \
+  test_Document-getElementsByTagNameNS.html \
+  test_Document-importNode.html \
+  test_DocumentType-remove.html \
+  test_DOMImplementation-createDocument.html \
+  test_DOMImplementation-createDocumentType.html \
+  test_DOMImplementation-createHTMLDocument.html \
+  test_DOMImplementation-hasFeature.html \
+  test_Element-children.html \
+  test_Element-getElementsByClassName.html \
+  test_Element-removeAttributeNS.html \
+  test_Element-remove.html \
+  test_Element-tagName.html \
+  test_getElementsByClassName-01.htm \
+  test_getElementsByClassName-02.htm \
+  test_getElementsByClassName-03.htm \
+  test_getElementsByClassName-04.htm \
+  test_getElementsByClassName-05.htm \
+  test_getElementsByClassName-06.htm \
+  test_getElementsByClassName-07.htm \
+  test_getElementsByClassName-08.htm \
+  test_getElementsByClassName-09.htm \
+  test_getElementsByClassName-10.xml \
+  test_getElementsByClassName-11.xml \
+  test_getElementsByClassName-12.htm \
+  test_getElementsByClassName-13.htm \
+  test_getElementsByClassName-14.htm \
+  test_getElementsByClassName-15.htm \
+  test_getElementsByClassName-16.htm \
+  test_getElementsByClassName-17.htm \
+  test_getElementsByClassName-18.htm \
+  test_Node-appendChild.html \
+  test_Node-cloneNode.html \
+  test_Node-compareDocumentPosition.html \
+  test_Node-constants.html \
+  test_Node-contains.html \
+  test_Node-contains.xml \
+  test_Node-insertBefore.html \
+  test_Node-isEqualNode.xhtml \
+  test_Node-lookupPrefix.xhtml \
+  test_Node-nodeName.html \
+  test_Node-nodeName.xhtml \
+  test_Node-normalize.html \
+  test_Node-parentElement.html \
+  test_Node-parentNode.html \
+  test_Node-properties.html \
+  test_Node-removeChild.html \
+  test_Node-replaceChild.html \
+  attributes.js \
+  case.js \
+  ChildNode-remove.js \
+  creators.js \
+  Document-createProcessingInstruction.js \
+  encoding.php \
+  productions.js \
+  $(NULL)
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/attributes.js
rename to dom/imptests/html/dom/nodes/attributes.js
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/case.js
rename to dom/imptests/html/dom/nodes/case.js
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/creators.js
rename to dom/imptests/html/dom/nodes/creators.js
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/nodes/encoding.php
@@ -0,0 +1,2 @@
+<!doctype html>
+<meta charset="<?php echo htmlspecialchars($_GET['label']) ?>">
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/nodes/moz.build
@@ -0,0 +1,4 @@
+# THIS FILE IS AUTOGENERATED BY importTestsuite.py - DO NOT EDIT
+
+DIRS += [
+]
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/productions.js
rename to dom/imptests/html/dom/nodes/productions.js
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_CharacterData-appendData.html
rename to dom/imptests/html/dom/nodes/test_CharacterData-appendData.html
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_CharacterData-deleteData.html
rename to dom/imptests/html/dom/nodes/test_CharacterData-deleteData.html
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_CharacterData-insertData.html
rename to dom/imptests/html/dom/nodes/test_CharacterData-insertData.html
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_CharacterData-remove.html
rename to dom/imptests/html/dom/nodes/test_CharacterData-remove.html
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_CharacterData-replaceData.html
rename to dom/imptests/html/dom/nodes/test_CharacterData-replaceData.html
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_DOMImplementation-createDocument.html
rename to dom/imptests/html/dom/nodes/test_DOMImplementation-createDocument.html
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_DOMImplementation-createDocumentType.html
rename to dom/imptests/html/dom/nodes/test_DOMImplementation-createDocumentType.html
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_DOMImplementation-createHTMLDocument.html
rename to dom/imptests/html/dom/nodes/test_DOMImplementation-createHTMLDocument.html
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_DOMImplementation-hasFeature.html
rename to dom/imptests/html/dom/nodes/test_DOMImplementation-hasFeature.html
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Document-adoptNode.html
rename to dom/imptests/html/dom/nodes/test_Document-adoptNode.html
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Document-createComment.html
rename to dom/imptests/html/dom/nodes/test_Document-createComment.html
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/nodes/test_Document-createElement-namespace.html
@@ -0,0 +1,103 @@
+<!doctype html>
+<title>document.createElement() namespace tests</title>
+<link rel=author title="Aryeh Gregor" href=ayg@aryeh.name>
+<div id=log></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+"use strict";
+/**
+ * This tests the namespace of elements created by the Document interface's
+ * createElement() method.  See bug:
+ * https://www.w3.org/Bugs/Public/show_bug.cgi?id=19431
+ */
+
+/**
+ * Test that an element created using the Document object doc has the namespace
+ * that would be expected for the given contentType.
+ */
+function testDoc(doc, contentType) {
+  // WebKit doesn't support document.contentType, so they don't get this sanity
+  // check :(
+  if (doc.contentType !== undefined) {
+    assert_equals(doc.contentType, contentType,
+                  "Wrong MIME type -- incorrect server config?");
+  }
+
+  var expectedNamespace = contentType == "text/html" ||
+                          contentType == "application/xhtml+xml"
+                          ? "http://www.w3.org/1999/xhtml" : null;
+
+  assert_equals(doc.createElement("x").namespaceURI, expectedNamespace);
+}
+
+// First test various objects we create in JS
+test(function() {
+  testDoc(document, "text/html")
+}, "Created element's namespace in current document");
+test(function() {
+  testDoc(document.implementation.createHTMLDocument(""), "text/html");
+}, "Created element's namespace in created HTML document");
+test(function() {
+  testDoc(document.implementation.createDocument(null, "", null),
+          "application/xml");
+}, "Created element's namespace in created XML document");
+test(function() {
+  testDoc(document.implementation.createDocument("http://www.w3.org/1999/xhtml", "html", null),
+          "application/xml");
+}, "Created element's namespace in created XHTML document");
+test(function() {
+  testDoc(document.implementation.createDocument("http://www.w3.org/2000/svg", "svg", null),
+          "application/xml");
+}, "Created element's namespace in created SVG document");
+test(function() {
+  testDoc(document.implementation.createDocument("http://www.w3.org/1998/Math/MathML", "math", null),
+          "application/xml");
+}, "Created element's namespace in created MathML document");
+
+// Now for various externally-loaded files.  Note: these lists must be kept
+// synced with the lists in generate.py in the subdirectory, and that script
+// must be run whenever the lists are updated.  (We could keep the lists in a
+// shared JSON file, but it seems like too much effort.)
+var testExtensions = {
+  html: "text/html",
+  xhtml: "application/xhtml+xml",
+  xml: "application/xml",
+  svg: "image/svg+xml",
+  // Was not able to get server MIME type working properly :(
+  //mml: "application/mathml+xml",
+};
+
+var tests = [
+  "empty",
+  "minimal_html",
+  
+  "xhtml",
+  "svg",
+  "mathml",
+
+  "bare_xhtml",
+  "bare_svg",
+  "bare_mathml",
+
+  "xhtml_ns_removed",
+  "xhtml_ns_changed",
+];
+
+tests.forEach(function(testName) {
+  Object.keys(testExtensions).forEach(function(ext) {
+    var iframe = document.createElement("iframe");
+    iframe.src = "Document-createElement-namespace-tests/" +
+                 testName + "." + ext;
+    var t = async_test("Created element's namespace in " + testName + "." + ext);
+    iframe.onload = function() {
+      t.step(function() {
+        testDoc(iframe.contentDocument, testExtensions[ext]);
+      });
+      document.body.removeChild(iframe);
+      t.done();
+    };
+    document.body.appendChild(iframe);
+  });
+});
+</script>
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Document-createElement.html
rename to dom/imptests/html/dom/nodes/test_Document-createElement.html
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Document-createElementNS.html
rename to dom/imptests/html/dom/nodes/test_Document-createElementNS.html
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Document-createEvent.html
rename to dom/imptests/html/dom/nodes/test_Document-createEvent.html
--- a/dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Document-createEvent.html
+++ b/dom/imptests/html/dom/nodes/test_Document-createEvent.html
@@ -1,27 +1,44 @@
 <!DOCTYPE html>
 <meta charset=utf-8>
 <title>Document.createEvent</title>
-<link rel=help href="http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#dom-document-createevent">
+<link rel=help href="http://dom.spec.whatwg.org/#dom-document-createevent">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <div id="log"></div>
 <script>
-// TODO: values of attributes
 function testAlias(arg, iface) {
+  var ev;
+  test(function() {
+    ev = document.createEvent(arg);
+    assert_true(ev instanceof window[iface]);
+    assert_true(ev instanceof Event);
+  }, arg + " should be an alias for " + iface + ".");
   test(function() {
-    if (iface === "Event" || iface in window) {
-      var ev = document.createEvent(arg);
-      assert_true(ev instanceof window[iface]);
-      assert_true(ev instanceof Event);
-    }
-  }, arg + " should be an alias for " + iface + ".");
+    assert_equals(ev.type, "",
+                  "type should be initialized to the empty string");
+    assert_equals(ev.target, null,
+                  "target should be initialized to null");
+    assert_equals(ev.currentTarget, null,
+                  "currentTarget should be initialized to null");
+    assert_equals(ev.eventPhase, 0,
+                  "eventPhase should be initialized to NONE (0)");
+    assert_equals(ev.bubbles, false,
+                  "bubbles should be initialized to false");
+    assert_equals(ev.cancelable, false,
+                  "cancelable should be initialized to false");
+    assert_equals(ev.defaultPrevented, false,
+                  "defaultPrevented should be initialized to false");
+    assert_equals(ev.isTrusted, false,
+                  "isTrusted should be initialized to false");
+  }, "createEvent('" + arg + "') should be initialized correctly.");
 }
 [
+  ["CustomEvent", "CustomEvent"],
   ["Event", "Event"],
   ["Events", "Event"],
   ["HTMLEvents", "Event"],
   ["MouseEvent", "MouseEvent"],
   ["MouseEvents", "MouseEvent"],
   ["UIEvent", "UIEvent"],
   ["UIEvents", "UIEvent"]
 ].forEach(function(alias) {
@@ -33,10 +50,14 @@ function testAlias(arg, iface) {
 test(function() {
   assert_throws("NOT_SUPPORTED_ERR", function() {
     var evt = document.createEvent("foo");
   });
   assert_throws("NOT_SUPPORTED_ERR", function() {
     // 'LATIN CAPITAL LETTER I WITH DOT ABOVE' (U+0130)
     var evt = document.createEvent("U\u0130Event");
   });
+  assert_throws("NOT_SUPPORTED_ERR", function() {
+    // 'LATIN SMALL LETTER DOTLESS I' (U+0131)
+    var evt = document.createEvent("U\u0131Event");
+  });
 }, "Should throw NOT_SUPPORTED_ERR for unrecognized arguments");
 </script>
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Document-createProcessingInstruction-literal-1.xhtml
rename to dom/imptests/html/dom/nodes/test_Document-createProcessingInstruction-literal-1.xhtml
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Document-createProcessingInstruction-literal-2.xhtml
rename to dom/imptests/html/dom/nodes/test_Document-createProcessingInstruction-literal-2.xhtml
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Document-createProcessingInstruction.html
rename to dom/imptests/html/dom/nodes/test_Document-createProcessingInstruction.html
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Document-createProcessingInstruction.xhtml
rename to dom/imptests/html/dom/nodes/test_Document-createProcessingInstruction.xhtml
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Document-createTreeWalker.html
rename to dom/imptests/html/dom/nodes/test_Document-createTreeWalker.html
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Document-getElementById.html
rename to dom/imptests/html/dom/nodes/test_Document-getElementById.html
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Document-getElementsByTagName.html
rename to dom/imptests/html/dom/nodes/test_Document-getElementsByTagName.html
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Document-getElementsByTagNameNS.html
rename to dom/imptests/html/dom/nodes/test_Document-getElementsByTagNameNS.html
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Document-importNode.html
rename to dom/imptests/html/dom/nodes/test_Document-importNode.html
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_DocumentType-remove.html
rename to dom/imptests/html/dom/nodes/test_DocumentType-remove.html
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Element-children.html
rename to dom/imptests/html/dom/nodes/test_Element-children.html
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Element-getElementsByClassName.html
rename to dom/imptests/html/dom/nodes/test_Element-getElementsByClassName.html
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Element-remove.html
rename to dom/imptests/html/dom/nodes/test_Element-remove.html
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Element-removeAttributeNS.html
rename to dom/imptests/html/dom/nodes/test_Element-removeAttributeNS.html
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Element-tagName.html
rename to dom/imptests/html/dom/nodes/test_Element-tagName.html
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Node-appendChild.html
rename to dom/imptests/html/dom/nodes/test_Node-appendChild.html
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Node-cloneNode.html
rename to dom/imptests/html/dom/nodes/test_Node-cloneNode.html
rename from dom/imptests/webapps/DOMCore/tests/approved/test_Node-compareDocumentPosition.html
rename to dom/imptests/html/dom/nodes/test_Node-compareDocumentPosition.html
--- a/dom/imptests/webapps/DOMCore/tests/approved/test_Node-compareDocumentPosition.html
+++ b/dom/imptests/html/dom/nodes/test_Node-compareDocumentPosition.html
@@ -1,15 +1,15 @@
 <!doctype html>
 <title>Node.compareDocumentPosition() tests</title>
 <link rel=author title="Aryeh Gregor" href=ayg@aryeh.name>
 <div id=log></div>
 <script src=/resources/testharness.js></script>
 <script src=/resources/testharnessreport.js></script>
-<script src=common.js></script>
+<script src=../common.js></script>
 <script>
 "use strict";
 
 testNodes.forEach(function(referenceName) {
   var reference = eval(referenceName);
   testNodes.forEach(function(otherName) {
     var other = eval(otherName);
     test(function() {
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Node-constants.html
rename to dom/imptests/html/dom/nodes/test_Node-constants.html
--- a/dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Node-constants.html
+++ b/dom/imptests/html/dom/nodes/test_Node-constants.html
@@ -1,13 +1,13 @@
 <!doctype html>
 <title>Node constants</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="constants.js"></script>
+<script src="../constants.js"></script>
 <div id="log"></div>
 <script>
 var objects = [
   [Node, "Node interface object"],
   [Node.prototype, "Node prototype object"],
   [document.createElement("foo"), "Element object"],
   [document.createTextNode("bar"), "Text object"]
 ]
rename from dom/imptests/webapps/DOMCore/tests/approved/test_Node-contains.html
rename to dom/imptests/html/dom/nodes/test_Node-contains.html
--- a/dom/imptests/webapps/DOMCore/tests/approved/test_Node-contains.html
+++ b/dom/imptests/html/dom/nodes/test_Node-contains.html
@@ -1,15 +1,15 @@
 <!doctype html>
 <title>Node.contains() tests</title>
 <link rel=author title="Aryeh Gregor" href=ayg@aryeh.name>
 <div id=log></div>
 <script src=/resources/testharness.js></script>
 <script src=/resources/testharnessreport.js></script>
-<script src=common.js></script>
+<script src=../common.js></script>
 <script>
 "use strict";
 
 testNodes.forEach(function(referenceName) {
   var reference = eval(referenceName);
 
   test(function() {
     assert_false(reference.contains(null));
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Node-contains.xml
rename to dom/imptests/html/dom/nodes/test_Node-contains.xml
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Node-insertBefore.html
rename to dom/imptests/html/dom/nodes/test_Node-insertBefore.html
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Node-isEqualNode.xhtml
rename to dom/imptests/html/dom/nodes/test_Node-isEqualNode.xhtml
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Node-lookupPrefix.xhtml
rename to dom/imptests/html/dom/nodes/test_Node-lookupPrefix.xhtml
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Node-nodeName.html
rename to dom/imptests/html/dom/nodes/test_Node-nodeName.html
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Node-nodeName.xhtml
rename to dom/imptests/html/dom/nodes/test_Node-nodeName.xhtml
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Node-normalize.html
rename to dom/imptests/html/dom/nodes/test_Node-normalize.html
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Node-parentElement.html
rename to dom/imptests/html/dom/nodes/test_Node-parentElement.html
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Node-parentNode.html
rename to dom/imptests/html/dom/nodes/test_Node-parentNode.html
rename from dom/imptests/webapps/DOMCore/tests/approved/test_Node-properties.html
rename to dom/imptests/html/dom/nodes/test_Node-properties.html
--- a/dom/imptests/webapps/DOMCore/tests/approved/test_Node-properties.html
+++ b/dom/imptests/html/dom/nodes/test_Node-properties.html
@@ -1,16 +1,16 @@
 <!doctype html>
 <title>Node assorted property tests</title>
 <link rel=author title="Aryeh Gregor" href=ayg@aryeh.name>
 <meta charset=utf-8>
 <div id=log></div>
 <script src=/resources/testharness.js></script>
 <script src=/resources/testharnessreport.js></script>
-<script src=common.js></script>
+<script src=../common.js></script>
 <script>
 "use strict";
 /**
  * First we define a data structure to tell us what tests to run.  The keys
  * will be eval()ed, and are mostly global variables defined in common.js.  The
  * values are objects, which maps properties to expected values.  So
  *
  * 	foo: {
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Node-removeChild.html
rename to dom/imptests/html/dom/nodes/test_Node-removeChild.html
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Node-replaceChild.html
rename to dom/imptests/html/dom/nodes/test_Node-replaceChild.html
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_attributes.html
rename to dom/imptests/html/dom/nodes/test_attributes.html
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_case.html
rename to dom/imptests/html/dom/nodes/test_case.html
rename from dom/imptests/webapps/DOMCore/tests/submissions/Opera/test_getElementsByClassName-01.htm
rename to dom/imptests/html/dom/nodes/test_getElementsByClassName-01.htm
rename from dom/imptests/webapps/DOMCore/tests/submissions/Opera/test_getElementsByClassName-02.htm
rename to dom/imptests/html/dom/nodes/test_getElementsByClassName-02.htm
rename from dom/imptests/webapps/DOMCore/tests/submissions/Opera/test_getElementsByClassName-03.htm
rename to dom/imptests/html/dom/nodes/test_getElementsByClassName-03.htm
rename from dom/imptests/webapps/DOMCore/tests/submissions/Opera/test_getElementsByClassName-04.htm
rename to dom/imptests/html/dom/nodes/test_getElementsByClassName-04.htm
rename from dom/imptests/webapps/DOMCore/tests/submissions/Opera/test_getElementsByClassName-05.htm
rename to dom/imptests/html/dom/nodes/test_getElementsByClassName-05.htm
rename from dom/imptests/webapps/DOMCore/tests/submissions/Opera/test_getElementsByClassName-06.htm
rename to dom/imptests/html/dom/nodes/test_getElementsByClassName-06.htm
rename from dom/imptests/webapps/DOMCore/tests/submissions/Opera/test_getElementsByClassName-07.htm
rename to dom/imptests/html/dom/nodes/test_getElementsByClassName-07.htm
rename from dom/imptests/webapps/DOMCore/tests/submissions/Opera/test_getElementsByClassName-08.htm
rename to dom/imptests/html/dom/nodes/test_getElementsByClassName-08.htm
rename from dom/imptests/webapps/DOMCore/tests/submissions/Opera/test_getElementsByClassName-09.htm
rename to dom/imptests/html/dom/nodes/test_getElementsByClassName-09.htm
rename from dom/imptests/webapps/DOMCore/tests/submissions/Opera/test_getElementsByClassName-10.xml
rename to dom/imptests/html/dom/nodes/test_getElementsByClassName-10.xml
rename from dom/imptests/webapps/DOMCore/tests/submissions/Opera/test_getElementsByClassName-11.xml
rename to dom/imptests/html/dom/nodes/test_getElementsByClassName-11.xml
rename from dom/imptests/webapps/DOMCore/tests/submissions/Opera/test_getElementsByClassName-12.htm
rename to dom/imptests/html/dom/nodes/test_getElementsByClassName-12.htm
rename from dom/imptests/webapps/DOMCore/tests/submissions/Opera/test_getElementsByClassName-13.htm
rename to dom/imptests/html/dom/nodes/test_getElementsByClassName-13.htm
rename from dom/imptests/webapps/DOMCore/tests/submissions/Opera/test_getElementsByClassName-14.htm
rename to dom/imptests/html/dom/nodes/test_getElementsByClassName-14.htm
rename from dom/imptests/webapps/DOMCore/tests/submissions/Opera/test_getElementsByClassName-15.htm
rename to dom/imptests/html/dom/nodes/test_getElementsByClassName-15.htm
rename from dom/imptests/webapps/DOMCore/tests/submissions/Opera/test_getElementsByClassName-16.htm
rename to dom/imptests/html/dom/nodes/test_getElementsByClassName-16.htm
rename from dom/imptests/webapps/DOMCore/tests/submissions/Opera/test_getElementsByClassName-17.htm
rename to dom/imptests/html/dom/nodes/test_getElementsByClassName-17.htm
rename from dom/imptests/webapps/DOMCore/tests/submissions/Opera/test_getElementsByClassName-18.htm
rename to dom/imptests/html/dom/nodes/test_getElementsByClassName-18.htm
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/ranges/Makefile.in
@@ -0,0 +1,25 @@
+# THIS FILE IS AUTOGENERATED BY importTestsuite.py - DO NOT EDIT
+
+MOCHITEST_FILES := \
+  test_Range-attributes.html \
+  test_Range-cloneContents.html \
+  test_Range-cloneRange.html \
+  test_Range-collapse.html \
+  test_Range-commonAncestorContainer-2.html \
+  test_Range-commonAncestorContainer.html \
+  test_Range-compareBoundaryPoints.html \
+  test_Range-comparePoint-2.html \
+  test_Range-comparePoint.html \
+  test_Range-deleteContents.html \
+  test_Range-detach.html \
+  test_Range-extractContents.html \
+  test_Range-insertNode.html \
+  test_Range-intersectsNode-binding.html \
+  test_Range-intersectsNode.html \
+  test_Range-isPointInRange.html \
+  test_Range-mutations.html \
+  test_Range-selectNode.html \
+  test_Range-set.html \
+  test_Range-surroundContents.html \
+  Range-test-iframe.html \
+  $(NULL)
rename from dom/imptests/webapps/DOMCore/tests/approved/Range-test-iframe.html
rename to dom/imptests/html/dom/ranges/Range-test-iframe.html
--- a/dom/imptests/webapps/DOMCore/tests/approved/Range-test-iframe.html
+++ b/dom/imptests/html/dom/ranges/Range-test-iframe.html
@@ -1,13 +1,13 @@
 <!doctype html>
 <title>Range test iframe</title>
 <link rel=author title="Aryeh Gregor" href=ayg@aryeh.name>
 <body onload=run()>
-<script src=common.js></script>
+<script src=../common.js></script>
 <script>
 "use strict";
 
 // This script only exists because we want to evaluate the range endpoints
 // in each iframe using that iframe's local variables set up by common.js.  It
 // just creates the range and does nothing else.  The data is returned via
 // window.testRange, and if an exception is thrown, it's put in
 // window.unexpectedException.
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/ranges/moz.build
@@ -0,0 +1,4 @@
+# THIS FILE IS AUTOGENERATED BY importTestsuite.py - DO NOT EDIT
+
+DIRS += [
+]
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Range-attributes.html
rename to dom/imptests/html/dom/ranges/test_Range-attributes.html
rename from dom/imptests/webapps/DOMCore/tests/approved/test_Range-cloneContents.html
rename to dom/imptests/html/dom/ranges/test_Range-cloneContents.html
--- a/dom/imptests/webapps/DOMCore/tests/approved/test_Range-cloneContents.html
+++ b/dom/imptests/html/dom/ranges/test_Range-cloneContents.html
@@ -2,17 +2,17 @@
 <title>Range.cloneContents() tests</title>
 <link rel=author title="Aryeh Gregor" href=ayg@aryeh.name>
 <p>To debug test failures, look at the URL of the hidden iframes corresponding
 to the test at the end of the document, load those individually, and use your
 browser's debugging tools.
 <div id=log></div>
 <script src=/resources/testharness.js></script>
 <script src=/resources/testharnessreport.js></script>
-<script src=common.js></script>
+<script src=../common.js></script>
 <script>
 "use strict";
 
 testDiv.parentNode.removeChild(testDiv);
 
 function myCloneContents(range) {
 	// "Let frag be a new DocumentFragment whose ownerDocument is the same as
 	// the ownerDocument of the context object's start node."
@@ -387,24 +387,22 @@ function onLoadExpected(i) {
 		assertNodesEqual(actualFrag, expectedFrag,
 			"returned fragment");
 	});
 	fragTests[i].done();
 }
 
 setup({timeout: 60000});
 
-// First test a detached Range, synchronously
+// First test a Range that has the no-op detach() called on it, synchronously
 test(function() {
 	var range = document.createRange();
 	range.detach();
-	assert_throws("INVALID_STATE_ERR", function() {
-		range.cloneContents();
-	}, "Detached Range must throw INVALID_STATE_ERR on .cloneContents()");
-}, "Detached Range");
+	assert_array_equals(range.cloneContents().childNodes, []);
+}, "Range.detach()");
 
 var domTests = [];
 var positionTests = [];
 var fragTests = [];
 var actualIframes = [];
 var expectedIframes = [];
 for (var i = 0; i < testRanges.length; i++) {
 	domTests.push(async_test("Resulting DOM for range " + i + " " + testRanges[i]));
rename from dom/imptests/webapps/DOMCore/tests/approved/test_Range-cloneRange.html
rename to dom/imptests/html/dom/ranges/test_Range-cloneRange.html
--- a/dom/imptests/webapps/DOMCore/tests/approved/test_Range-cloneRange.html
+++ b/dom/imptests/html/dom/ranges/test_Range-cloneRange.html
@@ -1,26 +1,32 @@
 <!doctype html>
 <title>Range.cloneRange() and document.createRange() tests</title>
 <link rel=author title="Aryeh Gregor" href=ayg@aryeh.name>
 <div id=log></div>
 <script src=/resources/testharness.js></script>
 <script src=/resources/testharnessreport.js></script>
-<script src=common.js></script>
+<script src=../common.js></script>
 <script>
 "use strict";
 
 function testCloneRange(rangeEndpoints) {
 	var range;
 	if (rangeEndpoints == "detached") {
 		range = document.createRange();
 		range.detach();
-		assert_throws("INVALID_STATE_ERR", function() {
-			range.cloneRange();
-		}, "Detached Range must throw INVALID_STATE_ERR on .cloneRange()");
+		var clonedRange = range.cloneRange();
+		assert_equals(clonedRange.startContainer, range.startContainer,
+			"startContainers must be equal after cloneRange()");
+		assert_equals(clonedRange.startOffset, range.startOffset,
+			"startOffsets must be equal after cloneRange()");
+		assert_equals(clonedRange.endContainer, range.endContainer,
+			"endContainers must be equal after cloneRange()");
+		assert_equals(clonedRange.endOffset, range.endOffset,
+			"endOffsets must be equal after cloneRange()");
 		return;
 	}
 
 	// Have to account for Ranges involving Documents!  We could just create
 	// the Range from the current document unconditionally, but some browsers
 	// (WebKit) don't implement setStart() and setEnd() per spec and will throw
 	// spurious exceptions at the time of this writing.  No need to mask other
 	// bugs.
@@ -87,75 +93,19 @@ function testCloneRange(rangeEndpoints) 
 	assert_equals(range.startOffset, 1,
 		"Modifying a clone must not modify the original Range's startOffset");
 	assert_equals(range.endContainer, testNode1,
 		"Modifying a clone must not modify the original Range's endContainer");
 	assert_equals(range.endOffset, 2,
 		"Modifying a clone must not modify the original Range's endOffset");
 }
 
-var ranges = [
-	// Various ranges within the text node children of different paragraphs.
-	"[paras[0].firstChild, 0, paras[0].firstChild, 0]",
-	"[paras[0].firstChild, 0, paras[0].firstChild, 1]",
-	"[paras[0].firstChild, 2, paras[0].firstChild, 8]",
-	"[paras[0].firstChild, 2, paras[0].firstChild, 9]",
-	"[paras[1].firstChild, 0, paras[1].firstChild, 0]",
-	"[paras[1].firstChild, 0, paras[1].firstChild, 1]",
-	"[paras[1].firstChild, 2, paras[1].firstChild, 8]",
-	"[paras[1].firstChild, 2, paras[1].firstChild, 9]",
-	"[detachedPara1.firstChild, 0, detachedPara1.firstChild, 0]",
-	"[detachedPara1.firstChild, 0, detachedPara1.firstChild, 1]",
-	"[detachedPara1.firstChild, 2, detachedPara1.firstChild, 8]",
-	"[foreignPara1.firstChild, 0, foreignPara1.firstChild, 0]",
-	"[foreignPara1.firstChild, 0, foreignPara1.firstChild, 1]",
-	"[foreignPara1.firstChild, 2, foreignPara1.firstChild, 8]",
-	// Now try testing some elements, not just text nodes.
-	"[document.documentElement, 0, document.documentElement, 1]",
-	"[document.head, 1, document.head, 1]",
-	"[document.body, 4, document.body, 5]",
-	"[foreignDoc.documentElement, 0, foreignDoc.documentElement, 1]",
-	"[foreignDoc.head, 1, foreignDoc.head, 1]",
-	"[foreignDoc.body, 0, foreignDoc.body, 0]",
-	"[paras[0], 0, paras[0], 0]",
-	"[paras[0], 0, paras[0], 1]",
-	"[detachedPara1, 0, detachedPara1, 0]",
-	"[detachedPara1, 0, detachedPara1, 1]",
-	// Now try some ranges that span elements.
-	"[paras[0].firstChild, 0, paras[1].firstChild, 0]",
-	"[paras[0].firstChild, 0, paras[1].firstChild, 8]",
-	"[paras[0].firstChild, 3, paras[3], 1]",
-	// How about something that spans a node and its descendant?
-	"[paras[0], 0, paras[0].firstChild, 7]",
-	"[testDiv, 2, paras[4], 1]",
-	"[testDiv, 1, paras[2].firstChild, 5]",
-	"[foreignDoc.documentElement, 1, foreignDoc.body, 0]",
-	// Then a few silly things just for good measure.  (Well, document probably
-	// isn't entirely silly.)
-	"[document, 0, document, 1]",
-	"[foreignDoc, 0, foreignDoc, 0]",
-	"[xmlDoc, 0, xmlDoc, 0]",
-	"[detachedTextNode, 0, detachedTextNode, 8]",
-	"[foreignTextNode, 7, foreignTextNode, 7]",
-	"[foreignTextNode, 0, foreignTextNode, 8]",
-	"[xmlTextNode, 7, xmlTextNode, 7]",
-	"[xmlTextNode, 0, xmlTextNode, 8]",
-	"[comment, 5, comment, 5]",
-	"[foreignComment, 4, foreignComment, 4]",
-	"[xmlComment, 2, xmlComment, 6]",
-	"[docfrag, 0, docfrag, 0]",
-	"[foreignDocfrag, 0, foreignDocfrag, 0]",
-	"[xmlDocfrag, 0, xmlDocfrag, 0]",
-	// Magic keyword!
-	'"detached"'
-];
-
 var tests = [];
-for (var i = 0; i < ranges.length; i++) {
+for (var i = 0; i < testRanges.length; i++) {
 	tests.push([
-		"Range " + i + " " + ranges[i],
-		eval(ranges[i])
+		"Range " + i + " " + testRanges[i],
+		eval(testRanges[i])
 	]);
 }
 generate_tests(testCloneRange, tests);
 
 testDiv.style.display = "none";
 </script>
rename from dom/imptests/webapps/DOMCore/tests/approved/test_Range-collapse.html
rename to dom/imptests/html/dom/ranges/test_Range-collapse.html
--- a/dom/imptests/webapps/DOMCore/tests/approved/test_Range-collapse.html
+++ b/dom/imptests/html/dom/ranges/test_Range-collapse.html
@@ -1,29 +1,26 @@
 <!doctype html>
 <title>Range.collapse() and .collapsed tests</title>
 <link rel=author title="Aryeh Gregor" href=ayg@aryeh.name>
 <div id=log></div>
 <script src=/resources/testharness.js></script>
 <script src=/resources/testharnessreport.js></script>
-<script src=common.js></script>
+<script src=../common.js></script>
 <script>
 "use strict";
 
 function testCollapse(rangeEndpoints, toStart) {
 	var range;
 	if (rangeEndpoints == "detached") {
 		range = document.createRange();
 		range.detach();
-		assert_throws("INVALID_STATE_ERR", function() {
-			range.collapse(toStart);
-		}, "Detached Range must throw INVALID_STATE_ERR on .collapse()");
-		assert_throws("INVALID_STATE_ERR", function() {
-			range.collapsed;
-		}, "Detached Range must throw INVALID_STATE_ERR on .collapsed access");
+		range.collapse(toStart);
+		assert_true(range.collapsed,
+			".collapsed must be set after .collapsed()");
 		return;
 	}
 
 	// Have to account for Ranges involving Documents!
 	var ownerDoc = rangeEndpoints[0].nodeType == Node.DOCUMENT_NODE
 		? rangeEndpoints[0]
 		: rangeEndpoints[0].ownerDocument;
 	range = ownerDoc.createRange();
@@ -46,90 +43,25 @@ function testCollapse(rangeEndpoints, to
 	assert_equals(range.startOffset, expectedOffset,
 		"Wrong startOffset");
 	assert_equals(range.endOffset, expectedOffset,
 		"Wrong endOffset");
 	assert_true(range.collapsed,
 		".collapsed must be set after .collapsed()");
 }
 
-var ranges = [
-	// Various ranges within the text node children of different paragraphs.
-	// (I don't try going out of bounds anywhere here, because these are used
-	// for setup, not testing setStart()/setEnd().)
-	//
-	// Note that the length of the in-document paragraphs is actually 9, due to
-	// the newline, but the detached and foreign ones lack the newline, so
-	// their length is 8.
-	//
-	// The format is a bit evil, but it's the only sensible way to output test
-	// names.
-	"[paras[0].firstChild, 0, paras[0].firstChild, 0]",
-	"[paras[0].firstChild, 0, paras[0].firstChild, 1]",
-	"[paras[0].firstChild, 2, paras[0].firstChild, 8]",
-	"[paras[0].firstChild, 2, paras[0].firstChild, 9]",
-	"[paras[1].firstChild, 0, paras[1].firstChild, 0]",
-	"[paras[1].firstChild, 0, paras[1].firstChild, 1]",
-	"[paras[1].firstChild, 2, paras[1].firstChild, 8]",
-	"[paras[1].firstChild, 2, paras[1].firstChild, 9]",
-	"[detachedPara1.firstChild, 0, detachedPara1.firstChild, 0]",
-	"[detachedPara1.firstChild, 0, detachedPara1.firstChild, 1]",
-	"[detachedPara1.firstChild, 2, detachedPara1.firstChild, 8]",
-	"[foreignPara1.firstChild, 0, foreignPara1.firstChild, 0]",
-	"[foreignPara1.firstChild, 0, foreignPara1.firstChild, 1]",
-	"[foreignPara1.firstChild, 2, foreignPara1.firstChild, 8]",
-	// Now try testing some elements, not just text nodes.
-	"[document.documentElement, 0, document.documentElement, 1]",
-	"[document.head, 1, document.head, 1]",
-	"[document.body, 4, document.body, 5]",
-	"[foreignDoc.documentElement, 0, foreignDoc.documentElement, 1]",
-	"[foreignDoc.head, 1, foreignDoc.head, 1]",
-	"[foreignDoc.body, 0, foreignDoc.body, 0]",
-	"[paras[0], 0, paras[0], 0]",
-	"[paras[0], 0, paras[0], 1]",
-	"[detachedPara1, 0, detachedPara1, 0]",
-	"[detachedPara1, 0, detachedPara1, 1]",
-	// Now try some ranges that span elements.
-	"[paras[0].firstChild, 0, paras[1].firstChild, 0]",
-	"[paras[0].firstChild, 0, paras[1].firstChild, 8]",
-	"[paras[0].firstChild, 3, paras[3], 1]",
-	// How about something that spans a node and its descendant?
-	"[paras[0], 0, paras[0].firstChild, 7]",
-	"[testDiv, 2, paras[4], 1]",
-	"[testDiv, 1, paras[2].firstChild, 5]",
-	"[foreignDoc.documentElement, 1, foreignDoc.body, 0]",
-	// Then a few silly things just for good measure.  (Well, document probably
-	// isn't entirely silly.)
-	"[document, 0, document, 1]",
-	"[foreignDoc, 0, foreignDoc, 0]",
-	"[xmlDoc, 0, xmlDoc, 0]",
-	"[detachedTextNode, 0, detachedTextNode, 8]",
-	"[foreignTextNode, 7, foreignTextNode, 7]",
-	"[foreignTextNode, 0, foreignTextNode, 8]",
-	"[xmlTextNode, 7, xmlTextNode, 7]",
-	"[xmlTextNode, 0, xmlTextNode, 8]",
-	"[comment, 5, comment, 5]",
-	"[foreignComment, 4, foreignComment, 4]",
-	"[xmlComment, 2, xmlComment, 6]",
-	"[docfrag, 0, docfrag, 0]",
-	"[foreignDocfrag, 0, foreignDocfrag, 0]",
-	"[xmlDocfrag, 0, xmlDocfrag, 0]",
-	// Magic keyword!
-	'"detached"'
-];
-
 var tests = [];
-for (var i = 0; i < ranges.length; i++) {
+for (var i = 0; i < testRanges.length; i++) {
 	tests.push([
-		"Range " + i + " " + ranges[i] + ", toStart true",
-		eval(ranges[i]),
+		"Range " + i + " " + testRanges[i] + ", toStart true",
+		eval(testRanges[i]),
 		true
 	]);
 	tests.push([
-		"Range " + i + " " + ranges[i] + ", toStart false",
-		eval(ranges[i]),
+		"Range " + i + " " + testRanges[i] + ", toStart false",
+		eval(testRanges[i]),
 		false
 	]);
 }
 generate_tests(testCollapse, tests);
 
 testDiv.style.display = "none";
 </script>
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Range-commonAncestorContainer.html
rename to dom/imptests/html/dom/ranges/test_Range-commonAncestorContainer-2.html
rename from dom/imptests/webapps/DOMCore/tests/approved/test_Range-commonAncestorContainer.html
rename to dom/imptests/html/dom/ranges/test_Range-commonAncestorContainer.html
--- a/dom/imptests/webapps/DOMCore/tests/approved/test_Range-commonAncestorContainer.html
+++ b/dom/imptests/html/dom/ranges/test_Range-commonAncestorContainer.html
@@ -1,39 +1,30 @@
 <!doctype html>
 <title>Range.commonAncestorContainer tests</title>
 <link rel=author title="Aryeh Gregor" href=ayg@aryeh.name>
 <div id=log></div>
 <script src=/resources/testharness.js></script>
 <script src=/resources/testharnessreport.js></script>
-<script src=common.js></script>
+<script src=../common.js></script>
 <script>
 "use strict";
 
 testRanges.unshift("[detached]");
 
 for (var i = 0; i < testRanges.length; i++) {
 	test(function() {
 		var range;
 		if (i == 0) {
 			range = document.createRange();
 			range.detach();
 		} else {
 			range = rangeFromEndpoints(eval(testRanges[i]));
 		}
 
-		// "If the detached flag is set, throw an "InvalidStateError" exception
-		// and terminate these steps."
-		if (i == 0) {
-			assert_throws("INVALID_STATE_ERR", function() {
-				range.commonAncestorContainer;
-			}, "Detached range must throw InvalidStateError");
-			return;
-		}
-
 		// "Let container be start node."
 		var container = range.startContainer;
 
 		// "While container is not an inclusive ancestor of end node, let
 		// container be container's parent."
 		while (container != range.endContainer
 		&& !isAncestor(container, range.endContainer)) {
 			container = container.parentNode;
rename from dom/imptests/webapps/DOMCore/tests/approved/test_Range-compareBoundaryPoints.html
rename to dom/imptests/html/dom/ranges/test_Range-compareBoundaryPoints.html
--- a/dom/imptests/webapps/DOMCore/tests/approved/test_Range-compareBoundaryPoints.html
+++ b/dom/imptests/html/dom/ranges/test_Range-compareBoundaryPoints.html
@@ -1,24 +1,24 @@
 <!doctype html>
 <title>Range.compareBoundaryPoints() tests</title>
 <link rel=author title="Aryeh Gregor" href=ayg@aryeh.name>
 <div id=log></div>
 <script src=/resources/testharness.js></script>
 <script src=/resources/testharnessreport.js></script>
-<script src=common.js></script>
+<script src=../common.js></script>
 <script>
 "use strict";
 
 var testRangesCached = [];
 testRangesCached.push(document.createRange());
 testRangesCached[0].detach();
-for (var i = 0; i < testRanges.length; i++) {
+for (var i = 0; i < testRangesShort.length; i++) {
 	try {
-		testRangesCached.push(rangeFromEndpoints(eval(testRanges[i])));
+		testRangesCached.push(rangeFromEndpoints(eval(testRangesShort[i])));
 	} catch(e) {
 		testRangesCached.push(null);
 	}
 }
 
 var testRangesCachedClones = [];
 testRangesCachedClones.push(document.createRange());
 testRangesCachedClones[0].detach();
@@ -100,26 +100,16 @@ for (var i = 0; i < testRangesCached.len
 					// "Return int16bit."
 					convertedHow = posInt % 65536;
 					if (convertedHow < 0) {
 						convertedHow += 65536;
 					}
 				}
 
 				// Now to the actual algorithm.
-				// "If context object's or sourceRange's detached flag is set,
-				// throw an "InvalidStateError" exception and terminate these
-				// steps."
-				if (i == 0 || j == 0) {
-					assert_throws("INVALID_STATE_ERR", function() {
-						range1.compareBoundaryPoints(how, range2);
-					}, "InvalidStateError required if one of the ranges is detached");
-					return;
-				}
-
 				// "If how is not one of
 				//   START_TO_START,
 				//   START_TO_END,
 				//   END_TO_END, and
 				//   END_TO_START,
 				// throw a "NotSupportedError" exception and terminate these
 				// steps."
 				if (convertedHow != Range.START_TO_START
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Range-comparePoint.html
rename to dom/imptests/html/dom/ranges/test_Range-comparePoint-2.html
rename from dom/imptests/webapps/DOMCore/tests/approved/test_Range-comparePoint.html
rename to dom/imptests/html/dom/ranges/test_Range-comparePoint.html
--- a/dom/imptests/webapps/DOMCore/tests/approved/test_Range-comparePoint.html
+++ b/dom/imptests/html/dom/ranges/test_Range-comparePoint.html
@@ -1,15 +1,15 @@
 <!doctype html>
 <title>Range.comparePoint() tests</title>
 <link rel=author title="Aryeh Gregor" href=ayg@aryeh.name>
 <div id=log></div>
 <script src=/resources/testharness.js></script>
 <script src=/resources/testharnessreport.js></script>
-<script src=common.js></script>
+<script src=../common.js></script>
 <script>
 "use strict";
 
 // Will be filled in on the first run for that range
 var testRangesCached = [];
 
 for (var i = 0; i < testPoints.length; i++) {
 	var node = eval(testPoints[i])[0];
@@ -17,26 +17,16 @@ for (var i = 0; i < testPoints.length; i
 
 	// comparePoint is an unsigned long, so per WebIDL, we need to treat it as
 	// though it wrapped to an unsigned 32-bit integer.
 	var normalizedOffset = offset % Math.pow(2, 32);
 	if (normalizedOffset < 0) {
 		normalizedOffset += Math.pow(2, 32);
 	}
 
-	// "If the detached flag is set, throw an "InvalidStateError" exception and
-	// terminate these steps."
-	test(function() {
-		var range = document.createRange();
-		range.detach();
-		assert_throws("INVALID_STATE_ERR", function() {
-			range.comparePoint(node, offset);
-		}, "Must throw InvalidStateError if range is detached");
-	}, "Point " + i + " " + testPoints[i] + ", detached range");
-
 	for (var j = 0; j < testRanges.length; j++) {
 		test(function() {
 			if (testRangesCached[j] === undefined) {
 				try {
 					testRangesCached[j] = rangeFromEndpoints(eval(testRanges[i]));
 				} catch(e) {
 					testRangesCached[j] = null;
 				}
rename from dom/imptests/webapps/DOMCore/tests/approved/test_Range-deleteContents.html
rename to dom/imptests/html/dom/ranges/test_Range-deleteContents.html
--- a/dom/imptests/webapps/DOMCore/tests/approved/test_Range-deleteContents.html
+++ b/dom/imptests/html/dom/ranges/test_Range-deleteContents.html
@@ -2,17 +2,17 @@
 <title>Range.deleteContents() tests</title>
 <link rel=author title="Aryeh Gregor" href=ayg@aryeh.name>
 <p>To debug test failures, look at the URL of the hidden iframes corresponding
 to the test at the end of the document, load those individually, and use your
 browser's debugging tools.
 <div id=log></div>
 <script src=/resources/testharness.js></script>
 <script src=/resources/testharnessreport.js></script>
-<script src=common.js></script>
+<script src=../common.js></script>
 <script>
 "use strict";
 
 testDiv.parentNode.removeChild(testDiv);
 
 function myDeleteContents(range) {
 	// "If the context object's start and end are the same, abort this method."
 	if (range.startContainer == range.endContainer
@@ -270,19 +270,17 @@ function onLoadExpected(i) {
 }
 
 setup({timeout: 60000});
 
 // First test a detached Range, synchronously
 test(function() {
 	var range = document.createRange();
 	range.detach();
-	assert_throws("INVALID_STATE_ERR", function() {
-		range.deleteContents();
-	}, "Detached Range must throw INVALID_STATE_ERR on .deleteContents()");
+	range.deleteContents();
 }, "Detached Range");
 
 var domTests = [];
 var positionTests = [];
 var actualIframes = [];
 var expectedIframes = [];
 for (var i = 0; i < testRanges.length; i++) {
 	domTests.push(async_test("Resulting DOM for range " + i + " " + testRanges[i]));
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Range-detach.html
rename to dom/imptests/html/dom/ranges/test_Range-detach.html
rename from dom/imptests/webapps/DOMCore/tests/approved/test_Range-extractContents.html
rename to dom/imptests/html/dom/ranges/test_Range-extractContents.html
--- a/dom/imptests/webapps/DOMCore/tests/approved/test_Range-extractContents.html
+++ b/dom/imptests/html/dom/ranges/test_Range-extractContents.html
@@ -2,17 +2,17 @@
 <title>Range.extractContents() tests</title>
 <link rel=author title="Aryeh Gregor" href=ayg@aryeh.name>
 <p>To debug test failures, look at the URL of the hidden iframes corresponding
 to the test at the end of the document, load those individually, and use your
 browser's debugging tools.
 <div id=log></div>
 <script src=/resources/testharness.js></script>
 <script src=/resources/testharnessreport.js></script>
-<script src=common.js></script>
+<script src=../common.js></script>
 <script>
 "use strict";
 
 testDiv.parentNode.removeChild(testDiv);
 
 function testExtractContents(i) {
 	// We only load the expected once the actual is finished, to avoid race
 	// conditions.  First set the onload to null and the src to the empty
@@ -185,19 +185,17 @@ function onLoadExpected(i) {
 }
 
 setup({timeout: 60000});
 
 // First test a detached Range, synchronously
 test(function() {
 	var range = document.createRange();
 	range.detach();
-	assert_throws("INVALID_STATE_ERR", function() {
-		range.extractContents();
-	}, "Detached Range must throw INVALID_STATE_ERR on .extractContents()");
+	assert_array_equals(range.extractContents().childNodes, []);
 }, "Detached Range");
 
 var domTests = [];
 var positionTests = [];
 var fragTests = [];
 var actualIframes = [];
 var expectedIframes = [];
 for (var i = 0; i < testRanges.length; i++) {
rename from dom/imptests/webapps/DOMCore/tests/approved/test_Range-insertNode.html
rename to dom/imptests/html/dom/ranges/test_Range-insertNode.html
--- a/dom/imptests/webapps/DOMCore/tests/approved/test_Range-insertNode.html
+++ b/dom/imptests/html/dom/ranges/test_Range-insertNode.html
@@ -2,17 +2,17 @@
 <title>Range.insertNode() tests</title>
 <link rel=author title="Aryeh Gregor" href=ayg@aryeh.name>
 <p>To debug test failures, add a query parameter with the test id (like
 "?5,16").  Only that test will be run.  Then you can look at the resulting
 iframes in the DOM.
 <div id=log></div>
 <script src=/resources/testharness.js></script>
 <script src=/resources/testharnessreport.js></script>
-<script src=common.js></script>
+<script src=../common.js></script>
 <script>
 "use strict";
 
 testDiv.parentNode.removeChild(testDiv);
 
 function restoreIframe(iframe, i, j) {
 	// Most of this function is designed to work around the fact that Opera
 	// doesn't let you add a doctype to a document that no longer has one, in
@@ -33,18 +33,18 @@ function restoreIframe(iframe, i, j) {
 		// This will throw an exception in Opera if we reach here, which is why
 		// I try to avoid it.  It will never happen in a browser that obeys the
 		// spec, so it's really just insurance.  I don't think it actually gets
 		// hit by anything.
 		iframe.contentDocument.appendChild(iframe.contentDocument.implementation.createDocumentType("html", "", ""));
 	}
 	iframe.contentDocument.appendChild(referenceDoc.documentElement.cloneNode(true));
 	iframe.contentWindow.setupRangeTests();
-	iframe.contentWindow.testRangeInput = testRanges[i];
-	iframe.contentWindow.testNodeInput = testNodes[j];
+	iframe.contentWindow.testRangeInput = testRangesShort[i];
+	iframe.contentWindow.testNodeInput = testNodesShort[j];
 	iframe.contentWindow.run();
 }
 
 function testInsertNode(i, j) {
 	var actualRange;
 	var expectedRange;
 	var actualNode;
 	var expectedNode;
@@ -231,36 +231,36 @@ function testInsertNode(i, j) {
 			"startContainer superficially looks right but is actually the wrong node if you trace back its index in all its ancestors (I'm surprised this actually happened");
 	});
 	positionTests[i][j].done();
 }
 
 testRanges.unshift('"detached"');
 
 var iStart = 0;
-var iStop = testRanges.length;
+var iStop = testRangesShort.length;
 var jStart = 0;
-var jStop = testNodes.length;
+var jStop = testNodesShort.length;
 
 if (/[0-9]+,[0-9]+/.test(location.search)) {
 	var matches = /([0-9]+),([0-9]+)/.exec(location.search);
 	iStart = Number(matches[1]);
 	iStop = Number(matches[1]) + 1;
 	jStart = Number(matches[2]) + 0;
 	jStop = Number(matches[2]) + 1;
 }
 
 var domTests = [];
 var positionTests = [];
 for (var i = iStart; i < iStop; i++) {
 	domTests[i] = [];
 	positionTests[i] = [];
 	for (var j = jStart; j < jStop; j++) {
-		domTests[i][j] = async_test(i + "," + j + ": resulting DOM for range " + testRanges[i] + ", node " + testNodes[j]);
-		positionTests[i][j] = async_test(i + "," + j + ": resulting range position for range " + testRanges[i] + ", node " + testNodes[j]);
+		domTests[i][j] = async_test(i + "," + j + ": resulting DOM for range " + testRangesShort[i] + ", node " + testNodesShort[j]);
+		positionTests[i][j] = async_test(i + "," + j + ": resulting range position for range " + testRangesShort[i] + ", node " + testNodesShort[j]);
 	}
 }
 
 var actualIframe = document.createElement("iframe");
 actualIframe.style.display = "none";
 document.body.appendChild(actualIframe);
 
 var expectedIframe = document.createElement("iframe");
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_Range-intersectsNode-binding.html
rename to dom/imptests/html/dom/ranges/test_Range-intersectsNode-binding.html
rename from dom/imptests/webapps/DOMCore/tests/approved/test_Range-intersectsNode.html
rename to dom/imptests/html/dom/ranges/test_Range-intersectsNode.html
--- a/dom/imptests/webapps/DOMCore/tests/approved/test_Range-intersectsNode.html
+++ b/dom/imptests/html/dom/ranges/test_Range-intersectsNode.html
@@ -1,32 +1,30 @@
 <!doctype html>
 <title>Range.intersectsNode() tests</title>
 <link rel=author title="Aryeh Gregor" href=ayg@aryeh.name>
 <div id=log></div>
 <script src=/resources/testharness.js></script>
 <script src=/resources/testharnessreport.js></script>
-<script src=common.js></script>
+<script src=../common.js></script>
 <script>
 "use strict";
 
 // Will be filled in on the first run for that range
 var testRangesCached = [];
 
 for (var i = 0; i < testNodes.length; i++) {
 	var node = eval(testNodes[i]);
 
 	// "If the detached flag is set, throw an "InvalidStateError" exception and
 	// terminate these steps."
 	test(function() {
 		var range = document.createRange();
 		range.detach();
-		assert_throws("INVALID_STATE_ERR", function() {
-			range.intersectsNode(node);
-		}, "Must throw InvalidStateError if range is detached");
+		assert_equals(range.intersectsNode(node), node === document);
 	}, "Node " + i + " " + testNodes[i] + ", detached range");
 
 	for (var j = 0; j < testRanges.length; j++) {
 		test(function() {
 			if (testRangesCached[j] === undefined) {
 				try {
 					testRangesCached[j] = rangeFromEndpoints(eval(testRanges[i]));
 				} catch(e) {
rename from dom/imptests/webapps/DOMCore/tests/approved/test_Range-isPointInRange.html
rename to dom/imptests/html/dom/ranges/test_Range-isPointInRange.html
--- a/dom/imptests/webapps/DOMCore/tests/approved/test_Range-isPointInRange.html
+++ b/dom/imptests/html/dom/ranges/test_Range-isPointInRange.html
@@ -1,54 +1,44 @@
 <!doctype html>
 <title>Range.isPointInRange() tests</title>
 <link rel=author title="Aryeh Gregor" href=ayg@aryeh.name>
 <div id=log></div>
 <script src=/resources/testharness.js></script>
 <script src=/resources/testharnessreport.js></script>
-<script src=common.js></script>
+<script src=../common.js></script>
 <script>
 "use strict";
 
-// Will be filled in on the first run for that range
 var testRangesCached = [];
+test(function() {
+	for (var j = 0; j < testRanges.length; j++) {
+		test(function() {
+			testRangesCached[j] = rangeFromEndpoints(eval(testRanges[j]));
+		}, "Set up for range " + j + " " + testRanges[j]);
+	}
+	var detachedRange = document.createRange();
+	detachedRange.detach();
+	testRanges.push("detached");
+	testRangesCached.push(detachedRange);
+}, "Setup");
 
 for (var i = 0; i < testPoints.length; i++) {
 	var node = eval(testPoints[i])[0];
 	var offset = eval(testPoints[i])[1];
 
 	// isPointInRange is an unsigned long, so per WebIDL, we need to treat it
 	// as though it wrapped to an unsigned 32-bit integer.
 	var normalizedOffset = offset % Math.pow(2, 32);
 	if (normalizedOffset < 0) {
 		normalizedOffset += Math.pow(2, 32);
 	}
 
-	// "If the detached flag is set, throw an "InvalidStateError" exception and
-	// terminate these steps."
-	test(function() {
-		var range = document.createRange();
-		range.detach();
-		assert_throws("INVALID_STATE_ERR", function() {
-			range.isPointInRange(node, offset);
-		}, "Must throw InvalidStateError if range is detached");
-	}, "Point " + i + " " + testPoints[i] + ", detached range");
-
 	for (var j = 0; j < testRanges.length; j++) {
 		test(function() {
-			if (testRangesCached[j] === undefined) {
-				try {
-					testRangesCached[j] = rangeFromEndpoints(eval(testRanges[i]));
-				} catch(e) {
-					testRangesCached[j] = null;
-				}
-			}
-			assert_not_equals(testRangesCached[j], null,
-				"Setting up the range failed");
-
 			var range = testRangesCached[j].cloneRange();
 
 			// "If node's root is different from the context object's root,
 			// return false and terminate these steps."
 			if (furthestAncestor(node) !== furthestAncestor(range.startContainer)) {
 				assert_false(range.isPointInRange(node, offset),
 					"Must return false if node has a different root from the context object");
 				return;
rename from dom/imptests/webapps/DOMCore/tests/approved/test_Range-mutations.html
rename to dom/imptests/html/dom/ranges/test_Range-mutations.html
--- a/dom/imptests/webapps/DOMCore/tests/approved/test_Range-mutations.html
+++ b/dom/imptests/html/dom/ranges/test_Range-mutations.html
@@ -1,15 +1,15 @@
 <!doctype html>
 <title>Range mutation tests</title>
 <link rel=author title="Aryeh Gregor" href=ayg@aryeh.name>
 <div id=log></div>
 <script src=/resources/testharness.js></script>
 <script src=/resources/testharnessreport.js></script>
-<script src=common.js></script>
+<script src=../common.js></script>
 <script>
 "use strict";
 
 // These tests probably use too much abstraction and too little copy-paste.
 // Reader beware.
 //
 // TODO:
 //
rename from dom/imptests/webapps/DOMCore/tests/approved/test_Range-selectNode.html
rename to dom/imptests/html/dom/ranges/test_Range-selectNode.html
--- a/dom/imptests/webapps/DOMCore/tests/approved/test_Range-selectNode.html
+++ b/dom/imptests/html/dom/ranges/test_Range-selectNode.html
@@ -1,15 +1,15 @@
 <!doctype html>
 <title>Range.selectNode() and .selectNodeContents() tests</title>
 <link rel=author title="Aryeh Gregor" href=ayg@aryeh.name>
 <div id=log></div>
 <script src=/resources/testharness.js></script>
 <script src=/resources/testharnessreport.js></script>
-<script src=common.js></script>
+<script src=../common.js></script>
 <script>
 "use strict";
 
 function testSelectNode(range, node) {
 	try {
 		range.collapsed;
 	} catch (e) {
 		// Range is detached
rename from dom/imptests/webapps/DOMCore/tests/approved/test_Range-set.html
rename to dom/imptests/html/dom/ranges/test_Range-set.html
--- a/dom/imptests/webapps/DOMCore/tests/approved/test_Range-set.html
+++ b/dom/imptests/html/dom/ranges/test_Range-set.html
@@ -1,15 +1,15 @@
 <!doctype html>
 <title>Range setting tests</title>
 <link rel=author title="Aryeh Gregor" href=ayg@aryeh.name>
 <div id=log></div>
 <script src=/resources/testharness.js></script>
 <script src=/resources/testharnessreport.js></script>
-<script src=common.js></script>
+<script src=../common.js></script>
 <script>
 "use strict";
 
 function testSetStart(range, node, offset) {
 	if (node.nodeType == Node.DOCUMENT_TYPE_NODE) {
 		assert_throws("INVALID_NODE_TYPE_ERR", function() {
 			range.setStart(node, offset);
 		}, "setStart() to a doctype must throw INVALID_NODE_TYPE_ERR");
@@ -150,120 +150,70 @@ function testSetEndAfter(range, node) {
 	while (node.parentNode.childNodes[idx] != node) {
 		idx++;
 	}
 
 	testSetEnd(range, node.parentNode, idx + 1);
 }
 
 
-test(function() {
-	for (var i = 0; i < testPoints.length; i++) {
-		var point = eval(testPoints[i]);
-		assert_throws("INVALID_STATE_ERR", function() {
-			var range = document.createRange();
-			range.detach();
-
-			range.setStart(point[0], point[1]);
-		}, "setStart(" + testPoints[i] + ")");
-
-		assert_throws("INVALID_STATE_ERR", function() {
-			var range = document.createRange();
-			range.detach();
-
-			range.setEnd(point[0], point[1]);
-		}, "setEnd(" + testPoints[i] + ")");
-	}
-
-	for (var i = 0; i < testNodes.length; i++) {
-		var node = eval(testNodes[i]);
-		assert_throws("INVALID_STATE_ERR", function() {
-			var range = document.createRange();
-			range.detach();
-
-			range.setStartBefore(node);
-		}, "setStartBefore(" + testNodes[i] + ")");
-
-		assert_throws("INVALID_STATE_ERR", function() {
-			var range = document.createRange();
-			range.detach();
-
-			range.setStartAfter(node);
-		}, "setStartAfter(" + testNodes[i] + "");
-
-		assert_throws("INVALID_STATE_ERR", function() {
-			var range = document.createRange();
-			range.detach();
-
-			range.setEndBefore(node);
-		}, "setEndBefore(" + testNodes[i] + ")");
-
-		assert_throws("INVALID_STATE_ERR", function() {
-			var range = document.createRange();
-			range.detach();
-
-			range.setStartAfter(node);
-		}, "setEndAfter(" + testNodes[i] + ")");
-	}
-}, "Setting boundary points on a detached Range must throw INVALID_STATE_ERR");
-
 var startTests = [];
 var endTests = [];
 var startBeforeTests = [];
 var startAfterTests = [];
 var endBeforeTests = [];
 var endAfterTests = [];
 
 // Don't want to eval() each point a bazillion times
 var testPointsCached = testPoints.map(eval);
-var testNodesCached = testNodes.map(eval);
+var testNodesCached = testNodesShort.map(eval);
 
-for (var i = 0; i < testRanges.length; i++) {
-	var endpoints = eval(testRanges[i]);
+for (var i = 0; i < testRangesShort.length; i++) {
+	var endpoints = eval(testRangesShort[i]);
 	var range;
 	test(function() {
 		range = ownerDocument(endpoints[0]).createRange();
 		range.setStart(endpoints[0], endpoints[1]);
 		range.setEnd(endpoints[2], endpoints[3]);
-	}, "Set up range " + i + " " + testRanges[i]);
+	}, "Set up range " + i + " " + testRangesShort[i]);
 
 	for (var j = 0; j < testPoints.length; j++) {
-		startTests.push(["setStart() with range " + i + " " + testRanges[i] + ", point " + j + " " + testPoints[j],
+		startTests.push(["setStart() with range " + i + " " + testRangesShort[i] + ", point " + j + " " + testPoints[j],
 			range,
 			testPointsCached[j][0],
 			testPointsCached[j][1]
 		]);
-		endTests.push(["setEnd() with range " + i + " " + testRanges[i] + ", point " + j + " " + testPoints[j],
+		endTests.push(["setEnd() with range " + i + " " + testRangesShort[i] + ", point " + j + " " + testPoints[j],
 			range,
 			testPointsCached[j][0],
 			testPointsCached[j][1]
 		]);
 	}
 
-	for (var j = 0; j < testNodes.length; j++) {
-		startBeforeTests.push(["setStartBefore() with range " + i + " " + testRanges[i] + ", node " + j + " " + testNodes[j],
+	for (var j = 0; j < testNodesShort.length; j++) {
+		startBeforeTests.push(["setStartBefore() with range " + i + " " + testRangesShort[i] + ", node " + j + " " + testNodesShort[j],
 			range,
 			testNodesCached[j]
 		]);
-		startAfterTests.push(["setStartAfter() with range " + i + " " + testRanges[i] + ", node " + j + " " + testNodes[j],
+		startAfterTests.push(["setStartAfter() with range " + i + " " + testRangesShort[i] + ", node " + j + " " + testNodesShort[j],
 			range,
 			testNodesCached[j]
 		]);
-		endBeforeTests.push(["setEndBefore() with range " + i + " " + testRanges[i] + ", node " + j + " " + testNodes[j],
+		endBeforeTests.push(["setEndBefore() with range " + i + " " + testRangesShort[i] + ", node " + j + " " + testNodesShort[j],
 			range,
 			testNodesCached[j]
 		]);
-		endAfterTests.push(["setEndAfter() with range " + i + " " + testRanges[i] + ", node " + j + " " + testNodes[j],
+		endAfterTests.push(["setEndAfter() with range " + i + " " + testRangesShort[i] + ", node " + j + " " + testNodesShort[j],
 			range,
 			testNodesCached[j]
 		]);
 	}
 }
 
 generate_tests(testSetStart, startTests);
 generate_tests(testSetEnd, endTests);
 generate_tests(testSetStartBefore, startBeforeTests);
 generate_tests(testSetStartAfter, startAfterTests);
-generate_tests(testSetEndBefore, startBeforeTests);
-generate_tests(testSetEndAfter, startAfterTests);
+generate_tests(testSetEndBefore, endBeforeTests);
+generate_tests(testSetEndAfter, endAfterTests);
 
 testDiv.style.display = "none";
 </script>
rename from dom/imptests/webapps/DOMCore/tests/approved/test_Range-surroundContents.html
rename to dom/imptests/html/dom/ranges/test_Range-surroundContents.html
--- a/dom/imptests/webapps/DOMCore/tests/approved/test_Range-surroundContents.html
+++ b/dom/imptests/html/dom/ranges/test_Range-surroundContents.html
@@ -3,17 +3,17 @@
 <title>Range.surroundContents() tests</title>
 <link rel=author title="Aryeh Gregor" href=ayg@aryeh.name>
 <p>To debug test failures, add a query parameter with the test id (like
 "?5,16").  Only that test will be run.  Then you can look at the resulting
 iframes in the DOM.
 <div id=log></div>
 <script src=/resources/testharness.js></script>
 <script src=/resources/testharnessreport.js></script>
-<script src=common.js></script>
+<script src=../common.js></script>
 <script>
 "use strict";
 
 testDiv.parentNode.removeChild(testDiv);
 
 function mySurroundContents(range, newParent) {
 	try {
 		// "If the detached flag is set, throw an "InvalidStateError" exception
@@ -99,18 +99,18 @@ function restoreIframe(iframe, i, j) {
 		// This will throw an exception in Opera if we reach here, which is why
 		// I try to avoid it.  It will never happen in a browser that obeys the
 		// spec, so it's really just insurance.  I don't think it actually gets
 		// hit by anything.
 		iframe.contentDocument.appendChild(iframe.contentDocument.implementation.createDocumentType("html", "", ""));
 	}
 	iframe.contentDocument.appendChild(referenceDoc.documentElement.cloneNode(true));
 	iframe.contentWindow.setupRangeTests();
-	iframe.contentWindow.testRangeInput = testRanges[i];
-	iframe.contentWindow.testNodeInput = testNodes[j];
+	iframe.contentWindow.testRangeInput = testRangesShort[i];
+	iframe.contentWindow.testNodeInput = testNodesShort[j];
 	iframe.contentWindow.run();
 }
 
 function testSurroundContents(i, j) {
 	var actualRange;
 	var expectedRange;
 	var actualNode;
 	var expectedNode;
@@ -297,36 +297,36 @@ function testSurroundContents(i, j) {
 			"startContainer superficially looks right but is actually the wrong node if you trace back its index in all its ancestors (I'm surprised this actually happened");
 	});
 	positionTests[i][j].done();
 }
 
 testRanges.unshift('"detached"');
 
 var iStart = 0;
-var iStop = testRanges.length;
+var iStop = testRangesShort.length;
 var jStart = 0;
-var jStop = testNodes.length;
+var jStop = testNodesShort.length;
 
 if (/[0-9]+,[0-9]+/.test(location.search)) {
 	var matches = /([0-9]+),([0-9]+)/.exec(location.search);
 	iStart = Number(matches[1]);
 	iStop = Number(matches[1]) + 1;
 	jStart = Number(matches[2]) + 0;
 	jStop = Number(matches[2]) + 1;
 }
 
 var domTests = [];
 var positionTests = [];
 for (var i = iStart; i < iStop; i++) {
 	domTests[i] = [];
 	positionTests[i] = [];
 	for (var j = jStart; j < jStop; j++) {
-		domTests[i][j] = async_test(i + "," + j + ": resulting DOM for range " + testRanges[i] + ", node " + testNodes[j]);
-		positionTests[i][j] = async_test(i + "," + j + ": resulting range position for range " + testRanges[i] + ", node " + testNodes[j]);
+		domTests[i][j] = async_test(i + "," + j + ": resulting DOM for range " + testRangesShort[i] + ", node " + testNodesShort[j]);
+		positionTests[i][j] = async_test(i + "," + j + ": resulting range position for range " + testRangesShort[i] + ", node " + testNodesShort[j]);
 	}
 }
 
 var actualIframe = document.createElement("iframe");
 actualIframe.style.display = "none";
 actualIframe.id = "actual";
 document.body.appendChild(actualIframe);
 
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_historical.html
rename to dom/imptests/html/dom/test_historical.html
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_interfaces.html
rename to dom/imptests/html/dom/test_interface-objects.html
rename from dom/imptests/webapps/DOMCore/tests/approved/test_interfaces.html
rename to dom/imptests/html/dom/test_interfaces.html
--- a/dom/imptests/webapps/DOMCore/tests/approved/test_interfaces.html
+++ b/dom/imptests/html/dom/test_interfaces.html
@@ -240,17 +240,17 @@ interface Document : Node {
   NodeIterator createNodeIterator(Node root, optional unsigned long whatToShow, optional NodeFilter? filter);
   TreeWalker createTreeWalker(Node root, optional unsigned long whatToShow, optional NodeFilter? filter);
 };
 
 interface XMLDocument : Document {};
 
 interface DOMImplementation {
   DocumentType createDocumentType(DOMString qualifiedName, DOMString publicId, DOMString systemId);
-  XMLDocument createDocument(DOMString? namespace, [TreatNullAs=EmptyString] DOMString qualifiedName, optional DocumentType? doctype = null);
+  XMLDocument createDocument(DOMString? namespace, [TreatNullAs=EmptyString] DOMString qualifiedName, DocumentType? doctype);
   Document createHTMLDocument(optional DOMString title);
 
   boolean hasFeature(DOMString feature, [TreatNullAs=EmptyString] DOMString version);
 };
 
 [Constructor]
 interface DocumentFragment : Node {
 };
@@ -329,17 +329,17 @@ interface Range {
   readonly attribute Node commonAncestorContainer;
 
   void setStart(Node refNode, unsigned long offset);
   void setEnd(Node refNode, unsigned long offset);
   void setStartBefore(Node refNode);
   void setStartAfter(Node refNode);
   void setEndBefore(Node refNode);
   void setEndAfter(Node refNode);
-  void collapse(optional boolean toStart = false);
+  void collapse(optional boolean toStart /* = false */);
   void selectNode(Node refNode);
   void selectNodeContents(Node refNode);
 
   const unsigned short START_TO_START = 0;
   const unsigned short START_TO_END = 1;
   const unsigned short END_TO_END = 2;
   const unsigned short END_TO_START = 3;
   short compareBoundaryPoints(unsigned short how, Range sourceRange);
@@ -437,40 +437,43 @@ interface DOMTokenList {
 };
 
 interface DOMSettableTokenList : DOMTokenList {
             attribute DOMString value;
 };
 </script>
 <script>
 "use strict";
-var xmlDoc = document.implementation.createDocument(null, "", null);
-var domException;
-try { document.appendChild(document); } catch(e) { domException = e; }
-var detachedRange = document.createRange();
-detachedRange.detach();
-var element = xmlDoc.createElementNS(null, "test");
-element.setAttribute("bar", "baz");
+var xmlDoc, domException, detachedRange, element;
+var idlArray;
+setup(function() {
+	xmlDoc = document.implementation.createDocument(null, "", null);
+	try { document.appendChild(document); } catch(e) { domException = e; }
+	detachedRange = document.createRange();
+	detachedRange.detach();
+	element = xmlDoc.createElementNS(null, "test");
+	element.setAttribute("bar", "baz");
 
-var idlArray = new IdlArray();
-idlArray.add_idls(document.querySelector("script[type=text\\/plain]").textContent);
-idlArray.add_objects({
-	DOMException: ['domException'],
-	Event: ['document.createEvent("Event")', 'new Event("foo")'],
-	CustomEvent: ['new CustomEvent("foo")'],
-	XMLDocument: ['xmlDoc'],
-	DOMImplementation: ['document.implementation'],
-	DocumentFragment: ['document.createDocumentFragment()'],
-	DocumentType: ['document.doctype'],
-	Element: ['element'],
-	Attr: ['document.querySelector("[id]").attributes[0]'],
-	Text: ['document.createTextNode("abc")'],
-	ProcessingInstruction: ['xmlDoc.createProcessingInstruction("abc", "def")'],
-	Comment: ['document.createComment("abc")'],
-	Range: ['document.createRange()', 'detachedRange'],
-	NodeIterator: ['document.createNodeIterator(document.body, NodeFilter.SHOW_ALL, null, false)'],
-	TreeWalker: ['document.createTreeWalker(document.body, NodeFilter.SHOW_ALL, null, false)'],
-	NodeList: ['document.querySelectorAll("script")'],
-	HTMLCollection: ['document.body.children'],
-	DOMTokenList: ['document.body.classList'],
+	idlArray = new IdlArray();
+	idlArray.add_idls(document.querySelector("script[type=text\\/plain]").textContent);
+	idlArray.add_objects({
+		DOMException: ['domException'],
+		Event: ['document.createEvent("Event")', 'new Event("foo")'],
+		CustomEvent: ['new CustomEvent("foo")'],
+		XMLDocument: ['xmlDoc'],
+		DOMImplementation: ['document.implementation'],
+		DocumentFragment: ['document.createDocumentFragment()'],
+		DocumentType: ['document.doctype'],
+		Element: ['element'],
+		Attr: ['document.querySelector("[id]").attributes[0]'],
+		Text: ['document.createTextNode("abc")'],
+		ProcessingInstruction: ['xmlDoc.createProcessingInstruction("abc", "def")'],
+		Comment: ['document.createComment("abc")'],
+		Range: ['document.createRange()', 'detachedRange'],
+		NodeIterator: ['document.createNodeIterator(document.body, NodeFilter.SHOW_ALL, null, false)'],
+		TreeWalker: ['document.createTreeWalker(document.body, NodeFilter.SHOW_ALL, null, false)'],
+		NodeList: ['document.querySelectorAll("script")'],
+		HTMLCollection: ['document.body.children'],
+		DOMTokenList: ['document.body.classList'],
+	});
 });
 idlArray.test();
 </script>
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/traversal/Makefile.in
@@ -0,0 +1,5 @@
+# THIS FILE IS AUTOGENERATED BY importTestsuite.py - DO NOT EDIT
+
+MOCHITEST_FILES := \
+  test_NodeFilter-constants.html \
+  $(NULL)
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/traversal/moz.build
@@ -0,0 +1,4 @@
+# THIS FILE IS AUTOGENERATED BY importTestsuite.py - DO NOT EDIT
+
+DIRS += [
+]
rename from dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_NodeFilter-constants.html
rename to dom/imptests/html/dom/traversal/test_NodeFilter-constants.html
--- a/dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/test_NodeFilter-constants.html
+++ b/dom/imptests/html/dom/traversal/test_NodeFilter-constants.html
@@ -1,13 +1,13 @@
 <!doctype html>
 <title>NodeFilter constants</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="constants.js"></script>
+<script src="../constants.js"></script>
 <div id="log"></div>
 <script>
 var objects = [
   [NodeFilter, "NodeFilter interface object"],
 ]
 testConstants(objects, [
   ["FILTER_ACCEPT", 1],
   ["FILTER_REJECT", 2],
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/traversal/unfinished/Makefile.in
@@ -0,0 +1,5 @@
+# THIS FILE IS AUTOGENERATED BY importTestsuite.py - DO NOT EDIT
+
+MOCHITEST_FILES := \
+  TODO \
+  $(NULL)
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/traversal/unfinished/TODO
@@ -0,0 +1,1 @@
+Check what happens when a NodeFilter turns a number not in the range 1..3
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/dom/traversal/unfinished/moz.build
@@ -0,0 +1,4 @@
+# THIS FILE IS AUTOGENERATED BY importTestsuite.py - DO NOT EDIT
+
+DIRS += [
+]
--- a/dom/imptests/html/html/dom/documents/dta/test_document.body-setter-01.html
+++ b/dom/imptests/html/html/dom/documents/dta/test_document.body-setter-01.html
@@ -2,16 +2,17 @@
 <title>Setting document.body to incorrect values</title>
 <link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
 <link rel="help" href="http://www.whatwg.org/html/#dom-document-body">
 <link rel="help" href="http://dev.w3.org/2006/webapi/WebIDL/#es-interface">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <div id="log"></div>
 <script>
+var originalBody = document.body;
 test(function() {
   assert_throws(new TypeError(), function() {
     document.body = "text"
   })
 }, "Should throw a TypeError when trying to set document.body to a string.")
 test(function() {
   assert_throws("HierarchyRequestError", function() {
     document.body = document.createElement("div")
@@ -19,9 +20,12 @@ test(function() {
 }, "Should throw a HierarchyRequestError when trying to set document.body to a div element.")
 test(function() {
   var doc = document.implementation.createHTMLDocument("")
   doc.removeChild(doc.documentElement)
   assert_throws("HierarchyRequestError", function() {
     doc.body = document.createElement("body")
   })
 }, "Should throw a HierarchyRequestError when trying to set document.body when there's no root element.")
+test(function() {
+  assert_equals(document.body, originalBody);
+}, "document.body has not changed")
 </script>
--- a/dom/imptests/html/html/dom/elements/global-attributes/Makefile.in
+++ b/dom/imptests/html/html/dom/elements/global-attributes/Makefile.in
@@ -1,14 +1,14 @@
 # THIS FILE IS AUTOGENERATED BY importTestsuite.py - DO NOT EDIT
 
 MOCHITEST_FILES := \
   test_classlist-nonstring.html \
   test_dataset-delete.html \
   test_dataset-enumeration.html \
   test_dataset-get.html \
   test_dataset.html \
-  test_dataset-instanceof.html \
+  test_dataset-prototype.html \
   test_dataset-set.html \
   test_document-dir.html \
   test_id-attribute.html \
   test_id-name.html \
   $(NULL)
--- a/dom/imptests/html/html/dom/elements/global-attributes/test_dataset-get.html
+++ b/dom/imptests/html/html/dom/elements/global-attributes/test_dataset-get.html
@@ -27,16 +27,18 @@
       test(function() { assert_true(testGet('data---foo', '-Foo')); },
         "Getting element.dataset['-Foo'] should return the value of element.getAttribute('data---foo')'");
       test(function() { assert_true(testGet('data-Foo', 'foo')); },
         "Getting element.dataset['foo'] should return the value of element.getAttribute('data-Foo')'");
       test(function() { assert_true(testGet('data-', '')); },
         "Getting element.dataset[''] should return the value of element.getAttribute('data-')'");
       test(function() { assert_true(testGet('data-\xE0', '\xE0')); },
         "Getting element.dataset['\xE0'] should return the value of element.getAttribute('data-\xE0')'");
+      test(function() { assert_true(testGet('data-to-string', 'toString')); },
+        "Getting element.dataset['toString'] should return the value of element.getAttribute('data-to-string')'");
 
       function matchesNothingInDataset(attr)
       {
         var d = document.createElement("div");
         d.setAttribute(attr, "value");
 
         if (!d.dataset)
           return false;
rename from dom/imptests/html/html/dom/elements/global-attributes/test_dataset-instanceof.html
rename to dom/imptests/html/html/dom/elements/global-attributes/test_dataset-prototype.html
--- a/dom/imptests/html/html/dom/elements/global-attributes/test_dataset-instanceof.html
+++ b/dom/imptests/html/html/dom/elements/global-attributes/test_dataset-prototype.html
@@ -6,11 +6,21 @@
     <script src="/resources/testharnessreport.js"></script>
   </head>
   <body>
     <h1>Dataset - element.dataset is an instance of DOMStringMap</h1>
     <div id="log"></div>
     <script>
       test(function() { assert_true(document.createElement("div").dataset instanceof window.DOMStringMap); },
         "An elements dataset property is an instance of a DOMStringMap");
+      test(function() {
+        var dataset = document.createElement("div").dataset;
+        assert_true("toString" in dataset, '"toString" in dataset');
+        assert_equals(dataset.toString, Object.prototype.toString);
+        assert_false("expando" in dataset, '"expando" in dataset');
+        assert_equals(dataset.expando, undefined);
+        Object.prototype.expando = 42;
+        assert_true("expando" in dataset, '"expando" in dataset');
+        assert_equals(dataset.expando, 42);
+      }, "Properties on Object.prototype should shine through.");
     </script>
   </body>
 </html>
--- a/dom/imptests/html/html/dom/elements/global-attributes/test_document-dir.html
+++ b/dom/imptests/html/html/dom/elements/global-attributes/test_document-dir.html
@@ -1,25 +1,26 @@
 <!DOCTYPE html>
 <html dir="LTR">
 <title>document.dir</title>
-<link rel="help" href="http://www.whatwg.org/html5/#dom-document-dir">
-<link rel="help" href="http://www.whatwg.org/html5/#reflect">
+<link rel="help" href="http://www.whatwg.org/html/#dom-document-dir">
+<link rel="help" href="http://www.whatwg.org/html/#reflect">
 <link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
-<link rel="stylesheet" href="/resources/testharness.css">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <div id="log"></div>
 <script>
 test(function() {
   assert_equals(document.dir, "ltr");
   assert_equals(document.documentElement.getAttribute("dir"), "LTR");
 }, "Markup attribute")
 test(function() {
   document.dir = "x-garbage";
   assert_equals(document.dir, "");
   assert_equals(document.documentElement.getAttribute("dir"), "x-garbage");
 }, "Setting the idl attribute to a garbage value")
 test(function() {
   document.dir = "";
-  assert_equals(document.documentElement.hasAttribute("dir"), false, "Attribute should be gone");
-}, "Setting the idl attribute to the empty sting")
+  assert_true(document.documentElement.hasAttribute("dir"), "Attribute should still be around");
+  assert_equals(document.dir, "");
+  assert_equals(document.documentElement.getAttribute("dir"), "");
+}, "Setting the idl attribute to the empty string")
 </script>
--- a/dom/imptests/html/html/editing/the-hidden-attribute/Makefile.in
+++ b/dom/imptests/html/html/editing/the-hidden-attribute/Makefile.in
@@ -1,2 +1,3 @@
 # THIS FILE IS AUTOGENERATED BY importTestsuite.py - DO NOT EDIT
 
+
--- a/dom/imptests/html/html/semantics/forms/the-form-element/Makefile.in
+++ b/dom/imptests/html/html/semantics/forms/the-form-element/Makefile.in
@@ -1,8 +1,9 @@
 # THIS FILE IS AUTOGENERATED BY importTestsuite.py - DO NOT EDIT
 
 MOCHITEST_FILES := \
   test_form-elements-interfaces-01.html \
   test_form-elements-matches.html \
   test_form-elements-nameditem-01.html \
   test_form-elements-nameditem-02.html \
+  test_form-nameditem.html \
   $(NULL)
new file mode 100644
--- /dev/null
+++ b/dom/imptests/html/html/semantics/forms/the-form-element/test_form-nameditem.html
@@ -0,0 +1,239 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Form named getter</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<!-- XXX Nothing tests id attributes yet. -->
+<!-- XXX Keygen. -->
+<!-- XXX We also need tests for moving inputs and forms in the DOM. -->
+<form>
+<input type=button name=button>
+<input type=radio name=radio value=x>
+<input type=radio name=radio value=y>
+<input type=radio name=radio value=z>
+</form>
+
+<form>
+<button name=l1></button>
+<fieldset name=l2></fieldset>
+<input type=hidden name=l3>
+<input type=text name=l4>
+<input type=search name=l5>
+<input type=tel name=l6>
+<input type=url name=l7>
+<input type=email name=l8>
+<input type=password name=l9>
+<input type=datetime name=l10>
+<input type=date name=l11>
+<input type=month name=l12>
+<input type=week name=l13>
+<input type=time name=l14>
+<input type=datetime-local name=l15>
+<input type=number name=l16>
+<input type=range name=l17>
+<input type=color name=l18>
+<input type=checkbox name=l19>
+<input type=radio name=l20>
+<input type=file name=l21>
+<input type=submit name=l22>
+<input type=image name=l23>
+<input type=reset name=l24>
+<input type=button name=l25>
+<input type=foo name=l26>
+<input name=l27>
+<object name=l28></object>
+<output name=l29></output>
+<select name=l30></select>
+<textarea name=l31></textarea>
+</form>
+
+<form>
+<!-- EventTarget -->
+<input type=radio name=addEventListener>
+<input type=radio name=removeEventListener>
+<input type=radio name=dispatchEvent>
+
+<!-- Node -->
+<input type=radio name=nodeType>
+<input type=radio name=nodeName>
+<input type=radio name=ownerDocument>
+
+<!-- Element -->
+<input type=radio name=namespaceURI>
+<input type=radio name=prefix>
+<input type=radio name=localName>
+
+<!-- HTMLElement -->
+<input type=radio name=title>
+<input type=radio name=lang>
+<input type=radio name=dir>
+
+<!-- HTMLFormElement -->
+<input type=radio name=acceptCharset>
+<input type=radio name=action>
+<input type=radio name=autocomplete>
+<input type=radio name=enctype>
+<input type=radio name=encoding>
+<input type=radio name=method>
+<input type=radio name=name>
+<input type=radio name=noValidate>
+<input type=radio name=target>
+<input type=radio name=elements>
+<input type=radio name=length>
+<input type=radio name=submit>
+<input type=radio name=reset>
+<input type=radio name=checkValidity>
+</form>
+
+<img name=x>
+<form></form><!-- no child nodes -->
+<img name=y>
+<form><!-- a child node --></form>
+<img name=z>
+
+<input form=a name=b>
+<form id=a></form>
+<input form=c name=d>
+<input form=c name=d>
+<form id=c></form>
+<script>
+test(function() {
+  var form = document.getElementsByTagName("form")[0]
+  assert_equals(form.item, undefined)
+  assert_false("item" in form)
+}, "Forms should not have an item method")
+
+test(function() {
+  var form = document.getElementsByTagName("form")[0]
+  assert_equals(form.namedItem, undefined)
+  assert_false("namedItem" in form)
+}, "Forms should not have a namedItem method")
+
+test(function() {
+  var form = document.getElementsByTagName("form")[0]
+  var button = document.getElementsByTagName("input")[0]
+  assert_equals(button.type, "button")
+  assert_equals(form.button, button)
+  assert_equals(form.button.length, undefined)
+}, "Name for a single element should work")
+
+test(function() {
+  var form = document.getElementsByTagName("form")[0]
+  assert_equals(form.radio.item(-1), null)
+  assert_array_equals([0, 1, 2].map(function(i) {
+    return form.radio.item(i).value
+  }), ["x", "y", "z"])
+  assert_equals(form.radio.item(3), null)
+}, "Calling item() on the NodeList returned from the named getter should work")
+
+test(function() {
+  var form = document.getElementsByTagName("form")[0]
+  assert_equals(form.radio.length, 3)
+  assert_equals(form.radio[-1], undefined)
+  assert_array_equals([0, 1, 2].map(function(i) {
+    return form.radio[i].value
+  }), ["x", "y", "z"])
+  assert_equals(form.radio[3], undefined)
+}, "Indexed getter on the NodeList returned from the named getter should work")
+
+test(function() {
+  var form = document.getElementsByTagName("form")[0]
+  var indices = [-1, 0, 1, 2, 3]
+  indices.forEach(function(i) {
+    assert_throws(new TypeError(), function() {
+      form.radio(i)
+    })
+  })
+}, "Invoking a legacycaller on the NodeList returned from the named getter " +
+   "should not work")
+
+test(function() {
+  var form = document.getElementsByTagName("form")[1]
+  for (var i = 1; i <= 31; ++i) {
+    if (i == 23) {
+      // input type=image
+      assert_equals(form["l" + i], undefined)
+    } else {
+      assert_equals(form["l" + i], form.children[i - 1])
+    }
+  }
+}, "All listed elements except input type=image should be present in the form")
+
+test(function() {
+  var names = [
+    // EventTarget
+    "addEventListener", "removeEventListener", "dispatchEvent",
+    // Node
+    "nodeType", "nodeName", "ownerDocument",
+    // Element
+    "namespaceURI", "prefix", "localName",
+    // HTMLElement
+    "title", "lang", "dir",
+    // HTMLFormElement
+    "acceptCharset", "action", "autocomplete", "enctype", "encoding", "method",
+    "name", "noValidate", "target", "elements", "length", "submit", "reset",
+    "checkValidity"
+  ]
+  var form = document.getElementsByTagName("form")[2]
+  names.forEach(function(name, i) {
+    assert_equals(form[name], form.children[i])
+  })
+}, "Named elements should override builtins")
+
+test(function() {
+  var form = document.getElementsByTagName("form")[3]
+  assert_equals(form.x, undefined, "x should not be associated with the form")
+  assert_equals(form.y, undefined, "y should not be associated with the form")
+  assert_equals(form.z, undefined, "z should not be associated with the form")
+  assert_equals(form[0], undefined, "The form should not have supported property indices")
+  assert_equals(form.length, 0)
+}, "Named items outside the form should not be returned (no children)")
+
+test(function() {
+  var form = document.getElementsByTagName("form")[4]
+  assert_equals(form.x, undefined, "x should not be associated with the form")
+  assert_equals(form.y, undefined, "y should not be associated with the form")
+  assert_equals(form.z, undefined, "z should not be associated with the form")
+  assert_equals(form[0], undefined, "The form should not have supported property indices")
+  assert_equals(form.length, 0)
+}, "Named items outside the form should not be returned (one child)")
+
+test(function() {
+  var form = document.getElementsByTagName("form")[5]
+  assert_equals(form.id, "a")
+
+  var input = document.getElementsByName("b")[0]
+  assert_equals(input.localName, "input")
+  assert_equals(input.getAttribute("form"), "a")
+
+  assert_equals(form.b, input);
+}, "The form attribute should be taken into account for named getters (single element)")
+
+test(function() {
+  var form = document.getElementsByTagName("form")[6]
+  assert_equals(form.id, "c")
+
+  var input1 = document.getElementsByName("d")[0]
+  assert_equals(input1.localName, "input")
+  assert_equals(input1.getAttribute("form"), "c")
+
+  var input2 = document.getElementsByName("d")[1]
+  assert_equals(input2.localName, "input")
+  assert_equals(input2.getAttribute("form"), "c")
+
+  assert_true(form.d instanceof NodeList, "form.d should be a NodeList")
+  assert_array_equals(form.d, [input1, input2])
+}, "The form attribute should be taken into account for named getters (multiple elements)")
+
+test(function() {
+  var f = document.body.appendChild(document.createElement("form"))
+  f.id = "f"
+  var g = f.appendChild(document.createElement("form"))
+  g.id = "g"
+  var input = g.appendChild(document.createElement("input"))
+  input.name = "x"
+  assert_equals(f.x, undefined)
+  assert_equals(g.x, input)
+}, "Input should only be a named property on the innermost form that contains it")
+</script>
--- a/dom/imptests/html/html/webappapis/atob/test_base64.html
+++ b/dom/imptests/html/html/webappapis/atob/test_base64.html
@@ -2,37 +2,16 @@
 <!-- Originally developed by Aryeh Gregor, funded by Google.  Copyright belongs
 to Google. -->
 <title>atob()/btoa() tests</title>
 <meta charset=utf-8>
 <div id=log></div>
 <script src=/resources/testharness.js></script>
 <script src=/resources/testharnessreport.js></script>
 <script>
-// From WebIDL:
-//
-// * The value of the Function object’s length property is a Number determined
-//   as follows:
-//
-//   1. Let S be the effective overload set for regular operations (if the
-//      operation is a regular operation) or for static operations (if the
-//      operation is a static operation) with identifier id on interface I and
-//      with argument count 0 (for the ECMAScript language binding).
-//   2. Return the maximum argument list length of the functions in the entries
-//      of S.
-//
-// As far as I understand it, this means the length must be 1 here.
-test(function() {
-	assert_equals(btoa.length, 1);
-}, "btoa.length must equal the maximum number of arguments, namely 1");
-
-test(function() {
-	assert_equals(atob.length, 1);
-}, "atob.length must equal the maximum number of arguments, namely 1");
-
 /**
  * btoa() as defined by the HTML5 spec, which mostly just references RFC4648.
  */
 function mybtoa(s) {
 	// String conversion as required by WebIDL.
 	s = String(s);
 
 	// "The btoa() method must throw an INVALID_CHARACTER_ERR exception if the
rename from dom/imptests/html/old-tests/submission/Opera/microdata/Makefile.in
rename to dom/imptests/html/microdata/microdata-dom-api/Makefile.in
rename from dom/imptests/html/old-tests/submission/Opera/microdata/moz.build
rename to dom/imptests/html/microdata/microdata-dom-api/moz.build
rename from dom/imptests/html/old-tests/submission/Opera/microdata/test_001.html
rename to dom/imptests/html/microdata/microdata-dom-api/test_001.html
--- a/dom/imptests/moz.build
+++ b/dom/imptests/moz.build
@@ -2,34 +2,35 @@
 # vim: set filetype=python:
 # 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/.
 
 DIRS += [
     'failures/editing/conformancetest',
     'failures/editing/selecttest',
+    'failures/html/dom',
+    'failures/html/dom/collections',
+    'failures/html/dom/errors',
+    'failures/html/dom/nodes',
+    'failures/html/dom/ranges',
     'failures/html/html/browsers/the-window-object',
     'failures/html/html/browsers/the-window-object/named-access-on-the-window-object',
     'failures/html/html/dom/documents/dta',
     'failures/html/html/dom/documents/dta/doc.gEBN',
-    'failures/html/html/dom/elements/global-attributes',
     'failures/html/html/obsolete/implreq/oeaaa',
     'failures/html/html/semantics/forms/the-form-element',
     'failures/html/html/semantics/forms/the-option-element',
     'failures/html/html/semantics/forms/the-select-element',
     'failures/html/html/semantics/scripting-1/the-script-element',
     'failures/html/html/semantics/tabular-data/the-table-element',
     'failures/html/html/webappapis/atob',
     'failures/html/js/builtins',
-    'failures/html/old-tests/submission/Opera/microdata',
+    'failures/html/microdata/microdata-dom-api',
     'failures/html/typedarrays',
-    'failures/webapps/DOMCore/tests/approved',
-    'failures/webapps/DOMCore/tests/submissions/Ms2ger',
-    'failures/webapps/DOMCore/tests/submissions/Opera',
     'failures/webapps/WebStorage/tests/submissions/Infraware',
     'failures/webapps/WebStorage/tests/submissions/Ms2ger',
     'failures/webapps/XMLHttpRequest/tests/submissions/Ms2ger'
 ]
 
 include('editing.mozbuild')
 include('html.mozbuild')
 include('webapps.mozbuild')
--- a/dom/imptests/parseManifest.py
+++ b/dom/imptests/parseManifest.py
@@ -1,27 +1,28 @@
-# Copyright (C) 2011-2012 Ms2ger
+# Copyright (C) 2011-2013 Ms2ger
 #
-# Permission is hereby granted, free of charge, to any person obtaining a copy of
-# this software and associated documentation files (the "Software"), to deal in
-# the Software without restriction, including without limitation the rights to
-# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-# of the Software, and to permit persons to whom the Software is furnished to do
-# so, subject to the following conditions:
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
 #
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
 #
 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
 
 def parseManifest(fd):
     def parseReftestLine(chunks):
         assert len(chunks) % 2 == 0
         reftests = []
         for i in range(2, len(chunks), 2):
             if not chunks[i] in ["==", "!="]:
                 raise Exception("Misformatted reftest line " + line)
@@ -38,27 +39,31 @@ def parseManifest(fd):
         if not line:
             continue
 
         chunks = line.split(" ")
 
         if chunks[0] == "MANIFEST":
             raise Exception("MANIFEST listed on line " + line)
 
-        if chunks[0] == "dir" or (chunks[0] == "support" and chunks[1] == "dir"):
-            dirs.append(chunks[1]);
+        if chunks[0] == "dir":
+            dirs.append(chunks[1])
+        elif chunks[0] == "support" and chunks[1] == "dir":
+            dirs.append(chunks[1])
         elif chunks[0] == "ref":
             if len(chunks) % 2:
                 raise Exception("Missing chunk in line " + line)
             reftests.extend(parseReftestLine(chunks))
         elif chunks[0] == "support":
             supportfiles.append(chunks[1])
-        elif chunks[0] in ["manual", "parser"]:
+        elif chunks[0] in ["manual", "parser", "http"]:
             othertests.append(chunks[1])
-        else: # automated
+        else:
+            # automated
             autotests.append(chunks[0])
     return dirs, autotests, reftests, othertests, supportfiles
 
+
 def parseManifestFile(path):
     fp = open(path)
     dirs, autotests, reftests, othertests, supportfiles = parseManifest(fp)
     fp.close()
     return dirs, autotests, reftests, othertests, supportfiles
--- a/dom/imptests/webapps.mozbuild
+++ b/dom/imptests/webapps.mozbuild
@@ -1,9 +1,6 @@
 # THIS FILE IS AUTOGENERATED BY importTestSuites.py - DO NOT EDIT
 
 DIRS += [
-    'webapps/DOMCore/tests/approved',
-    'webapps/DOMCore/tests/submissions/Ms2ger',
-    'webapps/DOMCore/tests/submissions/Opera',
     'webapps/WebStorage/tests/submissions',
     'webapps/XMLHttpRequest/tests/submissions/Ms2ger',
 ]
--- a/dom/imptests/webapps.txt
+++ b/dom/imptests/webapps.txt
@@ -1,6 +1,3 @@
 hg|https://dvcs.w3.org/hg/webapps|webapps
-DOMCore/tests/approved
-DOMCore/tests/submissions/Ms2ger
-DOMCore/tests/submissions/Opera
 WebStorage/tests/submissions
 XMLHttpRequest/tests/submissions/Ms2ger
deleted file mode 100644
--- a/dom/imptests/webapps/DOMCore/tests/approved/Makefile.in
+++ /dev/null
@@ -1,32 +0,0 @@
-# THIS FILE IS AUTOGENERATED BY importTestsuite.py - DO NOT EDIT
-
-MOCHITEST_FILES := \
-  test_exceptions.html \
-  test_interfaces.html \
-  test_Node-compareDocumentPosition.html \
-  test_Node-contains.html \
-  test_Node-properties.html \
-  test_Range-cloneContents.html \
-  test_Range-cloneRange.html \
-  test_Range-collapse.html \
-  test_Range-commonAncestorContainer.html \
-  test_Range-compareBoundaryPoints.html \
-  test_Range-comparePoint.html \
-  test_Range-deleteContents.html \
-  test_Range-extractContents.html \
-  test_Range-insertNode.html \
-  test_Range-intersectsNode.html \
-  test_Range-isPointInRange.html \
-  test_Range-mutations.html \
-  test_Range-selectNode.html \
-  test_Range-set.html \
-  common.js \
-  Range-test-iframe.html \
-  $(NULL)
-
-# Temporarily disable on Windows for bug 875585 and deps
-ifneq (windows,$(MOZ_WIDGET_TOOLKIT))
-MOCHITEST_FILES += \
-  test_Range-surroundContents.html \
-  $(NULL)
-endif
deleted file mode 100644
--- a/dom/imptests/webapps/DOMCore/tests/approved/moz.build
+++ /dev/null
@@ -1,5 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# THIS FILE IS AUTOGENERATED BY importTestsuite.py - DO NOT EDIT
-
-DIRS += [
-]
--- a/dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/Makefile.in
+++ b/dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/Makefile.in
@@ -1,71 +0,0 @@
-# THIS FILE IS AUTOGENERATED BY importTestsuite.py - DO NOT EDIT
-
-MOCHITEST_FILES := \
-  test_attributes.html \
-  test_case.html \
-  test_CharacterData-appendData.html \
-  test_CharacterData-deleteData.html \
-  test_CharacterData-insertData.html \
-  test_CharacterData-remove.html \
-  test_CharacterData-replaceData.html \
-  test_Document-adoptNode.html \
-  test_Document-createComment.html \
-  test_Document-createElement.html \
-  test_Document-createElementNS.html \
-  test_Document-createEvent.html \
-  test_Document-createProcessingInstruction.html \
-  test_Document-createProcessingInstruction-literal-1.xhtml \
-  test_Document-createProcessingInstruction-literal-2.xhtml \
-  test_Document-createProcessingInstruction.xhtml \
-  test_Document-createTreeWalker.html \
-  test_Document-getElementById.html \
-  test_Document-getElementsByTagName.html \
-  test_Document-getElementsByTagNameNS.html \
-  test_Document-importNode.html \
-  test_DocumentType-remove.html \
-  test_DOMException-constants.html \
-  test_DOMImplementation-createDocument.html \
-  test_DOMImplementation-createDocumentType.html \
-  test_DOMImplementation-createHTMLDocument.html \
-  test_DOMImplementation-hasFeature.html \
-  test_Element-children.html \
-  test_Element-getElementsByClassName.html \
-  test_Element-remove.html \
-  test_Element-removeAttributeNS.html \
-  test_Element-tagName.html \
-  test_Event-constants.html \
-  test_Event-constructors.html \
-  test_Event-defaultPrevented.html \
-  test_Event-initEvent.html \
-  test_EventTarget-dispatchEvent.html \
-  test_Event-type.html \
-  test_historical.html \
-  test_interfaces.html \
-  test_Node-appendChild.html \
-  test_Node-cloneNode.html \
-  test_Node-constants.html \
-  test_Node-contains.xml \
-  test_Node-insertBefore.html \
-  test_Node-isEqualNode.xhtml \
-  test_Node-lookupPrefix.xhtml \
-  test_Node-nodeName.html \
-  test_Node-nodeName.xhtml \
-  test_Node-normalize.html \
-  test_Node-parentElement.html \
-  test_Node-parentNode.html \
-  test_Node-removeChild.html \
-  test_Node-replaceChild.html \
-  test_NodeFilter-constants.html \
-  test_Range-attributes.html \
-  test_Range-commonAncestorContainer.html \
-  test_Range-comparePoint.html \
-  test_Range-detach.html \
-  test_Range-intersectsNode-binding.html \
-  attributes.js \
-  case.js \
-  creators.js \
-  constants.js \
-  ChildNode-remove.js \
-  Document-createProcessingInstruction.js \
-  productions.js \
-  $(NULL)
deleted file mode 100644
--- a/dom/imptests/webapps/DOMCore/tests/submissions/Ms2ger/moz.build
+++ /dev/null
@@ -1,5 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# THIS FILE IS AUTOGENERATED BY importTestsuite.py - DO NOT EDIT
-
-DIRS += [
-]
--- a/dom/imptests/webapps/DOMCore/tests/submissions/Opera/Makefile.in
+++ b/dom/imptests/webapps/DOMCore/tests/submissions/Opera/Makefile.in
@@ -1,22 +0,0 @@
-# THIS FILE IS AUTOGENERATED BY importTestsuite.py - DO NOT EDIT
-
-MOCHITEST_FILES := \
-  test_getElementsByClassName-01.htm \
-  test_getElementsByClassName-02.htm \
-  test_getElementsByClassName-03.htm \
-  test_getElementsByClassName-04.htm \
-  test_getElementsByClassName-05.htm \
-  test_getElementsByClassName-06.htm \
-  test_getElementsByClassName-07.htm \
-  test_getElementsByClassName-08.htm \
-  test_getElementsByClassName-09.htm \
-  test_getElementsByClassName-10.xml \
-  test_getElementsByClassName-11.xml \
-  test_getElementsByClassName-12.htm \
-  test_getElementsByClassName-13.htm \
-  test_getElementsByClassName-14.htm \
-  test_getElementsByClassName-15.htm \
-  test_getElementsByClassName-16.htm \
-  test_getElementsByClassName-17.htm \
-  test_getElementsByClassName-18.htm \
-  $(NULL)
deleted file mode 100644
--- a/dom/imptests/webapps/DOMCore/tests/submissions/Opera/moz.build
+++ /dev/null
@@ -1,5 +0,0 @@
-# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# THIS FILE IS AUTOGENERATED BY importTestsuite.py - DO NOT EDIT
-
-DIRS += [
-]
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl
+++ b/dom/interfaces/base/nsIDOMWindowUtils.idl
@@ -38,17 +38,17 @@ interface nsIDOMFile;
 interface nsIFile;
 interface nsIDOMTouch;
 interface nsIDOMClientRect;
 interface nsIURI;
 interface nsIDOMEventTarget;
 interface nsIRunnable;
 interface nsICompositionStringSynthesizer;
 
-[scriptable, uuid(a1383ae5-e828-4c9a-929d-5293e61beb64)]
+[scriptable, uuid(750a47b6-8bdb-4cad-ba2c-b7d3e66d8021)]
 interface nsIDOMWindowUtils : nsISupports {
 
   /**
    * Image animation mode of the window. When this attribute's value
    * is changed, the implementation should set all images in the window
    * to the given value. That is, when set to kDontAnimMode, all images
    * will stop animating. The attribute's value must be one of the
    * animationMode values from imgIContainer.
@@ -1082,16 +1082,22 @@ interface nsIDOMWindowUtils : nsISupport
   readonly attribute float displayDPI;
 
   /**
    * Return the outer window with the given ID, if any.  Can return null.
    * @deprecated Use nsIWindowMediator.getOuterWindowWithId.  See bug 865664.
    */
   nsIDOMWindow getOuterWindowWithId(in unsigned long long aOuterWindowID);
 
+  /**
+   * Return this window's frame element.
+   * Ignores all chrome/content or mozbrowser boundaries.
+   */
+  readonly attribute nsIDOMElement containerElement;
+
   [noscript] void RenderDocument(in nsConstRect aRect,
                                  in uint32_t aFlags,
                                  in nscolor aBackgroundColor,
                                  in gfxContext aThebesContext);
 
   /**
    * advanceTimeAndRefresh allows the caller to take over the refresh
    * driver timing for a window.  A call to advanceTimeAndRefresh does
--- a/dom/media/tests/mochitest/moz.build
+++ b/dom/media/tests/mochitest/moz.build
@@ -1,6 +1,7 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+WEBRTC_SIGNALLING_TEST_MANIFESTS += ['steeplechase.ini']
new file mode 100644
--- /dev/null
+++ b/dom/media/tests/mochitest/steeplechase.ini
@@ -0,0 +1,8 @@
+[DEFAULT]
+support-files =
+  head.js
+  mediaStreamPlayback.js
+  pc.js
+  templates.js
+
+[test_peerConnection_basicAudio.html]
--- a/dom/tests/browser/Makefile.in
+++ b/dom/tests/browser/Makefile.in
@@ -12,17 +12,19 @@ MOCHITEST_BROWSER_FILES := \
   browser_ConsoleStoragePBTest_perwindowpb.js \
   browser_autofocus_preference.js \
   browser_bug396843.js \
   browser_xhr_sandbox.js \
   browser_geolocation_privatebrowsing_page.html \
   browser_geolocation_privatebrowsing_perwindowpb.js \
   browser_localStorage_privatestorageevent.js \
   network_geolocation.sjs \
-  page_privatestorageevent.html
+  page_privatestorageevent.html \
+  browser_frame_elements.js \
+  browser_frame_elements.html
   $(NULL)
 
 ifdef MOZ_B2G
 MOCHITEST_BROWSER_FILES += \
   browser_webapps_permissions.js \
   test-webapp.webapp \
   test-webapp-reinstall.webapp \
   test-webapp-original.webapp \
new file mode 100644
--- /dev/null
+++ b/dom/tests/browser/browser_frame_elements.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<head>
+  <meta charset="utf-8">
+  <title>Frame Element Tests</title>
+</head>
+<body>
+  <h1>Frame Element Tests</h1>
+
+  <iframe id="iframe-blank"  src="about:blank"></iframe>
+
+  <iframe id="iframe-data-url" src="data:text/html;charset=utf-8,%3Chtml%3E%3Cbody%3Eiframe%3C/body%3E%3C/html%3E"></iframe>
+
+  <object id="object-data-url" type="text/html" data="data:text/html;charset=utf-8,%3Chtml%3E%3Cbody%3Eobject%3C/body%3E%3C/html%3E"></object>
+
+</body>
new file mode 100644
--- /dev/null
+++ b/dom/tests/browser/browser_frame_elements.js
@@ -0,0 +1,87 @@
+/* -*- Mode: Javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* 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/. */
+
+const TEST_URI = "http://example.com/browser/dom/tests/browser/browser_frame_elements.html";
+let gWindow;
+
+function test() {
+  waitForExplicitFinish();
+
+  var tab = gBrowser.addTab(TEST_URI);
+  gBrowser.selectedTab = tab;
+  var browser = gBrowser.selectedBrowser;
+
+  registerCleanupFunction(function () {
+    gBrowser.removeTab(tab);
+    gWindow = null;
+  });
+
+  browser.addEventListener("DOMContentLoaded", function onLoad(event) {
+    browser.removeEventListener("DOMContentLoaded", onLoad, false);
+    executeSoon(function test_executeSoon() {
+      gWindow = browser.contentWindow;
+      startTests();
+    });
+  }, false);
+}
+
+function startTests() {
+  info("Frame tests started");
+
+  info("Checking top window");
+  let windowUtils = getWindowUtils(gWindow);
+  is (windowUtils.containerElement, gBrowser.selectedBrowser, "Container element for main window is xul:browser");
+  is (gWindow.top, gWindow, "gWindow is top");
+  is (gWindow.parent, gWindow, "gWindow is parent");
+
+  info("Checking about:blank iframe");
+  let iframeBlank = gWindow.document.querySelector("#iframe-blank");
+  ok (iframeBlank, "Iframe exists on page");
+  let iframeBlankUtils = getWindowUtils(iframeBlank.contentWindow);
+  is (iframeBlankUtils.containerElement, iframeBlank, "Container element for iframe window is iframe");
+  is (iframeBlank.contentWindow.top, gWindow, "gWindow is top");
+  is (iframeBlank.contentWindow.parent, gWindow, "gWindow is parent");
+
+  info("Checking iframe with data url src");
+  let iframeDataUrl = gWindow.document.querySelector("#iframe-data-url");
+  ok (iframeDataUrl, "Iframe exists on page");
+  let iframeDataUrlUtils = getWindowUtils(iframeDataUrl.contentWindow);
+  is (iframeDataUrlUtils.containerElement, iframeDataUrl, "Container element for iframe window is iframe");
+  is (iframeDataUrl.contentWindow.top, gWindow, "gWindow is top");
+  is (iframeDataUrl.contentWindow.parent, gWindow, "gWindow is parent");
+
+  info("Checking object with data url data attribute");
+  let objectDataUrl = gWindow.document.querySelector("#object-data-url");
+  ok (objectDataUrl, "Object exists on page");
+  let objectDataUrlUtils = getWindowUtils(objectDataUrl.contentWindow);
+  is (objectDataUrlUtils.containerElement, objectDataUrl, "Container element for object window is the object");
+  is (objectDataUrl.contentWindow.top, gWindow, "gWindow is top");
+  is (objectDataUrl.contentWindow.parent, gWindow, "gWindow is parent");
+
+  info("Granting special powers for mozbrowser");
+  SpecialPowers.addPermission("browser", true, gWindow.document);
+  SpecialPowers.setBoolPref('dom.mozBrowserFramesEnabled', true);
+
+  info("Checking mozbrowser iframe");
+  let mozBrowserFrame = gWindow.document.createElement("iframe");
+  mozBrowserFrame.setAttribute("mozbrowser", "");
+  gWindow.document.body.appendChild(mozBrowserFrame);
+  is (mozBrowserFrame.contentWindow.top, mozBrowserFrame.contentWindow, "Mozbrowser top == iframe window");
+  is (mozBrowserFrame.contentWindow.parent, mozBrowserFrame.contentWindow, "Mozbrowser parent == iframe window");
+
+  info("Revoking special powers for mozbrowser");
+  SpecialPowers.clearUserPref('dom.mozBrowserFramesEnabled')
+  SpecialPowers.removePermission("browser", gWindow.document);
+
+  finish();
+}
+
+function getWindowUtils(window)
+{
+  return window.
+    QueryInterface(Components.interfaces.nsIInterfaceRequestor).
+    getInterface(Components.interfaces.nsIDOMWindowUtils);
+}
new file mode 100644
--- /dev/null
+++ b/dom/webidl/LegacyQueryInterface.webidl
@@ -0,0 +1,93 @@
+/* -*- 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/.
+ */
+
+interface nsISupports;
+interface IID;
+
+[NoInterfaceObject]
+interface LegacyQueryInterface {
+  // Legacy QueryInterface, only exposed to chrome or XBL code on the
+  // main thread.
+  nsISupports queryInterface(IID iid);
+};
+
+Attr implements LegacyQueryInterface;
+BarProp implements LegacyQueryInterface;
+CaretPosition implements LegacyQueryInterface;
+ClientRect implements LegacyQueryInterface;
+ClientRectList implements LegacyQueryInterface;
+Comment implements LegacyQueryInterface;
+Crypto implements LegacyQueryInterface;
+CSSPrimitiveValue implements LegacyQueryInterface;
+CSSStyleDeclaration implements LegacyQueryInterface;
+CSSValueList implements LegacyQueryInterface;
+DOMImplementation implements LegacyQueryInterface;
+DOMParser implements LegacyQueryInterface;
+DOMStringMap implements LegacyQueryInterface;
+DOMTokenList implements LegacyQueryInterface;
+Document implements LegacyQueryInterface;
+DocumentFragment implements LegacyQueryInterface;
+DocumentType implements LegacyQueryInterface;
+Element implements LegacyQueryInterface;
+Event implements LegacyQueryInterface;
+EventSource implements LegacyQueryInterface;
+FileList implements LegacyQueryInterface;
+FormData implements LegacyQueryInterface;
+HTMLCollection implements LegacyQueryInterface;
+History implements LegacyQueryInterface;
+IDBCursor implements LegacyQueryInterface;
+IDBDatabase implements LegacyQueryInterface;
+IDBFactory implements LegacyQueryInterface;
+IDBIndex implements LegacyQueryInterface;
+IDBObjectStore implements LegacyQueryInterface;
+IDBRequest implements LegacyQueryInterface;
+IDBTransaction implements LegacyQueryInterface;
+MimeTypeArray implements LegacyQueryInterface;
+MozNamedAttrMap implements LegacyQueryInterface;
+MutationObserver implements LegacyQueryInterface;
+MutationRecord implements LegacyQueryInterface;
+Navigator implements LegacyQueryInterface;
+NodeIterator implements LegacyQueryInterface;
+NodeList implements LegacyQueryInterface;
+Notification implements LegacyQueryInterface;
+OfflineResourceList implements LegacyQueryInterface;
+PaintRequest implements LegacyQueryInterface;
+PaintRequestList implements LegacyQueryInterface;
+Performance implements LegacyQueryInterface;
+Plugin implements LegacyQueryInterface;
+PluginArray implements LegacyQueryInterface;
+ProcessingInstruction implements LegacyQueryInterface;
+Range implements LegacyQueryInterface;
+Rect implements LegacyQueryInterface;
+SVGAnimatedEnumeration implements LegacyQueryInterface;
+SVGAnimatedInteger implements LegacyQueryInterface;
+SVGAnimatedNumber implements LegacyQueryInterface;
+SVGAnimatedNumberList implements LegacyQueryInterface;
+SVGAnimatedPreserveAspectRatio implements LegacyQueryInterface;
+SVGAnimatedString implements LegacyQueryInterface;
+SVGLengthList implements LegacyQueryInterface;
+SVGNumberList implements LegacyQueryInterface;
+SVGPathSegList implements LegacyQueryInterface;
+SVGPoint implements LegacyQueryInterface;
+SVGPointList implements LegacyQueryInterface;
+SVGPreserveAspectRatio implements LegacyQueryInterface;
+SVGRect implements LegacyQueryInterface;
+SVGStringList implements LegacyQueryInterface;
+SVGTransformList implements LegacyQueryInterface;
+Screen implements LegacyQueryInterface;
+StyleSheet implements LegacyQueryInterface;
+Text implements LegacyQueryInterface;
+Touch implements LegacyQueryInterface;
+TouchList implements LegacyQueryInterface;
+TreeColumns implements LegacyQueryInterface;
+TreeWalker implements LegacyQueryInterface;
+UndoManager implements LegacyQueryInterface;
+ValidityState implements LegacyQueryInterface;
+WebSocket implements LegacyQueryInterface;
+XMLHttpRequest implements LegacyQueryInterface;
+XMLHttpRequestUpload implements LegacyQueryInterface;
+XMLSerializer implements LegacyQueryInterface;
+XPathEvaluator implements LegacyQueryInterface;
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -188,16 +188,17 @@ WEBIDL_FILES = [
     'ImageDocument.webidl',
     'InspectorUtils.webidl',
     'InterAppConnection.webidl',
     'InterAppConnectionRequest.webidl',
     'InterAppMessageEvent.webidl',
     'InterAppMessagePort.webidl',
     'KeyboardEvent.webidl',
     'KeyEvent.webidl',
+    'LegacyQueryInterface.webidl',
     'LinkStyle.webidl',
     'LocalMediaStream.webidl',
     'Location.webidl',
     'MediaElementAudioSourceNode.webidl',
     'MediaError.webidl',
     'MediaRecorder.webidl',
     'MediaSource.webidl',
     'MediaStream.webidl',
--- a/js/jsd/jsd_lock.cpp
+++ b/js/jsd/jsd_lock.cpp
@@ -81,17 +81,17 @@ void ASSERT_VALID_LOCK(JSDStaticLock* lo
 #define ASSERT_VALID_LOCK(x) ((void)0)
 #endif
 
 JSDStaticLock*
 jsd_CreateLock()
 {
     JSDStaticLock* lock;
 
-    if( ! (lock = js_pod_calloc<JSDStaticLock>(1)) ||
+    if( ! (lock = js_pod_calloc<JSDStaticLock>()) ||
         ! (lock->lock = PR_NewLock()) )
     {
         if(lock)
         {
             free(lock);
             lock = nullptr;
         }
     }
--- a/js/public/Utility.h
+++ b/js/public/Utility.h
@@ -143,16 +143,22 @@ static JS_INLINE void* js_malloc(size_t 
 }
 
 static JS_INLINE void* js_calloc(size_t bytes)
 {
     JS_OOM_POSSIBLY_FAIL();
     return calloc(bytes, 1);
 }
 
+static JS_INLINE void* js_calloc(size_t nmemb, size_t size)
+{
+    JS_OOM_POSSIBLY_FAIL();
+    return calloc(nmemb, size);
+}
+
 static JS_INLINE void* js_realloc(void* p, size_t bytes)
 {
     JS_OOM_POSSIBLY_FAIL();
     return realloc(p, bytes);
 }
 
 static JS_INLINE void js_free(void* p)
 {
--- a/js/src/frontend/TokenStream.cpp
+++ b/js/src/frontend/TokenStream.cpp
@@ -211,17 +211,17 @@ TokenStream::SourceCoords::lineIndexOf(u
     }
 
     // This is a binary search with deferred detection of equality, which was
     // marginally faster in this case than a standard binary search.
     // The -2 is because |lineStartOffsets_.length() - 1| is the sentinel, and we
     // want one before that.
     iMax = lineStartOffsets_.length() - 2;
     while (iMax > iMin) {
-        iMid = (iMin + iMax) / 2;
+        iMid = iMin + (iMax - iMin) / 2;
         if (offset >= lineStartOffsets_[iMid + 1])
             iMin = iMid + 1;    // offset is above lineStartOffsets_[iMid]
         else
             iMax = iMid;        // offset is below or within lineStartOffsets_[iMid]
     }
     JS_ASSERT(iMax == iMin);
     JS_ASSERT(lineStartOffsets_[iMin] <= offset && offset < lineStartOffsets_[iMin + 1]);
     lastLineIndex_ = iMin;
--- a/js/src/jit/AsmJSSignalHandlers.cpp
+++ b/js/src/jit/AsmJSSignalHandlers.cpp
@@ -53,38 +53,42 @@ using JS::GenericNaN;
 # define R11_sig(p) ((p)->sc_r11)
 # define R12_sig(p) ((p)->sc_r12)
 # define R13_sig(p) ((p)->sc_r13)
 # define R14_sig(p) ((p)->sc_r14)
 # define R15_sig(p) ((p)->sc_r15)
 #elif defined(__linux__) || defined(SOLARIS)
 # if defined(__linux__)
 #  define XMM_sig(p,i) ((p)->uc_mcontext.fpregs->_xmm[i])
+#  define EIP_sig(p) ((p)->uc_mcontext.gregs[REG_EIP])
 # else
 #  define XMM_sig(p,i) ((p)->uc_mcontext.fpregs.fp_reg_set.fpchip_state.xmm[i])
+#  define EIP_sig(p) ((p)->uc_mcontext.gregs[REG_PC])
 # endif
-# define EIP_sig(p) ((p)->uc_mcontext.gregs[REG_EIP])
 # define RIP_sig(p) ((p)->uc_mcontext.gregs[REG_RIP])
-# define PC_sig(p) ((p)->uc_mcontext.arm_pc)
 # define RAX_sig(p) ((p)->uc_mcontext.gregs[REG_RAX])
 # define RCX_sig(p) ((p)->uc_mcontext.gregs[REG_RCX])
 # define RDX_sig(p) ((p)->uc_mcontext.gregs[REG_RDX])
 # define RBX_sig(p) ((p)->uc_mcontext.gregs[REG_RBX])
 # define RSP_sig(p) ((p)->uc_mcontext.gregs[REG_RSP])
 # define RBP_sig(p) ((p)->uc_mcontext.gregs[REG_RBP])
 # define RSI_sig(p) ((p)->uc_mcontext.gregs[REG_RSI])
 # define RDI_sig(p) ((p)->uc_mcontext.gregs[REG_RDI])
 # define R8_sig(p) ((p)->uc_mcontext.gregs[REG_R8])
 # define R9_sig(p) ((p)->uc_mcontext.gregs[REG_R9])
 # define R10_sig(p) ((p)->uc_mcontext.gregs[REG_R10])
 # define R11_sig(p) ((p)->uc_mcontext.gregs[REG_R11])
 # define R12_sig(p) ((p)->uc_mcontext.gregs[REG_R12])
 # define R13_sig(p) ((p)->uc_mcontext.gregs[REG_R13])
 # define R14_sig(p) ((p)->uc_mcontext.gregs[REG_R14])
-# define R15_sig(p) ((p)->uc_mcontext.gregs[REG_R15])
+# if defined(__linux__) && defined(__arm__)
+#  define R15_sig(p) ((p)->uc_mcontext.arm_pc)
+# else
+#  define R15_sig(p) ((p)->uc_mcontext.gregs[REG_R15])
+# endif
 #elif defined(__NetBSD__)
 # define XMM_sig(p,i) (((struct fxsave64 *)(p)->uc_mcontext.__fpregs)->fx_xmm[i])
 # define EIP_sig(p) ((p)->uc_mcontext.__gregs[_REG_EIP])
 # define RIP_sig(p) ((p)->uc_mcontext.__gregs[_REG_RIP])
 # define RAX_sig(p) ((p)->uc_mcontext.__gregs[_REG_RAX])
 # define RCX_sig(p) ((p)->uc_mcontext.__gregs[_REG_RCX])
 # define RDX_sig(p) ((p)->uc_mcontext.__gregs[_REG_RDX])
 # define RBX_sig(p) ((p)->uc_mcontext.__gregs[_REG_RBX])
@@ -118,17 +122,21 @@ using JS::GenericNaN;
 # define RDI_sig(p) ((p)->uc_mcontext.mc_rdi)
 # define R8_sig(p) ((p)->uc_mcontext.mc_r8)
 # define R9_sig(p) ((p)->uc_mcontext.mc_r9)
 # define R10_sig(p) ((p)->uc_mcontext.mc_r10)
 # define R11_sig(p) ((p)->uc_mcontext.mc_r11)
 # define R12_sig(p) ((p)->uc_mcontext.mc_r12)
 # define R13_sig(p) ((p)->uc_mcontext.mc_r13)
 # define R14_sig(p) ((p)->uc_mcontext.mc_r14)
-# define R15_sig(p) ((p)->uc_mcontext.mc_r15)
+# if defined(__FreeBSD__) && defined(__arm__)
+#  define R15_sig(p) ((p)->uc_mcontext.__gregs[_REG_R15])
+# else
+#  define R15_sig(p) ((p)->uc_mcontext.mc_r15)
+# endif
 #elif defined(XP_MACOSX)
 // Mach requires special treatment.
 #else
 # error "Don't know how to read/write to the thread state via the mcontext_t."
 #endif
 
 // For platforms where the signal/exception handler runs on the same
 // thread/stack as the victim (Unix and Windows), we can use TLS to find any
@@ -305,17 +313,18 @@ LookupHeapAccess(const AsmJSModule &modu
 
 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
 # include <sys/ucontext.h> // for ucontext_t, mcontext_t
 #endif
 
 #if defined(JS_CPU_X64)
 # if defined(__DragonFly__)
 #  include <machine/npx.h> // for union savefpu
-# elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__FreeBSD_kernel__)
+# elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
+       defined(__NetBSD__) || defined(__OpenBSD__)
 #  include <machine/fpu.h> // for struct savefpu/fxsave64
 # endif
 #endif
 
 #if defined(ANDROID)
 // Not all versions of the Android NDK define ucontext_t or mcontext_t.
 // Detect this and provide custom but compatible definitions. Note that these
 // follow the GLibc naming convention to access register values from
@@ -374,30 +383,30 @@ extern "C" MFBT_API bool IsSignalHandlin
 #else
 static bool IsSignalHandlingBroken() { return false; }
 #endif // defined(MOZ_LINKER)
 
 #if !defined(XP_WIN)
 # define CONTEXT ucontext_t
 #endif
 
+#if defined(JS_CPU_X64)
+# define PC_sig(p) RIP_sig(p)
+#elif defined(JS_CPU_X86)
+# define PC_sig(p) EIP_sig(p)
+#elif defined(JS_CPU_ARM)
+# define PC_sig(p) R15_sig(p)
+#endif
+
 #if !defined(XP_MACOSX)
 static uint8_t **
 ContextToPC(CONTEXT *context)
 {
-# if defined(JS_CPU_X64)
-    JS_STATIC_ASSERT(sizeof(RIP_sig(context)) == sizeof(void*));
-    return reinterpret_cast<uint8_t**>(&RIP_sig(context));
-# elif defined(JS_CPU_X86)
-    JS_STATIC_ASSERT(sizeof(EIP_sig(context)) == sizeof(void*));
-    return reinterpret_cast<uint8_t**>(&EIP_sig(context));
-# elif defined(JS_CPU_ARM)
     JS_STATIC_ASSERT(sizeof(PC_sig(context)) == sizeof(void*));
     return reinterpret_cast<uint8_t**>(&PC_sig(context));
-# endif
 }
 
 # if defined(JS_CPU_X64)
 static void
 SetRegisterToCoercedUndefined(CONTEXT *context, bool isFloat32, AnyRegister reg)
 {
     if (reg.isFloat()) {
         switch (reg.fpu().code()) {
--- a/js/src/jit/BaselineBailouts.cpp
+++ b/js/src/jit/BaselineBailouts.cpp
@@ -120,16 +120,18 @@ struct BaselineStackBuilder
         header_->resumeAddr = NULL;
         header_->monitorStub = NULL;
         header_->numFrames = 0;
         return true;
     }
 
     bool enlarge() {
         JS_ASSERT(buffer_ != NULL);
+        if (bufferTotal_ & mozilla::tl::MulOverflowMask<2>::value)
+            return false;
         size_t newSize = bufferTotal_ * 2;
         uint8_t *newBuffer = reinterpret_cast<uint8_t *>(js_calloc(newSize));
         if (!newBuffer)
             return false;
         memcpy((newBuffer + newSize) - bufferUsed_, header_->copyStackBottom, bufferUsed_);
         memcpy(newBuffer, header_, sizeof(BaselineBailoutInfo));
         js_free(buffer_);
         buffer_ = newBuffer;
--- a/js/src/jit/BaselineJIT.cpp
+++ b/js/src/jit/BaselineJIT.cpp
@@ -462,24 +462,24 @@ BaselineScript::pcMappingReader(size_t i
     return CompactBufferReader(dataStart, dataEnd);
 }
 
 ICEntry *
 BaselineScript::maybeICEntryFromReturnOffset(CodeOffsetLabel returnOffset)
 {
     size_t bottom = 0;
     size_t top = numICEntries();
-    size_t mid = (bottom + top) / 2;
+    size_t mid = bottom + (top - bottom) / 2;
     while (mid < top) {
         ICEntry &midEntry = icEntry(mid);
         if (midEntry.returnOffset().offset() < returnOffset.offset())
             bottom = mid + 1;
         else // if (midEntry.returnOffset().offset() >= returnOffset.offset())
             top = mid;
-        mid = (bottom + top) / 2;
+        mid = bottom + (top - bottom) / 2;
     }
     if (mid >= numICEntries())
         return NULL;
 
     if (icEntry(mid).returnOffset().offset() != returnOffset.offset())
         return NULL;
 
     return &icEntry(mid);
@@ -501,26 +501,26 @@ BaselineScript::returnAddressForIC(const
 
 ICEntry &
 BaselineScript::icEntryFromPCOffset(uint32_t pcOffset)
 {
     // Multiple IC entries can have the same PC offset, but this method only looks for
     // those which have isForOp() set.
     size_t bottom = 0;
     size_t top = numICEntries();
-    size_t mid = (bottom + top) / 2;
+    size_t mid = bottom + (top - bottom) / 2;
     while (mid < top) {
         ICEntry &midEntry = icEntry(mid);
         if (midEntry.pcOffset() < pcOffset)
             bottom = mid + 1;
         else if (midEntry.pcOffset() > pcOffset)
             top = mid;
         else
             break;
-        mid = (bottom + top) / 2;
+        mid = bottom + (top - bottom) / 2;
     }
     // Found an IC entry with a matching PC offset.  Search backward, and then
     // forward from this IC entry, looking for one with the same PC offset which
     // has isForOp() set.
     for (size_t i = mid; i < numICEntries() && icEntry(i).pcOffset() == pcOffset; i--) {
         if (icEntry(i).isForOp())
             return icEntry(i);
     }
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -5675,17 +5675,17 @@ CodeGenerator::link()
 
     // We encode safepoints after the OSI-point offsets have been determined.
     encodeSafepoints();
 
     // List of possible scripts that this graph may call. Currently this is
     // only tracked when compiling for parallel execution.
     CallTargetVector callTargets;
     if (executionMode == ParallelExecution)
-        AddPossibleCallees(graph.mir(), callTargets);
+        AddPossibleCallees(cx, graph.mir(), callTargets);
 
     IonScript *ionScript =
       IonScript::New(cx, graph.totalSlotCount(), scriptFrameSize, snapshots_.size(),
                      bailouts_.length(), graph.numConstants(),
                      safepointIndices_.length(), osiIndices_.length(),
                      cacheList_.length(), runtimeData_.length(),
                      safepoints_.size(), callTargets.length(),
                      patchableBackedges_.length());
--- a/js/src/jit/IonCode.h
+++ b/js/src/jit/IonCode.h
@@ -567,17 +567,17 @@ struct IonBlockCounts
 
   public:
 
     bool init(uint32_t id, uint32_t offset, uint32_t numSuccessors) {
         id_ = id;
         offset_ = offset;
         numSuccessors_ = numSuccessors;
         if (numSuccessors) {
-            successors_ = (uint32_t *) js_calloc(numSuccessors * sizeof(uint32_t));
+            successors_ = js_pod_calloc<uint32_t>(numSuccessors);
             if (!successors_)
                 return false;
         }
         return true;
     }
 
     void destroy() {
         js_free(successors_);
@@ -665,17 +665,17 @@ struct IonScriptCounts
         for (size_t i = 0; i < numBlocks_; i++)
             blocks_[i].destroy();
         js_free(blocks_);
         js_delete(previous_);
     }
 
     bool init(size_t numBlocks) {
         numBlocks_ = numBlocks;
-        blocks_ = (IonBlockCounts *) js_calloc(numBlocks * sizeof(IonBlockCounts));
+        blocks_ = js_pod_calloc<IonBlockCounts>(numBlocks);
         return blocks_ != NULL;
     }
 
     size_t numBlocks() const {
         return numBlocks_;
     }
 
     IonBlockCounts &block(size_t i) {
--- a/js/src/jit/ParallelSafetyAnalysis.cpp
+++ b/js/src/jit/ParallelSafetyAnalysis.cpp
@@ -775,35 +775,33 @@ ParallelSafetyVisitor::visitThrow(MThrow
 static bool
 GetPossibleCallees(JSContext *cx, HandleScript script, jsbytecode *pc,
                    types::TemporaryTypeSet *calleeTypes, CallTargetVector &targets);
 
 static bool
 AddCallTarget(HandleScript script, CallTargetVector &targets);
 
 bool
-jit::AddPossibleCallees(MIRGraph &graph, CallTargetVector &targets)
+jit::AddPossibleCallees(JSContext *cx, MIRGraph &graph, CallTargetVector &targets)
 {
-    JSContext *cx = GetIonContext()->cx;
-
     for (ReversePostorderIterator block(graph.rpoBegin()); block != graph.rpoEnd(); block++) {
         for (MInstructionIterator ins(block->begin()); ins != block->end(); ins++)
         {
             if (!ins->isCall())
                 continue;
 
             MCall *callIns = ins->toCall();
 
             RootedFunction target(cx, callIns->getSingleTarget());
             if (target) {
                 JS_ASSERT_IF(!target->isInterpreted(), target->hasParallelNative());
 
                 if (target->isInterpreted()) {
-                    RootedScript script(cx, target->nonLazyScript());
-                    if (!AddCallTarget(script, targets))
+                    RootedScript script(cx, target->getOrCreateScript(cx));
+                    if (!script || !AddCallTarget(script, targets))
                         return false;
                 }
 
                 continue;
             }
 
             types::TemporaryTypeSet *calleeTypes = callIns->getFunction()->resultTypeSet();
             RootedScript script(cx, callIns->block()->info().script());
--- a/js/src/jit/ParallelSafetyAnalysis.h
+++ b/js/src/jit/ParallelSafetyAnalysis.h
@@ -42,14 +42,14 @@ class ParallelSafetyAnalysis
 
 // Code to collect list of possible call targets by scraping through
 // TI and baseline data. Used to permit speculative transitive
 // compilation in vm/ForkJoin.
 //
 // This code may clone scripts and thus may invoke the GC.  Hence only
 // run from the link phase, which executes on the main thread.
 typedef Vector<JSScript *, 4, IonAllocPolicy> CallTargetVector;
-bool AddPossibleCallees(MIRGraph &graph, CallTargetVector &targets);
+bool AddPossibleCallees(JSContext *cx, MIRGraph &graph, CallTargetVector &targets);
 
 } // namespace jit
 } // namespace js
 
 #endif /* jit_ParallelSafetyAnalysis_h */
--- a/js/src/jit/RangeAnalysis.cpp
+++ b/js/src/jit/RangeAnalysis.cpp
@@ -1204,48 +1204,63 @@ MArgumentsLength::computeRange()
                   "NewUInt32Range requires a uint32 value");
     setRange(Range::NewUInt32Range(0, SNAPSHOT_MAX_NARGS));
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 // Range Analysis
 ///////////////////////////////////////////////////////////////////////////////
 
-void
-RangeAnalysis::markBlocksInLoopBody(MBasicBlock *header, MBasicBlock *current)
+bool
+RangeAnalysis::markBlocksInLoopBody(MBasicBlock *header, MBasicBlock *backedge)
 {
-    // Visited.
-    current->mark();
+    Vector<MBasicBlock *, 16, IonAllocPolicy> worklist;
+
+    // Mark the header as being in the loop. This terminates the walk.
+    header->mark();
+
+    backedge->mark();
+    if (!worklist.append(backedge))
+        return false;
 
-    // If we haven't reached the loop header yet, recursively explore predecessors
-    // if we haven't seen them already.
-    if (current != header) {
+    // If we haven't reached the loop header yet, walk up the predecessors
+    // we haven't seen already.
+    while (!worklist.empty()) {
+        MBasicBlock *current = worklist.popCopy();
         for (size_t i = 0; i < current->numPredecessors(); i++) {
-            if (current->getPredecessor(i)->isMarked())
+            MBasicBlock *pred = current->getPredecessor(i);
+
+            if (pred->isMarked())
                 continue;
-            markBlocksInLoopBody(header, current->getPredecessor(i));
+
+            pred->mark();
+            if (!worklist.append(pred))
+                return false;
         }
     }
+
+    return true;
 }
 
-void
+bool
 RangeAnalysis::analyzeLoop(MBasicBlock *header)
 {
     JS_ASSERT(header->hasUniqueBackedge());
 
     // Try to compute an upper bound on the number of times the loop backedge
     // will be taken. Look for tests that dominate the backedge and which have
     // an edge leaving the loop body.
     MBasicBlock *backedge = header->backedge();
 
     // Ignore trivial infinite loops.
     if (backedge == header)
-        return;
+        return true;
 
-    markBlocksInLoopBody(header, backedge);
+    if (!markBlocksInLoopBody(header, backedge))
+        return false;
 
     LoopIterationBound *iterationBound = NULL;
 
     MBasicBlock *block = backedge;
     do {
         BranchDirection direction;
         MTest *branch = block->immediateDominatorBranch(&direction);
 
@@ -1263,17 +1278,17 @@ RangeAnalysis::analyzeLoop(MBasicBlock *
                 if (iterationBound)
                     break;
             }
         }
     } while (block != header);
 
     if (!iterationBound) {
         graph_.unmarkBlocks();
-        return;
+        return true;
     }
 
 #ifdef DEBUG
     if (IonSpewEnabled(IonSpew_Range)) {
         Sprinter sp(GetIonContext()->cx);
         sp.init();
         iterationBound->sum.print(sp);
         IonSpew(IonSpew_Range, "computed symbolic bound on backedges: %s",
@@ -1295,18 +1310,20 @@ RangeAnalysis::analyzeLoop(MBasicBlock *
         for (ReversePostorderIterator iter(graph_.rpoBegin(header)); iter != graph_.rpoEnd(); iter++) {
             MBasicBlock *block = *iter;
             if (!block->isMarked())
                 continue;
 
             for (MDefinitionIterator iter(block); iter; iter++) {
                 MDefinition *def = *iter;
                 if (def->isBoundsCheck() && def->isMovable()) {
-                    if (tryHoistBoundsCheck(header, def->toBoundsCheck()))
-                        hoistedChecks.append(def->toBoundsCheck());
+                    if (tryHoistBoundsCheck(header, def->toBoundsCheck())) {
+                        if (!hoistedChecks.append(def->toBoundsCheck()))
+                            return false;
+                    }
                 }
             }
         }
 
         // Note: replace all uses of the original bounds check with the
         // actual index. This is usually done during bounds check elimination,
         // but in this case it's safe to do it here since the load/store is
         // definitely not loop-invariant, so we will never move it before
@@ -1314,16 +1331,17 @@ RangeAnalysis::analyzeLoop(MBasicBlock *
         for (size_t i = 0; i < hoistedChecks.length(); i++) {
             MBoundsCheck *ins = hoistedChecks[i];
             ins->replaceAllUsesWith(ins->index());
             ins->block()->discard(ins);
         }
     }
 
     graph_.unmarkBlocks();
+    return true;
 }
 
 LoopIterationBound *
 RangeAnalysis::analyzeLoopIterationCount(MBasicBlock *header,
                                          MTest *test, BranchDirection direction)
 {
     SimpleLinearSum lhs(NULL, 0);
     MDefinition *rhs;
@@ -1663,18 +1681,20 @@ RangeAnalysis::analyze()
         for (MDefinitionIterator iter(block); iter; iter++) {
             MDefinition *def = *iter;
 
             def->computeRange();
             IonSpew(IonSpew_Range, "computing range on %d", def->id());
             SpewRange(def);
         }
 
-        if (block->isLoopHeader())
-            analyzeLoop(block);
+        if (block->isLoopHeader()) {
+            if (!analyzeLoop(block))
+                return false;
+        }
 
         if (mir->compilingAsmJS()) {
             for (MInstructionIterator i = block->begin(); i != block->end(); i++) {
                 if (i->isAsmJSLoadHeap()) {
                     MAsmJSLoadHeap *ins = i->toAsmJSLoadHeap();
                     Range *range = ins->ptr()->range();
                     if (range && range->hasInt32LowerBound() && range->lower() >= 0 &&
                         range->hasInt32UpperBound() &&
--- a/js/src/jit/RangeAnalysis.h
+++ b/js/src/jit/RangeAnalysis.h
@@ -82,22 +82,22 @@ class RangeAnalysis
         mir(mir), graph_(graph) {}
     bool addBetaNodes();
     bool analyze();
     bool addRangeAssertions();
     bool removeBetaNodes();
     bool truncate();
 
   private:
-    void analyzeLoop(MBasicBlock *header);
+    bool analyzeLoop(MBasicBlock *header);
     LoopIterationBound *analyzeLoopIterationCount(MBasicBlock *header,
                                                   MTest *test, BranchDirection direction);
     void analyzeLoopPhi(MBasicBlock *header, LoopIterationBound *loopBound, MPhi *phi);
     bool tryHoistBoundsCheck(MBasicBlock *header, MBoundsCheck *ins);
-    void markBlocksInLoopBody(MBasicBlock *header, MBasicBlock *current);
+    bool markBlocksInLoopBody(MBasicBlock *header, MBasicBlock *current);
 };
 
 class Range : public TempObject {
   public:
     // Int32 are signed, so the value needs 31 bits except for INT_MIN value
     // which needs 32 bits.
     static const uint16_t MaxInt32Exponent = 31;
 
--- a/js/src/jsinferinlines.h
+++ b/js/src/jsinferinlines.h
@@ -715,25 +715,25 @@ TypeScript::BytecodeTypes(JSScript *scri
 
     // See if this pc is the same as the last one looked up.
     if (bytecodeMap[*hint] == offset)
         return script->types->typeArray()->toStackSet() + *hint;
 
     // Fall back to a binary search.
     size_t bottom = 0;
     size_t top = script->nTypeSets - 1;
-    size_t mid = (bottom + top) / 2;
+    size_t mid = bottom + (top - bottom) / 2;
     while (mid < top) {
         if (bytecodeMap[mid] < offset)
             bottom = mid + 1;
         else if (bytecodeMap[mid] > offset)
             top = mid;
         else
             break;
-        mid = (bottom + top) / 2;
+        mid = bottom + (top - bottom) / 2;
     }
 
     // We should have have zeroed in on either the exact offset, unless there
     // are more JOF_TYPESET opcodes than nTypeSets in the script (as can happen
     // if the script is very long).
     JS_ASSERT(bytecodeMap[mid] == offset || mid == top);
 
     *hint = mid;
--- a/js/src/jsutil.cpp
+++ b/js/src/jsutil.cpp
@@ -26,17 +26,17 @@ using namespace js;
 
 using mozilla::CeilingLog2Size;
 using mozilla::PodArrayZero;
 
 #if USE_ZLIB
 static void *
 zlib_alloc(void *cx, uInt items, uInt size)
 {
-    return js_malloc(items * size);
+    return js_calloc(items, size);
 }
 
 static void
 zlib_free(void *cx, void *addr)
 {
     js_free(addr);
 }
 
--- a/layout/base/RestyleManager.cpp
+++ b/layout/base/RestyleManager.cpp
@@ -340,48 +340,49 @@ RestyleManager::RecomputePosition(nsIFra
         // We don't currently support relative positioning of inner
         // table elements.  If we apply offsets to things we haven't
         // previously offset, we'll get confused.  So bail.
         return true;
       default:
         break;
     }
 
-    nsIFrame* cb = aFrame->GetContainingBlock();
-    nsMargin newOffsets;
 
     // Move the frame
     if (display->mPosition == NS_STYLE_POSITION_STICKY) {
       // Update sticky positioning for an entire element at once when
       // RecomputePosition is called with the first continuation in a chain.
-      if (!aFrame->GetPrevContinuation()) {
-        StickyScrollContainer::ComputeStickyOffsets(aFrame);
-        StickyScrollContainer* ssc =
-          StickyScrollContainer::GetStickyScrollContainerForFrame(aFrame);
-        if (ssc) {
-          ssc->PositionContinuations(aFrame);
-        }
+      StickyScrollContainer::ComputeStickyOffsets(aFrame);
+      StickyScrollContainer* ssc =
+        StickyScrollContainer::GetStickyScrollContainerForFrame(aFrame);
+      if (ssc) {
+        ssc->PositionContinuations(aFrame);
       }
     } else {
       MOZ_ASSERT(NS_STYLE_POSITION_RELATIVE == display->mPosition,
                  "Unexpected type of positioning");
-      const nsSize size = cb->GetContentRectRelativeToSelf().Size();
+      for (nsIFrame *cont = aFrame; cont;
+           cont = nsLayoutUtils::GetNextContinuationOrSpecialSibling(cont)) {
+        nsIFrame* cb = cont->GetContainingBlock();
+        nsMargin newOffsets;
+        const nsSize size = cb->GetContentRectRelativeToSelf().Size();
 
-      nsHTMLReflowState::ComputeRelativeOffsets(
-          cb->StyleVisibility()->mDirection,
-          aFrame, size.width, size.height, newOffsets);
-      NS_ASSERTION(newOffsets.left == -newOffsets.right &&
-                   newOffsets.top == -newOffsets.bottom,
-                   "ComputeRelativeOffsets should return valid results");
+        nsHTMLReflowState::ComputeRelativeOffsets(
+            cb->StyleVisibility()->mDirection,
+            cont, size.width, size.height, newOffsets);
+        NS_ASSERTION(newOffsets.left == -newOffsets.right &&
+                     newOffsets.top == -newOffsets.bottom,
+                     "ComputeRelativeOffsets should return valid results");
 
-      // nsHTMLReflowState::ApplyRelativePositioning would work here, but
-      // since we've already checked mPosition and aren't changing the frame's
-      // normal position, go ahead and add the offsets directly.
-      aFrame->SetPosition(aFrame->GetNormalPosition() +
+        // nsHTMLReflowState::ApplyRelativePositioning would work here, but
+        // since we've already checked mPosition and aren't changing the frame's
+        // normal position, go ahead and add the offsets directly.
+        cont->SetPosition(cont->GetNormalPosition() +
                           nsPoint(newOffsets.left, newOffsets.top));
+      }
     }
 
     return true;
   }
 
   // For absolute positioning, the width can potentially change if width is
   // auto and either of left or right are not.  The height can also potentially
   // change if height is auto and either of top or bottom are not.  In these
@@ -598,16 +599,18 @@ RestyleManager::ProcessRestyledFrames(ns
     if (changeData->mFrame) {
       propTable->Set(changeData->mFrame, ChangeListProperty(),
                      NS_INT32_TO_PTR(1));
     }
   }
 
   index = count;
 
+  bool didUpdateCursor = false;
+
   while (0 <= --index) {
     nsIFrame* frame;
     nsIContent* content;
     bool didReflowThisFrame = false;
     nsChangeHint hint;
     aChangeList.ChangeAt(index, frame, content, hint);
 
     NS_ASSERTION(!(hint & nsChangeHint_AllReflowHints) ||
@@ -628,36 +631,39 @@ RestyleManager::ProcessRestyledFrames(ns
       }
     }
 
     if ((hint & nsChangeHint_AddOrRemoveTransform) && frame &&
         !(hint & nsChangeHint_ReconstructFrame)) {
       if (NeedToReframeForAddingOrRemovingTransform(frame)) {
         NS_UpdateHint(hint, nsChangeHint_ReconstructFrame);
       } else {
-        // Normally frame construction would set state bits as needed,
-        // but we're not going to reconstruct the frame so we need to set them.
-        // It's because we need to set this state on each affected frame
-        // that we can't coalesce nsChangeHint_AddOrRemoveTransform hints up
-        // to ancestors (i.e. it can't be an inherited change hint).
-        if (frame->IsPositioned()) {
-          // If a transform has been added, we'll be taking this path,
-          // but we may be taking this path even if a transform has been
-          // removed. It's OK to add the bit even if it's not needed.
-          frame->AddStateBits(NS_FRAME_MAY_BE_TRANSFORMED);
-          if (!frame->IsAbsoluteContainer() &&
-              (frame->GetStateBits() & NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN)) {
-            frame->MarkAsAbsoluteContainingBlock();
-          }
-        } else {
-          // Don't remove NS_FRAME_MAY_BE_TRANSFORMED since it may still by
-          // transformed by other means. It's OK to have the bit even if it's
-          // not needed.
-          if (frame->IsAbsoluteContainer()) {
-            frame->MarkAsNotAbsoluteContainingBlock();
+        for (nsIFrame *cont = frame; cont;
+             cont = nsLayoutUtils::GetNextContinuationOrSpecialSibling(cont)) {
+          // Normally frame construction would set state bits as needed,
+          // but we're not going to reconstruct the frame so we need to set them.
+          // It's because we need to set this state on each affected frame
+          // that we can't coalesce nsChangeHint_AddOrRemoveTransform hints up
+          // to ancestors (i.e. it can't be an inherited change hint).
+          if (cont->IsPositioned()) {
+            // If a transform has been added, we'll be taking this path,
+            // but we may be taking this path even if a transform has been
+            // removed. It's OK to add the bit even if it's not needed.
+            cont->AddStateBits(NS_FRAME_MAY_BE_TRANSFORMED);
+            if (!cont->IsAbsoluteContainer() &&
+                (cont->GetStateBits() & NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN)) {
+              cont->MarkAsAbsoluteContainingBlock();
+            }
+          } else {
+            // Don't remove NS_FRAME_MAY_BE_TRANSFORMED since it may still by
+            // transformed by other means. It's OK to have the bit even if it's
+            // not needed.
+            if (cont->IsAbsoluteContainer()) {
+              cont->MarkAsNotAbsoluteContainingBlock();
+            }
           }
         }
       }
     }
     if (hint & nsChangeHint_ReconstructFrame) {
       // If we ever start passing true here, be careful of restyles
       // that involve a reframe and animations.  In particular, if the
       // restyle we're processing here is an animation restyle, but
@@ -673,17 +679,20 @@ RestyleManager::ProcessRestyledFrames(ns
         // frame does not maintain overflow rects, so avoid calling
         // FinishAndStoreOverflow on it:
         hint = NS_SubtractHint(hint,
                  NS_CombineHint(nsChangeHint_UpdateOverflow,
                                 nsChangeHint_ChildrenOnlyTransform));
       }
 
       if (hint & nsChangeHint_UpdateEffects) {
-        nsSVGEffects::UpdateEffects(frame);
+        for (nsIFrame *cont = frame; cont;
+             cont = nsLayoutUtils::GetNextContinuationOrSpecialSibling(cont)) {
+          nsSVGEffects::UpdateEffects(cont);
+        }
       }
       if (hint & nsChangeHint_NeedReflow) {
         StyleChangeReflow(frame, hint);
         didReflowThisFrame = true;
       }
       if (hint & (nsChangeHint_RepaintFrame | nsChangeHint_SyncFrameView |
                   nsChangeHint_UpdateOpacityLayer | nsChangeHint_UpdateTransformLayer |
                   nsChangeHint_ChildrenOnlyTransform)) {
@@ -698,16 +707,20 @@ RestyleManager::ProcessRestyledFrames(ns
       NS_ASSERTION(!(hint & nsChangeHint_ChildrenOnlyTransform) ||
                    (hint & nsChangeHint_UpdateOverflow),
                    "nsChangeHint_UpdateOverflow should be passed too");
       if ((hint & nsChangeHint_UpdateOverflow) && !didReflowThisFrame) {
         if (hint & nsChangeHint_ChildrenOnlyTransform) {
           // The overflow areas of the child frames need to be updated:
           nsIFrame* hintFrame = GetFrameForChildrenOnlyTransformHint(frame);
           nsIFrame* childFrame = hintFrame->GetFirstPrincipalChild();
+          NS_ASSERTION(!nsLayoutUtils::GetNextContinuationOrSpecialSibling(frame),
+                       "SVG frames should not have continuations or special siblings");
+          NS_ASSERTION(!nsLayoutUtils::GetNextContinuationOrSpecialSibling(hintFrame),
+                       "SVG frames should not have continuations or special siblings");
           for ( ; childFrame; childFrame = childFrame->GetNextSibling()) {
             NS_ABORT_IF_FALSE(childFrame->IsFrameOfType(nsIFrame::eSVG),
                               "Not expecting non-SVG children");
             // If |childFrame| is dirty or has dirty children, we don't bother
             // updating overflows since that will happen when it's reflowed.
             if (!(childFrame->GetStateBits() &
                   (NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN))) {
               mOverflowChangedTracker.AddFrame(childFrame);
@@ -717,26 +730,25 @@ RestyleManager::ProcessRestyledFrames(ns
             NS_ASSERTION(childFrame->GetParent() == hintFrame,
                          "SVG child frame not expected to have different parent");
           }
         }
         // If |frame| is dirty or has dirty children, we don't bother updating
         // overflows since that will happen when it's reflowed.
         if (!(frame->GetStateBits() &
               (NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN))) {
-          while (frame) {
-            mOverflowChangedTracker.AddFrame(frame);
-
-            frame =
-              nsLayoutUtils::GetNextContinuationOrSpecialSibling(frame);
+          for (nsIFrame *cont = frame; cont; cont =
+                 nsLayoutUtils::GetNextContinuationOrSpecialSibling(cont)) {
+            mOverflowChangedTracker.AddFrame(cont);
           }
         }
       }
-      if (hint & nsChangeHint_UpdateCursor) {
+      if ((hint & nsChangeHint_UpdateCursor) && !didUpdateCursor) {
         mPresContext->PresShell()->SynthesizeMouseMove(false);
+        didUpdateCursor = true;
       }
     }
   }
 
   FrameConstructor()->EndUpdate();
 
   // cleanup references and verify the style tree.  Note that the latter needs
   // to happen once we've processed the whole list, since until then the tree
@@ -1698,16 +1710,19 @@ ElementForStyleContext(nsIContent* aPare
     nsBlockFrame* block = nsBlockFrame::GetNearestAncestorBlock(aFrame);
     return block->GetContent()->AsElement();
   }
 
   nsIContent* content = aParentContent ? aParentContent : aFrame->GetContent();
   return content->AsElement();
 }
 
+/**
+ * FIXME: Temporary.  Should merge with following function.
+ */
 static nsIFrame*
 GetPrevContinuationWithPossiblySameStyle(nsIFrame* aFrame)
 {
   // Account for {ib} splits when looking for "prevContinuation".  In
   // particular, for the first-continuation of a part of an {ib} split we
   // want to use the special prevsibling of the special prevsibling of
   // aFrame, which should have the same style context as aFrame itself.
   // In particular, if aFrame is the first continuation of an inline part
@@ -1723,19 +1738,94 @@ GetPrevContinuationWithPossiblySameStyle
     // property directly
     prevContinuation = static_cast<nsIFrame*>(
       aFrame->Properties().Get(nsIFrame::IBSplitSpecialPrevSibling()));
     if (prevContinuation) {
       prevContinuation = static_cast<nsIFrame*>(
         prevContinuation->Properties().Get(nsIFrame::IBSplitSpecialPrevSibling()));
     }
   }
+
+  NS_ASSERTION(!prevContinuation ||
+               prevContinuation->GetContent() == aFrame->GetContent(),
+               "unexpected content mismatch");
+
   return prevContinuation;
 }
 
+/**
+ * Get the previous continuation or similar special sibling (assuming
+ * block/inline alternation), conditionally on it having the same style.
+ * This assumes that we're not between resolving the two (i.e., that
+ * they're both already resolved.
+ */
+static nsIFrame*
+GetPrevContinuationWithSameStyle(nsIFrame* aFrame)
+{
+  nsIFrame* prevContinuation = GetPrevContinuationWithPossiblySameStyle(aFrame);
+  if (!prevContinuation) {
+    return nullptr;
+  }
+
+  nsStyleContext* prevStyle = prevContinuation->StyleContext();
+  nsStyleContext* selfStyle = aFrame->StyleContext();
+  if (prevStyle != selfStyle) {
+    NS_ASSERTION(prevStyle->GetPseudo() != selfStyle->GetPseudo() ||
+                 prevStyle->GetParent() != selfStyle->GetParent(),
+                 "continuations should have the same style context");
+    prevContinuation = nullptr;
+  }
+  return prevContinuation;
+}
+
+/**
+ * Get the next continuation or similar special sibling (assuming
+ * block/inline alternation), conditionally on it having the same style.
+ *
+ * Since this is used when deciding to copy the new style context, it
+ * takes as an argument the old style context to check if the style is
+ * the same.  When it is used in other contexts (i.e., where the next
+ * continuation would already have the new style context), the current
+ * style context should be passed.
+ */
+static nsIFrame*
+GetNextContinuationWithSameStyle(nsIFrame* aFrame,
+                                 nsStyleContext* aOldStyleContext)
+{
+  // See GetPrevContinuationWithSameStyle about {ib} splits.
+
+  nsIFrame *nextContinuation = aFrame->GetNextContinuation();
+  if (!nextContinuation && (aFrame->GetStateBits() & NS_FRAME_IS_SPECIAL)) {
+    // We're the last continuation, so we have to hop back to the first
+    // before getting the frame property
+    nextContinuation = static_cast<nsIFrame*>(aFrame->FirstContinuation()->
+      Properties().Get(nsIFrame::IBSplitSpecialSibling()));
+    if (nextContinuation) {
+      nextContinuation = static_cast<nsIFrame*>(
+        nextContinuation->Properties().Get(nsIFrame::IBSplitSpecialSibling()));
+    }
+  }
+
+  if (!nextContinuation) {
+    return nullptr;
+  }
+
+  NS_ASSERTION(nextContinuation->GetContent() == aFrame->GetContent(),
+               "unexpected content mismatch");
+
+  nsStyleContext* nextStyle = nextContinuation->StyleContext();
+  if (nextStyle != aOldStyleContext) {
+    NS_ASSERTION(aOldStyleContext->GetPseudo() != nextStyle->GetPseudo() ||
+                 aOldStyleContext->GetParent() != nextStyle->GetParent(),
+                 "continuations should have the same style context");
+    nextContinuation = nullptr;
+  }
+  return nextContinuation;
+}
+
 nsresult
 RestyleManager::ReparentStyleContext(nsIFrame* aFrame)
 {
   if (nsGkAtoms::placeholderFrame == aFrame->GetType()) {
     // Also reparent the out-of-flow and all its continuations.
     nsIFrame* outOfFlow =
       nsPlaceholderFrame::GetRealFrameForPlaceholder(aFrame);
     NS_ASSERTION(outOfFlow, "no out-of-flow frame");
@@ -1828,24 +1918,26 @@ RestyleManager::ReparentStyleContext(nsI
       if (!copyFromContinuation) {
         TryStartingTransition(mPresContext, aFrame->GetContent(),
                               oldContext, &newContext);
       }
 #endif
 
       // Make sure to call CalcStyleDifference so that the new context ends
       // up resolving all the structs the old context resolved.
-      DebugOnly<nsChangeHint> styleChange =
-        oldContext->CalcStyleDifference(newContext, nsChangeHint(0));
-      // The style change is always 0 because we have the same rulenode and
-      // CalcStyleDifference optimizes us away.  That's OK, though:
-      // reparenting should never trigger a frame reconstruct, and whenever
-      // it's happening we already plan to reflow and repaint the frames.
-      NS_ASSERTION(!(styleChange & nsChangeHint_ReconstructFrame),
-                   "Our frame tree is likely to be bogus!");
+      if (!copyFromContinuation) {
+        DebugOnly<nsChangeHint> styleChange =
+          oldContext->CalcStyleDifference(newContext, nsChangeHint(0));
+        // The style change is always 0 because we have the same rulenode and
+        // CalcStyleDifference optimizes us away.  That's OK, though:
+        // reparenting should never trigger a frame reconstruct, and whenever
+        // it's happening we already plan to reflow and repaint the frames.
+        NS_ASSERTION(!(styleChange & nsChangeHint_ReconstructFrame),
+                     "Our frame tree is likely to be bogus!");
+      }
 
       aFrame->SetStyleContext(newContext);
 
       nsIFrame::ChildListIterator lists(aFrame);
       for (; !lists.IsDone(); lists.Next()) {
         nsFrameList::Enumerator childFrames(lists.CurrentList());
         for (; !childFrames.AtEnd(); childFrames.Next()) {
           nsIFrame* child = childFrames.get();
@@ -1891,17 +1983,17 @@ RestyleManager::ReparentStyleContext(nsI
         newExtraContext = mPresContext->StyleSet()->
                             ReparentStyleContext(oldExtraContext,
                                                  newContext, nullptr);
         if (newExtraContext) {
           if (newExtraContext != oldExtraContext) {
             // Make sure to call CalcStyleDifference so that the new
             // context ends up resolving all the structs the old context
             // resolved.
-            styleChange =
+            DebugOnly<nsChangeHint> styleChange =
               oldExtraContext->CalcStyleDifference(newExtraContext,
                                                    nsChangeHint(0));
             // The style change is always 0 because we have the same
             // rulenode and CalcStyleDifference optimizes us away.  That's
             // OK, though: reparenting should never trigger a frame
             // reconstruct, and whenever it's happening we already plan to
             // reflow and repaint the frames.
             NS_ASSERTION(!(styleChange & nsChangeHint_ReconstructFrame),
@@ -1972,16 +2064,26 @@ ElementRestyler::ElementRestyler(const E
 #ifdef ACCESSIBILITY
   , mDesiredA11yNotifications(aParentRestyler.mKidsDesiredA11yNotifications)
   , mKidsDesiredA11yNotifications(mDesiredA11yNotifications)
   , mOurA11yNotification(eDontNotify)
   , mVisibleKidsOfHiddenElement(aParentRestyler.mVisibleKidsOfHiddenElement)
 #endif
 {
   if (aConstructorFlags & FOR_OUT_OF_FLOW_CHILD) {
+    // Note that the out-of-flow may not be a geometric descendant of
+    // the frame where we started the reresolve.  Therefore, even if
+    // mHintsHandled already includes nsChangeHint_AllReflowHints we
+    // don't want to pass that on to the out-of-flow reresolve, since
+    // that can lead to the out-of-flow not getting reflowed when it
+    // should be (eg a reresolve starting at <body> that involves
+    // reflowing the <body> would miss reflowing fixed-pos nodes that
+    // also need reflow).  In the cases when the out-of-flow _is_ a
+    // geometric descendant of a frame we already have a reflow hint
+    // for, reflow coalescing should keep us from doing the work twice.
     mHintsHandled = NS_SubtractHint(mHintsHandled, nsChangeHint_AllReflowHints);
   }
 }
 
 ElementRestyler::ElementRestyler(ParentContextFromChildFrame,
                                  const ElementRestyler& aParentRestyler,
                                  nsIFrame* aFrame)
   : mPresContext(aParentRestyler.mPresContext)
@@ -2040,18 +2142,22 @@ ElementRestyler::CaptureChange(nsStyleCo
       mChangeList->AppendChange(mFrame, mContent, ourChange);
     }
   }
   NS_UpdateHint(mHintsNotHandledForDescendants,
                 NS_HintsNotHandledForDescendantsIn(ourChange));
 }
 
 /**
- * Recompute style for mFrame and accumulate changes into mChangeList
- * given that mHintsHandled is already accumulated for an ancestor.
+ * Recompute style for mFrame (which should not have a prev continuation
+ * with the same style), all of its next continuations with the same
+ * style, and all special siblings of the same type (either block or
+ * inline, skipping the intermediates of the other type) and accumulate
+ * changes into mChangeList given that mHintsHandled is already accumulated
+ * for an ancestor.
  * mParentContent is the content node used to resolve the parent style
  * context.  This means that, for pseudo-elements, it is the content
  * that should be used for selector matching (rather than the fake
  * content node attached to the frame).
  */
 void
 ElementRestyler::Restyle(nsRestyleHint aRestyleHint)
 {
@@ -2062,16 +2168,19 @@ ElementRestyler::Restyle(nsRestyleHint a
   // |mFrame->GetContent()|, make more sense.  However, we can't,
   // because of frame trees like the one in
   // https://bugzilla.mozilla.org/show_bug.cgi?id=472353#c14 .  Once we
   // fix bug 242277 we should be able to make this make more sense.
   NS_ASSERTION(mFrame->GetContent() || !mParentContent ||
                !mParentContent->GetParent(),
                "frame must have content (unless at the top of the tree)");
 
+  NS_ASSERTION(!GetPrevContinuationWithSameStyle(mFrame),
+               "should not be trying to restyle this frame separately");
+
   if (mContent && mContent->IsElement()) {
     mContent->OwnerDoc()->FlushPendingLinkUpdates();
     RestyleTracker::RestyleData restyleData;
     if (mRestyleTracker.GetRestyleData(mContent->AsElement(), &restyleData)) {
       if (NS_UpdateHint(mHintsHandled, restyleData.mChangeHint)) {
         mChangeList->AppendChange(mFrame, mContent, restyleData.mChangeHint);
       }
       aRestyleHint = nsRestyleHint(aRestyleHint | restyleData.mRestyleHint);
@@ -2079,209 +2188,168 @@ ElementRestyler::Restyle(nsRestyleHint a
   }
 
   nsRestyleHint childRestyleHint = aRestyleHint;
 
   if (childRestyleHint == eRestyle_Self) {
     childRestyleHint = nsRestyleHint(0);
   }
 
-  RestyleSelf(aRestyleHint);
+  {
+    nsRefPtr<nsStyleContext> oldContext = mFrame->StyleContext();
+
+    // TEMPORARY (until bug 918064):  Call RestyleSelf for each
+    // continuation or block-in-inline sibling.
+
+    for (nsIFrame* f = mFrame; f;
+         f = GetNextContinuationWithSameStyle(f, oldContext)) {
+      RestyleSelf(f, aRestyleHint);
+    }
+  }
 
   RestyleChildren(childRestyleHint);
 }
 
 void
-ElementRestyler::RestyleSelf(nsRestyleHint aRestyleHint)
+ElementRestyler::RestyleSelf(nsIFrame* aSelf, nsRestyleHint aRestyleHint)
 {
   // XXXldb get new context from prev-in-flow if possible, to avoid
   // duplication.  (Or should we just let |GetContext| handle that?)
   // Getting the hint would be nice too, but that's harder.
 
   // XXXbryner we may be able to avoid some of the refcounting goop here.
   // We do need a reference to oldContext for the lifetime of this function, and it's possible
   // that the frame has the last reference to it, so AddRef it here.
 
   nsChangeHint assumeDifferenceHint = NS_STYLE_HINT_NONE;
-  nsRefPtr<nsStyleContext> oldContext = mFrame->StyleContext();
+  nsRefPtr<nsStyleContext> oldContext = aSelf->StyleContext();
   nsStyleSet* styleSet = mPresContext->StyleSet();
 
 #ifdef ACCESSIBILITY
   mWasFrameVisible = nsIPresShell::IsAccessibilityActive() ?
     oldContext->StyleVisibility()->IsVisible() : false;
 #endif
 
   nsIAtom* const pseudoTag = oldContext->GetPseudo();
   const nsCSSPseudoElements::Type pseudoType = oldContext->GetPseudoType();
 
   nsStyleContext* parentContext;
   // Get the frame providing the parent style context.  If it is a
   // child, then resolve the provider first.
-  nsIFrame* providerFrame = mFrame->GetParentStyleContextFrame();
-  bool isChild = providerFrame && providerFrame->GetParent() == mFrame;
+  nsIFrame* providerFrame = aSelf->GetParentStyleContextFrame();
+  bool isChild = providerFrame && providerFrame->GetParent() == aSelf;
   if (!isChild) {
     if (providerFrame)
       parentContext = providerFrame->StyleContext();
     else
       parentContext = nullptr;
   }
   else {
-    MOZ_ASSERT(providerFrame->GetContent() == mFrame->GetContent(),
+    MOZ_ASSERT(providerFrame->GetContent() == aSelf->GetContent(),
                "Postcondition for GetParentStyleContextFrame() violated. "
                "That means we need to add the current element to the "
                "ancestor filter.");
 
-    // resolve the provider here (before mFrame below).
+    // resolve the provider here (before aSelf below).
 
     // assumeDifferenceHint forces the parent's change to be also
     // applied to this frame, no matter what
     // nsStyleContext::CalcStyleDifference says. CalcStyleDifference
     // can't be trusted because it assumes any changes to the parent
     // style context provider will be automatically propagated to
     // the frame(s) with child style contexts.
 
     ElementRestyler providerRestyler(PARENT_CONTEXT_FROM_CHILD_FRAME,
                                      *this, providerFrame);
     providerRestyler.Restyle(aRestyleHint);
     assumeDifferenceHint = providerRestyler.HintsHandledForFrame();
 
     // The provider's new context becomes the parent context of
-    // mFrame's context.
+    // aSelf's context.
     parentContext = providerFrame->StyleContext();
     // Set |mResolvedChild| so we don't bother resolving the
     // provider again.
     mResolvedChild = providerFrame;
   }
 
-  if (providerFrame != mFrame->GetParent()) {
+  if (providerFrame != aSelf->GetParent()) {
     // We don't actually know what the parent style context's
     // non-inherited hints were, so assume the worst.
     mParentFrameHintsNotHandledForDescendants =
       nsChangeHint_Hints_NotHandledForDescendants;
   }
 
-#ifdef DEBUG
-  {
-    // Check that our assumption that continuations of the same
-    // pseudo-type and with the same style context parent have the
-    // same style context is valid before the reresolution.  (We need
-    // to check the pseudo-type and style context parent because of
-    // :first-letter and :first-line, where we create styled and
-    // unstyled letter/line frames distinguished by pseudo-type, and
-    // then need to distinguish their descendants based on having
-    // different parents.)
-    nsIFrame *nextContinuation = mFrame->GetNextContinuation();
-    if (nextContinuation) {
-      nsStyleContext *nextContinuationContext =
-        nextContinuation->StyleContext();
-      NS_ASSERTION(oldContext == nextContinuationContext ||
-                   oldContext->GetPseudo() !=
-                     nextContinuationContext->GetPseudo() ||
-                   oldContext->GetParent() !=
-                     nextContinuationContext->GetParent(),
-                   "continuations should have the same style context");
-    }
-    // And assert the same thing for {ib} splits.  See the comments in
-    // GetPrevContinuationWithPossiblySameStyle for an explanation of
-    // why we step two forward in the special sibling chain.
-    if ((mFrame->GetStateBits() & NS_FRAME_IS_SPECIAL) &&
-        !mFrame->GetPrevContinuation()) {
-      nsIFrame *nextIBSibling = static_cast<nsIFrame*>(
-        mFrame->Properties().Get(nsIFrame::IBSplitSpecialSibling()));
-      if (nextIBSibling) {
-        nextIBSibling = static_cast<nsIFrame*>(
-          nextIBSibling->Properties().Get(nsIFrame::IBSplitSpecialSibling()));
-      }
-      if (nextIBSibling) {
-        nsStyleContext *nextIBSiblingContext =
-          nextIBSibling->StyleContext();
-        NS_ASSERTION(oldContext == nextIBSiblingContext ||
-                     oldContext->GetPseudo() !=
-                       nextIBSiblingContext->GetPseudo() ||
-                     oldContext->GetParent() !=
-                       nextIBSiblingContext->GetParent(),
-                     "continuations should have the same style context");
-      }
-    }
-  }
-#endif
-
   // do primary context
   nsRefPtr<nsStyleContext> newContext;
   nsIFrame *prevContinuation =
-    GetPrevContinuationWithPossiblySameStyle(mFrame);
+    GetPrevContinuationWithPossiblySameStyle(aSelf);
   nsStyleContext *prevContinuationContext;
   bool copyFromContinuation =
     prevContinuation &&
     (prevContinuationContext = prevContinuation->StyleContext())
       ->GetPseudo() == oldContext->GetPseudo() &&
      prevContinuationContext->GetParent() == parentContext;
   if (copyFromContinuation) {
     // Just use the style context from the frame's previous
-    // continuation (see assertion about mFrame->GetNextContinuation()
-    // above, which we would have previously hit for mFrame's previous
-    // continuation).
+    // continuation.
     newContext = prevContinuationContext;
   }
   else if (pseudoTag == nsCSSAnonBoxes::mozNonElement) {
-    NS_ASSERTION(mFrame->GetContent(),
+    NS_ASSERTION(aSelf->GetContent(),
                  "non pseudo-element frame without content node");
     newContext = styleSet->ResolveStyleForNonElement(parentContext);
   }
   else if (!aRestyleHint && !prevContinuation) {
     // Unfortunately, if prevContinuation is non-null then we may have
     // already stolen the restyle tracker entry for this element while
     // processing prevContinuation.  So we don't know whether aRestyleHint
     // should really be 0 here or whether it should be eRestyle_Self.  Be
     // pessimistic and force an actual reresolve in that situation.  The good
     // news is that in the common case when prevContinuation is non-null we
     // just used prevContinuationContext anyway and aren't reaching this code
     // to start with.
     newContext =
       styleSet->ReparentStyleContext(oldContext, parentContext,
                                      ElementForStyleContext(mParentContent,
-                                                            mFrame,
-                                                            pseudoType));
+                                                            aSelf, pseudoType));
   } else if (pseudoType == nsCSSPseudoElements::ePseudo_AnonBox) {
     newContext = styleSet->ResolveAnonymousBoxStyle(pseudoTag,
                                                     parentContext);
   }
   else {
-    Element* element = ElementForStyleContext(mParentContent,
-                                              mFrame,
-                                              pseudoType);
+    Element* element = ElementForStyleContext(mParentContent, aSelf, pseudoType);
     if (pseudoTag) {
       if (pseudoTag == nsCSSPseudoElements::before ||
           pseudoTag == nsCSSPseudoElements::after) {
         // XXX what other pseudos do we need to treat like this?
         newContext = styleSet->ProbePseudoElementStyle(element,
                                                        pseudoType,
                                                        parentContext,
                                                        mTreeMatchContext);
         if (!newContext) {
           // This pseudo should no longer exist; gotta reframe
           NS_UpdateHint(mHintsHandled, nsChangeHint_ReconstructFrame);
-          mChangeList->AppendChange(mFrame, element,
+          mChangeList->AppendChange(aSelf, element,
                                     nsChangeHint_ReconstructFrame);
           // We're reframing anyway; just keep the same context
           newContext = oldContext;
         }
       } else {
         // Don't expect XUL tree stuff here, since it needs a comparator and
         // all.
         NS_ASSERTION(pseudoType <
                        nsCSSPseudoElements::ePseudo_PseudoElementCount,
                      "Unexpected pseudo type");
         newContext = styleSet->ResolvePseudoElementStyle(element,
                                                          pseudoType,
                                                          parentContext);
       }
     }
     else {
-      NS_ASSERTION(mFrame->GetContent(),
+      NS_ASSERTION(aSelf->GetContent(),
                    "non pseudo-element frame without content node");
       // Skip flex-item style fixup for anonymous subtrees:
       TreeMatchContext::AutoFlexItemStyleFixupSkipper
         flexFixupSkipper(mTreeMatchContext,
                          element->IsRootOfNativeAnonymousSubtree());
       newContext = styleSet->ResolveStyleFor(element, parentContext,
                                              mTreeMatchContext);
     }
@@ -2300,34 +2368,41 @@ ElementRestyler::RestyleSelf(nsRestyleHi
       // style contexts around.  However, we need to start from the
       // same root.
       newContext = oldContext;
     }
   }
 
   if (newContext != oldContext) {
     if (!copyFromContinuation) {
-      TryStartingTransition(mPresContext, mFrame->GetContent(),
+      TryStartingTransition(mPresContext, aSelf->GetContent(),
                             oldContext, &newContext);
+
+      CaptureChange(oldContext, newContext, assumeDifferenceHint);
     }
 
-    CaptureChange(oldContext, newContext, assumeDifferenceHint);
     if (!(mHintsHandled & nsChangeHint_ReconstructFrame)) {
-      // if frame gets regenerated, let it keep old context
-      mFrame->SetStyleContext(newContext);
+      // If the frame gets regenerated, let it keep its old context,
+      // which is important to maintain various invariants about
+      // frame types matching their style contexts.
+      // Note that this check even makes sense if we didn't call
+      // CaptureChange because of copyFromContinuation being true,
+      // since we'll have copied the existing context from the
+      // previous continuation, so newContext == oldContext.
+      aSelf->SetStyleContext(newContext);
     }
   }
   oldContext = nullptr;
 
   // do additional contexts
   // XXXbz might be able to avoid selector matching here in some
   // cases; won't worry about it for now.
   int32_t contextIndex = 0;
   for (nsStyleContext* oldExtraContext;
-       (oldExtraContext = mFrame->GetAdditionalStyleContext(contextIndex));
+       (oldExtraContext = aSelf->GetAdditionalStyleContext(contextIndex));
        ++contextIndex) {
     nsRefPtr<nsStyleContext> newExtraContext;
     nsIAtom* const extraPseudoTag = oldExtraContext->GetPseudo();
     const nsCSSPseudoElements::Type extraPseudoType =
       oldExtraContext->GetPseudoType();
     NS_ASSERTION(extraPseudoTag &&
                  extraPseudoTag != nsCSSAnonBoxes::mozNonElement,
                  "extra style context is not pseudo element");
@@ -2346,17 +2421,17 @@ ElementRestyler::RestyleSelf(nsRestyleHi
                                                             newContext);
     }
 
     MOZ_ASSERT(newExtraContext);
 
     if (oldExtraContext != newExtraContext) {
       CaptureChange(oldExtraContext, newExtraContext, assumeDifferenceHint);
       if (!(mHintsHandled & nsChangeHint_ReconstructFrame)) {
-        mFrame->SetAdditionalStyleContext(contextIndex, newExtraContext);
+        aSelf->SetAdditionalStyleContext(contextIndex, newExtraContext);
       }
     }
   }
 }
 
 void
 ElementRestyler::RestyleChildren(nsRestyleHint aChildRestyleHint)
 {
@@ -2369,39 +2444,44 @@ ElementRestyler::RestyleChildren(nsResty
   // mFrame->StyleContext(), which is out of date if mHintsHandled has a
   // ReconstructFrame hint.  Using an out of date style context could
   // trigger assertions about mismatched rule trees.
   if (!(mHintsHandled & nsChangeHint_ReconstructFrame) &&
       aChildRestyleHint) {
     RestyleBeforePseudo();
   }
 
-  // Check whether we might need to create a new ::after frame.
-  // See comments above regarding :before.
-  if (!(mHintsHandled & nsChangeHint_ReconstructFrame) &&
-      aChildRestyleHint) {
-    RestyleAfterPseudo();
-  }
-
   // There is no need to waste time crawling into a frame's children
   // on a frame change.  The act of reconstructing frames will force
   // new style contexts to be resolved on all of this frame's
   // descendants anyway, so we want to avoid wasting time processing
   // style contexts that we're just going to throw away anyway. - dwh
   // It's also important to check mHintsHandled since reresolving the
   // kids would use mFrame->StyleContext(), which is out of date if
   // mHintsHandled has a ReconstructFrame hint; doing this could trigger
   // assertions about mismatched rule trees.
+  nsIFrame *lastContinuation;
   if (!(mHintsHandled & nsChangeHint_ReconstructFrame)) {
     InitializeAccessibilityNotifications();
 
-    RestyleContentChildren(aChildRestyleHint);
+    for (nsIFrame* f = mFrame; f;
+         f = GetNextContinuationWithSameStyle(f, f->StyleContext())) {
+      lastContinuation = f;
+      RestyleContentChildren(f, aChildRestyleHint);
+    }
 
     SendAccessibilityNotifications();
   }
+
+  // Check whether we might need to create a new ::after frame.
+  // See comments above regarding :before.
+  if (!(mHintsHandled & nsChangeHint_ReconstructFrame) &&
+      aChildRestyleHint) {
+    RestyleAfterPseudo(lastContinuation);
+  }
 }
 
 void
 ElementRestyler::RestyleUndisplayedChildren(nsRestyleHint aChildRestyleHint)
 {
   // When the root element is display:none, we still construct *some*
   // frames that have the root element as their mContent, down to the
   // DocElementContainingBlock.
@@ -2509,41 +2589,45 @@ ElementRestyler::RestyleBeforePseudo()
         NS_UpdateHint(mHintsHandled, nsChangeHint_ReconstructFrame);
         mChangeList->AppendChange(mFrame, mContent,
                                   nsChangeHint_ReconstructFrame);
       }
     }
   }
 }
 
+/**
+ * aFrame is the last continuation or block-in-inline sibling that this
+ * ElementRestyler is restyling.
+ */
 void
-ElementRestyler::RestyleAfterPseudo()
+ElementRestyler::RestyleAfterPseudo(nsIFrame* aFrame)
 {
   // Make sure not to do this for pseudo-frames or frames that
   // can't have generated content.
-  if (!mFrame->StyleContext()->GetPseudo() &&
-      ((mFrame->GetStateBits() & NS_FRAME_MAY_HAVE_GENERATED_CONTENT) ||
+  if (!aFrame->StyleContext()->GetPseudo() &&
+      ((aFrame->GetStateBits() & NS_FRAME_MAY_HAVE_GENERATED_CONTENT) ||
        // Our content insertion frame might have gotten flagged
-       (mFrame->GetContentInsertionFrame()->GetStateBits() &
+       (aFrame->GetContentInsertionFrame()->GetStateBits() &
         NS_FRAME_MAY_HAVE_GENERATED_CONTENT))) {
     // Check for new :after content, but only if the frame is the
     // last continuation.
-    nsIFrame* nextContinuation = mFrame->GetNextContinuation();
+    nsIFrame* nextContinuation = aFrame->GetNextContinuation();
 
     if (!nextContinuation) {
       // Getting the :after frame is more expensive than getting the pseudo
       // context, so get the pseudo context first.
-      if (nsLayoutUtils::HasPseudoStyle(mFrame->GetContent(),
-                                        mFrame->StyleContext(),
+      if (nsLayoutUtils::HasPseudoStyle(aFrame->GetContent(),
+                                        aFrame->StyleContext(),
                                         nsCSSPseudoElements::ePseudo_after,
                                         mPresContext) &&
-          !nsLayoutUtils::GetAfterFrame(mFrame)) {
+          !nsLayoutUtils::GetAfterFrame(aFrame)) {
         // have to create the new :after frame
         NS_UpdateHint(mHintsHandled, nsChangeHint_ReconstructFrame);
-        mChangeList->AppendChange(mFrame, mContent,
+        mChangeList->AppendChange(aFrame, mContent,
                                   nsChangeHint_ReconstructFrame);
       }
     }
   }
 }
 
 void
 ElementRestyler::InitializeAccessibilityNotifications()
@@ -2581,29 +2665,33 @@ ElementRestyler::InitializeAccessibility
       mVisibleKidsOfHiddenElement.AppendElement(mFrame->GetContent());
       mKidsDesiredA11yNotifications = eSkipNotifications;
     }
   }
 #endif
 }
 
 void
-ElementRestyler::RestyleContentChildren(nsRestyleHint aChildRestyleHint)
+ElementRestyler::RestyleContentChildren(nsIFrame* aParent,
+                                        nsRestyleHint aChildRestyleHint)
 {
-  nsIFrame::ChildListIterator lists(mFrame);
+  nsIFrame::ChildListIterator lists(aParent);
   for (TreeMatchContext::AutoAncestorPusher
          pushAncestor(!lists.IsDone(),
                       mTreeMatchContext,
                       mContent && mContent->IsElement()
                         ? mContent->AsElement() : nullptr);
        !lists.IsDone(); lists.Next()) {
     nsFrameList::Enumerator childFrames(lists.CurrentList());
     for (; !childFrames.AtEnd(); childFrames.Next()) {
       nsIFrame* child = childFrames.get();
-      if (!(child->GetStateBits() & NS_FRAME_OUT_OF_FLOW)) {
+      // Out-of-flows are reached through their placeholders.  Continuations
+      // and block-in-inline splits are reached through those chains.
+      if (!(child->GetStateBits() & NS_FRAME_OUT_OF_FLOW) &&
+          !GetPrevContinuationWithSameStyle(child)) {
         // Get the parent of the child frame's content and check if it
         // is a XBL children element. Push the children element as an
         // ancestor here because it does not have a frame and would not
         // otherwise be pushed as an ancestor.
 
         // Check if the frame has a content because |child| may be a
         // nsPageFrame that does not have a content.
         nsIContent* parent = child->GetContent() ? child->GetContent()->GetParent() : nullptr;
@@ -2616,30 +2704,26 @@ ElementRestyler::RestyleContentChildren(
         if (nsGkAtoms::placeholderFrame == child->GetType()) { // placeholder
           // get out of flow frame and recur there
           nsIFrame* outOfFlowFrame =
             nsPlaceholderFrame::GetRealFrameForPlaceholder(child);
           NS_ASSERTION(outOfFlowFrame, "no out-of-flow frame");
           NS_ASSERTION(outOfFlowFrame != mResolvedChild,
                        "out-of-flow frame not a true descendant");
 
-          // Note that the out-of-flow may not be a geometric descendant of
-          // the frame where we started the reresolve.  Therefore, even if
-          // mHintsHandled already includes nsChangeHint_AllReflowHints we don't
-          // want to pass that on to the out-of-flow reresolve, since that
-          // can lead to the out-of-flow not getting reflowed when it should
-          // be (eg a reresolve starting at <body> that involves reflowing
-          // the <body> would miss reflowing fixed-pos nodes that also need
-          // reflow).  In the cases when the out-of-flow _is_ a geometric
-          // descendant of a frame we already have a reflow hint for,
-          // reflow coalescing should keep us from doing the work twice.
-
           // |nsFrame::GetParentStyleContextFrame| checks being out
           // of flow so that this works correctly.
           do {
+            if (GetPrevContinuationWithSameStyle(outOfFlowFrame)) {
+              // Later continuations are likely restyled as a result of
+              // the restyling of the previous continuation.
+              // (Currently that's always true, but it's likely to
+              // change if we implement overflow:fragments or similar.)
+              continue;
+            }
             ElementRestyler oofRestyler(*this, outOfFlowFrame,
                                         FOR_OUT_OF_FLOW_CHILD);
             oofRestyler.Restyle(aChildRestyleHint);
           } while ((outOfFlowFrame = outOfFlowFrame->GetNextContinuation()));
 
           // reresolve placeholder's context under the same parent
           // as the out-of-flow frame
           ElementRestyler phRestyler(*this, child, 0);
@@ -2703,62 +2787,62 @@ RestyleManager::ComputeStyleChangeFor(ns
   PROFILER_LABEL("CSS", "ComputeStyleChangeFor");
 
   nsIContent *content = aFrame->GetContent();
   if (aMinChange) {
     aChangeList->AppendChange(aFrame, content, aMinChange);
   }
 
   nsIFrame* frame = aFrame;
-  nsIFrame* frame2 = aFrame;
 
   NS_ASSERTION(!frame->GetPrevContinuation(), "must start with the first in flow");
 
-  // We want to start with this frame and walk all its next-in-flows,
-  // as well as all its special siblings and their next-in-flows,
-  // reresolving style on all the frames we encounter in this walk.
+  // We need to handle aFrame and all of its continuations and special
+  // siblings and their continuations.  ReResolveStyleContext loops over
+  // the continuations, and also loops over the similar-type sequences
+  // in block-in-inline splits (i.e., either all the blocks or all the
+  // inlines), so here we only have to advance one step to the other set
+  // of special siblings (i.e., switch from blocks to inlines, or
+  // vice-versa).
 
   FramePropertyTable* propTable = mPresContext->PropertyTable();
 
   TreeMatchContext treeMatchContext(true,
                                     nsRuleWalker::eRelevantLinkUnvisited,
                                     mPresContext->Document());
   nsIContent *parent = content ? content->GetParent() : nullptr;
   Element *parentElement =
     parent && parent->IsElement() ? parent->AsElement() : nullptr;
   treeMatchContext.InitAncestors(parentElement);
   nsTArray<nsIContent*> visibleKidsOfHiddenElement;
-  do {
-    // Outer loop over special siblings
-    do {
-      // Inner loop over next-in-flows of the current frame
-      ElementRestyler restyler(mPresContext, frame, aChangeList,
-                               aMinChange, aRestyleTracker,
-                               treeMatchContext,
-                               visibleKidsOfHiddenElement);
+  for (int ibSet = 0; ibSet < 2; ++ibSet) {
+    // loop over the two sets (blocks, inlines) of special siblings
+    ElementRestyler restyler(mPresContext, frame, aChangeList,
+                             aMinChange, aRestyleTracker,
+                             treeMatchContext,
+                             visibleKidsOfHiddenElement);
 
-      restyler.Restyle(aRestyleDescendants ? eRestyle_Subtree : eRestyle_Self);
+    restyler.Restyle(aRestyleDescendants ? eRestyle_Subtree : eRestyle_Self);
 
-      if (restyler.HintsHandledForFrame() & nsChangeHint_ReconstructFrame) {
-        // If it's going to cause a framechange, then don't bother
-        // with the continuations or special siblings since they'll be
-        // clobbered by the frame reconstruct anyway.
-        NS_ASSERTION(!frame->GetPrevContinuation(),
-                     "continuing frame had more severe impact than first-in-flow");
-        return;
-      }
-
-      frame = frame->GetNextContinuation();
-    } while (frame);
+    if (restyler.HintsHandledForFrame() & nsChangeHint_ReconstructFrame) {
+      // If it's going to cause a framechange, then don't bother
+      // with the continuations or special siblings since they'll be
+      // clobbered by the frame reconstruct anyway.
+      NS_ASSERTION(!frame->GetPrevContinuation(),
+                   "continuing frame had more severe impact than first-in-flow");
+      return;
+    }
 
     // Might we have special siblings?
-    if (!(frame2->GetStateBits() & NS_FRAME_IS_SPECIAL)) {
+    if (!(frame->GetStateBits() & NS_FRAME_IS_SPECIAL)) {
       // nothing more to do here
       return;
     }
 
-    frame2 = static_cast<nsIFrame*>
-      (propTable->Get(frame2, nsIFrame::IBSplitSpecialSibling()));
-    frame = frame2;
-  } while (frame2);
+    frame = static_cast<nsIFrame*>
+      (propTable->Get(frame, nsIFrame::IBSplitSpecialSibling()));
+    if (!frame) {
+      return;
+    }
+  }
 }
 
 } // namespace mozilla
--- a/layout/base/RestyleManager.h
+++ b/layout/base/RestyleManager.h
@@ -317,17 +317,17 @@ public:
    * hints have been handled for this frame.
    */
   nsChangeHint HintsHandledForFrame() { return mHintsHandled; }
 
 private:
   /**
    * First half of Restyle().
    */
-  void RestyleSelf(nsRestyleHint aRestyleHint);
+  void RestyleSelf(nsIFrame* aSelf, nsRestyleHint aRestyleHint);
 
   /**
    * Restyle the children of this frame (and, in turn, their children).
    *
    * Second half of Restyle().
    */
   void RestyleChildren(nsRestyleHint aChildRestyleHint);
 
@@ -338,18 +338,19 @@ private:
                      nsStyleContext* aNewContext,
                      nsChangeHint aChangeToAssume);
 
   /**
    * Helpers for RestyleChildren().
    */
   void RestyleUndisplayedChildren(nsRestyleHint aChildRestyleHint);
   void RestyleBeforePseudo();
-  void RestyleAfterPseudo();
-  void RestyleContentChildren(nsRestyleHint aChildRestyleHint);
+  void RestyleAfterPseudo(nsIFrame* aFrame);
+  void RestyleContentChildren(nsIFrame* aParent,
+                              nsRestyleHint aChildRestyleHint);
   void InitializeAccessibilityNotifications();
   void SendAccessibilityNotifications();
 
   enum DesiredA11yNotifications {
     eSkipNotifications,
     eSendAllNotifications,
     eNotifyIfShown
   };
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -2541,16 +2541,30 @@ nsLayoutUtils::FirstContinuationOrSpecia
       result = f;
     }
   }
 
   return result;
 }
 
 bool
+nsLayoutUtils::IsFirstContinuationOrSpecialSibling(nsIFrame *aFrame)
+{
+  if (aFrame->GetPrevContinuation()) {
+    return false;
+  }
+  if ((aFrame->GetStateBits() & NS_FRAME_IS_SPECIAL) &&
+      aFrame->Properties().Get(nsIFrame::IBSplitSpecialPrevSibling())) {
+    return false;
+  }
+
+  return true;
+}
+
+bool
 nsLayoutUtils::IsViewportScrollbarFrame(nsIFrame* aFrame)
 {
   if (!aFrame)
     return false;
 
   nsIFrame* rootScrollFrame =
     aFrame->PresContext()->PresShell()->GetRootScrollFrame();
   if (!rootScrollFrame)
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -940,16 +940,23 @@ public:
   /**
    * Get the first frame in the continuation-plus-special-sibling chain
    * containing aFrame.
    */
   static nsIFrame*
   FirstContinuationOrSpecialSibling(nsIFrame *aFrame);
 
   /**
+   * Is FirstContinuationOrSpecialSibling(aFrame) going to return
+   * aFrame?
+   */
+  static bool
+  IsFirstContinuationOrSpecialSibling(nsIFrame *aFrame);
+
+  /**
    * Check whether aFrame is a part of the scrollbar or scrollcorner of
    * the root content.
    * @param aFrame the checking frame
    * @return if TRUE, the frame is a part of the scrollbar or scrollcorner of
    *         the root content.
    */
   static bool IsViewportScrollbarFrame(nsIFrame* aFrame);
 
--- a/layout/generic/StickyScrollContainer.cpp
+++ b/layout/generic/StickyScrollContainer.cpp
@@ -124,43 +124,52 @@ StickyScrollContainer::ComputeStickyOffs
               new nsMargin(computedOffsets));
   }
 }
 
 void
 StickyScrollContainer::ComputeStickyLimits(nsIFrame* aFrame, nsRect* aStick,
                                            nsRect* aContain) const
 {
-  NS_ASSERTION(!aFrame->GetPrevContinuation(),
+  NS_ASSERTION(nsLayoutUtils::IsFirstContinuationOrSpecialSibling(aFrame),
                "Can't sticky position individual continuations");
 
   aStick->SetRect(nscoord_MIN/2, nscoord_MIN/2, nscoord_MAX, nscoord_MAX);
   aContain->SetRect(nscoord_MIN/2, nscoord_MIN/2, nscoord_MAX, nscoord_MAX);
 
   const nsMargin* computedOffsets = static_cast<nsMargin*>(
     aFrame->Properties().Get(nsIFrame::ComputedOffsetProperty()));
   if (!computedOffsets) {
     // We haven't reflowed the scroll frame yet, so offsets haven't been
     // computed. Bail.
     return;
   }
 
   nsIFrame* scrolledFrame = mScrollFrame->GetScrolledFrame();
+  // FIXME (Bug 920688):  cbFrame isn't quite right if we're dealing
+  // with a block-in-inline split whose first part is a block.  We
+  // probably want the first in flow of the containing block of the
+  // first inline part.  (Or maybe those block-in-inline split pieces
+  // are never a containing block, and we're ok?)
   nsIFrame* cbFrame = aFrame->GetContainingBlock();
   NS_ASSERTION(cbFrame == scrolledFrame ||
     nsLayoutUtils::IsProperAncestorFrame(scrolledFrame, cbFrame),
     "Scroll frame should be an ancestor of the containing block");
 
   nsRect rect =
     nsLayoutUtils::GetAllInFlowRectsUnion(aFrame, aFrame->GetParent());
 
   // Containing block limits
   if (cbFrame != scrolledFrame) {
     *aContain = nsLayoutUtils::GetAllInFlowRectsUnion(cbFrame, cbFrame);
     aContain->MoveBy(-aFrame->GetParent()->GetOffsetTo(cbFrame));
+    // FIXME (Bug 920688): GetUsedBorderAndPadding / GetUsedMargin
+    // consider skip-sides, which doesn't quite mesh with the use of
+    // GetAllInFlowRectsUnion here.  This probably needs to do that
+    // computation *inside* the accumuation function over the in-flows.
     aContain->Deflate(cbFrame->GetUsedBorderAndPadding());
     aContain->Deflate(aFrame->GetUsedMargin());
     aContain->Deflate(nsMargin(0, rect.width, rect.height, 0));
   }
 
   nsMargin sfPadding = scrolledFrame->GetUsedPadding();
   nsPoint sfOffset = aFrame->GetParent()->GetOffsetTo(scrolledFrame);
 
@@ -224,19 +233,25 @@ StickyScrollContainer::ComputePosition(n
 
   return position;
 }
 
 void
 StickyScrollContainer::GetScrollRanges(nsIFrame* aFrame, nsRect* aOuter,
                                        nsRect* aInner) const
 {
+  // We need to use the first in flow; ComputeStickyLimits requires
+  // this, at the very least because its call to
+  // nsLayoutUtils::GetAllInFlowRectsUnion requires it.
+  nsIFrame *firstCont =
+    nsLayoutUtils::FirstContinuationOrSpecialSibling(aFrame);
+
   nsRect stick;
   nsRect contain;
-  ComputeStickyLimits(aFrame, &stick, &contain);
+  ComputeStickyLimits(firstCont, &stick, &contain);
 
   aOuter->SetRect(nscoord_MIN/2, nscoord_MIN/2, nscoord_MAX, nscoord_MAX);
   aInner->SetRect(nscoord_MIN/2, nscoord_MIN/2, nscoord_MAX, nscoord_MAX);
 
   const nsPoint normalPosition = aFrame->GetNormalPosition();
 
   // Bottom and top
   if (stick.YMost() != nscoord_MAX/2) {
@@ -259,25 +274,23 @@ StickyScrollContainer::GetScrollRanges(n
     aInner->SetRightEdge(normalPosition.x - stick.x);
     aOuter->SetRightEdge(contain.XMost() - stick.x);
   }
 }
 
 void
 StickyScrollContainer::PositionContinuations(nsIFrame* aFrame)
 {
-  NS_ASSERTION(!aFrame->GetPrevContinuation(),
+  NS_ASSERTION(nsLayoutUtils::IsFirstContinuationOrSpecialSibling(aFrame),
                "Should be starting from the first continuation");
-  nsPoint newPosition = ComputePosition(aFrame);
-  nsPoint translation = newPosition - aFrame->GetPosition();
-  aFrame->SetPosition(newPosition);
+  nsPoint translation = ComputePosition(aFrame) - aFrame->GetPosition();
 
   // Move all continuation frames by the same amount.
-  for (nsIFrame* cont = aFrame->GetNextContinuation(); cont;
-       cont = cont->GetNextContinuation()) {
+  for (nsIFrame* cont = aFrame; cont;
+       cont = nsLayoutUtils::GetNextContinuationOrSpecialSibling(cont)) {
     cont->SetPosition(cont->GetPosition() + translation);
   }
 }
 
 void
 StickyScrollContainer::UpdatePositions(nsPoint aScrollPosition,
                                        nsIFrame* aSubtreeRoot)
 {
@@ -289,26 +302,34 @@ StickyScrollContainer::UpdatePositions(n
   }
 #endif
   mScrollPosition = aScrollPosition;
 
   OverflowChangedTracker oct;
   oct.SetSubtreeRoot(aSubtreeRoot);
   for (nsTArray<nsIFrame*>::size_type i = 0; i < mFrames.Length(); i++) {
     nsIFrame* f = mFrames[i];
+    if (!nsLayoutUtils::IsFirstContinuationOrSpecialSibling(f)) {
+      // This frame was added in nsFrame::Init before we knew it wasn't
+      // the first special-sibling.
+      mFrames.RemoveElementAt(i);
+      --i;
+      continue;
+    }
 
     if (aSubtreeRoot) {
       // Reflowing the scroll frame, so recompute offsets.
       ComputeStickyOffsets(f);
     }
     // mFrames will only contain first continuations, because we filter in
     // nsIFrame::Init.
     PositionContinuations(f);
 
-    for (nsIFrame* cont = f; cont; cont = cont->GetNextContinuation()) {
+    for (nsIFrame* cont = f; cont;
+         cont = nsLayoutUtils::GetNextContinuationOrSpecialSibling(cont)) {
       oct.AddFrame(cont);
     }
   }
   oct.Flush();
 }
 
 void
 StickyScrollContainer::ScrollPositionWillChange(nscoord aX, nscoord aY)
--- a/layout/generic/crashtests/crashtests.list
+++ b/layout/generic/crashtests/crashtests.list
@@ -384,17 +384,17 @@ load 547843-1.xhtml
 load 551635-1.html
 asserts(3) load 553504-1.xhtml # nscoord_MAX assertions (bug 575011)
 load 564368-1.xhtml
 load 564968.xhtml
 load 570160.html
 load 570289-1.html
 load 571618-1.svg
 asserts(1) load 571975-1.html # bug 574889
-asserts(7) load 571995.xhtml # 761848
+asserts(1) load 571995.xhtml # 761848
 load 574958.xhtml
 asserts(0-4) load 578977.html # bug 757305
 load 580504-1.xhtml
 load 585598-1.xhtml
 asserts(0-11) load 586806-1.html # Bug 439258
 load 586806-2.html
 load 586806-3.html
 load 586973-1.html
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -340,17 +340,17 @@ NS_MergeReflowStatusInto(nsReflowStatus*
     (NS_FRAME_NOT_COMPLETE | NS_FRAME_OVERFLOW_INCOMPLETE |
      NS_FRAME_TRUNCATED | NS_FRAME_REFLOW_NEXTINFLOW);
   if (*aPrimary & NS_FRAME_NOT_COMPLETE) {
     *aPrimary &= ~NS_FRAME_OVERFLOW_INCOMPLETE;
   }
 }
 
 void
-nsWeakFrame::InitInternal(nsIFrame* aFrame)
+nsWeakFrame::Init(nsIFrame* aFrame)
 {
   Clear(mFrame ? mFrame->PresContext()->GetPresShell() : nullptr);
   mFrame = aFrame;
   if (mFrame) {
     nsIPresShell* shell = mFrame->PresContext()->GetPresShell();
     NS_WARN_IF_FALSE(shell, "Null PresShell in nsWeakFrame!");
     if (shell) {
       shell->AddWeakFrame(this);
@@ -510,16 +510,21 @@ nsFrame::Init(nsIContent*      aContent,
   if (disp->HasTransform(this)) {
     // The frame gets reconstructed if we toggle the -moz-transform
     // property, so we can set this bit here and then ignore it.
     mState |= NS_FRAME_MAY_BE_TRANSFORMED;
   }
   if (disp->mPosition == NS_STYLE_POSITION_STICKY &&
       !aPrevInFlow &&
       !(mState & NS_FRAME_IS_NONDISPLAY)) {
+    // Note that we only add first continuations, but we really only
+    // want to add first continuation-or-special-siblings.  But since we
+    // don't yet know if we're a later part of a block-in-inline split,
+    // we'll just add later members of a block-in-inline split here, and
+    // then StickyScrollContainer will remove them later.
     StickyScrollContainer* ssc =
       StickyScrollContainer::GetStickyScrollContainerForFrame(this);
     if (ssc) {
       ssc->AddFrame(this);
     }
   }
 
   if (nsLayoutUtils::FontSizeInflationEnabled(PresContext()) || !GetParent()
@@ -4241,63 +4246,53 @@ nsFrame::GetSplittableType() const
   return NS_FRAME_NOT_SPLITTABLE;
 }
 
 nsIFrame* nsFrame::GetPrevContinuation() const
 {
   return nullptr;
 }
 
-NS_IMETHODIMP nsFrame::SetPrevContinuation(nsIFrame* aPrevContinuation)
-{
-  // Ignore harmless requests to set it to NULL
-  if (aPrevContinuation) {
-    NS_ERROR("not splittable");
-    return NS_ERROR_NOT_IMPLEMENTED;
-  }
-  
-  return NS_OK;
+void
+nsFrame::SetPrevContinuation(nsIFrame* aPrevContinuation)
+{
+  MOZ_ASSERT(false, "not splittable");
 }
 
 nsIFrame* nsFrame::GetNextContinuation() const
 {
   return nullptr;
 }
 
-NS_IMETHODIMP nsFrame::SetNextContinuation(nsIFrame*)
-{
-  NS_ERROR("not splittable");
-  return NS_ERROR_NOT_IMPLEMENTED;
+void
+nsFrame::SetNextContinuation(nsIFrame*)
+{
+  MOZ_ASSERT(false, "not splittable");
 }
 
 nsIFrame* nsFrame::GetPrevInFlowVirtual() const
 {
   return nullptr;
 }
 
-NS_IMETHODIMP nsFrame::SetPrevInFlow(nsIFrame* aPrevInFlow)
-{
-  // Ignore harmless requests to set it to NULL
-  if (aPrevInFlow) {
-    NS_ERROR("not splittable");
-    return NS_ERROR_NOT_IMPLEMENTED;
-  }
-
-  return NS_OK;
+void
+nsFrame::SetPrevInFlow(nsIFrame* aPrevInFlow)
+{
+  MOZ_ASSERT(false, "not splittable");
 }
 
 nsIFrame* nsFrame::GetNextInFlowVirtual() const
 {
   return nullptr;
 }
 
-NS_IMETHODIMP nsFrame::SetNextInFlow(nsIFrame*)
-{
-  NS_ERROR("not splittable");
-  return NS_ERROR_NOT_IMPLEMENTED;
+void
+nsFrame::SetNextInFlow(nsIFrame*)
+{
+  MOZ_ASSERT(false, "not splittable");
 }
 
 nsIFrame* nsIFrame::GetTailContinuation()
 {
   nsIFrame* frame = this;
   while (frame->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER) {
     frame = frame->GetPrevContinuation();
     NS_ASSERTION(frame, "first continuation can't be overflow container");
--- a/layout/generic/nsFrame.h
+++ b/layout/generic/nsFrame.h
@@ -186,23 +186,23 @@ public:
                                         );
 
   NS_IMETHOD  CharacterDataChanged(CharacterDataChangeInfo* aInfo) MOZ_OVERRIDE;
   NS_IMETHOD  AttributeChanged(int32_t         aNameSpaceID,
                                nsIAtom*        aAttribute,
                                int32_t         aModType) MOZ_OVERRIDE;
   virtual nsSplittableType GetSplittableType() const MOZ_OVERRIDE;
   virtual nsIFrame* GetPrevContinuation() const MOZ_OVERRIDE;
-  NS_IMETHOD  SetPrevContinuation(nsIFrame*) MOZ_OVERRIDE;
+  virtual void SetPrevContinuation(nsIFrame*) MOZ_OVERRIDE;
   virtual nsIFrame* GetNextContinuation() const MOZ_OVERRIDE;
-  NS_IMETHOD  SetNextContinuation(nsIFrame*) MOZ_OVERRIDE;
+  virtual void SetNextContinuation(nsIFrame*) MOZ_OVERRIDE;
   virtual nsIFrame* GetPrevInFlowVirtual() const MOZ_OVERRIDE;
-  NS_IMETHOD  SetPrevInFlow(nsIFrame*) MOZ_OVERRIDE;
+  virtual void SetPrevInFlow(nsIFrame*) MOZ_OVERRIDE;
   virtual nsIFrame* GetNextInFlowVirtual() const MOZ_OVERRIDE;
-  NS_IMETHOD  SetNextInFlow(nsIFrame*) MOZ_OVERRIDE;
+  virtual void SetNextInFlow(nsIFrame*) MOZ_OVERRIDE;
   NS_IMETHOD  GetOffsetFromView(nsPoint& aOffset, nsView** aView) const MOZ_OVERRIDE;
   virtual nsIAtom* GetType() const MOZ_OVERRIDE;
 
   NS_IMETHOD  IsSelectable(bool* aIsSelectable, uint8_t* aSelectStyle) const MOZ_OVERRIDE;
 
   NS_IMETHOD  GetSelectionController(nsPresContext *aPresContext, nsISelectionController **aSelCon) MOZ_OVERRIDE;
 
   virtual bool PeekOffsetNoAmount(bool aForward, int32_t* aOffset) MOZ_OVERRIDE;
--- a/layout/generic/nsHTMLReflowState.cpp
+++ b/layout/generic/nsHTMLReflowState.cpp
@@ -869,17 +869,19 @@ nsHTMLReflowState::ApplyRelativePosition
   } else {
     props.Set(nsIFrame::NormalPositionProperty(), new nsPoint(*aPosition));
   }
 
   const nsStyleDisplay* display = aFrame->StyleDisplay();
   if (NS_STYLE_POSITION_RELATIVE == display->mPosition) {
     *aPosition += nsPoint(aComputedOffsets.left, aComputedOffsets.top);
   } else if (NS_STYLE_POSITION_STICKY == display->mPosition &&
-             !aFrame->GetNextContinuation() && !aFrame->GetPrevContinuation()) {
+             !aFrame->GetNextContinuation() &&
+             !aFrame->GetPrevContinuation() &&
+             !(aFrame->GetStateBits() & NS_FRAME_IS_SPECIAL)) {
     // Sticky positioning for elements with multiple frames needs to be
     // computed all at once. We can't safely do that here because we might be
     // partway through (re)positioning the frames, so leave it until the scroll
     // container reflows and calls StickyScrollContainer::UpdatePositions.
     // For single-frame sticky positioned elements, though, go ahead and apply
     // it now to avoid unnecessary overflow updates later.
     StickyScrollContainer* ssc =
       StickyScrollContainer::GetStickyScrollContainerForFrame(aFrame);
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -801,21 +801,19 @@ public:
   #define STYLE_STRUCT(name_, checkdata_cb_)                                  \
     const nsStyle##name_ * Style##name_ () const {                            \
       NS_ASSERTION(mStyleContext, "No style context found!");                 \
       return mStyleContext->Style##name_ ();                                  \
     }
   #include "nsStyleStructList.h"
   #undef STYLE_STRUCT
 
-#ifdef MOZILLA_INTERNAL_API
   /** Also forward GetVisitedDependentColor to the style context */
   nscolor GetVisitedDependentColor(nsCSSProperty aProperty)
     { return mStyleContext->GetVisitedDependentColor(aProperty); }
-#endif
 
   /**
    * These methods are to access any additional style contexts that
    * the frame may be holding. These are contexts that are children
    * of the frame's primary context and are NOT used as style contexts
    * for any child frames. These contexts also MUST NOT have any child 
    * contexts whatsoever. If you need to insert style contexts into the
    * style tree, then you should create pseudo element frames to own them
@@ -1482,19 +1480,19 @@ public:
    * Return how your frame can be split.
    */
   virtual nsSplittableType GetSplittableType() const = 0;
 
   /**
    * Continuation member functions
    */
   virtual nsIFrame* GetPrevContinuation() const = 0;
-  NS_IMETHOD SetPrevContinuation(nsIFrame*) = 0;
+  virtual void SetPrevContinuation(nsIFrame*) = 0;
   virtual nsIFrame* GetNextContinuation() const = 0;
-  NS_IMETHOD SetNextContinuation(nsIFrame*) = 0;
+  virtual void SetNextContinuation(nsIFrame*) = 0;
   virtual nsIFrame* FirstContinuation() const {
     return const_cast<nsIFrame*>(this);
   }
   virtual nsIFrame* LastContinuation() const {
     return const_cast<nsIFrame*>(this);
   }
 
   /**
@@ -1504,21 +1502,21 @@ public:
    */
   nsIFrame* GetTailContinuation();
 
   /**
    * Flow member functions
    */
   virtual nsIFrame* GetPrevInFlowVirtual() const = 0;
   nsIFrame* GetPrevInFlow() const { return GetPrevInFlowVirtual(); }
-  NS_IMETHOD SetPrevInFlow(nsIFrame*) = 0;
+  virtual void SetPrevInFlow(nsIFrame*) = 0;
 
   virtual nsIFrame* GetNextInFlowVirtual() const = 0;
   nsIFrame* GetNextInFlow() const { return GetNextInFlowVirtual(); }
-  NS_IMETHOD SetNextInFlow(nsIFrame*) = 0;
+  virtual void SetNextInFlow(nsIFrame*) = 0;
 
   /**
    * Return the first frame in our current flow. 
    */
   virtual nsIFrame* FirstInFlow() const {
     return const_cast<nsIFrame*>(this);
   }
 
@@ -3244,39 +3242,17 @@ public:
 
   void SetPreviousWeakFrame(nsWeakFrame* aPrev) { mPrev = aPrev; }
 
   ~nsWeakFrame()
   {
     Clear(mFrame ? mFrame->PresContext()->GetPresShell() : nullptr);
   }
 private:
-  void InitInternal(nsIFrame* aFrame);
-
-  void InitExternal(nsIFrame* aFrame) {
-    Clear(mFrame ? mFrame->PresContext()->GetPresShell() : nullptr);
-    mFrame = aFrame;
-    if (mFrame) {
-      nsIPresShell* shell = mFrame->PresContext()->GetPresShell();
-      NS_WARN_IF_FALSE(shell, "Null PresShell in nsWeakFrame!");
-      if (shell) {
-        shell->AddWeakFrame(this);
-      } else {
-        mFrame = nullptr;
-      }
-    }
-  }
-
-  void Init(nsIFrame* aFrame) {
-#ifdef MOZILLA_INTERNAL_API
-    InitInternal(aFrame);
-#else
-    InitExternal(aFrame);
-#endif
-  }
+  void Init(nsIFrame* aFrame);
 
   nsWeakFrame*  mPrev;
   nsIFrame*     mFrame;
 };
 
 inline bool
 nsFrameList::ContinueRemoveFrame(nsIFrame* aFrame)
 {
--- a/layout/generic/nsSplittableFrame.cpp
+++ b/layout/generic/nsSplittableFrame.cpp
@@ -45,38 +45,38 @@ nsSplittableFrame::GetSplittableType() c
   return NS_FRAME_SPLITTABLE;
 }
 
 nsIFrame* nsSplittableFrame::GetPrevContinuation() const
 {
   return mPrevContinuation;
 }
 
-NS_METHOD nsSplittableFrame::SetPrevContinuation(nsIFrame* aFrame)
+void
+nsSplittableFrame::SetPrevContinuation(nsIFrame* aFrame)
 {
   NS_ASSERTION (!aFrame || GetType() == aFrame->GetType(), "setting a prev continuation with incorrect type!");
   NS_ASSERTION (!IsInPrevContinuationChain(aFrame, this), "creating a loop in continuation chain!");
   mPrevContinuation = aFrame;
   RemoveStateBits(NS_FRAME_IS_FLUID_CONTINUATION);
-  return NS_OK;
 }
 
 nsIFrame* nsSplittableFrame::GetNextContinuation() const
 {
   return mNextContinuation;
 }
 
-NS_METHOD nsSplittableFrame::SetNextContinuation(nsIFrame* aFrame)
+void
+nsSplittableFrame::SetNextContinuation(nsIFrame* aFrame)
 {
   NS_ASSERTION (!aFrame || GetType() == aFrame->GetType(),  "setting a next continuation with incorrect type!");
   NS_ASSERTION (!IsInNextContinuationChain(aFrame, this), "creating a loop in continuation chain!");
   mNextContinuation = aFrame;
   if (aFrame)
     aFrame->RemoveStateBits(NS_FRAME_IS_FLUID_CONTINUATION);
-  return NS_OK;
 }
 
 nsIFrame*
 nsSplittableFrame::FirstContinuation() const
 {
   nsSplittableFrame* firstContinuation = const_cast<nsSplittableFrame*>(this);
   while (firstContinuation->mPrevContinuation)  {
     firstContinuation = static_cast<nsSplittableFrame*>(firstContinuation->mPrevContinuation);
@@ -124,39 +124,39 @@ bool nsSplittableFrame::IsInNextContinua
 }
 #endif
 
 nsIFrame* nsSplittableFrame::GetPrevInFlow() const
 {
   return (GetStateBits() & NS_FRAME_IS_FLUID_CONTINUATION) ? mPrevContinuation : nullptr;
 }
 
-NS_METHOD nsSplittableFrame::SetPrevInFlow(nsIFrame* aFrame)
+void
+nsSplittableFrame::SetPrevInFlow(nsIFrame* aFrame)
 {
   NS_ASSERTION (!aFrame || GetType() == aFrame->GetType(), "setting a prev in flow with incorrect type!");
   NS_ASSERTION (!IsInPrevContinuationChain(aFrame, this), "creating a loop in continuation chain!");
   mPrevContinuation = aFrame;
   AddStateBits(NS_FRAME_IS_FLUID_CONTINUATION);
-  return NS_OK;
 }
 
 nsIFrame* nsSplittableFrame::GetNextInFlow() const
 {
   return mNextContinuation && (mNextContinuation->GetStateBits() & NS_FRAME_IS_FLUID_CONTINUATION) ? 
     mNextContinuation : nullptr;
 }
 
-NS_METHOD nsSplittableFrame::SetNextInFlow(nsIFrame* aFrame)
+void
+nsSplittableFrame::SetNextInFlow(nsIFrame* aFrame)
 {
   NS_ASSERTION (!aFrame || GetType() == aFrame->GetType(),  "setting a next in flow with incorrect type!");
   NS_ASSERTION (!IsInNextContinuationChain(aFrame, this), "creating a loop in continuation chain!");
   mNextContinuation = aFrame;
   if (aFrame)
     aFrame->AddStateBits(NS_FRAME_IS_FLUID_CONTINUATION);
-  return NS_OK;
 }
 
 nsIFrame*
 nsSplittableFrame::FirstInFlow() const
 {
   nsSplittableFrame* firstInFlow = const_cast<nsSplittableFrame*>(this);
   while (nsIFrame* prev = firstInFlow->GetPrevInFlow())  {
     firstInFlow = static_cast<nsSplittableFrame*>(prev);
--- a/layout/generic/nsSplittableFrame.h
+++ b/layout/generic/nsSplittableFrame.h
@@ -36,18 +36,18 @@ public:
    * A "flow" is a chain of fluid continuations.
    */
   
   // Get the previous/next continuation, regardless of its type (fluid or non-fluid).
   virtual nsIFrame* GetPrevContinuation() const MOZ_OVERRIDE;
   virtual nsIFrame* GetNextContinuation() const MOZ_OVERRIDE;
 
   // Set a previous/next non-fluid continuation.
-  NS_IMETHOD SetPrevContinuation(nsIFrame*) MOZ_OVERRIDE;
-  NS_IMETHOD SetNextContinuation(nsIFrame*) MOZ_OVERRIDE;
+  virtual void SetPrevContinuation(nsIFrame*) MOZ_OVERRIDE;
+  virtual void SetNextContinuation(nsIFrame*) MOZ_OVERRIDE;
 
   // Get the first/last continuation for this frame.
   virtual nsIFrame* FirstContinuation() const MOZ_OVERRIDE;
   virtual nsIFrame* LastContinuation() const MOZ_OVERRIDE;
 
 #ifdef DEBUG
   // Can aFrame2 be reached from aFrame1 by following prev/next continuations?
   static bool IsInPrevContinuationChain(nsIFrame* aFrame1, nsIFrame* aFrame2);
@@ -57,18 +57,18 @@ public:
   // Get the previous/next continuation, only if it is fluid (an "in-flow").
   nsIFrame* GetPrevInFlow() const;
   nsIFrame* GetNextInFlow() const;
 
   virtual nsIFrame* GetPrevInFlowVirtual() const MOZ_OVERRIDE { return GetPrevInFlow(); }
   virtual nsIFrame* GetNextInFlowVirtual() const MOZ_OVERRIDE { return GetNextInFlow(); }
   
   // Set a previous/next fluid continuation.
-  NS_IMETHOD  SetPrevInFlow(nsIFrame*) MOZ_OVERRIDE;
-  NS_IMETHOD  SetNextInFlow(nsIFrame*) MOZ_OVERRIDE;
+  virtual void SetPrevInFlow(nsIFrame*) MOZ_OVERRIDE;
+  virtual void SetNextInFlow(nsIFrame*) MOZ_OVERRIDE;
 
   // Get the first/last frame in the current flow.
   virtual nsIFrame* FirstInFlow() const MOZ_OVERRIDE;
   virtual nsIFrame* LastInFlow() const MOZ_OVERRIDE;
 
   // Remove the frame from the flow. Connects the frame's prev-in-flow
   // and its next-in-flow. This should only be called in frame Destroy() methods.
   static void RemoveFromFlow(nsIFrame* aFrame);
--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -3897,37 +3897,35 @@ public:
                     nsIFrame*        aParent,
                     nsIFrame*        aPrevInFlow) MOZ_OVERRIDE;
 
   virtual void DestroyFrom(nsIFrame* aDestructRoot);
 
   virtual nsIFrame* GetPrevContinuation() const {
     return mPrevContinuation;
   }
-  NS_IMETHOD SetPrevContinuation(nsIFrame* aPrevContinuation) {
+  virtual void SetPrevContinuation(nsIFrame* aPrevContinuation) {
     NS_ASSERTION (!aPrevContinuation || GetType() == aPrevContinuation->GetType(),
                   "setting a prev continuation with incorrect type!");
     NS_ASSERTION (!nsSplittableFrame::IsInPrevContinuationChain(aPrevContinuation, this),
                   "creating a loop in continuation chain!");
     mPrevContinuation = aPrevContinuation;
     RemoveStateBits(NS_FRAME_IS_FLUID_CONTINUATION);
-    return NS_OK;
   }
   virtual nsIFrame* GetPrevInFlowVirtual() const { return GetPrevInFlow(); }
   nsIFrame* GetPrevInFlow() const {
     return (GetStateBits() & NS_FRAME_IS_FLUID_CONTINUATION) ? mPrevContinuation : nullptr;
   }
-  NS_IMETHOD SetPrevInFlow(nsIFrame* aPrevInFlow) {
+  virtual void SetPrevInFlow(nsIFrame* aPrevInFlow) MOZ_OVERRIDE {
     NS_ASSERTION (!aPrevInFlow || GetType() == aPrevInFlow->GetType(),
                   "setting a prev in flow with incorrect type!");
     NS_ASSERTION (!nsSplittableFrame::IsInPrevContinuationChain(aPrevInFlow, this),
                   "creating a loop in continuation chain!");
     mPrevContinuation = aPrevInFlow;
     AddStateBits(NS_FRAME_IS_FLUID_CONTINUATION);
-    return NS_OK;
   }
   virtual nsIFrame* FirstInFlow() const MOZ_OVERRIDE;
   virtual nsIFrame* FirstContinuation() const MOZ_OVERRIDE;
 
   virtual void AddInlineMinWidth(nsRenderingContext *aRenderingContext,
                                  InlineMinWidthData *aData);
   virtual void AddInlinePrefWidth(nsRenderingContext *aRenderingContext,
                                   InlinePrefWidthData *aData);
--- a/layout/generic/nsTextFrame.h
+++ b/layout/generic/nsTextFrame.h
@@ -66,40 +66,38 @@ public:
   
   NS_IMETHOD CharacterDataChanged(CharacterDataChangeInfo* aInfo) MOZ_OVERRIDE;
                                   
   virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext) MOZ_OVERRIDE;
   
   virtual nsIFrame* GetNextContinuation() const MOZ_OVERRIDE {
     return mNextContinuation;
   }
-  NS_IMETHOD SetNextContinuation(nsIFrame* aNextContinuation) MOZ_OVERRIDE {
+  virtual void SetNextContinuation(nsIFrame* aNextContinuation) MOZ_OVERRIDE {
     NS_ASSERTION (!aNextContinuation || GetType() == aNextContinuation->GetType(),
                   "setting a next continuation with incorrect type!");
     NS_ASSERTION (!nsSplittableFrame::IsInNextContinuationChain(aNextContinuation, this),
                   "creating a loop in continuation chain!");
     mNextContinuation = aNextContinuation;
     if (aNextContinuation)
       aNextContinuation->RemoveStateBits(NS_FRAME_IS_FLUID_CONTINUATION);
-    return NS_OK;
   }
   virtual nsIFrame* GetNextInFlowVirtual() const MOZ_OVERRIDE { return GetNextInFlow(); }
   nsIFrame* GetNextInFlow() const {
     return mNextContinuation && (mNextContinuation->GetStateBits() & NS_FRAME_IS_FLUID_CONTINUATION) ? 
       mNextContinuation : nullptr;
   }
-  NS_IMETHOD SetNextInFlow(nsIFrame* aNextInFlow) MOZ_OVERRIDE {
+  virtual void SetNextInFlow(nsIFrame* aNextInFlow) MOZ_OVERRIDE {
     NS_ASSERTION (!aNextInFlow || GetType() == aNextInFlow->GetType(),
                   "setting a next in flow with incorrect type!");
     NS_ASSERTION (!nsSplittableFrame::IsInNextContinuationChain(aNextInFlow, this),
                   "creating a loop in continuation chain!");
     mNextContinuation = aNextInFlow;
     if (aNextInFlow)
       aNextInFlow->AddStateBits(NS_FRAME_IS_FLUID_CONTINUATION);
-    return NS_OK;
   }
   virtual nsIFrame* LastInFlow() const MOZ_OVERRIDE;
   virtual nsIFrame* LastContinuation() const MOZ_OVERRIDE;
   
   virtual nsSplittableType GetSplittableType() const MOZ_OVERRIDE {
     return NS_FRAME_SPLITTABLE;
   }
   
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -1712,17 +1712,17 @@ needs-focus == 731726-1.html 731726-1-re
 skip-if(B2G) == 748803-1.html 748803-1-ref.html
 == 750551-1.html 750551-1-ref.html
 skip-if(B2G) == 751012-1a.html 751012-1-ref.html
 skip-if(B2G) == 751012-1b.html 751012-1-ref.html
 random-if(Android) == 753329-1.html about:blank
 == 758561-1.html 758561-1-ref.html
 fuzzy-if(true,1,19) fails-if(d2d) random-if(Android&&AndroidVersion<15) == 759036-1.html 759036-1-ref.html
 fuzzy-if(true,17,5860) random-if(Android&&AndroidVersion<15) == 759036-2.html 759036-2-ref.html
-== 776265-1a.html 776265-1-ref.html
+random-if(Android&&AndroidVersion<15) == 776265-1a.html 776265-1-ref.html
 == 776265-1b.html 776265-1-ref.html
 == 776265-1c.html 776265-1-ref.html
 == 776265-1d.html 776265-1-ref.html
 == 776265-2a.html 776265-2-ref.html
 == 776265-2b.html 776265-2-ref.html
 == 776265-2c.html 776265-2-ref.html
 == 776265-2d.html 776265-2-ref.html
 == 776443-1.html 776443-1-ref.html
new file mode 100644
--- /dev/null
+++ b/layout/reftests/position-sticky/block-in-inline-1-ref.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- Any copyright is dedicated to the Public Domain.
+   - http://creativecommons.org/publicdomain/zero/1.0/ -->
+<html>
+  <head>
+    <title>CSS Test: Sticky Positioning - block inside inline, normal position</title>
+    <link rel="author" title="L. David Baron" href="mailto:dbaron@mozilla.com">
+    <link rel="stylesheet" type="text/css" href="ahem.css">
+    <style>
+      #scroll {
+        height: 100px;
+        overflow: hidden;
+        font: 20px/1 Ahem;
+      }
+      #contain {
+        height: 100px;
+      }
+      .sticky {
+        position: relative;
+        top: 0;
+      }
+      .notsticky {
+        position: relative;
+        top: 0;
+      }
+    </style>
+  </head>
+  <body>
+    <div id="scroll">
+      <div style="height: 20px"></div>
+      <div id="contain">
+        <span class="notsticky">before inline</span>
+        <span class="sticky">before block</span>
+        <div><span class="sticky">in block</span></div>
+        <span class="sticky">after block</span>
+        <span class="notsticky">after inline</span>
+      </div>
+      <div style="height: 100px"></div>
+    </div>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/position-sticky/block-in-inline-1.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<!-- Any copyright is dedicated to the Public Domain.
+   - http://creativecommons.org/publicdomain/zero/1.0/ -->
+<html>
+  <head>
+    <title>CSS Test: Sticky Positioning - block inside inline, normal position</title>
+    <link rel="author" title="L. David Baron" href="mailto:dbaron@mozilla.com">
+    <link rel="match" href="block-in-inline-1-ref.html">
+    <meta name="assert" content="Inline elements split because they contain blocks should always have all parts moved the same offset from their normal position">
+    <link rel="stylesheet" type="text/css" href="ahem.css">
+    <style>
+      #scroll {
+        height: 100px;
+        overflow: hidden;
+        font: 20px/1 Ahem;
+      }
+      #contain {
+        height: 100px;
+      }
+      #sticky {
+        display: inline;
+        position: sticky;
+        top: 10px;
+      }
+    </style>
+  </head>
+  <body>
+    <div id="scroll">
+      <div style="height: 20px"></div>
+      <div id="contain">
+        before inline
+        <div id="sticky">
+          before block
+          <div>in block</div>
+          after block
+        </div>
+        after inline
+      </div>
+      <div style="height: 100px"></div>
+    </div>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/position-sticky/block-in-inline-2-ref.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- Any copyright is dedicated to the Public Domain.
+   - http://creativecommons.org/publicdomain/zero/1.0/ -->
+<html>
+  <head>
+    <title>CSS Test: Sticky Positioning - block inside inline, normal position</title>
+    <link rel="author" title="L. David Baron" href="mailto:dbaron@mozilla.com">
+    <link rel="stylesheet" type="text/css" href="ahem.css">
+    <style>
+      #scroll {
+        height: 100px;
+        overflow: hidden;
+        font: 20px/1 Ahem;
+      }
+      #contain {
+        height: 100px;
+      }
+      .sticky {
+        position: relative;
+        top: -10px;
+      }
+      .notsticky {
+        position: relative;
+        top: -30px;
+      }
+    </style>
+  </head>
+  <body>
+    <div id="scroll">
+      <div style="height: 20px"></div>
+      <div id="contain">
+        <span class="notsticky">before inline</span>
+        <span class="sticky">before block</span>
+        <div><span class="sticky">in block</span></div>
+        <span class="sticky">after block</span>
+        <span class="notsticky">after inline</span>
+      </div>
+      <div style="height: 100px"></div>
+    </div>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/position-sticky/block-in-inline-2.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<!-- Any copyright is dedicated to the Public Domain.
+   - http://creativecommons.org/publicdomain/zero/1.0/ -->
+<html>
+  <head>
+    <title>CSS Test: Sticky Positioning - block inside inline, stuck position</title>
+    <link rel="author" title="L. David Baron" href="mailto:dbaron@mozilla.com">
+    <link rel="match" href="block-in-inline-2-ref.html">
+    <meta name="assert" content="Inline elements split because they contain blocks should always have all parts moved the same offset from their normal position">
+    <link rel="stylesheet" type="text/css" href="ahem.css">
+    <style>
+      #scroll {
+        height: 100px;
+        overflow: hidden;
+        font: 20px/1 Ahem;
+      }
+      #contain {
+        height: 100px;
+      }
+      #sticky {
+        display: inline;
+        position: sticky;
+        top: 10px;
+      }
+    </style>
+  </head>
+  <body>
+    <div id="scroll">
+      <div style="height: 20px"></div>
+      <div id="contain">
+        before inline
+        <div id="sticky">
+          before block
+          <div>in block</div>
+          after block
+        </div>
+        after inline
+      </div>
+      <div style="height: 100px"></div>
+    </div>
+    <script type="application/javascript">
+      document.getElementById("scroll").scrollTop = 30;
+    </script>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/position-sticky/block-in-inline-3-ref.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- Any copyright is dedicated to the Public Domain.
+   - http://creativecommons.org/publicdomain/zero/1.0/ -->
+<html>
+  <head>
+    <title>CSS Test: Sticky Positioning - block inside inline, normal position</title>
+    <link rel="author" title="L. David Baron" href="mailto:dbaron@mozilla.com">
+    <link rel="stylesheet" type="text/css" href="ahem.css">
+    <style>
+      #scroll {
+        height: 100px;
+        overflow: hidden;
+        font: 20px/1 Ahem;
+      }
+      #contain {
+        height: 100px;
+      }
+      .sticky {
+        position: relative;
+        top: -20px;
+      }
+      .notsticky {
+        position: relative;
+        top: -60px;
+      }
+    </style>
+  </head>
+  <body>
+    <div id="scroll">
+      <div style="height: 20px"></div>
+      <div id="contain">
+        <span class="notsticky">before inline</span>
+        <span class="sticky">before block</span>
+        <div><span class="sticky">in block</span></div>
+        <span class="sticky">after block</span>
+        <span class="notsticky">after inline</span>
+      </div>
+      <div style="height: 100px"></div>
+    </div>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/position-sticky/block-in-inline-3.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<!-- Any copyright is dedicated to the Public Domain.
+   - http://creativecommons.org/publicdomain/zero/1.0/ -->
+<html>
+  <head>
+    <title>CSS Test: Sticky Positioning - block inside inline, contained position</title>
+    <link rel="author" title="L. David Baron" href="mailto:dbaron@mozilla.com">
+    <link rel="match" href="block-in-inline-3-ref.html">
+    <meta name="assert" content="Inline elements split because they contain blocks should always have all parts moved the same offset from their normal position">
+    <link rel="stylesheet" type="text/css" href="ahem.css">
+    <style>
+      #scroll {
+        height: 100px;
+        overflow: hidden;
+        font: 20px/1 Ahem;
+      }
+      #contain {
+        height: 100px;
+      }
+      #sticky {
+        display: inline;
+        position: sticky;
+        top: 10px;
+      }
+    </style>
+  </head>
+  <body>
+    <div id="scroll">
+      <div style="height: 20px"></div>
+      <div id="contain">
+        before inline
+        <div id="sticky">
+          before block
+          <div>in block</div>
+          after block
+        </div>
+        after inline
+      </div>
+      <div style="height: 100px"></div>
+    </div>
+    <script type="application/javascript">
+      // should start moving after 40px
+      document.getElementById("scroll").scrollTop = 60;
+    </script>
+  </body>
+</html>
--- a/layout/reftests/position-sticky/reftest.list
+++ b/layout/reftests/position-sticky/reftest.list
@@ -41,8 +41,11 @@ fuzzy-if(Android,4,1) == containing-bloc
 == overconstrained-1.html overconstrained-1-ref.html
 == overconstrained-2.html overconstrained-2-ref.html
 == overconstrained-3.html overconstrained-3-ref.html
 == inline-1.html inline-1-ref.html
 == inline-2.html inline-2-ref.html
 fails == inline-3.html inline-3-ref.html # bug 916302
 fails == column-contain-1a.html column-contain-1-ref.html
 == column-contain-1b.html column-contain-1-ref.html
+== block-in-inline-1.html block-in-inline-1-ref.html
+fuzzy-if(Android,4,19) == block-in-inline-2.html block-in-inline-2-ref.html
+fuzzy-if(Android,4,13) fuzzy-if(OSX==10.8,1,11) == block-in-inline-3.html block-in-inline-3-ref.html
--- a/layout/reftests/reftest-sanity/reftest.list
+++ b/layout/reftests/reftest-sanity/reftest.list
@@ -87,17 +87,17 @@ needs-focus load needs-focus.html
 
 # Bug 632636
 fails == data:text/plain,HELLO about:blank
 needs-focus == data:text/plain, about:blank
 
 # Sanity check of viewport+displayport overrides
 random-if(!browserIsRemote) == test-displayport.html test-displayport-ref.html # bug 593168
 skip-if(!browserIsRemote) != test-displayport-2.html test-displayport-ref.html # bug 593168
-skip-if(!browserIsRemote) fails-if(OSX&&layersGPUAccelerated) fuzzy-if(layersOMTC,1,1390) == 647192-1.html 647192-1-ref.html
+skip-if(!browserIsRemote) fails-if(OSX&&layersGPUAccelerated) fuzzy-if(layersOMTC,1,1390) random-if(Android&&AndroidVersion<15) == 647192-1.html 647192-1-ref.html
 skip-if(!browserIsRemote) == 656041-1.html 656041-1-ref.html
 skip-if(!browserIsRemote||layersOMTC) == test-displayport-bg.html test-displayport-ref.html # bug 694706
 
 # IPC Position-fixed frames/layers test
 # Fixed layers are temporarily disabled (bug 656167).
 #skip-if(!browserIsRemote) == test-pos-fixed.html test-pos-fixed-ref.html
 #skip-if(!browserIsRemote) == test-bg-attachment-fixed.html test-bg-attachment-fixed-ref.html
 skip-if(!browserIsRemote) == test-pos-fixed-transform.html test-pos-fixed-transform-ref.html
--- a/layout/style/nsCSSKeywordList.h
+++ b/layout/style/nsCSSKeywordList.h
@@ -276,16 +276,18 @@ CSS_KEY(flat, flat)
 CSS_KEY(flex, flex)
 CSS_KEY(flex-end, flex_end)
 CSS_KEY(flex-start, flex_start)
 CSS_KEY(flip, flip)
 CSS_KEY(forwards, forwards)
 CSS_KEY(from-image, from_image)
 CSS_KEY(full-width, full_width)
 CSS_KEY(georgian, georgian)
+CSS_KEY(grab, grab)
+CSS_KEY(grabbing, grabbing)
 CSS_KEY(grad, grad)
 CSS_KEY(grayscale, grayscale)
 CSS_KEY(graytext, graytext)
 CSS_KEY(groove, groove)
 CSS_KEY(hard-light, hard_light)
 CSS_KEY(hebrew, hebrew)
 CSS_KEY(help, help)
 CSS_KEY(hidden, hidden)
--- a/layout/style/nsCSSProps.cpp
+++ b/layout/style/nsCSSProps.cpp
@@ -906,16 +906,18 @@ const int32_t nsCSSProps::kCursorKTable[
   eCSSKeyword_no_drop, NS_STYLE_CURSOR_NO_DROP,
   eCSSKeyword_vertical_text, NS_STYLE_CURSOR_VERTICAL_TEXT,
   eCSSKeyword_all_scroll, NS_STYLE_CURSOR_ALL_SCROLL,
   eCSSKeyword_nesw_resize, NS_STYLE_CURSOR_NESW_RESIZE,
   eCSSKeyword_nwse_resize, NS_STYLE_CURSOR_NWSE_RESIZE,
   eCSSKeyword_ns_resize, NS_STYLE_CURSOR_NS_RESIZE,
   eCSSKeyword_ew_resize, NS_STYLE_CURSOR_EW_RESIZE,
   eCSSKeyword_none, NS_STYLE_CURSOR_NONE,
+  eCSSKeyword_grab, NS_STYLE_CURSOR_GRAB,
+  eCSSKeyword_grabbing, NS_STYLE_CURSOR_GRABBING,
   eCSSKeyword_zoom_in, NS_STYLE_CURSOR_ZOOM_IN,
   eCSSKeyword_zoom_out, NS_STYLE_CURSOR_ZOOM_OUT,
   // -moz- prefixed vendor specific
   eCSSKeyword__moz_grab, NS_STYLE_CURSOR_GRAB,
   eCSSKeyword__moz_grabbing, NS_STYLE_CURSOR_GRABBING,
   eCSSKeyword__moz_zoom_in, NS_STYLE_CURSOR_ZOOM_IN,
   eCSSKeyword__moz_zoom_out, NS_STYLE_CURSOR_ZOOM_OUT,
   eCSSKeyword_UNKNOWN,-1
--- a/layout/style/nsFontFaceLoader.cpp
+++ b/layout/style/nsFontFaceLoader.cpp
@@ -33,35 +33,35 @@
 #include "nsIConsoleService.h"
 
 #include "nsStyleSet.h"
 #include "nsPrintfCString.h"
 
 using namespace mozilla;
 
 #ifdef PR_LOGGING
-static PRLogModuleInfo *
+static PRLogModuleInfo* 
 GetFontDownloaderLog()
 {
-  static PRLogModuleInfo *sLog;
+  static PRLogModuleInfo* sLog;
   if (!sLog)
     sLog = PR_NewLogModule("fontdownloader");
   return sLog;
 }
 #endif /* PR_LOGGING */
 
 #define LOG(args) PR_LOG(GetFontDownloaderLog(), PR_LOG_DEBUG, args)
 #define LOG_ENABLED() PR_LOG_TEST(GetFontDownloaderLog(), PR_LOG_DEBUG)
 
 
-nsFontFaceLoader::nsFontFaceLoader(gfxMixedFontFamily *aFontFamily,
-                                   gfxProxyFontEntry *aProxy,
-                                   nsIURI *aFontURI,
-                                   nsUserFontSet *aFontSet,
-                                   nsIChannel *aChannel)
+nsFontFaceLoader::nsFontFaceLoader(gfxMixedFontFamily* aFontFamily,
+                                   gfxProxyFontEntry* aProxy,
+                                   nsIURI* aFontURI,
+                                   nsUserFontSet* aFontSet,
+                                   nsIChannel* aChannel)
   : mFontFamily(aFontFamily),
     mFontEntry(aProxy),
     mFontURI(aFontURI),
     mFontSet(aFontSet),
     mChannel(aChannel)
 {
 }
 
@@ -75,17 +75,17 @@ nsFontFaceLoader::~nsFontFaceLoader()
     mLoadTimer = nullptr;
   }
   if (mFontSet) {
     mFontSet->RemoveLoader(this);
   }
 }
 
 void
-nsFontFaceLoader::StartedLoading(nsIStreamLoader *aStreamLoader)
+nsFontFaceLoader::StartedLoading(nsIStreamLoader* aStreamLoader)
 {
   int32_t loadTimeout =
     Preferences::GetInt("gfx.downloadable_fonts.fallback_delay", 3000);
   if (loadTimeout > 0) {
     mLoadTimer = do_CreateInstance("@mozilla.org/timer;1");
     if (mLoadTimer) {
       mLoadTimer->InitWithFuncCallback(LoadTimerCallback,
                                        static_cast<void*>(this),
@@ -94,26 +94,26 @@ nsFontFaceLoader::StartedLoading(nsIStre
     }
   } else {
     mFontEntry->mLoadingState = gfxProxyFontEntry::LOADING_SLOWLY;
   }
   mStreamLoader = aStreamLoader;
 }
 
 void
-nsFontFaceLoader::LoadTimerCallback(nsITimer *aTimer, void *aClosure)
+nsFontFaceLoader::LoadTimerCallback(nsITimer* aTimer, void* aClosure)
 {
-  nsFontFaceLoader *loader = static_cast<nsFontFaceLoader*>(aClosure);
+  nsFontFaceLoader* loader = static_cast<nsFontFaceLoader*>(aClosure);
 
   if (!loader->mFontSet) {
     // We've been canceled
     return;
   }
 
-  gfxProxyFontEntry *pe = loader->mFontEntry.get();
+  gfxProxyFontEntry* pe = loader->mFontEntry.get();
   bool updateUserFontSet = true;
 
   // If the entry is loading, check whether it's >75% done; if so,
   // we allow another timeout period before showing a fallback font.
   if (pe->mLoadingState == gfxProxyFontEntry::LOADING_STARTED) {
     int64_t contentLength;
     uint32_t numBytesRead;
     if (NS_SUCCEEDED(loader->mChannel->GetContentLength(&contentLength)) &&
@@ -137,18 +137,18 @@ nsFontFaceLoader::LoadTimerCallback(nsIT
     }
   }
 
   // If the font is not 75% loaded, or if we've already timed out once
   // before, we mark this entry as "loading slowly", so the fallback
   // font will be used in the meantime, and tell the context to refresh.
   if (updateUserFontSet) {
     pe->mLoadingState = gfxProxyFontEntry::LOADING_SLOWLY;
-    gfxUserFontSet *fontSet = loader->mFontSet;
-    nsPresContext *ctx = loader->mFontSet->GetPresContext();
+    gfxUserFontSet* fontSet = loader->mFontSet;
+    nsPresContext* ctx = loader->mFontSet->GetPresContext();
     NS_ASSERTION(ctx, "userfontset doesn't have a presContext?");
     if (ctx) {
       fontSet->IncrementGeneration();
       ctx->UserFontSetUpdated();
       LOG(("fontdownloader (%p) timeout reflow\n", loader));
     }
   }
 }
@@ -178,17 +178,17 @@ nsFontFaceLoader::OnStreamComplete(nsISt
            this, fontURI.get()));
     } else {
       LOG(("fontdownloader (%p) download failed - font uri: (%s) error: %8.8x\n", 
            this, fontURI.get(), aStatus));
     }
   }
 #endif
 
-  nsPresContext *ctx = mFontSet->GetPresContext();
+  nsPresContext* ctx = mFontSet->GetPresContext();
   NS_ASSERTION(ctx && !ctx->PresShell()->IsDestroying(),
                "We should have been canceled already");
 
   if (NS_SUCCEEDED(aStatus)) {
     // for HTTP requests, check whether the request _actually_ succeeded;
     // the "request status" in aStatus does not necessarily indicate this,
     // because HTTP responses such as 404 (Not Found) will still result in
     // a success code and potentially an HTML error page from the server
@@ -252,17 +252,17 @@ nsFontFaceLoader::CheckLoadAllowed(nsIPr
                                    nsISupports* aContext)
 {
   nsresult rv;
 
   if (!aSourcePrincipal)
     return NS_OK;
 
   // check with the security manager
-  nsIScriptSecurityManager *secMan = nsContentUtils::GetSecurityManager();
+  nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
   rv = secMan->CheckLoadURIWithPrincipal(aSourcePrincipal, aTargetURI,
                                         nsIScriptSecurityManager::STANDARD);
   if (NS_FAILED(rv)) {
     return rv;
   }
 
   // check content policy
   int16_t shouldLoad = nsIContentPolicy::ACCEPT;
@@ -278,17 +278,17 @@ nsFontFaceLoader::CheckLoadAllowed(nsIPr
 
   if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) {
     return NS_ERROR_CONTENT_BLOCKED;
   }
 
   return NS_OK;
 }
 
-nsUserFontSet::nsUserFontSet(nsPresContext *aContext)
+nsUserFontSet::nsUserFontSet(nsPresContext* aContext)
   : mPresContext(aContext)
 {
   NS_ASSERTION(mPresContext, "null context passed to nsUserFontSet");
 }
 
 nsUserFontSet::~nsUserFontSet()
 {
   NS_ASSERTION(mLoaders.Count() == 0, "mLoaders should have been emptied");
@@ -305,29 +305,29 @@ void
 nsUserFontSet::Destroy()
 {
   mPresContext = nullptr;
   mLoaders.EnumerateEntries(DestroyIterator, nullptr);
   mRules.Clear();
 }
 
 void
-nsUserFontSet::RemoveLoader(nsFontFaceLoader *aLoader)
+nsUserFontSet::RemoveLoader(nsFontFaceLoader* aLoader)
 {
   mLoaders.RemoveEntry(aLoader);
 }
 
 nsresult
-nsUserFontSet::StartLoad(gfxMixedFontFamily *aFamily,
-                         gfxProxyFontEntry *aProxy,
-                         const gfxFontFaceSrc *aFontFaceSrc)
+nsUserFontSet::StartLoad(gfxMixedFontFamily* aFamily,
+                         gfxProxyFontEntry* aProxy,
+                         const gfxFontFaceSrc* aFontFaceSrc)
 {
   nsresult rv;
 
-  nsIPresShell *ps = mPresContext->PresShell();
+  nsIPresShell* ps = mPresContext->PresShell();
   if (!ps)
     return NS_ERROR_FAILURE;
 
   nsCOMPtr<nsIStreamLoader> streamLoader;
   nsCOMPtr<nsILoadGroup> loadGroup(ps->GetDocument()->GetDocumentLoadGroup());
 
   nsCOMPtr<nsIChannel> channel;
   // get Content Security Policy from principal to pass into channel
@@ -456,38 +456,38 @@ nsUserFontSet::UpdateRules(const nsTArra
     modified = true;
     // Any in-progress loaders for obsolete rules should be cancelled,
     // as the resource being downloaded will no longer be required.
     // We need to explicitly remove any loaders here, otherwise the loaders
     // will keep their "orphaned" font entries alive until they complete,
     // even after the oldRules array is deleted.
     size_t count = oldRules.Length();
     for (size_t i = 0; i < count; ++i) {
-      gfxFontEntry *fe = oldRules[i].mFontEntry;
+      gfxFontEntry* fe = oldRules[i].mFontEntry;
       if (!fe->mIsProxy) {
         continue;
       }
-      gfxProxyFontEntry *proxy = static_cast<gfxProxyFontEntry*>(fe);
-      nsFontFaceLoader *loader = proxy->mLoader;
+      gfxProxyFontEntry* proxy = static_cast<gfxProxyFontEntry*>(fe);
+      nsFontFaceLoader* loader = proxy->mLoader;
       if (loader) {
         loader->Cancel();
         RemoveLoader(loader);
       }
     }
   }
 
   if (modified) {
     IncrementGeneration();
   }
 
   return modified;
 }
 
 void
-nsUserFontSet::InsertRule(nsCSSFontFaceRule *aRule, uint8_t aSheetType,
+nsUserFontSet::InsertRule(nsCSSFontFaceRule* aRule, uint8_t aSheetType,
                           nsTArray<FontFaceRuleRecord>& aOldRules,
                           bool& aFontSetModified)
 {
   NS_ABORT_IF_FALSE(aRule->GetType() == mozilla::css::Rule::FONT_FACE_RULE,
                     "InsertRule passed a non-fontface CSS rule");
 
   // set up family name
   nsAutoString fontfamily;
@@ -595,23 +595,23 @@ nsUserFontSet::InsertRule(nsCSSFontFaceR
   }
 
   // set up src array
   nsTArray<gfxFontFaceSrc> srcArray;
 
   aRule->GetDesc(eCSSFontDesc_Src, val);
   unit = val.GetUnit();
   if (unit == eCSSUnit_Array) {
-    nsCSSValue::Array *srcArr = val.GetArrayValue();
+    nsCSSValue::Array* srcArr = val.GetArrayValue();
     size_t numSrc = srcArr->Count();
     
     for (size_t i = 0; i < numSrc; i++) {
       val = srcArr->Item(i);
       unit = val.GetUnit();
-      gfxFontFaceSrc *face = srcArray.AppendElements(1);
+      gfxFontFaceSrc* face = srcArray.AppendElements(1);
       if (!face)
         return;
 
       switch (unit) {
 
       case eCSSUnit_Local_Font:
         val.GetStringValue(face->mLocalName);
         face->mIsLocal = true;
@@ -684,47 +684,47 @@ nsUserFontSet::InsertRule(nsCSSFontFaceR
       mRules.AppendElement(ruleRec);
     }
     // this was a new rule and fontEntry, so note that the set was modified
     aFontSetModified = true;
   }
 }
 
 void
-nsUserFontSet::ReplaceFontEntry(gfxMixedFontFamily *aFamily,
-                                gfxProxyFontEntry *aProxy,
-                                gfxFontEntry *aFontEntry)
+nsUserFontSet::ReplaceFontEntry(gfxMixedFontFamily* aFamily,
+                                gfxProxyFontEntry* aProxy,
+                                gfxFontEntry* aFontEntry)
 {
   // aProxy is being supplanted by the "real" font aFontEntry, so we need to
   // update any rules that refer to it. Note that there may be multiple rules
   // that refer to the same proxy - e.g. if a stylesheet was loaded multiple
   // times, so that several identical @font-face rules are present.
   for (uint32_t i = 0; i < mRules.Length(); ++i) {
     if (mRules[i].mFontEntry == aProxy) {
       mRules[i].mFontEntry = aFontEntry;
     }
   }
   aFamily->ReplaceFontEntry(aProxy, aFontEntry);
 }
 
 nsCSSFontFaceRule*
-nsUserFontSet::FindRuleForEntry(gfxFontEntry *aFontEntry)
+nsUserFontSet::FindRuleForEntry(gfxFontEntry* aFontEntry)
 {
   for (uint32_t i = 0; i < mRules.Length(); ++i) {
     if (mRules[i].mFontEntry == aFontEntry) {
       return mRules[i].mContainer.mRule;
     }
   }
   return nullptr;
 }
 
 nsresult
-nsUserFontSet::LogMessage(gfxMixedFontFamily *aFamily,
-                          gfxProxyFontEntry *aProxy,
-                          const char        *aMessage,
+nsUserFontSet::LogMessage(gfxMixedFontFamily* aFamily,
+                          gfxProxyFontEntry* aProxy,
+                          const char*        aMessage,
                           uint32_t          aFlags,
                           nsresult          aStatus)
 {
   nsCOMPtr<nsIConsoleService>
     console(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
   if (!console) {
     return NS_ERROR_NOT_AVAILABLE;
   }
@@ -737,17 +737,17 @@ nsUserFontSet::LogMessage(gfxMixedFontFa
     if (aProxy->mSrcList[aProxy->mSrcIndex].mURI) {
       aProxy->mSrcList[aProxy->mSrcIndex].mURI->GetSpec(fontURI);
     } else {
       fontURI.AppendLiteral("(invalid URI)");
     }
   }
 
   char weightKeywordBuf[8]; // plenty to sprintf() a uint16_t
-  const char *weightKeyword;
+  const char* weightKeyword;
   const nsAFlatCString& weightKeywordString =
     nsCSSProps::ValueToKeyword(aProxy->Weight(),
                                nsCSSProps::kFontWeightKTable);
   if (weightKeywordString.Length() > 0) {
     weightKeyword = weightKeywordString.get();
   } else {
     sprintf(weightKeywordBuf, "%u", aProxy->Weight());
     weightKeyword = weightKeywordBuf;
@@ -825,22 +825,22 @@ nsUserFontSet::LogMessage(gfxMixedFontFa
   if (NS_SUCCEEDED(rv)) {
     console->LogMessage(scriptError);
   }
 
   return NS_OK;
 }
 
 nsresult
-nsUserFontSet::CheckFontLoad(const gfxFontFaceSrc *aFontFaceSrc,
-                             nsIPrincipal **aPrincipal,
-                             bool *aBypassCache)
+nsUserFontSet::CheckFontLoad(const gfxFontFaceSrc* aFontFaceSrc,
+                             nsIPrincipal** aPrincipal,
+                             bool* aBypassCache)
 {
   // check same-site origin
-  nsIPresShell *ps = mPresContext->PresShell();
+  nsIPresShell* ps = mPresContext->PresShell();
   if (!ps)
     return NS_ERROR_FAILURE;
 
   NS_ASSERTION(aFontFaceSrc && !aFontFaceSrc->mIsLocal,
                "bad font face url passed to fontloader");
   NS_ASSERTION(aFontFaceSrc->mURI, "null font uri");
   if (!aFontFaceSrc->mURI)
     return NS_ERROR_FAILURE;
@@ -876,20 +876,20 @@ nsUserFontSet::CheckFontLoad(const gfxFo
       }
     }
   }
 
   return rv;
 }
 
 nsresult
-nsUserFontSet::SyncLoadFontData(gfxProxyFontEntry *aFontToLoad,
-                                const gfxFontFaceSrc *aFontFaceSrc,
-                                uint8_t* &aBuffer,
-                                uint32_t &aBufferLength)
+nsUserFontSet::SyncLoadFontData(gfxProxyFontEntry* aFontToLoad,
+                                const gfxFontFaceSrc* aFontFaceSrc,
+                                uint8_t*& aBuffer,
+                                uint32_t& aBufferLength)
 {
   nsresult rv;
 
   nsCOMPtr<nsIChannel> channel;
   // get Content Security Policy from principal to pass into channel
   nsCOMPtr<nsIChannelPolicy> channelPolicy;
   nsCOMPtr<nsIContentSecurityPolicy> csp;
   rv = aFontToLoad->mPrincipal->GetCsp(getter_AddRefs(csp));
@@ -960,17 +960,17 @@ nsUserFontSet::SyncLoadFontData(gfxProxy
   }
 
   return NS_OK;
 }
 
 bool
 nsUserFontSet::GetPrivateBrowsing()
 {
-  nsIPresShell *ps = mPresContext->PresShell();
+  nsIPresShell* ps = mPresContext->PresShell();
   if (!ps) {
     return false;
   }
 
   nsCOMPtr<nsISupports> container = ps->GetDocument()->GetContainer();
   if (!container) {
     return false;
   }
--- a/layout/style/nsFontFaceLoader.h
+++ b/layout/style/nsFontFaceLoader.h
@@ -21,114 +21,114 @@ class nsPresContext;
 class nsIPrincipal;
 
 class nsFontFaceLoader;
 
 // nsUserFontSet - defines the loading mechanism for downloadable fonts
 class nsUserFontSet : public gfxUserFontSet
 {
 public:
-  nsUserFontSet(nsPresContext *aContext);
+  nsUserFontSet(nsPresContext* aContext);
   ~nsUserFontSet();
 
   // Called when this font set is no longer associated with a presentation.
   void Destroy();
 
   // starts loading process, creating and initializing a nsFontFaceLoader obj
   // returns whether load process successfully started or not
-  nsresult StartLoad(gfxMixedFontFamily *aFamily,
-                     gfxProxyFontEntry *aFontToLoad,
-                     const gfxFontFaceSrc *aFontFaceSrc);
+  nsresult StartLoad(gfxMixedFontFamily* aFamily,
+                     gfxProxyFontEntry* aFontToLoad,
+                     const gfxFontFaceSrc* aFontFaceSrc);
 
   // Called by nsFontFaceLoader when the loader has completed normally.
   // It's removed from the mLoaders set.
-  void RemoveLoader(nsFontFaceLoader *aLoader);
+  void RemoveLoader(nsFontFaceLoader* aLoader);
 
   bool UpdateRules(const nsTArray<nsFontFaceRuleContainer>& aRules);
 
-  nsPresContext *GetPresContext() { return mPresContext; }
+  nsPresContext* GetPresContext() { return mPresContext; }
 
-  virtual void ReplaceFontEntry(gfxMixedFontFamily *aFamily,
-                                gfxProxyFontEntry *aProxy,
-                                gfxFontEntry *aFontEntry);
+  virtual void ReplaceFontEntry(gfxMixedFontFamily* aFamily,
+                                gfxProxyFontEntry* aProxy,
+                                gfxFontEntry* aFontEntry);
 
-  nsCSSFontFaceRule *FindRuleForEntry(gfxFontEntry *aFontEntry);
+  nsCSSFontFaceRule* FindRuleForEntry(gfxFontEntry* aFontEntry);
 
 protected:
   // The font-set keeps track of the collection of rules, and their
   // corresponding font entries (whether proxies or real entries),
   // so that we can update the set without having to throw away
   // all the existing fonts.
   struct FontFaceRuleRecord {
     nsRefPtr<gfxFontEntry>       mFontEntry;
     nsFontFaceRuleContainer      mContainer;
   };
 
-  void InsertRule(nsCSSFontFaceRule *aRule, uint8_t aSheetType,
+  void InsertRule(nsCSSFontFaceRule* aRule, uint8_t aSheetType,
                   nsTArray<FontFaceRuleRecord>& oldRules,
                   bool& aFontSetModified);
 
-  virtual nsresult LogMessage(gfxMixedFontFamily *aFamily,
-                              gfxProxyFontEntry *aProxy,
-                              const char *aMessage,
+  virtual nsresult LogMessage(gfxMixedFontFamily* aFamily,
+                              gfxProxyFontEntry* aProxy,
+                              const char* aMessage,
                               uint32_t aFlags = nsIScriptError::errorFlag,
                               nsresult aStatus = NS_OK);
 
-  virtual nsresult CheckFontLoad(const gfxFontFaceSrc *aFontFaceSrc,
-                                 nsIPrincipal **aPrincipal,
-                                 bool *aBypassCache);
+  virtual nsresult CheckFontLoad(const gfxFontFaceSrc* aFontFaceSrc,
+                                 nsIPrincipal** aPrincipal,
+                                 bool* aBypassCache);
 
-  virtual nsresult SyncLoadFontData(gfxProxyFontEntry *aFontToLoad,
-                                    const gfxFontFaceSrc *aFontFaceSrc,
-                                    uint8_t* &aBuffer,
-                                    uint32_t &aBufferLength);
+  virtual nsresult SyncLoadFontData(gfxProxyFontEntry* aFontToLoad,
+                                    const gfxFontFaceSrc* aFontFaceSrc,
+                                    uint8_t*& aBuffer,
+                                    uint32_t& aBufferLength);
 
   virtual bool GetPrivateBrowsing() MOZ_OVERRIDE;
 
-  nsPresContext *mPresContext;  // weak reference
+  nsPresContext* mPresContext;  // weak reference
 
   // Set of all loaders pointing to us. These are not strong pointers,
   // but that's OK because nsFontFaceLoader always calls RemoveLoader on
   // us before it dies (unless we die first).
   nsTHashtable< nsPtrHashKey<nsFontFaceLoader> > mLoaders;
 
   nsTArray<FontFaceRuleRecord>   mRules;
 };
 
 class nsFontFaceLoader : public nsIStreamLoaderObserver
 {
 public:
-  nsFontFaceLoader(gfxMixedFontFamily *aFontFamily,
-                   gfxProxyFontEntry *aFontToLoad, nsIURI *aFontURI, 
-                   nsUserFontSet *aFontSet, nsIChannel *aChannel);
+  nsFontFaceLoader(gfxMixedFontFamily* aFontFamily,
+                   gfxProxyFontEntry* aFontToLoad, nsIURI* aFontURI, 
+                   nsUserFontSet* aFontSet, nsIChannel* aChannel);
 
   virtual ~nsFontFaceLoader();
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSISTREAMLOADEROBSERVER 
 
   // initiate the load
   nsresult Init();
   // cancel the load and remove its reference to mFontSet
   void Cancel();
 
   void DropChannel() { mChannel = nullptr; }
 
-  void StartedLoading(nsIStreamLoader *aStreamLoader);
+  void StartedLoading(nsIStreamLoader* aStreamLoader);
 
-  static void LoadTimerCallback(nsITimer *aTimer, void *aClosure);
+  static void LoadTimerCallback(nsITimer* aTimer, void* aClosure);
 
   static nsresult CheckLoadAllowed(nsIPrincipal* aSourcePrincipal,
                                    nsIURI* aTargetURI,
                                    nsISupports* aContext);
 
 private:
   nsRefPtr<gfxMixedFontFamily> mFontFamily;
   nsRefPtr<gfxProxyFontEntry>  mFontEntry;
   nsCOMPtr<nsIURI>        mFontURI;
   nsRefPtr<nsUserFontSet> mFontSet;
   nsCOMPtr<nsIChannel>    mChannel;
   nsCOMPtr<nsITimer>      mLoadTimer;
 
-  nsIStreamLoader        *mStreamLoader;
+  nsIStreamLoader*        mStreamLoader;
 };
 
 #endif /* !defined(nsFontFaceLoader_h_) */
--- a/layout/style/test/property_database.js
+++ b/layout/style/test/property_database.js
@@ -2331,17 +2331,17 @@ var gCSSProperties = {
 		other_values: [ "foo 1", "bar", "foo 3 bar baz 2", "\\32  1", "-\\32  1", "-c 1", "\\32 1", "-\\32 1", "\\2  1", "-\\2  1", "-c 1", "\\2 1", "-\\2 1", "-\\7f \\9e 1" ],
 		invalid_values: []
 	},
 	"cursor": {
 		domProp: "cursor",
 		inherited: true,
 		type: CSS_TYPE_LONGHAND,
 		initial_values: [ "auto" ],
-		other_values: [ "crosshair", "default", "pointer", "move", "e-resize", "ne-resize", "nw-resize", "n-resize", "se-resize", "sw-resize", "s-resize", "w-resize", "text", "wait", "help", "progress", "copy", "alias", "context-menu", "cell", "not-allowed", "col-resize", "row-resize", "no-drop", "vertical-text", "all-scroll", "nesw-resize", "nwse-resize", "ns-resize", "ew-resize", "none", "zoom-in", "zoom-out", "-moz-grab", "-moz-grabbing", "-moz-zoom-in", "-moz-zoom-out", "url(foo.png), move", "url(foo.png) 5 7, move", "url(foo.png) 12 3, url(bar.png), no-drop", "url(foo.png), url(bar.png) 7 2, wait", "url(foo.png) 3 2, url(bar.png) 7 9, pointer" ],
+		other_values: [ "crosshair", "default", "pointer", "move", "e-resize", "ne-resize", "nw-resize", "n-resize", "se-resize", "sw-resize", "s-resize", "w-resize", "text", "wait", "help", "progress", "copy", "alias", "context-menu", "cell", "not-allowed", "col-resize", "row-resize", "no-drop", "vertical-text", "all-scroll", "nesw-resize", "nwse-resize", "ns-resize", "ew-resize", "none", "grab", "grabbing", "zoom-in", "zoom-out", "-moz-grab", "-moz-grabbing", "-moz-zoom-in", "-moz-zoom-out", "url(foo.png), move", "url(foo.png) 5 7, move", "url(foo.png) 12 3, url(bar.png), no-drop", "url(foo.png), url(bar.png) 7 2, wait", "url(foo.png) 3 2, url(bar.png) 7 9, pointer" ],
 		invalid_values: [ "url(foo.png)", "url(foo.png) 5 5" ]
 	},
 	"direction": {
 		domProp: "direction",
 		inherited: true,
 		type: CSS_TYPE_LONGHAND,
 		initial_values: [ "ltr" ],
 		other_values: [ "rtl" ],
--- a/layout/style/ua.css
+++ b/layout/style/ua.css
@@ -204,18 +204,18 @@
 }
 
 *|*::-moz-pagebreak {
   display: block !important;
 }
 
 *|*::-moz-anonymous-positioned-block {
   display: block !important;
-  position: relative;
-  top: inherit; 
+  position: inherit; /* relative or sticky */
+  top: inherit;
   left: inherit;
   bottom: inherit;
   right: inherit;
   z-index: inherit;
   clip: inherit;
   opacity: inherit;
   unicode-bidi: inherit;
   text-overflow: inherit;
--- a/netwerk/base/public/security-prefs.js
+++ b/netwerk/base/public/security-prefs.js
@@ -8,17 +8,17 @@ pref("security.enable_tls_session_ticket
 pref("security.enable_md5_signatures", false);
 
 pref("security.ssl.allow_unrestricted_renego_everywhere__temporarily_available_pref", false);
 pref("security.ssl.renego_unrestricted_hosts", "");
 pref("security.ssl.treat_unsafe_negotiation_as_broken", false);
 pref("security.ssl.require_safe_negotiation",  false);
 pref("security.ssl.warn_missing_rfc5746",  1);
 pref("security.ssl.enable_ocsp_stapling", true);
-pref("security.ssl.enable_false_start", true);
+pref("security.ssl.enable_false_start", false);
 pref("security.ssl.false_start.require-npn", true);
 pref("security.ssl.false_start.require-forward-secrecy", false);
 
 pref("security.ssl3.rsa_rc4_128_md5", true);
 pref("security.ssl3.rsa_rc4_128_sha", true);
 pref("security.ssl3.rsa_fips_des_ede3_sha", true);
 pref("security.ssl3.rsa_des_ede3_sha", true);
 pref("security.ssl3.dhe_rsa_camellia_256_sha", true);
--- a/netwerk/cache2/CacheStorageService.cpp
+++ b/netwerk/cache2/CacheStorageService.cpp
@@ -1035,17 +1035,17 @@ CacheStorageService::OnMemoryConsumption
 
 void
 CacheStorageService::PurgeOverMemoryLimit()
 {
   MOZ_ASSERT(IsOnManagementThread());
 
   LOG(("CacheStorageService::PurgeOverMemoryLimit"));
 
-#ifdef MOZ_LOGGING
+#ifdef PR_LOG
   TimeStamp start(TimeStamp::Now());
 #endif
 
   uint32_t const memoryLimit = CacheObserver::MemoryLimit();
 
   if (mMemorySize > memoryLimit) {
     LOG(("  memory data consumption over the limit, abandon expired entries"));
     PurgeExpired();
--- a/netwerk/test/unit/test_cache2-11-evict-memory.js
+++ b/netwerk/test/unit/test_cache2-11-evict-memory.js
@@ -15,17 +15,17 @@ function run_test()
               }),
               true
             );
           }),
           true
         );
       })
     );
-  });
+  }, !newCacheBackEndUsed());
 
   asyncOpenCacheEntry("http://mem1/", "memory", Ci.nsICacheStorage.OPEN_NORMALLY, null,
     new OpenCallback(NEW, "m2m", "m2d", function(entry) {
       asyncOpenCacheEntry("http://mem1/", "memory", Ci.nsICacheStorage.OPEN_NORMALLY, null,
         new OpenCallback(NORMAL, "m2m", "m2d", function(entry) {
           mc.fired();
         })
       );
--- a/netwerk/test/unit/test_cache2-12-evict-disk.js
+++ b/netwerk/test/unit/test_cache2-12-evict-disk.js
@@ -20,17 +20,17 @@ function run_test()
               }),
               true
             );
           }),
           true
         );
       })
     );
-  });
+  }, !newCacheBackEndUsed());
 
   asyncOpenCacheEntry("http://mem1/", "memory", Ci.nsICacheStorage.OPEN_NORMALLY, null,
     new OpenCallback(NEW, "m2m", "m2d", function(entry) {
       asyncOpenCacheEntry("http://mem1/", "memory", Ci.nsICacheStorage.OPEN_NORMALLY, null,
         new OpenCallback(NORMAL, "m2m", "m2d", function(entry) {
           mc.fired();
         })
       );
--- a/netwerk/test/unit/test_cache2-22-anon-visit.js
+++ b/netwerk/test/unit/test_cache2-22-anon-visit.js
@@ -35,17 +35,17 @@ function run_test()
             true
           );
         }),
         true
       );
     });
   }
 
-  var mc = new MultipleCallbacks(2, newCacheBackEndUsed() ? checkNewBackEnd : checkOldBackEnd);
+  var mc = new MultipleCallbacks(2, newCacheBackEndUsed() ? checkNewBackEnd : checkOldBackEnd, !newCacheBackEndUsed());
 
   asyncOpenCacheEntry("http://an2/", "disk", Ci.nsICacheStorage.OPEN_NORMALLY, LoadContextInfo.default,
     new OpenCallback(NEW|WAITFORWRITE, "an2", "an2", function(entry) {
       mc.fired();
     })
   );
 
   asyncOpenCacheEntry("http://an2/", "disk", Ci.nsICacheStorage.OPEN_NORMALLY, LoadContextInfo.anonymous,
--- a/python/mozbuild/mozbuild/frontend/emitter.py
+++ b/python/mozbuild/mozbuild/frontend/emitter.py
@@ -216,16 +216,17 @@ class TreeMetadataEmitter(LoggingMixin):
         # We ideally don't filter out inactive tests. However, not every test
         # harness can yet deal with test filtering. Once all harnesses can do
         # this, this feature can be dropped.
         test_manifests = dict(
             A11Y=('a11y', 'testing/mochitest/a11y', True),
             BROWSER_CHROME=('browser-chrome', 'testing/mochitest/browser', True),
             MOCHITEST=('mochitest', 'testing/mochitest/tests', True),
             MOCHITEST_CHROME=('chrome', 'testing/mochitest/chrome', True),
+            WEBRTC_SIGNALLING_TEST=('steeplechase', 'steeplechase', True),
             XPCSHELL_TESTS=('xpcshell', 'xpcshell', False),
         )
 
         for prefix, info in test_manifests.items():
             for path in sandbox.get('%s_MANIFESTS' % prefix, []):
                 for obj in self._process_test_manifest(sandbox, info, path):
                     yield obj
 
--- a/python/mozbuild/mozbuild/frontend/sandbox_symbols.py
+++ b/python/mozbuild/mozbuild/frontend/sandbox_symbols.py
@@ -462,16 +462,20 @@ VARIABLES = {
     'MOCHITEST_MANIFESTS': (StrictOrderingOnAppendList, list, [],
         """List of manifest files defining mochitest tests.
         """),
 
     'MOCHITEST_CHROME_MANIFESTS': (StrictOrderingOnAppendList, list, [],
         """List of manifest files defining mochitest chrome tests.
         """),
 
+    'WEBRTC_SIGNALLING_TEST_MANIFESTS': (StrictOrderingOnAppendList, list, [],
+        """List of manifest files defining WebRTC signalling tests.
+        """),
+
     'XPCSHELL_TESTS_MANIFESTS': (StrictOrderingOnAppendList, list, [],
         """List of manifest files defining xpcshell tests.
         """),
 }
 
 # The set of functions exposed to the sandbox.
 #
 # Each entry is a tuple of:
--- a/security/manager/ssl/src/nsNSSComponent.cpp
+++ b/security/manager/ssl/src/nsNSSComponent.cpp
@@ -1210,21 +1210,20 @@ nsNSSComponent::InitializeNSS(bool showW
       bool allowUnrestrictedRenego =
         Preferences::GetBool("security.ssl.allow_unrestricted_renego_everywhere__temporarily_available_pref",
                              ALLOW_UNRESTRICTED_RENEGO_DEFAULT);
       SSL_OptionSetDefault(SSL_ENABLE_RENEGOTIATION,
                            allowUnrestrictedRenego ?
                              SSL_RENEGOTIATE_UNRESTRICTED :
                              SSL_RENEGOTIATE_REQUIRES_XTN);
 
-#ifdef SSL_ENABLE_FALSE_START // Requires NSS 3.12.8
-      bool falseStartEnabled = Preferences::GetBool("security.ssl.enable_false_start",
-                                                    FALSE_START_ENABLED_DEFAULT);
-      SSL_OptionSetDefault(SSL_ENABLE_FALSE_START, falseStartEnabled);
-#endif
+//    Bug 920248: temporarily disable false start
+//    bool falseStartEnabled = Preferences::GetBool("security.ssl.enable_false_start",
+//                                                  FALSE_START_ENABLED_DEFAULT);
+      SSL_OptionSetDefault(SSL_ENABLE_FALSE_START, false);
 
       // Disable any ciphers that NSS might have enabled by default
       for (uint16_t i = 0; i < SSL_NumImplementedCiphers; ++i)
       {
         uint16_t cipher_id = SSL_ImplementedCiphers[i];
         SSL_CipherPrefSetDefault(cipher_id, false);
       }
 
@@ -1646,22 +1645,21 @@ nsNSSComponent::Observe(nsISupports *aSu
     } else if (prefName.Equals("security.ssl.allow_unrestricted_renego_everywhere__temporarily_available_pref")) {
       bool allowUnrestrictedRenego =
         Preferences::GetBool("security.ssl.allow_unrestricted_renego_everywhere__temporarily_available_pref",
                              ALLOW_UNRESTRICTED_RENEGO_DEFAULT);
       SSL_OptionSetDefault(SSL_ENABLE_RENEGOTIATION,
                            allowUnrestrictedRenego ?
                              SSL_RENEGOTIATE_UNRESTRICTED :
                              SSL_RENEGOTIATE_REQUIRES_XTN);
-#ifdef SSL_ENABLE_FALSE_START // Requires NSS 3.12.8
     } else if (prefName.Equals("security.ssl.enable_false_start")) {
-      bool falseStartEnabled = Preferences::GetBool("security.ssl.enable_false_start",
-                                                    FALSE_START_ENABLED_DEFAULT);
-      SSL_OptionSetDefault(SSL_ENABLE_FALSE_START, falseStartEnabled);
-#endif
+//    Bug 920248: temporarily disable false start
+//    bool falseStartEnabled = Preferences::GetBool("security.ssl.enable_false_start",
+//                                                  FALSE_START_ENABLED_DEFAULT);
+      SSL_OptionSetDefault(SSL_ENABLE_FALSE_START, false);
     } else if (prefName.Equals("security.OCSP.enabled")
                || prefName.Equals("security.CRL_download.enabled")
                || prefName.Equals("security.fresh_revocation_info.require")
                || prefName.Equals("security.missing_cert_download.enabled")
                || prefName.Equals("security.first_network_revocation_method")
                || prefName.Equals("security.OCSP.require")
                || prefName.Equals("security.ssl.enable_ocsp_stapling")) {
       MutexAutoLock lock(mutex);
--- a/testing/mochitest/android.json
+++ b/testing/mochitest/android.json
@@ -123,24 +123,24 @@
  "dom/browser-element/mochitest/test_browserElement_inproc_AppFramePermission.html": "",
  "dom/browser-element/mochitest/test_browserElement_inproc_AppWindowNamespace.html": "TIMED_OUT, bug 783509",
  "dom/browser-element/mochitest/test_browserElement_inproc_SecurityChange.html": "TIMED_OUT, bug 766586",
  "dom/browser-element/mochitest/test_browserElement_inproc_CloseApp.html": "FAILS, bug 796982",
  "dom/devicestorage": "bug 781789 & bug 782275",
  "dom/imptests/editing/conformancetest/test_runtest.html": "",
  "dom/imptests/editing/selecttest/test_addRange.html": "bug 775227",
  "dom/imptests/html/webgl": "WebGL",
- "dom/imptests/webapps/DOMCore/tests/approved/test_Range-cloneContents.html": "bug 775227", 
- "dom/imptests/webapps/DOMCore/tests/approved/test_Range-compareBoundaryPoints.html": "bug 775227",
- "dom/imptests/webapps/DOMCore/tests/approved/test_Range-deleteContents.html": "bug 775227",
- "dom/imptests/webapps/DOMCore/tests/approved/test_Range-extractContents.html": "bug 775227",
- "dom/imptests/webapps/DOMCore/tests/approved/test_Range-insertNode.html": "bug 775227",
- "dom/imptests/webapps/DOMCore/tests/approved/test_Range-mutations.html": "bug 775227",
- "dom/imptests/webapps/DOMCore/tests/approved/test_Range-set.html": "bug 775227",
- "dom/imptests/webapps/DOMCore/tests/approved/test_Range-surroundContents.html": "bug 775227",
+ "dom/imptests/html/dom/ranges/test_Range-cloneContents.html": "bug 775227",
+ "dom/imptests/html/dom/ranges/test_Range-compareBoundaryPoints.html": "bug 775227",
+ "dom/imptests/html/dom/ranges/test_Range-deleteContents.html": "bug 775227",
+ "dom/imptests/html/dom/ranges/test_Range-extractContents.html": "bug 775227",
+ "dom/imptests/html/dom/ranges/test_Range-insertNode.html": "bug 775227",
+ "dom/imptests/html/dom/ranges/test_Range-mutations.html": "bug 775227",
+ "dom/imptests/html/dom/ranges/test_Range-set.html": "bug 775227",
+ "dom/imptests/html/dom/ranges/test_Range-surroundContents.html": "bug 775227",
  "dom/imptests/webapps/WebStorage/tests/submissions/Infraware/test_storage_local_key.html": "bug 775227",
  "dom/indexedDB/ipc/test_ipc.html": "bug 783513",
  "dom/indexedDB/test/test_third_party.html": "TIMED_OUT",
  "dom/indexedDB/test/test_event_propagation.html": "TIMED_OUT, bug 780855",
  "dom/indexedDB/test/test_app_isolation_inproc.html": "TIMED_OUT",
  "dom/indexedDB/test/test_app_isolation_oop.html": "TIMED_OUT",
  "dom/indexedDB/test/test_webapp_clearBrowserData_inproc_inproc.html": "No test app installed",
  "dom/indexedDB/test/test_webapp_clearBrowserData_inproc_oop.html": "No test app installed",
--- a/testing/mochitest/b2g.json
+++ b/testing/mochitest/b2g.json
@@ -62,24 +62,24 @@
     "content/media/test/test_unseekable.html":"",
     "content/media/webaudio":"bug 916135",
     "content/media/webspeech/recognition/test/test_recognition_service_error.html": "timed out",
     "content/media/webspeech/synth/ipc/test/test_ipc.html": "comp.classes['@mozilla.org/special-powers-observer;1'] is undefined",
     "content/media/webspeech/synth/test/test_speech_queue.html": "Test timed out",
     "content/media/webspeech/synth/test/test_speech_simple.html": "Test timed out",
 
     "dom/imptests/editing/selecttest/test_addRange.html": "oom?, bug 775227",
-    "dom/imptests/webapps/DOMCore/tests/approved/test_Range-insertNode.html":"oom?, bug 775227",
-    "dom/imptests/webapps/DOMCore/tests/approved/test_Range-cloneContents.html":"",
-    "dom/imptests/webapps/DOMCore/tests/approved/test_Range-compareBoundaryPoints.html":"times out, bug 862196",
-    "dom/imptests/webapps/DOMCore/tests/approved/test_Range-deleteContents.html":"",
-    "dom/imptests/webapps/DOMCore/tests/approved/test_Range-extractContents.html":"",
-    "dom/imptests/webapps/DOMCore/tests/approved/test_Range-set.html":"",
-    "dom/imptests/webapps/DOMCore/tests/approved/test_Range-surroundContents.html":"",
-    "dom/imptests/webapps/DOMCore/tests/approved/test_Range-mutations.html":"Test timed out.",
+    "dom/imptests/html/dom/ranges/test_Range-insertNode.html":"oom?, bug 775227",
+    "dom/imptests/html/dom/ranges/test_Range-cloneContents.html":"",
+    "dom/imptests/html/dom/ranges/test_Range-compareBoundaryPoints.html":"times out, bug 862196",
+    "dom/imptests/html/dom/ranges/test_Range-deleteContents.html":"",
+    "dom/imptests/html/dom/ranges/test_Range-extractContents.html":"",
+    "dom/imptests/html/dom/ranges/test_Range-set.html":"",
+    "dom/imptests/html/dom/ranges/test_Range-surroundContents.html":"",
+    "dom/imptests/html/dom/ranges/test_Range-mutations.html":"Test timed out.",
     "dom/encoding/test/test_stringencoding.html":"Test timed out on b2g board",
 
     "content/events/test/test_bug615597.html":"bug 900969, 5 tests",
     "content/events/test/test_bug667919-1.html":"bug 900969, 5 tests",
     "content/events/test/test_bug667919-2.html":"bug 900969, 5 tests",
 
     "content/html/content/test/test_bug561636.html":"observerservice not working",
     "content/base/test/test_bug548193.html":"observerservice issue",
--- a/testing/testsuite-targets.mk
+++ b/testing/testsuite-targets.mk
@@ -401,16 +401,17 @@ package-tests: \
   stage-jetpack \
   stage-peptest \
   stage-mozbase \
   stage-tps \
   stage-modules \
   stage-marionette \
   stage-cppunittests \
   stage-jittest \
+  stage-steeplechase \
   $(NULL)
 else
 # This staging area has been built for us by universal/flight.mk
 PKG_STAGE = $(DIST)/universal/test-package-stage
 endif
 
 package-tests:
 	@rm -f "$(DIST)/$(PKG_PATH)$(TEST_PACKAGE)"
@@ -508,16 +509,22 @@ endif
 
 stage-jittest:
 	$(NSINSTALL) -D $(PKG_STAGE)/jit-test/tests
 	cp -RL $(topsrcdir)/js/src/jsapi.h $(PKG_STAGE)/jit-test
 	cp -RL $(topsrcdir)/js/src/jit-test $(PKG_STAGE)/jit-test/jit-test
 	cp -RL $(topsrcdir)/js/src/tests/ecma_6 $(PKG_STAGE)/jit-test/tests/ecma_6
 	cp -RL $(topsrcdir)/js/src/tests/lib $(PKG_STAGE)/jit-test/tests/lib
 
+stage-steeplechase:
+	$(NSINSTALL) -D $(PKG_STAGE)/steeplechase/
+	cp -RL $(DEPTH)/_tests/steeplechase $(PKG_STAGE)/steeplechase/tests
+	cp -RL $(DIST)/xpi-stage/specialpowers $(PKG_STAGE)/steeplechase
+	cp -RL $(topsrcdir)/testing/profiles/prefs_general.js $(PKG_STAGE)/steeplechase
+
 MARIONETTE_DIR=$(PKG_STAGE)/marionette
 stage-marionette: make-stage-dir
 	$(NSINSTALL) -D $(MARIONETTE_DIR)/tests
 	@(cd $(topsrcdir)/testing/marionette/client && tar --exclude marionette/tests $(TAR_CREATE_FLAGS) - *) | (cd $(MARIONETTE_DIR) && tar -xf -)
 	$(PYTHON) $(topsrcdir)/testing/marionette/client/marionette/tests/print-manifest-dirs.py \
           $(topsrcdir) \
           $(topsrcdir)/testing/marionette/client/marionette/tests/unit-tests.ini \
           | (cd $(topsrcdir) && xargs tar $(TAR_CREATE_FLAGS) -) \
@@ -546,10 +553,11 @@ stage-mozbase: make-stage-dir
   stage-jstests \
   stage-android \
   stage-jetpack \
   stage-peptest \
   stage-mozbase \
   stage-tps \
   stage-modules \
   stage-marionette \
+  stage-steeplechase \
   $(NULL)
 
--- a/tools/profiler/BreakpadSampler.cpp
+++ b/tools/profiler/BreakpadSampler.cpp
@@ -5,30 +5,28 @@
 
 // System
 #include <string>
 #include <stdio.h>
 #include <errno.h>
 #include <ostream>
 #include <fstream>
 #include <sstream>
-#if defined(ANDROID)
-# include "android-signal-defs.h"
-#endif
 
 // Profiler
 #include "PlatformMacros.h"
 #include "GeckoProfilerImpl.h"
 #include "platform.h"
 #include "nsXULAppAPI.h"
 #include "nsThreadUtils.h"
 #include "prenv.h"
 #include "shared-libraries.h"
 #include "mozilla/StackWalk.h"
 #include "ProfileEntry.h"
+#include "SyncProfile.h"
 #include "SaveProfileTask.h"
 #include "UnwinderThread2.h"
 #include "TableTicker.h"
 
 // JSON
 #include "JSObjectBuilder.h"
 #include "nsIJSRuntimeService.h"
 
@@ -152,67 +150,63 @@ void genPseudoBacktraceEntries(/*MODIFIE
 #   ifdef ENABLE_ARM_LR_SAVING
     utb__addEntry( utb, ProfileEntry('L', (void*)sample->lr) );
 #   endif
   }
 # endif
 }
 
 // RUNS IN SIGHANDLER CONTEXT
-void TableTicker::UnwinderTick(TickSample* sample)
+static
+void populateBuffer(UnwinderThreadBuffer* utb, TickSample* sample,
+                    UTB_RELEASE_FUNC releaseFunction, bool jankOnly)
 {
-  if (!sample->threadProfile) {
-    // Platform doesn't support multithread, so use the main thread profile we created
-    sample->threadProfile = GetPrimaryThreadProfile();
-  }
-
-  ThreadProfile& currThreadProfile = *sample->threadProfile;
-
-  /* Get hold of an empty inter-thread buffer into which to park