Merge inbound to m-c a=merge
authorWes Kocher <wkocher@mozilla.com>
Fri, 07 Nov 2014 17:48:37 -0800
changeset 214713 eb0d3b3c0b22f3c8e1601e47e8f1e90a218b5fed
parent 214679 b7f2bf6856a2f15916c44fc094e9415045a84f8d (current diff)
parent 214712 970e11385295170eb53d18b37db21bd9968a2f66 (diff)
child 214714 80a0087967e64bd7adc9b90188cf690c55ebe229
child 214731 bc6087adc259410c765a5f9acd7c3538e89dc1e3
child 214764 09731edabab5a9b259a0b13f12f3bc4590118f3e
child 214840 de3ee8e6554ca640a8e0748470e1cb30629f1354
push id27792
push userkwierso@gmail.com
push dateSat, 08 Nov 2014 01:50:17 +0000
treeherderautoland@eb0d3b3c0b22 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone36.0a1
first release with
nightly linux32
eb0d3b3c0b22 / 36.0a1 / 20141108030205 / files
nightly linux64
eb0d3b3c0b22 / 36.0a1 / 20141108030205 / files
nightly mac
eb0d3b3c0b22 / 36.0a1 / 20141108030205 / files
nightly win32
eb0d3b3c0b22 / 36.0a1 / 20141108030205 / files
nightly win64
eb0d3b3c0b22 / 36.0a1 / 20141108030205 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to m-c a=merge
js/src/tests/ecma_6/TypedObject/Bug914137.js
js/src/tests/ecma_6/TypedObject/handle_unsized.js
js/src/tests/ecma_6/TypedObject/unsizedarrays.js
js/src/tests/ecma_6/TypedObject/unsizedarraysanddim.js
js/src/tests/ecma_6/TypedObject/unsizedarraysembedded.js
modules/libpref/init/all.js
--- a/accessible/base/nsAccessibilityService.h
+++ b/accessible/base/nsAccessibilityService.h
@@ -249,17 +249,17 @@ GetAccService()
  * Return true if we're in a content process and not B2G.
  */
 inline bool
 IPCAccessibilityActive()
 {
 #ifdef MOZ_B2G
   return false;
 #else
-  return XRE_GetProcessType() != GeckoProcessType_Default;
+  return XRE_GetProcessType() == GeckoProcessType_Content;
 #endif
 }
 
 /**
  * Map nsIAccessibleEvents constants to strings. Used by
  * nsIAccessibleRetrieval::getStringEventType() method.
  */
 static const char kEventTypeNames[][40] = {
--- a/accessible/windows/msaa/XULListboxAccessibleWrap.cpp
+++ b/accessible/windows/msaa/XULListboxAccessibleWrap.cpp
@@ -10,17 +10,18 @@ using namespace mozilla::a11y;
 ////////////////////////////////////////////////////////////////////////////////
 // XULListboxAccessibleWrap
 ////////////////////////////////////////////////////////////////////////////////
 
 NS_IMPL_ISUPPORTS_INHERITED0(XULListboxAccessibleWrap,
                              XULListboxAccessible)
 
 IMPL_IUNKNOWN_QUERY_HEAD(XULListboxAccessibleWrap)
-IMPL_IUNKNOWN_QUERY_CLASS_COND(ia2AccessibleTable, IsMulticolumn());
+IMPL_IUNKNOWN_QUERY_CLASS_COND(ia2AccessibleTable,
+                               !IsDefunct() && IsMulticolumn());
 IMPL_IUNKNOWN_QUERY_CLASS(AccessibleWrap)
 IMPL_IUNKNOWN_QUERY_TAIL
 
 void
 XULListboxAccessibleWrap::Shutdown()
 {
   ia2AccessibleTable::mTable = nullptr;
   XULListboxAccessible::Shutdown();
--- a/addon-sdk/mach_commands.py
+++ b/addon-sdk/mach_commands.py
@@ -98,17 +98,18 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] != "gonk
                     dir_path = ''
                 else:
                     # Ensure that we don't have things like:
                     #   EXTRA_JS_MODULES.commonjs.sdk.private-browsing
                     # which would be a Python syntax error.
                     path = d.split('/')
                     module_path = ''.join('.' + p if p.find('-') == -1 else "['%s']" % p for p in path)
                     dir_path = d + '/'
-                filelist = ["'source/lib/%s%s'" % (dir_path, f) for f in sorted(files)]
+                filelist = ["'source/lib/%s%s'" % (dir_path, f)
+                            for f in sorted(files, key=lambda x: x.lower())]
                 js_modules.append("EXTRA_JS_MODULES.commonjs%s += [\n    %s,\n]\n"
                                   % (module_path, ',\n    '.join(filelist)))
             stringified = '\n'.join(js_modules)
             # This isn't the same thing as |js_modules|, since |js_modules| had
             # embedded newlines.
             lines = stringified.split('\n')
             # Indent lines while avoiding trailing whitespace.
             lines = [indent + line if line else line for line in lines]
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -107,25 +107,17 @@ pref("browser.sessionstore.max_tabs_undo
 /* these should help performance */
 pref("mozilla.widget.force-24bpp", true);
 pref("mozilla.widget.use-buffer-pixmap", true);
 pref("mozilla.widget.disable-native-theme", true);
 pref("layout.reflow.synthMouseMove", false);
 pref("layers.enable-tiles", true);
 pref("layers.low-precision-buffer", true);
 pref("layers.low-precision-opacity", "0.5");
-/*
-   Cross Process Mutex is not supported on Mac OS X so progressive
-   paint cannot be enabled for B2G on Mac OS X desktop
-*/
-#ifdef MOZ_WIDGET_COCOA
-pref("layers.progressive-paint", false);
-#else
 pref("layers.progressive-paint", true);
-#endif
 
 /* download manager (don't show the window or alert) */
 pref("browser.download.useDownloadDir", true);
 pref("browser.download.folderList", 1); // Default to ~/Downloads
 pref("browser.download.manager.showAlertOnComplete", false);
 pref("browser.download.manager.showAlertInterval", 2000);
 pref("browser.download.manager.retention", 2);
 pref("browser.download.manager.showWhenStarting", false);
--- a/browser/devtools/debugger/test/browser.ini
+++ b/browser/devtools/debugger/test/browser.ini
@@ -501,47 +501,47 @@ skip-if = e10s || buildapp == 'mulet'
 skip-if = e10s
 [browser_dbg_variables-view-large-array-buffer.js]
 skip-if = e10s
 [browser_dbg_variables-view-override-01.js]
 skip-if = e10s
 [browser_dbg_variables-view-override-02.js]
 skip-if = e10s
 [browser_dbg_variables-view-popup-01.js]
-skip-if = e10s
+skip-if = e10s && debug
 [browser_dbg_variables-view-popup-02.js]
-skip-if = e10s
+skip-if = e10s && debug
 [browser_dbg_variables-view-popup-03.js]
-skip-if = e10s
+skip-if = e10s && debug
 [browser_dbg_variables-view-popup-04.js]
-skip-if = e10s
+skip-if = e10s && debug
 [browser_dbg_variables-view-popup-05.js]
-skip-if = e10s
+skip-if = e10s && debug
 [browser_dbg_variables-view-popup-06.js]
-skip-if = e10s
+skip-if = e10s && debug
 [browser_dbg_variables-view-popup-07.js]
-skip-if = e10s
+skip-if = e10s && debug
 [browser_dbg_variables-view-popup-08.js]
-skip-if = e10s
+skip-if = e10s && debug
 [browser_dbg_variables-view-popup-09.js]
-skip-if = e10s
+skip-if = e10s && debug
 [browser_dbg_variables-view-popup-10.js]
-skip-if = e10s
+skip-if = e10s && debug
 [browser_dbg_variables-view-popup-11.js]
-skip-if = e10s
+skip-if = e10s && debug
 [browser_dbg_variables-view-popup-12.js]
-skip-if = e10s
+skip-if = e10s && debug
 [browser_dbg_variables-view-popup-13.js]
-skip-if = e10s
+skip-if = e10s && debug
 [browser_dbg_variables-view-popup-14.js]
-skip-if = e10s
+skip-if = e10s && debug
 [browser_dbg_variables-view-popup-15.js]
-skip-if = e10s
+skip-if = e10s && debug
 [browser_dbg_variables-view-popup-16.js]
-skip-if = e10s
+skip-if = e10s  && debug
 [browser_dbg_variables-view-reexpand-01.js]
 skip-if = e10s
 [browser_dbg_variables-view-reexpand-02.js]
 skip-if = e10s
 [browser_dbg_variables-view-reexpand-03.js]
 skip-if = e10s
 [browser_dbg_variables-view-webidl.js]
 skip-if = e10s
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-01.js
+++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-01.js
@@ -5,17 +5,17 @@
  * Tests opening the variable inspection popup on a variable which has a
  * simple literal as the value.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_frame-parameters.html";
 
 function test() {
   Task.spawn(function() {
-    let [tab, debuggee, panel] = yield initDebugger(TAB_URL);
+    let [tab,, panel] = yield initDebugger(TAB_URL);
     let win = panel.panelWin;
     let bubble = win.DebuggerView.VariableBubble;
     let tooltip = bubble._tooltip.panel;
 
     bubble._ignoreLiterals = false;
 
     function verifyContents(textContent, className) {
       is(tooltip.querySelectorAll(".variables-view-container").length, 0,
@@ -24,18 +24,17 @@ function test() {
         "There should be a simple text node added to the tooltip instead.");
 
       is(tooltip.querySelector(".devtools-tooltip-simple-text").textContent, textContent,
         "The inspected property's value is correct.");
       ok(tooltip.querySelector(".devtools-tooltip-simple-text").className.contains(className),
         "The inspected property's value is colorized correctly.");
     }
 
-    // Allow this generator function to yield first.
-    executeSoon(() => debuggee.start());
+    callInTab(tab, "start");
     yield waitForSourceAndCaretAndScopes(panel, ".html", 24);
 
     // Inspect variables.
     yield openVarPopup(panel, { line: 15, ch: 12 });
     verifyContents("1", "token-number");
 
     yield reopenVarPopup(panel, { line: 16, ch: 21 });
     verifyContents("1", "token-number");
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-02.js
+++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-02.js
@@ -5,35 +5,34 @@
  * Tests opening the variable inspection popup on a variable which has a
  * a property accessible via getters and setters.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_frame-parameters.html";
 
 function test() {
   Task.spawn(function() {
-    let [tab, debuggee, panel] = yield initDebugger(TAB_URL);
+    let [tab,, panel] = yield initDebugger(TAB_URL);
     let win = panel.panelWin;
     let bubble = win.DebuggerView.VariableBubble;
     let tooltip = bubble._tooltip.panel;
 
     function verifyContents(textContent, className) {
       is(tooltip.querySelectorAll(".variables-view-container").length, 0,
         "There should be no variables view containers added to the tooltip.");
       is(tooltip.querySelectorAll(".devtools-tooltip-simple-text").length, 1,
         "There should be a simple text node added to the tooltip instead.");
 
       is(tooltip.querySelector(".devtools-tooltip-simple-text").textContent, textContent,
         "The inspected property's value is correct.");
       ok(tooltip.querySelector(".devtools-tooltip-simple-text").className.contains(className),
         "The inspected property's value is colorized correctly.");
     }
 
-    // Allow this generator function to yield first.
-    executeSoon(() => debuggee.start());
+    callInTab(tab, "start");
     yield waitForSourceAndCaretAndScopes(panel, ".html", 24);
 
     // Inspect properties.
     yield openVarPopup(panel, { line: 19, ch: 10 });
     verifyContents("42", "token-number");
 
     yield reopenVarPopup(panel, { line: 20, ch: 14 });
     verifyContents("42", "token-number");
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-03.js
+++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-03.js
@@ -4,22 +4,21 @@
 /**
  * Tests that the inspected indentifier is highlighted.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_frame-parameters.html";
 
 function test() {
   Task.spawn(function() {
-    let [tab, debuggee, panel] = yield initDebugger(TAB_URL);
+    let [tab,, panel] = yield initDebugger(TAB_URL);
     let win = panel.panelWin;
     let bubble = win.DebuggerView.VariableBubble;
 
-    // Allow this generator function to yield first.
-    executeSoon(() => debuggee.start());
+    callInTab(tab, "start");
     yield waitForSourceAndCaretAndScopes(panel, ".html", 24);
 
     // Inspect variable.
     yield openVarPopup(panel, { line: 15, ch: 12 });
 
     ok(bubble.contentsShown(),
       "The variable should register as being shown.");
     ok(!bubble._tooltip.isEmpty(),
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-04.js
+++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-04.js
@@ -4,22 +4,21 @@
 /**
  * Tests that the variable inspection popup is hidden when the editor scrolls.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_frame-parameters.html";
 
 function test() {
   Task.spawn(function() {
-    let [tab, debuggee, panel] = yield initDebugger(TAB_URL);
+    let [tab,, panel] = yield initDebugger(TAB_URL);
     let win = panel.panelWin;
     let bubble = win.DebuggerView.VariableBubble;
 
-    // Allow this generator function to yield first.
-    executeSoon(() => debuggee.start());
+    callInTab(tab, "start");
     yield waitForSourceAndCaretAndScopes(panel, ".html", 24);
 
     // Inspect variable.
     yield openVarPopup(panel, { line: 15, ch: 12 });
     yield hideVarPopupByScrollingEditor(panel);
     ok(true, "The variable inspection popup was hidden.");
 
     ok(bubble._tooltip.isEmpty(),
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-05.js
+++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-05.js
@@ -5,17 +5,17 @@
  * Tests opening the variable inspection popup on a variable which has a
  * simple object as the value.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_frame-parameters.html";
 
 function test() {
   Task.spawn(function() {
-    let [tab, debuggee, panel] = yield initDebugger(TAB_URL);
+    let [tab,, panel] = yield initDebugger(TAB_URL);
     let win = panel.panelWin;
     let bubble = win.DebuggerView.VariableBubble;
     let tooltip = bubble._tooltip.panel;
 
     function verifyContents() {
       is(tooltip.querySelectorAll(".variables-view-container").length, 1,
         "There should be one variables view container added to the tooltip.");
 
@@ -33,18 +33,17 @@ function test() {
         "The first property's value is correct.");
 
       is(tooltip.querySelectorAll(".variables-view-property .name")[1].getAttribute("value"), "__proto__",
         "The second property's name is correct.");
       is(tooltip.querySelectorAll(".variables-view-property .value")[1].getAttribute("value"), "Object",
         "The second property's value is correct.");
     }
 
-    // Allow this generator function to yield first.
-    executeSoon(() => debuggee.start());
+    callInTab(tab, "start");
     yield waitForSourceAndCaretAndScopes(panel, ".html", 24);
 
     // Inspect variable.
     yield openVarPopup(panel, { line: 16, ch: 12 }, true);
     verifyContents();
 
     yield resumeDebuggerThenCloseAndFinish(panel);
   });
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-06.js
+++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-06.js
@@ -6,17 +6,17 @@
  * complext object as the value.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_frame-parameters.html";
 
 function test() {
   requestLongerTimeout(2);
   Task.spawn(function() {
-    let [tab, debuggee, panel] = yield initDebugger(TAB_URL);
+    let [tab,, panel] = yield initDebugger(TAB_URL);
     let win = panel.panelWin;
     let bubble = win.DebuggerView.VariableBubble;
     let tooltip = bubble._tooltip.panel;
 
     function verifyContents() {
       is(tooltip.querySelectorAll(".variables-view-container").length, 1,
         "There should be one variables view container added to the tooltip.");
 
@@ -59,18 +59,17 @@ function test() {
         "The sixth property's value is correct.");
 
       is(tooltip.querySelectorAll(".variables-view-property .name")[6].getAttribute("value"), "__proto__",
         "The seventh property's name is correct.");
       is(tooltip.querySelectorAll(".variables-view-property .value")[6].getAttribute("value"), "Object",
         "The seventh property's value is correct.");
     }
 
-    // Allow this generator function to yield first.
-    executeSoon(() => debuggee.start());
+    callInTab(tab, "start");
     yield waitForSourceAndCaretAndScopes(panel, ".html", 24);
 
     // Inspect variable.
     yield openVarPopup(panel, { line: 17, ch: 12 }, true);
     verifyContents();
 
     yield resumeDebuggerThenCloseAndFinish(panel);
   });
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-07.js
+++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-07.js
@@ -5,17 +5,17 @@
  * Tests the variable inspection popup behaves correctly when switching
  * between simple and complex objects.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_frame-parameters.html";
 
 function test() {
   Task.spawn(function() {
-    let [tab, debuggee, panel] = yield initDebugger(TAB_URL);
+    let [tab,, panel] = yield initDebugger(TAB_URL);
     let win = panel.panelWin;
     let bubble = win.DebuggerView.VariableBubble;
     let tooltip = bubble._tooltip.panel;
 
     function verifySimpleContents(textContent, className) {
       is(tooltip.querySelectorAll(".variables-view-container").length, 0,
         "There should be no variables view container added to the tooltip.");
       is(tooltip.querySelectorAll(".devtools-tooltip-simple-text").length, 1,
@@ -37,18 +37,17 @@ function test() {
         "There should be one scope with no header displayed.");
       is(tooltip.querySelectorAll(".variables-view-variable[untitled]").length, 1,
         "There should be one variable with no header displayed.");
 
       ok(tooltip.querySelectorAll(".variables-view-property").length >= propertyCount,
         "There should be some properties displayed.");
     }
 
-    // Allow this generator function to yield first.
-    executeSoon(() => debuggee.start());
+    callInTab(tab, "start");
     yield waitForSourceAndCaretAndScopes(panel, ".html", 24);
 
     // Inspect variables.
     yield openVarPopup(panel, { line: 15, ch: 12 });
     verifySimpleContents("1", "token-number");
 
     yield reopenVarPopup(panel, { line: 16, ch: 12 }, true);
     verifyComplexContents(2);
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-08.js
+++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-08.js
@@ -4,17 +4,17 @@
 /**
  * Tests opening inspecting variables works across scopes.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_scope-variable.html";
 
 function test() {
   Task.spawn(function() {
-    let [tab, debuggee, panel] = yield initDebugger(TAB_URL);
+    let [tab,, panel] = yield initDebugger(TAB_URL);
     let win = panel.panelWin;
     let events = win.EVENTS;
     let editor = win.DebuggerView.editor;
     let frames = win.DebuggerView.StackFrames;
     let bubble = win.DebuggerView.VariableBubble;
     let tooltip = bubble._tooltip.panel;
 
     function verifyContents(textContent, className) {
@@ -35,18 +35,17 @@ function test() {
       is(frames.itemCount, 2,
         "Should have two frames.");
       is(frames.selectedDepth, selectedFrame,
         "The correct frame is selected in the widget.");
       ok(isCaretPos(panel, caretLine),
         "Editor caret location is correct.");
     }
 
-    // Allow this generator function to yield first.
-    executeSoon(() => debuggee.test());
+    callInTab(tab, "test");
     yield waitForSourceAndCaretAndScopes(panel, ".html", 20);
     checkView(0, 20);
 
     // Inspect variable in topmost frame.
     yield openVarPopup(panel, { line: 18, ch: 12 });
     verifyContents("\"second scope\"", "token-string");
     checkView(0, 20);
 
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-09.js
+++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-09.js
@@ -4,23 +4,22 @@
 /**
  * Tests opening inspecting variables works across scopes.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_scope-variable-3.html";
 
 function test() {
   Task.spawn(function() {
-    let [tab, debuggee, panel] = yield initDebugger(TAB_URL);
+    let [tab,, panel] = yield initDebugger(TAB_URL);
     let win = panel.panelWin;
     let bubble = win.DebuggerView.VariableBubble;
     let tooltip = bubble._tooltip.panel;
 
-    // Allow this generator function to yield first.
-    executeSoon(() => debuggee.test());
+    callInTab(tab, "test");
     yield waitForSourceAndCaretAndScopes(panel, ".html", 15);
 
     yield openVarPopup(panel, { line: 12, ch: 10 });
     ok(true, "The variable inspection popup was shown for the real variable.");
 
     once(tooltip, "popupshown").then(() => {
       ok(false, "The variable inspection popup shouldn't have been opened.");
     });
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-10.js
+++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-10.js
@@ -6,27 +6,26 @@
  * a variable inspection popup is opened and a watch expression is
  * also evaluated at the same time.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_frame-parameters.html";
 
 function test() {
   Task.spawn(function() {
-    let [tab, debuggee, panel] = yield initDebugger(TAB_URL);
+    let [tab,, panel] = yield initDebugger(TAB_URL);
     let win = panel.panelWin;
     let events = win.EVENTS;
     let editor = win.DebuggerView.editor;
     let editorContainer = win.document.getElementById("editor");
     let bubble = win.DebuggerView.VariableBubble;
     let expressions = win.DebuggerView.WatchExpressions;
     let tooltip = bubble._tooltip.panel;
 
-    // Allow this generator function to yield first.
-    executeSoon(() => debuggee.start());
+    callInTab(tab, "start");
     yield waitForSourceAndCaretAndScopes(panel, ".html", 24);
 
     let expressionsEvaluated = waitForDebuggerEvents(panel, events.FETCHED_WATCH_EXPRESSIONS);
     expressions.addExpression("this");
     editor.focus();
     yield expressionsEvaluated;
 
     // Scroll to the top of the editor and inspect variables.
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-11.js
+++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-11.js
@@ -4,17 +4,17 @@
 /**
  * Tests that the watch expression button is added in variable view popup.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_watch-expression-button.html";
 
 function test() {
   Task.spawn(function() {
-    let [tab, debuggee, panel] = yield initDebugger(TAB_URL);
+    let [tab,, panel] = yield initDebugger(TAB_URL);
     let win = panel.panelWin;
     let events = win.EVENTS;
     let watch = win.DebuggerView.WatchExpressions;
     let bubble = win.DebuggerView.VariableBubble;
     let tooltip = bubble._tooltip.panel;
 
     let label = win.L10N.getStr("addWatchExpressionButton");
     let className = "dbg-expression-button";
@@ -32,18 +32,17 @@ function test() {
       ok(!tooltip.querySelector("button"),
         "There should be no button available in variable view popup.");
       ok(watch.getItemAtIndex(0),
         "The expression at index 0 should be available.");
       is(watch.getItemAtIndex(0).attachment.initialExpression, aExpression,
         "The expression at index 0 is correct.");
     }
 
-    // Allow this generator function to yield first.
-    executeSoon(() => debuggee.start());
+    callInTab(tab, "start");
     yield waitForSourceAndCaretAndScopes(panel, ".html", 19);
 
     // Inspect primitive value variable.
     yield openVarPopup(panel, { line: 15, ch: 12 });
     let popupHiding = once(tooltip, "popuphiding");
     let expressionsEvaluated = waitForDebuggerEvents(panel, events.FETCHED_WATCH_EXPRESSIONS);
     testExpressionButton(label, className, "a");
     yield promise.all([popupHiding, expressionsEvaluated]);
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-12.js
+++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-12.js
@@ -5,35 +5,34 @@
  * Tests that the clicking "Watch" button twice, for the same expression, only adds it
  * once.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_watch-expression-button.html";
 
 function test() {
   Task.spawn(function() {
-    let [tab, debuggee, panel] = yield initDebugger(TAB_URL);
+    let [tab,, panel] = yield initDebugger(TAB_URL);
     let win = panel.panelWin;
     let events = win.EVENTS;
     let watch = win.DebuggerView.WatchExpressions;
     let bubble = win.DebuggerView.VariableBubble;
     let tooltip = bubble._tooltip.panel;
 
     function verifyContent(aExpression, aItemCount) {
 
       ok(watch.getItemAtIndex(0),
         "The expression at index 0 should be available.");
       is(watch.getItemAtIndex(0).attachment.initialExpression, aExpression,
         "The expression at index 0 is correct.");
       is(watch.itemCount, aItemCount,
         "The expression count is correct.");
     }
 
-    // Allow this generator function to yield first.
-    executeSoon(() => debuggee.start());
+    callInTab(tab, "start");
     yield waitForSourceAndCaretAndScopes(panel, ".html", 19);
 
     // Inspect primitive value variable.
     yield openVarPopup(panel, { line: 15, ch: 12 });
     let popupHiding = once(tooltip, "popuphiding");
     let expressionsEvaluated = waitForDebuggerEvents(panel, events.FETCHED_WATCH_EXPRESSIONS);
     tooltip.querySelector("button").click();
     verifyContent("a", 1);
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-13.js
+++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-13.js
@@ -5,17 +5,17 @@
  * Tests that the variable inspection popup has inspector links for DOMNode
  * properties and that the popup closes when the link is clicked
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_domnode-variables.html";
 
 function test() {
   Task.spawn(function() {
-    let [tab, debuggee, panel] = yield initDebugger(TAB_URL);
+    let [tab,, panel] = yield initDebugger(TAB_URL);
     let win = panel.panelWin;
     let bubble = win.DebuggerView.VariableBubble;
     let tooltip = bubble._tooltip.panel;
     let toolbox = gDevTools.getToolbox(panel.target);
 
     function getDomNodeInTooltip(propertyName) {
       let domNodeProperties = tooltip.querySelectorAll(".token-domnode");
       for (let prop of domNodeProperties) {
@@ -23,18 +23,17 @@ function test() {
         if (propName.getAttribute("value") === propertyName) {
           ok(true, "DOMNode " + propertyName + " was found in the tooltip");
           return prop;
         }
       }
       ok(false, "DOMNode " + propertyName + " wasn't found in the tooltip");
     }
 
-    // Allow this generator function to yield first.
-    executeSoon(() => debuggee.start());
+    callInTab(tab, "start");
     yield waitForSourceAndCaretAndScopes(panel, ".html", 19);
 
     // Inspect the div DOM variable.
     yield openVarPopup(panel, { line: 17, ch: 38 }, true);
     let property = getDomNodeInTooltip("firstElementChild");
 
     // Simulate mouseover on the property value
     let highlighted = once(toolbox, "node-highlight");
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-14.js
+++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-14.js
@@ -5,22 +5,21 @@
  * Tests that the variable inspection popup is hidden when
  * selecting text in the editor.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_frame-parameters.html";
 
 function test() {
   Task.spawn(function*() {
-    let [tab, debuggee, panel] = yield initDebugger(TAB_URL);
+    let [tab,, panel] = yield initDebugger(TAB_URL);
     let win = panel.panelWin;
     let bubble = win.DebuggerView.VariableBubble;
 
-    // Allow this generator function to yield first.
-    executeSoon(() => debuggee.start());
+    callInTab(tab, "start");
     yield waitForSourceAndCaretAndScopes(panel, ".html", 24);
 
     // Select some text.
     let cursor = win.DebuggerView.editor.getOffset({ line: 15, ch: 12 });
     let [ anchor, head ] = win.DebuggerView.editor.getPosition(
       cursor,
       cursor + 3
     );
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-15.js
+++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-15.js
@@ -4,23 +4,22 @@
 /**
  * Tests opening the variable inspection popup directly on literals.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_frame-parameters.html";
 
 function test() {
   Task.spawn(function() {
-    let [tab, debuggee, panel] = yield initDebugger(TAB_URL);
+    let [tab,, panel] = yield initDebugger(TAB_URL);
     let win = panel.panelWin;
     let bubble = win.DebuggerView.VariableBubble;
     let tooltip = bubble._tooltip.panel;
 
-    // Allow this generator function to yield first.
-    executeSoon(() => debuggee.start());
+    callInTab(tab, "start");
     yield waitForSourceAndCaretAndScopes(panel, ".html", 24);
 
     yield openVarPopup(panel, { line: 15, ch: 12 });
     ok(true, "The variable inspection popup was shown for the real variable.");
 
     once(tooltip, "popupshown").then(() => {
       ok(false, "The variable inspection popup shouldn't have been opened.");
     });
--- a/browser/devtools/debugger/test/browser_dbg_variables-view-popup-16.js
+++ b/browser/devtools/debugger/test/browser_dbg_variables-view-popup-16.js
@@ -5,17 +5,17 @@
  * Tests if opening the variables inspection popup preserves the highlighting
  * associated with the currently debugged line.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_recursion-stack.html";
 
 function test() {
   Task.spawn(function() {
-    let [tab, debuggee, panel] = yield initDebugger(TAB_URL);
+    let [tab,, panel] = yield initDebugger(TAB_URL);
     let win = panel.panelWin;
     let events = win.EVENTS;
     let editor = win.DebuggerView.editor;
     let frames = win.DebuggerView.StackFrames;
     let variables = win.DebuggerView.Variables;
     let bubble = win.DebuggerView.VariableBubble;
     let tooltip = bubble._tooltip.panel;
 
@@ -46,18 +46,17 @@ function test() {
       is(globalScope.expanded, false,
         "The globalScope should not be expanded yet.");
 
       let finished = waitForDebuggerEvents(panel, events.FETCHED_VARIABLES);
       globalScope.expand();
       return finished;
     }
 
-    // Allow this generator function to yield first.
-    executeSoon(() => debuggee.recurse());
+    callInTab(tab, "recurse");
     yield waitForSourceAndCaretAndScopes(panel, ".html", 26);
     yield checkView(0, 26);
 
     yield expandGlobalScope();
     yield checkView(0, 26);
 
     // Inspect variable in topmost frame.
     yield openVarPopup(panel, { line: 26, ch: 11 });
--- a/dom/base/DOMException.cpp
+++ b/dom/base/DOMException.cpp
@@ -153,16 +153,18 @@ NS_GetNameAndMessageForDOMNSResult(nsres
 namespace mozilla {
 namespace dom {
 
 bool Exception::sEverMadeOneFromFactory = false;
 
 NS_IMPL_CLASSINFO(Exception, nullptr, nsIClassInfo::DOM_OBJECT,
                   NS_XPCEXCEPTION_CID)
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Exception)
+  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
+  NS_INTERFACE_MAP_ENTRY(Exception)
   NS_INTERFACE_MAP_ENTRY(nsIException)
   NS_INTERFACE_MAP_ENTRY(nsIXPCException)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIException)
   NS_IMPL_QUERY_CLASSINFO(Exception)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(Exception)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(Exception)
--- a/dom/media/MediaPermissionGonk.cpp
+++ b/dom/media/MediaPermissionGonk.cpp
@@ -391,20 +391,19 @@ private:
 };
 
 NS_IMPL_ISUPPORTS(MediaDeviceErrorCallback, nsIDOMGetUserMediaErrorCallback)
 
 // nsIDOMGetUserMediaErrorCallback method
 NS_IMETHODIMP
 MediaDeviceErrorCallback::OnError(nsISupports* aError)
 {
-  MediaStreamError *error = nullptr;
-  nsresult rv = CallQueryInterface(aError, &error);
-  if (NS_FAILED(rv)) {
-    return rv;
+  nsRefPtr<MediaStreamError> error = do_QueryObject(aError);
+  if (!error) {
+    return NS_ERROR_NO_INTERFACE;
   }
 
   nsString name;
   error->GetName(name);
   return NotifyPermissionDeny(mCallID, name);
 }
 
 } // namespace anonymous
--- a/dom/media/PeerConnection.js
+++ b/dom/media/PeerConnection.js
@@ -830,23 +830,28 @@ RTCPeerConnection.prototype = {
       this.logWarning(
           "addIceCandidate called without success/failure callbacks. This is deprecated, and will be an error in the future.",
           null, 0);
     }
     if (!cand.candidate && !cand.sdpMLineIndex) {
       throw new this._win.DOMError("",
           "Invalid candidate passed to addIceCandidate!");
     }
+
+    this._queueOrRun({
+      func: this._addIceCandidate,
+      args: [cand, onSuccess, onError],
+      wait: false
+    });
+  },
+
+  _addIceCandidate: function(cand, onSuccess, onError) {
     this._onAddIceCandidateSuccess = onSuccess || null;
     this._onAddIceCandidateError = onError || null;
 
-    this._queueOrRun({ func: this._addIceCandidate, args: [cand], wait: false });
-  },
-
-  _addIceCandidate: function(cand) {
     this._impl.addIceCandidate(cand.candidate, cand.sdpMid || "",
                                (cand.sdpMLineIndex === null) ? 0 :
                                  cand.sdpMLineIndex + 1);
   },
 
   addStream: function(stream) {
     stream.getTracks().forEach(track => this.addTrack(track, stream));
   },
--- a/dom/webidl/WorkerGlobalScope.webidl
+++ b/dom/webidl/WorkerGlobalScope.webidl
@@ -45,10 +45,11 @@ WorkerGlobalScope implements GlobalFetch
 
 // Mozilla extensions
 partial interface WorkerGlobalScope {
   attribute EventHandler onclose;
 
   void dump(optional DOMString str);
 
   // XXXbz no spec for this yet, because the webperf WG is a bit dysfunctional
+  [Constant, Cached]
   readonly attribute Performance performance;
 };
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -3043,31 +3043,31 @@ ScrollableLayerGuid AsyncPanZoomControll
 
 void AsyncPanZoomController::UpdateSharedCompositorFrameMetrics()
 {
   mMonitor.AssertCurrentThreadIn();
 
   FrameMetrics* frame = mSharedFrameMetricsBuffer ?
       static_cast<FrameMetrics*>(mSharedFrameMetricsBuffer->memory()) : nullptr;
 
-  if (frame && mSharedLock && gfxPrefs::UseProgressiveTilePainting()) {
+  if (frame && mSharedLock && gfxPlatform::GetPlatform()->UseProgressivePaint()) {
     mSharedLock->Lock();
     *frame = mFrameMetrics.MakePODObject();
     mSharedLock->Unlock();
   }
 }
 
 void AsyncPanZoomController::ShareCompositorFrameMetrics() {
 
   PCompositorParent* compositor = GetSharedFrameMetricsCompositor();
 
   // Only create the shared memory buffer if it hasn't already been created,
   // we are using progressive tile painting, and we have a
   // compositor to pass the shared memory back to the content process/thread.
-  if (!mSharedFrameMetricsBuffer && compositor && gfxPrefs::UseProgressiveTilePainting()) {
+  if (!mSharedFrameMetricsBuffer && compositor && gfxPlatform::GetPlatform()->UseProgressivePaint()) {
 
     // Create shared memory and initialize it with the current FrameMetrics value
     mSharedFrameMetricsBuffer = new ipc::SharedMemoryBasic;
     FrameMetrics* frame = nullptr;
     mSharedFrameMetricsBuffer->Create(sizeof(FrameMetrics));
     mSharedFrameMetricsBuffer->Map(sizeof(FrameMetrics));
     frame = static_cast<FrameMetrics*>(mSharedFrameMetricsBuffer->memory());
 
--- a/gfx/layers/client/ClientTiledPaintedLayer.cpp
+++ b/gfx/layers/client/ClientTiledPaintedLayer.cpp
@@ -188,17 +188,17 @@ ClientTiledPaintedLayer::UseFastPath()
 {
   LayerMetricsWrapper scrollAncestor;
   GetAncestorLayers(&scrollAncestor, nullptr);
   if (!scrollAncestor) {
     return true;
   }
   const FrameMetrics& parentMetrics = scrollAncestor.Metrics();
 
-  bool multipleTransactionsNeeded = gfxPrefs::UseProgressiveTilePainting()
+  bool multipleTransactionsNeeded = gfxPlatform::GetPlatform()->UseProgressivePaint()
                                  || gfxPrefs::UseLowPrecisionBuffer()
                                  || !parentMetrics.mCriticalDisplayPort.IsEmpty();
   bool isFixed = GetIsFixedPosition() || GetParent()->GetIsFixedPosition();
   return !multipleTransactionsNeeded || isFixed || parentMetrics.mDisplayPort.IsEmpty();
 }
 
 bool
 ClientTiledPaintedLayer::RenderHighPrecision(nsIntRegion& aInvalidRegion,
@@ -209,17 +209,17 @@ ClientTiledPaintedLayer::RenderHighPreci
   // If we have no high-precision stuff to draw, or we have started drawing low-precision
   // already, then we shouldn't do anything there.
   if (aInvalidRegion.IsEmpty() || mPaintData.mLowPrecisionPaintCount != 0) {
     return false;
   }
 
   // Only draw progressively when the resolution is unchanged, and we're not
   // in a reftest scenario (that's what the HasShadowManager() check is for).
-  if (gfxPrefs::UseProgressiveTilePainting() &&
+  if (gfxPlatform::GetPlatform()->UseProgressivePaint() &&
       !ClientManager()->HasShadowTarget() &&
       mContentClient->mTiledBuffer.GetFrameResolution() == mPaintData.mResolution) {
     // Store the old valid region, then clear it before painting.
     // We clip the old valid region to the visible region, as it only gets
     // used to decide stale content (currently valid and previously visible)
     nsIntRegion oldValidRegion = mContentClient->mTiledBuffer.GetValidRegion();
     oldValidRegion.And(oldValidRegion, aVisibleRegion);
     if (!mPaintData.mCriticalDisplayPort.IsEmpty()) {
--- a/gfx/layers/composite/LayerManagerComposite.cpp
+++ b/gfx/layers/composite/LayerManagerComposite.cpp
@@ -871,17 +871,17 @@ GetDisplayportCoverage(const CSSRect& aD
 }
 #endif // MOZ_WIDGET_ANDROID
 
 float
 LayerManagerComposite::ComputeRenderIntegrity()
 {
   // We only ever have incomplete rendering when progressive tiles are enabled.
   Layer* root = GetRoot();
-  if (!gfxPrefs::UseProgressiveTilePainting() || !root) {
+  if (!gfxPlatform::GetPlatform()->UseProgressivePaint() || !root) {
     return 1.f;
   }
 
   FrameMetrics rootMetrics = LayerMetricsWrapper::TopmostScrollableMetrics(root);
   if (!rootMetrics.IsScrollable()) {
     // The root may not have any scrollable metrics, in which case rootMetrics
     // will just be an empty FrameMetrics. Instead use the actual metrics from
     // the root layer.
--- a/gfx/thebes/gfxPlatform.h
+++ b/gfx/thebes/gfxPlatform.h
@@ -258,19 +258,20 @@ public:
 
     bool SupportsAzureContentForType(mozilla::gfx::BackendType aType) {
       return BackendTypeBit(aType) & mContentBackendBitmask;
     }
 
     virtual bool UseAcceleratedSkiaCanvas();
     virtual void InitializeSkiaCacheLimits();
 
-    /// This should be used instead of directly accessing the preference,
+    /// These should be used instead of directly accessing the preference,
     /// as different platforms may override the behaviour.
     virtual bool UseTiling() { return gfxPrefs::LayersTilesEnabledDoNotUseDirectly(); }
+    virtual bool UseProgressivePaint() { return gfxPrefs::ProgressivePaintDoNotUseDirectly(); }
 
     void GetAzureBackendInfo(mozilla::widget::InfoObject &aObj) {
       aObj.DefineProperty("AzureCanvasBackend", GetBackendName(mPreferredCanvasBackend));
       aObj.DefineProperty("AzureSkiaAccelerated", UseAcceleratedSkiaCanvas());
       aObj.DefineProperty("AzureFallbackCanvasBackend", GetBackendName(mFallbackCanvasBackend));
       aObj.DefineProperty("AzureContentBackend", GetBackendName(mContentBackend));
     }
 
--- a/gfx/thebes/gfxPlatformMac.cpp
+++ b/gfx/thebes/gfxPlatformMac.cpp
@@ -406,16 +406,24 @@ gfxPlatformMac::UseTiling()
 {
   if (gfxPrefs::LayersTilesForceEnabled()) {
     return true;
   }
   // Tiling seems to be slow on 10.6 so disable it until we figure it out
   return nsCocoaFeatures::OnLionOrLater() && gfxPlatform::UseTiling();
 }
 
+bool
+gfxPlatformMac::UseProgressivePaint()
+{
+  // Progressive painting requires cross-process mutexes, which don't work so
+  // well on OS X 10.6 so we disable there.
+  return nsCocoaFeatures::OnLionOrLater() && gfxPlatform::UseProgressivePaint();
+}
+
 void
 gfxPlatformMac::GetPlatformCMSOutputProfile(void* &mem, size_t &size)
 {
     mem = nullptr;
     size = 0;
 
     CGColorSpaceRef cspace = ::CGDisplayCopyColorSpace(::CGMainDisplayID());
     if (!cspace) {
--- a/gfx/thebes/gfxPlatformMac.h
+++ b/gfx/thebes/gfxPlatformMac.h
@@ -66,16 +66,17 @@ public:
 
     virtual bool CanRenderContentToDataSurface() const MOZ_OVERRIDE {
       return true;
     }
 
     bool UseAcceleratedCanvas();
 
     virtual bool UseTiling() MOZ_OVERRIDE;
+    virtual bool UseProgressivePaint() MOZ_OVERRIDE;
 
     // lower threshold on font anti-aliasing
     uint32_t GetAntiAliasingThreshold() { return mFontAntiAliasingThreshold; }
 
 private:
     virtual void GetPlatformCMSOutputProfile(void* &mem, size_t &size);
 
     // read in the pref value for the lower threshold on font anti-aliasing
--- a/gfx/thebes/gfxPrefs.h
+++ b/gfx/thebes/gfxPrefs.h
@@ -288,17 +288,17 @@ private:
   DECL_GFX_PREF(Once, "layers.offmainthreadcomposition.enabled", LayersOffMainThreadCompositionEnabled, bool, false);
   DECL_GFX_PREF(Live, "layers.offmainthreadcomposition.frame-rate", LayersCompositionFrameRate, int32_t,-1);
   DECL_GFX_PREF(Once, "layers.offmainthreadcomposition.force-enabled", LayersOffMainThreadCompositionForceEnabled, bool, false);
   DECL_GFX_PREF(Once, "layers.offmainthreadcomposition.testing.enabled", LayersOffMainThreadCompositionTestingEnabled, bool, false);
   DECL_GFX_PREF(Once, "layers.use-image-offscreen-surfaces",   UseImageOffscreenSurfaces, bool, false);
   DECL_GFX_PREF(Live, "layers.orientation.sync.timeout",       OrientationSyncMillis, uint32_t, (uint32_t)0);
   DECL_GFX_PREF(Once, "layers.prefer-d3d9",                    LayersPreferD3D9, bool, false);
   DECL_GFX_PREF(Once, "layers.prefer-opengl",                  LayersPreferOpenGL, bool, false);
-  DECL_GFX_PREF(Once, "layers.progressive-paint",              UseProgressiveTilePainting, bool, false);
+  DECL_GFX_PREF(Once, "layers.progressive-paint",              ProgressivePaintDoNotUseDirectly, bool, false);
   DECL_GFX_PREF(Once, "layers.uniformity-info",                UniformityInfo, bool, false);
   DECL_GFX_PREF(Once, "layers.gralloc.disable",                DisableGralloc, bool, false);
 
   DECL_GFX_PREF(Live, "layout.css.scroll-behavior.damping-ratio", ScrollBehaviorDampingRatio, float, 1.0f);
   DECL_GFX_PREF(Live, "layout.css.scroll-behavior.enabled",    ScrollBehaviorEnabled, bool, false);
   DECL_GFX_PREF(Live, "layout.css.scroll-behavior.spring-constant", ScrollBehaviorSpringConstant, float, 250.0f);
   DECL_GFX_PREF(Once, "layout.css.touch_action.enabled",       TouchActionEnabled, bool, false);
   DECL_GFX_PREF(Once, "layout.frame_rate",                     LayoutFrameRate, int32_t, -1);
--- a/ipc/glue/CrossProcessMutex.h
+++ b/ipc/glue/CrossProcessMutex.h
@@ -4,17 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_CrossProcessMutex_h
 #define mozilla_CrossProcessMutex_h
 
 #include "base/process.h"
 #include "mozilla/Mutex.h"
 
-#if defined(OS_LINUX)
+#if defined(OS_POSIX)
 #include <pthread.h>
 #include "SharedMemoryBasic.h"
 #include "mozilla/Atomics.h"
 #include "nsAutoPtr.h"
 #endif
 
 namespace IPC {
 template<typename T>
@@ -27,19 +27,19 @@ struct ParamTraits;
 //  - CrossProcessMutex, a non-recursive mutex that can be shared across processes
 //  - CrossProcessMutexAutoLock, an RAII class for ensuring that Mutexes are
 //    properly locked and unlocked
 //
 // Using CrossProcessMutexAutoLock/CrossProcessMutexAutoUnlock is MUCH
 // preferred to making bare calls to CrossProcessMutex.Lock and Unlock.
 //
 namespace mozilla {
-#ifdef XP_WIN
+#if defined(OS_WIN)
 typedef HANDLE CrossProcessMutexHandle;
-#elif defined(OS_LINUX)
+#elif defined(OS_POSIX)
 typedef mozilla::ipc::SharedMemoryBasic::Handle CrossProcessMutexHandle;
 #else
 // Stub for other platforms. We can't use uintptr_t here since different
 // processes could disagree on its size.
 typedef uintptr_t CrossProcessMutexHandle;
 #endif
 
 class CrossProcessMutex
@@ -93,19 +93,19 @@ public:
 
 private:
   friend struct IPC::ParamTraits<CrossProcessMutex>;
 
   CrossProcessMutex();
   CrossProcessMutex(const CrossProcessMutex&);
   CrossProcessMutex &operator=(const CrossProcessMutex&);
 
-#ifdef XP_WIN
+#if defined(OS_WIN)
   HANDLE mMutex;
-#elif defined(OS_LINUX)
+#elif defined(OS_POSIX)
   nsRefPtr<mozilla::ipc::SharedMemoryBasic> mSharedBuffer;
   pthread_mutex_t* mMutex;
   mozilla::Atomic<int32_t>* mCount;
 #endif
 };
 
 typedef BaseAutoLock<CrossProcessMutex> CrossProcessMutexAutoLock;
 typedef BaseAutoUnlock<CrossProcessMutex> CrossProcessMutexAutoUnlock;
--- a/ipc/glue/CrossProcessMutex_posix.cpp
+++ b/ipc/glue/CrossProcessMutex_posix.cpp
@@ -3,16 +3,20 @@
  * 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 "CrossProcessMutex.h"
 #include "mozilla/unused.h"
 #include "nsDebug.h"
 #include "nsISupportsImpl.h"
 
+#ifdef OS_MACOSX
+#include "nsCocoaFeatures.h"
+#endif
+
 namespace {
 
 struct MutexData {
   pthread_mutex_t mMutex;
   mozilla::Atomic<int32_t> mCount;
 };
 
 }
@@ -36,16 +40,25 @@ InitMutex(pthread_mutex_t* mMutex)
     MOZ_CRASH();
   }
 }
 
 CrossProcessMutex::CrossProcessMutex(const char*)
     : mMutex(nullptr)
     , mCount(nullptr)
 {
+#ifdef OS_MACOSX
+  if (!nsCocoaFeatures::OnLionOrLater()) {
+    // Don't allow using the cross-process mutex before OS X 10.7 because it
+    // probably doesn't work very well. See discussion in bug 1072093 for more
+    // details.
+    MOZ_CRASH();
+  }
+#endif
+
   mSharedBuffer = new ipc::SharedMemoryBasic;
   if (!mSharedBuffer->Create(sizeof(MutexData))) {
     MOZ_CRASH();
   }
 
   if (!mSharedBuffer->Map(sizeof(MutexData))) {
     MOZ_CRASH();
   }
--- a/ipc/glue/moz.build
+++ b/ipc/glue/moz.build
@@ -54,17 +54,17 @@ else:
         'SharedMemory_posix.cpp',
         'Transport_posix.cpp',
     ]
 
 if CONFIG['OS_ARCH'] == 'WINNT':
     SOURCES += [
         'CrossProcessMutex_windows.cpp',
     ]
-elif CONFIG['OS_ARCH'] == 'Linux':
+elif CONFIG['OS_ARCH'] in ('Linux', 'Darwin'):
     UNIFIED_SOURCES += [
         'CrossProcessMutex_posix.cpp',
     ]
 else:
     UNIFIED_SOURCES += [
         'CrossProcessMutex_unimplemented.cpp',
     ]
 
--- a/js/src/asmjs/AsmJSValidate.cpp
+++ b/js/src/asmjs/AsmJSValidate.cpp
@@ -8387,16 +8387,17 @@ GenerateAsyncInterruptExit(ModuleCompile
     // This will restore stack to the address before the call.
     masm.movePtr(s0, StackPointer);
     masm.PopRegsInMask(AllRegsExceptSP);
 
     // Pop resumePC into PC. Clobber HeapReg to make the jump and restore it
     // during jump delay slot.
     masm.pop(HeapReg);
     masm.as_jr(HeapReg);
+    masm.loadAsmJSHeapRegisterFromGlobalData();
 #elif defined(JS_CODEGEN_ARM)
     masm.setFramePushed(0);         // set to zero so we can use masm.framePushed() below
     masm.PushRegsInMask(RegisterSet(GeneralRegisterSet(Registers::AllMask & ~(1<<Registers::sp)), FloatRegisterSet(uint32_t(0))));   // save all GP registers,excep sp
 
     // Save both the APSR and FPSCR in non-volatile registers.
     masm.as_mrs(r4);
     masm.as_vmrs(r5);
     // Save the stack pointer in a non-volatile register.
--- a/js/src/builtin/Eval.cpp
+++ b/js/src/builtin/Eval.cpp
@@ -7,16 +7,17 @@
 #include "builtin/Eval.h"
 
 #include "mozilla/HashFunctions.h"
 #include "mozilla/Range.h"
 
 #include "jscntxt.h"
 
 #include "frontend/BytecodeCompiler.h"
+#include "vm/Debugger.h"
 #include "vm/GlobalObject.h"
 #include "vm/JSONParser.h"
 
 #include "vm/Interpreter-inl.h"
 
 using namespace js;
 
 using mozilla::AddToHash;
@@ -475,16 +476,19 @@ js::ExecuteInGlobalAndReturnScope(JSCont
     assertSameCompartment(cx, global);
     MOZ_ASSERT(global->is<GlobalObject>());
 
     RootedScript script(cx, scriptArg);
     if (script->compartment() != cx->compartment()) {
         script = CloneScript(cx, NullPtr(), NullPtr(), script);
         if (!script)
             return false;
+
+        Rooted<GlobalObject *> global(cx, script->compileAndGo() ? &script->global() : nullptr);
+        Debugger::onNewScript(cx, script, global);
     }
 
     RootedObject scope(cx, JS_NewObject(cx, nullptr, JS::NullPtr(), JS::NullPtr()));
     if (!scope)
         return false;
 
     if (!scope->setQualifiedVarObj(cx))
         return false;
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -2012,17 +2012,18 @@ FindPath(JSContext *cx, unsigned argc, j
 }
 
 static bool
 EvalReturningScope(JSContext *cx, unsigned argc, jsval *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     RootedString str(cx);
-    if (!JS_ConvertArguments(cx, args, "S", str.address()))
+    RootedObject global(cx);
+    if (!JS_ConvertArguments(cx, args, "S/o", str.address(), global.address()))
         return false;
 
     AutoStableStringChars strChars(cx);
     if (!strChars.initTwoByte(cx, str))
         return false;
 
     mozilla::Range<const char16_t> chars = strChars.twoByteRange();
     size_t srclen = chars.length();
@@ -2038,26 +2039,102 @@ EvalReturningScope(JSContext *cx, unsign
     options.setNoScriptRval(true);
     options.setCompileAndGo(false);
 
     JS::SourceBufferHolder srcBuf(src, srclen, JS::SourceBufferHolder::NoOwnership);
     RootedScript script(cx);
     if (!JS::Compile(cx, JS::NullPtr(), options, srcBuf, &script))
         return false;
 
-    RootedObject global(cx, JS::CurrentGlobalOrNull(cx));
+    if (global) {
+        global = CheckedUnwrap(global);
+        if (!global) {
+            JS_ReportError(cx, "Permission denied to access global");
+            return false;
+        }
+        if (!global->is<GlobalObject>()) {
+            JS_ReportError(cx, "Argument must be a global object");
+            return false;
+        }
+    } else {
+        global = JS::CurrentGlobalOrNull(cx);
+    }
+
     RootedObject scope(cx);
-    if (!js::ExecuteInGlobalAndReturnScope(cx, global, script, &scope))
+
+    {
+        // If we're switching globals here, ExecuteInGlobalAndReturnScope will
+        // take care of cloning the script into that compartment before
+        // executing it.
+        AutoCompartment ac(cx, global);
+
+        if (!js::ExecuteInGlobalAndReturnScope(cx, global, script, &scope))
+            return false;
+    }
+
+    if (!cx->compartment()->wrap(cx, &scope))
         return false;
 
     args.rval().setObject(*scope);
     return true;
 }
 
 static bool
+ShellCloneAndExecuteScript(JSContext *cx, unsigned argc, Value *vp)
+{
+    CallArgs args = CallArgsFromVp(argc, vp);
+
+    RootedString str(cx);
+    RootedObject global(cx);
+    if (!JS_ConvertArguments(cx, args, "So", str.address(), global.address()))
+        return false;
+
+    AutoStableStringChars strChars(cx);
+    if (!strChars.initTwoByte(cx, str))
+        return false;
+
+    mozilla::Range<const char16_t> chars = strChars.twoByteRange();
+    size_t srclen = chars.length();
+    const char16_t *src = chars.start().get();
+
+    JS::AutoFilename filename;
+    unsigned lineno;
+
+    DescribeScriptedCaller(cx, &filename, &lineno);
+
+    JS::CompileOptions options(cx);
+    options.setFileAndLine(filename.get(), lineno);
+    options.setNoScriptRval(true);
+    options.setCompileAndGo(false);
+
+    JS::SourceBufferHolder srcBuf(src, srclen, JS::SourceBufferHolder::NoOwnership);
+    RootedScript script(cx);
+    if (!JS::Compile(cx, JS::NullPtr(), options, srcBuf, &script))
+        return false;
+
+    global = CheckedUnwrap(global);
+    if (!global) {
+        JS_ReportError(cx, "Permission denied to access global");
+        return false;
+    }
+    if (!global->is<GlobalObject>()) {
+        JS_ReportError(cx, "Argument must be a global object");
+        return false;
+    }
+
+    AutoCompartment ac(cx, global);
+
+    if (!JS::CloneAndExecuteScript(cx, global, script))
+        return false;
+
+    args.rval().setUndefined();
+    return true;
+}
+
+static bool
 IsSimdAvailable(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 #ifdef JS_CODEGEN_NONE
     bool available = false;
 #else
     bool available = cx->jitSupportsSimd();
 #endif
@@ -2394,18 +2471,24 @@ gc::ZealModeHelpText),
 #ifdef NIGHTLY_BUILD
     JS_FN_HELP("objectAddress", ObjectAddress, 1, 0,
 "objectAddress(obj)",
 "  Return the current address of the object. For debugging only--this\n"
 "  address may change during a moving GC."),
 #endif
 
     JS_FN_HELP("evalReturningScope", EvalReturningScope, 1, 0,
-"evalReturningScope(scriptStr)",
-"  Evaluate the script in a new scope and return the scope."),
+"evalReturningScope(scriptStr, [global])",
+"  Evaluate the script in a new scope and return the scope.\n"
+"  If |global| is present, clone the script to |global| before executing."),
+
+    JS_FN_HELP("cloneAndExecuteScript", ShellCloneAndExecuteScript, 2, 0,
+"cloneAndExecuteScript(source, global)",
+"  Compile |source| in the current compartment, clone it into |global|'s\n"
+"  compartment, and run it there."),
 
     JS_FN_HELP("backtrace", DumpBacktrace, 1, 0,
 "backtrace()",
 "  Dump out a brief backtrace."),
 
     JS_FN_HELP("getBacktrace", GetBacktrace, 1, 0,
 "getBacktrace([options])",
 "  Return the current stack as a string. Takes an optional options object,\n"
--- a/js/src/builtin/TypedObject.cpp
+++ b/js/src/builtin/TypedObject.cpp
@@ -500,57 +500,39 @@ CreatePrototypeObjectForComplexTypeInsta
                                             TenuredObject);
     if (!result)
         return nullptr;
 
     result->initTypeDescrSlot(*descr);
     return result;
 }
 
-const Class UnsizedArrayTypeDescr::class_ = {
+const Class ArrayTypeDescr::class_ = {
     "ArrayType",
     JSCLASS_HAS_RESERVED_SLOTS(JS_DESCR_SLOTS),
     JS_PropertyStub,
     JS_DeletePropertyStub,
     JS_PropertyStub,
     JS_StrictPropertyStub,
     JS_EnumerateStub,
     JS_ResolveStub,
     JS_ConvertStub,
     nullptr,
     nullptr,
     nullptr,
-    OutlineTypedObject::constructUnsized,
-    nullptr
-};
-
-const Class SizedArrayTypeDescr::class_ = {
-    "ArrayType",
-    JSCLASS_HAS_RESERVED_SLOTS(JS_DESCR_SLOTS),
-    JS_PropertyStub,
-    JS_DeletePropertyStub,
-    JS_PropertyStub,
-    JS_StrictPropertyStub,
-    JS_EnumerateStub,
-    JS_ResolveStub,
-    JS_ConvertStub,
-    nullptr,
-    nullptr,
-    nullptr,
-    TypedObject::constructSized,
+    TypedObject::construct,
     nullptr
 };
 
 const JSPropertySpec ArrayMetaTypeDescr::typeObjectProperties[] = {
     JS_PS_END
 };
 
 const JSFunctionSpec ArrayMetaTypeDescr::typeObjectMethods[] = {
     {"array", {nullptr, nullptr}, 1, 0, "ArrayShorthand"},
-    JS_FN("dimension", UnsizedArrayTypeDescr::dimension, 1, 0),
     JS_SELF_HOSTED_FN("toSource", "DescrToSource", 0, 0),
     {"equivalent", {nullptr, nullptr}, 1, 0, "TypeDescrEquivalent"},
     JS_SELF_HOSTED_FN("build",    "TypedObjectArrayTypeBuild", 3, 0),
     JS_SELF_HOSTED_FN("buildPar", "TypedObjectArrayTypeBuildPar", 3, 0),
     JS_SELF_HOSTED_FN("from",     "TypedObjectArrayTypeFrom", 3, 0),
     JS_SELF_HOSTED_FN("fromPar",  "TypedObjectArrayTypeFromPar", 3, 0),
     JS_FS_END
 };
@@ -572,31 +554,29 @@ const JSFunctionSpec ArrayMetaTypeDescr:
     JS_SELF_HOSTED_FN("filterPar",  "TypedArrayFilterPar",  1, 0),
     JS_FS_END
 };
 
 bool
 js::CreateUserSizeAndAlignmentProperties(JSContext *cx, HandleTypeDescr descr)
 {
     // If data is transparent, also store the public slots.
-    if (descr->transparent() && descr->is<SizedTypeDescr>()) {
-        Rooted<SizedTypeDescr*> sizedDescr(cx, &descr->as<SizedTypeDescr>());
-
+    if (descr->transparent()) {
         // byteLength
-        RootedValue typeByteLength(cx, Int32Value(sizedDescr->size()));
+        RootedValue typeByteLength(cx, Int32Value(descr->size()));
         if (!JSObject::defineProperty(cx, descr, cx->names().byteLength,
                                       typeByteLength,
                                       nullptr, nullptr,
                                       JSPROP_READONLY | JSPROP_PERMANENT))
         {
             return false;
         }
 
         // byteAlignment
-        RootedValue typeByteAlignment(cx, Int32Value(sizedDescr->alignment()));
+        RootedValue typeByteAlignment(cx, Int32Value(descr->alignment()));
         if (!JSObject::defineProperty(cx, descr, cx->names().byteAlignment,
                                       typeByteAlignment,
                                       nullptr, nullptr,
                                       JSPROP_READONLY | JSPROP_PERMANENT))
         {
             return false;
         }
     } else {
@@ -614,55 +594,52 @@ js::CreateUserSizeAndAlignmentProperties
                                       UndefinedHandleValue,
                                       nullptr, nullptr,
                                       JSPROP_READONLY | JSPROP_PERMANENT))
         {
             return false;
         }
     }
 
-    // variable -- true for unsized arrays
-    RootedValue variable(cx, BooleanValue(!descr->is<SizedTypeDescr>()));
-    if (!JSObject::defineProperty(cx, descr, cx->names().variable,
-                                  variable,
-                                  nullptr, nullptr,
-                                  JSPROP_READONLY | JSPROP_PERMANENT))
-    {
-        return false;
-    }
-
     return true;
 }
 
-template<class T>
-T *
+ArrayTypeDescr *
 ArrayMetaTypeDescr::create(JSContext *cx,
                            HandleObject arrayTypePrototype,
-                           HandleSizedTypeDescr elementType,
+                           HandleTypeDescr elementType,
                            HandleAtom stringRepr,
-                           int32_t size)
+                           int32_t size,
+                           int32_t length)
 {
-    Rooted<T*> obj(cx);
-    obj = NewObjectWithProto<T>(cx, arrayTypePrototype, nullptr, SingletonObject);
+    Rooted<ArrayTypeDescr*> obj(cx);
+    obj = NewObjectWithProto<ArrayTypeDescr>(cx, arrayTypePrototype, nullptr, SingletonObject);
     if (!obj)
         return nullptr;
 
-    obj->initReservedSlot(JS_DESCR_SLOT_KIND, Int32Value(T::Kind));
+    obj->initReservedSlot(JS_DESCR_SLOT_KIND, Int32Value(ArrayTypeDescr::Kind));
     obj->initReservedSlot(JS_DESCR_SLOT_STRING_REPR, StringValue(stringRepr));
     obj->initReservedSlot(JS_DESCR_SLOT_ALIGNMENT, Int32Value(elementType->alignment()));
     obj->initReservedSlot(JS_DESCR_SLOT_SIZE, Int32Value(size));
     obj->initReservedSlot(JS_DESCR_SLOT_OPAQUE, BooleanValue(elementType->opaque()));
     obj->initReservedSlot(JS_DESCR_SLOT_ARRAY_ELEM_TYPE, ObjectValue(*elementType));
+    obj->initReservedSlot(JS_DESCR_SLOT_ARRAY_LENGTH, Int32Value(length));
 
     RootedValue elementTypeVal(cx, ObjectValue(*elementType));
     if (!JSObject::defineProperty(cx, obj, cx->names().elementType,
                                   elementTypeVal, nullptr, nullptr,
                                   JSPROP_READONLY | JSPROP_PERMANENT))
         return nullptr;
 
+    RootedValue lengthValue(cx, NumberValue(length));
+    if (!JSObject::defineProperty(cx, obj, cx->names().length,
+                                  lengthValue, nullptr, nullptr,
+                                  JSPROP_READONLY | JSPROP_PERMANENT))
+        return nullptr;
+
     if (!CreateUserSizeAndAlignmentProperties(cx, obj))
         return nullptr;
 
     Rooted<TypedProto*> prototypeObj(cx);
     prototypeObj = CreatePrototypeObjectForComplexTypeInstance(cx, obj, arrayTypePrototype);
     if (!prototypeObj)
         return nullptr;
 
@@ -682,142 +659,79 @@ ArrayMetaTypeDescr::construct(JSContext 
     if (!args.isConstructing()) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
                              JSMSG_NOT_FUNCTION, "ArrayType");
         return false;
     }
 
     RootedObject arrayTypeGlobal(cx, &args.callee());
 
-    // Expect one argument which is a sized type object
-    if (args.length() < 1) {
+    // Expect two arguments. The first is a type object, the second is a length.
+    if (args.length() < 2) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_MORE_ARGS_NEEDED,
-                             "ArrayType", "0", "");
+                             "ArrayType", "1", "");
         return false;
     }
 
-    if (!args[0].isObject() || !args[0].toObject().is<SizedTypeDescr>()) {
+    if (!args[0].isObject() || !args[0].toObject().is<TypeDescr>()) {
         ReportCannotConvertTo(cx, args[0], "ArrayType element specifier");
         return false;
     }
 
-    Rooted<SizedTypeDescr*> elementType(cx);
-    elementType = &args[0].toObject().as<SizedTypeDescr>();
-
-    // Construct a canonical string `new ArrayType(<elementType>)`:
+    if (!args[1].isInt32() || args[1].toInt32() < 0) {
+        ReportCannotConvertTo(cx, args[1], "ArrayType length specifier");
+        return false;
+    }
+
+    Rooted<TypeDescr*> elementType(cx, &args[0].toObject().as<TypeDescr>());
+
+    int32_t length = args[1].toInt32();
+
+    // Compute the byte size.
+    CheckedInt32 size = CheckedInt32(elementType->size()) * length;
+    if (!size.isValid()) {
+        JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
+                             JSMSG_TYPEDOBJECT_TOO_BIG);
+        return false;
+    }
+
+    // Construct a canonical string `new ArrayType(<elementType>, N)`:
     StringBuffer contents(cx);
     contents.append("new ArrayType(");
     contents.append(&elementType->stringRepr());
+    contents.append(", ");
+    if (!NumberValueToStringBuffer(cx, NumberValue(length), contents))
+        return false;
     contents.append(")");
     RootedAtom stringRepr(cx, contents.finishAtom());
     if (!stringRepr)
         return false;
 
     // Extract ArrayType.prototype
     RootedObject arrayTypePrototype(cx, GetPrototype(cx, arrayTypeGlobal));
     if (!arrayTypePrototype)
         return false;
 
     // Create the instance of ArrayType
-    Rooted<UnsizedArrayTypeDescr *> obj(cx);
-    obj = create<UnsizedArrayTypeDescr>(cx, arrayTypePrototype, elementType,
-                                        stringRepr, 0);
+    Rooted<ArrayTypeDescr *> obj(cx);
+    obj = create(cx, arrayTypePrototype, elementType, stringRepr, size.value(), length);
     if (!obj)
         return false;
 
-    // Add `length` property, which is undefined for an unsized array.
-    if (!JSObject::defineProperty(cx, obj, cx->names().length,
-                                  UndefinedHandleValue, nullptr, nullptr,
-                                  JSPROP_READONLY | JSPROP_PERMANENT))
-        return false;
-
-    args.rval().setObject(*obj);
-    return true;
-}
-
-/*static*/ bool
-UnsizedArrayTypeDescr::dimension(JSContext *cx, unsigned int argc, jsval *vp)
-{
-    // Expect that the `this` pointer is an unsized array type
-    // and the first argument is an integer size.
-    CallArgs args = CallArgsFromVp(argc, vp);
-    if (args.length() != 1 ||
-        !args.thisv().isObject() ||
-        !args.thisv().toObject().is<UnsizedArrayTypeDescr>() ||
-        !args[0].isInt32() ||
-        args[0].toInt32() < 0)
-    {
-        JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
-                             JSMSG_TYPEDOBJECT_ARRAYTYPE_BAD_ARGS);
-        return false;
-    }
-
-    // Extract arguments.
-    Rooted<UnsizedArrayTypeDescr*> unsizedTypeDescr(cx);
-    unsizedTypeDescr = &args.thisv().toObject().as<UnsizedArrayTypeDescr>();
-    int32_t length = args[0].toInt32();
-    Rooted<SizedTypeDescr*> elementType(cx, &unsizedTypeDescr->elementType());
-
-    // Compute the size.
-    CheckedInt32 size = CheckedInt32(elementType->size()) * length;
-    if (!size.isValid()) {
-        JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
-                             JSMSG_TYPEDOBJECT_TOO_BIG);
-        return false;
-    }
-
-    // Construct a canonical string `new ArrayType(<elementType>).dimension(N)`:
-    StringBuffer contents(cx);
-    contents.append("new ArrayType(");
-    contents.append(&elementType->stringRepr());
-    contents.append(").dimension(");
-    if (!NumberValueToStringBuffer(cx, NumberValue(length), contents))
-        return false;
-    contents.append(")");
-    RootedAtom stringRepr(cx, contents.finishAtom());
-    if (!stringRepr)
-        return false;
-
-    // Create the sized type object.
-    Rooted<SizedArrayTypeDescr*> obj(cx);
-    obj = ArrayMetaTypeDescr::create<SizedArrayTypeDescr>(cx, unsizedTypeDescr,
-                                                          elementType,
-                                                          stringRepr, size.value());
-    if (!obj)
-        return false;
-
-    obj->initReservedSlot(JS_DESCR_SLOT_SIZED_ARRAY_LENGTH,
-                          Int32Value(length));
-
-    // Add `length` property.
-    RootedValue lengthVal(cx, Int32Value(length));
-    if (!JSObject::defineProperty(cx, obj, cx->names().length,
-                                  lengthVal, nullptr, nullptr,
-                                  JSPROP_READONLY | JSPROP_PERMANENT))
-        return false;
-
-    // Add `unsized` property, which is a link from the sized
-    // array to the unsized array.
-    RootedValue unsizedTypeDescrValue(cx, ObjectValue(*unsizedTypeDescr));
-    if (!JSObject::defineProperty(cx, obj, cx->names().unsized,
-                                  unsizedTypeDescrValue, nullptr, nullptr,
-                                  JSPROP_READONLY | JSPROP_PERMANENT))
-        return false;
-
     args.rval().setObject(*obj);
     return true;
 }
 
 bool
 js::IsTypedObjectArray(JSObject &obj)
 {
     if (!obj.is<TypedObject>())
         return false;
     TypeDescr& d = obj.as<TypedObject>().typeDescr();
-    return d.is<SizedArrayTypeDescr>() || d.is<UnsizedArrayTypeDescr>();
+    return d.is<ArrayTypeDescr>();
 }
 
 /*********************************
  * StructType class
  */
 
 const Class StructTypeDescr::class_ = {
     "StructType",
@@ -827,17 +741,17 @@ const Class StructTypeDescr::class_ = {
     JS_PropertyStub,
     JS_StrictPropertyStub,
     JS_EnumerateStub,
     JS_ResolveStub,
     JS_ConvertStub,
     nullptr, /* finalize */
     nullptr, /* call */
     nullptr, /* hasInstance */
-    TypedObject::constructSized,
+    TypedObject::construct,
     nullptr  /* trace */
 };
 
 const JSPropertySpec StructMetaTypeDescr::typeObjectProperties[] = {
     JS_PS_END
 };
 
 const JSFunctionSpec StructMetaTypeDescr::typeObjectMethods[] = {
@@ -888,33 +802,33 @@ StructMetaTypeDescr::create(JSContext *c
 
     if (!stringBuffer.append("new StructType({")) {
         js_ReportOutOfMemory(cx);
         return nullptr;
     }
 
     RootedValue fieldTypeVal(cx);
     RootedId id(cx);
-    Rooted<SizedTypeDescr*> fieldType(cx);
+    Rooted<TypeDescr*> fieldType(cx);
     for (unsigned int i = 0; i < ids.length(); i++) {
         id = ids[i];
 
         // Check that all the property names are non-numeric strings.
         uint32_t unused;
         if (!JSID_IS_ATOM(id) || JSID_TO_ATOM(id)->isIndex(&unused)) {
             RootedValue idValue(cx, IdToValue(id));
             ReportCannotConvertTo(cx, idValue, "StructType field name");
             return nullptr;
         }
 
         // Load the value for the current field from the `fields` object.
         // The value should be a type descriptor.
         if (!JSObject::getGeneric(cx, fields, fields, id, &fieldTypeVal))
             return nullptr;
-        fieldType = ToObjectIf<SizedTypeDescr>(fieldTypeVal);
+        fieldType = ToObjectIf<TypeDescr>(fieldTypeVal);
         if (!fieldType) {
             ReportCannotConvertTo(cx, fieldTypeVal, "StructType field specifier");
             return nullptr;
         }
 
         // Collect field name and type object
         RootedValue fieldName(cx, IdToValue(id));
         if (!fieldNames.append(fieldName)) {
@@ -1163,32 +1077,32 @@ StructTypeDescr::fieldOffset(size_t inde
 size_t
 StructTypeDescr::maybeForwardedFieldOffset(size_t index) const
 {
     NativeObject &fieldOffsets = maybeForwardedFieldInfoObject(JS_DESCR_SLOT_STRUCT_FIELD_OFFSETS);
     MOZ_ASSERT(index < fieldOffsets.getDenseInitializedLength());
     return AssertedCast<size_t>(fieldOffsets.getDenseElement(index).toInt32());
 }
 
-SizedTypeDescr&
+TypeDescr&
 StructTypeDescr::fieldDescr(size_t index) const
 {
     NativeObject &fieldDescrs = fieldInfoObject(JS_DESCR_SLOT_STRUCT_FIELD_TYPES);
     MOZ_ASSERT(index < fieldDescrs.getDenseInitializedLength());
-    return fieldDescrs.getDenseElement(index).toObject().as<SizedTypeDescr>();
+    return fieldDescrs.getDenseElement(index).toObject().as<TypeDescr>();
 }
 
-SizedTypeDescr&
+TypeDescr&
 StructTypeDescr::maybeForwardedFieldDescr(size_t index) const
 {
     NativeObject &fieldDescrs = maybeForwardedFieldInfoObject(JS_DESCR_SLOT_STRUCT_FIELD_TYPES);
     MOZ_ASSERT(index < fieldDescrs.getDenseInitializedLength());
     JSObject &descr =
         *MaybeForwarded(&fieldDescrs.getDenseElement(index).toObject());
-    return descr.as<SizedTypeDescr>();
+    return descr.as<TypeDescr>();
 }
 
 /******************************************************************************
  * Creating the TypedObject "module"
  *
  * We create one global, `TypedObject`, which contains the following
  * members:
  *
@@ -1463,19 +1377,17 @@ TypedObject::offset() const
     if (is<InlineTypedObject>())
         return 0;
     return typedMem() - typedMemBase();
 }
 
 int32_t
 TypedObject::length() const
 {
-    if (typeDescr().is<SizedArrayTypeDescr>())
-        return typeDescr().as<SizedArrayTypeDescr>().length();
-    return as<OutlineTypedObject>().unsizedLength();
+    return typeDescr().as<ArrayTypeDescr>().length();
 }
 
 uint8_t *
 TypedObject::typedMem() const
 {
     MOZ_ASSERT(isAttached());
 
     if (is<InlineTypedObject>())
@@ -1612,28 +1524,24 @@ OutlineTypedObject::createUnattachedWith
 {
     MOZ_ASSERT(clasp == &OutlineTransparentTypedObject::class_ ||
                clasp == &OutlineOpaqueTypedObject::class_);
 
     RootedObject proto(cx, PrototypeForTypeDescr(cx, type));
     if (!proto)
         return nullptr;
 
-    gc::AllocKind allocKind = allocKindForTypeDescriptor(type);
     NewObjectKind newKind = (heap == gc::TenuredHeap) ? MaybeSingletonObject : GenericObject;
-    JSObject *obj = NewObjectWithClassProto(cx, clasp, proto, nullptr, allocKind, newKind);
+    JSObject *obj = NewObjectWithClassProto(cx, clasp, proto, nullptr, gc::FINALIZE_OBJECT0, newKind);
     if (!obj)
         return nullptr;
 
     OutlineTypedObject *typedObj = &obj->as<OutlineTypedObject>();
 
     typedObj->setOwnerAndData(nullptr, nullptr);
-    if (type->kind() == type::UnsizedArray)
-        typedObj->setUnsizedLength(length);
-
     return typedObj;
 }
 
 void
 OutlineTypedObject::attach(JSContext *cx, ArrayBufferObject &buffer, int32_t offset)
 {
     MOZ_ASSERT(!isAttached());
     MOZ_ASSERT(offset >= 0);
@@ -1663,38 +1571,35 @@ OutlineTypedObject::attach(JSContext *cx
         attach(cx, owner->as<ArrayBufferObject>(), offset);
     } else {
         MOZ_ASSERT(owner->is<InlineTypedObject>());
         setOwnerAndData(owner, owner->as<InlineTypedObject>().inlineTypedMem() + offset);
     }
 }
 
 // Returns a suitable JS_TYPEDOBJ_SLOT_LENGTH value for an instance of
-// the type `type`. `type` must not be an unsized array.
+// the type `type`.
 static int32_t
 TypedObjLengthFromType(TypeDescr &descr)
 {
     switch (descr.kind()) {
       case type::Scalar:
       case type::Reference:
       case type::Struct:
       case type::Simd:
         return 0;
 
-      case type::SizedArray:
-        return descr.as<SizedArrayTypeDescr>().length();
-
-      case type::UnsizedArray:
-        MOZ_CRASH("TypedObjLengthFromType() invoked on unsized type");
+      case type::Array:
+        return descr.as<ArrayTypeDescr>().length();
     }
     MOZ_CRASH("Invalid kind");
 }
 
 /*static*/ OutlineTypedObject *
-OutlineTypedObject::createDerived(JSContext *cx, HandleSizedTypeDescr type,
+OutlineTypedObject::createDerived(JSContext *cx, HandleTypeDescr type,
                                   HandleTypedObject typedObj, int32_t offset)
 {
     MOZ_ASSERT(offset <= typedObj->size());
     MOZ_ASSERT(offset + type->size() <= typedObj->size());
 
     int32_t length = TypedObjLengthFromType(*type);
 
     const js::Class *clasp = typedObj->opaque()
@@ -1708,73 +1613,36 @@ OutlineTypedObject::createDerived(JSCont
     obj->attach(cx, *typedObj, offset);
     return obj;
 }
 
 /*static*/ TypedObject *
 TypedObject::createZeroed(JSContext *cx, HandleTypeDescr descr, int32_t length, gc::InitialHeap heap)
 {
     // If possible, create an object with inline data.
-    if (descr->is<SizedTypeDescr>() &&
-        (size_t) descr->as<SizedTypeDescr>().size() <= InlineTypedObject::MaximumSize)
-    {
+    if ((size_t) descr->size() <= InlineTypedObject::MaximumSize) {
         InlineTypedObject *obj = InlineTypedObject::create(cx, descr, heap);
-        descr->as<SizedTypeDescr>().initInstances(cx->runtime(), obj->inlineTypedMem(), 1);
+        descr->initInstances(cx->runtime(), obj->inlineTypedMem(), 1);
         return obj;
     }
 
     // Create unattached wrapper object.
     Rooted<OutlineTypedObject*> obj(cx, OutlineTypedObject::createUnattached(cx, descr, length, heap));
     if (!obj)
         return nullptr;
 
     // Allocate and initialize the memory for this instance.
-    // Also initialize the JS_TYPEDOBJ_SLOT_LENGTH slot.
-    switch (descr->kind()) {
-      case type::Scalar:
-      case type::Reference:
-      case type::Struct:
-      case type::Simd:
-      case type::SizedArray:
-      {
-        size_t totalSize = descr->as<SizedTypeDescr>().size();
-        Rooted<ArrayBufferObject*> buffer(cx);
-        buffer = ArrayBufferObject::create(cx, totalSize);
-        if (!buffer)
-            return nullptr;
-        descr->as<SizedTypeDescr>().initInstances(cx->runtime(), buffer->dataPointer(), 1);
-        obj->attach(cx, *buffer, 0);
-        return obj;
-      }
-
-      case type::UnsizedArray:
-      {
-        Rooted<SizedTypeDescr*> elementTypeRepr(cx);
-        elementTypeRepr = &descr->as<UnsizedArrayTypeDescr>().elementType();
-
-        CheckedInt32 totalSize = CheckedInt32(elementTypeRepr->size()) * length;
-        if (!totalSize.isValid()) {
-            JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
-                                 JSMSG_TYPEDOBJECT_TOO_BIG);
-            return nullptr;
-        }
-
-        Rooted<ArrayBufferObject*> buffer(cx);
-        buffer = ArrayBufferObject::create(cx, totalSize.value());
-        if (!buffer)
-            return nullptr;
-
-        if (length)
-            elementTypeRepr->initInstances(cx->runtime(), buffer->dataPointer(), length);
-        obj->attach(cx, *buffer, 0);
-        return obj;
-      }
-    }
-
-    MOZ_CRASH("Bad TypeRepresentation Kind");
+    size_t totalSize = descr->size();
+    Rooted<ArrayBufferObject*> buffer(cx);
+    buffer = ArrayBufferObject::create(cx, totalSize);
+    if (!buffer)
+        return nullptr;
+    descr->initInstances(cx->runtime(), buffer->dataPointer(), 1);
+    obj->attach(cx, *buffer, 0);
+    return obj;
 }
 
 static bool
 ReportTypedObjTypeError(JSContext *cx,
                         const unsigned errorNumber,
                         HandleTypedObject obj)
 {
     // Serialize type string of obj
@@ -1818,49 +1686,33 @@ OutlineTypedObject::obj_trace(JSTracer *
     {
         mem += reinterpret_cast<uint8_t *>(owner) - reinterpret_cast<uint8_t *>(oldOwner);
         typedObj.setData(mem);
     }
 
     if (!descr.opaque() || !typedObj.maybeForwardedIsAttached())
         return;
 
-    switch (descr.kind()) {
-      case type::Scalar:
-      case type::Reference:
-      case type::Struct:
-      case type::SizedArray:
-      case type::Simd:
-        descr.as<SizedTypeDescr>().traceInstances(trc, mem, 1);
-        break;
-
-      case type::UnsizedArray:
-      {
-        SizedTypeDescr &elemType = descr.as<UnsizedArrayTypeDescr>().maybeForwardedElementType();
-        elemType.traceInstances(trc, mem, typedObj.unsizedLength());
-        break;
-      }
-    }
+    descr.traceInstances(trc, mem, 1);
 }
 
 bool
 TypedObject::obj_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id,
                               MutableHandleObject objp, MutableHandleShape propp)
 {
     MOZ_ASSERT(obj->is<TypedObject>());
 
     Rooted<TypeDescr*> descr(cx, &obj->as<TypedObject>().typeDescr());
     switch (descr->kind()) {
       case type::Scalar:
       case type::Reference:
       case type::Simd:
         break;
 
-      case type::SizedArray:
-      case type::UnsizedArray:
+      case type::Array:
       {
         uint32_t index;
         if (js_IdIsIndex(id, &index))
             return obj_lookupElement(cx, obj, index, objp, propp);
 
         if (JSID_IS_ATOM(id, cx->names().length)) {
             MarkNonNativePropertyFound(propp);
             objp.set(obj);
@@ -1977,18 +1829,17 @@ TypedObject::obj_getGeneric(JSContext *c
     switch (typedObj->typeDescr().kind()) {
       case type::Scalar:
       case type::Reference:
         break;
 
       case type::Simd:
         break;
 
-      case type::SizedArray:
-      case type::UnsizedArray:
+      case type::Array:
         if (JSID_IS_ATOM(id, cx->names().length)) {
             if (!typedObj->isAttached()) {
                 JS_ReportErrorNumber(
                     cx, js_GetErrorMessage,
                     nullptr, JSMSG_TYPEDOBJECT_HANDLE_UNATTACHED);
                 return false;
             }
 
@@ -2000,17 +1851,17 @@ TypedObject::obj_getGeneric(JSContext *c
       case type::Struct: {
         Rooted<StructTypeDescr*> descr(cx, &typedObj->typeDescr().as<StructTypeDescr>());
 
         size_t fieldIndex;
         if (!descr->fieldIndex(id, &fieldIndex))
             break;
 
         size_t offset = descr->fieldOffset(fieldIndex);
-        Rooted<SizedTypeDescr*> fieldType(cx, &descr->fieldDescr(fieldIndex));
+        Rooted<TypeDescr*> fieldType(cx, &descr->fieldDescr(fieldIndex));
         return Reify(cx, fieldType, typedObj, offset, vp);
       }
     }
 
     RootedObject proto(cx, obj->getProto());
     if (!proto) {
         vp.setUndefined();
         return true;
@@ -2037,50 +1888,42 @@ TypedObject::obj_getElement(JSContext *c
 
     switch (descr->kind()) {
       case type::Scalar:
       case type::Reference:
       case type::Simd:
       case type::Struct:
         break;
 
-      case type::SizedArray:
-        return obj_getArrayElement<SizedArrayTypeDescr>(cx, typedObj, descr,
-                                                        index, vp);
-
-      case type::UnsizedArray:
-        return obj_getArrayElement<UnsizedArrayTypeDescr>(cx, typedObj, descr,
-                                                          index, vp);
+      case type::Array:
+        return obj_getArrayElement(cx, typedObj, descr, index, vp);
     }
 
     RootedObject proto(cx, obj->getProto());
     if (!proto) {
         vp.setUndefined();
         return true;
     }
 
     return JSObject::getElement(cx, proto, receiver, index, vp);
 }
 
-template<class T>
 /*static*/ bool
 TypedObject::obj_getArrayElement(JSContext *cx,
                                 Handle<TypedObject*> typedObj,
                                 Handle<TypeDescr*> typeDescr,
                                 uint32_t index,
                                 MutableHandleValue vp)
 {
-    MOZ_ASSERT(typeDescr->is<T>());
-
     if (index >= (size_t) typedObj->length()) {
         vp.setUndefined();
         return true;
     }
 
-    Rooted<SizedTypeDescr*> elementType(cx, &typeDescr->as<T>().elementType());
+    Rooted<TypeDescr*> elementType(cx, &typeDescr->as<ArrayTypeDescr>().elementType());
     size_t offset = elementType->size() * index;
     return Reify(cx, elementType, typedObj, offset, vp);
 }
 
 bool
 TypedObject::obj_setGeneric(JSContext *cx, HandleObject obj, HandleId id,
                            MutableHandleValue vp, bool strict)
 {
@@ -2094,34 +1937,33 @@ TypedObject::obj_setGeneric(JSContext *c
     switch (typedObj->typeDescr().kind()) {
       case type::Scalar:
       case type::Reference:
         break;
 
       case type::Simd:
         break;
 
-      case type::SizedArray:
-      case type::UnsizedArray:
+      case type::Array:
         if (JSID_IS_ATOM(id, cx->names().length)) {
             JS_ReportErrorNumber(cx, js_GetErrorMessage,
                                  nullptr, JSMSG_CANT_REDEFINE_ARRAY_LENGTH);
             return false;
         }
         break;
 
       case type::Struct: {
         Rooted<StructTypeDescr*> descr(cx, &typedObj->typeDescr().as<StructTypeDescr>());
 
         size_t fieldIndex;
         if (!descr->fieldIndex(id, &fieldIndex))
             break;
 
         size_t offset = descr->fieldOffset(fieldIndex);
-        Rooted<SizedTypeDescr*> fieldType(cx, &descr->fieldDescr(fieldIndex));
+        Rooted<TypeDescr*> fieldType(cx, &descr->fieldDescr(fieldIndex));
         return ConvertAndCopyTo(cx, fieldType, typedObj, offset, vp);
       }
     }
 
     return ReportTypedObjTypeError(cx, JSMSG_OBJECT_NOT_EXTENSIBLE, typedObj);
 }
 
 bool
@@ -2143,44 +1985,38 @@ TypedObject::obj_setElement(JSContext *c
 
     switch (descr->kind()) {
       case type::Scalar:
       case type::Reference:
       case type::Simd:
       case type::Struct:
         break;
 
-      case type::SizedArray:
-        return obj_setArrayElement<SizedArrayTypeDescr>(cx, typedObj, descr, index, vp);
-
-      case type::UnsizedArray:
-        return obj_setArrayElement<UnsizedArrayTypeDescr>(cx, typedObj, descr, index, vp);
+      case type::Array:
+        return obj_setArrayElement(cx, typedObj, descr, index, vp);
     }
 
     return ReportTypedObjTypeError(cx, JSMSG_OBJECT_NOT_EXTENSIBLE, typedObj);
 }
 
-template<class T>
 /*static*/ bool
 TypedObject::obj_setArrayElement(JSContext *cx,
                                 Handle<TypedObject*> typedObj,
                                 Handle<TypeDescr*> descr,
                                 uint32_t index,
                                 MutableHandleValue vp)
 {
-    MOZ_ASSERT(descr->is<T>());
-
     if (index >= (size_t) typedObj->length()) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage,
                              nullptr, JSMSG_TYPEDOBJECT_BINARYARRAY_BAD_INDEX);
         return false;
     }
 
-    Rooted<SizedTypeDescr*> elementType(cx);
-    elementType = &descr->as<T>().elementType();
+    Rooted<TypeDescr*> elementType(cx);
+    elementType = &descr->as<ArrayTypeDescr>().elementType();
     size_t offset = elementType->size() * index;
     return ConvertAndCopyTo(cx, elementType, typedObj, offset, vp);
 }
 
 bool
 TypedObject::obj_getGenericAttributes(JSContext *cx, HandleObject obj,
                                      HandleId id, unsigned *attrsp)
 {
@@ -2189,18 +2025,17 @@ TypedObject::obj_getGenericAttributes(JS
     switch (typedObj->typeDescr().kind()) {
       case type::Scalar:
       case type::Reference:
         break;
 
       case type::Simd:
         break;
 
-      case type::SizedArray:
-      case type::UnsizedArray:
+      case type::Array:
         if (js_IdIsIndex(id, &index)) {
             *attrsp = JSPROP_ENUMERATE | JSPROP_PERMANENT;
             return true;
         }
         if (JSID_IS_ATOM(id, cx->names().length)) {
             *attrsp = JSPROP_READONLY | JSPROP_PERMANENT;
             return true;
         }
@@ -2230,18 +2065,17 @@ IsOwnId(JSContext *cx, HandleObject obj,
     uint32_t index;
     Rooted<TypedObject *> typedObj(cx, &obj->as<TypedObject>());
     switch (typedObj->typeDescr().kind()) {
       case type::Scalar:
       case type::Reference:
       case type::Simd:
         return false;
 
-      case type::SizedArray:
-      case type::UnsizedArray:
+      case type::Array:
         return js_IdIsIndex(id, &index) || JSID_IS_ATOM(id, cx->names().length);
 
       case type::Struct:
         size_t index;
         if (typedObj->typeDescr().as<StructTypeDescr>().fieldIndex(id, &index))
             return true;
     }
 
@@ -2300,18 +2134,17 @@ TypedObject::obj_enumerate(JSContext *cx
 
           case JSENUMERATE_NEXT:
           case JSENUMERATE_DESTROY:
             statep.setNull();
             break;
         }
         break;
 
-      case type::SizedArray:
-      case type::UnsizedArray:
+      case type::Array:
         switch (enum_op) {
           case JSENUMERATE_INIT_ALL:
           case JSENUMERATE_INIT:
             statep.setInt32(0);
             idp.set(INT_TO_JSID(typedObj->length()));
             break;
 
           case JSENUMERATE_NEXT:
@@ -2361,18 +2194,16 @@ TypedObject::obj_enumerate(JSContext *cx
     }
 
     return true;
 }
 
 void
 OutlineTypedObject::neuter(void *newData)
 {
-    if (typeDescr().kind() == type::UnsizedArray)
-        setUnsizedLength(0);
     setData(reinterpret_cast<uint8_t *>(newData));
 }
 
 /******************************************************************************
  * Inline typed objects
  */
 
 /* static */ InlineTypedObject *
@@ -2413,17 +2244,17 @@ InlineTypedObject::createCopy(JSContext 
 InlineTypedObject::obj_trace(JSTracer *trc, JSObject *object)
 {
     InlineTypedObject &typedObj = object->as<InlineTypedObject>();
 
     // When this is called for compacting GC, the related objects we touch here
     // may not have had their slots updated yet.
     TypeDescr &descr = typedObj.maybeForwardedTypeDescr();
 
-    descr.as<SizedTypeDescr>().traceInstances(trc, typedObj.inlineTypedMem(), 1);
+    descr.traceInstances(trc, typedObj.inlineTypedMem(), 1);
 }
 
 ArrayBufferObject *
 InlineTransparentTypedObject::getOrCreateBuffer(JSContext *cx)
 {
     LazyArrayBufferTable *&table = cx->compartment()->lazyArrayBuffers;
     if (!table) {
         table = cx->new_<LazyArrayBufferTable>(cx);
@@ -2432,17 +2263,17 @@ InlineTransparentTypedObject::getOrCreat
     }
 
     ArrayBufferObject *buffer = table->maybeBuffer(this);
     if (buffer)
         return buffer;
 
     ArrayBufferObject::BufferContents contents =
         ArrayBufferObject::BufferContents::createPlain(inlineTypedMem());
-    size_t nbytes = typeDescr().as<SizedTypeDescr>().size();
+    size_t nbytes = typeDescr().size();
 
     // Prevent GC under ArrayBufferObject::create, which might move this object
     // and its contents.
     gc::AutoSuppressGC suppress(cx);
 
     buffer = ArrayBufferObject::create(cx, nbytes, contents, ArrayBufferObject::DoesntOwnData);
     if (!buffer)
         return nullptr;
@@ -2589,21 +2420,18 @@ LengthForType(TypeDescr &descr)
 {
     switch (descr.kind()) {
       case type::Scalar:
       case type::Reference:
       case type::Struct:
       case type::Simd:
         return 0;
 
-      case type::SizedArray:
-        return descr.as<SizedArrayTypeDescr>().length();
-
-      case type::UnsizedArray:
-        return 0;
+      case type::Array:
+        return descr.as<ArrayTypeDescr>().length();
     }
 
     MOZ_CRASH("Invalid kind");
 }
 
 static bool
 CheckOffset(int32_t offset,
             int32_t size,
@@ -2628,25 +2456,25 @@ CheckOffset(int32_t offset,
     // Offset must be aligned.
     if ((offset % alignment) != 0)
         return false;
 
     return true;
 }
 
 /*static*/ bool
-TypedObject::constructSized(JSContext *cx, unsigned int argc, Value *vp)
+TypedObject::construct(JSContext *cx, unsigned int argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
-    MOZ_ASSERT(args.callee().is<SizedTypeDescr>());
-    Rooted<SizedTypeDescr*> callee(cx, &args.callee().as<SizedTypeDescr>());
-
-    // Typed object constructors for sized types are overloaded in
-    // three ways, in order of precedence:
+    MOZ_ASSERT(args.callee().is<TypeDescr>());
+    Rooted<TypeDescr*> callee(cx, &args.callee().as<TypeDescr>());
+
+    // Typed object constructors are overloaded in three ways, in order of
+    // precedence:
     //
     //   new TypeObj()
     //   new TypeObj(buffer, [offset])
     //   new TypeObj(data)
 
     // Zero argument constructor:
     if (args.length() == 0) {
         int32_t length = LengthForType(*callee);
@@ -2721,203 +2549,47 @@ TypedObject::constructSized(JSContext *c
     }
 
     // Something bogus.
     JS_ReportErrorNumber(cx, js_GetErrorMessage,
                          nullptr, JSMSG_TYPEDOBJECT_BAD_ARGS);
     return false;
 }
 
-/*static*/ bool
-TypedObject::constructUnsized(JSContext *cx, unsigned int argc, Value *vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-
-    MOZ_ASSERT(args.callee().is<TypeDescr>());
-    Rooted<UnsizedArrayTypeDescr*> callee(cx);
-    callee = &args.callee().as<UnsizedArrayTypeDescr>();
-
-    // Typed object constructors for unsized arrays are overloaded in
-    // four ways, in order of precedence:
-    //
-    //   new TypeObj(buffer, [offset, [length]]) // [1]
-    //   new TypeObj(length)                     // [1]
-    //   new TypeObj(data)
-    //   new TypeObj()
-    //
-    // [1] Explicit lengths only available for unsized arrays.
-
-    // Zero argument constructor:
-    if (args.length() == 0) {
-        Rooted<TypedObject*> obj(cx, createZeroed(cx, callee, 0));
-        if (!obj)
-            return false;
-        args.rval().setObject(*obj);
-        return true;
-    }
-
-    // Length constructor.
-    if (args[0].isInt32()) {
-        int32_t length = args[0].toInt32();
-        if (length < 0) {
-            JS_ReportErrorNumber(cx, js_GetErrorMessage,
-                                 nullptr, JSMSG_TYPEDOBJECT_BAD_ARGS);
-            return false;
-        }
-        Rooted<TypedObject*> obj(cx, createZeroed(cx, callee, length));
-        if (!obj)
-            return false;
-        args.rval().setObject(*obj);
-        return true;
-    }
-
-    // Buffer constructor.
-    if (args[0].isObject() && args[0].toObject().is<ArrayBufferObject>()) {
-        Rooted<ArrayBufferObject*> buffer(cx);
-        buffer = &args[0].toObject().as<ArrayBufferObject>();
-
-        if (callee->opaque()) {
-            JS_ReportErrorNumber(cx, js_GetErrorMessage,
-                                 nullptr, JSMSG_TYPEDOBJECT_BAD_ARGS);
-            return false;
-        }
-
-        int32_t offset;
-        if (args.length() >= 2 && !args[1].isUndefined()) {
-            if (!args[1].isInt32()) {
-                JS_ReportErrorNumber(cx, js_GetErrorMessage,
-                                     nullptr, JSMSG_TYPEDOBJECT_BAD_ARGS);
-                return false;
-            }
-
-            offset = args[1].toInt32();
-        } else {
-            offset = 0;
-        }
-
-        if (!CheckOffset(offset, 0, callee->alignment(), buffer->byteLength())) {
-            JS_ReportErrorNumber(cx, js_GetErrorMessage,
-                                 nullptr, JSMSG_TYPEDOBJECT_BAD_ARGS);
-            return false;
-        }
-
-        int32_t elemSize = callee->elementType().size();
-        int32_t bytesRemaining = buffer->byteLength() - offset;
-        int32_t maximumLength = bytesRemaining / elemSize;
-
-        int32_t length;
-        if (args.length() >= 3 && !args[2].isUndefined()) {
-            if (!args[2].isInt32()) {
-                JS_ReportErrorNumber(cx, js_GetErrorMessage,
-                                     nullptr, JSMSG_TYPEDOBJECT_BAD_ARGS);
-                return false;
-            }
-            length = args[2].toInt32();
-
-            if (length < 0 || length > maximumLength) {
-                JS_ReportErrorNumber(cx, js_GetErrorMessage,
-                                     nullptr, JSMSG_TYPEDOBJECT_BAD_ARGS);
-                return false;
-            }
-        } else {
-            if ((bytesRemaining % elemSize) != 0) {
-                JS_ReportErrorNumber(cx, js_GetErrorMessage,
-                                     nullptr, JSMSG_TYPEDOBJECT_BAD_ARGS);
-                return false;
-            }
-
-            length = maximumLength;
-        }
-
-        if (buffer->isNeutered()) {
-            JS_ReportErrorNumber(cx, js_GetErrorMessage,
-                                 nullptr, JSMSG_TYPEDOBJECT_BAD_ARGS);
-            return false;
-        }
-
-        Rooted<OutlineTypedObject*> obj(cx);
-        obj = OutlineTypedObject::createUnattached(cx, callee, length);
-        if (!obj)
-            return false;
-
-        obj->attach(cx, args[0].toObject().as<ArrayBufferObject>(), offset);
-    }
-
-    // Data constructor for unsized values
-    if (args[0].isObject()) {
-        // Read length out of the object.
-        RootedObject arg(cx, &args[0].toObject());
-        RootedValue lengthVal(cx);
-        if (!JSObject::getProperty(cx, arg, arg, cx->names().length, &lengthVal))
-            return false;
-        if (!lengthVal.isInt32()) {
-            JS_ReportErrorNumber(cx, js_GetErrorMessage,
-                                 nullptr, JSMSG_TYPEDOBJECT_BAD_ARGS);
-            return false;
-        }
-        int32_t length = lengthVal.toInt32();
-
-        // Check that length * elementSize does not overflow.
-        int32_t elementSize = callee->elementType().size();
-        int32_t byteLength;
-        if (!SafeMul(elementSize, length, &byteLength)) {
-            JS_ReportErrorNumber(cx, js_GetErrorMessage,
-                                 nullptr, JSMSG_TYPEDOBJECT_BAD_ARGS);
-            return false;
-        }
-
-        // Create the unsized array.
-        Rooted<TypedObject*> obj(cx, createZeroed(cx, callee, length));
-        if (!obj)
-            return false;
-
-        // Initialize from `arg`
-        if (!ConvertAndCopyTo(cx, obj, args[0]))
-            return false;
-        args.rval().setObject(*obj);
-        return true;
-    }
-
-    // Something bogus.
-    JS_ReportErrorNumber(cx, js_GetErrorMessage,
-                         nullptr, JSMSG_TYPEDOBJECT_BAD_ARGS);
-    return false;
-}
-
 /******************************************************************************
  * Intrinsics
  */
 
 bool
 js::NewOpaqueTypedObject(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     MOZ_ASSERT(args.length() == 1);
-    MOZ_ASSERT(args[0].isObject() && args[0].toObject().is<SizedTypeDescr>());
-
-    Rooted<SizedTypeDescr*> descr(cx, &args[0].toObject().as<SizedTypeDescr>());
+    MOZ_ASSERT(args[0].isObject() && args[0].toObject().is<TypeDescr>());
+
+    Rooted<TypeDescr*> descr(cx, &args[0].toObject().as<TypeDescr>());
     int32_t length = TypedObjLengthFromType(*descr);
     Rooted<OutlineTypedObject*> obj(cx);
     obj = OutlineTypedObject::createUnattachedWithClass(cx, &OutlineOpaqueTypedObject::class_, descr, length);
     if (!obj)
         return false;
     args.rval().setObject(*obj);
     return true;
 }
 
 bool
 js::NewDerivedTypedObject(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     MOZ_ASSERT(args.length() == 3);
-    MOZ_ASSERT(args[0].isObject() && args[0].toObject().is<SizedTypeDescr>());
+    MOZ_ASSERT(args[0].isObject() && args[0].toObject().is<TypeDescr>());
     MOZ_ASSERT(args[1].isObject() && args[1].toObject().is<TypedObject>());
     MOZ_ASSERT(args[2].isInt32());
 
-    Rooted<SizedTypeDescr*> descr(cx, &args[0].toObject().as<SizedTypeDescr>());
+    Rooted<TypeDescr*> descr(cx, &args[0].toObject().as<TypeDescr>());
     Rooted<TypedObject*> typedObj(cx, &args[1].toObject().as<TypedObject>());
     int32_t offset = args[2].toInt32();
 
     Rooted<TypedObject*> obj(cx);
     obj = OutlineTypedObject::createDerived(cx, descr, typedObj, offset);
     if (!obj)
         return false;
 
@@ -3052,56 +2724,25 @@ JS_JITINFO_NATIVE_PARALLEL_THREADSAFE(js
 bool
 js::TypeDescrIsArrayType(ThreadSafeContext *, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     MOZ_ASSERT(args.length() == 1);
     MOZ_ASSERT(args[0].isObject());
     MOZ_ASSERT(args[0].toObject().is<js::TypeDescr>());
     JSObject& obj = args[0].toObject();
-    args.rval().setBoolean(obj.is<js::SizedArrayTypeDescr>() ||
-                           obj.is<js::UnsizedArrayTypeDescr>());
+    args.rval().setBoolean(obj.is<js::ArrayTypeDescr>());
     return true;
 }
 
 JS_JITINFO_NATIVE_PARALLEL_THREADSAFE(js::TypeDescrIsArrayTypeJitInfo,
                                       TypeDescrIsArrayTypeJitInfo,
                                       js::TypeDescrIsArrayType);
 
 bool
-js::TypeDescrIsSizedArrayType(ThreadSafeContext *, unsigned argc, Value *vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-    MOZ_ASSERT(args.length() == 1);
-    MOZ_ASSERT(args[0].isObject());
-    MOZ_ASSERT(args[0].toObject().is<js::TypeDescr>());
-    args.rval().setBoolean(args[0].toObject().is<js::SizedArrayTypeDescr>());
-    return true;
-}
-
-JS_JITINFO_NATIVE_PARALLEL_THREADSAFE(js::TypeDescrIsSizedArrayTypeJitInfo,
-                                      TypeDescrIsSizedArrayTypeJitInfo,
-                                      js::TypeDescrIsSizedArrayType);
-
-bool
-js::TypeDescrIsUnsizedArrayType(ThreadSafeContext *, unsigned argc, Value *vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-    MOZ_ASSERT(args.length() == 1);
-    MOZ_ASSERT(args[0].isObject());
-    MOZ_ASSERT(args[0].toObject().is<js::TypeDescr>());
-    args.rval().setBoolean(args[0].toObject().is<js::UnsizedArrayTypeDescr>());
-    return true;
-}
-
-JS_JITINFO_NATIVE_PARALLEL_THREADSAFE(js::TypeDescrIsUnsizedArrayTypeJitInfo,
-                                      TypeDescrIsUnsizedArrayTypeJitInfo,
-                                      js::TypeDescrIsUnsizedArrayType);
-
-bool
 js::TypedObjectIsAttached(ThreadSafeContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     TypedObject &typedObj = args[0].toObject().as<TypedObject>();
     args.rval().setBoolean(typedObj.isAttached());
     return true;
 }
 
@@ -3306,53 +2947,48 @@ JS_FOR_EACH_UNIQUE_SCALAR_TYPE_REPR_CTYP
 JS_FOR_EACH_REFERENCE_TYPE_REPR(JS_STORE_REFERENCE_CLASS_IMPL)
 JS_FOR_EACH_REFERENCE_TYPE_REPR(JS_LOAD_REFERENCE_CLASS_IMPL)
 
 ///////////////////////////////////////////////////////////////////////////
 // Walking memory
 
 template<typename V>
 static void
-visitReferences(SizedTypeDescr &descr,
+visitReferences(TypeDescr &descr,
                 uint8_t *mem,
                 V& visitor)
 {
     if (descr.transparent())
         return;
 
     switch (descr.kind()) {
       case type::Scalar:
       case type::Simd:
         return;
 
       case type::Reference:
         visitor.visitReference(descr.as<ReferenceTypeDescr>(), mem);
         return;
 
-      case type::SizedArray:
+      case type::Array:
       {
-        SizedArrayTypeDescr &arrayDescr = descr.as<SizedArrayTypeDescr>();
-        SizedTypeDescr &elementDescr = arrayDescr.maybeForwardedElementType();
+        ArrayTypeDescr &arrayDescr = descr.as<ArrayTypeDescr>();
+        TypeDescr &elementDescr = arrayDescr.maybeForwardedElementType();
         for (int32_t i = 0; i < arrayDescr.length(); i++) {
             visitReferences(elementDescr, mem, visitor);
             mem += elementDescr.size();
         }
         return;
       }
 
-      case type::UnsizedArray:
-      {
-        MOZ_CRASH("Only Sized Type representations");
-      }
-
       case type::Struct:
       {
         StructTypeDescr &structDescr = descr.as<StructTypeDescr>();
         for (size_t i = 0; i < structDescr.maybeForwardedFieldCount(); i++) {
-            SizedTypeDescr &descr = structDescr.maybeForwardedFieldDescr(i);
+            TypeDescr &descr = structDescr.maybeForwardedFieldDescr(i);
             size_t offset = structDescr.maybeForwardedFieldOffset(i);
             visitReferences(descr, mem + offset, visitor);
         }
         return;
       }
     }
 
     MOZ_CRASH("Invalid type repr kind");
@@ -3401,17 +3037,17 @@ js::MemoryInitVisitor::visitReference(Re
         return;
       }
     }
 
     MOZ_CRASH("Invalid kind");
 }
 
 void
-SizedTypeDescr::initInstances(const JSRuntime *rt, uint8_t *mem, size_t length)
+TypeDescr::initInstances(const JSRuntime *rt, uint8_t *mem, size_t length)
 {
     MOZ_ASSERT(length >= 1);
 
     MemoryInitVisitor visitor(rt);
 
     // Initialize the 0th instance
     memset(mem, 0, size());
     if (opaque())
@@ -3471,17 +3107,17 @@ js::MemoryTracingVisitor::visitReference
         return;
       }
     }
 
     MOZ_CRASH("Invalid kind");
 }
 
 void
-SizedTypeDescr::traceInstances(JSTracer *trace, uint8_t *mem, size_t length)
+TypeDescr::traceInstances(JSTracer *trace, uint8_t *mem, size_t length)
 {
     MemoryTracingVisitor visitor(trace);
 
     for (size_t i = 0; i < length; i++) {
         visitReferences(*this, mem, visitor);
         mem += size();
     }
 }
--- a/js/src/builtin/TypedObject.h
+++ b/js/src/builtin/TypedObject.h
@@ -114,35 +114,29 @@ static T ConvertScalar(double d)
 
 namespace type {
 
 enum Kind {
     Scalar = JS_TYPEREPR_SCALAR_KIND,
     Reference = JS_TYPEREPR_REFERENCE_KIND,
     Simd = JS_TYPEREPR_SIMD_KIND,
     Struct = JS_TYPEREPR_STRUCT_KIND,
-    SizedArray = JS_TYPEREPR_SIZED_ARRAY_KIND,
-    UnsizedArray = JS_TYPEREPR_UNSIZED_ARRAY_KIND,
+    Array = JS_TYPEREPR_ARRAY_KIND
 };
 
-static inline bool isSized(type::Kind kind) {
-    return kind > JS_TYPEREPR_MAX_UNSIZED_KIND;
-}
-
 }
 
 ///////////////////////////////////////////////////////////////////////////
 // Typed Prototypes
 
-class SizedTypeDescr;
 class SimpleTypeDescr;
 class ComplexTypeDescr;
 class SimdTypeDescr;
 class StructTypeDescr;
-class SizedTypedProto;
+class TypedProto;
 
 /*
  * The prototype for a typed object. Currently, carries a link to the
  * type descriptor. Eventually will carry most of the type information
  * we want.
  */
 class TypedProto : public NativeObject
 {
@@ -169,20 +163,16 @@ class TypeDescr : public NativeObject
     // errors if a is<FooTypeDescr>() etc goes wrong. Otherwise, the
     // default implementation resolves this to a reference to
     // FooTypeDescr::class_ which resolves to
     // JSObject::class_. Debugging the resulting errors leads to much
     // fun and rejoicing.
     static const Class class_;
 
   public:
-    static bool isSized(type::Kind kind) {
-        return kind > JS_TYPEREPR_MAX_UNSIZED_KIND;
-    }
-
     TypedProto &typedProto() const {
         return getReservedSlot(JS_DESCR_SLOT_TYPROTO).toObject().as<TypedProto>();
     }
 
     JSAtom &stringRepr() const {
         return getReservedSlot(JS_DESCR_SLOT_STRING_REPR).toString()->asAtom();
     }
 
@@ -196,34 +186,28 @@ class TypeDescr : public NativeObject
 
     bool transparent() const {
         return !opaque();
     }
 
     int32_t alignment() const {
         return getReservedSlot(JS_DESCR_SLOT_ALIGNMENT).toInt32();
     }
-};
 
-typedef Handle<TypeDescr*> HandleTypeDescr;
-
-class SizedTypeDescr : public TypeDescr
-{
-  public:
     int32_t size() const {
         return getReservedSlot(JS_DESCR_SLOT_SIZE).toInt32();
     }
 
     void initInstances(const JSRuntime *rt, uint8_t *mem, size_t length);
     void traceInstances(JSTracer *trace, uint8_t *mem, size_t length);
 };
 
-typedef Handle<SizedTypeDescr*> HandleSizedTypeDescr;
+typedef Handle<TypeDescr*> HandleTypeDescr;
 
-class SimpleTypeDescr : public SizedTypeDescr
+class SimpleTypeDescr : public TypeDescr
 {
 };
 
 // Type for scalar type constructors like `uint8`. All such type
 // constructors share a common js::Class and JSFunctionSpec. Scalar
 // types are non-opaque (their storage is visible unless combined with
 // an opaque reference type.)
 class ScalarTypeDescr : public SimpleTypeDescr
@@ -323,17 +307,17 @@ class ReferenceTypeDescr : public Simple
 
 #define JS_FOR_EACH_REFERENCE_TYPE_REPR(macro_)                    \
     macro_(ReferenceTypeDescr::TYPE_ANY,    HeapValue, Any)        \
     macro_(ReferenceTypeDescr::TYPE_OBJECT, HeapPtrObject, Object) \
     macro_(ReferenceTypeDescr::TYPE_STRING, HeapPtrString, string)
 
 // Type descriptors whose instances are objects and hence which have
 // an associated `prototype` property.
-class ComplexTypeDescr : public SizedTypeDescr
+class ComplexTypeDescr : public TypeDescr
 {
   public:
     // Returns the prototype that instances of this type descriptor
     // will have.
     TypedProto &instancePrototype() const {
         return getReservedSlot(JS_DESCR_SLOT_TYPROTO).toObject().as<TypedProto>();
     }
 };
@@ -367,43 +351,38 @@ class SimdTypeDescr : public ComplexType
     macro_(SimdTypeDescr::TYPE_INT32, int32_t, int32)                  \
     macro_(SimdTypeDescr::TYPE_FLOAT32, float, float32)
 
 bool IsTypedObjectClass(const Class *clasp); // Defined below
 bool IsTypedObjectArray(JSObject& obj);
 
 bool CreateUserSizeAndAlignmentProperties(JSContext *cx, HandleTypeDescr obj);
 
+class ArrayTypeDescr;
+
 /*
  * Properties and methods of the `ArrayType` meta type object. There
  * is no `class_` field because `ArrayType` is just a native
  * constructor function.
  */
 class ArrayMetaTypeDescr : public JSObject
 {
   private:
-    friend class UnsizedArrayTypeDescr;
-
-    // Helper for creating a new ArrayType object, either sized or unsized.
-    // The template parameter `T` should be either `UnsizedArrayTypeDescr`
-    // or `SizedArrayTypeDescr`.
+    // Helper for creating a new ArrayType object.
     //
-    // - `arrayTypePrototype` - prototype for the new object to be created,
-    //                          either ArrayType.prototype or
-    //                          unsizedArrayType.__proto__ depending on
-    //                          whether this is a sized or unsized array
+    // - `arrayTypePrototype` - prototype for the new object to be created
     // - `elementType` - type object for the elements in the array
     // - `stringRepr` - canonical string representation for the array
-    // - `size` - length of the array (0 if unsized)
-    template<class T>
-    static T *create(JSContext *cx,
-                     HandleObject arrayTypePrototype,
-                     HandleSizedTypeDescr elementType,
-                     HandleAtom stringRepr,
-                     int32_t size);
+    // - `size` - length of the array
+    static ArrayTypeDescr *create(JSContext *cx,
+                                  HandleObject arrayTypePrototype,
+                                  HandleTypeDescr elementType,
+                                  HandleAtom stringRepr,
+                                  int32_t size,
+                                  int32_t length);
 
   public:
     // 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,
@@ -412,64 +391,35 @@ class ArrayMetaTypeDescr : public JSObje
     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);
 };
 
 /*
- * Type descriptor created by `new ArrayType(typeObj)`
- *
- * These have a prototype, and hence *could* be a subclass of
- * `ComplexTypeDescr`, but it would require some reshuffling of the
- * hierarchy, and it's not worth the trouble since they will be going
- * away as part of bug 973238.
+ * Type descriptor created by `new ArrayType(type, n)`
  */
-class UnsizedArrayTypeDescr : public TypeDescr
+class ArrayTypeDescr : public ComplexTypeDescr
 {
   public:
     static const Class class_;
-    static const type::Kind Kind = type::UnsizedArray;
+    static const type::Kind Kind = type::Array;
 
-    // This is the sized method on unsized array type objects.  It
-    // produces a sized variant.
-    static bool dimension(JSContext *cx, unsigned int argc, jsval *vp);
-
-    SizedTypeDescr &elementType() const {
-        return getReservedSlot(JS_DESCR_SLOT_ARRAY_ELEM_TYPE).toObject().as<SizedTypeDescr>();
+    TypeDescr &elementType() const {
+        return getReservedSlot(JS_DESCR_SLOT_ARRAY_ELEM_TYPE).toObject().as<TypeDescr>();
     }
 
-    SizedTypeDescr &maybeForwardedElementType() const {
-        JSObject *elemType =
-            MaybeForwarded(&getReservedSlot(JS_DESCR_SLOT_ARRAY_ELEM_TYPE).toObject());
-        return elemType->as<SizedTypeDescr>();
-    }
-};
-
-/*
- * Type descriptor created by `unsizedArrayTypeObj.dimension()`
- */
-class SizedArrayTypeDescr : public ComplexTypeDescr
-{
-  public:
-    static const Class class_;
-    static const type::Kind Kind = type::SizedArray;
-
-    SizedTypeDescr &elementType() const {
-        return getReservedSlot(JS_DESCR_SLOT_ARRAY_ELEM_TYPE).toObject().as<SizedTypeDescr>();
-    }
-
-    SizedTypeDescr &maybeForwardedElementType() const {
+    TypeDescr &maybeForwardedElementType() const {
         JSObject *elemType = &getReservedSlot(JS_DESCR_SLOT_ARRAY_ELEM_TYPE).toObject();
-        return MaybeForwarded(elemType)->as<SizedTypeDescr>();
+        return MaybeForwarded(elemType)->as<TypeDescr>();
     }
 
     int32_t length() const {
-        return getReservedSlot(JS_DESCR_SLOT_SIZED_ARRAY_LENGTH).toInt32();
+        return getReservedSlot(JS_DESCR_SLOT_ARRAY_LENGTH).toInt32();
     }
 };
 
 /*
  * Properties and methods of the `StructType` meta type object. There
  * is no `class_` field because `StructType` is just a native
  * constructor function.
  */
@@ -507,18 +457,18 @@ class StructTypeDescr : public ComplexTy
     // Set `*out` to the index of the field named `id` and returns true,
     // or return false if no such field exists.
     bool fieldIndex(jsid id, size_t *out) const;
 
     // Return the name of the field at index `index`.
     JSAtom &fieldName(size_t index) const;
 
     // Return the type descr of the field at index `index`.
-    SizedTypeDescr &fieldDescr(size_t index) const;
-    SizedTypeDescr &maybeForwardedFieldDescr(size_t index) const;
+    TypeDescr &fieldDescr(size_t index) const;
+    TypeDescr &maybeForwardedFieldDescr(size_t index) const;
 
     // Return the offset of the field at index `index`.
     size_t fieldOffset(size_t index) const;
     size_t maybeForwardedFieldOffset(size_t index) const;
 
   private:
     NativeObject &fieldInfoObject(size_t slot) const {
         return getReservedSlot(slot).toObject().as<NativeObject>();
@@ -548,24 +498,22 @@ class TypedObjectModuleObject : public N
 };
 
 /* Base type for transparent and opaque typed objects. */
 class TypedObject : public JSObject
 {
   private:
     static const bool IsTypedObjectClass = true;
 
-    template<class T>
     static bool obj_getArrayElement(JSContext *cx,
                                     Handle<TypedObject*> typedObj,
                                     Handle<TypeDescr*> typeDescr,
                                     uint32_t index,
                                     MutableHandleValue vp);
 
-    template<class T>
     static bool obj_setArrayElement(JSContext *cx,
                                     Handle<TypedObject*> typedObj,
                                     Handle<TypeDescr*> typeDescr,
                                     uint32_t index,
                                     MutableHandleValue vp);
 
   protected:
     static bool obj_lookupGeneric(JSContext *cx, HandleObject obj,
@@ -595,19 +543,16 @@ class TypedObject : public JSObject
                                HandleId id, MutableHandleValue vp);
 
     static bool obj_getProperty(JSContext *cx, HandleObject obj, HandleObject receiver,
                                 HandlePropertyName name, MutableHandleValue vp);
 
     static bool obj_getElement(JSContext *cx, HandleObject obj, HandleObject receiver,
                                uint32_t index, MutableHandleValue vp);
 
-    static bool obj_getUnsizedArrayElement(JSContext *cx, HandleObject obj, HandleObject receiver,
-                                         uint32_t index, MutableHandleValue vp);
-
     static bool obj_setGeneric(JSContext *cx, HandleObject obj, HandleId id,
                                MutableHandleValue vp, bool strict);
     static bool obj_setProperty(JSContext *cx, HandleObject obj, HandlePropertyName name,
                                 MutableHandleValue vp, bool strict);
     static bool obj_setElement(JSContext *cx, HandleObject obj, uint32_t index,
                                MutableHandleValue vp, bool strict);
 
     static bool obj_getGenericAttributes(JSContext *cx, HandleObject obj,
@@ -640,30 +585,17 @@ class TypedObject : public JSObject
     int32_t offset() const;
     int32_t length() const;
     uint8_t *typedMem() const;
     uint8_t *typedMemBase() const;
     bool isAttached() const;
     bool maybeForwardedIsAttached() const;
 
     int32_t size() const {
-        switch (typeDescr().kind()) {
-          case type::Scalar:
-          case type::Simd:
-          case type::Reference:
-          case type::Struct:
-          case type::SizedArray:
-            return typeDescr().as<SizedTypeDescr>().size();
-
-          case type::UnsizedArray: {
-            SizedTypeDescr &elementType = typeDescr().as<UnsizedArrayTypeDescr>().elementType();
-            return elementType.size() * length();
-          }
-        }
-        MOZ_CRASH("unhandled typerepresentation kind");
+        return typeDescr().size();
     }
 
     uint8_t *typedMem(size_t offset) const {
         // It seems a bit surprising that one might request an offset
         // == size(), but it can happen when taking the "address of" a
         // 0-sized value. (In other words, we maintain the invariant
         // that `offset + size <= size()` -- this is always checked in
         // the caller's side.)
@@ -674,22 +606,19 @@ class TypedObject : public JSObject
     inline bool opaque() const;
 
     // Creates a new typed object whose memory is freshly allocated and
     // initialized with zeroes (or, in the case of references, an appropriate
     // default value).
     static TypedObject *createZeroed(JSContext *cx, HandleTypeDescr typeObj, int32_t length,
                                      gc::InitialHeap heap = gc::DefaultHeap);
 
-    // User-accessible constructor (`new TypeDescriptor(...)`) used for sized
-    // types. Note that the callee here is the type descriptor.
-    static bool constructSized(JSContext *cx, unsigned argc, Value *vp);
-
-    // As `constructSized`, but for unsized array types.
-    static bool constructUnsized(JSContext *cx, unsigned argc, Value *vp);
+    // User-accessible constructor (`new TypeDescriptor(...)`). Note that the
+    // callee here is the type descriptor.
+    static bool construct(JSContext *cx, unsigned argc, Value *vp);
 
     /* Accessors for self hosted code. */
     static bool GetBuffer(JSContext *cx, unsigned argc, Value *vp);
     static bool GetByteOffset(JSContext *cx, unsigned argc, Value *vp);
 };
 
 typedef Handle<TypedObject*> HandleTypedObject;
 
@@ -698,59 +627,36 @@ class OutlineTypedObject : public TypedO
     // The object which owns the data this object points to. Because this
     // pointer is managed in tandem with |data|, this is not a HeapPtr and
     // barriers are managed directly.
     JSObject *owner_;
 
     // Data pointer to some offset in the owner's contents.
     uint8_t *data_;
 
-    // The length for unsized array objects. For other outline objects the
-    // space for this field is not allocated and cannot be accessed.
-    uint32_t unsizedLength_;
-
     void setOwnerAndData(JSObject *owner, uint8_t *data);
 
-    void setUnsizedLength(uint32_t length) {
-        MOZ_ASSERT(typeDescr().is<UnsizedArrayTypeDescr>());
-        unsizedLength_ = length;
-    }
-
   public:
-    static gc::AllocKind allocKindForTypeDescriptor(TypeDescr *descr) {
-        // Use a larger allocation kind for unsized arrays, to accommodate the
-        // unsized length.
-        if (descr->is<UnsizedArrayTypeDescr>())
-            return gc::FINALIZE_OBJECT2;
-        return gc::FINALIZE_OBJECT0;
-    }
-
     // JIT accessors.
     static size_t offsetOfData() { return offsetof(OutlineTypedObject, data_); }
     static size_t offsetOfOwner() { return offsetof(OutlineTypedObject, owner_); }
-    static size_t offsetOfUnsizedLength() { return offsetof(OutlineTypedObject, unsizedLength_); }
 
     JSObject &owner() const {
         MOZ_ASSERT(owner_);
         return *owner_;
     }
 
     JSObject *maybeOwner() const {
         return owner_;
     }
 
     uint8_t *outOfLineTypedMem() const {
         return data_;
     }
 
-    int32_t unsizedLength() const {
-        MOZ_ASSERT(typeDescr().is<UnsizedArrayTypeDescr>());
-        return unsizedLength_;
-    }
-
     void setData(uint8_t *data) {
         data_ = data;
     }
 
     // Helper for createUnattached()
     static OutlineTypedObject *createUnattachedWithClass(JSContext *cx,
                                                          const Class *clasp,
                                                          HandleTypeDescr type,
@@ -767,17 +673,17 @@ class OutlineTypedObject : public TypedO
     // - length: 0 unless this is an array, otherwise the length
     static OutlineTypedObject *createUnattached(JSContext *cx, HandleTypeDescr type,
                                                 int32_t length, gc::InitialHeap heap = gc::DefaultHeap);
 
     // Creates a typedObj that aliases the memory pointed at by `owner`
     // at the given offset. The typedObj will be a handle iff type is a
     // handle and a typed object otherwise.
     static OutlineTypedObject *createDerived(JSContext *cx,
-                                             HandleSizedTypeDescr type,
+                                             HandleTypeDescr type,
                                              Handle<TypedObject*> typedContents,
                                              int32_t offset);
 
     // Use this method when `buffer` is the owner of the memory.
     void attach(JSContext *cx, ArrayBufferObject &buffer, int32_t offset);
 
     // Otherwise, use this to attach to memory referenced by another typedObj.
     void attach(JSContext *cx, TypedObject &typedObj, int32_t offset);
@@ -811,17 +717,17 @@ class InlineTypedObject : public TypedOb
     // Start of the inline data, which immediately follows the shape and type.
     uint8_t data_[1];
 
   public:
     static const size_t MaximumSize =
         sizeof(NativeObject) - sizeof(TypedObject) + NativeObject::MAX_FIXED_SLOTS * sizeof(Value);
 
     static gc::AllocKind allocKindForTypeDescriptor(TypeDescr *descr) {
-        size_t nbytes = descr->as<SizedTypeDescr>().size();
+        size_t nbytes = descr->size();
         MOZ_ASSERT(nbytes <= MaximumSize);
 
         size_t dataSlots = AlignBytes(nbytes, sizeof(Value) / sizeof(Value));
         MOZ_ASSERT(nbytes <= dataSlots * sizeof(Value));
         return gc::GetGCObjectKind(dataSlots);
     }
 
     uint8_t *inlineTypedMem() const {
@@ -927,22 +833,16 @@ extern const JSJitInfo ObjectIsTranspare
 /* Predicates on type descriptor objects.  In all cases, 'obj' must be a type descriptor. */
 
 bool TypeDescrIsSimpleType(ThreadSafeContext *, unsigned argc, Value *vp);
 extern const JSJitInfo TypeDescrIsSimpleTypeJitInfo;
 
 bool TypeDescrIsArrayType(ThreadSafeContext *, unsigned argc, Value *vp);
 extern const JSJitInfo TypeDescrIsArrayTypeJitInfo;
 
-bool TypeDescrIsSizedArrayType(ThreadSafeContext *, unsigned argc, Value *vp);
-extern const JSJitInfo TypeDescrIsSizedArrayTypeJitInfo;
-
-bool TypeDescrIsUnsizedArrayType(ThreadSafeContext *, unsigned argc, Value *vp);
-extern const JSJitInfo TypeDescrIsUnsizedArrayTypeJitInfo;
-
 /*
  * Usage: TypedObjectIsAttached(obj)
  *
  * Given a TypedObject `obj`, returns true if `obj` is
  * "attached" (i.e., its data pointer is nullptr).
  */
 bool TypedObjectIsAttached(ThreadSafeContext *cx, unsigned argc, Value *vp);
 extern const JSJitInfo TypedObjectIsAttachedJitInfo;
@@ -1096,32 +996,25 @@ IsSimpleTypeDescrClass(const Class* clas
     return clasp == &ScalarTypeDescr::class_ ||
            clasp == &ReferenceTypeDescr::class_;
 }
 
 inline bool
 IsComplexTypeDescrClass(const Class* clasp)
 {
     return clasp == &StructTypeDescr::class_ ||
-           clasp == &SizedArrayTypeDescr::class_ ||
+           clasp == &ArrayTypeDescr::class_ ||
            clasp == &SimdTypeDescr::class_;
 }
 
 inline bool
-IsSizedTypeDescrClass(const Class* clasp)
-{
-    return IsSimpleTypeDescrClass(clasp) ||
-           IsComplexTypeDescrClass(clasp);
-}
-
-inline bool
 IsTypeDescrClass(const Class* clasp)
 {
-    return IsSizedTypeDescrClass(clasp) ||
-           clasp == &UnsizedArrayTypeDescr::class_;
+    return IsSimpleTypeDescrClass(clasp) ||
+           IsComplexTypeDescrClass(clasp);
 }
 
 inline bool
 TypedObject::opaque() const
 {
     return IsOpaqueTypedObjectClass(getClass());
 }
 
@@ -1158,23 +1051,16 @@ template <>
 inline bool
 JSObject::is<js::SimpleTypeDescr>() const
 {
     return IsSimpleTypeDescrClass(getClass());
 }
 
 template <>
 inline bool
-JSObject::is<js::SizedTypeDescr>() const
-{
-    return IsSizedTypeDescrClass(getClass());
-}
-
-template <>
-inline bool
 JSObject::is<js::ComplexTypeDescr>() const
 {
     return IsComplexTypeDescrClass(getClass());
 }
 
 template <>
 inline bool
 JSObject::is<js::TypeDescr>() const
--- a/js/src/builtin/TypedObject.js
+++ b/js/src/builtin/TypedObject.js
@@ -14,18 +14,18 @@
 #define DESCR_SIZE(obj) \
     UnsafeGetReservedSlot(obj, JS_DESCR_SLOT_SIZE)
 #define DESCR_OPAQUE(obj) \
     UnsafeGetReservedSlot(obj, JS_DESCR_SLOT_OPAQUE)
 #define DESCR_TYPE(obj)   \
     UnsafeGetReservedSlot(obj, JS_DESCR_SLOT_TYPE)
 #define DESCR_ARRAY_ELEMENT_TYPE(obj) \
     UnsafeGetReservedSlot(obj, JS_DESCR_SLOT_ARRAY_ELEM_TYPE)
-#define DESCR_SIZED_ARRAY_LENGTH(obj) \
-    TO_INT32(UnsafeGetReservedSlot(obj, JS_DESCR_SLOT_SIZED_ARRAY_LENGTH))
+#define DESCR_ARRAY_LENGTH(obj) \
+    TO_INT32(UnsafeGetReservedSlot(obj, JS_DESCR_SLOT_ARRAY_LENGTH))
 #define DESCR_STRUCT_FIELD_NAMES(obj) \
     UnsafeGetReservedSlot(obj, JS_DESCR_SLOT_STRUCT_FIELD_NAMES)
 #define DESCR_STRUCT_FIELD_TYPES(obj) \
     UnsafeGetReservedSlot(obj, JS_DESCR_SLOT_STRUCT_FIELD_TYPES)
 #define DESCR_STRUCT_FIELD_OFFSETS(obj) \
     UnsafeGetReservedSlot(obj, JS_DESCR_SLOT_STRUCT_FIELD_OFFSETS)
 
 // Typed prototype slots
@@ -65,22 +65,19 @@ function TypedObjectGet(descr, typedObj,
     return TypedObjectGetScalar(descr, typedObj, offset);
 
   case JS_TYPEREPR_REFERENCE_KIND:
     return TypedObjectGetReference(descr, typedObj, offset);
 
   case JS_TYPEREPR_SIMD_KIND:
     return TypedObjectGetSimd(descr, typedObj, offset);
 
-  case JS_TYPEREPR_SIZED_ARRAY_KIND:
+  case JS_TYPEREPR_ARRAY_KIND:
   case JS_TYPEREPR_STRUCT_KIND:
     return TypedObjectGetDerived(descr, typedObj, offset);
-
-  case JS_TYPEREPR_UNSIZED_ARRAY_KIND:
-    assert(false, "Unhandled repr kind: " + DESCR_KIND(descr));
   }
 
   assert(false, "Unhandled kind: " + DESCR_KIND(descr));
   return undefined;
 }
 
 function TypedObjectGetDerived(descr, typedObj, offset) {
   assert(!TypeDescrIsSimpleType(descr),
@@ -196,24 +193,18 @@ function TypedObjectSet(descr, typedObj,
   case JS_TYPEREPR_REFERENCE_KIND:
     TypedObjectSetReference(descr, typedObj, offset, fromValue);
     return;
 
   case JS_TYPEREPR_SIMD_KIND:
     TypedObjectSetSimd(descr, typedObj, offset, fromValue);
     return;
 
-  case JS_TYPEREPR_SIZED_ARRAY_KIND:
-    var length = DESCR_SIZED_ARRAY_LENGTH(descr);
-    if (TypedObjectSetArray(descr, length, typedObj, offset, fromValue))
-      return;
-    break;
-
-  case JS_TYPEREPR_UNSIZED_ARRAY_KIND:
-    var length = typedObj.length;
+  case JS_TYPEREPR_ARRAY_KIND:
+    var length = DESCR_ARRAY_LENGTH(descr);
     if (TypedObjectSetArray(descr, length, typedObj, offset, fromValue))
       return;
     break;
 
   case JS_TYPEREPR_STRUCT_KIND:
     if (!IsObject(fromValue))
       break;
 
@@ -422,41 +413,32 @@ function TypedArrayRedimension(newArrayT
     ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
 
   if (!IsObject(newArrayType) || !ObjectIsTypeDescr(newArrayType))
     ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
 
   // Peel away the outermost array layers from the type of `this` to find
   // the core element type. In the process, count the number of elements.
   var oldArrayType = TypedObjectTypeDescr(this);
-  var oldArrayReprKind = DESCR_KIND(oldArrayType);
   var oldElementType = oldArrayType;
   var oldElementCount = 1;
-  switch (oldArrayReprKind) {
-  case JS_TYPEREPR_UNSIZED_ARRAY_KIND:
-    oldElementCount *= this.length;
-    oldElementType = oldElementType.elementType;
-    break;
 
-  case JS_TYPEREPR_SIZED_ARRAY_KIND:
-    break;
+  if (DESCR_KIND(oldArrayType) != JS_TYPEREPR_ARRAY_KIND)
+    ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
 
-  default:
-    ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
-  }
-  while (DESCR_KIND(oldElementType) === JS_TYPEREPR_SIZED_ARRAY_KIND) {
+  while (DESCR_KIND(oldElementType) === JS_TYPEREPR_ARRAY_KIND) {
     oldElementCount *= oldElementType.length;
     oldElementType = oldElementType.elementType;
   }
 
   // Peel away the outermost array layers from `newArrayType`. In the
   // process, count the number of elements.
   var newElementType = newArrayType;
   var newElementCount = 1;
-  while (DESCR_KIND(newElementType) == JS_TYPEREPR_SIZED_ARRAY_KIND) {
+  while (DESCR_KIND(newElementType) == JS_TYPEREPR_ARRAY_KIND) {
     newElementCount *= newElementType.length;
     newElementType = newElementType.elementType;
   }
 
   // Check that the total number of elements does not change.
   if (oldElementCount !== newElementCount) {
     ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
   }
@@ -531,21 +513,21 @@ function DescrToSource() {
 // Warning: user exposed!
 function ArrayShorthand(...dims) {
   if (!IsObject(this) || !ObjectIsTypeDescr(this))
     ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
 
   var T = GetTypedObjectModule();
 
   if (dims.length == 0)
-    return new T.ArrayType(this);
+    ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
 
   var accum = this;
   for (var i = dims.length - 1; i >= 0; i--)
-    accum = new T.ArrayType(accum).dimension(dims[i]);
+    accum = new T.ArrayType(accum, dims[i]);
   return accum;
 }
 
 // This is the `storage()` function defined in the spec.  When
 // provided with a *transparent* typed object, it returns an object
 // containing buffer, byteOffset, byteLength. When given an opaque
 // typed object, it returns null. Otherwise it throws.
 //
@@ -555,21 +537,17 @@ function StorageOfTypedObject(obj) {
     if (ObjectIsOpaqueTypedObject(obj))
       return null;
 
     if (ObjectIsTransparentTypedObject(obj)) {
       if (!TypedObjectIsAttached(obj))
           ThrowError(JSMSG_TYPEDOBJECT_HANDLE_UNATTACHED);
 
       var descr = TypedObjectTypeDescr(obj);
-      var byteLength;
-      if (DESCR_KIND(descr) == JS_TYPEREPR_UNSIZED_ARRAY_KIND)
-        byteLength = DESCR_SIZE(descr.elementType) * obj.length;
-      else
-        byteLength = DESCR_SIZE(descr);
+      var byteLength = DESCR_SIZE(descr);
 
       return { buffer: TypedObjectBuffer(obj),
                byteLength: byteLength,
                byteOffset: TypedObjectByteOffset(obj) };
     }
   }
 
   ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
@@ -600,42 +578,31 @@ function TypeOfTypedObject(obj) {
   }
 }
 
 ///////////////////////////////////////////////////////////////////////////
 // TypedObject surface API methods (sequential implementations).
 
 // Warning: user exposed!
 function TypedObjectArrayTypeBuild(a,b,c) {
-  // Arguments (this sized) : [depth], func
-  // Arguments (this unsized) : length, [depth], func
+  // Arguments : [depth], func
 
   if (!IsObject(this) || !ObjectIsTypeDescr(this))
     ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
   var kind = DESCR_KIND(this);
   switch (kind) {
-  case JS_TYPEREPR_SIZED_ARRAY_KIND:
+  case JS_TYPEREPR_ARRAY_KIND:
     if (typeof a === "function") // XXX here and elsewhere: these type dispatches are fragile at best.
       return BuildTypedSeqImpl(this, this.length, 1, a);
     else if (typeof a === "number" && typeof b === "function")
       return BuildTypedSeqImpl(this, this.length, a, b);
     else if (typeof a === "number")
       ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
     else
       ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
-  case JS_TYPEREPR_UNSIZED_ARRAY_KIND:
-    var len = a;
-    if (typeof b === "function")
-      return BuildTypedSeqImpl(this, len, 1, b);
-    else if (typeof b === "number" && typeof c === "function")
-      return BuildTypedSeqImpl(this, len, b, c);
-    else if (typeof b === "number")
-      ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
-    else
-      ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
   default:
     ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
   }
 }
 
 // Warning: user exposed!
 function TypedObjectArrayTypeFrom(a, b, c) {
   // Arguments: arrayLike, [depth], func
@@ -726,17 +693,17 @@ function TypedArrayReduce(a, b) {
 function TypedArrayScatter(a, b, c, d) {
   // Arguments: outputArrayType, indices, defaultValue, conflictFunction
   if (!IsObject(this) || !ObjectIsTypedObject(this))
     ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
   var thisType = TypedObjectTypeDescr(this);
   if (!TypeDescrIsArrayType(thisType))
     ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
 
-  if (!IsObject(a) || !ObjectIsTypeDescr(a) || !TypeDescrIsSizedArrayType(a))
+  if (!IsObject(a) || !ObjectIsTypeDescr(a) || !TypeDescrIsArrayType(a))
     ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
 
   if (d !== undefined && typeof d !== "function")
     ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
 
   return ScatterTypedSeqImpl(this, a, b, c, d);
 }
 
@@ -823,17 +790,17 @@ function BuildTypedSeqImpl(arrayType, le
   //    ArrayType(ArrayType(T, 4), 5)
   // and a depth of 2, we get
   //    grainType = T
   //    iterationSpace = [5, 4]
   var [iterationSpace, grainType, totalLength] =
     ComputeIterationSpace(arrayType, depth, len);
 
   // Create a zeroed instance with no data
-  var result = arrayType.variable ? new arrayType(len) : new arrayType();
+  var result = new arrayType();
 
   var indices = NewDenseArray(depth);
   for (var i = 0; i < depth; i++) {
     indices[i] = 0;
   }
 
   var grainTypeIsComplex = !TypeDescrIsSimpleType(grainType);
   var size = DESCR_SIZE(grainType);
@@ -916,21 +883,21 @@ function MapUntypedSeqImpl(inArray, outp
 
   if (!IsCallable(maybeFunc))
     ThrowError(JSMSG_NOT_FUNCTION, DecompileArg(0, maybeFunc));
   var func = maybeFunc;
 
   // Skip check for compatible iteration spaces; any normal JS array
   // is trivially compatible with any iteration space of depth 1.
 
-  var outLength = outputType.variable ? inArray.length : outputType.length;
+  var outLength = outputType.length;
   var outGrainType = outputType.elementType;
 
   // Create a zeroed instance with no data
-  var result = outputType.variable ? new outputType(inArray.length) : new outputType();
+  var result = new outputType();
 
   var outUnitSize = DESCR_SIZE(outGrainType);
   var outGrainTypeIsComplex = !TypeDescrIsSimpleType(outGrainType);
   var outOffset = 0;
 
   // Core of map computation starts here (comparable to
   // DoMapTypedSeqDepth1 and DoMapTypedSeqDepthN below).
 
@@ -970,24 +937,24 @@ function MapTypedSeqImpl(inArray, depth,
 
   // Compute iteration space for input and output and check for compatibility.
   var inputType = TypeOfTypedObject(inArray);
   var [inIterationSpace, inGrainType, _] =
     ComputeIterationSpace(inputType, depth, inArray.length);
   if (!IsObject(inGrainType) || !ObjectIsTypeDescr(inGrainType))
     ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
   var [iterationSpace, outGrainType, totalLength] =
-    ComputeIterationSpace(outputType, depth, outputType.variable ? inArray.length : outputType.length);
+    ComputeIterationSpace(outputType, depth, outputType.length);
   for (var i = 0; i < depth; i++)
     if (inIterationSpace[i] !== iterationSpace[i])
       // TypeError("Incompatible iteration space in input and output type");
       ThrowError(JSMSG_TYPEDOBJECT_ARRAYTYPE_BAD_ARGS);
 
   // Create a zeroed instance with no data
-  var result = outputType.variable ? new outputType(inArray.length) : new outputType();
+  var result = new outputType();
 
   var inGrainTypeIsComplex = !TypeDescrIsSimpleType(inGrainType);
   var outGrainTypeIsComplex = !TypeDescrIsSimpleType(outGrainType);
 
   var inOffset = 0;
   var outOffset = 0;
 
   var isDepth1Simple = depth == 1 && !(inGrainTypeIsComplex || outGrainTypeIsComplex);
@@ -1078,17 +1045,17 @@ function MapTypedParImpl(inArray, depth,
          "Map/From called on something not callable");
 
   var inArrayType = TypeOfTypedObject(inArray);
 
   if (ShouldForceSequential() ||
       depth <= 0 ||
       TO_INT32(depth) !== depth ||
       !TypeDescrIsArrayType(inArrayType) ||
-      !TypeDescrIsUnsizedArrayType(outputType))
+      !TypeDescrIsArrayType(outputType))
   {
     // defer error cases to seq implementation:
     return MapTypedSeqImpl(inArray, depth, outputType, func);
   }
 
   switch (depth) {
   case 1:
     return MapTypedParImplDepth1(inArray, inArrayType, outputType, func);
@@ -1156,17 +1123,17 @@ function MapTypedParImplDepth1(inArray, 
   const inGrainTypeSize = DESCR_SIZE(inGrainType);
   const outGrainTypeSize = DESCR_SIZE(outGrainType);
   const inGrainTypeIsComplex = !TypeDescrIsSimpleType(inGrainType);
   const outGrainTypeIsComplex = !TypeDescrIsSimpleType(outGrainType);
 
   const length = inArray.length;
   const mode = undefined;
 
-  const outArray = new outArrayType(length);
+  const outArray = new outArrayType();
   if (length === 0)
     return outArray;
 
   const outGrainTypeIsTransparent = ObjectIsTransparentTypedObject(outArray);
 
   // Construct the slices and initial pointers for each worker:
   const slicesInfo = ComputeSlicesInfo(length);
   const numWorkers = ForkJoinNumWorkers();
@@ -1302,17 +1269,17 @@ function ReduceTypedSeqImpl(array, outpu
   }
 
   return value;
 }
 
 function ScatterTypedSeqImpl(array, outputType, indices, defaultValue, conflictFunc) {
   assert(IsObject(array) && ObjectIsTypedObject(array), "Scatter called on non-object or untyped input array.");
   assert(IsObject(outputType) && ObjectIsTypeDescr(outputType), "Scatter called on non-type-object outputType");
-  assert(TypeDescrIsSizedArrayType(outputType), "Scatter called on non-sized array type");
+  assert(TypeDescrIsArrayType(outputType), "Scatter called on non-array type");
   assert(conflictFunc === undefined || typeof conflictFunc === "function", "Scatter called with invalid conflictFunc");
 
   var result = new outputType();
   var bitvec = new Uint8Array(result.length);
   var elemType = outputType.elementType;
   var i, j;
   if (defaultValue !== elemType(undefined)) {
     for (i = 0; i < result.length; i++) {
@@ -1351,16 +1318,18 @@ function FilterTypedSeqImpl(array, func)
     var v = TypedObjectGet(elementType, array, inOffset);
     if (func(v, i, array)) {
       SET_BIT(flags, i);
       count++;
     }
     inOffset += size;
   }
 
-  var resultType = (arrayType.variable ? arrayType : arrayType.unsized);
-  var result = new resultType(count);
+  var T = GetTypedObjectModule();
+
+  var resultType = new T.ArrayType(elementType, count);
+  var result = new resultType();
   for (var i = 0, j = 0; i < array.length; i++) {
     if (GET_BIT(flags, i))
       result[j++] = array[i];
   }
   return result;
 }
--- a/js/src/builtin/TypedObjectConstants.h
+++ b/js/src/builtin/TypedObjectConstants.h
@@ -22,46 +22,44 @@
 // particular kinds of type objects. For simplicity we use the same
 // number of slots no matter what kind of type descriptor we are
 // working with, even though this is mildly wasteful.
 
 // Slots on all type objects
 #define JS_DESCR_SLOT_KIND               0  // Atomized string representation
 #define JS_DESCR_SLOT_STRING_REPR        1  // Atomized string representation
 #define JS_DESCR_SLOT_ALIGNMENT          2  // Alignment in bytes
-#define JS_DESCR_SLOT_SIZE               3  // Size in bytes, if sized, else 0
+#define JS_DESCR_SLOT_SIZE               3  // Size in bytes, else 0
 #define JS_DESCR_SLOT_OPAQUE             4  // Atomized string representation
 #define JS_DESCR_SLOT_TYPROTO            5  // Prototype for instances, if any
 
 // Slots on scalars, references, and x4s
 #define JS_DESCR_SLOT_TYPE               6  // Type code
 
 // Slots on all array descriptors
 #define JS_DESCR_SLOT_ARRAY_ELEM_TYPE    6
 
-// Slots on sized array descriptors
-#define JS_DESCR_SLOT_SIZED_ARRAY_LENGTH 7
+// Slots on array descriptors
+#define JS_DESCR_SLOT_ARRAY_LENGTH 7
 
 // Slots on struct type objects
 #define JS_DESCR_SLOT_STRUCT_FIELD_NAMES 6
 #define JS_DESCR_SLOT_STRUCT_FIELD_TYPES 7
 #define JS_DESCR_SLOT_STRUCT_FIELD_OFFSETS 8
 
 // Maximum number of slots for any descriptor
 #define JS_DESCR_SLOTS                   9
 
 // These constants are for use exclusively in JS code. In C++ code,
 // prefer TypeRepresentation::Scalar etc, which allows you to
 // write a switch which will receive a warning if you omit a case.
-#define JS_TYPEREPR_UNSIZED_ARRAY_KIND  0
-#define JS_TYPEREPR_MAX_UNSIZED_KIND    0    // Unsized kinds go above here
 #define JS_TYPEREPR_SCALAR_KIND         1
 #define JS_TYPEREPR_REFERENCE_KIND      2
 #define JS_TYPEREPR_STRUCT_KIND         3
-#define JS_TYPEREPR_SIZED_ARRAY_KIND    4
+#define JS_TYPEREPR_ARRAY_KIND          4
 #define JS_TYPEREPR_SIMD_KIND           5
 
 // These constants are for use exclusively in JS code. In C++ code,
 // prefer Scalar::Int8 etc, which allows you to write a switch which will
 // receive a warning if you omit a case.
 #define JS_SCALARTYPEREPR_INT8          0
 #define JS_SCALARTYPEREPR_UINT8         1
 #define JS_SCALARTYPEREPR_INT16         2
--- a/js/src/frontend/BytecodeCompiler.cpp
+++ b/js/src/frontend/BytecodeCompiler.cpp
@@ -270,18 +270,17 @@ frontend::CompileScript(ExclusiveContext
                                     /* foldConstants = */ true,
                                     canLazilyParse ? syntaxParser.ptr() : nullptr, nullptr);
     parser.sct = sct;
     parser.ss = ss;
 
     Directives directives(options.strictOption);
     GlobalSharedContext globalsc(cx, scopeChain, directives, options.extraWarningsOption);
 
-    bool savedCallerFun = options.compileAndGo &&
-                          evalCaller && evalCaller->functionOrCallerFunction();
+    bool savedCallerFun = evalCaller && evalCaller->functionOrCallerFunction();
     Rooted<JSScript*> script(cx, JSScript::Create(cx, NullPtr(), savedCallerFun,
                                                   options, staticLevel, sourceObject, 0,
                                                   srcBuf.length()));
     if (!script)
         return nullptr;
 
     // We can specialize a bit for the given scope chain if that scope chain is the global object.
     JSObject *globalScope =
@@ -307,17 +306,17 @@ frontend::CompileScript(ExclusiveContext
                /* blockScopeDepth = */ 0);
     if (!pc->init(parser.tokenStream))
         return nullptr;
 
     /* If this is a direct call to eval, inherit the caller's strictness.  */
     if (evalCaller && evalCaller->strict())
         globalsc.strict = true;
 
-    if (options.compileAndGo && evalCaller && evalCaller->functionOrCallerFunction()) {
+    if (savedCallerFun) {
         /*
          * An eval script in a caller frame needs to have its enclosing
          * function captured in case it refers to an upvar, and someone
          * wishes to decompile it while it's running.
          */
         JSFunction *fun = evalCaller->functionOrCallerFunction();
         Directives directives(/* strict = */ fun->strict());
         ObjectBox *funbox = parser.newFunctionBox(/* fn = */ nullptr, fun, pc.ptr(),
--- a/js/src/gc/Nursery.cpp
+++ b/js/src/gc/Nursery.cpp
@@ -399,21 +399,19 @@ GetObjectAllocKindForCopy(const Nursery 
         // Figure out the size of this object, from the prototype's TypeDescr.
         // The objects we are traversing here are all tenured, so we don't need
         // to check forwarding pointers.
         TypeDescr *descr = &obj->as<InlineTypedObject>().typeDescr();
         MOZ_ASSERT(!IsInsideNursery(descr));
         return InlineTypedObject::allocKindForTypeDescriptor(descr);
     }
 
-    // Outline typed objects have special requirements for their allocation kind.
-    if (obj->is<OutlineTypedObject>()) {
-        TypeDescr *descr = &obj->as<OutlineTypedObject>().typeDescr();
-        return OutlineTypedObject::allocKindForTypeDescriptor(descr);
-    }
+    // Outline typed objects use the minimum allocation kind.
+    if (obj->is<OutlineTypedObject>())
+        return FINALIZE_OBJECT0;
 
     // The only non-native objects in existence are proxies and typed objects.
     MOZ_ASSERT(obj->isNative());
 
     AllocKind kind = GetGCObjectFixedSlotsKind(obj->as<NativeObject>().numFixedSlots());
     MOZ_ASSERT(!IsBackgroundFinalized(kind));
     MOZ_ASSERT(CanBeFinalizedInBackground(kind, obj->getClass()));
     return GetBackgroundAllocKind(kind);
--- a/js/src/jit-test/tests/TypedObject/Bug981650.js
+++ b/js/src/jit-test/tests/TypedObject/Bug981650.js
@@ -1,10 +1,9 @@
-// Fuzz bug 981650: Test creating an unsized array type based on an instance of
+// Fuzz bug 981650: Test creating an array type based on an instance of
 // that same type.
 
 if (typeof TypedObject === "undefined")
   quit();
 
 var T = TypedObject;
-var AT = new T.ArrayType(T.int32);
-var v = new AT(10);
-new AT(v);
+var v = new T.ArrayType(T.int32, 10);
+new v(v);
--- a/js/src/jit-test/tests/TypedObject/atopneuteredbuffer.js
+++ b/js/src/jit-test/tests/TypedObject/atopneuteredbuffer.js
@@ -4,21 +4,21 @@
 if (typeof TypedObject === "undefined")
   quit();
 
 load(libdir + "asserts.js")
 
 var {StructType, uint32, Object, Any, storage, objectType} = TypedObject;
 
 function main(variant) { // once a C programmer, always a C programmer.
-  var Uints = uint32.array();
+  var Uints = uint32.array(0);
   var Unit = new StructType({});   // Empty struct type
   var buffer = new ArrayBuffer(0); // Empty buffer
   var p = new Unit(buffer);        // OK
   neuter(buffer, variant);
   assertThrowsInstanceOf(() => new Unit(buffer), TypeError,
                          "Able to instantiate atop neutered buffer");
-  assertThrowsInstanceOf(() => new Uints(buffer, 0), TypeError,
+  assertThrowsInstanceOf(() => new Uints(buffer), TypeError,
                          "Able to instantiate atop neutered buffer");
 }
 
 main("same-data");
 main("change-data");
--- a/js/src/jit-test/tests/TypedObject/bug950458.js
+++ b/js/src/jit-test/tests/TypedObject/bug950458.js
@@ -8,16 +8,16 @@ if (!this.hasOwnProperty("TypedObject"))
 // with an empty type set, which would then fail sanity
 // checking assertions.
 //
 // Public domain.
 
 var N = 100;
 var T = TypedObject;
 var Point = new T.StructType({x: T.uint32, y: T.uint32, z: T.uint32});
-var PointArray = Point.array();
+var PointArray = Point.array(N);
 function foo(arr) {
   var sum = 0;
   for (var i = 0; i < N; i++) {
     sum += arr[i].x + arr[i].y + arr[i].z;
   }
 }
-foo(new PointArray(N));
+foo(new PointArray());
--- a/js/src/jit-test/tests/TypedObject/bug953111.js
+++ b/js/src/jit-test/tests/TypedObject/bug953111.js
@@ -3,16 +3,16 @@
  * http://creativecommons.org/licenses/publicdomain/
  */
 
 if (!this.hasOwnProperty("TypedObject"))
   quit();
 
 // bug 953111
 
-var A = TypedObject.uint8.array();
-var a = new A(0);
+var A = TypedObject.uint8.array(0);
+var a = new A();
 a.forEach(function(val, i) {});
 
 // bug 951356 (dup, but a dup that is more likely to crash)
 
-var AA = TypedObject.uint8.array(2147483647).array();
-var aa = new AA(0);
+var AA = TypedObject.uint8.array(2147483647).array(0);
+var aa = new AA();
--- a/js/src/jit-test/tests/TypedObject/jit-read-unsized.js
+++ b/js/src/jit-test/tests/TypedObject/jit-read-unsized.js
@@ -6,26 +6,26 @@
 if (!this.hasOwnProperty("TypedObject"))
   quit();
 
 setJitCompilerOption("ion.warmup.trigger", 30);
 
 var N = 100;
 var T = TypedObject;
 var Point = new T.StructType({x: T.uint32, y: T.uint32, z: T.uint32});
-var PointArray = Point.array();
+var PointArray = Point.array(N);
 
 function bar(array, i, x, y, z) {
   assertEq(array[i].x, x);
   assertEq(array[i].y, y);
   assertEq(array[i].z, z);
 }
 
 function foo() {
-  var array = new PointArray(N);
+  var array = new PointArray();
   for (var i = 0; i < N; i++) {
     array[i].x = i + 0;
     array[i].y = i + 1;
     array[i].z = i + 2;
   }
 
   // get it primed up..
   for (var i = 0; i < N; i++)
--- a/js/src/jit-test/tests/TypedObject/neutertypedobjunsizedarray.js
+++ b/js/src/jit-test/tests/TypedObject/neutertypedobjunsizedarray.js
@@ -1,24 +1,24 @@
 // Test the case where we neuter an instance of a variable-length array.
 // Here we can fold the neuter check into the bounds check.
 
 if (!this.hasOwnProperty("TypedObject"))
   quit();
 
 var {StructType, uint32, storage} = TypedObject;
 var S = new StructType({f: uint32, g: uint32});
-var A = S.array();
+var A = S.array(10);
 
 function readFrom(a) {
   return a[2].f + a[2].g;
 }
 
 function main(variant) {
-  var a = new A(10);
+  var a = new A();
   a[2].f = 22;
   a[2].g = 44;
 
   for (var i = 0; i < 10; i++)
     assertEq(readFrom(a), 66);
 
   neuter(storage(a).buffer, variant);
 
--- a/js/src/jit-test/tests/TypedObject/opaqueatopbuffer.js
+++ b/js/src/jit-test/tests/TypedObject/opaqueatopbuffer.js
@@ -9,16 +9,11 @@ var {StructType, ArrayType, uint32, Obje
 var anArray = new Uint32Array(100);
 anArray[0] = 22;
 var buffer = anArray.buffer;
 
 var Unit = new StructType(({ f : Object, } ));
 assertThrowsInstanceOf(() => new Unit(buffer), TypeError,
                        "Able to instantiate opaque type atop buffer");
 
-var Units = new ArrayType(Unit);
+var Units = new ArrayType(Unit, 2);
 assertThrowsInstanceOf(() => new Units(buffer), TypeError,
                        "Able to instantiate opaque type atop buffer");
-
-var Units2 = Units.dimension(2);
-assertThrowsInstanceOf(() => new Units2(buffer), TypeError,
-                       "Able to instantiate opaque type atop buffer");
-
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/onNewScript-CloneAndExecuteScript.js
@@ -0,0 +1,28 @@
+// Debugger should be notified of scripts created with cloneAndExecuteScript.
+
+var g = newGlobal();
+var g2 = newGlobal();
+var dbg = new Debugger(g, g2);
+var log = '';
+
+dbg.onNewScript = function (evalScript) {
+  log += 'e';
+
+  dbg.onNewScript = function (clonedScript) {
+    log += 'c';
+    clonedScript.setBreakpoint(0, {
+      hit(frame) {
+        log += 'b';
+        assertEq(frame.script, clonedScript);
+      }
+    });
+  };
+};
+
+dbg.onDebuggerStatement = function (frame) {
+  log += 'd';
+};
+
+assertEq(log, '');
+g.cloneAndExecuteScript("debugger; // nee", g2);
+assertEq(log, 'ecbd');
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/onNewScript-ExecuteInGlobalAndReturnScope.js
@@ -0,0 +1,28 @@
+// Debugger should be notified of scripts created with ExecuteInGlobalAndReturnScope.
+
+var g = newGlobal();
+var g2 = newGlobal();
+var dbg = new Debugger(g, g2);
+var log = '';
+
+dbg.onNewScript = function (evalScript) {
+  log += 'e';
+
+  dbg.onNewScript = function (clonedScript) {
+    log += 'c';
+    clonedScript.setBreakpoint(0, {
+      hit(frame) {
+        log += 'b';
+        assertEq(frame.script, clonedScript);
+      }
+    });
+  };
+};
+
+dbg.onDebuggerStatement = function (frame) {
+  log += 'd';
+};
+
+assertEq(log, '');
+var evalScope = g.evalReturningScope("debugger; // nee", g2);
+assertEq(log, 'ecbd');
--- a/js/src/jit-test/tests/gc/bug-948423.js
+++ b/js/src/jit-test/tests/gc/bug-948423.js
@@ -3,22 +3,21 @@ if (!this.hasOwnProperty("TypedObject"))
 
 var ArrayType = TypedObject.ArrayType;
 var StructType = TypedObject.StructType;
 var uint8 = TypedObject.uint8;
 var uint32 = TypedObject.uint32;
 var ObjectType = TypedObject.Object;
 function runTests() {
   (function DimensionLinkedToUndimension() {
-    var UintsA = uint32.array();
-    var FiveUintsA = UintsA.dimension(5);
+    var FiveUintsA = uint32.array(5);
     var FiveUintsB = uint32.array(5);
     assertEq(true, 
 	FiveUintsA.equivalent(FiveUintsB)
 	);
   })();
   (function PrototypeHierarchy() {
     schedulegc(3);
-    var Uint8s = uint8.array();
+    var Uint8s = uint8.array(5);
   })();
 }
 
 runTests();
--- a/js/src/jit-test/tests/ion/inlining/TypedObject-TypeDescrIsArrayType-unknown.js
+++ b/js/src/jit-test/tests/ion/inlining/TypedObject-TypeDescrIsArrayType-unknown.js
@@ -24,24 +24,24 @@
  */
 
 if (!this.TypedObject) {
     print("No TypedObject, skipping");
     quit();
 }
 
 var T = TypedObject;
-var AT = new T.ArrayType(T.int32);
+var AT = new T.ArrayType(T.int32, 100);
 
 function check(v) {
     return v.map(x => x+1);
 }
 
 function test() {
-    var w1 = AT.build(100, x => x+1);
+    var w1 = AT.build(x => x+1);
     var w2 = Array.build(100, x => x+1);
     w2.map = w1.map;
     var a = [ w1, w2 ];
     for ( var i=0 ; i < 2000 ; i++ )
 	try { a[i%2] = check(a[i%2]); } catch (e) { assertEq( i%2, 1 ); }
     return a[0];
 }
 
--- a/js/src/jit-test/tests/ion/inlining/TypedObject-TypeDescrIsArrayType.js
+++ b/js/src/jit-test/tests/ion/inlining/TypedObject-TypeDescrIsArrayType.js
@@ -20,24 +20,24 @@
  */
 
 if (!this.TypedObject) {
     print("No TypedObject, skipping");
     quit();
 }
 
 var T = TypedObject;
-var AT = new T.ArrayType(T.int32);
+var AT = new T.ArrayType(T.int32, 100);
 
 function check(v) {
     return v.map(x => x+1);
 }
 
 function test() {
-    var w = new AT(100);
+    var w = new AT();
     for ( var i=0 ; i < 1000 ; i++ )
 	w = check(w);
     return w;
 }
 
 var w = test();
 assertEq(w.length, 100);
 assertEq(w[99], 1000);
--- a/js/src/jit-test/tests/ion/inlining/TypedObject-TypeDescrIsSimpleType.js
+++ b/js/src/jit-test/tests/ion/inlining/TypedObject-TypeDescrIsSimpleType.js
@@ -18,20 +18,20 @@
  */
 
 if (!this.TypedObject) {
     print("No TypedObject, skipping");
     quit();
 }
 
 var T = TypedObject;
-var AT = new T.ArrayType(T.uint32);
+var AT = new T.ArrayType(T.uint32, 100);
 
 function check() {
-    return AT.build(100, x => x+1);
+    return AT.build(x => x+1);
 }
 
 function test() {
     var w;
     for ( var i=0 ; i < 100 ; i++ )
 	w = check();
     return w;
 }
--- a/js/src/jit-test/tests/ion/inlining/TypedObject-TypeDescrIsSizedArrayType.js
+++ b/js/src/jit-test/tests/ion/inlining/TypedObject-TypeDescrIsSizedArrayType.js
@@ -16,27 +16,26 @@
  */
 
 if (!this.TypedObject) {
     print("No TypedObject, skipping");
     quit();
 }
 
 var T = TypedObject;
-var AT = new T.ArrayType(T.int32);
-var IT = AT.dimension(100);
-var ix = AT.build(100, x => x == 0 ? 99 : x-1);  // [99, 0, 1, ..., 98]
+var IT = new T.ArrayType(T.int32, 100);
+var ix = IT.build(x => x == 0 ? 99 : x-1);  // [99, 0, 1, ..., 98]
 
 // This is a left-rotate by one place
 function check(v) {
     return v.scatter(IT, ix);
 }
 
 function test() {
-    var w = AT.build(100, x => x);
+    var w = IT.build(x => x);
     for ( var i=0 ; i < 77 ; i++ )
 	w = check(w);
     return w;
 }
 
 w = test();
 assertEq(w.length, 100);
 assertEq(w[0], 77);
--- a/js/src/jit-test/tests/ion/inlining/TypedObject-storage-opaque.js
+++ b/js/src/jit-test/tests/ion/inlining/TypedObject-storage-opaque.js
@@ -22,15 +22,15 @@ if (!this.TypedObject)
 var T = TypedObject;
 
 function check(v) {
     return T.storage(v);
 }
 
 function test() {
     var AT = new T.ArrayType(T.Any,10);
-    var v = new AT(10);
+    var v = new AT();
     for ( var i=0 ; i < 1000 ; i++ )
         check(v);
     return check(v);
 }
 
 test();
--- a/js/src/jit-test/tests/ion/inlining/TypedObject-storage-transparent.js
+++ b/js/src/jit-test/tests/ion/inlining/TypedObject-storage-transparent.js
@@ -21,16 +21,16 @@ if (!this.TypedObject)
 
 var T = TypedObject;
 
 function check(v) {
     return T.storage(v);
 }
 
 function test() {
-    var AT = new T.ArrayType(T.int32,10);
-    var v = new AT(10);
+    var AT = new T.ArrayType(T.int32, 10);
+    var v = new AT();
     for ( var i=0 ; i < 1000 ; i++ )
         check(v);
     return check(v);
 }
 
 test();
--- a/js/src/jit-test/tests/ion/inlining/TypedObject-storage-unknown.js
+++ b/js/src/jit-test/tests/ion/inlining/TypedObject-storage-unknown.js
@@ -24,16 +24,16 @@ var T = TypedObject;
 
 function check(v) {
     return T.storage(v);
 }
 
 function test() {
     var AT = new T.ArrayType(T.int32,10);
     var v = new Object;         // Not actually a typed object
-    var w = new AT(10);         // Actually a typed object
+    var w = new AT();           // Actually a typed object
     var a = [v,w];
     for ( var i=0 ; i < 1000 ; i++ )
         try { check(a[i%2]); } catch (e) {}
     try { return check(a[1]); } catch (e) {}
 }
 
 test();
--- a/js/src/jit-test/tests/parallel/TypedObj-fromPar-outpointer-struct.js
+++ b/js/src/jit-test/tests/parallel/TypedObj-fromPar-outpointer-struct.js
@@ -12,17 +12,17 @@ function test() {
   var L = minItemsTestingThreshold;
 
   var Matrix = uint32.array(L, 2);
   var matrix = new Matrix();
   for (var i = 0; i < L; i++)
     matrix[i][0] = i;
 
   var Point = new StructType({x: uint32, y: uint32});
-  var Points = Point.array();
+  var Points = Point.array(L);
 
   assertParallelExecSucceeds(
     // FIXME Bug 983692 -- no where to pass `m` to
     function(m) Points.fromPar(matrix, function(p, i, c, out) { out.y = p[0]; }),
     function(points) {
       for (var i = 0; i < L; i++) {
         assertEq(matrix[i][0], i);
         assertEq(matrix[i][1], 0);
--- a/js/src/jit-test/tests/parallel/TypedObj-fromPar-return-scalar.js
+++ b/js/src/jit-test/tests/parallel/TypedObj-fromPar-return-scalar.js
@@ -5,17 +5,17 @@ if (!getBuildConfiguration().parallelJS)
 
 load(libdir + "parallelarray-helpers.js")
 
 var { uint8, uint32 } = TypedObject;
 
 function test() {
   var L = minItemsTestingThreshold;
   var Uints = uint32.array(L);
-  var Uint8s = uint8.array();
+  var Uint8s = uint8.array(L);
 
   var uint32s = new Uints();
 
   assertParallelExecSucceeds(
     // FIXME Bug 983692 -- no where to pass `m` to
     function(m) Uint8s.fromPar(uint32s, function(e) e + 1),
     function(uint8s) {
       for (var i = 0; i < L; i++)
--- a/js/src/jit-test/tests/parallel/TypedObj-mapPar-outpointer-struct.js
+++ b/js/src/jit-test/tests/parallel/TypedObj-mapPar-outpointer-struct.js
@@ -6,18 +6,18 @@ if (!this.hasOwnProperty("TypedObject"))
 
 load(libdir + "parallelarray-helpers.js")
 
 var { ArrayType, StructType, uint32 } = TypedObject;
 
 function test() {
   var L = minItemsTestingThreshold;
   var Point = new StructType({x: uint32, y: uint32});
-  var Points = Point.array();
-  var points = new Points(L);
+  var Points = Point.array(L);
+  var points = new Points();
   for (var i = 0; i < L; i++)
     points[i].x = i;
 
   assertParallelExecSucceeds(
     // FIXME Bug 983692 -- no where to pass `m` to
     function(m) points.mapPar(function(p, i, c, out) { out.y = p.x; }),
     function(points2) {
       for (var i = 0; i < L; i++) {
--- a/js/src/jit-test/tests/parallel/bug977647.js
+++ b/js/src/jit-test/tests/parallel/bug977647.js
@@ -1,12 +1,12 @@
 // Check for mapPar() applied to an empty array.
 // Public domain.
 
 if (!this.hasOwnProperty("TypedObject"))
   quit();
 
 var { ArrayType, StructType, uint32 } = TypedObject;
 var Point = new StructType({x: uint32, y: uint32});
-var Points = Point.array();
+var Points = Point.array(0);
 var points = new Points();
 points.mapPar(function() {});
 
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -8602,17 +8602,17 @@ GetTemplateObjectForNative(JSContext *cx
 
     return true;
 }
 
 static bool
 GetTemplateObjectForClassHook(JSContext *cx, JSNative hook, CallArgs &args,
                               MutableHandleObject templateObject)
 {
-    if (hook == TypedObject::constructSized) {
+    if (hook == TypedObject::construct) {
         Rooted<TypeDescr *> descr(cx, &args.callee().as<TypeDescr>());
         JSObject *obj = TypedObject::createZeroed(cx, descr, 1, gc::TenuredHeap);
         if (!obj)
             return false;
         templateObject.set(obj);
         return true;
     }
 
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -5093,26 +5093,16 @@ CodeGenerator::visitTypedObjectProto(LTy
     const Register tempReg = ToRegister(lir->temp());
     masm.setupUnalignedABICall(1, tempReg);
     masm.passABIArg(obj);
     masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, TypedObjectProto));
     return true;
 }
 
 bool
-CodeGenerator::visitTypedObjectUnsizedLength(LTypedObjectUnsizedLength *lir)
-{
-    Register obj = ToRegister(lir->object());
-    Register out = ToRegister(lir->output());
-
-    masm.load32(Address(obj, OutlineTypedObject::offsetOfUnsizedLength()), out);
-    return true;
-}
-
-bool
 CodeGenerator::visitTypedObjectElements(LTypedObjectElements *lir)
 {
     Register obj = ToRegister(lir->object());
     Register out = ToRegister(lir->output());
 
     Label inlineObject, done;
     masm.loadObjClass(obj, out);
     masm.branchPtr(Assembler::Equal, out, ImmPtr(&InlineOpaqueTypedObject::class_), &inlineObject);
--- a/js/src/jit/CodeGenerator.h
+++ b/js/src/jit/CodeGenerator.h
@@ -181,17 +181,16 @@ class CodeGenerator : public CodeGenerat
     bool visitLoadArrowThis(LLoadArrowThis *lir);
     bool visitArrayLength(LArrayLength *lir);
     bool visitSetArrayLength(LSetArrayLength *lir);
     bool visitTypedArrayLength(LTypedArrayLength *lir);
     bool visitTypedArrayElements(LTypedArrayElements *lir);
     bool visitTypedObjectElements(LTypedObjectElements *lir);
     bool visitSetTypedObjectOffset(LSetTypedObjectOffset *lir);
     bool visitTypedObjectProto(LTypedObjectProto *ins);
-    bool visitTypedObjectUnsizedLength(LTypedObjectUnsizedLength *ins);
     bool visitStringLength(LStringLength *lir);
     bool visitInitializedLength(LInitializedLength *lir);
     bool visitSetInitializedLength(LSetInitializedLength *lir);
     bool visitNotO(LNotO *ins);
     bool visitNotV(LNotV *ins);
     bool visitBoundsCheck(LBoundsCheck *lir);
     bool visitBoundsCheckRange(LBoundsCheckRange *lir);
     bool visitBoundsCheckLower(LBoundsCheckLower *lir);
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -7230,29 +7230,27 @@ IonBuilder::getElemTryTypedObject(bool *
 
     if (!objPrediction.ofArrayKind())
         return true;
 
     TypedObjectPrediction elemPrediction = objPrediction.arrayElementType();
     if (elemPrediction.isUseless())
         return true;
 
-    MOZ_ASSERT(TypeDescr::isSized(elemPrediction.kind()));
-
     int32_t elemSize;
     if (!elemPrediction.hasKnownSize(&elemSize))
         return true;
 
     switch (elemPrediction.kind()) {
       case type::Simd:
         // FIXME (bug 894105): load into a MIRType_float32x4 etc
         return true;
 
       case type::Struct:
-      case type::SizedArray:
+      case type::Array:
         return getElemTryComplexElemOfTypedObject(emitted,
                                                   obj,
                                                   index,
                                                   objPrediction,
                                                   elemPrediction,
                                                   elemSize);
       case type::Scalar:
         return getElemTryScalarElemOfTypedObject(emitted,
@@ -7263,19 +7261,16 @@ IonBuilder::getElemTryTypedObject(bool *
                                                  elemSize);
 
       case type::Reference:
         return getElemTryReferenceElemOfTypedObject(emitted,
                                                     obj,
                                                     index,
                                                     objPrediction,
                                                     elemPrediction);
-
-      case type::UnsizedArray:
-        MOZ_CRASH("Unsized arrays cannot be element types");
     }
 
     MOZ_CRASH("Bad kind");
 }
 
 static MIRType
 MIRTypeForTypedArrayRead(Scalar::Type arrayType, bool observedDouble);
 
@@ -7299,22 +7294,16 @@ IonBuilder::checkTypedObjectIndexInBound
     if (objPrediction.hasKnownArrayLength(&lenOfAll)) {
         length = constantInt(lenOfAll);
 
         // If we are not loading the length from the object itself, only
         // optimize if the array buffer can't have been neutered.
         types::TypeObjectKey *globalType = types::TypeObjectKey::get(&script()->global());
         if (globalType->hasFlags(constraints(), types::OBJECT_FLAG_TYPED_OBJECT_NEUTERED))
             return false;
-    } else if (objPrediction.kind() == type::UnsizedArray) {
-        // Note: unsized arrays will have their length set to zero if they are
-        // neutered, so we don't need to make sure that no neutering has
-        // occurred which affects this object.
-        length = MTypedObjectUnsizedLength::New(alloc(), obj);
-        current->add(length->toInstruction());
     } else {
         return false;
     }
 
     index = addBoundsCheck(idInt32, length);
 
     // Since we passed the bounds check, it is impossible for the
     // result of multiplication to overflow; so enable imul path.
@@ -8197,18 +8186,16 @@ IonBuilder::setElemTryTypedObject(bool *
 
     if (!objPrediction.ofArrayKind())
         return true;
 
     TypedObjectPrediction elemPrediction = objPrediction.arrayElementType();
     if (elemPrediction.isUseless())
         return true;
 
-    MOZ_ASSERT(TypeDescr::isSized(elemPrediction.kind()));
-
     int32_t elemSize;
     if (!elemPrediction.hasKnownSize(&elemSize))
         return true;
 
     switch (elemPrediction.kind()) {
       case type::Simd:
         // FIXME (bug 894105): store a MIRType_float32x4 etc
         return true;
@@ -8222,18 +8209,17 @@ IonBuilder::setElemTryTypedObject(bool *
                                                  obj,
                                                  index,
                                                  objPrediction,
                                                  value,
                                                  elemPrediction,
                                                  elemSize);
 
       case type::Struct:
-      case type::SizedArray:
-      case type::UnsizedArray:
+      case type::Array:
         // Not yet optimized.
         return true;
     }
 
     MOZ_CRASH("Bad kind");
 }
 
 bool
@@ -8715,18 +8701,16 @@ IonBuilder::jsop_length_fastPath()
             if (globalType->hasFlags(constraints(), types::OBJECT_FLAG_TYPED_OBJECT_NEUTERED))
                 return false;
 
             MInstruction *length;
             int32_t sizedLength;
             if (prediction.hasKnownArrayLength(&sizedLength)) {
                 obj->setImplicitlyUsedUnchecked();
                 length = MConstant::New(alloc(), Int32Value(sizedLength));
-            } else if (prediction.kind() == type::UnsizedArray) {
-                length = MTypedObjectUnsizedLength::New(alloc(), obj);
             } else {
                 return false;
             }
 
             current->pop();
             current->add(length);
             current->push(length);
             return true;
@@ -9444,17 +9428,17 @@ IonBuilder::getPropTryTypedObject(bool *
         return true;
 
     switch (fieldPrediction.kind()) {
       case type::Simd:
         // FIXME (bug 894104): load into a MIRType_float32x4 etc
         return true;
 
       case type::Struct:
-      case type::SizedArray:
+      case type::Array:
         return getPropTryComplexPropOfTypedObject(emitted,
                                                   obj,
                                                   fieldOffset,
                                                   fieldPrediction,
                                                   fieldIndex,
                                                   resultTypes);
 
       case type::Reference:
@@ -9465,19 +9449,16 @@ IonBuilder::getPropTryTypedObject(bool *
                                                     resultTypes);
 
       case type::Scalar:
         return getPropTryScalarPropOfTypedObject(emitted,
                                                  obj,
                                                  fieldOffset,
                                                  fieldPrediction,
                                                  resultTypes);
-
-      case type::UnsizedArray:
-        MOZ_CRASH("Field of unsized array type");
     }
 
     MOZ_CRASH("Bad kind");
 }
 
 bool
 IonBuilder::getPropTryScalarPropOfTypedObject(bool *emitted, MDefinition *typedObj,
                                               int32_t fieldOffset,
@@ -10161,18 +10142,17 @@ IonBuilder::setPropTryTypedObject(bool *
         return setPropTryReferencePropOfTypedObject(emitted, obj, fieldOffset,
                                                     value, fieldPrediction);
 
       case type::Scalar:
         return setPropTryScalarPropOfTypedObject(emitted, obj, fieldOffset,
                                                  value, fieldPrediction);
 
       case type::Struct:
-      case type::SizedArray:
-      case type::UnsizedArray:
+      case type::Array:
         return true;
     }
 
     MOZ_CRASH("Unknown kind");
 }
 
 bool
 IonBuilder::setPropTryReferencePropOfTypedObject(bool *emitted,
--- a/js/src/jit/IonBuilder.h
+++ b/js/src/jit/IonBuilder.h
@@ -772,17 +772,17 @@ class IonBuilder
     // ForkJoin intrinsics
     InliningStatus inlineForkJoinGetSlice(CallInfo &callInfo);
 
     // TypedObject intrinsics and natives.
     InliningStatus inlineObjectIsTypeDescr(CallInfo &callInfo);
     InliningStatus inlineSetTypedObjectOffset(CallInfo &callInfo);
     bool elementAccessIsTypedObjectArrayOfScalarType(MDefinition* obj, MDefinition* id,
                                                      ScalarTypeDescr::Type *arrayType);
-    InliningStatus inlineConstructTypedObject(CallInfo &callInfo, SizedTypeDescr *target);
+    InliningStatus inlineConstructTypedObject(CallInfo &callInfo, TypeDescr *target);
 
     // Utility intrinsics.
     InliningStatus inlineIsCallable(CallInfo &callInfo);
     InliningStatus inlineIsObject(CallInfo &callInfo);
     InliningStatus inlineHaveSameClass(CallInfo &callInfo);
     InliningStatus inlineToObject(CallInfo &callInfo);
     InliningStatus inlineToInteger(CallInfo &callInfo);
     InliningStatus inlineToString(CallInfo &callInfo);
--- a/js/src/jit/LIR-Common.h
+++ b/js/src/jit/LIR-Common.h
@@ -4226,30 +4226,16 @@ class LTypedObjectProto : public LCallIn
     const LAllocation *object() {
         return getOperand(0);
     }
     const LDefinition *temp() {
         return getTemp(0);
     }
 };
 
-// Load an unsized typed object's length.
-class LTypedObjectUnsizedLength : public LInstructionHelper<1, 1, 0>
-{
-  public:
-    LIR_HEADER(TypedObjectUnsizedLength)
-
-    explicit LTypedObjectUnsizedLength(const LAllocation &object) {
-        setOperand(0, object);
-    }
-    const LAllocation *object() {
-        return getOperand(0);
-    }
-};
-
 // Load a typed object's elements vector.
 class LTypedObjectElements : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(TypedObjectElements)
 
     explicit LTypedObjectElements(const LAllocation &object) {
         setOperand(0, object);
--- a/js/src/jit/LOpcodes.h
+++ b/js/src/jit/LOpcodes.h
@@ -279,17 +279,16 @@
     _(IteratorMore)                 \
     _(IsNoIterAndBranch)            \
     _(IteratorEnd)                  \
     _(ArrayLength)                  \
     _(SetArrayLength)               \
     _(TypedArrayLength)             \
     _(TypedArrayElements)           \
     _(TypedObjectProto)             \
-    _(TypedObjectUnsizedLength)     \
     _(TypedObjectElements)          \
     _(SetTypedObjectOffset)         \
     _(StringLength)                 \
     _(ArgumentsLength)              \
     _(GetFrameArgument)             \
     _(SetFrameArgumentT)            \
     _(SetFrameArgumentC)            \
     _(SetFrameArgumentV)            \
--- a/js/src/jit/Lowering.cpp
+++ b/js/src/jit/Lowering.cpp
@@ -2518,23 +2518,16 @@ LIRGenerator::visitTypedObjectProto(MTyp
     MOZ_ASSERT(ins->type() == MIRType_Object);
     return defineReturn(new(alloc()) LTypedObjectProto(
                             useFixed(ins->object(), CallTempReg0),
                             tempFixed(CallTempReg1)),
                         ins);
 }
 
 bool
-LIRGenerator::visitTypedObjectUnsizedLength(MTypedObjectUnsizedLength *ins)
-{
-    MOZ_ASSERT(ins->type() == MIRType_Int32);
-    return define(new(alloc()) LTypedObjectUnsizedLength(useRegisterAtStart(ins->object())), ins);
-}
-
-bool
 LIRGenerator::visitTypedObjectElements(MTypedObjectElements *ins)
 {
     MOZ_ASSERT(ins->type() == MIRType_Elements);
     return define(new(alloc()) LTypedObjectElements(useRegister(ins->object())), ins);
 }
 
 bool
 LIRGenerator::visitSetTypedObjectOffset(MSetTypedObjectOffset *ins)
--- a/js/src/jit/Lowering.h
+++ b/js/src/jit/Lowering.h
@@ -187,17 +187,16 @@ class LIRGenerator : public LIRGenerator
     bool visitPostWriteBarrier(MPostWriteBarrier *ins);
     bool visitArrayLength(MArrayLength *ins);
     bool visitSetArrayLength(MSetArrayLength *ins);
     bool visitTypedArrayLength(MTypedArrayLength *ins);
     bool visitTypedArrayElements(MTypedArrayElements *ins);
     bool visitTypedObjectElements(MTypedObjectElements *ins);
     bool visitSetTypedObjectOffset(MSetTypedObjectOffset *ins);
     bool visitTypedObjectProto(MTypedObjectProto *ins);
-    bool visitTypedObjectUnsizedLength(MTypedObjectUnsizedLength *ins);
     bool visitInitializedLength(MInitializedLength *ins);
     bool visitSetInitializedLength(MSetInitializedLength *ins);
     bool visitNot(MNot *ins);
     bool visitBoundsCheck(MBoundsCheck *ins);
     bool visitBoundsCheckLower(MBoundsCheckLower *ins);
     bool visitLoadElement(MLoadElement *ins);
     bool visitLoadElementHole(MLoadElementHole *ins);
     bool visitLoadUnboxedObjectOrNull(MLoadUnboxedObjectOrNull *ins);
--- a/js/src/jit/MCallOptimize.cpp
+++ b/js/src/jit/MCallOptimize.cpp
@@ -214,22 +214,17 @@ IonBuilder::inlineNativeCall(CallInfo &c
                               &OutlineOpaqueTypedObject::class_,
                               &InlineOpaqueTypedObject::class_);
     if (native == intrinsic_ObjectIsTypeDescr)
         return inlineObjectIsTypeDescr(callInfo);
     if (native == intrinsic_TypeDescrIsSimpleType)
         return inlineHasClass(callInfo,
                               &ScalarTypeDescr::class_, &ReferenceTypeDescr::class_);
     if (native == intrinsic_TypeDescrIsArrayType)
-        return inlineHasClass(callInfo,
-                              &SizedArrayTypeDescr::class_, &UnsizedArrayTypeDescr::class_);
-    if (native == intrinsic_TypeDescrIsSizedArrayType)
-        return inlineHasClass(callInfo, &SizedArrayTypeDescr::class_);
-    if (native == intrinsic_TypeDescrIsUnsizedArrayType)
-        return inlineHasClass(callInfo, &UnsizedArrayTypeDescr::class_);
+        return inlineHasClass(callInfo, &ArrayTypeDescr::class_);
     if (native == intrinsic_SetTypedObjectOffset)
         return inlineSetTypedObjectOffset(callInfo);
 
     // Testing Functions
     if (native == testingFunc_inParallelSection)
         return inlineForceSequentialOrInParallelSection(callInfo);
     if (native == testingFunc_bailout)
         return inlineBailout(callInfo);
@@ -281,18 +276,18 @@ IonBuilder::inlineNativeGetter(CallInfo 
 }
 
 IonBuilder::InliningStatus
 IonBuilder::inlineNonFunctionCall(CallInfo &callInfo, JSObject *target)
 {
     // Inline a call to a non-function object, invoking the object's call or
     // construct hook.
 
-    if (callInfo.constructing() && target->constructHook() == TypedObject::constructSized)
-        return inlineConstructTypedObject(callInfo, &target->as<SizedTypeDescr>());
+    if (callInfo.constructing() && target->constructHook() == TypedObject::construct)
+        return inlineConstructTypedObject(callInfo, &target->as<TypeDescr>());
 
     return InliningStatus_NotInlined;
 }
 
 types::TemporaryTypeSet *
 IonBuilder::getInlineReturnTypeSet()
 {
     return bytecodeTypes(pc);
@@ -1647,17 +1642,16 @@ IonBuilder::elementAccessIsTypedObjectAr
     TypedObjectPrediction prediction = typedObjectPrediction(obj);
     if (prediction.isUseless() || !prediction.ofArrayKind())
         return false;
 
     TypedObjectPrediction elemPrediction = prediction.arrayElementType();
     if (elemPrediction.isUseless() || elemPrediction.kind() != type::Scalar)
         return false;
 
-    MOZ_ASSERT(type::isSized(elemPrediction.kind()));
     *arrayType = elemPrediction.scalarType();
     return true;
 }
 
 bool
 IonBuilder::inlineUnsafeSetDenseArrayElement(CallInfo &callInfo, uint32_t base)
 {
     // Note: we do not check the conditions that are asserted as true
@@ -2514,17 +2508,17 @@ IonBuilder::inlineIsConstructing(CallInf
     }
 
     bool constructing = inlineCallInfo_->constructing();
     pushConstant(BooleanValue(constructing));
     return InliningStatus_Inlined;
 }
 
 IonBuilder::InliningStatus
-IonBuilder::inlineConstructTypedObject(CallInfo &callInfo, SizedTypeDescr *descr)
+IonBuilder::inlineConstructTypedObject(CallInfo &callInfo, TypeDescr *descr)
 {
     // Only inline default constructors for now.
     if (callInfo.argc() != 0)
         return InliningStatus_NotInlined;
 
     if (size_t(descr->size()) > InlineTypedObject::MaximumSize)
         return InliningStatus_NotInlined;
 
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -2802,46 +2802,16 @@ class MTypedObjectProto
     bool congruentTo(const MDefinition *ins) const {
         return congruentIfOperandsEqual(ins);
     }
     AliasSet getAliasSet() const {
         return AliasSet::Load(AliasSet::ObjectFields);
     }
 };
 
-class MTypedObjectUnsizedLength
-  : public MUnaryInstruction,
-    public SingleObjectPolicy::Data
-{
-  private:
-    explicit MTypedObjectUnsizedLength(MDefinition *object)
-      : MUnaryInstruction(object)
-    {
-        setResultType(MIRType_Int32);
-        setMovable();
-    }
-
-  public:
-    INSTRUCTION_HEADER(TypedObjectUnsizedLength)
-
-    static MTypedObjectUnsizedLength *New(TempAllocator &alloc, MDefinition *object) {
-        return new(alloc) MTypedObjectUnsizedLength(object);
-    }
-
-    MDefinition *object() const {
-        return getOperand(0);
-    }
-    bool congruentTo(const MDefinition *ins) const {
-        return congruentIfOperandsEqual(ins);
-    }
-    AliasSet getAliasSet() const {
-        return AliasSet::Load(AliasSet::ObjectFields);
-    }
-};
-
 // Creates a new derived type object. At runtime, this is just a call
 // to `BinaryBlock::createDerived()`. That is, the MIR itself does not
 // compile to particularly optimized code. However, using a distinct
 // MIR for creating derived type objects allows the compiler to
 // optimize ephemeral typed objects as would be created for a
 // reference like `a.b.c` -- here, the `a.b` will create an ephemeral
 // derived type object that aliases the memory of `a` itself. The
 // specific nature of `a.b` is revealed by using
--- a/js/src/jit/MOpcodes.h
+++ b/js/src/jit/MOpcodes.h
@@ -158,17 +158,16 @@ namespace jit {
     _(GuardObjectType)                                                      \
     _(GuardObjectIdentity)                                                  \
     _(GuardClass)                                                           \
     _(ArrayLength)                                                          \
     _(SetArrayLength)                                                       \
     _(TypedArrayLength)                                                     \
     _(TypedArrayElements)                                                   \
     _(TypedObjectProto)                                                     \
-    _(TypedObjectUnsizedLength)                                             \
     _(TypedObjectElements)                                                  \
     _(SetTypedObjectOffset)                                                 \
     _(InitializedLength)                                                    \
     _(SetInitializedLength)                                                 \
     _(Not)                                                                  \
     _(BoundsCheck)                                                          \
     _(BoundsCheckLower)                                                     \
     _(InArray)                                                              \
--- a/js/src/jit/ParallelSafetyAnalysis.cpp
+++ b/js/src/jit/ParallelSafetyAnalysis.cpp
@@ -244,17 +244,16 @@ class ParallelSafetyVisitor : public MDe
     SAFE_OP(GuardObjectIdentity)
     SAFE_OP(GuardClass)
     SAFE_OP(AssertRange)
     SAFE_OP(ArrayLength)
     WRITE_GUARDED_OP(SetArrayLength, elements)
     SAFE_OP(TypedArrayLength)
     SAFE_OP(TypedArrayElements)
     SAFE_OP(TypedObjectProto)
-    SAFE_OP(TypedObjectUnsizedLength)
     SAFE_OP(TypedObjectElements)
     SAFE_OP(SetTypedObjectOffset)
     SAFE_OP(InitializedLength)
     WRITE_GUARDED_OP(SetInitializedLength, elements)
     SAFE_OP(Not)
     SAFE_OP(BoundsCheck)
     SAFE_OP(BoundsCheckLower)
     SAFE_OP(LoadElement)
--- a/js/src/jit/Recover.cpp
+++ b/js/src/jit/Recover.cpp
@@ -1108,17 +1108,17 @@ MNewDerivedTypedObject::writeRecoverData
 }
 
 RNewDerivedTypedObject::RNewDerivedTypedObject(CompactBufferReader &reader)
 { }
 
 bool
 RNewDerivedTypedObject::recover(JSContext *cx, SnapshotIterator &iter) const
 {
-    Rooted<SizedTypeDescr *> descr(cx, &iter.read().toObject().as<SizedTypeDescr>());
+    Rooted<TypeDescr *> descr(cx, &iter.read().toObject().as<TypeDescr>());
     Rooted<TypedObject *> owner(cx, &iter.read().toObject().as<TypedObject>());
     int32_t offset = iter.read().toInt32();
 
     JSObject *obj = OutlineTypedObject::createDerived(cx, descr, owner, offset);
     if (!obj)
         return false;
 
     RootedValue result(cx, ObjectValue(*obj));
--- a/js/src/jit/TypedObjectPrediction.cpp
+++ b/js/src/jit/TypedObjectPrediction.cpp
@@ -118,44 +118,34 @@ TypedObjectPrediction::ofArrayKind() con
 {
     switch (kind()) {
       case type::Scalar:
       case type::Reference:
       case type::Simd:
       case type::Struct:
         return false;
 
-      case type::SizedArray:
-      case type::UnsizedArray:
+      case type::Array:
         return true;
     }
 
     MOZ_CRASH("Bad kind");
 }
 
-static bool
-DescrHasKnownSize(const TypeDescr &descr, int32_t *out)
-{
-    if (!descr.is<SizedTypeDescr>())
-        return false;
-
-    *out = descr.as<SizedTypeDescr>().size();
-    return true;
-}
-
 bool
 TypedObjectPrediction::hasKnownSize(int32_t *out) const
 {
     switch (predictionKind()) {
       case TypedObjectPrediction::Empty:
       case TypedObjectPrediction::Inconsistent:
         break;
 
       case TypedObjectPrediction::Descr:
-        return DescrHasKnownSize(descr(), out);
+        *out = descr().size();
+        return true;
 
       case TypedObjectPrediction::Prefix:
         // We only know a prefix of the struct fields, hence we do not
         // know its complete size.
         return false;
     }
 
     MOZ_CRASH("Bad prediction kind");
@@ -228,46 +218,39 @@ TypedObjectPrediction::hasKnownArrayLeng
     switch (predictionKind()) {
       case TypedObjectPrediction::Empty:
       case TypedObjectPrediction::Inconsistent:
         break;
 
       case TypedObjectPrediction::Descr:
         // In later patches, this condition will always be true
         // so long as this represents an array
-        if (descr().is<SizedArrayTypeDescr>()) {
-            *length = descr().as<SizedArrayTypeDescr>().length();
+        if (descr().is<ArrayTypeDescr>()) {
+            *length = descr().as<ArrayTypeDescr>().length();
             return true;
         }
         return false;
 
       case TypedObjectPrediction::Prefix:
         break; // Prefixes are always structs, never arrays
     }
     MOZ_CRASH("Bad prediction kind");
 }
 
-static TypeDescr &
-DescrArrayElementType(const TypeDescr &descr) {
-    return (descr.is<SizedArrayTypeDescr>()
-            ? descr.as<SizedArrayTypeDescr>().elementType()
-            : descr.as<UnsizedArrayTypeDescr>().elementType());
-}
-
 TypedObjectPrediction
 TypedObjectPrediction::arrayElementType() const
 {
     MOZ_ASSERT(ofArrayKind());
     switch (predictionKind()) {
       case TypedObjectPrediction::Empty:
       case TypedObjectPrediction::Inconsistent:
         break;
 
       case TypedObjectPrediction::Descr:
-        return TypedObjectPrediction(DescrArrayElementType(descr()));
+        return TypedObjectPrediction(descr().as<ArrayTypeDescr>().elementType());
 
       case TypedObjectPrediction::Prefix:
         break; // Prefixes are always structs, never arrays
     }
     MOZ_CRASH("Bad prediction kind");
 }
 
 bool
--- a/js/src/jit/VMFunctions.cpp
+++ b/js/src/jit/VMFunctions.cpp
@@ -1009,19 +1009,19 @@ InitBaselineFrameForOsr(BaselineFrame *f
 {
     return frame->initForOsr(interpFrame, numStackValues);
 }
 
 JSObject *
 CreateDerivedTypedObj(JSContext *cx, HandleObject descr,
                       HandleObject owner, int32_t offset)
 {
-    MOZ_ASSERT(descr->is<SizedTypeDescr>());
+    MOZ_ASSERT(descr->is<TypeDescr>());
     MOZ_ASSERT(owner->is<TypedObject>());
-    Rooted<SizedTypeDescr*> descr1(cx, &descr->as<SizedTypeDescr>());
+    Rooted<TypeDescr*> descr1(cx, &descr->as<TypeDescr>());
     Rooted<TypedObject*> owner1(cx, &owner->as<TypedObject>());
     return OutlineTypedObject::createDerived(cx, descr1, owner1, offset);
 }
 
 JSString *
 RegExpReplace(JSContext *cx, HandleString string, HandleObject regexp, HandleString repl)
 {
     MOZ_ASSERT(string);
--- a/js/src/jit/mips/MacroAssembler-mips.cpp
+++ b/js/src/jit/mips/MacroAssembler-mips.cpp
@@ -834,16 +834,22 @@ MacroAssemblerMIPS::ma_sw(Imm32 imm, Add
 
         ma_li(SecondScratchReg, Imm32(address.offset));
         as_addu(SecondScratchReg, address.base, SecondScratchReg);
         as_sw(ScratchRegister, SecondScratchReg, 0);
     }
 }
 
 void
+MacroAssemblerMIPS::ma_sw(Register data, BaseIndex &address)
+{
+    ma_store(data, address, SizeWord);
+}
+
+void
 MacroAssemblerMIPS::ma_pop(Register r)
 {
     as_lw(r, StackPointer, 0);
     as_addiu(StackPointer, StackPointer, sizeof(intptr_t));
 }
 
 void
 MacroAssemblerMIPS::ma_push(Register r)
@@ -2531,16 +2537,29 @@ MacroAssemblerMIPSCompat::branchTestValu
 
     // Load payload
     ma_lw(ScratchRegister, Address(valaddr.base, valaddr.offset + PAYLOAD_OFFSET));
     branchPtr(cond, ScratchRegister, value.payloadReg(), label);
 }
 
 // unboxing code
 void
+MacroAssemblerMIPSCompat::unboxNonDouble(const ValueOperand &operand, Register dest)
+{
+    if (operand.payloadReg() != dest)
+        ma_move(dest, operand.payloadReg());
+}
+
+void
+MacroAssemblerMIPSCompat::unboxNonDouble(const Address &src, Register dest)
+{
+    ma_lw(dest, Address(src.base, src.offset + PAYLOAD_OFFSET));
+}
+
+void
 MacroAssemblerMIPSCompat::unboxInt32(const ValueOperand &operand, Register dest)
 {
     ma_move(dest, operand.payloadReg());
 }
 
 void
 MacroAssemblerMIPSCompat::unboxInt32(const Address &src, Register dest)
 {
--- a/js/src/jit/mips/MacroAssembler-mips.h
+++ b/js/src/jit/mips/MacroAssembler-mips.h
@@ -211,16 +211,17 @@ class MacroAssemblerMIPS : public Assemb
                      int32_t shift, Label *negZero = nullptr);
 
     // memory
     // shortcut for when we know we're transferring 32 bits of data
     void ma_lw(Register data, Address address);
 
     void ma_sw(Register data, Address address);
     void ma_sw(Imm32 imm, Address address);
+    void ma_sw(Register data, BaseIndex &address);
 
     void ma_pop(Register r);
     void ma_push(Register r);
 
     // branches when done from within mips-specific code
     void ma_b(Register lhs, Register rhs, Label *l, Condition c, JumpKind jumpKind = LongJump);
     void ma_b(Register lhs, Imm32 imm, Label *l, Condition c, JumpKind jumpKind = LongJump);
     void ma_b(Register lhs, ImmPtr imm, Label *l, Condition c, JumpKind jumpKind = LongJump) {
@@ -544,16 +545,18 @@ class MacroAssemblerMIPSCompat : public 
     void branchTestPrimitive(Condition cond, const ValueOperand &value, Label *label);
     void branchTestPrimitive(Condition cond, Register tag, Label *label);
 
     void branchTestValue(Condition cond, const ValueOperand &value, const Value &v, Label *label);
     void branchTestValue(Condition cond, const Address &valaddr, const ValueOperand &value,
                          Label *label);
 
     // unboxing code
+    void unboxNonDouble(const ValueOperand &operand, Register dest);
+    void unboxNonDouble(const Address &src, Register dest);
     void unboxInt32(const ValueOperand &operand, Register dest);
     void unboxInt32(const Address &src, Register dest);
     void unboxBoolean(const ValueOperand &operand, Register dest);
     void unboxBoolean(const Address &src, Register dest);
     void unboxDouble(const ValueOperand &operand, FloatRegister dest);
     void unboxDouble(const Address &src, FloatRegister dest);
     void unboxString(const ValueOperand &operand, Register dest);
     void unboxString(const Address &src, Register dest);
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -4748,16 +4748,19 @@ JS::CloneAndExecuteScript(JSContext *cx,
 {
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     RootedScript script(cx, scriptArg);
     if (script->compartment() != cx->compartment()) {
         script = CloneScript(cx, NullPtr(), NullPtr(), script);
         if (!script)
             return false;
+
+        Rooted<GlobalObject *> global(cx, script->compileAndGo() ? &script->global() : nullptr);
+        js::Debugger::onNewScript(cx, script, global);
     }
     return ExecuteScript(cx, obj, script, nullptr);
 }
 
 JS_PUBLIC_API(bool)
 JS_ExecuteScriptVersion(JSContext *cx, HandleObject obj, HandleScript script,
                         MutableHandleValue rval, JSVersion version)
 {
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -991,18 +991,16 @@ bool intrinsic_ForkJoinGetSlice(JSContex
 bool intrinsic_InParallelSection(JSContext *cx, unsigned argc, Value *vp);
 
 bool intrinsic_ObjectIsTypedObject(JSContext *cx, unsigned argc, Value *vp);
 bool intrinsic_ObjectIsTransparentTypedObject(JSContext *cx, unsigned argc, Value *vp);
 bool intrinsic_ObjectIsOpaqueTypedObject(JSContext *cx, unsigned argc, Value *vp);
 bool intrinsic_ObjectIsTypeDescr(JSContext *cx, unsigned argc, Value *vp);
 bool intrinsic_TypeDescrIsSimpleType(JSContext *cx, unsigned argc, Value *vp);
 bool intrinsic_TypeDescrIsArrayType(JSContext *cx, unsigned argc, Value *vp);
-bool intrinsic_TypeDescrIsUnsizedArrayType(JSContext *cx, unsigned argc, Value *vp);
-bool intrinsic_TypeDescrIsSizedArrayType(JSContext *cx, unsigned argc, Value *vp);
 
 class AutoLockForExclusiveAccess
 {
     JSRuntime *runtime;
 
     void init(JSRuntime *rt) {
         runtime = rt;
         if (runtime->numExclusiveThreads) {
--- a/js/src/jsnum.cpp
+++ b/js/src/jsnum.cpp
@@ -1447,34 +1447,43 @@ CharsToNumber(ThreadSafeContext *cx, con
         else
             *result = GenericNaN();
         return true;
     }
 
     const CharT *end = chars + length;
     const CharT *bp = SkipSpace(chars, end);
 
-    /* ECMA doesn't allow signed hex numbers (bug 273467). */
-    if (end - bp >= 2 && bp[0] == '0' && (bp[1] == 'x' || bp[1] == 'X')) {
-        /*
-         * It's probably a hex number.  Accept if there's at least one hex
-         * digit after the 0x, and if no non-whitespace characters follow all
-         * the hex digits.
-         */
-        const CharT *endptr;
-        double d;
-        if (!GetPrefixInteger(cx, bp + 2, end, 16, &endptr, &d) ||
-            endptr == bp + 2 ||
-            SkipSpace(endptr, end) != end)
-        {
-            *result = GenericNaN();
-        } else {
-            *result = d;
+    /* ECMA doesn't allow signed non-decimal numbers (bug 273467). */
+    if (end - bp >= 2 && bp[0] == '0') {
+        int radix = 0;
+        if (bp[1] == 'b' || bp[1] == 'B')
+            radix = 2;
+        else if (bp[1] == 'o' || bp[1] == 'O')
+            radix = 8;
+        else if (bp[1] == 'x' || bp[1] == 'X')
+            radix = 16;
+
+        if (radix != 0) {
+            /*
+             * It's probably a non-decimal number. Accept if there's at least one digit after
+             * the 0b|0o|0x, and if no non-whitespace characters follow all the digits.
+             */
+            const CharT *endptr;
+            double d;
+            if (!GetPrefixInteger(cx, bp + 2, end, radix, &endptr, &d) ||
+                endptr == bp + 2 ||
+                SkipSpace(endptr, end) != end)
+            {
+                *result = GenericNaN();
+            } else {
+                *result = d;
+            }
+            return true;
         }
-        return true;
     }
 
     /*
      * Note that ECMA doesn't treat a string beginning with a '0' as
      * an octal number here. This works because all such numbers will
      * be interpreted as decimal by js_strtod.  Also, any hex numbers
      * that have made it here (which can only be negative ones) will
      * be treated as 0 without consuming the 'x' by js_strtod.
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/Number/ToNumber.js
@@ -0,0 +1,26 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * https://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+assertEq(Number("0b11"), 3);
+assertEq(Number("0B11"), 3);
+assertEq(Number(" 0b11 "), 3);
+assertEq(Number("0b12"), NaN);
+assertEq(Number("-0b11"), NaN);
+assertEq(+"0b11", 3);
+
+assertEq(Number("0o66"), 54);
+assertEq(Number("0O66"), 54);
+assertEq(Number(" 0o66 "), 54);
+assertEq(Number("0o88"), NaN);
+assertEq(Number("-0o66"), NaN);
+assertEq(+"0o66", 54);
+
+if(typeof getSelfHostedValue === "function"){
+    assertEq(getSelfHostedValue("ToNumber")("0b11"), 3);
+    assertEq(getSelfHostedValue("ToNumber")("0o66"), 54);
+}
+
+if (typeof reportCompare === "function")
+    reportCompare(true, true);
deleted file mode 100644
--- a/js/src/tests/ecma_6/TypedObject/Bug914137.js
+++ /dev/null
@@ -1,15 +0,0 @@
-// |reftest| skip-if(!this.hasOwnProperty("TypedObject")||(Android))
-var BUGNUMBER = 914137;
-var summary = 'Fuzz bug';
-
-function test() {
-  var A = new TypedObject.ArrayType(TypedObject.uint8, 2147483647);
-  var a = new A();
-  assertEq(arguments[5], a);
-}
-
-print(BUGNUMBER + ": " + summary);
-assertThrows(test);
-if (typeof reportCompare === "function")
-  reportCompare(true, true);
-print("Tests complete");
--- a/js/src/tests/ecma_6/TypedObject/arrayofstructs.js
+++ b/js/src/tests/ecma_6/TypedObject/arrayofstructs.js
@@ -2,19 +2,19 @@
 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).dimension(3);
+  var Point = new ArrayType(float32, 3);
   var Line = new StructType({from: Point, to: Point});
-  var Lines = new ArrayType(Line).dimension(3);
+  var Lines = new ArrayType(Line, 3);
 
   var lines = new Lines([
     {from: [1, 2, 3], to: [4, 5, 6]},
     {from: [7, 8, 9], to: [10, 11, 12]},
     {from: [13, 14, 15], to: [16, 17, 18]}
   ]);
 
   assertEq(lines[1].to[1], 11);
--- a/js/src/tests/ecma_6/TypedObject/arraytype.js
+++ b/js/src/tests/ecma_6/TypedObject/arraytype.js
@@ -23,24 +23,24 @@ function runTests() {
 
     assertEq(typeof ArrayType.prototype.prototype.forEach == "function", true);
 
     assertThrows(function() ArrayType(uint8, 10));
     assertThrows(function() new ArrayType());
     assertThrows(function() new ArrayType(""));
     assertThrows(function() new ArrayType(5));
     assertThrows(function() new ArrayType(uint8).dimension(-1));
-    var A = new ArrayType(uint8).dimension(10);
-    assertEq(A.__proto__.__proto__, ArrayType.prototype);
+    var A = new ArrayType(uint8, 10);
+    //assertEq(A.__proto__.__proto__, ArrayType.prototype);
     assertEq(A.length, 10);
     assertEq(A.elementType, uint8);
     assertEq(A.byteLength, 10);
-    assertEq(A.toSource(), "new ArrayType(uint8).dimension(10)");
+    assertEq(A.toSource(), "new ArrayType(uint8, 10)");
 
-    assertEq(A.prototype.__proto__.__proto__, ArrayType.prototype.prototype);
+    //assertEq(A.prototype.__proto__.__proto__, ArrayType.prototype.prototype);
 
     var a = new A();
     assertEq(a.__proto__, A.prototype);
     assertEq(a.length, 10);
 
     assertThrows(function() a.length = 2);
 
     for (var i = 0; i < a.length; i++)
@@ -69,18 +69,18 @@ function runTests() {
     for (var i = 0; i < b.length; i++)
         assertEq(b[i], i%2);
 
     assertThrows(function() new A(5));
     assertThrows(function() new A(/fail/));
     // Length different
     assertThrows(function() new A([0, 1, 0, 1, 0, 1, 0, 1, 0]));
 
-    var Vec3 = new ArrayType(float32).dimension(3);
-    var Sprite = new ArrayType(Vec3).dimension(3); // say for position, velocity, and direction
+    var Vec3 = new ArrayType(float32, 3);
+    var Sprite = new ArrayType(Vec3, 3); // say for position, velocity, and direction
     assertEq(Sprite.elementType, Vec3);
     assertEq(Sprite.elementType.elementType, float32);
 
 
     var mario = new Sprite();
     // setting using binary data
     mario[0] = new Vec3([1, 0, 0]);
     // setting using JS array conversion
@@ -91,17 +91,17 @@ function runTests() {
     assertEq(mario[0][1], 0);
     assertEq(mario[0][2], 0);
 
     assertThrows(function() mario[1] = 5);
     mario[1][1] = {};
     assertEq(Number.isNaN(mario[1][1]), true);
 
     // ok this is just for kicks
-    var AllSprites = new ArrayType(Sprite).dimension(65536);
+    var AllSprites = new ArrayType(Sprite, 65536);
     var as = new AllSprites();
     assertEq(as.length, 65536);
 
     var indexPropDesc = Object.getOwnPropertyDescriptor(as, '0');
     assertEq(typeof indexPropDesc == "undefined", false);
     assertEq(indexPropDesc.configurable, false);
     assertEq(indexPropDesc.enumerable, true);
     assertEq(indexPropDesc.writable, true);
deleted file mode 100644
--- a/js/src/tests/ecma_6/TypedObject/handle_unsized.js
+++ /dev/null
@@ -1,25 +0,0 @@
-// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
-
-/*
- * Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/licenses/publicdomain/
- */
-
-var BUGNUMBER = 922115;
-var summary = 'check we cannot create handles to unsized arrays';
-
-var T = TypedObject;
-
-function runTests() {
-  var Line = new T.StructType({from: T.uint8, to: T.uint8});
-  var Lines = Line.array();
-  assertThrowsInstanceOf(function() Lines.handle(), TypeError,
-                         "was able to create handle to unsized array");
-
-  reportCompare(true, true);
-  print("Tests complete");
-}
-
-runTests();
-
-
--- a/js/src/tests/ecma_6/TypedObject/method_filter.js
+++ b/js/src/tests/ecma_6/TypedObject/method_filter.js
@@ -16,50 +16,32 @@ var uint8Clamped = TypedObject.uint8Clam
 var int8 = TypedObject.int8;
 var int16 = TypedObject.int16;
 var int32 = TypedObject.int32;
 var float32 = TypedObject.float32;
 var float64 = TypedObject.float64;
 
 var objectType = TypedObject.objectType;
 
-function filterOddsFromVariable() {
+function filterOdds() {
   var length = 100;
-  var Uint32s = uint32.array();
-  var uint32s = new Uint32s(100);
-  for (var i = 0; i < length; i++)
-    uint32s[i] = i;
-
-  var odds = uint32s.filter(i => (i % 2) != 0);
-  assertEq(true, objectType(odds) == Uint32s);
-  assertEq(true, Uint32s.variable);
-  assertEq(50, odds.length);
-  for (var i = 0, j = 1; j < length; i++, j += 2)
-    assertEq(odds[i], j);
-}
-
-function filterOddsFromSized() {
-  var length = 100;
-  var Uint32s = uint32.array(100);
+  var Uint32s = new ArrayType(uint32, 100);
   var uint32s = new Uint32s();
   for (var i = 0; i < length; i++)
     uint32s[i] = i;
 
   var odds = uint32s.filter(i => (i % 2) != 0);
-  assertEq(true, objectType(odds) == Uint32s.unsized);
-  assertEq(true, objectType(odds).variable);
   assertEq(50, odds.length);
   for (var i = 0, j = 1; j < length; i++, j += 2)
     assertEq(odds[i], j);
 }
 
 function runTests() {
     print(BUGNUMBER + ": " + summary);
 
-    filterOddsFromVariable();
-    filterOddsFromSized();
+    filterOdds();
 
     if (typeof reportCompare === "function")
         reportCompare(true, true);
     print("Tests complete");
 }
 
 runTests();
--- a/js/src/tests/ecma_6/TypedObject/referencetypecoercions.js
+++ b/js/src/tests/ecma_6/TypedObject/referencetypecoercions.js
@@ -22,17 +22,17 @@ function TestValues(type, values) {
   }
 
   for (var i = 0; i < values.length; i++) {
     var struct = new Struct();
     struct.f = values[i].input;
     compare(struct.f, values[i]);
   }
 
-  var Array = new ArrayType(type).dimension(1);
+  var Array = new ArrayType(type, 1);
   for (var i = 0; i < values.length; i++) {
     var array = new Array();
     array[0] = values[i].input;
     compare(array[0], values[i]);
   }
 
   function compare(v, spec) {
     if (spec.source)
--- a/js/src/tests/ecma_6/TypedObject/referencetypetrace.js
+++ b/js/src/tests/ecma_6/TypedObject/referencetypetrace.js
@@ -34,36 +34,27 @@ function TestStructFields(RefType) {
   var s1 = new S1({f: rabbit});
   assertCanReach(s1, rabbit);
   s1.f = null;
   assertCannotReach(s1, rabbit);
 }
 
 function TestArrayElements(RefType) {
   var rabbit = {};
-  var S1 = new ArrayType(RefType).dimension(1);
-  var s1 = new S1([rabbit]);
-  assertCanReach(s1, rabbit);
-  s1[0] = null;
-  assertCannotReach(s1, rabbit);
-}
-
-function TestUnsizedArrayElements(RefType) {
-  var rabbit = {};
-  var S1 = new ArrayType(RefType);
+  var S1 = new ArrayType(RefType, 1);
   var s1 = new S1([rabbit]);
   assertCanReach(s1, rabbit);
   s1[0] = null;
   assertCannotReach(s1, rabbit);
 }
 
 function TestStructInArray(RefType) {
   var rabbit = {};
   var S2 = new StructType({f: RefType, g: RefType});
-  var S1 = new ArrayType(S2).dimension(1);
+  var S1 = new ArrayType(S2, 1);
   var s1 = new S1([{f: rabbit, g: {}}]);
   assertCanReach(s1, rabbit);
   s1[0].f = null;
   assertCannotReach(s1, rabbit);
 }
 
 function TestStringInStruct() {
   // Rather subtle hair-pullingly maddening testing phenomena: If you
@@ -86,19 +77,16 @@ function runTests()
   printStatus(summary);
 
   TestStructFields(Object);
   TestStructFields(Any);
 
   TestArrayElements(Object);
   TestArrayElements(Any);
 
-  TestUnsizedArrayElements(Object);
-  TestUnsizedArrayElements(Any);
-
   TestStructInArray(Object);
   TestStructInArray(Any);
 
   TestStringInStruct();
 
   reportCompare(true, true, "TypedObjects trace tests");
 }
 
--- a/js/src/tests/ecma_6/TypedObject/size_and_alignment.js
+++ b/js/src/tests/ecma_6/TypedObject/size_and_alignment.js
@@ -34,19 +34,19 @@ function runTests() {
 
     {type: float32, size: 4, alignment: 4},
     {type: float64, size: 8, alignment: 8},
 
     {type: new StructType({a: uint8, b: uint16, c: uint8}), size: 6, alignment: 2},
 
     {type: new StructType({a: uint8, b: uint8, c: uint16}), size: 4, alignment: 2},
 
-    {type: new ArrayType(uint8).dimension(32), size: 32, alignment: 1},
-    {type: new ArrayType(uint16).dimension(16), size: 32, alignment: 2},
-    {type: new ArrayType(uint32).dimension(8), size: 32, alignment: 4},
+    {type: new ArrayType(uint8, 32), size: 32, alignment: 1},
+    {type: new ArrayType(uint16, 16), size: 32, alignment: 2},
+    {type: new ArrayType(uint32, 8), size: 32, alignment: 4},
   ];
 
   for (var i = 0; i < typesAndAlignments.length; i++) {
     var test = typesAndAlignments[i];
     print("Type:", test.type.toSource(),
           "Size:", test.type.byteLength,
           "Alignment:", test.type.byteAlignment);
     assertEq(test.type.byteLength, test.size);
--- a/js/src/tests/ecma_6/TypedObject/structtypereflection.js
+++ b/js/src/tests/ecma_6/TypedObject/structtypereflection.js
@@ -16,17 +16,16 @@ 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(), "new StructType({x: int32, y: uint8, z: float64})");
-    assertEq(S.variable, false);
     assertEq(S.byteLength, 16);
     assertEq(S.byteAlignment, 8);
     var fieldNames = Object.getOwnPropertyNames(S.fieldTypes);
     assertEq(fieldNames[0], "x");
     assertEq(fieldNames[1], "y");
     assertEq(fieldNames[2], "z");
     assertEq(fieldNames.length, 3);
     assertEq(S.fieldTypes.x, int32);
deleted file mode 100644
--- a/js/src/tests/ecma_6/TypedObject/unsizedarrays.js
+++ /dev/null
@@ -1,54 +0,0 @@
-// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
-var BUGNUMBER = 922115;
-var summary = 'TypedObjects ArrayType implementation';
-
-/*
- * Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/licenses/publicdomain/
- */
-
-var { ArrayType, StructType, uint8, float32, uint32 } = TypedObject;
-var ObjectType = TypedObject.Object;
-
-function runTests() {
-  print(BUGNUMBER + ": " + summary);
-
-  (function SimpleArrayOfTwoObjects() {
-    print("SimpleArrayOfTwoObjects");
-    var Objects = new ArrayType(ObjectType);
-    var objects2 = new Objects([{f: "Hello"},
-                                {f: "World"}]);
-    assertEq(objects2[0].f, "Hello");
-    assertEq(objects2[1].f, "World");
-    assertEq(objects2.length, 2);
-  })();
-
-  (function EmbedUnsizedArraysBad() {
-    print("EmbedUnsizedArraysBad");
-    var Objects = new ArrayType(ObjectType);
-    assertThrows(() => new ArrayType(Objects));
-    assertThrows(() => new StructType({f: Objects}));
-  })();
-
-  (function MultipleSizes() {
-    print("MultipleSizes");
-    var Uints = new ArrayType(uint32);
-    var Point = new StructType({values: new ArrayType(uint32).dimension(3)});
-
-    var uints = new Uints([0, 1, 2]);
-    var point = new Point({values: uints});
-
-    assertEq(uints.length, point.values.length);
-    for (var i = 0; i < uints.length; i++) {
-      assertEq(uints[i], i);
-      assertEq(uints[i], point.values[i]);
-    }
-  })();
-
-  if (typeof reportCompare === "function")
-    reportCompare(true, true);
-  print("Tests complete");
-}
-
-runTests();
-
deleted file mode 100644
--- a/js/src/tests/ecma_6/TypedObject/unsizedarraysanddim.js
+++ /dev/null
@@ -1,47 +0,0 @@
-// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
-var BUGNUMBER = 922115;
-var summary = 'TypedObjects ArrayType implementation';
-
-var ArrayType = TypedObject.ArrayType;
-var StructType = TypedObject.StructType;
-var uint8 = TypedObject.uint8;
-var float32 = TypedObject.float32;
-var uint32 = TypedObject.uint32;
-var ObjectType = TypedObject.Object;
-
-function runTests() {
-  (function DimensionLinkedToUndimension() {
-    var UintsA = uint32.array();
-    var FiveUintsA = UintsA.dimension(5);
-    var FiveUintsB = uint32.array(5);
-
-    assertEq(true, FiveUintsA.equivalent(FiveUintsB));
-    assertEq(true, FiveUintsA.unsized === UintsA);
-    assertEq(true, FiveUintsB.unsized !== UintsA);
-  })();
-
-  (function PrototypeHierarchy() {
-    var Uint8s = uint8.array();
-    assertEq(Uint8s.prototype.__proto__, ArrayType.prototype.prototype);
-    Uint8s.prototype.sum = function() {
-      var r = 0;
-      for (var i = 0; i < this.length; i++)
-        r = uint8(r + this[i]);
-      return r;
-    };
-
-    var FiveUint8s = Uint8s.dimension(5);
-    assertEq(FiveUint8s.__proto__, Uint8s);
-
-    var fiveUint8s = new FiveUint8s([128, 128, 128, 128, 128]);
-    assertEq(128, fiveUint8s.sum());
-  })();
-
-  if (typeof reportCompare === "function")
-    reportCompare(true, true);
-
-  print("Tests complete");
-}
-
-runTests();
-
deleted file mode 100644
--- a/js/src/tests/ecma_6/TypedObject/unsizedarraysembedded.js
+++ /dev/null
@@ -1,23 +0,0 @@
-// |reftest| skip-if(!this.hasOwnProperty("TypedObject"))
-var BUGNUMBER = 922115;
-var summary = 'cannot embed unsized array in a struct';
-
-/*
- * Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/licenses/publicdomain/
- */
-
-var T = TypedObject;
-
-function runTests() {
-  print(BUGNUMBER + ": " + summary);
-
-  var Uints = T.uint32.array();
-  assertThrowsInstanceOf(() => { new T.StructType({f: Uints}) }, TypeError);
-  assertThrowsInstanceOf(() => { Uints.array() }, TypeError);
-
-  reportCompare(true, true);
-  print("Tests complete");
-}
-
-runTests();
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -4827,18 +4827,21 @@ DebuggerArguments_getArg(JSContext *cx, 
      * Since getters can be extracted and applied to other objects,
      * there is no guarantee this object has an ith argument.
      */
     MOZ_ASSERT(i >= 0);
     RootedValue arg(cx);
     RootedScript script(cx);
     if (unsigned(i) < frame.numActualArgs()) {
         script = frame.script();
-        if (!script->ensureHasAnalyzedArgsUsage(cx))
-            return false;
+        {
+            AutoCompartment ac(cx, script->compartment());
+            if (!script->ensureHasAnalyzedArgsUsage(cx))
+                return false;
+        }
         if (unsigned(i) < frame.numFormalArgs() && script->formalIsAliased(i)) {
             for (AliasedFormalIter fi(script); ; fi++) {
                 if (fi.frameIndex() == unsigned(i)) {
                     arg = frame.callObj().aliasedVar(fi);
                     break;
                 }
             }
         } else if (script->argsObjAliasesFormals() && frame.hasArgsObj()) {
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -909,28 +909,16 @@ js::intrinsic_TypeDescrIsSimpleType(JSCo
 }
 
 bool
 js::intrinsic_TypeDescrIsArrayType(JSContext *cx, unsigned argc, Value *vp)
 {
     return js::TypeDescrIsArrayType(cx, argc, vp);
 }
 
-bool
-js::intrinsic_TypeDescrIsUnsizedArrayType(JSContext *cx, unsigned argc, Value *vp)
-{
-    return js::TypeDescrIsUnsizedArrayType(cx, argc, vp);
-}
-
-bool
-js::intrinsic_TypeDescrIsSizedArrayType(JSContext *cx, unsigned argc, Value *vp)
-{
-    return js::TypeDescrIsSizedArrayType(cx, argc, vp);
-}
-
 /**
  * Returns the default locale as a well-formed, but not necessarily canonicalized,
  * BCP-47 language tag.
  */
 static bool
 intrinsic_RuntimeDefaultLocale(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
@@ -1126,22 +1114,16 @@ static const JSFunctionSpec intrinsic_fu
               JSNativeThreadSafeWrapper<js::TypedObjectIsAttached>,
               &js::TypedObjectIsAttachedJitInfo, 1, 0),
     JS_FNINFO("ObjectIsOpaqueTypedObject",
               intrinsic_ObjectIsOpaqueTypedObject,
               &js::ObjectIsOpaqueTypedObjectJitInfo, 1, 0),
     JS_FNINFO("TypeDescrIsArrayType",
               intrinsic_TypeDescrIsArrayType,
               &js::TypeDescrIsArrayTypeJitInfo, 1, 0),
-    JS_FNINFO("TypeDescrIsUnsizedArrayType",
-              intrinsic_TypeDescrIsUnsizedArrayType,
-              &js::TypeDescrIsUnsizedArrayTypeJitInfo, 1, 0),
-    JS_FNINFO("TypeDescrIsSizedArrayType",
-              intrinsic_TypeDescrIsSizedArrayType,
-              &js::TypeDescrIsSizedArrayTypeJitInfo, 1, 0),
     JS_FNINFO("TypeDescrIsSimpleType",
               intrinsic_TypeDescrIsSimpleType,
               &js::TypeDescrIsSimpleTypeJitInfo, 1, 0),
     JS_FNINFO("ClampToUint8",
               JSNativeThreadSafeWrapper<js::ClampToUint8>,
               &js::ClampToUint8JitInfo, 1, 0),
     JS_FN("GetTypedObjectModule", js::GetTypedObjectModule, 0, 0),
     JS_FN("GetFloat32x4TypeDescr", js::GetFloat32x4TypeDescr, 0, 0),
--- a/media/libvpx/moz.build
+++ b/media/libvpx/moz.build
@@ -46,28 +46,31 @@ if CONFIG['VPX_X86_ASM']:
         SOURCES += files['AVX2']
 
     #postproc is only enabled on x86 with asm
     SOURCES += files['VP8_POSTPROC']
 
 arm_asm_files = []
 if CONFIG['VPX_ARM_ASM']:
     arm_asm_files += files['ARM_ASM']
-    CFLAGS += ['-mfpu=neon']
 
     if CONFIG['VPX_AS_CONVERSION']:
         GENERATED_SOURCES += [ "%s.%s" % (f, CONFIG['VPX_ASM_SUFFIX'])
             for f in sorted(arm_asm_files) if f.endswith('.asm')
         ]
         SOURCES += [
             f for f in sorted(arm_asm_files) if not f.endswith('.asm')
         ]
     else:
         SOURCES += sorted(arm_asm_files)
 
+    for f in SOURCES:
+        if f.endswith('.c') and 'neon' in f:
+            SOURCES[f].flags += ['-march=armv7-a', '-mthumb', '-mfloat-abi=softfp', '-mfpu=neon']
+
 # boolhuff_armv5te.asm defines the same functions as boolhuff.c instead of
 # using RTCD, so we have to make sure we only add one of the two.
 if 'vp8/encoder/arm/armv5te/boolhuff_armv5te.asm' not in arm_asm_files:
     SOURCES += [
         'vp8/encoder/boolhuff.c',
     ]
 
 MSVC_ENABLE_PGO = True
--- a/media/mtransport/third_party/nICEr/src/stun/turn_client_ctx.c
+++ b/media/mtransport/third_party/nICEr/src/stun/turn_client_ctx.c
@@ -58,16 +58,21 @@ int NR_LOG_TURN = 0;
 #define TURN_USECS_PER_S                 1000000
 #define TURN_REFRESH_SLACK_SECONDS       10    /* How long before expiry to refresh
                                                   allocations/permissions. The RFC 5766
                                                   Section 7 recommendation if 60 seconds,
                                                   but this is silly since the transaction
                                                   times out after about 5. */
 #define TURN_PERMISSION_LIFETIME_SECONDS 300   /* 5 minutes. From RFC 5766 2.3 */
 
+// Set to enable a temporary fix that will run the TURN reservation keep-alive
+// logic when data is received via a TURN relayed path: a DATA_INDICATION packet is received.
+// TODO(pkerr@mozilla.com) This should be replace/removed when bug 935806 is implemented.
+#define REFRESH_RESERVATION_ON_RECV 1
+
 static int nr_turn_stun_ctx_create(nr_turn_client_ctx *tctx, int type,
                                    NR_async_cb success_cb,
                                    NR_async_cb failure_cb,
                                    nr_turn_stun_ctx **ctxp);
 static int nr_turn_stun_ctx_destroy(nr_turn_stun_ctx **ctxp);
 static void nr_turn_stun_ctx_cb(NR_SOCKET s, int how, void *arg);
 static int nr_turn_stun_set_auth_params(nr_turn_stun_ctx *ctx,
                                         char *realm, char *nonce);
@@ -785,16 +790,22 @@ int nr_turn_client_parse_data_indication
     }
     ABORT(r);
   }
 
   if ((r=nr_transport_addr_copy(remote_addr,
                                 &attr->u.xor_mapped_address.unmasked)))
     ABORT(r);
 
+#if REFRESH_RESERVATION_ON_RECV
+  if ((r=nr_turn_client_ensure_perm(ctx, remote_addr))) {
+    ABORT(r);
+  }
+#endif
+
   if (!nr_stun_message_has_attribute(ind, NR_STUN_ATTR_DATA, &attr)) {
     ABORT(R_BAD_DATA);
   }
 
   assert(newsize >= attr->u.data.length);
   if (newsize < attr->u.data.length)
     ABORT(R_BAD_ARGS);
 
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -3901,16 +3901,17 @@ pref("layers.acceleration.draw-fps", fal
 pref("layers.dump", false);
 pref("layers.draw-borders", false);
 pref("layers.draw-tile-borders", false);
 pref("layers.draw-bigimage-borders", false);
 pref("layers.frame-counter", false);
 pref("layers.enable-tiles", false);
 pref("layers.tiled-drawtarget.enabled", false);
 pref("layers.low-precision-buffer", false);
+pref("layers.progressive-paint", false);
 pref("layers.tile-width", 256);
 pref("layers.tile-height", 256);
 // Max number of layers per container. See Overwrite in mobile prefs.
 pref("layers.max-active", -1);
 
 // Set the default values, and then override per-platform as needed
 pref("layers.offmainthreadcomposition.enabled", false);
 // Compositor target frame rate. NOTE: If vsync is enabled the compositor
--- a/netwerk/base/src/BackgroundFileSaver.cpp
+++ b/netwerk/base/src/BackgroundFileSaver.cpp
@@ -613,20 +613,25 @@ BackgroundFileSaver::ProcessStateChange(
   int32_t creationIoFlags;
   if (isContinuation) {
     creationIoFlags = PR_APPEND;
   } else {
     creationIoFlags = (append ? PR_APPEND : PR_TRUNCATE) | PR_CREATE_FILE;
   }
 
   // Create the target file, or append to it if we already started writing it.
+  // The 0600 permissions are used while the file is being downloaded, and for
+  // interrupted downloads. Those may be located in the system temporary
+  // directory, as well as the target directory, and generally have a ".part"
+  // extension. Those part files should never be group or world-writable even
+  // if the umask allows it.
   nsCOMPtr<nsIOutputStream> outputStream;
   rv = NS_NewLocalFileOutputStream(getter_AddRefs(outputStream),
                                    mActualTarget,
-                                   PR_WRONLY | creationIoFlags, 0644);
+                                   PR_WRONLY | creationIoFlags, 0600);
   NS_ENSURE_SUCCESS(rv, rv);
 
   outputStream = NS_BufferOutputStream(outputStream, BUFFERED_IO_SIZE);
   if (!outputStream) {
     return NS_ERROR_FAILURE;
   }
 
   // Wrap the output stream so that it feeds the digest context if needed.
--- a/netwerk/protocol/http/Http2Session.cpp
+++ b/netwerk/protocol/http/Http2Session.cpp
@@ -2578,28 +2578,30 @@ Http2Session::WriteSegments(nsAHttpSegme
   if (mDownstreamState == PROCESSING_CONTROL_RST_STREAM) {
     nsresult streamCleanupCode;
 
     // There is no bounds checking on the error code.. we provide special
     // handling for a couple of cases and all others (including unknown) are
     // equivalent to cancel.
     if (mDownstreamRstReason == REFUSED_STREAM_ERROR) {
       streamCleanupCode = NS_ERROR_NET_RESET;      // can retry this 100% safely
+      mInputFrameDataStream->Transaction()->ReuseConnectionOnRestartOK(true);
     } else if (mDownstreamRstReason == HTTP_1_1_REQUIRED) {
       streamCleanupCode = NS_ERROR_NET_RESET;
       mInputFrameDataStream->Transaction()->ReuseConnectionOnRestartOK(true);
       mInputFrameDataStream->Transaction()->DisableSpdy();
     } else {
       streamCleanupCode = mInputFrameDataStream->RecvdData() ?
         NS_ERROR_NET_PARTIAL_TRANSFER :
         NS_ERROR_NET_INTERRUPT;
     }
 
-    if (mDownstreamRstReason == COMPRESSION_ERROR)
+    if (mDownstreamRstReason == COMPRESSION_ERROR) {
       mShouldGoAway = true;
+    }
 
     // mInputFrameDataStream is reset by ChangeDownstreamState
     Http2Stream *stream = mInputFrameDataStream;
     ResetDownstreamState();
     LOG3(("Http2Session::WriteSegments cleanup stream on recv of rst "
           "session=%p stream=%p 0x%X\n", this, stream,
           stream ? stream->StreamID() : 0));
     CleanupStream(stream, streamCleanupCode, CANCEL_ERROR);
--- a/netwerk/test/unit/test_http2.js
+++ b/netwerk/test/unit/test_http2.js
@@ -497,16 +497,22 @@ H11RequiredSessionListener.prototype.onS
 
 function test_http2_h11required_session() {
   var chan = makeChan("https://localhost:6944/h11required_session");
   var listener = new H11RequiredSessionListener();
   listener.shouldBeHttp2 = false;
   chan.asyncOpen(listener, null);
 }
 
+function test_http2_retry_rst() {
+  var chan = makeChan("https://localhost:6944/rstonce");
+  var listener = new Http2CheckListener();
+  chan.asyncOpen(listener, null);
+}
+
 // hack - the header test resets the multiplex object on the server,
 // so make sure header is always run before the multiplex test.
 //
 // make sure post_big runs first to test race condition in restarting
 // a stalled stream when a SETTINGS frame arrives
 var tests = [ test_http2_post_big
             , test_http2_basic
             , test_http2_nospdy
@@ -521,16 +527,17 @@ var tests = [ test_http2_post_big
             , test_http2_cookie_crumbling
             , test_http2_multiplex
             , test_http2_big
             , test_http2_post
             , test_http2_pushapi_1
             // These next two must always come in this order
             , test_http2_h11required_stream
             , test_http2_h11required_session
+            , test_http2_retry_rst
             ];
 var current_test = 0;
 
 function run_next_test() {
   if (current_test < tests.length) {
     tests[current_test]();
     current_test++;
     do_test_pending();
--- a/security/manager/tools/PreloadedHPKPins.json
+++ b/security/manager/tools/PreloadedHPKPins.json
@@ -207,17 +207,17 @@
       "pins": "mozilla_services", "test_mode": false, "id": 5 },
     { "name": "cdn.mozilla.net", "include_subdomains": true,
       "pins": "mozilla", "test_mode": false },
     { "name": "cdn.mozilla.org", "include_subdomains": true,
       "pins": "mozilla", "test_mode": false },
     { "name": "media.mozilla.com", "include_subdomains": true,
       "pins": "mozilla", "test_mode": false },
     { "name": "services.mozilla.com", "include_subdomains": true,
-      "pins": "mozilla_services", "test_mode": true, "id": 6 },
+      "pins": "mozilla_services", "test_mode": false, "id": 6 },
     { "name": "include-subdomains.pinning.example.com",
       "include_subdomains": true, "pins": "mozilla_test",
       "test_mode": false },
     // Example domain to collect per-host stats for telemetry tests.
     { "name": "exclude-subdomains.pinning.example.com",
       "include_subdomains": false, "pins": "mozilla_test",
       "test_mode": false, "id": 0 },
     { "name": "test-mode.pinning.example.com", "include_subdomains": true,
--- a/testing/marionette/client/marionette/marionette.py
+++ b/testing/marionette/client/marionette/marionette.py
@@ -8,16 +8,17 @@ import datetime
 import json
 import os
 import socket
 import StringIO
 import time
 import traceback
 import warnings
 
+from contextlib import contextmanager
 
 from application_cache import ApplicationCache
 from decorators import do_crash_check
 from keys import Keys
 from marionette_transport import MarionetteTransport
 
 from mozrunner import B2GEmulatorRunner
 
@@ -951,30 +952,51 @@ class Marionette(object):
 
         """
 
         response = self._send_message("close", "ok")
         return response
 
     def set_context(self, context):
         '''
-        Sets the context that marionette commands are running in.
+        Sets the context that Marionette commands are running in.
 
         :param context: Context, may be one of the class properties
          `CONTEXT_CHROME` or `CONTEXT_CONTENT`.
 
-        Usage example:
-
-        ::
+        Usage example::
 
           marionette.set_context(marionette.CONTEXT_CHROME)
         '''
         assert(context == self.CONTEXT_CHROME or context == self.CONTEXT_CONTENT)
         return self._send_message('setContext', 'ok', value=context)
 
+    @contextmanager
+    def using_context(self, context):
+        '''
+        Sets the context that Marionette commands are running in using
+        a `with` statement. The state of the context on the server is
+        saved before entering the block, and restored upon exiting it.
+
+        :param context: Context, may be one of the class properties
+         `CONTEXT_CHROME` or `CONTEXT_CONTENT`.
+
+        Usage example::
+
+          with marionette.using_context(marionette.CONTEXT_CHROME):
+              # chrome scope
+              ... do stuff ...
+        '''
+        scope = self._send_message('getContext', 'value')
+        self.set_context(context)
+        try:
+            yield
+        finally:
+            self.set_context(scope)
+
     def switch_to_window(self, window_id):
         '''
         Switch to the specified window; subsequent commands will be directed at the new window.
 
         :param window_id: The id or name of the window to switch to.
         '''
         response = self._send_message('switchToWindow', 'ok', name=window_id)
         self.window = window_id
new file mode 100644
--- /dev/null
+++ b/testing/marionette/client/marionette/tests/unit/test_with_using_context.py
@@ -0,0 +1,54 @@
+# 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/.
+
+from marionette_test import MarionetteTestCase
+from errors import MarionetteException
+
+
+class TestSetContext(MarionetteTestCase):
+    def setUp(self):
+        MarionetteTestCase.setUp(self)
+
+        # shortcuts to improve readability of these tests
+        self.chrome = self.marionette.CONTEXT_CHROME
+        self.content = self.marionette.CONTEXT_CONTENT
+
+        test_url = self.marionette.absolute_url('empty.html')
+        self.marionette.navigate(test_url)
+        self.marionette.set_context(self.content)
+        self.assertEquals(self.get_context(), self.content)
+
+    def get_context(self):
+        return self.marionette._send_message('getContext', 'value')
+
+    def test_set_different_context_using_with_block(self):
+        with self.marionette.using_context(self.chrome):
+            self.assertEquals(self.get_context(), self.chrome)
+        self.assertEquals(self.get_context(), self.content)
+
+    def test_set_same_context_using_with_block(self):
+        with self.marionette.using_context(self.content):
+            self.assertEquals(self.get_context(), self.content)
+        self.assertEquals(self.get_context(), self.content)
+
+    def test_nested_with_blocks(self):
+        with self.marionette.using_context(self.chrome):
+            self.assertEquals(self.get_context(), self.chrome)
+            with self.marionette.using_context(self.content):
+                self.assertEquals(self.get_context(), self.content)
+            self.assertEquals(self.get_context(), self.chrome)
+        self.assertEquals(self.get_context(), self.content)
+
+    def test_set_scope_while_in_with_block(self):
+        with self.marionette.using_context(self.chrome):
+            self.assertEquals(self.get_context(), self.chrome)
+            self.marionette.set_context(self.content)
+            self.assertEquals(self.get_context(), self.content)
+        self.assertEquals(self.get_context(), self.content)
+
+    def test_exception_raised_while_in_with_block_is_propagated(self):
+        with self.assertRaises(MarionetteException):
+            with self.marionette.using_context(self.chrome):
+                raise MarionetteException
+        self.assertEquals(self.get_context(), self.content)
--- a/testing/marionette/client/marionette/tests/unit/unit-tests.ini
+++ b/testing/marionette/client/marionette/tests/unit/unit-tests.ini
@@ -128,8 +128,9 @@ browser = false
 
 [test_execute_isolate.py]
 [test_click_scrolling.py]
 [test_profile_management.py]
 b2g = false
 [test_set_window_size.py]
 b2g = false
 skip-if = os == "linux" # Bug 1085717
+[test_with_using_context.py]
--- a/testing/marionette/marionette-server.js
+++ b/testing/marionette/marionette-server.js
@@ -694,16 +694,24 @@ MarionetteServerConnection.prototype = {
     }
     else {
       this.context = context;
       this.sendOk(this.command_id);
     }
   },
 
   /**
+   * Gets the context of the server, either 'chrome' or 'content'.
+   */
+  getContext: function MDA_getContext() {
+    this.command_id = this.getCommandId();
+    this.sendResponse(this.context, this.command_id);
+  },
+
+  /**
    * Returns a chrome sandbox that can be used by the execute_foo functions.
    *
    * @param nsIDOMWindow aWindow
    *        Window in which we will execute code
    * @param Marionette marionette
    *        Marionette test instance
    * @param object args
    *        Client given args
@@ -2730,16 +2738,17 @@ MarionetteServerConnection.prototype = {
 MarionetteServerConnection.prototype.requestTypes = {
   "getMarionetteID": MarionetteServerConnection.prototype.getMarionetteID,
   "sayHello": MarionetteServerConnection.prototype.sayHello,
   "newSession": MarionetteServerConnection.prototype.newSession,
   "getSessionCapabilities": MarionetteServerConnection.prototype.getSessionCapabilities,
   "log": MarionetteServerConnection.prototype.log,
   "getLogs": MarionetteServerConnection.prototype.getLogs,
   "setContext": MarionetteServerConnection.prototype.setContext,
+  "getContext": MarionetteServerConnection.prototype.getContext,
   "executeScript": MarionetteServerConnection.prototype.execute,
   "setScriptTimeout": MarionetteServerConnection.prototype.setScriptTimeout,
   "timeouts": MarionetteServerConnection.prototype.timeouts,
   "singleTap": MarionetteServerConnection.prototype.singleTap,
   "actionChain": MarionetteServerConnection.prototype.actionChain,
   "multiAction": MarionetteServerConnection.prototype.multiAction,
   "executeAsyncScript": MarionetteServerConnection.prototype.executeWithCallback,
   "executeJSScript": MarionetteServerConnection.prototype.executeJSScript,
--- a/testing/xpcshell/moz-http2/moz-http2.js
+++ b/testing/xpcshell/moz-http2/moz-http2.js
@@ -80,16 +80,18 @@ var m = {
     } else {
       res.end();
     }
   }
 };
 
 var h11required_conn = null;
 var h11required_header = "yes";
+var didRst = false;
+var rstConnection = null;
 
 function handleRequest(req, res) {
   var u = url.parse(req.url);
   var content = getHttpContent(u.pathname);
   var push, push1, push1a, push2, push3;
 
   if (req.httpVersionMajor === 2) {
     res.setHeader('X-Connection-Http2', 'yes');
@@ -257,16 +259,36 @@ function handleRequest(req, res) {
       }
       res.stream.connection.close('HTTP_1_1_REQUIRED', res.stream.id - 2);
       return;
     } else {
       res.setHeader('X-H11Required-Stream-Ok', h11required_header);
     }
   }
 
+  else if (u.pathname === "/rstonce") {
+    if (!didRst) {
+      didRst = true;
+      rstConnection = req.stream.connection;
+      req.stream.reset('REFUSED_STREAM');
+      return;
+    }
+
+    if (rstConnection === null ||
+        rstConnection !== req.stream.connection) {
+      res.writeHead(400);
+      res.end("WRONG CONNECTION, HOMIE!");
+      return;
+    }
+
+    res.writeHead(200);
+    res.end("It's all good.");
+    return;
+  }
+
   res.setHeader('Content-Type', 'text/html');
   res.writeHead(200);
   res.end(content);
 }
 
 // Set up the SSL certs for our server
 var options = {
   key: fs.readFileSync(__dirname + '/../moz-spdy/spdy-key.pem'),
--- a/toolkit/components/downloads/nsDownloadManager.cpp
+++ b/toolkit/components/downloads/nsDownloadManager.cpp
@@ -3321,33 +3321,55 @@ nsDownload::ExecuteDesiredAction()
 
   // Assume an unknown action is save to disk
   nsHandlerInfoAction action = nsIMIMEInfo::saveToDisk;
   if (mMIMEInfo) {
     nsresult rv = mMIMEInfo->GetPreferredAction(&action);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
-  nsresult retVal = NS_OK;
+  nsresult rv = NS_OK;
   switch (action) {
     case nsIMIMEInfo::saveToDisk:
       // Move the file to the proper location
-      retVal = MoveTempToTarget();
+      rv = MoveTempToTarget();
+      if (NS_SUCCEEDED(rv)) {
+        rv = FixTargetPermissions();
+      }
       break;
     case nsIMIMEInfo::useHelperApp:
     case nsIMIMEInfo::useSystemDefault:
       // For these cases we have to move the file to the target location and
       // open with the appropriate application
-      retVal = OpenWithApplication();
+      rv = OpenWithApplication();
       break;
     default:
       break;
   }
 
-  return retVal;
+  return rv;
+}
+
+nsresult
+nsDownload::FixTargetPermissions()
+{
+  nsCOMPtr<nsIFile> target;
+  nsresult rv = GetTargetFile(getter_AddRefs(target));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Set perms according to umask.
+  nsCOMPtr<nsIPropertyBag2> infoService =
+      do_GetService("@mozilla.org/system-info;1");
+  uint32_t gUserUmask = 0;
+  rv = infoService->GetPropertyAsUint32(NS_LITERAL_STRING("umask"),
+                                        &gUserUmask);
+  if (NS_SUCCEEDED(rv)) {
+    rv = target->SetPermissions(0666 & ~gUserUmask);
+  }
+  return rv;
 }
 
 nsresult
 nsDownload::MoveTempToTarget()
 {
   nsCOMPtr<nsIFile> target;
   nsresult rv = GetTargetFile(getter_AddRefs(target));
   NS_ENSURE_SUCCESS(rv, rv);
@@ -3363,39 +3385,31 @@ nsDownload::MoveTempToTarget()
   // Extract the new leaf name from the file location
   nsAutoString fileName;
   rv = target->GetLeafName(fileName);
   NS_ENSURE_SUCCESS(rv, rv);
   nsCOMPtr<nsIFile> dir;
   rv = target->GetParent(getter_AddRefs(dir));
   NS_ENSURE_SUCCESS(rv, rv);
   rv = mTempFile->MoveTo(dir, fileName);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  return NS_OK;
+  return rv;
 }
 
 nsresult
 nsDownload::OpenWithApplication()
 {
   // First move the temporary file to the target location
   nsCOMPtr<nsIFile> target;
   nsresult rv = GetTargetFile(getter_AddRefs(target));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Move the temporary file to the target location
   rv = MoveTempToTarget();
   NS_ENSURE_SUCCESS(rv, rv);
 
-  // We do not verify the return value here because, irrespective of success
-  // or failure of the method, the deletion of temp file has to take place, as
-  // per the corresponding preference. But we store this separately as this is
-  // what we ultimately return from this function.
-  nsresult retVal = mMIMEInfo->LaunchWithFile(target);
-
   bool deleteTempFileOnExit;
   nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
   if (!prefs || NS_FAILED(prefs->GetBoolPref(PREF_BH_DELETETEMPFILEONEXIT,
                                              &deleteTempFileOnExit))) {
     // No prefservice or no pref set; use default value
 #if !defined(XP_MACOSX)
     // Mac users have been very verbal about temp files being deleted on
     // app exit - they don't like it - but we'll continue to do this on
@@ -3404,33 +3418,37 @@ nsDownload::OpenWithApplication()
 #else
     deleteTempFileOnExit = false;
 #endif
   }
 
   // Always schedule files to be deleted at the end of the private browsing
   // mode, regardless of the value of the pref.
   if (deleteTempFileOnExit || mPrivate) {
+
+    // Make the tmp file readonly so users won't lose changes.
+    target->SetPermissions(0400);
+
     // Use the ExternalHelperAppService to push the temporary file to the list
     // of files to be deleted on exit.
     nsCOMPtr<nsPIExternalAppLauncher> appLauncher(do_GetService
                     (NS_EXTERNALHELPERAPPSERVICE_CONTRACTID));
 
     // Even if we are unable to get this service we return the result
     // of LaunchWithFile() which makes more sense.
     if (appLauncher) {
       if (mPrivate) {
         (void)appLauncher->DeleteTemporaryPrivateFileWhenPossible(target);
       } else {
         (void)appLauncher->DeleteTemporaryFileOnExit(target);
       }
     }
   }
 
-  return retVal;
+  return mMIMEInfo->LaunchWithFile(target);
 }
 
 void
 nsDownload::SetStartTime(int64_t aStartTime)
 {
   mStartTime = aStartTime;
   mLastUpdate = aStartTime;
 }
--- a/toolkit/components/downloads/nsDownloadManager.h
+++ b/toolkit/components/downloads/nsDownloadManager.h
@@ -303,16 +303,21 @@ protected:
 
   /**
    * Move the temporary file to the final destination by removing the existing
    * dummy target and renaming the temporary.
    */
   nsresult MoveTempToTarget();
 
   /**
+   * Set the target file permissions to be appropriate.
+   */
+  nsresult FixTargetPermissions();
+
+  /**
    * Update the start time which also implies the last update time is the same.
    */
   void SetStartTime(int64_t aStartTime);
 
   /**
    * Update the amount of bytes transferred and max bytes; and recalculate the
    * download percent.
    */
--- a/toolkit/components/jsdownloads/src/DownloadIntegration.jsm
+++ b/toolkit/components/jsdownloads/src/DownloadIntegration.jsm
@@ -607,25 +607,39 @@ this.DownloadIntegration = {
           // specific error.
           if (!(ex instanceof OS.File.Error) || ex.winLastError != 123) {
             Cu.reportError(ex);
           }
         }
       }
 #endif
 
-      // Now that the file is completely downloaded, make it accessible by other
-      // users on this system.  On Unix, the umask of the process is respected.
-      // This call has no effect on Windows.
+      // The file with the partially downloaded data has restrictive permissions
+      // that don't allow other users on the system to access it.  Now that the
+      // download is completed, we need to adjust permissions based on whether
+      // this is a permanently downloaded file or a temporary download to be
+      // opened read-only with an external application.
       try {
-        yield OS.File.setPermissions(aDownload.target.path,
-                                     { unixMode: 0o666 });
+        // The following logic to determine whether this is a temporary download
+        // is due to the fact that "deleteTempFileOnExit" is false on Mac, where
+        // downloads to be opened with external applications are preserved in
+        // the "Downloads" folder like normal downloads.
+        let isTemporaryDownload =
+          aDownload.launchWhenSucceeded && (aDownload.source.isPrivate ||
+          Services.prefs.getBoolPref("browser.helperApps.deleteTempFileOnExit"));
+        // Permanently downloaded files are made accessible by other users on
+        // this system, while temporary downloads are marked as read-only.
+        let unixMode = isTemporaryDownload ? 0o400 : 0o666;
+        // On Unix, the umask of the process is respected.  This call has no
+        // effect on Windows.
+        yield OS.File.setPermissions(aDownload.target.path, { unixMode });
       } catch (ex) {
-        // Errors with making the permissions less restrictive should be
-        // reported, but should not prevent the download from completing.
+        // We should report errors with making the permissions less restrictive
+        // or marking the file as read-only on Unix and Mac, but this should not
+        // prevent the download from completing.
         Cu.reportError(ex);
       }
 
       gDownloadPlatform.downloadDone(NetUtil.newURI(aDownload.source.url),
                                      new FileUtils.File(aDownload.target.path),
                                      aDownload.contentType,
                                      aDownload.source.isPrivate);
       this.downloadDoneCalled = true;
--- a/toolkit/components/jsdownloads/test/unit/common_test_Download.js
+++ b/toolkit/components/jsdownloads/test/unit/common_test_Download.js
@@ -9,16 +9,18 @@
  * the "copy" and "legacy" saver implementations.
  */
 
 "use strict";
 
 ////////////////////////////////////////////////////////////////////////////////
 //// Globals
 
+const kDeleteTempFileOnExit = "browser.helperApps.deleteTempFileOnExit";
+
 /**
  * Creates and starts a new download, using either DownloadCopySaver or
  * DownloadLegacySaver based on the current test run.
  *
  * @return {Promise}
  * @resolves The newly created Download object.  The download may be in progress
  *           or already finished.  The promiseDownloadStopped function can be
  *           used to wait for completion.
@@ -165,31 +167,65 @@ add_task(function test_basic_tryToKeepPa
                               TEST_DATA_SHORT + TEST_DATA_SHORT);
   do_check_false(yield OS.File.exists(download.target.partFilePath));
   do_check_eq(32, download.saver.getSha256Hash().length);
 });
 
 /**
  * Tests the permissions of the final target file once the download finished.
  */
-add_task(function test_basic_unix_permissions()
+add_task(function test_unix_permissions()
 {
   // This test is only executed on Linux and Mac.
   if (Services.appinfo.OS != "Darwin" && Services.appinfo.OS != "Linux") {
-    do_print("Skipping test_basic_unix_permissions");
+    do_print("Skipping test.");
     return;
   }
 
-  let download = yield promiseStartDownload(httpUrl("source.txt"));
-  yield promiseDownloadStopped(download);
+  let launcherPath = getTempFile("app-launcher").path;
+
+  for (let autoDelete of [false, true]) {
+    for (let isPrivate of [false, true]) {
+      for (let launchWhenSucceeded of [false, true]) {
+        do_print("Checking " + JSON.stringify({ autoDelete,
+                                                isPrivate,
+                                                launchWhenSucceeded }));
+
+        Services.prefs.setBoolPref(kDeleteTempFileOnExit, autoDelete);
 
-  // The file should readable and writable by everyone, but the restrictions
-  // from the umask of the process should still apply.
-  do_check_eq((yield OS.File.stat(download.target.path)).unixMode,
-              0o666 & ~OS.Constants.Sys.umask);
+        let download;
+        if (!gUseLegacySaver) {
+          download = yield Downloads.createDownload({
+            source: { url: httpUrl("source.txt"), isPrivate },
+            target: getTempFile(TEST_TARGET_FILE_NAME).path,
+            launchWhenSucceeded,
+            launcherPath,
+          });
+          yield download.start();
+        } else {
+          download = yield promiseStartLegacyDownload(httpUrl("source.txt"), {
+            isPrivate,
+            launchWhenSucceeded,
+            launcherPath: launchWhenSucceeded && launcherPath,
+          });
+          yield promiseDownloadStopped(download);
+        }
+
+        // Temporary downloads should be read-only and not accessible to other
+        // users, while permanently downloaded files should be readable and
+        // writable as specified by the system umask.
+        let isTemporary = launchWhenSucceeded && (autoDelete || isPrivate);
+        do_check_eq((yield OS.File.stat(download.target.path)).unixMode,
+                    isTemporary ? 0o400 : (0o666 & ~OS.Constants.Sys.umask));
+      }
+    }
+  }
+
+  // Clean up the changes to the preference.
+  Services.prefs.clearUserPref(kDeleteTempFileOnExit);
 });
 
 /**
  * Checks the referrer for downloads.
  */
 add_task(function test_referrer()
 {
   let sourcePath = "/test_referrer.txt";
@@ -769,16 +805,23 @@ add_task(function test_cancel_midway_res
 
   yield promiseDownloadMidway(download);
   yield promisePartFileReady(download);
 
   // While the download is in progress, we should still have a ".part" file.
   do_check_false(download.hasPartialData);
   do_check_true(yield OS.File.exists(download.target.partFilePath));
 
+  // On Unix, verify that the file with the partially downloaded data is not
+  // accessible by other users on the system.
+  if (Services.appinfo.OS == "Darwin" || Services.appinfo.OS == "Linux") {
+    do_check_eq((yield OS.File.stat(download.target.partFilePath)).unixMode,
+                0o600);
+  }
+
   yield download.cancel();
 
   // The ".part" file should be deleted now that the download is canceled.
   do_check_false(download.hasPartialData);
   do_check_false(yield OS.File.exists(download.target.partFilePath));
 
   // The third time, we'll request and obtain the entire response again.
   continueResponses();
--- a/uriloader/exthandler/nsExternalHelperAppService.cpp
+++ b/uriloader/exthandler/nsExternalHelperAppService.cpp
@@ -1449,17 +1449,17 @@ nsresult nsExternalAppHandler::SetUpTemp
 
   // Add an additional .part to prevent the OS from running this file in the
   // default application.
   tempLeafName.AppendLiteral(".part");
 
   rv = mTempFile->Append(NS_ConvertUTF8toUTF16(tempLeafName));
   // make this file unique!!!
   NS_ENSURE_SUCCESS(rv, rv);
-  rv = mTempFile->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0644);
+  rv = mTempFile->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0600);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Now save the temp leaf name, minus the ".part" bit, so we can use it later.
   // This is a bit broken in the case when createUnique actually had to append
   // some numbers, because then we now have a filename like foo.bar-1.part and
   // we'll end up with foo.bar-1.bar as our final filename if we end up using
   // this.  But the other options are all bad too....  Ideally we'd have a way
   // to tell createUnique to put its unique marker before the extension that
@@ -2396,17 +2396,17 @@ NS_IMETHODIMP nsExternalAppHandler::Laun
   }
 
 #ifdef XP_WIN
   fileToUse->Append(mSuggestedFileName + mTempFileExtension);
 #else
   fileToUse->Append(mSuggestedFileName);  
 #endif
 
-  nsresult rv = fileToUse->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0644);
+  nsresult rv = fileToUse->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0600);
   if(NS_SUCCEEDED(rv)) {
     mFinalFileDestination = do_QueryInterface(fileToUse);
     // launch the progress window now that the user has picked the desired action.
     rv = CreateTransfer();
     if (NS_FAILED(rv)) {
       Cancel(rv);
     }
   } else {
--- a/widget/cocoa/nsChildView.h
+++ b/widget/cocoa/nsChildView.h
@@ -578,17 +578,16 @@ public:
 
   NS_IMETHOD        ReparentNativeWidget(nsIWidget* aNewParent);
 
   mozilla::widget::TextInputHandler* GetTextInputHandler()
   {
     return mTextInputHandler;
   }
 
-  void              NotifyDirtyRegion(const nsIntRegion& aDirtyRegion);
   void              ClearVibrantAreas();
   NSColor*          VibrancyFillColorForWidgetType(uint8_t aWidgetType);
   NSColor*          VibrancyFontSmoothingBackgroundColorForWidgetType(uint8_t aWidgetType);
 
   // unit conversion convenience functions
   int32_t           CocoaPointsToDevPixels(CGFloat aPts) const {
     return nsCocoaUtils::CocoaPointsToDevPixels(aPts, BackingScaleFactor());
   }
--- a/widget/cocoa/nsChildView.mm
+++ b/widget/cocoa/nsChildView.mm
@@ -2116,25 +2116,16 @@ nsChildView::NewCompositorParent(int aSu
       [EventThreadRunner start];
     }
     gNumberOfWidgetsNeedingEventThread++;
   }
 
   return compositor;
 }
 
-void
-nsChildView::NotifyDirtyRegion(const nsIntRegion& aDirtyRegion)
-{
-  if ([(ChildView*)mView isCoveringTitlebar]) {
-    // We store the dirty region so that we know what to repaint in the titlebar.
-    mDirtyTitlebarRegion.Or(mDirtyTitlebarRegion, aDirtyRegion);
-  }
-}
-
 nsIntRect
 nsChildView::RectContainingTitlebarControls()
 {
   // Start with a thin strip at the top of the window for the highlight line.
   NSRect rect = NSMakeRect(0, 0, [mView bounds].size.width,
                            [(ChildView*)mView cornerRadius]);
 
   // Add the rects of the titlebar controls.
@@ -2338,57 +2329,50 @@ CreateCGContext(const nsIntSize& aSize)
 
   return ctx;
 }
 
 // When this method is entered, mEffectsLock is already being held.
 void
 nsChildView::UpdateTitlebarCGContext()
 {
-  nsIntRegion dirtyTitlebarRegion;
-  dirtyTitlebarRegion.And(mDirtyTitlebarRegion, mTitlebarRect);
-  mDirtyTitlebarRegion.SetEmpty();
-
   if (mTitlebarRect.IsEmpty()) {
     ReleaseTitlebarCGContext();
     return;
   }
 
+  NSRect titlebarRect = DevPixelsToCocoaPoints(mTitlebarRect);
+  NSRect dirtyRect = [mView convertRect:[(BaseWindow*)[mView window] getAndResetNativeDirtyRect] fromView:nil];
+  NSRect dirtyTitlebarRect = NSIntersectionRect(titlebarRect, dirtyRect);
+
   nsIntSize texSize = RectTextureImage::TextureSizeForSize(mTitlebarRect.Size());
   if (!mTitlebarCGContext ||
       CGBitmapContextGetWidth(mTitlebarCGContext) != size_t(texSize.width) ||
       CGBitmapContextGetHeight(mTitlebarCGContext) != size_t(texSize.height)) {
-    dirtyTitlebarRegion = mTitlebarRect;
+    dirtyTitlebarRect = titlebarRect;
 
     ReleaseTitlebarCGContext();
 
     mTitlebarCGContext = CreateCGContext(texSize);
   }
 
-  if (dirtyTitlebarRegion.IsEmpty())
+  if (NSIsEmptyRect(dirtyTitlebarRect)) {
     return;
+  }
 
   CGContextRef ctx = mTitlebarCGContext;
 
   CGContextSaveGState(ctx);
 
-  nsTArray<CGRect> rects;
-  nsIntRegionRectIterator iter(dirtyTitlebarRegion);
-  for (;;) {
-    const nsIntRect* r = iter.Next();
-    if (!r)
-      break;
-    rects.AppendElement(CGRectMake(r->x, r->y, r->width, r->height));
-  }
-  CGContextClipToRects(ctx, rects.Elements(), rects.Length());
-
-  CGContextClearRect(ctx, CGRectMake(0, 0, texSize.width, texSize.height));
-
   double scale = BackingScaleFactor();
   CGContextScaleCTM(ctx, scale, scale);
+
+  CGContextClipToRect(ctx, NSRectToCGRect(dirtyTitlebarRect));
+  CGContextClearRect(ctx, NSRectToCGRect(dirtyTitlebarRect));
+
   NSGraphicsContext* oldContext = [NSGraphicsContext currentContext];
 
   CGContextSaveGState(ctx);
 
   BaseWindow* window = (BaseWindow*)[mView window];
   NSView* frameView = [[window contentView] superview];
   if (![frameView isFlipped]) {
     CGContextTranslateCTM(ctx, 0, [frameView bounds].size.height);
@@ -2400,18 +2384,18 @@ nsChildView::UpdateTitlebarCGContext()
   // Draw the title string.
   if ([window wantsTitleDrawn] && [frameView respondsToSelector:@selector(_drawTitleBar:)]) {
     [frameView _drawTitleBar:[frameView bounds]];
   }
 
   // Draw the titlebar controls into the titlebar image.
   for (id view in [window titlebarControls]) {
     NSRect viewFrame = [view frame];
-    nsIntRect viewRect = CocoaPointsToDevPixels([mView convertRect:viewFrame fromView:frameView]);
-    if (!dirtyTitlebarRegion.Intersects(viewRect)) {
+    NSRect viewRect = [mView convertRect:viewFrame fromView:frameView];
+    if (!NSIntersectsRect(dirtyTitlebarRect, viewRect)) {
       continue;
     }
     // All of the titlebar controls we're interested in are subclasses of
     // NSButton.
     if (![view isKindOfClass:[NSButton class]]) {
       continue;
     }
     NSButton *button = (NSButton *) view;
@@ -2461,17 +2445,17 @@ nsChildView::UpdateTitlebarCGContext()
 
   DrawTitlebarHighlight([frameView bounds].size, [(ChildView*)mView cornerRadius],
                         DevPixelsToCocoaPoints(1));
 
   [NSGraphicsContext setCurrentContext:oldContext];
 
   CGContextRestoreGState(ctx);
 
-  mUpdatedTitlebarRegion.Or(mUpdatedTitlebarRegion, dirtyTitlebarRegion);
+  mUpdatedTitlebarRegion.OrWith(CocoaPointsToDevPixels(dirtyTitlebarRect));
 }
 
 // This method draws an overlay in the top of the window which contains the
 // titlebar controls (e.g. close, min, zoom, fullscreen) and the titlebar
 // highlight effect.
 // This is necessary because the real titlebar controls are covered by our
 // OpenGL context. Note that in terms of the NSView hierarchy, our ChildView
 // is actually below the titlebar controls - that's why hovering and clicking
@@ -4097,21 +4081,16 @@ NSEvent* gLastDragMouseDownEvent = nil;
       NS_ADDREF(mGeckoChild);
       [widgetArray addObject:[NSNumber numberWithUnsignedInteger:(NSUInteger)mGeckoChild]];
       [self performSelector:@selector(releaseWidgets:)
                  withObject:widgetArray
                  afterDelay:0];
     }
 
     if ([self isUsingOpenGL]) {
-      // When our view covers the titlebar, we need to repaint the titlebar
-      // texture buffer when, for example, the window buttons are hovered.
-      // So we notify our nsChildView about any areas needing repainting.
-      mGeckoChild->NotifyDirtyRegion([self nativeDirtyRegionWithBoundingRect:[self bounds]]);
-
       if (mGeckoChild->GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_CLIENT) {
         ClientLayerManager *manager = static_cast<ClientLayerManager*>(mGeckoChild->GetLayerManager());
         manager->AsShadowForwarder()->WindowOverlayChanged();
       }
     }
 
     mGeckoChild->WillPaintWindow();
   }
--- a/widget/cocoa/nsCocoaWindow.h
+++ b/widget/cocoa/nsCocoaWindow.h
@@ -72,16 +72,18 @@ typedef struct _nsCocoaWindowList {
 
   // DPI cache. Getting the physical screen size (CGDisplayScreenSize)
   // is ridiculously slow, so we cache it in the toplevel window for all
   // descendants to use.
   float mDPI;
 
   NSTrackingArea* mTrackingArea;
 
+  NSRect mDirtyRect;
+
   BOOL mBeingShown;
   BOOL mDrawTitle;
   BOOL mBrightTitlebarForeground;
 }
 
 - (void)importState:(NSDictionary*)aState;
 - (NSMutableDictionary*)exportState;
 - (void)setDrawsContentsIntoWindowFrame:(BOOL)aState;
@@ -111,16 +113,18 @@ typedef struct _nsCocoaWindowList {
 - (BOOL)wantsTitleDrawn;
 
 - (void)setUseBrightTitlebarForeground:(BOOL)aBrightForeground;
 - (BOOL)useBrightTitlebarForeground;
 
 - (void)disableSetNeedsDisplay;
 - (void)enableSetNeedsDisplay;
 
+- (NSRect)getAndResetNativeDirtyRect;
+
 @end
 
 @interface NSWindow (Undocumented)
 
 // If a window has been explicitly removed from the "window cache" (to
 // deactivate it), it's sometimes necessary to "reset" it to reactivate it
 // (and put it back in the "window cache").  One way to do this, which Apple
 // often uses, is to set the "window number" to '-1' and then back to its
--- a/widget/cocoa/nsCocoaWindow.mm
+++ b/widget/cocoa/nsCocoaWindow.mm
@@ -2645,16 +2645,17 @@ static NSMutableSet *gSwizzledFrameViewC
   [super initWithContentRect:aContentRect styleMask:aStyle backing:aBufferingType defer:aFlag];
   mState = nil;
   mActiveTitlebarColor = nil;
   mInactiveTitlebarColor = nil;
   mScheduledShadowInvalidation = NO;
   mDisabledNeedsDisplay = NO;
   mDPI = GetDPI(self);
   mTrackingArea = nil;
+  mDirtyRect = NSZeroRect;
   mBeingShown = NO;
   mDrawTitle = NO;
   mBrightTitlebarForeground = NO;
   [self updateTrackingArea];
 
   return self;
 }
 
@@ -2866,19 +2867,27 @@ static const NSString* kStateShowsToolba
 - (void)_setNeedsDisplayInRect:(NSRect)aRect
 {
   // Prevent unnecessary invalidations due to moving NSViews (e.g. for plugins)
   if (!mDisabledNeedsDisplay) {
     // This method is only called by Cocoa, so when we're here, we know that
     // it's available and don't need to check whether our superclass responds
     // to the selector.
     [super _setNeedsDisplayInRect:aRect];
+    mDirtyRect = NSUnionRect(mDirtyRect, aRect);
   }
 }
 
+- (NSRect)getAndResetNativeDirtyRect
+{
+  NSRect dirtyRect = mDirtyRect;
+  mDirtyRect = NSZeroRect;
+  return dirtyRect;
+}
+
 - (void)updateContentViewSize
 {
   NSRect rect = [self contentRectForFrameRect:[self frame]];
   [[self contentView] setFrameSize:rect.size];
 }
 
 // Possibly move the titlebar buttons.
 - (void)reflowTitlebarElements
--- a/xpfe/components/autocomplete/resources/content/autocomplete.xml
+++ b/xpfe/components/autocomplete/resources/content/autocomplete.xml
@@ -1326,17 +1326,17 @@
 
       <handler event="mousedown" phase="capturing"
                action="if ( !this.mMenuOpen ) this.finishAutoComplete(false, false, event);"/>
     </handlers>
   </binding>
 
   <binding id="autocomplete-result-popup" extends="chrome://global/content/bindings/popup.xml#popup">
     <resources>
-      <stylesheet src="chrome://global/content/autocomplete.css"/>
+      <stylesheet src="chrome://communicator/content/autocomplete.css"/>
       <stylesheet src="chrome://global/skin/autocomplete.css"/>
     </resources>
 
     <content ignorekeys="true" level="top">
       <xul:tree anonid="tree" class="autocomplete-tree plain" flex="1">
         <xul:treecols anonid="treecols">
           <xul:treecol class="autocomplete-treecol" id="treecolAutoCompleteValue" flex="2"/>
           <xul:treecol class="autocomplete-treecol" id="treecolAutoCompleteComment" flex="1" hidden="true"/>
@@ -1593,17 +1593,17 @@
         }
       ]]></handler>
     </handlers>
   </binding>
 
   <binding id="autocomplete-history-popup"
            extends="chrome://global/content/bindings/popup.xml#popup-scrollbars">
     <resources>
-      <stylesheet src="chrome://global/content/autocomplete.css"/>
+      <stylesheet src="chrome://communicator/content/autocomplete.css"/>
       <stylesheet src="chrome://global/skin/autocomplete.css"/>
     </resources>
 
     <implementation>
       <method name="removeOpenAttribute">
         <parameter name="parentNode"/>
         <body><![CDATA[
           parentNode.removeAttribute("open");