Merge inbound to m-c a=merge
authorWes Kocher <wkocher@mozilla.com>
Fri, 22 Aug 2014 16:47:32 -0700
changeset 222792 64c4ec2df3d40da04e5213efa9a6f09539e2aa0c
parent 222696 bde9525e91912d5ca5641641414fd3999440ca03 (current diff)
parent 222791 9f2e00997d30ffbfd210226a0c500bbcb977e7fa (diff)
child 222793 84e8790a5785c9205259214a13a094c1adf0b992
child 222804 70512ae817cbb7d4fcee5f8cf3576ed0246644f3
child 222857 74e1bdee5f6e0c203f98646d219b6d4bd3f6092a
child 222908 09ee525ce99d6a3c791d9dd0b113316f6515827a
push id3979
push userraliiev@mozilla.com
push dateMon, 13 Oct 2014 16:35:44 +0000
treeherdermozilla-beta@30f2cc610691 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone34.0a1
first release with
nightly linux32
64c4ec2df3d4 / 34.0a1 / 20140823030201 / files
nightly linux64
64c4ec2df3d4 / 34.0a1 / 20140823030201 / files
nightly mac
64c4ec2df3d4 / 34.0a1 / 20140823030201 / files
nightly win32
64c4ec2df3d4 / 34.0a1 / 20140823030201 / files
nightly win64
64c4ec2df3d4 / 34.0a1 / 20140823030201 / 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
content/media/BufferDecoder.cpp
content/media/BufferDecoder.h
content/media/mediasource/SubBufferDecoder.cpp
content/media/mediasource/SubBufferDecoder.h
dom/ipc/TabChild.cpp
netwerk/test/unit/test_force_sniffing.js
--- a/accessible/base/AccCollector.h
+++ b/accessible/base/AccCollector.h
@@ -66,17 +66,17 @@ private:
   AccCollector(const AccCollector&);
   AccCollector& operator =(const AccCollector&);
 };
 
 /**
  * Collect embedded objects. Provide quick access to accessible by index and
  * vice versa.
  */
-class EmbeddedObjCollector : public AccCollector
+class EmbeddedObjCollector MOZ_FINAL : public AccCollector
 {
 public:
   virtual ~EmbeddedObjCollector() { }
 
 public:
   virtual int32_t GetIndexAt(Accessible* aAccessible);
 
 protected:
--- a/accessible/base/NotificationController.h
+++ b/accessible/base/NotificationController.h
@@ -80,18 +80,18 @@ private:
   Class* mInstance;
   Callback mCallback;
   nsRefPtr<Arg> mArg;
 };
 
 /**
  * Used to process notifications from core for the document accessible.
  */
-class NotificationController : public EventQueue,
-                               public nsARefreshObserver
+class NotificationController MOZ_FINAL : public EventQueue,
+                                         public nsARefreshObserver
 {
 public:
   NotificationController(DocAccessible* aDocument, nsIPresShell* aPresShell);
 
   NS_IMETHOD_(MozExternalRefCountType) AddRef(void);
   NS_IMETHOD_(MozExternalRefCountType) Release(void);
 
   NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(NotificationController)
--- a/accessible/base/nsAccessibilityService.h
+++ b/accessible/base/nsAccessibilityService.h
@@ -36,21 +36,21 @@ SelectionManager* SelectionMgr();
 /**
  * Returns the application accessible.
  */
 ApplicationAccessible* ApplicationAcc();
 
 } // namespace a11y
 } // namespace mozilla
 
-class nsAccessibilityService : public mozilla::a11y::DocManager,
-                               public mozilla::a11y::FocusManager,
-                               public mozilla::a11y::SelectionManager,
-                               public nsIAccessibilityService,
-                               public nsIObserver
+class nsAccessibilityService MOZ_FINAL : public mozilla::a11y::DocManager,
+                                         public mozilla::a11y::FocusManager,
+                                         public mozilla::a11y::SelectionManager,
+                                         public nsIAccessibilityService,
+                                         public nsIObserver
 {
 public:
   typedef mozilla::a11y::Accessible Accessible;
   typedef mozilla::a11y::DocAccessible DocAccessible;
 
 protected:
   virtual ~nsAccessibilityService();
 
--- a/accessible/generic/OuterDocAccessible.h
+++ b/accessible/generic/OuterDocAccessible.h
@@ -15,17 +15,17 @@ namespace a11y {
  * Used for <browser>, <frame>, <iframe>, <page> or editor> elements.
  * 
  * In these variable names, "outer" relates to the OuterDocAccessible as
  * opposed to the DocAccessibleWrap which is "inner". The outer node is
  * a something like tags listed above, whereas the inner node corresponds to
  * the inner document root.
  */
 
-class OuterDocAccessible : public AccessibleWrap
+class OuterDocAccessible MOZ_FINAL : public AccessibleWrap
 {
 public:
   OuterDocAccessible(nsIContent* aContent, DocAccessible* aDoc);
 
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIAccessible
   NS_IMETHOD GetActionName(uint8_t aIndex, nsAString& aName);
--- a/accessible/html/HTMLFormControlAccessible.h
+++ b/accessible/html/HTMLFormControlAccessible.h
@@ -104,17 +104,17 @@ protected:
   virtual ENameValueFlag NativeName(nsString& aName) MOZ_OVERRIDE;
 };
 
 
 /**
  * Accessible for HTML input@type="text", input@type="password", textarea and
  * other HTML text controls.
  */
-class HTMLTextFieldAccessible : public HyperTextAccessibleWrap
+class HTMLTextFieldAccessible MOZ_FINAL : public HyperTextAccessibleWrap
 {
 
 public:
   enum { eAction_Click = 0 };
 
   HTMLTextFieldAccessible(nsIContent* aContent, DocAccessible* aDoc);
 
   NS_DECL_ISUPPORTS_INHERITED
--- a/accessible/html/HTMLImageMapAccessible.h
+++ b/accessible/html/HTMLImageMapAccessible.h
@@ -11,17 +11,17 @@
 #include "nsIDOMHTMLMapElement.h"
 
 namespace mozilla {
 namespace a11y {
 
 /**
  * Used for HTML image maps.
  */
-class HTMLImageMapAccessible : public ImageAccessibleWrap
+class HTMLImageMapAccessible MOZ_FINAL : public ImageAccessibleWrap
 {
 public:
   HTMLImageMapAccessible(nsIContent* aContent, DocAccessible* aDoc);
 
   // nsISupports and cycle collector
   NS_DECL_ISUPPORTS_INHERITED
 
   // Accessible
@@ -47,17 +47,17 @@ protected:
 
   // Accessible
   virtual void CacheChildren();
 };
 
 /**
  * Accessible for image map areas - must be child of image.
  */
-class HTMLAreaAccessible : public HTMLLinkAccessible
+class HTMLAreaAccessible MOZ_FINAL : public HTMLLinkAccessible
 {
 public:
 
   HTMLAreaAccessible(nsIContent* aContent, DocAccessible* aDoc);
 
   // Accessible
   virtual void Description(nsString& aDescription);
   virtual Accessible* ChildAtPoint(int32_t aX, int32_t aY,
--- a/accessible/html/HTMLSelectAccessible.h
+++ b/accessible/html/HTMLSelectAccessible.h
@@ -158,17 +158,17 @@ public:
 /**  Finally, the Combobox widgets                         */
 /** ------------------------------------------------------ */
 
 class HTMLComboboxListAccessible;
 
 /*
  * A class the represents the HTML Combobox widget.
  */
-class HTMLComboboxAccessible : public AccessibleWrap
+class HTMLComboboxAccessible MOZ_FINAL : public AccessibleWrap
 {
 public:
   enum { eAction_Click = 0 };
 
   HTMLComboboxAccessible(nsIContent* aContent, DocAccessible* aDoc);
   virtual ~HTMLComboboxAccessible() {}
 
   // nsIAccessible
--- a/accessible/xul/XULFormControlAccessible.h
+++ b/accessible/xul/XULFormControlAccessible.h
@@ -105,17 +105,17 @@ public:
 
 private:
   bool DropmarkerOpen(bool aToggleOpen);
 };
 
 /**
  * Used for XUL groupbox element.
  */
-class XULGroupboxAccessible : public AccessibleWrap
+class XULGroupboxAccessible MOZ_FINAL : public AccessibleWrap
 {
 public:
   XULGroupboxAccessible(nsIContent* aContent, DocAccessible* aDoc);
 
   // Accessible
   virtual mozilla::a11y::role NativeRole();
   virtual Relation RelationByType(RelationType aType) MOZ_OVERRIDE;
 
--- a/accessible/xul/XULTreeGridAccessible.h
+++ b/accessible/xul/XULTreeGridAccessible.h
@@ -67,17 +67,17 @@ protected:
     CreateTreeItemAccessible(int32_t aRow) const MOZ_OVERRIDE;
 };
 
 
 /**
  * Represents accessible for XUL tree item in the case when XUL tree has
  * multiple columns.
  */
-class XULTreeGridRowAccessible : public XULTreeItemAccessibleBase
+class XULTreeGridRowAccessible MOZ_FINAL : public XULTreeItemAccessibleBase
 {
 public:
   using Accessible::GetChildAt;
 
   XULTreeGridRowAccessible(nsIContent* aContent, DocAccessible* aDoc,
                            Accessible* aParent, nsITreeBoxObject* aTree,
                            nsITreeView* aTreeView, int32_t aRow);
 
--- a/browser/base/content/browser-plugins.js
+++ b/browser/base/content/browser-plugins.js
@@ -499,18 +499,17 @@ var gPluginHandler = {
     if (plugin) {
       let userComment = this.getPluginUI(plugin, "submitComment").value.trim();
       if (userComment)
         keyVals.PluginUserComment = userComment;
       if (this.getPluginUI(plugin, "submitURLOptIn").checked)
         keyVals.PluginContentURL = plugin.ownerDocument.URL;
     }
 
-    let pluginProcessType = Services.crashmanager.PROCESS_TYPE_PLUGIN;
-    this.CrashSubmit.submit(pluginDumpID, { processType: pluginProcessType,
+    this.CrashSubmit.submit(pluginDumpID, { recordSubmission: true,
                                             extraExtraKeyVals: keyVals });
     if (browserDumpID)
       this.CrashSubmit.submit(browserDumpID);
   },
 #endif
 
   // Callback for user clicking a "reload page" link
   reloadPage: function (browser) {
--- a/browser/base/content/test/general/browser_devices_get_user_media.js
+++ b/browser/base/content/test/general/browser_devices_get_user_media.js
@@ -431,16 +431,17 @@ let gTests = [
 
     PopupNotifications.getNotification("webRTC-sharingDevices").reshow();
     activateSecondaryAction(kActionDeny);
 
     yield promiseObserverCalled("recording-device-events");
     expectObserverCalled("getUserMedia:revoke");
 
     yield promiseNoPopupNotification("webRTC-sharingDevices");
+    expectObserverCalled("recording-window-ended");
 
     if (gObservedTopics["recording-device-events"] == 1) {
       todo(false, "Got the 'recording-device-events' notification twice, likely because of bug 962719");
       gObservedTopics["recording-device-events"] = 0;
     }
 
     expectNoObserverCalled();
     checkNotSharing();
@@ -704,16 +705,17 @@ let gTests = [
 
       // Stop sharing.
       activateSecondaryAction(kActionDeny);
 
       yield promiseObserverCalled("recording-device-events");
       expectObserverCalled("getUserMedia:revoke");
 
       yield promiseNoPopupNotification("webRTC-sharingDevices");
+      expectObserverCalled("recording-window-ended");
 
       if (gObservedTopics["recording-device-events"] == 1) {
         todo(false, "Got the 'recording-device-events' notification twice, likely because of bug 962719");
         gObservedTopics["recording-device-events"] = 0;
       }
 
       // Check that permissions have been removed as expected.
       let audioPerm = Perms.testExactPermission(uri, "microphone");
--- a/browser/components/loop/standalone/content/l10n/data.ini
+++ b/browser/components/loop/standalone/content/l10n/data.ini
@@ -1,40 +1,39 @@
+## LOCALIZATION NOTE: In this file, don't translate the part between {{..}}
 [en]
 call_has_ended=Your call has ended.
 call_timeout_notification_text=Your call did not go through.
 missing_conversation_info=Missing conversation information.
 network_disconnected=The network connection terminated abruptly.
 peer_ended_conversation=Your peer ended the conversation.
 unable_retrieve_call_info=Unable to retrieve conversation information.
 hangup_button_title=Hangup
 mute_local_audio_button_title=Mute your audio
 unmute_local_audio_button_title=Unute your audio
 mute_local_video_button_title=Mute your video
 unmute_local_video_button_title=Unmute your video
 start_call=Start the call
-welcome=Welcome to the Loop web client.
+welcome=Welcome to the {{clientShortname}} web client.
 incompatible_browser=Incompatible Browser
-powered_by_webrtc=The audio and video components of Loop are powered by WebRTC.
-use_latest_firefox.innerHTML=Please try this link in a WebRTC-enabled browser, such as <a href="{{ff_url}}">Firefox</a>.
+powered_by_webrtc=The audio and video components of {{clientShortname}} are powered by WebRTC.
+use_latest_firefox.innerHTML=Please try this link in a WebRTC-enabled browser, such as <a href="{{ff_url}}">{{brandShortname}}</a>.
 incompatible_device=Incompatible device
-sorry_device_unsupported=Sorry, Loop does not currently support your device.
-use_firefox_windows_mac_linux=Please open this page using the latest Firefox on Windows, Android, Mac or Linux.
+sorry_device_unsupported=Sorry, {{clientShortname}} does not currently support your device.
+use_firefox_windows_mac_linux=Please open this page using the latest {{brandShortname}} on Windows, Android, Mac or Linux.
 connection_error_see_console_notification=Call failed; see console for details.
 call_url_unavailable_notification_heading=Oops!
 call_url_unavailable_notification_message=This URL is unavailable.
-promote_firefox_hello_heading=Download Firefox to make free audio and video calls!
-get_firefox_button=Get Firefox
+promote_firefox_hello_heading=Download {{brandShortname}} to make free audio and video calls!
+get_firefox_button=Get {{brandShortname}}
 call_url_unavailable_notification=This URL is unavailable.
 initiate_call_button_label=Click Call to start a video chat
 initiate_audio_video_call_button=Call
 initiate_audio_video_call_tooltip=Start a video call
 initiate_audio_call_button=Voice call
-## LOCALIZATION NOTE (legal_text_and_links): In this item, don't translate the
-## part between {{..}}
 legal_text_and_links=By using this product you agree to the {{terms_of_use_url}} and {{privacy_notice_url}}
 terms_of_use_link_text=Terms of use
 privacy_notice_link_text=Privacy notice
 brandShortname=Firefox
 clientShortname=WebRTC!
 ## LOCALIZATION NOTE (call_url_creation_date_label): Example output: (from May 26, 2014)
 call_url_creation_date_label=(from {{call_url_creation_date}})
 
@@ -46,19 +45,19 @@ network_disconnected=La connexion réseau semble avoir été interrompue.
 peer_ended_conversation=Votre correspondant a mis fin à la communication.
 unable_retrieve_call_info=Impossible de récupérer les informations liées à cet appel.
 hangup_button_title=Terminer l'appel
 mute_local_audio_button_title=Couper la diffusion audio
 unmute_local_audio_button_title=Reprendre la diffusion audio
 mute_local_video_button_title=Couper la diffusion vidéo
 unmute_local_video_button_title=Reprendre la diffusion vidéo
 start_call=Démarrer l'appel
-welcome=Bienvenue sur Loop.
+welcome=Bienvenue sur {{clientShortname}}.
 incompatible_browser=Navigateur non supporté
-powered_by_webrtc=Les fonctionnalités audio et vidéo de Loop utilisent WebRTC.
-use_latest_firefox.innerHTML=Veuillez essayer ce lien dans un navigateur acceptant WebRTC, par exemple <a href="{{ff_url}}">Firefox</a>.
+powered_by_webrtc=Les fonctionnalités audio et vidéo de {{clientShortname}} utilisent WebRTC.
+use_latest_firefox.innerHTML=Veuillez essayer ce lien dans un navigateur acceptant WebRTC, par exemple <a href="{{ff_url}}">{{brandShortname}}</a>.
 incompatible_device=Plateforme non supportée
-sorry_device_unsupported=Désolé, Loop ne fonctionne actuellement pas sur votre appareil.
-use_firefox_windows_mac_linux=Merci d'ouvrir cette page avec une version récente de Firefox pour Windows, Android, Mac ou Linux.
+sorry_device_unsupported=Désolé, {{clientShortname}} ne fonctionne actuellement pas sur votre appareil.
+use_firefox_windows_mac_linux=Merci d'ouvrir cette page avec une version récente de {{brandShortname}} pour Windows, Android, Mac ou Linux.
 call_url_unavailable_notification_heading=Oups !
 call_url_unavailable_notification_message=Cette URL n'est pas disponible.
-promote_firefox_hello_heading=Téléchargez Firefox pour passer des appels audio et vidéo gratuitement !
-get_firefox_button=Téléchargez Firefox
+promote_firefox_hello_heading=Téléchargez {{brandShortname}} pour passer des appels audio et vidéo gratuitement !
+get_firefox_button=Téléchargez {{brandShortname}}
--- a/browser/components/places/content/treeView.js
+++ b/browser/components/places/content/treeView.js
@@ -314,18 +314,17 @@ PlacesTreeView.prototype = {
       // Recursively do containers.
       if (!this._flatList &&
           curChild instanceof Ci.nsINavHistoryContainerResultNode &&
           !this._controller.hasCachedLivemarkInfo(curChild)) {
         let uri = curChild.uri;
         let isopen = false;
 
         if (uri) {
-          let docURI = this._getDocumentURI();
-          let val = this._xulStore.getValue(docURI, uri, "open");
+          let val = this._xulStore.getValue(document.documentURIObject, uri, "open");
           isopen = (val == "true");
         }
 
         if (isopen != curChild.containerOpen)
           aToOpen.push(curChild);
         else if (curChild.containerOpen && curChild.childCount > 0)
           rowsInserted += this._buildVisibleSection(curChild, row + 1, aToOpen);
       }
@@ -1116,28 +1115,16 @@ PlacesTreeView.prototype = {
     try {
       return this._getRowForNode(aNode, true);
     }
     catch(ex) { }
 
     return Ci.nsINavHistoryResultTreeViewer.INDEX_INVISIBLE;
   },
 
-  // Retrieves an nsIURI for the document
-  _documentURI: null,
-  _getDocumentURI: function()
-  {
-    if (!this._documentURI) {
-      let ioService = Cc["@mozilla.org/network/io-service;1"].
-                      getService(Ci.nsIIOService);
-      this._documentURI = ioService.newURI(document.URL, null, null);
-    }
-    return this._documentURI;
-  },
-
   // nsITreeView
   get rowCount() this._rows.length,
   get selection() this._selection,
   set selection(val) this._selection = val,
 
   getRowProperties: function() { return ""; },
 
   getCellProperties:
@@ -1512,17 +1499,17 @@ PlacesTreeView.prototype = {
       return;
     }
 
     // Persist containers open status, but never persist livemarks.
     if (!this._controller.hasCachedLivemarkInfo(node)) {
       let uri = node.uri;
 
       if (uri) {
-        let docURI = this._getDocumentURI();
+        let docURI = document.documentURIObject;
 
         if (node.containerOpen) {
           this._xulStore.removeValue(docURI, uri, "open");
         } else {
           this._xulStore.setValue(docURI, uri, "open", "true");
         }
       }
     }
--- a/browser/modules/TabCrashReporter.jsm
+++ b/browser/modules/TabCrashReporter.jsm
@@ -53,18 +53,17 @@ this.TabCrashReporter = {
   },
 
   submitCrashReport: function (aBrowser) {
     let childID = this.browserMap.get(aBrowser);
     let dumpID = this.childMap.get(childID);
     if (!dumpID)
       return
 
-    let contentProcessType = Services.crashmanager.PROCESS_TYPE_CONTENT;
-    if (CrashSubmit.submit(dumpID, { processType: contentProcessType })) {
+    if (CrashSubmit.submit(dumpID, { recordSubmission: true })) {
       this.childMap.set(childID, null); // Avoid resubmission.
     }
   },
 
   reloadCrashedTabs: function () {
     let enumerator = Services.wm.getEnumerator("navigator:browser");
     while (enumerator.hasMoreElements()) {
       let window = enumerator.getNext();
--- a/browser/modules/webrtcUI.jsm
+++ b/browser/modules/webrtcUI.jsm
@@ -772,24 +772,16 @@ function updateBrowserSpecificIndicator(
       if (camera.value &&
           perms.testExactPermission(uri, "camera") == perms.ALLOW_ACTION)
         perms.remove(uri.host, "camera");
       if (microphone.value &&
           perms.testExactPermission(uri, "microphone") == perms.ALLOW_ACTION)
         perms.remove(uri.host, "microphone");
 
       Services.obs.notifyObservers(null, "getUserMedia:revoke", windowId);
-
-      // Performing an action from a notification removes it, but if the page
-      // uses screensharing and a device, we may have another notification to remove.
-      let outerWindowID = Services.wm.getCurrentInnerWindowWithId(windowId)
-                                     .QueryInterface(Ci.nsIInterfaceRequestor)
-                                     .getInterface(Ci.nsIDOMWindowUtils)
-                                     .outerWindowID;
-      removeBrowserSpecificIndicator(null, null, outerWindowID);
     }
   }];
   let options = {
     hideNotNow: true,
     dismissed: true,
     eventCallback: function(aTopic) {
       if (aTopic == "shown") {
         let PopupNotifications = this.browser.ownerDocument.defaultView.PopupNotifications;
@@ -822,16 +814,23 @@ function updateBrowserSpecificIndicator(
     eventCallback: function(aTopic) {
       if (aTopic == "shown") {
         let PopupNotifications = this.browser.ownerDocument.defaultView.PopupNotifications;
         PopupNotifications.panel.firstChild.setAttribute("popupid", "webRTC-sharingScreen");
       }
       return aTopic == "swapping";
     }
   };
+  secondaryActions = [{
+    label: stringBundle.getString("getUserMedia.stopSharing.label"),
+    accessKey: stringBundle.getString("getUserMedia.stopSharing.accesskey"),
+    callback: function () {
+      Services.obs.notifyObservers(null, "getUserMedia:revoke", "screen:" + windowId);
+    }
+  }];
   // If we are sharing both a window and the screen, show 'Screen'.
   let stringId = "getUserMedia.sharing" + (screen.value ? "Screen" : "Window") + ".message";
   chromeWin.PopupNotifications.show(aBrowser, "webRTC-sharingScreen",
                                     stringBundle.getString(stringId),
                                     "webRTC-sharingScreen-notification-icon",
                                     mainAction, secondaryActions, options);
 }
 
--- a/caps/nsNullPrincipal.h
+++ b/caps/nsNullPrincipal.h
@@ -22,17 +22,17 @@ class nsIURI;
 
 #define NS_NULLPRINCIPAL_CID \
 { 0xa0bd8b42, 0xf6bf, 0x4fb9, \
   { 0x93, 0x42, 0x90, 0xbf, 0xc9, 0xb7, 0xa1, 0xab } }
 #define NS_NULLPRINCIPAL_CONTRACTID "@mozilla.org/nullprincipal;1"
 
 #define NS_NULLPRINCIPAL_SCHEME "moz-nullprincipal"
 
-class nsNullPrincipal : public nsJSPrincipals
+class nsNullPrincipal MOZ_FINAL : public nsJSPrincipals
 {
 public:
   nsNullPrincipal();
   
   // Our refcount is managed by nsJSPrincipals.  Use this macro to avoid an
   // extra refcount member.
 
   // FIXME: bug 327245 -- I sorta wish there were a clean way to share the
--- a/caps/nsPrincipal.h
+++ b/caps/nsPrincipal.h
@@ -39,17 +39,17 @@ protected:
 
 #ifdef DEBUG
   virtual void dumpImpl() = 0;
 #endif
 
   nsCOMPtr<nsIContentSecurityPolicy> mCSP;
 };
 
-class nsPrincipal : public nsBasePrincipal
+class nsPrincipal MOZ_FINAL : public nsBasePrincipal
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSISERIALIZABLE
   NS_IMETHOD Equals(nsIPrincipal* other, bool* _retval);
   NS_IMETHOD EqualsConsideringDomain(nsIPrincipal* other, bool* _retval);
   NS_IMETHOD GetHashValue(uint32_t* aHashValue);
   NS_IMETHOD GetURI(nsIURI** aURI);
--- a/caps/nsScriptSecurityManager.h
+++ b/caps/nsScriptSecurityManager.h
@@ -27,19 +27,19 @@ class ClassInfoData;
 
 /////////////////////////////
 // nsScriptSecurityManager //
 /////////////////////////////
 #define NS_SCRIPTSECURITYMANAGER_CID \
 { 0x7ee2a4c0, 0x4b93, 0x17d3, \
 { 0xba, 0x18, 0x00, 0x60, 0xb0, 0xf1, 0x99, 0xa2 }}
 
-class nsScriptSecurityManager : public nsIScriptSecurityManager,
-                                public nsIChannelEventSink,
-                                public nsIObserver
+class nsScriptSecurityManager MOZ_FINAL : public nsIScriptSecurityManager,
+                                          public nsIChannelEventSink,
+                                          public nsIObserver
 {
 public:
     static void Shutdown();
 
     NS_DEFINE_STATIC_CID_ACCESSOR(NS_SCRIPTSECURITYMANAGER_CID)
 
     NS_DECL_ISUPPORTS
     NS_DECL_NSISCRIPTSECURITYMANAGER
--- a/caps/nsSystemPrincipal.h
+++ b/caps/nsSystemPrincipal.h
@@ -12,17 +12,17 @@
 #include "nsJSPrincipals.h"
 
 #define NS_SYSTEMPRINCIPAL_CID \
 { 0x4a6212db, 0xaccb, 0x11d3, \
 { 0xb7, 0x65, 0x0, 0x60, 0xb0, 0xb6, 0xce, 0xcb }}
 #define NS_SYSTEMPRINCIPAL_CONTRACTID "@mozilla.org/systemprincipal;1"
 
 
-class nsSystemPrincipal : public nsJSPrincipals
+class nsSystemPrincipal MOZ_FINAL : public nsJSPrincipals
 {
 public:
     // Our refcount is managed by nsJSPrincipals.  Use this macro to avoid
     // an extra refcount member.
     NS_DECL_ISUPPORTS_INHERITED
     NS_DECL_NSIPRINCIPAL
     NS_DECL_NSISERIALIZABLE
 
--- a/configure.in
+++ b/configure.in
@@ -2481,43 +2481,16 @@ dnl ====================================
 AC_HEADER_STDC
 AC_C_CONST
 AC_TYPE_MODE_T
 AC_TYPE_OFF_T
 AC_TYPE_PID_T
 AC_TYPE_SIZE_T
 AC_LANG_CPLUSPLUS
 AC_LANG_C
-AC_MSG_CHECKING(for ssize_t)
-AC_CACHE_VAL(ac_cv_type_ssize_t,
- [AC_TRY_COMPILE([#include <stdio.h>
-                  #include <sys/types.h>],
-                 [ssize_t foo = 0;],
-                 [ac_cv_type_ssize_t=true],
-                 [ac_cv_type_ssize_t=false])])
-if test "$ac_cv_type_ssize_t" = true ; then
-  AC_DEFINE(HAVE_SSIZE_T)
-  AC_MSG_RESULT(yes)
-else
-  AC_MSG_RESULT(no)
-fi
-AC_STRUCT_ST_BLKSIZE
-AC_MSG_CHECKING(for siginfo_t)
-AC_CACHE_VAL(ac_cv_siginfo_t,
- [AC_TRY_COMPILE([#define _POSIX_C_SOURCE 199506L
-                  #include <signal.h>],
-                 [siginfo_t* info;],
-                 [ac_cv_siginfo_t=true],
-                 [ac_cv_siginfo_t=false])])
-if test "$ac_cv_siginfo_t" = true ; then
-  AC_DEFINE(HAVE_SIGINFO_T)
-  AC_MSG_RESULT(yes)
-else
-  AC_MSG_RESULT(no)
-fi
 
 AC_LANG_CPLUSPLUS
 
 MOZ_CXX11
 
 AC_LANG_C
 
 dnl Check for .hidden assembler directive and visibility attribute.
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -1567,20 +1567,16 @@ public:
    * Return whether aStr contains an ASCII uppercase character.
    */
   static bool StringContainsASCIIUpper(const nsAString& aStr);
 
   // Returns NS_OK for same origin, error (NS_ERROR_DOM_BAD_URI) if not.
   static nsresult CheckSameOrigin(nsIChannel *aOldChannel, nsIChannel *aNewChannel);
   static nsIInterfaceRequestor* GetSameOriginChecker();
 
-  // Trace the safe JS context.
-  static void TraceSafeJSContext(JSTracer* aTrc);
-
-
   /**
    * Get the Origin of the passed in nsIPrincipal or nsIURI. If the passed in
    * nsIURI or the URI of the passed in nsIPrincipal does not have a host, the
    * origin is set to 'null'.
    *
    * The ASCII versions return a ASCII strings that are puny-code encoded,
    * suitable for, for example, header values. The UTF versions return strings
    * containing international characters.
--- a/content/base/public/nsNameSpaceManager.h
+++ b/content/base/public/nsNameSpaceManager.h
@@ -61,17 +61,17 @@ private:
  * consistent accross the app. NameSpace IDs are only consistent at runtime
  * ie: they are not guaranteed to be consistent accross app sessions.
  *
  * The nsNameSpaceManager needs to have a live reference for as long as
  * the NameSpace IDs are needed.
  *
  */
 
-class nsNameSpaceManager
+class nsNameSpaceManager MOZ_FINAL
 {
 public:
   virtual ~nsNameSpaceManager() {}
 
   virtual nsresult RegisterNameSpace(const nsAString& aURI,
                                      int32_t& aNameSpaceID);
 
   virtual nsresult GetNameSpaceURI(int32_t aNameSpaceID, nsAString& aURI);
--- a/content/base/src/WebSocket.h
+++ b/content/base/src/WebSocket.h
@@ -27,22 +27,22 @@
 #include "nsWrapperCache.h"
 
 #define DEFAULT_WS_SCHEME_PORT  80
 #define DEFAULT_WSS_SCHEME_PORT 443
 
 namespace mozilla {
 namespace dom {
 
-class WebSocket : public DOMEventTargetHelper,
-                  public nsIInterfaceRequestor,
-                  public nsIWebSocketListener,
-                  public nsIObserver,
-                  public nsSupportsWeakReference,
-                  public nsIRequest
+class WebSocket MOZ_FINAL : public DOMEventTargetHelper,
+                            public nsIInterfaceRequestor,
+                            public nsIWebSocketListener,
+                            public nsIObserver,
+                            public nsSupportsWeakReference,
+                            public nsIRequest
 {
 friend class CallDispatchConnectionCloseEvents;
 friend class nsAutoCloseWS;
 
 public:
   enum {
     CONNECTING = 0,
     OPEN       = 1,
--- a/content/base/src/nsCCUncollectableMarker.cpp
+++ b/content/base/src/nsCCUncollectableMarker.cpp
@@ -479,12 +479,9 @@ mozilla::dom::TraceBlackJS(JSTracer* aTr
   TraceClosure closure(aTrc, aGCNumber);
 
   // Mark globals of active windows black.
   nsGlobalWindow::WindowByIdTable* windowsById =
     nsGlobalWindow::GetWindowsTable();
   if (windowsById) {
     windowsById->Enumerate(TraceActiveWindowGlobal, &closure);
   }
-
-  // Mark the safe context black
-  nsContentUtils::TraceSafeJSContext(aTrc);
 }
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -1931,31 +1931,16 @@ nsContentUtils::InProlog(nsINode *aNode)
   }
 
   nsIDocument* doc = static_cast<nsIDocument*>(parent);
   nsIContent* root = doc->GetRootElement();
 
   return !root || doc->IndexOf(aNode) < doc->IndexOf(root);
 }
 
-//static
-void
-nsContentUtils::TraceSafeJSContext(JSTracer* aTrc)
-{
-  JSContext* cx = GetSafeJSContext();
-  if (!cx) {
-    return;
-  }
-  if (JSObject* global = js::DefaultObjectForContextOrNull(cx)) {
-    JS::AssertGCThingMustBeTenured(global);
-    JS_CallUnbarrieredObjectTracer(aTrc, &global, "safe context");
-    MOZ_ASSERT(global == js::DefaultObjectForContextOrNull(cx));
-  }
-}
-
 nsIDocument*
 nsContentUtils::GetDocumentFromCaller()
 {
   AutoJSContext cx;
 
   nsCOMPtr<nsPIDOMWindow> win =
     do_QueryInterface(nsJSUtils::GetStaticScriptGlobal(JS::CurrentGlobalOrNull(cx)));
   if (!win) {
--- a/content/base/src/nsFrameLoader.cpp
+++ b/content/base/src/nsFrameLoader.cpp
@@ -141,20 +141,16 @@ nsContentView::Update(const ViewConfig& 
       // ever get one.
       return NS_OK;
     } else {
       // This view is no longer valid.
       return NS_ERROR_NOT_AVAILABLE;
     }
   }
 
-  if (RenderFrameParent* rfp = mFrameLoader->GetCurrentRemoteFrame()) {
-    rfp->ContentViewScaleChanged(this);
-  }
-
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsContentView::ScrollTo(float aXpx, float aYpx)
 {
   ViewConfig config(mConfig);
   config.mScrollOffset = nsPoint(nsPresContext::CSSPixelsToAppUnits(aXpx),
@@ -2389,44 +2385,18 @@ nsFrameLoader::GetMessageManager(nsIMess
 
 NS_IMETHODIMP
 nsFrameLoader::GetContentViewsIn(float aXPx, float aYPx,
                                  float aTopSize, float aRightSize,
                                  float aBottomSize, float aLeftSize,
                                  uint32_t* aLength,
                                  nsIContentView*** aResult)
 {
-  nscoord x = nsPresContext::CSSPixelsToAppUnits(aXPx - aLeftSize);
-  nscoord y = nsPresContext::CSSPixelsToAppUnits(aYPx - aTopSize);
-  nscoord w = nsPresContext::CSSPixelsToAppUnits(aLeftSize + aRightSize) + 1;
-  nscoord h = nsPresContext::CSSPixelsToAppUnits(aTopSize + aBottomSize) + 1;
-  nsRect target(x, y, w, h);
-
-  nsIFrame* frame = GetPrimaryFrameOfOwningContent();
-
-  nsTArray<ViewID> ids;
-  nsLayoutUtils::GetRemoteContentIds(frame, target, ids, true);
-  if (ids.Length() == 0 || !GetCurrentRemoteFrame()) {
-    *aResult = nullptr;
-    *aLength = 0;
-    return NS_OK;
-  }
-
-  nsIContentView** result = reinterpret_cast<nsIContentView**>(
-    NS_Alloc(ids.Length() * sizeof(nsIContentView*)));
-
-  for (uint32_t i = 0; i < ids.Length(); i++) {
-    nsIContentView* view = GetCurrentRemoteFrame()->GetContentView(ids[i]);
-    NS_ABORT_IF_FALSE(view, "Retrieved ID from RenderFrameParent, it should be valid!");
-    nsRefPtr<nsIContentView>(view).forget(&result[i]);
-  }
-
-  *aResult = result;
-  *aLength = ids.Length();
-
+  *aResult = nullptr;
+  *aLength = 0;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsFrameLoader::GetRootContentView(nsIContentView** aContentView)
 {
   RenderFrameParent* rfp = GetCurrentRemoteFrame();
   if (!rfp) {
--- a/content/base/src/nsXMLHttpRequest.h
+++ b/content/base/src/nsXMLHttpRequest.h
@@ -174,26 +174,26 @@ public:
 private:
   virtual ~nsXMLHttpRequestUpload() {}
 };
 
 class nsXMLHttpRequestXPCOMifier;
 
 // Make sure that any non-DOM interfaces added here are also added to
 // nsXMLHttpRequestXPCOMifier.
-class nsXMLHttpRequest : public nsXHREventTarget,
-                         public nsIXMLHttpRequest,
-                         public nsIJSXMLHttpRequest,
-                         public nsIStreamListener,
-                         public nsIChannelEventSink,
-                         public nsIProgressEventSink,
-                         public nsIInterfaceRequestor,
-                         public nsSupportsWeakReference,
-                         public nsITimerCallback,
-                         public nsISizeOfEventTarget
+class nsXMLHttpRequest MOZ_FINAL : public nsXHREventTarget,
+                                   public nsIXMLHttpRequest,
+                                   public nsIJSXMLHttpRequest,
+                                   public nsIStreamListener,
+                                   public nsIChannelEventSink,
+                                   public nsIProgressEventSink,
+                                   public nsIInterfaceRequestor,
+                                   public nsSupportsWeakReference,
+                                   public nsITimerCallback,
+                                   public nsISizeOfEventTarget
 {
   friend class nsXHRParseEndListener;
   friend class nsXMLHttpRequestXPCOMifier;
 
 public:
   nsXMLHttpRequest();
 
   virtual JSObject* WrapObject(JSContext *cx) MOZ_OVERRIDE
--- a/content/html/content/src/HTMLOptionsCollection.h
+++ b/content/html/content/src/HTMLOptionsCollection.h
@@ -24,19 +24,19 @@ namespace mozilla {
 namespace dom {
 
 class HTMLSelectElement;
 
 /**
  * The collection of options in the select (what you get back when you do
  * select.options in DOM)
  */
-class HTMLOptionsCollection : public nsIHTMLCollection
-                            , public nsIDOMHTMLOptionsCollection
-                            , public nsWrapperCache
+class HTMLOptionsCollection MOZ_FINAL : public nsIHTMLCollection
+                                      , public nsIDOMHTMLOptionsCollection
+                                      , public nsWrapperCache
 {
   typedef HTMLOptionElementOrHTMLOptGroupElement HTMLOptionOrOptGroupElement;
 public:
   HTMLOptionsCollection(HTMLSelectElement* aSelect);
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
   // nsWrapperCache
--- a/content/media/MediaDecoderReader.cpp
+++ b/content/media/MediaDecoderReader.cpp
@@ -120,69 +120,16 @@ VideoData* MediaDecoderReader::DecodeToF
   }
   if (eof) {
     VideoQueue().Finish();
   }
   VideoData* d = nullptr;
   return (d = VideoQueue().PeekFront()) ? d : nullptr;
 }
 
-AudioData* MediaDecoderReader::DecodeToFirstAudioData()
-{
-  bool eof = false;
-  while (!eof && AudioQueue().GetSize() == 0) {
-    {
-      ReentrantMonitorAutoEnter decoderMon(mDecoder->GetReentrantMonitor());
-      if (mDecoder->IsShutdown()) {
-        return nullptr;
-      }
-    }
-    eof = !DecodeAudioData();
-  }
-  if (eof) {
-    AudioQueue().Finish();
-  }
-  AudioData* d = nullptr;
-  return (d = AudioQueue().PeekFront()) ? d : nullptr;
-}
-
-VideoData* MediaDecoderReader::FindStartTime(int64_t& aOutStartTime)
-{
-  NS_ASSERTION(mDecoder->OnStateMachineThread() || mDecoder->OnDecodeThread(),
-               "Should be on state machine or decode thread.");
-
-  // Extract the start times of the bitstreams in order to calculate
-  // the duration.
-  int64_t videoStartTime = INT64_MAX;
-  int64_t audioStartTime = INT64_MAX;
-  VideoData* videoData = nullptr;
-
-  if (HasVideo()) {
-    videoData = DecodeToFirstVideoData();
-    if (videoData) {
-      videoStartTime = videoData->mTime;
-      DECODER_LOG(PR_LOG_DEBUG, ("MediaDecoderReader::FindStartTime() video=%lld", videoStartTime));
-    }
-  }
-  if (HasAudio()) {
-    AudioData* audioData = DecodeToFirstAudioData();
-    if (audioData) {
-      audioStartTime = audioData->mTime;
-      DECODER_LOG(PR_LOG_DEBUG, ("MediaDecoderReader::FindStartTime() audio=%lld", audioStartTime));
-    }
-  }
-
-  int64_t startTime = std::min(videoStartTime, audioStartTime);
-  if (startTime != INT64_MAX) {
-    aOutStartTime = startTime;
-  }
-
-  return videoData;
-}
-
 nsresult
 MediaDecoderReader::GetBuffered(mozilla::dom::TimeRanges* aBuffered,
                                 int64_t aStartTime)
 {
   MediaResource* stream = mDecoder->GetResource();
   int64_t durationUs = 0;
   {
     ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
--- a/content/media/MediaDecoderReader.h
+++ b/content/media/MediaDecoderReader.h
@@ -90,22 +90,16 @@ public:
 
   // Read header data for all bitstreams in the file. Fills aInfo with
   // the data required to present the media, and optionally fills *aTags
   // with tag metadata from the file.
   // Returns NS_OK on success, or NS_ERROR_FAILURE on failure.
   virtual nsresult ReadMetadata(MediaInfo* aInfo,
                                 MetadataTags** aTags) = 0;
 
-  // TODO: DEPRECATED. This uses synchronous decoding.
-  // Stores the presentation time of the first frame we'd be able to play if
-  // we started playback at the current position. Returns the first video
-  // frame, if we have video.
-  virtual VideoData* FindStartTime(int64_t& aOutStartTime);
-
   // Moves the decode head to aTime microseconds. aStartTime and aEndTime
   // denote the start and end times of the media in usecs, and aCurrentTime
   // is the current playback position in microseconds.
   virtual nsresult Seek(int64_t aTime,
                         int64_t aStartTime,
                         int64_t aEndTime,
                         int64_t aCurrentTime) = 0;
 
@@ -164,17 +158,17 @@ public:
   virtual MediaQueue<AudioData>& AudioQueue() { return mAudioQueue; }
   virtual MediaQueue<VideoData>& VideoQueue() { return mVideoQueue; }
 
   // Returns a pointer to the decoder.
   AbstractMediaDecoder* GetDecoder() {
     return mDecoder;
   }
 
-  AudioData* DecodeToFirstAudioData();
+  // TODO: DEPRECATED.  This uses synchronous decoding.
   VideoData* DecodeToFirstVideoData();
 
   MediaInfo GetMediaInfo() { return mInfo; }
 
   // Indicates if the media is seekable.
   // ReadMetada should be called before calling this method.
   virtual bool IsMediaSeekable() = 0;
 
--- a/content/media/fmp4/MP4Reader.cpp
+++ b/content/media/fmp4/MP4Reader.cpp
@@ -769,19 +769,17 @@ MP4Reader::Seek(int64_t aTime,
   return NS_OK;
 }
 
 void
 MP4Reader::NotifyDataArrived(const char* aBuffer, uint32_t aLength,
                              int64_t aOffset)
 {
   if (NS_IsMainThread()) {
-    MediaTaskQueue* queue =
-      mAudio.mTaskQueue ? mAudio.mTaskQueue : mVideo.mTaskQueue;
-    queue->Dispatch(NS_NewRunnableMethod(this, &MP4Reader::UpdateIndex));
+    GetTaskQueue()->Dispatch(NS_NewRunnableMethod(this, &MP4Reader::UpdateIndex));
   } else {
     UpdateIndex();
   }
 }
 
 void
 MP4Reader::UpdateIndex()
 {
--- a/content/media/fmp4/apple/AppleATDecoder.cpp
+++ b/content/media/fmp4/apple/AppleATDecoder.cpp
@@ -11,18 +11,18 @@
 #include "mozilla/RefPtr.h"
 #include "mozilla/ReentrantMonitor.h"
 #include "mp4_demuxer/DecoderData.h"
 #include "nsIThread.h"
 #include "AppleATDecoder.h"
 #include "prlog.h"
 
 #ifdef PR_LOGGING
-PRLogModuleInfo* GetDemuxerLog();
-#define LOG(...) PR_LOG(GetDemuxerLog(), PR_LOG_DEBUG, (__VA_ARGS__))
+PRLogModuleInfo* GetAppleMediaLog();
+#define LOG(...) PR_LOG(GetAppleMediaLog(), PR_LOG_DEBUG, (__VA_ARGS__))
 #else
 #define LOG(...)
 #endif
 
 namespace mozilla {
 
 AppleATDecoder::AppleATDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
                                MediaTaskQueue* aAudioTaskQueue,
--- a/content/media/fmp4/apple/AppleCMLinker.cpp
+++ b/content/media/fmp4/apple/AppleCMLinker.cpp
@@ -6,18 +6,18 @@
 
 #include <dlfcn.h>
 
 #include "AppleCMLinker.h"
 #include "MainThreadUtils.h"
 #include "nsDebug.h"
 
 #ifdef PR_LOGGING
-PRLogModuleInfo* GetDemuxerLog();
-#define LOG(...) PR_LOG(GetDemuxerLog(), PR_LOG_DEBUG, (__VA_ARGS__))
+PRLogModuleInfo* GetAppleMediaLog();
+#define LOG(...) PR_LOG(GetAppleMediaLog(), PR_LOG_DEBUG, (__VA_ARGS__))
 #else
 #define LOG(...)
 #endif
 
 namespace mozilla {
 
 AppleCMLinker::LinkStatus
 AppleCMLinker::sLinkStatus = LinkStatus_INIT;
--- a/content/media/fmp4/apple/AppleUtils.cpp
+++ b/content/media/fmp4/apple/AppleUtils.cpp
@@ -4,18 +4,24 @@
 
 // Utility functions to help with Apple API calls.
 
 #include "AppleUtils.h"
 #include "prlog.h"
 #include "nsAutoPtr.h"
 
 #ifdef PR_LOGGING
-PRLogModuleInfo* GetDemuxerLog();
-#define WARN(...) PR_LOG(GetDemuxerLog(), PR_LOG_WARNING, (__VA_ARGS__))
+PRLogModuleInfo* GetAppleMediaLog() {
+  static PRLogModuleInfo* log = nullptr;
+  if (!log) {
+    log = PR_NewLogModule("AppleMedia");
+  }
+  return log;
+}
+#define WARN(...) PR_LOG(GetAppleMediaLog(), PR_LOG_WARNING, (__VA_ARGS__))
 #else
 #define WARN(...)
 #endif
 
 #define PROPERTY_ID_FORMAT "%c%c%c%c"
 #define PROPERTY_ID_PRINT(x) ((x) >> 24), \
                              ((x) >> 16) & 0xff, \
                              ((x) >> 8) & 0xff, \
--- a/content/media/fmp4/apple/AppleVTDecoder.cpp
+++ b/content/media/fmp4/apple/AppleVTDecoder.cpp
@@ -2,37 +2,40 @@
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include <CoreFoundation/CFString.h>
 
 #include "AppleUtils.h"
-#include "mozilla/SHA1.h"
 #include "mp4_demuxer/DecoderData.h"
 #include "MP4Reader.h"
 #include "MP4Decoder.h"
 #include "nsAutoPtr.h"
 #include "nsThreadUtils.h"
 #include "AppleCMLinker.h"
 #include "AppleVTDecoder.h"
 #include "AppleVTLinker.h"
 #include "prlog.h"
 #include "MediaData.h"
 #include "VideoUtils.h"
 
 #ifdef PR_LOGGING
-PRLogModuleInfo* GetDemuxerLog();
-#define LOG(...) PR_LOG(GetDemuxerLog(), PR_LOG_DEBUG, (__VA_ARGS__))
-#define LOG_MEDIA_SHA1
+PRLogModuleInfo* GetAppleMediaLog();
+#define LOG(...) PR_LOG(GetAppleMediaLog(), PR_LOG_DEBUG, (__VA_ARGS__))
+//#define LOG_MEDIA_SHA1
 #else
 #define LOG(...)
 #endif
 
+#ifdef LOG_MEDIA_SHA1
+#include "mozilla/SHA1.h"
+#endif
+
 namespace mozilla {
 
 AppleVTDecoder::AppleVTDecoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
                                MediaTaskQueue* aVideoTaskQueue,
                                MediaDataDecoderCallback* aCallback,
                                layers::ImageContainer* aImageContainer)
   : mConfig(aConfig)
   , mTaskQueue(aVideoTaskQueue)
--- a/content/media/fmp4/apple/AppleVTLinker.cpp
+++ b/content/media/fmp4/apple/AppleVTLinker.cpp
@@ -6,18 +6,18 @@
 
 #include <dlfcn.h>
 
 #include "AppleVTLinker.h"
 #include "MainThreadUtils.h"
 #include "nsDebug.h"
 
 #ifdef PR_LOGGING
-PRLogModuleInfo* GetDemuxerLog();
-#define LOG(...) PR_LOG(GetDemuxerLog(), PR_LOG_DEBUG, (__VA_ARGS__))
+PRLogModuleInfo* GetAppleMediaLog();
+#define LOG(...) PR_LOG(GetAppleMediaLog(), PR_LOG_DEBUG, (__VA_ARGS__))
 #else
 #define LOG(...)
 #endif
 
 namespace mozilla {
 
 AppleVTLinker::LinkStatus
 AppleVTLinker::sLinkStatus = LinkStatus_INIT;
--- a/content/media/fmp4/eme/EMEH264Decoder.cpp
+++ b/content/media/fmp4/eme/EMEH264Decoder.cpp
@@ -11,16 +11,17 @@
 #include "gmp-video-frame-encoded.h"
 #include "GMPVideoEncodedFrameImpl.h"
 #include "mp4_demuxer/AnnexB.h"
 #include "mozilla/CDMProxy.h"
 #include "nsServiceManagerUtils.h"
 #include "prsystem.h"
 #include "gfx2DGlue.h"
 #include "mozilla/EMELog.h"
+#include "mozilla/Move.h"
 
 namespace mozilla {
 
 EMEH264Decoder::EMEH264Decoder(CDMProxy* aProxy,
                                const mp4_demuxer::VideoDecoderConfig& aConfig,
                                layers::LayersBackend aLayersBackend,
                                layers::ImageContainer* aImageContainer,
                                MediaTaskQueue* aTaskQueue,
@@ -292,17 +293,17 @@ EMEH264Decoder::GmpInput(MP4Sample* aSam
 
   GMPVideoFrame* ftmp = nullptr;
   GMPErr err = mHost->CreateFrame(kGMPEncodedVideoFrame, &ftmp);
   if (GMP_FAILED(err)) {
     mCallback->Error();
     return NS_ERROR_FAILURE;
   }
 
-  gmp::GMPVideoEncodedFrameImpl* frame = static_cast<gmp::GMPVideoEncodedFrameImpl*>(ftmp);
+  UniquePtr<gmp::GMPVideoEncodedFrameImpl> frame(static_cast<gmp::GMPVideoEncodedFrameImpl*>(ftmp));
   err = frame->CreateEmptyFrame(sample->size);
   if (GMP_FAILED(err)) {
     mCallback->Error();
     return NS_ERROR_FAILURE;
   }
 
   memcpy(frame->Buffer(), sample->data, frame->Size());
 
@@ -313,17 +314,17 @@ EMEH264Decoder::GmpInput(MP4Sample* aSam
   frame->SetDuration(sample->duration);
   if (sample->crypto.valid) {
     frame->InitCrypto(sample->crypto);
   }
   frame->SetFrameType(sample->is_sync_point ? kGMPKeyFrame : kGMPDeltaFrame);
   frame->SetBufferType(GMP_BufferLength32);
 
   nsTArray<uint8_t> info; // No codec specific per-frame info to pass.
-  nsresult rv = mGMP->Decode(frame, false, info, 0);
+  nsresult rv = mGMP->Decode(UniquePtr<GMPVideoEncodedFrame>(frame.release()), false, info, 0);
   if (NS_FAILED(rv)) {
     mCallback->Error();
     return rv;
   }
 
   return NS_OK;
 }
 
--- a/content/media/fmp4/eme/moz.build
+++ b/content/media/fmp4/eme/moz.build
@@ -13,18 +13,14 @@ EXPORTS += [
 UNIFIED_SOURCES += [
     'EMEAudioDecoder.cpp',
     'EMEDecoderModule.cpp',
     'EMEH264Decoder.cpp',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
-LOCAL_INCLUDES += [
-    '../base',
-]
-  
 FINAL_LIBRARY = 'xul'
 
 FAIL_ON_WARNINGS = True
 
 if CONFIG['OS_ARCH'] == 'WINNT':
     DEFINES['NOMINMAX'] = True
--- a/content/media/fmp4/moz.build
+++ b/content/media/fmp4/moz.build
@@ -60,18 +60,14 @@ if CONFIG['MOZ_APPLEMEDIA']:
   ]
 
 if CONFIG['ANDROID_VERSION'] >= '18'and CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
     DEFINES['MOZ_GONK_MEDIACODEC'] = True
     DIRS += ['gonk']
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
-LOCAL_INCLUDES += [
-    '../base',
-]
-
 FINAL_LIBRARY = 'xul'
 
 FAIL_ON_WARNINGS = True
 
 if CONFIG['OS_ARCH'] == 'WINNT':
     DEFINES['NOMINMAX'] = True
--- a/content/media/fmp4/wmf/WMFAudioMFTManager.cpp
+++ b/content/media/fmp4/wmf/WMFAudioMFTManager.cpp
@@ -71,59 +71,93 @@ WMFAudioMFTManager::WMFAudioMFTManager(
   : mAudioChannels(aConfig.channel_count)
   , mAudioBytesPerSample(aConfig.bits_per_sample / 8)
   , mAudioRate(aConfig.samples_per_second)
   , mAudioFrameOffset(0)
   , mAudioFrameSum(0)
   , mMustRecaptureAudioPosition(true)
 {
   MOZ_COUNT_CTOR(WMFAudioMFTManager);
-  AACAudioSpecificConfigToUserData(&aConfig.audio_specific_config[0],
-                                   aConfig.audio_specific_config.length(),
-                                   mUserData);
+
+  if (!strcmp(aConfig.mime_type, "audio/mpeg")) {
+    mStreamType = MP3;
+  } else if (!strcmp(aConfig.mime_type, "audio/mp4a-latm")) {
+    mStreamType = AAC;
+    AACAudioSpecificConfigToUserData(&aConfig.audio_specific_config[0],
+                                     aConfig.audio_specific_config.length(),
+                                     mUserData);
+  } else {
+    mStreamType = Unknown;
+  }
 }
 
 WMFAudioMFTManager::~WMFAudioMFTManager()
 {
   MOZ_COUNT_DTOR(WMFAudioMFTManager);
 }
 
+const GUID&
+WMFAudioMFTManager::GetMFTGUID()
+{
+  MOZ_ASSERT(mStreamType != Unknown);
+  switch (mStreamType) {
+    case AAC: return CLSID_CMSAACDecMFT;
+    case MP3: return CLSID_CMP3DecMediaObject;
+    default: return GUID_NULL;
+  };
+}
+
+const GUID&
+WMFAudioMFTManager::GetMediaSubtypeGUID()
+{
+  MOZ_ASSERT(mStreamType != Unknown);
+  switch (mStreamType) {
+    case AAC: return MFAudioFormat_AAC;
+    case MP3: return MFAudioFormat_MP3;
+    default: return GUID_NULL;
+  };
+}
+
 TemporaryRef<MFTDecoder>
 WMFAudioMFTManager::Init()
 {
+  NS_ENSURE_TRUE(mStreamType != Unknown, nullptr);
+
   RefPtr<MFTDecoder> decoder(new MFTDecoder());
 
-  HRESULT hr = decoder->Create(CLSID_CMSAACDecMFT);
+  HRESULT hr = decoder->Create(GetMFTGUID());
   NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
 
   // Setup input/output media types
   RefPtr<IMFMediaType> type;
 
   hr = wmf::MFCreateMediaType(byRef(type));
   NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
 
   hr = type->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio);
   NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
 
-  hr = type->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_AAC);
+  hr = type->SetGUID(MF_MT_SUBTYPE, GetMediaSubtypeGUID());
   NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
 
   hr = type->SetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, mAudioRate);
   NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
 
   hr = type->SetUINT32(MF_MT_AUDIO_NUM_CHANNELS, mAudioChannels);
   NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
 
-  hr = type->SetUINT32(MF_MT_AAC_PAYLOAD_TYPE, 0x1); // ADTS
-  NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
+  if (mStreamType == AAC) {
+    hr = type->SetUINT32(MF_MT_AAC_PAYLOAD_TYPE, 0x1); // ADTS
+    NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
 
-  hr = type->SetBlob(MF_MT_USER_DATA,
-                     mUserData.Elements(),
-                     mUserData.Length());
-  NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
+    hr = type->SetBlob(MF_MT_USER_DATA,
+                       mUserData.Elements(),
+                       mUserData.Length());
+    NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
+  }
 
   hr = decoder->SetMediaTypes(type, MFAudioFormat_PCM);
   NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
 
   mDecoder = decoder;
 
   return decoder.forget();
 }
--- a/content/media/fmp4/wmf/WMFAudioMFTManager.h
+++ b/content/media/fmp4/wmf/WMFAudioMFTManager.h
@@ -43,16 +43,26 @@ private:
 
   // The offset, in audio frames, at which playback started since the
   // last discontinuity.
   int64_t mAudioFrameOffset;
   // The number of audio frames that we've played since the last
   // discontinuity.
   int64_t mAudioFrameSum;
 
+  enum StreamType {
+    Unknown,
+    AAC,
+    MP3
+  };
+  StreamType mStreamType;
+
+  const GUID& GetMFTGUID();
+  const GUID& GetMediaSubtypeGUID();
+
   // True if we need to re-initialize mAudioFrameOffset and mAudioFrameSum
   // from the next audio packet we decode. This happens after a seek, since
   // WMF doesn't mark a stream as having a discontinuity after a seek(0).
   bool mMustRecaptureAudioPosition;
 };
 
 } // namespace mozilla
 
--- a/content/media/fmp4/wmf/WMFDecoderModule.cpp
+++ b/content/media/fmp4/wmf/WMFDecoderModule.cpp
@@ -87,9 +87,16 @@ WMFDecoderModule::CreateAudioDecoder(con
 {
   nsRefPtr<MediaDataDecoder> decoder =
     new WMFMediaDataDecoder(new WMFAudioMFTManager(aConfig),
                             aAudioTaskQueue,
                             aCallback);
   return decoder.forget();
 }
 
+bool
+WMFDecoderModule::SupportsAudioMimeType(const char* aMimeType)
+{
+  return !strcmp(aMimeType, "audio/mp4a-latm") ||
+         !strcmp(aMimeType, "audio/mpeg");
+}
+
 } // namespace mozilla
--- a/content/media/fmp4/wmf/WMFDecoderModule.h
+++ b/content/media/fmp4/wmf/WMFDecoderModule.h
@@ -29,16 +29,18 @@ public:
                     MediaTaskQueue* aVideoTaskQueue,
                     MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE;
 
   virtual already_AddRefed<MediaDataDecoder>
   CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
                      MediaTaskQueue* aAudioTaskQueue,
                      MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE;
 
+  bool SupportsAudioMimeType(const char* aMimeType) MOZ_OVERRIDE;
+
   // Called on main thread.
   static void Init();
 private:
   static bool sIsWMFEnabled;
   static bool sDXVAEnabled;
 };
 
 } // namespace mozilla
--- a/content/media/gmp/GMPVideoDecoderParent.cpp
+++ b/content/media/gmp/GMPVideoDecoderParent.cpp
@@ -9,23 +9,16 @@
 #include "nsAutoRef.h"
 #include "nsThreadUtils.h"
 #include "GMPVideoEncodedFrameImpl.h"
 #include "GMPVideoi420FrameImpl.h"
 #include "GMPParent.h"
 #include "GMPMessageUtils.h"
 #include "mozilla/gmp/GMPTypes.h"
 
-template <>
-class nsAutoRefTraits<GMPVideoEncodedFrame> : public nsPointerRefTraits<GMPVideoEncodedFrame>
-{
-public:
-  static void Release(GMPVideoEncodedFrame* aFrame) { aFrame->Destroy(); }
-};
-
 namespace mozilla {
 
 #ifdef LOG
 #undef LOG
 #endif
 
 #ifdef PR_LOGGING
 extern PRLogModuleInfo* GetGMPLog();
@@ -109,31 +102,30 @@ GMPVideoDecoderParent::InitDecode(const 
   }
   mIsOpen = true;
 
   // Async IPC, we don't have access to a return value.
   return NS_OK;
 }
 
 nsresult
-GMPVideoDecoderParent::Decode(GMPVideoEncodedFrame* aInputFrame,
+GMPVideoDecoderParent::Decode(UniquePtr<GMPVideoEncodedFrame> aInputFrame,
                               bool aMissingFrames,
                               const nsTArray<uint8_t>& aCodecSpecificInfo,
                               int64_t aRenderTimeMs)
 {
-  nsAutoRef<GMPVideoEncodedFrame> autoDestroy(aInputFrame);
-
   if (!mIsOpen) {
     NS_WARNING("Trying to use an dead GMP video decoder");
     return NS_ERROR_FAILURE;
   }
 
   MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
 
-  auto inputFrameImpl = static_cast<GMPVideoEncodedFrameImpl*>(aInputFrame);
+  UniquePtr<GMPVideoEncodedFrameImpl> inputFrameImpl(
+    static_cast<GMPVideoEncodedFrameImpl*>(aInputFrame.release()));
 
   // Very rough kill-switch if the plugin stops processing.  If it's merely
   // hung and continues, we'll come back to life eventually.
   // 3* is because we're using 3 buffers per frame for i420 data for now.
   if ((NumInUse(GMPSharedMem::kGMPFrameData) > 3*GMPSharedMem::kGMPBufLimit) ||
       (NumInUse(GMPSharedMem::kGMPEncodedData) > GMPSharedMem::kGMPBufLimit)) {
     return NS_ERROR_FAILURE;
   }
--- a/content/media/gmp/GMPVideoDecoderParent.h
+++ b/content/media/gmp/GMPVideoDecoderParent.h
@@ -32,17 +32,17 @@ public:
   nsresult Shutdown();
 
   // GMPVideoDecoder
   virtual void Close() MOZ_OVERRIDE;
   virtual nsresult InitDecode(const GMPVideoCodec& aCodecSettings,
                               const nsTArray<uint8_t>& aCodecSpecific,
                               GMPVideoDecoderCallbackProxy* aCallback,
                               int32_t aCoreCount) MOZ_OVERRIDE;
-  virtual nsresult Decode(GMPVideoEncodedFrame* aInputFrame,
+  virtual nsresult Decode(UniquePtr<GMPVideoEncodedFrame> aInputFrame,
                           bool aMissingFrames,
                           const nsTArray<uint8_t>& aCodecSpecificInfo,
                           int64_t aRenderTimeMs = -1) MOZ_OVERRIDE;
   virtual nsresult Reset() MOZ_OVERRIDE;
   virtual nsresult Drain() MOZ_OVERRIDE;
   virtual const uint64_t ParentID() MOZ_OVERRIDE { return reinterpret_cast<uint64_t>(mPlugin.get()); }
 
   // GMPSharedMemManager
--- a/content/media/gmp/GMPVideoDecoderProxy.h
+++ b/content/media/gmp/GMPVideoDecoderProxy.h
@@ -7,16 +7,17 @@
 #define GMPVideoDecoderProxy_h_
 
 #include "nsTArray.h"
 #include "gmp-video-decode.h"
 #include "gmp-video-frame-i420.h"
 #include "gmp-video-frame-encoded.h"
 
 #include "GMPCallbackBase.h"
+#include "mozilla/UniquePtr.h"
 
 class GMPVideoDecoderCallbackProxy : public GMPCallbackBase,
                                      public GMPVideoDecoderCallback
 {
 public:
   virtual ~GMPVideoDecoderCallbackProxy() {}
 };
 
@@ -32,22 +33,35 @@ public:
 
 // This interface is not thread-safe and must only be used from GMPThread.
 class GMPVideoDecoderProxy {
 public:
   virtual nsresult InitDecode(const GMPVideoCodec& aCodecSettings,
                               const nsTArray<uint8_t>& aCodecSpecific,
                               GMPVideoDecoderCallbackProxy* aCallback,
                               int32_t aCoreCount) = 0;
-  virtual nsresult Decode(GMPVideoEncodedFrame* aInputFrame,
+  virtual nsresult Decode(mozilla::UniquePtr<GMPVideoEncodedFrame> aInputFrame,
                           bool aMissingFrames,
                           const nsTArray<uint8_t>& aCodecSpecificInfo,
                           int64_t aRenderTimeMs = -1) = 0;
   virtual nsresult Reset() = 0;
   virtual nsresult Drain() = 0;
   virtual const uint64_t ParentID() = 0;
 
   // Call to tell GMP/plugin the consumer will no longer use this
   // interface/codec.
   virtual void Close() = 0;
 };
 
+namespace mozilla {
+
+template<>
+struct DefaultDelete<GMPVideoEncodedFrame>
+{
+  void operator()(GMPVideoEncodedFrame* aFrame) const
+  {
+    aFrame->Destroy();
+  }
+};
+
+} // namespace mozilla
+
 #endif
--- a/content/media/gmp/GMPVideoEncodedFrameImpl.h
+++ b/content/media/gmp/GMPVideoEncodedFrameImpl.h
@@ -30,16 +30,17 @@
 
 #ifndef GMPVideoEncodedFrameImpl_h_
 #define GMPVideoEncodedFrameImpl_h_
 
 #include "gmp-errors.h"
 #include "gmp-video-frame.h"
 #include "gmp-video-frame-encoded.h"
 #include "gmp-decryption.h"
+#include "mozilla/UniquePtr.h"
 #include "mozilla/ipc/Shmem.h"
 #include "mp4_demuxer/DecoderData.h"
 
 namespace mozilla {
 namespace gmp {
 
 class GMPVideoHostImpl;
 class GMPVideoEncodedFrameData;
@@ -109,11 +110,21 @@ private:
   bool     mCompleteFrame;
   GMPVideoHostImpl* mHost;
   ipc::Shmem mBuffer;
   GMPBufferType mBufferType;
   nsAutoPtr<GMPEncryptedBufferDataImpl> mCrypto;
 };
 
 } // namespace gmp
+
+template<>
+struct DefaultDelete<mozilla::gmp::GMPVideoEncodedFrameImpl>
+{
+  void operator()(mozilla::gmp::GMPVideoEncodedFrameImpl* aFrame) const
+  {
+    aFrame->Destroy();
+  }
+};
+
 } // namespace mozilla
 
 #endif // GMPVideoEncodedFrameImpl_h_
--- a/content/media/gmp/GMPVideoEncoderParent.cpp
+++ b/content/media/gmp/GMPVideoEncoderParent.cpp
@@ -11,23 +11,16 @@
 #include "GMPMessageUtils.h"
 #include "nsAutoRef.h"
 #include "GMPParent.h"
 #include "mozilla/gmp/GMPTypes.h"
 #include "nsThread.h"
 #include "nsThreadUtils.h"
 #include "runnable_utils.h"
 
-template <>
-class nsAutoRefTraits<GMPVideoi420Frame> : public nsPointerRefTraits<GMPVideoi420Frame>
-{
-public:
-  static void Release(GMPVideoi420Frame* aFrame) { aFrame->Destroy(); }
-};
-
 namespace mozilla {
 
 #ifdef LOG
 #undef LOG
 #endif
 
 #ifdef PR_LOGGING
 extern PRLogModuleInfo* GetGMPLog();
@@ -126,30 +119,29 @@ GMPVideoEncoderParent::InitEncode(const 
   }
   mIsOpen = true;
 
   // Async IPC, we don't have access to a return value.
   return GMPNoErr;
 }
 
 GMPErr
-GMPVideoEncoderParent::Encode(GMPVideoi420Frame* aInputFrame,
+GMPVideoEncoderParent::Encode(UniquePtr<GMPVideoi420Frame> aInputFrame,
                               const nsTArray<uint8_t>& aCodecSpecificInfo,
                               const nsTArray<GMPVideoFrameType>& aFrameTypes)
 {
-  nsAutoRef<GMPVideoi420Frame> frameRef(aInputFrame);
-
   if (!mIsOpen) {
     NS_WARNING("Trying to use an dead GMP video encoder");
     return GMPGenericErr;
   }
 
   MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
 
-  auto inputFrameImpl = static_cast<GMPVideoi420FrameImpl*>(aInputFrame);
+  UniquePtr<GMPVideoi420FrameImpl> inputFrameImpl(
+    static_cast<GMPVideoi420FrameImpl*>(aInputFrame.release()));
 
   // Very rough kill-switch if the plugin stops processing.  If it's merely
   // hung and continues, we'll come back to life eventually.
   // 3* is because we're using 3 buffers per frame for i420 data for now.
   if ((NumInUse(GMPSharedMem::kGMPFrameData) > 3*GMPSharedMem::kGMPBufLimit) ||
       (NumInUse(GMPSharedMem::kGMPEncodedData) > GMPSharedMem::kGMPBufLimit)) {
     return GMPGenericErr;
   }
--- a/content/media/gmp/GMPVideoEncoderParent.h
+++ b/content/media/gmp/GMPVideoEncoderParent.h
@@ -33,17 +33,17 @@ public:
 
   // GMPVideoEncoderProxy
   virtual void Close() MOZ_OVERRIDE;
   virtual GMPErr InitEncode(const GMPVideoCodec& aCodecSettings,
                             const nsTArray<uint8_t>& aCodecSpecific,
                             GMPVideoEncoderCallbackProxy* aCallback,
                             int32_t aNumberOfCores,
                             uint32_t aMaxPayloadSize) MOZ_OVERRIDE;
-  virtual GMPErr Encode(GMPVideoi420Frame* aInputFrame,
+  virtual GMPErr Encode(UniquePtr<GMPVideoi420Frame> aInputFrame,
                         const nsTArray<uint8_t>& aCodecSpecificInfo,
                         const nsTArray<GMPVideoFrameType>& aFrameTypes) MOZ_OVERRIDE;
   virtual GMPErr SetChannelParameters(uint32_t aPacketLoss, uint32_t aRTT) MOZ_OVERRIDE;
   virtual GMPErr SetRates(uint32_t aNewBitRate, uint32_t aFrameRate) MOZ_OVERRIDE;
   virtual GMPErr SetPeriodicKeyFrames(bool aEnable) MOZ_OVERRIDE;
   virtual const uint64_t ParentID() MOZ_OVERRIDE { return reinterpret_cast<uint64_t>(mPlugin.get()); }
 
   // GMPSharedMemManager
--- a/content/media/gmp/GMPVideoEncoderProxy.h
+++ b/content/media/gmp/GMPVideoEncoderProxy.h
@@ -7,16 +7,17 @@
 #define GMPVideoEncoderProxy_h_
 
 #include "nsTArray.h"
 #include "gmp-video-encode.h"
 #include "gmp-video-frame-i420.h"
 #include "gmp-video-frame-encoded.h"
 
 #include "GMPCallbackBase.h"
+#include "mozilla/UniquePtr.h"
 
 class GMPVideoEncoderCallbackProxy : public GMPCallbackBase {
 public:
   virtual ~GMPVideoEncoderCallbackProxy() {}
   virtual void Encoded(GMPVideoEncodedFrame* aEncodedFrame,
                        const nsTArray<uint8_t>& aCodecSpecificInfo) = 0;
   virtual void Error(GMPErr aError) = 0;
 };
@@ -34,22 +35,35 @@ public:
 // This interface is not thread-safe and must only be used from GMPThread.
 class GMPVideoEncoderProxy {
 public:
   virtual GMPErr InitEncode(const GMPVideoCodec& aCodecSettings,
                             const nsTArray<uint8_t>& aCodecSpecific,
                             GMPVideoEncoderCallbackProxy* aCallback,
                             int32_t aNumberOfCores,
                             uint32_t aMaxPayloadSize) = 0;
-  virtual GMPErr Encode(GMPVideoi420Frame* aInputFrame,
+  virtual GMPErr Encode(mozilla::UniquePtr<GMPVideoi420Frame> aInputFrame,
                         const nsTArray<uint8_t>& aCodecSpecificInfo,
                         const nsTArray<GMPVideoFrameType>& aFrameTypes) = 0;
   virtual GMPErr SetChannelParameters(uint32_t aPacketLoss, uint32_t aRTT) = 0;
   virtual GMPErr SetRates(uint32_t aNewBitRate, uint32_t aFrameRate) = 0;
   virtual GMPErr SetPeriodicKeyFrames(bool aEnable) = 0;
   virtual const uint64_t ParentID() = 0;
 
   // Call to tell GMP/plugin the consumer will no longer use this
   // interface/codec.
   virtual void Close() = 0;
 };
 
+namespace mozilla {
+
+template<>
+struct DefaultDelete<GMPVideoi420Frame>
+{
+  void operator()(GMPVideoi420Frame* aFrame) const
+  {
+    aFrame->Destroy();
+  }
+};
+
+} // namespace mozilla
+
 #endif // GMPVideoEncoderProxy_h_
--- a/content/media/gmp/GMPVideoi420FrameImpl.h
+++ b/content/media/gmp/GMPVideoi420FrameImpl.h
@@ -2,16 +2,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef GMPVideoi420FrameImpl_h_
 #define GMPVideoi420FrameImpl_h_
 
 #include "gmp-video-frame-i420.h"
+#include "mozilla/UniquePtr.h"
 #include "mozilla/ipc/Shmem.h"
 #include "GMPVideoPlaneImpl.h"
 
 namespace mozilla {
 namespace gmp {
 
 class GMPVideoi420FrameData;
 
@@ -71,11 +72,21 @@ private:
   GMPPlaneImpl mVPlane;
   int32_t mWidth;
   int32_t mHeight;
   uint64_t mTimestamp;
   uint64_t mDuration;
 };
 
 } // namespace gmp
+
+template<>
+struct DefaultDelete<mozilla::gmp::GMPVideoi420FrameImpl>
+{
+  void operator()(mozilla::gmp::GMPVideoi420FrameImpl* aFrame) const
+  {
+    aFrame->Destroy();
+  }
+};
+
 } // namespace mozilla
 
 #endif // GMPVideoi420FrameImpl_h_
--- a/content/media/gmp/moz.build
+++ b/content/media/gmp/moz.build
@@ -109,14 +109,13 @@ DEFINES['GMP_SAFE_SHMEM'] = True
 
 FAIL_ON_WARNINGS = True
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 # media/mtransport so we work with --disable-webrtc
 LOCAL_INCLUDES += [
-    '../base',
     '/media/mtransport',
     '/xpcom/base',
     '/xpcom/build',
     '/xpcom/threads',
 ]
--- a/content/media/mediasource/MediaSourceDecoder.cpp
+++ b/content/media/mediasource/MediaSourceDecoder.cpp
@@ -1,15 +1,16 @@
 /* -*- mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #include "MediaSourceDecoder.h"
 
+#include "prlog.h"
 #include "mozilla/dom/HTMLMediaElement.h"
 #include "mozilla/dom/TimeRanges.h"
 #include "MediaDecoderStateMachine.h"
 #include "MediaSource.h"
 #include "MediaSourceReader.h"
 #include "MediaSourceResource.h"
 #include "MediaSourceUtils.h"
 
@@ -23,17 +24,17 @@ extern PRLogModuleInfo* GetMediaSourceAP
 #else
 #define MSE_DEBUG(...)
 #define MSE_DEBUGV(...)
 #define MSE_API(...)
 #endif
 
 namespace mozilla {
 
-class SubBufferDecoder;
+class SourceBufferDecoder;
 
 MediaSourceDecoder::MediaSourceDecoder(dom::HTMLMediaElement* aElement)
   : mMediaSource(nullptr)
 {
   Init(aElement);
 }
 
 MediaDecoder*
@@ -100,16 +101,16 @@ MediaSourceDecoder::AttachMediaSource(do
 }
 
 void
 MediaSourceDecoder::DetachMediaSource()
 {
   mMediaSource = nullptr;
 }
 
-already_AddRefed<SubBufferDecoder>
+already_AddRefed<SourceBufferDecoder>
 MediaSourceDecoder::CreateSubDecoder(const nsACString& aType)
 {
   MOZ_ASSERT(mReader);
   return mReader->CreateSubDecoder(aType);
 }
 
 } // namespace mozilla
--- a/content/media/mediasource/MediaSourceDecoder.h
+++ b/content/media/mediasource/MediaSourceDecoder.h
@@ -14,17 +14,17 @@
 
 class nsIStreamListener;
 
 namespace mozilla {
 
 class MediaResource;
 class MediaDecoderStateMachine;
 class MediaSourceReader;
-class SubBufferDecoder;
+class SourceBufferDecoder;
 
 namespace dom {
 
 class HTMLMediaElement;
 class MediaSource;
 
 } // namespace dom
 
@@ -38,17 +38,17 @@ public:
   virtual nsresult Load(nsIStreamListener**, MediaDecoder*) MOZ_OVERRIDE;
   virtual nsresult GetSeekable(dom::TimeRanges* aSeekable) MOZ_OVERRIDE;
 
   static already_AddRefed<MediaResource> CreateResource();
 
   void AttachMediaSource(dom::MediaSource* aMediaSource);
   void DetachMediaSource();
 
-  already_AddRefed<SubBufferDecoder> CreateSubDecoder(const nsACString& aType);
+  already_AddRefed<SourceBufferDecoder> CreateSubDecoder(const nsACString& aType);
 
 private:
   // The owning MediaSource holds a strong reference to this decoder, and
   // calls Attach/DetachMediaSource on this decoder to set and clear
   // mMediaSource.
   dom::MediaSource* mMediaSource;
   nsRefPtr<MediaSourceReader> mReader;
 };
--- a/content/media/mediasource/MediaSourceReader.cpp
+++ b/content/media/mediasource/MediaSourceReader.cpp
@@ -1,23 +1,24 @@
 /* -*- mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #include "MediaSourceReader.h"
 
+#include "prlog.h"
 #include "mozilla/dom/TimeRanges.h"
 #include "DecoderTraits.h"
 #include "MediaDataDecodedListener.h"
 #include "MediaDecoderOwner.h"
 #include "MediaSource.h"
 #include "MediaSourceDecoder.h"
 #include "MediaSourceUtils.h"
-#include "SubBufferDecoder.h"
+#include "SourceBufferDecoder.h"
 
 #ifdef MOZ_FMP4
 #include "MP4Decoder.h"
 #include "MP4Reader.h"
 #endif
 
 #ifdef PR_LOGGING
 extern PRLogModuleInfo* GetMediaSourceLog();
@@ -212,17 +213,17 @@ MediaSourceReader::SwitchReaders(SwitchT
   ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
 
   InitializePendingDecoders();
 
   bool didSwitch = false;
   double decodeTarget = double(mTimeThreshold) / USECS_PER_S;
 
   for (uint32_t i = 0; i < mDecoders.Length(); ++i) {
-    SubBufferDecoder* decoder = mDecoders[i];
+    SourceBufferDecoder* decoder = mDecoders[i];
     const MediaInfo& info = decoder->GetReader()->GetMediaInfo();
 
     nsRefPtr<dom::TimeRanges> ranges = new dom::TimeRanges();
     decoder->GetBuffered(ranges);
 
     MSE_DEBUGV("MediaDecoderReader(%p)::SwitchReaders(%d) decoder=%u (%p) discarded=%d"
                " reader=%p audioReader=%p videoReader=%p"
                " hasAudio=%d hasVideo=%d decodeTarget=%f ranges=%s",
@@ -253,36 +254,36 @@ MediaSourceReader::SetMediaSourceDuratio
 {
   MOZ_ASSERT(NS_IsMainThread());
   ErrorResult dummy;
   mMediaSource->SetDuration(aDuration, dummy);
 }
 
 class ReleaseDecodersTask : public nsRunnable {
 public:
-  ReleaseDecodersTask(nsTArray<nsRefPtr<SubBufferDecoder>>& aDecoders)
+  ReleaseDecodersTask(nsTArray<nsRefPtr<SourceBufferDecoder>>& aDecoders)
   {
     mDecoders.SwapElements(aDecoders);
   }
 
   NS_IMETHOD Run() MOZ_OVERRIDE MOZ_FINAL {
     mDecoders.Clear();
     return NS_OK;
   }
 
 private:
-  nsTArray<nsRefPtr<SubBufferDecoder>> mDecoders;
+  nsTArray<nsRefPtr<SourceBufferDecoder>> mDecoders;
 };
 
 void
 MediaSourceReader::InitializePendingDecoders()
 {
   ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
   for (uint32_t i = 0; i < mPendingDecoders.Length(); ++i) {
-    nsRefPtr<SubBufferDecoder> decoder = mPendingDecoders[i];
+    nsRefPtr<SourceBufferDecoder> decoder = mPendingDecoders[i];
     MediaDecoderReader* reader = decoder->GetReader();
     MSE_DEBUG("MediaSourceReader(%p): Initializing subdecoder %p reader %p",
               this, decoder.get(), reader);
 
     MediaInfo mi;
     nsAutoPtr<MetadataTags> tags; // TODO: Handle metadata.
     nsresult rv;
     {
@@ -334,22 +335,22 @@ CreateReaderForType(const nsACString& aT
        aType.LowerCaseEqualsLiteral("audio/mp4")) &&
       MP4Decoder::IsEnabled()) {
     return new MP4Reader(aDecoder);
   }
 #endif
   return DecoderTraits::CreateReader(aType, aDecoder);
 }
 
-already_AddRefed<SubBufferDecoder>
+already_AddRefed<SourceBufferDecoder>
 MediaSourceReader::CreateSubDecoder(const nsACString& aType)
 {
   MOZ_ASSERT(GetTaskQueue());
-  nsRefPtr<SubBufferDecoder> decoder =
-    new SubBufferDecoder(new SourceBufferResource(nullptr, aType), mDecoder);
+  nsRefPtr<SourceBufferDecoder> decoder =
+    new SourceBufferDecoder(new SourceBufferResource(nullptr, aType), mDecoder);
   nsRefPtr<MediaDecoderReader> reader(CreateReaderForType(aType, decoder));
   if (!reader) {
     return nullptr;
   }
   // Set a callback on the subreader that forwards calls to this reader.
   // This reader will then forward them onto the state machine via this
   // reader's callback.
   RefPtr<MediaDataDecodedListener<MediaSourceReader>> callback =
@@ -428,22 +429,24 @@ MediaSourceReader::Seek(int64_t aTime, i
 
   if (IsShutdown()) {
     return NS_OK;
   }
 
   ResetDecode();
   if (mAudioReader) {
     nsresult rv = mAudioReader->Seek(aTime, aStartTime, aEndTime, aCurrentTime);
+    MSE_DEBUG("MediaSourceReader(%p)::Seek audio reader=%p rv=%xf", this, mAudioReader.get(), rv);
     if (NS_FAILED(rv)) {
       return rv;
     }
   }
   if (mVideoReader) {
     nsresult rv = mVideoReader->Seek(aTime, aStartTime, aEndTime, aCurrentTime);
+    MSE_DEBUG("MediaSourceReader(%p)::Seek video reader=%p rv=%xf", this, mVideoReader.get(), rv);
     if (NS_FAILED(rv)) {
       return rv;
     }
   }
   return NS_OK;
 }
 
 nsresult
--- a/content/media/mediasource/MediaSourceReader.h
+++ b/content/media/mediasource/MediaSourceReader.h
@@ -13,17 +13,17 @@
 #include "nsError.h"
 #include "nsString.h"
 #include "nsTArray.h"
 #include "MediaDecoderReader.h"
 
 namespace mozilla {
 
 class MediaSourceDecoder;
-class SubBufferDecoder;
+class SourceBufferDecoder;
 
 namespace dom {
 
 class MediaSource;
 
 } // namespace dom
 
 class MediaSourceReader : public MediaDecoderReader
@@ -65,17 +65,17 @@ public:
     return mInfo.HasAudio();
   }
 
   bool IsMediaSeekable() { return true; }
 
   nsresult ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags) MOZ_OVERRIDE;
   nsresult Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime,
                 int64_t aCurrentTime) MOZ_OVERRIDE;
-  already_AddRefed<SubBufferDecoder> CreateSubDecoder(const nsACString& aType);
+  already_AddRefed<SourceBufferDecoder> CreateSubDecoder(const nsACString& aType);
 
   void Shutdown();
 
   virtual void BreakCycles();
 
   void InitializePendingDecoders();
 
   bool IsShutdown()
@@ -100,18 +100,18 @@ private:
 
   void SetMediaSourceDuration(double aDuration) ;
 
   // These are read and written on the decode task queue threads.
   int64_t mTimeThreshold;
   bool mDropAudioBeforeThreshold;
   bool mDropVideoBeforeThreshold;
 
-  nsTArray<nsRefPtr<SubBufferDecoder>> mPendingDecoders;
-  nsTArray<nsRefPtr<SubBufferDecoder>> mDecoders;
+  nsTArray<nsRefPtr<SourceBufferDecoder>> mPendingDecoders;
+  nsTArray<nsRefPtr<SourceBufferDecoder>> mDecoders;
 
   nsRefPtr<MediaDecoderReader> mAudioReader;
   nsRefPtr<MediaDecoderReader> mVideoReader;
 
   dom::MediaSource* mMediaSource;
 };
 
 } // namespace mozilla
--- a/content/media/mediasource/MediaSourceResource.h
+++ b/content/media/mediasource/MediaSourceResource.h
@@ -3,16 +3,28 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MOZILLA_MEDIASOURCERESOURCE_H_
 #define MOZILLA_MEDIASOURCERESOURCE_H_
 
 #include "MediaResource.h"
+#include "prlog.h"
+
+#ifdef PR_LOGGING
+extern PRLogModuleInfo* GetMediaSourceLog();
+extern PRLogModuleInfo* GetMediaSourceAPILog();
+
+#define MSE_DEBUG(...) PR_LOG(GetMediaSourceLog(), PR_LOG_DEBUG, (__VA_ARGS__))
+#else
+#define MSE_DEBUG(...)
+#endif
+
+#define UNIMPLEMENTED() MSE_DEBUG("MediaSourceResource(%p): UNIMPLEMENTED FUNCTION at line %d", this, __LINE__)
 
 namespace mozilla {
 
 class MediaSourceResource MOZ_FINAL : public MediaResource
 {
 public:
   MediaSourceResource() {}
 
@@ -39,22 +51,23 @@ public:
   virtual bool IsDataCachedToEndOfResource(int64_t aOffset) MOZ_OVERRIDE { return false; }
   virtual bool IsSuspendedByCache() MOZ_OVERRIDE { return false; }
   virtual bool IsSuspended() MOZ_OVERRIDE { return false; }
   virtual nsresult ReadFromCache(char* aBuffer, int64_t aOffset, uint32_t aCount) MOZ_OVERRIDE { return NS_ERROR_FAILURE; }
   virtual nsresult Open(nsIStreamListener** aStreamListener) MOZ_OVERRIDE { return NS_ERROR_FAILURE; }
 
   virtual nsresult GetCachedRanges(nsTArray<MediaByteRange>& aRanges) MOZ_OVERRIDE
   {
+    UNIMPLEMENTED();
     aRanges.AppendElement(MediaByteRange(0, GetLength()));
     return NS_OK;
   }
 
-  virtual bool IsTransportSeekable() MOZ_OVERRIDE { return true; }
-  virtual const nsCString& GetContentType() const MOZ_OVERRIDE { return mType; }
+  virtual bool IsTransportSeekable() MOZ_OVERRIDE { UNIMPLEMENTED(); return true; }
+  virtual const nsCString& GetContentType() const MOZ_OVERRIDE { UNIMPLEMENTED(); return mType; }
 
 private:
   virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE
   {
     size_t size = MediaResource::SizeOfExcludingThis(aMallocSizeOf);
     size += mType.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
 
     return size;
@@ -65,9 +78,11 @@ private:
     return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
   }
 
   const nsCString mType;
 };
 
 } // namespace mozilla
 
+#undef UNIMPLEMENTED
+
 #endif /* MOZILLA_MEDIASOURCERESOURCE_H_ */
--- a/content/media/mediasource/SourceBuffer.cpp
+++ b/content/media/mediasource/SourceBuffer.cpp
@@ -16,17 +16,17 @@
 #include "mozilla/FloatingPoint.h"
 #include "mozilla/dom/MediaSourceBinding.h"
 #include "mozilla/dom/TimeRanges.h"
 #include "nsError.h"
 #include "nsIEventTarget.h"
 #include "nsIRunnable.h"
 #include "nsThreadUtils.h"
 #include "prlog.h"
-#include "SubBufferDecoder.h"
+#include "SourceBufferDecoder.h"
 #include "mozilla/Preferences.h"
 
 struct JSContext;
 class JSObject;
 
 #ifdef PR_LOGGING
 extern PRLogModuleInfo* GetMediaSourceLog();
 extern PRLogModuleInfo* GetMediaSourceAPILog();
@@ -376,17 +376,17 @@ SourceBuffer::QueueAsyncSimpleEvent(cons
 
 bool
 SourceBuffer::InitNewDecoder()
 {
   MOZ_ASSERT(NS_IsMainThread());
   MSE_DEBUG("SourceBuffer(%p)::InitNewDecoder", this);
   MOZ_ASSERT(!mDecoder);
   MediaSourceDecoder* parentDecoder = mMediaSource->GetDecoder();
-  nsRefPtr<SubBufferDecoder> decoder = parentDecoder->CreateSubDecoder(mType);
+  nsRefPtr<SourceBufferDecoder> decoder = parentDecoder->CreateSubDecoder(mType);
   if (!decoder) {
     return false;
   }
   mDecoder = decoder;
   mDecoderInitialized = false;
   mDecoders.AppendElement(mDecoder);
   return true;
 }
--- a/content/media/mediasource/SourceBuffer.h
+++ b/content/media/mediasource/SourceBuffer.h
@@ -27,17 +27,17 @@
 class JSObject;
 struct JSContext;
 
 namespace mozilla {
 
 class ContainerParser;
 class ErrorResult;
 class SourceBufferResource;
-class SubBufferDecoder;
+class SourceBufferDecoder;
 template <typename T> class AsyncEventRunner;
 
 namespace dom {
 
 class TimeRanges;
 
 class SourceBuffer MOZ_FINAL : public DOMEventTargetHelper
 {
@@ -136,18 +136,18 @@ private:
   void AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aRv);
 
   nsRefPtr<MediaSource> mMediaSource;
 
   const nsCString mType;
 
   nsAutoPtr<ContainerParser> mParser;
 
-  nsRefPtr<SubBufferDecoder> mDecoder;
-  nsTArray<nsRefPtr<SubBufferDecoder>> mDecoders;
+  nsRefPtr<SourceBufferDecoder> mDecoder;
+  nsTArray<nsRefPtr<SourceBufferDecoder>> mDecoders;
 
   double mAppendWindowStart;
   double mAppendWindowEnd;
 
   double mTimestampOffset;
 
   SourceBufferAppendMode mAppendMode;
   bool mUpdating;
rename from content/media/mediasource/SubBufferDecoder.cpp
rename to content/media/mediasource/SourceBufferDecoder.cpp
--- a/content/media/mediasource/SubBufferDecoder.cpp
+++ b/content/media/mediasource/SourceBufferDecoder.cpp
@@ -1,14 +1,15 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "SubBufferDecoder.h"
+#include "SourceBufferDecoder.h"
+#include "prlog.h"
 #include "AbstractMediaDecoder.h"
 #include "MediaDecoderReader.h"
 #include "mozilla/dom/TimeRanges.h"
 
 #ifdef PR_LOGGING
 extern PRLogModuleInfo* GetMediaSourceLog();
 extern PRLogModuleInfo* GetMediaSourceAPILog();
 
@@ -24,98 +25,206 @@ namespace mozilla {
 class ReentrantMonitor;
 
 namespace layers {
 
 class ImageContainer;
 
 } // namespace layers
 
+NS_IMPL_ISUPPORTS0(SourceBufferDecoder)
+
+SourceBufferDecoder::SourceBufferDecoder(MediaResource* aResource,
+                                         AbstractMediaDecoder* aParentDecoder)
+  : mResource(aResource)
+  , mParentDecoder(aParentDecoder)
+  , mReader(nullptr)
+  , mMediaDuration(-1)
+  , mDiscarded(false)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_COUNT_CTOR(SourceBufferDecoder);
+}
+
+SourceBufferDecoder::~SourceBufferDecoder()
+{
+  MOZ_COUNT_DTOR(SourceBufferDecoder);
+}
+
+bool
+SourceBufferDecoder::IsShutdown() const
+{
+  // SourceBufferDecoder cannot be shut down.
+  MSE_DEBUG("SourceBufferDecoder(%p)::IsShutdown UNIMPLEMENTED", this);
+  return false;
+}
+
+void
+SourceBufferDecoder::NotifyBytesConsumed(int64_t aBytes, int64_t aOffset)
+{
+  MSE_DEBUG("SourceBufferDecoder(%p)::NotifyBytesConsumed UNIMPLEMENTED", this);
+}
+
+int64_t
+SourceBufferDecoder::GetEndMediaTime() const
+{
+  MSE_DEBUG("SourceBufferDecoder(%p)::GetEndMediaTime UNIMPLEMENTED", this);
+  return -1;
+}
+
+int64_t
+SourceBufferDecoder::GetMediaDuration()
+{
+  return mMediaDuration;
+}
+
+VideoFrameContainer*
+SourceBufferDecoder::GetVideoFrameContainer()
+{
+  MSE_DEBUG("SourceBufferDecoder(%p)::GetVideoFrameContainer UNIMPLEMENTED", this);
+  return nullptr;
+}
+
+bool
+SourceBufferDecoder::IsTransportSeekable()
+{
+  MSE_DEBUG("SourceBufferDecoder(%p)::IsTransportSeekable UNIMPLEMENTED", this);
+  return false;
+}
+
+bool
+SourceBufferDecoder::IsMediaSeekable()
+{
+  MSE_DEBUG("SourceBufferDecoder(%p)::IsMediaSeekable UNIMPLEMENTED", this);
+  return false;
+}
+
+void
+SourceBufferDecoder::MetadataLoaded(MediaInfo* aInfo, MetadataTags* aTags)
+{
+  MSE_DEBUG("SourceBufferDecoder(%p)::MetadataLoaded UNIMPLEMENTED", this);
+}
+
+void
+SourceBufferDecoder::QueueMetadata(int64_t aTime, MediaInfo* aInfo, MetadataTags* aTags)
+{
+  MSE_DEBUG("SourceBufferDecoder(%p)::QueueMetadata UNIMPLEMENTED", this);
+}
+
+void
+SourceBufferDecoder::RemoveMediaTracks()
+{
+  MSE_DEBUG("SourceBufferDecoder(%p)::RemoveMediaTracks UNIMPLEMENTED", this);
+}
+
+void
+SourceBufferDecoder::SetMediaEndTime(int64_t aTime)
+{
+  MSE_DEBUG("SourceBufferDecoder(%p)::SetMediaEndTime UNIMPLEMENTED", this);
+}
+
+void
+SourceBufferDecoder::UpdatePlaybackPosition(int64_t aTime)
+{
+  MSE_DEBUG("SourceBufferDecoder(%p)::UpdatePlaybackPosition UNIMPLEMENTED", this);
+}
+
+void
+SourceBufferDecoder::OnReadMetadataCompleted()
+{
+  MSE_DEBUG("SourceBufferDecoder(%p)::OnReadMetadataCompleted UNIMPLEMENTED", this);
+}
+
+void
+SourceBufferDecoder::NotifyWaitingForResourcesStatusChanged()
+{
+  MSE_DEBUG("SourceBufferDecoder(%p)::NotifyWaitingForResourcesStatusChanged UNIMPLEMENTED", this);
+}
 
 ReentrantMonitor&
-SubBufferDecoder::GetReentrantMonitor()
+SourceBufferDecoder::GetReentrantMonitor()
 {
   return mParentDecoder->GetReentrantMonitor();
 }
 
 bool
-SubBufferDecoder::OnStateMachineThread() const
+SourceBufferDecoder::OnStateMachineThread() const
 {
   return mParentDecoder->OnStateMachineThread();
 }
 
 bool
-SubBufferDecoder::OnDecodeThread() const
+SourceBufferDecoder::OnDecodeThread() const
 {
   return mParentDecoder->OnDecodeThread();
 }
 
 SourceBufferResource*
-SubBufferDecoder::GetResource() const
+SourceBufferDecoder::GetResource() const
 {
   return static_cast<SourceBufferResource*>(mResource.get());
 }
 
 void
-SubBufferDecoder::NotifyDecodedFrames(uint32_t aParsed, uint32_t aDecoded)
+SourceBufferDecoder::NotifyDecodedFrames(uint32_t aParsed, uint32_t aDecoded)
 {
   return mParentDecoder->NotifyDecodedFrames(aParsed, aDecoded);
 }
 
 void
-SubBufferDecoder::SetMediaDuration(int64_t aDuration)
+SourceBufferDecoder::SetMediaDuration(int64_t aDuration)
 {
   mMediaDuration = aDuration;
 }
 
 void
-SubBufferDecoder::UpdateEstimatedMediaDuration(int64_t aDuration)
+SourceBufferDecoder::UpdateEstimatedMediaDuration(int64_t aDuration)
 {
-  MSE_DEBUG("SubBufferDecoder(%p)::UpdateEstimatedMediaDuration(aDuration=%lld)", this, aDuration);
+  MSE_DEBUG("SourceBufferDecoder(%p)::UpdateEstimatedMediaDuration UNIMPLEMENTED", this);
 }
 
 void
-SubBufferDecoder::SetMediaSeekable(bool aMediaSeekable)
+SourceBufferDecoder::SetMediaSeekable(bool aMediaSeekable)
 {
-  MSE_DEBUG("SubBufferDecoder(%p)::SetMediaSeekable(aMediaSeekable=%d)", this, aMediaSeekable);
+  MSE_DEBUG("SourceBufferDecoder(%p)::SetMediaSeekable UNIMPLEMENTED", this);
 }
 
 layers::ImageContainer*
-SubBufferDecoder::GetImageContainer()
+SourceBufferDecoder::GetImageContainer()
 {
   return mParentDecoder->GetImageContainer();
 }
 
 MediaDecoderOwner*
-SubBufferDecoder::GetOwner()
+SourceBufferDecoder::GetOwner()
 {
   return mParentDecoder->GetOwner();
 }
 
 void
-SubBufferDecoder::NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset)
+SourceBufferDecoder::NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset)
 {
   mReader->NotifyDataArrived(aBuffer, aLength, aOffset);
 
   // XXX: Params make no sense to parent decoder as it relates to a
-  // specific SubBufferDecoder's data stream.  Pass bogus values here to
+  // specific SourceBufferDecoder's data stream.  Pass bogus values here to
   // force parent decoder's state machine to recompute end time for
   // infinite length media.
   mParentDecoder->NotifyDataArrived(nullptr, 0, 0);
 }
 
 nsresult
-SubBufferDecoder::GetBuffered(dom::TimeRanges* aBuffered)
+SourceBufferDecoder::GetBuffered(dom::TimeRanges* aBuffered)
 {
   // XXX: Need mStartTime (from StateMachine) instead of passing 0.
   return mReader->GetBuffered(aBuffered, 0);
 }
 
 int64_t
-SubBufferDecoder::ConvertToByteOffset(double aTime)
+SourceBufferDecoder::ConvertToByteOffset(double aTime)
 {
   int64_t readerOffset = mReader->GetEvictionOffset(aTime);
   if (readerOffset >= 0) {
     return readerOffset;
   }
 
   // Uses a conversion based on (aTime/duration) * length.  For the
   // purposes of eviction this should be adequate since we have the
@@ -126,17 +235,17 @@ SubBufferDecoder::ConvertToByteOffset(do
   }
   int64_t length = GetResource()->GetLength();
   MOZ_ASSERT(length > 0);
   int64_t offset = (aTime / (double(mMediaDuration) / USECS_PER_S)) * length;
   return offset;
 }
 
 bool
-SubBufferDecoder::ContainsTime(double aTime)
+SourceBufferDecoder::ContainsTime(double aTime)
 {
   ErrorResult dummy;
   nsRefPtr<dom::TimeRanges> ranges = new dom::TimeRanges();
   nsresult rv = GetBuffered(ranges);
   if (NS_FAILED(rv) || ranges->Length() == 0) {
     return false;
   }
   return ranges->Find(aTime) != dom::TimeRanges::NoIndex;
rename from content/media/mediasource/SubBufferDecoder.h
rename to content/media/mediasource/SourceBufferDecoder.h
--- a/content/media/mediasource/SubBufferDecoder.h
+++ b/content/media/mediasource/SourceBufferDecoder.h
@@ -1,95 +1,109 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef MOZILLA_SUBBUFFERDECODER_H_
-#define MOZILLA_SUBBUFFERDECODER_H_
+#ifndef MOZILLA_SOURCEBUFFERDECODER_H_
+#define MOZILLA_SOURCEBUFFERDECODER_H_
 
-#include "BufferDecoder.h"
+#include "AbstractMediaDecoder.h"
+#include "mozilla/Attributes.h"
+#include "mozilla/ReentrantMonitor.h"
 #include "SourceBufferResource.h"
 
 namespace mozilla {
 
 class MediaResource;
-class MediaSourceDecoder;
 class MediaDecoderReader;
 
 namespace dom {
 
 class TimeRanges;
 
 } // namespace dom
 
-class SubBufferDecoder : public BufferDecoder
+class SourceBufferDecoder : public AbstractMediaDecoder
 {
 public:
   // This class holds a weak pointer to MediaResource.  It's the responsibility
   // of the caller to manage the memory of the MediaResource object.
-  SubBufferDecoder(MediaResource* aResource, AbstractMediaDecoder* aParentDecoder)
-    : BufferDecoder(aResource), mParentDecoder(aParentDecoder), mReader(nullptr)
-    , mMediaDuration(-1), mDiscarded(false)
-  {
-  }
+  SourceBufferDecoder(MediaResource* aResource, AbstractMediaDecoder* aParentDecoder);
+
+  NS_DECL_THREADSAFE_ISUPPORTS
+
+  virtual bool IsMediaSeekable() MOZ_FINAL MOZ_OVERRIDE;
+  virtual bool IsShutdown() const MOZ_FINAL MOZ_OVERRIDE;
+  virtual bool IsTransportSeekable() MOZ_FINAL MOZ_OVERRIDE;
+  virtual bool OnDecodeThread() const MOZ_FINAL MOZ_OVERRIDE;
+  virtual bool OnStateMachineThread() const MOZ_FINAL MOZ_OVERRIDE;
+  virtual int64_t GetEndMediaTime() const MOZ_FINAL MOZ_OVERRIDE;
+  virtual int64_t GetMediaDuration() MOZ_FINAL MOZ_OVERRIDE;
+  virtual layers::ImageContainer* GetImageContainer() MOZ_FINAL MOZ_OVERRIDE;
+  virtual MediaDecoderOwner* GetOwner() MOZ_FINAL MOZ_OVERRIDE;
+  virtual SourceBufferResource* GetResource() const MOZ_FINAL MOZ_OVERRIDE;
+  virtual ReentrantMonitor& GetReentrantMonitor() MOZ_FINAL MOZ_OVERRIDE;
+  virtual VideoFrameContainer* GetVideoFrameContainer() MOZ_FINAL MOZ_OVERRIDE;
+  virtual void MetadataLoaded(MediaInfo* aInfo, MetadataTags* aTags) MOZ_FINAL MOZ_OVERRIDE;
+  virtual void NotifyBytesConsumed(int64_t aBytes, int64_t aOffset) MOZ_FINAL MOZ_OVERRIDE;
+  virtual void NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset) MOZ_FINAL MOZ_OVERRIDE;
+  virtual void NotifyDecodedFrames(uint32_t aParsed, uint32_t aDecoded) MOZ_FINAL MOZ_OVERRIDE;
+  virtual void NotifyWaitingForResourcesStatusChanged() MOZ_FINAL MOZ_OVERRIDE;
+  virtual void OnReadMetadataCompleted() MOZ_FINAL MOZ_OVERRIDE;
+  virtual void QueueMetadata(int64_t aTime, MediaInfo* aInfo, MetadataTags* aTags) MOZ_FINAL MOZ_OVERRIDE;
+  virtual void RemoveMediaTracks() MOZ_FINAL MOZ_OVERRIDE;
+  virtual void SetMediaDuration(int64_t aDuration) MOZ_FINAL MOZ_OVERRIDE;
+  virtual void SetMediaEndTime(int64_t aTime) MOZ_FINAL MOZ_OVERRIDE;
+  virtual void SetMediaSeekable(bool aMediaSeekable) MOZ_FINAL MOZ_OVERRIDE;
+  virtual void UpdateEstimatedMediaDuration(int64_t aDuration) MOZ_FINAL MOZ_OVERRIDE;
+  virtual void UpdatePlaybackPosition(int64_t aTime) MOZ_FINAL MOZ_OVERRIDE;
+
+  // SourceBufferResource specific interface below.
+
+  // Warning: this mirrors GetBuffered in MediaDecoder, but this class's base is
+  // AbstractMediaDecoder, which does not supply this interface.
+  nsresult GetBuffered(dom::TimeRanges* aBuffered);
 
   void SetReader(MediaDecoderReader* aReader)
   {
     MOZ_ASSERT(!mReader);
     mReader = aReader;
   }
 
   MediaDecoderReader* GetReader()
   {
     return mReader;
   }
 
-  virtual ReentrantMonitor& GetReentrantMonitor() MOZ_OVERRIDE;
-  virtual bool OnStateMachineThread() const MOZ_OVERRIDE;
-  virtual bool OnDecodeThread() const MOZ_OVERRIDE;
-  virtual SourceBufferResource* GetResource() const MOZ_OVERRIDE;
-  virtual void NotifyDecodedFrames(uint32_t aParsed, uint32_t aDecoded) MOZ_OVERRIDE;
-  virtual void SetMediaDuration(int64_t aDuration) MOZ_OVERRIDE;
-  virtual void UpdateEstimatedMediaDuration(int64_t aDuration) MOZ_OVERRIDE;
-  virtual void SetMediaSeekable(bool aMediaSeekable) MOZ_OVERRIDE;
-  virtual layers::ImageContainer* GetImageContainer() MOZ_OVERRIDE;
-  virtual MediaDecoderOwner* GetOwner() MOZ_OVERRIDE;
-
-  // Warning: these mirror calls from MediaDecoder, but this class's base is
-  // AbstractMediaDecoder, which does not supply this interface.
-  void NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset);
-  nsresult GetBuffered(dom::TimeRanges* aBuffered);
-
   // Given a time convert it into an approximate byte offset from the
   // cached data. Returns -1 if no such value is computable.
   int64_t ConvertToByteOffset(double aTime);
 
-  int64_t GetMediaDuration() MOZ_OVERRIDE
-  {
-    return mMediaDuration;
-  }
-
   bool IsDiscarded()
   {
     return mDiscarded;
   }
 
   void SetDiscarded()
   {
     GetResource()->Ended();
     mDiscarded = true;
   }
 
   // Returns true if the data buffered by this decoder contains the given time.
   bool ContainsTime(double aTime);
 
 private:
+  virtual ~SourceBufferDecoder();
+
+  nsRefPtr<MediaResource> mResource;
+
   AbstractMediaDecoder* mParentDecoder;
   nsRefPtr<MediaDecoderReader> mReader;
   int64_t mMediaDuration;
   bool mDiscarded;
 };
 
 } // namespace mozilla
 
-#endif /* MOZILLA_SUBBUFFERDECODER_H_ */
+#endif /* MOZILLA_SOURCEBUFFERDECODER_H_ */
--- a/content/media/mediasource/SourceBufferResource.h
+++ b/content/media/mediasource/SourceBufferResource.h
@@ -13,16 +13,28 @@
 #include "mozilla/Attributes.h"
 #include "mozilla/ReentrantMonitor.h"
 #include "nsCOMPtr.h"
 #include "nsError.h"
 #include "nsIPrincipal.h"
 #include "nsString.h"
 #include "nsTArray.h"
 #include "nscore.h"
+#include "prlog.h"
+
+#ifdef PR_LOGGING
+extern PRLogModuleInfo* GetMediaSourceLog();
+extern PRLogModuleInfo* GetMediaSourceAPILog();
+
+#define MSE_DEBUG(...) PR_LOG(GetMediaSourceLog(), PR_LOG_DEBUG, (__VA_ARGS__))
+#else
+#define MSE_DEBUG(...)
+#endif
+
+#define UNIMPLEMENTED() MSE_DEBUG("SourceBufferResource(%p): UNIMPLEMENTED FUNCTION at line %d", this, __LINE__)
 
 class nsIStreamListener;
 
 namespace mozilla {
 
 class MediaDecoder;
 
 namespace dom {
@@ -32,49 +44,50 @@ class SourceBuffer;
 }  // namespace dom
 
 class SourceBufferResource MOZ_FINAL : public MediaResource
 {
 public:
   SourceBufferResource(nsIPrincipal* aPrincipal,
                        const nsACString& aType);
   virtual nsresult Close() MOZ_OVERRIDE;
-  virtual void Suspend(bool aCloseImmediately) MOZ_OVERRIDE {}
-  virtual void Resume() MOZ_OVERRIDE {}
+  virtual void Suspend(bool aCloseImmediately) MOZ_OVERRIDE { UNIMPLEMENTED(); }
+  virtual void Resume() MOZ_OVERRIDE { UNIMPLEMENTED(); }
 
   virtual already_AddRefed<nsIPrincipal> GetCurrentPrincipal() MOZ_OVERRIDE
   {
     return nsCOMPtr<nsIPrincipal>(mPrincipal).forget();
   }
 
   virtual already_AddRefed<MediaResource> CloneData(MediaDecoder* aDecoder) MOZ_OVERRIDE
   {
+    UNIMPLEMENTED();
     return nullptr;
   }
 
-  virtual void SetReadMode(MediaCacheStream::ReadMode aMode) MOZ_OVERRIDE {}
-  virtual void SetPlaybackRate(uint32_t aBytesPerSecond) MOZ_OVERRIDE {}
+  virtual void SetReadMode(MediaCacheStream::ReadMode aMode) MOZ_OVERRIDE { UNIMPLEMENTED(); }
+  virtual void SetPlaybackRate(uint32_t aBytesPerSecond) MOZ_OVERRIDE { UNIMPLEMENTED(); }
   virtual nsresult Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes) MOZ_OVERRIDE;
   virtual nsresult ReadAt(int64_t aOffset, char* aBuffer, uint32_t aCount, uint32_t* aBytes) MOZ_OVERRIDE;
   virtual nsresult Seek(int32_t aWhence, int64_t aOffset) MOZ_OVERRIDE;
-  virtual void StartSeekingForMetadata() MOZ_OVERRIDE { }
-  virtual void EndSeekingForMetadata() MOZ_OVERRIDE {}
+  virtual void StartSeekingForMetadata() MOZ_OVERRIDE { UNIMPLEMENTED(); }
+  virtual void EndSeekingForMetadata() MOZ_OVERRIDE { UNIMPLEMENTED(); }
   virtual int64_t Tell() MOZ_OVERRIDE { return mOffset; }
-  virtual void Pin() MOZ_OVERRIDE {}
-  virtual void Unpin() MOZ_OVERRIDE {}
-  virtual double GetDownloadRate(bool* aIsReliable) MOZ_OVERRIDE { *aIsReliable = false; return 0; }
+  virtual void Pin() MOZ_OVERRIDE { UNIMPLEMENTED(); }
+  virtual void Unpin() MOZ_OVERRIDE { UNIMPLEMENTED(); }
+  virtual double GetDownloadRate(bool* aIsReliable) MOZ_OVERRIDE { UNIMPLEMENTED(); *aIsReliable = false; return 0; }
   virtual int64_t GetLength() MOZ_OVERRIDE { return mInputBuffer.GetLength(); }
   virtual int64_t GetNextCachedData(int64_t aOffset) MOZ_OVERRIDE { return GetLength() == aOffset ? -1 : aOffset; }
   virtual int64_t GetCachedDataEnd(int64_t aOffset) MOZ_OVERRIDE { return GetLength(); }
-  virtual bool IsDataCachedToEndOfResource(int64_t aOffset) MOZ_OVERRIDE { return false; }
-  virtual bool IsSuspendedByCache() MOZ_OVERRIDE { return false; }
-  virtual bool IsSuspended() MOZ_OVERRIDE { return false; }
+  virtual bool IsDataCachedToEndOfResource(int64_t aOffset) MOZ_OVERRIDE { UNIMPLEMENTED(); return false; }
+  virtual bool IsSuspendedByCache() MOZ_OVERRIDE { UNIMPLEMENTED(); return false; }
+  virtual bool IsSuspended() MOZ_OVERRIDE { UNIMPLEMENTED(); return false; }
   virtual nsresult ReadFromCache(char* aBuffer, int64_t aOffset, uint32_t aCount) MOZ_OVERRIDE;
-  virtual bool IsTransportSeekable() MOZ_OVERRIDE { return true; }
-  virtual nsresult Open(nsIStreamListener** aStreamListener) MOZ_OVERRIDE { return NS_ERROR_FAILURE; }
+  virtual bool IsTransportSeekable() MOZ_OVERRIDE { UNIMPLEMENTED(); return true; }
+  virtual nsresult Open(nsIStreamListener** aStreamListener) MOZ_OVERRIDE { UNIMPLEMENTED(); return NS_ERROR_FAILURE; }
 
   virtual nsresult GetCachedRanges(nsTArray<MediaByteRange>& aRanges) MOZ_OVERRIDE
   {
     if (mInputBuffer.GetLength()) {
       aRanges.AppendElement(MediaByteRange(mInputBuffer.GetOffset(),
                                            mInputBuffer.GetLength()));
     }
     return NS_OK;
@@ -129,9 +142,12 @@ private:
   ResourceQueue mInputBuffer;
 
   uint64_t mOffset;
   bool mClosed;
   bool mEnded;
 };
 
 } // namespace mozilla
+
+#undef UNIMPLEMENTED
+
 #endif /* MOZILLA_SOURCEBUFFERRESOURCE_H_ */
--- a/content/media/mediasource/moz.build
+++ b/content/media/mediasource/moz.build
@@ -17,16 +17,16 @@ EXPORTS.mozilla.dom += [
 ]
 
 UNIFIED_SOURCES += [
     'MediaSource.cpp',
     'MediaSourceDecoder.cpp',
     'MediaSourceReader.cpp',
     'MediaSourceUtils.cpp',
     'SourceBuffer.cpp',
+    'SourceBufferDecoder.cpp',
     'SourceBufferList.cpp',
     'SourceBufferResource.cpp',
-    'SubBufferDecoder.cpp',
 ]
 
 FAIL_ON_WARNINGS = True
 
 FINAL_LIBRARY = 'xul'
--- a/content/media/moz.build
+++ b/content/media/moz.build
@@ -64,17 +64,16 @@ MOCHITEST_CHROME_MANIFESTS += ['test/chr
 EXPORTS += [
     'AbstractMediaDecoder.h',
     'AudioChannelFormat.h',
     'AudioCompactor.h',
     'AudioMixer.h',
     'AudioSampleFormat.h',
     'AudioSegment.h',
     'AudioStream.h',
-    'BufferDecoder.h',
     'BufferMediaResource.h',
     'DecoderTraits.h',
     'DOMMediaStream.h',
     'EncodedBufferCache.h',
     'FileBlockCache.h',
     'Latency.h',
     'MediaCache.h',
     'MediaData.h',
@@ -128,17 +127,16 @@ UNIFIED_SOURCES += [
     'AudioChannelFormat.cpp',
     'AudioCompactor.cpp',
     'AudioSegment.cpp',
     'AudioSink.cpp',
     'AudioStream.cpp',
     'AudioStreamTrack.cpp',
     'AudioTrack.cpp',
     'AudioTrackList.cpp',
-    'BufferDecoder.cpp',
     'DOMMediaStream.cpp',
     'EncodedBufferCache.cpp',
     'FileBlockCache.cpp',
     'MediaCache.cpp',
     'MediaData.cpp',
     'MediaDecoder.cpp',
     'MediaDecoderReader.cpp',
     'MediaDecoderStateMachine.cpp',
--- a/content/media/ogg/OggReader.cpp
+++ b/content/media/ogg/OggReader.cpp
@@ -911,17 +911,17 @@ GetChecksum(ogg_page* page)
 int64_t OggReader::RangeStartTime(int64_t aOffset)
 {
   NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
   MediaResource* resource = mDecoder->GetResource();
   NS_ENSURE_TRUE(resource != nullptr, 0);
   nsresult res = resource->Seek(nsISeekableStream::NS_SEEK_SET, aOffset);
   NS_ENSURE_SUCCESS(res, 0);
   int64_t startTime = 0;
-  MediaDecoderReader::FindStartTime(startTime);
+  FindStartTime(startTime);
   return startTime;
 }
 
 struct nsAutoOggSyncState {
   nsAutoOggSyncState() {
     ogg_sync_init(&mState);
   }
   ~nsAutoOggSyncState() {
@@ -1855,16 +1855,69 @@ nsresult OggReader::GetBuffered(dom::Tim
       }
     }
   }
 
   return NS_OK;
 #endif
 }
 
+VideoData* OggReader::FindStartTime(int64_t& aOutStartTime)
+{
+  NS_ASSERTION(mDecoder->OnStateMachineThread() || mDecoder->OnDecodeThread(),
+               "Should be on state machine or decode thread.");
+
+  // Extract the start times of the bitstreams in order to calculate
+  // the duration.
+  int64_t videoStartTime = INT64_MAX;
+  int64_t audioStartTime = INT64_MAX;
+  VideoData* videoData = nullptr;
+
+  if (HasVideo()) {
+    videoData = DecodeToFirstVideoData();
+    if (videoData) {
+      videoStartTime = videoData->mTime;
+      LOG(PR_LOG_DEBUG, ("OggReader::FindStartTime() video=%lld", videoStartTime));
+    }
+  }
+  if (HasAudio()) {
+    AudioData* audioData = DecodeToFirstAudioData();
+    if (audioData) {
+      audioStartTime = audioData->mTime;
+      LOG(PR_LOG_DEBUG, ("OggReader::FindStartTime() audio=%lld", audioStartTime));
+    }
+  }
+
+  int64_t startTime = std::min(videoStartTime, audioStartTime);
+  if (startTime != INT64_MAX) {
+    aOutStartTime = startTime;
+  }
+
+  return videoData;
+}
+
+AudioData* OggReader::DecodeToFirstAudioData()
+{
+  bool eof = false;
+  while (!eof && AudioQueue().GetSize() == 0) {
+    {
+      ReentrantMonitorAutoEnter decoderMon(mDecoder->GetReentrantMonitor());
+      if (mDecoder->IsShutdown()) {
+        return nullptr;
+      }
+    }
+    eof = !DecodeAudioData();
+  }
+  if (eof) {
+    AudioQueue().Finish();
+  }
+  AudioData* d = nullptr;
+  return (d = AudioQueue().PeekFront()) ? d : nullptr;
+}
+
 OggCodecStore::OggCodecStore()
 : mMonitor("CodecStore")
 {
 }
 
 void OggCodecStore::Add(uint32_t serial, OggCodecState* codecState)
 {
   MonitorAutoLock mon(mMonitor);
--- a/content/media/ogg/OggReader.h
+++ b/content/media/ogg/OggReader.h
@@ -40,17 +40,17 @@ class OggCodecStore
   private:
     // Maps Ogg serialnos to OggStreams.
     nsClassHashtable<nsUint32HashKey, OggCodecState> mCodecStates;
 
     // Protects the |mCodecStates| and the |mKnownStreams| members.
     Monitor mMonitor;
 };
 
-class OggReader : public MediaDecoderReader
+class OggReader MOZ_FINAL : public MediaDecoderReader
 {
 public:
   OggReader(AbstractMediaDecoder* aDecoder);
 
 protected:
   ~OggReader();
 
 public:
@@ -79,16 +79,23 @@ public:
   virtual nsresult ReadMetadata(MediaInfo* aInfo,
                                 MetadataTags** aTags);
   virtual nsresult Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime, int64_t aCurrentTime);
   virtual nsresult GetBuffered(dom::TimeRanges* aBuffered, int64_t aStartTime);
 
   virtual bool IsMediaSeekable() MOZ_OVERRIDE;
 
 private:
+  // TODO: DEPRECATED. This uses synchronous decoding.
+  // Stores the presentation time of the first frame we'd be able to play if
+  // we started playback at the current position. Returns the first video
+  // frame, if we have video.
+  VideoData* FindStartTime(int64_t& aOutStartTime);
+  AudioData* DecodeToFirstAudioData();
+
   // This monitor should be taken when reading or writing to mIsChained.
   ReentrantMonitor mMonitor;
 
   // Specialized Reset() method to signal if the seek is
   // to the start of the stream.
   nsresult ResetDecode(bool start);
 
   bool HasSkeleton() {
rename from content/media/BufferDecoder.cpp
rename to content/media/webaudio/BufferDecoder.cpp
rename from content/media/BufferDecoder.h
rename to content/media/webaudio/BufferDecoder.h
--- a/content/media/BufferDecoder.h
+++ b/content/media/webaudio/BufferDecoder.h
@@ -24,65 +24,65 @@ public:
   // of the caller to manage the memory of the MediaResource object.
   explicit BufferDecoder(MediaResource* aResource);
 
   NS_DECL_THREADSAFE_ISUPPORTS
 
   // This has to be called before decoding begins
   void BeginDecoding(nsIThread* aDecodeThread);
 
-  virtual ReentrantMonitor& GetReentrantMonitor() MOZ_OVERRIDE;
+  virtual ReentrantMonitor& GetReentrantMonitor() MOZ_FINAL MOZ_OVERRIDE;
 
-  virtual bool IsShutdown() const MOZ_OVERRIDE;
+  virtual bool IsShutdown() const MOZ_FINAL MOZ_OVERRIDE;
 
-  virtual bool OnStateMachineThread() const MOZ_OVERRIDE;
+  virtual bool OnStateMachineThread() const MOZ_FINAL MOZ_OVERRIDE;
 
-  virtual bool OnDecodeThread() const MOZ_OVERRIDE;
+  virtual bool OnDecodeThread() const MOZ_FINAL MOZ_OVERRIDE;
 
-  virtual MediaResource* GetResource() const MOZ_OVERRIDE;
+  virtual MediaResource* GetResource() const MOZ_FINAL MOZ_OVERRIDE;
 
-  virtual void NotifyBytesConsumed(int64_t aBytes, int64_t aOffset) MOZ_OVERRIDE;
+  virtual void NotifyBytesConsumed(int64_t aBytes, int64_t aOffset) MOZ_FINAL MOZ_OVERRIDE;
 
-  virtual void NotifyDecodedFrames(uint32_t aParsed, uint32_t aDecoded) MOZ_OVERRIDE;
+  virtual void NotifyDecodedFrames(uint32_t aParsed, uint32_t aDecoded) MOZ_FINAL MOZ_OVERRIDE;
 
-  virtual int64_t GetEndMediaTime() const MOZ_OVERRIDE;
+  virtual int64_t GetEndMediaTime() const MOZ_FINAL MOZ_OVERRIDE;
 
-  virtual int64_t GetMediaDuration() MOZ_OVERRIDE;
+  virtual int64_t GetMediaDuration() MOZ_FINAL MOZ_OVERRIDE;
 
-  virtual void SetMediaDuration(int64_t aDuration) MOZ_OVERRIDE;
+  virtual void SetMediaDuration(int64_t aDuration) MOZ_FINAL MOZ_OVERRIDE;
 
-  virtual void UpdateEstimatedMediaDuration(int64_t aDuration) MOZ_OVERRIDE;
+  virtual void UpdateEstimatedMediaDuration(int64_t aDuration) MOZ_FINAL MOZ_OVERRIDE;
 
-  virtual void SetMediaSeekable(bool aMediaSeekable) MOZ_OVERRIDE;
+  virtual void SetMediaSeekable(bool aMediaSeekable) MOZ_FINAL MOZ_OVERRIDE;
 
-  virtual VideoFrameContainer* GetVideoFrameContainer() MOZ_OVERRIDE;
-  virtual layers::ImageContainer* GetImageContainer() MOZ_OVERRIDE;
+  virtual VideoFrameContainer* GetVideoFrameContainer() MOZ_FINAL MOZ_OVERRIDE;
+  virtual layers::ImageContainer* GetImageContainer() MOZ_FINAL MOZ_OVERRIDE;
 
-  virtual bool IsTransportSeekable() MOZ_OVERRIDE;
+  virtual bool IsTransportSeekable() MOZ_FINAL MOZ_OVERRIDE;
 
-  virtual bool IsMediaSeekable() MOZ_OVERRIDE;
+  virtual bool IsMediaSeekable() MOZ_FINAL MOZ_OVERRIDE;
 
-  virtual void MetadataLoaded(MediaInfo* aInfo, MetadataTags* aTags) MOZ_OVERRIDE;
-  virtual void QueueMetadata(int64_t aTime, MediaInfo* aInfo, MetadataTags* aTags) MOZ_OVERRIDE;
+  virtual void MetadataLoaded(MediaInfo* aInfo, MetadataTags* aTags) MOZ_FINAL MOZ_OVERRIDE;
+  virtual void QueueMetadata(int64_t aTime, MediaInfo* aInfo, MetadataTags* aTags) MOZ_FINAL MOZ_OVERRIDE;
 
-  virtual void RemoveMediaTracks() MOZ_OVERRIDE;
+  virtual void RemoveMediaTracks() MOZ_FINAL MOZ_OVERRIDE;
 
-  virtual void SetMediaEndTime(int64_t aTime) MOZ_OVERRIDE;
+  virtual void SetMediaEndTime(int64_t aTime) MOZ_FINAL MOZ_OVERRIDE;
 
-  virtual void UpdatePlaybackPosition(int64_t aTime) MOZ_OVERRIDE;
+  virtual void UpdatePlaybackPosition(int64_t aTime) MOZ_FINAL MOZ_OVERRIDE;
 
-  virtual void OnReadMetadataCompleted() MOZ_OVERRIDE;
+  virtual void OnReadMetadataCompleted() MOZ_FINAL MOZ_OVERRIDE;
 
-  virtual MediaDecoderOwner* GetOwner() MOZ_OVERRIDE;
+  virtual MediaDecoderOwner* GetOwner() MOZ_FINAL MOZ_OVERRIDE;
 
-  virtual void NotifyWaitingForResourcesStatusChanged() MOZ_OVERRIDE;
+  virtual void NotifyWaitingForResourcesStatusChanged() MOZ_FINAL MOZ_OVERRIDE;
 
-  virtual void NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset) MOZ_OVERRIDE;
+  virtual void NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset) MOZ_FINAL MOZ_OVERRIDE;
 
-protected:
+private:
   virtual ~BufferDecoder();
 
   // This monitor object is not really used to synchronize access to anything.
   // It's just there in order for us to be able to override
   // GetReentrantMonitor correctly.
   ReentrantMonitor mReentrantMonitor;
   nsCOMPtr<nsIThread> mDecodeThread;
   nsRefPtr<MediaResource> mResource;
--- a/content/media/webaudio/moz.build
+++ b/content/media/webaudio/moz.build
@@ -70,16 +70,17 @@ UNIFIED_SOURCES += [
     'AudioListener.cpp',
     'AudioNode.cpp',
     'AudioNodeEngine.cpp',
     'AudioNodeExternalInputStream.cpp',
     'AudioNodeStream.cpp',
     'AudioParam.cpp',
     'AudioProcessingEvent.cpp',
     'BiquadFilterNode.cpp',
+    'BufferDecoder.cpp',
     'ChannelMergerNode.cpp',
     'ChannelSplitterNode.cpp',
     'ConvolverNode.cpp',
     'DelayBuffer.cpp',
     'DelayNode.cpp',
     'DynamicsCompressorNode.cpp',
     'FFTBlock.cpp',
     'GainNode.cpp',
--- a/content/media/webaudio/test/mochitest.ini
+++ b/content/media/webaudio/test/mochitest.ini
@@ -33,17 +33,17 @@ support-files =
 [test_audioBufferSourceNodeLazyLoopParam.html]
 [test_audioBufferSourceNodeLoop.html]
 [test_audioBufferSourceNodeLoopStartEnd.html]
 [test_audioBufferSourceNodeLoopStartEndSame.html]
 [test_audioBufferSourceNodeNeutered.html]
 [test_audioBufferSourceNodeNoStart.html]
 [test_audioBufferSourceNodeNullBuffer.html]
 [test_audioBufferSourceNodeOffset.html]
-skip-if = (toolkit == 'gonk' && !debug) || (toolkit == 'android') #bug 906752
+skip-if = (toolkit == 'gonk') || (toolkit == 'android') || debug #bug 906752
 [test_audioBufferSourceNodePassThrough.html]
 [test_AudioContext.html]
 [test_audioDestinationNode.html]
 [test_AudioListener.html]
 [test_audioParamExponentialRamp.html]
 [test_audioParamGain.html]
 [test_audioParamLinearRamp.html]
 [test_audioParamSetCurveAtTime.html]
--- a/content/svg/content/src/SVGMotionSMILAnimationFunction.h
+++ b/content/svg/content/src/SVGMotionSMILAnimationFunction.h
@@ -26,17 +26,17 @@ class SVGMPathElement;
 }
 
 //----------------------------------------------------------------------
 // SVGMotionSMILAnimationFunction
 //
 // Subclass of nsSMILAnimationFunction to support a few extra features offered
 // by the <animateMotion> element.
 //
-class SVGMotionSMILAnimationFunction : public nsSMILAnimationFunction
+class SVGMotionSMILAnimationFunction MOZ_FINAL : public nsSMILAnimationFunction
 {
   typedef mozilla::gfx::Path Path;
 
 public:
   SVGMotionSMILAnimationFunction();
   virtual bool SetAttr(nsIAtom* aAttribute,
                        const nsAString& aValue,
                        nsAttrValue& aResult,
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -2891,16 +2891,46 @@ nsDocShell::AddWeakScrollObserver(nsIScr
 
 NS_IMETHODIMP
 nsDocShell::RemoveWeakScrollObserver(nsIScrollObserver* aObserver)
 {
     nsWeakPtr obs = do_GetWeakReference(aObserver);
     return mScrollObservers.RemoveElement(obs) ? NS_OK : NS_ERROR_FAILURE;
 }
 
+void
+nsDocShell::NotifyAsyncPanZoomStarted()
+{
+    nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mScrollObservers);
+    while (iter.HasMore()) {
+        nsWeakPtr ref = iter.GetNext();
+        nsCOMPtr<nsIScrollObserver> obs = do_QueryReferent(ref);
+        if (obs) {
+            obs->AsyncPanZoomStarted();
+        } else {
+            mScrollObservers.RemoveElement(ref);
+        }
+    }
+}
+
+void
+nsDocShell::NotifyAsyncPanZoomStopped()
+{
+    nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mScrollObservers);
+    while (iter.HasMore()) {
+        nsWeakPtr ref = iter.GetNext();
+        nsCOMPtr<nsIScrollObserver> obs = do_QueryReferent(ref);
+        if (obs) {
+            obs->AsyncPanZoomStopped();
+        } else {
+            mScrollObservers.RemoveElement(ref);
+        }
+    }
+}
+
 NS_IMETHODIMP
 nsDocShell::NotifyScrollObservers()
 {
     nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mScrollObservers);
     while (iter.HasMore()) {
         nsWeakPtr ref = iter.GetNext();
         nsCOMPtr<nsIScrollObserver> obs = do_QueryReferent(ref);
         if (obs) {
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -118,34 +118,34 @@ typedef enum {
     eCharsetReloadRequested,
     eCharsetReloadStopOrigional
 } eCharsetReloadState;
 
 //*****************************************************************************
 //***    nsDocShell
 //*****************************************************************************
 
-class nsDocShell : public nsDocLoader,
-                   public nsIDocShell,
-                   public nsIWebNavigation,
-                   public nsIBaseWindow, 
-                   public nsIScrollable, 
-                   public nsITextScroll, 
-                   public nsIDocCharset, 
-                   public nsIContentViewerContainer,
-                   public nsIRefreshURI,
-                   public nsIWebProgressListener,
-                   public nsIWebPageDescriptor,
-                   public nsIAuthPromptProvider,
-                   public nsILoadContext,
-                   public nsIWebShellServices,
-                   public nsILinkHandler,
-                   public nsIClipboardCommands,
-                   public nsIDOMStorageManager,
-                   public mozilla::SupportsWeakPtr<nsDocShell>
+class nsDocShell MOZ_FINAL : public nsDocLoader,
+                             public nsIDocShell,
+                             public nsIWebNavigation,
+                             public nsIBaseWindow,
+                             public nsIScrollable,
+                             public nsITextScroll,
+                             public nsIDocCharset,
+                             public nsIContentViewerContainer,
+                             public nsIRefreshURI,
+                             public nsIWebProgressListener,
+                             public nsIWebPageDescriptor,
+                             public nsIAuthPromptProvider,
+                             public nsILoadContext,
+                             public nsIWebShellServices,
+                             public nsILinkHandler,
+                             public nsIClipboardCommands,
+                             public nsIDOMStorageManager,
+                             public mozilla::SupportsWeakPtr<nsDocShell>
 {
     friend class nsDSURIContentListener;
 
 public:
     MOZ_DECLARE_REFCOUNTED_TYPENAME(nsDocShell)
     // Object Management
     nsDocShell();
 
@@ -238,16 +238,23 @@ public:
     // updating security info.
     void FireDummyOnLocationChange()
     {
         FireOnLocationChange(this, nullptr, mCurrentURI,
                              LOCATION_CHANGE_SAME_DOCUMENT);
     }
 
     nsresult HistoryTransactionRemoved(int32_t aIndex);
+
+    // Notify Scroll observers when an async panning/zooming transform
+    // has started being applied
+    void NotifyAsyncPanZoomStarted();
+    // Notify Scroll observers when an async panning/zooming transform
+    // is no longer applied
+    void NotifyAsyncPanZoomStopped();
 protected:
     // Object Management
     virtual ~nsDocShell();
     virtual void DestroyChildren();
 
     // Content Viewer Management
     NS_IMETHOD EnsureContentViewer();
     // aPrincipal can be passed in if the caller wants.  If null is
--- a/docshell/base/nsIScrollObserver.h
+++ b/docshell/base/nsIScrollObserver.h
@@ -4,25 +4,35 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsIScrollObserver_h___
 #define nsIScrollObserver_h___
 
 #include "nsISupports.h"
 
 #define NS_ISCROLLOBSERVER_IID \
-  { 0x7c1a8b63, 0xe322, 0x4827, \
-    { 0xa4, 0xb1, 0x3b, 0x6e, 0x59, 0x03, 0x47, 0x7e } }
+  { 0x03465b77, 0x9ce2, 0x4d19, \
+    { 0xb2, 0xf6, 0x82, 0xae, 0xee, 0x85, 0xc3, 0xbf } }
 
 class nsIScrollObserver : public nsISupports
 {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISCROLLOBSERVER_IID)
 
   /**
    * Called when the scroll position of some element has changed.
    */
   virtual void ScrollPositionChanged() = 0;
+
+  /**
+   * Called when an async panning/zooming transform has started being applied.
+   */
+  virtual void AsyncPanZoomStarted(){};
+
+  /**
+   * Called when an async panning/zooming transform is no longer applied.
+   */
+  virtual void AsyncPanZoomStopped(){};
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIScrollObserver, NS_ISCROLLOBSERVER_IID)
 
 #endif /* nsIScrollObserver_h___ */
--- a/docshell/shistory/src/nsSHistory.h
+++ b/docshell/shistory/src/nsSHistory.h
@@ -22,20 +22,20 @@
 #include "prclist.h"
 
 class nsIDocShell;
 class nsSHEnumerator;
 class nsSHistoryObserver;
 class nsISHEntry;
 class nsISHTransaction;
 
-class nsSHistory: public PRCList,
-                  public nsISHistory,
-                  public nsISHistoryInternal,
-                  public nsIWebNavigation
+class nsSHistory MOZ_FINAL : public PRCList,
+                             public nsISHistory,
+                             public nsISHistoryInternal,
+                             public nsIWebNavigation
 {
 public:
   nsSHistory();
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSISHISTORY
   NS_DECL_NSISHISTORYINTERNAL
   NS_DECL_NSIWEBNAVIGATION
--- a/dom/animation/Animation.cpp
+++ b/dom/animation/Animation.cpp
@@ -1,15 +1,16 @@
 /* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/Animation.h"
 #include "mozilla/dom/AnimationBinding.h"
+#include "mozilla/dom/AnimationEffect.h"
 #include "mozilla/FloatingPoint.h"
 
 namespace mozilla {
 
 void
 ComputedTimingFunction::Init(const nsTimingFunction &aFunction)
 {
   mType = aFunction.mType;
@@ -63,16 +64,23 @@ NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(Ani
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(Animation, Release)
 
 JSObject*
 Animation::WrapObject(JSContext* aCx)
 {
   return AnimationBinding::Wrap(aCx, this);
 }
 
+already_AddRefed<AnimationEffect>
+Animation::GetEffect()
+{
+  nsRefPtr<AnimationEffect> effect = new AnimationEffect(this);
+  return effect.forget();
+}
+
 void
 Animation::SetParentTime(Nullable<TimeDuration> aParentTime)
 {
   mParentTime = aParentTime;
 }
 
 ComputedTiming
 Animation::GetComputedTimingAt(const Nullable<TimeDuration>& aLocalTime,
--- a/dom/animation/Animation.h
+++ b/dom/animation/Animation.h
@@ -115,22 +115,27 @@ struct AnimationProperty
   nsCSSProperty mProperty;
   InfallibleTArray<AnimationPropertySegment> mSegments;
 };
 
 struct ElementPropertyTransition;
 
 namespace dom {
 
+class AnimationEffect;
+
 class Animation : public nsWrapperCache
 {
 public:
-  Animation(nsIDocument* aDocument, const AnimationTiming &aTiming)
+  Animation(nsIDocument* aDocument,
+            const AnimationTiming &aTiming,
+            const nsSubstring& aName)
     : mDocument(aDocument)
     , mTiming(aTiming)
+    , mName(aName)
     , mIsFinishedTransition(false)
     , mLastNotification(LAST_NOTIFICATION_NONE)
   {
     SetIsDOMBinding();
   }
 
   NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(Animation)
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(Animation)
@@ -141,25 +146,34 @@ public:
   // FIXME: If we succeed in moving transition-specific code to a type of
   // AnimationEffect (as per the Web Animations API) we should remove these
   // virtual methods.
   virtual ElementPropertyTransition* AsTransition() { return nullptr; }
   virtual const ElementPropertyTransition* AsTransition() const {
     return nullptr;
   }
 
+  // Animation interface
+  // This currently returns a new object each time when used from C++ but is
+  // cached when used from JS.
+  already_AddRefed<AnimationEffect> GetEffect();
+
   void SetParentTime(Nullable<TimeDuration> aParentTime);
 
   const AnimationTiming& Timing() const {
     return mTiming;
   }
   AnimationTiming& Timing() {
     return mTiming;
   }
 
+  const nsString& Name() const {
+    return mName;
+  }
+
   // Return the duration from the start the active interval to the point where
   // the animation begins playback. This is zero unless the animation has
   // a negative delay in which case it is the absolute value of the delay.
   // This is used for setting the elapsedTime member of CSS AnimationEvents.
   TimeDuration InitialAdvance() const {
     return std::max(TimeDuration(), mTiming.mDelay * -1);
   }
 
@@ -238,16 +252,17 @@ protected:
   virtual ~Animation() { }
 
   // We use a document for a parent object since the other likely candidate,
   // the target element, can be empty.
   nsRefPtr<nsIDocument> mDocument;
   Nullable<TimeDuration> mParentTime;
 
   AnimationTiming mTiming;
+  nsString mName;
   // A flag to mark transitions that have finished and are due to
   // be removed on the next throttle-able cycle.
   bool mIsFinishedTransition;
   // One of the LAST_NOTIFICATION_* constants, or an integer for the iteration
   // whose start we last notified on.
   uint64_t mLastNotification;
 
   InfallibleTArray<AnimationProperty> mProperties;
new file mode 100644
--- /dev/null
+++ b/dom/animation/AnimationEffect.cpp
@@ -0,0 +1,24 @@
+/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/dom/AnimationEffect.h"
+#include "mozilla/dom/AnimationEffectBinding.h"
+
+namespace mozilla {
+namespace dom {
+
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(AnimationEffect, mAnimation)
+
+NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(AnimationEffect, AddRef)
+NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(AnimationEffect, Release)
+
+JSObject*
+AnimationEffect::WrapObject(JSContext* aCx)
+{
+  return AnimationEffectBinding::Wrap(aCx, this);
+}
+
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/animation/AnimationEffect.h
@@ -0,0 +1,47 @@
+/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_AnimationEffect_h
+#define mozilla_dom_AnimationEffect_h
+
+#include "nsCycleCollectionParticipant.h"
+#include "nsWrapperCache.h"
+#include "mozilla/dom/Animation.h"
+
+struct JSContext;
+
+namespace mozilla {
+namespace dom {
+
+class AnimationEffect MOZ_FINAL : public nsWrapperCache
+{
+public:
+  AnimationEffect(Animation* aAnimation)
+    : mAnimation(aAnimation)
+  {
+    SetIsDOMBinding();
+  }
+
+  NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(AnimationEffect)
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(AnimationEffect)
+
+  Animation* GetParentObject() const { return mAnimation; }
+  virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
+
+  // AnimationEffect interface
+  void GetName(nsString& aRetVal) const {
+    aRetVal = mAnimation->Name();
+  }
+
+private:
+  ~AnimationEffect() { }
+
+  nsRefPtr<Animation> mAnimation;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_AnimationEffect_h
--- a/dom/animation/AnimationPlayer.h
+++ b/dom/animation/AnimationPlayer.h
@@ -45,20 +45,25 @@ public:
   AnimationTimeline* GetParentObject() const { return mTimeline; }
   virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
 
   // AnimationPlayer methods
   Animation* GetSource() const { return mSource; }
   AnimationTimeline* Timeline() const { return mTimeline; }
   double StartTime() const;
   double CurrentTime() const;
+  bool IsRunningOnCompositor() const { return mIsRunningOnCompositor; }
 
   void SetSource(Animation* aSource);
   void Tick();
 
+  const nsString& Name() const {
+    return mSource ? mSource->Name() : EmptyString();
+  }
+
   bool IsPaused() const {
     return mPlayState == NS_STYLE_ANIMATION_PLAY_STATE_PAUSED;
   }
 
   bool IsRunning() const;
   bool IsCurrent() const;
 
   // Return the duration since the start time of the player, taking into
@@ -77,17 +82,16 @@ public:
 
     Nullable<TimeDuration> result; // Initializes to null
     if (!timelineTime.IsNull() && !mStartTime.IsNull()) {
       result.SetValue((IsPaused() ? mPauseStart : timelineTime) - mStartTime);
     }
     return result;
   }
 
-  nsString mName;
   // The beginning of the delay period.
   TimeStamp mStartTime;
   TimeStamp mPauseStart;
   uint8_t mPlayState;
   bool mIsRunningOnCompositor;
 
   nsRefPtr<AnimationTimeline> mTimeline;
   nsRefPtr<Animation> mSource;
--- a/dom/animation/moz.build
+++ b/dom/animation/moz.build
@@ -1,23 +1,26 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 MOCHITEST_MANIFESTS += ['test/mochitest.ini']
+MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
 
 EXPORTS.mozilla.dom += [
     'Animation.h',
+    'AnimationEffect.h',
     'AnimationPlayer.h',
     'AnimationTimeline.h',
 ]
 
 SOURCES += [
     'Animation.cpp',
+    'AnimationEffect.cpp',
     'AnimationPlayer.cpp',
     'AnimationTimeline.cpp',
 ]
 
 FAIL_ON_WARNINGS = True
 
 FINAL_LIBRARY = 'xul'
new file mode 100644
--- /dev/null
+++ b/dom/animation/test/chrome.ini
@@ -0,0 +1,1 @@
+[chrome/test_running_on_compositor.html]
new file mode 100644
--- /dev/null
+++ b/dom/animation/test/chrome/test_running_on_compositor.html
@@ -0,0 +1,68 @@
+<!doctype html>
+<head>
+<meta charset=utf-8>
+<title>Bug 1045994 - Add a chrome-only property to inspect if an animation is
+       running on the compositor or not</title>
+<script type="application/javascript"
+  src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+<script type="application/javascript"
+  src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
+<link rel="stylesheet" type="text/css"
+  href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
+<style>
+@keyframes anim {
+  to { transform: translate(100px) }
+}
+.target {
+  // Element needs geometry to be eligible for layerization
+  width: 100px;
+  height: 100px;
+  background-color: white;
+}
+</style>
+</head>
+<body>
+<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1045994"
+  target="_blank">Mozilla Bug 1045994</a>
+<div class="target"></div>
+<script>
+'use strict';
+
+/** Test for bug 1045994 - Add a chrome-only property to inspect if an
+    animation is running on the compositor or not **/
+
+SimpleTest.waitForExplicitFinish();
+
+var div = document.querySelector('div.target');
+
+const OMTAPrefKey = 'layers.offmainthreadcomposition.async-animations';
+var omtaEnabled = SpecialPowers.DOMWindowUtils.layerManagerRemote &&
+                  SpecialPowers.getBoolPref(OMTAPrefKey);
+
+// FIXME: When we implement Element.animate, use that here instead of CSS
+// so that we remove any dependency on the CSS mapping.
+div.style.animation = 'anim 100s';
+window.getComputedStyle(div).animationName;
+var player = div.getAnimationPlayers()[0];
+
+// Wait so that animation can be set up.
+// FIXME: When we implement the AnimationPlayer.ready promise we should wait
+// on that here.
+window.requestAnimationFrame(function() {
+  is(player.isRunningOnCompositor, omtaEnabled,
+     'AnimationPlayer reports that it is running on the compositor'
+     + ' during playback');
+
+  div.style.animationPlayState = 'paused';
+  window.getComputedStyle(div).animationPlayState;
+
+  // FIXME: Likewise, we should wait on AnimationPlayer.ready here too.
+  window.requestAnimationFrame(function() {
+    is(player.isRunningOnCompositor, false,
+       'AnimationPlayer reports that it is NOT running on the compositor'
+       + ' when paused');
+    SimpleTest.finish();
+  });
+});
+</script>
+</body>
new file mode 100644
--- /dev/null
+++ b/dom/animation/test/css-integration/test_animation-effect-name.html
@@ -0,0 +1,65 @@
+<!doctype html>
+<meta charset=utf-8>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<style>
+@keyframes xyz {
+  to { left: 100px }
+}
+</style>
+<script>
+'use strict';
+
+function addDiv() {
+  var div = document.createElement('div');
+  document.body.appendChild(div);
+  return div;
+}
+
+test(function() {
+  var div = addDiv();
+  div.style.animation = 'xyz 100s';
+  window.getComputedStyle(div).animationName;
+
+  assert_equals(div.getAnimationPlayers()[0].source.effect.name, 'xyz',
+                'Animation effect name matches keyframes rule name');
+  div.remove();
+}, 'Effect name makes keyframe rule');
+
+test(function() {
+  var div = addDiv();
+  div.style.animation = 'x\\yz 100s';
+  dump(window.getComputedStyle(div).animationName + "\n");
+
+  assert_equals(div.getAnimationPlayers()[0].source.effect.name, 'xyz',
+                'Escaped animation effect name matches keyframes rule name');
+  div.remove();
+}, 'Escaped animation name');
+
+test(function() {
+  var div = addDiv();
+  div.style.animation = 'x\\79 z 100s';
+  window.getComputedStyle(div).animationName;
+
+  assert_equals(div.getAnimationPlayers()[0].source.effect.name, 'xyz',
+                'Hex-escaped animation effect name matches keyframes rule'
+                + ' name');
+  div.remove();
+}, 'Animation name with hex-escape');
+
+test(function() {
+  var div = addDiv();
+
+  // Add a transition
+  div.style.left = '0px';
+  window.getComputedStyle(div).transitionProperty;
+  div.style.transition = 'all 100s';
+  div.style.left = '100px';
+  window.getComputedStyle(div).left;
+
+  assert_equals(div.getAnimationPlayers()[0].source.effect.name, '',
+                'Animation effects for transitions have an empty name');
+  div.remove();
+}, 'Effect name for transitions');
+</script>
--- a/dom/animation/test/mochitest.ini
+++ b/dom/animation/test/mochitest.ini
@@ -1,5 +1,6 @@
 [animation-timeline/test_animation-timeline.html]
 skip-if = buildapp == 'mulet'
 [css-integration/test_element-get-animation-players.html]
 skip-if = buildapp == 'mulet'
 [css-integration/test_animations-dynamic-changes.html]
+[css-integration/test_animation-effect-name.html]
--- a/dom/base/Navigator.h
+++ b/dom/base/Navigator.h
@@ -100,19 +100,19 @@ class TimeManager;
 } // namespace time
 
 namespace system {
 #ifdef MOZ_AUDIO_CHANNEL_MANAGER
 class AudioChannelManager;
 #endif
 } // namespace system
 
-class Navigator : public nsIDOMNavigator
-                , public nsIMozNavigatorNetwork
-                , public nsWrapperCache
+class Navigator MOZ_FINAL : public nsIDOMNavigator
+                          , public nsIMozNavigatorNetwork
+                          , public nsWrapperCache
 {
 public:
   Navigator(nsPIDOMWindow *aInnerWindow);
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(Navigator,
                                                          nsIDOMNavigator)
   NS_DECL_NSIDOMNAVIGATOR
--- a/dom/base/ScriptSettings.cpp
+++ b/dom/base/ScriptSettings.cpp
@@ -403,29 +403,22 @@ danger::AutoCxPusher::AutoCxPusher(JSCon
   mPushedContext = cx;
   mCompartmentDepthOnEntry = cx ? js::GetEnterCompartmentDepth(cx) : 0;
 #endif
 
   // Enter a request and a compartment for the duration that the cx is on the
   // stack if non-null.
   if (cx) {
     mAutoRequest.emplace(cx);
-
-    // DOM JSContexts don't store their default compartment object on the cx.
-    JSObject *compartmentObject = mScx ? mScx->GetWindowProxy()
-                                       : js::DefaultObjectForContextOrNull(cx);
-    if (compartmentObject)
-      mAutoCompartment.emplace(cx, compartmentObject);
   }
 }
 
 danger::AutoCxPusher::~AutoCxPusher()
 {
-  // Leave the compartment and request before popping.
-  mAutoCompartment.reset();
+  // Leave the request before popping.
   mAutoRequest.reset();
 
   // When we push a context, we may save the frame chain and pretend like we
   // haven't entered any compartment. This gets restored on Pop(), but we can
   // run into trouble if a Push/Pop are interleaved with a
   // JSAutoEnterCompartment. Make sure the compartment depth right before we
   // pop is the same as it was right after we pushed.
   MOZ_ASSERT_IF(mPushedContext, mCompartmentDepthOnEntry ==
--- a/dom/base/ScriptSettings.h
+++ b/dom/base/ScriptSettings.h
@@ -41,17 +41,16 @@ public:
   nsIScriptContext* GetScriptContext() { return mScx; }
 
   // Returns true if this AutoCxPusher performed the push that is currently at
   // the top of the cx stack.
   bool IsStackTop() const;
 
 private:
   mozilla::Maybe<JSAutoRequest> mAutoRequest;
-  mozilla::Maybe<JSAutoCompartment> mAutoCompartment;
   nsCOMPtr<nsIScriptContext> mScx;
   uint32_t mStackDepthAfterPush;
 #ifdef DEBUG
   JSContext* mPushedContext;
   unsigned mCompartmentDepthOnEntry;
 #endif
 };
 
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -736,18 +736,17 @@ nsJSContext::nsJSContext(bool aGCOnDestr
 
   ++sContextCount;
 
   mContext = ::JS_NewContext(sRuntime, gStackSize);
   if (mContext) {
     ::JS_SetContextPrivate(mContext, static_cast<nsIScriptContext *>(this));
 
     // Make sure the new context gets the default context options
-    JS::ContextOptionsRef(mContext).setPrivateIsNSISupports(true)
-                                   .setNoDefaultCompartmentObject(true);
+    JS::ContextOptionsRef(mContext).setPrivateIsNSISupports(true);
 
     // Watch for the JS boolean options
     Preferences::RegisterCallback(JSOptionChangedCallback,
                                   js_options_dot_str, this);
   }
   mIsInitialized = false;
   mProcessingScriptTag = false;
   HoldJSObjects(this);
--- a/dom/base/nsJSUtils.cpp
+++ b/dom/base/nsJSUtils.cpp
@@ -98,18 +98,17 @@ nsJSUtils::ReportPendingException(JSCont
       // exception and produce a JSErrorReport.  It will then pass that
       // JSErrorReport to the error reporter on aContext, which might expose
       // information from it to script via onerror handlers.  So it's very
       // important that the duck typing happen in the same compartment as the
       // onerror handler.  In practice, that's the compartment of the window (or
       // otherwise default global) of aContext, so use that here.
       nsIScriptContext* scx = GetScriptContextFromJSContext(aContext);
       JS::Rooted<JSObject*> scope(aContext);
-      scope = scx ? scx->GetWindowProxy()
-                  : js::DefaultObjectForContextOrNull(aContext);
+      scope = scx ? scx->GetWindowProxy() : nullptr;
       if (!scope) {
         // The SafeJSContext has no default object associated with it.
         MOZ_ASSERT(NS_IsMainThread());
         MOZ_ASSERT(aContext == nsContentUtils::GetSafeJSContext());
         scope = xpc::UnprivilegedJunkScope(); // Usage approved by bholley
       }
       JSAutoCompartment ac(aContext, scope);
       JS_ReportPendingException(aContext);
@@ -314,13 +313,10 @@ nsJSUtils::EvaluateString(JSContext* aCx
 //
 
 JSObject* GetDefaultScopeFromJSContext(JSContext *cx)
 {
   // DOM JSContexts don't store their default compartment object on
   // the cx, so in those cases we need to fetch it via the scx
   // instead.
   nsIScriptContext *scx = GetScriptContextFromJSContext(cx);
-  if (scx) {
-    return scx->GetWindowProxy();
-  }
-  return js::DefaultObjectForContextOrNull(cx);
+  return  scx ? scx->GetWindowProxy() : nullptr;
 }
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -1534,25 +1534,28 @@ class CGClassFinalizeHook(CGAbstractClas
         args = [Argument('js::FreeOp*', 'fop'), Argument('JSObject*', 'obj')]
         CGAbstractClassHook.__init__(self, descriptor, FINALIZE_HOOK_NAME,
                                      'void', args)
 
     def generate_code(self):
         return finalizeHook(self.descriptor, self.name, self.args[0].name).define()
 
 
+def JSNativeArguments():
+    return [Argument('JSContext*', 'cx'),
+            Argument('unsigned', 'argc'),
+            Argument('JS::Value*', 'vp')]
+
 class CGClassConstructor(CGAbstractStaticMethod):
     """
     JS-visible constructor for our objects
     """
     def __init__(self, descriptor, ctor, name=CONSTRUCT_HOOK_NAME):
-        args = [Argument('JSContext*', 'cx'),
-                Argument('unsigned', 'argc'),
-                Argument('JS::Value*', 'vp')]
-        CGAbstractStaticMethod.__init__(self, descriptor, name, 'bool', args)
+        CGAbstractStaticMethod.__init__(self, descriptor, name, 'bool',
+                                        JSNativeArguments())
         self._ctor = ctor
 
     def define(self):
         if not self._ctor:
             return ""
         return CGAbstractStaticMethod.define(self)
 
     def definition_body(self):
@@ -2032,16 +2035,31 @@ def methodLength(method):
     return min(overloadLength(arguments) for retType, arguments in signatures)
 
 
 def isMaybeExposedIn(member, descriptor):
     # All we can say for sure is that if this is a worker descriptor
     # and member is only exposed in windows, then it's not exposed.
     return not descriptor.workers or member.exposureSet != set(["Window"])
 
+def clearableCachedAttrs(descriptor):
+    return (m for m in descriptor.interface.members if
+            m.isAttr() and
+            # Constants should never need clearing!
+            not m.getExtendedAttribute("Constant") and
+            not m.getExtendedAttribute("SameObject") and
+            m.slotIndex is not None)
+
+def MakeClearCachedValueNativeName(member):
+    return "ClearCached%sValue" % MakeNativeName(member.identifier.name)
+
+def MakeJSImplClearCachedValueNativeName(member):
+    return "_" + MakeClearCachedValueNativeName(member)
+
+
 class MethodDefiner(PropertyDefiner):
     """
     A class for defining methods on a prototype object.
     """
     def __init__(self, descriptor, name, static, unforgeable=False):
         assert not (static and unforgeable)
         PropertyDefiner.__init__(self, descriptor, name)
 
@@ -2160,26 +2178,39 @@ class MethodDefiner(PropertyDefiner):
                     "name": 'valueOf',
                     "nativeName": "UnforgeableValueOf",
                     "methodInfo": False,
                     "length": 0,
                     "flags": "JSPROP_ENUMERATE", # readonly/permanent added
                                                  # automatically.
                     "condition": MemberCondition(None, None)
                 })
-        elif (descriptor.interface.isJSImplemented() and
-              descriptor.interface.hasInterfaceObject()):
-            self.chrome.append({
-                "name": '_create',
-                "nativeName": ("%s::_Create" % descriptor.name),
-                "methodInfo": False,
-                "length": 2,
-                "flags": "0",
-                "condition": MemberCondition(None, None)
-            })
+
+        if (descriptor.interface.isJSImplemented() and
+            descriptor.interface.hasInterfaceObject()):
+            if static:
+                self.chrome.append({
+                    "name": '_create',
+                    "nativeName": ("%s::_Create" % descriptor.name),
+                    "methodInfo": False,
+                    "length": 2,
+                    "flags": "0",
+                    "condition": MemberCondition(None, None)
+                })
+            else:
+                for m in clearableCachedAttrs(descriptor):
+                    attrName = MakeNativeName(m.identifier.name)
+                    self.chrome.append({
+                        "name": "_clearCached%sValue" % attrName,
+                        "nativeName": MakeJSImplClearCachedValueNativeName(m),
+                        "methodInfo": False,
+                        "length": "0",
+                        "flags": "0",
+                        "condition": MemberCondition(None, None)
+                    })
 
         self.unforgeable = unforgeable
 
         if static:
             if not descriptor.interface.hasInterfaceObject():
                 # static methods go on the interface object
                 assert not self.hasChromeOnly() and not self.hasNonChromeOnly()
         else:
@@ -3242,17 +3273,17 @@ class CGClearCachedValueMethod(CGAbstrac
         # If we're StoreInSlot, we'll need to call the getter
         if member.getExtendedAttribute("StoreInSlot"):
             args = [Argument('JSContext*', 'aCx')]
             returnType = 'bool'
         else:
             args = []
             returnType = 'void'
         args.append(Argument(descriptor.nativeType + '*', 'aObject'))
-        name = ("ClearCached%sValue" % MakeNativeName(member.identifier.name))
+        name = MakeClearCachedValueNativeName(member)
         CGAbstractMethod.__init__(self, descriptor, name, returnType, args)
 
     def definition_body(self):
         slotIndex = memberReservedSlot(self.member)
         if self.member.getExtendedAttribute("StoreInSlot"):
             # We have to root things and save the old value in case
             # regetting fails, so we can restore it.
             declObj = "JS::Rooted<JSObject*> obj(aCx);\n"
@@ -7078,18 +7109,18 @@ class CGSetterCall(CGPerSignatureCall):
 
     def wrap_return_value(self):
         attr = self.idlNode
         if self.descriptor.wrapperCache and attr.slotIndex is not None:
             if attr.getExtendedAttribute("StoreInSlot"):
                 args = "cx, self"
             else:
                 args = "self"
-            clearSlot = ("ClearCached%sValue(%s);\n" %
-                         (MakeNativeName(self.idlNode.identifier.name), args))
+            clearSlot = ("%s(%s);\n" %
+                         (MakeClearCachedValueNativeName(self.idlNode), args))
         else:
             clearSlot = ""
 
         # We have no return value
         return ("\n"
                 "%s"
                 "return true;\n" % clearSlot)
 
@@ -7172,20 +7203,18 @@ class CGAbstractStaticBindingMethod(CGAb
     """
     Common class to generate the JSNatives for all our static methods, getters
     and setters.  This will generate the function declaration and unwrap the
     global object.  Subclasses are expected to override the generate_code
     function to do the rest of the work.  This function should return a
     CGThing which is already properly indented.
     """
     def __init__(self, descriptor, name):
-        args = [Argument('JSContext*', 'cx'),
-                Argument('unsigned', 'argc'),
-                Argument('JS::Value*', 'vp')]
-        CGAbstractStaticMethod.__init__(self, descriptor, name, "bool", args)
+        CGAbstractStaticMethod.__init__(self, descriptor, name, "bool",
+                                        JSNativeArguments())
 
     def definition_body(self):
         # Make sure that "obj" is in the same compartment as "cx", since we'll
         # later use it to wrap return values.
         unwrap = dedent("""
             JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
             JS::Rooted<JSObject*> obj(cx, &args.callee());
 
@@ -7203,25 +7232,22 @@ def MakeNativeName(name):
 class CGGenericMethod(CGAbstractBindingMethod):
     """
     A class for generating the C++ code for an IDL method.
 
     If allowCrossOriginThis is true, then this-unwrapping will first do an
     UncheckedUnwrap and after that operate on the result.
     """
     def __init__(self, descriptor, allowCrossOriginThis=False):
-        args = [Argument('JSContext*', 'cx'),
-                Argument('unsigned', 'argc'),
-                Argument('JS::Value*', 'vp')]
         unwrapFailureCode = (
             'return ThrowInvalidThis(cx, args, GetInvalidThisErrorForMethod(%%(securityError)s), "%s");\n' %
             descriptor.interface.identifier.name)
         name = "genericCrossOriginMethod" if allowCrossOriginThis else "genericMethod"
         CGAbstractBindingMethod.__init__(self, descriptor, name,
-                                         args,
+                                         JSNativeArguments(),
                                          unwrapFailureCode=unwrapFailureCode,
                                          allowCrossOriginThis=allowCrossOriginThis)
 
     def generate_code(self):
         return CGGeneric(dedent("""
             const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(args.calleev());
             MOZ_ASSERT(info->type() == JSJitInfo::Method);
             JSJitMethodOp method = info->method;
@@ -7236,34 +7262,31 @@ class CGGenericMethod(CGAbstractBindingM
 
 class CGGenericPromiseReturningMethod(CGAbstractBindingMethod):
     """
     A class for generating the C++ code for an IDL method that returns a Promise.
 
     Does not handle cross-origin this.
     """
     def __init__(self, descriptor):
-        args = [Argument('JSContext*', 'cx'),
-                Argument('unsigned', 'argc'),
-                Argument('JS::Value*', 'vp')]
         unwrapFailureCode = dedent("""
             ThrowInvalidThis(cx, args, GetInvalidThisErrorForMethod(%%(securityError)s), "%s");\n
             return ConvertExceptionToPromise(cx, xpc::XrayAwareCalleeGlobal(callee),
                                              args.rval());\n""" %
             descriptor.interface.identifier.name)
 
         name = "genericPromiseReturningMethod"
         customCallArgs = dedent("""
             JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
             // Make sure to save the callee before someone maybe messes with rval().
             JS::Rooted<JSObject*> callee(cx, &args.callee());
         """)
 
         CGAbstractBindingMethod.__init__(self, descriptor, name,
-                                         args,
+                                         JSNativeArguments(),
                                          callArgs=customCallArgs,
                                          unwrapFailureCode=unwrapFailureCode)
 
     def generate_code(self):
         return CGGeneric(dedent("""
             const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(args.calleev());
             MOZ_ASSERT(info->type() == JSJitInfo::Method);
             JSJitMethodOp method = info->method;
@@ -7377,23 +7400,20 @@ class CGJsonifierMethod(CGSpecializedMet
 
 
 class CGLegacyCallHook(CGAbstractBindingMethod):
     """
     Call hook for our object
     """
     def __init__(self, descriptor):
         self._legacycaller = descriptor.operations["LegacyCaller"]
-        args = [Argument('JSContext*', 'cx'),
-                Argument('unsigned', 'argc'),
-                Argument('JS::Value*', 'vp')]
         # Our "self" is actually the callee in this case, not the thisval.
         CGAbstractBindingMethod.__init__(
             self, descriptor, LEGACYCALLER_HOOK_NAME,
-            args, getThisObj="&args.callee()")
+            JSNativeArguments(), getThisObj="&args.callee()")
 
     def define(self):
         if not self._legacycaller:
             return ""
         return CGAbstractBindingMethod.define(self)
 
     def generate_code(self):
         name = self._legacycaller.identifier.name
@@ -7544,19 +7564,16 @@ class CGStaticMethod(CGAbstractStaticBin
         return CGMethodCall(nativeName, True, self.descriptor, self.method)
 
 
 class CGGenericGetter(CGAbstractBindingMethod):
     """
     A class for generating the C++ code for an IDL attribute getter.
     """
     def __init__(self, descriptor, lenientThis=False, allowCrossOriginThis=False):
-        args = [Argument('JSContext*', 'cx'),
-                Argument('unsigned', 'argc'),
-                Argument('JS::Value*', 'vp')]
         if lenientThis:
             name = "genericLenientGetter"
             unwrapFailureCode = dedent("""
                 MOZ_ASSERT(!JS_IsExceptionPending(cx));
                 if (!ReportLenientThisUnwrappingFailure(cx, &args.callee())) {
                   return false;
                 }
                 args.rval().set(JS::UndefinedValue());
@@ -7565,17 +7582,17 @@ class CGGenericGetter(CGAbstractBindingM
         else:
             if allowCrossOriginThis:
                 name = "genericCrossOriginGetter"
             else:
                 name = "genericGetter"
             unwrapFailureCode = (
                 'return ThrowInvalidThis(cx, args, GetInvalidThisErrorForGetter(%%(securityError)s), "%s");\n' %
                 descriptor.interface.identifier.name)
-        CGAbstractBindingMethod.__init__(self, descriptor, name, args,
+        CGAbstractBindingMethod.__init__(self, descriptor, name, JSNativeArguments(),
                                          unwrapFailureCode,
                                          allowCrossOriginThis=allowCrossOriginThis)
 
     def generate_code(self):
         return CGGeneric(dedent("""
             const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(args.calleev());
             MOZ_ASSERT(info->type() == JSJitInfo::Getter);
             JSJitGetterOp getter = info->getter;
@@ -7676,19 +7693,16 @@ class CGStaticGetter(CGAbstractStaticBin
                             self.attr)
 
 
 class CGGenericSetter(CGAbstractBindingMethod):
     """
     A class for generating the C++ code for an IDL attribute setter.
     """
     def __init__(self, descriptor, lenientThis=False, allowCrossOriginThis=False):
-        args = [Argument('JSContext*', 'cx'),
-                Argument('unsigned', 'argc'),
-                Argument('JS::Value*', 'vp')]
         if lenientThis:
             name = "genericLenientSetter"
             unwrapFailureCode = dedent("""
                 MOZ_ASSERT(!JS_IsExceptionPending(cx));
                 if (!ReportLenientThisUnwrappingFailure(cx, &args.callee())) {
                   return false;
                 }
                 args.rval().set(JS::UndefinedValue());
@@ -7698,17 +7712,17 @@ class CGGenericSetter(CGAbstractBindingM
             if allowCrossOriginThis:
                 name = "genericCrossOriginSetter"
             else:
                 name = "genericSetter"
             unwrapFailureCode = (
                 'return ThrowInvalidThis(cx, args, GetInvalidThisErrorForSetter(%%(securityError)s), "%s");\n' %
                 descriptor.interface.identifier.name)
 
-        CGAbstractBindingMethod.__init__(self, descriptor, name, args,
+        CGAbstractBindingMethod.__init__(self, descriptor, name, JSNativeArguments(),
                                          unwrapFailureCode,
                                          allowCrossOriginThis=allowCrossOriginThis)
 
     def generate_code(self):
         return CGGeneric(fill(
             """
             if (args.length() == 0) {
               return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "${name} attribute setter");
@@ -10834,16 +10848,21 @@ class CGDescriptor(CGThing):
             for (k, v) in sorted(descriptor.permissions.items()):
                 perms = CGList((CGGeneric('"%s",' % p) for p in k), joiner="\n")
                 perms.append(CGGeneric("nullptr"))
                 cgThings.append(CGWrapper(CGIndenter(perms),
                                           pre="static const char* const permissions_%i[] = {\n" % v,
                                           post="\n};\n",
                                           defineOnly=True))
 
+        # Generate the _ClearCachedFooValue methods before the property arrays that use them.
+        if descriptor.interface.isJSImplemented():
+            for m in clearableCachedAttrs(descriptor):
+                cgThings.append(CGJSImplClearCachedValueMethod(descriptor, m))
+
         properties = PropertyArrays(descriptor)
         cgThings.append(CGGeneric(define=str(properties)))
         cgThings.append(CGNativeProperties(descriptor, properties))
 
         # Set up our Xray callbacks as needed.  Note that we don't need to do
         # it in workers.
         if not descriptor.workers and descriptor.concrete and descriptor.proxy:
             cgThings.append(CGResolveOwnProperty(descriptor))
@@ -10925,22 +10944,17 @@ class CGDescriptor(CGThing):
             else:
                 cgThings.append(CGWrapNonWrapperCacheMethod(descriptor,
                                                             properties))
 
         # If we're not wrappercached, we don't know how to clear our
         # cached values, since we can't get at the JSObject.
         if descriptor.wrapperCache:
             cgThings.extend(CGClearCachedValueMethod(descriptor, m) for
-                            m in descriptor.interface.members if
-                            m.isAttr() and
-                            # Constants should never need clearing!
-                            not m.getExtendedAttribute("Constant") and
-                            not m.getExtendedAttribute("SameObject") and
-                            m.slotIndex is not None)
+                            m in clearableCachedAttrs(descriptor))
 
         # CGCreateInterfaceObjectsMethod needs to come after our
         # CGDOMJSClass, if any.
         cgThings.append(CGCreateInterfaceObjectsMethod(descriptor, properties))
 
         # CGGetProtoObjectMethod and CGGetConstructorObjectMethod need
         # to come after CGCreateInterfaceObjectsMethod.
         if descriptor.interface.hasInterfacePrototypeObject():
@@ -12954,16 +12968,37 @@ def callbackGetterName(attr, descriptor)
         descriptor.binaryNameFor(attr.identifier.name))
 
 
 def callbackSetterName(attr, descriptor):
     return "Set" + MakeNativeName(
         descriptor.binaryNameFor(attr.identifier.name))
 
 
+class CGJSImplClearCachedValueMethod(CGAbstractBindingMethod):
+    def __init__(self, descriptor, attr):
+        if attr.getExtendedAttribute("StoreInSlot"):
+            raise TypeError("[StoreInSlot] is not supported for JS-implemented WebIDL. See bug 1056325.")
+
+        CGAbstractBindingMethod.__init__(self, descriptor,
+                                         MakeJSImplClearCachedValueNativeName(attr),
+                                         JSNativeArguments())
+        self.attr = attr
+
+    def generate_code(self):
+        return CGGeneric(fill(
+            """
+            ${bindingNamespace}::${fnName}(self);
+            args.rval().setUndefined();
+            return true;
+            """,
+            bindingNamespace=toBindingNamespace(self.descriptor.name),
+            fnName=MakeClearCachedValueNativeName(self.attr)))
+
+
 class CGJSImplGetter(CGJSImplMember):
     """
     Class for generating code for the getters of attributes for a JS-implemented
     WebIDL interface.
     """
     def __init__(self, descriptor, attr):
         CGJSImplMember.__init__(self, descriptor, attr,
                                 CGSpecializedGetter.makeNativeName(descriptor,
@@ -13106,19 +13141,17 @@ class CGJSImplClass(CGBindingImplClass):
              Argument("nsPIDOMWindow*", "aParent")],
             visibility="public",
             baseConstructors=baseConstructors,
             body=constructorBody)
 
         self.methodDecls.append(
             ClassMethod("_Create",
                         "bool",
-                        [Argument("JSContext*", "cx"),
-                         Argument("unsigned", "argc"),
-                         Argument("JS::Value*", "vp")],
+                        JSNativeArguments(),
                         static=True,
                         body=self.getCreateFromExistingBody()))
 
         CGClass.__init__(self, descriptor.name,
                          bases=baseClasses,
                          constructors=[constructor],
                          destructor=destructor,
                          methods=self.methodDecls,
--- a/dom/bindings/moz.build
+++ b/dom/bindings/moz.build
@@ -49,17 +49,16 @@ LOCAL_INCLUDES += [
     '/content/svg/content/src',
     '/content/xul/content/src',
     '/content/xul/document/src',
     '/dom/base',
     '/dom/battery',
     '/dom/bluetooth',
     '/dom/camera',
     '/dom/canvas',
-    '/dom/file',
     '/dom/indexedDB',
     '/dom/src/geolocation',
     '/dom/workers',
     '/dom/xbl',
     '/dom/xml',
     '/dom/xslt/base',
     '/dom/xslt/xpath',
     '/js/ipc',
--- a/dom/bindings/parser/WebIDL.py
+++ b/dom/bindings/parser/WebIDL.py
@@ -3192,18 +3192,17 @@ class IDLAttribute(IDLInterfaceMember):
             raise WebIDLError("Readonly attributes must not be flagged as "
                               "[SetterThrows]",
                               [self.location])
         elif (((identifier == "Throws" or identifier == "GetterThrows") and
                self.getExtendedAttribute("StoreInSlot")) or
               (identifier == "StoreInSlot" and
                (self.getExtendedAttribute("Throws") or
                 self.getExtendedAttribute("GetterThrows")))):
-            raise WebIDLError("Throwing things can't be [Pure] or [Constant] "
-                              "or [SameObject] or [StoreInSlot]",
+            raise WebIDLError("Throwing things can't be [StoreInSlot]",
                               [attr.location])
         elif identifier == "LenientThis":
             if not attr.noArguments():
                 raise WebIDLError("[LenientThis] must take no arguments",
                                   [attr.location])
             if self.isStatic():
                 raise WebIDLError("[LenientThis] is only allowed on non-static "
                                   "attributes", [attr.location, self.location])
--- a/dom/bindings/test/TestInterfaceJS.js
+++ b/dom/bindings/test/TestInterfaceJS.js
@@ -17,16 +17,17 @@ TestInterfaceJS.prototype = {
   QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports]),
 
   __init: function (anyArg, objectArg, dictionaryArg) {
     this._anyAttr = undefined;
     this._objectAttr = null;
     this._anyArg = anyArg;
     this._objectArg = objectArg;
     this._dictionaryArg = dictionaryArg;
+    this._cachedAttr = 15;
   },
 
   get anyArg() { return this._anyArg; },
   get objectArg() { return this._objectArg; },
   get dictionaryArg() { return this._dictionaryArg; },
   get anyAttr() { return this._anyAttr; },
   set anyAttr(val) { this._anyAttr = val; },
   get objectAttr() { return this._objectAttr; },
@@ -45,12 +46,16 @@ TestInterfaceJS.prototype = {
 
   getCallerPrincipal: function() { return Cu.getWebIDLCallerPrincipal().origin; },
 
   convertSVS: function(svs) { return svs; },
 
   pingPongUnion: function(x) { return x; },
   pingPongUnionContainingNull: function(x) { return x; },
   pingPongNullableUnion: function(x) { return x; },
-  returnBadUnion: function(x) { return 3; }
+  returnBadUnion: function(x) { return 3; },
+
+  get cachedAttr() { return this._cachedAttr; },
+  setCachedAttr: function(n) { this._cachedAttr = n; },
+  clearCachedAttrCache: function () { this.__DOM_IMPL__._clearCachedCachedAttrValue(); },
 };
 
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([TestInterfaceJS])
--- a/dom/bindings/test/mochitest.ini
+++ b/dom/bindings/test/mochitest.ini
@@ -14,16 +14,18 @@ support-files =
 [test_bug742191.html]
 [test_bug759621.html]
 [test_bug773326.html]
 [test_bug788369.html]
 [test_bug852846.html]
 [test_bug862092.html]
 [test_bug1036214.html]
 skip-if = debug == false
+[test_bug963382.html]
+skip-if = debug == false
 [test_bug1041646.html]
 [test_barewordGetsWindow.html]
 [test_callback_default_thisval.html]
 [test_cloneAndImportNode.html]
 [test_defineProperty.html]
 [test_enums.html]
 [test_exceptionThrowing.html]
 [test_exception_messages.html]
new file mode 100644
--- /dev/null
+++ b/dom/bindings/test/test_bug963382.html
@@ -0,0 +1,43 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=963382
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 963382</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <script type="application/javascript">
+
+  /** Test for clearing cache attributes in JS-implemented WebIDL implementations. **/
+  SimpleTest.waitForExplicitFinish();
+  SpecialPowers.pushPrefEnv({set: [['dom.expose_test_interfaces', true]]}, go);
+
+  function go() {
+    var t = new TestInterfaceJS();
+
+    // Test [Cached] attribute clearing.
+    is(t.cachedAttr, 15, "Initial value of number");
+
+    t.setCachedAttr(3);
+    is(t.cachedAttr, 15, "Setting the number on the inner JS object should not affect cached value");
+
+    t.clearCachedAttrCache();
+    is(t.cachedAttr, 3, "Setting the number on the inner JS object should affect cached value after clearing the cache.");
+
+    SimpleTest.finish();
+  }
+
+  </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=963382">Mozilla Bug 963382</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
--- a/dom/canvas/CanvasRenderingContext2D.h
+++ b/dom/canvas/CanvasRenderingContext2D.h
@@ -107,17 +107,17 @@ private:
 };
 
 struct CanvasBidiProcessor;
 class CanvasRenderingContext2DUserData;
 
 /**
  ** CanvasRenderingContext2D
  **/
-class CanvasRenderingContext2D :
+class CanvasRenderingContext2D MOZ_FINAL :
   public nsICanvasRenderingContextInternal,
   public nsWrapperCache
 {
 typedef HTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement
   HTMLImageOrCanvasOrVideoElement;
 
   virtual ~CanvasRenderingContext2D();
 
--- a/dom/canvas/WebGLContext.h
+++ b/dom/canvas/WebGLContext.h
@@ -1046,16 +1046,17 @@ protected:
     bool ValidateDrawModeEnum(GLenum mode, const char *info);
     bool ValidateAttribIndex(GLuint index, const char *info);
     bool ValidateStencilParamsForDrawCall();
 
     bool ValidateGLSLVariableName(const nsAString& name, const char *info);
     bool ValidateGLSLCharacter(char16_t c);
     bool ValidateGLSLString(const nsAString& string, const char *info);
 
+    bool ValidateCopyTexImage(GLenum format, WebGLTexImageFunc func);
     bool ValidateTexImage(GLuint dims, GLenum target,
                           GLint level, GLint internalFormat,
                           GLint xoffset, GLint yoffset, GLint zoffset,
                           GLint width, GLint height, GLint depth,
                           GLint border, GLenum format, GLenum type,
                           WebGLTexImageFunc func);
     bool ValidateTexImageTarget(GLuint dims, GLenum target, WebGLTexImageFunc func);
     bool ValidateTexImageFormat(GLenum format, WebGLTexImageFunc func);
--- a/dom/canvas/WebGLContextGL.cpp
+++ b/dom/canvas/WebGLContextGL.cpp
@@ -365,16 +365,22 @@ WebGLContext::CopyTexSubImage2D_base(GLe
                           xoffset, yoffset, 0,
                           width, height, 0,
                           0, internalformat, LOCAL_GL_UNSIGNED_BYTE,
                           func))
     {
         return;
     }
 
+    if (!ValidateCopyTexImage(internalformat, func))
+        return;
+
+    if (!mBoundFramebuffer)
+        ClearBackbufferIfNeeded();
+
     MakeContextCurrent();
 
     WebGLTexture *tex = activeBoundTextureForTarget(target);
 
     if (!tex)
         return ErrorInvalidOperation("%s: no texture is bound to this target");
 
     if (CanvasUtils::CheckSaneSubrectSize(x, y, width, height, framebufferWidth, framebufferHeight)) {
@@ -468,37 +474,21 @@ WebGLContext::CopyTexImage2D(GLenum targ
                           0, 0, 0,
                           width, height, 0,
                           border, format, type,
                           func))
     {
         return;
     }
 
-    if (mBoundFramebuffer) {
-        if (!mBoundFramebuffer->CheckAndInitializeAttachments())
-            return ErrorInvalidFramebufferOperation("copyTexImage2D: incomplete framebuffer");
-
-        GLenum readPlaneBits = LOCAL_GL_COLOR_BUFFER_BIT;
-        if (!mBoundFramebuffer->HasCompletePlanes(readPlaneBits)) {
-            return ErrorInvalidOperation("copyTexImage2D: Read source attachment doesn't have the"
-                                         " correct color/depth/stencil type.");
-        }
-    } else {
-      ClearBackbufferIfNeeded();
-    }
-
-    bool texFormatRequiresAlpha = format == LOCAL_GL_RGBA ||
-                                  format == LOCAL_GL_ALPHA ||
-                                  format == LOCAL_GL_LUMINANCE_ALPHA;
-    bool fboFormatHasAlpha = mBoundFramebuffer ? mBoundFramebuffer->ColorAttachment(0).HasAlpha()
-                                               : bool(gl->GetPixelFormat().alpha > 0);
-    if (texFormatRequiresAlpha && !fboFormatHasAlpha)
-        return ErrorInvalidOperation("copyTexImage2D: texture format requires an alpha channel "
-                                     "but the framebuffer doesn't have one");
+    if (!ValidateCopyTexImage(format, func))
+        return;
+
+    if (!mBoundFramebuffer)
+        ClearBackbufferIfNeeded();
 
     // check if the memory size of this texture may change with this call
     bool sizeMayChange = true;
     WebGLTexture* tex = activeBoundTextureForTarget(target);
     if (tex->HasImageInfoAt(target, level)) {
         const WebGLTexture::ImageInfo& imageInfo = tex->ImageInfoAt(target, level);
 
         sizeMayChange = width != imageInfo.Width() ||
@@ -575,43 +565,24 @@ WebGLContext::CopyTexSubImage2D(GLenum t
     GLsizei texHeight = imageInfo.Height();
 
     if (xoffset + width > texWidth || xoffset + width < 0)
       return ErrorInvalidValue("copyTexSubImage2D: xoffset+width is too large");
 
     if (yoffset + height > texHeight || yoffset + height < 0)
       return ErrorInvalidValue("copyTexSubImage2D: yoffset+height is too large");
 
-    if (mBoundFramebuffer) {
-        if (!mBoundFramebuffer->CheckAndInitializeAttachments())
-            return ErrorInvalidFramebufferOperation("copyTexSubImage2D: incomplete framebuffer");
-
-        GLenum readPlaneBits = LOCAL_GL_COLOR_BUFFER_BIT;
-        if (!mBoundFramebuffer->HasCompletePlanes(readPlaneBits)) {
-            return ErrorInvalidOperation("copyTexSubImage2D: Read source attachment doesn't have the"
-                                         " correct color/depth/stencil type.");
-        }
-    } else {
+    if (!mBoundFramebuffer)
         ClearBackbufferIfNeeded();
-    }
-
-    GLenum webGLFormat = imageInfo.WebGLFormat();
-    bool texFormatRequiresAlpha = FormatHasAlpha(webGLFormat);
-    bool fboFormatHasAlpha = mBoundFramebuffer ? mBoundFramebuffer->ColorAttachment(0).HasAlpha()
-                                               : bool(gl->GetPixelFormat().alpha > 0);
-
-    if (texFormatRequiresAlpha && !fboFormatHasAlpha)
-        return ErrorInvalidOperation("copyTexSubImage2D: texture format requires an alpha channel "
-                                     "but the framebuffer doesn't have one");
 
     if (imageInfo.HasUninitializedImageData()) {
         tex->DoDeferredImageInitialization(target, level);
     }
 
-    return CopyTexSubImage2D_base(target, level, webGLFormat, xoffset, yoffset, x, y, width, height, true);
+    return CopyTexSubImage2D_base(target, level, imageInfo.WebGLFormat(), xoffset, yoffset, x, y, width, height, true);
 }
 
 
 already_AddRefed<WebGLProgram>
 WebGLContext::CreateProgram()
 {
     if (IsContextLost())
         return nullptr;
--- a/dom/canvas/WebGLContextUtils.cpp
+++ b/dom/canvas/WebGLContextUtils.cpp
@@ -17,16 +17,17 @@
 #include "nsServiceManagerUtils.h"
 #include "prprf.h"
 #include "WebGLBuffer.h"
 #include "WebGLExtensions.h"
 #include "WebGLFramebuffer.h"
 #include "WebGLProgram.h"
 #include "WebGLTexture.h"
 #include "WebGLVertexArray.h"
+#include "WebGLContextUtils.h"
 
 #include "mozilla/dom/ScriptSettings.h"
 
 namespace mozilla {
 
 using namespace gl;
 
 bool
@@ -50,16 +51,57 @@ FormatHasAlpha(GLenum webGLFormat)
     return webGLFormat == LOCAL_GL_RGBA ||
            webGLFormat == LOCAL_GL_LUMINANCE_ALPHA ||
            webGLFormat == LOCAL_GL_ALPHA ||
            webGLFormat == LOCAL_GL_RGBA4 ||
            webGLFormat == LOCAL_GL_RGB5_A1 ||
            webGLFormat == LOCAL_GL_SRGB_ALPHA;
 }
 
+GLComponents::GLComponents(GLenum format)
+{
+    mComponents = 0;
+
+    switch (format) {
+        case LOCAL_GL_RGBA:
+        case LOCAL_GL_RGBA4:
+        case LOCAL_GL_RGBA8:
+        case LOCAL_GL_RGB5_A1:
+        // Luminance + Alpha can be converted
+        // to and from RGBA
+        case LOCAL_GL_LUMINANCE_ALPHA:
+            mComponents |= Components::Alpha;
+        // Drops through
+        case LOCAL_GL_RGB:
+        case LOCAL_GL_RGB565:
+        // Luminance can be converted to and from RGB
+        case LOCAL_GL_LUMINANCE:
+            mComponents |= Components::Red | Components::Green | Components::Blue;
+            break;
+        case LOCAL_GL_ALPHA:
+            mComponents |= Components::Alpha;
+            break;
+        case LOCAL_GL_DEPTH_COMPONENT:
+            mComponents |= Components::Depth;
+            break;
+        case LOCAL_GL_DEPTH_STENCIL:
+            mComponents |= Components::Stencil;
+            break;
+        default:
+            MOZ_ASSERT(false, "Unhandled case - GLComponents");
+            break;
+    }
+}
+
+bool
+GLComponents::IsSubsetOf(const GLComponents& other) const
+{
+    return (mComponents | other.mComponents) == other.mComponents;
+}
+
 /**
  * Convert WebGL/ES format and type into GL format and GL internal
  * format valid for underlying driver.
  */
 void
 DriverFormatsFromFormatAndType(GLContext* gl, GLenum webGLFormat, GLenum webGLType,
                                GLenum* out_driverInternalFormat, GLenum* out_driverFormat)
 {
--- a/dom/canvas/WebGLContextUtils.h
+++ b/dom/canvas/WebGLContextUtils.h
@@ -14,16 +14,40 @@ namespace mozilla {
 
 bool IsGLDepthFormat(GLenum webGLFormat);
 bool IsGLDepthStencilFormat(GLenum webGLFormat);
 bool FormatHasAlpha(GLenum webGLFormat);
 void DriverFormatsFromFormatAndType(gl::GLContext* gl, GLenum webGLFormat, GLenum webGLType,
                                     GLenum* out_driverInternalFormat, GLenum* out_driverFormat);
 GLenum DriverTypeFromType(gl::GLContext* gl, GLenum webGLType);
 
+struct GLComponents
+{
+    unsigned char mComponents;
+
+    enum Components {
+        Red     = (1 << 0),
+        Green   = (1 << 1),
+        Blue    = (1 << 2),
+        Alpha   = (1 << 3),
+        Stencil = (1 << 4),
+        Depth   = (1 << 5),
+    };
+
+    GLComponents()
+        : mComponents(0)
+    { }
+
+    GLComponents(GLenum format);
+
+    // Returns true iff other has all (or more) of
+    // the components present in this GLComponents
+    bool IsSubsetOf(const GLComponents& other) const;
+};
+
 template <typename WebGLObjectType>
 JS::Value
 WebGLContext::WebGLObjectAsJSValue(JSContext *cx, const WebGLObjectType *object, ErrorResult& rv) const
 {
     if (!object) {
         return JS::NullValue();
     }
     MOZ_ASSERT(this == object->Context());
--- a/dom/canvas/WebGLContextValidate.cpp
+++ b/dom/canvas/WebGLContextValidate.cpp
@@ -10,16 +10,17 @@
 #include "WebGLProgram.h"
 #include "WebGLUniformLocation.h"
 #include "WebGLFramebuffer.h"
 #include "WebGLRenderbuffer.h"
 #include "WebGLTexture.h"
 #include "WebGLVertexArray.h"
 #include "GLContext.h"
 #include "CanvasUtils.h"
+#include "WebGLContextUtils.h"
 
 #include "mozilla/CheckedInt.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
 
 #include "jsfriendapi.h"
 
 #include "angle/ShaderLang.h"
@@ -1252,16 +1253,61 @@ WebGLContext::ValidateTexInputData(GLenu
 
     if (!validInput)
         ErrorInvalidOperation(invalidTypedArray, InfoFrom(func));
 
     return validInput;
 }
 
 /**
+ * Checks specific for the CopyTex[Sub]Image2D functions.
+ * Verifies:
+ * - Framebuffer is complete and has valid read planes
+ * - Copy format is a subset of framebuffer format (i.e. all required components are available)
+ */
+bool
+WebGLContext::ValidateCopyTexImage(GLenum format, WebGLTexImageFunc func)
+{
+    MOZ_ASSERT(IsCopyFunc(func));
+
+    // Default framebuffer format
+    GLenum fboFormat = bool(gl->GetPixelFormat().alpha > 0) ? LOCAL_GL_RGBA : LOCAL_GL_RGB;
+
+    if (mBoundFramebuffer) {
+        if (!mBoundFramebuffer->CheckAndInitializeAttachments()) {
+            ErrorInvalidFramebufferOperation("%s: incomplete framebuffer", InfoFrom(func));
+            return false;
+        }
+
+        GLenum readPlaneBits = LOCAL_GL_COLOR_BUFFER_BIT;
+        if (!mBoundFramebuffer->HasCompletePlanes(readPlaneBits)) {
+            ErrorInvalidOperation("%s: Read source attachment doesn't have the"
+                                  " correct color/depth/stencil type.", InfoFrom(func));
+            return false;
+        }
+
+        // Get the correct format for the framebuffer, as it's not the default one
+        const WebGLFramebuffer::Attachment& color0 = mBoundFramebuffer->GetAttachment(LOCAL_GL_COLOR_ATTACHMENT0);
+        fboFormat = mBoundFramebuffer->GetFormatForAttachment(color0);
+    }
+
+    // Make sure the format of the framebuffer is a superset of
+    // the format requested by the CopyTex[Sub]Image2D functions.
+    const GLComponents formatComps = GLComponents(format);
+    const GLComponents fboComps = GLComponents(fboFormat);
+    if (!formatComps.IsSubsetOf(fboComps)) {
+        ErrorInvalidOperation("%s: format %s is not a subset of the current framebuffer format, which is %s.",
+                              InfoFrom(func), EnumName(format), EnumName(fboFormat));
+        return false;
+    }
+
+    return true;
+}
+
+/**
  * Test the gl(Copy|Compressed)?Tex[Sub]?Image[23]() parameters for errors.
  * Verifies each of the parameters against the WebGL standard and enabled extensions.
  */
 // TODO: Texture dims is here for future expansion in WebGL 2.0
 bool
 WebGLContext::ValidateTexImage(GLuint dims, GLenum target,
                                GLint level, GLint internalFormat,
                                GLint xoffset, GLint yoffset, GLint zoffset,
--- a/dom/canvas/WebGLFramebuffer.cpp
+++ b/dom/canvas/WebGLFramebuffer.cpp
@@ -71,16 +71,36 @@ WebGLFramebuffer::Attachment::HasAlpha()
     GLenum format = 0;
     if (Texture() && Texture()->HasImageInfoAt(mTexImageTarget, mTexImageLevel))
         format = Texture()->ImageInfoAt(mTexImageTarget, mTexImageLevel).WebGLFormat();
     else if (Renderbuffer())
         format = Renderbuffer()->InternalFormat();
     return FormatHasAlpha(format);
 }
 
+GLenum
+WebGLFramebuffer::GetFormatForAttachment(const WebGLFramebuffer::Attachment& attachment) const
+{
+    MOZ_ASSERT(attachment.IsDefined());
+    MOZ_ASSERT(attachment.Texture() || attachment.Renderbuffer());
+
+    if (attachment.Texture()) {
+        const WebGLTexture& tex = *attachment.Texture();
+        MOZ_ASSERT(tex.HasImageInfoAt(tex.Target(), 0));
+
+        const WebGLTexture::ImageInfo& imgInfo = tex.ImageInfoAt(tex.Target(), 0);
+        return imgInfo.WebGLFormat();
+    }
+
+    if (attachment.Renderbuffer())
+        return attachment.Renderbuffer()->InternalFormat();
+
+    return LOCAL_GL_NONE;
+}
+
 bool
 WebGLFramebuffer::Attachment::IsReadableFloat() const
 {
     const WebGLTexture* tex = Texture();
     if (tex && tex->HasImageInfoAt(mTexImageTarget, mTexImageLevel)) {
         GLenum type = tex->ImageInfoAt(mTexImageTarget, mTexImageLevel).WebGLType();
         switch (type) {
         case LOCAL_GL_FLOAT:
--- a/dom/canvas/WebGLFramebuffer.h
+++ b/dom/canvas/WebGLFramebuffer.h
@@ -112,16 +112,17 @@ private:
     Attachment* GetAttachmentOrNull(GLenum attachment);
 
 public:
     bool HasDefinedAttachments() const;
     bool HasIncompleteAttachments() const;
     bool AllImageRectsMatch() const;
     GLenum PrecheckFramebufferStatus() const;
     GLenum CheckFramebufferStatus() const;
+    GLenum GetFormatForAttachment(const WebGLFramebuffer::Attachment& attachment) const;
 
     bool HasDepthStencilConflict() const {
         return int(mDepthAttachment.IsDefined()) +
                int(mStencilAttachment.IsDefined()) +
                int(mDepthStencilAttachment.IsDefined()) >= 2;
     }
 
     size_t ColorAttachmentCount() const {
--- a/dom/indexedDB/IDBDatabase.h
+++ b/dom/indexedDB/IDBDatabase.h
@@ -43,18 +43,18 @@ class IDBFactory;
 class IDBIndex;
 class IDBObjectStore;
 class IDBTransaction;
 class IndexedDatabaseManager;
 class IndexedDBDatabaseChild;
 class IndexedDBDatabaseParent;
 struct ObjectStoreInfoGuts;
 
-class IDBDatabase : public IDBWrapperCache,
-                    public nsIOfflineStorage
+class IDBDatabase MOZ_FINAL : public IDBWrapperCache,
+                              public nsIOfflineStorage
 {
   friend class AsyncConnectionHelper;
   friend class IndexedDatabaseManager;
   friend class IndexedDBDatabaseParent;
   friend class IndexedDBDatabaseChild;
 
 public:
   NS_DECL_ISUPPORTS_INHERITED
--- a/dom/indexedDB/IDBObjectStore.cpp
+++ b/dom/indexedDB/IDBObjectStore.cpp
@@ -645,17 +645,16 @@ class ThreadLocalJSRuntime
     NS_ENSURE_TRUE(mContext, NS_ERROR_OUT_OF_MEMORY);
 
     JSAutoRequest ar(mContext);
 
     mGlobal = JS_NewGlobalObject(mContext, &sGlobalClass, nullptr,
                                  JS::FireOnNewGlobalHook);
     NS_ENSURE_TRUE(mGlobal, NS_ERROR_OUT_OF_MEMORY);
 
-    js::SetDefaultObjectForContext(mContext, mGlobal);
     return NS_OK;
   }
 
  public:
   static ThreadLocalJSRuntime *Create()
   {
     ThreadLocalJSRuntime *entry = new ThreadLocalJSRuntime();
     NS_ENSURE_TRUE(entry, nullptr);
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -329,16 +329,44 @@ template<>
 struct nsIConsoleService::COMTypeInfo<nsConsoleService, void> {
   static const nsIID kIID;
 };
 const nsIID nsIConsoleService::COMTypeInfo<nsConsoleService, void>::kIID = NS_ICONSOLESERVICE_IID;
 
 namespace mozilla {
 namespace dom {
 
+#ifdef MOZ_NUWA_PROCESS
+bool ContentParent::sNuwaReady = false;
+
+// Contains data that is observed by Nuwa and is going to be sent to
+// the new process when it is forked.
+struct ContentParent::NuwaReinitializeData {
+    NuwaReinitializeData()
+        : mReceivedFilePathUpdate(false)
+        , mReceivedFileSystemUpdate(false) { }
+
+    bool mReceivedFilePathUpdate;
+    nsString mFilePathUpdateStoageType;
+    nsString mFilePathUpdateStorageName;
+    nsString mFilePathUpdatePath;
+    nsCString mFilePathUpdateReason;
+
+    bool mReceivedFileSystemUpdate;
+    nsString mFileSystemUpdateFsName;
+    nsString mFileSystemUpdateMountPount;
+    int32_t mFileSystemUpdateState;
+    int32_t mFileSystemUpdateMountGeneration;
+    bool mFileSystemUpdateIsMediaPresent;
+    bool mFileSystemUpdateIsSharing;
+    bool mFileSystemUpdateIsFormatting;
+    bool mFileSystemUpdateIsFake;
+};
+#endif
+
 #define NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC "ipc:network:set-offline"
 
 class MemoryReportRequestParent : public PMemoryReportRequestParent
 {
 public:
     MemoryReportRequestParent();
     virtual ~MemoryReportRequestParent();
 
@@ -569,16 +597,19 @@ ContentParent::RunNuwaProcess()
     nsRefPtr<ContentParent> nuwaProcess =
         new ContentParent(/* aApp = */ nullptr,
                           /* aOpener = */ nullptr,
                           /* aIsForBrowser = */ false,
                           /* aIsForPreallocated = */ true,
                           PROCESS_PRIORITY_BACKGROUND,
                           /* aIsNuwaProcess = */ true);
     nuwaProcess->Init();
+#ifdef MOZ_NUWA_PROCESS
+    sNuwaReady = false;
+#endif
     return nuwaProcess.forget();
 }
 
 // PreallocateAppProcess is called by the PreallocatedProcessManager.
 // ContentParent then takes this process back within
 // GetNewOrPreallocatedAppProcess.
 /*static*/ already_AddRefed<ContentParent>
 ContentParent::PreallocateAppProcess()
@@ -1966,16 +1997,22 @@ ContentParent::~ContentParent()
     } else {
         // In general, we expect sAppContentParents->Get(mAppManifestURL) to be
         // nullptr.  But it could be that we created another ContentParent for
         // this app after we did this->ActorDestroy(), so the right check is
         // that sAppContentParents->Get(mAppManifestURL) != this.
         MOZ_ASSERT(!sAppContentParents ||
                    sAppContentParents->Get(mAppManifestURL) != this);
     }
+
+#ifdef MOZ_NUWA_PROCESS
+    if (IsNuwaProcess()) {
+        sNuwaReady = false;
+    }
+#endif
 }
 
 void
 ContentParent::InitInternal(ProcessPriority aInitialPriority,
                             bool aSetupOffMainThreadCompositing,
                             bool aSendRegisteredChrome)
 {
     // Set the subprocess's priority.  We do this early on because we're likely
@@ -2426,16 +2463,17 @@ ContentParent::RecvNuwaReady()
         NS_ERROR(
             nsPrintfCString(
                 "Terminating child process %d for unauthorized IPC message: NuwaReady",
                 Pid()).get());
 
         KillHard();
         return false;
     }
+    sNuwaReady = true;
     PreallocatedProcessManager::OnNuwaReady();
     return true;
 #else
     NS_ERROR("ContentParent::RecvNuwaReady() not implemented!");
     return false;
 #endif
 }
 
@@ -2461,16 +2499,42 @@ ContentParent::RecvAddNewProcess(const u
     content->Init();
 
     size_t numNuwaPrefUpdates = sNuwaPrefUpdates ?
                                 sNuwaPrefUpdates->Length() : 0;
     // Resend pref updates to the forked child.
     for (int i = 0; i < numNuwaPrefUpdates; i++) {
         content->SendPreferenceUpdate(sNuwaPrefUpdates->ElementAt(i));
     }
+
+    // Update offline settings.
+    bool isOffline;
+    RecvGetXPCOMProcessAttributes(&isOffline);
+    content->SendSetOffline(isOffline);
+
+    // Send observed updates to new content.
+    if (mReinitializeData) {
+        if (mReinitializeData->mReceivedFilePathUpdate) {
+            unused << content->SendFilePathUpdate(mReinitializeData->mFilePathUpdateStoageType,
+                                                  mReinitializeData->mFilePathUpdateStorageName,
+                                                  mReinitializeData->mFilePathUpdatePath,
+                                                  mReinitializeData->mFilePathUpdateReason);
+        }
+        if (mReinitializeData->mReceivedFilePathUpdate) {
+            unused << content->SendFileSystemUpdate(mReinitializeData->mFileSystemUpdateFsName,
+                                                    mReinitializeData->mFileSystemUpdateMountPount,
+                                                    mReinitializeData->mFileSystemUpdateState,
+                                                    mReinitializeData->mFileSystemUpdateMountGeneration,
+                                                    mReinitializeData->mFileSystemUpdateIsMediaPresent,
+                                                    mReinitializeData->mFileSystemUpdateIsSharing,
+                                                    mReinitializeData->mFileSystemUpdateIsFormatting,
+                                                    mReinitializeData->mFileSystemUpdateIsFake);
+        }
+    }
+
     PreallocatedProcessManager::PublishSpareProcess(content);
     return true;
 #else
     NS_ERROR("ContentParent::RecvAddNewProcess() not implemented!");
     return false;
 #endif
 }
 
@@ -2529,18 +2593,25 @@ ContentParent::Observe(nsISupports* aSub
         if (!SendPreferenceUpdate(pref)) {
             return NS_ERROR_NOT_AVAILABLE;
         }
 #endif
     }
     else if (!strcmp(aTopic, NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC)) {
       NS_ConvertUTF16toUTF8 dataStr(aData);
       const char *offline = dataStr.get();
-      if (!SendSetOffline(!strcmp(offline, "true") ? true : false))
-          return NS_ERROR_NOT_AVAILABLE;
+#ifdef MOZ_NUWA_PROCESS
+      if (!(IsNuwaReady() && IsNuwaProcess())) {
+#endif
+          if (!SendSetOffline(!strcmp(offline, "true") ? true : false)) {
+              return NS_ERROR_NOT_AVAILABLE;
+          }
+#ifdef MOZ_NUWA_PROCESS
+      }
+#endif
     }
     // listening for alert notifications
     else if (!strcmp(aTopic, "alertfinished") ||
              !strcmp(aTopic, "alertclickcallback") ||
              !strcmp(aTopic, "alertshow") ) {
         if (!SendNotifyAlertsObserver(nsDependentCString(aTopic),
                                       nsDependentString(aData)))
             return NS_ERROR_NOT_AVAILABLE;
@@ -2595,17 +2666,34 @@ ContentParent::Observe(nsISupports* aSub
     else if (!strcmp(aTopic, "last-pb-context-exited")) {
         unused << SendLastPrivateDocShellDestroyed();
     }
     else if (!strcmp(aTopic, "file-watcher-update")) {
         nsCString creason;
         CopyUTF16toUTF8(aData, creason);
         DeviceStorageFile* file = static_cast<DeviceStorageFile*>(aSubject);
 
-        unused << SendFilePathUpdate(file->mStorageType, file->mStorageName, file->mPath, creason);
+#ifdef MOZ_NUWA_PROCESS
+        if (!(IsNuwaReady() && IsNuwaProcess())) {
+#endif
+
+            unused << SendFilePathUpdate(file->mStorageType, file->mStorageName, file->mPath, creason);
+
+#ifdef MOZ_NUWA_PROCESS
+        } else {
+            if (!mReinitializeData) {
+                mReinitializeData = new NuwaReinitializeData();
+            }
+            mReinitializeData->mReceivedFilePathUpdate = true;
+            mReinitializeData->mFilePathUpdateStoageType = file->mStorageType;
+            mReinitializeData->mFilePathUpdateStorageName = file->mStorageName;
+            mReinitializeData->mFilePathUpdatePath = file->mPath;
+            mReinitializeData->mFilePathUpdateReason = creason;
+        }
+#endif
     }
 #ifdef MOZ_WIDGET_GONK
     else if(!strcmp(aTopic, NS_VOLUME_STATE_CHANGED)) {
         nsCOMPtr<nsIVolume> vol = do_QueryInterface(aSubject);
         if (!vol) {
             return NS_ERROR_NOT_AVAILABLE;
         }
 
@@ -2622,19 +2710,40 @@ ContentParent::Observe(nsISupports* aSub
         vol->GetMountPoint(mountPoint);
         vol->GetState(&state);
         vol->GetMountGeneration(&mountGeneration);
         vol->GetIsMediaPresent(&isMediaPresent);
         vol->GetIsSharing(&isSharing);
         vol->GetIsFormatting(&isFormatting);
         vol->GetIsFake(&isFake);
 
-        unused << SendFileSystemUpdate(volName, mountPoint, state,
-                                       mountGeneration, isMediaPresent,
-                                       isSharing, isFormatting, isFake);
+#ifdef MOZ_NUWA_PROCESS
+        if (!(IsNuwaReady() && IsNuwaProcess())) {
+#endif
+
+            unused << SendFileSystemUpdate(volName, mountPoint, state,
+                                           mountGeneration, isMediaPresent,
+                                           isSharing, isFormatting, isFake);
+
+#ifdef MOZ_NUWA_PROCESS
+        } else {
+            if (!mReinitializeData) {
+                mReinitializeData = new NuwaReinitializeData();
+            }
+            mReinitializeData->mReceivedFileSystemUpdate = true;
+            mReinitializeData->mFileSystemUpdateFsName = volName;
+            mReinitializeData->mFileSystemUpdateMountPount = mountPoint;
+            mReinitializeData->mFileSystemUpdateState = state;
+            mReinitializeData->mFileSystemUpdateMountPount = mountGeneration;
+            mReinitializeData->mFileSystemUpdateIsMediaPresent = isMediaPresent;
+            mReinitializeData->mFileSystemUpdateIsSharing = isSharing;
+            mReinitializeData->mFileSystemUpdateIsFormatting = isFormatting;
+            mReinitializeData->mFileSystemUpdateIsFake = isFake;
+        }
+#endif
     } else if (!strcmp(aTopic, "phone-state-changed")) {
         nsString state(aData);
         unused << SendNotifyPhoneStateChange(state);
     }
 #endif
 #ifdef ACCESSIBILITY
     // Make sure accessibility is running in content process when accessibility
     // gets initiated in chrome process.
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -60,29 +60,34 @@ class Element;
 class TabParent;
 class PStorageParent;
 class ClonedMessageData;
 class MemoryReport;
 class TabContext;
 class PFileDescriptorSetParent;
 class ContentBridgeParent;
 
-class ContentParent : public PContentParent
-                    , public nsIContentParent
-                    , public nsIObserver
-                    , public nsIDOMGeoPositionCallback
-                    , public mozilla::LinkedListElement<ContentParent>
+class ContentParent MOZ_FINAL : public PContentParent
+                              , public nsIContentParent
+                              , public nsIObserver
+                              , public nsIDOMGeoPositionCallback
+                              , public mozilla::LinkedListElement<ContentParent>
 {
     typedef mozilla::ipc::GeckoChildProcessHost GeckoChildProcessHost;
     typedef mozilla::ipc::OptionalURIParams OptionalURIParams;
     typedef mozilla::ipc::TestShellParent TestShellParent;
     typedef mozilla::ipc::URIParams URIParams;
     typedef mozilla::dom::ClonedMessageData ClonedMessageData;
 
 public:
+#ifdef MOZ_NUWA_PROCESS
+    static bool IsNuwaReady() {
+        return sNuwaReady;
+    }
+#endif
     virtual bool IsContentParent() MOZ_OVERRIDE { return true; }
     /**
      * Start up the content-process machinery.  This might include
      * scheduling pre-launch tasks.
      */
     static void StartUp();
     /** Shut down the content-process machinery. */
     static void ShutDown();
@@ -696,16 +701,22 @@ private:
 
     nsDataHashtable<nsUint64HashKey, nsRefPtr<ParentIdleListener> > mIdleListeners;
 
 #ifdef MOZ_X11
     // Dup of child's X socket, used to scope its resources to this
     // object instead of the child process's lifetime.
     ScopedClose mChildXSocketFdDup;
 #endif
+
+#ifdef MOZ_NUWA_PROCESS
+    static bool sNuwaReady;
+    struct NuwaReinitializeData;
+    nsAutoPtr<NuwaReinitializeData> mReinitializeData;
+#endif
 };
 
 } // namespace dom
 } // namespace mozilla
 
 class ParentIdleListener : public nsIObserver {
 public:
   NS_DECL_ISUPPORTS
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -29,16 +29,17 @@
 #include "mozilla/MouseEvents.h"
 #include "mozilla/Services.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/TextEvents.h"
 #include "mozilla/TouchEvents.h"
 #include "mozilla/unused.h"
 #include "mozIApplication.h"
 #include "nsContentUtils.h"
+#include "nsDocShell.h"
 #include "nsEmbedCID.h"
 #include <algorithm>
 #ifdef MOZ_CRASHREPORTER
 #include "nsExceptionHandler.h"
 #endif
 #include "nsFilePickerProxy.h"
 #include "mozilla/dom/Element.h"
 #include "nsIBaseWindow.h"
@@ -1456,22 +1457,16 @@ TabChild::DestroyWindow()
 
             nsRefPtr<CloseFileRunnable> runnable =
                 new CloseFileRunnable(info->mFileDescriptor);
             runnable->Dispatch();
         }
     }
 }
 
-bool
-TabChild::UseDirectCompositor()
-{
-    return !!CompositorChild::Get();
-}
-
 void
 TabChild::ActorDestroy(ActorDestroyReason why)
 {
   if (mTabChildGlobal) {
     // The messageManager relays messages via the TabChild which
     // no longer exists.
     static_cast<nsFrameMessageManager*>
       (mTabChildGlobal->mMessageManager.get())->Disconnect();
@@ -1884,25 +1879,43 @@ TabChild::RecvNotifyAPZStateChange(const
   {
   case APZStateChange::TransformBegin:
   {
     nsIScrollableFrame* sf = nsLayoutUtils::FindScrollableFrameFor(aViewId);
     nsIScrollbarOwner* scrollbarOwner = do_QueryFrame(sf);
     if (scrollbarOwner) {
       scrollbarOwner->ScrollbarActivityStarted();
     }
+
+    nsCOMPtr<nsIDocument> doc = GetDocument();
+    if (doc) {
+      nsCOMPtr<nsIDocShell> docshell(doc->GetDocShell());
+      if (docshell) {
+        nsDocShell* nsdocshell = static_cast<nsDocShell*>(docshell.get());
+        nsdocshell->NotifyAsyncPanZoomStarted();
+      }
+    }
     break;
   }
   case APZStateChange::TransformEnd:
   {
     nsIScrollableFrame* sf = nsLayoutUtils::FindScrollableFrameFor(aViewId);
     nsIScrollbarOwner* scrollbarOwner = do_QueryFrame(sf);
     if (scrollbarOwner) {
       scrollbarOwner->ScrollbarActivityStopped();
     }
+
+    nsCOMPtr<nsIDocument> doc = GetDocument();
+    if (doc) {
+      nsCOMPtr<nsIDocShell> docshell(doc->GetDocShell());
+      if (docshell) {
+        nsDocShell* nsdocshell = static_cast<nsDocShell*>(docshell.get());
+        nsdocshell->NotifyAsyncPanZoomStopped();
+      }
+    }
     break;
   }
   case APZStateChange::StartTouch:
   {
     mActiveElementManager->HandleTouchStart(aArg);
     break;
   }
   case APZStateChange::StartPanning:
@@ -2575,38 +2588,33 @@ TabChild::InitRenderingState()
         return false;
     }
     if (!success) {
         NS_WARNING("failed to construct RenderFrame");
         PRenderFrameChild::Send__delete__(remoteFrame);
         return false;
     }
 
-    PLayerTransactionChild* shadowManager = nullptr;
-    if (id != 0) {
-        // Pushing layers transactions directly to a separate
-        // compositor context.
-        PCompositorChild* compositorChild = CompositorChild::Get();
-        if (!compositorChild) {
-          NS_WARNING("failed to get CompositorChild instance");
-          return false;
-        }
-        nsTArray<LayersBackend> backends;
-        backends.AppendElement(mTextureFactoryIdentifier.mParentBackend);
-        bool success;
-        shadowManager =
-            compositorChild->SendPLayerTransactionConstructor(backends,
-                                                              id, &mTextureFactoryIdentifier, &success);
-        if (!success) {
-          NS_WARNING("failed to properly allocate layer transaction");
-          return false;
-        }
-    } else {
-        // Pushing transactions to the parent content.
-        shadowManager = remoteFrame->SendPLayerTransactionConstructor();
+    MOZ_ASSERT(id != 0);
+
+    // Pushing layers transactions directly to a separate
+    // compositor context.
+    PCompositorChild* compositorChild = CompositorChild::Get();
+    if (!compositorChild) {
+      NS_WARNING("failed to get CompositorChild instance");
+      return false;
+    }
+    nsTArray<LayersBackend> backends;
+    backends.AppendElement(mTextureFactoryIdentifier.mParentBackend);
+    PLayerTransactionChild* shadowManager =
+        compositorChild->SendPLayerTransactionConstructor(backends,
+                                                          id, &mTextureFactoryIdentifier, &success);
+    if (!success) {
+      NS_WARNING("failed to properly allocate layer transaction");
+      return false;
     }
 
     if (!shadowManager) {
       NS_WARNING("failed to construct LayersChild");
       // This results in |remoteFrame| being deleted.
       PRenderFrameChild::Send__delete__(remoteFrame);
       return false;
     }
@@ -2678,17 +2686,17 @@ TabChild::GetDefaultScale(double* aScale
     }
 
     SendGetDefaultScale(aScale);
 }
 
 void
 TabChild::NotifyPainted()
 {
-    if (UseDirectCompositor() && !mNotified) {
+    if (!mNotified) {
         mRemoteFrame->SendNotifyCompositorTransaction();
         mNotified = true;
     }
 }
 
 bool
 TabChild::DispatchMouseEvent(const nsString&       aType,
                              const CSSPoint&       aPoint,
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -221,30 +221,30 @@ protected:
     CSSSize mOldViewportSize;
     bool mContentDocumentIsDisplayed;
     nsRefPtr<TabChildGlobal> mTabChildGlobal;
     ScreenIntSize mInnerSize;
     mozilla::layers::FrameMetrics mLastRootMetrics;
     mozilla::layout::ScrollingBehavior mScrolling;
 };
 
-class TabChild : public TabChildBase,
-                 public PBrowserChild,
-                 public nsIWebBrowserChrome2,
-                 public nsIEmbeddingSiteWindow,
-                 public nsIWebBrowserChromeFocus,
-                 public nsIInterfaceRequestor,
-                 public nsIWindowProvider,
-                 public nsIDOMEventListener,
-                 public nsIWebProgressListener,
-                 public nsSupportsWeakReference,
-                 public nsITabChild,
-                 public nsIObserver,
-                 public TabContext,
-                 public nsITooltipListener
+class TabChild MOZ_FINAL : public TabChildBase,
+                           public PBrowserChild,
+                           public nsIWebBrowserChrome2,
+                           public nsIEmbeddingSiteWindow,
+                           public nsIWebBrowserChromeFocus,
+                           public nsIInterfaceRequestor,
+                           public nsIWindowProvider,
+                           public nsIDOMEventListener,
+                           public nsIWebProgressListener,
+                           public nsSupportsWeakReference,
+                           public nsITabChild,
+                           public nsIObserver,
+                           public TabContext,
+                           public nsITooltipListener
 {
     typedef mozilla::dom::ClonedMessageData ClonedMessageData;
     typedef mozilla::layout::RenderFrameChild RenderFrameChild;
     typedef mozilla::layout::ScrollingBehavior ScrollingBehavior;
     typedef mozilla::layers::ActiveElementManager ActiveElementManager;
 
 public:
     static std::map<uint64_t, nsRefPtr<TabChild> >& NestedTabChildMap();
@@ -512,18 +512,16 @@ private:
 
     // Notify others that our TabContext has been updated.  (At the moment, this
     // sets the appropriate app-id and is-browser flags on our docshell.)
     //
     // You should call this after calling TabContext::SetTabContext().  We also
     // call this during Init().
     void NotifyTabContextUpdated();
 
-    bool UseDirectCompositor();
-
     void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
 
     enum FrameScriptLoading { DONT_LOAD_SCRIPTS, DEFAULT_LOAD_SCRIPTS };
     bool InitTabChildGlobal(FrameScriptLoading aScriptLoading = DEFAULT_LOAD_SCRIPTS);
     bool InitRenderingState();
     void DestroyWindow();
     void SetProcessNameToAppName();
 
--- a/dom/ipc/moz.build
+++ b/dom/ipc/moz.build
@@ -95,17 +95,16 @@ IPDL_SOURCES += [
 ]
 
 FAIL_ON_WARNINGS = True
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
-    '../src/base',
     '../src/geolocation',
     '../src/storage',
     '/chrome',
     '/content/base/src',
     '/content/media/webspeech/synth/ipc',
     '/docshell/base',
     '/dom/base',
     '/dom/bluetooth',
@@ -132,19 +131,14 @@ DEFINES['BIN_SUFFIX'] = '"%s"' % CONFIG[
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gtk2', 'gonk', 'qt'):
     DEFINES['MOZ_ENABLE_FREETYPE'] = True
 
 for var in ('MOZ_PERMISSIONS', 'MOZ_CHILD_PERMISSIONS'):
     if CONFIG[var]:
         DEFINES[var] = True
 
-if CONFIG['ENABLE_TESTS']:
-    LOCAL_INCLUDES += [
-      'ipc/glue',
-    ]
-
 JAR_MANIFESTS += ['jar.mn']
 
 MOCHITEST_CHROME_MANIFESTS += ['tests/chrome.ini']
 MOCHITEST_MANIFESTS += ['tests/mochitest.ini']
 
 CXXFLAGS += CONFIG['TK_CFLAGS']
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -1799,56 +1799,64 @@ MediaManager::OnNavigation(uint64_t aWin
   }
   listeners->Clear();
 
   RemoveWindowID(aWindowID);
   // listeners has been deleted
 }
 
 void
+MediaManager::RemoveWindowID(uint64_t aWindowId)
+{
+  mActiveWindows.Remove(aWindowId);
+
+  // get outer windowID
+  nsPIDOMWindow *window = static_cast<nsPIDOMWindow*>
+    (nsGlobalWindow::GetInnerWindowWithId(aWindowId));
+  if (!window) {
+    LOG(("No inner window for %llu", aWindowId));
+    return;
+  }
+
+  nsPIDOMWindow *outer = window->GetOuterWindow();
+  if (!outer) {
+    LOG(("No outer window for inner %llu", aWindowId));
+    return;
+  }
+
+  uint64_t outerID = outer->WindowID();
+
+  // Notify the UI that this window no longer has gUM active
+  char windowBuffer[32];
+  PR_snprintf(windowBuffer, sizeof(windowBuffer), "%llu", outerID);
+  nsString data = NS_ConvertUTF8toUTF16(windowBuffer);
+
+  nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
+  obs->NotifyObservers(nullptr, "recording-window-ended", data.get());
+  LOG(("Sent recording-window-ended for window %llu (outer %llu)",
+       aWindowId, outerID));
+}
+
+void
 MediaManager::RemoveFromWindowList(uint64_t aWindowID,
   GetUserMediaCallbackMediaStreamListener *aListener)
 {
   NS_ASSERTION(NS_IsMainThread(), "RemoveFromWindowList called off main thread");
 
   // This is defined as safe on an inactive GUMCMSListener
   aListener->Remove(); // really queues the remove
 
   StreamListeners* listeners = GetWindowListeners(aWindowID);
   if (!listeners) {
     return;
   }
   listeners->RemoveElement(aListener);
   if (listeners->Length() == 0) {
     RemoveWindowID(aWindowID);
     // listeners has been deleted here
-
-    // get outer windowID
-    nsPIDOMWindow *window = static_cast<nsPIDOMWindow*>
-      (nsGlobalWindow::GetInnerWindowWithId(aWindowID));
-    if (window) {
-      nsPIDOMWindow *outer = window->GetOuterWindow();
-      if (outer) {
-        uint64_t outerID = outer->WindowID();
-
-        // Notify the UI that this window no longer has gUM active
-        char windowBuffer[32];
-        PR_snprintf(windowBuffer, sizeof(windowBuffer), "%llu", outerID);
-        nsString data = NS_ConvertUTF8toUTF16(windowBuffer);
-
-        nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
-        obs->NotifyObservers(nullptr, "recording-window-ended", data.get());
-        LOG(("Sent recording-window-ended for window %llu (outer %llu)",
-             aWindowID, outerID));
-      } else {
-        LOG(("No outer window for inner %llu", aWindowID));
-      }
-    } else {
-      LOG(("No inner window for %llu", aWindowID));
-    }
   }
 }
 
 void
 MediaManager::GetPref(nsIPrefBranch *aBranch, const char *aPref,
                       const char *aData, int32_t *aVal)
 {
   int32_t temp;
@@ -1987,23 +1995,33 @@ MediaManager::Observe(nsISupports* aSubj
       return NS_OK;
     }
     mActiveCallbacks.Remove(key);
     runnable->Denied(errorMessage);
     return NS_OK;
 
   } else if (!strcmp(aTopic, "getUserMedia:revoke")) {
     nsresult rv;
-    uint64_t windowID = nsString(aData).ToInteger64(&rv);
-    MOZ_ASSERT(NS_SUCCEEDED(rv));
-    if (NS_SUCCEEDED(rv)) {
-      LOG(("Revoking MediaCapture access for window %llu",windowID));
-      OnNavigation(windowID);
+    // may be windowid or screen:windowid
+    nsDependentString data(aData);
+    if (Substring(data, 0, strlen("screen:")).EqualsLiteral("screen:")) {
+      uint64_t windowID = PromiseFlatString(Substring(data, strlen("screen:"))).ToInteger64(&rv);
+      MOZ_ASSERT(NS_SUCCEEDED(rv));
+      if (NS_SUCCEEDED(rv)) {
+        LOG(("Revoking Screeen/windowCapture access for window %llu", windowID));
+        StopScreensharing(windowID);
+      }
+    } else {
+      uint64_t windowID = nsString(aData).ToInteger64(&rv);
+      MOZ_ASSERT(NS_SUCCEEDED(rv));
+      if (NS_SUCCEEDED(rv)) {
+        LOG(("Revoking MediaCapture access for window %llu", windowID));
+        OnNavigation(windowID);
+      }
     }
-
     return NS_OK;
   }
 #ifdef MOZ_WIDGET_GONK
   else if (!strcmp(aTopic, "phone-state-changed")) {
     nsString state(aData);
     nsresult rv;
     uint32_t phoneState = state.ToInteger(&rv);
 
@@ -2143,16 +2161,77 @@ MediaManager::MediaCaptureWindowStateInt
 
         MediaCaptureWindowStateInternal(win, aVideo, aAudio, aScreenShare, aWindowShare);
       }
     }
   }
   return NS_OK;
 }
 
+// XXX abstract out the iteration over all children and provide a function pointer and data ptr
+
+void
+MediaManager::StopScreensharing(uint64_t aWindowID)
+{
+  // We need to stop window/screensharing for all streams in all innerwindows that
+  // correspond to that outerwindow.
+
+  nsPIDOMWindow *window = static_cast<nsPIDOMWindow*>
+      (nsGlobalWindow::GetInnerWindowWithId(aWindowID));
+  if (!window) {
+    return;
+  }
+  StopScreensharing(window);
+}
+
+void
+MediaManager::StopScreensharing(nsPIDOMWindow *aWindow)
+{
+  // We need to stop window/screensharing for all streams in all innerwindows that
+  // correspond to that outerwindow.
+
+  // Iterate the docshell tree to find all the child windows, find
+  // all the listeners for each one, and tell them to stop
+  // window/screensharing
+  nsCOMPtr<nsPIDOMWindow> piWin = do_QueryInterface(aWindow);
+  if (piWin) {
+    if (piWin->IsInnerWindow() || piWin->GetCurrentInnerWindow()) {
+      uint64_t windowID;
+      if (piWin->IsInnerWindow()) {
+        windowID = piWin->WindowID();
+      } else {
+        windowID = piWin->GetCurrentInnerWindow()->WindowID();
+      }
+      StreamListeners* listeners = GetActiveWindows()->Get(windowID);
+      if (listeners) {
+        uint32_t length = listeners->Length();
+        for (uint32_t i = 0; i < length; ++i) {
+          listeners->ElementAt(i)->StopScreenWindowSharing();
+        }
+      }
+    }
+
+    // iterate any children of *this* window (iframes, etc)
+    nsCOMPtr<nsIDocShell> docShell = piWin->GetDocShell();
+    if (docShell) {
+      int32_t i, count;
+      docShell->GetChildCount(&count);
+      for (i = 0; i < count; ++i) {
+        nsCOMPtr<nsIDocShellTreeItem> item;
+        docShell->GetChildAt(i, getter_AddRefs(item));
+        nsCOMPtr<nsPIDOMWindow> win = item ? item->GetWindow() : nullptr;
+
+        if (win) {
+          StopScreensharing(win);
+        }
+      }
+    }
+  }
+}
+
 void
 MediaManager::StopMediaStreams()
 {
   nsCOMPtr<nsISupportsArray> array;
   GetActiveMediaCaptureWindows(getter_AddRefs(array));
   uint32_t len;
   array->Count(&len);
   for (uint32_t i = 0; i < len; i++) {
@@ -2177,16 +2256,36 @@ GetUserMediaCallbackMediaStreamListener:
   // source stream info.
   runnable = new MediaOperationRunnable(MEDIA_STOP,
                                         this, nullptr, nullptr,
                                         mAudioSource, mVideoSource,
                                         mFinished, mWindowID, nullptr);
   mMediaThread->Dispatch(runnable, NS_DISPATCH_NORMAL);
 }
 
+// Doesn't kill audio
+// XXX refactor to combine with Invalidate()?
+void
+GetUserMediaCallbackMediaStreamListener::StopScreenWindowSharing()
+{
+  NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
+  if (mVideoSource && !mStopped &&
+      (mVideoSource->GetMediaSource() == MediaSourceType::Screen ||
+       mVideoSource->GetMediaSource() == MediaSourceType::Window)) {
+    // Stop the whole stream if there's no audio; just the video track if we have both
+    nsRefPtr<MediaOperationRunnable> runnable(
+      new MediaOperationRunnable(mAudioSource ? MEDIA_STOP_TRACK : MEDIA_STOP,
+                                 this, nullptr, nullptr,
+                                 nullptr, mVideoSource,
+                                 mFinished, mWindowID, nullptr));
+    mMediaThread->Dispatch(runnable, NS_DISPATCH_NORMAL);
+  }
+}
+
+
 // Called from the MediaStreamGraph thread
 void
 GetUserMediaCallbackMediaStreamListener::NotifyFinished(MediaStreamGraph* aGraph)
 {
   mFinished = true;
   Invalidate(); // we know it's been activated
   NS_DispatchToMainThread(new GetUserMediaListenerRemove(mWindowID, this));
 }
@@ -2237,16 +2336,19 @@ GetUserMediaNotificationEvent::Run()
     stream->OnTracksAvailable(mOnTracksAvailableCallback.forget());
     break;
   case STOPPING:
     msg = NS_LITERAL_STRING("shutdown");
     if (mListener) {
       mListener->SetStopped();
     }
     break;
+  case STOPPED_TRACK:
+    msg = NS_LITERAL_STRING("shutdown");
+    break;
   }
 
   nsCOMPtr<nsPIDOMWindow> window = nsGlobalWindow::GetInnerWindowWithId(mWindowID);
   NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
 
   return MediaManager::NotifyRecordingStatusChange(window, msg, mIsAudio, mIsVideo);
 }
 
--- a/dom/media/MediaManager.h
+++ b/dom/media/MediaManager.h
@@ -94,16 +94,18 @@ public:
   {
     NS_ASSERTION(mStream,"Getting stream from never-activated GUMCMSListener");
     if (!mStream) {
       return nullptr;
     }
     return mStream->AsSourceStream();
   }
 
+  void StopScreenWindowSharing();
+
   // mVideo/AudioSource are set by Activate(), so we assume they're capturing
   // if set and represent a real capture device.
   bool CapturingVideo()
   {
     NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
     return mVideoSource && !mStopped &&
            mVideoSource->GetMediaSource() == MediaSourceType::Camera &&
            (!mVideoSource->IsFake() ||
@@ -114,23 +116,23 @@ public:
     NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
     return mAudioSource && !mStopped &&
            (!mAudioSource->IsFake() ||
             Preferences::GetBool("media.navigator.permission.fake"));
   }
   bool CapturingScreen()
   {
     NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
-    return mVideoSource && !mStopped &&
+    return mVideoSource && !mStopped && !mVideoSource->IsAvailable() &&
            mVideoSource->GetMediaSource() == MediaSourceType::Screen;
   }
   bool CapturingWindow()
   {
     NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
-    return mVideoSource && !mStopped &&
+    return mVideoSource && !mStopped && !mVideoSource->IsAvailable() &&
            mVideoSource->GetMediaSource() == MediaSourceType::Window;
   }
 
   void SetStopped()
   {
     mStopped = true;
   }
 
@@ -241,17 +243,18 @@ private:
   bool mRemoved;
 };
 
 class GetUserMediaNotificationEvent: public nsRunnable
 {
   public:
     enum GetUserMediaStatus {
       STARTING,
-      STOPPING
+      STOPPING,
+      STOPPED_TRACK
     };
     GetUserMediaNotificationEvent(GetUserMediaCallbackMediaStreamListener* aListener,
                                   GetUserMediaStatus aStatus,
                                   bool aIsAudio, bool aIsVideo, uint64_t aWindowID)
     : mListener(aListener) , mStatus(aStatus) , mIsAudio(aIsAudio)
     , mIsVideo(aIsVideo), mWindowID(aWindowID) {}
 
     GetUserMediaNotificationEvent(GetUserMediaStatus aStatus,
@@ -278,16 +281,17 @@ class GetUserMediaNotificationEvent: pub
     bool mIsVideo;
     uint64_t mWindowID;
     nsRefPtr<nsIDOMGetUserMediaErrorCallback> mError;
 };
 
 typedef enum {
   MEDIA_START,
   MEDIA_STOP,
+  MEDIA_STOP_TRACK,
   MEDIA_DIRECT_LISTENERS
 } MediaOperation;
 
 class MediaManager;
 class GetUserMediaRunnable;
 
 /**
  * Send an error back to content. The error is the form a string.
@@ -421,33 +425,37 @@ public:
                                               mWindowID, mError.forget());
           // event must always be released on mainthread due to the JS callbacks
           // in the TracksAvailableCallback
           NS_DispatchToMainThread(event);
         }
         break;
 
       case MEDIA_STOP:
+      case MEDIA_STOP_TRACK:
         {
           NS_ASSERTION(!NS_IsMainThread(), "Never call on main thread");
           if (mAudioSource) {
             mAudioSource->Stop(source, kAudioTrack);
             mAudioSource->Deallocate();
           }
           if (mVideoSource) {
             mVideoSource->Stop(source, kVideoTrack);
             mVideoSource->Deallocate();
           }
           // Do this after stopping all tracks with EndTrack()
           if (mBool) {
             source->Finish();
           }
+
           nsIRunnable *event =
             new GetUserMediaNotificationEvent(mListener,
-                                              GetUserMediaNotificationEvent::STOPPING,
+                                              mType == MEDIA_STOP ?
+                                              GetUserMediaNotificationEvent::STOPPING :
+                                              GetUserMediaNotificationEvent::STOPPED_TRACK,
                                               mAudioSource != nullptr,
                                               mVideoSource != nullptr,
                                               mWindowID);
           // event must always be released on mainthread due to the JS callbacks
           // in the TracksAvailableCallback
           NS_DispatchToMainThread(event);
         }
         break;
@@ -544,19 +552,17 @@ public:
   NS_DECL_NSIMEDIAMANAGERSERVICE
 
   MediaEngine* GetBackend(uint64_t aWindowId = 0);
   StreamListeners *GetWindowListeners(uint64_t aWindowId) {
     NS_ASSERTION(NS_IsMainThread(), "Only access windowlist on main thread");
 
     return mActiveWindows.Get(aWindowId);
   }
-  void RemoveWindowID(uint64_t aWindowId) {
-    mActiveWindows.Remove(aWindowId);
-  }
+  void RemoveWindowID(uint64_t aWindowId);
   bool IsWindowStillActive(uint64_t aWindowId) {
     return !!GetWindowListeners(aWindowId);
   }
   // Note: also calls aListener->Remove(), even if inactive
   void RemoveFromWindowList(uint64_t aWindowID,
     GetUserMediaCallbackMediaStreamListener *aListener);
 
   nsresult GetUserMedia(bool aPrivileged,
@@ -590,16 +596,19 @@ private:
   MediaManager();
 
   ~MediaManager() {}
 
   nsresult MediaCaptureWindowStateInternal(nsIDOMWindow* aWindow, bool* aVideo,
                                            bool* aAudio, bool *aScreenShare,
                                            bool* aWindowShare);
 
+  void StopScreensharing(uint64_t aWindowID);
+  void StopScreensharing(nsPIDOMWindow *aWindow);
+
   void StopMediaStreams();
 
   // ONLY access from MainThread so we don't need to lock
   WindowTable mActiveWindows;
   nsRefPtrHashtable<nsStringHashKey, GetUserMediaRunnable> mActiveCallbacks;
   nsClassHashtable<nsUint64HashKey, nsTArray<nsString>> mCallIds;
   // Always exists
   nsCOMPtr<nsIThread> mMediaThread;
--- a/dom/plugins/base/android/moz.build
+++ b/dom/plugins/base/android/moz.build
@@ -25,17 +25,16 @@ SOURCES += [
 
 FAIL_ON_WARNINGS = True
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '/dom/plugins/base',
-    '/dom/plugins/base/android/include',
     '/gfx/gl',
     '/widget/android',
     '/widget/xpwidgets',
 ]
 
 DEFINES['MOZ_APP_NAME'] = '"%s"' % CONFIG['MOZ_APP_NAME']
 
 CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
--- a/dom/plugins/base/moz.build
+++ b/dom/plugins/base/moz.build
@@ -94,18 +94,16 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'andr
     # Therefore, enable FAIL_ON_WARNINGS only on non-Android platforms.
     FAIL_ON_WARNINGS = True
 
 MSVC_ENABLE_PGO = True
 
 LOCAL_INCLUDES += [
     '/content/base/src',
     '/dom/base',
-    '/gfx/skia/include/config',
-    '/gfx/skia/include/core',
     '/layout/generic',
     '/layout/xul',
     '/widget/android',
     '/widget/xpwidgets',
     '/xpcom/base',
 ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
--- a/dom/plugins/base/nsPluginInstanceOwner.h
+++ b/dom/plugins/base/nsPluginInstanceOwner.h
@@ -39,20 +39,20 @@ struct MozPluginParameter;
 class gfxXlibSurface;
 #ifdef MOZ_WIDGET_QT
 #include "gfxQtNativeRenderer.h"
 #else
 #include "gfxXlibNativeRenderer.h"
 #endif
 #endif
 
-class nsPluginInstanceOwner : public nsIPluginInstanceOwner,
-                              public nsIDOMEventListener,
-                              public nsIPrivacyTransitionObserver,
-                              public nsSupportsWeakReference
+class nsPluginInstanceOwner MOZ_FINAL : public nsIPluginInstanceOwner,
+                                        public nsIDOMEventListener,
+                                        public nsIPrivacyTransitionObserver,
+                                        public nsSupportsWeakReference
 {
 public:
   nsPluginInstanceOwner();
   
   NS_DECL_ISUPPORTS
   NS_DECL_NSIPLUGININSTANCEOWNER
   NS_DECL_NSIPRIVACYTRANSITIONOBSERVER
   
--- a/dom/src/geolocation/nsGeolocation.cpp
+++ b/dom/src/geolocation/nsGeolocation.cpp
@@ -49,17 +49,17 @@ class nsIPrincipal;
 
 // The settings key.
 #define GEO_SETINGS_ENABLED          "geolocation.enabled"
 
 using mozilla::unused;          // <snicker>
 using namespace mozilla;
 using namespace mozilla::dom;
 
-class nsGeolocationRequest
+class nsGeolocationRequest MOZ_FINAL
  : public nsIContentPermissionRequest
  , public nsITimerCallback
  , public nsIGeolocationUpdate
 {
  public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_NSICONTENTPERMISSIONREQUEST
   NS_DECL_NSITIMERCALLBACK
--- a/dom/tests/mochitest/general/test_interfaces.html
+++ b/dom/tests/mochitest/general/test_interfaces.html
@@ -117,16 +117,18 @@ var interfaceNamesInGlobalScope =
     {name: "AlarmsManager", pref: "dom.mozAlarms.enabled"},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "AnalyserNode",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "AnimationEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "Animation", pref: "dom.animations-api.core.enabled"},
 // IMPORTANT: Do not change this list without review from a DOM peer!
+    {name: "AnimationEffect", pref: "dom.animations-api.core.enabled"},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "AnimationPlayer", pref: "dom.animations-api.core.enabled"},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "AnimationTimeline", pref: "dom.animations-api.core.enabled"},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "Attr",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "Audio",
 // IMPORTANT: Do not change this list without review from a DOM peer!
--- a/dom/webidl/Animation.webidl
+++ b/dom/webidl/Animation.webidl
@@ -7,9 +7,12 @@
  * http://dev.w3.org/fxtf/web-animations/#the-animation-interface
  *
  * Copyright © 2014 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
  * liability, trademark and document use rules apply.
  */
 
 [Pref="dom.animations-api.core.enabled"]
 interface Animation {
+  // FIXME: |effect| should have type (AnimationEffect or EffectCallback)?
+  // but we haven't implemented EffectCallback yet.
+  [Cached,Pure] readonly attribute AnimationEffect? effect;
 };
new file mode 100644
--- /dev/null
+++ b/dom/webidl/AnimationEffect.webidl
@@ -0,0 +1,16 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * The origin of this IDL file is
+ * http://dev.w3.org/fxtf/web-animations/#the-animationeffect-interface
+ *
+ * Copyright © 2014 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
+ * liability, trademark and document use rules apply.
+ */
+
+[Pref="dom.animations-api.core.enabled"]
+interface AnimationEffect {
+  readonly attribute DOMString name;
+};
--- a/dom/webidl/AnimationPlayer.webidl
+++ b/dom/webidl/AnimationPlayer.webidl
@@ -13,8 +13,13 @@
 [Pref="dom.animations-api.core.enabled"]
 interface AnimationPlayer {
   // Bug 1049975: Per spec, this should be a writeable AnimationNode? member
   [Pure] readonly attribute Animation? source;
   readonly attribute AnimationTimeline timeline;
   [Pure] readonly attribute double startTime;
   readonly attribute double currentTime;
 };
+
+// Non-standard extensions
+partial interface AnimationPlayer {
+  [ChromeOnly] readonly attribute boolean isRunningOnCompositor;
+};
--- a/dom/webidl/TestInterfaceJS.webidl
+++ b/dom/webidl/TestInterfaceJS.webidl
@@ -32,9 +32,14 @@ interface TestInterfaceJS {
   DOMString getCallerPrincipal();
 
   DOMString convertSVS(ScalarValueString svs);
 
   (TestInterfaceJS or long) pingPongUnion((TestInterfaceJS or long) something);
   (DOMString or TestInterfaceJS?) pingPongUnionContainingNull((TestInterfaceJS? or DOMString) something);
   (TestInterfaceJS or long)? pingPongNullableUnion((TestInterfaceJS or long)? something);
   (Location or TestInterfaceJS) returnBadUnion();
+
+  [Cached, Pure]
+  readonly attribute short cachedAttr;
+  void setCachedAttr(short n);
+  void clearCachedAttrCache();
 };
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -17,16 +17,17 @@ PREPROCESSED_WEBIDL_FILES = [
 
 WEBIDL_FILES = [
     'AbstractWorker.webidl',
     'ActivityRequestHandler.webidl',
     'AlarmsManager.webidl',
     'AnalyserNode.webidl',
     'Animatable.webidl',
     'Animation.webidl',
+    'AnimationEffect.webidl',
     'AnimationEvent.webidl',
     'AnimationPlayer.webidl',
     'AnimationTimeline.webidl',
     'AppInfo.webidl',
     'AppNotificationServiceOptions.webidl',
     'Apps.webidl',
     'APZTestData.webidl',
     'ArchiveReader.webidl',
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -3939,20 +3939,18 @@ WorkerPrivate::DoRunLoop(JSContext* aCx)
 
   InitializeGCTimers();
 
   Maybe<JSAutoCompartment> workerCompartment;
 
   for (;;) {
     // Workers lazily create a global object in CompileScriptRunnable. We need
     // to enter the global's compartment as soon as it has been created.
-    if (!workerCompartment) {
-      if (JSObject* global = js::DefaultObjectForContextOrNull(aCx)) {
-        workerCompartment.emplace(aCx, global);
-      }
+    if (!workerCompartment && GlobalScope()) {
+      workerCompartment.emplace(aCx, GlobalScope()->GetGlobalJSObject());
     }
 
     Status currentStatus;
     bool normalRunnablesPending = false;
 
     {
       MutexAutoLock lock(mMutex);
 
--- a/editor/composer/nsEditorSpellCheck.h
+++ b/editor/composer/nsEditorSpellCheck.h
@@ -22,17 +22,17 @@ class nsITextServicesFilter;
 #define NS_EDITORSPELLCHECK_CID                     \
 { /* {75656ad9-bd13-4c5d-939a-ec6351eea0cc} */        \
     0x75656ad9, 0xbd13, 0x4c5d,                       \
     { 0x93, 0x9a, 0xec, 0x63, 0x51, 0xee, 0xa0, 0xcc }\
 }
 
 class DictionaryFetcher;
 
-class nsEditorSpellCheck : public nsIEditorSpellCheck
+class nsEditorSpellCheck MOZ_FINAL : public nsIEditorSpellCheck
 {
   friend class DictionaryFetcher;
 
 public:
   nsEditorSpellCheck();
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(nsEditorSpellCheck)
--- a/editor/libeditor/nsHTMLEditor.h
+++ b/editor/libeditor/nsHTMLEditor.h
@@ -58,25 +58,25 @@ namespace widget {
 struct IMEState;
 } // namespace widget
 } // namespace mozilla
 
 /**
  * The HTML editor implementation.<br>
  * Use to edit HTML document represented as a DOM tree. 
  */
-class nsHTMLEditor : public nsPlaintextEditor,
-                     public nsIHTMLEditor,
-                     public nsIHTMLObjectResizer,
-                     public nsIHTMLAbsPosEditor,
-                     public nsITableEditor,
-                     public nsIHTMLInlineTableEditor,
-                     public nsIEditorStyleSheets,
-                     public nsICSSLoaderObserver,
-                     public nsStubMutationObserver
+class nsHTMLEditor MOZ_FINAL : public nsPlaintextEditor,
+                               public nsIHTMLEditor,
+                               public nsIHTMLObjectResizer,
+                               public nsIHTMLAbsPosEditor,
+                               public nsITableEditor,
+                               public nsIHTMLInlineTableEditor,
+                               public nsIEditorStyleSheets,
+                               public nsICSSLoaderObserver,
+                               public nsStubMutationObserver
 {
   typedef enum {eNoOp, eReplaceParent=1, eInsertParent=2} BlockTransformationType;
 
 public:
 
   enum ResizingRequestID
   {
     kX      = 0,
--- a/editor/txmgr/nsTransactionItem.h
+++ b/editor/txmgr/nsTransactionItem.h
@@ -11,17 +11,17 @@
 #include "nsCycleCollectionParticipant.h"
 #include "nsISupportsImpl.h"
 #include "nscore.h"
 
 class nsITransaction;
 class nsTransactionManager;
 class nsTransactionStack;
 
-class nsTransactionItem
+class nsTransactionItem MOZ_FINAL
 {
   nsCOMArray<nsISupports>  mData;
   nsCOMPtr<nsITransaction> mTransaction;
   nsTransactionStack      *mUndoStack;
   nsTransactionStack      *mRedoStack;
 
 public:
 
--- a/editor/txmgr/nsTransactionManager.h
+++ b/editor/txmgr/nsTransactionManager.h
@@ -18,18 +18,18 @@
 
 class nsITransaction;
 class nsITransactionListener;
 class nsTransactionItem;
 
 /** implementation of a transaction manager object.
  *
  */
-class nsTransactionManager : public nsITransactionManager
-                           , public nsSupportsWeakReference
+class nsTransactionManager MOZ_FINAL : public nsITransactionManager
+                                     , public nsSupportsWeakReference
 {
 private:
 
   int32_t                mMaxTransactionCount;
   nsTransactionStack     mDoStack;
   nsTransactionStack     mUndoStack;
   nsTransactionStack     mRedoStack;
   nsCOMArray<nsITransactionListener> mListeners;
--- a/embedding/browser/nsWebBrowser.h
+++ b/embedding/browser/nsWebBrowser.h
@@ -67,28 +67,28 @@ public:
     nsIID mID;
 };
 
 //  {cda5863a-aa9c-411e-be49-ea0d525ab4b5} - 
 #define NS_WEBBROWSER_CID \
 {0xcda5863a, 0xaa9c, 0x411e, { 0xbe, 0x49, 0xea, 0x0d, 0x52, 0x5a, 0xb4, 0xb5 }}
 
 
-class nsWebBrowser : public nsIWebBrowser,
-                     public nsIWebNavigation,
-                     public nsIWebBrowserSetup,
-                     public nsIDocShellTreeItem,
-                     public nsIBaseWindow,
-                     public nsIScrollable, 
-                     public nsITextScroll, 
-                     public nsIInterfaceRequestor,
-                     public nsIWebBrowserPersist,
-                     public nsIWebBrowserFocus,
-                     public nsIWebProgressListener,
-                     public nsIWebBrowserStream,
+class nsWebBrowser MOZ_FINAL : public nsIWebBrowser,
+                               public nsIWebNavigation,
+                               public nsIWebBrowserSetup,
+                               public nsIDocShellTreeItem,
+                               public nsIBaseWindow,
+                               public nsIScrollable, 
+                               public nsITextScroll, 
+                               public nsIInterfaceRequestor,
+                               public nsIWebBrowserPersist,
+                               public nsIWebBrowserFocus,
+                               public nsIWebProgressListener,
+                               public nsIWebBrowserStream,
                      public nsIWidgetListener,
                      public nsSupportsWeakReference
 {
 friend class nsDocShellTreeOwner;
 public:
     nsWebBrowser();
 
     NS_DECL_ISUPPORTS
--- a/gfx/2d/BasePoint4D.h
+++ b/gfx/2d/BasePoint4D.h
@@ -111,14 +111,16 @@ struct BasePoint4D {
 
   T Length() const {
     return sqrt(x*x + y*y + z*z + w*w);
   }
 
   void Normalize() {
     *this /= Length();
   }
+
+  bool HasPositiveWCoord() { return w > 0; }
 };
 
 }
 }
 
 #endif /* MOZILLA_BASEPOINT4D_H_ */
--- a/gfx/2d/Matrix.cpp
+++ b/gfx/2d/Matrix.cpp
@@ -1,35 +1,38 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "Matrix.h"
 #include "Tools.h"
+#include <algorithm>
 #include <math.h>
 
 #include "mozilla/FloatingPoint.h" // for UnspecifiedNaN
 
+using namespace std;
+
 namespace mozilla {
 namespace gfx {
 
 Matrix
 Matrix::Rotation(Float aAngle)
 {
   Matrix newMatrix;
 
   Float s = sin(aAngle);
   Float c = cos(aAngle);
 
   newMatrix._11 = c;
   newMatrix._12 = s;
   newMatrix._21 = -s;
   newMatrix._22 = c;
-  
+
   return newMatrix;
 }
 
 Rect
 Matrix::TransformBounds(const Rect &aRect) const
 {
   int i;
   Point quad[4];
@@ -99,16 +102,83 @@ Matrix4x4::TransformBounds(const Rect& a
     if (quad[i].y > max_y) {
       max_y = quad[i].y;
     }
   }
 
   return Rect(min_x, min_y, max_x - min_x, max_y - min_y);
 }
 
+Point4D ComputePerspectivePlaneIntercept(const Point4D& aFirst,
+                                         const Point4D& aSecond)
+{
+  // FIXME: See bug 1035611
+  // Since we can't easily deal with points as w=0 (since we divide by w), we
+  // approximate this by finding a point with w just greater than 0. Unfortunately
+  // this is a tradeoff between accuracy and floating point precision.
+
+  // We want to interpolate aFirst and aSecond to find a point as close to
+  // the positive side of the w=0 plane as possible.
+
+  // Since we know what we want the w component to be, we can rearrange the
+  // interpolation equation and solve for t.
+  float w = 0.00001f;
+  float t = (w - aFirst.w) / (aSecond.w - aFirst.w);
+
+  // Use t to find the remainder of the components
+  return aFirst + (aSecond - aFirst) * t;
+}
+
+Rect Matrix4x4::ProjectRectBounds(const Rect& aRect) const
+{
+  Point4D points[4];
+
+  points[0] = ProjectPoint(aRect.TopLeft());
+  points[1] = ProjectPoint(aRect.TopRight());
+  points[2] = ProjectPoint(aRect.BottomLeft());
+  points[3] = ProjectPoint(aRect.BottomRight());
+
+  Float min_x = std::numeric_limits<Float>::max();
+  Float min_y = std::numeric_limits<Float>::max();
+  Float max_x = -std::numeric_limits<Float>::max();
+  Float max_y = -std::numeric_limits<Float>::max();
+
+  bool foundPoint = false;
+  for (int i=0; i<4; i++) {
+    // Only use points that exist above the w=0 plane
+    if (points[i].HasPositiveWCoord()) {
+      foundPoint = true;
+      Point point2d = points[i].As2DPoint();
+      min_x = min<Float>(point2d.x, min_x);
+      max_x = max<Float>(point2d.x, max_x);
+      min_y = min<Float>(point2d.y, min_y);
+      max_y = max<Float>(point2d.y, max_y);
+    }
+
+    int next = (i == 3) ? 0 : i + 1;
+    if (points[i].HasPositiveWCoord() != points[next].HasPositiveWCoord()) {
+      // If the line between two points crosses the w=0 plane, then interpolate a point
+      // as close to the w=0 plane as possible and use that instead.
+      Point4D intercept = ComputePerspectivePlaneIntercept(points[i], points[next]);
+
+      Point point2d = intercept.As2DPoint();
+      min_x = min<Float>(point2d.x, min_x);
+      max_x = max<Float>(point2d.x, max_x);
+      min_y = min<Float>(point2d.y, min_y);
+      max_y = max<Float>(point2d.y, max_y);
+    }
+  }
+
+  if (!foundPoint) {
+    return Rect(0, 0, 0, 0);
+  }
+
+  return Rect(min_x, min_y, max_x - min_x, max_y - min_y);
+}
+
 bool
 Matrix4x4::Invert()
 {
   Float det = Determinant();
   if (!det) {
     return false;
   }
 
--- a/gfx/2d/Matrix.h
+++ b/gfx/2d/Matrix.h
@@ -370,16 +370,29 @@ public:
     _13 = 0.0f;
     _23 = 0.0f;
     _33 = 1.0f;
     _43 = 0.0f;
     _34 = 0.0f;
     return *this;
   }
 
+  Point4D ProjectPoint(const Point& aPoint) const {
+    // Find a value for z that will transform to 0.
+
+    // The transformed value of z is computed as:
+    // z' = aPoint.x * _13 + aPoint.y * _23 + z * _33 + _43;
+
+    // Solving for z when z' = 0 gives us:
+    float z = -(aPoint.x * _13 + aPoint.y * _23 + _43) / _33;
+
+    // Compute the transformed point
+    return *this * Point4D(aPoint.x, aPoint.y, z, 1);
+  }
+
   static Matrix4x4 From2D(const Matrix &aMatrix) {
     Matrix4x4 matrix;
     matrix._11 = aMatrix._11;
     matrix._12 = aMatrix._12;
     matrix._21 = aMatrix._21;
     matrix._22 = aMatrix._22;
     matrix._41 = aMatrix._31;
     matrix._42 = aMatrix._32;
@@ -447,16 +460,18 @@ public:
     _41 += aX * _11 + aY * _21 + aZ * _31;
     _42 += aX * _12 + aY * _22 + aZ * _32;
     _43 += aX * _13 + aY * _23 + aZ * _33;
     _44 += aX * _14 + aY * _24 + aZ * _34;
 
     return *this;
   }
 
+  Rect ProjectRectBounds(const Rect& aRect) const;
+
   Matrix4x4 &PostTranslate(Float aX, Float aY, Float aZ)
   {
     _11 += _14 * aX;
     _21 += _24 * aX;
     _31 += _34 * aX;
     _41 += _44 * aX;
     _12 += _14 * aY;
     _22 += _24 * aY;
@@ -664,16 +679,45 @@ public:
          Float a41, Float a42, Float a43, Float a44,
          Float a51, Float a52, Float a53, Float a54)
     : _11(a11), _12(a12), _13(a13), _14(a14)
     , _21(a21), _22(a22), _23(a23), _24(a24)
     , _31(a31), _32(a32), _33(a33), _34(a34)
     , _41(a41), _42(a42), _43(a43), _44(a44)
     , _51(a51), _52(a52), _53(a53), _54(a54)
   {}
+
+  Matrix5x4 operator*(const Matrix5x4 &aMatrix) const
+  {
+    Matrix5x4 resultMatrix;
+
+    resultMatrix._11 = this->_11 * aMatrix._11 + this->_12 * aMatrix._21 + this->_13 * aMatrix._31 + this->_14 * aMatrix._41;
+    resultMatrix._12 = this->_11 * aMatrix._12 + this->_12 * aMatrix._22 + this->_13 * aMatrix._32 + this->_14 * aMatrix._42;
+    resultMatrix._13 = this->_11 * aMatrix._13 + this->_12 * aMatrix._23 + this->_13 * aMatrix._33 + this->_14 * aMatrix._43;
+    resultMatrix._14 = this->_11 * aMatrix._14 + this->_12 * aMatrix._24 + this->_13 * aMatrix._34 + this->_14 * aMatrix._44;
+    resultMatrix._21 = this->_21 * aMatrix._11 + this->_22 * aMatrix._21 + this->_23 * aMatrix._31 + this->_24 * aMatrix._41;
+    resultMatrix._22 = this->_21 * aMatrix._12 + this->_22 * aMatrix._22 + this->_23 * aMatrix._32 + this->_24 * aMatrix._42;
+    resultMatrix._23 = this->_21 * aMatrix._13 + this->_22 * aMatrix._23 + this->_23 * aMatrix._33 + this->_24 * aMatrix._43;
+    resultMatrix._24 = this->_21 * aMatrix._14 + this->_22 * aMatrix._24 + this->_23 * aMatrix._34 + this->_24 * aMatrix._44;
+    resultMatrix._31 = this->_31 * aMatrix._11 + this->_32 * aMatrix._21 + this->_33 * aMatrix._31 + this->_34 * aMatrix._41;
+    resultMatrix._32 = this->_31 * aMatrix._12 + this->_32 * aMatrix._22 + this->_33 * aMatrix._32 + this->_34 * aMatrix._42;
+    resultMatrix._33 = this->_31 * aMatrix._13 + this->_32 * aMatrix._23 + this->_33 * aMatrix._33 + this->_34 * aMatrix._43;
+    resultMatrix._34 = this->_31 * aMatrix._14 + this->_32 * aMatrix._24 + this->_33 * aMatrix._34 + this->_34 * aMatrix._44;
+    resultMatrix._41 = this->_41 * aMatrix._11 + this->_42 * aMatrix._21 + this->_43 * aMatrix._31 + this->_44 * aMatrix._41;
+    resultMatrix._42 = this->_41 * aMatrix._12 + this->_42 * aMatrix._22 + this->_43 * aMatrix._32 + this->_44 * aMatrix._42;
+    resultMatrix._43 = this->_41 * aMatrix._13 + this->_42 * aMatrix._23 + this->_43 * aMatrix._33 + this->_44 * aMatrix._43;
+    resultMatrix._44 = this->_41 * aMatrix._14 + this->_42 * aMatrix._24 + this->_43 * aMatrix._34 + this->_44 * aMatrix._44;
+    resultMatrix._51 = this->_51 * aMatrix._11 + this->_52 * aMatrix._21 + this->_53 * aMatrix._31 + this->_54 * aMatrix._41 + aMatrix._51;
+    resultMatrix._52 = this->_51 * aMatrix._12 + this->_52 * aMatrix._22 + this->_53 * aMatrix._32 + this->_54 * aMatrix._42 + aMatrix._52;
+    resultMatrix._53 = this->_51 * aMatrix._13 + this->_52 * aMatrix._23 + this->_53 * aMatrix._33 + this->_54 * aMatrix._43 + aMatrix._53;
+    resultMatrix._54 = this->_51 * aMatrix._14 + this->_52 * aMatrix._24 + this->_53 * aMatrix._34 + this->_54 * aMatrix._44 + aMatrix._54;
+
+    return resultMatrix;
+  }
+
   Float _11, _12, _13, _14;
   Float _21, _22, _23, _24;
   Float _31, _32, _33, _34;
   Float _41, _42, _43, _44;
   Float _51, _52, _53, _54;
 };
 
 }
--- a/gfx/2d/Point.h
+++ b/gfx/2d/Point.h
@@ -148,16 +148,20 @@ struct Point4DTyped :
 
   static Point4DTyped<units> FromUnknownPoint(const Point4DTyped<UnknownUnits>& aPoint) {
     return Point4DTyped<units>(aPoint.x, aPoint.y, aPoint.z, aPoint.w);
   }
 
   Point4DTyped<UnknownUnits> ToUnknownPoint() const {
     return Point4DTyped<UnknownUnits>(this->x, this->y, this->z, this->w);
   }
+
+  PointTyped<units> As2DPoint() {
+    return PointTyped<units>(this->x / this->w, this->y / this->w);
+  }
 };
 typedef Point4DTyped<UnknownUnits> Point4D;
 
 template<class units>
 struct IntSizeTyped :
   public BaseSize< int32_t, IntSizeTyped<units> >,
   public units {
   static_assert(IsPixel<units>::value,
--- a/gfx/gl/GLTextureImage.h
+++ b/gfx/gl/GLTextureImage.h
@@ -307,17 +307,17 @@ protected:
     nsIntPoint mUpdateOffset;
 };
 
 /**
  * A container class that complements many sub TextureImages into a big TextureImage.
  * Aims to behave just like the real thing.
  */
 
-class TiledTextureImage
+class TiledTextureImage MOZ_FINAL
     : public TextureImage
 {
 public:
     TiledTextureImage(GLContext* aGL,
                       gfx::IntSize aSize,
                       TextureImage::ContentType,
                       TextureImage::Flags aFlags = TextureImage::NoFlags,
                       TextureImage::ImageFormat aImageFormat = gfxImageFormat::Unknown);
--- a/gfx/gl/TextureImageEGL.h
+++ b/gfx/gl/TextureImageEGL.h
@@ -6,17 +6,17 @@
 #ifndef TEXTUREIMAGEEGL_H_
 #define TEXTUREIMAGEEGL_H_
 
 #include "GLTextureImage.h"
 
 namespace mozilla {
 namespace gl {
 
-class TextureImageEGL
+class TextureImageEGL MOZ_FINAL
     : public TextureImage
 {
 public:
     TextureImageEGL(GLuint aTexture,
                     const nsIntSize& aSize,
                     GLenum aWrapMode,
                     ContentType aContentType,
                     GLContext* aContext,
--- a/gfx/layers/ImageContainer.h
+++ b/gfx/layers/ImageContainer.h
@@ -860,18 +860,18 @@ protected:
   nsRefPtr<BufferRecycleBin> mRecycleBin;
 };
 
 /**
  * Currently, the data in a CairoImage surface is treated as being in the
  * device output color space. This class is very simple as all backends
  * have to know about how to deal with drawing a cairo image.
  */
-class CairoImage : public Image,
-                   public ISharedImage {
+class CairoImage MOZ_FINAL : public Image,
+                             public ISharedImage {
 public:
   struct Data {
     gfx::IntSize mSize;
     RefPtr<gfx::SourceSurface> mSourceSurface;
   };
 
   /**
    * This can only be called on the main thread. It may add a reference
--- a/gfx/layers/apz/src/APZCTreeManager.cpp
+++ b/gfx/layers/apz/src/APZCTreeManager.cpp
@@ -897,20 +897,16 @@ APZCTreeManager::DispatchScroll(AsyncPan
   }
 
   next = aOverscrollHandoffChain.GetApzcAtIndex(aOverscrollHandoffChainIndex);
 
   if (next == nullptr || next->IsDestroyed()) {
     return false;
   }
 
-  if (next->GetGuid().mLayersId != aPrev->GetGuid().mLayersId) {
-    NS_WARNING("Handing off scroll across a layer tree boundary; may need to revise approach to bug 1031067");
-  }
-
   // Convert the start and end points from |aPrev|'s coordinate space to
   // |next|'s coordinate space. Since |aPrev| may be the same as |next|
   // (if |aPrev| is the APZC that is initiating the scroll and there is no
   // scroll grabbing to grab the scroll from it), don't bother doing the
   // transformations in that case.
   if (next != aPrev) {
     TransformDisplacement(this, aPrev, next, aStartPoint, aEndPoint);
   }
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -1311,18 +1311,24 @@ nsEventStatus AsyncPanZoomController::On
   {
     ReentrantMonitorAutoEnter lock(mMonitor);
 
     // We can get into a situation where we are overscrolled at the end of a
     // pinch if we go into overscroll with a two-finger pan, and then turn
     // that into a pinch by increasing the span sufficiently. In such a case,
     // there is no snap-back animation to get us out of overscroll, so we need
     // to get out of it somehow.
-    mX.ClearOverscroll();
-    mY.ClearOverscroll();
+    // Moreover, in cases of scroll handoff, the overscroll can be on an APZC
+    // further up in the handoff chain rather than on the current APZC, so
+    // we need to clear overscroll along the entire handoff chain.
+    if (HasReadyTouchBlock()) {
+      CurrentTouchBlock()->GetOverscrollHandoffChain()->ClearOverscroll();
+    } else {
+      ClearOverscroll();
+    }
 
     ScheduleComposite();
     RequestContentRepaint();
     UpdateSharedCompositorFrameMetrics();
   }
 
   return nsEventStatus_eConsumeNoDefault;
 }
@@ -1892,24 +1898,29 @@ void AsyncPanZoomController::CancelAnima
   // Since there is no animation in progress now the axes should
   // have no velocity either.
   mX.SetVelocity(0);
   mY.SetVelocity(0);
   // Setting the state to nothing and cancelling the animation can
   // preempt normal mechanisms for relieving overscroll, so we need to clear
   // overscroll here.
   if (mX.IsOverscrolled() || mY.IsOverscrolled()) {
-    mX.ClearOverscroll();
-    mY.ClearOverscroll();
+    ClearOverscroll();
     RequestContentRepaint();
     ScheduleComposite();
     UpdateSharedCompositorFrameMetrics();
   }
 }
 
+void AsyncPanZoomController::ClearOverscroll() {
+  ReentrantMonitorAutoEnter lock(mMonitor);
+  mX.ClearOverscroll();
+  mY.ClearOverscroll();
+}
+
 void AsyncPanZoomController::SetCompositorParent(CompositorParent* aCompositorParent) {
   mCompositorParent = aCompositorParent;
 }
 
 void AsyncPanZoomController::ShareFrameMetricsAcrossProcesses() {
   mSharingFrameMetricsAcrossProcesses = true;
 }
 
--- a/gfx/layers/apz/src/AsyncPanZoomController.h
+++ b/gfx/layers/apz/src/AsyncPanZoomController.h
@@ -283,23 +283,26 @@ public:
   /**
    * Returns true if this APZC instance is for the layer identified by the guid.
    */
   bool Matches(const ScrollableLayerGuid& aGuid);
 
   void StartAnimation(AsyncPanZoomAnimation* aAnimation);
 
   /**
-   * Cancels any currently running animation. Note that all this does is set the
-   * state of the AsyncPanZoomController back to NOTHING, but it is the
-   * animation's responsibility to check this before advancing.
+   * Cancels any currently running animation.
    */
   void CancelAnimation();
 
   /**
+   * Clear any overscroll on this APZC.
+   */
+  void ClearOverscroll();
+
+  /**
    * Returns allowed touch behavior for the given point on the scrollable layer.
    * Internally performs a kind of hit testing based on the regions constructed
    * on the main thread and attached to the current scrollable layer. Each of such regions
    * contains info about allowed touch behavior. If regions info isn't enough it returns
    * UNKNOWN value and we should switch to the fallback approach - asking content.
    * TODO: for now it's only a stub and returns hardcoded magic value. As soon as bug 928833
    * is done we should integrate its logic here.
    */
--- a/gfx/layers/apz/src/OverscrollHandoffChain.cpp
+++ b/gfx/layers/apz/src/OverscrollHandoffChain.cpp
@@ -56,31 +56,40 @@ OverscrollHandoffChain::IndexOf(const As
     if (mChain[i] == aApzc) {
       break;
     }
   }
   return i;
 }
 
 void
-OverscrollHandoffChain::FlushRepaints() const
+OverscrollHandoffChain::ForEachApzc(APZCMethod aMethod) const
 {
   MOZ_ASSERT(Length() > 0);
   for (uint32_t i = 0; i < Length(); ++i) {
-    mChain[i]->FlushRepaintForOverscrollHandoff();
+    (mChain[i]->*aMethod)();
   }
 }
 
 void
+OverscrollHandoffChain::FlushRepaints() const
+{
+  ForEachApzc(&AsyncPanZoomController::FlushRepaintForOverscrollHandoff);
+}
+
+void
 OverscrollHandoffChain::CancelAnimations() const
 {
-  MOZ_ASSERT(Length() > 0);
-  for (uint32_t i = 0; i < Length(); ++i) {
-    mChain[i]->CancelAnimation();
-  }
+  ForEachApzc(&AsyncPanZoomController::CancelAnimation);
+}
+
+void
+OverscrollHandoffChain::ClearOverscroll() const
+{
+  ForEachApzc(&AsyncPanZoomController::ClearOverscroll);
 }
 
 void
 OverscrollHandoffChain::SnapBackOverscrolledApzc() const
 {
   for (uint32_t i = 0; i < Length(); ++i) {
     AsyncPanZoomController* apzc = mChain[i];
     if (!apzc->IsDestroyed() && apzc->SnapBackIfOverscrolled()) {
--- a/gfx/layers/apz/src/OverscrollHandoffChain.h
+++ b/gfx/layers/apz/src/OverscrollHandoffChain.h
@@ -89,24 +89,30 @@ public:
    */
 
   // Flush repaints all the way up the chain.
   void FlushRepaints() const;
 
   // Cancel animations all the way up the chain.
   void CancelAnimations() const;
 
+  // Clear overscroll all the way up the chain.
+  void ClearOverscroll() const;
+
   // Snap back the APZC that is overscrolled, if any.
   void SnapBackOverscrolledApzc() const;
 
   // Determine whether the given APZC, or any APZC further in the chain,
   // has room to be panned.
   bool CanBePanned(const AsyncPanZoomController* aApzc) const;
 private:
   std::vector<nsRefPtr<AsyncPanZoomController>> mChain;
+
+  typedef void (AsyncPanZoomController::*APZCMethod)();
+  void ForEachApzc(APZCMethod aMethod) const;
 };
 
 // Don't pollute other files with this macro for now.
 #undef NS_INLINE_DECL_THREADSAFE_MUTABLE_REFCOUNTING
 
 }
 }
 
--- a/gfx/layers/basic/BasicLayers.h
+++ b/gfx/layers/basic/BasicLayers.h
@@ -36,17 +36,17 @@ class ReadbackProcessor;
 /**
  * This is a cairo/Thebes-only, main-thread-only implementation of layers.
  * 
  * In each transaction, the client sets up the layer tree and then during
  * the drawing phase, each ThebesLayer is painted directly into the target
  * context (with appropriate clipping and Push/PopGroups performed
  * between layers).
  */
-class BasicLayerManager :
+class BasicLayerManager MOZ_FINAL :
     public LayerManager
 {
 public:
   enum BasicLayerManagerType {
     BLM_WIDGET,
     BLM_OFFSCREEN,
     BLM_INACTIVE
   };
--- a/gfx/layers/client/ClientLayerManager.cpp
+++ b/gfx/layers/client/ClientLayerManager.cpp
@@ -446,17 +446,17 @@ ClientLayerManager::ForwardTransaction(b
 {
   mPhase = PHASE_FORWARD;
 
   mLatestTransactionId = mTransactionIdAllocator->GetTransactionId();
 
   // forward this transaction's changeset to our LayerManagerComposite
   bool sent;
   AutoInfallibleTArray<EditReply, 10> replies;
-  if (HasShadowManager() && mForwarder->EndTransaction(&replies, mRegionToClear,
+  if (mForwarder->EndTransaction(&replies, mRegionToClear,
         mLatestTransactionId, aScheduleComposite, mPaintSequenceNumber,
         mIsRepeatTransaction, &sent)) {
     for (nsTArray<EditReply>::size_type i = 0; i < replies.Length(); ++i) {
       const EditReply& reply = replies[i];
 
       switch (reply.type()) {
       case EditReply::TOpContentBufferSwap: {
         MOZ_LAYERS_LOG(("[LayersForwarder] DoubleBufferSwap"));
@@ -502,26 +502,27 @@ ClientLayerManager::ForwardTransaction(b
       default:
         NS_RUNTIMEABORT("not reached");
       }
     }
 
     if (sent) {
       mNeedsComposite = false;
     }
-    if (!sent || mForwarder->GetShadowManager()->HasNoCompositor()) {
-      // Clear the transaction id so that it doesn't get returned
-      // unless we forwarded to somewhere that doesn't actually
-      // have a compositor.
-      mTransactionIdAllocator->RevokeTransactionId(mLatestTransactionId);
-    }
   } else if (HasShadowManager()) {
     NS_WARNING("failed to forward Layers transaction");
   }
 
+  if (!sent) {
+    // Clear the transaction id so that it doesn't get returned
+    // unless we forwarded to somewhere that doesn't actually
+    // have a compositor.
+    mTransactionIdAllocator->RevokeTransactionId(mLatestTransactionId);
+  }
+
   mForwarder->RemoveTexturesIfNecessary();
   mForwarder->SendPendingAsyncMessge();
   mPhase = PHASE_NONE;
 
   // this may result in Layers being deleted, which results in
   // PLayer::Send__delete__() and DeallocShmem()
   mKeepAlive.Clear();
 }
--- a/gfx/layers/client/ClientLayerManager.h
+++ b/gfx/layers/client/ClientLayerManager.h
@@ -33,17 +33,17 @@ namespace layers {
 
 class ClientThebesLayer;
 class CompositorChild;
 class ImageLayer;
 class PLayerChild;
 class TextureClientPool;
 class SimpleTextureClientPool;
 
-class ClientLayerManager : public LayerManager
+class ClientLayerManager MOZ_FINAL : public LayerManager
 {
   typedef nsTArray<nsRefPtr<Layer> > LayerRefArray;
 
 public:
   explicit ClientLayerManager(nsIWidget* aWidget);
 
 protected:
   virtual ~ClientLayerManager();
--- a/gfx/layers/client/ContentClient.h
+++ b/gfx/layers/client/ContentClient.h
@@ -118,18 +118,18 @@ public:
   {}
 
   virtual void Updated(const nsIntRegion& aRegionToDraw,
                        const nsIntRegion& aVisibleRegion,
                        bool aDidSelfCopy) = 0;
 };
 
 // thin wrapper around RotatedContentBuffer, for on-mtc
-class ContentClientBasic : public ContentClient
-                         , protected RotatedContentBuffer
+class ContentClientBasic MOZ_FINAL : public ContentClient
+                                   , protected RotatedContentBuffer
 {
 public:
   ContentClientBasic();
 
   typedef RotatedContentBuffer::PaintState PaintState;
   typedef RotatedContentBuffer::ContentType ContentType;
 
   virtual void Clear() { RotatedContentBuffer::Clear(); }
--- a/gfx/layers/composite/LayerManagerComposite.h
+++ b/gfx/layers/composite/LayerManagerComposite.h
@@ -61,17 +61,17 @@ class LayerComposite;
 class RefLayerComposite;
 class SurfaceDescriptor;
 class ThebesLayerComposite;
 class TiledLayerComposer;
 class TextRenderer;
 class CompositingRenderTarget;
 struct FPSState;
 
-class LayerManagerComposite : public LayerManager
+class LayerManagerComposite MOZ_FINAL : public LayerManager
 {
   typedef mozilla::gfx::DrawTarget DrawTarget;
   typedef mozilla::gfx::IntSize IntSize;
   typedef mozilla::gfx::SurfaceFormat SurfaceFormat;
 
 public:
   explicit LayerManagerComposite(Compositor* aCompositor);
   ~LayerManagerComposite();
--- a/gfx/layers/ipc/CompositorParent.h
+++ b/gfx/layers/ipc/CompositorParent.h
@@ -82,18 +82,18 @@ private:
   base::Thread* const mCompositorThread;
 
   static base::Thread* CreateCompositorThread();
   static void DestroyCompositorThread(base::Thread* aCompositorThread);
 
   friend class CompositorParent;
 };
 
-class CompositorParent : public PCompositorParent,
-                         public ShadowLayersManager
+class CompositorParent MOZ_FINAL : public PCompositorParent,
+                                   public ShadowLayersManager
 {
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(CompositorParent)
 
 public:
   explicit CompositorParent(nsIWidget* aWidget,
                             bool aUseExternalSurfaceSize = false,
                             int aSurfaceWidth = -1, int aSurfaceHeight = -1);
 
--- a/gfx/layers/ipc/ImageBridgeParent.h
+++ b/gfx/layers/ipc/ImageBridgeParent.h
@@ -32,18 +32,18 @@ class Shmem;
 
 namespace layers {
 
 /**
  * ImageBridgeParent is the manager Protocol of ImageContainerParent.
  * It's purpose is mainly to setup the IPDL connection. Most of the
  * interesting stuff is in ImageContainerParent.
  */
-class ImageBridgeParent : public PImageBridgeParent,
-                          public CompositableParentManager
+class ImageBridgeParent MOZ_FINAL : public PImageBridgeParent,
+                                    public CompositableParentManager
 {
 public:
   typedef InfallibleTArray<CompositableOperation> EditArray;
   typedef InfallibleTArray<EditReply> EditReplyArray;
   typedef InfallibleTArray<AsyncChildMessageData> AsyncChildMessageArray;
 
   ImageBridgeParent(MessageLoop* aLoop, Transport* aTransport, ProcessId aChildProcessId);
   ~ImageBridgeParent();
--- a/gfx/layers/ipc/LayerTransactionChild.h
+++ b/gfx/layers/ipc/LayerTransactionChild.h
@@ -36,34 +36,30 @@ public:
    * It is expected (checked with an assert) that all shadow layers
    * created by this have already been destroyed and
    * Send__delete__()d by the time this method is called.
    */
   void Destroy();
 
   bool IPCOpen() const { return mIPCOpen; }
 
-  void SetHasNoCompositor() { mHasNoCompositor = true; }
-  bool HasNoCompositor() { return mHasNoCompositor; }
-
   void SetForwarder(ShadowLayerForwarder* aForwarder)
   {
     mForwarder = aForwarder;
   }
 
   virtual void SendFenceHandle(AsyncTransactionTracker* aTracker,
                                PTextureChild* aTexture,
                                const FenceHandle& aFence);
 
 protected:
   LayerTransactionChild()
     : mForwarder(nullptr)
     , mIPCOpen(false)
     , mDestroyed(false)
-    , mHasNoCompositor(false)
   {}
   ~LayerTransactionChild() { }
 
   virtual PLayerChild* AllocPLayerChild() MOZ_OVERRIDE;
   virtual bool DeallocPLayerChild(PLayerChild* actor) MOZ_OVERRIDE;
 
   virtual PCompositableChild* AllocPCompositableChild(const TextureInfo& aInfo) MOZ_OVERRIDE;
   virtual bool DeallocPCompositableChild(PCompositableChild* actor) MOZ_OVERRIDE;
@@ -88,15 +84,14 @@ protected:
     Release();
   }
   friend class CompositorChild;
   friend class layout::RenderFrameChild;
 
   ShadowLayerForwarder* mForwarder;
   bool mIPCOpen;
   bool mDestroyed;
-  bool mHasNoCompositor;
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif // MOZILLA_LAYERS_LAYERTRANSACTIONCHILD_H
--- a/gfx/layers/ipc/PLayerTransaction.ipdl
+++ b/gfx/layers/ipc/PLayerTransaction.ipdl
@@ -32,17 +32,17 @@ namespace mozilla {
 namespace layers {
 
 union MaybeTransform {
   Matrix4x4;
   void_t;
 };
 
 sync protocol PLayerTransaction {
-  manager PCompositor or PRenderFrame;
+  manager PCompositor;
   manages PLayer;
   manages PCompositable;
   manages PTexture;
 
 child:
   async ParentAsyncMessages(AsyncParentMessageData[] aMessages);
 
 parent:
--- a/gfx/layers/opengl/TextureHostOGL.cpp
+++ b/gfx/layers/opengl/TextureHostOGL.cpp
@@ -179,17 +179,31 @@ bool
 TextureHostOGL::SetReleaseFence(const android::sp<android::Fence>& aReleaseFence)
 {
   if (!aReleaseFence.get() || !aReleaseFence->isValid()) {
     // HWC might not provide Fence.
     // In this case, HWC implicitly handles buffer's fence.
     return false;
   }
 
-  mReleaseFence = aReleaseFence;
+  if (!mReleaseFence.get()) {
+    mReleaseFence = aReleaseFence;
+  } else {
+    android::sp<android::Fence> mergedFence = android::Fence::merge(
+                  android::String8::format("TextureHostOGL"),
+                  mReleaseFence, aReleaseFence);
+    if (!mergedFence.get()) {
+      // synchronization is broken, the best we can do is hope fences
+      // signal in order so the new fence will act like a union.
+      // This error handling is same as android::ConsumerBase does.
+      mReleaseFence = aReleaseFence;
+      return false;
+    }
+    mReleaseFence = mergedFence;
+  }
   return true;
 }
 
 android::sp<android::Fence>
 TextureHostOGL::GetAndResetReleaseFence()
 {
   // Hold previous ReleaseFence to prevent Fence delivery failure via gecko IPC.
   mPrevReleaseFence = mReleaseFence;
--- a/gfx/layers/opengl/TextureHostOGL.h
+++ b/gfx/layers/opengl/TextureHostOGL.h
@@ -202,19 +202,19 @@ protected:
  * A TextureSource backed by a TextureImage.
  *
  * Depending on the underlying TextureImage, may support texture tiling, so
  * make sure to check AsBigImageIterator() and use the texture accordingly.
  *
  * This TextureSource can be used without a TextureHost and manage it's own
  * GL texture(s).
  */
-class TextureImageTextureSourceOGL : public DataTextureSource
-                                   , public TextureSourceOGL
-                                   , public BigImageIterator
+class TextureImageTextureSourceOGL MOZ_FINAL : public DataTextureSource
+                                             , public TextureSourceOGL
+                                             , public BigImageIterator
 {
 public:
   explicit TextureImageTextureSourceOGL(gl::GLContext* aGL,
                                         TextureFlags aFlags = TextureFlags::DEFAULT)
     : mGL(aGL)
     , mFlags(aFlags)
     , mIterating(false)
   {}
--- a/gfx/skia/generate_mozbuild.py
+++ b/gfx/skia/generate_mozbuild.py
@@ -51,34 +51,32 @@ MSVC_ENABLE_PGO = True
 
 FINAL_LIBRARY = 'gkmedias'
 LOCAL_INCLUDES += [
     'trunk/include/config',
     'trunk/include/core',
     'trunk/include/effects',
     'trunk/include/gpu',
     'trunk/include/images',
-    'trunk/include/lazy',
     'trunk/include/pathops',
     'trunk/include/pipe',
     'trunk/include/ports',
     'trunk/include/utils',
     'trunk/include/utils/mac',
     'trunk/include/utils/win',
     'trunk/include/views',
     'trunk/src/core',
     'trunk/src/gpu',
     'trunk/src/gpu/effects',
     'trunk/src/gpu/gl',
     'trunk/src/image',
     'trunk/src/lazy',
     'trunk/src/opts',
     'trunk/src/sfnt',
     'trunk/src/utils',
-    'trunk/src/utils/android',
     'trunk/src/utils/mac',
     'trunk/src/utils/win',
 ]
 
 DEFINES['SK_A32_SHIFT'] = 24
 DEFINES['SK_R32_SHIFT'] = 16
 DEFINES['SK_G32_SHIFT'] = 8
 DEFINES['SK_B32_SHIFT'] = 0
--- a/gfx/skia/moz.build
+++ b/gfx/skia/moz.build
@@ -883,34 +883,32 @@ MSVC_ENABLE_PGO = True
 
 FINAL_LIBRARY = 'gkmedias'
 LOCAL_INCLUDES += [
     'trunk/include/config',
     'trunk/include/core',
     'trunk/include/effects',
     'trunk/include/gpu',
     'trunk/include/images',
-    'trunk/include/lazy',
     'trunk/include/pathops',
     'trunk/include/pipe',
     'trunk/include/ports',
     'trunk/include/utils',
     'trunk/include/utils/mac',
     'trunk/include/utils/win',
     'trunk/include/views',
     'trunk/src/core',
     'trunk/src/gpu',
     'trunk/src/gpu/effects',
     'trunk/src/gpu/gl',
     'trunk/src/image',
     'trunk/src/lazy',
     'trunk/src/opts',
     'trunk/src/sfnt',
     'trunk/src/utils',
-    'trunk/src/utils/android',
     'trunk/src/utils/mac',
     'trunk/src/utils/win',
 ]
 
 DEFINES['SK_A32_SHIFT'] = 24
 DEFINES['SK_R32_SHIFT'] = 16
 DEFINES['SK_G32_SHIFT'] = 8
 DEFINES['SK_B32_SHIFT'] = 0
--- a/gfx/src/gfxCrashReporterUtils.cpp
+++ b/gfx/src/gfxCrashReporterUtils.cpp
@@ -29,17 +29,17 @@
 #include "nsTArray.h"                   // for nsTArray
 #include "nsThreadUtils.h"              // for NS_DispatchToMainThread, etc
 #include "nscore.h"                     // for NS_IMETHOD, NS_IMETHODIMP, etc
 
 namespace mozilla {
 
 static nsTArray<nsCString> *gFeaturesAlreadyReported = nullptr;
 
-class ObserverToDestroyFeaturesAlreadyReported : public nsIObserver
+class ObserverToDestroyFeaturesAlreadyReported MOZ_FINAL : public nsIObserver
 {
 
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIOBSERVER
 
   ObserverToDestroyFeaturesAlreadyReported() {}
 private:
--- a/gfx/thebes/gfx3DMatrix.cpp
+++ b/gfx/thebes/gfx3DMatrix.cpp
@@ -772,83 +772,16 @@ gfxPointH3D gfx3DMatrix::ProjectPoint(co
 
   // Solving for z when z' = 0 gives us:
   float z = -(aPoint.x * _13 + aPoint.y * _23 + _43) / _33;
 
   // Compute the transformed point
   return Transform4D(gfxPointH3D(aPoint.x, aPoint.y, z, 1));
 }
 
-gfxPointH3D ComputePerspectivePlaneIntercept(const gfxPointH3D& aFirst,
-                                             const gfxPointH3D& aSecond)
-{
-  // FIXME: See bug 1035611
-  // Since we can't easily deal with points as w=0 (since we divide by w), we
-  // approximate this by finding a point with w just greater than 0. Unfortunately
-  // this is a tradeoff between accuracy and floating point precision.
-  
-  // We want to interpolate aFirst and aSecond to find a point as close to
-  // the positive side of the w=0 plane as possible.
-
-  // Since we know what we want the w component to be, we can rearrange the
-  // interpolation equation and solve for t.
-  float w = 0.00001f;
-  float t = (w - aFirst.w) / (aSecond.w - aFirst.w);
-
-  // Use t to find the remainder of the components
-  return aFirst + (aSecond - aFirst) * t;
-}
-
-gfxRect gfx3DMatrix::ProjectRectBounds(const gfxRect& aRect) const
-{
-  gfxPointH3D points[4];
-
-  points[0] = ProjectPoint(aRect.TopLeft());
-  points[1] = ProjectPoint(aRect.TopRight());
-  points[2] = ProjectPoint(aRect.BottomLeft());
-  points[3] = ProjectPoint(aRect.BottomRight());
-
-  gfxFloat min_x = std::numeric_limits<gfxFloat>::max();
-  gfxFloat min_y = std::numeric_limits<gfxFloat>::max();
-  gfxFloat max_x = -std::numeric_limits<gfxFloat>::max();
-  gfxFloat max_y = -std::numeric_limits<gfxFloat>::max();
-
-  bool foundPoint = false;
-  for (int i=0; i<4; i++) {
-    // Only use points that exist above the w=0 plane
-    if (points[i].HasPositiveWCoord()) {
-      foundPoint = true;
-      gfxPoint point2d = points[i].As2DPoint();
-      min_x = min(point2d.x, min_x);
-      max_x = max(point2d.x, max_x);
-      min_y = min(point2d.y, min_y);
-      max_y = max(point2d.y, max_y);
-    }
-
-    int next = (i == 3) ? 0 : i + 1;
-    if (points[i].HasPositiveWCoord() != points[next].HasPositiveWCoord()) {
-      // If the line between two points crosses the w=0 plane, then interpolate a point
-      // as close to the w=0 plane as possible and use that instead.
-      gfxPointH3D intercept = ComputePerspectivePlaneIntercept(points[i], points[next]);
-
-      gfxPoint point2d = intercept.As2DPoint();
-      min_x = min(point2d.x, min_x);
-      max_x = max(point2d.x, max_x);
-      min_y = min(point2d.y, min_y);
-      max_y = max(point2d.y, max_y);
-    }
-  }
-
-  if (!foundPoint) {
-    return gfxRect(0, 0, 0, 0);
-  }
-
-  return gfxRect(min_x, min_y, max_x - min_x, max_y - min_y);
-}
-
 gfxPoint3D gfx3DMatrix::GetNormalVector() const
 {
   // Define a plane in transformed space as the transformations
   // of 3 points on the z=0 screen plane.
   gfxPoint3D a = Transform3D(gfxPoint3D(0, 0, 0));
   gfxPoint3D b = Transform3D(gfxPoint3D(0, 1, 0));
   gfxPoint3D c = Transform3D(gfxPoint3D(1, 0, 0));
 
--- a/gfx/thebes/gfx3DMatrix.h
+++ b/gfx/thebes/gfx3DMatrix.h
@@ -259,17 +259,16 @@ public:
   gfxPointH3D Transform4D(const gfxPointH3D& aPoint) const;
   gfxPointH3D TransposeTransform4D(const gfxPointH3D& aPoint) const;
 
   /**
    * Given a point (x,y) find a value for z such that (x,y,z,1) transforms
    * into (x',y',0,w') and returns the latter.
    */
   gfxPointH3D ProjectPoint(const gfxPoint& aPoint) const;
-  gfxRect ProjectRectBounds(const gfxRect& aRect) const;
 
   /**
    * Inverts this matrix, if possible. Otherwise, the matrix is left
    * unchanged.
    */
   gfx3DMatrix Inverse() const;
 
   gfx3DMatrix& Invert()
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -500,18 +500,17 @@ gfxPlatform::InitLayersIPC()
 {
     if (sLayersIPCIsUp) {
       return;
     }
     sLayersIPCIsUp = true;
 
     AsyncTransactionTrackersHolder::Initialize();
 
-    if (UsesOffMainThreadCompositing() &&
-        XRE_GetProcessType() == GeckoProcessType_Default)
+    if (XRE_GetProcessType() == GeckoProcessType_Default)
     {
         mozilla::layers::CompositorParent::StartUp();
 #ifndef MOZ_WIDGET_GONK
         if (gfxPrefs::AsyncVideoEnabled()) {
             mozilla::layers::ImageBridgeChild::StartUp();
         }
 #else
         mozilla::layers::ImageBridgeChild::StartUp();
@@ -523,18 +522,17 @@ gfxPlatform::InitLayersIPC()
 /* static */ void
 gfxPlatform::ShutdownLayersIPC()
 {
     if (!sLayersIPCIsUp) {
       return;
     }
     sLayersIPCIsUp = false;
 
-    if (UsesOffMainThreadCompositing() &&
-        XRE_GetProcessType() == GeckoProcessType_Default)
+    if (XRE_GetProcessType() == GeckoProcessType_Default)
     {
         // This must happen after the shutdown of media and widgets, which
         // are triggered by the NS_XPCOM_SHUTDOWN_OBSERVER_ID notification.
         layers::ImageBridgeChild::ShutDown();
 #ifdef MOZ_WIDGET_GONK
         layers::SharedBufferManagerChild::ShutDown();
 #endif
 
--- a/gfx/thebes/gfxXlibSurface.h
+++ b/gfx/thebes/gfxXlibSurface.h
@@ -12,17 +12,17 @@
 #include <X11/Xlib.h>
 
 #if defined(GL_PROVIDER_GLX)
 #include "GLXLibrary.h"
 #endif
 
 #include "nsSize.h"
 
-class gfxXlibSurface : public gfxASurface {
+class gfxXlibSurface MOZ_FINAL : public gfxASurface {
 public:
     // construct a wrapper around the specified drawable with dpy/visual.
     // Will use XGetGeometry to query the window/pixmap size.
     gfxXlibSurface(Display *dpy, Drawable drawable, Visual *visual);
 
     // construct a wrapper around the specified drawable with dpy/visual,
     // and known width/height.
     gfxXlibSurface(Display *dpy, Drawable drawable, Visual *visual, const gfxIntSize& size);
--- a/image/decoders/icon/nsIconURI.h
+++ b/image/decoders/icon/nsIconURI.h
@@ -14,17 +14,17 @@
 #define NS_MOZICONURI_CID                            \
 {                                                    \
     0x43a88e0e,                                      \
     0x2d37,                                          \
     0x11d5,                                          \
     { 0x99, 0x7, 0x0, 0x10, 0x83, 0x1, 0xe, 0x9b }   \
 }
 
-class nsMozIconURI : public nsIMozIconURI
+class nsMozIconURI MOZ_FINAL : public nsIMozIconURI
 {
 public:    
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIURI
   NS_DECL_NSIMOZICONURI
 
   // nsMozIconURI
   nsMozIconURI();
--- a/image/src/RasterImage.h
+++ b/image/src/RasterImage.h
@@ -130,21 +130,21 @@ class Image;
 }
 
 namespace image {
 
 class ScaleRequest;
 class Decoder;
 class FrameAnimator;
 
-class RasterImage : public ImageResource
-                  , public nsIProperties
-                  , public SupportsWeakPtr<RasterImage>
+class RasterImage MOZ_FINAL : public ImageResource
+                            , public nsIProperties
+                            , public SupportsWeakPtr<RasterImage>
 #ifdef DEBUG
-                  , public imgIContainerDebug
+                            , public imgIContainerDebug
 #endif
 {
   // (no public constructor - use ImageFactory)
   virtual ~RasterImage();
 
 public:
   MOZ_DECLARE_REFCOUNTED_TYPENAME(RasterImage)
   NS_DECL_THREADSAFE_ISUPPORTS
--- a/image/src/SurfaceCache.cpp
+++ b/image/src/SurfaceCache.cpp
@@ -202,17 +202,17 @@ private:
 
 /*
  * SurfaceCacheImpl is responsible for determining which surfaces will be cached
  * and managing the surface cache data structures. Rather than interact with
  * SurfaceCacheImpl directly, client code interacts with SurfaceCache, which
  * maintains high-level invariants and encapsulates the details of the surface
  * cache's implementation.
  */
-class SurfaceCacheImpl : public nsIMemoryReporter
+class SurfaceCacheImpl MOZ_FINAL : public nsIMemoryReporter
 {
 public:
   NS_DECL_ISUPPORTS
 
   SurfaceCacheImpl(uint32_t aSurfaceCacheExpirationTimeMS,
                    uint32_t aSurfaceCacheSize)
     : mExpirationTracker(MOZ_THIS_IN_INITIALIZER_LIST(),
                          aSurfaceCacheExpirationTimeMS)
--- a/image/src/VectorImage.h
+++ b/image/src/VectorImage.h
@@ -21,18 +21,18 @@ class ImageContainer;
 namespace image {
 
 struct SVGDrawingParameters;
 class  SVGDocumentWrapper;
 class  SVGRootRenderingObserver;
 class  SVGLoadEventListener;
 class  SVGParseCompleteListener;
 
-class VectorImage : public ImageResource,
-                    public nsIStreamListener
+class VectorImage MOZ_FINAL : public ImageResource,
+                              public nsIStreamListener
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIREQUESTOBSERVER
   NS_DECL_NSISTREAMLISTENER
   NS_DECL_IMGICONTAINER
 
   // (no public constructor - use ImageFactory)
--- a/image/src/imgLoader.h
+++ b/image/src/imgLoader.h
@@ -200,21 +200,21 @@ public:
   const_iterator end() const;
 
 private:
   queueContainer mQueue;
   bool mDirty;
   uint32_t mSize;
 };
 
-class imgLoader : public imgILoader,
-                  public nsIContentSniffer,
-                  public imgICache,
-                  public nsSupportsWeakReference,
-                  public nsIObserver
+class imgLoader MOZ_FINAL : public imgILoader,
+                            public nsIContentSniffer,
+                            public imgICache,
+                            public nsSupportsWeakReference,
+                            public nsIObserver
 {
   virtual ~imgLoader();
 
 public:
   typedef mozilla::image::ImageURL ImageURL;
   typedef nsRefPtrHashtable<nsCStringHashKey, imgCacheEntry> imgCacheTable;
 
   NS_DECL_ISUPPORTS
--- a/image/src/imgRequest.h
+++ b/image/src/imgRequest.h
@@ -35,21 +35,21 @@ class nsIURI;
 
 namespace mozilla {
 namespace image {
 class Image;
 class ImageURL;
 } // namespace image
 } // namespace mozilla
 
-class imgRequest : public nsIStreamListener,
-                   public nsIThreadRetargetableStreamListener,
-                   public nsIChannelEventSink,
-                   public nsIInterfaceRequestor,
-                   public nsIAsyncVerifyRedirectCallback
+class imgRequest MOZ_FINAL : public nsIStreamListener,
+                             public nsIThreadRetargetableStreamListener,
+                             public nsIChannelEventSink,
+                             public nsIInterfaceRequestor,
+                             public nsIAsyncVerifyRedirectCallback
 {
   virtual ~imgRequest();
 
 public:
   typedef mozilla::image::ImageURL ImageURL;
   explicit imgRequest(imgLoader* aLoader);
 
   NS_DECL_THREADSAFE_ISUPPORTS
--- a/image/src/imgTools.h
+++ b/image/src/imgTools.h
@@ -9,17 +9,17 @@
 #define NS_IMGTOOLS_CID \
 { /* 3d8fa16d-c9e1-4b50-bdef-2c7ae249967a */         \
      0x3d8fa16d,                                     \
      0xc9e1,                                         \
      0x4b50,                                         \
     {0xbd, 0xef, 0x2c, 0x7a, 0xe2, 0x49, 0x96, 0x7a} \
 }
 
-class imgTools : public imgITools
+class imgTools MOZ_FINAL : public imgITools
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_IMGITOOLS
 
   imgTools();
 
 private:
--- a/intl/lwbrk/tests/moz.build
+++ b/intl/lwbrk/tests/moz.build
@@ -5,18 +5,14 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 CPP_UNIT_TESTS += [
     'TestLineBreak',
 ]
 
 SOURCES += sorted('%s.cpp' % t for t in CPP_UNIT_TESTS)
 
-LOCAL_INCLUDES += [
-    '../public',
-]
-
 USE_LIBS += [
     'mozalloc',
     'nspr',
     'xpcomglue_s',
     'xul',
 ]
--- a/intl/unicharutil/tests/moz.build
+++ b/intl/unicharutil/tests/moz.build
@@ -10,20 +10,16 @@ SOURCES += [
     'NormalizationTest.cpp',
     'UnicharSelfTest.cpp',
 ]
 
 SIMPLE_PROGRAMS += [
     "%s" % (fyl[0:-4]) for fyl in SOURCES
 ]
 
-LOCAL_INCLUDES += [
-    '../public',
-]
-
 USE_STATIC_LIBS = True
 
 USE_LIBS += [
     'mozalloc',
     'nspr',
     'unicharutil_external_s',
     'xul',
 ]
--- a/intl/unicharutil/util/internal/moz.build
+++ b/intl/unicharutil/util/internal/moz.build
@@ -7,10 +7,9 @@
 include('../objs.mozbuild')
 
 UNIFIED_SOURCES += intl_unicharutil_util_cppsrcs
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '..',
-    '../../src',
 ]
--- a/intl/unicharutil/util/moz.build
+++ b/intl/unicharutil/util/moz.build
@@ -22,20 +22,16 @@ include('objs.mozbuild')
 UNIFIED_SOURCES += intl_unicharutil_util_cppsrcs
 
 LIBRARY_NAME = 'unicharutil_external_s'
 
 FORCE_STATIC_LIB = True
 
 SDK_LIBRARY = True
 
-LOCAL_INCLUDES += [
-    '../src',
-]
-
 USE_STATIC_LIBS = True
 
 if CONFIG['_MSC_VER']:
     DEFINES['_USE_ANSI_CPP'] = True
     # Don't include directives about which CRT to use
     CFLAGS += ['-Zl']
     CXXFLAGS += ['-Zl']
 
--- a/js/src/configure.in
+++ b/js/src/configure.in
@@ -2053,30 +2053,16 @@ AC_CACHE_VAL(ac_cv_type_ssize_t,
                  [ac_cv_type_ssize_t=true],
                  [ac_cv_type_ssize_t=false])])
 if test "$ac_cv_type_ssize_t" = true ; then
   AC_DEFINE(HAVE_SSIZE_T)
   AC_MSG_RESULT(yes)
 else
   AC_MSG_RESULT(no)
 fi
-AC_STRUCT_ST_BLKSIZE
-AC_MSG_CHECKING(for siginfo_t)
-AC_CACHE_VAL(ac_cv_siginfo_t,
- [AC_TRY_COMPILE([#define _POSIX_C_SOURCE 199506L
-                  #include <signal.h>],
-                 [siginfo_t* info;],
-                 [ac_cv_siginfo_t=true],
-                 [ac_cv_siginfo_t=false])])
-if test "$ac_cv_siginfo_t" = true ; then
-  AC_DEFINE(HAVE_SIGINFO_T)
-  AC_MSG_RESULT(yes)
-else
-  AC_MSG_RESULT(no)
-fi
 
 MOZ_CHECK_HEADERS(endian.h)
 if test "$ac_cv_header_endian_h" = yes; then
     AC_DEFINE(JS_HAVE_ENDIAN_H)
 fi
 
 MOZ_CHECK_HEADERS([machine/endian.h],[],[],[#include <sys/types.h>])
 if test "$ac_cv_header_machine_endian_h" = yes; then
--- a/js/src/ds/LifoAlloc.h
+++ b/js/src/ds/LifoAlloc.h
@@ -386,17 +386,17 @@ class LifoAlloc
 
     // Get the peak size of the arena chunks (including unused space and
     // bookkeeping space).
     size_t peakSizeOfExcludingThis() const { return peakSize_; }
 
     // Doesn't perform construction; useful for lazily-initialized POD types.
     template <typename T>
     MOZ_ALWAYS_INLINE
-    T *newPod() {
+    T *pod_malloc() {
         return static_cast<T *>(alloc(sizeof(T)));
     }
 
     JS_DECLARE_NEW_METHODS(new_, alloc, MOZ_ALWAYS_INLINE)
     JS_DECLARE_NEW_METHODS(newInfallible, allocInfallible, MOZ_ALWAYS_INLINE)
 
     // A mutable enumeration of the allocated data.
     class Enum
--- a/js/src/frontend/Parser-inl.h
+++ b/js/src/frontend/Parser-inl.h
@@ -26,15 +26,14 @@ ParseContext<ParseHandler>::init(TokenSt
 
 template <typename ParseHandler>
 ParseContext<ParseHandler>::~ParseContext()
 {
     // |*parserPC| pointed to this object.  Now that this object is about to
     // die, make |*parserPC| point to this object's parent.
     JS_ASSERT(*parserPC == this);
     *parserPC = this->oldpc;
-    js_delete(funcStmts);
 }
 
 } // namespace frontend
 } // namespace js
 
 #endif /* frontend_Parser_inl_h */
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -1667,17 +1667,17 @@ Parser<FullParseHandler>::checkFunctionD
 
             /*
              * Instead of setting bindingsAccessedDynamically, which would be
              * overly conservative, remember the names of all function
              * statements and mark any bindings with the same as aliased at the
              * end of functionBody.
              */
             if (!pc->funcStmts) {
-                pc->funcStmts = context->new_<FuncStmtSet>(context);
+                pc->funcStmts = alloc.new_<FuncStmtSet>(alloc);
                 if (!pc->funcStmts || !pc->funcStmts->init())
                     return false;
             }
             if (!pc->funcStmts->put(funName))
                 return false;
 
             /*
              * Due to the implicit declaration mechanism, 'arguments' will not
--- a/js/src/frontend/Parser.h
+++ b/js/src/frontend/Parser.h
@@ -28,17 +28,17 @@ struct StmtInfoPC : public StmtInfoBase 
     StmtInfoPC      *downScope;     /* next enclosing lexical scope */
 
     uint32_t        blockid;        /* for simplified dominance computation */
     uint32_t        innerBlockScopeDepth; /* maximum depth of nested block scopes, in slots */
 
     explicit StmtInfoPC(ExclusiveContext *cx) : StmtInfoBase(cx), innerBlockScopeDepth(0) {}
 };
 
-typedef HashSet<JSAtom *> FuncStmtSet;
+typedef HashSet<JSAtom *, DefaultHasher<JSAtom *>, LifoAllocPolicy<Fallible>> FuncStmtSet;
 class SharedContext;
 
 typedef Vector<Definition *, 16> DeclVector;
 
 struct GenericParseContext
 {
     // Enclosing function or global context.
     GenericParseContext *parent;
--- a/js/src/gc/StoreBuffer.h
+++ b/js/src/gc/StoreBuffer.h
@@ -201,17 +201,17 @@ class StoreBuffer
         template <typename T>
         void put(StoreBuffer *owner, const T &t) {
             JS_ASSERT(storage_);
 
             /* Ensure T is derived from BufferableRef. */
             (void)static_cast<const BufferableRef*>(&t);
 
             unsigned size = sizeof(T);
-            unsigned *sizep = storage_->newPod<unsigned>();
+            unsigned *sizep = storage_->pod_malloc<unsigned>();
             if (!sizep)
                 CrashAtUnhandlableOOM("Failed to allocate for GenericBuffer::put.");
             *sizep = size;
 
             T *tp = storage_->new_<T>(t);
             if (!tp)
                 CrashAtUnhandlableOOM("Failed to allocate for GenericBuffer::put.");
 
--- a/js/src/gdb/gdb-tests.cpp
+++ b/js/src/gdb/gdb-tests.cpp
@@ -71,18 +71,16 @@ main (int argc, const char **argv)
 
     JSAutoRequest ar(cx);
 
     /* Create the global object. */
     JS::CompartmentOptions options;
     options.setVersion(JSVERSION_LATEST);
     RootedObject global(cx, checkPtr(JS_NewGlobalObject(cx, &global_class,
                         nullptr, JS::FireOnNewGlobalHook, options)));
-    js::SetDefaultObjectForContext(cx, global);
-
     JSAutoCompartment ac(cx, global);
 
     /* Populate the global object with the standard globals,
        like Object and Array. */
     checkBool(JS_InitStandardClasses(cx, global));
 
     argv++;
     while (*argv) {
--- a/js/src/jit-test/tests/asm.js/testBug999790.js
+++ b/js/src/jit-test/tests/asm.js/testBug999790.js
@@ -6,28 +6,24 @@ function CanBeConstructed(f) {
         caught = true;
     }
     return !caught;
 }
 
 function IsConstructedFunction(f) {
     return f.hasOwnProperty('length')
         && f.hasOwnProperty('name')
-        && f.hasOwnProperty('arguments')
-        && f.hasOwnProperty('caller')
         && f.hasOwnProperty('prototype')
         && f.prototype.hasOwnProperty('constructor')
         && f.prototype.constructor === f;
 }
 
 function IsntConstructedFunction(f) {
     return !f.hasOwnProperty('length')
         && !f.hasOwnProperty('name')
-        && !f.hasOwnProperty('arguments')
-        && !f.hasOwnProperty('caller')
         && !f.hasOwnProperty('prototype')
 }
 
 var m = function() {
     "use asm"
     function g(){}
     return g;
 };
--- a/js/src/jit-test/tests/basic/bug632778-1.js
+++ b/js/src/jit-test/tests/basic/bug632778-1.js
@@ -1,6 +1,5 @@
-// |jit-test| error: TypeError
 function f() {
     "use strict";
 }
 g = wrap(f);
 Object.defineProperty(g, "arguments", {set: function(){}});
--- a/js/src/jit-test/tests/basic/bug632778-2.js
+++ b/js/src/jit-test/tests/basic/bug632778-2.js
@@ -1,3 +1,2 @@
-// |jit-test| error: TypeError
 obj = wrap(Number.bind());
 Object.defineProperty(obj, "caller", {set: function () {}});
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/typed-array-copyWithin.js
@@ -0,0 +1,189 @@
+// Bug 1021379 - Rename typed arrays' move method to copyWithin,
+// fix up to ES6 semantics
+// Tests for TypedArray#copyWithin
+
+load(libdir + "asserts.js");
+
+const constructors = [
+  Int8Array,
+  Uint8Array,
+  Uint8ClampedArray,
+  Int16Array,
+  Uint16Array,
+  Int32Array,
+  Uint32Array,
+  Float32Array,
+  Float64Array
+];
+
+for (var constructor of constructors) {
+
+    assertEq(constructor.prototype.copyWithin.length, 2);
+
+    // works with two arguments
+    assertDeepEq(new constructor([1, 2, 3, 4, 5]).copyWithin(0, 3),
+                 new constructor([4, 5, 3, 4, 5]));
+    assertDeepEq(new constructor([1, 2, 3, 4, 5]).copyWithin(1, 3),
+                 new constructor([1, 4, 5, 4, 5]));
+    assertDeepEq(new constructor([1, 2, 3, 4, 5]).copyWithin(1, 2),
+                 new constructor([1, 3, 4, 5, 5]));
+    assertDeepEq(new constructor([1, 2, 3, 4, 5]).copyWithin(2, 2),
+                 new constructor([1, 2, 3, 4, 5]));
+
+    // works with three arguments
+    assertDeepEq(new constructor([1, 2, 3, 4, 5]).copyWithin(0, 3, 4),
+                 new constructor([4, 2, 3, 4, 5]));
+    assertDeepEq(new constructor([1, 2, 3, 4, 5]).copyWithin(1, 3, 4),
+                 new constructor([1, 4, 3, 4, 5]));
+    assertDeepEq(new constructor([1, 2, 3, 4, 5]).copyWithin(1, 2, 4),
+                 new constructor([1, 3, 4, 4, 5]));
+
+    // works with negative arguments
+    assertDeepEq(new constructor([1, 2, 3, 4, 5]).copyWithin(0, -2),
+                 new constructor([4, 5, 3, 4, 5]));
+    assertDeepEq(new constructor([1, 2, 3, 4, 5]).copyWithin(0, -2, -1),
+                 new constructor([4, 2, 3, 4, 5]));
+    assertDeepEq(new constructor([1, 2, 3, 4, 5]).copyWithin(-4, -3, -2),
+                 new constructor([1, 3, 3, 4, 5]));
+    assertDeepEq(new constructor([1, 2, 3, 4, 5]).copyWithin(-4, -3, -1),
+                 new constructor([1, 3, 4, 4, 5]));
+    assertDeepEq(new constructor([1, 2, 3, 4, 5]).copyWithin(-4, -3),
+                 new constructor([1, 3, 4, 5, 5]));
+
+    // throws on null/undefined values
+    assertThrowsInstanceOf(function() {
+      constructor.prototype.copyWithin.call(null, 0, 3);
+    }, TypeError, "Assert that copyWithin fails if this value is null");
+
+    assertThrowsInstanceOf(function() {
+      var throw42 = { valueOf: function() { throw 42; } };
+      constructor.prototype.copyWithin.call(null, throw42, throw42, throw42);
+    }, TypeError, "Assert that copyWithin fails if this value is null");
+
+    assertThrowsInstanceOf(function() {
+      var throw42 = { valueOf: function() { throw 42; } };
+      constructor.prototype.copyWithin.call(undefined, throw42, throw42, throw42);
+    }, TypeError, "Assert that copyWithin fails if this value is undefined");
+
+    assertThrowsInstanceOf(function() {
+      constructor.prototype.copyWithin.call(undefined, 0, 3);
+    }, TypeError, "Assert that copyWithin fails if this value is undefined");
+
+    // test with this value as string
+    assertThrowsInstanceOf(function() {
+      constructor.prototype.copyWithin.call("hello world", 0, 3);
+    }, TypeError, "Assert that copyWithin fails if this value is string");
+
+    assertThrowsInstanceOf(function() {
+      var throw42 = { valueOf: function() { throw 42; } };
+      constructor.prototype.copyWithin.call("hello world", throw42, throw42, throw42);
+    }, TypeError, "Assert that copyWithin fails if this value is string");
+
+    // test with target > start on 2 arguments
+    assertDeepEq(new constructor([1, 2, 3, 4, 5]).copyWithin(3, 0),
+                 new constructor([1, 2, 3, 1, 2]));
+
+    // test with target > start on 3 arguments
+    assertDeepEq(new constructor([1, 2, 3, 4, 5]).copyWithin(3, 0, 4),
+                 new constructor([1, 2, 3, 1, 2]));
+
+    // test on fractional arguments
+    assertDeepEq(new constructor([1, 2, 3, 4, 5]).copyWithin(0.2, 3.9),
+                 new constructor([4, 5, 3, 4, 5]));
+
+    // test with -0
+    assertDeepEq(new constructor([1, 2, 3, 4, 5]).copyWithin(-0, 3),
+                 new constructor([4, 5, 3, 4, 5]));
+
+    // test with arguments more than this.length
+    assertDeepEq(new constructor([1, 2, 3, 4, 5]).copyWithin(0, 7),
+                 new constructor([1, 2, 3, 4, 5]));
+
+    assertDeepEq(new constructor([1, 2, 3, 4, 5]).copyWithin(7, 0),
+                 new constructor([1, 2, 3, 4, 5]));
+
+    // test with arguments less than -this.length
+    assertDeepEq(new constructor([1, 2, 3, 4, 5]).copyWithin(-7, 0),
+                 new constructor([1, 2, 3, 4, 5]));
+
+    // test with arguments equal to -this.length
+    assertDeepEq(new constructor([1, 2, 3, 4, 5]).copyWithin(-5, 0),
+                 new constructor([1, 2, 3, 4, 5]));
+
+    // test on empty constructor
+    assertDeepEq(new constructor([]).copyWithin(0, 3),
+                 new constructor([]));
+
+    // test with target range being shorter than end - start
+    assertDeepEq(new constructor([1, 2, 3, 4, 5]).copyWithin(2, 1, 4),
+                 new constructor([1, 2, 2, 3, 4]));
+
+    // test overlapping ranges
+    arr = new constructor([1, 2, 3, 4, 5]);
+    arr.copyWithin(2, 1, 4);
+    assertDeepEq(arr.copyWithin(2, 1, 4),
+                 new constructor([1, 2, 2, 2, 3]));
+
+    // undefined as third argument
+    assertDeepEq(new constructor([1, 2, 3, 4, 5]).copyWithin(0, 3, undefined),
+                 new constructor([4, 5, 3, 4, 5]));
+
+    // test that this.length is never called
+    arr = new constructor([0, 1, 2, 3, 5]);
+    Object.defineProperty(arr, "length", {
+      get: function () { throw new Error("length accessor called"); }
+    });
+    arr.copyWithin(1, 3);
+
+    var large = 10000;
+
+    // test on a large constructor
+    arr = new constructor(large);
+    assertDeepEq(arr.copyWithin(45, 900), arr);
+
+    // test on floating point numbers
+    for (var i = 0; i < large; i++) {
+      arr[i] = Math.random();
+    }
+    arr.copyWithin(45, 900);
+
+    // test on constructor of objects
+    for (var i = 0; i < large; i++) {
+      arr[i] = { num: Math.random() };
+    }
+    arr.copyWithin(45, 900);
+
+    // test constructor length remains same
+    assertEq(arr.length, large);
+
+    // test null on third argument is handled correctly
+    assertDeepEq(new constructor([1, 2, 3, 4, 5]).copyWithin(0, 3, null),
+                 new constructor([1, 2, 3, 4, 5]));
+
+    //Any argument referenced, but not provided, has the value |undefined|
+    var tarray = new constructor(8);
+    try
+    {
+      tarray.copyWithin({ valueOf: function() { throw 42; } });
+      throw new Error("expected to throw");
+    }
+    catch (e)
+    {
+      assertEq(e, 42, "should have failed converting target to index");
+    }
+
+    /* // fails, unclear whether it should, disabling for now
+    // test with a proxy object
+    var handler = {
+      get: function(recipient, name) {
+          return recipient[name] + 2;
+      }
+    };
+
+    var p = new Proxy(new constructor([1, 2, 3, 4, 5]), handler);
+
+    assertThrowsInstanceOf(function() {
+      constructor.prototype.copyWithin.call(p, 0, 3);
+    }, TypeError, "Assert that copyWithin fails if used with a proxy object");
+    */
+}
--- a/js/src/jit-test/tests/heap-analysis/findPath.js
+++ b/js/src/jit-test/tests/heap-analysis/findPath.js
@@ -25,17 +25,17 @@ Match.Pattern([{node: {}, edge: "type"},
                {node: Match.Pattern.ANY, edge: "type_proto"},
                {node: { constructor: Match.Pattern.ANY }, edge: "obj"}])
   .assert(findPath(c, c.obj));
 print(uneval(findPath(c, c.obj)));
 
 function f(x) { return function g(y) { return x+y; }; }
 var o = {}
 var gc = f(o);
-Match.Pattern([{node: gc, edge: "fun_callscope"},
+Match.Pattern([{node: gc, edge: "fun_environment"},
                {node: Match.Pattern.ANY, edge: "x"}])
   .assert(findPath(gc, o));
 print(uneval(findPath(gc, o)));
 
 Match.Pattern([{node: {}, edge: "shape"},
                {node: Match.Pattern.ANY, edge: "base"},
                {node: Match.Pattern.ANY, edge: "parent"},
                {node: {}, edge: "o"}])
--- a/js/src/jit-test/tests/proxy/bug897403.js
+++ b/js/src/jit-test/tests/proxy/bug897403.js
@@ -1,5 +1,3 @@
-// |jit-test| error: TypeError
-
 var f = (function () {}).bind({});
 var p = new Proxy(f, {});
 Object.defineProperty(p, "caller", {get: function(){}});
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -3405,22 +3405,22 @@ CodeGenerator::generateBody()
                 return false;
         }
 
 #if defined(JS_ION_PERF)
         perfSpewer->startBasicBlock(current->mir(), masm);
 #endif
 
         for (LInstructionIterator iter = current->begin(); iter != current->end(); iter++) {
+#ifdef DEBUG
             IonSpewStart(IonSpew_Codegen, "instruction %s", iter->opName());
-#ifdef DEBUG
             if (const char *extra = iter->extraName())
                 IonSpewCont(IonSpew_Codegen, ":%s", extra);
+            IonSpewFin(IonSpew_Codegen);
 #endif
-            IonSpewFin(IonSpew_Codegen);
 
             if (counts)
                 blockCounts->visitInstruction(*iter);
 
             if (iter->safepoint() && pushedArgumentSlots_.length()) {
                 if (!markArgumentSlots(iter->safepoint()))
                     return false;
             }
--- a/js/src/jit/Ion.cpp
+++ b/js/src/jit/Ion.cpp
@@ -1416,24 +1416,26 @@ OptimizeMIR(MIRGenerator *mir)
         if (!analysis.analyze())
             return false;
         IonSpewPass("Alias analysis");
         AssertExtendedGraphCoherency(graph);
 
         if (mir->shouldCancel("Alias analysis"))
             return false;
 
-        // Eliminating dead resume point operands requires basic block
-        // instructions to be numbered. Reuse the numbering computed during
-        // alias analysis.
-        if (!EliminateDeadResumePointOperands(mir, graph))
-            return false;
-
-        if (mir->shouldCancel("Eliminate dead resume point operands"))
-            return false;
+        if (!mir->compilingAsmJS()) {
+            // Eliminating dead resume point operands requires basic block
+            // instructions to be numbered. Reuse the numbering computed during
+            // alias analysis.
+            if (!EliminateDeadResumePointOperands(mir, graph))
+                return false;
+
+            if (mir->shouldCancel("Eliminate dead resume point operands"))
+                return false;
+        }
     }
 
     if (mir->optimizationInfo().gvnEnabled()) {
         AutoTraceLog log(logger, TraceLogger::GVN);
         ValueNumberer gvn(mir, graph);
         if (!gvn.run(ValueNumberer::UpdateAliasAnalysis))
             return false;
         IonSpewPass("GVN");
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -711,20 +711,16 @@ IonBuilder::build()
 
     // It's safe to start emitting actual IR, so now build the scope chain.
     if (!initScopeChain())
         return false;
 
     if (info().needsArgsObj() && !initArgumentsObject())
         return false;
 
-    // Prevent |this| from being DCE'd: necessary for constructors.
-    if (info().funMaybeLazy())
-        current->getSlot(info().thisSlot())->setGuard();
-
     // The type analysis phase attempts to insert unbox operations near
     // definitions of values. It also attempts to replace uses in resume points
     // with the narrower, unboxed variants. However, we must prevent this
     // replacement from happening on values in the entry snapshot. Otherwise we
     // could get this:
     //
     //       v0 = MParameter(0)
     //       v1 = MParameter(1)
@@ -6023,21 +6019,16 @@ IonBuilder::newOsrPreheader(MBasicBlock 
     }
 
     // Finish the osrBlock.
     osrBlock->end(MGoto::New(alloc(), preheader));
     if (!preheader->addPredecessor(alloc(), osrBlock))
         return nullptr;
     graph().setOsrBlock(osrBlock);
 
-    // Wrap |this| with a guaranteed use, to prevent instruction elimination.
-    // Prevent |this| from being DCE'd: necessary for constructors.
-    if (info().funMaybeLazy())
-        preheader->getSlot(info().thisSlot())->setGuard();
-
     return preheader;
 }
 
 MBasicBlock *
 IonBuilder::newPendingLoopHeader(MBasicBlock *predecessor, jsbytecode *pc, bool osr, bool canOsr,
                                  unsigned stackPhiCount)
 {
     loopDepth_++;
--- a/js/src/jit/IonSpewer.cpp
+++ b/js/src/jit/IonSpewer.cpp
@@ -391,17 +391,17 @@ jit::IonSpew(IonSpewChannel channel, con
 
 void
 jit::IonSpewDef(IonSpewChannel channel, const char *str, MDefinition *def)
 {
     if (!IonSpewEnabled(channel))
         return;
 
     IonSpewHeader(channel);
-    fprintf(IonSpewFile, str);
+    fprintf(IonSpewFile, "%s", str);
     def->dump(IonSpewFile);
     def->dumpLocation(IonSpewFile);
 }
 
 void
 jit::IonSpewStart(IonSpewChannel channel, const char *fmt, ...)
 {
     va_list ap;
--- a/js/src/jit/none/Lowering-none.h
+++ b/js/src/jit/none/Lowering-none.h
@@ -51,18 +51,30 @@ class LIRGeneratorNone : public LIRGener
     bool lowerConstantFloat32(float, MInstruction *) { MOZ_CRASH(); }
     bool lowerTruncateDToInt32(MTruncateToInt32 *) { MOZ_CRASH(); }
     bool lowerTruncateFToInt32(MTruncateToInt32 *) { MOZ_CRASH(); }
     bool lowerDivI(MDiv *) { MOZ_CRASH(); }
     bool lowerModI(MMod *) { MOZ_CRASH(); }
     bool lowerMulI(MMul *, MDefinition *, MDefinition *) { MOZ_CRASH(); }
     bool lowerUDiv(MDiv *) { MOZ_CRASH(); }
     bool lowerUMod(MMod *) { MOZ_CRASH(); }
+    bool visitBox(MBox *box) { MOZ_CRASH(); }
+    bool visitUnbox(MUnbox *unbox) { MOZ_CRASH(); }
+    bool visitReturn(MReturn *ret) { MOZ_CRASH(); }
     bool visitPowHalf(MPowHalf *) { MOZ_CRASH(); }
     bool visitAsmJSNeg(MAsmJSNeg *) { MOZ_CRASH(); }
+    bool visitGuardShape(MGuardShape *ins) { MOZ_CRASH(); }
+    bool visitGuardObjectType(MGuardObjectType *ins) { MOZ_CRASH(); }
+    bool visitAsmJSUnsignedToDouble(MAsmJSUnsignedToDouble *ins) { MOZ_CRASH(); }
+    bool visitAsmJSUnsignedToFloat32(MAsmJSUnsignedToFloat32 *ins) { MOZ_CRASH(); }
+    bool visitAsmJSLoadHeap(MAsmJSLoadHeap *ins) { MOZ_CRASH(); }
+    bool visitAsmJSStoreHeap(MAsmJSStoreHeap *ins) { MOZ_CRASH(); }
+    bool visitAsmJSLoadFuncPtr(MAsmJSLoadFuncPtr *ins) { MOZ_CRASH(); }
+    bool visitStoreTypedArrayElementStatic(MStoreTypedArrayElementStatic *ins) { MOZ_CRASH(); }
+    bool visitForkJoinGetSlice(MForkJoinGetSlice *ins) { MOZ_CRASH(); }
 
     LTableSwitch *newLTableSwitch(LAllocation, LDefinition, MTableSwitch *) { MOZ_CRASH(); }
     LTableSwitchV *newLTableSwitchV(MTableSwitch *) { MOZ_CRASH(); }
 };
 
 typedef LIRGeneratorNone LIRGeneratorSpecific;
 
 } // namespace jit
--- a/js/src/jit/none/MacroAssembler-none.h
+++ b/js/src/jit/none/MacroAssembler-none.h
@@ -2,19 +2,20 @@
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef jit_none_MacroAssembler_none_h
 #define jit_none_MacroAssembler_none_h
 
+#include "jit/JitCompartment.h"
 #include "jit/MoveResolver.h"
+#include "jit/shared/Assembler-shared.h"
 
-#include "jit/shared/Assembler-shared.h"
 
 namespace js {
 namespace jit {
 
 class MDefinition;
 
 static MOZ_CONSTEXPR_VAR Register StackPointer = { 0 };
 static MOZ_CONSTEXPR_VAR Register FramePointer = { 0 };
@@ -214,16 +215,17 @@ class MacroAssemblerNone : public Assemb
     template <typename T> void Push(T) { MOZ_CRASH(); }
     template <typename T> void pop(T) { MOZ_CRASH(); }
     template <typename T> void Pop(T) { MOZ_CRASH(); }
     template <typename T> CodeOffsetLabel PushWithPatch(T) { MOZ_CRASH(); }
     void implicitPop(uint32_t) { MOZ_CRASH(); }
 
     CodeOffsetJump jumpWithPatch(RepatchLabel *) { MOZ_CRASH(); }
     CodeOffsetJump jumpWithPatch(RepatchLabel *, Condition) { MOZ_CRASH(); }
+    CodeOffsetJump backedgeJump(RepatchLabel *label) { MOZ_CRASH(); }
     template <typename T, typename S>
     CodeOffsetJump branchPtrWithPatch(Condition, T, S, RepatchLabel *) { MOZ_CRASH(); }
 
     template <typename T, typename S> void branchTestValue(Condition, T, S, Label *) { MOZ_CRASH(); }
     void testNullSet(Condition, ValueOperand, Register) { MOZ_CRASH(); }
     void testObjectSet(Condition, ValueOperand, Register) { MOZ_CRASH(); }
     void testUndefinedSet(Condition, ValueOperand, Register) { MOZ_CRASH(); }
 
@@ -398,13 +400,18 @@ class ABIArgGenerator
     static const Register NonArgReturnReg1;
     static const Register NonArg_VolatileReg;
     static const Register NonReturn_VolatileReg0;
     static const Register NonReturn_VolatileReg1;
 };
 
 static inline void PatchJump(CodeLocationJump &, CodeLocationLabel) { MOZ_CRASH(); }
 static inline bool GetTempRegForIntArg(uint32_t, uint32_t, Register *) { MOZ_CRASH(); }
+static inline
+void PatchBackedge(CodeLocationJump &jump_, CodeLocationLabel label, JitRuntime::BackedgeTarget target)
+{
+    MOZ_CRASH();
+}
 
 } // namespace jit
 } // namespace js
 
 #endif /* jit_none_MacroAssembler_none_h */
--- a/js/src/js.msg
+++ b/js/src/js.msg
@@ -125,17 +125,17 @@ MSG_DEF(JSMSG_RESULTING_STRING_TOO_LARGE
 MSG_DEF(JSMSG_BAD_RADIX,               0, JSEXN_RANGEERR, "radix must be an integer at least 2 and no greater than 36")
 MSG_DEF(JSMSG_PRECISION_RANGE,         1, JSEXN_RANGEERR, "precision {0} out of range")
 
 // Function
 MSG_DEF(JSMSG_BAD_APPLY_ARGS,          1, JSEXN_TYPEERR, "second argument to Function.prototype.{0} must be an array")
 MSG_DEF(JSMSG_BAD_FORMAL,              0, JSEXN_SYNTAXERR, "malformed formal parameter")
 MSG_DEF(JSMSG_CALLER_IS_STRICT,        0, JSEXN_TYPEERR, "access to strict mode caller function is censored")
 MSG_DEF(JSMSG_DEPRECATED_USAGE,        1, JSEXN_REFERENCEERR, "deprecated {0} usage")
-MSG_DEF(JSMSG_FUNCTION_ARGUMENTS_AND_REST, 0, JSEXN_ERR, "the 'arguments' property of a function with a rest parameter may not be used")
+MSG_DEF(JSMSG_FUNCTION_ARGUMENTS_AND_REST, 0, JSEXN_TYPEERR, "the 'arguments' property of a function with a rest parameter may not be used")
 MSG_DEF(JSMSG_NOT_SCRIPTED_FUNCTION,   1, JSEXN_TYPEERR, "{0} is not a scripted function")
 MSG_DEF(JSMSG_NO_REST_NAME,            0, JSEXN_SYNTAXERR, "no parameter name after ...")
 MSG_DEF(JSMSG_PARAMETER_AFTER_REST,    0, JSEXN_SYNTAXERR, "parameter after rest parameter")
 MSG_DEF(JSMSG_TOO_MANY_FUN_APPLY_ARGS, 0, JSEXN_RANGEERR, "arguments array passed to Function.prototype.apply is too large")
 
 // CSP
 MSG_DEF(JSMSG_CSP_BLOCKED_EVAL,        0, JSEXN_ERR, "call to eval() blocked by CSP")
 MSG_DEF(JSMSG_CSP_BLOCKED_FUNCTION,    0, JSEXN_ERR, "call to Function() blocked by CSP")
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -1134,17 +1134,16 @@ JS_RefreshCrossCompartmentWrappers(JSCon
 
 JS_PUBLIC_API(bool)
 JS_InitStandardClasses(JSContext *cx, HandleObject obj)
 {
     JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
 
-    cx->setDefaultCompartmentObjectIfUnset(obj);
     assertSameCompartment(cx, obj);
 
     Rooted<GlobalObject*> global(cx, &obj->global());
     return GlobalObject::initStandardClasses(cx, global);
 }
 
 #define EAGER_ATOM(name)            NAME_OFFSET(name)
 
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -1525,18 +1525,17 @@ RuntimeOptionsRef(JSRuntime *rt);
 
 JS_PUBLIC_API(RuntimeOptions &)
 RuntimeOptionsRef(JSContext *cx);
 
 class JS_PUBLIC_API(ContextOptions) {
   public:
     ContextOptions()
       : privateIsNSISupports_(false),
-        dontReportUncaught_(false),
-        noDefaultCompartmentObject_(false)
+        dontReportUncaught_(false)
     {
     }
 
     bool privateIsNSISupports() const { return privateIsNSISupports_; }
     ContextOptions &setPrivateIsNSISupports(bool flag) {
         privateIsNSISupports_ = flag;
         return *this;
     }
@@ -1550,30 +1549,19 @@ class JS_PUBLIC_API(ContextOptions) {
         dontReportUncaught_ = flag;
         return *this;
     }
     ContextOptions &toggleDontReportUncaught() {
         dontReportUncaught_ = !dontReportUncaught_;
         return *this;
     }
 
-    bool noDefaultCompartmentObject() const { return noDefaultCompartmentObject_; }
-    ContextOptions &setNoDefaultCompartmentObject(bool flag) {
-        noDefaultCompartmentObject_ = flag;
-        return *this;
-    }
-    ContextOptions &toggleNoDefaultCompartmentObject() {
-        noDefaultCompartmentObject_ = !noDefaultCompartmentObject_;
-        return *this;
-    }
-
   private:
     bool privateIsNSISupports_ : 1;
     bool dontReportUncaught_ : 1;
-    bool noDefaultCompartmentObject_ : 1;
 };
 
 JS_PUBLIC_API(ContextOptions &)
 ContextOptionsRef(JSContext *cx);
 
 class JS_PUBLIC_API(AutoSaveContextOptions) {
   public:
     explicit AutoSaveContextOptions(JSContext *cx)
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -137,16 +137,20 @@ js::ExistingCloneFunctionAtCallsite(cons
 }
 
 JSFunction *
 js::CloneFunctionAtCallsite(JSContext *cx, HandleFunction fun, HandleScript script, jsbytecode *pc)
 {
     if (JSFunction *clone = ExistingCloneFunctionAtCallsite(cx->compartment()->callsiteClones, fun, script, pc))
         return clone;
 
+    MOZ_ASSERT(fun->isSelfHostedBuiltin(),
+               "only self-hosted builtin functions may be cloned at call sites, and "
+               "Function.prototype.caller relies on this");
+
     RootedObject parent(cx, fun->environment());
     JSFunction *clone = CloneFunctionObject(cx, fun, parent);
     if (!clone)
         return nullptr;
 
     /*
      * Store a link back to the original for function.caller and avoid cloning
      * clones.
@@ -1098,17 +1102,16 @@ JSContext::JSContext(JSRuntime *rt)
     throwing(false),
     unwrappedException_(UndefinedValue()),
     options_(),
     propagatingForcedReturn_(false),
     reportGranularity(JS_DEFAULT_JITREPORT_GRANULARITY),
     resolvingList(nullptr),
     generatingError(false),
     savedFrameChains_(),
-    defaultCompartmentObject_(nullptr),
     cycleDetectorSet(MOZ_THIS_IN_INITIALIZER_LIST()),
     errorReporter(nullptr),
     data(nullptr),
     data2(nullptr),
     outstandingRequests(0),
     iterValue(MagicValue(JS_NO_ITER_VALUE)),
     jitIsBroken(false),
 #ifdef MOZ_TRACE_JSCALLS
@@ -1295,18 +1298,16 @@ JSContext::sizeOfIncludingThis(mozilla::
 }
 
 void
 JSContext::mark(JSTracer *trc)
 {
     /* Stack frames and slots are traced by StackSpace::mark. */
 
     /* Mark other roots-by-definition in the JSContext. */
-    if (defaultCompartmentObject_)
-        MarkObjectRoot(trc, &defaultCompartmentObject_, "default compartment object");
     if (isExceptionPending())
         MarkValueRoot(trc, &unwrappedException_, "unwrapped exception");
 
     TraceCycleDetectionSet(trc, cycleDetectorSet);
 
     MarkValueRoot(trc, &iterValue, "iterValue");
 }
 
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -450,31 +450,17 @@ struct JSContext : public js::ExclusiveC
         unsigned enterCompartmentCount;
     };
     typedef js::Vector<SavedFrameChain, 1, js::SystemAllocPolicy> SaveStack;
     SaveStack           savedFrameChains_;
   public:
     bool saveFrameChain();
     void restoreFrameChain();
 
-    /*
-     * When no compartments have been explicitly entered, the context's
-     * compartment will be set to the compartment of the "default compartment
-     * object".
-     */
-  private:
-    JSObject *defaultCompartmentObject_;
   public:
-    inline void setDefaultCompartmentObject(JSObject *obj);
-    inline void setDefaultCompartmentObjectIfUnset(JSObject *obj);
-    JSObject *maybeDefaultCompartmentObject() const {
-        JS_ASSERT(!options().noDefaultCompartmentObject());
-        return defaultCompartmentObject_;
-    }
-
     /* State for object and array toSource conversion. */
     js::ObjectSet       cycleDetectorSet;
 
     /* Per-context optional error reporter. */
     JSErrorReporter     errorReporter;
 
     /* Client opaque pointers. */
     void                *data;
--- a/js/src/jscntxtinlines.h
+++ b/js/src/jscntxtinlines.h
@@ -376,33 +376,16 @@ JSContext::setPendingException(js::Value
 
 inline bool
 JSContext::runningWithTrustedPrincipals() const
 {
     return !compartment() || compartment()->principals == runtime()->trustedPrincipals();
 }
 
 inline void
-JSContext::setDefaultCompartmentObject(JSObject *obj)
-{
-    JS_ASSERT(!options().noDefaultCompartmentObject());
-    defaultCompartmentObject_ = obj;
-}
-
-inline void
-JSContext::setDefaultCompartmentObjectIfUnset(JSObject *obj)
-{
-    if (!options().noDefaultCompartmentObject() &&
-        !defaultCompartmentObject_)
-    {
-        setDefaultCompartmentObject(obj);
-    }
-}
-
-inline void
 js::ExclusiveContext::enterCompartment(JSCompartment *c)
 {
     enterCompartmentDepth_++;
     c->enter();
     setCompartment(c);
 }
 
 inline void
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -411,30 +411,16 @@ js::AssertSameCompartment(JSContext *cx,
 #ifdef DEBUG
 JS_FRIEND_API(void)
 js::AssertSameCompartment(JSObject *objA, JSObject *objB)
 {
     JS_ASSERT(objA->compartment() == objB->compartment());
 }
 #endif
 
-JS_FRIEND_API(JSObject *)
-js::DefaultObjectForContextOrNull(JSContext *cx)
-{
-    if (cx->options().noDefaultCompartmentObject())
-        return nullptr;
-    return cx->maybeDefaultCompartmentObject();
-}
-
-JS_FRIEND_API(void)
-js::SetDefaultObjectForContext(JSContext *cx, JSObject *obj)
-{
-    cx->setDefaultCompartmentObject(obj);
-}
-
 JS_FRIEND_API(void)
 js::NotifyAnimationActivity(JSObject *obj)
 {
     obj->compartment()->lastAnimationTime = PRMJ_Now();
 }
 
 JS_FRIEND_API(uint32_t)
 js::GetObjectSlotSpan(JSObject *obj)
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -716,23 +716,16 @@ AssertSameCompartment(JSContext *cx, JSO
 
 #ifdef JS_DEBUG
 JS_FRIEND_API(void)
 AssertSameCompartment(JSObject *objA, JSObject *objB);
 #else
 inline void AssertSameCompartment(JSObject *objA, JSObject *objB) {}
 #endif
 
-// For legacy consumers only. This whole concept is going away soon.
-JS_FRIEND_API(JSObject *)
-DefaultObjectForContextOrNull(JSContext *cx);
-
-JS_FRIEND_API(void)
-SetDefaultObjectForContext(JSContext *cx, JSObject *obj);
-
 JS_FRIEND_API(void)
 NotifyAnimationActivity(JSObject *obj);
 
 /*
  * Return the outermost enclosing function (script) of the scripted caller.
  * This function returns nullptr in several cases:
  *  - no script is running on the context
  *  - the caller is in global or eval code
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -29,16 +29,18 @@
 
 #include "builtin/Eval.h"
 #include "builtin/Object.h"
 #include "frontend/BytecodeCompiler.h"
 #include "frontend/TokenStream.h"
 #include "gc/Marking.h"
 #include "jit/Ion.h"
 #include "jit/JitFrameIterator.h"
+#include "js/CallNonGenericMethod.h"
+#include "vm/GlobalObject.h"
 #include "vm/Interpreter.h"
 #include "vm/Shape.h"
 #include "vm/StringBuffer.h"
 #include "vm/WrapperObject.h"
 #include "vm/Xdr.h"
 
 #include "jsscriptinlines.h"
 
@@ -50,117 +52,19 @@ using namespace js::gc;
 using namespace js::types;
 using namespace js::frontend;
 
 using mozilla::ArrayLength;
 using mozilla::PodCopy;
 using mozilla::RangedPtr;
 
 static bool
-fun_getProperty(JSContext *cx, HandleObject obj_, HandleId id, MutableHandleValue vp)
-{
-    RootedObject obj(cx, obj_);
-    while (!obj->is<JSFunction>()) {
-        if (!JSObject::getProto(cx, obj, &obj))
-            return false;
-        if (!obj)
-            return true;
-    }
-    RootedFunction fun(cx, &obj->as<JSFunction>());
-
-    /* Set to early to null in case of error */
-    vp.setNull();
-
-    /* Find fun's top-most activation record. */
-    NonBuiltinScriptFrameIter iter(cx);
-    for (; !iter.done(); ++iter) {
-        if (!iter.isFunctionFrame() || iter.isEvalFrame())
-            continue;
-        if (iter.callee() == fun)
-            break;
-    }
-    if (iter.done())
-        return true;
-
-    if (JSID_IS_ATOM(id, cx->names().arguments)) {
-        if (fun->hasRest()) {
-            JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
-                                 JSMSG_FUNCTION_ARGUMENTS_AND_REST);
-            return false;
-        }
-        /* Warn if strict about f.arguments or equivalent unqualified uses. */
-        if (!JS_ReportErrorFlagsAndNumber(cx, JSREPORT_WARNING | JSREPORT_STRICT, js_GetErrorMessage,
-                                          nullptr, JSMSG_DEPRECATED_USAGE, js_arguments_str)) {
-            return false;
-        }
-
-        ArgumentsObject *argsobj = ArgumentsObject::createUnexpected(cx, iter);
-        if (!argsobj)
-            return false;
-
-        // Disabling compiling of this script in IonMonkey.
-        // IonMonkey does not guarantee |f.arguments| can be
-        // fully recovered, so we try to mitigate observing this behavior by
-        // detecting its use early.
-        JSScript *script = iter.script();
-        jit::ForbidCompilation(cx, script);
-
-        vp.setObject(*argsobj);
-        return true;
-    }
-
-    if (JSID_IS_ATOM(id, cx->names().caller)) {
-        ++iter;
-        if (iter.done() || !iter.isFunctionFrame()) {
-            JS_ASSERT(vp.isNull());
-            return true;
-        }
-
-        /* Callsite clones should never escape to script. */
-        JSObject &maybeClone = iter.calleev().toObject();
-        if (maybeClone.is<JSFunction>())
-            vp.setObject(*maybeClone.as<JSFunction>().originalFunction());
-        else
-            vp.set(iter.calleev());
-
-        if (!cx->compartment()->wrap(cx, vp))
-            return false;
-
-        /*
-         * Censor the caller if we don't have full access to it.
-         */
-        RootedObject caller(cx, &vp.toObject());
-        if (caller->is<WrapperObject>() && Wrapper::wrapperHandler(caller)->hasSecurityPolicy()) {
-            vp.setNull();
-        } else if (caller->is<JSFunction>()) {
-            JSFunction *callerFun = &caller->as<JSFunction>();
-            if (callerFun->isInterpreted() && callerFun->strict()) {
-                JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, js_GetErrorMessage, nullptr,
-                                             JSMSG_CALLER_IS_STRICT);
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-    MOZ_CRASH("fun_getProperty");
-}
-
-/* NB: no sentinels at ends -- use ArrayLength to bound loops.
- * Properties censored into [[ThrowTypeError]] in strict mode. */
-static const uint16_t poisonPillProps[] = {
-    NAME_OFFSET(arguments),
-    NAME_OFFSET(caller),
-};
-
-static bool
 fun_enumerate(JSContext *cx, HandleObject obj)
 {
-    JS_ASSERT(obj->is<JSFunction>());
+    MOZ_ASSERT(obj->is<JSFunction>());
 
     RootedId id(cx);
     bool found;
 
     if (!obj->isBoundFunction() && !obj->as<JSFunction>().isArrow()) {
         id = NameToId(cx->names().prototype);
         if (!JSObject::hasProperty(cx, obj, id, &found))
             return false;
@@ -169,26 +73,342 @@ fun_enumerate(JSContext *cx, HandleObjec
     id = NameToId(cx->names().length);
     if (!JSObject::hasProperty(cx, obj, id, &found))
         return false;
 
     id = NameToId(cx->names().name);
     if (!JSObject::hasProperty(cx, obj, id, &found))
         return false;
 
-    for (unsigned i = 0; i < ArrayLength(poisonPillProps); i++) {
-        const uint16_t offset = poisonPillProps[i];
-        id = NameToId(AtomStateOffsetToName(cx->names(), offset));
-        if (!JSObject::hasProperty(cx, obj, id, &found))
-            return false;
+    return true;
+}
+
+bool
+IsFunction(HandleValue v)
+{
+    return v.isObject() && v.toObject().is<JSFunction>();
+}
+
+static bool
+AdvanceToActiveCallLinear(NonBuiltinScriptFrameIter &iter, HandleFunction fun)
+{
+    MOZ_ASSERT(!fun->isBuiltin());
+    MOZ_ASSERT(!fun->isBoundFunction(), "all bound functions are currently native (ergo builtin)");
+
+    for (; !iter.done(); ++iter) {
+        if (!iter.isFunctionFrame() || iter.isEvalFrame())
+            continue;
+        if (iter.callee() == fun)
+            return true;
+    }
+    return false;
+}
+
+static void
+ThrowTypeErrorBehavior(JSContext *cx)
+{
+    JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, js_GetErrorMessage, nullptr,
+                                 JSMSG_THROW_TYPE_ERROR);
+}
+
+// Beware: this function can be invoked on *any* function! That includes
+// natives, strict mode functions, bound functions, arrow functions,
+// self-hosted functions and constructors, asm.js functions, functions with
+// destructuring arguments and/or a rest argument, and probably a few more I
+// forgot. Turn back and save yourself while you still can. It's too late for
+// me.
+static bool
+ArgumentsRestrictions(JSContext *cx, HandleFunction fun)
+{
+    // Throw if the function is a strict mode function or a bound function.
+    if ((!fun->isBuiltin() && fun->isInterpreted() && fun->strict()) ||
+        fun->isBoundFunction())
+    {
+        ThrowTypeErrorBehavior(cx);
+        return false;
+    }
+
+    // Functions with rest arguments don't include a local |arguments| binding.
+    // Similarly, "arguments" shouldn't work on them.
+    if (fun->hasRest()) {
+        JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
+                             JSMSG_FUNCTION_ARGUMENTS_AND_REST);
+        return false;
+    }
+
+    // Otherwise emit a strict warning about |f.arguments| to discourage use of
+    // this non-standard, performance-harmful feature.
+    if (!JS_ReportErrorFlagsAndNumber(cx, JSREPORT_WARNING | JSREPORT_STRICT, js_GetErrorMessage,
+                                      nullptr, JSMSG_DEPRECATED_USAGE, js_arguments_str))
+    {
+        return false;
     }
 
     return true;
 }
 
+bool
+ArgumentsGetterImpl(JSContext *cx, CallArgs args)
+{
+    MOZ_ASSERT(IsFunction(args.thisv()));
+
+    RootedFunction fun(cx, &args.thisv().toObject().as<JSFunction>());
+    if (!ArgumentsRestrictions(cx, fun))
+        return false;
+
+    // FIXME: Bug 929642 will break "arguments" and "caller" properties on
+    //        builtin functions, at which point this condition should be added
+    //        to the early exit at the start of ArgumentsGuts.
+    if (fun->isBuiltin()) {
+        args.rval().setNull();
+        return true;
+    }
+
+    // Return null if this function wasn't found on the stack.
+    NonBuiltinScriptFrameIter iter(cx);
+    if (!AdvanceToActiveCallLinear(iter, fun)) {
+        args.rval().setNull();
+        return true;
+    }
+
+    Rooted<ArgumentsObject*> argsobj(cx, ArgumentsObject::createUnexpected(cx, iter));
+    if (!argsobj)
+        return false;
+
+    // Disabling compiling of this script in IonMonkey.  IonMonkey doesn't
+    // guarantee |f.arguments| can be fully recovered, so we try to mitigate
+    // observing this behavior by detecting its use early.
+    JSScript *script = iter.script();
+    jit::ForbidCompilation(cx, script);
+
+    args.rval().setObject(*argsobj);
+    return true;
+}
+
+static bool
+ArgumentsGetter(JSContext *cx, unsigned argc, Value *vp)
+{
+    CallArgs args = CallArgsFromVp(argc, vp);
+    return CallNonGenericMethod<IsFunction, ArgumentsGetterImpl>(cx, args);
+}
+
+bool
+ArgumentsSetterImpl(JSContext *cx, CallArgs args)
+{
+    MOZ_ASSERT(IsFunction(args.thisv()));
+
+    RootedFunction fun(cx, &args.thisv().toObject().as<JSFunction>());
+    if (!ArgumentsRestrictions(cx, fun))
+        return false;
+
+    // FIXME: Bug 929642 will break "arguments" and "caller" properties on
+    //        builtin functions, at which point this bit should be removed.
+    if (fun->isBuiltin()) {
+        args.rval().setUndefined();
+        return true;
+    }
+
+    // If the function passes the gauntlet, return |undefined|.
+    args.rval().setUndefined();
+    return true;
+}
+
+static bool
+ArgumentsSetter(JSContext *cx, unsigned argc, Value *vp)
+{
+    CallArgs args = CallArgsFromVp(argc, vp);
+    return CallNonGenericMethod<IsFunction, ArgumentsSetterImpl>(cx, args);
+}
+
+// Beware: this function can be invoked on *any* function! That includes
+// natives, strict mode functions, bound functions, arrow functions,
+// self-hosted functions and constructors, asm.js functions, functions with
+// destructuring arguments and/or a rest argument, and probably a few more I
+// forgot. Turn back and save yourself while you still can. It's too late for
+// me.
+static bool
+CallerRestrictions(JSContext *cx, HandleFunction fun)
+{
+    // Throw if the function is a strict mode function or a bound function.
+    if ((!fun->isBuiltin() && fun->isInterpreted() && fun->strict()) ||
+        fun->isBoundFunction())
+    {
+        ThrowTypeErrorBehavior(cx);
+        return false;
+    }
+
+    // Otherwise emit a strict warning about |f.caller| to discourage use of
+    // this non-standard, performance-harmful feature.
+    if (!JS_ReportErrorFlagsAndNumber(cx, JSREPORT_WARNING | JSREPORT_STRICT, js_GetErrorMessage,
+                                      nullptr, JSMSG_DEPRECATED_USAGE, js_caller_str))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool
+CallerGetterImpl(JSContext *cx, CallArgs args)
+{
+    MOZ_ASSERT(IsFunction(args.thisv()));
+
+    // Beware!  This function can be invoked on *any* function!  It can't
+    // assume it'll never be invoked on natives, strict mode functions, bound
+    // functions, or anything else that ordinarily has immutable .caller
+    // defined with [[ThrowTypeError]].
+    RootedFunction fun(cx, &args.thisv().toObject().as<JSFunction>());
+    if (!CallerRestrictions(cx, fun))
+        return false;
+
+    // FIXME: Bug 929642 will break "arguments" and "caller" properties on
+    //        builtin functions, at which point this condition should be added
+    //        to the early exit at the start of CallerRestrictions.
+    if (fun->isBuiltin()) {
+        args.rval().setNull();
+        return true;
+    }
+
+    // Also return null if this function wasn't found on the stack.
+    NonBuiltinScriptFrameIter iter(cx);
+    if (!AdvanceToActiveCallLinear(iter, fun)) {
+        args.rval().setNull();
+        return true;
+    }
+
+    ++iter;
+    if (iter.done() || !iter.isFunctionFrame()) {
+        args.rval().setNull();
+        return true;
+    }
+
+    // It might seem we need to replace call site clones with the original
+    // functions here.  But we're iterating over *non-builtin* frames, and the
+    // only call site-clonable scripts are for builtin, self-hosted functions
+    // (see assertions in js::CloneFunctionAtCallsite).  So the callee can't be
+    // a call site clone.
+    JSFunction *maybeClone = iter.callee();
+    MOZ_ASSERT(!maybeClone->nonLazyScript()->isCallsiteClone(),
+               "non-builtin functions aren't call site-clonable");
+
+    RootedObject caller(cx, maybeClone);
+    if (!cx->compartment()->wrap(cx, &caller))
+        return false;
+
+    // Censor the caller if we don't have full access to it.  If we do, but the
+    // caller is a function with strict mode code, throw a TypeError per ES5.
+    // If we pass these checks, we can return the computed caller.
+    {
+        JSObject *callerObj = CheckedUnwrap(caller);
+        if (!callerObj) {
+            args.rval().setNull();
+            return true;
+        }
+
+        JSFunction *callerFun = &callerObj->as<JSFunction>();
+        MOZ_ASSERT(!callerFun->isBuiltin(), "non-builtin iterator returned a builtin?");
+
+        if (callerFun->strict()) {
+            JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, js_GetErrorMessage, nullptr,
+                                         JSMSG_CALLER_IS_STRICT);
+            return false;
+        }
+    }
+
+    args.rval().setObject(*caller);
+    return true;
+}
+
+static bool
+CallerGetter(JSContext *cx, unsigned argc, Value *vp)
+{
+    CallArgs args = CallArgsFromVp(argc, vp);
+    return CallNonGenericMethod<IsFunction, CallerGetterImpl>(cx, args);
+}
+
+bool
+CallerSetterImpl(JSContext *cx, CallArgs args)
+{
+    MOZ_ASSERT(IsFunction(args.thisv()));
+
+    // Beware!  This function can be invoked on *any* function!  It can't
+    // assume it'll never be invoked on natives, strict mode functions, bound
+    // functions, or anything else that ordinarily has immutable .caller
+    // defined with [[ThrowTypeError]].
+    RootedFunction fun(cx, &args.thisv().toObject().as<JSFunction>());
+    if (!CallerRestrictions(cx, fun))
+        return false;
+
+    // Return |undefined| unless an error must be thrown.
+    args.rval().setUndefined();
+
+    // FIXME: Bug 929642 will break "arguments" and "caller" properties on
+    //        builtin functions, at which point this bit should be removed.
+    if (fun->isBuiltin())
+        return true;
+
+    // We can almost just return |undefined| here -- but if the caller function
+    // was strict mode code, we still have to throw a TypeError.  This requires
+    // computing the caller, checking that no security boundaries are crossed,
+    // and throwing a TypeError if the resulting caller is strict.
+
+    NonBuiltinScriptFrameIter iter(cx);
+    if (!AdvanceToActiveCallLinear(iter, fun))
+        return true;
+
+    ++iter;
+    if (iter.done() || !iter.isFunctionFrame())
+        return true;
+
+    // It might seem we need to replace call site clones with the original
+    // functions here.  But we're iterating over *non-builtin* frames, and the
+    // only call site-clonable scripts are for builtin, self-hosted functions
+    // (see assertions in js::CloneFunctionAtCallsite).  So the callee can't be
+    // a call site clone.
+    JSFunction *maybeClone = iter.callee();
+    MOZ_ASSERT(!maybeClone->nonLazyScript()->isCallsiteClone(),
+               "non-builtin functions aren't call site-clonable");
+
+    RootedObject caller(cx, maybeClone);
+    if (!cx->compartment()->wrap(cx, &caller)) {
+        cx->clearPendingException();
+        return true;
+    }
+
+    // If we don't have full access to the caller, or the caller is not strict,
+    // return undefined.  Otherwise throw a TypeError.
+    JSObject *callerObj = CheckedUnwrap(caller);
+    if (!callerObj)
+        return true;
+
+    JSFunction *callerFun = &callerObj->as<JSFunction>();
+    MOZ_ASSERT(!callerFun->isBuiltin(), "non-builtin iterator returned a builtin?");
+
+    if (callerFun->strict()) {
+        JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, js_GetErrorMessage, nullptr,
+                                     JSMSG_CALLER_IS_STRICT);
+        return false;
+    }
+
+    return true;
+}
+
+static bool
+CallerSetter(JSContext *cx, unsigned argc, Value *vp)
+{
+    CallArgs args = CallArgsFromVp(argc, vp);
+    return CallNonGenericMethod<IsFunction, CallerSetterImpl>(cx, args);
+}
+
+static const JSPropertySpec function_properties[] = {
+    JS_PSGS("arguments", ArgumentsGetter, ArgumentsSetter, 0),
+    JS_PSGS("caller", CallerGetter, CallerSetter, 0),
+    JS_PS_END
+};
+
 static JSObject *
 ResolveInterpretedFunctionPrototype(JSContext *cx, HandleObject obj)
 {
 #ifdef DEBUG
     JSFunction *fun = &obj->as<JSFunction>();
     JS_ASSERT(fun->isInterpreted() || fun->isAsmJSNative());
     JS_ASSERT(!fun->isFunctionPrototype());
 #endif
@@ -242,27 +462,17 @@ ResolveInterpretedFunctionPrototype(JSCo
     }
 
     return proto;
 }
 
 bool
 js::FunctionHasResolveHook(const JSAtomState &atomState, PropertyName *name)
 {
-    if (name == atomState.prototype || name == atomState.length || name == atomState.name)
-        return true;
-
-    for (unsigned i = 0; i < ArrayLength(poisonPillProps); i++) {
-        const uint16_t offset = poisonPillProps[i];
-
-        if (name == AtomStateOffsetToName(atomState, offset))
-            return true;
-    }
-
-    return false;
+    return name == atomState.prototype || name == atomState.length || name == atomState.name;
 }
 
 bool
 js::fun_resolve(JSContext *cx, HandleObject obj, HandleId id, MutableHandleObject objp)
 {
     if (!JSID_IS_ATOM(id))
         return true;
 
@@ -309,45 +519,16 @@ js::fun_resolve(JSContext *cx, HandleObj
         if (!DefineNativeProperty(cx, fun, id, v, JS_PropertyStub, JS_StrictPropertyStub,
                                   JSPROP_PERMANENT | JSPROP_READONLY)) {
             return false;
         }
         objp.set(fun);
         return true;
     }
 
-    for (unsigned i = 0; i < ArrayLength(poisonPillProps); i++) {
-        const uint16_t offset = poisonPillProps[i];
-
-        if (JSID_IS_ATOM(id, AtomStateOffsetToName(cx->names(), offset))) {
-            JS_ASSERT(!IsInternalFunctionObject(fun));
-
-            PropertyOp getter;
-            StrictPropertyOp setter;
-            unsigned attrs = JSPROP_PERMANENT | JSPROP_SHARED;
-            if (fun->isInterpretedLazy() && !fun->getOrCreateScript(cx))
-                return false;
-            if (fun->isInterpreted() ? fun->strict() : fun->isBoundFunction()) {
-                JSObject *throwTypeError = fun->global().getThrowTypeError();
-
-                getter = CastAsPropertyOp(throwTypeError);
-                setter = CastAsStrictPropertyOp(throwTypeError);
-                attrs |= JSPROP_GETTER | JSPROP_SETTER;
-            } else {
-                getter = fun_getProperty;
-                setter = JS_StrictPropertyStub;
-            }
-
-            if (!DefineNativeProperty(cx, fun, id, UndefinedHandleValue, getter, setter, attrs))
-                return false;
-            objp.set(fun);
-            return true;
-        }
-    }
-
     return true;
 }
 
 template<XDRMode mode>
 bool
 js::XDRInterpretedFunction(XDRState<mode> *xdr, HandleObject enclosingScope, HandleScript enclosingScript,
                            MutableHandleObject objp)
 {
@@ -583,33 +764,39 @@ JSFunction::trace(JSTracer *trc)
                 relazify(trc);
             } else {
                 MarkScriptUnbarriered(trc, &u.i.s.script_, "script");
             }
         } else if (isInterpretedLazy() && u.i.s.lazy_) {
             MarkLazyScriptUnbarriered(trc, &u.i.s.lazy_, "lazyScript");
         }
         if (u.i.env_)
-            MarkObjectUnbarriered(trc, &u.i.env_, "fun_callscope");
+            MarkObjectUnbarriered(trc, &u.i.env_, "fun_environment");
     }
 }
 
 static void
 fun_trace(JSTracer *trc, JSObject *obj)
 {
     obj->as<JSFunction>().trace(trc);
 }
 
+static bool
+ThrowTypeError(JSContext *cx, unsigned argc, Value *vp)
+{
+    ThrowTypeErrorBehavior(cx);
+    return false;
+}
+
 static JSObject *
 CreateFunctionConstructor(JSContext *cx, JSProtoKey key)
 {
     Rooted<GlobalObject*> self(cx, cx->global());
     RootedObject functionProto(cx, &self->getPrototype(JSProto_Function).toObject());
 
-    // Note that ctor is rooted purely for the JS_ASSERT at the end
     RootedObject ctor(cx, NewObjectWithGivenProto(cx, &JSFunction::class_, functionProto,
                                                   self, SingletonObject));
     if (!ctor)
         return nullptr;
     RootedObject functionCtor(cx, NewFunction(cx, ctor, Function, 1, JSFunction::NATIVE_CTOR, self,
                                               HandlePropertyName(cx->names().Function)));
     if (!functionCtor)
         return nullptr;
@@ -618,16 +805,17 @@ CreateFunctionConstructor(JSContext *cx,
     return functionCtor;
 
 }
 
 static JSObject *
 CreateFunctionPrototype(JSContext *cx, JSProtoKey key)
 {
     Rooted<GlobalObject*> self(cx, cx->global());
+
     RootedObject objectProto(cx, &self->getPrototype(JSProto_Object).toObject());
     JSObject *functionProto_ = NewObjectWithGivenProto(cx, &JSFunction::class_,
                                                        objectProto, self, SingletonObject);
     if (!functionProto_)
         return nullptr;
 
     RootedFunction functionProto(cx, &functionProto_->as<JSFunction>());
 
@@ -688,16 +876,31 @@ CreateFunctionPrototype(JSContext *cx, J
     /*
      * The default 'new' type of Function.prototype is required by type
      * inference to have unknown properties, to simplify handling of e.g.
      * CloneFunctionObject.
      */
     if (!JSObject::setNewTypeUnknown(cx, &JSFunction::class_, functionProto))
         return nullptr;
 
+    // Construct the unique [[%ThrowTypeError%]] function object, used only for
+    // "callee" and "caller" accessors on strict mode arguments objects.  (The
+    // spec also uses this for "arguments" and "caller" on various functions,
+    // but we're experimenting with implementing them using accessors on
+    // |Function.prototype| right now.)
+    RootedObject tte(cx, NewObjectWithGivenProto(cx, &JSFunction::class_, functionProto, self,
+                                                 SingletonObject));
+    if (!tte)
+        return nullptr;
+    RootedFunction throwTypeError(cx, NewFunction(cx, tte, ThrowTypeError, 0,
+                                                  JSFunction::NATIVE_FUN, self, js::NullPtr()));
+    if (!throwTypeError || !JSObject::preventExtensions(cx, throwTypeError))
+        return nullptr;
+    self->setThrowTypeError(throwTypeError);
+
     return functionProto;
 }
 
 const Class JSFunction::class_ = {
     js_Function_str,
     JSCLASS_NEW_RESOLVE | JSCLASS_IMPLEMENTS_BARRIERS |
     JSCLASS_HAS_CACHED_PROTO(JSProto_Function),
     JS_PropertyStub,         /* addProperty */
@@ -711,17 +914,18 @@ const Class JSFunction::class_ = {
     nullptr,                 /* call        */
     fun_hasInstance,
     nullptr,                 /* construct   */
     fun_trace,
     {
         CreateFunctionConstructor,
         CreateFunctionPrototype,
         nullptr,
-        function_methods
+        function_methods,
+        function_properties
     }
 };
 
 const Class* const js::FunctionClassPtr = &JSFunction::class_;
 
 /* Find the body of a function (not including braces). */
 bool
 js::FindBody(JSContext *cx, HandleFunction fun, HandleLinearString src, size_t *bodyStart,
--- a/js/src/jsfun.h
+++ b/js/src/jsfun.h
@@ -163,17 +163,18 @@ class JSFunction : public JSObject
     bool hasParallelNative() const {
         return isNative() && jitInfo() && jitInfo()->hasParallelNative();
     }
 
     bool isBuiltinFunctionConstructor();
 
     /* Returns the strictness of this function, which must be interpreted. */
     bool strict() const {
-        return nonLazyScript()->strict();
+        MOZ_ASSERT(isInterpreted());
+        return isInterpretedLazy() ? lazyScript()->strict() : nonLazyScript()->strict();
     }
 
     void setFlags(uint16_t flags) {
         this->flags_ = flags;
     }
 
     // Can be called multiple times by the parser.
     void setArgCount(uint16_t nargs) {
--- a/js/src/jsgcinlines.h
+++ b/js/src/jsgcinlines.h
@@ -611,17 +611,20 @@ AllocateObject(ThreadSafeContext *cx, Al
             TryNewNurseryObject<allowGC>(cx->asForkJoinContext(), thingSize, nDynamicSlots);
         if (obj)
             return obj;
     }
 #endif
 
     HeapSlot *slots = nullptr;
     if (nDynamicSlots) {
-        slots = cx->pod_malloc<HeapSlot>(nDynamicSlots);
+        if (cx->isExclusiveContext())
+            slots = cx->asExclusiveContext()->zone()->pod_malloc<HeapSlot>(nDynamicSlots);
+        else
+            slots = js_pod_malloc<HeapSlot>(nDynamicSlots);
         if (MOZ_UNLIKELY(!slots))
             return nullptr;
         js::Debug_SetSlotRangeToCrashOnTouch(slots, nDynamicSlots);
     }
 
     JSObject *obj = static_cast<JSObject *>(cx->allocator()->arenas.allocateFromFreeList(kind, thingSize));
     if (!obj)
         obj = static_cast<JSObject *>(js::gc::ArenaLists::refillFreeList<allowGC>(cx, kind));
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -91,17 +91,16 @@ CreateObjectConstructor(JSContext *cx, J
     return NewFunction(cx, ctor, obj_construct, 1, JSFunction::NATIVE_CTOR, self,
                        HandlePropertyName(cx->names().Object));
 }
 
 static JSObject *
 CreateObjectPrototype(JSContext *cx, JSProtoKey key)
 {
     Rooted<GlobalObject*> self(cx, cx->global());
-    cx->setDefaultCompartmentObjectIfUnset(self);
 
     JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
     JS_ASSERT(self->isNative());
 
     /*
      * Create |Object.prototype| first, mirroring CreateBlankProto but for the
      * prototype of the created object.
      */
@@ -117,44 +116,27 @@ CreateObjectPrototype(JSContext *cx, JSP
      */
     if (!JSObject::setNewTypeUnknown(cx, &JSObject::class_, objectProto))
         return nullptr;
 
     return objectProto;
 }
 
 static bool
-ThrowTypeError(JSContext *cx, unsigned argc, Value *vp)
-{
-    JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, js_GetErrorMessage, nullptr,
-                                 JSMSG_THROW_TYPE_ERROR);
-    return false;
-}
-
-static bool
 FinishObjectClassInit(JSContext *cx, JS::HandleObject ctor, JS::HandleObject proto)
 {
     Rooted<GlobalObject*> self(cx, cx->global());
 
     /* ES5 15.1.2.1. */
     RootedId evalId(cx, NameToId(cx->names().eval));
     JSObject *evalobj = DefineFunction(cx, self, evalId, IndirectEval, 1, JSFUN_STUB_GSOPS);
     if (!evalobj)
         return false;
     self->setOriginalEval(evalobj);
 
-    /* ES5 13.2.3: Construct the unique [[ThrowTypeError]] function object. */
-    RootedFunction throwTypeError(cx, NewFunction(cx, js::NullPtr(), ThrowTypeError, 0,
-                                                  JSFunction::NATIVE_FUN, self, js::NullPtr()));
-    if (!throwTypeError)
-        return false;
-    if (!JSObject::preventExtensions(cx, throwTypeError))
-        return false;
-    self->setThrowTypeError(throwTypeError);
-
     RootedObject intrinsicsHolder(cx);
     if (cx->runtime()->isSelfHostingGlobal(self)) {
         intrinsicsHolder = self;
     } else {
         intrinsicsHolder = NewObjectWithGivenProto(cx, &JSObject::class_, proto, self,
                                                    TenuredObject);
         if (!intrinsicsHolder)
             return false;
@@ -5971,28 +5953,52 @@ js_GetObjectSlotName(JSTracer *trc, char
         shape = obj->lastProperty();
         while (shape && (!shape->hasSlot() || shape->slot() != slot))
             shape = shape->previous();
     } else {
         shape = nullptr;
     }
 
     if (!shape) {
-        const char *slotname = nullptr;
-        if (obj->is<GlobalObject>()) {
-#define TEST_SLOT_MATCHES_PROTOTYPE(name,code,init,clasp)                     \
-            if ((code) == slot) { slotname = js_##name##_str; goto found; }
-            JS_FOR_EACH_PROTOTYPE(TEST_SLOT_MATCHES_PROTOTYPE)
+        do {
+            const char *slotname = nullptr;
+            const char *pattern = nullptr;
+            if (obj->is<GlobalObject>()) {
+                pattern = "CLASS_OBJECT(%s)";
+                if (false)
+                    ;
+#define TEST_SLOT_MATCHES_PROTOTYPE(name,code,init,clasp) \
+                else if ((code) == slot) { slotname = js_##name##_str; }
+                JS_FOR_EACH_PROTOTYPE(TEST_SLOT_MATCHES_PROTOTYPE)
 #undef TEST_SLOT_MATCHES_PROTOTYPE
-        }
-      found:
-        if (slotname)
-            JS_snprintf(buf, bufsize, "CLASS_OBJECT(%s)", slotname);
-        else
-            JS_snprintf(buf, bufsize, "**UNKNOWN SLOT %ld**", (long)slot);
+            } else {
+                pattern = "%s";
+                if (obj->is<ScopeObject>()) {
+                    if (slot == ScopeObject::enclosingScopeSlot()) {
+                        slotname = "enclosing_environment";
+                    } else if (obj->is<CallObject>()) {
+                        if (slot == CallObject::calleeSlot())
+                            slotname = "callee_slot";
+                    } else if (obj->is<DeclEnvObject>()) {
+                        if (slot == DeclEnvObject::lambdaSlot())
+                            slotname = "named_lambda";
+                    } else if (obj->is<DynamicWithObject>()) {
+                        if (slot == DynamicWithObject::objectSlot())
+                            slotname = "with_object";
+                        else if (slot == DynamicWithObject::thisSlot())
+                            slotname = "with_this";
+                    }
+                }
+            }
+
+            if (slotname)
+                JS_snprintf(buf, bufsize, pattern, slotname);
+            else
+                JS_snprintf(buf, bufsize, "**UNKNOWN SLOT %ld**", (long)slot);
+        } while (false);
     } else {
         jsid propid = shape->propid();
         if (JSID_IS_INT(propid)) {
             JS_snprintf(buf, bufsize, "%ld", (long)JSID_TO_INT(propid));
         } else if (JSID_IS_ATOM(propid)) {
             PutEscapedString(buf, bufsize, JSID_TO_ATOM(propid), 0);
         } else if (JSID_IS_SYMBOL(propid)) {
             JS_snprintf(buf, bufsize, "**SYMBOL KEY**");
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -632,18 +632,26 @@ JSObject::createArray(js::ExclusiveConte
 inline void
 JSObject::finish(js::FreeOp *fop)
 {
     if (hasDynamicSlots())
         fop->free_(slots);
 
     if (hasDynamicElements()) {
         js::ObjectElements *elements = getElementsHeader();
-        if (!elements->isCopyOnWrite() || elements->ownerObject() == this)
+        if (elements->isCopyOnWrite()) {
+            if (elements->ownerObject() == this) {
+                // Don't free the elements until object finalization finishes,
+                // so that other objects can access these elements while they
+                // are themselves finalized.
+                fop->freeLater(elements);
+            }
+        } else {
             fop->free_(elements);
+        }
     }
 }
 
 /* static */ inline bool
 JSObject::hasProperty(JSContext *cx, js::HandleObject obj,
                       js::HandleId id, bool *foundp)
 {
     JS::RootedObject pobj(cx);
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -953,17 +953,16 @@ class AutoNewContext
 
     bool enter(JSContext *cx) {
         JS_ASSERT(!JS_IsExceptionPending(cx));
         oldcx = cx;
         newcx = NewContext(JS_GetRuntime(cx));
         if (!newcx)
             return false;
         JS::ContextOptionsRef(newcx).setDontReportUncaught(true);
-        js::SetDefaultObjectForContext(newcx, JS::CurrentGlobalOrNull(cx));
 
         newRequest.emplace(newcx);
         newCompartment.emplace(newcx, JS::CurrentGlobalOrNull(cx));
         return true;
     }
 
     JSContext *get() { return newcx; }
 
@@ -2658,24 +2657,16 @@ EvalInFrame(JSContext *cx, unsigned argc
     ScriptFrameIter fi(cx);
     for (uint32_t i = 0; i < upCount; ++i, ++fi) {
         ScriptFrameIter next(fi);
         ++next;
         if (next.done())
             break;
     }
 
-    AutoSaveFrameChain sfc(cx);
-    mozilla::Maybe<AutoCompartment> ac;
-    if (saveCurrent) {
-        if (!sfc.save())
-            return false;
-        ac.emplace(cx, DefaultObjectForContextOrNull(cx));
-    }
-
     AutoStableStringChars stableChars(cx);
     if (!stableChars.initTwoByte(cx, str))
         return JSTRAP_ERROR;
 
     AbstractFramePtr frame = fi.abstractFramePtr();
     RootedScript fpscript(cx, frame.script());
 
     RootedObject scope(cx);
@@ -2687,16 +2678,22 @@ EvalInFrame(JSContext *cx, unsigned argc
     Rooted<Env*> env(cx, scope);
     if (!env)
         return false;
 
     if (!ComputeThis(cx, frame))
         return false;
     RootedValue thisv(cx, frame.thisValue());
 
+    AutoSaveFrameChain sfc(cx);
+    if (saveCurrent) {
+        if (!sfc.save())
+            return false;
+    }
+
     bool ok;
     {
         AutoCompartment ac(cx, env);
         ok = EvaluateInEnv(cx, env, thisv, frame, stableChars.twoByteRange(), fpscript->filename(),
                            JS_PCToLineNumber(cx, fpscript, fi.pc()), args.rval());
     }
     return ok;
 }
@@ -5920,16 +5917,18 @@ SetRuntimeOptions(JSRuntime *rt, const O
     compileOnly = op.getBoolOption('c');
     printTiming = op.getBoolOption('b');
     rt->profilingScripts = enableDisassemblyDumps = op.getBoolOption('D');
 
     jsCacheDir = op.getStringOption("js-cache");
     if (jsCacheDir) {
         if (!op.getBoolOption("no-js-cache-per-process"))
             jsCacheDir = JS_smprintf("%s/%u", jsCacheDir, (unsigned)getpid());
+        else
+            jsCacheDir = JS_strdup(rt, jsCacheDir);
         jsCacheAsmJSPath = JS_smprintf("%s/asmjs.cache", jsCacheDir);
     }
 
 #ifdef DEBUG
     dumpEntrainedVariables = op.getBoolOption("dump-entrained-variables");
 #endif
 
     return true;
@@ -5948,33 +5947,36 @@ Shell(JSContext *cx, OptionParser *op, c
     RootedObject glob(cx);
     JS::CompartmentOptions options;
     options.setVersion(JSVERSION_LATEST);
     glob = NewGlobalObject(cx, options, nullptr);
     if (!glob)
         return 1;
 
     JSAutoCompartment ac(cx, glob);
-    js::SetDefaultObjectForContext(cx, glob);
 
     JSObject *envobj = JS_DefineObject(cx, glob, "environment", &env_class);
     if (!envobj)
         return 1;
     JS_SetPrivate(envobj, envp);
 
     int result = ProcessArgs(cx, glob, op);
 
     if (enableDisassemblyDumps)
         JS_DumpCompartmentPCCounts(cx);
 
     if (!op->getBoolOption("no-js-cache-per-process")) {
-        if (jsCacheAsmJSPath)
+        if (jsCacheAsmJSPath) {
             unlink(jsCacheAsmJSPath);
-        if (jsCacheDir)
+            JS_free(cx, const_cast<char *>(jsCacheAsmJSPath));
+        }
+        if (jsCacheDir) {
             rmdir(jsCacheDir);
+            JS_free(cx, const_cast<char *>(jsCacheDir));
+        }
     }
 
     return result;
 }
 
 static void
 MaybeOverrideOutFileFromEnv(const char* const envVar,
                             FILE* defaultOut,
--- a/js/src/tests/ecma_5/Function/builtin-no-construct.js
+++ b/js/src/tests/ecma_5/Function/builtin-no-construct.js
@@ -11,17 +11,17 @@ function checkMethod(method) {
         assertEq(e.message, "method is not a constructor");
     }
 }
 
 function checkMethods(proto) {
     var names = Object.getOwnPropertyNames(proto);
     for (var i = 0; i < names.length; i++) {
         var name = names[i];
-        if (name == "constructor")
+        if (["constructor", "arguments", "caller"].indexOf(name) >= 0)
             continue;
         var prop = proto[name];
         if (typeof prop === "function")
             checkMethod(prop);
     }
 }
 
 checkMethod(Function.prototype);
--- a/js/src/tests/ecma_5/Function/function-bind.js
+++ b/js/src/tests/ecma_5/Function/function-bind.js
@@ -234,44 +234,38 @@ bound.foo = 17;
 var fooDesc = Object.getOwnPropertyDescriptor(bound, "foo");
 assertEq(fooDesc.value, 17);
 assertEq(fooDesc.writable, true);
 assertEq(fooDesc.enumerable, true);
 assertEq(fooDesc.configurable, true);
 
 
 /*
- * 19. Let thrower be the [[ThrowTypeError]] function Object (13.2.3).
- * 20. Call the [[DefineOwnProperty]] internal method of F with arguments
- *     "caller", PropertyDescriptor {[[Get]]: thrower, [[Set]]: thrower,
- *     [[Enumerable]]: false, [[Configurable]]: false}, and false.
- * 21. Call the [[DefineOwnProperty]] internal method of F with arguments
- *     "arguments", PropertyDescriptor {[[Get]]: thrower, [[Set]]: thrower,
- *     [[Enumerable]]: false, [[Configurable]]: false}, and false.
+ * Steps 19-21 are removed from ES6, instead implemented through "arguments" and
+ * "caller" accessors on Function.prototype.  So no own properties, but do check
+ * for the same observable behavior (modulo where the accessors live).
  */
-function f() { "use strict"; }
-var canonicalTTE = Object.getOwnPropertyDescriptor(f, "caller").get;
+function strict() { "use strict"; }
+function nonstrict() {}
 
-var tte;
+function testBound(fun)
+{
+  var boundf = fun.bind();
 
-var boundf = f.bind();
+  assertEq(Object.getOwnPropertyDescriptor(boundf, "arguments"), undefined,
+           "should be no arguments property");
+  assertEq(Object.getOwnPropertyDescriptor(boundf, "caller"), undefined,
+           "should be no caller property");
 
-var boundfCaller = Object.getOwnPropertyDescriptor(boundf, "caller");
-assertEq("get" in boundfCaller, true);
-assertEq("set" in boundfCaller, true);
-tte = boundfCaller.get;
-assertEq(tte, canonicalTTE);
-assertEq(tte, boundfCaller.set);
+  expectThrowTypeError(function() { return boundf.arguments; });
+  expectThrowTypeError(function() { return boundf.caller; });
+}
 
-var boundfArguments = Object.getOwnPropertyDescriptor(boundf, "arguments");
-assertEq("get" in boundfArguments, true);
-assertEq("set" in boundfArguments, true);
-tte = boundfArguments.get;
-assertEq(tte, canonicalTTE);
-assertEq(tte, boundfArguments.set);
+testBound(strict);
+testBound(nonstrict);
 
 
 /* 22. Return F. */
 var passim = function p(){}.bind(1);
 assertEq(typeof passim, "function");
 
 
 /******************************************************************************/
--- a/js/src/tests/ecma_5/Function/function-caller.js
+++ b/js/src/tests/ecma_5/Function/function-caller.js
@@ -32,56 +32,14 @@ function expectTypeError(fun)
 }
 
 function bar() { "use strict"; }
 expectTypeError(function barCaller() { bar.caller; });
 
 function baz() { "use strict"; return 17; }
 expectTypeError(function bazCaller() { baz.caller; });
 
-
-// accessor identity
-
-function strictMode() { "use strict"; return 42; }
-var canonicalTTE = Object.getOwnPropertyDescriptor(strictMode, "caller").get;
-
-var barCaller = Object.getOwnPropertyDescriptor(bar, "caller");
-assertEq("get" in barCaller, true);
-assertEq("set" in barCaller, true);
-assertEq(barCaller.get, canonicalTTE);
-assertEq(barCaller.set, canonicalTTE);
-
-var barArguments = Object.getOwnPropertyDescriptor(bar, "arguments");
-assertEq("get" in barArguments, true);
-assertEq("set" in barArguments, true);
-assertEq(barArguments.get, canonicalTTE);
-assertEq(barArguments.set, canonicalTTE);
-
-var bazCaller = Object.getOwnPropertyDescriptor(baz, "caller");
-assertEq("get" in bazCaller, true);
-assertEq("set" in bazCaller, true);
-assertEq(bazCaller.get, canonicalTTE);
-assertEq(bazCaller.set, canonicalTTE);
-
-var bazArguments = Object.getOwnPropertyDescriptor(baz, "arguments");
-assertEq("get" in bazArguments, true);
-assertEq("set" in bazArguments, true);
-assertEq(bazArguments.get, canonicalTTE);
-assertEq(bazArguments.set, canonicalTTE);
-
-
-// [[ThrowTypeError]] characteristics
-
-assertEq(Object.prototype.toString.call(canonicalTTE), "[object Function]");
-assertEq(Object.getPrototypeOf(canonicalTTE), Function.prototype);
-assertEq(canonicalTTE.length, 0);
-assertEq(Object.isExtensible(canonicalTTE), false);
-canonicalTTE.lumpy = 17;
-assertEq(canonicalTTE.hasOwnProperty("lumpy"), false);
-assertEq("lumpy" in canonicalTTE, false);
-expectTypeError(function setTTEProp() { "use strict"; canonicalTTE.x = 42; });
-
 /******************************************************************************/
 
 if (typeof reportCompare === "function")
   reportCompare(true, true);
 
 print("All tests passed!");
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_5/extensions/builtin-function-arguments-caller.js
@@ -0,0 +1,60 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+
+var gTestfile = 'builtin-function-arguments-caller.js';
+var BUGNUMBER = 929642;
+var summary =
+  "Built-in functions defined in ECMAScript pick up arguments/caller " +
+  "properties from Function.prototype";
+
+print(BUGNUMBER + ": " + summary);
+
+/**************
+ * BEGIN TEST *
+ **************/
+
+function expectNoProperty(obj, prop)
+{
+  var desc = Object.getOwnPropertyDescriptor(obj, prop);
+  assertEq(desc, undefined,
+           "should be no '" + prop + "' property on " + obj);
+}
+
+// Test a builtin that's native.
+expectNoProperty(Object, "arguments");
+expectNoProperty(Object, "caller");
+
+// Also test a builtin that's self-hosted.
+expectNoProperty(Array.prototype.indexOf, "arguments");
+expectNoProperty(Array.prototype.indexOf, "caller");
+
+// Test the Function construct for good measure, because it's so intricately
+// invovled in bootstrapping.
+expectNoProperty(Function, "arguments");
+expectNoProperty(Function, "caller");
+
+var argsDesc = Object.getOwnPropertyDescriptor(Function.prototype, "arguments");
+var callerDesc = Object.getOwnPropertyDescriptor(Function.prototype, "caller");
+
+var argsGet = argsDesc.get, argsSet = argsDesc.set;
+
+expectNoProperty(argsGet, "arguments");
+expectNoProperty(argsGet, "caller");
+expectNoProperty(argsSet, "arguments");
+expectNoProperty(argsSet, "caller");
+
+var callerGet = callerDesc.get, callerSet = callerDesc.set;
+
+expectNoProperty(callerGet, "arguments");
+expectNoProperty(callerGet, "caller");
+expectNoProperty(callerSet, "arguments");
+expectNoProperty(callerSet, "caller");
+
+/******************************************************************************/
+
+if (typeof reportCompare === "function")
+  reportCompare(true, true);
+
+print("Tests complete");
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_5/extensions/function-caller-strict-cross-global.js
@@ -0,0 +1,28 @@
+// |reftest| skip-if(!xulRuntime.shell) -- needs newGlobal()
+// Any copyright is dedicated to the Public Domain.
+// http://creativecommons.org/licenses/publicdomain/
+
+var g1 = newGlobal();
+g1.evaluate("function f() { return f.caller; }");
+
+var g2 = newGlobal();
+g2.f = g1.f;
+
+try
+{
+  g2.evaluate("function g() { 'use strict'; return f(); } g()");
+  throw new Error("failed to throw");
+}
+catch (e)
+{
+  assertEq(e.constructor.name, "TypeError",
+           "expected TypeError accessing strict .caller across globals, got " +
+           e);
+}
+
+/******************************************************************************/
+
+if (typeof reportCompare === "function")
+  reportCompare(true, true);
+
+print("Tests complete");
new file mode 100644
--- /dev/null
+++ b/js/src/tests/function-arguments-caller-changes.diff
@@ -0,0 +1,234 @@
+diff --git a/js/src/tests/test262/ch13/13.2/13.2-29-s.js b/js/src/tests/test262/ch13/13.2/13.2-29-s.js
+--- a/js/src/tests/test262/ch13/13.2/13.2-29-s.js
++++ b/js/src/tests/test262/ch13/13.2/13.2-29-s.js
+@@ -8,12 +8,12 @@
+  * @description StrictMode - property named 'caller' of function objects is not configurable
+  * @onlyStrict
+  */
+ 
+ 
+ 
+ function testcase() {
+         function foo() {"use strict";}
+-        return ! Object.getOwnPropertyDescriptor(foo, 
+-                                                  "caller").configurable;
++        return Object.getOwnPropertyDescriptor(foo, 
++                                               "caller") === undefined;
+ }
+-runTestCase(testcase);
+\ No newline at end of file
++runTestCase(testcase);
+diff --git a/js/src/tests/test262/ch13/13.2/13.2-30-s.js b/js/src/tests/test262/ch13/13.2/13.2-30-s.js
+--- a/js/src/tests/test262/ch13/13.2/13.2-30-s.js
++++ b/js/src/tests/test262/ch13/13.2/13.2-30-s.js
+@@ -7,12 +7,12 @@
+  * @path ch13/13.2/13.2-30-s.js
+  * @description StrictMode - property named 'caller' of function objects is not configurable
+  * @onlyStrict
+  */
+ 
+ 
+ 
+ function testcase() {
+-        return ! Object.getOwnPropertyDescriptor(Function("'use strict';"), 
+-                                                  "caller").configurable;
++        return Object.getOwnPropertyDescriptor(Function("'use strict';"), 
++                                               "caller") === undefined;
+ }
+-runTestCase(testcase);
+\ No newline at end of file
++runTestCase(testcase);
+diff --git a/js/src/tests/test262/ch13/13.2/13.2-31-s.js b/js/src/tests/test262/ch13/13.2/13.2-31-s.js
+--- a/js/src/tests/test262/ch13/13.2/13.2-31-s.js
++++ b/js/src/tests/test262/ch13/13.2/13.2-31-s.js
+@@ -7,12 +7,12 @@
+  * @path ch13/13.2/13.2-31-s.js
+  * @description StrictMode - property named 'caller' of function objects is not configurable
+  * @onlyStrict
+  */
+ 
+ 
+ 
+ function testcase() {
+-        return ! Object.getOwnPropertyDescriptor(new Function("'use strict';"), 
+-                                                  "caller").configurable;
++        return Object.getOwnPropertyDescriptor(new Function("'use strict';"), 
++                                               "caller") === undefined;
+ }
+-runTestCase(testcase);
+\ No newline at end of file
++runTestCase(testcase);
+diff --git a/js/src/tests/test262/ch13/13.2/13.2-32-s.js b/js/src/tests/test262/ch13/13.2/13.2-32-s.js
+--- a/js/src/tests/test262/ch13/13.2/13.2-32-s.js
++++ b/js/src/tests/test262/ch13/13.2/13.2-32-s.js
+@@ -8,12 +8,12 @@
+  * @description StrictMode - property named 'caller' of function objects is not configurable
+  * @onlyStrict
+  */
+ 
+ 
+ 
+ function testcase() {
+         var funcExpr = function () { "use strict";};
+-        return ! Object.getOwnPropertyDescriptor(funcExpr, 
+-                                                  "caller").configurable;
++        return Object.getOwnPropertyDescriptor(funcExpr, 
++                                                  "caller") === undefined;
+ }
+-runTestCase(testcase);
+\ No newline at end of file
++runTestCase(testcase);
+diff --git a/js/src/tests/test262/ch13/13.2/13.2-33-s.js b/js/src/tests/test262/ch13/13.2/13.2-33-s.js
+--- a/js/src/tests/test262/ch13/13.2/13.2-33-s.js
++++ b/js/src/tests/test262/ch13/13.2/13.2-33-s.js
+@@ -8,12 +8,12 @@
+  * @description StrictMode - property named 'arguments' of function objects is not configurable
+  * @onlyStrict
+  */
+ 
+ 
+ 
+ function testcase() {
+         function foo() {"use strict";}
+-        return ! Object.getOwnPropertyDescriptor(foo, 
+-                                                  "arguments").configurable;
++        return Object.getOwnPropertyDescriptor(foo, 
++                                               "arguments") === undefined;
+ }
+-runTestCase(testcase);
+\ No newline at end of file
++runTestCase(testcase);
+diff --git a/js/src/tests/test262/ch13/13.2/13.2-34-s.js b/js/src/tests/test262/ch13/13.2/13.2-34-s.js
+--- a/js/src/tests/test262/ch13/13.2/13.2-34-s.js
++++ b/js/src/tests/test262/ch13/13.2/13.2-34-s.js
+@@ -7,12 +7,12 @@
+  * @path ch13/13.2/13.2-34-s.js
+  * @description StrictMode - property named 'arguments' of function objects is not configurable
+  * @onlyStrict
+  */
+ 
+ 
+ 
+ function testcase() {
+-        return ! Object.getOwnPropertyDescriptor(Function("'use strict';"), 
+-                                                  "arguments").configurable;
++        return Object.getOwnPropertyDescriptor(Function("'use strict';"), 
++                                               "arguments") === undefined;
+ }
+-runTestCase(testcase);
+\ No newline at end of file
++runTestCase(testcase);
+diff --git a/js/src/tests/test262/ch13/13.2/13.2-35-s.js b/js/src/tests/test262/ch13/13.2/13.2-35-s.js
+--- a/js/src/tests/test262/ch13/13.2/13.2-35-s.js
++++ b/js/src/tests/test262/ch13/13.2/13.2-35-s.js
+@@ -7,12 +7,12 @@
+  * @path ch13/13.2/13.2-35-s.js
+  * @description StrictMode - property named 'arguments' of function objects is not configurable
+  * @onlyStrict
+  */
+ 
+ 
+ 
+ function testcase() {
+-        return ! Object.getOwnPropertyDescriptor(new Function("'use strict';"), 
+-                                                  "arguments").configurable;
++        return Object.getOwnPropertyDescriptor(new Function("'use strict';"), 
++                                               "arguments") === undefined;
+ }
+-runTestCase(testcase);
+\ No newline at end of file
++runTestCase(testcase);
+diff --git a/js/src/tests/test262/ch13/13.2/13.2-36-s.js b/js/src/tests/test262/ch13/13.2/13.2-36-s.js
+--- a/js/src/tests/test262/ch13/13.2/13.2-36-s.js
++++ b/js/src/tests/test262/ch13/13.2/13.2-36-s.js
+@@ -8,12 +8,12 @@
+  * @description StrictMode - property named 'arguments' of function objects is not configurable
+  * @onlyStrict
+  */
+ 
+ 
+ 
+ function testcase() {
+         var funcExpr = function () { "use strict";};
+-        return ! Object.getOwnPropertyDescriptor(funcExpr, 
+-                                                  "arguments").configurable;
++        return Object.getOwnPropertyDescriptor(funcExpr, 
++                                                "arguments") === undefined;
+ }
+-runTestCase(testcase);
+\ No newline at end of file
++runTestCase(testcase);
+diff --git a/js/src/tests/test262/ch13/13.2/S13.2.3_A1.js b/js/src/tests/test262/ch13/13.2/S13.2.3_A1.js
+--- a/js/src/tests/test262/ch13/13.2/S13.2.3_A1.js
++++ b/js/src/tests/test262/ch13/13.2/S13.2.3_A1.js
+@@ -1,49 +1,61 @@
+ // Copyright 2011 Google Inc.  All rights reserved.
+ // This code is governed by the BSD license found in the LICENSE file.
+ 
+ /**
+  * @path ch13/13.2/S13.2.3_A1.js
+- * @description check that all poisoning use the [[ThrowTypeError]]
++ * @description check that strict mode functions/arguments have
++ *   [[ThrowTypeError]]-like behavior
+  * function object.
+  * @onlyStrict
+  */
+ 
+ "use strict";
+-var poison = Object.getOwnPropertyDescriptor(function() {}, 'caller').get;
++var poison = Object.getOwnPropertyDescriptor(Function.prototype, 'caller').get;
+ 
+ if (typeof poison !== 'function') {
+   $ERROR("#1: A strict function's .caller should be poisoned with a function");
+ }
+ var threw = null;
+ try {
+-  poison();
++  poison.call(function() {});
+ } catch (err) {
+   threw = err;
+ }
+ if (!threw || !(threw instanceof TypeError)) {
+   $ERROR("#2: Poisoned property should throw TypeError");
+ }
+ 
++function checkNotPresent(obj, name) {
++  var desc = Object.getOwnPropertyDescriptor(obj, name);
++  if (desc !== undefined) {
++    $ERROR("#3: " + name + " should not appear as a descriptor");
++  }
++}
++
++var argumentsPoison =
++  Object.getOwnPropertyDescriptor(function() { return arguments; }(),
++                                  "callee").get;
++
+ function checkPoison(obj, name) {
+   var desc = Object.getOwnPropertyDescriptor(obj, name);
+   if (desc.enumerable) {
+     $ERROR("#3: Poisoned " + name + " should not be enumerable");
+   }
+   if (desc.configurable) {
+     $ERROR("#4: Poisoned " + name + " should not be configurable");
+   }
+-  if (poison !== desc.get) {
++  if (argumentsPoison !== desc.get) {
+     $ERROR("#5: " + name + "'s getter not poisoned with same poison");
+   }
+-  if (poison !== desc.set) {
++  if (argumentsPoison !== desc.set) {
+     $ERROR("#6: " + name + "'s setter not poisoned with same poison");
+   }
+ }
+ 
+-checkPoison(function() {}, 'caller');
+-checkPoison(function() {}, 'arguments');
++checkNotPresent(function() {}, 'caller');
++checkNotPresent(function() {}, 'arguments');
+ checkPoison((function() { return arguments; })(), 'caller');
+ checkPoison((function() { return arguments; })(), 'callee');
+-checkPoison((function() {}).bind(null), 'caller');
+-checkPoison((function() {}).bind(null), 'arguments');
++checkNotPresent((function() {}).bind(null), 'caller');
++checkNotPresent((function() {}).bind(null), 'arguments');
+ 
--- a/js/src/tests/js1_8_5/extensions/findReferences-02.js
+++ b/js/src/tests/js1_8_5/extensions/findReferences-02.js
@@ -4,22 +4,22 @@
 
 if (typeof findReferences == "function") {
     (function f() {
          assertEq(referencesVia(arguments, 'callee', f), true);
      })();
 
     var o = ({});
 
-    function returnHeavy(y) { eval(''); return function heavy() { return y; }; }
-    assertEq(referencesVia(returnHeavy(o), 'fun_callscope; y', o), true);
-    assertEq(referencesVia(returnHeavy(o), 'fun_callscope; shape; base; parent', this), true);
+    function returnHeavy(y) { eval(''); Math.sin(); return function heavy() { return y; }; }
+    assertEq(referencesVia(returnHeavy(o), 'fun_environment; y', o), true);
+    assertEq(referencesVia(returnHeavy(o), 'fun_environment; enclosing_environment', this), true);
 
     function returnBlock(z) { eval(''); let(w = z) { return function block() { return w; }; }; }
-    assertEq(referencesVia(returnBlock(o), 'fun_callscope; w', o), true);
+    assertEq(referencesVia(returnBlock(o), 'fun_environment; w', o), true);
 
     function returnWithObj(v) { with(v) return function withObj() { return u; }; }
-    assertEq(referencesVia(returnWithObj(o), 'fun_callscope; type; type_proto', o), true);
+    assertEq(referencesVia(returnWithObj(o), 'fun_environment; with_object', o), true);
 
     reportCompare(true, true);
 } else {
     reportCompare(true, true, "test skipped: findReferences is not a function");
 }
--- a/js/src/tests/js1_8_5/extensions/typedarray.js
+++ b/js/src/tests/js1_8_5/extensions/typedarray.js
@@ -576,61 +576,61 @@ function test()
     // pulled into the ES spec, so for now this is disallowed.
     if (false) {
         check(function () simple.byteLength == 12);
         getter = Object.getOwnPropertyDescriptor(Int8Array.prototype, 'byteLength').get;
         Object.defineProperty(Int8Array.prototype, 'byteLength', { get: function () { return 1 + getter.apply(this) } });
         check(function () simple.byteLength == 13);
     }
 
-    // test move()
+    // test copyWithin()
     var numbers = [ 0, 1, 2, 3, 4, 5, 6, 7, 8 ];
 
     function tastring(tarray) {
         return [ x for (x of tarray) ].toString();
     }
 
-    function checkMove(offset, start, end, dest, want) {
+    function checkCopyWithin(offset, start, end, dest, want) {
         var numbers_buffer = new Uint8Array(numbers).buffer;
         var view = new Int8Array(numbers_buffer, offset);
-        view.move(start, end, dest);
+        view.copyWithin(dest, start, end);
         check(function () tastring(view) == want.toString());
         if (tastring(view) != want.toString()) {
             print("Wanted: " + want.toString());
             print("Got   : " + tastring(view));
         }
     }
 
-    // basic move [2,5) -> 4
-    checkMove(0, 2, 5, 4, [ 0, 1, 2, 3, 2, 3, 4, 7, 8 ]);
+    // basic copyWithin [2,5) -> 4
+    checkCopyWithin(0, 2, 5, 4, [ 0, 1, 2, 3, 2, 3, 4, 7, 8 ]);
 
     // negative values should count from end
-    checkMove(0, -7,  5,  4, [ 0, 1, 2, 3, 2, 3, 4, 7, 8 ]);
-    checkMove(0,  2, -4,  4, [ 0, 1, 2, 3, 2, 3, 4, 7, 8 ]);
-    checkMove(0,  2,  5, -5, [ 0, 1, 2, 3, 2, 3, 4, 7, 8 ]);
-    checkMove(0, -7, -4, -5, [ 0, 1, 2, 3, 2, 3, 4, 7, 8 ]);
+    checkCopyWithin(0, -7,  5,  4, [ 0, 1, 2, 3, 2, 3, 4, 7, 8 ]);
+    checkCopyWithin(0,  2, -4,  4, [ 0, 1, 2, 3, 2, 3, 4, 7, 8 ]);
+    checkCopyWithin(0,  2,  5, -5, [ 0, 1, 2, 3, 2, 3, 4, 7, 8 ]);
+    checkCopyWithin(0, -7, -4, -5, [ 0, 1, 2, 3, 2, 3, 4, 7, 8 ]);
 
     // offset
-    checkMove(2, 0, 3, 4, [ 2, 3, 4, 5, 2, 3, 4 ]);
+    checkCopyWithin(2, 0, 3, 4, [ 2, 3, 4, 5, 2, 3, 4 ]);
 
     // clipping
-    checkMove(0,  5000,  6000, 0, [ 0, 1, 2, 3, 4, 5, 6, 7, 8 ]);
-    checkMove(0, -5000, -6000, 0, [ 0, 1, 2, 3, 4, 5, 6, 7, 8 ]);
-    checkMove(0, -5000,  6000, 0, [ 0, 1, 2, 3, 4, 5, 6, 7, 8 ]);
-    checkMove(0,  5000,  6000, 1, [ 0, 1, 2, 3, 4, 5, 6, 7, 8 ]);
-    checkMove(0, -5000, -6000, 1, [ 0, 1, 2, 3, 4, 5, 6, 7, 8 ]);
-    checkMove(0,  5000,  6000, 0, [ 0, 1, 2, 3, 4, 5, 6, 7, 8 ]);
-    checkMove(2, -5000, -6000, 0, [ 2, 3, 4, 5, 6, 7, 8 ]);
-    checkMove(2, -5000,  6000, 0, [ 2, 3, 4, 5, 6, 7, 8 ]);
-    checkMove(2,  5000,  6000, 1, [ 2, 3, 4, 5, 6, 7, 8 ]);
-    checkMove(2, -5000, -6000, 1, [ 2, 3, 4, 5, 6, 7, 8 ]);
+    checkCopyWithin(0,  5000,  6000, 0, [ 0, 1, 2, 3, 4, 5, 6, 7, 8 ]);
+    checkCopyWithin(0, -5000, -6000, 0, [ 0, 1, 2, 3, 4, 5, 6, 7, 8 ]);
+    checkCopyWithin(0, -5000,  6000, 0, [ 0, 1, 2, 3, 4, 5, 6, 7, 8 ]);
+    checkCopyWithin(0,  5000,  6000, 1, [ 0, 1, 2, 3, 4, 5, 6, 7, 8 ]);
+    checkCopyWithin(0, -5000, -6000, 1, [ 0, 1, 2, 3, 4, 5, 6, 7, 8 ]);
+    checkCopyWithin(0,  5000,  6000, 0, [ 0, 1, 2, 3, 4, 5, 6, 7, 8 ]);
+    checkCopyWithin(2, -5000, -6000, 0, [ 2, 3, 4, 5, 6, 7, 8 ]);
+    checkCopyWithin(2, -5000,  6000, 0, [ 2, 3, 4, 5, 6, 7, 8 ]);
+    checkCopyWithin(2,  5000,  6000, 1, [ 2, 3, 4, 5, 6, 7, 8 ]);
+    checkCopyWithin(2, -5000, -6000, 1, [ 2, 3, 4, 5, 6, 7, 8 ]);
 
-    checkMove(2, -5000,    3, 1,     [ 2, 2, 3, 4, 6, 7, 8 ]);
-    checkMove(2,     1, 6000, 0,     [ 3, 4, 5, 6, 7, 8, 8 ]);
-    checkMove(2,     1, 6000, -4000, [ 3, 4, 5, 6, 7, 8, 8 ]);
+    checkCopyWithin(2, -5000,    3, 1,     [ 2, 2, 3, 4, 6, 7, 8 ]);
+    checkCopyWithin(2,     1, 6000, 0,     [ 3, 4, 5, 6, 7, 8, 8 ]);
+    checkCopyWithin(2,     1, 6000, -4000, [ 3, 4, 5, 6, 7, 8, 8 ]);
 
     testBufferManagement();
 
     print ("done");
 
     reportCompare(0, TestFailCount, "typed array tests");
 
     exitFunc ('test');
--- a/js/src/tests/js1_8_5/regress/regress-591846.js
+++ b/js/src/tests/js1_8_5/regress/regress-591846.js
@@ -46,19 +46,16 @@ function check(obj, name, value, readonl
     // Assert that the right getter result "stuck".
     assertEq(obj[name], value);
 
     // Test that it is operationally non-writable now.
     obj[name] = "eek!";
     assertEq(obj[name], value);
 }
 
-check(Object, 'caller', null, false);
-check(Object, 'arguments', null, false);
-
 // Reset RegExp.leftContext to the empty string.
 /x/.test('x');
 
 var d = Object.getOwnPropertyDescriptor(RegExp, "leftContext");
 assertEq(d.set, undefined);
 assertEq(typeof d.get, "function");
 assertEq(d.enumerable, true);
 assertEq(d.configurable, false);
--- a/js/src/tests/test262/ch13/13.2/13.2-29-s.js
+++ b/js/src/tests/test262/ch13/13.2/13.2-29-s.js
@@ -8,12 +8,12 @@
  * @description StrictMode - property named 'caller' of function objects is not configurable
  * @onlyStrict
  */
 
 
 
 function testcase() {
         function foo() {"use strict";}
-        return ! Object.getOwnPropertyDescriptor(foo, 
-                                                  "caller").configurable;
+        return Object.getOwnPropertyDescriptor(foo, 
+                                               "caller") === undefined;
 }
-runTestCase(testcase);
\ No newline at end of file
+runTestCase(testcase);
--- a/js/src/tests/test262/ch13/13.2/13.2-30-s.js
+++ b/js/src/tests/test262/ch13/13.2/13.2-30-s.js
@@ -7,12 +7,12 @@
  * @path ch13/13.2/13.2-30-s.js
  * @description StrictMode - property named 'caller' of function objects is not configurable
  * @onlyStrict
  */
 
 
 
 function testcase() {
-        return ! Object.getOwnPropertyDescriptor(Function("'use strict';"), 
-                                                  "caller").configurable;
+        return Object.getOwnPropertyDescriptor(Function("'use strict';"), 
+                                               "caller") === undefined;
 }
-runTestCase(testcase);
\ No newline at end of file
+runTestCase(testcase);
--- a/js/src/tests/test262/ch13/13.2/13.2-31-s.js
+++ b/js/src/tests/test262/ch13/13.2/13.2-31-s.js
@@ -7,12 +7,12 @@
  * @path ch13/13.2/13.2-31-s.js
  * @description StrictMode - property named 'caller' of function objects is not configurable
  * @onlyStrict
  */
 
 
 
 function testcase() {
-        return ! Object.getOwnPropertyDescriptor(new Function("'use strict';"), 
-                                                  "caller").configurable;
+        return Object.getOwnPropertyDescriptor(new Function("'use strict';"), 
+                                               "caller") === undefined;
 }
-runTestCase(testcase);
\ No newline at end of file
+runTestCase(testcase);
--- a/js/src/tests/test262/ch13/13.2/13.2-32-s.js
+++ b/js/src/tests/test262/ch13/13.2/13.2-32-s.js
@@ -8,12 +8,12 @@
  * @description StrictMode - property named 'caller' of function objects is not configurable
  * @onlyStrict
  */
 
 
 
 function testcase() {
         var funcExpr = function () { "use strict";};
-        return ! Object.getOwnPropertyDescriptor(funcExpr, 
-                                                  "caller").configurable;
+        return Object.getOwnPropertyDescriptor(funcExpr, 
+                                                  "caller") === undefined;
 }
-runTestCase(testcase);
\ No newline at end of file
+runTestCase(testcase);
--- a/js/src/tests/test262/ch13/13.2/13.2-33-s.js
+++ b/js/src/tests/test262/ch13/13.2/13.2-33-s.js
@@ -8,12 +8,12 @@
  * @description StrictMode - property named 'arguments' of function objects is not configurable
  * @onlyStrict
  */
 
 
 
 function testcase() {
         function foo() {"use strict";}
-        return ! Object.getOwnPropertyDescriptor(foo, 
-                                                  "arguments").configurable;
+        return Object.getOwnPropertyDescriptor(foo, 
+                                               "arguments") === undefined;
 }
-runTestCase(testcase);
\ No newline at end of file
+runTestCase(testcase);
--- a/js/src/tests/test262/ch13/13.2/13.2-34-s.js
+++ b/js/src/tests/test262/ch13/13.2/13.2-34-s.js
@@ -7,12 +7,12 @@
  * @path ch13/13.2/13.2-34-s.js
  * @description StrictMode - property named 'arguments' of function objects is not configurable
  * @onlyStrict
  */
 
 
 
 function testcase() {
-        return ! Object.getOwnPropertyDescriptor(Function("'use strict';"), 
-                                                  "arguments").configurable;
+        return Object.getOwnPropertyDescriptor(Function("'use strict';"), 
+                                               "arguments") === undefined;
 }
-runTestCase(testcase);
\ No newline at end of file
+runTestCase(testcase);
--- a/js/src/tests/test262/ch13/13.2/13.2-35-s.js
+++ b/js/src/tests/test262/ch13/13.2/13.2-35-s.js
@@ -7,12 +7,12 @@
  * @path ch13/13.2/13.2-35-s.js
  * @description StrictMode - property named 'arguments' of function objects is not configurable
  * @onlyStrict
  */
 
 
 
 function testcase() {
-        return ! Object.getOwnPropertyDescriptor(new Function("'use strict';"), 
-                                                  "arguments").configurable;
+        return Object.getOwnPropertyDescriptor(new Function("'use strict';"), 
+                                               "arguments") === undefined;
 }
-runTestCase(testcase);
\ No newline at end of file
+runTestCase(testcase);
--- a/js/src/tests/test262/ch13/13.2/13.2-36-s.js
+++ b/js/src/tests/test262/ch13/13.2/13.2-36-s.js
@@ -8,12 +8,12 @@
  * @description StrictMode - property named 'arguments' of function objects is not configurable
  * @onlyStrict
  */
 
 
 
 function testcase() {
         var funcExpr = function () { "use strict";};
-        return ! Object.getOwnPropertyDescriptor(funcExpr, 
-                                                  "arguments").configurable;
+        return Object.getOwnPropertyDescriptor(funcExpr, 
+                                                "arguments") === undefined;
 }
-runTestCase(testcase);
\ No newline at end of file
+runTestCase(testcase);
--- a/js/src/tests/test262/ch13/13.2/S13.2.3_A1.js
+++ b/js/src/tests/test262/ch13/13.2/S13.2.3_A1.js
@@ -1,49 +1,61 @@
 // Copyright 2011 Google Inc.  All rights reserved.
 // This code is governed by the BSD license found in the LICENSE file.
 
 /**
  * @path ch13/13.2/S13.2.3_A1.js
- * @description check that all poisoning use the [[ThrowTypeError]]
+ * @description check that strict mode functions/arguments have
+ *   [[ThrowTypeError]]-like behavior
  * function object.
  * @onlyStrict
  */
 
 "use strict";
-var poison = Object.getOwnPropertyDescriptor(function() {}, 'caller').get;
+var poison = Object.getOwnPropertyDescriptor(Function.prototype, 'caller').get;
 
 if (typeof poison !== 'function') {
   $ERROR("#1: A strict function's .caller should be poisoned with a function");
 }
 var threw = null;
 try {
-  poison();
+  poison.call(function() {});
 } catch (err) {
   threw = err;
 }
 if (!threw || !(threw instanceof TypeError)) {
   $ERROR("#2: Poisoned property should throw TypeError");
 }
 
+function checkNotPresent(obj, name) {
+  var desc = Object.getOwnPropertyDescriptor(obj, name);
+  if (desc !== undefined) {
+    $ERROR("#3: " + name + " should not appear as a descriptor");
+  }
+}
+
+var argumentsPoison =
+  Object.getOwnPropertyDescriptor(function() { return arguments; }(),
+                                  "callee").get;
+
 function checkPoison(obj, name) {
   var desc = Object.getOwnPropertyDescriptor(obj, name);
   if (desc.enumerable) {
     $ERROR("#3: Poisoned " + name + " should not be enumerable");
   }
   if (desc.configurable) {
     $ERROR("#4: Poisoned " + name + " should not be configurable");
   }
-  if (poison !== desc.get) {
+  if (argumentsPoison !== desc.get) {
     $ERROR("#5: " + name + "'s getter not poisoned with same poison");
   }
-  if (poison !== desc.set) {
+  if (argumentsPoison !== desc.set) {
     $ERROR("#6: " + name + "'s setter not poisoned with same poison");
   }
 }
 
-checkPoison(function() {}, 'caller');
-checkPoison(function() {}, 'arguments');
+checkNotPresent(function() {}, 'caller');
+checkNotPresent(function() {}, 'arguments');
 checkPoison((function() { return arguments; })(), 'caller');
 checkPoison((function() { return arguments; })(), 'callee');
-checkPoison((function() {}).bind(null), 'caller');
-checkPoison((function() {}).bind(null), 'arguments');
+checkNotPresent((function() {}).bind(null), 'caller');
+checkNotPresent((function() {}).bind(null), 'arguments');
 
--- a/js/src/tests/update-test262.sh
+++ b/js/src/tests/update-test262.sh
@@ -126,13 +126,18 @@ cp ${js_src_tests_dir}/supporting/test40
 # Keep a record of what we imported.
 echo "URL:         $1" > ${test262_dir}/HG-INFO
 hg -R ${tmp_dir} log -r. >> ${test262_dir}/HG-INFO
 
 # Update for the patch.
 hg addremove ${js_src_tests_dir}/supporting
 hg addremove ${test262_dir}
 
+# Apply a very narrow set of post-fixes to tests that haven't yet been updated
+# for spec changes, or where we're experimenting with semantics that disagree
+# with those in test262.  See below: this isn't every test we don't pass!
+patch -d "${js_src_tests_dir}" -p4 < ./function-arguments-caller-changes.diff
+
 # The alert reader may now be wondering: what about test262 tests that we don't
 # pass?  (And what about any test262 tests whose format we don't yet support?)
 # We explicitly disable all such tests in js/src/tests/jstests.list one by one.
 # This has the moderate benefit that if a bug is fixed, only that one file must
 # be updated, and we don't have to rerun this script.
--- a/js/src/vm/GlobalObject.h
+++ b/js/src/vm/GlobalObject.h
@@ -553,18 +553,20 @@ class GlobalObject : public JSObject
     bool getSelfHostedFunction(JSContext *cx, HandleAtom selfHostedName, HandleAtom name,
                                unsigned nargs, MutableHandleValue funVal);
 
     bool hasRegExpStatics() const;
     RegExpStatics *getRegExpStatics(ExclusiveContext *cx) const;
     RegExpStatics *getAlreadyCreatedRegExpStatics() const;
 
     JSObject *getThrowTypeError() const {
-        JS_ASSERT(functionObjectClassesInitialized());
-        return &getSlot(THROWTYPEERROR).toObject();
+        const Value v = getReservedSlot(THROWTYPEERROR);
+        MOZ_ASSERT(v.isObject(),
+                   "attempting to access [[ThrowTypeError]] too early");
+        return &v.toObject();
     }
 
     Value createDataViewForThis() const {
         JS_ASSERT(dataViewClassInitialized());
         return getSlot(CREATE_DATAVIEW_FOR_THIS);
     }
 
     template<typename T>
--- a/js/src/vm/MallocProvider.h
+++ b/js/src/vm/MallocProvider.h
@@ -49,23 +49,17 @@
 
 namespace js {
 
 template<class Client>
 struct MallocProvider
 {
     template <class T>
     T *pod_malloc() {
-        T *p = js_pod_malloc<T>();
-        if (MOZ_LIKELY(p)) {
-            client()->updateMallocCounter(sizeof(T));
-            return p;
-        }
-        client()->onOutOfMemory(nullptr, sizeof(T));
-        return nullptr;
+        return pod_malloc<T>(1);
     }
 
     template <class T>
     T *pod_malloc(size_t numElems) {
         T *p = js_pod_malloc<T>(numElems);
         if (MOZ_LIKELY(p)) {
             client()->updateMallocCounter(numElems * sizeof(T));
             return p;
@@ -101,39 +95,27 @@ struct MallocProvider
     template <class T>
     mozilla::UniquePtr<T[], JS::FreePolicy>
     make_pod_array(size_t numElems) {
         return mozilla::UniquePtr<T[], JS::FreePolicy>(pod_malloc<T>(numElems));
     }
 
     template <class T>
     T *pod_calloc() {
-        T *p = js_pod_calloc<T>();
-        if (MOZ_LIKELY(p)) {
-            client()->updateMallocCounter(sizeof(T));
-            return p;
-        }
-        client()->onOutOfMemory(reinterpret_cast<void *>(1), sizeof(T));
-        return nullptr;
+        return pod_calloc<T>(1);
     }
 
     template <class T>
     T *
     pod_calloc(size_t numElems) {
-        T *p = js_pod_calloc<T>(numElems);
-        if (MOZ_LIKELY(p)) {
-            client()->updateMallocCounter(numElems * sizeof(T));
-            return p;
-        }
-        if (numElems & mozilla::tl::MulOverflowMask<sizeof(T)>::value) {
-            client()->reportAllocationOverflow();
+        T *p = pod_malloc<T>(numElems);
+        if (MOZ_UNLIKELY(!p))
             return nullptr;
-        }
-        client()->onOutOfMemory(reinterpret_cast<void *>(1), sizeof(T));
-        return nullptr;
+        memset(p, 0, numElems * sizeof(T));
+        return p;
     }
 
     template <class T, class U>
     T *
     pod_calloc_with_extra(size_t numExtra) {
         T *p = pod_malloc_with_extra<T, U>(numExtra);
         if (MOZ_UNLIKELY(!p))
             return nullptr;
@@ -143,28 +125,16 @@ struct MallocProvider
 
     template <class T>
     mozilla::UniquePtr<T[], JS::FreePolicy>
     make_zeroed_pod_array(size_t numElems)
     {
         return mozilla::UniquePtr<T[], JS::FreePolicy>(pod_calloc<T>(numElems));
     }
 
-    void *realloc_(void *p, size_t oldBytes, size_t newBytes) {
-        Client *client = static_cast<Client *>(this);
-        /*
-         * For compatibility we do not account for realloc that decreases
-         * previously allocated memory.
-         */
-        if (newBytes > oldBytes)
-            client->updateMallocCounter(newBytes - oldBytes);
-        void *p2 = js_realloc(p, newBytes);
-        return MOZ_LIKELY(!!p2) ? p2 : client->onOutOfMemory(p, newBytes);
-    }
-
     template <class T>
     T *pod_realloc(T *prior, size_t oldSize, size_t newSize) {
         T *p = js_pod_realloc(prior, oldSize, newSize);
         if (MOZ_LIKELY(p)) {
             // For compatibility we do not account for realloc that decreases
             // previously allocated memory.
             if (newSize > oldSize)
                 client()->updateMallocCounter((newSize - oldSize) * sizeof(T));
--- a/js/src/vm/Runtime.h
+++ b/js/src/vm/Runtime.h
@@ -376,26 +376,34 @@ struct RegExpTestCache
  * A FreeOp can do one thing: free memory. For convenience, it has delete_
  * convenience methods that also call destructors.
  *
  * FreeOp is passed to finalizers and other sweep-phase hooks so that we do not
  * need to pass a JSContext to those hooks.
  */
 class FreeOp : public JSFreeOp
 {
+    Vector<void *, 0, SystemAllocPolicy> freeLaterList;
+
   public:
     static FreeOp *get(JSFreeOp *fop) {
         return static_cast<FreeOp *>(fop);
     }
 
     FreeOp(JSRuntime *rt)
       : JSFreeOp(rt)
     {}
 
+    ~FreeOp() {
+        for (size_t i = 0; i < freeLaterList.length(); i++)
+            free_(freeLaterList[i]);
+    }
+
     inline void free_(void *p);
+    inline void freeLater(void *p);
 
     template <class T>
     inline void delete_(T *p) {
         if (p) {
             p->~T();
             free_(p);
         }
     }
@@ -1468,16 +1476,27 @@ VersionIsKnown(JSVersion version)
 }
 
 inline void
 FreeOp::free_(void *p)
 {
     js_free(p);
 }
 
+inline void
+FreeOp::freeLater(void *p)
+{
+    // FreeOps other than the defaultFreeOp() are constructed on the stack,
+    // and won't hold onto the pointers to free indefinitely.
+    JS_ASSERT(this != runtime()->defaultFreeOp());
+
+    if (!freeLaterList.append(p))
+        CrashAtUnhandlableOOM("FreeOp::freeLater");
+}
+
 class AutoLockGC
 {
   public:
     explicit AutoLockGC(JSRuntime *rt = nullptr
                         MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
       : runtime(rt)
     {
         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
--- a/js/src/vm/ScopeObject.h
+++ b/js/src/vm/ScopeObject.h
@@ -409,16 +409,24 @@ class DynamicWithObject : public NestedS
     JSObject &object() const {
         return getReservedSlot(OBJECT_SLOT).toObject();
     }
 
     /* Return object for the 'this' class hook. */
     JSObject &withThis() const {
         return getReservedSlot(THIS_SLOT).toObject();
     }
+
+    static inline size_t objectSlot() {
+        return OBJECT_SLOT;
+    }
+
+    static inline size_t thisSlot() {
+        return THIS_SLOT;
+    }
 };
 
 class BlockObject : public NestedScopeObject
 {
   protected:
     static const unsigned DEPTH_SLOT = 1;
 
   public:
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -981,29 +981,23 @@ JSRuntime::initSelfHosting(JSContext *cx
     }
 
     /*
      * Self hosted state can be accessed from threads for other runtimes
      * parented to this one, so cannot include state in the nursery.
      */
     JS::AutoDisableGenerationalGC disable(cx->runtime());
 
-    bool receivesDefaultObject = !cx->options().noDefaultCompartmentObject();
-    RootedObject savedGlobal(cx, receivesDefaultObject
-                                 ? js::DefaultObjectForContextOrNull(cx)
-                                 : nullptr);
     JS::CompartmentOptions compartmentOptions;
     compartmentOptions.setDiscardSource(true);
     if (!(selfHostingGlobal_ = JS_NewGlobalObject(cx, &self_hosting_global_class,
                                                   nullptr, JS::DontFireOnNewGlobalHook,
                                                   compartmentOptions)))
         return false;
     JSAutoCompartment ac(cx, selfHostingGlobal_);
-    if (receivesDefaultObject)
-        js::SetDefaultObjectForContext(cx, selfHostingGlobal_);
     Rooted<GlobalObject*> shg(cx, &selfHostingGlobal_->as<GlobalObject>());
     selfHostingGlobal_->compartment()->isSelfHosting = true;
     selfHostingGlobal_->compartment()->isSystem = true;
     /*
      * During initialization of standard classes for the self-hosting global,
      * all self-hosted functions are ignored. Thus, we don't create cyclic
      * dependencies in the order of initialization.
      */
@@ -1042,18 +1036,16 @@ JSRuntime::initSelfHosting(JSContext *cx
                                       reinterpret_cast<unsigned char *>(src.get()), srcLen))
         {
             return false;
         }
 
         ok = Evaluate(cx, shg, options, src, srcLen, &rv);
     }
     JS_SetErrorReporter(cx, oldReporter);
-    if (receivesDefaultObject)
-        js::SetDefaultObjectForContext(cx, savedGlobal);
     return ok;
 }
 
 void
 JSRuntime::finishSelfHosting()