merge mozilla-inbound to mozilla-central a=merge
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Mon, 10 Oct 2016 11:55:47 +0200
changeset 317235 7be6b348c431d69f96f0765af3a0c0a0fe56d4bf
parent 317227 142098bba3d41b4a0ca6ef5bf58d6fcf5ad209fc (current diff)
parent 317234 bfe9d976f7509cf82989edbac61d56eb3fa4f2c5 (diff)
child 317241 8e35ac64eaf6bd5dc63ed15e2e1b8aa22b995975
child 317319 1215be5477392bdc60bd4da85e174d5c6417a096
child 317354 e70b480ce6c24db5f13e1c5f402592d1ef0922ab
push id30798
push usercbook@mozilla.com
push dateMon, 10 Oct 2016 09:55:56 +0000
treeherdermozilla-central@7be6b348c431 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone52.0a1
first release with
nightly linux32
7be6b348c431 / 52.0a1 / 20161010030204 / files
nightly linux64
7be6b348c431 / 52.0a1 / 20161010030204 / files
nightly mac
7be6b348c431 / 52.0a1 / 20161010030204 / files
nightly win32
7be6b348c431 / 52.0a1 / 20161010030204 / files
nightly win64
7be6b348c431 / 52.0a1 / 20161010030204 / 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 mozilla-inbound to mozilla-central a=merge
--- a/dom/animation/DocumentTimeline.cpp
+++ b/dom/animation/DocumentTimeline.cpp
@@ -16,16 +16,19 @@
 
 namespace mozilla {
 namespace dom {
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(DocumentTimeline)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(DocumentTimeline,
                                                 AnimationTimeline)
   tmp->UnregisterFromRefreshDriver();
+  if (tmp->isInList()) {
+    tmp->remove();
+  }
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocument)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(DocumentTimeline,
                                                   AnimationTimeline)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(DocumentTimeline,
@@ -129,16 +132,19 @@ DocumentTimeline::ToTimelineTime(const T
 void
 DocumentTimeline::NotifyAnimationUpdated(Animation& aAnimation)
 {
   AnimationTimeline::NotifyAnimationUpdated(aAnimation);
 
   if (!mIsObservingRefreshDriver) {
     nsRefreshDriver* refreshDriver = GetRefreshDriver();
     if (refreshDriver) {
+      MOZ_ASSERT(isInList(),
+                "We should not register with the refresh driver if we are not"
+                " in the document's list of timelines");
       refreshDriver->AddRefreshObserver(this, Flush_Style);
       mIsObservingRefreshDriver = true;
     }
   }
 }
 
 void
 DocumentTimeline::WillRefresh(mozilla::TimeStamp aTime)
@@ -193,16 +199,19 @@ DocumentTimeline::WillRefresh(mozilla::T
 void
 DocumentTimeline::NotifyRefreshDriverCreated(nsRefreshDriver* aDriver)
 {
   MOZ_ASSERT(!mIsObservingRefreshDriver,
              "Timeline should not be observing the refresh driver before"
              " it is created");
 
   if (!mAnimationOrder.isEmpty()) {
+    MOZ_ASSERT(isInList(),
+               "We should not register with the refresh driver if we are not"
+               " in the document's list of timelines");
     aDriver->AddRefreshObserver(this, Flush_Style);
     mIsObservingRefreshDriver = true;
   }
 }
 
 void
 DocumentTimeline::NotifyRefreshDriverDestroying(nsRefreshDriver* aDriver)
 {
--- a/dom/animation/DocumentTimeline.h
+++ b/dom/animation/DocumentTimeline.h
@@ -3,16 +3,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 mozilla_dom_DocumentTimeline_h
 #define mozilla_dom_DocumentTimeline_h
 
 #include "mozilla/dom/DocumentTimelineBinding.h"
+#include "mozilla/LinkedList.h"
 #include "mozilla/TimeStamp.h"
 #include "AnimationTimeline.h"
 #include "nsIDocument.h"
 #include "nsDOMNavigationTiming.h" // for DOMHighResTimeStamp
 #include "nsRefreshDriver.h"
 
 struct JSContext;
 
@@ -23,31 +24,38 @@ struct JSContext;
 #endif
 
 namespace mozilla {
 namespace dom {
 
 class DocumentTimeline final
   : public AnimationTimeline
   , public nsARefreshObserver
+  , public LinkedListElement<DocumentTimeline>
 {
 public:
   DocumentTimeline(nsIDocument* aDocument, const TimeDuration& aOriginTime)
     : AnimationTimeline(aDocument->GetParentObject())
     , mDocument(aDocument)
     , mIsObservingRefreshDriver(false)
     , mOriginTime(aOriginTime)
   {
+    if (mDocument) {
+      mDocument->Timelines().insertBack(this);
+    }
   }
 
 protected:
   virtual ~DocumentTimeline()
   {
     MOZ_ASSERT(!mIsObservingRefreshDriver, "Timeline should have disassociated"
                " from the refresh driver before being destroyed");
+    if (isInList()) {
+      remove();
+    }
   }
 
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(DocumentTimeline,
                                                          AnimationTimeline)
 
   virtual JSObject* WrapObject(JSContext* aCx,
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -1471,16 +1471,18 @@ nsDocument::~nsDocument()
   if (mStyleSheetSetList) {
     mStyleSheetSetList->Disconnect();
   }
 
   if (mAnimationController) {
     mAnimationController->Disconnect();
   }
 
+  MOZ_ASSERT(mTimelines.isEmpty());
+
   mParentDocument = nullptr;
 
   // Kill the subdocument map, doing this will release its strong
   // references, if any.
   delete mSubDocuments;
   mSubDocuments = nullptr;
 
   // Destroy link map now so we don't waste time removing
@@ -1993,25 +1995,17 @@ nsDocument::Reset(nsIChannel* aChannel, 
     }
   }
 
   ResetToURI(uri, aLoadGroup, principal);
 
   // Note that, since mTiming does not change during a reset, the
   // navigationStart time remains unchanged and therefore any future new
   // timeline will have the same global clock time as the old one.
-  if (mDocumentTimeline) {
-    nsRefreshDriver* rd = mPresShell && mPresShell->GetPresContext() ?
-                          mPresShell->GetPresContext()->RefreshDriver() :
-                          nullptr;
-    if (rd) {
-      mDocumentTimeline->NotifyRefreshDriverDestroying(rd);
-    }
-    mDocumentTimeline = nullptr;
-  }
+  mDocumentTimeline = nullptr;
 
   nsCOMPtr<nsIPropertyBag2> bag = do_QueryInterface(aChannel);
   if (bag) {
     nsCOMPtr<nsIURI> baseURI;
     bag->GetPropertyAsInterface(NS_LITERAL_STRING("baseURI"),
                                 NS_GET_IID(nsIURI), getter_AddRefs(baseURI));
     if (baseURI) {
       mDocumentBaseURI = baseURI;
--- a/dom/base/nsDocument.h
+++ b/dom/base/nsDocument.h
@@ -601,16 +601,20 @@ public:
 
   virtual already_AddRefed<mozilla::dom::UndoManager> GetUndoManager() override;
 
   static bool IsElementAnimateEnabled(JSContext* aCx, JSObject* aObject);
   static bool IsWebAnimationsEnabled(JSContext* aCx, JSObject* aObject);
   virtual mozilla::dom::DocumentTimeline* Timeline() override;
   virtual void GetAnimations(
       nsTArray<RefPtr<mozilla::dom::Animation>>& aAnimations) override;
+  mozilla::LinkedList<mozilla::dom::DocumentTimeline>& Timelines() override
+  {
+    return mTimelines;
+  }
 
   virtual nsresult SetSubDocumentFor(Element* aContent,
                                      nsIDocument* aSubDoc) override;
   virtual nsIDocument* GetSubDocumentFor(nsIContent* aContent) const override;
   virtual Element* FindContentForSubDocument(nsIDocument *aDocument) const override;
   virtual Element* GetRootElementInternal() const override;
 
   virtual void EnsureOnDemandBuiltInUASheet(mozilla::StyleSheet* aSheet) override;
@@ -1592,16 +1596,17 @@ private:
   nsDataHashtable< nsPtrHashKey<imgIRequest>, uint32_t> mImageTracker;
 
   // Tracking for plugins in the document.
   nsTHashtable< nsPtrHashKey<nsIObjectLoadingContent> > mPlugins;
 
   RefPtr<mozilla::dom::UndoManager> mUndoManager;
 
   RefPtr<mozilla::dom::DocumentTimeline> mDocumentTimeline;
+  mozilla::LinkedList<mozilla::dom::DocumentTimeline> mTimelines;
 
   enum ViewportType {
     DisplayWidthHeight,
     Specified,
     Unknown
   };
 
   ViewportType mViewportType;
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -29,16 +29,17 @@
 #include "mozilla/WeakPtr.h"
 #include "Units.h"
 #include "nsContentListDeclarations.h"
 #include "nsExpirationTracker.h"
 #include "nsClassHashtable.h"
 #include "prclist.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/CORSMode.h"
+#include "mozilla/LinkedList.h"
 #include "mozilla/StyleBackendType.h"
 #include "mozilla/StyleSheet.h"
 #include <bitset>                        // for member
 
 #ifdef MOZILLA_INTERNAL_API
 #include "mozilla/dom/DocumentBinding.h"
 #else
 namespace mozilla {
@@ -2320,16 +2321,17 @@ public:
    * @param aId the ID associated the element we want to lookup
    * @return the element associated with |aId|
    */
   virtual Element* LookupImageElement(const nsAString& aElementId) = 0;
 
   virtual already_AddRefed<mozilla::dom::UndoManager> GetUndoManager() = 0;
 
   virtual mozilla::dom::DocumentTimeline* Timeline() = 0;
+  virtual mozilla::LinkedList<mozilla::dom::DocumentTimeline>& Timelines() = 0;
 
   virtual void GetAnimations(
       nsTArray<RefPtr<mozilla::dom::Animation>>& aAnimations) = 0;
 
   mozilla::dom::SVGSVGElement* GetSVGRootElement() const;
 
   nsresult ScheduleFrameRequestCallback(mozilla::dom::FrameRequestCallback& aCallback,
                                         int32_t *aHandle);
--- a/dom/tests/mochitest/general/test_interfaces.html
+++ b/dom/tests/mochitest/general/test_interfaces.html
@@ -30,17 +30,16 @@ https://bugzilla.mozilla.org/show_bug.cg
 // property giving the interface name as a string, and additional
 // properties which qualify the exposure of that interface. For example:
 //
 // [
 //   "AGlobalInterface",
 //   {name: "ExperimentalThing", release: false},
 //   {name: "ReallyExperimentalThing", nightly: true},
 //   {name: "DesktopOnlyThing", desktop: true},
-//   {name: "NonB2gOnlyThing", b2g: false},
 //   {name: "FancyControl", xbl: true},
 //   {name: "DisabledEverywhere", disabled: true},
 // ];
 //
 // See createInterfaceMap() below for a complete list of properties.
 
 // IMPORTANT: Do not change this list without review from
 //            a JavaScript Engine peer!
@@ -115,18 +114,16 @@ var legacyMozPrefixedInterfaces =
   ];
 // IMPORTANT: Do not change the list above without review from a DOM peer,
 //            except to remove items from it!
 
 // IMPORTANT: Do not change the list below without review from a DOM peer!
 var interfaceNamesInGlobalScope =
   [
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "AlarmsManager", b2g: true},
-// 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!
     {name: "Animation"},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "AnimationEffectReadOnly", release: false},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "AnimationEffectTiming", release: false},
 // IMPORTANT: Do not change this list without review from a DOM peer!
@@ -139,171 +136,64 @@ var interfaceNamesInGlobalScope =
     {name: "AnimationTimeline", release: false},
 // 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!
     "AudioBuffer",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "AudioChannelManager", b2g: true},
-// IMPORTANT: Do not change this list without review from a DOM peer!
     "AudioContext",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "AudioBufferSourceNode",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "AudioDestinationNode",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "AudioListener",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "AudioNode",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "AudioParam",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "AudioProcessingEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "AudioStreamTrack",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "AVInputPort", b2g: true, permission: ["inputport"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
     "BarProp",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "BatteryManager",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "BeforeAfterKeyboardEvent", b2g: true,
-     permission: ["embed-apps", "before-after-keyboard-event"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
     "BeforeUnloadEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "BiquadFilterNode",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "Blob",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "BlobEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "BluetoothAdapter", b2g: true, permission: ["bluetooth"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "BluetoothAdapterEvent", b2g: true, permission: ["bluetooth"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "BluetoothAttributeEvent", b2g: true, permission: ["bluetooth"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "BluetoothClassOfDevice", b2g: true, permission: ["bluetooth"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "BluetoothDevice", b2g: true, permission: ["bluetooth"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "BluetoothDeviceEvent", b2g: true, permission: ["bluetooth"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "BluetoothDiscoveryHandle", b2g: true, permission: ["bluetooth"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "BluetoothGatt", b2g: true, permission: ["bluetooth"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "BluetoothGattAttributeEvent", b2g: true,
-     permission: ["bluetooth"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "BluetoothGattCharacteristic", b2g: true,
-     permission: ["bluetooth"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "BluetoothGattCharacteristicEvent", b2g: true,
-     permission: ["bluetooth"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "BluetoothGattDescriptor", b2g: true, permission: ["bluetooth"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "BluetoothGattServer", b2g: true, permission: ["bluetooth"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "BluetoothGattService", b2g: true, permission: ["bluetooth"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "BluetoothLeDeviceEvent", b2g: true, permission: ["bluetooth"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "BluetoothManager", b2g: true, permission: ["bluetooth"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "BluetoothMapFolderListingEvent", b2g: true, permission: ["bluetooth"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "BluetoothMapGetMessageEvent", b2g: true, permission: ["bluetooth"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "BluetoothMapMessagesListingEvent", b2g: true, permission: ["bluetooth"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "BluetoothMapMessageUpdateEvent", b2g: true, permission: ["bluetooth"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "BluetoothMapRequestHandle", b2g: true, permission: ["bluetooth"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "BluetoothMapSendMessageEvent", b2g: true, permission: ["bluetooth"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "BluetoothMapSetMessageStatusEvent", b2g: true, permission: ["bluetooth"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "BluetoothObexAuthEvent", b2g: true, permission: ["bluetooth"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "BluetoothObexAuthHandle", b2g: true, permission: ["bluetooth"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "BluetoothPbapRequestHandle", b2g: true, permission: ["bluetooth"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "BluetoothPairingEvent", b2g: true, permission: ["bluetooth"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "BluetoothPairingHandle", b2g: true, permission: ["bluetooth"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "BluetoothPhonebookPullingEvent", b2g: true, permission: ["bluetooth"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "BluetoothStatusChangedEvent", b2g: true,
-     permission: ["bluetooth"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "BluetoothVCardListingEvent", b2g: true, permission: ["bluetooth"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "BluetoothVCardPullingEvent", b2g: true, permission: ["bluetooth"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "BoxObject", xbl: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "BrowserElementAudioChannel", b2g: true, permission: ["browser"] },
-// IMPORTANT: Do not change this list without review from a DOM peer!
     "BroadcastChannel",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "Cache",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "CacheStorage",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "CallEvent", b2g: true},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "CallGroupErrorEvent", b2g: true},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "CameraCapabilities", b2g: true},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "CameraClosedEvent", b2g: true},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "CameraConfigurationEvent", b2g: true},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "CameraControl", b2g: true},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "CameraDetectedFace", b2g: true, permission: ["camera"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "CameraFacesDetectedEvent", b2g: true, permission: ["camera"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "CameraManager", b2g: true},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "CameraRecorderAudioProfile", b2g: true},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "CameraRecorderProfile", b2g: true},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "CameraRecorderProfiles", b2g: true},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "CameraRecorderVideoProfile", b2g: true},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "CameraStateChangeEvent", b2g: true},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "CanvasCaptureMediaStream"},
+    "CanvasCaptureMediaStream",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "CanvasGradient",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "CanvasPattern",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "CanvasRenderingContext2D",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "CaretPosition",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "CDATASection",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "CFStateChangeEvent", b2g: true},
-// IMPORTANT: Do not change this list without review from a DOM peer!
     "ChannelMergerNode",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "ChannelSplitterNode",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "CharacterData",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "ChromeNodeList", xbl: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
@@ -380,18 +270,16 @@ var interfaceNamesInGlobalScope =
     "CSSValueList",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "CustomElementsRegistry",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "CustomEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "DataChannel",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "DataErrorEvent", b2g: true},
-// IMPORTANT: Do not change this list without review from a DOM peer!
     "DataTransfer",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "DataTransferItem",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "DataTransferItemList",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "DelayNode",
 // IMPORTANT: Do not change this list without review from a DOM peer!
@@ -412,18 +300,16 @@ var interfaceNamesInGlobalScope =
     { name: "DeviceStorageAreaListener", desktop: false},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     { name: "DeviceStorage", desktop: false},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     { name: "DeviceStorageChangeEvent", desktop: false},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "Directory",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "DisplayPortInputPort", b2g: true, permission: ["inputport"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
     "Document",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "DocumentFragment",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "DocumentTimeline", release: false},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "DocumentType",
 // IMPORTANT: Do not change this list without review from a DOM peer!
@@ -474,17 +360,17 @@ var interfaceNamesInGlobalScope =
     "ErrorEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "Event",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "EventSource",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "EventTarget",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "External", b2g: false},
+    "External",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "File",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "FileList",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "FileReader",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "FileSystem",
@@ -492,48 +378,44 @@ var interfaceNamesInGlobalScope =
     "FileSystemDirectoryEntry",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "FileSystemDirectoryReader",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "FileSystemEntry",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "FileSystemFileEntry",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "FMRadio", b2g: true},
-// IMPORTANT: Do not change this list without review from a DOM peer!
     "FocusEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "FormData",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "FontFace",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "FontFaceSet",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "FontFaceSetLoadEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "GainNode",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "Gamepad", b2g: false},
+    "Gamepad",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "GamepadAxisMoveEvent", b2g: false},
+    "GamepadAxisMoveEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "GamepadButtonEvent", b2g: false},
+    "GamepadButtonEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "GamepadButton", b2g: false},
+    "GamepadButton",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "GamepadEvent", b2g: false},
+    "GamepadEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "HashChangeEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "Headers",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "History",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "HDMIInputPort", b2g: true, permission: ["inputport"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLAllCollection",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLAnchorElement",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLAppletElement",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLAreaElement",
 // IMPORTANT: Do not change this list without review from a DOM peer!
@@ -722,21 +604,17 @@ var interfaceNamesInGlobalScope =
     {name: "ImageCapture", disabled: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "ImageCaptureErrorEvent", disabled: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "ImageData",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "InputEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "InputPort", b2g: true, permission: ["inputport"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "InputPortManager", b2g: true, permission: ["inputport"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "InstallTrigger", b2g: false},
+    "InstallTrigger",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "KeyEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "KeyboardEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "KeyframeEffectReadOnly", release: false},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "KeyframeEffect", release: false},
@@ -798,80 +676,22 @@ var interfaceNamesInGlobalScope =
     "MimeType",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "MimeTypeArray",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "MouseEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "MouseScrollEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "MozActivity", b2g: true},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "MozClirModeEvent", b2g: true},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "mozContact", b2g: true, permission: "contacts-read"},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "MozContactChangeEvent", b2g: true, permission: "contacts-read"},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "MozEmergencyCbModeEvent", b2g: true},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "MozInputContext", b2g: true, permission: ["input"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "MozInputMethodManager", b2g: true, permission: ["input"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "MozMobileCellInfo", b2g: true},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "MozMobileConnection", b2g: true},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "MozMobileConnectionArray", b2g: true},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "MozMobileConnectionInfo", b2g: true},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "MozMobileNetworkInfo", b2g: true},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "MozNDEFRecord", b2g: true},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "MozOtaStatusEvent", b2g: true},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "MozPowerManager", b2g: true, permission: "power"},
-// IMPORTANT: Do not change this list without review from a DOM peer!
     "mozRTCIceCandidate",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "mozRTCPeerConnection",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "mozRTCSessionDescription",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "MozSettingsEvent", permission: ["settings-api-read"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "MozSettingsTransactionEvent", permission: ["settings-api-read"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "MozSpeakerManager", b2g: true},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "MozTimeManager", b2g: true},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "MozWakeLock", b2g: true},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "MozWifiCapabilities", b2g: true, permission: ["wifi-manage"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "MozWifiConnectionInfoEvent", b2g: true},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "MozWifiStationInfoEvent", b2g: true},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-   {name: "MozWifiManager", b2g: true, permission: ["wifi-manage"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "MozWifiNetwork", b2g: true, permission: ["wifi-manage"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "MozWifiStatusChangeEvent", b2g: true},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "MozWifiP2pGroupOwner", b2g: true, permission: ["wifi-manage"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "MozWifiP2pManager", b2g: true, permission: ["wifi-manage"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "MozWifiP2pStatusChangeEvent", b2g: true, permission: ["wifi-manage"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
     "MutationEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "MutationObserver",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "MutationRecord",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "NamedNodeMap",
 // IMPORTANT: Do not change this list without review from a DOM peer!
@@ -930,37 +750,32 @@ var interfaceNamesInGlobalScope =
     "PerformanceResourceTiming",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "PerformanceTiming",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "PeriodicWave",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "Permissions",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "PermissionSettings", b2g: true, permission: ["permissions"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
     "PermissionStatus",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "PhoneNumberService", permission: ["phonenumberservice"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
     "Plugin",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "PluginArray",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "PointerEvent", nightly: true, desktop: true, disabled: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "PopStateEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "PopupBlockedEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "PopupBoxObject", xbl: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "PresentationDeviceInfoManager",
-     disabled: true,
-     permission: ["presentation-device-manage"]},
+     disabled: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "Presentation", disabled: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "PresentationAvailability", disabled: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "PresentationConnection", disabled: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "PresentationConnectionAvailableEvent", disabled: true},
@@ -972,21 +787,21 @@ var interfaceNamesInGlobalScope =
     {name: "PresentationReceiver", disabled: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "PresentationRequest", disabled: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "ProcessingInstruction",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "ProgressEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "PushManager", b2g: false},
+    "PushManager",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "PushSubscription", b2g: false},
+    "PushSubscription",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "PushSubscriptionOptions", b2g: false},
+    "PushSubscriptionOptions",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "RadioNodeList",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "Range",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "RecordErrorEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "Rect",
@@ -1026,29 +841,26 @@ var interfaceNamesInGlobalScope =
     "ScreenOrientation",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "ScriptProcessorNode",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "ScrollAreaEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "Selection",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "ServiceWorker", b2g: false},
+    "ServiceWorker",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "ServiceWorkerContainer", b2g: false},
+    "ServiceWorkerContainer",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "ServiceWorkerMessageEvent", b2g: false},
+    "ServiceWorkerMessageEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "ServiceWorkerRegistration", b2g: false},
+    "ServiceWorkerRegistration",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "SettingsLock",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "SettingsManager",
-     permission: ["settings-read", "settings-write"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
     "ShadowRoot", // Bogus, but the test harness forces it on.  See bug 1159768.
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "SharedWorker",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "SimpleGestureEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "SimpleTest", xbl: false},
 // IMPORTANT: Do not change this list without review from a DOM peer!
@@ -1315,24 +1127,16 @@ var interfaceNamesInGlobalScope =
     "SVGUseElement",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGViewElement",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGZoomAndPan",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "SVGZoomEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "Telephony", b2g: true},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "TelephonyCall", b2g: true},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "TelephonyCallGroup", b2g: true},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "TelephonyCallId", b2g: true},
-// IMPORTANT: Do not change this list without review from a DOM peer!
     "Text",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "TextDecoder",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "TextEncoder",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "TextMetrics",
 // IMPORTANT: Do not change this list without review from a DOM peer!
@@ -1363,40 +1167,18 @@ var interfaceNamesInGlobalScope =
     {name: "TreeColumns", xbl: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "TreeContentView", xbl: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "TreeSelection", xbl: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "TreeWalker",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "TVChannel", b2g: true, permission: "tv"},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "TVCurrentChannelChangedEvent", b2g: true, permission: "tv"},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "TVCurrentSourceChangedEvent", b2g: true, permission: "tv"},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "TVEITBroadcastedEvent", b2g: true, permission: ["tv"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "TVManager", b2g: true, permission: ["tv"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "TVProgram", b2g: true, permission: ["tv"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "TVScanningStateChangedEvent", b2g: true, permission: ["tv"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "TVSource", b2g: true, permission: ["tv"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "TVTuner", b2g: true, permission: ["tv"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "U2F", disabled: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "UDPMessageEvent", b2g: true, permission: ["udp-socket"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "UDPSocket", b2g: true, permission: ["udp-socket"]},
-// IMPORTANT: Do not change this list without review from a DOM peer!
     "UIEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "UndoManager",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "URL",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "URLSearchParams",
 // IMPORTANT: Do not change this list without review from a DOM peer!
@@ -1517,49 +1299,39 @@ var interfaceNamesInGlobalScope =
   ];
 // IMPORTANT: Do not change the list above without review from a DOM peer!
 
 function createInterfaceMap(isXBLScope) {
   var version = SpecialPowers.Cc["@mozilla.org/xre/app-info;1"].getService(SpecialPowers.Ci.nsIXULAppInfo).version;
   var isNightly = version.endsWith("a1");
   var isRelease = !version.includes("a");
   var isDesktop = !/Mobile|Tablet/.test(navigator.userAgent);
-  var isB2G = !isDesktop && !navigator.userAgent.includes("Android");
   var isMac = /Mac OS/.test(navigator.oscpu);
   var isWindows = /Windows/.test(navigator.oscpu);
   var isAndroid = navigator.userAgent.includes("Android");
   var isLinux = /Linux/.test(navigator.oscpu) && !isAndroid;
-  var hasPermission = function (aPermissions) {
-    var result = false;
-    for (var p of aPermissions) {
-      result = result || SpecialPowers.hasPermission(p, window.document);
-    }
-    return result;
-  };
 
   var interfaceMap = {};
 
   function addInterfaces(interfaces)
   {
     for (var entry of interfaces) {
       if (typeof(entry) === "string") {
         interfaceMap[entry] = true;
       } else {
         ok(!("pref" in entry), "Bogus pref annotation for " + entry.name);
         if ((entry.nightly === !isNightly) ||
             (entry.nightlyAndroid === !(isAndroid && isNightly) && isAndroid) ||
             (entry.xbl === !isXBLScope) ||
             (entry.desktop === !isDesktop) ||
-            (entry.b2g === !isB2G) ||
             (entry.windows === !isWindows) ||
             (entry.mac === !isMac) ||
             (entry.linux === !isLinux) ||
             (entry.android === !isAndroid && !entry.nightlyAndroid) ||
             (entry.release === !isRelease) ||
-            (entry.permission && !hasPermission(entry.permission)) ||
             entry.disabled) {
           interfaceMap[entry.name] = false;
         } else {
           interfaceMap[entry.name] = true;
         }
       }
     }
   }
--- a/dom/workers/test/serviceworkers/serviceworker_wrapper.js
+++ b/dom/workers/test/serviceworkers/serviceworker_wrapper.js
@@ -26,31 +26,16 @@ function workerTestArrayEquals(a, b) {
   }
   return true;
 }
 
 function workerTestDone() {
   client.postMessage({ type: 'finish' });
 }
 
-function workerTestGetPermissions(permissions, cb) {
-  addEventListener('message', function workerTestGetPermissionsCB(e) {
-    if (e.data.type != 'returnPermissions' ||
-        !workerTestArrayEquals(permissions, e.data.permissions)) {
-      return;
-    }
-    removeEventListener('message', workerTestGetPermissionsCB);
-    cb(e.data.result);
-  });
-  client.postMessage({
-    type: 'getPermissions',
-    permissions: permissions
-  });
-}
-
 function workerTestGetVersion(cb) {
   addEventListener('message', function workerTestGetVersionCB(e) {
     if (e.data.type !== 'returnVersion') {
       return;
     }
     removeEventListener('message', workerTestGetVersionCB);
     cb(e.data.result);
   });
@@ -80,29 +65,16 @@ function workerTestGetOSCPU(cb) {
     removeEventListener('message', workerTestGetOSCPUCB);
     cb(e.data.result);
   });
   client.postMessage({
     type: 'getOSCPU'
   });
 }
 
-function workerTestGetIsB2G(cb) {
-  addEventListener('message', function workerTestGetIsB2GCB(e) {
-    if (e.data.type !== 'returnIsB2G') {
-      return;
-    }
-    removeEventListener('message', workerTestGetIsB2GCB);
-    cb(e.data.result);
-  });
-  client.postMessage({
-    type: 'getIsB2G'
-  });
-}
-
 function workerTestGetStorageManager(cb) {
   addEventListener('message', function workerTestGetStorageManagerCB(e) {
     if (e.data.type !== 'returnStorageManager') {
       return;
     }
     removeEventListener('message', workerTestGetStorageManagerCB);
     cb(e.data.result);
   });
--- a/dom/workers/test/serviceworkers/test_serviceworker_interfaces.html
+++ b/dom/workers/test/serviceworkers/test_serviceworker_interfaces.html
@@ -33,27 +33,16 @@
           result[pref] = SpecialPowers.Services.prefs.getBoolPref(pref);
         });
         worker.postMessage({
           type: 'returnPrefs',
           prefs: event.data.prefs,
           result: result
         });
 
-      } else if (event.data.type == 'getPermissions') {
-        var result = {};
-        event.data.permissions.forEach(function(permission) {
-          result[permission] = SpecialPowers.hasPermission(permission, window.document);
-        });
-        worker.postMessage({
-          type: 'returnPermissions',
-          permissions: event.data.permissions,
-          result: result
-        });
-
       } else if (event.data.type == 'getVersion') {
         var result = SpecialPowers.Cc['@mozilla.org/xre/app-info;1'].getService(SpecialPowers.Ci.nsIXULAppInfo).version;
         worker.postMessage({
           type: 'returnVersion',
           result: result
         });
 
       } else if (event.data.type == 'getUserAgent') {
@@ -61,21 +50,16 @@
           type: 'returnUserAgent',
           result: navigator.userAgent
         });
       } else if (event.data.type == 'getOSCPU') {
         worker.postMessage({
           type: 'returnOSCPU',
           result: navigator.oscpu
         });
-      } else if (event.data.type == 'getIsB2G') {
-        worker.postMessage({
-          type: 'returnIsB2G',
-          result: SpecialPowers.isB2G
-        });
       }
     }
 
     worker.onerror = function(event) {
       ok(false, 'Worker had an error: ' + event.data);
       SimpleTest.finish();
     };
 
--- a/dom/workers/test/serviceworkers/test_serviceworker_interfaces.js
+++ b/dom/workers/test/serviceworkers/test_serviceworker_interfaces.js
@@ -8,17 +8,16 @@
 // property giving the interface name as a string, and additional
 // properties which qualify the exposure of that interface. For example:
 //
 // [
 //   "AGlobalInterface",
 //   { name: "ExperimentalThing", release: false },
 //   { name: "ReallyExperimentalThing", nightly: true },
 //   { name: "DesktopOnlyThing", desktop: true },
-//   { name: "NonB2gOnlyThing", b2g: false },
 //   { name: "FancyControl", xbl: true },
 //   { name: "DisabledEverywhere", disabled: true },
 // ];
 //
 // See createInterfaceMap() below for a complete list of properties.
 
 // IMPORTANT: Do not change this list without review from
 //            a JavaScript Engine peer!
@@ -155,41 +154,42 @@ var interfaceNamesInGlobalScope =
     "ImageData",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "MessageChannel",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "MessageEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "MessagePort",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    { name: "Notification", nonReleaseB2G: true, b2g: false },
+    "Notification",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    { name: "NotificationEvent", nonReleaseB2G: true, b2g: false },
+    "NotificationEvent",
+// IMPORTANT: Do not change this list without review from a DOM peer!
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "Performance",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "PerformanceEntry",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "PerformanceMark",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "PerformanceMeasure",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     { name: "PerformanceObserver", nightly: true },
 // IMPORTANT: Do not change this list without review from a DOM peer!
     { name: "PerformanceObserverEntryList", nightly: true },
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    { name: "PushEvent", b2g: false },
+    "PushEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    { name: "PushManager", b2g: false },
+    "PushManager",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    { name: "PushMessageData", b2g: false },
+    "PushMessageData",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    { name: "PushSubscription", b2g: false },
+    "PushSubscription",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    { name: "PushSubscriptionOptions", b2g: false },
+    "PushSubscriptionOptions",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "Request",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "Response",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "ServiceWorker",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "ServiceWorkerGlobalScope",
@@ -216,56 +216,53 @@ var interfaceNamesInGlobalScope =
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "WorkerLocation",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "WorkerNavigator",
 // IMPORTANT: Do not change this list without review from a DOM peer!
   ];
 // IMPORTANT: Do not change the list above without review from a DOM peer!
 
-function createInterfaceMap(permissionMap, version, userAgent, isB2G) {
+function createInterfaceMap(version, userAgent) {
   var isNightly = version.endsWith("a1");
   var isRelease = !version.includes("a");
   var isDesktop = !/Mobile|Tablet/.test(userAgent);
   var isAndroid = !!navigator.userAgent.includes("Android");
 
   var interfaceMap = {};
 
   function addInterfaces(interfaces)
   {
     for (var entry of interfaces) {
       if (typeof(entry) === "string") {
         interfaceMap[entry] = true;
       } else {
         ok(!("pref" in entry), "Bogus pref annotation for " + entry.name);
         if ((entry.nightly === !isNightly) ||
             (entry.nightlyAndroid === !(isAndroid && isNightly) && isAndroid) ||
-            (entry.nonReleaseB2G === !(isB2G && !isRelease) && isB2G) ||
             (entry.nonReleaseAndroid === !(isAndroid && !isRelease) && isAndroid) ||
             (entry.desktop === !isDesktop) ||
             (entry.android === !isAndroid && !entry.nonReleaseAndroid && !entry.nightlyAndroid) ||
-            (entry.b2g === !isB2G && !entry.nonReleaseB2G) ||
-            (entry.release === !isRelease) ||
-            (entry.permission && !permissionMap[entry.permission])) {
+            (entry.release === !isRelease)) {
           interfaceMap[entry.name] = false;
         } else {
           interfaceMap[entry.name] = true;
         }
       }
     }
   }
 
   addInterfaces(ecmaGlobals);
   addInterfaces(interfaceNamesInGlobalScope);
 
   return interfaceMap;
 }
 
-function runTest(permissionMap, version, userAgent, isB2G) {
-  var interfaceMap = createInterfaceMap(permissionMap, version, userAgent, isB2G);
+function runTest(version, userAgent) {
+  var interfaceMap = createInterfaceMap(version, userAgent);
   for (var name of Object.getOwnPropertyNames(self)) {
     // An interface name should start with an upper case character.
     if (!/^[A-Z]/.test(name)) {
       continue;
     }
     ok(interfaceMap[name],
        "If this is failing: DANGER, are you sure you want to expose the new interface " + name +
        " to all webpages as a property on the service worker? Do not make a change to this file without a " +
@@ -278,31 +275,14 @@ function runTest(permissionMap, version,
     if (!interfaceMap[name]) {
       delete interfaceMap[name];
     }
   }
   is(Object.keys(interfaceMap).length, 0,
      "The following interface(s) are not enumerated: " + Object.keys(interfaceMap).join(", "));
 }
 
-function appendPermissions(permissions, interfaces) {
-  for (var entry of interfaces) {
-    if (entry.permission !== undefined &&
-        permissions.indexOf(entry.permission) === -1) {
-      permissions.push(entry.permission);
-    }
-  }
-}
-
-var permissions = [];
-appendPermissions(permissions, ecmaGlobals);
-appendPermissions(permissions, interfaceNamesInGlobalScope);
-
-workerTestGetPermissions(permissions, function(permissionMap) {
-  workerTestGetVersion(function(version) {
-    workerTestGetUserAgent(function(userAgent) {
-      workerTestGetIsB2G(function(isB2G) {
-        runTest(permissionMap, version, userAgent, isB2G);
-        workerTestDone();
-      });
-    });
+workerTestGetVersion(function(version) {
+  workerTestGetUserAgent(function(userAgent) {
+    runTest(version, userAgent);
+    workerTestDone();
   });
 });
--- a/dom/workers/test/test_worker_interfaces.js
+++ b/dom/workers/test/test_worker_interfaces.js
@@ -8,17 +8,16 @@
 // property giving the interface name as a string, and additional
 // properties which qualify the exposure of that interface. For example:
 //
 // [
 //   "AGlobalInterface",
 //   { name: "ExperimentalThing", release: false },
 //   { name: "ReallyExperimentalThing", nightly: true },
 //   { name: "DesktopOnlyThing", desktop: true },
-//   { name: "NonB2gOnlyThing", b2g: false },
 //   { name: "FancyControl", xbl: true },
 //   { name: "DisabledEverywhere", disabled: true },
 // ];
 //
 // See createInterfaceMap() below for a complete list of properties.
 
 // IMPORTANT: Do not change this list without review from
 //            a JavaScript Engine peer!
@@ -163,27 +162,27 @@ var interfaceNamesInGlobalScope =
     "PerformanceMark",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "PerformanceMeasure",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     { name: "PerformanceObserver", nightly: true },
 // IMPORTANT: Do not change this list without review from a DOM peer!
     { name: "PerformanceObserverEntryList", nightly: true },
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    { name: "PushManager", b2g: false },
+    "PushManager",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    { name: "PushSubscription", b2g: false },
+    "PushSubscription",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    { name: "PushSubscriptionOptions", b2g: false },
+    "PushSubscriptionOptions",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "Request",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "Response",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    { name: "ServiceWorkerRegistration", b2g: false },
+    "ServiceWorkerRegistration",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "StorageManager",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "SubtleCrypto",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "TextDecoder",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "TextEncoder",
@@ -228,17 +227,17 @@ var interfaceNamesInGlobalScope =
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "WorkerLocation",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "WorkerNavigator",
 // IMPORTANT: Do not change this list without review from a DOM peer!
   ];
 // IMPORTANT: Do not change the list above without review from a DOM peer!
 
-function createInterfaceMap(permissionMap, version, userAgent, isB2G) {
+function createInterfaceMap(version, userAgent) {
   var isNightly = version.endsWith("a1");
   var isRelease = !version.includes("a");
   var isDesktop = !/Mobile|Tablet/.test(userAgent);
   var isAndroid = !!navigator.userAgent.includes("Android");
 
   var interfaceMap = {};
 
   function addInterfaces(interfaces)
@@ -247,36 +246,34 @@ function createInterfaceMap(permissionMa
       if (typeof(entry) === "string") {
         interfaceMap[entry] = true;
       } else {
         ok(!("pref" in entry), "Bogus pref annotation for " + entry.name);
         if ((entry.nightly === !isNightly) ||
             (entry.nightlyAndroid === !(isAndroid && isNightly) && isAndroid) ||
             (entry.desktop === !isDesktop) ||
             (entry.android === !isAndroid && !entry.nightlyAndroid) ||
-            (entry.b2g === !isB2G) ||
             (entry.release === !isRelease) ||
-            (entry.permission && !permissionMap[entry.permission]) ||
             entry.disabled) {
           interfaceMap[entry.name] = false;
         } else {
           interfaceMap[entry.name] = true;
         }
       }
     }
   }
 
   addInterfaces(ecmaGlobals);
   addInterfaces(interfaceNamesInGlobalScope);
 
   return interfaceMap;
 }
 
-function runTest(permissionMap, version, userAgent, isB2G) {
-  var interfaceMap = createInterfaceMap(permissionMap, version, userAgent, isB2G);
+function runTest(version, userAgent) {
+  var interfaceMap = createInterfaceMap(version, userAgent);
   for (var name of Object.getOwnPropertyNames(self)) {
     // An interface name should start with an upper case character.
     if (!/^[A-Z]/.test(name)) {
       continue;
     }
     ok(interfaceMap[name],
        "If this is failing: DANGER, are you sure you want to expose the new interface " + name +
        " to all webpages as a property on the worker? Do not make a change to this file without a " +
@@ -289,31 +286,14 @@ function runTest(permissionMap, version,
     if (!interfaceMap[name]) {
       delete interfaceMap[name];
     }
   }
   is(Object.keys(interfaceMap).length, 0,
      "The following interface(s) are not enumerated: " + Object.keys(interfaceMap).join(", "));
 }
 
-function appendPermissions(permissions, interfaces) {
-  for (var entry of interfaces) {
-    if (entry.permission !== undefined &&
-        permissions.indexOf(entry.permission) === -1) {
-      permissions.push(entry.permission);
-    }
-  }
-}
-
-var permissions = [];
-appendPermissions(permissions, ecmaGlobals);
-appendPermissions(permissions, interfaceNamesInGlobalScope);
-
-workerTestGetPermissions(permissions, function(permissionMap) {
-  workerTestGetVersion(function(version) {
-    workerTestGetUserAgent(function(userAgent) {
-      workerTestGetIsB2G(function(isB2G) {
-        runTest(permissionMap, version, userAgent, isB2G);
-        workerTestDone();
-      });
-    });
+workerTestGetVersion(function(version) {
+  workerTestGetUserAgent(function(userAgent) {
+    runTest(version, userAgent);
+    workerTestDone();
   });
 });
--- a/dom/workers/test/worker_driver.js
+++ b/dom/workers/test/worker_driver.js
@@ -14,44 +14,32 @@
 //
 //  ok() - like the SimpleTest assert
 //  is() - like the SimpleTest assert
 //  workerTestDone() - like SimpleTest.finish() indicating the test is complete
 //
 // There are also some functions for requesting information that requires
 // SpecialPowers or other main-thread-only resources:
 //
-//  workerTestGetPermissions() - request an array permissions from the MT
 //  workerTestGetVersion() - request the current version string from the MT
 //  workerTestGetUserAgent() - request the user agent string from the MT
 //  workerTestGetOSCPU() - request the navigator.oscpu string from the MT
 //
 // For an example see test_worker_interfaces.html and test_worker_interfaces.js.
 
 function workerTestExec(script) {
   SimpleTest.waitForExplicitFinish();
   var worker = new Worker('worker_wrapper.js');
   worker.onmessage = function(event) {
     if (event.data.type == 'finish') {
       SimpleTest.finish();
 
     } else if (event.data.type == 'status') {
       ok(event.data.status, event.data.msg);
 
-    } else if (event.data.type == 'getPermissions') {
-      var result = {};
-      event.data.permissions.forEach(function(permission) {
-        result[permission] = SpecialPowers.hasPermission(permission, window.document);
-      });
-      worker.postMessage({
-        type: 'returnPermissions',
-        permissions: event.data.permissions,
-        result: result
-      });
-
     } else if (event.data.type == 'getVersion') {
       var result = SpecialPowers.Cc['@mozilla.org/xre/app-info;1'].getService(SpecialPowers.Ci.nsIXULAppInfo).version;
       worker.postMessage({
         type: 'returnVersion',
         result: result
       });
 
     } else if (event.data.type == 'getUserAgent') {
@@ -59,21 +47,16 @@ function workerTestExec(script) {
         type: 'returnUserAgent',
         result: navigator.userAgent
       });
     } else if (event.data.type == 'getOSCPU') {
       worker.postMessage({
         type: 'returnOSCPU',
         result: navigator.oscpu
       });
-    } else if (event.data.type == 'getIsB2G') {
-      worker.postMessage({
-        type: 'returnIsB2G',
-        result: SpecialPowers.isB2G
-      });
     }
   }
 
   worker.onerror = function(event) {
     ok(false, 'Worker had an error: ' + event.data);
     SimpleTest.finish();
   };
 
--- a/dom/workers/test/worker_wrapper.js
+++ b/dom/workers/test/worker_wrapper.js
@@ -79,29 +79,16 @@ function workerTestGetOSCPU(cb) {
     removeEventListener('message', workerTestGetOSCPUCB);
     cb(e.data.result);
   });
   postMessage({
     type: 'getOSCPU'
   });
 }
 
-function workerTestGetIsB2G(cb) {
-  addEventListener('message', function workerTestGetIsB2GCB(e) {
-    if (e.data.type !== 'returnIsB2G') {
-      return;
-    }
-    removeEventListener('message', workerTestGetIsB2GCB);
-    cb(e.data.result);
-  });
-  postMessage({
-    type: 'getIsB2G'
-  });
-}
-
 addEventListener('message', function workerWrapperOnMessage(e) {
   removeEventListener('message', workerWrapperOnMessage);
   var data = e.data;
   try {
     importScripts(data.script);
   } catch(e) {
     postMessage({
       type: 'status',
--- a/js/src/builtin/Object.cpp
+++ b/js/src/builtin/Object.cpp
@@ -665,16 +665,68 @@ js::ObjectCreateImpl(JSContext* cx, Hand
 PlainObject*
 js::ObjectCreateWithTemplate(JSContext* cx, HandlePlainObject templateObj)
 {
     RootedObject proto(cx, templateObj->staticPrototype());
     RootedObjectGroup group(cx, templateObj->group());
     return ObjectCreateImpl(cx, proto, GenericObject, group);
 }
 
+// ES 2017 draft 19.1.2.3.1
+static bool
+ObjectDefineProperties(JSContext* cx, HandleObject obj, HandleValue properties)
+{
+    // Step 1. implicit
+    // Step 2.
+    RootedObject props(cx, ToObject(cx, properties));
+    if (!props)
+        return false;
+
+    // Step 3.
+    AutoIdVector keys(cx);
+    if (!GetPropertyKeys(cx, props, JSITER_OWNONLY | JSITER_SYMBOLS | JSITER_HIDDEN, &keys))
+        return false;
+
+    RootedId nextKey(cx);
+    Rooted<PropertyDescriptor> desc(cx);
+    RootedValue descObj(cx);
+
+    // Step 4.
+    Rooted<PropertyDescriptorVector> descriptors(cx, PropertyDescriptorVector(cx));
+    AutoIdVector descriptorKeys(cx);
+
+    // Step 5.
+    for (size_t i = 0, len = keys.length(); i < len; i++) {
+        nextKey = keys[i];
+
+        // Step 5.a.
+        if (!GetOwnPropertyDescriptor(cx, props, nextKey, &desc))
+            return false;
+
+        // Step 5.b.
+        if (desc.object() && desc.enumerable()) {
+            if (!GetProperty(cx, props, props, nextKey, &descObj) ||
+                !ToPropertyDescriptor(cx, descObj, false, &desc) ||
+                !descriptors.append(desc) ||
+                !descriptorKeys.append(nextKey))
+            {
+                return false;
+            }
+        }
+    }
+
+    // Step 6.
+    for (size_t i = 0, len = descriptors.length(); i < len; i++) {
+        if (!DefineProperty(cx, obj, descriptorKeys[i], descriptors[i]))
+            return false;
+    }
+
+    return true;
+}
+
 // ES6 draft rev34 (2015/02/20) 19.1.2.2 Object.create(O [, Properties])
 bool
 js::obj_create(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     // Step 1.
     if (args.length() == 0) {
@@ -697,19 +749,17 @@ js::obj_create(JSContext* cx, unsigned a
     // Step 2.
     RootedObject proto(cx, args[0].toObjectOrNull());
     RootedPlainObject obj(cx, ObjectCreateImpl(cx, proto));
     if (!obj)
         return false;
 
     // Step 3.
     if (args.hasDefined(1)) {
-        RootedValue val(cx, args[1]);
-        RootedObject props(cx, ToObject(cx, val));
-        if (!props || !DefineProperties(cx, obj, props))
+        if (!ObjectDefineProperties(cx, obj, args[1]))
             return false;
     }
 
     // Step 4.
     args.rval().setObject(*obj);
     return true;
 }
 
@@ -765,17 +815,16 @@ EnumerableOwnProperties(JSContext* cx, c
     RootedId id(cx);
     RootedValue key(cx);
     RootedValue value(cx);
     RootedNativeObject nobj(cx);
     if (obj->is<NativeObject>())
         nobj = &obj->as<NativeObject>();
     RootedShape shape(cx);
     Rooted<PropertyDescriptor> desc(cx);
-
     // Step 4.
     size_t out = 0;
     for (size_t i = 0; i < len; i++) {
         id = ids[i];
 
         // Step 4.a. (Symbols were filtered out in step 2.)
         MOZ_ASSERT(!JSID_IS_SYMBOL(id));
 
@@ -982,23 +1031,19 @@ obj_defineProperties(JSContext* cx, unsi
     args.rval().setObject(*obj);
 
     /* Step 2. */
     if (args.length() < 2) {
         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_MORE_ARGS_NEEDED,
                                   "Object.defineProperties", "0", "s");
         return false;
     }
-    RootedValue val(cx, args[1]);
-    RootedObject props(cx, ToObject(cx, val));
-    if (!props)
-        return false;
 
     /* Steps 3-6. */
-    return DefineProperties(cx, obj, props);
+    return ObjectDefineProperties(cx, obj, args[1]);
 }
 
 // ES6 20141014 draft 19.1.2.15 Object.preventExtensions(O)
 static bool
 obj_preventExtensions(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     args.rval().set(args.get(0));
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -437,33 +437,16 @@ js::ReadPropertyDescriptors(JSContext* c
             !descs.append(desc))
         {
             return false;
         }
     }
     return true;
 }
 
-bool
-js::DefineProperties(JSContext* cx, HandleObject obj, HandleObject props)
-{
-    AutoIdVector ids(cx);
-    Rooted<PropertyDescriptorVector> descs(cx, PropertyDescriptorVector(cx));
-    if (!ReadPropertyDescriptors(cx, props, true, &ids, &descs))
-        return false;
-
-    for (size_t i = 0, len = ids.length(); i < len; i++) {
-        if (!DefineProperty(cx, obj, ids[i], descs[i]))
-            return false;
-    }
-
-    return true;
-}
-
-
 /*** Seal and freeze *****************************************************************************/
 
 static unsigned
 GetSealedOrFrozenAttributes(unsigned attrs, IntegrityLevel level)
 {
     /* Make all attributes permanent; if freezing, make data attributes read-only. */
     if (level == IntegrityLevel::Frozen && !(attrs & (JSPROP_GETTER | JSPROP_SETTER)))
         return JSPROP_PERMANENT | JSPROP_READONLY;
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -1169,19 +1169,16 @@ extern JSObject*
 CreateThis(JSContext* cx, const js::Class* clasp, js::HandleObject callee);
 
 extern JSObject*
 CloneObject(JSContext* cx, HandleObject obj, Handle<js::TaggedProto> proto);
 
 extern JSObject*
 DeepCloneObjectLiteral(JSContext* cx, HandleObject obj, NewObjectKind newKind = GenericObject);
 
-extern bool
-DefineProperties(JSContext* cx, HandleObject obj, HandleObject props);
-
 inline JSGetterOp
 CastAsGetterOp(JSObject* object)
 {
     return JS_DATA_TO_FUNC_PTR(JSGetterOp, object);
 }
 
 inline JSSetterOp
 CastAsSetterOp(JSObject* object)
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/Object/defineProperties-order.js
@@ -0,0 +1,17 @@
+// Based on testcases provided by André Bargull
+
+let log = [];
+let logger = new Proxy({}, {
+    get(target, key) {
+        log.push(key);
+    }
+});
+
+Object.create(null, new Proxy({a: {value: 0}, b: {value: 1}}, logger));
+assertEq(log.join(), "ownKeys,getOwnPropertyDescriptor,get,getOwnPropertyDescriptor,get");
+
+log = [];
+Object.defineProperties({}, new Proxy({a: {value: 0}, b: {value: 1}}, logger));
+assertEq(log.join(), "ownKeys,getOwnPropertyDescriptor,get,getOwnPropertyDescriptor,get");
+
+reportCompare(true, true);
new file mode 100644
--- /dev/null
+++ b/layout/base/crashtests/1308793.svg
@@ -0,0 +1,31 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<svg xmlns="http://www.w3.org/2000/svg">
+
+<title>Crash test for bug 1308793</title>
+
+<style id="s" type="text/css">
+tspan { fill: green;}
+.flex { display:flex; }
+.grid { display:grid; }
+.col { columns: 3; }
+</style>
+
+<text class="flex">
+  <tspan x="100" y="50">A</tspan>
+  B
+</text>
+
+<text class="grid">
+  <tspan x="100" y="50">A</tspan>
+  B
+</text>
+
+<text class="col">
+  <tspan x="100" y="50">A</tspan>
+  B
+</text>
+
+</svg>
--- a/layout/base/crashtests/crashtests.list
+++ b/layout/base/crashtests/crashtests.list
@@ -474,8 +474,9 @@ load 1234622-1.html
 load 1235467-1.html
 pref(dom.webcomponents.enabled,true) load 1261351.html
 load 1270797-1.html
 load 1278455-1.html
 load 1286889.html
 load 1297835.html
 load 1288608.html
 load 1299736-1.html
+load 1308793.svg
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -3582,17 +3582,18 @@ nsCSSFrameConstructor::FindHTMLData(Elem
     COMPLEX_TAG_CREATE(fieldset,
                        &nsCSSFrameConstructor::ConstructFieldSetFrame),
     { &nsGkAtoms::legend,
       FCDATA_DECL(FCDATA_ALLOW_BLOCK_STYLES | FCDATA_MAY_NEED_SCROLLFRAME,
                   NS_NewLegendFrame) },
     SIMPLE_TAG_CREATE(frameset, NS_NewHTMLFramesetFrame),
     SIMPLE_TAG_CREATE(iframe, NS_NewSubDocumentFrame),
     { &nsGkAtoms::button,
-      FCDATA_WITH_WRAPPING_BLOCK(FCDATA_ALLOW_BLOCK_STYLES,
+      FCDATA_WITH_WRAPPING_BLOCK(FCDATA_ALLOW_BLOCK_STYLES |
+                                 FCDATA_ALLOW_GRID_FLEX_COLUMNSET,
                                  NS_NewHTMLButtonControlFrame,
                                  nsCSSAnonBoxes::buttonContent) },
     SIMPLE_TAG_CHAIN(canvas, nsCSSFrameConstructor::FindCanvasData),
     SIMPLE_TAG_CREATE(video, NS_NewHTMLVideoFrame),
     SIMPLE_TAG_CREATE(audio, NS_NewHTMLVideoFrame),
     SIMPLE_TAG_CREATE(progress, NS_NewProgressFrame),
     SIMPLE_TAG_CREATE(meter, NS_NewMeterFrame),
     COMPLEX_TAG_CREATE(details, &nsCSSFrameConstructor::ConstructDetailsFrame)
@@ -3888,52 +3889,58 @@ nsCSSFrameConstructor::ConstructFrameFro
                                                          styleContext);
 #ifdef DEBUG
       nsContainerFrame* containerFrame = do_QueryFrame(newFrame);
       MOZ_ASSERT(containerFrame);
 #endif
       nsContainerFrame* container = static_cast<nsContainerFrame*>(newFrame);
       nsContainerFrame* outerFrame;
       nsContainerFrame* innerFrame;
-      switch (display->mDisplay) {
-        case StyleDisplay::Flex:
-        case StyleDisplay::InlineFlex:
-          outerFrame = NS_NewFlexContainerFrame(mPresShell, outerSC);
-          InitAndRestoreFrame(aState, content, container, outerFrame);
-          innerFrame = outerFrame;
-          break;
-        case StyleDisplay::Grid:
-        case StyleDisplay::InlineGrid:
-          outerFrame = NS_NewGridContainerFrame(mPresShell, outerSC);
-          InitAndRestoreFrame(aState, content, container, outerFrame);
-          innerFrame = outerFrame;
-          break;
-        default: {
-          nsContainerFrame* columnSetFrame = nullptr;
-          RefPtr<nsStyleContext> innerSC = outerSC;
-          const nsStyleColumn* columns = outerSC->StyleColumn();
-          if (columns->mColumnCount != NS_STYLE_COLUMN_COUNT_AUTO ||
-              columns->mColumnWidth.GetUnit() != eStyleUnit_Auto) {
-            columnSetFrame =
-              NS_NewColumnSetFrame(mPresShell, outerSC, nsFrameState(0));
-            InitAndRestoreFrame(aState, content, container, columnSetFrame);
-            innerSC = mPresShell->StyleSet()->ResolveAnonymousBoxStyle(
-              nsCSSAnonBoxes::columnContent, outerSC);
+      if (bits & FCDATA_ALLOW_GRID_FLEX_COLUMNSET) {
+        switch (display->mDisplay) {
+          case StyleDisplay::Flex:
+          case StyleDisplay::InlineFlex:
+            outerFrame = NS_NewFlexContainerFrame(mPresShell, outerSC);
+            InitAndRestoreFrame(aState, content, container, outerFrame);
+            innerFrame = outerFrame;
+            break;
+          case StyleDisplay::Grid:
+          case StyleDisplay::InlineGrid:
+            outerFrame = NS_NewGridContainerFrame(mPresShell, outerSC);
+            InitAndRestoreFrame(aState, content, container, outerFrame);
+            innerFrame = outerFrame;
+            break;
+          default: {
+            nsContainerFrame* columnSetFrame = nullptr;
+            RefPtr<nsStyleContext> innerSC = outerSC;
+            const nsStyleColumn* columns = outerSC->StyleColumn();
+            if (columns->mColumnCount != NS_STYLE_COLUMN_COUNT_AUTO ||
+                columns->mColumnWidth.GetUnit() != eStyleUnit_Auto) {
+              columnSetFrame =
+                NS_NewColumnSetFrame(mPresShell, outerSC, nsFrameState(0));
+              InitAndRestoreFrame(aState, content, container, columnSetFrame);
+              innerSC = mPresShell->StyleSet()->ResolveAnonymousBoxStyle(
+                nsCSSAnonBoxes::columnContent, outerSC);
+            }
+            innerFrame = NS_NewBlockFormattingContext(mPresShell, innerSC);
+            if (columnSetFrame) {
+              InitAndRestoreFrame(aState, content, columnSetFrame, innerFrame);
+              SetInitialSingleChild(columnSetFrame, innerFrame);
+              outerFrame = columnSetFrame;
+            } else {
+              InitAndRestoreFrame(aState, content, container, innerFrame);
+              outerFrame = innerFrame;
+            }
+            break;
           }
-          innerFrame = NS_NewBlockFormattingContext(mPresShell, innerSC);
-          if (columnSetFrame) {
-            InitAndRestoreFrame(aState, content, columnSetFrame, innerFrame);
-            SetInitialSingleChild(columnSetFrame, innerFrame);
-            outerFrame = columnSetFrame;
-          } else {
-            InitAndRestoreFrame(aState, content, container, innerFrame);
-            outerFrame = innerFrame;
-          }
-          break;
         }
+      } else {
+        innerFrame = NS_NewBlockFormattingContext(mPresShell, outerSC);
+        InitAndRestoreFrame(aState, content, container, innerFrame);
+        outerFrame = innerFrame;
       }
 
       SetInitialSingleChild(container, outerFrame);
 
       // Now figure out whether newFrame or outerFrame should be the
       // absolute container.
       auto outerDisplay = outerSC->StyleDisplay();
       if (outerDisplay->IsAbsPosContainingBlock(outerFrame)) {
--- a/layout/base/nsCSSFrameConstructor.h
+++ b/layout/base/nsCSSFrameConstructor.h
@@ -684,16 +684,22 @@ private:
 #define FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS 0x40000
   /* If FCDATA_IS_SVG_TEXT is set, then this text frame is a descendant of
      an SVG text frame. */
 #define FCDATA_IS_SVG_TEXT 0x80000
   /**
    * display:contents
    */
 #define FCDATA_IS_CONTENTS 0x100000
+  /**
+   * When FCDATA_CREATE_BLOCK_WRAPPER_FOR_ALL_KIDS is set, this bit says
+   * if we should create a grid/flex/columnset container instead of
+   * a block wrapper when the styles says so.
+   */
+#define FCDATA_ALLOW_GRID_FLEX_COLUMNSET 0x200000
 
   /* Structure representing information about how a frame should be
      constructed.  */
   struct FrameConstructionData {
     // Flag bits that can modify the way the construction happens
     uint32_t mBits;
     // We have exactly one of three types of functions, so use a union for
     // better cache locality for the ones that aren't pointer-to-member.  That
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -970,18 +970,19 @@ PresShell::Init(nsIDocument* aDocument,
     }
 #endif
 
   if (mDocument->HasAnimationController()) {
     nsSMILAnimationController* animCtrl = mDocument->GetAnimationController();
     animCtrl->NotifyRefreshDriverCreated(GetPresContext()->RefreshDriver());
   }
 
-  mDocument->Timeline()->NotifyRefreshDriverCreated(GetPresContext()->
-                                                      RefreshDriver());
+  for (DocumentTimeline* timeline : mDocument->Timelines()) {
+    timeline->NotifyRefreshDriverCreated(GetPresContext()->RefreshDriver());
+  }
 
   // Get our activeness from the docShell.
   QueryIsActive();
 
   // Setup our font inflation preferences.
   SetupFontInflation();
 
   mTouchManager.Init(this, mDocument);
@@ -1271,18 +1272,19 @@ PresShell::Destroy()
   // this presshell while the frames are being torn down
   if (mDocument) {
     NS_ASSERTION(mDocument->GetShell() == this, "Wrong shell?");
     mDocument->DeleteShell();
 
     if (mDocument->HasAnimationController()) {
       mDocument->GetAnimationController()->NotifyRefreshDriverDestroying(rd);
     }
-
-    mDocument->Timeline()->NotifyRefreshDriverDestroying(rd);
+    for (DocumentTimeline* timeline : mDocument->Timelines()) {
+      timeline->NotifyRefreshDriverDestroying(rd);
+    }
   }
 
   if (mPresContext) {
     mPresContext->AnimationManager()->ClearEventQueue();
     mPresContext->TransitionManager()->ClearEventQueue();
   }
 
   // Revoke any pending events.  We need to do this and cancel pending reflows