Merge m-c to fx-team.
authorRyan VanderMeulen <ryanvm@gmail.com>
Wed, 16 Oct 2013 17:04:40 -0400
changeset 164859 85fc49eda28abe327690b2318cd1b0126c5e7742
parent 164858 723aed267eb044ffae88bf93d404d45b26e78206 (current diff)
parent 164844 66af8b3096a61f6eb95059817eb0de629d0c187b (diff)
child 164860 7bbd04f256988298d56eb5e6b549d79bb16fa2f2
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.
build/autoconf/moznbytetype.m4
js/src/build/autoconf/moznbytetype.m4
--- a/accessible/tests/mochitest/elm/test_HTMLSpec.html
+++ b/accessible/tests/mochitest/elm/test_HTMLSpec.html
@@ -689,17 +689,17 @@
         role: ROLE_ENTRY,
         extraStates: EXT_STATE_EDITABLE | EXT_STATE_SINGLE_LINE,
         actions: "activate",
         interfaces: [ nsIAccessibleText, nsIAccessibleEditableText ],
         children: [
           { role: ROLE_TEXT_LEAF }
         ]
       };
-      testElm("input_number", obj);
+      // TODO: re-enable in bug 559761 testElm("input_number", obj);
       testElm("input_email", obj);
       testElm("input_search", obj);
       testElm("input_tel", obj);
       testElm("input_text", obj);
       testElm("input_url", obj);
 
       //////////////////////////////////////////////////////////////////////////
       // HTML:input@type="password"
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -797,20 +797,17 @@ pref("dom.promise.enabled", false);
 // Enable dataStore
 #ifdef RELEASE_BUILD
 pref("dom.datastore.enabled", false);
 #else
 pref("dom.datastore.enabled", true);
 #endif
 
 // DOM Inter-App Communication API.
-#ifdef MOZ_WIDGET_GONK
-// Enable this only for gonk-specific build but not for desktop build.
 pref("dom.inter-app-communication-api.enabled", true);
-#endif
 
 // Allow ADB to run for this many hours before disabling
 // (only applies when marionette is disabled)
 // 0 disables the timer.
 pref("b2g.adb.timeout-hours", 12);
 
 // InputMethod so we can do soft keyboards
 pref("dom.mozInputMethod.enabled", true);
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,4 +1,4 @@
 {
-    "revision": "36aa3e5d226a844b07b3e4b2219f54b549456ec1", 
+    "revision": "86e06b1db110e34eb66826d3b1bdee3a5d57b3a7", 
     "repo_path": "/integration/gaia-central"
 }
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -773,28 +773,16 @@ var gBrowserInit = {
           .getInterface(nsIWebNavigation)
           .QueryInterface(Ci.nsIDocShellTreeItem).treeOwner
           .QueryInterface(Ci.nsIInterfaceRequestor)
           .getInterface(Ci.nsIXULWindow)
           .XULBrowserWindow = window.XULBrowserWindow;
     window.QueryInterface(Ci.nsIDOMChromeWindow).browserDOMWindow =
       new nsBrowserAccess();
 
-    // set default character set if provided
-    // window.arguments[1]: character set (string)
-    if ("arguments" in window && window.arguments.length > 1 && window.arguments[1]) {
-      if (window.arguments[1].startsWith("charset=")) {
-        var arrayArgComponents = window.arguments[1].split("=");
-        if (arrayArgComponents) {
-          //we should "inherit" the charset menu setting in a new window
-          getMarkupDocumentViewer().defaultCharacterSet = arrayArgComponents[1];
-        }
-      }
-    }
-
     // Manually hook up session and global history for the first browser
     // so that we don't have to load global history before bringing up a
     // window.
     // Wire up session and global history before any possible
     // progress notifications for back/forward button updating
     gBrowser.webNavigation.sessionHistory = Cc["@mozilla.org/browser/shistory;1"].
                                             createInstance(Ci.nsISHistory);
     Services.obs.addObserver(gBrowser.browsers[0], "browser:purge-session-history", false);
deleted file mode 100644
--- a/build/autoconf/moznbytetype.m4
+++ /dev/null
@@ -1,103 +0,0 @@
-dnl This Source Code Form is subject to the terms of the Mozilla Public
-dnl License, v. 2.0. If a copy of the MPL was not distributed with this
-dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-dnl MOZ_N_BYTE_TYPE(VARIABLE, SIZE, POSSIBLE-TYPES)
-dnl
-dnl Check to see which of POSSIBLE-TYPES has a size of SIZE.  If we
-dnl find one, define VARIABLE to be the size-BYTE type.  If no type
-dnl matches, exit the configure script with an error message.  Types
-dnl whose written form contains spaces should appear in POSSIBLE-TYPES
-dnl enclosed by shell quotes.
-dnl
-dnl The cache variable moz_cv_n_byte_type_VARIABLE gets set to the
-dnl type, if found.
-dnl 
-dnl for example:
-dnl MOZ_N_BYTE_TYPE([JS_INT32_T], [4], [int long 'long long' short])
-dnl
-AC_DEFUN([MOZ_N_BYTE_TYPE],
-[
-dnl The simplest approach would simply be to run a program that says
-dnl   printf ("%d\n", sizeof ($type));
-dnl But that won't work when cross-compiling; this will.
-AC_CACHE_CHECK([for a $2-byte type], moz_cv_n_byte_type_$1, [
-  moz_cv_n_byte_type_$1=
-  for type in $3; do
-    AC_TRY_COMPILE([],
-                   [
-                     int a[sizeof ($type) == $2 ? 1 : -1];
-                     return 0;
-                   ],
-                   [moz_cv_n_byte_type_$1=$type; break], [])
-  done
-  if test ! "$moz_cv_n_byte_type_$1"; then
-    AC_MSG_ERROR([Couldn't find a $2-byte type])
-  fi
-])
-AC_DEFINE_UNQUOTED($1, [$moz_cv_n_byte_type_$1],
-                   [a $2-byte type on the target machine])
-])
-
-dnl MOZ_SIZE_OF_TYPE(VARIABLE, TYPE, POSSIBLE-SIZES)
-dnl
-dnl Check to see which of POSSIBLE-SIZES is the sizeof(TYPE). If we find one,
-dnl define VARIABLE SIZE. If no size matches, exit the configure script with
-dnl an error message.
-dnl
-dnl The cache variable moz_cv_size_of_VARIABLE gets set to the size, if
-dnl found.
-dnl
-dnl for example:
-dnl MOZ_SIZE_OF_TYPE([JS_BYTES_PER_WORD], [void*], [4 8])
-AC_DEFUN([MOZ_SIZE_OF_TYPE],
-[
-AC_CACHE_CHECK([for the size of $2], moz_cv_size_of_$1, [
-  moz_cv_size_of_$1=
-  for size in $3; do
-    AC_TRY_COMPILE([],
-                   [
-                     int a[sizeof ($2) == $size ? 1 : -1];
-                     return 0;
-                   ],
-                   [moz_cv_size_of_$1=$size; break], [])
-  done
-  if test ! "$moz_cv_size_of_$1"; then
-    AC_MSG_ERROR([No size found for $2])
-  fi
-])
-AC_DEFINE_UNQUOTED($1, [$moz_cv_size_of_$1])
-])
-
-dnl MOZ_ALIGN_OF_TYPE(VARIABLE, TYPE, POSSIBLE-ALIGNS)
-dnl
-dnl Check to see which of POSSIBLE-ALIGNS is the necessary alignment of TYPE.
-dnl If we find one, define VARIABLE ALIGNMENT. If no alignment matches, exit
-dnl the configure script with an error message.
-dnl
-dnl The cache variable moz_cv_align_of_VARIABLE gets set to the size, if
-dnl found.
-dnl
-dnl for example:
-dnl MOZ_ALIGN_OF_TYPE(JS_ALIGN_OF_POINTER, void*, 2 4 8 16)
-AC_DEFUN([MOZ_ALIGN_OF_TYPE],
-[
-AC_CACHE_CHECK([for the alignment of $2], moz_cv_align_of_$1, [
-  moz_cv_align_of_$1=
-  for align in $3; do
-    AC_TRY_COMPILE([
-                     #include <stddef.h>
-                     struct aligner { char c; $2 a; };
-                   ],
-                   [
-                     int a[offsetof(struct aligner, a) == $align ? 1 : -1];
-                     return 0;
-                   ],
-                   [moz_cv_align_of_$1=$align; break], [])
-  done
-  if test ! "$moz_cv_align_of_$1"; then
-    AC_MSG_ERROR([No alignment found for $2])
-  fi
-])
-AC_DEFINE_UNQUOTED($1, [$moz_cv_align_of_$1])
-])
--- a/build/mobile/remoteautomation.py
+++ b/build/mobile/remoteautomation.py
@@ -6,16 +6,17 @@ import time
 import re
 import os
 import tempfile
 import shutil
 import subprocess
 
 from automation import Automation
 from devicemanager import NetworkTools, DMError
+import mozcrash
 
 # signatures for logcat messages that we don't care about much
 fennecLogcatFilters = [ "The character encoding of the HTML document was not declared",
                            "Use of Mutation Events is deprecated. Use MutationObserver instead." ]
 
 class RemoteAutomation(Automation):
     _devicemanager = None
 
@@ -81,46 +82,16 @@ class RemoteAutomation(Automation):
                       "allowed maximum time of %s seconds" % (self.lastTestSeen, maxTime)
             else:
                 print "TEST-UNEXPECTED-FAIL | %s | application ran for longer than " \
                       "allowed maximum time" % (self.lastTestSeen)
             proc.kill()
 
         return status
 
-    def checkForJavaException(self, logcat):
-        found_exception = False
-        for i, line in enumerate(logcat):
-            if "REPORTING UNCAUGHT EXCEPTION" in line or "FATAL EXCEPTION" in line:
-                # Strip away the date, time, logcat tag and pid from the next two lines and
-                # concatenate the remainder to form a concise summary of the exception. 
-                #
-                # For example:
-                #
-                # 01-30 20:15:41.937 E/GeckoAppShell( 1703): >>> REPORTING UNCAUGHT EXCEPTION FROM THREAD 9 ("GeckoBackgroundThread")
-                # 01-30 20:15:41.937 E/GeckoAppShell( 1703): java.lang.NullPointerException
-                # 01-30 20:15:41.937 E/GeckoAppShell( 1703): 	at org.mozilla.gecko.GeckoApp$21.run(GeckoApp.java:1833)
-                # 01-30 20:15:41.937 E/GeckoAppShell( 1703): 	at android.os.Handler.handleCallback(Handler.java:587)
-                # 01-30 20:15:41.937 E/GeckoAppShell( 1703): 	at android.os.Handler.dispatchMessage(Handler.java:92)
-                # 01-30 20:15:41.937 E/GeckoAppShell( 1703): 	at android.os.Looper.loop(Looper.java:123)
-                # 01-30 20:15:41.937 E/GeckoAppShell( 1703): 	at org.mozilla.gecko.util.GeckoBackgroundThread.run(GeckoBackgroundThread.java:31)
-                #
-                #   -> java.lang.NullPointerException at org.mozilla.gecko.GeckoApp$21.run(GeckoApp.java:1833)
-                found_exception = True
-                logre = re.compile(r".*\): \t?(.*)")
-                m = logre.search(logcat[i+1])
-                if m and m.group(1):
-                    top_frame = m.group(1)
-                m = logre.search(logcat[i+2])
-                if m and m.group(1):
-                    top_frame = top_frame + m.group(1)
-                print "PROCESS-CRASH | java-exception | %s" % top_frame
-                break
-        return found_exception
-
     def deleteANRs(self):
         # delete ANR traces.txt file; usually need root permissions
         traces = "/data/anr/traces.txt"
         try:
             self._devicemanager.shellCheckOutput(['rm', traces], root=True)
         except DMError:
             print "Error deleting %s" % traces
             pass
@@ -139,17 +110,17 @@ class RemoteAutomation(Automation):
                 pass
         else:
             print "%s not found" % traces
 
     def checkForCrashes(self, directory, symbolsPath):
         self.checkForANRs()
 
         logcat = self._devicemanager.getLogcat(filterOutRegexps=fennecLogcatFilters)
-        javaException = self.checkForJavaException(logcat)
+        javaException = mozcrash.check_for_java_exception(logcat)
         if javaException:
             return True
 
         # If crash reporting is disabled (MOZ_CRASHREPORTER!=1), we can't say
         # anything.
         if not self.CRASHREPORTER:
             return False
 
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -3473,16 +3473,21 @@ nsDocument::doCreateShell(nsPresContext*
   FillStyleSet(aStyleSet);
 
   nsRefPtr<PresShell> shell = new PresShell;
   shell->Init(this, aContext, aViewManager, aStyleSet, aCompatMode);
 
   // Note: we don't hold a ref to the shell (it holds a ref to us)
   mPresShell = shell;
 
+  // Make sure to never paint if we belong to an invisible DocShell.
+  nsCOMPtr<nsIDocShell> docShell = do_QueryReferent(mDocumentContainer);
+  if (docShell && docShell->IsInvisible())
+    shell->SetNeverPainting(true);
+
   mExternalResourceMap.ShowViewers();
 
   MaybeRescheduleAnimationFrameNotifications();
 
   return shell.forget();
 }
 
 void
--- a/content/canvas/src/CanvasRenderingContext2D.cpp
+++ b/content/canvas/src/CanvasRenderingContext2D.cpp
@@ -2850,16 +2850,51 @@ void
 CanvasRenderingContext2D::SetMozDashOffset(double mozDashOffset)
 {
   ContextState& state = CurrentState();
   if (!state.dash.IsEmpty()) {
     state.dashOffset = mozDashOffset;
   }
 }
 
+void
+CanvasRenderingContext2D::SetLineDash(const mozilla::dom::AutoSequence<double>& mSegments) {
+  FallibleTArray<mozilla::gfx::Float>& dash = CurrentState().dash;
+  dash.Clear();
+
+  for(mozilla::dom::AutoSequence<double>::index_type x = 0; x < mSegments.Length(); x++) {
+    dash.AppendElement(mSegments[x]);
+  }
+  if(mSegments.Length()%2) { // If the number of elements is odd, concatenate again
+    for(mozilla::dom::AutoSequence<double>::index_type x = 0; x < mSegments.Length(); x++) {
+      dash.AppendElement(mSegments[x]);
+    }
+  }
+}
+
+void
+CanvasRenderingContext2D::GetLineDash(nsTArray<double>& mSegments) const {
+  const FallibleTArray<mozilla::gfx::Float>& dash = CurrentState().dash;
+  mSegments.Clear();
+
+  for(FallibleTArray<mozilla::gfx::Float>::index_type x = 0; x < dash.Length(); x++) {
+    mSegments.AppendElement(dash[x]);
+  }
+}
+
+void
+CanvasRenderingContext2D::SetLineDashOffset(double mOffset) {
+  CurrentState().dashOffset = mOffset;
+}
+
+double
+CanvasRenderingContext2D::LineDashOffset() const {
+  return CurrentState().dashOffset;
+}
+
 bool
 CanvasRenderingContext2D::IsPointInPath(double x, double y, const CanvasWindingRule& winding)
 {
   if (!FloatValidate(x,y)) {
     return false;
   }
 
   EnsureUserSpacePath(winding);
--- a/content/canvas/src/CanvasRenderingContext2D.h
+++ b/content/canvas/src/CanvasRenderingContext2D.h
@@ -328,16 +328,22 @@ public:
                                      JS::Handle<JSObject*> currentTransform,
                                      mozilla::ErrorResult& error);
   void GetFillRule(nsAString& fillRule);
   void SetFillRule(const nsAString& fillRule);
   JS::Value GetMozDash(JSContext* cx, mozilla::ErrorResult& error);
   void SetMozDash(JSContext* cx, const JS::Value& mozDash,
                   mozilla::ErrorResult& error);
 
+  void SetLineDash(const mozilla::dom::AutoSequence<double>& mSegments);
+  void GetLineDash(nsTArray<double>& mSegments) const;
+
+  void SetLineDashOffset(double mOffset);
+  double LineDashOffset() const;
+
   double MozDashOffset()
   {
     return CurrentState().dashOffset;
   }
   void SetMozDashOffset(double mozDashOffset);
 
   void GetMozTextStyle(nsAString& mozTextStyle)
   {
@@ -839,16 +845,20 @@ protected:
   };
 
   nsAutoTArray<ContextState, 3> mStyleStack;
 
   inline ContextState& CurrentState() {
     return mStyleStack[mStyleStack.Length() - 1];
   }
 
+  inline const ContextState& CurrentState() const {
+    return mStyleStack[mStyleStack.Length() - 1];
+  }
+
   friend class CanvasGeneralPattern;
   friend class AdjustedTarget;
 
   // other helpers
   void GetAppUnitsValues(int32_t *perDevPixel, int32_t *perCSSPixel)
   {
     // If we don't have a canvas element, we just return something generic.
     int32_t devPixel = 60;
--- a/content/canvas/test/test_canvas.html
+++ b/content/canvas/test/test_canvas.html
@@ -21483,16 +21483,91 @@ function test_getImageData_after_zero_ca
     var same = false;
     ok(imgdata.data.length === oldimgdata.data.length, "not the same length");
     for (var i = 0; i < imgdata.data.length; ++i)
         same = imgdata.data[i] === oldimgdata.data[i];
     ok(same, "changing dimensions broke canvas");
 }
 </script>
 
+<p>Canvas test: zero_dimensions_image_data</p>
+<canvas id="c687" width="150" height="50"></canvas>
+<script type="text/javascript">
+
+function test_linedash() {
+  var c = document.getElementById("c687");
+  var ctx = c.getContext("2d");
+  ok(ctx.lineDashOffset==0, "initial dash offset is not 0");
+
+  ctx.setLineDash([15, 10]);
+  ctx.lineDashOffset = 5;
+  ctx.strokeRect (10,10,100,100);
+
+  var lineDash = ctx.getLineDash();
+  ok(lineDash[0]==15&&lineDash[1]==10, "dash pattern [15, 10] is wrong");
+  ok(ctx.lineDashOffset==5, "dash offset is wrong");
+
+  ctx.setLineDash([5, 10, 15]);
+  ctx.strokeRect(20, 20, 120, 120);
+  lineDash = ctx.getLineDash();
+  ok(lineDash[0]==5
+    && lineDash[1]==10
+    && lineDash[2]==15
+    && lineDash[3]==5
+    && lineDash[4]==10
+    && lineDash[5]==15, "dash pattern [5, 10, 15] is wrong");
+
+  ctx.setLineDash(["1", 2]);
+  lineDash = ctx.getLineDash();
+  ok(lineDash[0] == 1 && lineDash[1] == 2, "dash pattern ['1', 2] is wrong");
+
+  ctx.clearRect(0, 0, 700, 700);
+  ok(ctx.lineDashOffset==5, "dash offset is wrong");
+
+  ctx.setLineDash([20, 10]);
+  ctx.lineDashOffset = 0;
+  ctx.lineWidth = 4; // To make the test immune to plaform anti-aliasing discrepancies
+  ctx.strokeStyle = '#00FF00';
+  ctx.strokeRect(10.5, 10.5, 30, 30);
+
+  isPixel(ctx, 25, 10, 0, 255, 0, 255, 0);
+  isPixel(ctx, 35, 10, 0, 0, 0, 0, 0);
+  isPixel(ctx, 40, 25, 0, 255, 0, 255, 0);
+  isPixel(ctx, 40, 35, 0, 0, 0, 0, 0);
+  isPixel(ctx, 25, 40, 0, 255, 0, 255, 0);
+  isPixel(ctx, 15, 40, 0, 0, 0, 0, 0);
+  isPixel(ctx, 10, 25, 0, 255, 0, 255, 0);
+  isPixel(ctx, 10, 15, 0, 0, 0, 0, 0);
+
+  // Verify that lineDashOffset works as expected
+  ctx.lineDashOffset = 20;
+  ctx.strokeRect(50.5, 10.5, 30, 30);
+  isPixel(ctx, 55, 10, 0, 0, 0, 0, 0);
+  isPixel(ctx, 65, 10, 0, 255, 0, 255, 0);
+  isPixel(ctx, 80, 15, 0, 0, 0, 0, 0);
+  isPixel(ctx, 80, 25, 0, 255, 0, 255, 0);
+  isPixel(ctx, 75, 40, 0, 0, 0, 0, 0);
+  isPixel(ctx, 65, 40, 0, 255, 0, 255, 0);
+  isPixel(ctx, 50, 35, 0, 0, 0, 0, 0);
+  isPixel(ctx, 50, 25, 0, 255, 0, 255, 0);
+
+  // Verify negative lineDashOffset
+  ctx.lineDashOffset = -10;
+  ctx.strokeRect(90.5, 10.5, 30, 30);
+  isPixel(ctx, 95, 10, 0, 0, 0, 0, 0);
+  isPixel(ctx, 105, 10, 0, 255, 0, 255, 0);
+  isPixel(ctx, 120, 15, 0, 0, 0, 0, 0);
+  isPixel(ctx, 120, 25, 0, 255, 0, 255, 0);
+  isPixel(ctx, 115, 40, 0, 0, 0, 0, 0);
+  isPixel(ctx, 105, 40, 0, 255, 0, 255, 0);
+  isPixel(ctx, 90, 35, 0, 0, 0, 0, 0);
+  isPixel(ctx, 90, 25, 0, 255, 0, 255, 0);
+}
+</script>
+
 <script>
 
 function asyncTestsDone() {
 	if (isDone_test_2d_drawImage_animated_apng &&
 		isDone_test_2d_drawImage_animated_gif) {
 		SimpleTest.finish();
 	} else {
 		setTimeout(asyncTestsDone, 500);
@@ -24774,16 +24849,22 @@ function runTests() {
  }
  try {
   test_getImageData_after_zero_canvas();
  } catch(e) {
   throw e;
   ok(false, "unexpected exception thrown in: test_getImageData_after_zero_canvas");
  }
  try {
+  test_linedash();
+ } catch(e) {
+  throw e;
+  ok(false, "unexpected exception thrown in: test_linedash");
+ }
+ try {
   // run this test last since it replaces the getContext method
   test_type_replace();
  } catch (e) {
   ok(false, "unexpected exception thrown in: test_type_replace");
  }
  
  //run the asynchronous tests
  try {
--- a/content/events/src/DOMWheelEvent.cpp
+++ b/content/events/src/DOMWheelEvent.cpp
@@ -8,38 +8,38 @@
 #include "mozilla/MouseEvents.h"
 #include "prtime.h"
 
 namespace mozilla {
 namespace dom {
 
 DOMWheelEvent::DOMWheelEvent(EventTarget* aOwner,
                              nsPresContext* aPresContext,
-                             WheelEvent* aWheelEvent)
+                             WidgetWheelEvent* aWheelEvent)
   : nsDOMMouseEvent(aOwner, aPresContext,
                     aWheelEvent ? aWheelEvent :
-                                  new WheelEvent(false, 0, nullptr))
+                                  new WidgetWheelEvent(false, 0, nullptr))
 {
   if (aWheelEvent) {
     mEventIsInternal = false;
   } else {
     mEventIsInternal = true;
     mEvent->time = PR_Now();
     mEvent->refPoint.x = mEvent->refPoint.y = 0;
-    static_cast<WheelEvent*>(mEvent)->inputSource =
+    static_cast<WidgetWheelEvent*>(mEvent)->inputSource =
       nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN;
   }
 }
 
 DOMWheelEvent::~DOMWheelEvent()
 {
   if (mEventIsInternal && mEvent) {
     MOZ_ASSERT(mEvent->eventStructType == NS_WHEEL_EVENT,
-               "The mEvent must be WheelEvent");
-    delete static_cast<WheelEvent*>(mEvent);
+               "The mEvent must be WidgetWheelEvent");
+    delete static_cast<WidgetWheelEvent*>(mEvent);
     mEvent = nullptr;
   }
 }
 
 NS_IMPL_ADDREF_INHERITED(DOMWheelEvent, nsDOMMouseEvent)
 NS_IMPL_RELEASE_INHERITED(DOMWheelEvent, nsDOMMouseEvent)
 
 NS_INTERFACE_MAP_BEGIN(DOMWheelEvent)
@@ -66,17 +66,17 @@ DOMWheelEvent::InitWheelEvent(const nsAS
 {
   nsresult rv =
     nsDOMMouseEvent::InitMouseEvent(aType, aCanBubble, aCancelable, aView,
                                     aDetail, aScreenX, aScreenY,
                                     aClientX, aClientY, aButton,
                                     aRelatedTarget, aModifiersList);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  WheelEvent* wheelEvent = static_cast<WheelEvent*>(mEvent);
+  WidgetWheelEvent* wheelEvent = static_cast<WidgetWheelEvent*>(mEvent);
   wheelEvent->deltaX = aDeltaX;
   wheelEvent->deltaY = aDeltaY;
   wheelEvent->deltaZ = aDeltaZ;
   wheelEvent->deltaMode = aDeltaMode;
 
   return NS_OK;
 }
 
@@ -158,26 +158,26 @@ DOMWheelEvent::Constructor(const GlobalO
                   modifierList);
   aRv = e->InitWheelEvent(aType, aParam.mBubbles, aParam.mCancelable,
                           aParam.mView, aParam.mDetail,
                           aParam.mScreenX, aParam.mScreenY,
                           aParam.mClientX, aParam.mClientY,
                           aParam.mButton, aParam.mRelatedTarget,
                           modifierList, aParam.mDeltaX,
                           aParam.mDeltaY, aParam.mDeltaZ, aParam.mDeltaMode);
-  static_cast<WheelEvent*>(e->mEvent)->buttons = aParam.mButtons;
+  static_cast<WidgetWheelEvent*>(e->mEvent)->buttons = aParam.mButtons;
   e->SetTrusted(trusted);
   return e.forget();
 }
 
 } // namespace dom
 } // namespace mozilla
 
 using namespace mozilla;
 
 nsresult NS_NewDOMWheelEvent(nsIDOMEvent** aInstancePtrResult,
                              mozilla::dom::EventTarget* aOwner,
                              nsPresContext* aPresContext,
-                             WheelEvent *aEvent)
+                             WidgetWheelEvent* aEvent)
 {
   dom::DOMWheelEvent* it = new dom::DOMWheelEvent(aOwner, aPresContext, aEvent);
   return CallQueryInterface(it, aInstancePtrResult);
 }
--- a/content/events/src/DOMWheelEvent.h
+++ b/content/events/src/DOMWheelEvent.h
@@ -16,17 +16,17 @@ namespace mozilla {
 namespace dom {
 
 class DOMWheelEvent : public nsDOMMouseEvent,
                       public nsIDOMWheelEvent
 {
 public:
   DOMWheelEvent(mozilla::dom::EventTarget* aOwner,
                 nsPresContext* aPresContext,
-                WheelEvent* aWheelEvent);
+                WidgetWheelEvent* aWheelEvent);
   virtual ~DOMWheelEvent();
 
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIDOMWheelEvent Interface
   NS_DECL_NSIDOMWHEELEVENT
   
   // Forward to base class
@@ -41,31 +41,31 @@ public:
   virtual JSObject* WrapObject(JSContext* aCx,
                                JS::Handle<JSObject*> aScope) MOZ_OVERRIDE
   {
     return mozilla::dom::WheelEventBinding::Wrap(aCx, aScope, this);
   }
 
   double DeltaX()
   {
-    return static_cast<WheelEvent*>(mEvent)->deltaX;
+    return static_cast<WidgetWheelEvent*>(mEvent)->deltaX;
   }
 
   double DeltaY()
   {
-    return static_cast<WheelEvent*>(mEvent)->deltaY;
+    return static_cast<WidgetWheelEvent*>(mEvent)->deltaY;
   }
 
   double DeltaZ()
   {
-    return static_cast<WheelEvent*>(mEvent)->deltaZ;
+    return static_cast<WidgetWheelEvent*>(mEvent)->deltaZ;
   }
 
   uint32_t DeltaMode()
   {
-    return static_cast<WheelEvent*>(mEvent)->deltaMode;
+    return static_cast<WidgetWheelEvent*>(mEvent)->deltaMode;
   }
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_DOMWheelEvent_h__
--- a/content/events/src/nsDOMEvent.cpp
+++ b/content/events/src/nsDOMEvent.cpp
@@ -610,18 +610,18 @@ nsDOMEvent::DuplicatePrivateData()
       WidgetMouseScrollEvent* mouseScrollEvent =
         new WidgetMouseScrollEvent(false, msg, nullptr);
       mouseScrollEvent->AssignMouseScrollEventData(*oldMouseScrollEvent, true);
       newEvent = mouseScrollEvent;
       break;
     }
     case NS_WHEEL_EVENT:
     {
-      WheelEvent* oldWheelEvent = static_cast<WheelEvent*>(mEvent);
-      WheelEvent* wheelEvent = new WheelEvent(false, msg, nullptr);
+      WidgetWheelEvent* oldWheelEvent = static_cast<WidgetWheelEvent*>(mEvent);
+      WidgetWheelEvent* wheelEvent = new WidgetWheelEvent(false, msg, nullptr);
       wheelEvent->AssignWheelEventData(*oldWheelEvent, true);
       newEvent = wheelEvent;
       break;
     }
     case NS_SCROLLPORT_EVENT:
     {
       InternalScrollPortEvent* oldScrollPortEvent =
         static_cast<InternalScrollPortEvent*>(mEvent);
--- a/content/events/src/nsEventDispatcher.cpp
+++ b/content/events/src/nsEventDispatcher.cpp
@@ -714,17 +714,17 @@ nsEventDispatcher::CreateEvent(mozilla::
     case NS_FOCUS_EVENT:
       return NS_NewDOMFocusEvent(aDOMEvent, aOwner, aPresContext,
                                  static_cast<InternalFocusEvent*>(aEvent));
     case NS_MOUSE_SCROLL_EVENT:
       return NS_NewDOMMouseScrollEvent(aDOMEvent, aOwner, aPresContext,
                                        static_cast<WidgetInputEvent*>(aEvent));
     case NS_WHEEL_EVENT:
       return NS_NewDOMWheelEvent(aDOMEvent, aOwner, aPresContext,
-                                 static_cast<WheelEvent*>(aEvent));
+                                 static_cast<WidgetWheelEvent*>(aEvent));
     case NS_DRAG_EVENT:
       return NS_NewDOMDragEvent(aDOMEvent, aOwner, aPresContext,
                                 static_cast<WidgetDragEvent*>(aEvent));
     case NS_TEXT_EVENT:
       return NS_NewDOMTextEvent(aDOMEvent, aOwner, aPresContext,
                                 static_cast<WidgetTextEvent*>(aEvent));
     case NS_CLIPBOARD_EVENT:
       return NS_NewDOMClipboardEvent(aDOMEvent, aOwner, aPresContext,
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -255,34 +255,34 @@ struct DeltaValues
 {
   DeltaValues() : deltaX(0.0), deltaY(0.0) {}
 
   DeltaValues(double aDeltaX, double aDeltaY) :
     deltaX(aDeltaX), deltaY(aDeltaY)
   {
   }
 
-  explicit DeltaValues(WheelEvent* aEvent) :
+  explicit DeltaValues(WidgetWheelEvent* aEvent) :
     deltaX(aEvent->deltaX), deltaY(aEvent->deltaY)
   {
   }
 
   double deltaX;
   double deltaY;
 };
 
 /******************************************************************/
 /* nsScrollbarsForWheel                                           */
 /******************************************************************/
 
 class nsScrollbarsForWheel {
 public:
   static void PrepareToScrollText(nsEventStateManager* aESM,
                                   nsIFrame* aTargetFrame,
-                                  WheelEvent* aEvent);
+                                  WidgetWheelEvent* aEvent);
   static void SetActiveScrollTarget(nsIScrollableFrame* aScrollTarget);
   // Hide all scrollbars (both mActiveOwner's and mActivatedScrollTargets')
   static void MayInactivate();
   static void Inactivate();
   static bool IsActive();
   static void OwnWheelTransaction(bool aOwn);
 
 protected:
@@ -296,17 +296,17 @@ protected:
 
   /**
    * These two methods are called upon NS_WHEEL_START/NS_WHEEL_STOP events
    * to show/hide the right scrollbars.
    */
   static void TemporarilyActivateAllPossibleScrollTargets(
                                   nsEventStateManager* aESM,
                                   nsIFrame* aTargetFrame,
-                                  WheelEvent* aEvent);
+                                  WidgetWheelEvent* aEvent);
   static void DeactivateAllTemporarilyActivatedScrollTargets();
 };
 
 const DeltaValues nsScrollbarsForWheel::directions[kNumberOfTargets] = {
   DeltaValues(-1, 0), DeltaValues(+1, 0), DeltaValues(0, -1), DeltaValues(0, +1)
 };
 nsWeakFrame nsScrollbarsForWheel::sActiveOwner = nullptr;
 nsWeakFrame nsScrollbarsForWheel::sActivatedScrollTargets[kNumberOfTargets] = {
@@ -318,43 +318,43 @@ bool nsScrollbarsForWheel::sOwnWheelTran
 /******************************************************************/
 /* nsMouseWheelTransaction                                        */
 /******************************************************************/
 
 class nsMouseWheelTransaction {
 public:
   static nsIFrame* GetTargetFrame() { return sTargetFrame; }
   static void BeginTransaction(nsIFrame* aTargetFrame,
-                               WheelEvent* aEvent);
+                               WidgetWheelEvent* aEvent);
   // Be careful, UpdateTransaction may fire a DOM event, therefore, the target
   // frame might be destroyed in the event handler.
-  static bool UpdateTransaction(WheelEvent* aEvent);
+  static bool UpdateTransaction(WidgetWheelEvent* aEvent);
   static void MayEndTransaction();
   static void EndTransaction();
   static void OnEvent(WidgetEvent* aEvent);
   static void Shutdown();
   static uint32_t GetTimeoutTime();
 
   static void OwnScrollbars(bool aOwn);
 
-  static DeltaValues AccelerateWheelDelta(WheelEvent* aEvent,
+  static DeltaValues AccelerateWheelDelta(WidgetWheelEvent* aEvent,
                                           bool aAllowScrollSpeedOverride);
 
   enum {
     kScrollSeriesTimeout = 80
   };
 protected:
   static nsIntPoint GetScreenPoint(WidgetGUIEvent* aEvent);
   static void OnFailToScrollTarget();
   static void OnTimeout(nsITimer *aTimer, void *aClosure);
   static void SetTimeout();
   static uint32_t GetIgnoreMoveDelayTime();
   static int32_t GetAccelerationStart();
   static int32_t GetAccelerationFactor();
-  static DeltaValues OverrideSystemScrollSpeed(WheelEvent* aEvent);
+  static DeltaValues OverrideSystemScrollSpeed(WidgetWheelEvent* aEvent);
   static double ComputeAcceleratedWheelDelta(double aDelta, int32_t aFactor);
   static bool OutOfTime(uint32_t aBaseTime, uint32_t aThreshold);
 
   static nsWeakFrame sTargetFrame;
   static uint32_t    sTime;        // in milliseconds
   static uint32_t    sMouseMoved;  // in milliseconds
   static nsITimer*   sTimer;
   static int32_t     sScrollSeriesCounter;
@@ -402,32 +402,32 @@ nsMouseWheelTransaction::OutOfTime(uint3
 void
 nsMouseWheelTransaction::OwnScrollbars(bool aOwn)
 {
   sOwnScrollbars = aOwn;
 }
 
 void
 nsMouseWheelTransaction::BeginTransaction(nsIFrame* aTargetFrame,
-                                          WheelEvent* aEvent)
+                                          WidgetWheelEvent* aEvent)
 {
   NS_ASSERTION(!sTargetFrame, "previous transaction is not finished!");
   MOZ_ASSERT(aEvent->message == NS_WHEEL_WHEEL,
              "Transaction must be started with a wheel event");
   nsScrollbarsForWheel::OwnWheelTransaction(false);
   sTargetFrame = aTargetFrame;
   sScrollSeriesCounter = 0;
   if (!UpdateTransaction(aEvent)) {
     NS_ERROR("BeginTransaction is called even cannot scroll the frame");
     EndTransaction();
   }
 }
 
 bool
-nsMouseWheelTransaction::UpdateTransaction(WheelEvent* aEvent)
+nsMouseWheelTransaction::UpdateTransaction(WidgetWheelEvent* aEvent)
 {
   nsIScrollableFrame* sf = GetTargetFrame()->GetScrollTargetFrame();
   NS_ENSURE_TRUE(sf, false);
 
   if (!CanScrollOn(sf, aEvent->deltaX, aEvent->deltaY)) {
     OnFailToScrollTarget();
     // We should not modify the transaction state when the view will not be
     // scrolled actually.
@@ -489,28 +489,28 @@ nsMouseWheelTransaction::OnEvent(WidgetE
   }
 
   switch (aEvent->message) {
     case NS_WHEEL_WHEEL:
       if (sMouseMoved != 0 &&
           OutOfTime(sMouseMoved, GetIgnoreMoveDelayTime())) {
         // Terminate the current mousewheel transaction if the mouse moved more
         // than ignoremovedelay milliseconds ago
-        MayEndTransaction();
+        EndTransaction();
       }
       return;
     case NS_MOUSE_MOVE:
     case NS_DRAGDROP_OVER:
       if (IsMouseEventReal(aEvent)) {
         // If the cursor is moving to be outside the frame,
         // terminate the scrollwheel transaction.
         nsIntPoint pt = GetScreenPoint(static_cast<WidgetGUIEvent*>(aEvent));
         nsIntRect r = sTargetFrame->GetScreenRectExternal();
         if (!r.Contains(pt)) {
-          MayEndTransaction();
+          EndTransaction();
           return;
         }
 
         // If the cursor is moving inside the frame, and it is less than
         // ignoremovedelay milliseconds since the last scroll operation, ignore
         // the mouse move; otherwise, record the current mouse move time to be
         // checked later
         if (OutOfTime(sTime, GetIgnoreMoveDelayTime())) {
@@ -618,17 +618,17 @@ nsMouseWheelTransaction::GetTimeoutTime(
 
 uint32_t
 nsMouseWheelTransaction::GetIgnoreMoveDelayTime()
 {
   return Preferences::GetUint("mousewheel.transaction.ignoremovedelay", 100);
 }
 
 DeltaValues
-nsMouseWheelTransaction::AccelerateWheelDelta(WheelEvent* aEvent,
+nsMouseWheelTransaction::AccelerateWheelDelta(WidgetWheelEvent* aEvent,
                                               bool aAllowScrollSpeedOverride)
 {
   DeltaValues result(aEvent);
 
   // Don't accelerate the delta values if the event isn't line scrolling.
   if (aEvent->deltaMode != nsIDOMWheelEvent::DOM_DELTA_LINE) {
     return result;
   }
@@ -669,17 +669,17 @@ nsMouseWheelTransaction::GetAcceleration
 
 int32_t
 nsMouseWheelTransaction::GetAccelerationFactor()
 {
   return Preferences::GetInt("mousewheel.acceleration.factor", -1);
 }
 
 DeltaValues
-nsMouseWheelTransaction::OverrideSystemScrollSpeed(WheelEvent* aEvent)
+nsMouseWheelTransaction::OverrideSystemScrollSpeed(WidgetWheelEvent* aEvent)
 {
   MOZ_ASSERT(sTargetFrame, "We don't have mouse scrolling transaction");
   MOZ_ASSERT(aEvent->deltaMode == nsIDOMWheelEvent::DOM_DELTA_LINE);
 
   // If the event doesn't scroll to both X and Y, we don't need to do anything
   // here.
   if (!aEvent->deltaX && !aEvent->deltaY) {
     return DeltaValues(aEvent);
@@ -708,17 +708,17 @@ nsMouseWheelTransaction::OverrideSystemS
 /******************************************************************/
 /* nsScrollbarsForWheel                                           */
 /******************************************************************/
 
 void
 nsScrollbarsForWheel::PrepareToScrollText(
                                   nsEventStateManager* aESM,
                                   nsIFrame* aTargetFrame,
-                                  WheelEvent* aEvent)
+                                  WidgetWheelEvent* aEvent)
 {
   if (aEvent->message == NS_WHEEL_START) {
     nsMouseWheelTransaction::OwnScrollbars(false);
     if (!IsActive()) {
       TemporarilyActivateAllPossibleScrollTargets(aESM, aTargetFrame, aEvent);
       sHadWheelStart = true;
     }
   } else {
@@ -786,17 +786,17 @@ nsScrollbarsForWheel::OwnWheelTransactio
 {
   sOwnWheelTransaction = aOwn;
 }
 
 void
 nsScrollbarsForWheel::TemporarilyActivateAllPossibleScrollTargets(
                                                nsEventStateManager* aESM,
                                                nsIFrame* aTargetFrame,
-                                               WheelEvent* aEvent)
+                                               WidgetWheelEvent* aEvent)
 {
   for (size_t i = 0; i < kNumberOfTargets; i++) {
     const DeltaValues *dir = &directions[i];
     nsWeakFrame* scrollTarget = &sActivatedScrollTargets[i];
     MOZ_ASSERT(!*scrollTarget, "scroll target still temporarily activated!");
     nsIScrollableFrame* target =
       aESM->ComputeScrollTarget(aTargetFrame, dir->deltaX, dir->deltaY, aEvent, 
                                 nsEventStateManager::COMPUTE_DEFAULT_ACTION_TARGET);
@@ -1188,17 +1188,17 @@ nsEventStateManager::PreHandleEvent(nsPr
       if (content) {
         mCurrentTargetContent = content;
       }
 
       if (aEvent->message != NS_WHEEL_WHEEL) {
         break;
       }
 
-      WheelEvent* wheelEvent = static_cast<WheelEvent*>(aEvent);
+      WidgetWheelEvent* wheelEvent = static_cast<WidgetWheelEvent*>(aEvent);
       WheelPrefs::GetInstance()->ApplyUserPrefsToDelta(wheelEvent);
 
       // If we won't dispatch a DOM event for this event, nothing to do anymore.
       if (!wheelEvent->IsAllowedToDispatchDOMEvent()) {
         break;
       }
 
       // Init lineOrPageDelta values for line scroll events for some devices
@@ -1608,17 +1608,17 @@ nsEventStateManager::DispatchCrossProces
     WidgetMouseEvent* mouseEvent = static_cast<WidgetMouseEvent*>(aEvent);
     return remote->SendRealMouseEvent(*mouseEvent);
   }
   case NS_KEY_EVENT: {
     WidgetKeyboardEvent* keyEvent = static_cast<WidgetKeyboardEvent*>(aEvent);
     return remote->SendRealKeyEvent(*keyEvent);
   }
   case NS_WHEEL_EVENT: {
-    WheelEvent* wheelEvent = static_cast<WheelEvent*>(aEvent);
+    WidgetWheelEvent* wheelEvent = static_cast<WidgetWheelEvent*>(aEvent);
     return remote->SendMouseWheelEvent(*wheelEvent);
   }
   case NS_TOUCH_EVENT: {
     // Let the child process synthesize a mouse event if needed, and
     // ensure we don't synthesize one in this process.
     *aStatus = nsEventStatus_eConsumeNoDefault;
     WidgetTouchEvent* touchEvent = static_cast<WidgetTouchEvent*>(aEvent);
     return remote->SendRealTouchEvent(*touchEvent);
@@ -2550,17 +2550,17 @@ GetParentFrameToScroll(nsIFrame* aFrame)
       nsLayoutUtils::IsReallyFixedPos(aFrame))
     return aFrame->PresContext()->GetPresShell()->GetRootScrollFrame();
 
   return aFrame->GetParent();
 }
 
 void
 nsEventStateManager::DispatchLegacyMouseScrollEvents(nsIFrame* aTargetFrame,
-                                                     WheelEvent* aEvent,
+                                                     WidgetWheelEvent* aEvent,
                                                      nsEventStatus* aStatus)
 {
   MOZ_ASSERT(aEvent);
   MOZ_ASSERT(aStatus);
 
   if (!aTargetFrame || *aStatus == nsEventStatus_eConsumeNoDefault) {
     return;
   }
@@ -2675,17 +2675,17 @@ nsEventStateManager::DispatchLegacyMouse
   if (statusY == nsEventStatus_eConsumeDoDefault ||
       statusX == nsEventStatus_eConsumeDoDefault) {
     *aStatus = nsEventStatus_eConsumeDoDefault;
   }
 }
 
 void
 nsEventStateManager::SendLineScrollEvent(nsIFrame* aTargetFrame,
-                                         WheelEvent* aEvent,
+                                         WidgetWheelEvent* aEvent,
                                          nsEventStatus* aStatus,
                                          int32_t aDelta,
                                          DeltaDirection aDeltaDirection)
 {
   nsCOMPtr<nsIContent> targetContent = aTargetFrame->GetContent();
   if (!targetContent)
     targetContent = GetFocusedContent();
   if (!targetContent)
@@ -2710,17 +2710,17 @@ nsEventStateManager::SendLineScrollEvent
   event.inputSource = aEvent->inputSource;
 
   nsEventDispatcher::Dispatch(targetContent, aTargetFrame->PresContext(),
                               &event, nullptr, aStatus);
 }
 
 void
 nsEventStateManager::SendPixelScrollEvent(nsIFrame* aTargetFrame,
-                                          WheelEvent* aEvent,
+                                          WidgetWheelEvent* aEvent,
                                           nsEventStatus* aStatus,
                                           int32_t aPixelDelta,
                                           DeltaDirection aDeltaDirection)
 {
   nsCOMPtr<nsIContent> targetContent = aTargetFrame->GetContent();
   if (!targetContent) {
     targetContent = GetFocusedContent();
     if (!targetContent)
@@ -2746,31 +2746,31 @@ nsEventStateManager::SendPixelScrollEven
   event.inputSource = aEvent->inputSource;
 
   nsEventDispatcher::Dispatch(targetContent, aTargetFrame->PresContext(),
                               &event, nullptr, aStatus);
 }
 
 nsIScrollableFrame*
 nsEventStateManager::ComputeScrollTarget(nsIFrame* aTargetFrame,
-                                         WheelEvent* aEvent,
+                                         WidgetWheelEvent* aEvent,
                                          ComputeScrollTargetOptions aOptions)
 {
   return ComputeScrollTarget(aTargetFrame, aEvent->deltaX, aEvent->deltaY,
                              aEvent, aOptions);
 }
 
 // Overload ComputeScrollTarget method to allow passing "test" dx and dy when looking
 // for which scrollbarowners to activate when two finger down on trackpad
 // and before any actual motion
 nsIScrollableFrame*
 nsEventStateManager::ComputeScrollTarget(nsIFrame* aTargetFrame,
                                          double aDirectionX,
                                          double aDirectionY,
-                                         WheelEvent* aEvent,
+                                         WidgetWheelEvent* aEvent,
                                          ComputeScrollTargetOptions aOptions)
 {
   if (aOptions & PREFER_MOUSE_WHEEL_TRANSACTION) {
     // If the user recently scrolled with the mousewheel, then they probably
     // want to scroll the same view as before instead of the view under the
     // cursor.  nsMouseWheelTransaction tracks the frame currently being
     // scrolled with the mousewheel. We consider the transaction ended when the
     // mouse moves more than "mousewheel.transaction.ignoremovedelay"
@@ -2847,17 +2847,17 @@ nsEventStateManager::ComputeScrollTarget
       aTargetFrame->PresContext()->FrameManager()->GetRootFrame());
   aOptions =
     static_cast<ComputeScrollTargetOptions>(aOptions & ~START_FROM_PARENT);
   return newFrame ? ComputeScrollTarget(newFrame, aEvent, aOptions) : nullptr;
 }
 
 nsSize
 nsEventStateManager::GetScrollAmount(nsPresContext* aPresContext,
-                                     WheelEvent* aEvent,
+                                     WidgetWheelEvent* aEvent,
                                      nsIScrollableFrame* aScrollableFrame)
 {
   MOZ_ASSERT(aPresContext);
   MOZ_ASSERT(aEvent);
 
   bool isPage = (aEvent->deltaMode == nsIDOMWheelEvent::DOM_DELTA_PAGE);
   if (aScrollableFrame) {
     return isPage ? aScrollableFrame->GetPageScrollAmount() :
@@ -2878,17 +2878,17 @@ nsEventStateManager::GetScrollAmount(nsP
   nsLayoutUtils::GetFontMetricsForFrame(rootFrame, getter_AddRefs(fm),
     nsLayoutUtils::FontSizeInflationFor(rootFrame));
   NS_ENSURE_TRUE(fm, nsSize(0, 0));
   return nsSize(fm->AveCharWidth(), fm->MaxHeight());
 }
 
 void
 nsEventStateManager::DoScrollText(nsIScrollableFrame* aScrollableFrame,
-                                  WheelEvent* aEvent)
+                                  WidgetWheelEvent* aEvent)
 {
   MOZ_ASSERT(aScrollableFrame);
   MOZ_ASSERT(aEvent);
 
   nsIFrame* scrollFrame = do_QueryFrame(aScrollableFrame);
   MOZ_ASSERT(scrollFrame);
   nsWeakFrame scrollFrameWeak(scrollFrame);
 
@@ -2965,30 +2965,30 @@ nsEventStateManager::DoScrollText(nsIScr
                                             -devPixelPageSize.height;
   }
 
   bool isDeltaModePixel =
     (aEvent->deltaMode == nsIDOMWheelEvent::DOM_DELTA_PIXEL);
 
   nsIScrollableFrame::ScrollMode mode;
   switch (aEvent->scrollType) {
-    case WheelEvent::SCROLL_DEFAULT:
+    case WidgetWheelEvent::SCROLL_DEFAULT:
       if (isDeltaModePixel) {
         mode = nsIScrollableFrame::NORMAL;
       } else {
         mode = nsIScrollableFrame::SMOOTH;
       }
       break;
-    case WheelEvent::SCROLL_SYNCHRONOUSLY:
+    case WidgetWheelEvent::SCROLL_SYNCHRONOUSLY:
       mode = nsIScrollableFrame::INSTANT;
       break;
-    case WheelEvent::SCROLL_ASYNCHRONOUSELY:
+    case WidgetWheelEvent::SCROLL_ASYNCHRONOUSELY:
       mode = nsIScrollableFrame::NORMAL;
       break;
-    case WheelEvent::SCROLL_SMOOTHLY:
+    case WidgetWheelEvent::SCROLL_SMOOTHLY:
       mode = nsIScrollableFrame::SMOOTH;
       break;
     default:
       MOZ_CRASH("Invalid scrollType value comes");
   }
 
   nsIntPoint overflow;
   aScrollableFrame->ScrollBy(actualDevPixelScrollAmount,
@@ -3402,17 +3402,17 @@ nsEventStateManager::PostHandleEvent(nsP
     {
       MOZ_ASSERT(aEvent->mFlags.mIsTrusted);
 
       if (*aStatus == nsEventStatus_eConsumeNoDefault) {
         nsScrollbarsForWheel::Inactivate();
         break;
       }
 
-      WheelEvent* wheelEvent = static_cast<WheelEvent*>(aEvent);
+      WidgetWheelEvent* wheelEvent = static_cast<WidgetWheelEvent*>(aEvent);
       switch (WheelPrefs::GetInstance()->ComputeActionFor(wheelEvent)) {
         case WheelPrefs::ACTION_SCROLL: {
           // For scrolling of default action, we should honor the mouse wheel
           // transaction.
 
           nsScrollbarsForWheel::PrepareToScrollText(this, aTargetFrame, wheelEvent);
 
           if (aEvent->message != NS_WHEEL_WHEEL ||
@@ -3421,17 +3421,23 @@ nsEventStateManager::PostHandleEvent(nsP
           }
 
           nsIScrollableFrame* scrollTarget =
             ComputeScrollTarget(aTargetFrame, wheelEvent,
                                 COMPUTE_DEFAULT_ACTION_TARGET);
 
           nsScrollbarsForWheel::SetActiveScrollTarget(scrollTarget);
 
-          if (!scrollTarget) {
+          nsIFrame* rootScrollFrame = !aTargetFrame ? nullptr :
+            aTargetFrame->PresContext()->PresShell()->GetRootScrollFrame();
+          nsIScrollableFrame* rootScrollableFrame = nullptr;
+          if (rootScrollFrame) {
+            rootScrollableFrame = do_QueryFrame(rootScrollFrame);
+          }
+          if (!scrollTarget || scrollTarget == rootScrollableFrame) {
             wheelEvent->mViewPortIsOverscrolled = true;
           }
           wheelEvent->overflowDeltaX = wheelEvent->deltaX;
           wheelEvent->overflowDeltaY = wheelEvent->deltaY;
           WheelPrefs::GetInstance()->
             CancelApplyingUserPrefsFromOverflowDelta(wheelEvent);
           if (scrollTarget) {
             DoScrollText(scrollTarget, wheelEvent);
@@ -5348,17 +5354,17 @@ nsEventStateManager::ClearGlobalActiveCo
 /******************************************************************/
 /* nsEventStateManager::DeltaAccumulator                          */
 /******************************************************************/
 
 void
 nsEventStateManager::DeltaAccumulator::InitLineOrPageDelta(
                                          nsIFrame* aTargetFrame,
                                          nsEventStateManager* aESM,
-                                         WheelEvent* aEvent)
+                                         WidgetWheelEvent* aEvent)
 {
   MOZ_ASSERT(aESM);
   MOZ_ASSERT(aEvent);
 
   // Reset if the previous wheel event is too old.
   if (!mLastTime.IsNull()) {
     TimeDuration duration = TimeStamp::Now() - mLastTime;
     if (duration.ToMilliseconds() > nsMouseWheelTransaction::GetTimeoutTime()) {
@@ -5451,17 +5457,17 @@ nsEventStateManager::DeltaAccumulator::R
   mX = mY = 0.0;
   mPendingScrollAmountX = mPendingScrollAmountY = 0.0;
   mHandlingDeltaMode = UINT32_MAX;
   mHandlingPixelOnlyDevice = false;
 }
 
 nsIntPoint
 nsEventStateManager::DeltaAccumulator::ComputeScrollAmountForDefaultAction(
-                       WheelEvent* aEvent,
+                       WidgetWheelEvent* aEvent,
                        const nsIntSize& aScrollAmountInDevPixels)
 {
   MOZ_ASSERT(aEvent);
 
   // If the wheel event is line scroll and the delta value is computed from
   // system settings, allow to override the system speed.
   bool allowScrollSpeedOverride =
     (!aEvent->customizedByUserPrefs &&
@@ -5535,17 +5541,17 @@ nsEventStateManager::WheelPrefs::~WheelP
 void
 nsEventStateManager::WheelPrefs::Reset()
 {
   memset(mInit, 0, sizeof(mInit));
 
 }
 
 nsEventStateManager::WheelPrefs::Index
-nsEventStateManager::WheelPrefs::GetIndexFor(WheelEvent* aEvent)
+nsEventStateManager::WheelPrefs::GetIndexFor(WidgetWheelEvent* aEvent)
 {
   if (!aEvent) {
     return INDEX_DEFAULT;
   }
 
   Modifiers modifiers =
     (aEvent->modifiers & (MODIFIER_ALT |
                           MODIFIER_CONTROL |
@@ -5646,17 +5652,17 @@ nsEventStateManager::WheelPrefs::Init(
     actionOverrideX = -1;
   }
   mOverriddenActionsX[aIndex] = (actionOverrideX == -1)
                               ? static_cast<Action>(action)
                               : static_cast<Action>(actionOverrideX);
 }
 
 void
-nsEventStateManager::WheelPrefs::ApplyUserPrefsToDelta(WheelEvent* aEvent)
+nsEventStateManager::WheelPrefs::ApplyUserPrefsToDelta(WidgetWheelEvent* aEvent)
 {
   Index index = GetIndexFor(aEvent);
   Init(index);
 
   aEvent->deltaX *= mMultiplierX[index];
   aEvent->deltaY *= mMultiplierY[index];
   aEvent->deltaZ *= mMultiplierZ[index];
 
@@ -5673,17 +5679,17 @@ nsEventStateManager::WheelPrefs::ApplyUs
 
   aEvent->customizedByUserPrefs =
     ((mMultiplierX[index] != 1.0) || (mMultiplierY[index] != 1.0) ||
      (mMultiplierZ[index] != 1.0));
 }
 
 void
 nsEventStateManager::WheelPrefs::CancelApplyingUserPrefsFromOverflowDelta(
-                                                   WheelEvent* aEvent)
+                                                   WidgetWheelEvent* aEvent)
 {
   Index index = GetIndexFor(aEvent);
   Init(index);
 
   // XXX If the multiplier pref value is negative, the scroll direction was
   //     changed and caused to scroll different direction.  In such case,
   //     this method reverts the sign of overflowDelta.  Does it make widget
   //     happy?  Although, widget can know the pref applied delta values by
@@ -5693,17 +5699,17 @@ nsEventStateManager::WheelPrefs::CancelA
     aEvent->overflowDeltaX /= mMultiplierX[index];
   }
   if (mMultiplierY[index]) {
     aEvent->overflowDeltaY /= mMultiplierY[index];
   }
 }
 
 nsEventStateManager::WheelPrefs::Action
-nsEventStateManager::WheelPrefs::ComputeActionFor(WheelEvent* aEvent)
+nsEventStateManager::WheelPrefs::ComputeActionFor(WidgetWheelEvent* aEvent)
 {
   Index index = GetIndexFor(aEvent);
   Init(index);
 
   bool deltaXPreferred =
     (Abs(aEvent->deltaX) > Abs(aEvent->deltaY) &&
      Abs(aEvent->deltaX) > Abs(aEvent->deltaZ));
   Action* actions = deltaXPreferred ? mOverriddenActionsX : mActions;
@@ -5719,38 +5725,38 @@ nsEventStateManager::WheelPrefs::Compute
                                                        ACTION_NONE;
   }
 
   return actions[index];
 }
 
 bool
 nsEventStateManager::WheelPrefs::NeedToComputeLineOrPageDelta(
-                                   WheelEvent* aEvent)
+                                   WidgetWheelEvent* aEvent)
 {
   Index index = GetIndexFor(aEvent);
   Init(index);
 
   return (mMultiplierX[index] != 1.0 && mMultiplierX[index] != -1.0) ||
          (mMultiplierY[index] != 1.0 && mMultiplierY[index] != -1.0);
 }
 
 bool
 nsEventStateManager::WheelPrefs::IsOverOnePageScrollAllowedX(
-                                   WheelEvent* aEvent)
+                                   WidgetWheelEvent* aEvent)
 {
   Index index = GetIndexFor(aEvent);
   Init(index);
   return Abs(mMultiplierX[index]) >=
            MIN_MULTIPLIER_VALUE_ALLOWING_OVER_ONE_PAGE_SCROLL;
 }
 
 bool
 nsEventStateManager::WheelPrefs::IsOverOnePageScrollAllowedY(
-                                   WheelEvent* aEvent)
+                                   WidgetWheelEvent* aEvent)
 {
   Index index = GetIndexFor(aEvent);
   Init(index);
   return Abs(mMultiplierY[index]) >=
            MIN_MULTIPLIER_VALUE_ALLOWING_OVER_ONE_PAGE_SCROLL;
 }
 
 /******************************************************************/
--- a/content/events/src/nsEventStateManager.h
+++ b/content/events/src/nsEventStateManager.h
@@ -84,17 +84,17 @@ public:
                            nsIFrame* aTargetFrame,
                            nsEventStatus* aStatus);
 
   /**
    * DispatchLegacyMouseScrollEvents() dispatches NS_MOUSE_SCROLL event and
    * NS_MOUSE_PIXEL_SCROLL event for compatiblity with old Gecko.
    */
   void DispatchLegacyMouseScrollEvents(nsIFrame* aTargetFrame,
-                                       mozilla::WheelEvent* aEvent,
+                                       mozilla::WidgetWheelEvent* aEvent,
                                        nsEventStatus* aStatus);
 
   void NotifyDestroyPresContext(nsPresContext* aPresContext);
   void SetPresContext(nsPresContext* aPresContext);
   void ClearFrameRefs(nsIFrame* aFrame);
 
   nsIFrame* GetEventTarget();
   already_AddRefed<nsIContent> GetEventTargetContent(
@@ -363,51 +363,51 @@ protected:
   public:
     static WheelPrefs* GetInstance();
     static void Shutdown();
 
     /**
      * ApplyUserPrefsToDelta() overrides the wheel event's delta values with
      * user prefs.
      */
-    void ApplyUserPrefsToDelta(mozilla::WheelEvent* aEvent);
+    void ApplyUserPrefsToDelta(mozilla::WidgetWheelEvent* aEvent);
 
     /**
      * If ApplyUserPrefsToDelta() changed the delta values with customized
      * prefs, the overflowDelta values would be inflated.
      * CancelApplyingUserPrefsFromOverflowDelta() cancels the inflation.
      */
     void CancelApplyingUserPrefsFromOverflowDelta(
-                                    mozilla::WheelEvent* aEvent);
+                                    mozilla::WidgetWheelEvent* aEvent);
 
     /**
      * Computes the default action for the aEvent with the prefs.
      */
     enum Action MOZ_ENUM_TYPE(uint8_t)
     {
       ACTION_NONE = 0,
       ACTION_SCROLL,
       ACTION_HISTORY,
       ACTION_ZOOM,
       ACTION_LAST = ACTION_ZOOM
     };
-    Action ComputeActionFor(mozilla::WheelEvent* aEvent);
+    Action ComputeActionFor(mozilla::WidgetWheelEvent* aEvent);
 
     /**
      * NeedToComputeLineOrPageDelta() returns if the aEvent needs to be
      * computed the lineOrPageDelta values.
      */
-    bool NeedToComputeLineOrPageDelta(mozilla::WheelEvent* aEvent);
+    bool NeedToComputeLineOrPageDelta(mozilla::WidgetWheelEvent* aEvent);
 
     /**
      * IsOverOnePageScrollAllowed*() checks whether wheel scroll amount should
      * be rounded down to the page width/height (false) or not (true).
      */
-    bool IsOverOnePageScrollAllowedX(mozilla::WheelEvent* aEvent);
-    bool IsOverOnePageScrollAllowedY(mozilla::WheelEvent* aEvent);
+    bool IsOverOnePageScrollAllowedX(mozilla::WidgetWheelEvent* aEvent);
+    bool IsOverOnePageScrollAllowedY(mozilla::WidgetWheelEvent* aEvent);
 
   private:
     WheelPrefs();
     ~WheelPrefs();
 
     static int OnPrefChanged(const char* aPrefName, void* aClosure);
 
     enum Index
@@ -424,17 +424,17 @@ protected:
     /**
      * GetIndexFor() returns the index of the members which should be used for
      * the aEvent.  When only one modifier key of MODIFIER_ALT,
      * MODIFIER_CONTROL, MODIFIER_META, MODIFIER_SHIFT or MODIFIER_OS is
      * pressed, returns the index for the modifier.  Otherwise, this return the
      * default index which is used at either no modifier key is pressed or
      * two or modifier keys are pressed.
      */
-    Index GetIndexFor(mozilla::WheelEvent* aEvent);
+    Index GetIndexFor(mozilla::WidgetWheelEvent* aEvent);
 
     /**
      * GetPrefNameBase() returns the base pref name for aEvent.
      * It's decided by GetModifierForPref() which modifier should be used for
      * the aEvent.
      *
      * @param aBasePrefName The result, must be "mousewheel.with_*." or
      *                      "mousewheel.default.".
@@ -477,46 +477,46 @@ protected:
   enum DeltaDirection
   {
     DELTA_DIRECTION_X = 0,
     DELTA_DIRECTION_Y
   };
 
   /**
    * SendLineScrollEvent() dispatches a DOMMouseScroll event for the
-   * WheelEvent.  This method shouldn't be called for non-trusted
+   * WidgetWheelEvent.  This method shouldn't be called for non-trusted
    * wheel event because it's not necessary for compatiblity.
    *
    * @param aTargetFrame        The event target of wheel event.
    * @param aEvent              The original Wheel event.
    * @param aStatus             The event status, must not be
    *                            nsEventStatus_eConsumeNoDefault.
    * @param aDelta              The delta value of the event.
    * @param aDeltaDirection     The X/Y direction of dispatching event.
    */
   void SendLineScrollEvent(nsIFrame* aTargetFrame,
-                           mozilla::WheelEvent* aEvent,
+                           mozilla::WidgetWheelEvent* aEvent,
                            nsEventStatus* aStatus,
                            int32_t aDelta,
                            DeltaDirection aDeltaDirection);
 
   /**
    * SendPixelScrollEvent() dispatches a MozMousePixelScroll event for the
-   * WheelEvent.  This method shouldn't be called for non-trusted
+   * WidgetWheelEvent.  This method shouldn't be called for non-trusted
    * wheel event because it's not necessary for compatiblity.
    *
    * @param aTargetFrame        The event target of wheel event.
    * @param aEvent              The original Wheel event.
    * @param aStatus             The event status, must not be
    *                            nsEventStatus_eConsumeNoDefault.
    * @param aPixelDelta         The delta value of the event.
    * @param aDeltaDirection     The X/Y direction of dispatching event.
    */
   void SendPixelScrollEvent(nsIFrame* aTargetFrame,
-                            mozilla::WheelEvent* aEvent,
+                            mozilla::WidgetWheelEvent* aEvent,
                             nsEventStatus* aStatus,
                             int32_t aPixelDelta,
                             DeltaDirection aDeltaDirection);
 
   /**
    * ComputeScrollTarget() returns the scrollable frame which should be
    * scrolled.
    *
@@ -550,46 +550,46 @@ protected:
     // Look for the nearest scrollable ancestor which can be scrollable with
     // aEvent.
     COMPUTE_SCROLLABLE_ANCESTOR_ALONG_X_AXIS     =
       (PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_X_AXIS | START_FROM_PARENT),
     COMPUTE_SCROLLABLE_ANCESTOR_ALONG_Y_AXIS     =
       (PREFER_ACTUAL_SCROLLABLE_TARGET_ALONG_Y_AXIS | START_FROM_PARENT)
   };
   nsIScrollableFrame* ComputeScrollTarget(nsIFrame* aTargetFrame,
-                                          mozilla::WheelEvent* aEvent,
+                                          mozilla::WidgetWheelEvent* aEvent,
                                           ComputeScrollTargetOptions aOptions);
 
   nsIScrollableFrame* ComputeScrollTarget(nsIFrame* aTargetFrame,
                                           double aDirectionX,
                                           double aDirectionY,
-                                          mozilla::WheelEvent* aEvent,
+                                          mozilla::WidgetWheelEvent* aEvent,
                                           ComputeScrollTargetOptions aOptions);
 
   /**
    * GetScrollAmount() returns the scroll amount in app uints of one line or
    * one page.  If the wheel event scrolls a page, returns the page width and
    * height.  Otherwise, returns line height for both its width and height.
    *
    * @param aScrollableFrame    A frame which will be scrolled by the event.
    *                            The result of ComputeScrollTarget() is
    *                            expected for this value.
    *                            This can be nullptr if there is no scrollable
    *                            frame.  Then, this method uses root frame's
    *                            line height or visible area's width and height.
    */
   nsSize GetScrollAmount(nsPresContext* aPresContext,
-                         mozilla::WheelEvent* aEvent,
+                         mozilla::WidgetWheelEvent* aEvent,
                          nsIScrollableFrame* aScrollableFrame);
 
   /**
    * DoScrollText() scrolls the scrollable frame for aEvent.
    */
   void DoScrollText(nsIScrollableFrame* aScrollableFrame,
-                    mozilla::WheelEvent* aEvent);
+                    mozilla::WidgetWheelEvent* aEvent);
 
   void DoScrollHistory(int32_t direction);
   void DoScrollZoom(nsIFrame *aTargetFrame, int32_t adjustment);
   nsresult GetMarkupDocumentViewer(nsIMarkupDocumentViewer** aMv);
   nsresult ChangeTextSize(int32_t change);
   nsresult ChangeFullZoom(int32_t change);
 
   /**
@@ -613,35 +613,35 @@ protected:
     {
       delete sInstance;
       sInstance = nullptr;
     }
 
     bool IsInTransaction() { return mHandlingDeltaMode != UINT32_MAX; }
 
     /**
-     * InitLineOrPageDelta() stores pixel delta values of WheelEvents which are
-     * caused if it's needed.  And if the accumulated delta becomes a
+     * InitLineOrPageDelta() stores pixel delta values of WidgetWheelEvents
+     * which are caused if it's needed.  And if the accumulated delta becomes a
      * line height, sets lineOrPageDeltaX and lineOrPageDeltaY automatically.
      */
     void InitLineOrPageDelta(nsIFrame* aTargetFrame,
                              nsEventStateManager* aESM,
-                             mozilla::WheelEvent* aEvent);
+                             mozilla::WidgetWheelEvent* aEvent);
 
     /**
      * Reset() resets all members.
      */
     void Reset();
 
     /**
      * ComputeScrollAmountForDefaultAction() computes the default action's
      * scroll amount in device pixels with mPendingScrollAmount*.
      */
     nsIntPoint ComputeScrollAmountForDefaultAction(
-                 mozilla::WheelEvent* aEvent,
+                 mozilla::WidgetWheelEvent* aEvent,
                  const nsIntSize& aScrollAmountInDevPixels);
 
   private:
     DeltaAccumulator() :
       mX(0.0), mY(0.0), mPendingScrollAmountX(0.0), mPendingScrollAmountY(0.0),
       mHandlingDeltaMode(UINT32_MAX), mHandlingPixelOnlyDevice(false)
     {
     }
--- a/content/events/src/nsIMEStateManager.cpp
+++ b/content/events/src/nsIMEStateManager.cpp
@@ -478,17 +478,17 @@ nsIMEStateManager::SetIMEState(const IME
       mozilla::dom::Element* formElement = control->GetFormElement();
       nsCOMPtr<nsIForm> form;
       if (control) {
         // is this a form and does it have a default submit element?
         if ((form = do_QueryInterface(formElement)) && form->GetDefaultSubmitElement()) {
           willSubmit = true;
         // is this an html form and does it only have a single text input element?
         } else if (formElement && formElement->Tag() == nsGkAtoms::form && formElement->IsHTML() &&
-                   static_cast<dom::HTMLFormElement*>(formElement)->HasSingleTextControl()) {
+                   !static_cast<dom::HTMLFormElement*>(formElement)->ImplicitSubmissionIsDisabled()) {
           willSubmit = true;
         }
       }
       context.mActionHint.Assign(willSubmit ? control->GetType() == NS_FORM_INPUT_SEARCH
                                                 ? NS_LITERAL_STRING("search")
                                                 : NS_LITERAL_STRING("go")
                                             : formElement
                                                 ? NS_LITERAL_STRING("next")
--- a/content/html/content/src/HTMLFormElement.cpp
+++ b/content/html/content/src/HTMLFormElement.cpp
@@ -1641,27 +1641,28 @@ HTMLFormElement::IsDefaultSubmitElement(
   nsIFormControl* defaultSubmit =
     CompareFormControlPosition(mFirstSubmitInElements,
                                mFirstSubmitNotInElements, this) < 0 ?
       mFirstSubmitInElements : mFirstSubmitNotInElements;
   return aControl == defaultSubmit;
 }
 
 bool
-HTMLFormElement::HasSingleTextControl() const
+HTMLFormElement::ImplicitSubmissionIsDisabled() const
 {
   // Input text controls are always in the elements list.
-  uint32_t numTextControlsFound = 0;
+  uint32_t numDisablingControlsFound = 0;
   uint32_t length = mControls->mElements.Length();
-  for (uint32_t i = 0; i < length && numTextControlsFound < 2; ++i) {
-    if (mControls->mElements[i]->IsSingleLineTextControl(false)) {
-      numTextControlsFound++;
+  for (uint32_t i = 0; i < length && numDisablingControlsFound < 2; ++i) {
+    if (mControls->mElements[i]->IsSingleLineTextControl(false) ||
+        mControls->mElements[i]->GetType() == NS_FORM_INPUT_NUMBER) {
+      numDisablingControlsFound++;
     }
   }
-  return numTextControlsFound == 1;
+  return numDisablingControlsFound > 1;
 }
 
 NS_IMETHODIMP
 HTMLFormElement::GetEncoding(nsAString& aEncoding)
 {
   return GetEnctype(aEncoding);
 }
  
--- a/content/html/content/src/HTMLFormElement.h
+++ b/content/html/content/src/HTMLFormElement.h
@@ -211,21 +211,22 @@ public:
    * We can't fold this method into AddImageElement() because when
    * AddImageElement() is called, the image attributes can change.
    * The name or id attributes of the image are used as a key into the table.
    */
   nsresult AddImageElementToTable(mozilla::dom::HTMLImageElement* aChild,
                                  const nsAString& aName);
 
    /**
-    * Return whether there is one and only one input text control.
+    * Returns true if implicit submission of this form is disabled. For more
+    * on implicit submission see:
     *
-    * @return Whether there is exactly one input text control.
+    * http://www.whatwg.org/specs/web-apps/current-work/multipage/association-of-controls-and-forms.html#implicit-submission
     */
-  bool HasSingleTextControl() const;
+  bool ImplicitSubmissionIsDisabled() const;
 
   /**
    * Check whether a given nsIFormControl is the default submit
    * element.  This is different from just comparing to
    * GetDefaultSubmitElement() in certain situations inside an update
    * when GetDefaultSubmitElement() might not be up to date.  aControl
    * is expected to not be null.
    */
--- a/content/html/content/src/HTMLInputElement.cpp
+++ b/content/html/content/src/HTMLInputElement.cpp
@@ -2890,17 +2890,17 @@ HTMLInputElement::MaybeSubmitForm(nsPres
     nsCOMPtr<nsIContent> submitContent = do_QueryInterface(submitControl);
     NS_ASSERTION(submitContent, "Form control not implementing nsIContent?!");
     // Fire the button's onclick handler and let the button handle
     // submitting the form.
     WidgetMouseEvent event(true, NS_MOUSE_CLICK, nullptr,
                            WidgetMouseEvent::eReal);
     nsEventStatus status = nsEventStatus_eIgnore;
     shell->HandleDOMEventWithTarget(submitContent, &event, &status);
-  } else if (mForm->HasSingleTextControl() &&
+  } else if (!mForm->ImplicitSubmissionIsDisabled() &&
              (mForm->HasAttr(kNameSpaceID_None, nsGkAtoms::novalidate) ||
               mForm->CheckValidFormSubmission())) {
     // TODO: removing this code and have the submit event sent by the form,
     // bug 592124.
     // If there's only one text control, just submit the form
     // Hold strong ref across the event
     nsRefPtr<mozilla::dom::HTMLFormElement> form = mForm;
     InternalFormEvent event(true, NS_FORM_SUBMIT);
@@ -3597,16 +3597,17 @@ HTMLInputElement::PostHandleEvent(nsEven
            * (c) if there is more than one text input and no submit buttons, do
            *     not submit, period.
            */
 
           if (aVisitor.mEvent->message == NS_KEY_PRESS &&
               (keyEvent->keyCode == NS_VK_RETURN ||
                keyEvent->keyCode == NS_VK_ENTER) &&
                (IsSingleLineTextControl(false, mType) ||
+                mType == NS_FORM_INPUT_NUMBER ||
                 IsExperimentalMobileType(mType))) {
             FireChangeEventIfNeeded();
             rv = MaybeSubmitForm(aVisitor.mPresContext);
             NS_ENSURE_SUCCESS(rv, rv);
           }
 
           if (aVisitor.mEvent->message == NS_KEY_PRESS &&
               mType == NS_FORM_INPUT_RANGE && !keyEvent->IsAlt() &&
--- a/content/html/document/src/MediaDocument.cpp
+++ b/content/html/document/src/MediaDocument.cpp
@@ -16,16 +16,17 @@
 #include "nsIMarkupDocumentViewer.h"
 #include "nsIDocShell.h"
 #include "nsCharsetSource.h" // kCharsetFrom* macro definition
 #include "nsNodeInfoManager.h"
 #include "nsContentUtils.h"
 #include "nsDocElementCreatedNotificationRunner.h"
 #include "mozilla/Services.h"
 #include "nsServiceManagerUtils.h"
+#include "nsIPrincipal.h"
 
 namespace mozilla {
 namespace dom {
 
 MediaDocumentStreamListener::MediaDocumentStreamListener(MediaDocument *aDocument)
 {
   mDocument = aDocument;
 }
@@ -145,55 +146,39 @@ MediaDocument::StartDocumentLoad(const c
 
   // We try to set the charset of the current document to that of the 
   // 'genuine' (as opposed to an intervening 'chrome') parent document 
   // that may be in a different window/tab. Even if we fail here,
   // we just return NS_OK because another attempt is made in 
   // |UpdateTitleAndCharset| and the worst thing possible is a mangled 
   // filename in the titlebar and the file picker.
 
-  // When this document is opened in the window/tab of the referring 
-  // document (by a simple link-clicking), |prevDocCharacterSet| contains 
-  // the charset of the referring document. On the other hand, if the
-  // document is opened in a new window, it is |defaultCharacterSet| of |muCV| 
-  // where the charset of our interest is stored. In case of openining 
-  // in a new tab, we get the charset from the docShell. Note that we 
+  // Note that we
   // exclude UTF-8 as 'invalid' because UTF-8 is likely to be the charset 
   // of a chrome document that has nothing to do with the actual content 
   // whose charset we want to know. Even if "the actual content" is indeed 
   // in UTF-8, we don't lose anything because the default empty value is 
   // considered synonymous with UTF-8. 
     
   nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(aContainer));
 
   // not being able to set the charset is not critical.
   NS_ENSURE_TRUE(docShell, NS_OK); 
 
   nsAutoCString charset;
+  int32_t source;
+  nsCOMPtr<nsIPrincipal> principal;
   // opening in a new tab
-  docShell->GetParentCharset(charset);
-
-  if (charset.IsEmpty() || charset.Equals("UTF-8")) {
-    nsCOMPtr<nsIContentViewer> cv;
-    docShell->GetContentViewer(getter_AddRefs(cv));
+  docShell->GetParentCharset(charset, &source, getter_AddRefs(principal));
 
-    // not being able to set the charset is not critical.
-    NS_ENSURE_TRUE(cv, NS_OK); 
-    nsCOMPtr<nsIMarkupDocumentViewer> muCV = do_QueryInterface(cv);
-    if (muCV) {
-      muCV->GetPrevDocCharacterSet(charset);   // opening in the same window/tab
-      if (charset.Equals("UTF-8") || charset.IsEmpty()) {
-        muCV->GetDefaultCharacterSet(charset); // opening in a new window
-      }
-    } 
-  }
-
-  if (!charset.IsEmpty() && !charset.Equals("UTF-8")) {
+  if (!charset.IsEmpty() &&
+      !charset.Equals("UTF-8") &&
+      NodePrincipal()->Equals(principal)) {
+    SetDocumentCharacterSetSource(source);
     SetDocumentCharacterSet(charset);
-    mCharacterSetSource = kCharsetFromUserDefault;
   }
 
   return NS_OK;
 }
 
 void
 MediaDocument::BecomeInteractive()
 {
--- a/content/html/document/src/nsHTMLContentSink.cpp
+++ b/content/html/document/src/nsHTMLContentSink.cpp
@@ -1129,57 +1129,18 @@ HTMLContentSink::FlushTags()
   }
   
   return mCurrentContext ? mCurrentContext->FlushTags() : NS_OK;
 }
 
 NS_IMETHODIMP
 HTMLContentSink::SetDocumentCharset(nsACString& aCharset)
 {
-  if (mDocShell) {
-    // the following logic to get muCV is copied from
-    // nsHTMLDocument::StartDocumentLoad
-    // We need to call muCV->SetPrevDocCharacterSet here in case
-    // the charset is detected by parser DetectMetaTag
-    nsCOMPtr<nsIMarkupDocumentViewer> muCV;
-    nsCOMPtr<nsIContentViewer> cv;
-    mDocShell->GetContentViewer(getter_AddRefs(cv));
-    if (cv) {
-       muCV = do_QueryInterface(cv);
-    } else {
-      // in this block of code, if we get an error result, we return
-      // it but if we get a null pointer, that's perfectly legal for
-      // parent and parentContentViewer
-
-      NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
-
-      nsCOMPtr<nsIDocShellTreeItem> parentAsItem;
-      mDocShell->GetSameTypeParent(getter_AddRefs(parentAsItem));
-
-      nsCOMPtr<nsIDocShell> parent(do_QueryInterface(parentAsItem));
-      if (parent) {
-        nsCOMPtr<nsIContentViewer> parentContentViewer;
-        nsresult rv =
-          parent->GetContentViewer(getter_AddRefs(parentContentViewer));
-        if (NS_SUCCEEDED(rv) && parentContentViewer) {
-          muCV = do_QueryInterface(parentContentViewer);
-        }
-      }
-    }
-
-    if (muCV) {
-      muCV->SetPrevDocCharacterSet(aCharset);
-    }
-  }
-
-  if (mDocument) {
-    mDocument->SetDocumentCharacterSet(aCharset);
-  }
-
-  return NS_OK;
+  MOZ_ASSUME_UNREACHABLE("<meta charset> case doesn't occur with about:blank");
+  return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 nsISupports *
 HTMLContentSink::GetTarget()
 {
   return mDocument;
 }
 
--- a/content/html/document/src/nsHTMLDocument.cpp
+++ b/content/html/document/src/nsHTMLDocument.cpp
@@ -390,88 +390,56 @@ nsHTMLDocument::TryCacheCharset(nsICachi
       !cachedCharset.IsEmpty() &&
       EncodingUtils::IsAsciiCompatible(cachedCharset))
   {
     aCharset = cachedCharset;
     aCharsetSource = kCharsetFromCache;
   }
 }
 
-static bool
-CheckSameOrigin(nsINode* aNode1, nsINode* aNode2)
-{
-  NS_PRECONDITION(aNode1, "Null node?");
-  NS_PRECONDITION(aNode2, "Null node?");
-
-  bool equal;
-  return
-    NS_SUCCEEDED(aNode1->NodePrincipal()->
-                   Equals(aNode2->NodePrincipal(), &equal)) &&
-    equal;
-}
-
 void
 nsHTMLDocument::TryParentCharset(nsIDocShell*  aDocShell,
-                                 nsIDocument* aParentDocument,
                                  int32_t& aCharsetSource,
                                  nsACString& aCharset)
 {
   if (!aDocShell) {
     return;
   }
   if (aCharsetSource >= kCharsetFromParentForced) {
     return;
   }
 
   int32_t parentSource;
   nsAutoCString parentCharset;
-  aDocShell->GetParentCharset(parentCharset);
+  nsCOMPtr<nsIPrincipal> parentPrincipal;
+  aDocShell->GetParentCharset(parentCharset,
+                              &parentSource,
+                              getter_AddRefs(parentPrincipal));
   if (parentCharset.IsEmpty()) {
     return;
   }
-  aDocShell->GetParentCharsetSource(&parentSource);
   if (kCharsetFromParentForced == parentSource ||
       kCharsetFromUserForced == parentSource) {
     if (WillIgnoreCharsetOverride() ||
         !EncodingUtils::IsAsciiCompatible(aCharset) || // if channel said UTF-16
         !EncodingUtils::IsAsciiCompatible(parentCharset)) {
       return;
     }
     aCharset.Assign(parentCharset);
     aCharsetSource = kCharsetFromParentForced;
     return;
   }
 
-  if (aCharsetSource >= kCharsetFromHintPrevDoc) {
-    return;
-  }
-
-  if (kCharsetFromHintPrevDoc == parentSource) {
-    // Make sure that's OK
-    if (!aParentDocument ||
-        !CheckSameOrigin(this, aParentDocument) ||
-        !EncodingUtils::IsAsciiCompatible(parentCharset)) {
-      return;
-    }
-
-    // if parent is posted doc, set this prevent autodetections
-    // I'm not sure this makes much sense... but whatever.
-    aCharset.Assign(parentCharset);
-    aCharsetSource = kCharsetFromHintPrevDoc;
-    return;
-  }
-
   if (aCharsetSource >= kCharsetFromParentFrame) {
     return;
   }
 
   if (kCharsetFromCache <= parentSource) {
     // Make sure that's OK
-    if (!aParentDocument ||
-        !CheckSameOrigin(this, aParentDocument) ||
+    if (!NodePrincipal()->Equals(parentPrincipal) ||
         !EncodingUtils::IsAsciiCompatible(parentCharset)) {
       return;
     }
 
     aCharset.Assign(parentCharset);
     aCharsetSource = kCharsetFromParentFrame;
   }
 }
@@ -495,35 +463,16 @@ nsHTMLDocument::TryWeakDocTypeDefault(in
   } else {
     aCharset.AssignLiteral("windows-1252");
   }
   aCharsetSource = kCharsetFromWeakDocTypeDefault;
   return;
 }
 
 void
-nsHTMLDocument::TryDefaultCharset( nsIMarkupDocumentViewer* aMarkupDV,
-                                   int32_t& aCharsetSource,
-                                   nsACString& aCharset)
-{
-  if(kCharsetFromUserDefault <= aCharsetSource)
-    return;
-
-  nsAutoCString defaultCharsetFromDocShell;
-  if (aMarkupDV) {
-    nsresult rv =
-      aMarkupDV->GetDefaultCharacterSet(defaultCharsetFromDocShell);
-    if(NS_SUCCEEDED(rv) && EncodingUtils::IsAsciiCompatible(defaultCharsetFromDocShell)) {
-      aCharset = defaultCharsetFromDocShell;
-      aCharsetSource = kCharsetFromUserDefault;
-    }
-  }
-}
-
-void
 nsHTMLDocument::SetDocumentCharacterSet(const nsACString& aCharSetID)
 {
   nsDocument::SetDocumentCharacterSet(aCharSetID);
   // Make sure to stash this charset on our channel as needed if it's a wyciwyg
   // channel.
   nsCOMPtr<nsIWyciwygChannel> wyciwygChannel = do_QueryInterface(mChannel);
   if (wyciwygChannel) {
     wyciwygChannel->SetCharsetAndSource(GetDocumentCharacterSetSource(),
@@ -647,42 +596,31 @@ nsHTMLDocument::StartDocumentLoad(const 
   // and parentContentViewer
   nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(aContainer));
   nsCOMPtr<nsIDocShellTreeItem> parentAsItem;
   if (docShell) {
     docShell->GetSameTypeParent(getter_AddRefs(parentAsItem));
   }
 
   nsCOMPtr<nsIDocShell> parent(do_QueryInterface(parentAsItem));
-  nsCOMPtr<nsIDocument> parentDocument;
   nsCOMPtr<nsIContentViewer> parentContentViewer;
   if (parent) {
     rv = parent->GetContentViewer(getter_AddRefs(parentContentViewer));
     NS_ENSURE_SUCCESS(rv, rv);
-    if (parentContentViewer) {
-      parentDocument = parentContentViewer->GetDocument();
-    }
   }
 
-  //
-  // The following logic is mirrored in nsWebShell::Embed!
-  //
   nsCOMPtr<nsIMarkupDocumentViewer> muCV;
-  bool muCVIsParent = false;
   nsCOMPtr<nsIContentViewer> cv;
   if (docShell) {
     docShell->GetContentViewer(getter_AddRefs(cv));
   }
   if (cv) {
      muCV = do_QueryInterface(cv);
   } else {
     muCV = do_QueryInterface(parentContentViewer);
-    if (muCV) {
-      muCVIsParent = true;
-    }
   }
 
   nsAutoCString urlSpec;
   uri->GetSpec(urlSpec);
 #ifdef DEBUG_charset
   printf("Determining charset for %s\n", urlSpec.get());
 #endif
 
@@ -734,45 +672,24 @@ nsHTMLDocument::StartDocumentLoad(const 
       // interpretation as ASCII and the user can be lured to using the
       // charset menu.
       TryChannelCharset(aChannel, charsetSource, charset, executor);
     }
 
     TryUserForcedCharset(muCV, docShell, charsetSource, charset);
 
     TryHintCharset(muCV, charsetSource, charset); // XXX mailnews-only
-    TryParentCharset(docShell, parentDocument, charsetSource, charset);
+    TryParentCharset(docShell, charsetSource, charset);
 
     if (cachingChan && !urlSpec.IsEmpty()) {
       TryCacheCharset(cachingChan, charsetSource, charset);
     }
 
-    TryDefaultCharset(muCV, charsetSource, charset);
-
     TryWeakDocTypeDefault(charsetSource, charset);
 
-    bool isPostPage = false;
-    // check if current doc is from POST command
-    nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
-    if (httpChannel) {
-      nsAutoCString methodStr;
-      rv = httpChannel->GetRequestMethod(methodStr);
-      isPostPage = (NS_SUCCEEDED(rv) &&
-                    methodStr.EqualsLiteral("POST"));
-    }
-
-    if (isPostPage && muCV && kCharsetFromHintPrevDoc > charsetSource) {
-      nsAutoCString requestCharset;
-      muCV->GetPrevDocCharacterSet(requestCharset);
-      if (!requestCharset.IsEmpty()) {
-        charsetSource = kCharsetFromHintPrevDoc;
-        charset = requestCharset;
-      }
-    }
-
     if (wyciwygChannel) {
       // We know for sure that the parser needs to be using UTF16.
       parserCharset = "UTF-16";
       parserCharsetSource = charsetSource < kCharsetFromChannel ?
         kCharsetFromChannel : charsetSource;
         
       nsAutoCString cachedCharset;
       int32_t cachedSource;
@@ -791,21 +708,16 @@ nsHTMLDocument::StartDocumentLoad(const 
       parserCharset = charset;
       parserCharsetSource = charsetSource;
     }
   }
 
   SetDocumentCharacterSetSource(charsetSource);
   SetDocumentCharacterSet(charset);
 
-  // set doc charset to muCV for next document.
-  // Don't propagate this back up to the parent document if we have one.
-  if (muCV && !muCVIsParent)
-    muCV->SetPrevDocCharacterSet(charset);
-
   if (cachingChan) {
     NS_ASSERTION(charset == parserCharset,
                  "How did those end up different here?  wyciwyg channels are "
                  "not nsICachingChannel");
     rv = cachingChan->SetCacheTokenCachedCharset(charset);
     NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "cannot SetMetaDataElement");
     rv = NS_OK; // don't propagate error
   }
--- a/content/html/document/src/nsHTMLDocument.h
+++ b/content/html/document/src/nsHTMLDocument.h
@@ -306,25 +306,20 @@ protected:
                              nsACString& aCharset);
   void TryUserForcedCharset(nsIMarkupDocumentViewer* aMarkupDV,
                             nsIDocShell*  aDocShell,
                             int32_t& aCharsetSource,
                             nsACString& aCharset);
   static void TryCacheCharset(nsICachingChannel* aCachingChannel,
                                 int32_t& aCharsetSource,
                                 nsACString& aCharset);
-  // aParentDocument could be null.
   void TryParentCharset(nsIDocShell*  aDocShell,
-                        nsIDocument* aParentDocument,
                         int32_t& charsetSource, nsACString& aCharset);
   static void TryWeakDocTypeDefault(int32_t& aCharsetSource,
                                     nsACString& aCharset);
-  static void TryDefaultCharset(nsIMarkupDocumentViewer* aMarkupDV,
-                                int32_t& aCharsetSource,
-                                nsACString& aCharset);
 
   // Override so we can munge the charset on our wyciwyg channel as needed.
   virtual void SetDocumentCharacterSet(const nsACString& aCharSetID) MOZ_OVERRIDE;
 
   // Tracks if we are currently processing any document.write calls (either
   // implicit or explicit). Note that if a write call writes out something which
   // would block the parser, then mWriteLevel will be incorrect until the parser
   // finishes processing that script.
--- a/content/html/document/test/Makefile.in
+++ b/content/html/document/test/Makefile.in
@@ -61,10 +61,13 @@ MOCHITEST_FILES = 	test_bug1682.html \
 		bug499092.html \
 		test_bug512367.html \
 		test_bug677495.html \
 		test_bug677495-1.html \
 		test_bug741266.html \
 		test_non-ascii-cookie.html \
 		test_non-ascii-cookie.html^headers^ \
 		test_bug765780.html \
+		test_bug871161.html \
+		file_bug871161-1.html \
+		file_bug871161-2.html \
 		$(NULL)
 
new file mode 100644
--- /dev/null
+++ b/content/html/document/test/file_bug871161-1.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=windows-1251>
+<title>Page with non-default charset</title>
+<script>
+function run() {
+  document.forms[0].submit();
+}
+</script>
+</head>
+<body onload="run();">
+<form method=post action="http://example.org/tests/content/html/document/test/file_bug871161-2.html"></form>
+</body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/content/html/document/test/file_bug871161-2.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Page without declared charset</title>
+<script>
+function done() {
+  window.opener.postMessage(document.characterSet, "*");
+}
+</script>
+</head>
+<body onload="done();">
+</body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/content/html/document/test/test_bug871161.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=871161
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 871161</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <script type="application/javascript">
+
+  /** Test for Bug 871161 **/
+  SimpleTest.waitForExplicitFinish();
+
+  window.onmessage = function(e) {
+    is(e.data, "windows-1252", "Wrong charset");
+    e.source.close();
+    SimpleTest.finish();
+  }
+
+  function run() {
+    window.open("file_bug871161-1.html");
+  }
+
+  </script>
+</head>
+<body onload="run();">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=871161">Mozilla Bug 871161</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -760,16 +760,17 @@ nsDocShell::nsDocShell():
     mIsBeingDestroyed(false),
     mIsExecutingOnLoadHandler(false),
     mIsPrintingOrPP(false),
     mSavingOldViewer(false),
 #ifdef DEBUG
     mInEnsureScriptEnv(false),
 #endif
     mAffectPrivateSessionLifetime(true),
+    mInvisible(false),
     mDefaultLoadFlags(nsIRequest::LOAD_NORMAL),
     mFrameType(eFrameTypeRegular),
     mOwnOrContainingAppId(nsIScriptSecurityManager::UNKNOWN_APP_ID),
     mParentCharsetSource(0)
 {
     mHistoryID = ++gDocshellIDCounter;
     if (gDocShellCount++ == 0) {
         NS_ASSERTION(sURIFixup == nullptr,
@@ -1853,30 +1854,25 @@ nsDocShell::SetCurrentURI(nsIURI *aURI, 
 
     if (aFireOnLocationChange) {
         FireOnLocationChange(this, aRequest, aURI, aLocationFlags);
     }
     return !aFireOnLocationChange;
 }
 
 NS_IMETHODIMP
-nsDocShell::GetCharset(char** aCharset)
-{
-    NS_ENSURE_ARG_POINTER(aCharset);
-    *aCharset = nullptr; 
+nsDocShell::GetCharset(nsACString& aCharset)
+{
+    aCharset.Truncate();
 
     nsIPresShell* presShell = GetPresShell();
     NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
     nsIDocument *doc = presShell->GetDocument();
     NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
-    *aCharset = ToNewCString(doc->GetDocumentCharacterSet());
-    if (!*aCharset) {
-        return NS_ERROR_OUT_OF_MEMORY;
-    }
-
+    aCharset = doc->GetDocumentCharacterSet();
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocShell::GatherCharsetMenuTelemetry()
 {
   nsCOMPtr<nsIContentViewer> viewer;
   GetContentViewer(getter_AddRefs(viewer));
@@ -1895,17 +1891,16 @@ nsDocShell::GatherCharsetMenuTelemetry()
   nsIURI* url = doc->GetOriginalURI();
   if (url) {
     url->SchemeIs("file", &isFileURL);
   }
 
   int32_t charsetSource = doc->GetDocumentCharacterSetSource();
   switch (charsetSource) {
     case kCharsetFromWeakDocTypeDefault:
-    case kCharsetFromUserDefault:
     case kCharsetFromDocTypeDefault:
     case kCharsetFromCache:
     case kCharsetFromParentFrame:
     case kCharsetFromHintPrevDoc:
       // Changing charset on an unlabeled doc.
       if (isFileURL) {
         Telemetry::Accumulate(Telemetry::CHARSET_OVERRIDE_SITUATION, 0);
       } else {
@@ -1939,71 +1934,54 @@ nsDocShell::GatherCharsetMenuTelemetry()
       // Bug. This isn't supposed to happen.
       Telemetry::Accumulate(Telemetry::CHARSET_OVERRIDE_SITUATION, 6);
       break;
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsDocShell::SetCharset(const char* aCharset)
-{
-    // set the default charset
-    nsCOMPtr<nsIContentViewer> viewer;
-    GetContentViewer(getter_AddRefs(viewer));
-    if (viewer) {
-      nsCOMPtr<nsIMarkupDocumentViewer> muDV(do_QueryInterface(viewer));
-      if (muDV) {
-        nsCString charset(aCharset);
-        NS_ENSURE_SUCCESS(muDV->SetDefaultCharacterSet(charset),
-                          NS_ERROR_FAILURE);
-      }
-    }
-
+nsDocShell::SetCharset(const nsACString& aCharset)
+{
     // set the charset override
-    nsCString charset(aCharset);
-    SetForcedCharset(charset);
+    SetForcedCharset(aCharset);
 
     return NS_OK;
 }
 
 NS_IMETHODIMP nsDocShell::SetForcedCharset(const nsACString& aCharset)
 {
   mForcedCharset = aCharset;
   return NS_OK;
 }
 
 NS_IMETHODIMP nsDocShell::GetForcedCharset(nsACString& aResult)
 {
   aResult = mForcedCharset;
   return NS_OK;
 }
 
-NS_IMETHODIMP nsDocShell::SetParentCharset(const nsACString& aCharset)
+void
+nsDocShell::SetParentCharset(const nsACString& aCharset,
+                             int32_t aCharsetSource,
+                             nsIPrincipal* aPrincipal)
 {
   mParentCharset = aCharset;
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsDocShell::GetParentCharset(nsACString& aResult)
-{
-  aResult = mParentCharset;
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsDocShell::SetParentCharsetSource(int32_t aCharsetSource)
-{
   mParentCharsetSource = aCharsetSource;
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsDocShell::GetParentCharsetSource(int32_t * aParentCharsetSource)
-{
-  *aParentCharsetSource = mParentCharsetSource;
-  return NS_OK;
+  mParentCharsetPrincipal = aPrincipal;
+}
+
+void
+nsDocShell::GetParentCharset(nsACString& aCharset,
+                             int32_t* aCharsetSource,
+                             nsIPrincipal** aPrincipal)
+{
+  aCharset = mParentCharset;
+  *aCharsetSource = mParentCharsetSource;
+  NS_IF_ADDREF(*aPrincipal = mParentCharsetPrincipal);
 }
 
 NS_IMETHODIMP
 nsDocShell::GetChannelIsUnsafe(bool *aUnsafe)
 {
     *aUnsafe = false;
 
     nsIChannel* channel = GetCurrentDocChannel();
@@ -3566,42 +3544,36 @@ nsDocShell::AddChild(nsIDocShellTreeItem
         return NS_OK;
 
     // get the parent's current charset
     if (!mContentViewer)
         return NS_OK;
     nsIDocument* doc = mContentViewer->GetDocument();
     if (!doc)
         return NS_OK;
-    const nsACString &parentCS = doc->GetDocumentCharacterSet();
 
     bool isWyciwyg = false;
 
     if (mCurrentURI) {
         // Check if the url is wyciwyg
         mCurrentURI->SchemeIs("wyciwyg", &isWyciwyg);      
     }
 
     if (!isWyciwyg) {
         // If this docshell is loaded from a wyciwyg: URI, don't
         // advertise our charset since it does not in any way reflect
         // the actual source charset, which is what we're trying to
         // expose here.
 
-        // set the child's parentCharset
-        res = childAsDocShell->SetParentCharset(parentCS);
-        if (NS_FAILED(res))
-            return NS_OK;
-
+        const nsACString &parentCS = doc->GetDocumentCharacterSet();
         int32_t charsetSource = doc->GetDocumentCharacterSetSource();
-
         // set the child's parentCharset
-        res = childAsDocShell->SetParentCharsetSource(charsetSource);
-        if (NS_FAILED(res))
-            return NS_OK;
+        childAsDocShell->SetParentCharset(parentCS,
+                                          charsetSource,
+                                          doc->NodePrincipal());
     }
 
     // printf("### 1 >>> Adding child. Parent CS = %s. ItemType = %d.\n", NS_LossyConvertUTF16toASCII(parentCS).get(), mItemType);
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
@@ -8292,21 +8264,19 @@ nsDocShell::SetupNewViewer(nsIContentVie
     // Init settings
     DoGetPositionAndSize(&x, &y, &cx, &cy);
 
     nsCOMPtr<nsIDocShellTreeItem> parentAsItem;
     NS_ENSURE_SUCCESS(GetSameTypeParent(getter_AddRefs(parentAsItem)),
                       NS_ERROR_FAILURE);
     nsCOMPtr<nsIDocShell> parent(do_QueryInterface(parentAsItem));
 
-    nsAutoCString defaultCharset;
     nsAutoCString forceCharset;
     nsAutoCString hintCharset;
     int32_t hintCharsetSource;
-    nsAutoCString prevDocCharset;
     int32_t minFontSize;
     float textZoom;
     float pageZoom;
     bool styleDisabled;
     // |newMUDV| also serves as a flag to set the data from the above vars
     nsCOMPtr<nsIMarkupDocumentViewer> newMUDV;
 
     if (mContentViewer || parent) {
@@ -8335,19 +8305,16 @@ nsDocShell::SetupNewViewer(nsIContentVie
         }
 
         if (oldMUDV) {
             nsresult rv;
 
             newMUDV = do_QueryInterface(aNewViewer,&rv);
             if (newMUDV) {
                 NS_ENSURE_SUCCESS(oldMUDV->
-                                  GetDefaultCharacterSet(defaultCharset),
-                                  NS_ERROR_FAILURE);
-                NS_ENSURE_SUCCESS(oldMUDV->
                                   GetForceCharacterSet(forceCharset),
                                   NS_ERROR_FAILURE);
                 NS_ENSURE_SUCCESS(oldMUDV->
                                   GetHintCharacterSet(hintCharset),
                                   NS_ERROR_FAILURE);
                 NS_ENSURE_SUCCESS(oldMUDV->
                                   GetHintCharacterSetSource(&hintCharsetSource),
                                   NS_ERROR_FAILURE);
@@ -8358,19 +8325,16 @@ nsDocShell::SetupNewViewer(nsIContentVie
                                   GetTextZoom(&textZoom),
                                   NS_ERROR_FAILURE);
                 NS_ENSURE_SUCCESS(oldMUDV->
                                   GetFullZoom(&pageZoom),
                                   NS_ERROR_FAILURE);
                 NS_ENSURE_SUCCESS(oldMUDV->
                                   GetAuthorStyleDisabled(&styleDisabled),
                                   NS_ERROR_FAILURE);
-                NS_ENSURE_SUCCESS(oldMUDV->
-                                  GetPrevDocCharacterSet(prevDocCharset),
-                                  NS_ERROR_FAILURE);
             }
         }
     }
 
     nscolor bgcolor = NS_RGBA(0, 0, 0, 0);
     // Ensure that the content viewer is destroyed *after* the GC - bug 71515
     nsCOMPtr<nsIContentViewer> kungfuDeathGrip = mContentViewer;
     if (mContentViewer) {
@@ -8415,27 +8379,23 @@ nsDocShell::SetupNewViewer(nsIContentVie
         mContentViewer = nullptr;
         NS_ERROR("ContentViewer Initialization failed");
         return NS_ERROR_FAILURE;
     }
 
     // If we have old state to copy, set the old state onto the new content
     // viewer
     if (newMUDV) {
-        NS_ENSURE_SUCCESS(newMUDV->SetDefaultCharacterSet(defaultCharset),
-                          NS_ERROR_FAILURE);
         NS_ENSURE_SUCCESS(newMUDV->SetForceCharacterSet(forceCharset),
                           NS_ERROR_FAILURE);
         NS_ENSURE_SUCCESS(newMUDV->SetHintCharacterSet(hintCharset),
                           NS_ERROR_FAILURE);
         NS_ENSURE_SUCCESS(newMUDV->
                           SetHintCharacterSetSource(hintCharsetSource),
                           NS_ERROR_FAILURE);
-        NS_ENSURE_SUCCESS(newMUDV->SetPrevDocCharacterSet(prevDocCharset),
-                          NS_ERROR_FAILURE);
         NS_ENSURE_SUCCESS(newMUDV->SetMinFontSize(minFontSize),
                           NS_ERROR_FAILURE);
         NS_ENSURE_SUCCESS(newMUDV->SetTextZoom(textZoom),
                           NS_ERROR_FAILURE);
         NS_ENSURE_SUCCESS(newMUDV->SetFullZoom(pageZoom),
                           NS_ERROR_FAILURE);
         NS_ENSURE_SUCCESS(newMUDV->SetAuthorStyleDisabled(styleDisabled),
                           NS_ERROR_FAILURE);
@@ -12796,8 +12756,20 @@ nsDocShell::HasUnloadedParent()
             if (inUnload) {
                 return true;
             }
         }
         currentTreeItem.swap(parentTreeItem);
     }
     return false;
 }
+
+bool
+nsDocShell::IsInvisible()
+{
+    return mInvisible;
+}
+
+void
+nsDocShell::SetInvisible(bool aInvisible)
+{
+    mInvisible = aInvisible;
+}
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -841,16 +841,17 @@ protected:
     bool                       mSavingOldViewer;
     
     // @see nsIDocShellHistory::createdDynamically
     bool                       mDynamicallyCreated;
 #ifdef DEBUG
     bool                       mInEnsureScriptEnv;
 #endif
     bool                       mAffectPrivateSessionLifetime;
+    bool                       mInvisible;
     uint64_t                   mHistoryID;
     uint32_t                   mDefaultLoadFlags;
 
     static nsIURIFixup *sURIFixup;
 
     nsRefPtr<nsDOMNavigationTiming> mTiming;
 
     // Are we a regular frame, a browser frame, or an app frame?
@@ -864,19 +865,20 @@ protected:
     // (This needs to be the docshell's own /or containing/ app id because the
     // containing app frame might be in another process, in which case we won't
     // find it by walking up the docshell hierarchy.)
     uint32_t mOwnOrContainingAppId;
 
 private:
     nsCString         mForcedCharset;
     nsCString         mParentCharset;
+    int32_t           mParentCharsetSource;
+    nsCOMPtr<nsIPrincipal> mParentCharsetPrincipal;
     nsTObserverArray<nsWeakPtr> mPrivacyObservers;
     nsTObserverArray<nsWeakPtr> mReflowObservers;
-    int32_t           mParentCharsetSource;
     nsCString         mOriginalUriString;
 
     // Separate function to do the actual name (i.e. not _top, _self etc.)
     // searching for FindItemWithName.
     nsresult DoFindItemWithName(const PRUnichar* aName,
                                 nsISupports* aRequestor,
                                 nsIDocShellTreeItem* aOriginalRequestor,
                                 nsIDocShellTreeItem** _retval);
--- a/docshell/base/nsIDocShell.idl
+++ b/docshell/base/nsIDocShell.idl
@@ -38,17 +38,17 @@ interface nsIDOMStorage;
 interface nsIPrincipal;
 interface nsIWebBrowserPrint;
 interface nsIVariant;
 interface nsIPrivacyTransitionObserver;
 interface nsIReflowObserver;
 
 typedef unsigned long nsLoadFlags;
 
-[scriptable, builtinclass, uuid(4ca172c3-67bf-4e6d-89a3-cbfb929c370d)]
+[scriptable, builtinclass, uuid(4c8cd9da-4e93-42ed-9901-3781e90458d9)]
 interface nsIDocShell : nsIDocShellTreeItem
 {
   /**
    * Loads a given URI.  This will give priority to loading the requested URI
    * in the object implementing	this interface.  If it can't be loaded here
    * however, the URL dispatcher will go through its normal process of content
    * loading.
    *
@@ -592,76 +592,46 @@ interface nsIDocShell : nsIDocShellTreeI
 
   /**
    * Create a new about:blank document and content viewer.
    * @param aPrincipal the principal to use for the new document.
    */
   void createAboutBlankContentViewer(in nsIPrincipal aPrincipal);
 
   /**
-   * The charset attribute allows the user to view, hint, and set which
-   * converter is used to read the document's data.
-   *
-   * <P>Inside Mozilla all text is encoded as Unicode. By standardizing  
-   * on Unicode every piece of code that handles characters no longer 
-   * needs to: 
-   *
-   *     Have access to a character encoding parameter.
-   *     Ask is the data stateful?
-   *     Ask is the data single byte?
-   *     Ask is the data multi-byte?
-   *     If multi-byte: have access to a routine that can
-   *         determine how many bytes in the current character.
-   *
-   * When the document is read in a converter is used to convert 
-   * the document's data to Unicode.
+   * Upon getting, returns the canonical encoding label of the document
+   * currently loaded into this docshell.
    *
-   * The charset attribute provides the ability to:
-   *
-   *   See what converter was used when inputting the documents
-   *   data.
-   *
-   *   Override the character set for documents where the specified 
-   *   fallback, or auto-detected character set is incorrect
-   *
-   * Get/sets the encoding (converter) used to read the 
-   * document. Get returns the encoding used. Set forces 
-   * (overrides) the encoding. After forcing the charset the 
-   * embedding application will need to cause the data to be 
-   * reparsed in order to update the DOM / display.
-   *
-   * A force also sets the fallback encoding for this frame.
+   * Upon setting, sets forcedCharset for compatibility with legacy callers.
    */
-  attribute string charset;
+  attribute ACString charset;
 
   /**
    * Called when the user chose an encoding override from the character
    * encoding menu. Separate from the setter for the charset property to avoid
    * extensions adding noise to the data.
    */
   void gatherCharsetMenuTelemetry();
 
   /**
-   * The charset forced by the user. When the charset attribute is set this
-   * attribute is set to the same value.
-   *
-   * XXX Could this be replaced by a boolean?
+   * The charset forced by the user.
    */
   attribute ACString forcedCharset;
 
   /**
    * In a child docshell, this is the charset of the parent docshell
    */
-  attribute ACString parentCharset;
-
-  /*
-   * In a child docshell, this is the source of parentCharset
-   * @see nsCharsetSource.h
-   */
-  attribute int32_t parentCharsetSource;
+  [noscript, notxpcom, nostdcall] void setParentCharset(
+    in ACString parentCharset,
+    in int32_t parentCharsetSource,
+    in nsIPrincipal parentCharsetPrincipal);
+  [noscript, notxpcom, nostdcall] void getParentCharset(
+    out ACString parentCharset,
+    out int32_t parentCharsetSource,
+    out nsIPrincipal parentCharsetPrincipal);
 
   /**
    * Add an observer to the list of parties to be notified when this docshell's
    * private browsing status is changed. |obs| must support weak references.
    */
   void addWeakPrivacyTransitionObserver(in nsIPrivacyTransitionObserver obs);
 
   /**
@@ -917,9 +887,17 @@ interface nsIDocShell : nsIDocShellTreeI
 
   /**
     * Cherry picked parts of nsIController.
     * They are here, because we want to call these functions
     * from JS.
     */
   boolean isCommandEnabled(in string command);
   void doCommand(in string command);
+
+  /**
+   * Invisible DocShell are dummy construct to simulate DOM windows
+   * without any actual visual representation. They have to be marked
+   * at construction time, to avoid any painting activity.
+   */
+  [noscript, notxpcom] bool IsInvisible();
+  [noscript, notxpcom] void SetInvisible(in bool aIsInvisibleDochsell);
 };
--- a/docshell/base/nsIMarkupDocumentViewer.idl
+++ b/docshell/base/nsIMarkupDocumentViewer.idl
@@ -18,17 +18,17 @@ interface nsIDOMNode;
 template<class T> class nsCOMPtr;
 template<class T> class nsTArray;
 %}
 
 interface nsIMarkupDocumentViewer;
 
 [ref] native nsIMarkupDocumentViewerTArray(nsTArray<nsCOMPtr<nsIMarkupDocumentViewer> >);
 
-[scriptable, uuid(23326580-e6ce-4ee1-94b8-f1d9424a9977)]
+[scriptable, uuid(6acfadef-22ee-4924-be6c-776e8def6e1b)]
 interface nsIMarkupDocumentViewer : nsISupports
 {
 
 	/*
 	Scrolls to a given DOM content node. 
 	*/
 	void scrollToNode(in nsIDOMNode node);
 
@@ -36,42 +36,32 @@ interface nsIMarkupDocumentViewer : nsIS
 	attribute float textZoom;
 
 	/** The amount by which to scale all lengths. Default is 1.0. */
 	attribute float fullZoom;
 
 	/** Disable entire author style level (including HTML presentation hints) */
 	attribute boolean authorStyleDisabled;
 
-	/*
-	XXX Comment here!
-	*/
-	attribute ACString defaultCharacterSet;
-
 	/**
 	 * XXX comm-central only: bug 829543. Not the Character Encoding menu in 
      * browser!
 	 */
 	attribute ACString forceCharacterSet;
 
 	/**
 	 * XXX comm-central only: bug 829543.
 	 */
 	attribute ACString hintCharacterSet;
 
 	/**
 	 * XXX comm-central only: bug 829543.
 	 */
 	attribute int32_t hintCharacterSetSource;
 
-	/*
-	character set from prev document 
-	*/
-	attribute ACString prevDocCharacterSet;
-
 	//void GetCharacterSetHint(in wstring hintCharset, in int32_t charsetSource);
 
   /**
    * Requests the size of the content to the container.
    */
   void getContentSize(out long width, out long height);
 
   /**
--- a/docshell/test/chrome/chrome.ini
+++ b/docshell/test/chrome/chrome.ini
@@ -60,16 +60,17 @@ support-files =
 [test_bug364461.xul]
 [test_bug396519.xul]
 [test_bug396649.xul]
 [test_bug428288.html]
 [test_bug449778.xul]
 [test_bug449780.xul]
 [test_bug453650.xul]
 [test_bug456980.xul]
+[test_bug565388.xul]
 [test_bug582176.xul]
 [test_bug608669.xul]
 [test_bug662200.xul]
 [test_bug690056.xul]
 [test_bug789773.xul]
 [test_bug846906.xul]
 [test_bug89419.xul]
 [test_bug909218.html]
new file mode 100644
--- /dev/null
+++ b/docshell/test/chrome/test_bug565388.xul
@@ -0,0 +1,82 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=565388
+-->
+<window title="Mozilla Bug 565388"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+  <title>Test for Bug 565388</title>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+  <!-- test code goes here -->
+  <script type="application/javascript">
+  <![CDATA[
+
+  /** Test for Bug 565388 **/
+  SimpleTest.waitForExplicitFinish();
+
+  var Ci = Components.interfaces;
+  var Cc = Components.classes;
+
+  var progressListener = {
+    add: function(docShell, callback) {
+      this.callback = callback;
+      this.docShell = docShell;
+      docShell.
+            QueryInterface(Ci.nsIInterfaceRequestor).
+            getInterface(Ci.nsIWebProgress).
+            addProgressListener(this, Ci.nsIWebProgress.NOTIFY_STATE_WINDOW);
+    },
+
+    finish: function() {
+      this.docShell.
+            QueryInterface(Ci.nsIInterfaceRequestor).
+            getInterface(Ci.nsIWebProgress).
+            removeProgressListener(this);
+      this.callback();
+    },
+
+    onStateChange: function (webProgress, req, flags, status) {
+      if (req.name.startsWith("data:application/vnd.mozilla.xul")) {
+        if (flags & Ci.nsIWebProgressListener.STATE_STOP)
+          this.finish();
+      }
+    },
+
+    QueryInterface: function(iid) {
+      if (iid.equals(Components.interfaces.nsIWebProgressListener) ||
+          iid.equals(Components.interfaces.nsISupportsWeakReference))
+        return this;
+      throw Components.results.NS_ERROR_NO_INTERFACE;
+    }
+  }
+
+  var systemPrincipal = Cc["@mozilla.org/systemprincipal;1"].
+  createInstance(Ci.nsIPrincipal);
+  var docShell = Cc["@mozilla.org/appshell/appShellService;1"].
+  getService(Ci.nsIAppShellService).
+  createWindowlessBrowser(true).
+  QueryInterface(Ci.nsIInterfaceRequestor).
+  getInterface(Ci.nsIDocShell);
+  docShell.createAboutBlankContentViewer(systemPrincipal);
+  var win = docShell.contentViewer.DOMDocument.defaultView;
+
+  progressListener.add(docShell, function(){
+    is(win.document.documentURI, "data:application/vnd.mozilla.xul+xml;charset=utf-8,<window/>");
+    SimpleTest.finish();
+  });
+
+  win.location = "data:application/vnd.mozilla.xul+xml;charset=utf-8,<window/>";
+
+  ]]>
+  </script>
+
+  <!-- test results are displayed in the html:body -->
+  <body xmlns="http://www.w3.org/1999/xhtml">
+  <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=565388"
+     target="_blank">Mozilla Bug 565388</a>
+  </body>
+</window>
--- a/dom/base/URL.cpp
+++ b/dom/base/URL.cpp
@@ -41,17 +41,17 @@ URL::Constructor(const GlobalObject& aGl
     aRv.Throw(rv);
     return nullptr;
   }
 
   nsCOMPtr<nsIURI> uri;
   rv = ioService->NewURI(NS_ConvertUTF16toUTF8(aUrl), nullptr, aBase.GetURI(),
                          getter_AddRefs(uri));
   if (NS_FAILED(rv)) {
-    aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
+    aRv.Throw(NS_ERROR_DOM_TYPE_ERR);
     return nullptr;
   }
 
   nsRefPtr<URL> url = new URL(uri);
   return url.forget();
 }
 
 /* static */ already_AddRefed<URL>
@@ -64,25 +64,25 @@ URL::Constructor(const GlobalObject& aGl
     aRv.Throw(rv);
     return nullptr;
   }
 
   nsCOMPtr<nsIURI> baseUri;
   rv = ioService->NewURI(NS_ConvertUTF16toUTF8(aBase), nullptr, nullptr,
                          getter_AddRefs(baseUri));
   if (NS_FAILED(rv)) {
-    aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
+    aRv.Throw(NS_ERROR_DOM_TYPE_ERR);
     return nullptr;
   }
 
   nsCOMPtr<nsIURI> uri;
   rv = ioService->NewURI(NS_ConvertUTF16toUTF8(aUrl), nullptr, baseUri,
                          getter_AddRefs(uri));
   if (NS_FAILED(rv)) {
-    aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
+    aRv.Throw(NS_ERROR_DOM_TYPE_ERR);
     return nullptr;
   }
 
   nsRefPtr<URL> url = new URL(uri);
   return url.forget();
 }
 
 void
@@ -186,17 +186,33 @@ URL::GetHref(nsString& aHref) const
   if (NS_SUCCEEDED(rv)) {
     CopyUTF8toUTF16(href, aHref);
   }
 }
 
 void
 URL::SetHref(const nsAString& aHref, ErrorResult& aRv)
 {
-  aRv = mURI->SetSpec(NS_ConvertUTF16toUTF8(aHref));
+  nsCString href = NS_ConvertUTF16toUTF8(aHref);
+
+  nsresult rv;
+  nsCOMPtr<nsIIOService> ioService(do_GetService(NS_IOSERVICE_CONTRACTID, &rv));
+  if (NS_FAILED(rv)) {
+    aRv.Throw(rv);
+    return;
+  }
+
+  nsCOMPtr<nsIURI> uri;
+  rv = ioService->NewURI(href, nullptr, nullptr, getter_AddRefs(uri));
+  if (NS_FAILED(rv)) {
+    aRv.Throw(NS_ERROR_DOM_TYPE_ERR);
+    return;
+  }
+
+  aRv = mURI->SetSpec(href);
 }
 
 void
 URL::GetOrigin(nsString& aOrigin) const
 {
   nsContentUtils::GetUTFNonNullOrigin(mURI, aOrigin);
 }
 
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -762,17 +762,17 @@ nsDOMWindowUtils::SendWheelEvent(float a
 
   // get the widget to send the event to
   nsPoint offset;
   nsCOMPtr<nsIWidget> widget = GetWidget(&offset);
   if (!widget) {
     return NS_ERROR_NULL_POINTER;
   }
 
-  WheelEvent wheelEvent(true, NS_WHEEL_WHEEL, widget);
+  WidgetWheelEvent wheelEvent(true, NS_WHEEL_WHEEL, widget);
   wheelEvent.modifiers = GetWidgetModifiers(aModifiers);
   wheelEvent.deltaX = aDeltaX;
   wheelEvent.deltaY = aDeltaY;
   wheelEvent.deltaZ = aDeltaZ;
   wheelEvent.deltaMode = aDeltaMode;
   wheelEvent.isMomentum =
     (aOptions & WHEEL_EVENT_CAUSED_BY_MOMENTUM) != 0;
   wheelEvent.isPixelOnlyDevice =
--- a/dom/base/test/mochitest.ini
+++ b/dom/base/test/mochitest.ini
@@ -30,8 +30,9 @@ support-files =
 [test_screen_orientation.html]
 [test_setting_opener.html]
 [test_url.html]
 [test_window_constructor.html]
 [test_window_enumeration.html]
 [test_window_extensible.html]
 [test_window_indexing.html]
 [test_writable-replaceable.html]
+[test_urlExceptions.html]
new file mode 100644
--- /dev/null
+++ b/dom/base/test/test_urlExceptions.html
@@ -0,0 +1,57 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=926890
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 926890</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=926890">Mozilla Bug 926890</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  <iframe name="x" id="x"></iframe>
+  <iframe name="y" id="y"></iframe>
+</div>
+<pre id="test">
+</pre>
+  <script type="application/javascript">
+
+  // URL.href throws
+  var url = new URL('http://www.example.com');
+  ok(url, "URL created");
+
+  var status = false;
+  try {
+    url.href = '42';
+  } catch(e) {
+    status = true;
+  }
+  ok(status, "url.href = 42 should throw");
+
+  url.href = 'http://www.example.org';
+  ok(true, "url.href should not throw");
+
+  status = false
+  try {
+    new URL('42');
+  } catch(e) {
+    status = true;
+  }
+  ok(status, "new URL(42) should throw");
+
+  status = false
+  try {
+    new URL('http://www.example.com', '42');
+  } catch(e) {
+    status = true;
+  }
+  ok(status, "new URL(something, 42) should throw");
+
+  </script>
+</body>
+</html>
+
--- a/dom/browser-element/BrowserElementParent.cpp
+++ b/dom/browser-element/BrowserElementParent.cpp
@@ -297,16 +297,17 @@ private:
   nsRefPtr<TabParent> mTabParent;
   const CSSRect mContentRect;
   const CSSSize mContentSize;
 };
 
 NS_IMETHODIMP DispatchAsyncScrollEventRunnable::Run()
 {
   nsCOMPtr<Element> frameElement = mTabParent->GetOwnerElement();
+  NS_ENSURE_STATE(frameElement);
   nsIDocument *doc = frameElement->OwnerDoc();
   nsCOMPtr<nsIGlobalObject> globalObject = doc->GetScopeObject();
   NS_ENSURE_TRUE(globalObject, NS_ERROR_UNEXPECTED);
 
   // Create the event's detail object.
   AsyncScrollEventDetail detail;
   detail.mLeft = mContentRect.x;
   detail.mTop = mContentRect.y;
--- a/dom/camera/DOMCameraManager.cpp
+++ b/dom/camera/DOMCameraManager.cpp
@@ -61,17 +61,19 @@ nsDOMCameraManager::nsDOMCameraManager(n
   SetIsDOMBinding();
 }
 
 nsDOMCameraManager::~nsDOMCameraManager()
 {
   /* destructor code */
   DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
   nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
-  obs->RemoveObserver(this, "xpcom-shutdown");
+  if (obs) {
+    obs->RemoveObserver(this, "xpcom-shutdown");
+  }
 }
 
 bool
 nsDOMCameraManager::CheckPermission(nsPIDOMWindow* aWindow)
 {
   nsCOMPtr<nsIPermissionManager> permMgr =
     do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
   NS_ENSURE_TRUE(permMgr, false);
--- a/dom/contacts/fallback/ContactDB.jsm
+++ b/dom/contacts/fallback/ContactDB.jsm
@@ -1057,16 +1057,33 @@ ContactDB.prototype = {
           let substringRequest = index.mozGetAll(substring, limit);
 
           substringRequest.onsuccess = function (event) {
             if (DEBUG) debug("Request successful. Record count: " + event.target.result.length);
             for (let i in event.target.result) {
               substringResult[event.target.result[i].id] = event.target.result[i];
             }
           }.bind(this);
+        } else if (normalized[0] !== "+") {
+          // We might have an international prefix like '00'
+          let parsed = PhoneNumberUtils.parse(normalized);
+          if (parsed && parsed.internationalNumber &&
+              parsed.nationalNumber  &&
+              parsed.nationalNumber !== normalized &&
+              parsed.internationalNumber !== normalized) {
+            if (DEBUG) debug("Search with " + parsed.internationalNumber);
+            let prefixRequest = index.mozGetAll(parsed.internationalNumber, limit);
+
+            prefixRequest.onsuccess = function (event) {
+              if (DEBUG) debug("Request successful. Record count: " + event.target.result.length);
+              for (let i in event.target.result) {
+                substringResult[event.target.result[i].id] = event.target.result[i];
+              }
+            }.bind(this);
+          }
         }
 
         request = index.mozGetAll(normalized, limit);
       } else {
         // XXX: "contains" should be handled separately, this is "startsWith"
         if (options.filterOp === 'contains' && key !== 'tel') {
           dump("ContactDB: 'contains' only works for 'tel'. Falling back " +
                "to 'startsWith'.\n");
--- a/dom/contacts/tests/test_contacts_international.html
+++ b/dom/contacts/tests/test_contacts_international.html
@@ -56,16 +56,26 @@ var properties1 = {
 };
 
 var shortNumber = "888";
 var properties2 = {
   name: "Testname2",
   tel: [{type: ["work"], value: shortNumber, carrier: "testCarrier"}]
 };
 
+var number3 = {
+  international1: "0041557932012345",
+  international2: "+557932012345"
+};
+
+var properties3 = {
+  name: "Testname2",
+  tel: [{value: number3.international2}]
+};
+
 var req;
 var index = 0;
 var createResult1;
 var findResult1;
 var sample_id1;
 
 var mozContacts = window.navigator.mozContacts;
 
@@ -233,16 +243,51 @@ var steps = [
     req = mozContacts.clear();
     req.onsuccess = function () {
       ok(true, "Deleted the database");
       next();
     }
     req.onerror = onFailure;
   },
   function () {
+    ok(true, "Adding a new contact with country code");
+    createResult1 = new mozContact();
+    createResult1.init(properties3);
+    req = navigator.mozContacts.save(createResult1);
+    req.onsuccess = function () {
+      ok(createResult1.id, "The contact now has an ID.");
+      sample_id1 = createResult1.id;
+      next();
+    };
+    req.onerror = onFailure;
+  },
+  function () {
+    ok(true, "Searching for international number with prefix");
+    var options = {filterBy: ["tel"],
+                   filterOp: "match",
+                   filterValue: number3.international1};
+    req = mozContacts.find(options);
+    req.onsuccess = function () {
+      ok(req.result.length == 1, "Found exactly 1 contact.");
+      findResult1 = req.result[0];
+      ok(findResult1.id == sample_id1, "Same ID");
+      next();
+    };
+    req.onerror = onFailure;
+  },
+  function () {
+    ok(true, "Deleting database");
+    req = mozContacts.clear();
+    req.onsuccess = function () {
+      ok(true, "Deleted the database");
+      next();
+    }
+    req.onerror = onFailure;
+  },
+  function () {
     ok(true, "all done!\n");
     SimpleTest.finish();
   }
 ];
 
 function next() {
   ok(true, "Begin!");
   if (index >= steps.length) {
--- a/dom/datastore/tests/file_arrays.html
+++ b/dom/datastore/tests/file_arrays.html
@@ -40,42 +40,44 @@
       ok("clear" in store, "store.clear exists");
 
       gStore = stores[0];
 
       runTest();
     }, cbError);
   }
 
+  var itemNumber = 60;
+
   function testStoreAdd() {
     var objects = [];
-    for (var i = 0; i < 300; ++i) {
+    for (var i = 0; i < itemNumber; ++i) {
       objects.push(i);
     }
 
     function testStoreAddInternal() {
       if (!objects.length) {
-        ok(true, "We inserted 300 items");
+        ok(true, "We inserted " + itemNumber + " items");
         runTest();
         return;
       }
 
       var obj = objects.shift();
       gStore.add(obj).then(function() {
         ok(true, "We inserted a new item!");
         testStoreAddInternal();
       }, cbError);
     }
 
     testStoreAddInternal();
   }
 
   function testStoreGet() {
     var objects = [];
-    for (var i = 1; i <= 300; ++i) {
+    for (var i = 1; i <= itemNumber; ++i) {
       objects.push(i);
     }
 
     gStore.get(objects).then(function(data) {
        is(data.length, objects.length, "Get - Data matches");
        for (var i = 0; i < data.length; ++i) {
          is(data[i], objects[i] - 1, "Get - Data matches: " + i + " " + data[i] + " == " + objects[i]);
        }
--- a/dom/interfaces/events/nsIDOMEvent.idl
+++ b/dom/interfaces/events/nsIDOMEvent.idl
@@ -252,17 +252,17 @@ nsresult
 NS_NewDOMMouseScrollEvent(nsIDOMEvent** aInstancePtrResult,
                           mozilla::dom::EventTarget* aOwner,
                           nsPresContext* aPresContext,
                           mozilla::WidgetInputEvent* aEvent);
 nsresult
 NS_NewDOMWheelEvent(nsIDOMEvent** aInstancePtrResult,
                     mozilla::dom::EventTarget* aOwner,
                     nsPresContext* aPresContext,
-                    mozilla::WheelEvent* aEvent);
+                    mozilla::WidgetWheelEvent* aEvent);
 nsresult
 NS_NewDOMDragEvent(nsIDOMEvent** aInstancePtrResult,
                    mozilla::dom::EventTarget* aOwner,
                    nsPresContext* aPresContext,
                    mozilla::WidgetDragEvent* aEvent);
 nsresult
 NS_NewDOMClipboardEvent(nsIDOMEvent** aInstancePtrResult,
                         mozilla::dom::EventTarget* aOwner,
--- a/dom/ipc/PBrowser.ipdl
+++ b/dom/ipc/PBrowser.ipdl
@@ -38,17 +38,17 @@ using mozilla::WindowsHandle;
 using nscolor;
 using mozilla::WidgetCompositionEvent;
 using nsIMEUpdatePreference;
 using nsIntPoint;
 using nsIntRect;
 using nsIntSize;
 using mozilla::WidgetKeyboardEvent;
 using mozilla::WidgetMouseEvent;
-using mozilla::WheelEvent;
+using mozilla::WidgetWheelEvent;
 using nsRect;
 using mozilla::WidgetSelectionEvent;
 using mozilla::WidgetTextEvent;
 using mozilla::WidgetTouchEvent;
 using RemoteDOMEvent;
 using mozilla::dom::ScreenOrientation;
 using mozilla::layers::TextureFactoryIdentifier;
 using mozilla::CSSIntPoint;
@@ -362,17 +362,17 @@ child:
                float aY,
                int32_t aButton,
                int32_t aClickCount,
                int32_t aModifiers,
                bool aIgnoreRootScrollFrame);
 
     RealMouseEvent(WidgetMouseEvent event);
     RealKeyEvent(WidgetKeyboardEvent event);
-    MouseWheelEvent(WheelEvent event);
+    MouseWheelEvent(WidgetWheelEvent event);
     RealTouchEvent(WidgetTouchEvent event);
     // We use a separate message for touchmove events only to apply
     // compression to them.
     RealTouchMoveEvent(WidgetTouchEvent event) compress;
 
     /**
      * @see nsIDOMWindowUtils sendKeyEvent.
      */
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -1670,19 +1670,19 @@ bool
 TabChild::RecvRealMouseEvent(const WidgetMouseEvent& event)
 {
   WidgetMouseEvent localEvent(event);
   DispatchWidgetEvent(localEvent);
   return true;
 }
 
 bool
-TabChild::RecvMouseWheelEvent(const WheelEvent& event)
+TabChild::RecvMouseWheelEvent(const WidgetWheelEvent& event)
 {
-  WheelEvent localEvent(event);
+  WidgetWheelEvent localEvent(event);
   DispatchWidgetEvent(localEvent);
   return true;
 }
 
 void
 TabChild::DispatchSynthesizedMouseEvent(uint32_t aMsg, uint64_t aTime,
                                         const LayoutDevicePoint& aRefPoint)
 {
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -223,17 +223,17 @@ public:
                                 const float&    aX,
                                 const float&    aY,
                                 const int32_t&  aButton,
                                 const int32_t&  aClickCount,
                                 const int32_t&  aModifiers,
                                 const bool&     aIgnoreRootScrollFrame);
     virtual bool RecvRealMouseEvent(const mozilla::WidgetMouseEvent& event);
     virtual bool RecvRealKeyEvent(const mozilla::WidgetKeyboardEvent& event);
-    virtual bool RecvMouseWheelEvent(const mozilla::WheelEvent& event);
+    virtual bool RecvMouseWheelEvent(const mozilla::WidgetWheelEvent& event);
     virtual bool RecvRealTouchEvent(const WidgetTouchEvent& event);
     virtual bool RecvRealTouchMoveEvent(const WidgetTouchEvent& event);
     virtual bool RecvKeyEvent(const nsString& aType,
                               const int32_t&  aKeyCode,
                               const int32_t&  aCharCode,
                               const int32_t&  aModifiers,
                               const bool&     aPreventDefault);
     virtual bool RecvCompositionEvent(const mozilla::WidgetCompositionEvent& event);
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -647,22 +647,22 @@ bool TabParent::SendRealMouseEvent(Widge
   WidgetMouseEvent e(event);
   MaybeForwardEventToRenderFrame(event, &e);
   if (!MapEventCoordinatesForChildProcess(&e)) {
     return false;
   }
   return PBrowserParent::SendRealMouseEvent(e);
 }
 
-bool TabParent::SendMouseWheelEvent(WheelEvent& event)
+bool TabParent::SendMouseWheelEvent(WidgetWheelEvent& event)
 {
   if (mIsDestroyed) {
     return false;
   }
-  WheelEvent e(event);
+  WidgetWheelEvent e(event);
   MaybeForwardEventToRenderFrame(event, &e);
   if (!MapEventCoordinatesForChildProcess(&e)) {
     return false;
   }
   return PBrowserParent::SendMouseWheelEvent(event);
 }
 
 bool TabParent::SendRealKeyEvent(WidgetKeyboardEvent& event)
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -193,17 +193,17 @@ public:
 
     void SendMouseEvent(const nsAString& aType, float aX, float aY,
                         int32_t aButton, int32_t aClickCount,
                         int32_t aModifiers, bool aIgnoreRootScrollFrame);
     void SendKeyEvent(const nsAString& aType, int32_t aKeyCode,
                       int32_t aCharCode, int32_t aModifiers,
                       bool aPreventDefault);
     bool SendRealMouseEvent(mozilla::WidgetMouseEvent& event);
-    bool SendMouseWheelEvent(mozilla::WheelEvent& event);
+    bool SendMouseWheelEvent(mozilla::WidgetWheelEvent& event);
     bool SendRealKeyEvent(mozilla::WidgetKeyboardEvent& event);
     bool SendRealTouchEvent(WidgetTouchEvent& event);
 
     virtual PDocumentRendererParent*
     AllocPDocumentRendererParent(const nsRect& documentRect, const gfxMatrix& transform,
                                  const nsString& bgcolor,
                                  const uint32_t& renderFlags, const bool& flushLayout,
                                  const nsIntSize& renderSize);
--- a/dom/messages/SystemMessageManager.js
+++ b/dom/messages/SystemMessageManager.js
@@ -131,16 +131,17 @@ SystemMessageManager.prototype = {
       delete dispatchers[aType];
       return;
     }
 
     // Last registered handler wins.
     dispatchers[aType] = { handler: aHandler, messages: [], isHandling: false };
 
     // Ask for the list of currently pending messages.
+    this.addMessageListeners("SystemMessageManager:GetPendingMessages:Return");
     cpmm.sendAsyncMessage("SystemMessageManager:GetPendingMessages",
                           { type: aType,
                             uri: this._uri,
                             manifest: this._manifest });
   },
 
   mozHasPendingMessage: function sysMessMgr_hasPendingMessage(aType) {
     debug("asking pending message for [" + aType + "]");
@@ -209,16 +210,18 @@ SystemMessageManager.prototype = {
     if (aMessage.name == "SystemMessageManager:Message") {
       // Send an acknowledgement to parent to clean up the pending message,
       // so a re-launched app won't handle it again, which is redundant.
       cpmm.sendAsyncMessage("SystemMessageManager:Message:Return:OK",
                             { type: msg.type,
                               manifest: this._manifest,
                               uri: this._uri,
                               msgID: msg.msgID });
+    } else if (aMessage.name == "SystemMessageManager:GetPendingMessages:Return") {
+      this.removeMessageListeners(aMessage.name);
     }
 
     let messages = (aMessage.name == "SystemMessageManager:Message")
                    ? [msg.msg]
                    : msg.msgQueue;
 
     // We only dispatch messages when a handler is registered.
     let dispatcher = this._dispatchers[msg.type];
@@ -243,18 +246,17 @@ SystemMessageManager.prototype = {
                                    "handle-system-messages-done",
                                    /* aData */ null);
     }
   },
 
   // nsIDOMGlobalPropertyInitializer implementation.
   init: function sysMessMgr_init(aWindow) {
     debug("init");
-    this.initDOMRequestHelper(aWindow, ["SystemMessageManager:Message",
-                              "SystemMessageManager:GetPendingMessages:Return"]);
+    this.initDOMRequestHelper(aWindow, ["SystemMessageManager:Message"]);
 
     let principal = aWindow.document.nodePrincipal;
     this._isInBrowserElement = principal.isInBrowserElement;
     this._uri = principal.URI.spec;
 
     let appsService = Cc["@mozilla.org/AppsService;1"]
                         .getService(Ci.nsIAppsService);
     this._manifest = appsService.getManifestURLByLocalId(principal.appId);
--- a/dom/system/gonk/ril_consts.js
+++ b/dom/system/gonk/ril_consts.js
@@ -1147,38 +1147,42 @@ this.STK_SUPPORTED_TERMINAL_PROFILE = [
  *
  * @see 3GPP TS 51.011 10.3.7 (SIM) and 3GPP TS 31.102 4.2.8 (USIM).
  */
 this.GECKO_ICC_SERVICES = {
   sim: {
     ADN: 2,
     FDN: 3,
     PLMNSEL: 7,
+    MSISDN: 9,
     CBMI: 14,
     SPN: 17,
     SDN: 18,
     DATA_DOWNLOAD_SMS_CB: 25,
     DATA_DOWNLOAD_SMS_PP: 26,
     CBMIR: 30,
     BDN: 31,
     PNN: 51,
     OPL: 52,
+    MDN: 53,
     SPDI: 56
   },
   usim: {
     FDN: 2,
     SDN: 4,
     BDN: 6,
     CBMI: 15,
     CBMIR: 16,
     SPN: 19,
+    MSISDN: 21,
     DATA_DOWNLOAD_SMS_PP: 28,
     DATA_DOWNLOAD_SMS_CB: 29,
     PNN: 45,
     OPL: 46,
+    MDN: 47,
     SPDI: 51
   },
   ruim: {
     ENHANCED_PHONEBOOK: 6,
     SPN: 17
   }
 };
 
--- a/dom/system/gonk/ril_worker.js
+++ b/dom/system/gonk/ril_worker.js
@@ -10990,20 +10990,18 @@ ICCIOHelper[ICC_COMMAND_UPDATE_RECORD] =
  */
 let ICCRecordHelper = {
   /**
    * Fetch ICC records.
    */
   fetchICCRecords: function fetchICCRecords() {
     this.readICCID();
     RIL.getIMSI();
-    this.readMSISDN();
     this.readAD();
     this.readSST();
-    this.readMBDN();
   },
 
   /**
    * Read EF_phase.
    * This EF is only available in SIM.
    */
   readICCPhase: function readICCPhase() {
     function callback() {
@@ -11138,24 +11136,38 @@ let ICCRecordHelper = {
       if (DEBUG) {
         let str = "";
         for (let i = 0; i < sst.length; i++) {
           str += sst[i] + ", ";
         }
         debug("SST: " + str);
       }
 
+      if (ICCUtilsHelper.isICCServiceAvailable("MSISDN")) {
+        if (DEBUG) debug("MSISDN: MSISDN is available");
+        this.readMSISDN();
+      } else {
+        if (DEBUG) debug("MSISDN: MSISDN service is not available");
+      }
+
       // Fetch SPN and PLMN list, if some of them are available.
       if (ICCUtilsHelper.isICCServiceAvailable("SPN")) {
         if (DEBUG) debug("SPN: SPN is available");
         this.readSPN();
       } else {
         if (DEBUG) debug("SPN: SPN service is not available");
       }
 
+      if (ICCUtilsHelper.isICCServiceAvailable("MDN")) {
+        if (DEBUG) debug("MDN: MDN available.");
+        this.readMBDN();
+      } else {
+        if (DEBUG) debug("MDN: MDN service is not available");
+      }
+
       if (ICCUtilsHelper.isICCServiceAvailable("SPDI")) {
         if (DEBUG) debug("SPDI: SPDI available.");
         this.readSPDI();
       } else {
         if (DEBUG) debug("SPDI: SPDI service is not available");
       }
 
       if (ICCUtilsHelper.isICCServiceAvailable("PNN")) {
--- a/dom/system/gonk/tests/test_ril_worker_icc.js
+++ b/dom/system/gonk/tests/test_ril_worker_icc.js
@@ -1890,8 +1890,91 @@ add_test(function test_reading_ad_and_pa
 
   do_test(undefined, "466923202422409", "466", "92" );
   do_test(0x03,      "466923202422409", "466", "923");
   do_test(undefined, "310260542718417", "310", "260");
   do_test(0x02,      "310260542718417", "310", "26" );
 
   run_next_test();
 });
+
+add_test(function test_reading_optional_efs() {
+  let worker = newUint8Worker();
+  let record = worker.ICCRecordHelper;
+  let gsmPdu = worker.GsmPDUHelper;
+  let ril    = worker.RIL;
+  let buf    = worker.Buf;
+  let io     = worker.ICCIOHelper;
+
+  function buildSST(supportedEf) {
+    let sst = [];
+    let len = supportedEf.length;
+    for (let i = 0; i < len; i++) {
+      let index, bitmask, iccService;
+      if (ril.appType === CARD_APPTYPE_SIM) {
+        iccService = GECKO_ICC_SERVICES.sim[supportedEf[i]];
+        iccService -= 1;
+        index = Math.floor(iccService / 4);
+        bitmask = 2 << ((iccService % 4) << 1);
+      } else if (ril.appType === CARD_APPTYPE_USIM){
+        iccService = GECKO_ICC_SERVICES.usim[supportedEf[i]];
+        iccService -= 1;
+        index = Math.floor(iccService / 8);
+        bitmask = 1 << ((iccService % 8) << 0);
+      }
+
+      if (sst) {
+        sst[index] |= bitmask;
+      }
+    }
+    return sst;
+  }
+
+  ril.updateCellBroadcastConfig = function fakeUpdateCellBroadcastConfig() {
+    // Ignore updateCellBroadcastConfig after reading SST
+  };
+
+  function do_test(sst, supportedEf) {
+    // Clone supportedEf to local array for testing
+    let testEf = supportedEf.slice(0);
+
+    record.readMSISDN = function fakeReadMSISDN() {
+      testEf.splice(testEf.indexOf("MSISDN"), 1);
+    };
+
+    record.readMBDN = function fakeReadMBDN() {
+      testEf.splice(testEf.indexOf("MDN"), 1);
+    };
+
+    io.loadTransparentEF = function fakeLoadTransparentEF(options) {
+      // Write data size
+      buf.writeInt32(sst.length * 2);
+
+      // Write data
+      for (let i = 0; i < sst.length; i++) {
+         gsmPdu.writeHexOctet(sst[i] || 0);
+      }
+
+      // Write string delimiter
+      buf.writeStringDelimiter(sst.length * 2);
+
+      if (options.callback) {
+        options.callback(options);
+      }
+
+      if (testEf.length !== 0) {
+        do_print("Un-handled EF: " + JSON.stringify(testEf));
+        do_check_true(false);
+      }
+    };
+
+    record.readSST();
+  }
+
+  // TODO: Add all necessary optional EFs eventually
+  let supportedEf = ["MSISDN", "MDN"];
+  ril.appType = CARD_APPTYPE_SIM;
+  do_test(buildSST(supportedEf), supportedEf);
+  ril.appType = CARD_APPTYPE_USIM;
+  do_test(buildSST(supportedEf), supportedEf);
+
+  run_next_test();
+});
--- a/dom/tests/mochitest/general/test_interfaces.html
+++ b/dom/tests/mochitest/general/test_interfaces.html
@@ -23,21 +23,19 @@ https://bugzilla.mozilla.org/show_bug.cg
 // This is a list of all interfaces that are exposed to every webpage.  Please only
 // add things to this list with great care.
 
 // IMPORTANT: Do not change this list without review from a JavaScript Engine peer!
 var ecmaGlobals =
   [
     "Array",
     "ArrayBuffer",
-    {name: "ArrayType", nightly: true},
     "Boolean",
     "DataView",
     "Date",
-    {name: "Data", nightly: true},
     "Error",
     "EvalError",
     "Float32Array",
     "Float64Array",
     "Function",
     "Infinity",
     "Int16Array",
     "Int32Array",
@@ -54,19 +52,18 @@ var ecmaGlobals =
     {name: "ParallelArray", nightly: true},
     "Proxy",
     "RangeError",
     "ReferenceError",
     "RegExp",
     "Set",
     "StopIteration",
     "String",
-    {name: "StructType", nightly: true},
     "SyntaxError",
-    {name: "Type", nightly: true},
+    {name: "TypedObject", nightly: true},
     "TypeError",
     "Uint16Array",
     "Uint32Array",
     "Uint8Array",
     "Uint8ClampedArray",
     "URIError",
     "WeakMap",
   ];
--- a/dom/webidl/CanvasRenderingContext2D.webidl
+++ b/dom/webidl/CanvasRenderingContext2D.webidl
@@ -224,19 +224,19 @@ interface CanvasDrawingStyles {
            attribute double lineWidth; // (default 1)
            attribute DOMString lineCap; // "butt", "round", "square" (default "butt")
            [GetterThrows]
            attribute DOMString lineJoin; // "round", "bevel", "miter" (default "miter")
            [LenientFloat]
            attribute double miterLimit; // (default 10)
 
   // dashed lines
-// NOT IMPLEMENTED    [LenientFloat] void setLineDash(sequence<double> segments); // default empty
-// NOT IMPLEMENTED    sequence<double> getLineDash();
-// NOT IMPLEMENTED             [LenientFloat] attribute double lineDashOffset;
+    [LenientFloat] void setLineDash(sequence<double> segments); // default empty
+    sequence<double> getLineDash();
+    [LenientFloat] attribute double lineDashOffset;
 
   // text
            [SetterThrows]
            attribute DOMString font; // (default 10px sans-serif)
            attribute DOMString textAlign; // "start", "end", "left", "right", "center" (default: "start")
            attribute DOMString textBaseline; // "top", "hanging", "middle", "alphabetic", "ideographic", "bottom" (default: "alphabetic")
 };
 
--- a/dom/workers/test/mochitest.ini
+++ b/dom/workers/test/mochitest.ini
@@ -48,16 +48,17 @@ support-files =
   transferable_worker.js
   urlApi_worker.js
   url_worker.js
   workersDisabled_worker.js
   xhr2_worker.js
   xhrAbort_worker.js
   xhr_implicit_cancel_worker.js
   xhr_worker.js
+  url_exceptions_worker.js
 
 [test_404.html]
 [test_atob.html]
 [test_blobConstructor.html]
 [test_blobWorkers.html]
 [test_chromeWorker.html]
 [test_clearTimeouts.html]
 [test_close.html]
@@ -102,8 +103,9 @@ support-files =
 [test_xhr.html]
 [test_xhr2.html]
 [test_xhrAbort.html]
 [test_xhr_implicit_cancel.html]
 [test_xhr_parameters.html]
 [test_xhr_parameters.js]
 [test_xhr_system.html]
 [test_xhr_system.js]
+[test_url_exceptions.html]
new file mode 100644
--- /dev/null
+++ b/dom/workers/test/test_url_exceptions.html
@@ -0,0 +1,44 @@
+<!--
+  Any copyright is dedicated to the Public Domain.
+  http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for URL exceptions in workers</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none"></div>
+<pre id="test"></pre>
+<script class="testbody" type="text/javascript">
+
+  var worker = new Worker("url_exceptions_worker.js");
+
+  worker.onmessage = function(event) {
+    is(event.target, worker);
+
+    if (event.data.type == 'finish') {
+      SimpleTest.finish();
+    } else if (event.data.type == 'status') {
+      ok(event.data.status, event.data.msg);
+    }
+  };
+
+  worker.onerror = function(event) {
+    is(event.target, worker);
+    ok(false, "Worker had an error: " + event.data);
+    SimpleTest.finish();
+  };
+
+  worker.postMessage(0);
+  SimpleTest.waitForExplicitFinish();
+
+</script>
+</pre>
+</body>
+</html>
+
+
new file mode 100644
--- /dev/null
+++ b/dom/workers/test/url_exceptions_worker.js
@@ -0,0 +1,38 @@
+function ok(a, msg) {
+  postMessage({type: 'status', status: !!a, msg: msg });
+}
+
+onmessage = function(event) {
+  // URL.href throws
+  var url = new URL('http://www.example.com');
+  ok(url, "URL created");
+
+  var status = false;
+  try {
+    url.href = '42';
+  } catch(e) {
+    status = true;
+  }
+  ok(status, "url.href = 42 should throw");
+
+  url.href = 'http://www.example.org';
+  ok(true, "url.href should not throw");
+
+  status = false
+  try {
+    new URL('42');
+  } catch(e) {
+    status = true;
+  }
+  ok(status, "new URL(42) should throw");
+
+  status = false
+  try {
+    new URL('http://www.example.com', '42');
+  } catch(e) {
+    status = true;
+  }
+  ok(status, "new URL(something, 42) should throw");
+
+  postMessage({type: 'finish' });
+}
--- a/embedding/components/windowwatcher/src/nsWindowWatcher.cpp
+++ b/embedding/components/windowwatcher/src/nsWindowWatcher.cpp
@@ -766,62 +766,16 @@ nsWindowWatcher::OpenWindowInternal(nsID
   if (windowNeedsName) {
     if (nameSpecified && !name.LowerCaseEqualsLiteral("_blank")) {
       newDocShellItem->SetName(name);
     } else {
       newDocShellItem->SetName(EmptyString());
     }
   }
 
-  // Inherit the right character set into the new window to use as a fallback
-  // in the event the document being loaded does not specify a charset.  When
-  // aCalledFromJS is true, we want to use the character set of the document in
-  // the caller; otherwise we want to use the character set of aParent's
-  // docshell. Failing to set this charset is not fatal, so we want to continue
-  // in the face of errors.
-  nsCOMPtr<nsIContentViewer> newCV;
-  newDocShell->GetContentViewer(getter_AddRefs(newCV));
-  nsCOMPtr<nsIMarkupDocumentViewer> newMuCV = do_QueryInterface(newCV);
-  if (newMuCV) {
-    nsCOMPtr<nsIDocShellTreeItem> parentItem;
-    GetWindowTreeItem(aParent, getter_AddRefs(parentItem));
-
-    if (aCalledFromJS) {
-      nsCOMPtr<nsIDocShellTreeItem> callerItem = GetCallerTreeItem(parentItem);
-      nsCOMPtr<nsPIDOMWindow> callerWin = do_GetInterface(callerItem);
-      if (callerWin) {
-        nsCOMPtr<nsIDocument> doc = callerWin->GetExtantDoc();
-        if (doc) {
-          newMuCV->SetDefaultCharacterSet(doc->GetDocumentCharacterSet());
-        }
-      }
-    }
-    else {
-      nsCOMPtr<nsIDocShell> parentDocshell = do_QueryInterface(parentItem);
-      // parentDocshell may be null if the parent got closed in the meantime
-      if (parentDocshell) {
-        nsCOMPtr<nsIContentViewer> parentCV;
-        parentDocshell->GetContentViewer(getter_AddRefs(parentCV));
-        nsCOMPtr<nsIMarkupDocumentViewer> parentMuCV =
-          do_QueryInterface(parentCV);
-        if (parentMuCV) {
-          nsAutoCString charset;
-          nsresult res = parentMuCV->GetDefaultCharacterSet(charset);
-          if (NS_SUCCEEDED(res)) {
-            newMuCV->SetDefaultCharacterSet(charset);
-          }
-          res = parentMuCV->GetPrevDocCharacterSet(charset);
-          if (NS_SUCCEEDED(res)) {
-            newMuCV->SetPrevDocCharacterSet(charset);
-          }
-        }
-      }
-    }
-  }
-
   // Now we have to set the right opener principal on the new window.  Note
   // that we have to do this _before_ starting any URI loads, thanks to the
   // sync nature of javascript: loads.  Since this is the only place where we
   // set said opener principal, we need to do it for all URIs, including
   // chrome ones.  So to deal with the mess that is bug 79775, just press on in
   // a reasonable way even if GetSubjectPrincipal fails.  In that case, just
   // use a null subjectPrincipal.
   nsCOMPtr<nsIPrincipal> subjectPrincipal;
--- a/extensions/widgetutils/src/nsWidgetUtils.cpp
+++ b/extensions/widgetutils/src/nsWidgetUtils.cpp
@@ -229,17 +229,17 @@ nsWidgetUtils::MouseMove(nsIDOMEvent* aD
     return NS_OK;
 
   nsView* aView = mViewManager->GetRootView();
   if (!aView)
     if (NS_FAILED(UpdateFromEvent(aDOMEvent)))
       return NS_OK;
 
   nsEventStatus status;
-  WheelEvent wheelEvent(true, NS_WHEEL_WHEEL, mWidget);
+  WidgetWheelEvent wheelEvent(true, NS_WHEEL_WHEEL, mWidget);
   wheelEvent.deltaMode = nsIDOMWheelEvent::DOM_DELTA_LINE;
   wheelEvent.deltaX = wheelEvent.lineOrPageDeltaX = dx;
   wheelEvent.deltaY = wheelEvent.lineOrPageDeltaY = dy;
   mViewManager->DispatchEvent(&wheelEvent, aView, &status);
   if (status != nsEventStatus_eIgnore) {
     if (dx > 5 || dy > 5) {
       g_panning = true;
     }
--- a/gfx/layers/composite/ContainerLayerComposite.cpp
+++ b/gfx/layers/composite/ContainerLayerComposite.cpp
@@ -193,17 +193,23 @@ ContainerRender(ContainerT* aContainer,
     }
 
     nsIntRect clipRect = layerToRender->GetLayer()->
         CalculateScissorRect(aClipRect, &aManager->GetWorldTransform());
     if (clipRect.IsEmpty()) {
       continue;
     }
 
-    layerToRender->RenderLayer(childOffset, clipRect);
+    if (layerToRender->HasLayerBeenComposited()) {
+      // Composer2D will compose this layer so skip GPU composition
+      // this time & reset composition flag for next composition phase
+      layerToRender->SetLayerComposited(false);
+    } else {
+      layerToRender->RenderLayer(childOffset, clipRect);
+    }
     // invariant: our GL context should be current here, I don't think we can
     // assert it though
   }
 
   if (needsSurface) {
     // Unbind the current surface and rebind the previous one.
 #ifdef MOZ_DUMP_PAINTING
     if (gfxUtils::sDumpPainting) {
--- a/gfx/layers/composite/LayerManagerComposite.cpp
+++ b/gfx/layers/composite/LayerManagerComposite.cpp
@@ -721,16 +721,17 @@ LayerManagerComposite::CreateDrawTarget(
 
 LayerComposite::LayerComposite(LayerManagerComposite *aManager)
   : mCompositeManager(aManager)
   , mCompositor(aManager->GetCompositor())
   , mShadowOpacity(1.0)
   , mUseShadowClipRect(false)
   , mShadowTransformSetByAnimation(false)
   , mDestroyed(false)
+  , mLayerComposited(false)
 { }
 
 LayerComposite::~LayerComposite()
 {
 }
 
 void
 LayerComposite::Destroy()
--- a/gfx/layers/composite/LayerManagerComposite.h
+++ b/gfx/layers/composite/LayerManagerComposite.h
@@ -376,32 +376,39 @@ public:
   {
     mShadowTransform = aMatrix;
   }
   void SetShadowTransformSetByAnimation(bool aSetByAnimation)
   {
     mShadowTransformSetByAnimation = aSetByAnimation;
   }
 
+  void SetLayerComposited(bool value)
+  {
+    mLayerComposited = value;
+  }
+
   // These getters can be used anytime.
   float GetShadowOpacity() { return mShadowOpacity; }
   const nsIntRect* GetShadowClipRect() { return mUseShadowClipRect ? &mShadowClipRect : nullptr; }
   const nsIntRegion& GetShadowVisibleRegion() { return mShadowVisibleRegion; }
   const gfx3DMatrix& GetShadowTransform() { return mShadowTransform; }
   bool GetShadowTransformSetByAnimation() { return mShadowTransformSetByAnimation; }
+  bool HasLayerBeenComposited() { return mLayerComposited; }
 
 protected:
   gfx3DMatrix mShadowTransform;
   nsIntRegion mShadowVisibleRegion;
   nsIntRect mShadowClipRect;
   LayerManagerComposite* mCompositeManager;
   RefPtr<Compositor> mCompositor;
   float mShadowOpacity;
   bool mUseShadowClipRect;
   bool mShadowTransformSetByAnimation;
   bool mDestroyed;
+  bool mLayerComposited;
 };
 
 
 } /* layers */
 } /* mozilla */
 
 #endif /* GFX_LayerManagerComposite_H */
--- a/image/src/RasterImage.cpp
+++ b/image/src/RasterImage.cpp
@@ -2220,22 +2220,16 @@ RasterImage::RequestDecodeCore(RequestDe
 
   if (mError)
     return NS_ERROR_FAILURE;
 
   // If we're already decoded, there's nothing to do.
   if (mDecoded)
     return NS_OK;
 
-  // If we don't have any bytes to flush to the decoder, we can't do anything.
-  // mBytesDecoded can be bigger than mSourceData.Length() if we're not storing
-  // the source data.
-  if (mBytesDecoded > mSourceData.Length())
-    return NS_OK;
-
   // mFinishing protects against the case when we enter RequestDecode from
   // ShutdownDecoder -- in that case, we're done with the decode, we're just
   // not quite ready to admit it.  See bug 744309.
   if (mFinishing)
     return NS_OK;
 
   // If we're currently waiting for a new frame, we can't do anything until
   // that frame is allocated.
@@ -2263,16 +2257,22 @@ RasterImage::RequestDecodeCore(RequestDe
     if (!mHasSize) {
       mWantFullDecode = true;
       return NS_OK;
     }
   }
 
   MutexAutoLock lock(mDecodingMutex);
 
+  // If we don't have any bytes to flush to the decoder, we can't do anything.
+  // mBytesDecoded can be bigger than mSourceData.Length() if we're not storing
+  // the source data.
+  if (mBytesDecoded > mSourceData.Length())
+    return NS_OK;
+
   // If the image is waiting for decode work to be notified, go ahead and do that.
   if (mDecodeRequest &&
       mDecodeRequest->mRequestStatus == DecodeRequest::REQUEST_WORK_DONE &&
       aDecodeType != ASYNCHRONOUS) {
     nsresult rv = FinishedSomeDecoding();
     CONTAINER_ENSURE_SUCCESS(rv);
   }
 
--- a/js/public/Class.h
+++ b/js/public/Class.h
@@ -555,17 +555,17 @@ struct JSClass {
 // member initial value.  The "original ... value" verbiage is there because
 // in ECMA-262, global properties naming class objects are read/write and
 // deleteable, for the most part.
 //
 // Implementing this efficiently requires that global objects have classes
 // with the following flags. Failure to use JSCLASS_GLOBAL_FLAGS was
 // previously allowed, but is now an ES5 violation and thus unsupported.
 //
-#define JSCLASS_GLOBAL_SLOT_COUNT      (3 + JSProto_LIMIT * 3 + 26)
+#define JSCLASS_GLOBAL_SLOT_COUNT      (3 + JSProto_LIMIT * 3 + 27)
 #define JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(n)                                    \
     (JSCLASS_IS_GLOBAL | JSCLASS_HAS_RESERVED_SLOTS(JSCLASS_GLOBAL_SLOT_COUNT + (n)))
 #define JSCLASS_GLOBAL_FLAGS                                                  \
     JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(0)
 #define JSCLASS_HAS_GLOBAL_FLAG_AND_SLOTS(clasp)                              \
   (((clasp)->flags & JSCLASS_IS_GLOBAL)                                       \
    && JSCLASS_RESERVED_SLOTS(clasp) >= JSCLASS_GLOBAL_SLOT_COUNT)
 
--- a/js/public/HashTable.h
+++ b/js/public/HashTable.h
@@ -515,17 +515,17 @@ class HashSet
 template <typename Key, size_t zeroBits>
 struct PointerHasher
 {
     typedef Key Lookup;
     static HashNumber hash(const Lookup &l) {
         JS_ASSERT(!JS::IsPoisonedPtr(l));
         size_t word = reinterpret_cast<size_t>(l) >> zeroBits;
         JS_STATIC_ASSERT(sizeof(HashNumber) == 4);
-#if JS_BYTES_PER_WORD == 4
+#if JS_BITS_PER_WORD == 32
         return HashNumber(word);
 #else
         JS_STATIC_ASSERT(sizeof word == 8);
         return HashNumber((word >> 32) ^ word);
 #endif
     }
     static bool match(const Key &k, const Lookup &l) {
         JS_ASSERT(!JS::IsPoisonedPtr(k));
--- a/js/public/Value.h
+++ b/js/public/Value.h
@@ -10,16 +10,18 @@
 #define js_Value_h
 
 #include "mozilla/Attributes.h"
 #include "mozilla/FloatingPoint.h"
 #include "mozilla/Likely.h"
 
 #include <limits> /* for std::numeric_limits */
 
+#include "jstypes.h"
+
 #include "js/Anchor.h"
 #include "js/RootingAPI.h"
 #include "js/Utility.h"
 
 namespace JS { class Value; }
 
 /* JS::Value can store a full int32_t. */
 #define JSVAL_INT_BITS          32
--- a/js/src/aclocal.m4
+++ b/js/src/aclocal.m4
@@ -7,17 +7,16 @@ builtin(include, build/autoconf/acwinpat
 builtin(include, build/autoconf/hooks.m4)dnl
 builtin(include, build/autoconf/config.status.m4)dnl
 builtin(include, build/autoconf/toolchain.m4)dnl
 builtin(include, build/autoconf/ccache.m4)dnl
 builtin(include, build/autoconf/wrapper.m4)dnl
 builtin(include, build/autoconf/pkg.m4)dnl
 builtin(include, build/autoconf/nspr.m4)dnl
 builtin(include, build/autoconf/altoptions.m4)dnl
-builtin(include, build/autoconf/moznbytetype.m4)dnl
 builtin(include, build/autoconf/mozprog.m4)dnl
 builtin(include, build/autoconf/mozheader.m4)dnl
 builtin(include, build/autoconf/mozcommonheader.m4)dnl
 builtin(include, build/autoconf/lto.m4)dnl
 builtin(include, build/autoconf/gcc-pr49911.m4)dnl
 builtin(include, build/autoconf/gcc-pr39608.m4)dnl
 builtin(include, build/autoconf/llvm-pr8927.m4)dnl
 builtin(include, build/autoconf/frameptr.m4)dnl
deleted file mode 100644
--- a/js/src/build/autoconf/moznbytetype.m4
+++ /dev/null
@@ -1,103 +0,0 @@
-dnl This Source Code Form is subject to the terms of the Mozilla Public
-dnl License, v. 2.0. If a copy of the MPL was not distributed with this
-dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-dnl MOZ_N_BYTE_TYPE(VARIABLE, SIZE, POSSIBLE-TYPES)
-dnl
-dnl Check to see which of POSSIBLE-TYPES has a size of SIZE.  If we
-dnl find one, define VARIABLE to be the size-BYTE type.  If no type
-dnl matches, exit the configure script with an error message.  Types
-dnl whose written form contains spaces should appear in POSSIBLE-TYPES
-dnl enclosed by shell quotes.
-dnl
-dnl The cache variable moz_cv_n_byte_type_VARIABLE gets set to the
-dnl type, if found.
-dnl 
-dnl for example:
-dnl MOZ_N_BYTE_TYPE([JS_INT32_T], [4], [int long 'long long' short])
-dnl
-AC_DEFUN([MOZ_N_BYTE_TYPE],
-[
-dnl The simplest approach would simply be to run a program that says
-dnl   printf ("%d\n", sizeof ($type));
-dnl But that won't work when cross-compiling; this will.
-AC_CACHE_CHECK([for a $2-byte type], moz_cv_n_byte_type_$1, [
-  moz_cv_n_byte_type_$1=
-  for type in $3; do
-    AC_TRY_COMPILE([],
-                   [
-                     int a[sizeof ($type) == $2 ? 1 : -1];
-                     return 0;
-                   ],
-                   [moz_cv_n_byte_type_$1=$type; break], [])
-  done
-  if test ! "$moz_cv_n_byte_type_$1"; then
-    AC_MSG_ERROR([Couldn't find a $2-byte type])
-  fi
-])
-AC_DEFINE_UNQUOTED($1, [$moz_cv_n_byte_type_$1],
-                   [a $2-byte type on the target machine])
-])
-
-dnl MOZ_SIZE_OF_TYPE(VARIABLE, TYPE, POSSIBLE-SIZES)
-dnl
-dnl Check to see which of POSSIBLE-SIZES is the sizeof(TYPE). If we find one,
-dnl define VARIABLE SIZE. If no size matches, exit the configure script with
-dnl an error message.
-dnl
-dnl The cache variable moz_cv_size_of_VARIABLE gets set to the size, if
-dnl found.
-dnl
-dnl for example:
-dnl MOZ_SIZE_OF_TYPE([JS_BYTES_PER_WORD], [void*], [4 8])
-AC_DEFUN([MOZ_SIZE_OF_TYPE],
-[
-AC_CACHE_CHECK([for the size of $2], moz_cv_size_of_$1, [
-  moz_cv_size_of_$1=
-  for size in $3; do
-    AC_TRY_COMPILE([],
-                   [
-                     int a[sizeof ($2) == $size ? 1 : -1];
-                     return 0;
-                   ],
-                   [moz_cv_size_of_$1=$size; break], [])
-  done
-  if test ! "$moz_cv_size_of_$1"; then
-    AC_MSG_ERROR([No size found for $2])
-  fi
-])
-AC_DEFINE_UNQUOTED($1, [$moz_cv_size_of_$1])
-])
-
-dnl MOZ_ALIGN_OF_TYPE(VARIABLE, TYPE, POSSIBLE-ALIGNS)
-dnl
-dnl Check to see which of POSSIBLE-ALIGNS is the necessary alignment of TYPE.
-dnl If we find one, define VARIABLE ALIGNMENT. If no alignment matches, exit
-dnl the configure script with an error message.
-dnl
-dnl The cache variable moz_cv_align_of_VARIABLE gets set to the size, if
-dnl found.
-dnl
-dnl for example:
-dnl MOZ_ALIGN_OF_TYPE(JS_ALIGN_OF_POINTER, void*, 2 4 8 16)
-AC_DEFUN([MOZ_ALIGN_OF_TYPE],
-[
-AC_CACHE_CHECK([for the alignment of $2], moz_cv_align_of_$1, [
-  moz_cv_align_of_$1=
-  for align in $3; do
-    AC_TRY_COMPILE([
-                     #include <stddef.h>
-                     struct aligner { char c; $2 a; };
-                   ],
-                   [
-                     int a[offsetof(struct aligner, a) == $align ? 1 : -1];
-                     return 0;
-                   ],
-                   [moz_cv_align_of_$1=$align; break], [])
-  done
-  if test ! "$moz_cv_align_of_$1"; then
-    AC_MSG_ERROR([No alignment found for $2])
-  fi
-])
-AC_DEFINE_UNQUOTED($1, [$moz_cv_align_of_$1])
-])
--- a/js/src/builtin/TypedObject.cpp
+++ b/js/src/builtin/TypedObject.cpp
@@ -24,16 +24,28 @@
 #include "jsobjinlines.h"
 
 #include "vm/Shape-inl.h"
 
 using mozilla::DebugOnly;
 
 using namespace js;
 
+const Class js::TypedObjectClass = {
+    "TypedObject",
+    JSCLASS_HAS_CACHED_PROTO(JSProto_TypedObject),
+    JS_PropertyStub,         /* addProperty */
+    JS_DeletePropertyStub,   /* delProperty */
+    JS_PropertyStub,         /* getProperty */
+    JS_StrictPropertyStub,   /* setProperty */
+    JS_EnumerateStub,
+    JS_ResolveStub,
+    JS_ConvertStub
+};
+
 /*
  * Reify() converts a binary value into a JS Object.
  *
  * The type of the value to be converted is described by `typeRepr`,
  * and `type` is an associated type descriptor object with that
  * same representation (note that there may be many descriptors
  * that all share the same `typeRepr`).
  *
@@ -48,28 +60,16 @@ static bool Reify(JSContext *cx, TypeRep
 /*
  * ConvertAndCopyTo() converts `from` to type `type` and stores the result in
  * `mem`, which MUST be pre-allocated to the appropriate size for instances of
  * `type`.
  */
 static bool ConvertAndCopyTo(JSContext *cx, TypeRepresentation *typeRepr,
                              HandleValue from, uint8_t *mem);
 
-static bool
-TypeThrowError(JSContext *cx, unsigned argc, Value *vp)
-{
-    return ReportIsNotFunction(cx, *vp);
-}
-
-static bool
-DataThrowError(JSContext *cx, unsigned argc, Value *vp)
-{
-    return ReportIsNotFunction(cx, *vp);
-}
-
 static void
 ReportCannotConvertTo(JSContext *cx, HandleValue fromValue, const char *toType)
 {
     JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_CANT_CONVERT_TO,
                          InformalValueTypeName(fromValue), toType);
 }
 
 static void
@@ -234,39 +234,21 @@ IsBlockOfKind(JSContext *cx, HandleObjec
 }
 
 static inline bool
 IsBinaryArray(JSContext *cx, HandleObject obj)
 {
     return IsBlockOfKind(cx, obj, TypeRepresentation::Array);
 }
 
-const Class js::DataClass = {
-    "Data",
-    JSCLASS_HAS_CACHED_PROTO(JSProto_Data),
-    JS_PropertyStub,
-    JS_DeletePropertyStub,
-    JS_PropertyStub,
-    JS_StrictPropertyStub,
-    JS_EnumerateStub,
-    JS_ResolveStub,
-    JS_ConvertStub
-};
-
-const Class js::TypeClass = {
-    "Type",
-    JSCLASS_HAS_CACHED_PROTO(JSProto_Type),
-    JS_PropertyStub,
-    JS_DeletePropertyStub,
-    JS_PropertyStub,
-    JS_StrictPropertyStub,
-    JS_EnumerateStub,
-    JS_ResolveStub,
-    JS_ConvertStub
-};
+static inline bool
+IsBinaryStruct(JSContext *cx, HandleObject obj)
+{
+    return IsBlockOfKind(cx, obj, TypeRepresentation::Struct);
+}
 
 static bool
 TypeEquivalent(JSContext *cx, unsigned int argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     RootedObject thisObj(cx, ToObjectIfObject(args.thisv()));
     if (!thisObj || !IsBinaryType(thisObj)) {
@@ -293,18 +275,17 @@ TypeEquivalent(JSContext *cx, unsigned i
     TypeRepresentation *otherRepr = typeRepresentation(otherObj);
     args.rval().setBoolean(thisRepr == otherRepr);
     return true;
 }
 
 #define BINARYDATA_NUMERIC_CLASSES(constant_, type_, name_)                   \
 {                                                                             \
     #name_,                                                                   \
-    JSCLASS_HAS_RESERVED_SLOTS(1) |                                           \
-    JSCLASS_HAS_CACHED_PROTO(JSProto_##name_),                                \
+    JSCLASS_HAS_RESERVED_SLOTS(TYPE_RESERVED_SLOTS),                          \
     JS_PropertyStub,       /* addProperty */                                  \
     JS_DeletePropertyStub, /* delProperty */                                  \
     JS_PropertyStub,       /* getProperty */                                  \
     JS_StrictPropertyStub, /* setProperty */                                  \
     JS_EnumerateStub,                                                         \
     JS_ResolveStub,                                                           \
     JS_ConvertStub,                                                           \
     nullptr,                                                                  \
@@ -380,18 +361,30 @@ NumericType<ScalarTypeRepresentation::TY
     } else {
         if (!ToDoubleForTypedArray(cx, val, &d))
             return false;
     }
     *converted = ClampDoubleToUint8(d);
     return true;
 }
 
+} // namespace js
 
-} // namespace js
+template<ScalarTypeRepresentation::Type N>
+static bool
+NumericTypeToString(JSContext *cx, unsigned int argc, Value *vp)
+{
+    static_assert(N < ScalarTypeRepresentation::TYPE_MAX, "bad numeric type");
+    CallArgs args = CallArgsFromVp(argc, vp);
+    JSString *s = JS_NewStringCopyZ(cx, ScalarTypeRepresentation::typeName(N));
+    if (!s)
+        return false;
+    args.rval().setString(s);
+    return true;
+}
 
 static bool
 ConvertAndCopyScalarTo(JSContext *cx, ScalarTypeRepresentation *typeRepr,
                        HandleValue from, uint8_t *mem)
 {
 #define CONVERT_CASES(constant_, type_, name_)                                \
     case constant_: {                                                         \
         type_ temp;                                                           \
@@ -447,93 +440,176 @@ NumericType<type, T>::call(JSContext *cx
     if (!NumericType<type, T>::reify(cx, &answer, &reified)) {
         return false;
     }
 
     args.rval().set(reified);
     return true;
 }
 
-template<ScalarTypeRepresentation::Type N>
-bool
-NumericTypeToString(JSContext *cx, unsigned int argc, Value *vp)
-{
-    JS_STATIC_ASSERT(N < ScalarTypeRepresentation::TYPE_MAX);
-    CallArgs args = CallArgsFromVp(argc, vp);
-    JSString *s = JS_NewStringCopyZ(cx, ScalarTypeRepresentation::typeName(N));
-    if (!s)
-        return false;
-    args.rval().set(StringValue(s));
-    return true;
-}
-
 /*
- * When creating:
- *   var A = new ArrayType(uint8, 10)
- * or
- *   var S = new StructType({...})
+ * For code like:
+ *
+ *   var A = new TypedObject.ArrayType(uint8, 10);
+ *   var S = new TypedObject.StructType({...});
+ *
+ * As usual, the [[Prototype]] of A is
+ * TypedObject.ArrayType.prototype.  This permits adding methods to
+ * all ArrayType types, by setting
+ * TypedObject.ArrayType.prototype.methodName = function() { ... }.
+ * The same holds for S with respect to TypedObject.StructType.
+ *
+ * We may also want to add methods to *instances* of an ArrayType:
+ *
+ *   var a = new A();
+ *   var s = new S();
  *
- * A.prototype.__proto__ === ArrayType.prototype.prototype (and similar for
- * StructType).
+ * As usual, the [[Prototype]] of a is A.prototype.  What's
+ * A.prototype?  It's an empty object, and you can set
+ * A.prototype.methodName = function() { ... } to add a method to all
+ * A instances.  (And the same with respect to s and S.)
  *
- * This function takes a reference to either ArrayType or StructType and
- * returns a JSObject which can be set as A.prototype.
+ * But what if you want to add a method to all ArrayType instances,
+ * not just all A instances?  (Or to all StructType instances.)  The
+ * [[Prototype]] of the A.prototype empty object is
+ * TypedObject.ArrayType.prototype.prototype (two .prototype levels!).
+ * So just set TypedObject.ArrayType.prototype.prototype.methodName =
+ * function() { ... } to add a method to all ArrayType instances.
+ * (And, again, same with respect to s and S.)
+ *
+ * This function creates the A.prototype/S.prototype object.  It takes
+ * as an argument either the TypedObject.ArrayType or the
+ * TypedObject.StructType constructor function, then returns an empty
+ * object with the .prototype.prototype object as its [[Prototype]].
  */
 static JSObject *
-SetupAndGetPrototypeObjectForComplexTypeInstance(JSContext *cx,
-                                                 HandleObject complexTypeGlobal)
+CreateComplexTypeInstancePrototype(JSContext *cx,
+                                   HandleObject typeObjectCtor)
 {
-    RootedObject global(cx, cx->compartment()->maybeGlobal());
-    RootedValue complexTypePrototypeVal(cx);
-    RootedValue complexTypePrototypePrototypeVal(cx);
+    RootedValue ctorPrototypeVal(cx);
+    if (!JSObject::getProperty(cx, typeObjectCtor, typeObjectCtor,
+                               cx->names().prototype,
+                               &ctorPrototypeVal))
+    {
+        return nullptr;
+    }
+    JS_ASSERT(ctorPrototypeVal.isObject()); // immutable binding
+    RootedObject ctorPrototypeObj(cx, &ctorPrototypeVal.toObject());
+
+    RootedValue ctorPrototypePrototypeVal(cx);
+    if (!JSObject::getProperty(cx, ctorPrototypeObj, ctorPrototypeObj,
+                               cx->names().prototype,
+                               &ctorPrototypePrototypeVal))
+    {
+        return nullptr;
+    }
 
-    if (!JSObject::getProperty(cx, complexTypeGlobal, complexTypeGlobal,
-                               cx->names().prototype, &complexTypePrototypeVal))
+    JS_ASSERT(ctorPrototypePrototypeVal.isObject()); // immutable binding
+    RootedObject proto(cx, &ctorPrototypePrototypeVal.toObject());
+    return NewObjectWithGivenProto(cx, &JSObject::class_, proto,
+                                   &typeObjectCtor->global());
+}
+
+template<typename T>
+static JSObject *
+CreateMetaTypeObject(JSContext *cx,
+                     Handle<GlobalObject*> global)
+{
+    RootedAtom className(cx, Atomize(cx, T::class_.name,
+                                     strlen(T::class_.name)));
+    if (!className)
+        return nullptr;
+
+    RootedObject funcProto(cx, global->getOrCreateFunctionPrototype(cx));
+    if (!funcProto)
         return nullptr;
 
-    JS_ASSERT(complexTypePrototypeVal.isObject()); // immutable binding
-    RootedObject complexTypePrototypeObj(cx,
-        &complexTypePrototypeVal.toObject());
+    // Create ctor.prototype, which inherits from Function.prototype
+
+    RootedObject proto(
+        cx, NewObjectWithGivenProto(cx, &JSObject::class_, funcProto,
+                                    global, SingletonObject));
+    if (!proto)
+        return nullptr;
 
-    if (!JSObject::getProperty(cx, complexTypePrototypeObj,
-                               complexTypePrototypeObj,
-                               cx->names().prototype,
-                               &complexTypePrototypePrototypeVal))
+    // Create ctor.prototype.prototype, which inherits from Object.__proto__
+
+    RootedObject objProto(cx, global->getOrCreateObjectPrototype(cx));
+    if (!objProto)
+        return nullptr;
+    RootedObject protoProto(
+        cx, NewObjectWithGivenProto(cx, &JSObject::class_, objProto,
+                                    global, SingletonObject));
+    if (!proto)
         return nullptr;
 
-    RootedObject prototypeObj(cx,
-        NewObjectWithGivenProto(cx, &JSObject::class_, nullptr, global));
-
-    JS_ASSERT(complexTypePrototypePrototypeVal.isObject()); // immutable binding
-    RootedObject proto(cx, &complexTypePrototypePrototypeVal.toObject());
-    if (!JS_SetPrototype(cx, prototypeObj, proto))
+    RootedValue protoProtoValue(cx, ObjectValue(*protoProto));
+    if (!JSObject::defineProperty(cx, proto, cx->names().prototype,
+                                  protoProtoValue,
+                                  nullptr, nullptr,
+                                  JSPROP_READONLY | JSPROP_PERMANENT))
         return nullptr;
 
-    return prototypeObj;
+    // Create ctor itself
+
+    RootedFunction ctor(
+        cx, global->createConstructor(cx, T::construct, className, 2));
+    if (!ctor ||
+        !LinkConstructorAndPrototype(cx, ctor, proto) ||
+        !DefinePropertiesAndBrand(cx, proto,
+                                  T::typeObjectProperties,
+                                  T::typeObjectMethods) ||
+        !DefinePropertiesAndBrand(cx, protoProto,
+                                  T::typedObjectProperties,
+                                  T::typedObjectMethods))
+    {
+        return nullptr;
+    }
+
+    return ctor;
 }
 
 const Class ArrayType::class_ = {
     "ArrayType",
-    JSCLASS_HAS_RESERVED_SLOTS(ARRAY_TYPE_RESERVED_SLOTS) |
-    JSCLASS_HAS_CACHED_PROTO(JSProto_ArrayType),
+    JSCLASS_HAS_RESERVED_SLOTS(ARRAY_TYPE_RESERVED_SLOTS),
     JS_PropertyStub,
     JS_DeletePropertyStub,
     JS_PropertyStub,
     JS_StrictPropertyStub,
     JS_EnumerateStub,
     JS_ResolveStub,
     JS_ConvertStub,
     nullptr,
     nullptr,
     nullptr,
     nullptr,
     BinaryBlock::construct,
     nullptr
 };
 
+const JSPropertySpec ArrayType::typeObjectProperties[] = {
+    JS_PS_END
+};
+
+const JSFunctionSpec ArrayType::typeObjectMethods[] = {
+    JS_FN("repeat", ArrayType::repeat, 1, 0),
+    JS_FN("toSource", ArrayType::toSource, 0, 0),
+    JS_FS_END
+};
+
+const JSPropertySpec ArrayType::typedObjectProperties[] = {
+    JS_PS_END
+};
+
+const JSFunctionSpec ArrayType::typedObjectMethods[] = {
+    JS_FN("subarray", ArrayType::subarray, 2, 0),
+    {"forEach", {nullptr, nullptr}, 1, 0, "ArrayForEach"},
+    JS_FS_END
+};
+
 static JSObject *
 ArrayElementType(HandleObject array)
 {
     JS_ASSERT(IsArrayType(array));
     return &array->getFixedSlot(SLOT_ARRAY_ELEM_TYPE).toObject();
 }
 
 static bool
@@ -592,45 +668,16 @@ ConvertAndCopyArrayTo(JSContext *cx, Arr
 
         p += elementType->size();
     }
 
     return true;
 }
 
 static bool
-DataInstanceUpdate(JSContext *cx, unsigned argc, Value *vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-
-    if (args.length() < 1) {
-        JS_ReportErrorNumber(cx, js_GetErrorMessage,
-                             nullptr, JSMSG_MORE_ARGS_NEEDED,
-                             "update()", "0", "s");
-        return false;
-    }
-
-    RootedObject thisObj(cx, ToObjectIfObject(args.thisv()));
-    if (!thisObj || !IsBlock(thisObj)) {
-        JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
-                             JSMSG_INCOMPATIBLE_PROTO,
-                             "Data", "update",
-                             InformalValueTypeName(args.thisv()));
-        return false;
-    }
-
-    RootedValue val(cx, args[0]);
-    if (!ConvertAndCopyTo(cx, val, thisObj))
-        return false;
-
-    args.rval().setUndefined();
-    return true;
-}
-
-static bool
 FillBinaryArrayWithValue(JSContext *cx, HandleObject array, HandleValue val)
 {
     JS_ASSERT(IsBinaryArray(cx, array));
 
     // set array[0] = [[Convert]](val)
     RootedObject type(cx, GetType(array));
     ArrayTypeRepresentation *typeRepr = typeRepresentation(type)->asArray();
     uint8_t *base = BlockMem(array);
@@ -642,18 +689,18 @@ FillBinaryArrayWithValue(JSContext *cx, 
     for (size_t i = 1; i < typeRepr->length(); i++) {
         uint8_t *dest = base + elementSize * i;
         memcpy(dest, base, elementSize);
     }
 
     return true;
 }
 
-static bool
-ArrayRepeat(JSContext *cx, unsigned int argc, Value *vp)
+bool
+ArrayType::repeat(JSContext *cx, unsigned int argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     if (args.length() < 1) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage,
                              nullptr, JSMSG_MORE_ARGS_NEEDED,
                              "repeat()", "0", "s");
         return false;
@@ -721,18 +768,18 @@ ArrayType::toSource(JSContext *cx, unsig
  *     return ret
  *
  * The range specified by the begin and end values is clamped to the valid
  * index range for the current array. If the computed length of the new
  * TypedArray would be negative, it is clamped to zero.
  * see: http://www.khronos.org/registry/typedarray/specs/latest/#7
  *
  */
-static bool
-ArraySubarray(JSContext *cx, unsigned int argc, Value *vp)
+/* static */ bool
+ArrayType::subarray(JSContext *cx, unsigned int argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     if (args.length() < 1) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage,
                              nullptr, JSMSG_MORE_ARGS_NEEDED,
                              "subarray()", "0", "s");
         return false;
@@ -776,17 +823,17 @@ ArraySubarray(JSContext *cx, unsigned in
     end = Clamp(end, 0, length);
 
     int32_t sublength = end - begin; // end exclusive
     sublength = Clamp(sublength, 0, length);
 
     RootedObject globalObj(cx, cx->compartment()->maybeGlobal());
     JS_ASSERT(globalObj);
     Rooted<GlobalObject*> global(cx, &globalObj->as<GlobalObject>());
-    RootedObject arrayTypeGlobal(cx, global->getOrCreateArrayTypeObject(cx));
+    RootedObject arrayTypeGlobal(cx, global->getArrayType(cx));
 
     RootedObject elementType(cx, ArrayElementType(type));
     RootedObject subArrayType(cx, ArrayType::create(cx, arrayTypeGlobal,
                                                     elementType, sublength));
     if (!subArrayType)
         return false;
 
     int32_t elementSize = typeRepr->element()->size();
@@ -824,76 +871,101 @@ ArrayFillSubarray(JSContext *cx, unsigne
     Value funArrayTypeVal = GetFunctionNativeReserved(&args.callee(), 0);
     JS_ASSERT(funArrayTypeVal.isObject());
 
     RootedObject type(cx, GetType(thisObj));
     TypeRepresentation *typeRepr = typeRepresentation(type);
     RootedObject funArrayType(cx, &funArrayTypeVal.toObject());
     TypeRepresentation *funArrayTypeRepr = typeRepresentation(funArrayType);
     if (typeRepr != funArrayTypeRepr) {
-        RootedValue thisObjVal(cx, ObjectValue(*thisObj));
-        ReportCannotConvertTo(cx, thisObjVal, funArrayTypeRepr);
+        RootedValue thisObjValue(cx, ObjectValue(*thisObj));
+        ReportCannotConvertTo(cx, thisObjValue, funArrayTypeRepr);
         return false;
     }
 
     args.rval().setUndefined();
     RootedValue val(cx, args[0]);
     return FillBinaryArrayWithValue(cx, thisObj, val);
 }
 
 static bool
 InitializeCommonTypeDescriptorProperties(JSContext *cx,
                                          HandleObject obj,
                                          HandleObject typeReprOwnerObj)
 {
     TypeRepresentation *typeRepr =
         TypeRepresentation::fromOwnerObject(typeReprOwnerObj);
 
+    // equivalent()
+    if (!JS_DefineFunction(cx, obj, "equivalent",
+                           TypeEquivalent, 1, 0))
+    {
+        return false;
+    }
+
     // byteLength
     RootedValue typeByteLength(cx, NumberValue(typeRepr->size()));
     if (!JSObject::defineProperty(cx, obj, cx->names().byteLength,
                                   typeByteLength,
                                   nullptr, nullptr,
                                   JSPROP_READONLY | JSPROP_PERMANENT))
+    {
         return false;
+    }
 
     // byteAlignment
     RootedValue typeByteAlignment(cx, NumberValue(typeRepr->alignment()));
     if (!JSObject::defineProperty(cx, obj, cx->names().byteAlignment,
                                   typeByteAlignment,
                                   nullptr, nullptr,
                                   JSPROP_READONLY | JSPROP_PERMANENT))
+    {
         return false;
+    }
 
     // variable -- always false since we do not yet support variable-size types
     RootedValue variable(cx, JSVAL_FALSE);
     if (!JSObject::defineProperty(cx, obj, cx->names().variable,
                                   variable,
                                   nullptr, nullptr,
                                   JSPROP_READONLY | JSPROP_PERMANENT))
+    {
         return false;
+    }
 
     return true;
 }
 
 JSObject *
-ArrayType::create(JSContext *cx, HandleObject arrayTypeGlobal,
-                  HandleObject elementType, size_t length)
+ArrayType::create(JSContext *cx,
+                  HandleObject metaTypeObject,
+                  HandleObject elementType,
+                  size_t length)
 {
     JS_ASSERT(elementType);
     JS_ASSERT(IsBinaryType(elementType));
 
     TypeRepresentation *elementTypeRepr = typeRepresentation(elementType);
     RootedObject typeReprObj(
-        cx,
-        ArrayTypeRepresentation::Create(cx, elementTypeRepr, length));
+        cx, ArrayTypeRepresentation::Create(cx, elementTypeRepr, length));
     if (!typeReprObj)
         return nullptr;
 
-    RootedObject obj(cx, NewBuiltinClassInstance(cx, &ArrayType::class_));
+    RootedValue prototypeVal(cx);
+    if (!JSObject::getProperty(cx, metaTypeObject, metaTypeObject,
+                               cx->names().prototype,
+                               &prototypeVal))
+    {
+        return nullptr;
+    }
+    JS_ASSERT(prototypeVal.isObject()); // immutable binding
+
+    RootedObject obj(
+        cx, NewObjectWithClassProto(cx, &ArrayType::class_,
+                                    &prototypeVal.toObject(), cx->global()));
     if (!obj)
         return nullptr;
     obj->initFixedSlot(SLOT_TYPE_REPR, ObjectValue(*typeReprObj));
 
     RootedValue elementTypeVal(cx, ObjectValue(*elementType));
     if (!JSObject::defineProperty(cx, obj, cx->names().elementType,
                                   elementTypeVal, nullptr, nullptr,
                                   JSPROP_READONLY | JSPROP_PERMANENT))
@@ -905,19 +977,18 @@ ArrayType::create(JSContext *cx, HandleO
     if (!JSObject::defineProperty(cx, obj, cx->names().length,
                                   lengthVal, nullptr, nullptr,
                                   JSPROP_READONLY | JSPROP_PERMANENT))
         return nullptr;
 
     if (!InitializeCommonTypeDescriptorProperties(cx, obj, typeReprObj))
         return nullptr;
 
-    RootedObject prototypeObj(cx,
-        SetupAndGetPrototypeObjectForComplexTypeInstance(cx, arrayTypeGlobal));
-
+    RootedObject prototypeObj(
+        cx, CreateComplexTypeInstancePrototype(cx, metaTypeObject));
     if (!prototypeObj)
         return nullptr;
 
     if (!LinkConstructorAndPrototype(cx, obj, prototypeObj))
         return nullptr;
 
     JSFunction *fillFun = DefineFunctionWithReserved(cx, prototypeObj, "fill", ArrayFillSubarray, 1, 0);
     if (!fillFun)
@@ -979,36 +1050,53 @@ ArrayType::construct(JSContext *cx, unsi
         return false;
     args.rval().setObject(*obj);
     return true;
 }
 
 /*********************************
  * Structs
  *********************************/
+
 const Class StructType::class_ = {
     "StructType",
     JSCLASS_HAS_RESERVED_SLOTS(STRUCT_TYPE_RESERVED_SLOTS) |
-    JSCLASS_HAS_PRIVATE | // used to store FieldList
-    JSCLASS_HAS_CACHED_PROTO(JSProto_StructType),
+    JSCLASS_HAS_PRIVATE, // used to store FieldList
     JS_PropertyStub,
     JS_DeletePropertyStub,
     JS_PropertyStub,
     JS_StrictPropertyStub,
     JS_EnumerateStub,
     JS_ResolveStub,
     JS_ConvertStub,
     nullptr, /* finalize */
     nullptr, /* checkAccess */
     nullptr, /* call */
     nullptr, /* hasInstance */
     BinaryBlock::construct,
     nullptr  /* trace */
 };
 
+const JSPropertySpec StructType::typeObjectProperties[] = {
+    JS_PS_END
+};
+
+const JSFunctionSpec StructType::typeObjectMethods[] = {
+    JS_FN("toSource", StructType::toSource, 0, 0),
+    JS_FS_END
+};
+
+const JSPropertySpec StructType::typedObjectProperties[] = {
+    JS_PS_END
+};
+
+const JSFunctionSpec StructType::typedObjectMethods[] = {
+    JS_FS_END
+};
+
 static bool
 ConvertAndCopyStructTo(JSContext *cx,
                        StructTypeRepresentation *typeRepr,
                        HandleValue from,
                        uint8_t *mem)
 {
     if (!from.isObject()) {
         ReportCannotConvertTo(cx, from, typeRepr);
@@ -1087,45 +1175,43 @@ StructType::layout(JSContext *cx, Handle
         if (!fieldTypeReprObjs.append(typeRepresentationOwnerObj(fieldType))) {
             js_ReportOutOfMemory(cx);
             return false;
         }
     }
 
     // Construct the `TypeRepresentation*`.
     RootedObject typeReprObj(
-        cx,
-        StructTypeRepresentation::Create(cx, ids, fieldTypeReprObjs));
+        cx, StructTypeRepresentation::Create(cx, ids, fieldTypeReprObjs));
     if (!typeReprObj)
         return false;
     StructTypeRepresentation *typeRepr =
         TypeRepresentation::fromOwnerObject(typeReprObj)->asStruct();
-    structType->initFixedSlot(SLOT_TYPE_REPR, ObjectValue(*typeReprObj));
+    structType->initReservedSlot(SLOT_TYPE_REPR, ObjectValue(*typeReprObj));
 
     // Construct for internal use an array with the type object for each field.
     RootedObject fieldTypeVec(
-        cx,
-        NewDenseCopiedArray(cx, fieldTypeObjs.length(), fieldTypeObjs.begin()));
+        cx, NewDenseCopiedArray(cx, fieldTypeObjs.length(),
+                                fieldTypeObjs.begin()));
     if (!fieldTypeVec)
         return false;
 
     structType->initFixedSlot(SLOT_STRUCT_FIELD_TYPES,
                              ObjectValue(*fieldTypeVec));
 
     // Construct the fieldNames vector
     AutoValueVector fieldNameValues(cx);
     for (unsigned int i = 0; i < ids.length(); i++) {
         RootedValue value(cx, IdToValue(ids[i]));
         if (!fieldNameValues.append(value))
             return false;
     }
     RootedObject fieldNamesVec(
-        cx,
-        NewDenseCopiedArray(cx, fieldNameValues.length(),
-                            fieldNameValues.begin()));
+        cx, NewDenseCopiedArray(cx, fieldNameValues.length(),
+                                fieldNameValues.begin()));
     if (!fieldNamesVec)
         return false;
     RootedValue fieldNamesVecValue(cx, ObjectValue(*fieldNamesVec));
     if (!JSObject::defineProperty(cx, structType, cx->names().fieldNames,
                                   fieldNamesVecValue, nullptr, nullptr,
                                   JSPROP_READONLY | JSPROP_PERMANENT))
         return false;
 
@@ -1147,18 +1233,17 @@ StructType::layout(JSContext *cx, Handle
         RootedValue offset(cx, NumberValue(field.offset));
         if (!JSObject::defineGeneric(cx, fieldOffsets, fieldId,
                                      offset, nullptr, nullptr,
                                      JSPROP_READONLY | JSPROP_PERMANENT))
             return false;
 
         // fieldTypes[id] = typeObj
         if (!JSObject::defineGeneric(cx, fieldTypes, fieldId,
-                                     fieldTypeObjs.handleAt(i),
-                                     nullptr, nullptr,
+                                     fieldTypeObjs.handleAt(i), nullptr, nullptr,
                                      JSPROP_READONLY | JSPROP_PERMANENT))
             return false;
     }
 
     RootedValue fieldOffsetsValue(cx, ObjectValue(*fieldOffsets));
     if (!JSObject::defineProperty(cx, structType, cx->names().fieldOffsets,
                                   fieldOffsetsValue, nullptr, nullptr,
                                   JSPROP_READONLY | JSPROP_PERMANENT))
@@ -1169,37 +1254,45 @@ StructType::layout(JSContext *cx, Handle
                                   fieldTypesValue, nullptr, nullptr,
                                   JSPROP_READONLY | JSPROP_PERMANENT))
         return false;
 
     return true;
 }
 
 JSObject *
-StructType::create(JSContext *cx, HandleObject structTypeGlobal,
+StructType::create(JSContext *cx, HandleObject metaTypeObject,
                    HandleObject fields)
 {
-    RootedObject obj(cx, NewBuiltinClassInstance(cx, &StructType::class_));
+    RootedValue prototypeVal(cx);
+    if (!JSObject::getProperty(cx, metaTypeObject, metaTypeObject,
+                               cx->names().prototype,
+                               &prototypeVal))
+        return nullptr;
+    JS_ASSERT(prototypeVal.isObject()); // immutable binding
+
+    RootedObject obj(
+        cx, NewObjectWithClassProto(cx, &StructType::class_,
+                                    &prototypeVal.toObject(), cx->global()));
     if (!obj)
         return nullptr;
 
     if (!StructType::layout(cx, obj, fields))
         return nullptr;
 
     RootedObject fieldsProto(cx);
     if (!JSObject::getProto(cx, fields, &fieldsProto))
         return nullptr;
 
     RootedObject typeReprObj(cx, typeRepresentationOwnerObj(obj));
     if (!InitializeCommonTypeDescriptorProperties(cx, obj, typeReprObj))
         return nullptr;
 
-    RootedObject prototypeObj(cx,
-        SetupAndGetPrototypeObjectForComplexTypeInstance(cx, structTypeGlobal));
-
+    RootedObject prototypeObj(
+        cx, CreateComplexTypeInstancePrototype(cx, metaTypeObject));
     if (!prototypeObj)
         return nullptr;
 
     if (!LinkConstructorAndPrototype(cx, obj, prototypeObj))
         return nullptr;
 
     return obj;
 }
@@ -1211,19 +1304,19 @@ StructType::construct(JSContext *cx, uns
 
     if (!args.isConstructing()) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
                              JSMSG_NOT_FUNCTION, "StructType");
         return false;
     }
 
     if (args.length() >= 1 && args[0].isObject()) {
-        RootedObject structTypeGlobal(cx, &args.callee());
+        RootedObject metaTypeObject(cx, &args.callee());
         RootedObject fields(cx, &args[0].toObject());
-        RootedObject obj(cx, create(cx, structTypeGlobal, fields));
+        RootedObject obj(cx, create(cx, metaTypeObject, fields));
         if (!obj)
             return false;
         args.rval().setObject(*obj);
         return true;
     }
 
     JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
                          JSMSG_TYPEDOBJECT_STRUCTTYPE_BAD_ARGS);
@@ -1300,243 +1393,169 @@ Reify(JSContext *cx, TypeRepresentation 
         return ReifyScalar(cx, typeRepr->asScalar(), type, owner, offset, to);
       case TypeRepresentation::Struct:
       case TypeRepresentation::Array:
         return ReifyComplex(cx, type, owner, offset, to);
     }
     MOZ_ASSUME_UNREACHABLE("Invalid typeRepr kind");
 }
 
-bool
-GlobalObject::initDataObject(JSContext *cx, Handle<GlobalObject *> global)
-{
-    RootedObject DataProto(cx);
-    DataProto = NewObjectWithGivenProto(cx, &DataClass,
-                                        global->getOrCreateObjectPrototype(cx),
-                                        global, SingletonObject);
-    if (!DataProto)
-        return false;
-
-    RootedAtom DataName(cx, ClassName(JSProto_Data, cx));
-    RootedFunction DataCtor(cx,
-            global->createConstructor(cx, DataThrowError, DataName,
-                                      1, JSFunction::ExtendedFinalizeKind));
-
-    if (!DataCtor)
-        return false;
-
-    if (!JS_DefineFunction(cx, DataProto, "update", DataInstanceUpdate, 1, 0))
-        return false;
-
-    if (!LinkConstructorAndPrototype(cx, DataCtor, DataProto))
-        return false;
-
-    if (!DefineConstructorAndPrototype(cx, global, JSProto_Data,
-                                       DataCtor, DataProto))
-        return false;
-
-    global->setConstructor(JSProto_Data, ObjectValue(*DataCtor));
-    return true;
-}
-
-bool
-GlobalObject::initTypeObject(JSContext *cx, Handle<GlobalObject *> global)
-{
-    RootedObject TypeProto(cx, global->getOrCreateDataObject(cx));
-    if (!TypeProto)
-        return false;
-
-    RootedAtom TypeName(cx, ClassName(JSProto_Type, cx));
-    RootedFunction TypeCtor(cx,
-            global->createConstructor(cx, TypeThrowError, TypeName,
-                                      1, JSFunction::ExtendedFinalizeKind));
-    if (!TypeCtor)
-        return false;
-
-    if (!LinkConstructorAndPrototype(cx, TypeCtor, TypeProto))
-        return false;
+///////////////////////////////////////////////////////////////////////////
+// Creating the TypedObject "module"
+//
+// We create one global, `TypedObject`, which contains the following
+// members:
+//
+// 1. uint8, uint16, etc
+// 2. ArrayType
+// 3. StructType
+//
+// These are all callable/constructable objects whose [[Prototype]]s
+// are Function.prototype, but they are not functions in the JSAPI
+// sense (as in having the class JSFunction::class_).
+//
+// Each type object also has its own `prototype` field. Therefore,
+// using `StructType` as an example, the basic setup is as shown here
+// (each edge is labeled with a property name, and [[P]] is short for
+// [[Prototype]]):
+//
+//   StructType --[[P]]--> Function.[[P]]
+//        |
+//    prototype
+//        |
+//        v
+//       { } -----[[P]]--> Function.[[P]]
+//        |
+//    prototype
+//        |
+//        v
+//       { } -----[[P]]--> Object.[[P]]
+//
+// When a new type object (e.g., an instance of StructType) is created,
+// it will look as follows:
+//
+//   MyStruct -[[P]]-> StructType.prototype -[[P]]-> Function.[[P]]
+//        |
+//    prototype
+//        |
+//        v
+//       { } --[[P]]-> StructType.prototype.prototype
+//
+// Finally, when an instance of `MyStruct` is created, its
+// structure is as follows:
+//
+//    object -[[P]]--> MyStruct.prototype
+//
+// This structure permits users to install methods for all struct
+// types (by modifying StructType.prototype); for all struct instances
+// (by modifying StructType.prototype.prototype); or for all instances
+// of `MyStruct` specifically (MyStruct.prototype).
 
-    if (!DefineConstructorAndPrototype(cx, global, JSProto_Type,
-                                       TypeCtor, TypeProto))
-        return false;
-
-    global->setConstructor(JSProto_Type, ObjectValue(*TypeCtor));
-    return true;
-}
+template<ScalarTypeRepresentation::Type type>
+static bool
+DefineNumericClass(JSContext *cx, Handle<GlobalObject*> global,
+                   HandleObject module, HandlePropertyName className);
 
-bool
-GlobalObject::initArrayTypeObject(JSContext *cx, Handle<GlobalObject *> global)
-{
-    RootedFunction ctor(cx,
-        global->createConstructor(cx, ArrayType::construct,
-                                  cx->names().ArrayType, 2));
-
-    global->setConstructor(JSProto_ArrayTypeObject, ObjectValue(*ctor));
-    return true;
-}
-
-static JSObject *
-SetupComplexHeirarchy(JSContext *cx, Handle<GlobalObject*> global, JSProtoKey protoKey,
-                      HandleObject complexObject, MutableHandleObject proto,
-                      MutableHandleObject protoProto)
+JSObject *
+js_InitTypedObjectClass(JSContext *cx, HandleObject obj)
 {
-    // get the 'Type' constructor
-    RootedObject TypeObject(cx, global->getOrCreateTypeObject(cx));
-    if (!TypeObject)
-        return nullptr;
-
-    // Set complexObject.__proto__ = Type
-    if (!JS_SetPrototype(cx, complexObject, TypeObject))
-        return nullptr;
-
-    RootedObject DataObject(cx, global->getOrCreateDataObject(cx));
-    if (!DataObject)
-        return nullptr;
+    /*
+     * The initialization strategy for TypedObjects is mildly unusual
+     * compared to other classes. Because all of the types are members
+     * of a single global, `TypedObject`, we basically make the
+     * initialized for the `TypedObject` class populate the
+     * `TypedObject` global (which is referred to as "module" herein).
+     */
 
-    RootedValue DataProtoVal(cx);
-    if (!JSObject::getProperty(cx, DataObject, DataObject,
-                               cx->names().prototype, &DataProtoVal))
-        return nullptr;
-
-    RootedObject DataProto(cx, &DataProtoVal.toObject());
-    if (!DataProto)
-        return nullptr;
+    JS_ASSERT(obj->is<GlobalObject>());
+    Rooted<GlobalObject *> global(cx, &obj->as<GlobalObject>());
 
-    RootedObject prototypeObj(cx,
-        NewObjectWithGivenProto(cx, &JSObject::class_, nullptr, global));
-    if (!prototypeObj)
-        return nullptr;
-    if (!LinkConstructorAndPrototype(cx, complexObject, prototypeObj))
-        return nullptr;
-    if (!DefineConstructorAndPrototype(cx, global, protoKey,
-                                       complexObject, prototypeObj))
+    RootedObject objProto(cx, global->getOrCreateObjectPrototype(cx));
+    if (!objProto)
         return nullptr;
 
-    // Set complexObject.prototype.__proto__ = Data
-    if (!JS_SetPrototype(cx, prototypeObj, DataObject))
-        return nullptr;
+    RootedObject module(cx, NewObjectWithClassProto(cx, &JSObject::class_,
+                                                    objProto, global));
 
-    proto.set(prototypeObj);
+    // Define TypedObject global.
+
+    RootedValue moduleValue(cx, ObjectValue(*module));
+
+    // uint8, uint16, etc
 
-    // Set complexObject.prototype.prototype.__proto__ = Data.prototype
-    RootedObject prototypePrototypeObj(cx, JS_NewObject(cx, nullptr, nullptr,
-                                       global));
+#define BINARYDATA_NUMERIC_DEFINE(constant_, type_, name_)                      \
+    if (!DefineNumericClass<constant_>(cx, global, module, cx->names().name_))  \
+        return nullptr;
+    JS_FOR_EACH_SCALAR_TYPE_REPR(BINARYDATA_NUMERIC_DEFINE)
+#undef BINARYDATA_NUMERIC_DEFINE
 
-    if (!LinkConstructorAndPrototype(cx, prototypeObj,
-                                     prototypePrototypeObj))
-        return nullptr;
+    // ArrayType.
 
-    if (!JS_SetPrototype(cx, prototypePrototypeObj, DataProto))
+    RootedObject arrayType(cx, CreateMetaTypeObject<ArrayType>(cx, global));
+    if (!arrayType)
         return nullptr;
 
-    protoProto.set(prototypePrototypeObj);
+    RootedValue arrayTypeValue(cx, ObjectValue(*arrayType));
+    if (!JSObject::defineProperty(cx, module, cx->names().ArrayType,
+                                  arrayTypeValue,
+                                  nullptr, nullptr,
+                                  JSPROP_READONLY | JSPROP_PERMANENT))
+        return nullptr;
 
-    return complexObject;
-}
+    // StructType.
+
+    RootedObject structType(cx, CreateMetaTypeObject<StructType>(cx, global));
+    if (!structType)
+        return nullptr;
 
-static bool
-InitType(JSContext *cx, HandleObject globalObj)
-{
-    JS_ASSERT(globalObj->isNative());
-    Rooted<GlobalObject*> global(cx, &globalObj->as<GlobalObject>());
-    RootedObject ctor(cx, global->getOrCreateTypeObject(cx));
-    if (!ctor)
-        return false;
+    RootedValue structTypeValue(cx, ObjectValue(*structType));
+    if (!JSObject::defineProperty(cx, module, cx->names().StructType,
+                                  structTypeValue,
+                                  nullptr, nullptr,
+                                  JSPROP_READONLY | JSPROP_PERMANENT))
+        return nullptr;
 
-    RootedValue protoVal(cx);
-    if (!JSObject::getProperty(cx, ctor, ctor,
-                               cx->names().prototype, &protoVal))
-        return false;
+    // Everything is setup, install module on the global object:
+    if (!JSObject::defineProperty(cx, global, cx->names().TypedObject,
+                                  moduleValue,
+                                  nullptr, nullptr,
+                                  0))
+        return nullptr;
+    global->setReservedSlot(JSProto_TypedObject, moduleValue);
+    global->setArrayType(arrayType);
+    global->markStandardClassInitializedNoProto(&TypedObjectClass);
 
-    JS_ASSERT(protoVal.isObject());
-    RootedObject protoObj(cx, &protoVal.toObject());
-
-    if (!JS_DefineFunction(cx, protoObj, "equivalent", TypeEquivalent, 0, 0))
-        return false;
-
-    return true;
+    return module;
 }
 
-static bool
-InitArrayType(JSContext *cx, HandleObject globalObj)
+JSObject *
+js_InitTypedObjectDummy(JSContext *cx, HandleObject obj)
 {
-    JS_ASSERT(globalObj->isNative());
-    Rooted<GlobalObject*> global(cx, &globalObj->as<GlobalObject>());
-    RootedObject ctor(cx, global->getOrCreateArrayTypeObject(cx));
-    if (!ctor)
-        return false;
-
-    RootedObject proto(cx);
-    RootedObject protoProto(cx);
-    if (!SetupComplexHeirarchy(cx, global, JSProto_ArrayType,
-                               ctor, &proto, &protoProto))
-        return false;
-
-    if (!JS_DefineFunction(cx, proto, "repeat", ArrayRepeat, 1, 0))
-        return false;
-
-    if (!JS_DefineFunction(cx, proto, "toSource", ArrayType::toSource, 0, 0))
-        return false;
-
-    RootedObject arrayProto(cx);
-    if (!FindProto(cx, &ArrayObject::class_, &arrayProto))
-        return false;
-
-    RootedValue forEachFunVal(cx);
-    RootedAtom forEachAtom(cx, Atomize(cx, "forEach", 7));
-    RootedId forEachId(cx, AtomToId(forEachAtom));
-    if (!JSObject::getProperty(cx, arrayProto, arrayProto, forEachAtom->asPropertyName(), &forEachFunVal))
-        return false;
+    /*
+     * This function is entered into the jsprototypes.h table
+     * as the initializer for `TypedObject`. It should not
+     * be executed via the `standard_class_atoms` mechanism.
+     */
 
-    if (!JSObject::defineGeneric(cx, protoProto, forEachId, forEachFunVal, nullptr, nullptr, 0))
-        return false;
-
-    if (!JS_DefineFunction(cx, protoProto, "subarray",
-                           ArraySubarray, 1, 0))
-        return false;
-
-    return true;
-}
-
-static bool
-InitStructType(JSContext *cx, HandleObject obj)
-{
-    JS_ASSERT(obj->isNative());
-    Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
-    RootedFunction ctor(cx,
-        global->createConstructor(cx, StructType::construct,
-                                  cx->names().StructType, 1));
-
-    if (!ctor)
-        return false;
-
-    RootedObject proto(cx);
-    RootedObject protoProto(cx);
-    if (!SetupComplexHeirarchy(cx, global, JSProto_StructType,
-                               ctor, &proto, &protoProto))
-        return false;
-
-    if (!JS_DefineFunction(cx, proto, "toSource", StructType::toSource, 0, 0))
-        return false;
-
-    return true;
+    MOZ_ASSUME_UNREACHABLE("shouldn't be initializing TypedObject via the JSProtoKey initializer mechanism");
 }
 
 template<ScalarTypeRepresentation::Type type>
 static bool
 DefineNumericClass(JSContext *cx,
-                   HandleObject global,
-                   const char *name)
+                   Handle<GlobalObject*> global,
+                   HandleObject module,
+                   HandlePropertyName className)
 {
-    RootedObject globalProto(cx, JS_GetFunctionPrototype(cx, global));
-    RootedObject numFun(
-        cx,
-        JS_DefineObject(cx, global, name,
-                        (const JSClass *) &NumericTypeClasses[type],
-                        globalProto, 0));
+    RootedObject funcProto(cx, global->getOrCreateFunctionPrototype(cx));
+    if (!funcProto)
+        return false;
+
+    RootedObject numFun(cx, NewObjectWithClassProto(cx, &NumericTypeClasses[type],
+                                                    funcProto, global));
     if (!numFun)
         return false;
 
     RootedObject typeReprObj(cx, ScalarTypeRepresentation::Create(cx, type));
     if (!typeReprObj)
         return false;
 
     numFun->initFixedSlot(SLOT_TYPE_REPR, ObjectValue(*typeReprObj));
@@ -1545,55 +1564,37 @@ DefineNumericClass(JSContext *cx,
         return false;
 
     if (!JS_DefineFunction(cx, numFun, "toString",
                            NumericTypeToString<type>, 0, 0))
         return false;
 
     if (!JS_DefineFunction(cx, numFun, "toSource",
                            NumericTypeToString<type>, 0, 0))
+    {
+        return false;
+    }
+
+    RootedValue numFunValue(cx, ObjectValue(*numFun));
+    if (!JSObject::defineProperty(cx, module, className,
+                                  numFunValue, nullptr, nullptr, 0))
         return false;
 
     return true;
 }
 
-JSObject *
-js_InitTypedObjectClasses(JSContext *cx, HandleObject obj)
-{
-    JS_ASSERT(obj->is<GlobalObject>());
-    Rooted<GlobalObject *> global(cx, &obj->as<GlobalObject>());
-
-    if (!InitType(cx, obj))
-        return nullptr;
-
-#define BINARYDATA_NUMERIC_DEFINE(constant_, type_, name_)                    \
-    if (!DefineNumericClass<constant_>(cx, global, #name_))                   \
-        return nullptr;
-    JS_FOR_EACH_SCALAR_TYPE_REPR(BINARYDATA_NUMERIC_DEFINE)
-#undef BINARYDATA_NUMERIC_DEFINE
-
-    if (!InitArrayType(cx, obj))
-        return nullptr;
-
-    if (!InitStructType(cx, obj))
-        return nullptr;
-
-    return global;
-}
-
 ///////////////////////////////////////////////////////////////////////////
 // Binary blocks
 
 const Class BinaryBlock::class_ = {
     "BinaryBlock",
     Class::NON_NATIVE |
     JSCLASS_HAS_RESERVED_SLOTS(BLOCK_RESERVED_SLOTS) |
     JSCLASS_HAS_PRIVATE |
-    JSCLASS_IMPLEMENTS_BARRIERS |
-    JSCLASS_HAS_CACHED_PROTO(JSProto_ArrayType),
+    JSCLASS_IMPLEMENTS_BARRIERS,
     JS_PropertyStub,
     JS_DeletePropertyStub,
     JS_PropertyStub,
     JS_StrictPropertyStub,
     JS_EnumerateStub,
     JS_ResolveStub,
     JS_ConvertStub,
     BinaryBlock::obj_finalize,
@@ -1655,36 +1656,36 @@ ReportBlockTypeError(JSContext *cx,
 
     JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
                          errorNumber, typeReprStr);
 
     JS_free(cx, (void *) typeReprStr);
     return false;
 }
 
-/*static*/ void
+/* static */ void
 BinaryBlock::obj_trace(JSTracer *trace, JSObject *object)
 {
     JS_ASSERT(object->hasClass(&class_));
 
     for (size_t i = 0; i < BLOCK_RESERVED_SLOTS; i++)
         gc::MarkSlot(trace, &object->getReservedSlotRef(i), "BinaryBlockSlot");
 }
 
-/*static*/ void
+/* static */ void
 BinaryBlock::obj_finalize(js::FreeOp *op, JSObject *obj)
 {
     if (!obj->getFixedSlot(SLOT_BLOCKREFOWNER).isNull())
         return;
 
     if (void *mem = obj->getPrivate())
         op->free_(mem);
 }
 
-/*static*/ JSObject *
+/* static */ JSObject *
 BinaryBlock::createNull(JSContext *cx, HandleObject type, HandleValue owner)
 {
     JS_ASSERT(IsBinaryType(type));
 
     RootedValue protoVal(cx);
     if (!JSObject::getProperty(cx, type, type,
                                cx->names().prototype, &protoVal))
         return nullptr;
@@ -1703,17 +1704,17 @@ BinaryBlock::createNull(JSContext *cx, H
             if (!typeObj->addTypedObjectAddendum(cx, typeRepr))
                 return nullptr;
         }
     }
 
     return obj;
 }
 
-/*static*/ JSObject *
+/* static */ JSObject *
 BinaryBlock::createZeroed(JSContext *cx, HandleObject type)
 {
     RootedValue owner(cx, NullValue());
     RootedObject obj(cx, createNull(cx, type, owner));
     if (!obj)
         return nullptr;
 
     TypeRepresentation *typeRepr = typeRepresentation(type);
@@ -1721,34 +1722,34 @@ BinaryBlock::createZeroed(JSContext *cx,
     void *memory = JS_malloc(cx, memsize);
     if (!memory)
         return nullptr;
     memset(memory, 0, memsize);
     obj->setPrivate(memory);
     return obj;
 }
 
-/*static*/ JSObject *
+/* static */ JSObject *
 BinaryBlock::createDerived(JSContext *cx, HandleObject type,
                            HandleObject owner, size_t offset)
 {
     JS_ASSERT(IsBlock(owner));
     JS_ASSERT(offset <= BlockSize(cx, owner));
     JS_ASSERT(offset + TypeSize(type) <= BlockSize(cx, owner));
 
     RootedValue ownerValue(cx, ObjectValue(*owner));
     RootedObject obj(cx, createNull(cx, type, ownerValue));
     if (!obj)
         return nullptr;
 
     obj->setPrivate(BlockMem(owner) + offset);
     return obj;
 }
 
-/*static*/ bool
+/* static */ bool
 BinaryBlock::construct(JSContext *cx, unsigned int argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     RootedObject callee(cx, &args.callee());
     JS_ASSERT(IsBinaryType(callee));
 
     RootedObject obj(cx, createZeroed(cx, callee));
@@ -2269,30 +2270,27 @@ BinaryBlock::obj_enumerate(JSContext *cx
         }
         break;
 
       case TypeRepresentation::Array:
         switch (enum_op) {
           case JSENUMERATE_INIT_ALL:
           case JSENUMERATE_INIT:
             statep.setInt32(0);
-            idp.set(INT_TO_JSID(typeRepr->asArray()->length() + 1));
+            idp.set(INT_TO_JSID(typeRepr->asArray()->length()));
             break;
 
           case JSENUMERATE_NEXT:
             index = static_cast<int32_t>(statep.toInt32());
 
             if (index < typeRepr->asArray()->length()) {
                 idp.set(INT_TO_JSID(index));
                 statep.setInt32(index + 1);
-            } else if (index == typeRepr->asArray()->length()) {
-                idp.set(NameToId(cx->names().length));
-                statep.setInt32(index + 1);
             } else {
-                JS_ASSERT(index == typeRepr->asArray()->length() + 1);
+                JS_ASSERT(index == typeRepr->asArray()->length());
                 statep.setNull();
             }
 
             break;
 
           case JSENUMERATE_DESTROY:
             statep.setNull();
             break;
@@ -2329,9 +2327,8 @@ BinaryBlock::obj_enumerate(JSContext *cx
     return true;
 }
 
 /* static */ size_t
 BinaryBlock::dataOffset()
 {
     return JSObject::getPrivateDataOffset(BLOCK_RESERVED_SLOTS + 1);
 }
-
--- a/js/src/builtin/TypedObject.h
+++ b/js/src/builtin/TypedObject.h
@@ -8,16 +8,23 @@
 #define builtin_TypedObject_h
 
 #include "jsobj.h"
 
 #include "builtin/TypeRepresentation.h"
 
 namespace js {
 
+/*
+ * This object exists in order to encapsulate the typed object types
+ * somewhat, rather than sticking them all into the global object.
+ * Eventually it will go away and become a module.
+ */
+extern const Class TypedObjectClass;
+
 // Slots common to all type descriptors:
 enum TypeCommonSlots {
     // Canonical type representation of this type (see TypeRepresentation.h).
     SLOT_TYPE_REPR=0,
     TYPE_RESERVED_SLOTS
 };
 
 // Slots for ArrayType type descriptors:
@@ -42,48 +49,63 @@ enum BlockCommonSlots {
     // If this value is nullptr, then the block instance owns the
     // uint8_t* in its priate data. Otherwise, this field contains the
     // owner, and thus keeps the owner alive.
     SLOT_BLOCKREFOWNER,
 
     BLOCK_RESERVED_SLOTS
 };
 
-extern const Class DataClass;
-
-extern const Class TypeClass;
-
 template <ScalarTypeRepresentation::Type type, typename T>
 class NumericType
 {
   private:
     static const Class * typeToClass();
   public:
     static bool convert(JSContext *cx, HandleValue val, T* converted);
     static bool reify(JSContext *cx, void *mem, MutableHandleValue vp);
     static bool call(JSContext *cx, unsigned argc, Value *vp);
 };
 
+/*
+ * These are the classes of the scalar type descriptors, like `uint8`,
+ * `uint16` etc. Each of these classes has exactly one instance that
+ * is pre-created.
+ */
 extern const Class NumericTypeClasses[ScalarTypeRepresentation::TYPE_MAX];
 
 /*
  * Type descriptor created by `new ArrayType(...)`
  */
 class ArrayType : public JSObject
 {
   private:
   public:
     static const Class class_;
 
+    // Properties and methods to be installed on ArrayType.prototype,
+    // and hence inherited by all array type objects:
+    static const JSPropertySpec typeObjectProperties[];
+    static const JSFunctionSpec typeObjectMethods[];
+
+    // Properties and methods to be installed on ArrayType.prototype.prototype,
+    // and hence inherited by all array *typed* objects:
+    static const JSPropertySpec typedObjectProperties[];
+    static const JSFunctionSpec typedObjectMethods[];
+
+    // This is the function that gets called when the user
+    // does `new ArrayType(elem)`. It produces an array type object.
+    static bool construct(JSContext *cx, unsigned argc, Value *vp);
+
     static JSObject *create(JSContext *cx, HandleObject arrayTypeGlobal,
                             HandleObject elementType, size_t length);
-    static bool construct(JSContext *cx, unsigned int argc, jsval *vp);
-    static bool repeat(JSContext *cx, unsigned int argc, jsval *vp);
+    static bool repeat(JSContext *cx, unsigned argc, Value *vp);
+    static bool subarray(JSContext *cx, unsigned argc, Value *vp);
 
-    static bool toSource(JSContext *cx, unsigned int argc, jsval *vp);
+    static bool toSource(JSContext *cx, unsigned argc, Value *vp);
 
     static JSObject *elementType(JSContext *cx, HandleObject obj);
 };
 
 /*
  * Type descriptor created by `new StructType(...)`
  */
 class StructType : public JSObject
@@ -96,23 +118,35 @@ class StructType : public JSObject
      * and alignment and stores fieldmap as well.
      */
     static bool layout(JSContext *cx, HandleObject structType,
                        HandleObject fields);
 
   public:
     static const Class class_;
 
-    static bool toSource(JSContext *cx, unsigned int argc, jsval *vp);
+    // Properties and methods to be installed on StructType.prototype,
+    // and hence inherited by all struct type objects:
+    static const JSPropertySpec typeObjectProperties[];
+    static const JSFunctionSpec typeObjectMethods[];
+
+    // Properties and methods to be installed on StructType.prototype.prototype,
+    // and hence inherited by all struct *typed* objects:
+    static const JSPropertySpec typedObjectProperties[];
+    static const JSFunctionSpec typedObjectMethods[];
+
+    // This is the function that gets called when the user
+    // does `new StructType(...)`. It produces a struct type object.
+    static bool construct(JSContext *cx, unsigned argc, Value *vp);
+
+    static bool toSource(JSContext *cx, unsigned argc, Value *vp);
 
     static bool convertAndCopyTo(JSContext *cx,
                                  StructTypeRepresentation *typeRepr,
                                  HandleValue from, uint8_t *mem);
-
-    static bool construct(JSContext *cx, unsigned int argc, jsval *vp);
 };
 
 /* Binary data objects and handles */
 class BinaryBlock
 {
   private:
     // Creates a binary data object of the given type and class, but with
     // a nullptr memory pointer. Caller must use setPrivate() to set the
@@ -208,15 +242,15 @@ class BinaryBlock
     static JSObject *createZeroed(JSContext *cx, HandleObject type);
 
     // creates a block that aliases the memory owned by `owner` at the
     // given offset
     static JSObject *createDerived(JSContext *cx, HandleObject type,
                                    HandleObject owner, size_t offset);
 
     // user-accessible constructor (`new TypeDescriptor(...)`)
-    static bool construct(JSContext *cx, unsigned int argc, jsval *vp);
+    static bool construct(JSContext *cx, unsigned argc, Value *vp);
 };
 
 
 } // namespace js
 
 #endif /* builtin_TypedObject_h */
--- a/js/src/configure.in
+++ b/js/src/configure.in
@@ -2120,25 +2120,16 @@ AC_CACHE_VAL(ac_cv_siginfo_t,
                  [ac_cv_siginfo_t=false])])
 if test "$ac_cv_siginfo_t" = true ; then
   AC_DEFINE(HAVE_SIGINFO_T)
   AC_MSG_RESULT(yes)
 else
   AC_MSG_RESULT(no)
 fi
 
-MOZ_SIZE_OF_TYPE(JS_BYTES_PER_WORD, void*, 4 8)
-if test "$moz_cv_size_of_JS_BYTES_PER_WORD" -eq "4"; then
-  AC_DEFINE(JS_BITS_PER_WORD_LOG2, 5)
-elif test "$moz_cv_size_of_JS_BYTES_PER_WORD" -eq "8"; then
-  AC_DEFINE(JS_BITS_PER_WORD_LOG2, 6)
-else
-  AC_MSG_ERROR([Unexpected JS_BYTES_PER_WORD])
-fi
-
 MOZ_CHECK_HEADERS(endian.h)
 if test "$ac_cv_header_endian_h" = yes; then
     AC_DEFINE(JS_HAVE_ENDIAN_H)
 fi
 
 MOZ_CHECK_HEADERS([machine/endian.h],[],[],[#include <sys/types.h>])
 if test "$ac_cv_header_machine_endian_h" = yes; then
     AC_DEFINE(JS_HAVE_MACHINE_ENDIAN_H)
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -2404,29 +2404,29 @@ EmitSwitch(ExclusiveContext *cx, Bytecod
              * Check for duplicates, which require a JSOP_CONDSWITCH.
              * We bias i by 65536 if it's negative, and hope that's a rare
              * case (because it requires a malloc'd bitmap).
              */
             if (i < 0)
                 i += JS_BIT(16);
             if (i >= intmap_bitlen) {
                 if (!intmap &&
-                    i < (INTMAP_LENGTH << JS_BITS_PER_WORD_LOG2)) {
+                    size_t(i) < (INTMAP_LENGTH * JS_BITMAP_NBITS)) {
                     intmap = intmap_space;
-                    intmap_bitlen = INTMAP_LENGTH << JS_BITS_PER_WORD_LOG2;
+                    intmap_bitlen = INTMAP_LENGTH * JS_BITMAP_NBITS;
                 } else {
                     /* Just grab 8K for the worst-case bitmap. */
                     intmap_bitlen = JS_BIT(16);
-                    intmap = cx->pod_malloc<jsbitmap>(JS_BIT(16) >> JS_BITS_PER_WORD_LOG2);
+                    intmap = cx->pod_malloc<jsbitmap>(JS_BIT(16) / JS_BITMAP_NBITS);
                     if (!intmap) {
                         js_ReportOutOfMemory(cx);
                         return false;
                     }
                 }
-                memset(intmap, 0, intmap_bitlen >> JS_BITS_PER_BYTE_LOG2);
+                memset(intmap, 0, size_t(intmap_bitlen) / JS_BITMAP_NBITS);
             }
             if (JS_TEST_BIT(intmap, i)) {
                 switchOp = JSOP_CONDSWITCH;
                 continue;
             }
             JS_SET_BIT(intmap, i);
         }
 
--- a/js/src/frontend/FoldConstants.cpp
+++ b/js/src/frontend/FoldConstants.cpp
@@ -12,16 +12,17 @@
 #include "jslibmath.h"
 
 #include "frontend/ParseNode.h"
 #include "frontend/Parser.h"
 #include "vm/NumericConversions.h"
 
 #include "jscntxtinlines.h"
 #include "jsinferinlines.h"
+#include "jsobjinlines.h"
 
 using namespace js;
 using namespace js::frontend;
 
 using mozilla::IsNaN;
 using mozilla::IsNegative;
 using mozilla::NegativeInfinity;
 using mozilla::PositiveInfinity;
--- a/js/src/gc/RootMarking.cpp
+++ b/js/src/gc/RootMarking.cpp
@@ -10,16 +10,17 @@
 # include <valgrind/memcheck.h>
 #endif
 
 #include "jsapi.h"
 #include "jscntxt.h"
 #include "jsgc.h"
 #include "jsonparser.h"
 #include "jsprf.h"
+#include "jstypes.h"
 #include "jswatchpoint.h"
 
 #include "builtin/MapObject.h"
 #include "frontend/BytecodeCompiler.h"
 #include "gc/GCInternals.h"
 #include "gc/Marking.h"
 #ifdef JS_ION
 # include "jit/IonMacroAssembler.h"
--- a/js/src/jit-test/tests/TypedObject/fuzz1.js
+++ b/js/src/jit-test/tests/TypedObject/fuzz1.js
@@ -1,8 +1,10 @@
-if (!this.hasOwnProperty("Type"))
-  quit();
+// |jit-test| error:RangeError
+
+if (!this.hasOwnProperty("TypedObject"))
+  throw new RangeError();
 
 function eval() {
     yield(undefined)
 }
-new(StructType)
-(eval())
+new TypedObject.StructType();
+eval();
--- a/js/src/jit-test/tests/TypedObject/fuzz10.js
+++ b/js/src/jit-test/tests/TypedObject/fuzz10.js
@@ -1,8 +1,8 @@
 // |jit-test| error:Error
 
-if (!this.hasOwnProperty("Type"))
+if (!this.hasOwnProperty("TypedObject"))
   throw new Error("type too large");
 
-var AA = new ArrayType(new ArrayType(uint8, (2147483647)), 5);
+var AA = new TypedObject.ArrayType(new ArrayType(TypedObject.uint8, 2147483647), 5);
 var aa = new AA();
 var aa0 = aa[0];
--- a/js/src/jit-test/tests/TypedObject/fuzz11.js
+++ b/js/src/jit-test/tests/TypedObject/fuzz11.js
@@ -1,13 +1,13 @@
 // |jit-test| error:Error
 
-if (!this.hasOwnProperty("Type"))
+if (!this.hasOwnProperty("TypedObject"))
   throw new Error("type too large");
 
-var A = new ArrayType(uint8, (2147483647));
-var S = new StructType({a: A,
-                        b: A,
-                        c: A,
-                        d: A,
-                        e: A});
+var A = new TypedObject.ArrayType(TypedObject.uint8, 2147483647);
+var S = new TypedObject.StructType({a: A,
+                                    b: A,
+                                    c: A,
+                                    d: A,
+                                    e: A});
 var aa = new S();
 var aa0 = aa.a;
--- a/js/src/jit-test/tests/TypedObject/fuzz2.js
+++ b/js/src/jit-test/tests/TypedObject/fuzz2.js
@@ -1,4 +1,4 @@
-if (!this.hasOwnProperty("Type"))
+if (!this.hasOwnProperty("TypedObject"))
   quit();
 
-new StructType([])
+new TypedObject.StructType([]);
--- a/js/src/jit-test/tests/TypedObject/fuzz3.js
+++ b/js/src/jit-test/tests/TypedObject/fuzz3.js
@@ -1,7 +1,7 @@
 // |jit-test| error:RangeError;
 
-if (!this.hasOwnProperty("Type"))
+if (!this.hasOwnProperty("TypedObject"))
   throw new RangeError();
 
 this.__proto__ =  Proxy.create({});
-new StructType;
+new TypedObject.StructType;
--- a/js/src/jit-test/tests/TypedObject/fuzz4.js
+++ b/js/src/jit-test/tests/TypedObject/fuzz4.js
@@ -1,10 +1,10 @@
 // |jit-test| error:Error;
 
-if (!this.hasOwnProperty("Type"))
+if (!this.hasOwnProperty("TypedObject"))
   throw new Error();
 
-var A = new ArrayType(uint8, 10);
+var A = new TypedObject.ArrayType(TypedObject.uint8, 10);
 var a = new A();
 a.forEach(function(val, i) {
   assertEq(arguments[5], a);
 });
--- a/js/src/jit-test/tests/TypedObject/fuzz5.js
+++ b/js/src/jit-test/tests/TypedObject/fuzz5.js
@@ -1,6 +1,8 @@
-if (!this.hasOwnProperty("Type"))
+if (!this.hasOwnProperty("TypedObject"))
   quit();
 
-var Color = new StructType({r: uint8, g: uint8, b: uint8});
+var Color = new TypedObject.StructType({r: TypedObject.uint8,
+                                        g: TypedObject.uint8,
+                                        b: TypedObject.uint8});
 var white2 = new Color({r: 255, toString: null, b: 253});
 
--- a/js/src/jit-test/tests/TypedObject/fuzz6.js
+++ b/js/src/jit-test/tests/TypedObject/fuzz6.js
@@ -1,6 +1,6 @@
 // |jit-test| error:TypeError
 
-if (!this.hasOwnProperty("Type"))
+if (!this.hasOwnProperty("TypedObject"))
   throw new TypeError();
 
-new StructType(RegExp);
+new TypedObject.StructType(RegExp);
--- a/js/src/jit-test/tests/TypedObject/fuzz7.js
+++ b/js/src/jit-test/tests/TypedObject/fuzz7.js
@@ -1,4 +1,4 @@
-if (!this.hasOwnProperty("Type"))
+if (!this.hasOwnProperty("TypedObject"))
   quit();
 
-new StructType(RegExp());
+new TypedObject.StructType(RegExp());
--- a/js/src/jit-test/tests/TypedObject/fuzz8.js
+++ b/js/src/jit-test/tests/TypedObject/fuzz8.js
@@ -1,6 +1,6 @@
 // |jit-test| error:Error
 
-if (!this.hasOwnProperty("Type"))
+if (!this.hasOwnProperty("TypedObject"))
   throw new Error();
 
-new ArrayType(uint8, .0000000009);
+new TypedObject.ArrayType(TypedObject.uint8, .0000000009);
--- a/js/src/jit-test/tests/TypedObject/fuzz9.js
+++ b/js/src/jit-test/tests/TypedObject/fuzz9.js
@@ -1,10 +1,10 @@
 // |jit-test| error: TypeError
 
-if (!this.hasOwnProperty("Type"))
+if (!this.hasOwnProperty("TypedObject"))
   throw new TypeError();
 
-var Vec3 = new ArrayType(float32, 3);
-var Sprite = new ArrayType(Vec3, 3);
+var Vec3 = new TypedObject.ArrayType(TypedObject.float32, 3);
+var Sprite = new TypedObject.ArrayType(Vec3, 3);
 var mario = new Sprite();
 mario[/\u00ee[]/] = new Vec3([1, 0, 0]);
 
--- a/js/src/jit-test/tests/TypedObject/jit-complex.js
+++ b/js/src/jit-test/tests/TypedObject/jit-complex.js
@@ -1,18 +1,18 @@
 // Test that we can optimize stuff like line.target.x without
 // creating an intermediate object.
 
-if (!this.hasOwnProperty("Type"))
+if (!this.hasOwnProperty("TypedObject"))
   quit();
 
-var PointType = new StructType({x: float64,
-                                y: float64});
-var LineType = new StructType({source: PointType,
-                               target: PointType});
+var PointType = new TypedObject.StructType({x: TypedObject.float64,
+                                            y: TypedObject.float64});
+var LineType = new TypedObject.StructType({source: PointType,
+                                           target: PointType});
 
 function manhattenDistance(line) {
   return (Math.abs(line.target.x - line.source.x) +
           Math.abs(line.target.y - line.source.y));
 }
 
 function foo() {
   var N = 30000;
--- a/js/src/jit-test/tests/TypedObject/jit-prefix.js
+++ b/js/src/jit-test/tests/TypedObject/jit-prefix.js
@@ -1,17 +1,21 @@
-if (!this.hasOwnProperty("Type"))
+if (!this.hasOwnProperty("TypedObject"))
   quit();
 
-var PointType2 = new StructType({x: float64,
-                                 y: float64});
+var PointType2 =
+  new TypedObject.StructType({
+    x: TypedObject.float64,
+    y: TypedObject.float64});
 
-var PointType3 = new StructType({x: float64,
-                                 y: float64,
-                                 z: float64});
+var PointType3 =
+  new TypedObject.StructType({
+    x: TypedObject.float64,
+    y: TypedObject.float64,
+    z: TypedObject.float64});
 
 function xPlusY(p) {
   return p.x + p.y;
 }
 
 function xPlusYTweak(p) {
   p.x = 22;
   return xPlusY(p);
--- a/js/src/jit-test/tests/TypedObject/jit-read-float64.js
+++ b/js/src/jit-test/tests/TypedObject/jit-read-float64.js
@@ -1,14 +1,14 @@
-if (!this.hasOwnProperty("Type"))
+if (!this.hasOwnProperty("TypedObject"))
   quit();
 
-var PointType = new StructType({x: float64,
-                                y: float64,
-                                z: float64});
+var PointType = new TypedObject.StructType({x: TypedObject.float64,
+                                            y: TypedObject.float64,
+                                            z: TypedObject.float64});
 
 function foo() {
   for (var i = 0; i < 30000; i += 3) {
     var pt = new PointType({x: i, y: i+1, z: i+2});
     var sum = pt.x + pt.y + pt.z;
     print(pt.x, pt.y, pt.z);
     assertEq(sum, 3*i + 3);
   }
--- a/js/src/jit-test/tests/TypedObject/jit-read-int.js
+++ b/js/src/jit-test/tests/TypedObject/jit-read-int.js
@@ -1,14 +1,14 @@
-if (!this.hasOwnProperty("Type"))
+if (!this.hasOwnProperty("TypedObject"))
   quit();
 
-var PointType = new StructType({x: uint32,
-                                y: uint32,
-                                z: uint32});
+var PointType = new TypedObject.StructType({x: TypedObject.uint32,
+                                            y: TypedObject.uint32,
+                                            z: TypedObject.uint32});
 
 function foo() {
   for (var i = 0; i < 30000; i += 3) {
     var pt = new PointType({x: i, y: i+1, z: i+2});
     var sum = pt.x + pt.y + pt.z;
     assertEq(sum, 3*i + 3);
   }
 }
--- a/js/src/jit/AsmJS.cpp
+++ b/js/src/jit/AsmJS.cpp
@@ -25,16 +25,17 @@
 #include "jit/MIR.h"
 #include "jit/MIRGraph.h"
 #ifdef JS_ION_PERF
 # include "jit/PerfSpewer.h"
 #endif
 #include "vm/Interpreter.h"
 
 #include "jsinferinlines.h"
+#include "jsobjinlines.h"
 
 #include "frontend/ParseNode-inl.h"
 #include "frontend/Parser-inl.h"
 
 using namespace js;
 using namespace js::frontend;
 using namespace js::jit;
 
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -1,18 +1,21 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "jit/BaselineIC.h"
 
+#include "mozilla/TemplateLib.h"
+
 #include "jsautooplen.h"
 #include "jslibmath.h"
+#include "jstypes.h"
 
 #include "builtin/Eval.h"
 #include "jit/BaselineHelpers.h"
 #include "jit/BaselineJIT.h"
 #include "jit/IonLinker.h"
 #include "jit/IonSpewer.h"
 #include "jit/Lowering.h"
 #ifdef JS_ION_PERF
@@ -4490,17 +4493,19 @@ ICGetElem_Arguments::Compiler::generateS
     // Load ArgumentsData
     masm.loadPrivate(Address(objReg, ArgumentsObject::getDataSlotOffset()), argData);
 
     // Load deletedBits bitArray pointer into scratchReg
     masm.loadPtr(Address(argData, offsetof(ArgumentsData, deletedBits)), scratchReg);
 
     // In tempReg, calculate index of word containing bit: (idx >> logBitsPerWord)
     masm.movePtr(idxReg, tempReg);
-    masm.rshiftPtr(Imm32(JS_BITS_PER_WORD_LOG2), tempReg);
+    const uint32_t shift = mozilla::tl::FloorLog2<(sizeof(size_t) * JS_BITS_PER_BYTE)>::value;
+    JS_ASSERT(shift == 5 || shift == 6);
+    masm.rshiftPtr(Imm32(shift), tempReg);
     masm.loadPtr(BaseIndex(scratchReg, tempReg, ScaleFromElemWidth(sizeof(size_t))), scratchReg);
 
     // Don't bother testing specific bit, if any bit is set in the word, fail.
     masm.branchPtr(Assembler::NotEqual, scratchReg, ImmPtr(nullptr), &failureReconstructInputs);
 
     // Load the value.  use scratchReg and tempReg to form a ValueOperand to load into.
     masm.addPtr(Imm32(ArgumentsData::offsetOfArgs()), argData);
     regs.add(scratchReg);
--- a/js/src/jit/Ion.cpp
+++ b/js/src/jit/Ion.cpp
@@ -39,16 +39,17 @@
 #include "jit/StupidAllocator.h"
 #include "jit/UnreachableCodeElimination.h"
 #include "jit/ValueNumbering.h"
 #include "vm/ForkJoin.h"
 
 #include "jscompartmentinlines.h"
 #include "jsgcinlines.h"
 #include "jsinferinlines.h"
+#include "jsobjinlines.h"
 
 using namespace js;
 using namespace js::jit;
 
 // Global variables.
 IonOptions jit::js_IonOptions;
 
 // Assert that IonCode is gc::Cell aligned.
--- a/js/src/jit/IonAnalysis.cpp
+++ b/js/src/jit/IonAnalysis.cpp
@@ -11,16 +11,17 @@
 #include "jit/BaselineInspector.h"
 #include "jit/Ion.h"
 #include "jit/IonBuilder.h"
 #include "jit/LIR.h"
 #include "jit/Lowering.h"
 #include "jit/MIRGraph.h"
 
 #include "jsinferinlines.h"
+#include "jsobjinlines.h"
 
 using namespace js;
 using namespace js::jit;
 
 using mozilla::DebugOnly;
 
 // A critical edge is an edge which is neither its successor's only predecessor
 // nor its predecessor's only successor. Critical edges must be split to
--- a/js/src/jit/IonCaches.cpp
+++ b/js/src/jit/IonCaches.cpp
@@ -2,18 +2,20 @@
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "jit/IonCaches.h"
 
 #include "mozilla/DebugOnly.h"
+#include "mozilla/TemplateLib.h"
 
 #include "jsproxy.h"
+#include "jstypes.h"
 
 #include "builtin/TypeRepresentation.h"
 #include "jit/Ion.h"
 #include "jit/IonLinker.h"
 #include "jit/IonSpewer.h"
 #include "jit/Lowering.h"
 #ifdef JS_ION_PERF
 # include "jit/PerfSpewer.h"
@@ -25,16 +27,17 @@
 #include "jit/IonFrames-inl.h"
 #include "vm/Interpreter-inl.h"
 #include "vm/Shape-inl.h"
 
 using namespace js;
 using namespace js::jit;
 
 using mozilla::DebugOnly;
+using mozilla::tl::FloorLog2;
 
 void
 CodeLocationJump::repoint(IonCode *code, MacroAssembler *masm)
 {
     JS_ASSERT(state_ == Relative);
     size_t new_off = (size_t)raw_;
 #ifdef JS_SMALL_BRANCH
     size_t jumpTableEntryOffset = reinterpret_cast<size_t>(jumpTableEntry_);
@@ -3271,17 +3274,19 @@ GetElementIC::attachArgumentsElement(JSC
     Label failurePopIndex;
     masm.push(indexReg);
 
     // Check if property was deleted on arguments object.
     masm.loadPrivate(Address(object(), ArgumentsObject::getDataSlotOffset()), tmpReg);
     masm.loadPtr(Address(tmpReg, offsetof(ArgumentsData, deletedBits)), tmpReg);
 
     // In tempReg, calculate index of word containing bit: (idx >> logBitsPerWord)
-    masm.rshiftPtr(Imm32(JS_BITS_PER_WORD_LOG2), indexReg);
+    const uint32_t shift = FloorLog2<(sizeof(size_t) * JS_BITS_PER_BYTE)>::value;
+    JS_ASSERT(shift == 5 || shift == 6);
+    masm.rshiftPtr(Imm32(shift), indexReg);
     masm.loadPtr(BaseIndex(tmpReg, indexReg, ScaleFromElemWidth(sizeof(size_t))), tmpReg);
 
     // Don't bother testing specific bit, if any bit is set in the word, fail.
     masm.branchPtr(Assembler::NotEqual, tmpReg, ImmPtr(nullptr), &failurePopIndex);
 
     // Get the address to load from into tmpReg
     masm.loadPrivate(Address(object(), ArgumentsObject::getDataSlotOffset()), tmpReg);
     masm.addPtr(Imm32(ArgumentsData::offsetOfArgs()), tmpReg);
--- a/js/src/jit/IonCode.h
+++ b/js/src/jit/IonCode.h
@@ -6,16 +6,17 @@
 
 #ifndef jit_IonCode_h
 #define jit_IonCode_h
 
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/PodOperations.h"
 
 #include "jsinfer.h"
+#include "jstypes.h"
 
 #include "gc/Heap.h"
 #include "jit/IonTypes.h"
 
 namespace JSC {
     class ExecutablePool;
 }
 
--- a/js/src/jit/IonMacroAssembler.cpp
+++ b/js/src/jit/IonMacroAssembler.cpp
@@ -18,16 +18,17 @@
 #include "jit/MIR.h"
 #include "jit/ParallelFunctions.h"
 #include "vm/ForkJoin.h"
 
 #ifdef JSGC_GENERATIONAL
 # include "jsgcinlines.h"
 #endif
 #include "jsinferinlines.h"
+#include "jsobjinlines.h"
 
 using namespace js;
 using namespace js::jit;
 
 using JS::GenericNaN;
 
 namespace {
 
--- a/js/src/jit/Lowering.cpp
+++ b/js/src/jit/Lowering.cpp
@@ -11,16 +11,17 @@
 #include "jsanalyze.h"
 
 #include "jit/IonSpewer.h"
 #include "jit/LIR.h"
 #include "jit/MIR.h"
 #include "jit/MIRGraph.h"
 
 #include "jsinferinlines.h"
+#include "jsobjinlines.h"
 
 #include "jit/shared/Lowering-shared-inl.h"
 
 using namespace js;
 using namespace jit;
 
 using mozilla::DebugOnly;
 using JS::GenericNaN;
--- a/js/src/jit/ParallelFunctions.cpp
+++ b/js/src/jit/ParallelFunctions.cpp
@@ -561,14 +561,14 @@ jit::InitRestParameterPar(ForkJoinSlice 
     JS_ASSERT(!res->getDenseInitializedLength());
     JS_ASSERT(res->type() == templateObj->type());
 
     if (length > 0) {
         JSObject::EnsureDenseResult edr =
             res->ensureDenseElementsPreservePackedFlag(slice, 0, length);
         if (edr != JSObject::ED_OK)
             return nullptr;
-        res->initDenseElements(0, rest, length);
+        res->initDenseElementsUnbarriered(0, rest, length);
         res->as<ArrayObject>().setLengthInt32(length);
     }
 
     return res;
 }
--- a/js/src/jit/ParallelSafetyAnalysis.cpp
+++ b/js/src/jit/ParallelSafetyAnalysis.cpp
@@ -10,16 +10,17 @@
 #include "jit/IonAnalysis.h"
 #include "jit/IonSpewer.h"
 #include "jit/MIR.h"
 #include "jit/MIRGenerator.h"
 #include "jit/MIRGraph.h"
 #include "jit/UnreachableCodeElimination.h"
 
 #include "jsinferinlines.h"
+#include "jsobjinlines.h"
 
 using namespace js;
 using namespace jit;
 
 using parallel::Spew;
 using parallel::SpewMIR;
 using parallel::SpewCompile;
 
--- a/js/src/jit/StupidAllocator.cpp
+++ b/js/src/jit/StupidAllocator.cpp
@@ -1,16 +1,18 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "jit/StupidAllocator.h"
 
+#include "jstypes.h"
+
 using namespace js;
 using namespace js::jit;
 
 static inline uint32_t
 DefaultStackSlot(uint32_t vreg)
 {
 #if JS_BITS_PER_WORD == 32
     return vreg * 2 + 2;
--- a/js/src/js-config.h.in
+++ b/js/src/js-config.h.in
@@ -29,17 +29,13 @@
 /* Define to 1 if the <machine/endian.h> header is present and
    useable.  See jscpucfg.h.  */
 #undef JS_HAVE_MACHINE_ENDIAN_H
 
 /* Define to 1 if the <sys/isa_defs.h> header is present and
    useable.  See jscpucfg.h.  */
 #undef JS_HAVE_SYS_ISA_DEFS_H
 
-/* The configure script defines these if it doesn't #define
-   JS_HAVE_STDINT_H.  */
-#undef JS_BYTES_PER_WORD
-
 /* MOZILLA JSAPI version number components */
 #undef MOZJS_MAJOR_VERSION
 #undef MOZJS_MINOR_VERSION
 
 #endif /* js_config_h */
--- a/js/src/jsanalyze.cpp
+++ b/js/src/jsanalyze.cpp
@@ -10,16 +10,17 @@
 #include "mozilla/MathAlgorithms.h"
 #include "mozilla/PodOperations.h"
 
 #include "jsautooplen.h"
 #include "jscntxt.h"
 #include "jscompartment.h"
 
 #include "jsinferinlines.h"
+#include "jsobjinlines.h"
 
 using namespace js;
 using namespace js::analyze;
 
 using mozilla::DebugOnly;
 using mozilla::PodCopy;
 using mozilla::PodZero;
 using mozilla::FloorLog2;
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -1428,17 +1428,17 @@ static const JSStdName standard_class_at
 #ifdef ENABLE_PARALLEL_JS
     {js_InitParallelArrayClass,         EAGER_ATOM_AND_OCLASP(ParallelArray)},
 #endif
     {js_InitProxyClass,                 EAGER_CLASS_ATOM(Proxy), &ProxyObject::uncallableClass_},
 #if EXPOSE_INTL_API
     {js_InitIntlClass,                  EAGER_ATOM_AND_CLASP(Intl)},
 #endif
 #ifdef ENABLE_BINARYDATA
-    {js_InitTypedObjectClasses,         EAGER_ATOM_AND_CLASP(Type)},
+    {js_InitTypedObjectClass,           EAGER_ATOM_AND_CLASP(TypedObject)},
 #endif
     {nullptr,                           0, nullptr}
 };
 
 /*
  * Table of top-level function and constant names and their init functions.
  * If you add a "standard" global function or property, remember to update
  * this table.
@@ -1486,27 +1486,16 @@ static const JSStdName standard_class_na
     {js_InitTypedArrayClasses,  EAGER_CLASS_ATOM(Int32Array),   TYPED_ARRAY_CLASP(TYPE_INT32)},
     {js_InitTypedArrayClasses,  EAGER_CLASS_ATOM(Uint32Array),  TYPED_ARRAY_CLASP(TYPE_UINT32)},
     {js_InitTypedArrayClasses,  EAGER_CLASS_ATOM(Float32Array), TYPED_ARRAY_CLASP(TYPE_FLOAT32)},
     {js_InitTypedArrayClasses,  EAGER_CLASS_ATOM(Float64Array), TYPED_ARRAY_CLASP(TYPE_FLOAT64)},
     {js_InitTypedArrayClasses,  EAGER_CLASS_ATOM(Uint8ClampedArray),
                                 TYPED_ARRAY_CLASP(TYPE_UINT8_CLAMPED)},
     {js_InitTypedArrayClasses,  EAGER_CLASS_ATOM(DataView),     &DataViewObject::class_},
 
-    /* Binary Data */
-#ifdef ENABLE_BINARYDATA
-    {js_InitTypedObjectClasses,   EAGER_ATOM_AND_CLASP(Type)},
-    {js_InitTypedObjectClasses,   EAGER_ATOM_AND_CLASP(Data)},
-#define BINARYDATA_NUMERIC_NAMES(constant_, type_, name_) \
-    {js_InitTypedObjectClasses,   EAGER_CLASS_ATOM(name_),      &NumericTypeClasses[constant_]},
-    JS_FOR_EACH_SCALAR_TYPE_REPR(BINARYDATA_NUMERIC_NAMES)
-#undef BINARYDATA_NUMERIC_NAMES
-    {js_InitTypedObjectClasses,   EAGER_CLASS_ATOM(ArrayType),  &js::ArrayType::class_},
-    {js_InitTypedObjectClasses,   EAGER_CLASS_ATOM(StructType), &js::StructType::class_},
-#endif
     {nullptr,                     0, nullptr}
 };
 
 static const JSStdName object_prototype_names[] = {
     /* Object.prototype properties (global delegates to Object.prototype). */
     {js_InitObjectClass,        EAGER_ATOM(proto), &JSObject::class_},
 #if JS_HAS_TOSOURCE
     {js_InitObjectClass,        EAGER_ATOM(toSource), &JSObject::class_},
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -112,16 +112,22 @@ JSCompartment::sweepCallsiteClones()
 JSFunction *
 js::CloneFunctionAtCallsite(JSContext *cx, HandleFunction fun, HandleScript script, jsbytecode *pc)
 {
     JS_ASSERT(cx->typeInferenceEnabled());
     JS_ASSERT(fun->nonLazyScript()->shouldCloneAtCallsite);
     JS_ASSERT(!fun->nonLazyScript()->enclosingStaticScope());
     JS_ASSERT(types::UseNewTypeForClone(fun));
 
+    /*
+     * If we start allocating function objects in the nursery, then the callsite
+     * clone table will need a postbarrier.
+     */
+    JS_ASSERT(fun->isTenured());
+
     typedef CallsiteCloneKey Key;
     typedef CallsiteCloneTable Table;
 
     Table &table = cx->compartment()->callsiteClones;
     if (!table.initialized() && !table.init())
         return nullptr;
 
     uint32_t offset = pc - script->code;
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -23,16 +23,17 @@
 #include "js/RootingAPI.h"
 #include "vm/StopIterationObject.h"
 #include "vm/WrapperObject.h"
 
 #include "jsatominlines.h"
 #include "jsfuninlines.h"
 #include "jsgcinlines.h"
 #include "jsinferinlines.h"
+#include "jsobjinlines.h"
 
 using namespace js;
 using namespace js::gc;
 
 using mozilla::DebugOnly;
 
 JSCompartment::JSCompartment(Zone *zone, const JS::CompartmentOptions &options = JS::CompartmentOptions())
   : options_(options),
--- a/js/src/jscpucfg.h
+++ b/js/src/jscpucfg.h
@@ -9,32 +9,28 @@
 
 #define JS_HAVE_LONG_LONG
 
 #if defined(_WIN64)
 
 # if defined(_M_X64) || defined(_M_AMD64) || defined(_AMD64_)
 #  define IS_LITTLE_ENDIAN 1
 #  undef  IS_BIG_ENDIAN
-#  define JS_BYTES_PER_WORD   8
-#  define JS_BITS_PER_WORD_LOG2   6
 # else  /* !(defined(_M_X64) || defined(_M_AMD64) || defined(_AMD64_)) */
 #  error "CPU type is unknown"
 # endif /* !(defined(_M_X64) || defined(_M_AMD64) || defined(_AMD64_)) */
 
 #elif defined(_WIN32) || defined(XP_OS2)
 
 # ifdef __WATCOMC__
 #  define HAVE_VA_LIST_AS_ARRAY 1
 # endif
 
 # define IS_LITTLE_ENDIAN 1
 # undef  IS_BIG_ENDIAN
-# define JS_BYTES_PER_WORD   4
-# define JS_BITS_PER_WORD_LOG2   5
 
 #elif defined(__APPLE__)
 # if __LITTLE_ENDIAN__
 #  define IS_LITTLE_ENDIAN 1
 #  undef  IS_BIG_ENDIAN
 # elif __BIG_ENDIAN__
 #  undef  IS_LITTLE_ENDIAN
 #  define IS_BIG_ENDIAN 1
--- a/js/src/jscrashreport.cpp
+++ b/js/src/jscrashreport.cpp
@@ -41,40 +41,42 @@ GetStack(uint64_t *stack, uint64_t *stac
 
     if (len > size)
         len = size;
 
     *stack = p;
     *stack_len = len;
 
     /* Get the register state. */
-#if defined(_MSC_VER) && JS_BITS_PER_WORD == 32
+#if defined(_MSC_VER) && defined(_M_IX86)
     /* ASM version for win2k that doesn't support RtlCaptureContext */
     uint32_t vip, vsp, vbp;
     __asm {
     Label:
         mov [vbp], ebp;
         mov [vsp], esp;
         mov eax, [Label];
         mov [vip], eax;
     }
     regs->ip = vip;
     regs->sp = vsp;
     regs->bp = vbp;
 #else
     CONTEXT context;
     RtlCaptureContext(&context);
-#if JS_BITS_PER_WORD == 32
+#if defined(_M_IX86)
     regs->ip = context.Eip;
     regs->sp = context.Esp;
     regs->bp = context.Ebp;
-#else
+#elif defined(_M_X64)
     regs->ip = context.Rip;
     regs->sp = context.Rsp;
     regs->bp = context.Rbp;
+#else
+#error unknown cpu architecture
 #endif
 #endif
 
     js_memcpy(buffer, (void *)p, len);
 
     return true;
 }
 
@@ -109,24 +111,26 @@ GetStack(uint64_t *stack, uint64_t *stac
     *stack = p;
     *stack_len = len;
 
     /* Get the register state. */
     ucontext_t context;
     if (getcontext(&context) != 0)
 	return false;
 
-#if JS_BITS_PER_WORD == 64
+#if defined(__x86_64__)
     regs->sp = (uint64_t)context.uc_mcontext.gregs[REG_RSP];
     regs->bp = (uint64_t)context.uc_mcontext.gregs[REG_RBP];
     regs->ip = (uint64_t)context.uc_mcontext.gregs[REG_RIP];
-#elif JS_BITS_PER_WORD == 32
+#elif defined(__i386__)
     regs->sp = (uint64_t)context.uc_mcontext.gregs[REG_ESP];
     regs->bp = (uint64_t)context.uc_mcontext.gregs[REG_EBP];
     regs->ip = (uint64_t)context.uc_mcontext.gregs[REG_EIP];
+#else
+#error unknown cpu architecture
 #endif
 
     js_memcpy(buffer, (void *)p, len);
 
     return true;
 }
 
 #else
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -1487,17 +1487,17 @@ JSID_IS_ATOM(jsid id, JSAtom *atom)
 }
 
 static JS_ALWAYS_INLINE JSAtom *
 JSID_TO_ATOM(jsid id)
 {
     return (JSAtom *)JSID_TO_STRING(id);
 }
 
-JS_STATIC_ASSERT(sizeof(jsid) == JS_BYTES_PER_WORD);
+JS_STATIC_ASSERT(sizeof(jsid) == sizeof(void*));
 
 namespace js {
 
 static JS_ALWAYS_INLINE JS::Value
 IdToValue(jsid id)
 {
     if (JSID_IS_STRING(id))
         return JS::StringValue(JSID_TO_STRING(id));
--- a/js/src/jsfun.h
+++ b/js/src/jsfun.h
@@ -8,16 +8,17 @@
 #define jsfun_h
 
 /*
  * JS function definitions.
  */
 
 #include "jsobj.h"
 #include "jsscript.h"
+#include "jstypes.h"
 
 namespace js {
 class FunctionExtended;
 
 typedef JSNative           Native;
 typedef JSParallelNative   ParallelNative;
 typedef JSThreadSafeNative ThreadSafeNative;
 }
--- a/js/src/jsinfer.h
+++ b/js/src/jsinfer.h
@@ -8,16 +8,17 @@
 
 #ifndef jsinfer_h
 #define jsinfer_h
 
 #include "mozilla/MemoryReporting.h"
 
 #include "jsalloc.h"
 #include "jsfriendapi.h"
+#include "jstypes.h"
 
 #include "ds/IdValuePair.h"
 #include "ds/LifoAlloc.h"
 #include "gc/Barrier.h"
 #include "gc/Marking.h"
 #include "js/Utility.h"
 #include "js/Vector.h"
 
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -662,17 +662,34 @@ class JSObject : public js::ObjectImpl
             memcpy(&elements[dstStart], src, count * sizeof(js::HeapSlot));
             DenseRangeWriteBarrierPost(rt, this, dstStart, count);
         }
     }
 
     void initDenseElements(uint32_t dstStart, const js::Value *src, uint32_t count) {
         JS_ASSERT(dstStart + count <= getDenseCapacity());
         memcpy(&elements[dstStart], src, count * sizeof(js::HeapSlot));
-        DenseRangeWriteBarrierPost(runtimeFromAnyThread(), this, dstStart, count);
+        DenseRangeWriteBarrierPost(runtimeFromMainThread(), this, dstStart, count);
+    }
+
+    void initDenseElementsUnbarriered(uint32_t dstStart, const js::Value *src, uint32_t count) {
+        /*
+         * For use by parallel threads, which since they cannot see nursery
+         * things do not require a barrier.
+         */
+        JS_ASSERT(dstStart + count <= getDenseCapacity());
+#if defined(DEBUG) && defined(JSGC_GENERATIONAL)
+        JS::shadow::Runtime *rt = JS::shadow::Runtime::asShadowRuntime(runtimeFromAnyThread());
+        for (uint32_t index = 0; index < count; ++index) {
+            const JS::Value& value = src[index];
+            if (value.isMarkable())
+                JS_ASSERT(js::gc::IsInsideNursery(rt, value.toGCThing()));
+        }
+#endif
+        memcpy(&elements[dstStart], src, count * sizeof(js::HeapSlot));
     }
 
     void moveDenseElements(uint32_t dstStart, uint32_t srcStart, uint32_t count) {
         JS_ASSERT(dstStart + count <= getDenseCapacity());
         JS_ASSERT(srcStart + count <= getDenseInitializedLength());
 
         /*
          * Using memmove here would skip write barriers. Also, we need to consider
--- a/js/src/jsopcode.cpp
+++ b/js/src/jsopcode.cpp
@@ -37,16 +37,17 @@
 #include "js/CharacterEncoding.h"
 #include "vm/ScopeObject.h"
 #include "vm/Shape.h"
 #include "vm/StringBuffer.h"
 
 #include "jscntxtinlines.h"
 #include "jscompartmentinlines.h"
 #include "jsinferinlines.h"
+#include "jsobjinlines.h"
 #include "jsscriptinlines.h"
 
 using namespace js;
 using namespace js::gc;
 
 using js::frontend::IsIdentifier;
 using mozilla::ArrayLength;
 
--- a/js/src/jsopcode.h
+++ b/js/src/jsopcode.h
@@ -7,16 +7,17 @@
 #ifndef jsopcode_h
 #define jsopcode_h
 
 /*
  * JS bytecode definitions.
  */
 
 #include "jsbytecode.h"
+#include "jstypes.h"
 #include "NamespaceImports.h"
 
 #include "frontend/SourceNotes.h"
 
 /*
  * JS operation bytecodes.
  */
 typedef enum JSOp {
--- a/js/src/jsprototypes.h
+++ b/js/src/jsprototypes.h
@@ -49,25 +49,12 @@
     macro(Uint8ClampedArray,     30,     js_InitTypedArrayClasses) \
     macro(Proxy,                 31,     js_InitProxyClass) \
     macro(WeakMap,               32,     js_InitWeakMapClass) \
     macro(Map,                   33,     js_InitMapClass) \
     macro(Set,                   34,     js_InitSetClass) \
     macro(DataView,              35,     js_InitTypedArrayClasses) \
     macro(ParallelArray,         36,     js_InitParallelArrayClass) \
     macro(Intl,                  37,     js_InitIntlClass) \
-    macro(Type,                  38,     js_InitTypedObjectClasses) \
-    macro(Data,                  39,     js_InitTypedObjectClasses) \
-    macro(uint8Clamped,          40,     js_InitTypedObjectClasses) \
-    macro(uint8,                 41,     js_InitTypedObjectClasses) \
-    macro(uint16,                42,     js_InitTypedObjectClasses) \
-    macro(uint32,                43,     js_InitTypedObjectClasses) \
-    macro(int8,                  44,     js_InitTypedObjectClasses) \
-    macro(int16,                 45,     js_InitTypedObjectClasses) \
-    macro(int32,                 46,     js_InitTypedObjectClasses) \
-    macro(float32,               47,     js_InitTypedObjectClasses) \
-    macro(float64,               48,     js_InitTypedObjectClasses) \
-    macro(ArrayType,             49,     js_InitTypedObjectClasses) \
-    macro(StructType,            50,     js_InitTypedObjectClasses) \
-    macro(ArrayTypeObject,       51,     js_InitTypedObjectClasses) \
-    macro(GeneratorFunction,     52,     js_InitIteratorClasses) \
+    macro(TypedObject,           38,     js_InitTypedObjectDummy) \
+    macro(GeneratorFunction,     39,     js_InitIteratorClasses) \
 
 #endif /* jsprototypes_h */
--- a/js/src/jsscript.h
+++ b/js/src/jsscript.h
@@ -13,16 +13,17 @@
 #include "mozilla/PodOperations.h"
 
 #include "jsatom.h"
 #ifdef JS_THREADSAFE
 #include "jslock.h"
 #endif
 #include "jsobj.h"
 #include "jsopcode.h"
+#include "jstypes.h"
 
 #include "gc/Barrier.h"
 #include "gc/Rooting.h"
 #include "jit/IonCode.h"
 #include "vm/Shape.h"
 
 namespace js {
 
--- a/js/src/jstypes.h
+++ b/js/src/jstypes.h
@@ -233,17 +233,21 @@
 ***********************************************************************/
 
 #define JS_ARRAY_LENGTH(array) (sizeof (array) / sizeof (array)[0])
 #define JS_ARRAY_END(array)    ((array) + JS_ARRAY_LENGTH(array))
 
 #define JS_BITS_PER_BYTE 8
 #define JS_BITS_PER_BYTE_LOG2 3
 
-#define JS_BITS_PER_WORD (JS_BITS_PER_BYTE * JS_BYTES_PER_WORD)
+#if defined(JS_64BIT)
+# define JS_BITS_PER_WORD 64
+#else
+# define JS_BITS_PER_WORD 32
+#endif
 
 /***********************************************************************
 ** MACROS:      JS_FUNC_TO_DATA_PTR
 **              JS_DATA_TO_FUNC_PTR
 ** DESCRIPTION:
 **      Macros to convert between function and data pointers assuming that
 **      they have the same size. Use them like this:
 **
--- a/js/src/tests/ecma_6/TypedObject/architecture.js
+++ b/js/src/tests/ecma_6/TypedObject/architecture.js
@@ -1,9 +1,10 @@
-// |reftest| skip-if(!this.hasOwnProperty("Type"))
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
+
 var BUGNUMBER = 578700;
 var summary = 'Binary Data class diagram';
 
 function assertNotEq(a, b) {
     var ok = false;
     try {
         assertEq(a, b);
     } catch(exc) {
@@ -21,49 +22,34 @@ function assertThrows(f) {
     } catch (exc) {
         ok = true;
     }
     if (!ok)
         throw new TypeError("Assertion failed: " + f + " did not throw as expected");
 }
 
 function runTests() {
-    print(BUGNUMBER + ": " + summary);
+  print(BUGNUMBER + ": " + summary);
 
-    assertEq(Data.__proto__, Function.prototype);
-    assertEq(Data.prototype.__proto__, Object.prototype);
-    assertEq(Data.prototype.constructor, Data);
-    assertEq(typeof Data.prototype.update === "function", true);
+  var ArrayType = TypedObject.ArrayType;
+  var StructType = TypedObject.StructType;
 
-    assertEq(Type.__proto__, Function.prototype);
-    assertEq(Type.prototype, Data);
+  assertEq(ArrayType instanceof Function, true);
+  assertEq(ArrayType.prototype instanceof Function, true);
 
-    assertEq(ArrayType.__proto__, Type);
-    assertEq(ArrayType.prototype.__proto__, Type.prototype);
-    assertEq(typeof ArrayType.prototype.repeat === "function", true);
-
-    assertEq(ArrayType.prototype.prototype.__proto__, Data.prototype);
+  assertEq(ArrayType.__proto__, Function.__proto__);
+  assertEq(ArrayType.prototype.__proto__, Function.__proto__);
 
-    assertEq(StructType.__proto__, Type);
-    assertEq(StructType.prototype.__proto__, Type.prototype);
-    assertEq(StructType.prototype.prototype.__proto__, Data.prototype);
-
-    // Change global 'Type' and see if things stay sane.
-    Type = function() {
-        return 42;
-    }
+  assertEq(StructType instanceof Function, true);
+  assertEq(StructType.prototype instanceof Function, true);
 
-    Data = function() {
-        return 43;
-    }
-
-    assertNotEq(ArrayType.prototype.__proto__, Type.prototype);
-    assertNotEq(ArrayType.prototype.prototype.__proto__, Data.prototype);
+  assertEq(Object.getPrototypeOf(StructType),
+           Object.getPrototypeOf(Function));
+  assertEq(Object.getPrototypeOf(StructType.prototype),
+           Object.getPrototypeOf(Function));
 
-    assertNotEq(StructType.prototype.__proto__, Type.prototype);
-    assertNotEq(StructType.prototype.prototype.__proto__, Data.prototype);
+  if (typeof reportCompare === "function")
+    reportCompare(true, true);
 
-    if (typeof reportCompare === "function")
-        reportCompare(true, true);
-    print("Tests complete");
+  print("Tests complete");
 }
 
 runTests();
--- a/js/src/tests/ecma_6/TypedObject/arrayofstructs.js
+++ b/js/src/tests/ecma_6/TypedObject/arrayofstructs.js
@@ -1,12 +1,15 @@
-// |reftest| skip-if(!this.hasOwnProperty("Type"))
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
 var BUGNUMBER = 578700;
 var summary = 'TypedObjects StructType prototype chains';
 
+var ArrayType = TypedObject.ArrayType;
+var StructType = TypedObject.StructType;
+var float32 = TypedObject.float32;
 
 function runTests() {
   var Point = new ArrayType(float32, 3);
   var Line = new StructType({from: Point, to: Point});
   var Lines = new ArrayType(Line, 3);
 
   var lines = new Lines([
     {from: [1, 2, 3], to: [4, 5, 6]},
--- a/js/src/tests/ecma_6/TypedObject/arraytype.js
+++ b/js/src/tests/ecma_6/TypedObject/arraytype.js
@@ -1,23 +1,28 @@
-// |reftest| skip-if(!this.hasOwnProperty("Type"))
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
 var BUGNUMBER = 578700;
 var summary = 'TypedObjects ArrayType implementation';
 
 function assertThrows(f) {
     var ok = false;
     try {
         f();
     } catch (exc) {
         ok = true;
     }
     if (!ok)
         throw new TypeError("Assertion failed: " + f + " did not throw as expected");
 }
 
+var ArrayType = TypedObject.ArrayType;
+var uint8 = TypedObject.uint8;
+var float32 = TypedObject.float32;
+var uint32 = TypedObject.uint32;
+
 function runTests() {
     print(BUGNUMBER + ": " + summary);
 
     assertEq(typeof ArrayType.prototype.prototype.forEach == "function", true);
     assertEq(typeof ArrayType.prototype.prototype.subarray == "function", true);
 
     assertThrows(function() ArrayType(uint8, 10));
     assertThrows(function() new ArrayType());
@@ -101,27 +106,18 @@ function runTests() {
     assertEq(as.length, 65536);
 
     // test methods
     var c = new A();
     c.fill(3);
     for (var i = 0; i < c.length; i++)
         assertEq(c[i], 3);
 
-    assertThrows(function() c.update([3.14, 4.52, 5]));
-    //assertThrows(function() c.update([3000, 0, 1, 1, 1, 1, 1, 1, 1, 1]));
-
     assertThrows(function() Vec3.prototype.fill.call(c, 2));
 
-    var updatingPos = new Vec3();
-    updatingPos.update([5, 3, 1]);
-    assertEq(updatingPos[0], 5);
-    assertEq(updatingPos[1], 3);
-    assertEq(updatingPos[2], 1);
-
     var d = A.repeat(10);
     for (var i = 0; i < d.length; i++)
         assertEq(d[i], 10);
 
     assertThrows(function() ArrayType.prototype.repeat.call(d, 2));
 
     var MA = new ArrayType(uint32, 5);
     var ma = new MA([1, 2, 3, 4, 5]);
@@ -132,25 +128,16 @@ function runTests() {
     assertEq(mb[1], 4);
     assertEq(mb[2], 5);
 
     assertThrows(function() ma.subarray());
     assertThrows(function() ma.subarray(2.14));
     assertThrows(function() ma.subarray({}));
     assertThrows(function() ma.subarray(2, []));
 
-    // check similarity even though mb's ArrayType
-    // is not script accessible
-    var Similar = new ArrayType(uint32, 3);
-    var sim = new Similar();
-    sim.update(mb);
-    assertEq(sim[0], 3);
-    assertEq(sim[1], 4);
-    assertEq(sim[2], 5);
-
     var range = ma.subarray(0, 3);
     assertEq(range.length, 3);
     assertEq(range[0], 1);
     assertEq(range[1], 2);
     assertEq(range[2], 3);
 
     assertEq(ma.subarray(ma.length).length, 0);
     assertEq(ma.subarray(ma.length, ma.length-1).length, 0);
@@ -176,23 +163,28 @@ function runTests() {
     assertEq(modifyOriginal[2], 97);
 
     var indexPropDesc = Object.getOwnPropertyDescriptor(as, '0');
     assertEq(typeof indexPropDesc == "undefined", false);
     assertEq(indexPropDesc.configurable, false);
     assertEq(indexPropDesc.enumerable, true);
     assertEq(indexPropDesc.writable, true);
 
-
     var lengthPropDesc = Object.getOwnPropertyDescriptor(as, 'length');
     assertEq(typeof lengthPropDesc == "undefined", false);
     assertEq(lengthPropDesc.configurable, false);
     assertEq(lengthPropDesc.enumerable, false);
     assertEq(lengthPropDesc.writable, false);
 
+    var counter = 0;
+    for (var nm in as) {
+      assertEq(+nm, counter++);
+    }
+    assertEq(counter, as.length);
+
     assertThrows(function() Object.defineProperty(o, "foo", { value: "bar" }));
 
     // check if a reference acts the way it should
     var AA = new ArrayType(new ArrayType(uint8, 5), 5);
     var aa = new AA();
     var aa0 = aa[0];
     aa[0] = [0,1,2,3,4];
     for (var i = 0; i < aa0.length; i++)
--- a/js/src/tests/ecma_6/TypedObject/memory.js
+++ b/js/src/tests/ecma_6/TypedObject/memory.js
@@ -1,17 +1,30 @@
-// |reftest| skip-if(!this.hasOwnProperty("Type"))
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
 var BUGNUMBER = 578700;
 var summary = 'TypedObjects memory check';
 
 function spin() {
     for (var i = 0; i < 10000; i++)
         ;
 }
 
+var ArrayType = TypedObject.ArrayType;
+var StructType = TypedObject.StructType;
+var uint8 = TypedObject.uint8;
+var uint16 = TypedObject.uint16;
+var uint32 = TypedObject.uint32;
+var uint8Clamped = TypedObject.uint8Clamped;
+var int8 = TypedObject.int8;
+var int16 = TypedObject.int16;
+var int32 = TypedObject.int32;
+var float32 = TypedObject.float32;
+var float64 = TypedObject.float64;
+
+
 function runTests() {
     print(BUGNUMBER + ": " + summary);
 
     var AA = new ArrayType(new ArrayType(uint8, 5), 5);
     var aa = new AA();
     var aa0 = aa[0];
     aa[0] = [0,1,2,3,4];
 
@@ -44,17 +57,19 @@ function runTests() {
 
     var theOneISawWasJustBlack = Rainbow.repeat({'r': 0, 'g': 0, 'b': 0});
 
     var middleBand = theOneISawWasJustBlack[3];
     theOneISawWasJustBlack = null;
     gc();
     spin();
     assertEq(middleBand['r'] == 0 && middleBand['g'] == 0 && middleBand['b'] == 0, true);
-    middleBand.update({'r': 255, 'g': 207, 'b': 142});
+    middleBand.r = 255;
+    middleBand.g = 207;
+    middleBand.b = 142;
     assertEq(middleBand['r'] == 255 && middleBand['g'] == 207 && middleBand['b'] == 142, true);
 
     var scopedType = function() {
         var Point = new StructType({'x': int32, 'y': int32});
         var aPoint = new Point();
         aPoint.x = 4;
         aPoint.y = 5;
         return aPoint;
--- a/js/src/tests/ecma_6/TypedObject/numerictypes.js
+++ b/js/src/tests/ecma_6/TypedObject/numerictypes.js
@@ -1,14 +1,26 @@
-// |reftest| skip-if(!this.hasOwnProperty("Type"))
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
 var BUGNUMBER = 578700;
 var summary = 'TypedObjects numeric types';
 var actual = '';
 var expect = '';
 
+var ArrayType = TypedObject.ArrayType;
+var StructType = TypedObject.StructType;
+var uint8 = TypedObject.uint8;
+var uint16 = TypedObject.uint16;
+var uint32 = TypedObject.uint32;
+var uint8Clamped = TypedObject.uint8Clamped;
+var int8 = TypedObject.int8;
+var int16 = TypedObject.int16;
+var int32 = TypedObject.int32;
+var float32 = TypedObject.float32;
+var float64 = TypedObject.float64;
+
 function runTests()
 {
     printBugNumber(BUGNUMBER);
     printStatus(summary);
 
     var TestPassCount = 0;
     var TestFailCount = 0;
     var TestTodoCount = 0;
--- a/js/src/tests/ecma_6/TypedObject/size_and_alignment.js
+++ b/js/src/tests/ecma_6/TypedObject/size_and_alignment.js
@@ -1,14 +1,28 @@
-// |reftest| skip-if(!this.hasOwnProperty("Type"))
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
 var BUGNUMBER = 578700;
 var summary = 'Size and Alignment of TypedObjects types';
 var actual = '';
 var expect = '';
 
+
+var ArrayType = TypedObject.ArrayType;
+var StructType = TypedObject.StructType;
+var uint8 = TypedObject.uint8;
+var uint16 = TypedObject.uint16;
+var uint32 = TypedObject.uint32;
+var uint8Clamped = TypedObject.uint8Clamped;
+var int8 = TypedObject.int8;
+var int16 = TypedObject.int16;
+var int32 = TypedObject.int32;
+var float32 = TypedObject.float32;
+var float64 = TypedObject.float64;
+
+
 function runTests() {
   printBugNumber(BUGNUMBER);
   printStatus(summary);
 
   var typesAndAlignments = [
     {type: uint8, size: 1, alignment: 1},
     {type: uint8Clamped, size: 1, alignment: 1},
     {type: uint16, size: 2, alignment: 2},
--- a/js/src/tests/ecma_6/TypedObject/structequiv.js
+++ b/js/src/tests/ecma_6/TypedObject/structequiv.js
@@ -1,12 +1,24 @@
-// |reftest| skip-if(!this.hasOwnProperty("Type"))
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
 var BUGNUMBER = 578700;
 var summary = 'TypedObjects Equivalent StructTypes';
 
+var ArrayType = TypedObject.ArrayType;
+var StructType = TypedObject.StructType;
+var uint8 = TypedObject.uint8;
+var uint16 = TypedObject.uint16;
+var uint32 = TypedObject.uint32;
+var uint8Clamped = TypedObject.uint8Clamped;
+var int8 = TypedObject.int8;
+var int16 = TypedObject.int16;
+var int32 = TypedObject.int32;
+var float32 = TypedObject.float32;
+var float64 = TypedObject.float64;
+
 function assertEquivalent(t1, t2) {
   assertEq(true, t1.equivalent(t2));
   assertEq(true, t2.equivalent(t1));
 }
 
 function assertNotEquivalent(t1, t2) {
   assertEq(false, t1.equivalent(t2));
   assertEq(false, t2.equivalent(t1));
--- a/js/src/tests/ecma_6/TypedObject/structtypeenumerate.js
+++ b/js/src/tests/ecma_6/TypedObject/structtypeenumerate.js
@@ -1,12 +1,24 @@
-// |reftest| skip-if(!this.hasOwnProperty("Type"))
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
 var BUGNUMBER = 578700;
 var summary = 'TypedObjects StructType propery enumeration';
 
+var ArrayType = TypedObject.ArrayType;
+var StructType = TypedObject.StructType;
+var uint8 = TypedObject.uint8;
+var uint16 = TypedObject.uint16;
+var uint32 = TypedObject.uint32;
+var uint8Clamped = TypedObject.uint8Clamped;
+var int8 = TypedObject.int8;
+var int16 = TypedObject.int16;
+var int32 = TypedObject.int32;
+var float32 = TypedObject.float32;
+var float64 = TypedObject.float64;
+
 function runTests() {
   var RgbColor = new StructType({r: uint8, g: uint8, b: uint8});
   var Fade = new StructType({from: RgbColor, to: RgbColor});
 
   var white = new RgbColor({r: 255, g: 255, b: 255});
   var gray = new RgbColor({r: 129, g: 128, b: 127});
   var fade = new Fade({from: white, to: gray});
 
--- a/js/src/tests/ecma_6/TypedObject/structtypeindexedfields.js
+++ b/js/src/tests/ecma_6/TypedObject/structtypeindexedfields.js
@@ -1,12 +1,24 @@
-// |reftest| skip-if(!this.hasOwnProperty("Type"))
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
 var BUGNUMBER = 578700;
 var summary = 'TypedObjects: indexed properties are illegal in a StructType';
 
+var ArrayType = TypedObject.ArrayType;
+var StructType = TypedObject.StructType;
+var uint8 = TypedObject.uint8;
+var uint16 = TypedObject.uint16;
+var uint32 = TypedObject.uint32;
+var uint8Clamped = TypedObject.uint8Clamped;
+var int8 = TypedObject.int8;
+var int16 = TypedObject.int16;
+var int32 = TypedObject.int32;
+var float32 = TypedObject.float32;
+var float64 = TypedObject.float64;
+
 function runTests() {
   print(BUGNUMBER + ": " + summary);
 
   var failed;
   try {
     new StructType({1: int32, 2: uint8, 3: float64});
     failed = false;
   } catch (e) {
--- a/js/src/tests/ecma_6/TypedObject/structtypeprototype.js
+++ b/js/src/tests/ecma_6/TypedObject/structtypeprototype.js
@@ -1,21 +1,33 @@
-// |reftest| skip-if(!this.hasOwnProperty("Type"))
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
 var BUGNUMBER = 578700;
 var summary = 'TypedObjects StructType prototype chains';
 
+var ArrayType = TypedObject.ArrayType;
+var StructType = TypedObject.StructType;
+var uint8 = TypedObject.uint8;
+var uint16 = TypedObject.uint16;
+var uint32 = TypedObject.uint32;
+var uint8Clamped = TypedObject.uint8Clamped;
+var int8 = TypedObject.int8;
+var int16 = TypedObject.int16;
+var int32 = TypedObject.int32;
+var float32 = TypedObject.float32;
+var float64 = TypedObject.float64;
 
 function runTests() {
   var RgbColor1 = new StructType({r: uint8, g: uint8, b: uint8});
   var RgbColor2 = new StructType({r: uint8, g: uint8, b: uint8});
   var Fade1 = new StructType({from: RgbColor1, to: RgbColor1});
   var Fade2 = new StructType({from: RgbColor2, to: RgbColor2});
 
-  // Available on all objects
-  Data.prototype.sub = function(c) {
+  // Available on all struct types (even though it would only make
+  // sense on a RgbColor1 or RgbColor2 instance)
+  StructType.prototype.prototype.sub = function(c) {
     this.r -= c;
     this.g -= c;
     this.b -= c;
   };
 
   // Available on `RgbColor2` instances only
   RgbColor2.prototype.add = function(c) {
     this.r += c;
--- a/js/src/tests/ecma_6/TypedObject/structtypereflection.js
+++ b/js/src/tests/ecma_6/TypedObject/structtypereflection.js
@@ -1,12 +1,24 @@
-// |reftest| skip-if(!this.hasOwnProperty("Type"))
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
 var BUGNUMBER = 578700;
 var summary = 'TypedObjects: check reflection on StructType objects';
 
+var ArrayType = TypedObject.ArrayType;
+var StructType = TypedObject.StructType;
+var uint8 = TypedObject.uint8;
+var uint16 = TypedObject.uint16;
+var uint32 = TypedObject.uint32;
+var uint8Clamped = TypedObject.uint8Clamped;
+var int8 = TypedObject.int8;
+var int16 = TypedObject.int16;
+var int32 = TypedObject.int32;
+var float32 = TypedObject.float32;
+var float64 = TypedObject.float64;
+
 function runTests() {
     print(BUGNUMBER + ": " + summary);
 
     var S = new StructType({x: int32, y: uint8, z: float64});
     assertEq(S.__proto__, StructType.prototype);
     assertEq(S.prototype.__proto__, StructType.prototype.prototype);
     assertEq(S.toSource(), "StructType({x: int32, y: uint8, z: float64})");
     assertEq(S.variable, false);
--- a/js/src/tests/ecma_6/TypedObject/structtypestructuralassign.js
+++ b/js/src/tests/ecma_6/TypedObject/structtypestructuralassign.js
@@ -1,12 +1,24 @@
-// |reftest| skip-if(!this.hasOwnProperty("Type"))
+// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
 var BUGNUMBER = 578700;
 var summary = 'TypedObjects StructType structural assignment';
 
+var ArrayType = TypedObject.ArrayType;
+var StructType = TypedObject.StructType;
+var uint8 = TypedObject.uint8;
+var uint16 = TypedObject.uint16;
+var uint32 = TypedObject.uint32;
+var uint8Clamped = TypedObject.uint8Clamped;
+var int8 = TypedObject.int8;
+var int16 = TypedObject.int16;
+var int32 = TypedObject.int32;
+var float32 = TypedObject.float32;
+var float64 = TypedObject.float64;
+
 function assertEqColor(c1, c2) {
   assertEq(c1.r, c2.r);
   assertEq(c1.g, c2.g);
   assertEq(c1.b, c2.b);
 }
 
 function runTests() {
   var RgbColor = new StructType({r: uint8, g: uint8, b: uint8});
--- a/js/src/vm/CommonPropertyNames.h
+++ b/js/src/vm/CommonPropertyNames.h
@@ -10,16 +10,17 @@
 #define vm_CommonPropertyNames_h
 
 #include "jsprototypes.h"
 
 #define FOR_EACH_COMMON_PROPERTYNAME(macro) \
     macro(anonymous, anonymous, "anonymous") \
     macro(apply, apply, "apply") \
     macro(arguments, arguments, "arguments") \
+    macro(ArrayType, ArrayType, "ArrayType") \
     macro(buffer, buffer, "buffer") \
     macro(builder, builder, "builder") \
     macro(byteLength, byteLength, "byteLength") \
     macro(byteAlignment, byteAlignment, "byteAlignment") \
     macro(byteOffset, byteOffset, "byteOffset") \
     macro(bytes, bytes, "bytes") \
     macro(BYTES_PER_ELEMENT, BYTES_PER_ELEMENT, "BYTES_PER_ELEMENT") \
     macro(call, call, "call") \
@@ -57,16 +58,18 @@
     macro(escape, escape, "escape") \
     macro(eval, eval, "eval") \
     macro(false, false_, "false") \
     macro(fieldNames, fieldNames, "fieldNames") \
     macro(fieldOffsets, fieldOffsets, "fieldOffsets") \
     macro(fieldTypes, fieldTypes, "fieldTypes") \
     macro(fileName, fileName, "fileName") \
     macro(fix, fix, "fix") \
+    macro(float32, float32, "float32") \
+    macro(float64, float64, "float64") \
     macro(format, format, "format") \
     macro(get, get, "get") \
     macro(getInternals, getInternals, "getInternals") \
     macro(getOwnPropertyDescriptor, getOwnPropertyDescriptor, "getOwnPropertyDescriptor") \
     macro(getOwnPropertyNames, getOwnPropertyNames, "getOwnPropertyNames") \
     macro(getPropertyDescriptor, getPropertyDescriptor, "getPropertyDescriptor") \
     macro(global, global, "global") \
     macro(has, has, "has") \
@@ -80,16 +83,19 @@
     macro(InitializeNumberFormat, InitializeNumberFormat, "InitializeNumberFormat") \
     macro(innermost, innermost, "innermost") \
     macro(input, input, "input") \
     macro(isFinite, isFinite, "isFinite") \
     macro(isNaN, isNaN, "isNaN") \
     macro(isPrototypeOf, isPrototypeOf, "isPrototypeOf") \
     macro(iterate, iterate, "iterate") \
     macro(Infinity, Infinity, "Infinity") \
+    macro(int8, int8, "int8") \
+    macro(int16, int16, "int16") \
+    macro(int32, int32, "int32") \
     macro(iterator, iterator, "iterator") \
     macro(iteratorIntrinsic, iteratorIntrinsic, "__iterator__") \
     macro(join, join, "join") \
     macro(keys, keys, "keys") \
     macro(lastIndex, lastIndex, "lastIndex") \
     macro(length, length, "length") \
     macro(line, line, "line") \
     macro(lineNumber, lineNumber, "lineNumber") \
@@ -126,30 +132,35 @@
     macro(prototype, prototype, "prototype") \
     macro(return, return_, "return") \
     macro(sensitivity, sensitivity, "sensitivity") \
     macro(set, set, "set") \
     macro(shape, shape, "shape") \
     macro(source, source, "source") \
     macro(stack, stack, "stack") \
     macro(sticky, sticky, "sticky") \
+    macro(StructType, StructType, "StructType") \
     macro(style, style, "style") \
     macro(test, test, "test") \
     macro(throw, throw_, "throw") \
     macro(timeZone, timeZone, "timeZone") \
     macro(toGMTString, toGMTString, "toGMTString") \
     macro(toISOString, toISOString, "toISOString") \
     macro(toJSON, toJSON, "toJSON") \
     macro(toLocaleString, toLocaleString, "toLocaleString") \
     macro(toSource, toSource, "toSource") \
     macro(toString, toString, "toString") \
     macro(toUTCString, toUTCString, "toUTCString") \
     macro(true, true_, "true") \
     macro(unescape, unescape, "unescape") \
     macro(uneval, uneval, "uneval") \
+    macro(uint8, uint8, "uint8") \
+    macro(uint8Clamped, uint8Clamped, "uint8Clamped") \
+    macro(uint16, uint16, "uint16") \
+    macro(uint32, uint32, "uint32") \
     macro(unwatch, unwatch, "unwatch") \
     macro(url, url, "url") \
     macro(usage, usage, "usage") \
     macro(useGrouping, useGrouping, "useGrouping") \
     macro(useAsm, useAsm, "use asm") \
     macro(useStrict, useStrict, "use strict") \
     macro(value, value, "value") \
     macro(valueOf, valueOf, "valueOf") \
--- a/js/src/vm/GlobalObject.h
+++ b/js/src/vm/GlobalObject.h
@@ -21,17 +21,17 @@ js_InitObjectClass(JSContext *cx, js::Ha
 
 extern JSObject *
 js_InitFunctionClass(JSContext *cx, js::HandleObject obj);
 
 extern JSObject *
 js_InitTypedArrayClasses(JSContext *cx, js::HandleObject obj);
 
 extern JSObject *
-js_InitTypedObjectClasses(JSContext *cx, js::HandleObject obj);
+js_InitTypedObjectClass(JSContext *cx, js::HandleObject obj);
 
 namespace js {
 
 class Debugger;
 
 /*
  * Global object slots are reserved as follows:
  *
@@ -103,19 +103,20 @@ class GlobalObject : public JSObject
     static const unsigned COLLATOR_PROTO          = SET_ITERATOR_PROTO + 1;
     static const unsigned NUMBER_FORMAT_PROTO     = COLLATOR_PROTO + 1;
     static const unsigned DATE_TIME_FORMAT_PROTO  = NUMBER_FORMAT_PROTO + 1;
     static const unsigned REGEXP_STATICS          = DATE_TIME_FORMAT_PROTO + 1;
     static const unsigned FUNCTION_NS             = REGEXP_STATICS + 1;
     static const unsigned RUNTIME_CODEGEN_ENABLED = FUNCTION_NS + 1;
     static const unsigned DEBUGGERS               = RUNTIME_CODEGEN_ENABLED + 1;
     static const unsigned INTRINSICS              = DEBUGGERS + 1;
+    static const unsigned ARRAY_TYPE              = INTRINSICS + 1;
 
     /* Total reserved-slot count for global objects. */
-    static const unsigned RESERVED_SLOTS = INTRINSICS + 1;
+    static const unsigned RESERVED_SLOTS = ARRAY_TYPE + 1;
 
     void staticAsserts() {
         /*
          * The slot count must be in the public API for JSCLASS_GLOBAL_FLAGS,
          * and we aren't going to expose GlobalObject, so just assert that the
          * two values are synchronized.
          */
         JS_STATIC_ASSERT(JSCLASS_GLOBAL_SLOT_COUNT == RESERVED_SLOTS);
@@ -410,41 +411,43 @@ class GlobalObject : public JSObject
     JSObject *getOrCreateIntlObject(JSContext *cx) {
         return getOrCreateObject(cx, APPLICATION_SLOTS + JSProto_Intl, initIntlObject);
     }
 
     JSObject *getIteratorPrototype() {
         return &getPrototype(JSProto_Iterator).toObject();
     }
 
-    JSObject *getOrCreateDataObject(JSContext *cx) {
-        return getOrCreateObject(cx, APPLICATION_SLOTS + JSProto_Data, initDataObject);
-    }
-
-    JSObject *getOrCreateTypeObject(JSContext *cx) {
-        return getOrCreateObject(cx, APPLICATION_SLOTS + JSProto_Type, initTypeObject);
-    }
-
-    JSObject *getOrCreateArrayTypeObject(JSContext *cx) {
-        return getOrCreateObject(cx, APPLICATION_SLOTS + JSProto_ArrayTypeObject,
-                                 initArrayTypeObject);
-    }
-
     JSObject *getOrCreateCollatorPrototype(JSContext *cx) {
         return getOrCreateObject(cx, COLLATOR_PROTO, initCollatorProto);
     }
 
     JSObject *getOrCreateNumberFormatPrototype(JSContext *cx) {
         return getOrCreateObject(cx, NUMBER_FORMAT_PROTO, initNumberFormatProto);
     }
 
     JSObject *getOrCreateDateTimeFormatPrototype(JSContext *cx) {
         return getOrCreateObject(cx, DATE_TIME_FORMAT_PROTO, initDateTimeFormatProto);
     }
 
+    JSObject *getArrayType(JSContext *cx) {
+        const Value &v = getReservedSlot(ARRAY_TYPE);
+
+        MOZ_ASSERT(v.isObject(),
+                   "GlobalObject::arrayType must only be called from "
+                   "TypedObject code that can assume TypedObject has "
+                   "been initialized");
+
+        return &v.toObject();
+    }
+
+    void setArrayType(JSObject *obj) {
+        initReservedSlot(ARRAY_TYPE, ObjectValue(*obj));
+    }
+
   private:
     typedef bool (*ObjectInitOp)(JSContext *cx, Handle<GlobalObject*> global);
 
     JSObject *getOrCreateObject(JSContext *cx, unsigned slot, ObjectInitOp init) {
         Value v = getSlotRef(slot);
         if (v.isObject())
             return &v.toObject();
         Rooted<GlobalObject*> self(cx, this);
@@ -564,21 +567,16 @@ class GlobalObject : public JSObject
     static bool initSetIteratorProto(JSContext *cx, Handle<GlobalObject*> global);
 
     // Implemented in Intl.cpp.
     static bool initIntlObject(JSContext *cx, Handle<GlobalObject*> global);
     static bool initCollatorProto(JSContext *cx, Handle<GlobalObject*> global);
     static bool initNumberFormatProto(JSContext *cx, Handle<GlobalObject*> global);
     static bool initDateTimeFormatProto(JSContext *cx, Handle<GlobalObject*> global);
 
-    // Implemented in builtin/TypedObject.cpp
-    static bool initTypeObject(JSContext *cx, Handle<GlobalObject*> global);
-    static bool initDataObject(JSContext *cx, Handle<GlobalObject*> global);
-    static bool initArrayTypeObject(JSContext *cx, Handle<GlobalObject*> global);
-
     static bool initStandardClasses(JSContext *cx, Handle<GlobalObject*> global);
 
     typedef js::Vector<js::Debugger *, 0, js::SystemAllocPolicy> DebuggerVector;
 
     /*
      * The collection of Debugger objects debugging this global. If this global
      * is not a debuggee, this returns either nullptr or an empty vector.
      */
--- a/js/xpconnect/src/Sandbox.cpp
+++ b/js/xpconnect/src/Sandbox.cpp
@@ -1115,283 +1115,272 @@ nsXPCComponents_utils_Sandbox::Construct
     RootedObject obj(cx, objArg);
     return CallOrConstruct(wrapper, cx, obj, args, _retval);
 }
 
 /*
  * For sandbox constructor the first argument can be a URI string in which case
  * we use the related Codebase Principal for the sandbox.
  */
-static nsresult
-GetPrincipalFromString(JSContext *cx, HandleString codebase, nsIPrincipal **principal)
+bool
+ParsePrincipal(JSContext *cx, HandleString codebase, nsIPrincipal **principal)
 {
     MOZ_ASSERT(principal);
     MOZ_ASSERT(codebase);
     nsCOMPtr<nsIURI> uri;
     nsDependentJSString codebaseStr;
-    NS_ENSURE_TRUE(codebaseStr.init(cx, codebase), NS_ERROR_FAILURE);
+    NS_ENSURE_TRUE(codebaseStr.init(cx, codebase), false);
     nsresult rv = NS_NewURI(getter_AddRefs(uri), codebaseStr);
-    NS_ENSURE_SUCCESS(rv, rv);
+    if (NS_FAILED(rv)) {
+        JS_ReportError(cx, "Creating URI from string failed");
+        return false;
+    }
 
     nsCOMPtr<nsIScriptSecurityManager> secman =
         do_GetService(kScriptSecurityManagerContractID);
-    NS_ENSURE_TRUE(secman, NS_ERROR_FAILURE);
+    NS_ENSURE_TRUE(secman, false);
 
     // We could allow passing in the app-id and browser-element info to the
     // sandbox constructor. But creating a sandbox based on a string is a
     // deprecated API so no need to add features to it.
     rv = secman->GetNoAppCodebasePrincipal(uri, principal);
-    NS_ENSURE_SUCCESS(rv, rv);
-    NS_ENSURE_TRUE(*principal, NS_ERROR_FAILURE);
-
-    return NS_OK;
+    if (NS_FAILED(rv) || !*principal) {
+        JS_ReportError(cx, "Creating Principal from URI failed");
+        return false;
+    }
+    return true;
 }
 
 /*
  * For sandbox constructor the first argument can be a principal object or
  * a script object principal (Document, Window).
  */
-static nsresult
+static bool
 GetPrincipalOrSOP(JSContext *cx, HandleObject from, nsISupports **out)
 {
     MOZ_ASSERT(out);
     *out = nullptr;
 
     nsXPConnect* xpc = nsXPConnect::XPConnect();
     nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
     xpc->GetWrappedNativeOfJSObject(cx, from,
                                     getter_AddRefs(wrapper));
 
-    NS_ENSURE_TRUE(wrapper, NS_ERROR_INVALID_ARG);
+    NS_ENSURE_TRUE(wrapper, false);
 
     if (nsCOMPtr<nsIScriptObjectPrincipal> sop = do_QueryWrappedNative(wrapper)) {
         sop.forget(out);
-        return NS_OK;
+        return true;
     }
 
     nsCOMPtr<nsIPrincipal> principal = do_QueryWrappedNative(wrapper);
     principal.forget(out);
-    NS_ENSURE_TRUE(*out, NS_ERROR_INVALID_ARG);
+    NS_ENSURE_TRUE(*out, false);
 
-    return NS_OK;
+    return true;
 }
 
 /*
  * The first parameter of the sandbox constructor might be an array of principals, either in string
  * format or actual objects (see GetPrincipalOrSOP)
  */
-static nsresult
+static bool
 GetExpandedPrincipal(JSContext *cx, HandleObject arrayObj, nsIExpandedPrincipal **out)
 {
     MOZ_ASSERT(out);
     uint32_t length;
 
     if (!JS_IsArrayObject(cx, arrayObj) ||
         !JS_GetArrayLength(cx, arrayObj, &length) ||
         !length)
     {
         // We need a whitelist of principals or uri strings to create an
         // expanded principal, if we got an empty array or something else
         // report error.
-        return NS_ERROR_INVALID_ARG;
+        JS_ReportError(cx, "Expected an array of URI strings");
+        return false;
     }
 
     nsTArray< nsCOMPtr<nsIPrincipal> > allowedDomains(length);
     allowedDomains.SetLength(length);
     nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
-    NS_ENSURE_TRUE(ssm, NS_ERROR_XPC_UNEXPECTED);
+    NS_ENSURE_TRUE(ssm, false);
 
     for (uint32_t i = 0; i < length; ++i) {
         RootedValue allowed(cx);
         if (!JS_GetElement(cx, arrayObj, i, &allowed))
-            return NS_ERROR_INVALID_ARG;
+            return false;
 
         nsresult rv;
         nsCOMPtr<nsIPrincipal> principal;
         if (allowed.isString()) {
             // In case of string let's try to fetch a codebase principal from it.
             RootedString str(cx, allowed.toString());
-            rv = GetPrincipalFromString(cx, str, getter_AddRefs(principal));
-            NS_ENSURE_SUCCESS(rv, rv);
+            if (!ParsePrincipal(cx, str, getter_AddRefs(principal)))
+                return false;
+
         } else if (allowed.isObject()) {
             // In case of object let's see if it's a Principal or a ScriptObjectPrincipal.
             nsCOMPtr<nsISupports> prinOrSop;
             RootedObject obj(cx, &allowed.toObject());
-            rv = GetPrincipalOrSOP(cx, obj, getter_AddRefs(prinOrSop));
-            NS_ENSURE_SUCCESS(rv, rv);
+            if (!GetPrincipalOrSOP(cx, obj, getter_AddRefs(prinOrSop)))
+                return false;
 
             nsCOMPtr<nsIScriptObjectPrincipal> sop(do_QueryInterface(prinOrSop));
             principal = do_QueryInterface(prinOrSop);
-            if (sop) {
+            if (sop)
                 principal = sop->GetPrincipal();
-            }
         }
-        NS_ENSURE_TRUE(principal, NS_ERROR_INVALID_ARG);
+        NS_ENSURE_TRUE(principal, false);
 
         // We do not allow ExpandedPrincipals to contain any system principals.
         bool isSystem;
         rv = ssm->IsSystemPrincipal(principal, &isSystem);
-        NS_ENSURE_SUCCESS(rv, rv);
-        NS_ENSURE_FALSE(isSystem, NS_ERROR_INVALID_ARG);
+        NS_ENSURE_SUCCESS(rv, false);
+        if (isSystem) {
+            JS_ReportError(cx, "System principal is not allowed in an expanded principal");
+            return false;
+        }
         allowedDomains[i] = principal;
   }
 
   nsCOMPtr<nsIExpandedPrincipal> result = new nsExpandedPrincipal(allowedDomains);
   result.forget(out);
-  return NS_OK;
+  return true;
 }
 
 /*
  * Helper that tries to get a property form the options object.
  */
-static nsresult
-GetPropFromOptions(JSContext *cx, HandleObject from, const char *name, MutableHandleValue prop,
-                   bool *found)
+bool
+OptionsBase::ParseValue(const char *name, MutableHandleValue prop, bool *found)
 {
     MOZ_ASSERT(found);
-    bool ok = JS_HasProperty(cx, from, name, found);
-    NS_ENSURE_TRUE(ok, NS_ERROR_INVALID_ARG);
+    bool ok = JS_HasProperty(mCx, mObject, name, found);
+    NS_ENSURE_TRUE(ok, false);
 
     if (!*found)
-        return NS_OK;
+        return true;
 
-    ok = JS_GetProperty(cx, from, name, prop);
-    NS_ENSURE_TRUE(ok, NS_ERROR_INVALID_ARG);
-    return NS_OK;
+    return JS_GetProperty(mCx, mObject, name, prop);
 }
 
 /*
  * Helper that tries to get a boolean property form the options object.
  */
-static nsresult
-GetBoolPropFromOptions(JSContext *cx, HandleObject from, const char *name, bool *prop)
+bool
+OptionsBase::ParseBoolean(const char *name, bool *prop)
 {
     MOZ_ASSERT(prop);
-
-    RootedValue value(cx);
+    RootedValue value(mCx);
     bool found;
-    nsresult rv = GetPropFromOptions(cx, from, name, &value, &found);
-    NS_ENSURE_SUCCESS(rv, rv);
+    bool ok = ParseValue(name, &value, &found);
+    NS_ENSURE_TRUE(ok, false);
 
     if (!found)
-        return NS_OK;
+        return true;
 
-    NS_ENSURE_TRUE(value.isBoolean(), NS_ERROR_INVALID_ARG);
+    if (!value.isBoolean()) {
+        JS_ReportError(mCx, "Expected a boolean value for property %s", name);
+        return false;
+    }
 
     *prop = value.toBoolean();
-    return NS_OK;
+    return true;
 }
 
 /*
  * Helper that tries to get an object property form the options object.
  */
-static nsresult
-GetObjPropFromOptions(JSContext *cx, HandleObject from, const char *name, JSObject **prop)
+bool
+OptionsBase::ParseObject(const char *name, MutableHandleObject prop)
 {
-    MOZ_ASSERT(prop);
-
-    RootedValue value(cx);
+    RootedValue value(mCx);
     bool found;
-    nsresult rv = GetPropFromOptions(cx, from, name, &value, &found);
-    NS_ENSURE_SUCCESS(rv, rv);
+    bool ok = ParseValue(name, &value, &found);
+    NS_ENSURE_TRUE(ok, false);
+
+    if (!found)
+        return true;
 
-    if (!found) {
-        *prop = nullptr;
-        return NS_OK;
+    if (!value.isObject()) {
+        JS_ReportError(mCx, "Expected an object value for property %s", name);
+        return false;
     }
-
-    NS_ENSURE_TRUE(value.isObject(), NS_ERROR_INVALID_ARG);
-    *prop = &value.toObject();
-    return NS_OK;
+    prop.set(&value.toObject());
+    return true;
 }
 
 /*
  * Helper that tries to get a string property form the options object.
  */
-static nsresult
-GetStringPropFromOptions(JSContext *cx, HandleObject from, const char *name, nsCString &prop)
+bool
+OptionsBase::ParseString(const char *name, nsCString &prop)
 {
-    RootedValue value(cx);
+    RootedValue value(mCx);
     bool found;
-    nsresult rv = GetPropFromOptions(cx, from, name, &value, &found);
-    NS_ENSURE_SUCCESS(rv, rv);
+    bool ok = ParseValue(name, &value, &found);
+    NS_ENSURE_TRUE(ok, false);
 
     if (!found)
-        return NS_OK;
-
-    NS_ENSURE_TRUE(value.isString(), NS_ERROR_INVALID_ARG);
+        return true;
 
-    char *tmp = JS_EncodeString(cx, value.toString());
-    NS_ENSURE_TRUE(tmp, NS_ERROR_INVALID_ARG);
+    if (!value.isString()) {
+        JS_ReportError(mCx, "Expected a string value for property %s", name);
+        return false;
+    }
+
+    char *tmp = JS_EncodeString(mCx, value.toString());
+    NS_ENSURE_TRUE(tmp, false);
     prop.Adopt(tmp, strlen(tmp));
-    return NS_OK;
+    return true;
 }
 
 /*
  * Helper that tries to get a list of DOM constructors and other helpers from the options object.
  */
-static nsresult
-GetGlobalPropertiesFromOptions(JSContext *cx, HandleObject from, SandboxOptions& options)
+bool
+SandboxOptions::ParseGlobalProperties()
 {
-    RootedValue value(cx);
+    RootedValue value(mCx);
     bool found;
-    nsresult rv = GetPropFromOptions(cx, from, "wantGlobalProperties", &value, &found);
-    NS_ENSURE_SUCCESS(rv, rv);
+    bool ok = ParseValue("wantGlobalProperties", &value, &found);
+    NS_ENSURE_TRUE(ok, false);
     if (!found)
-        return NS_OK;
+        return true;
+
+    if (!value.isObject()) {
+        JS_ReportError(mCx, "Expected an array value for wantGlobalProperties");
+        return false;
+    }
 
-    NS_ENSURE_TRUE(value.isObject(), NS_ERROR_INVALID_ARG);
-    RootedObject ctors(cx, &value.toObject());
-    NS_ENSURE_TRUE(JS_IsArrayObject(cx, ctors), NS_ERROR_INVALID_ARG);
-    bool ok = options.globalProperties.Parse(cx, ctors);
-    NS_ENSURE_TRUE(ok, NS_ERROR_INVALID_ARG);
-    return NS_OK;
+    RootedObject ctors(mCx, &value.toObject());
+    if (!JS_IsArrayObject(mCx, ctors)) {
+        JS_ReportError(mCx, "Expected an array value for wantGlobalProperties");
+        return false;
+    }
+
+    return globalProperties.Parse(mCx, ctors);
 }
 
 /*
  * Helper that parsing the sandbox options object (from) and sets the fields of the incoming options struct (options).
  */
-static nsresult
-ParseOptionsObject(JSContext *cx, jsval from, SandboxOptions &options)
+bool
+SandboxOptions::Parse()
 {
-    NS_ENSURE_TRUE(from.isObject(), NS_ERROR_INVALID_ARG);
-    RootedObject optionsObject(cx, &from.toObject());
-    nsresult rv = GetObjPropFromOptions(cx, optionsObject,
-                                        "sandboxPrototype", options.proto.address());
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    rv = GetBoolPropFromOptions(cx, optionsObject,
-                                "wantXrays", &options.wantXrays);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    rv = GetBoolPropFromOptions(cx, optionsObject,
-                                "wantComponents", &options.wantComponents);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    rv = GetBoolPropFromOptions(cx, optionsObject,
-                                "wantExportHelpers", &options.wantExportHelpers);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    rv = GetStringPropFromOptions(cx, optionsObject,
-                                  "sandboxName", options.sandboxName);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    rv = GetObjPropFromOptions(cx, optionsObject,
-                               "sameZoneAs", options.sameZoneAs.address());
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    rv = GetGlobalPropertiesFromOptions(cx, optionsObject, options);
-    NS_ENSURE_SUCCESS(rv, rv);
-
     bool found;
-    rv = GetPropFromOptions(cx, optionsObject,
-                            "metadata", &options.metadata, &found);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    return NS_OK;
+    return ParseObject("sandboxPrototype", &proto) &&
+           ParseBoolean("wantXrays", &wantXrays) &&
+           ParseBoolean("wantComponents", &wantComponents) &&
+           ParseBoolean("wantExportHelpers", &wantExportHelpers) &&
+           ParseString("sandboxName", sandboxName) &&
+           ParseObject("sameZoneAs", &sameZoneAs) &&
+           ParseGlobalProperties() &&
+           ParseValue("metadata", &metadata, &found);
 }
 
 static nsresult
 AssembleSandboxMemoryReporterName(JSContext *cx, nsCString &sandboxName)
 {
     // Use a default name when the caller did not provide a sandboxName.
     if (sandboxName.IsEmpty())
         sandboxName = NS_LITERAL_CSTRING("[anonymous sandbox]");
@@ -1428,59 +1417,61 @@ nsresult
 nsXPCComponents_utils_Sandbox::CallOrConstruct(nsIXPConnectWrappedNative *wrapper,
                                                JSContext *cx, HandleObject obj,
                                                const CallArgs &args, bool *_retval)
 {
     if (args.length() < 1)
         return ThrowAndFail(NS_ERROR_XPC_NOT_ENOUGH_ARGS, cx, _retval);
 
     nsresult rv;
+    bool ok = false;
 
     // Make sure to set up principals on the sandbox before initing classes.
     nsCOMPtr<nsIPrincipal> principal;
     nsCOMPtr<nsIExpandedPrincipal> expanded;
     nsCOMPtr<nsISupports> prinOrSop;
 
     if (args[0].isString()) {
         RootedString str(cx, args[0].toString());
-        rv = GetPrincipalFromString(cx, str, getter_AddRefs(principal));
+        ok = ParsePrincipal(cx, str, getter_AddRefs(principal));
         prinOrSop = principal;
     } else if (args[0].isObject()) {
         RootedObject obj(cx, &args[0].toObject());
         if (JS_IsArrayObject(cx, obj)) {
-            rv = GetExpandedPrincipal(cx, obj, getter_AddRefs(expanded));
+            ok = GetExpandedPrincipal(cx, obj, getter_AddRefs(expanded));
             prinOrSop = expanded;
         } else {
-            rv = GetPrincipalOrSOP(cx, obj, getter_AddRefs(prinOrSop));
+            ok = GetPrincipalOrSOP(cx, obj, getter_AddRefs(prinOrSop));
         }
-    } else {
-        return ThrowAndFail(NS_ERROR_INVALID_ARG, cx, _retval);
     }
 
-    if (NS_FAILED(rv))
-        return ThrowAndFail(rv, cx, _retval);
+    if (!ok)
+        return ThrowAndFail(NS_ERROR_INVALID_ARG, cx, _retval);
 
-    SandboxOptions options(cx);
+    bool calledWithOptions = args.length() > 1;
+    if (calledWithOptions && !args[1].isObject())
+        return ThrowAndFail(NS_ERROR_INVALID_ARG, cx, _retval);
 
-    if (args.length() > 1 && args[1].isObject()) {
-        if (NS_FAILED(ParseOptionsObject(cx, args[1], options)))
-            return ThrowAndFail(NS_ERROR_INVALID_ARG, cx, _retval);
-    }
+    RootedObject optionsObject(cx, calledWithOptions ? &args[1].toObject()
+                                                     : nullptr);
+
+    SandboxOptions options(cx, optionsObject);
+    if (calledWithOptions && !options.Parse())
+        return ThrowAndFail(NS_ERROR_INVALID_ARG, cx, _retval);
 
     if (NS_FAILED(AssembleSandboxMemoryReporterName(cx, options.sandboxName)))
         return ThrowAndFail(NS_ERROR_INVALID_ARG, cx, _retval);
 
     rv = CreateSandboxObject(cx, args.rval().address(), prinOrSop, options);
 
     if (NS_FAILED(rv))
         return ThrowAndFail(rv, cx, _retval);
 
     *_retval = true;
-
-    return rv;
+    return NS_OK;
 }
 
 class ContextHolder : public nsIScriptObjectPrincipal
 {
 public:
     ContextHolder(JSContext *aOuterCx, HandleObject aSandbox, nsIPrincipal *aPrincipal);
     virtual ~ContextHolder();
 
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -3320,17 +3320,17 @@ XPCJSRuntime::RemoveContextCallback(xpcC
     }
 }
 
 JSObject *
 XPCJSRuntime::GetJunkScope()
 {
     if (!mJunkScope) {
         AutoSafeJSContext cx;
-        SandboxOptions options(cx);
+        SandboxOptions options;
         options.sandboxName.AssignASCII("XPConnect Junk Compartment");
         RootedValue v(cx);
         nsresult rv = CreateSandboxObject(cx, v.address(),
                                           nsContentUtils::GetSystemPrincipal(),
                                           options);
 
         NS_ENSURE_SUCCESS(rv, nullptr);
 
--- a/js/xpconnect/src/XPCWrappedNativeScope.cpp
+++ b/js/xpconnect/src/XPCWrappedNativeScope.cpp
@@ -240,17 +240,17 @@ XPCWrappedNativeScope::EnsureXBLScope(JS
     // Set up the sandbox options. Note that we use the DOM global as the
     // sandboxPrototype so that the XBL scope can access all the DOM objects
     // it's accustomed to accessing.
     //
     // NB: One would think that wantXrays wouldn't make a difference here.
     // However, wantXrays lives a secret double life, and one of its other
     // hobbies is to waive Xray on the returned sandbox when set to false.
     // So make sure to keep this set to true, here.
-    SandboxOptions options(cx);
+    SandboxOptions options;
     options.wantXrays = true;
     options.wantComponents = true;
     options.proto = global;
     options.sameZoneAs = global;
 
     // Use an nsExpandedPrincipal to create asymmetric security.
     nsIPrincipal *principal = GetPrincipal();
     nsCOMPtr<nsIExpandedPrincipal> ep;
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -252,18 +252,17 @@ xpc::SystemErrorReporter(JSContext *cx, 
               uclinebuf ? nsDependentString(uclinebuf) : EmptyString(),
               rep->lineno, column, rep->flags,
               "system javascript");
         if (NS_SUCCEEDED(rv))
             consoleService->LogMessage(errorObject);
     }
 
     if (nsContentUtils::DOMWindowDumpEnabled()) {
-        fprintf(stderr, "System JS : %s %s:%d\n"
-                "                     %s\n",
+        fprintf(stderr, "System JS : %s %s:%d - %s\n",
                 JSREPORT_IS_WARNING(rep->flags) ? "WARNING" : "ERROR",
                 rep->filename, rep->lineno,
                 message ? message : "<no message>");
     }
 
 }
 
 NS_EXPORT_(void)
@@ -908,17 +907,17 @@ nsXPConnect::ClearAllWrappedNativeSecuri
 NS_IMETHODIMP
 nsXPConnect::CreateSandbox(JSContext *cx, nsIPrincipal *principal,
                            nsIXPConnectJSObjectHolder **_retval)
 {
     *_retval = nullptr;
 
     RootedValue rval(cx, JSVAL_VOID);
 
-    SandboxOptions options(cx);
+    SandboxOptions options;
     nsresult rv = CreateSandboxObject(cx, rval.address(), principal, options);
     MOZ_ASSERT(NS_FAILED(rv) || !JSVAL_IS_PRIMITIVE(rval),
                "Bad return value from xpc_CreateSandboxObject()!");
 
     if (NS_SUCCEEDED(rv) && !JSVAL_IS_PRIMITIVE(rval)) {
         *_retval = XPCJSObjectHolder::newHolder(JSVAL_TO_OBJECT(rval));
         NS_ENSURE_TRUE(*_retval, NS_ERROR_OUT_OF_MEMORY);
 
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -3602,34 +3602,62 @@ struct GlobalProperties {
 // Infallible.
 already_AddRefed<nsIXPCComponents_utils_Sandbox>
 NewSandboxConstructor();
 
 // Returns true if class of 'obj' is SandboxClass.
 bool
 IsSandbox(JSObject *obj);
 
-struct SandboxOptions {
-    SandboxOptions(JSContext *cx)
-        : wantXrays(true)
+class MOZ_STACK_CLASS OptionsBase {
+public:
+    OptionsBase(JSContext *cx = xpc_GetSafeJSContext(),
+                JS::HandleObject options = JS::NullPtr())
+        : mCx(cx)
+        , mObject(cx, options)
+    { }
+
+    virtual bool Parse() = 0;
+
+protected:
+    bool ParseValue(const char *name, JS::MutableHandleValue prop, bool *found);
+    bool ParseBoolean(const char *name, bool *prop);
+    bool ParseObject(const char *name, JS::MutableHandleObject prop);
+    bool ParseString(const char *name, nsCString &prop);
+
+    JSContext *mCx;
+    JS::RootedObject mObject;
+};
+
+class MOZ_STACK_CLASS SandboxOptions : public OptionsBase {
+public:
+    SandboxOptions(JSContext *cx = xpc_GetSafeJSContext(),
+                   JS::HandleObject options = JS::NullPtr())
+        : OptionsBase(cx, options)
+        , wantXrays(true)
         , wantComponents(true)
         , wantExportHelpers(false)
-        , proto(xpc_GetSafeJSContext())
-        , sameZoneAs(xpc_GetSafeJSContext())
-        , metadata(xpc_GetSafeJSContext())
+        , proto(cx)
+        , sameZoneAs(cx)
+        , metadata(cx)
     { }
 
+    virtual bool Parse();
+
     bool wantXrays;
     bool wantComponents;
     bool wantExportHelpers;
     JS::RootedObject proto;
     nsCString sandboxName;
     JS::RootedObject sameZoneAs;
     GlobalProperties globalProperties;
     JS::RootedValue metadata;
+
+protected:
+    bool ParseGlobalProperties();
 };
 
 JSObject *
 CreateGlobalObject(JSContext *cx, const JSClass *clasp, nsIPrincipal *principal,
                    JS::CompartmentOptions& aOptions);
 
 // Helper for creating a sandbox object to use for evaluating
 // untrusted code completely separated from all other code in the
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -411,19 +411,17 @@ protected:
 #ifdef DEBUG
   FILE* mDebugFile;
 #endif // DEBUG
 #endif // NS_PRINTING
 
   /* character set member data */
   int32_t mHintCharsetSource;
   nsCString mHintCharset;
-  nsCString mDefaultCharacterSet;
   nsCString mForceCharacterSet;
-  nsCString mPrevDocCharacterSet;
   
   bool mIsPageMode;
   bool mCallerIsClosingWindow;
   bool mInitializedForPrintPreview;
   bool mHidden;
 };
 
 class nsPrintEventDispatcher
@@ -2998,57 +2996,16 @@ nsDocumentViewer::StopEmulatingMedium()
   if (mDocument) {
     mDocument->EnumerateExternalResources(ExtResourceStopEmulatingMedium,
                                           nullptr);
   }
 
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsDocumentViewer::GetDefaultCharacterSet(nsACString& aDefaultCharacterSet)
-{
-  if (mDefaultCharacterSet.IsEmpty())
-  {
-    const nsAdoptingCString& defCharset =
-      Preferences::GetLocalizedCString("intl.charset.default");
-
-    // Don't let the user break things by setting intl.charset.default to
-    // not a rough ASCII superset
-    nsAutoCString canonical;
-    if (EncodingUtils::FindEncodingForLabel(defCharset, canonical) &&
-        EncodingUtils::IsAsciiCompatible(canonical)) {
-      mDefaultCharacterSet = canonical;
-    } else {
-      mDefaultCharacterSet.AssignLiteral("windows-1252");
-    }
-  }
-  aDefaultCharacterSet = mDefaultCharacterSet;
-  return NS_OK;
-}
-
-static void
-SetChildDefaultCharacterSet(nsIMarkupDocumentViewer* aChild, void* aClosure)
-{
-  const nsACString* charset = static_cast<nsACString*>(aClosure);
-  aChild->SetDefaultCharacterSet(*charset);
-}
-
-NS_IMETHODIMP
-nsDocumentViewer::SetDefaultCharacterSet(const nsACString& aDefaultCharacterSet)
-{
-  mDefaultCharacterSet = aDefaultCharacterSet;  // this does a copy of aDefaultCharacterSet
-  // now set the default char set on all children of mContainer
-  CallChildren(SetChildDefaultCharacterSet, (void*) &aDefaultCharacterSet);
-  return NS_OK;
-}
-
-// XXX: SEMANTIC CHANGE!
-//      returns a copy of the string.  Caller is responsible for freeing result
-//      using Recycle(aForceCharacterSet)
 NS_IMETHODIMP nsDocumentViewer::GetForceCharacterSet(nsACString& aForceCharacterSet)
 {
   aForceCharacterSet = mForceCharacterSet;
   return NS_OK;
 }
 
 static void
 SetChildForceCharacterSet(nsIMarkupDocumentViewer* aChild, void* aClosure)
@@ -3061,19 +3018,16 @@ NS_IMETHODIMP
 nsDocumentViewer::SetForceCharacterSet(const nsACString& aForceCharacterSet)
 {
   mForceCharacterSet = aForceCharacterSet;
   // now set the force char set on all children of mContainer
   CallChildren(SetChildForceCharacterSet, (void*) &aForceCharacterSet);
   return NS_OK;
 }
 
-// XXX: SEMANTIC CHANGE!
-//      returns a copy of the string.  Caller is responsible for freeing result
-//      using Recycle(aHintCharacterSet)
 NS_IMETHODIMP nsDocumentViewer::GetHintCharacterSet(nsACString& aHintCharacterSet)
 {
 
   if(kCharsetUninitialized == mHintCharsetSource) {
     aHintCharacterSet.Truncate();
   } else {
     aHintCharacterSet = mHintCharset;
     // this can't possibly be right.  we can't set a value just because somebody got a related value!
@@ -3085,41 +3039,16 @@ NS_IMETHODIMP nsDocumentViewer::GetHintC
 NS_IMETHODIMP nsDocumentViewer::GetHintCharacterSetSource(int32_t *aHintCharacterSetSource)
 {
   NS_ENSURE_ARG_POINTER(aHintCharacterSetSource);
 
   *aHintCharacterSetSource = mHintCharsetSource;
   return NS_OK;
 }
 
-
-NS_IMETHODIMP nsDocumentViewer::GetPrevDocCharacterSet(nsACString& aPrevDocCharacterSet)
-{
-  aPrevDocCharacterSet = mPrevDocCharacterSet;
-
-  return NS_OK;
-}
-
-static void
-SetChildPrevDocCharacterSet(nsIMarkupDocumentViewer* aChild, void* aClosure)
-{
-  const nsACString* charset = static_cast<nsACString*>(aClosure);
-  aChild->SetPrevDocCharacterSet(*charset);
-}
-
-
-NS_IMETHODIMP
-nsDocumentViewer::SetPrevDocCharacterSet(const nsACString& aPrevDocCharacterSet)
-{
-  mPrevDocCharacterSet = aPrevDocCharacterSet;  
-  CallChildren(SetChildPrevDocCharacterSet, (void*) &aPrevDocCharacterSet);
-  return NS_OK;
-}
-
-
 static void
 SetChildHintCharacterSetSource(nsIMarkupDocumentViewer* aChild, void* aClosure)
 {
   aChild->SetHintCharacterSetSource(NS_PTR_TO_INT32(aClosure));
 }
 
 NS_IMETHODIMP
 nsDocumentViewer::SetHintCharacterSetSource(int32_t aHintCharacterSetSource)
--- a/layout/base/nsIPresShell.h
+++ b/layout/base/nsIPresShell.h
@@ -121,20 +121,20 @@ typedef struct CapturingContentInfo {
   bool mAllowed;
   bool mPointerLock;
   bool mRetargetToElement;
   bool mPreventDrag;
   nsIContent* mContent;
 } CapturingContentInfo;
 
 
-// d39cd4ce-6b38-4793-8c1a-00985c56d931
+// f5b542a9-eaf0-4560-a656-37a9d379864c
 #define NS_IPRESSHELL_IID \
-{ 0xd39cd4ce, 0x6b38, 0x4793, \
-  { 0x8c, 0x1a, 0x00, 0x98, 0x5c, 0x56, 0xd9, 0x31 } }
+{ 0xf5b542a9, 0xeaf0, 0x4560, \
+  { 0x37, 0xa9, 0xd3, 0x79, 0x86, 0x4c } }
 
 // debug VerifyReflow flags
 #define VERIFY_REFLOW_ON                    0x01
 #define VERIFY_REFLOW_NOISY                 0x02
 #define VERIFY_REFLOW_ALL                   0x04
 #define VERIFY_REFLOW_DUMP_COMMANDS         0x08
 #define VERIFY_REFLOW_NOISY_RC              0x10
 #define VERIFY_REFLOW_REALLY_NOISY_RC       0x20
@@ -1462,16 +1462,27 @@ public:
   /**
    * Clear the flag indicating whether a reflow on zoom event is pending. This
    * is performed at the very end of DoReflow().
    */
   void ClearReflowOnZoomPending() {
     mReflowOnZoomPending = false;
   }
 
+  /**
+   * Documents belonging to an invisible DocShell must not be painted ever.
+   */
+  bool IsNeverPainting() {
+    return mIsNeverPainting;
+  }
+
+  void SetNeverPainting(bool aNeverPainting) {
+    mIsNeverPainting = aNeverPainting;
+  }
+
 protected:
   friend class nsRefreshDriver;
 
   // IMPORTANT: The ownership implicit in the following member variables
   // has been explicitly checked.  If you add any members to this class,
   // please make the ownership explicit (pinkerton, scc).
 
   // These are the same Document and PresContext owned by the DocViewer.
@@ -1583,11 +1594,16 @@ protected:
 
   // Flag to indicate whether or not there is a reflow on zoom event pending.
   // See IsReflowOnZoomPending() for more information.
   bool mReflowOnZoomPending;
 
   // The maximum width of a line box. Text on a single line that exceeds this
   // width will be wrapped. A value of 0 indicates that no limit is enforced.
   nscoord mMaxLineBoxWidth;
+  
+  // If a document belongs to an invisible DocShell, this flag must be set
+  // to true, so we can avoid any paint calls for widget related to this
+  // presshell.
+  bool mIsNeverPainting;
 };
 
 #endif /* nsIPresShell_h___ */
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -456,17 +456,17 @@ public:
         if (frame) {
           // chrome (including addons) should be able to know if content
           // handles both D3E "wheel" event and legacy mouse scroll events.
           // We should dispatch legacy mouse events before dispatching the
           // "wheel" event into system group.
           nsRefPtr<nsEventStateManager> esm =
             aVisitor.mPresContext->EventStateManager();
           esm->DispatchLegacyMouseScrollEvents(frame,
-                 static_cast<WheelEvent*>(aVisitor.mEvent),
+                 static_cast<WidgetWheelEvent*>(aVisitor.mEvent),
                  &aVisitor.mEventStatus);
         }
       }
       nsIFrame* frame = mPresShell->GetCurrentEventFrame();
       if (!frame &&
           (aVisitor.mEvent->message == NS_MOUSE_BUTTON_UP ||
            aVisitor.mEvent->message == NS_TOUCH_END)) {
         // Redirect BUTTON_UP and TOUCH_END events to the root frame to ensure
@@ -7419,17 +7419,17 @@ PresShell::GetCurrentItemAndPositionForE
   }
 
   NS_IF_ADDREF(*aTargetToUse = focusedContent);
 }
 
 bool
 PresShell::ShouldIgnoreInvalidation()
 {
-  return mPaintingSuppressed || !mIsActive;
+  return mPaintingSuppressed || !mIsActive || mIsNeverPainting;
 }
 
 void
 PresShell::WillPaint()
 {
   nsRootPresContext* rootPresContext = mPresContext->GetRootPresContext();
   if (!rootPresContext) {
     // In some edge cases, such as when we don't have a root frame yet,
--- a/layout/forms/nsTextControlFrame.cpp
+++ b/layout/forms/nsTextControlFrame.cpp
@@ -95,17 +95,17 @@ public:
 private:
   nsTextControlFrame &mFrame;
   bool mFirstEntry;
 };
 #endif
 
 nsTextControlFrame::nsTextControlFrame(nsIPresShell* aShell, nsStyleContext* aContext)
   : nsContainerFrame(aContext)
-  , mUseEditor(false)
+  , mEditorHasBeenInitialized(false)
   , mIsProcessing(false)
 #ifdef DEBUG
   , mInEditorInitialization(false)
 #endif
 {
 }
 
 nsTextControlFrame::~nsTextControlFrame()
@@ -248,19 +248,17 @@ nsTextControlFrame::EnsureEditorInitiali
   // PresShell listener which called FlushPendingNotifications()
   // during frame construction. This was causing other form controls
   // to display wrong values.  Additionally, calling this every time
   // a text frame control is instantiated means that we're effectively
   // instantiating the editor for all text fields, even if they
   // never get used.  So, now this method is being called lazily only
   // when we actually need an editor.
 
-  // Check if this method has been called already.
-  // If so, just return early.
-  if (mUseEditor)
+  if (mEditorHasBeenInitialized)
     return NS_OK;
 
   nsIDocument* doc = mContent->GetCurrentDoc();
   NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
 
   nsWeakFrame weakFrame(this);
 
   // Flush out content on our document.  Have to do this, because script
@@ -303,19 +301,19 @@ nsTextControlFrame::EnsureEditorInitiali
 
     // Create an editor for the frame, if one doesn't already exist
     nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent());
     NS_ASSERTION(txtCtrl, "Content not a text control element");
     nsresult rv = txtCtrl->CreateEditor();
     NS_ENSURE_SUCCESS(rv, rv);
     NS_ENSURE_STATE(weakFrame.IsAlive());
 
-    // Turn on mUseEditor so that subsequent calls will use the
+    // Set mEditorHasBeenInitialized so that subsequent calls will use the
     // editor.
-    mUseEditor = true;
+    mEditorHasBeenInitialized = true;
 
     // Set the selection to the beginning of the text field.
     if (weakFrame.IsAlive()) {
       SetSelectionEndPoints(0, 0);
     }
   }
   NS_ENSURE_STATE(weakFrame.IsAlive());
   return NS_OK;
@@ -1133,17 +1131,17 @@ nsTextControlFrame::AttributeChanged(int
     selCon->SetDisplaySelection(displaySelection);
     if (focused) {
       selCon->SetCaretEnabled(!hasAttr);
     }
     editor->SetFlags(flags);
     return NS_OK;
   }
 
-  if (!mUseEditor && nsGkAtoms::value == aAttribute) {
+  if (!mEditorHasBeenInitialized && nsGkAtoms::value == aAttribute) {
     UpdateValueDisplay(true);
     return NS_OK;
   }
 
   // Allow the base class to handle common attributes supported by all form
   // elements...
   return nsContainerFrame::AttributeChanged(aNameSpaceID, aAttribute, aModType);
 }
@@ -1275,17 +1273,17 @@ nsTextControlFrame::UpdateValueDisplay(b
   if (!IsSingleLineTextControl()) // textareas don't use this
     return NS_OK;
 
   nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent());
   NS_ASSERTION(txtCtrl, "Content not a text control element");
   nsIContent* rootNode = txtCtrl->GetRootEditorNode();
 
   NS_PRECONDITION(rootNode, "Must have a div content\n");
-  NS_PRECONDITION(!mUseEditor,
+  NS_PRECONDITION(!mEditorHasBeenInitialized,
                   "Do not call this after editor has been initialized");
   NS_ASSERTION(!mUsePlaceholder || txtCtrl->GetPlaceholderNode(),
                "A placeholder div must exist");
 
   nsIContent *textContent = rootNode->GetChildAt(0);
   if (!textContent) {
     // Set up a textnode with our value
     nsRefPtr<nsTextNode> textNode =
--- a/layout/forms/nsTextControlFrame.h
+++ b/layout/forms/nsTextControlFrame.h
@@ -296,17 +296,17 @@ private:
   nsresult GetRootNodeAndInitializeEditor(nsIDOMElement **aRootElement);
 
   void FinishedInitializer() {
     Properties().Delete(TextControlInitializer());
   }
 
 private:
   // these packed bools could instead use the high order bits on mState, saving 4 bytes 
-  bool mUseEditor;
+  bool mEditorHasBeenInitialized;
   bool mIsProcessing;
   // Keep track if we have asked a placeholder node creation.
   bool mUsePlaceholder;
 
 #ifdef DEBUG
   bool mInEditorInitialization;
   friend class EditorInitializerEntryTracker;
 #endif
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -2418,18 +2418,23 @@ var DesktopUserAgent = {
       } catch (ex) { }
     }
 
     return null;
   },
 
   _getWindowForRequest: function ua_getWindowForRequest(aRequest) {
     let loadContext = this._getRequestLoadContext(aRequest);
-    if (loadContext)
-      return loadContext.associatedWindow;
+    if (loadContext) {
+      try {
+        return loadContext.associatedWindow;
+      } catch (e) {
+        // loadContext.associatedWindow can throw when there's no window
+      }
+    }
     return null;
   },
 
   observe: function ua_observe(aSubject, aTopic, aData) {
     if (aTopic === "DesktopMode:Change") {
       let args = JSON.parse(aData);
       let tab = BrowserApp.getTabForId(args.tabId);
       if (tab != null)
--- a/netwerk/protocol/http/UserAgentOverrides.jsm
+++ b/netwerk/protocol/http/UserAgentOverrides.jsm
@@ -51,17 +51,18 @@ this.UserAgentOverrides = {
       gUpdatedOverrides = overrides;
     });
 
     buildOverrides();
     gInitialized = true;
   },
 
   addComplexOverride: function uao_addComplexOverride(callback) {
-    gOverrideFunctions.push(callback);
+    // Add to front of array so complex overrides have precedence
+    gOverrideFunctions.unshift(callback);
   },
 
   getOverrideForURI: function uao_getOverrideForURI(aURI) {
     if (!gInitialized ||
         (!gOverrides.size && !gUpdatedOverrides) ||
         !(aURI instanceof Ci.nsIStandardURL))
       return null;
 
--- a/parser/html/nsHtml5StreamParser.cpp
+++ b/parser/html/nsHtml5StreamParser.cpp
@@ -794,18 +794,23 @@ nsHtml5StreamParser::SniffStreamBytes(co
 }
 
 nsresult
 nsHtml5StreamParser::WriteStreamBytes(const uint8_t* aFromSegment,
                                       uint32_t aCount,
                                       uint32_t* aWriteCount)
 {
   NS_ASSERTION(IsParserThread(), "Wrong thread!");
-  // mLastBuffer always points to a buffer of the size
+  // mLastBuffer should always point to a buffer of the size
   // NS_HTML5_STREAM_PARSER_READ_BUFFER_SIZE.
+  if (!mLastBuffer) {
+    NS_WARNING("mLastBuffer should not be null!");
+    MarkAsBroken();
+    return NS_ERROR_NULL_POINTER;
+  }
   if (mLastBuffer->getEnd() == NS_HTML5_STREAM_PARSER_READ_BUFFER_SIZE) {
     nsRefPtr<nsHtml5OwningUTF16Buffer> newBuf =
       nsHtml5OwningUTF16Buffer::FalliblyCreate(
         NS_HTML5_STREAM_PARSER_READ_BUFFER_SIZE);
     if (!newBuf) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
     mLastBuffer = (mLastBuffer->next = newBuf.forget());
--- a/parser/html/nsHtml5TreeOpExecutor.cpp
+++ b/parser/html/nsHtml5TreeOpExecutor.cpp
@@ -216,49 +216,16 @@ nsHtml5TreeOpExecutor::FlushPendingNotif
 
 void
 nsHtml5TreeOpExecutor::SetDocumentCharsetAndSource(nsACString& aCharset, int32_t aCharsetSource)
 {
   if (mDocument) {
     mDocument->SetDocumentCharacterSetSource(aCharsetSource);
     mDocument->SetDocumentCharacterSet(aCharset);
   }
-  if (mDocShell) {
-    // the following logic to get muCV is copied from
-    // nsHTMLDocument::StartDocumentLoad
-    // We need to call muCV->SetPrevDocCharacterSet here in case
-    // the charset is detected by parser DetectMetaTag
-    nsCOMPtr<nsIMarkupDocumentViewer> mucv;
-    nsCOMPtr<nsIContentViewer> cv;
-    mDocShell->GetContentViewer(getter_AddRefs(cv));
-    if (cv) {
-      mucv = do_QueryInterface(cv);
-    } else {
-      // in this block of code, if we get an error result, we return
-      // it but if we get a null pointer, that's perfectly legal for
-      // parent and parentContentViewer
-      if (!mDocShell) {
-    	  return;
-      }
-      nsCOMPtr<nsIDocShellTreeItem> parentAsItem;
-      mDocShell->GetSameTypeParent(getter_AddRefs(parentAsItem));
-      nsCOMPtr<nsIDocShell> parent(do_QueryInterface(parentAsItem));
-      if (parent) {
-        nsCOMPtr<nsIContentViewer> parentContentViewer;
-        nsresult rv =
-          parent->GetContentViewer(getter_AddRefs(parentContentViewer));
-        if (NS_SUCCEEDED(rv) && parentContentViewer) {
-          mucv = do_QueryInterface(parentContentViewer);
-        }
-      }
-    }
-    if (mucv) {
-      mucv->SetPrevDocCharacterSet(aCharset);
-    }
-  }
 }
 
 nsISupports*
 nsHtml5TreeOpExecutor::GetTarget()
 {
   return mDocument;
 }
 
--- a/parser/nsCharsetSource.h
+++ b/parser/nsCharsetSource.h
@@ -3,24 +3,23 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsCharsetSource_h_
 #define nsCharsetSource_h_
 
 // note: the value order defines the priority; higher numbers take priority
 #define kCharsetUninitialized           0
 #define kCharsetFromWeakDocTypeDefault  1
-#define kCharsetFromUserDefault         2
-#define kCharsetFromDocTypeDefault      3 // This and up confident for XHR
-#define kCharsetFromCache               4
-#define kCharsetFromParentFrame         5
-#define kCharsetFromAutoDetection       6
-#define kCharsetFromHintPrevDoc         7
-#define kCharsetFromMetaPrescan         8 // this one and smaller: HTML5 Tentative
-#define kCharsetFromMetaTag             9 // this one and greater: HTML5 Confident
-#define kCharsetFromIrreversibleAutoDetection 10
-#define kCharsetFromChannel            11
-#define kCharsetFromOtherComponent     12
-#define kCharsetFromParentForced       13 // propagates to child frames
-#define kCharsetFromUserForced         14 // propagates to child frames
-#define kCharsetFromByteOrderMark      15
+#define kCharsetFromDocTypeDefault      2 // This and up confident for XHR
+#define kCharsetFromCache               3
+#define kCharsetFromParentFrame         4
+#define kCharsetFromAutoDetection       5
+#define kCharsetFromHintPrevDoc         6
+#define kCharsetFromMetaPrescan         7 // this one and smaller: HTML5 Tentative
+#define kCharsetFromMetaTag             8 // this one and greater: HTML5 Confident
+#define kCharsetFromIrreversibleAutoDetection 9
+#define kCharsetFromChannel            10
+#define kCharsetFromOtherComponent     11
+#define kCharsetFromParentForced       12 // propagates to child frames
+#define kCharsetFromUserForced         13 // propagates to child frames
+#define kCharsetFromByteOrderMark      14
 
 #endif /* nsCharsetSource_h_ */
--- a/testing/mozbase/generate_diff.py
+++ b/testing/mozbase/generate_diff.py
@@ -115,26 +115,28 @@ def generate_packages_txt():
     """
     generate a packages.txt file appropriate for
     http://mxr.mozilla.org/mozilla-central/source/build/virtualenv/populate_virtualenv.py
 
     See also:
     http://mxr.mozilla.org/mozilla-central/source/build/virtualenv/packages.txt
     """
 
-    prefix = 'testing/mozbase/' # relative path from topsrcdir
+    # relative path from topsrcdir
+    prefix = 'testing/mozbase/'
 
     # gather the packages
     packages = setup_development.mozbase_packages
 
     # write them in the appropriate format
     path = os.path.join(here, 'packages.txt')
-    with file(path, 'w') as f:
-        for package in sorted(packages):
-            f.write("%s.pth:%s%s\n" % (package, prefix, package))
+    packages_manifest = [("%s.pth:%s%s\n" % (package, prefix, package))
+                         for package in sorted(packages)]
+    with open(path, 'wb') as f:
+        f.writelines(packages_manifest)
 
 ### version-related functions
 
 def parse_versions(*args):
     """return a list of 2-tuples of (directory, version)"""
 
     retval = []
     for arg in args:
--- a/toolkit/components/telemetry/TelemetryPing.js
+++ b/toolkit/components/telemetry/TelemetryPing.js
@@ -544,18 +544,19 @@ TelemetryPing.prototype = {
       slowSQL: Telemetry.slowSQL,
       chromeHangs: Telemetry.chromeHangs,
       lateWrites: Telemetry.lateWrites,
       addonHistograms: this.getAddonHistograms(),
       addonDetails: AddonManagerPrivate.getTelemetryDetails(),
       info: info
     };
 
-    if (Object.keys(this._slowSQLStartup.mainThread).length
-      || Object.keys(this._slowSQLStartup.otherThreads).length) {
+    if (Object.keys(this._slowSQLStartup).length != 0 &&
+        (Object.keys(this._slowSQLStartup.mainThread).length ||
+         Object.keys(this._slowSQLStartup.otherThreads).length)) {
       payloadObj.slowSQLStartup = this._slowSQLStartup;
     }
 
     return payloadObj;
   },
 
   getSessionPayload: function getSessionPayload(reason) {
     let measurements = this.getSimpleMeasurements(reason == "saved-session");
--- a/toolkit/components/viewsource/content/viewSource.js
+++ b/toolkit/components/viewsource/content/viewSource.js
@@ -105,19 +105,19 @@ function viewSource(url)
     var charset;
     if (window.arguments.length >= 2) {
       arg = window.arguments[1];
 
       try {
         if (typeof(arg) == "string" && arg.indexOf('charset=') != -1) {
           var arrayArgComponents = arg.split('=');
           if (arrayArgComponents) {
-            //we should "inherit" the charset menu setting in a new window
+            // Remember the charset here so that it can be used below in case
+            // the document had a forced charset.
             charset = arrayArgComponents[1];
-            gBrowser.markupDocumentViewer.defaultCharacterSet = charset;
           }
         }
       } catch (ex) {
         // Ignore the failure and keep processing arguments...
       }
     }
     // If the document had a forced charset, set it here also
     if (window.arguments.length >= 5) {
--- a/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp
+++ b/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp
@@ -308,27 +308,33 @@ proxy_MaskIPv6Addr(PRIPv6Addr &addr, uin
     addr.pr_s6_addr32[2] = 0;
     addr.pr_s6_addr32[1] = 0;
     addr.pr_s6_addr32[0] = PR_htonl(
             PR_ntohl(addr.pr_s6_addr32[0]) & (~0L << (32 - mask_len)));
   }
 }
 
 static bool ConvertToIPV6Addr(const nsACString& aName,
-                                PRIPv6Addr* aAddr)
+                                PRIPv6Addr* aAddr, int32_t* aMask)
 {
   PRNetAddr addr;
   // try to convert hostname to IP
   if (PR_StringToNetAddr(PromiseFlatCString(aName).get(), &addr) != PR_SUCCESS)
     return false;
 
   // convert parsed address to IPv6
   if (addr.raw.family == PR_AF_INET) {
     // convert to IPv4-mapped address
     PR_ConvertIPv4AddrToIPv6(addr.inet.ip, aAddr);
+    if (aMask) {
+      if (*aMask <= 32)
+        *aMask += 96;
+      else
+        return false;
+    }
   } else if (addr.raw.family == PR_AF_INET6) {
     // copy the address
     memcpy(aAddr, &addr.ipv6.ip, sizeof(PRIPv6Addr));
   } else {
     return false;
   }
   
   return true;
@@ -363,18 +369,18 @@ static bool HostIgnoredByProxy(const nsA
     }
     --slash;
   } else {
     slash = end;
   }
 
   nsDependentCSubstring ignoreStripped(start, slash);
   PRIPv6Addr ignoreAddr, hostAddr;
-  if (!ConvertToIPV6Addr(ignoreStripped, &ignoreAddr) ||
-      !ConvertToIPV6Addr(aHost, &hostAddr))
+  if (!ConvertToIPV6Addr(ignoreStripped, &ignoreAddr, &mask) ||
+      !ConvertToIPV6Addr(aHost, &hostAddr, NULL))
     return false;
 
   proxy_MaskIPv6Addr(ignoreAddr, mask);
   proxy_MaskIPv6Addr(hostAddr, mask);
   
   return memcmp(&ignoreAddr, &hostAddr, sizeof(PRIPv6Addr)) == 0;
 }
 
--- a/view/src/nsViewManager.cpp
+++ b/view/src/nsViewManager.cpp
@@ -290,16 +290,20 @@ nsView* nsViewManager::GetDisplayRootFor
    aRegion is given in device coordinates!!
    aContext may be null, in which case layers should be used for
    rendering.
 */
 void nsViewManager::Refresh(nsView *aView, const nsIntRegion& aRegion)
 {
   NS_ASSERTION(aView->GetViewManager() == this, "wrong view manager");
 
+  if (mPresShell && mPresShell->IsNeverPainting()) {
+    return;
+  }
+
   // damageRegion is the damaged area, in twips, relative to the view origin
   nsRegion damageRegion = aRegion.ToAppUnits(AppUnitsPerDevPixel());
   // move region from widget coordinates into view coordinates
   damageRegion.MoveBy(-aView->ViewToWidgetOffset());
 
   if (damageRegion.IsEmpty()) {
 #ifdef DEBUG_roc
     nsRect viewRect = aView->GetDimensions();
@@ -365,16 +369,20 @@ void nsViewManager::ProcessPendingUpdate
 {
   NS_ASSERTION(IsRootVM(), "Updates will be missed");
 
   // Protect against a null-view.
   if (!aView) {
     return;
   }
 
+  if (mPresShell && mPresShell->IsNeverPainting()) {
+    return;
+  }
+
   if (aView->HasWidget()) {
     aView->ResetWidgetBounds(false, true);
   }
 
   // process pending updates in child view.
   for (nsView* childView = aView->GetFirstChild(); childView;
        childView = childView->GetNextSibling()) {
     ProcessPendingUpdatesForView(childView, aFlushDirtyRegion);
@@ -410,16 +418,17 @@ void nsViewManager::ProcessPendingUpdate
       SetPainting(true);
       mPresShell->Paint(aView, nsRegion(),
                         nsIPresShell::PAINT_LAYERS);
 #ifdef MOZ_DUMP_PAINTING
       if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) {
         printf("---- PAINT END ----\n");
       }
 #endif
+
       aView->SetForcedRepaint(false);
       SetPainting(false);
       FlushDirtyRegionToWidget(aView);
     } else {
       FlushDirtyRegionToWidget(aView);
     }
   }
 }
--- a/widget/EventForwards.h
+++ b/widget/EventForwards.h
@@ -97,14 +97,9 @@ class InternalAnimationEvent;
 class WidgetCommandEvent;
 class WidgetContentCommandEvent;
 class WidgetPluginEvent;
 
 // MutationEvent.h (content/events/public)
 class InternalMutationEvent;
 } // namespace mozilla
 
-// TODO: Remove following typedefs
-namespace mozilla {
-typedef WidgetWheelEvent                   WheelEvent;
-}
-
 #endif // mozilla_EventForwards_h__
--- a/widget/MouseEvents.h
+++ b/widget/MouseEvents.h
@@ -421,14 +421,11 @@ public:
     lineOrPageDeltaY = aEvent.lineOrPageDeltaY;
     scrollType = aEvent.scrollType;
     overflowDeltaX = aEvent.overflowDeltaX;
     overflowDeltaY = aEvent.overflowDeltaY;
     mViewPortIsOverscrolled = aEvent.mViewPortIsOverscrolled;
   }
 };
 
-// TODO: Remove following typedef
-typedef WidgetWheelEvent                WheelEvent;
-
 } // namespace mozilla
 
 #endif // mozilla_MouseEvents_h__
--- a/widget/cocoa/nsChildView.mm
+++ b/widget/cocoa/nsChildView.mm
@@ -4201,37 +4201,37 @@ NSEvent* gLastDragMouseDownEvent = nil;
     }
   } else {
     return;
   }
 
   // Track the direction we're going in.
   mCurrentSwipeDir = direction;
 
-  // If a swipe is currently being tracked kill it -- it's been interrupted
-  // by another gesture event.
-  if (mCancelSwipeAnimation && *mCancelSwipeAnimation == NO) {
-    *mCancelSwipeAnimation = YES;
-    mCancelSwipeAnimation = nil;
-  }
-
   uint32_t allowedDirections = 0;
   // We're ready to start the animation. Tell Gecko about it, and at the same
   // time ask it if it really wants to start an animation for this event.
   // This event also reports back the directions that we can swipe in.
   bool shouldStartSwipe = [self sendSwipeEvent:anEvent
                                       withKind:NS_SIMPLE_GESTURE_SWIPE_START
                              allowedDirections:&allowedDirections
                                      direction:direction
                                          delta:0.0];
 
   if (!shouldStartSwipe) {
     return;
   }
 
+  // If a swipe is currently being tracked kill it -- it's been interrupted
+  // by another gesture event.
+  if (mCancelSwipeAnimation && *mCancelSwipeAnimation == NO) {
+    *mCancelSwipeAnimation = YES;
+    mCancelSwipeAnimation = nil;
+  }
+
   CGFloat min = 0.0;
   CGFloat max = 0.0;
   if (!(direction & vDirs)) {
     min = (allowedDirections & nsIDOMSimpleGestureEvent::DIRECTION_RIGHT) ?
           -1.0 : 0.0;
     max = (allowedDirections & nsIDOMSimpleGestureEvent::DIRECTION_LEFT) ?
           1.0 : 0.0;
   }
--- a/widget/gonk/HwcComposer2D.cpp
+++ b/widget/gonk/HwcComposer2D.cpp
@@ -152,21 +152,23 @@ HwcComposer2D::PrepareLayerList(Layer* a
 
     bool fillColor = false;
 
     const nsIntRegion& visibleRegion = aLayer->GetEffectiveVisibleRegion();
     if (visibleRegion.IsEmpty()) {
         return true;
     }
 
-    float opacity = aLayer->GetEffectiveOpacity();
-    if (opacity < 1) {
+    uint8_t opacity = std::min(0xFF, (int)(aLayer->GetEffectiveOpacity() * 256.0));
+#if ANDROID_VERSION < 18
+    if (opacity < 0xFF) {
         LOGD("%s Layer has planar semitransparency which is unsupported", aLayer->Name());
         return false;
     }
+#endif
 
     nsIntRect clip;
     if (!HwcUtils::CalculateClipRect(aParentTransform * aGLWorldTransform,
                                      aLayer->GetEffectiveClipRect(),
                                      aClip,
                                      &clip))
     {
         LOGD("%s Clip rect is empty. Skip layer", aLayer->Name());
@@ -271,17 +273,17 @@ HwcComposer2D::PrepareLayerList(Layer* a
     hwcLayer.flags = 0;
     hwcLayer.hints = 0;
     hwcLayer.blending = HWC_BLENDING_PREMULT;
 #if ANDROID_VERSION >= 18
     hwcLayer.compositionType = HWC_FRAMEBUFFER;
 
     hwcLayer.acquireFenceFd = -1;
     hwcLayer.releaseFenceFd = -1;
-    hwcLayer.planeAlpha = 0xFF; // Until plane alpha is enabled
+    hwcLayer.planeAlpha = opacity;
 #else
     hwcLayer.compositionType = HwcUtils::HWC_USE_COPYBIT;
 #endif
 
     if (!fillColor) {
         if (state.FormatRBSwapped()) {
             if (!mRBSwapSupport) {
                 LOGD("No R/B swap support in H/W Composer");
@@ -429,16 +431,17 @@ HwcComposer2D::PrepareLayerList(Layer* a
         ColorLayer* colorLayer = aLayer->AsColorLayer();
         if (colorLayer->GetColor().a < 1.0) {
             LOGD("Color layer has semitransparency which is unsupported");
             return false;
         }
         hwcLayer.transform = colorLayer->GetColor().Packed();
     }
 
+    mHwcLayerMap.AppendElement(static_cast<LayerComposite*>(aLayer->ImplData()));
     mList->numHwLayers++;
     return true;
 }
 
 
 #if ANDROID_VERSION >= 18
 bool
 HwcComposer2D::TryHwComposition()
@@ -456,23 +459,39 @@ HwcComposer2D::TryHwComposition()
         if (!ReallocLayerList() || idx >= mMaxLayerCount) {
             LOGE("TryHwComposition failed! Could not add FB layer");
             return false;
         }
     }
 
     Prepare(fbsurface->lastHandle, -1);
 
+    bool fullHwcComposite = true;
     for (int j = 0; j < idx; j++) {
         if (mList->hwLayers[j].compositionType == HWC_FRAMEBUFFER) {
+            // After prepare, if there is an HWC_FRAMEBUFFER layer,
+            // it means full HWC Composition is not possible this time
             LOGD("GPU or Partial HWC Composition");
-            return false;
+            fullHwcComposite = false;
+            break;
         }
     }
 
+    if (!fullHwcComposite) {
+        for (int k=0; k < idx; k++) {
+            if (mList->hwLayers[k].compositionType == HWC_OVERLAY) {
+                // HWC will compose HWC_OVERLAY layers in partial
+                // HWC Composition, so set layer composition flag
+                // on mapped LayerComposite to skip GPU composition
+                mHwcLayerMap[k]->SetLayerComposited(true);
+            }
+        }
+        return false;
+    }
+
     // Full HWC Composition
     Commit();
 
     // No composition on FB layer, so closing releaseFenceFd
     close(mList->hwLayers[idx].releaseFenceFd);
     mList->hwLayers[idx].releaseFenceFd = -1;
     mList->numHwLayers = 0;
     return true;
@@ -549,38 +568,36 @@ HwcComposer2D::Prepare(buffer_handle_t f
 bool
 HwcComposer2D::Commit()
 {
     hwc_display_contents_1_t *displays[HWC_NUM_DISPLAY_TYPES] = { nullptr };
     displays[HWC_DISPLAY_PRIMARY] = mList;
 
     int err = mHwc->set(mHwc, HWC_NUM_DISPLAY_TYPES, displays);
 
-    for (int i = 0; i <= MAX_HWC_LAYERS; i++) {
-        if (mPrevRelFd[i] <= 0) {
-            break;
+    if (!mPrevReleaseFds.IsEmpty()) {
+        // Wait for previous retire Fence to signal.
+        // Denotes contents on display have been replaced.
+        // For buffer-sync, framework should not over-write
+        // prev buffers until we close prev releaseFenceFds
+        sp<Fence> fence = new Fence(mPrevReleaseFds[0]);
+        if (fence->wait(1000) == -ETIME) {
+            LOGE("Wait timed-out for retireFenceFd %d", mPrevReleaseFds[0]);
         }
-        if (!i) {
-            // Wait for previous retire Fence to signal.
-            // Denotes contents on display have been replaced.
-            // For buffer-sync, framework should not over-write
-            // prev buffers until we close prev releaseFenceFds
-            sp<Fence> fence = new Fence(mPrevRelFd[i]);
-            if (fence->wait(1000) == -ETIME) {
-                LOGE("Wait timed-out for retireFenceFd %d", mPrevRelFd[i]);
-            }
+
+        for (int i = 0; i < mPrevReleaseFds.Length(); i++) {
+            close(mPrevReleaseFds[i]);
         }
-        close(mPrevRelFd[i]);
-        mPrevRelFd[i] = -1;
+        mPrevReleaseFds.Clear();
     }
 
-    mPrevRelFd[0] = mList->retireFenceFd;
-    for (uint32_t j = 0; j < (mList->numHwLayers - 1); j++) {
+    mPrevReleaseFds.AppendElement(mList->retireFenceFd);
+    for (uint32_t j=0; j < (mList->numHwLayers - 1); j++) {
         if (mList->hwLayers[j].compositionType == HWC_OVERLAY) {
-            mPrevRelFd[j + 1] = mList->hwLayers[j].releaseFenceFd;
+            mPrevReleaseFds.AppendElement(mList->hwLayers[j].releaseFenceFd);
             mList->hwLayers[j].releaseFenceFd = -1;
         }
     }
 
     mList->retireFenceFd = -1;
     return !err;
 }
 #else
@@ -604,22 +621,24 @@ HwcComposer2D::TryRender(Layer* aRoot,
     if (!aGLWorldTransform.PreservesAxisAlignedRectangles()) {
         LOGD("Render aborted. World transform has non-square angle rotation");
         return false;
     }
 
     MOZ_ASSERT(Initialized());
     if (mList) {
         mList->numHwLayers = 0;
+        mHwcLayerMap.Clear();
     }
 
     // XXX: The clear() below means all rect vectors will be have to be
     // reallocated. We may want to avoid this if possible
     mVisibleRegions.clear();
 
+    MOZ_ASSERT(mHwcLayerMap.IsEmpty());
     if (!PrepareLayerList(aRoot,
                           mScreenRect,
                           gfxMatrix(),
                           aGLWorldTransform))
     {
         LOGD("Render aborted. Nothing was drawn to the screen");
         if (mList) {
            mList->numHwLayers = 0;
--- a/widget/gonk/HwcComposer2D.h
+++ b/widget/gonk/HwcComposer2D.h
@@ -19,18 +19,16 @@
 
 #include "Composer2D.h"
 #include "Layers.h"
 #include <vector>
 #include <list>
 
 #include <hardware/hwcomposer.h>
 
-#define MAX_HWC_LAYERS 15
-
 namespace mozilla {
 
 namespace layers {
 class ContainerLayer;
 class Layer;
 }
 
 //Holds a dynamically allocated vector of rectangles
@@ -78,14 +76,15 @@ private:
     hwc_surface_t           mSur;
     nsIntRect               mScreenRect;
     int                     mMaxLayerCount;
     bool                    mColorFill;
     bool                    mRBSwapSupport;
     //Holds all the dynamically allocated RectVectors needed
     //to render the current frame
     std::list<RectVector>   mVisibleRegions;
-    int                     mPrevRelFd[MAX_HWC_LAYERS + 1];
+    nsTArray<int>           mPrevReleaseFds;
+    nsTArray<layers::LayerComposite*> mHwcLayerMap;
 };
 
 } // namespace mozilla
 
 #endif // mozilla_HwcComposer2D
--- a/widget/gtk/nsWindow.cpp
+++ b/widget/gtk/nsWindow.cpp
@@ -3087,17 +3087,17 @@ nsWindow::OnKeyReleaseEvent(GdkEventKey 
 
 void
 nsWindow::OnScrollEvent(GdkEventScroll *aEvent)
 {
     // check to see if we should rollup
     if (CheckForRollup(aEvent->x_root, aEvent->y_root, true, false))
         return;
 
-    WheelEvent wheelEvent(true, NS_WHEEL_WHEEL, this);
+    WidgetWheelEvent wheelEvent(true, NS_WHEEL_WHEEL, this);
     wheelEvent.deltaMode = nsIDOMWheelEvent::DOM_DELTA_LINE;
     switch (aEvent->direction) {
     case GDK_SCROLL_UP:
         wheelEvent.deltaY = wheelEvent.lineOrPageDeltaY = -3;
         break;
     case GDK_SCROLL_DOWN:
         wheelEvent.deltaY = wheelEvent.lineOrPageDeltaY = 3;
         break;
--- a/widget/nsGUIEventIPC.h
+++ b/widget/nsGUIEventIPC.h
@@ -121,19 +121,19 @@ struct ParamTraits<mozilla::WidgetMouseE
            ReadParam(aMsg, aIter, &aResult->button) &&
            ReadParam(aMsg, aIter, &aResult->buttons) &&
            ReadParam(aMsg, aIter, &aResult->pressure) &&
            ReadParam(aMsg, aIter, &aResult->inputSource);
   }
 };
 
 template<>
-struct ParamTraits<mozilla::WheelEvent>
+struct ParamTraits<mozilla::WidgetWheelEvent>
 {
-  typedef mozilla::WheelEvent paramType;
+  typedef mozilla::WidgetWheelEvent paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, static_cast<mozilla::WidgetMouseEventBase>(aParam));
     WriteParam(aMsg, aParam.deltaX);
     WriteParam(aMsg, aParam.deltaY);
     WriteParam(aMsg, aParam.deltaZ);
     WriteParam(aMsg, aParam.deltaMode);
@@ -161,17 +161,17 @@ struct ParamTraits<mozilla::WheelEvent>
       ReadParam(aMsg, aIter, &aResult->isMomentum) &&
       ReadParam(aMsg, aIter, &aResult->isPixelOnlyDevice) &&
       ReadParam(aMsg, aIter, &aResult->lineOrPageDeltaX) &&
       ReadParam(aMsg, aIter, &aResult->lineOrPageDeltaY) &&
       ReadParam(aMsg, aIter, &scrollType) &&
       ReadParam(aMsg, aIter, &aResult->overflowDeltaX) &&
       ReadParam(aMsg, aIter, &aResult->overflowDeltaY);
     aResult->scrollType =
-      static_cast<mozilla::WheelEvent::ScrollType>(scrollType);
+      static_cast<mozilla::WidgetWheelEvent::ScrollType>(scrollType);
     return rv;
   }
 };
 
 template<>
 struct ParamTraits<mozilla::WidgetMouseEvent>
 {
   typedef mozilla::WidgetMouseEvent paramType;
--- a/widget/os2/nsWindow.cpp
+++ b/widget/os2/nsWindow.cpp
@@ -3312,17 +3312,17 @@ bool nsWindow::DispatchActivationEvent(u
 
   return DispatchWindowEvent(&event);
 }
 
 //-----------------------------------------------------------------------------
 
 bool nsWindow::DispatchScrollEvent(ULONG msg, MPARAM mp1, MPARAM mp2)
 {
-  WheelEvent wheelEvent(true, NS_WHEEL_WHEEL, this);
+  WidgetWheelEvent wheelEvent(true, NS_WHEEL_WHEEL, this);
   InitEvent(wheelEvent);
 
   wheelEvent.InitBasicModifiers(isKeyDown(VK_CTRL),
                                 isKeyDown(VK_ALT) || isKeyDown(VK_ALTGRAF),
                                 isKeyDown(VK_SHIFT), false);
   // The SB_* constants for analogous vertical & horizontal ops have the
   // the same values, so only use the verticals to avoid compiler errors.
   int32_t delta;
--- a/widget/qt/nsWindow.cpp
+++ b/widget/qt/nsWindow.cpp
@@ -1910,17 +1910,17 @@ nsWindow::OnKeyReleaseEvent(QKeyEvent *a
 
     return DispatchEvent(&event);
 }
 
 nsEventStatus
 nsWindow::OnScrollEvent(QGraphicsSceneWheelEvent *aEvent)
 {
     // check to see if we should rollup
-    WheelEvent wheelEvent(true, NS_WHEEL_WHEEL, this);
+    WidgetWheelEvent wheelEvent(true, NS_WHEEL_WHEEL, this);
     wheelEvent.deltaMode = nsIDOMWheelEvent::DOM_DELTA_LINE;
 
     // negative values for aEvent->delta indicate downward scrolling;
     // this is opposite Gecko usage.
     // TODO: Store the unused delta values due to fraction round and add it
     //       to next event.  The stored values should be reset by other
     //       direction scroll event.
     int32_t delta = (int)(aEvent->delta() / WHEEL_DELTA) * -3;
--- a/widget/windows/WinMouseScrollHandler.cpp
+++ b/widget/windows/WinMouseScrollHandler.cpp
@@ -639,17 +639,17 @@ MouseScrollHandler::HandleMouseWheelMess
 
   mLastEventInfo.RecordEvent(eventInfo);
 
   ModifierKeyState modKeyState = GetModifierKeyState(aMessage);
 
   // Grab the widget, it might be destroyed by a DOM event handler.
   nsRefPtr<nsWindowBase> kungFuDethGrip(aWidget);
 
-  WheelEvent wheelEvent(true, NS_WHEEL_WHEEL, aWidget);
+  WidgetWheelEvent wheelEvent(true, NS_WHEEL_WHEEL, aWidget);
   if (mLastEventInfo.InitWheelEvent(aWidget, wheelEvent, modKeyState)) {
     PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS,
       ("MouseScroll::HandleMouseWheelMessage: dispatching "
        "NS_WHEEL_WHEEL event"));
     DispatchEvent(aWidget, wheelEvent);
     if (aWidget->Destroyed()) {
       PR_LOG(gMouseScrollLog, PR_LOG_ALWAYS,
         ("MouseScroll::HandleMouseWheelMessage: The window was destroyed "
@@ -677,17 +677,17 @@ MouseScrollHandler::HandleScrollMessageA
     (aMessage == MOZ_WM_VSCROLL || aMessage == MOZ_WM_HSCROLL),
     "HandleScrollMessageAsMouseWheelMessage must be called with "
     "MOZ_WM_VSCROLL or MOZ_WM_HSCROLL");
 
   mIsWaitingInternalMessage = false;
 
   ModifierKeyState modKeyState = GetModifierKeyState(aMessage);
 
-  WheelEvent wheelEvent(true, NS_WHEEL_WHEEL, aWidget);
+  WidgetWheelEvent wheelEvent(true, NS_WHEEL_WHEEL, aWidget);
   double& delta =
    (aMessage == MOZ_WM_VSCROLL) ? wheelEvent.deltaY : wheelEvent.deltaX;
   int32_t& lineOrPageDelta =
    (aMessage == MOZ_WM_VSCROLL) ? wheelEvent.lineOrPageDeltaY :
                                   wheelEvent.lineOrPageDeltaX;
 
   delta = 1.0;
   lineOrPageDelta = 1;
@@ -831,17 +831,17 @@ int32_t
 MouseScrollHandler::LastEventInfo::RoundDelta(double aDelta)
 {
   return (aDelta >= 0) ? (int32_t)floor(aDelta) : (int32_t)ceil(aDelta);
 }
 
 bool
 MouseScrollHandler::LastEventInfo::InitWheelEvent(
                                      nsWindowBase* aWidget,
-                                     WheelEvent& aWheelEvent,
+                                     WidgetWheelEvent& aWheelEvent,
                                      const ModifierKeyState& aModKeyState)
 {
   MOZ_ASSERT(aWheelEvent.message == NS_WHEEL_WHEEL);
 
   // XXX Why don't we use lParam value? We should use lParam value because
   //     our internal message is always posted by original message handler.
   //     So, GetMessagePos() may return different cursor position.
   InitEvent(aWidget, aWheelEvent);
--- a/widget/windows/WinMouseScrollHandler.h
+++ b/widget/windows/WinMouseScrollHandler.h
@@ -255,17 +255,17 @@ private:
      * @param aWidget           A window which will dispatch the event.
      * @param aWheelEvent       An NS_WHEEL_WHEEL event, this will be
      *                          initialized.
      * @param aModKeyState      Current modifier key state.
      * @return                  TRUE if the event is ready to dispatch.
      *                          Otherwise, FALSE.
      */
     bool InitWheelEvent(nsWindowBase* aWidget,
-                        WheelEvent& aWheelEvent,
+                        WidgetWheelEvent& aWheelEvent,
                         const ModifierKeyState& aModKeyState);
 
   private:
     static int32_t RoundDelta(double aDelta);
 
     int32_t mAccumulatedDelta;
   };
 
--- a/widget/windows/nsWinGesture.cpp
+++ b/widget/windows/nsWinGesture.cpp
@@ -562,25 +562,25 @@ nsWinGesture::PanFeedbackFinalize(HWND h
     EndPanningFeedback(hWnd);
     return;
   }
 
   UpdatePanningFeedback(hWnd, mPixelScrollOverflow.x, mPixelScrollOverflow.y, mPanInertiaActive);
 }
 
 bool
-nsWinGesture::PanDeltaToPixelScroll(WheelEvent& aWheelEvent)
+nsWinGesture::PanDeltaToPixelScroll(WidgetWheelEvent& aWheelEvent)
 {
   aWheelEvent.deltaX = aWheelEvent.deltaY = aWheelEvent.deltaZ = 0.0;
   aWheelEvent.lineOrPageDeltaX = aWheelEvent.lineOrPageDeltaY = 0;
 
   aWheelEvent.refPoint.x = mPanRefPoint.x;
   aWheelEvent.refPoint.y = mPanRefPoint.y;
   aWheelEvent.deltaMode = nsIDOMWheelEvent::DOM_DELTA_PIXEL;
-  aWheelEvent.scrollType = WheelEvent::SCROLL_SYNCHRONOUSLY;
+  aWheelEvent.scrollType = WidgetWheelEvent::SCROLL_SYNCHRONOUSLY;
   aWheelEvent.isPixelOnlyDevice = true;
 
   aWheelEvent.overflowDeltaX = 0.0;
   aWheelEvent.overflowDeltaY = 0.0;
 
   // Don't scroll the view if we are currently at a bounds, or, if we are
   // panning back from a max feedback position. This keeps the original drag point
   // constant.
--- a/widget/windows/nsWinGesture.h
+++ b/widget/windows/nsWinGesture.h
@@ -207,17 +207,17 @@ public:
   bool IsAvailable();
   
   // Simple gesture process
   bool ProcessGestureMessage(HWND hWnd, WPARAM wParam, LPARAM lParam, mozilla::WidgetSimpleGestureEvent& evt);
 
   // Pan processing
   bool IsPanEvent(LPARAM lParam);
   bool ProcessPanMessage(HWND hWnd, WPARAM wParam, LPARAM lParam);
-  bool PanDeltaToPixelScroll(mozilla::WheelEvent& aWheelEvent);
+  bool PanDeltaToPixelScroll(mozilla::WidgetWheelEvent& aWheelEvent);
   void UpdatePanFeedbackX(HWND hWnd, int32_t scrollOverflow, bool& endFeedback);
   void UpdatePanFeedbackY(HWND hWnd, int32_t scrollOverflow, bool& endFeedback);
   void PanFeedbackFinalize(HWND hWnd, bool endFeedback);
   
 public:
   // Helpers
   bool GetGestureInfo(HGESTUREINFO hGestureInfo, PGESTUREINFO pGestureInfo);
   bool CloseGestureInfoHandle(HGESTUREINFO hGestureInfo);
--- a/widget/windows/nsWindow.cpp
+++ b/widget/windows/nsWindow.cpp
@@ -6218,17 +6218,17 @@ bool nsWindow::OnGesture(WPARAM wParam, 
 {
   // Treatment for pan events which translate into scroll events:
   if (mGesture.IsPanEvent(lParam)) {
     if ( !mGesture.ProcessPanMessage(mWnd, wParam, lParam) )
       return false; // ignore
 
     nsEventStatus status;
 
-    WheelEvent wheelEvent(true, NS_WHEEL_WHEEL, this);
+    WidgetWheelEvent wheelEvent(true, NS_WHEEL_WHEEL, this);
 
     ModifierKeyState modifierKeyState;
     modifierKeyState.InitInputEvent(wheelEvent);
 
     wheelEvent.button      = 0;
     wheelEvent.time        = ::GetMessageTime();
     wheelEvent.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
 
--- a/xpfe/appshell/public/nsIAppShellService.idl
+++ b/xpfe/appshell/public/nsIAppShellService.idl
@@ -12,17 +12,17 @@ interface nsIDOMWindow;
 interface nsIAppShell;
 
 [ptr] native JSContext(JSContext);
 
 %{C++
 #include "js/TypeDecls.h"
 %}
 
-[scriptable, uuid(5c19ab54-67bf-46d0-ac5b-21abd9050c3b)]
+[scriptable, uuid(3927a495-575a-4a12-b9ab-6b948f76ec1f)]
 interface nsIAppShellService : nsISupports
 {
   /**
    * Create a window, which will be initially invisible.
    * @param aParent the parent window.  Can be null.
    * @param aUrl the contents of the new window.
    * @param aChromeMask chrome flags affecting the kind of OS border
    *                    given to the window. see nsIBrowserWindow for
@@ -39,17 +39,23 @@ interface nsIAppShellService : nsISuppor
    */
   const long SIZE_TO_CONTENT = -1;
   nsIXULWindow createTopLevelWindow(in nsIXULWindow aParent,
                                     in nsIURI aUrl, 
                                     in uint32_t aChromeMask,
                                     in long aInitialWidth,
                                     in long aInitialHeight);
 
-  nsIWebNavigation createWindowlessBrowser();
+  /**
+   * This is the constructor for creating an invisible DocShell.
+   * It is used to simulate DOM windows without an actual physical
+   * representation.
+   * @param aIsChrome Set true if you want to use it for chrome content.
+   */
+  nsIWebNavigation createWindowlessBrowser([optional] in bool aIsChrome);
 
   [noscript]
   void createHiddenWindow();
 
   void destroyHiddenWindow();
 
   /**
    * Return the (singleton) application hidden window, automatically created
--- a/xpfe/appshell/src/nsAppShellService.cpp
+++ b/xpfe/appshell/src/nsAppShellService.cpp
@@ -343,17 +343,17 @@ NS_INTERFACE_MAP_BEGIN(WindowlessBrowser
   NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_ADDREF(WindowlessBrowserStub)
 NS_IMPL_RELEASE(WindowlessBrowserStub)
 
 
 NS_IMETHODIMP
-nsAppShellService::CreateWindowlessBrowser(nsIWebNavigation **aResult)
+nsAppShellService::CreateWindowlessBrowser(bool aIsChrome, nsIWebNavigation **aResult)
 {
   /* First, we create an instance of nsWebBrowser. Instances of this class have
    * an associated doc shell, which is what we're interested in.
    */
   nsCOMPtr<nsIWebBrowser> browser = do_CreateInstance(NS_WEBBROWSER_CONTRACTID);
   if (!browser) {
     NS_ERROR("Couldn't create instance of nsWebBrowser!");
     return NS_ERROR_FAILURE;
@@ -369,17 +369,18 @@ nsAppShellService::CreateWindowlessBrows
     NS_ERROR("Couldn't create instance of WebBrowserChrome2Stub!");
     return NS_ERROR_FAILURE;
   }
   browser->SetContainerWindow(stub);
 
   nsCOMPtr<nsIWebNavigation> navigation = do_QueryInterface(browser);
 
   nsCOMPtr<nsIDocShellTreeItem> item = do_QueryInterface(navigation);
-  item->SetItemType(nsIDocShellTreeItem::typeContentWrapper);
+  item->SetItemType(aIsChrome ? nsIDocShellTreeItem::typeChromeWrapper
+                              : nsIDocShellTreeItem::typeContentWrapper);
 
   /* A windowless web browser doesn't have an associated OS level window. To
    * accomplish this, we initialize the window associated with our instance of
    * nsWebBrowser with an instance of PuppetWidget, which provides a stub
    * implementation of nsIWidget.
    */
   nsCOMPtr<nsIWidget> widget = nsIWidget::CreatePuppetWidget(nullptr);
   if (!widget) {
@@ -389,16 +390,19 @@ nsAppShellService::CreateWindowlessBrows
   widget->Create(nullptr, 0, nsIntRect(nsIntPoint(0, 0), nsIntSize(0, 0)),
                  nullptr, nullptr);
   nsCOMPtr<nsIBaseWindow> window = do_QueryInterface(navigation);
   window->InitWindow(0, widget, 0, 0, 0, 0);
   window->Create();
 
   nsISupports *isstub = NS_ISUPPORTS_CAST(nsIWebBrowserChrome2*, stub);
   nsRefPtr<nsIWebNavigation> result = new WindowlessBrowserStub(browser, isstub);
+  nsCOMPtr<nsIDocShell> docshell = do_GetInterface(result);
+  docshell->SetInvisible(true);
+
   result.forget(aResult);
   return NS_OK;
 }
 
 uint32_t
 nsAppShellService::CalculateWindowZLevel(nsIXULWindow *aParent,
                                          uint32_t      aChromeMask)
 {