merge mozilla-inbound to mozilla-central. r=merge a=merge
authorSebastian Hengst <archaeopteryx@coole-files.de>
Mon, 28 Aug 2017 16:53:53 +0200
changeset 426713 e2efa420beb1a578c7350ba925c82230da6b1267
parent 426697 d5b6d113cf17f4c91b574eaa2d077a233bc4bc69 (current diff)
parent 426712 0535c19bb610445d379eb98b67a9e8ee34fc37ac (diff)
child 426714 eb9f9ee96f264a56506b2185071ec28dc13c2bcd
child 426760 2932577f253f4d2fe8f459bb281a1d92695c417a
child 426925 40c5c8d062dea507791c22e53ccb33b30308f5a4
push id7761
push userjlund@mozilla.com
push dateFri, 15 Sep 2017 00:19:52 +0000
treeherdermozilla-beta@c38455951db4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge, merge
milestone57.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
merge mozilla-inbound to mozilla-central. r=merge a=merge MozReview-Commit-ID: AeoHOxZLi6m
dom/html/HTMLVideoElement.cpp
dom/html/HTMLVideoElement.h
dom/media/MediaPrefs.h
dom/webidl/HTMLVideoElement.webidl
editor/libeditor/EditorBase.cpp
js/src/jit/none/AtomicOperations-none.h
mobile/android/app/mobile.js
toolkit/content/widgets/videocontrols.xml
--- a/dom/base/Link.cpp
+++ b/dom/base/Link.cpp
@@ -4,16 +4,21 @@
  * 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 "Link.h"
 
 #include "mozilla/EventStates.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/dom/Element.h"
+#ifdef ANDROID
+#include "mozilla/IHistory.h"
+#else
+#include "mozilla/places/History.h"
+#endif
 #include "nsIURL.h"
 #include "nsISizeOf.h"
 #include "nsIDocShell.h"
 #include "nsIPrefetchService.h"
 #include "nsCPrefetchService.h"
 #include "nsStyleLinkElement.h"
 
 #include "nsEscape.h"
@@ -23,36 +28,40 @@
 #include "mozAutoDocUpdate.h"
 
 #include "mozilla/Services.h"
 #include "nsAttrValueInlines.h"
 
 namespace mozilla {
 namespace dom {
 
+#ifndef ANDROID
+using places::History;
+#endif
+
 Link::Link(Element *aElement)
   : mElement(aElement)
-  , mHistory(services::GetHistoryService())
   , mLinkState(eLinkState_NotLink)
   , mNeedsRegistration(false)
   , mRegistered(false)
   , mHasPendingLinkUpdate(false)
   , mInDNSPrefetch(false)
+  , mHistory(true)
 {
   MOZ_ASSERT(mElement, "Must have an element");
 }
 
 Link::Link()
   : mElement(nullptr)
-  , mHistory(nullptr)
   , mLinkState(eLinkState_NotLink)
   , mNeedsRegistration(false)
   , mRegistered(false)
   , mHasPendingLinkUpdate(false)
   , mInDNSPrefetch(false)
+  , mHistory(false)
 {
 }
 
 Link::~Link()
 {
   // !mElement is for mock_Link.
   MOZ_ASSERT(!mElement || !mElement->IsInComposedDoc());
   if (IsInDNSPrefetch()) {
@@ -375,22 +384,29 @@ Link::LinkState() const
     nsCOMPtr<nsIURI> hrefURI(GetURI());
 
     // Assume that we are not visited until we are told otherwise.
     self->mLinkState = eLinkState_Unvisited;
 
     // Make sure the href attribute has a valid link (bug 23209).
     // If we have a good href, register with History if available.
     if (mHistory && hrefURI) {
-      nsresult rv = mHistory->RegisterVisitedCallback(hrefURI, self);
-      if (NS_SUCCEEDED(rv)) {
-        self->mRegistered = true;
+#ifdef ANDROID
+      nsCOMPtr<IHistory> history = services::GetHistoryService();
+#else
+      History* history = History::GetService();
+#endif
+      if (history) {
+        nsresult rv = history->RegisterVisitedCallback(hrefURI, self);
+        if (NS_SUCCEEDED(rv)) {
+          self->mRegistered = true;
 
-        // And make sure we are in the document's link map.
-        element->GetComposedDoc()->AddStyleRelevantLink(self);
+          // And make sure we are in the document's link map.
+          element->GetComposedDoc()->AddStyleRelevantLink(self);
+        }
       }
     }
   }
 
   // Otherwise, return our known state.
   if (mLinkState == eLinkState_Visited) {
     return NS_EVENT_STATE_VISITED;
   }
@@ -747,24 +763,23 @@ Link::ResetLinkState(bool aNotify, bool 
   // from the doc and the history.
   if (!mNeedsRegistration && mLinkState != eLinkState_NotLink) {
     nsIDocument *doc = mElement->GetComposedDoc();
     if (doc && (mRegistered || mLinkState == eLinkState_Visited)) {
       // Tell the document to forget about this link if we've registered
       // with it before.
       doc->ForgetLink(this);
     }
-
-    UnregisterFromHistory();
   }
 
   // If we have an href, we should register with the history.
   mNeedsRegistration = aHasHref;
 
   // If we've cached the URI, reset always invalidates it.
+  UnregisterFromHistory();
   mCachedURI = nullptr;
 
   // Update our state back to the default.
   mLinkState = defaultState;
 
   // We have to be very careful here: if aNotify is false we do NOT
   // want to call UpdateState, because that will call into LinkState()
   // and try to start off loads, etc.  But ResetLinkState is called
@@ -787,24 +802,29 @@ Link::ResetLinkState(bool aNotify, bool 
 void
 Link::UnregisterFromHistory()
 {
   // If we are not registered, we have nothing to do.
   if (!mRegistered) {
     return;
   }
 
-  NS_ASSERTION(mCachedURI, "mRegistered is true, but we have no cached URI?!");
-
   // And tell History to stop tracking us.
-  if (mHistory) {
-    nsresult rv = mHistory->UnregisterVisitedCallback(mCachedURI, this);
-    NS_ASSERTION(NS_SUCCEEDED(rv), "This should only fail if we misuse the API!");
-    if (NS_SUCCEEDED(rv)) {
-      mRegistered = false;
+  if (mHistory && mCachedURI) {
+#ifdef ANDROID
+    nsCOMPtr<IHistory> history = services::GetHistoryService();
+#else
+    History* history = History::GetService();
+#endif
+    if (history) {
+      nsresult rv = history->UnregisterVisitedCallback(mCachedURI, this);
+      NS_ASSERTION(NS_SUCCEEDED(rv), "This should only fail if we misuse the API!");
+      if (NS_SUCCEEDED(rv)) {
+        mRegistered = false;
+      }
     }
   }
 }
 
 already_AddRefed<nsIURI>
 Link::GetURIToMutate()
 {
   nsCOMPtr<nsIURI> uri(GetURI());
@@ -839,17 +859,16 @@ Link::SizeOfExcludingThis(mozilla::SizeO
     nsCOMPtr<nsISizeOf> iface = do_QueryInterface(mCachedURI);
     if (iface) {
       n += iface->SizeOfIncludingThis(aState.mMallocSizeOf);
     }
   }
 
   // The following members don't need to be measured:
   // - mElement, because it is a pointer-to-self used to avoid QIs
-  // - mHistory, because it is non-owning
 
   return n;
 }
 
 static const nsAttrValue::EnumTable kAsAttributeTable[] = {
   { "",              DESTINATION_INVALID       },
   { "audio",         DESTINATION_AUDIO         },
   { "font",          DESTINATION_FONT          },
--- a/dom/base/Link.h
+++ b/dom/base/Link.h
@@ -6,17 +6,16 @@
 
 /**
  * This is the base class for all link classes.
  */
 
 #ifndef mozilla_dom_Link_h__
 #define mozilla_dom_Link_h__
 
-#include "mozilla/IHistory.h"
 #include "mozilla/MemoryReporting.h"
 #include "nsIContent.h" // for nsLinkState
 #include "nsIContentPolicy.h"
 
 namespace mozilla {
 
 class EventStates;
 
@@ -177,29 +176,27 @@ private:
                                      nsContentPolicyType& aPolicyType,
                                      nsString& aMimeType,
                                      nsAString& aMedia);
 
   mutable nsCOMPtr<nsIURI> mCachedURI;
 
   Element * const mElement;
 
-  // Strong reference to History.  The link has to unregister before History
-  // can disappear.
-  nsCOMPtr<IHistory> mHistory;
-
   uint16_t mLinkState;
 
   bool mNeedsRegistration : 1;
 
   bool mRegistered : 1;
 
   bool mHasPendingLinkUpdate : 1;
 
   bool mInDNSPrefetch : 1;
+
+  bool mHistory: 1;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(Link, MOZILLA_DOM_LINK_IMPLEMENTATION_IID)
 
 enum ASDestination : uint8_t {
   DESTINATION_INVALID,
   DESTINATION_AUDIO,
   DESTINATION_DOCUMENT,
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -690,18 +690,17 @@ nsDOMClassInfo::Resolve(nsIXPConnectWrap
   }
 
   if (desc.object() && !desc.hasGetterOrSetter() && desc.value().isObject()) {
     // If val is not an (non-null) object there either is no
     // constructor for this class, or someone messed with
     // window.classname, just fall through and let the JS engine
     // return the Object constructor.
     if (!::JS_DefinePropertyById(cx, obj, id, desc.value(),
-                                 JSPROP_ENUMERATE,
-                                 JS_STUBGETTER, JS_STUBSETTER)) {
+                                 JSPROP_ENUMERATE)) {
       return NS_ERROR_UNEXPECTED;
     }
 
     *resolvedp = true;
   }
 
   return NS_OK;
 }
@@ -939,18 +938,17 @@ DefineInterfaceConstants(JSContext *cx, 
 
   JS::Rooted<JS::Value> v(cx);
   for (i = parent_constant_count; i < constant_count; i++) {
     nsCString name;
     rv = if_info->GetConstant(i, &v, getter_Copies(name));
     NS_ENSURE_TRUE(NS_SUCCEEDED(rv), rv);
 
     if (!::JS_DefineProperty(cx, obj, name.get(), v,
-                             JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT,
-                             JS_STUBGETTER, JS_STUBSETTER)) {
+                             JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT)) {
       return NS_ERROR_UNEXPECTED;
     }
   }
 
   return NS_OK;
 }
 
 class nsDOMConstructor final : public nsIDOMDOMConstructor
@@ -1470,18 +1468,17 @@ ResolvePrototype(nsIXPConnect *aXPConnec
 
   v.setObject(*dot_prototype);
 
   JSAutoCompartment ac(cx, class_obj);
 
   // Per ECMA, the prototype property is {DontEnum, DontDelete, ReadOnly}
   if (!JS_WrapValue(cx, &v) ||
       !JS_DefineProperty(cx, class_obj, "prototype", v,
-                         JSPROP_PERMANENT | JSPROP_READONLY,
-                         JS_STUBGETTER, JS_STUBSETTER)) {
+                         JSPROP_PERMANENT | JSPROP_READONLY)) {
     return NS_ERROR_UNEXPECTED;
   }
 
   return NS_OK;
 }
 
 static bool
 OldBindingConstructorEnabled(const nsGlobalNameStruct *aStruct,
@@ -1752,18 +1749,17 @@ LookupComponentsShim(JSContext *cx, JS::
   JS::Rooted<JSObject*> components(cx, JS_NewPlainObject(cx));
   NS_ENSURE_TRUE(components, NS_ERROR_OUT_OF_MEMORY);
 
   // Create a fake interfaces object.
   JS::Rooted<JSObject*> interfaces(cx, JS_NewPlainObject(cx));
   NS_ENSURE_TRUE(interfaces, NS_ERROR_OUT_OF_MEMORY);
   bool ok =
     JS_DefineProperty(cx, components, "interfaces", interfaces,
-                      JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY,
-                      JS_STUBGETTER, JS_STUBSETTER);
+                      JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY);
   NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
 
   // Define a bunch of shims from the Ci.nsIDOMFoo to window.Foo for DOM
   // interfaces with constants.
   for (uint32_t i = 0; i < ArrayLength(kInterfaceShimMap); ++i) {
 
     // Grab the names from the table.
     const char *geckoName = kInterfaceShimMap[i].geckoName;
@@ -1775,18 +1771,17 @@ LookupComponentsShim(JSContext *cx, JS::
     NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
     if (!v.isObject()) {
       NS_WARNING("Unable to find interface object on global");
       continue;
     }
 
     // Define the shim on the interfaces object.
     ok = JS_DefineProperty(cx, interfaces, geckoName, v,
-                           JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY,
-                           JS_STUBGETTER, JS_STUBSETTER);
+                           JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY);
     NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
   }
 
   FillPropertyDescriptor(desc, global, JS::ObjectValue(*components), false);
 
   return NS_OK;
 }
 
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -14681,18 +14681,17 @@ nsGlobalWindow::RedefineProperty(JSConte
 {
   JS::Rooted<JSObject*> thisObj(aCx, GetWrapperPreserveColor());
   if (!thisObj) {
     aError.Throw(NS_ERROR_UNEXPECTED);
     return;
   }
 
   if (!JS_WrapObject(aCx, &thisObj) ||
-      !JS_DefineProperty(aCx, thisObj, aPropName, aValue, JSPROP_ENUMERATE,
-                         JS_STUBGETTER, JS_STUBSETTER)) {
+      !JS_DefineProperty(aCx, thisObj, aPropName, aValue, JSPROP_ENUMERATE)) {
     aError.Throw(NS_ERROR_FAILURE);
   }
 }
 
 void
 nsGlobalWindow::GetReplaceableWindowCoord(JSContext* aCx,
                                           nsGlobalWindow::WindowCoordGetter aGetter,
                                           JS::MutableHandle<JS::Value> aRetval,
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -832,18 +832,17 @@ CreateInterfaceObject(JSContext* cx, JS:
     while (namedConstructors->mName) {
       JS::Rooted<JSObject*> namedConstructor(cx,
         CreateConstructor(cx, global, namedConstructors->mName,
                           &namedConstructors->mHolder,
                           namedConstructors->mNargs));
       if (!namedConstructor ||
           !JS_DefineProperty(cx, namedConstructor, "prototype",
                              proto,
-                             JSPROP_PERMANENT | JSPROP_READONLY,
-                             JS_STUBGETTER, JS_STUBSETTER) ||
+                             JSPROP_PERMANENT | JSPROP_READONLY) ||
           (defineOnGlobal &&
            !DefineConstructor(cx, global, namedConstructors->mName,
                               namedConstructor))) {
         return nullptr;
       }
       js::SetReservedSlot(constructor, namedConstructorSlot++,
                           JS::ObjectValue(*namedConstructor));
       ++namedConstructors;
--- a/dom/bindings/DOMJSProxyHandler.cpp
+++ b/dom/bindings/DOMJSProxyHandler.cpp
@@ -175,20 +175,16 @@ BaseDOMProxyHandler::getOwnPropertyDescr
                               desc);
 }
 
 bool
 DOMProxyHandler::defineProperty(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
                                 Handle<PropertyDescriptor> desc,
                                 JS::ObjectOpResult &result, bool *defined) const
 {
-  if (desc.hasGetterObject() && desc.setter() == JS_StrictPropertyStub) {
-    return result.failGetterOnly();
-  }
-
   if (xpc::WrapperFactory::IsXrayWrapper(proxy)) {
     return result.succeed();
   }
 
   JS::Rooted<JSObject*> expando(cx, EnsureExpandoObject(cx, proxy));
   if (!expando) {
     return false;
   }
--- a/dom/html/HTMLVideoElement.cpp
+++ b/dom/html/HTMLVideoElement.cpp
@@ -43,16 +43,17 @@ namespace dom {
 
 static bool sVideoStatsEnabled;
 
 NS_IMPL_ELEMENT_CLONE(HTMLVideoElement)
 
 HTMLVideoElement::HTMLVideoElement(already_AddRefed<NodeInfo>& aNodeInfo)
   : HTMLMediaElement(aNodeInfo)
   , mUseScreenWakeLock(true)
+  , mIsOrientationLocked(false)
 {
 }
 
 HTMLVideoElement::~HTMLVideoElement()
 {
 }
 
 nsresult HTMLVideoElement::GetVideoSize(nsIntSize* size)
--- a/dom/html/HTMLVideoElement.h
+++ b/dom/html/HTMLVideoElement.h
@@ -4,16 +4,17 @@
  * 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_HTMLVideoElement_h
 #define mozilla_dom_HTMLVideoElement_h
 
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/HTMLMediaElement.h"
+#include "MediaPrefs.h"
 
 namespace mozilla {
 
 class FrameStatistics;
 
 namespace dom {
 
 class WakeLock;
@@ -134,28 +135,46 @@ public:
 
   void NotifyOwnerDocumentActivityChanged() override;
 
   // Gives access to the decoder's frame statistics, if present.
   FrameStatistics* GetFrameStatistics();
 
   already_AddRefed<VideoPlaybackQuality> GetVideoPlaybackQuality();
 
+
+  bool MozOrientationLockEnabled() const
+  {
+    return MediaPrefs::VideoOrientationLockEnabled();
+  }
+
+  bool MozIsOrientationLocked() const
+  {
+    return mIsOrientationLocked;
+  }
+
+  void SetMozIsOrientationLocked(bool aLock)
+  {
+    mIsOrientationLocked = aLock;
+  }
+
 protected:
   virtual ~HTMLVideoElement();
 
   virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   virtual void WakeLockCreate() override;
   virtual void WakeLockRelease() override;
   void UpdateScreenWakeLock();
 
   bool mUseScreenWakeLock;
   RefPtr<WakeLock> mScreenWakeLock;
 
+  bool mIsOrientationLocked;
+
 private:
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
                                     GenericSpecifiedValues* aGenericData);
 
   static bool IsVideoStatsEnabled();
   double TotalPlayTime() const;
 };
 
--- a/dom/media/MediaPrefs.h
+++ b/dom/media/MediaPrefs.h
@@ -206,16 +206,17 @@ private:
                                                               MediaWarningsAsErrorsStageFrightVsRust, bool, false);
 
   // resume background video decoding when the cursor is hovering over the tab.
   DECL_MEDIA_PREF("media.resume-bkgnd-video-on-tabhover",     ResumeVideoDecodingOnTabHover, bool, false);
 
 #ifdef MOZ_CUBEB_REMOTING
   DECL_MEDIA_PREF("media.cubeb.sandbox",                      CubebSandbox, bool, false);
 #endif // MOZ_CUBEB_REMOTING
+  DECL_MEDIA_PREF("media.videocontrols.lock-video-orientation",  VideoOrientationLockEnabled, bool, false);
 
 public:
   // Manage the singleton:
   static MediaPrefs& GetSingleton();
   static bool SingletonExists();
 
 private:
   template<class T> friend class StaticAutoPtr;
new file mode 100644
--- /dev/null
+++ b/dom/media/test/crashtests/1368490.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<head>
+  <title> Bug 1368490 : Crash if media recorder source stream reduces number of channels. </title>
+</head>
+<meta charset="utf-8">
+<script type="text/javascript">
+
+function boom() {
+  let audioContext = new window.AudioContext();
+  let oscillator  = audioContext.createOscillator();
+  let dst = audioContext.createMediaStreamDestination();
+  oscillator.channelCount = 4;
+  dst.channelCount = 4;
+  oscillator.connect(dst, 0, 0);
+  oscillator.start();
+  mediaRec = new MediaRecorder(dst.stream);
+
+  mediaRec.start(100);
+  setTimeout(() => {
+    dst.channelCount = 1;
+    setTimeout(() => {
+      mediaRec.stop();
+      document.documentElement.removeAttribute("class");
+    }, 100);
+  }, 100);
+}
+</script>
+<body onload="boom();"></body>
+</html>
--- a/dom/media/test/crashtests/crashtests.list
+++ b/dom/media/test/crashtests/crashtests.list
@@ -78,16 +78,17 @@ load 1080986.html
 load 1122218.html
 load 1127188.html
 load 1157994.html
 load 1158427.html
 load 1185176.html
 load 1185192.html
 load 1304948.html
 load 1319486.html
+load 1368490.html
 load 1291702.html
 load 1384248.html
 load disconnect-wrong-destination.html
 load analyser-channels-1.html
 load audiocontext-double-suspend.html
 load buffer-source-duration-1.html
 load buffer-source-ended-1.html
 load buffer-source-resampling-start-1.html
--- a/dom/webidl/HTMLVideoElement.webidl
+++ b/dom/webidl/HTMLVideoElement.webidl
@@ -44,15 +44,23 @@ partial interface HTMLVideoElement {
   readonly attribute double mozFrameDelay;
 
   // True if the video has an audio track available.
   readonly attribute boolean mozHasAudio;
 
   // True if the video should use a screen wake lock.
   [Pref="dom.wakelock.enabled", Func="Navigator::HasWakeLockSupport"]
   attribute boolean mozUseScreenWakeLock;
+
+  // Attributes for builtin video controls to lock screen orientation.
+  // True if video controls should lock orientation when fullscreen.
+  [Pref="media.videocontrols.lock-video-orientation", Func="IsChromeOrXBL"]
+    readonly attribute boolean mozOrientationLockEnabled;
+  // True if screen orientation is locked by video controls.
+  [Pref="media.videocontrols.lock-video-orientation", Func="IsChromeOrXBL"]
+    attribute boolean mozIsOrientationLocked;
 };
 
 // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#idl-def-HTMLVideoElement
 partial interface HTMLVideoElement {
   [Func="mozilla::dom::MediaSource::Enabled", NewObject]
   VideoPlaybackQuality getVideoPlaybackQuality();
 };
--- a/dom/xbl/nsXBLBinding.cpp
+++ b/dom/xbl/nsXBLBinding.cpp
@@ -900,18 +900,17 @@ GetOrCreateClassObjectMap(JSContext *cx,
   if (desc.object() && desc.value().isObject() &&
       JS::IsWeakMapObject(&desc.value().toObject())) {
     return &desc.value().toObject();
   }
 
   // It's not there. Create and define it.
   JS::Rooted<JSObject*> map(cx, JS::NewWeakMapObject(cx));
   if (!map || !JS_DefineProperty(cx, scope, mapName, map,
-                                 JSPROP_PERMANENT | JSPROP_READONLY,
-                                 JS_STUBGETTER, JS_STUBSETTER))
+                                 JSPROP_PERMANENT | JSPROP_READONLY))
   {
     return nullptr;
   }
   return map;
 }
 
 static JSObject*
 GetOrCreateMapEntryForPrototype(JSContext *cx, JS::Handle<JSObject*> proto)
@@ -1062,18 +1061,17 @@ nsXBLBinding::DoInitJSClass(JSContext *c
     NS_ADDREF(docInfo);
     JS_SetReservedSlot(proto, 0, JS::PrivateValue(aProtoBinding));
 
     // Next, enter the compartment of the property holder, wrap the proto, and
     // stick it on.
     JSAutoCompartment ac3(cx, holder);
     if (!JS_WrapObject(cx, &proto) ||
         !JS_DefineUCProperty(cx, holder, aClassName.get(), -1, proto,
-                             JSPROP_READONLY | JSPROP_PERMANENT,
-                             JS_STUBGETTER, JS_STUBSETTER))
+                             JSPROP_READONLY | JSPROP_PERMANENT))
     {
       return NS_ERROR_OUT_OF_MEMORY;
     }
   }
 
   // Whew. We have the proto. Wrap it back into the compartment of |obj|,
   // splice it in, and return it.
   JSAutoCompartment ac4(cx, obj);
--- a/dom/xbl/nsXBLProtoImpl.cpp
+++ b/dom/xbl/nsXBLProtoImpl.cpp
@@ -115,18 +115,17 @@ nsXBLProtoImpl::InstallImplementation(ns
 
     // This is just a property holder, so it doesn't need any special JSClass.
     propertyHolder = JS_NewObjectWithGivenProto(cx, nullptr, nullptr);
     NS_ENSURE_TRUE(propertyHolder, NS_ERROR_OUT_OF_MEMORY);
 
     // Define it as a property on the scopeObject, using the same name used on
     // the content side.
     bool ok = JS_DefineUCProperty(cx, scopeObject, className, -1, propertyHolder,
-                                  JSPROP_PERMANENT | JSPROP_READONLY,
-                                  JS_STUBGETTER, JS_STUBSETTER);
+                                  JSPROP_PERMANENT | JSPROP_READONLY);
     NS_ENSURE_TRUE(ok, NS_ERROR_UNEXPECTED);
   } else {
     propertyHolder = targetClassObject;
   }
 
   // Walk our member list and install each one in turn on the XBL scope object.
   if (propertyHolderIsNew) {
     for (nsXBLProtoImplMember* curr = mMembers;
--- a/editor/libeditor/EditorBase.cpp
+++ b/editor/libeditor/EditorBase.cpp
@@ -2495,22 +2495,24 @@ EditorBase::InsertTextImpl(const nsAStri
 
   // In some cases, the node may be the anonymous div elemnt or a mozBR
   // element.  Let's try to look for better insertion point in the nearest
   // text node if there is.
   FindBetterInsertionPoint(node, offset);
 
   // If a neighboring text node already exists, use that
   if (!node->IsNodeOfType(nsINode::eTEXT)) {
-    if (offset && node->GetChildAt(offset - 1)->IsNodeOfType(nsINode::eTEXT)) {
-      node = node->GetChildAt(offset - 1);
+    nsIContent* child = node->GetChildAt(offset);
+    if (offset && child && child->GetPreviousSibling() &&
+        child->GetPreviousSibling()->IsNodeOfType(nsINode::eTEXT)) {
+      node = child->GetPreviousSibling();
       offset = node->Length();
     } else if (offset < static_cast<int32_t>(node->Length()) &&
-               node->GetChildAt(offset)->IsNodeOfType(nsINode::eTEXT)) {
-      node = node->GetChildAt(offset);
+               child && child->IsNodeOfType(nsINode::eTEXT)) {
+      node = child;
       offset = 0;
     }
   }
 
   if (ShouldHandleIMEComposition()) {
     CheckedInt<int32_t> newOffset;
     if (!node->IsNodeOfType(nsINode::eTEXT)) {
       // create a text node
--- a/ipc/testshell/XPCShellEnvironment.cpp
+++ b/ipc/testshell/XPCShellEnvironment.cpp
@@ -473,18 +473,17 @@ XPCShellEnvironment::Init()
     }
     JSAutoCompartment ac(cx, globalObj);
 
     backstagePass->SetGlobalObject(globalObj);
 
     JS::Rooted<Value> privateVal(cx, PrivateValue(this));
     if (!JS_DefineProperty(cx, globalObj, "__XPCShellEnvironment",
                            privateVal,
-                           JSPROP_READONLY | JSPROP_PERMANENT,
-                           JS_STUBGETTER, JS_STUBSETTER) ||
+                           JSPROP_READONLY | JSPROP_PERMANENT) ||
         !JS_DefineFunctions(cx, globalObj, gGlobalFunctions) ||
         !JS_DefineProfilingFunctions(cx, globalObj))
     {
         NS_ERROR("JS_DefineFunctions failed!");
         return false;
     }
 
     mGlobalHolder = globalObj;
--- a/js/ipc/JavaScriptShared.cpp
+++ b/js/ipc/JavaScriptShared.cpp
@@ -570,30 +570,28 @@ JavaScriptShared::fromDescriptor(JSConte
         out->getter() = 0;
     } else if (desc.hasGetterObject()) {
         JSObject* getter = desc.getterObject();
         ObjectVariant objVar;
         if (!toObjectVariant(cx, getter, &objVar))
             return false;
         out->getter() = objVar;
     } else {
-        MOZ_ASSERT(desc.getter() != JS_PropertyStub);
         out->getter() = UnknownPropertyOp;
     }
 
     if (!desc.setter()) {
         out->setter() = 0;
     } else if (desc.hasSetterObject()) {
         JSObject* setter = desc.setterObject();
         ObjectVariant objVar;
         if (!toObjectVariant(cx, setter, &objVar))
             return false;
         out->setter() = objVar;
     } else {
-        MOZ_ASSERT(desc.setter() != JS_StrictPropertyStub);
         out->setter() = UnknownPropertyOp;
     }
 
     return true;
 }
 
 bool
 UnknownPropertyStub(JSContext* cx, HandleObject obj, HandleId id, MutableHandleValue vp)
--- a/js/src/Makefile.in
+++ b/js/src/Makefile.in
@@ -164,16 +164,17 @@ endif # HAVE_DTRACE
 # (only possible when tar is found)
 ifneq (,$(TAR))
 
 source-package:
 	SRCDIR=$(srcdir) \
 	DIST=$(DIST) \
 	MKDIR=$(MKDIR) \
 	TAR=$(TAR) \
+	AUTOCONF=$(AUTOCONF) \
 	MOZJS_MAJOR_VERSION=$(MOZJS_MAJOR_VERSION) \
 	MOZJS_MINOR_VERSION=$(MOZJS_MINOR_VERSION) \
 	MOZJS_PATCH_VERSION=$(MOZJS_PATCH_VERSION) \
 	MOZJS_ALPHA=$(MOZJS_ALPHA) \
 	$(srcdir)/make-source-package.sh
 
 clean::
 	DIST=$(DIST) \
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -2076,40 +2076,31 @@ ShellAllocationMetadataBuilder::build(JS
 
     RootedObject stack(cx, NewDenseEmptyArray(cx));
     if (!stack)
         oomUnsafe.crash("ShellAllocationMetadataBuilder::build");
 
     static int createdIndex = 0;
     createdIndex++;
 
-    if (!JS_DefineProperty(cx, obj, "index", createdIndex, 0,
-                           JS_STUBGETTER, JS_STUBSETTER))
-    {
+    if (!JS_DefineProperty(cx, obj, "index", createdIndex, 0))
         oomUnsafe.crash("ShellAllocationMetadataBuilder::build");
-    }
-
-    if (!JS_DefineProperty(cx, obj, "stack", stack, 0,
-                           JS_STUBGETTER, JS_STUBSETTER))
-    {
+
+    if (!JS_DefineProperty(cx, obj, "stack", stack, 0))
         oomUnsafe.crash("ShellAllocationMetadataBuilder::build");
-    }
 
     int stackIndex = 0;
     RootedId id(cx);
     RootedValue callee(cx);
     for (NonBuiltinScriptFrameIter iter(cx); !iter.done(); ++iter) {
         if (iter.isFunctionFrame() && iter.compartment() == cx->compartment()) {
             id = INT_TO_JSID(stackIndex);
             RootedObject callee(cx, iter.callee(cx));
-            if (!JS_DefinePropertyById(cx, stack, id, callee, 0,
-                                       JS_STUBGETTER, JS_STUBSETTER))
-            {
+            if (!JS_DefinePropertyById(cx, stack, id, callee, 0))
                 oomUnsafe.crash("ShellAllocationMetadataBuilder::build");
-            }
             stackIndex++;
         }
     }
 
     return obj;
 }
 
 const ShellAllocationMetadataBuilder ShellAllocationMetadataBuilder::metadataBuilder;
--- a/js/src/ctypes/CTypes.cpp
+++ b/js/src/ctypes/CTypes.cpp
@@ -2470,18 +2470,17 @@ JS_PUBLIC_API(bool)
 JS_InitCTypesClass(JSContext* cx, HandleObject global)
 {
   // attach ctypes property to global object
   RootedObject ctypes(cx, JS_NewObject(cx, &sCTypesGlobalClass));
   if (!ctypes)
     return false;
 
   if (!JS_DefineProperty(cx, global, "ctypes", ctypes,
-                         JSPROP_READONLY | JSPROP_PERMANENT,
-                         JS_STUBGETTER, JS_STUBSETTER)){
+                         JSPROP_READONLY | JSPROP_PERMANENT)) {
     return false;
   }
 
   if (!InitTypeClasses(cx, ctypes))
     return false;
 
   // attach API functions and properties
   if (!JS_DefineFunctions(cx, ctypes, sModuleFunctions) ||
--- a/js/src/jit/AtomicOperations.h
+++ b/js/src/jit/AtomicOperations.h
@@ -315,45 +315,75 @@ AtomicOperations::isLockfree(int32_t siz
       default:
         return false;
     }
 }
 
 } // namespace jit
 } // namespace js
 
-#if defined(JS_CODEGEN_ARM)
-# include "jit/arm/AtomicOperations-arm.h"
-#elif defined(JS_CODEGEN_ARM64)
+// As explained above, our atomic operations are not portable even in principle,
+// so we must include platform+compiler specific definitions here.
+//
+// x86, x64, arm, and arm64 are maintained by Mozilla.  All other platform
+// setups are by platform maintainers' request and are not maintained by
+// Mozilla.
+//
+// If you are using a platform+compiler combination that causes an error below
+// (and if the problem isn't just that the compiler uses a different name for a
+// known architecture), you have basically three options:
+//
+//  - find an already-supported compiler for the platform and use that instead
+//
+//  - write your own support code for the platform+compiler and create a new
+//    case below
+//
+//  - include jit/none/AtomicOperations-feeling-lucky.h in a case for the
+//    platform below, if you have a gcc-compatible compiler and truly feel
+//    lucky.  You may have to add a little code to that file, too.
+//
+// Simulators are confusing.  These atomic primitives must be compatible with
+// the code that the JIT emits, but of course for an ARM simulator running on
+// x86 the primitives here will be for x86, not for ARM, while the JIT emits ARM
+// code.  Our ARM simulator solves that the easy way: by using these primitives
+// to implement its atomic operations.  For other simulators there may need to
+// be special cases below to provide simulator-compatible primitives, for
+// example, for our ARM64 simulator the primitives could in principle
+// participate in the memory exclusivity monitors implemented by the simulator.
+// Such a solution is likely to be difficult.
+
+#if defined(__x86_64__) || defined(_M_X64) || defined(__i386__) || defined(_M_IX86)
+# if defined(__clang__) || defined(__GNUC__) || defined(_MSC_VER)
+#  include "jit/x86-shared/AtomicOperations-x86-shared.h"
+# else
+#  error "No AtomicOperations support for this platform+compiler combination"
+# endif
+#elif defined(__arm__)
+# if defined(__clang__) || defined(__GNUC__)
+#  include "jit/arm/AtomicOperations-arm.h"
+# else
+#  error "No AtomicOperations support for this platform+compiler combination"
+# endif
+#elif defined(__aarch64__)
 # include "jit/arm64/AtomicOperations-arm64.h"
-#elif defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
-# include "jit/mips-shared/AtomicOperations-mips-shared.h"
+#elif defined(__mips__)
+# if defined(__clang__) || defined(__GNUC__)
+#  include "jit/mips-shared/AtomicOperations-mips-shared.h"
+# else
+#  error "No AtomicOperations support for this platform+compiler combination"
+# endif
 #elif defined(__ppc__) || defined(__PPC__)
 # include "jit/none/AtomicOperations-feeling-lucky.h"
 #elif defined(__sparc__)
 # include "jit/none/AtomicOperations-feeling-lucky.h"
-#elif defined(JS_CODEGEN_NONE)
-  // You can disable the JIT with --disable-ion but you must still
-  // provide the atomic operations that will be used by the JS engine.
-  // When the JIT is disabled the operations are simply safe-for-races
-  // C++ realizations of atomics.  These operations cannot be written
-  // in portable C++, hence the default here is to crash.  See the
-  // top of the file for more guidance.
-# if defined(__ppc64__) || defined(__PPC64__) || defined(__ppc64le__) || defined(__PPC64LE__)
-#  include "jit/none/AtomicOperations-feeling-lucky.h"
-# elif defined(__aarch64__)
-#  include "jit/arm64/AtomicOperations-arm64.h"
-# elif defined(__alpha__)
-#  include "jit/none/AtomicOperations-feeling-lucky.h"
-# elif defined(__hppa__)
-#  include "jit/none/AtomicOperations-feeling-lucky.h"
-# elif defined(__sh__)
-#  include "jit/none/AtomicOperations-feeling-lucky.h"
-# else
-#  include "jit/none/AtomicOperations-none.h" // These MOZ_CRASH() always
-# endif
-#elif defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
-# include "jit/x86-shared/AtomicOperations-x86-shared.h"
+#elif defined(__ppc64__) || defined(__PPC64__) || defined(__ppc64le__) || defined(__PPC64LE__)
+# include "jit/none/AtomicOperations-feeling-lucky.h"
+#elif defined(__alpha__)
+# include "jit/none/AtomicOperations-feeling-lucky.h"
+#elif defined(__hppa__)
+# include "jit/none/AtomicOperations-feeling-lucky.h"
+#elif defined(__sh__)
+# include "jit/none/AtomicOperations-feeling-lucky.h"
 #else
-# error "Atomic operations must be defined for this platform"
+# error "No AtomicOperations support provided for this platform"
 #endif
 
 #endif // jit_AtomicOperations_h
--- a/js/src/jit/arm/CodeGenerator-arm.cpp
+++ b/js/src/jit/arm/CodeGenerator-arm.cpp
@@ -3099,16 +3099,17 @@ CodeGeneratorARM::visitSignExtendInt64(L
     switch (lir->mode()) {
       case MSignExtendInt64::Byte:
         masm.move8SignExtend(input.low, output.low);
         break;
       case MSignExtendInt64::Half:
         masm.move16SignExtend(input.low, output.low);
         break;
       case MSignExtendInt64::Word:
+        masm.move32(input.low, output.low);
         break;
     }
     masm.ma_asr(Imm32(31), output.low, output.high);
 }
 
 static Register
 WasmGetTemporaryForDivOrMod(Register64 lhs, Register64 rhs)
 {
deleted file mode 100644
--- a/js/src/jit/none/AtomicOperations-none.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set ts=8 sts=4 et sw=4 tw=99:
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/* For documentation, see jit/AtomicOperations.h */
-
-#ifndef jit_none_AtomicOperations_none_h
-#define jit_none_AtomicOperations_none_h
-
-#include "mozilla/Assertions.h"
-
-// A "none" build is never run (ref IRC discussion with h4writer) and
-// all functions here can therefore MOZ_CRASH, even if they are
-// referenced from other than jitted code.
-
-inline bool
-js::jit::AtomicOperations::isLockfree8()
-{
-    MOZ_CRASH();
-}
-
-inline void
-js::jit::AtomicOperations::fenceSeqCst()
-{
-    MOZ_CRASH();
-}
-
-template<typename T>
-inline T
-js::jit::AtomicOperations::loadSeqCst(T* addr)
-{
-    MOZ_CRASH();
-}
-
-template<typename T>
-inline void
-js::jit::AtomicOperations::storeSeqCst(T* addr, T val)
-{
-    MOZ_CRASH();
-}
-
-template<typename T>
-inline T
-js::jit::AtomicOperations::compareExchangeSeqCst(T* addr, T oldval, T newval)
-{
-    MOZ_CRASH();
-}
-
-template<typename T>
-inline T
-js::jit::AtomicOperations::fetchAddSeqCst(T* addr, T val)
-{
-    MOZ_CRASH();
-}
-
-template<typename T>
-inline T
-js::jit::AtomicOperations::fetchSubSeqCst(T* addr, T val)
-{
-    MOZ_CRASH();
-}
-
-template<typename T>
-inline T
-js::jit::AtomicOperations::fetchAndSeqCst(T* addr, T val)
-{
-    MOZ_CRASH();
-}
-
-template<typename T>
-inline T
-js::jit::AtomicOperations::fetchOrSeqCst(T* addr, T val)
-{
-    MOZ_CRASH();
-}
-
-template<typename T>
-inline T
-js::jit::AtomicOperations::fetchXorSeqCst(T* addr, T val)
-{
-    MOZ_CRASH();
-}
-
-template<typename T>
-inline T
-js::jit::AtomicOperations::exchangeSeqCst(T* addr, T val)
-{
-    MOZ_CRASH();
-}
-
-template<typename T>
-inline T
-js::jit::AtomicOperations::loadSafeWhenRacy(T* addr)
-{
-    MOZ_CRASH();
-}
-
-template<typename T>
-inline void
-js::jit::AtomicOperations::storeSafeWhenRacy(T* addr, T val)
-{
-    MOZ_CRASH();
-}
-
-inline void
-js::jit::AtomicOperations::memcpySafeWhenRacy(void* dest, const void* src, size_t nbytes)
-{
-    MOZ_ASSERT(!((char*)dest <= (char*)src && (char*)src < (char*)dest+nbytes));
-    MOZ_ASSERT(!((char*)src <= (char*)dest && (char*)dest < (char*)src+nbytes));
-    MOZ_CRASH();
-}
-
-inline void
-js::jit::AtomicOperations::memmoveSafeWhenRacy(void* dest, const void* src, size_t nbytes)
-{
-    MOZ_CRASH();
-}
-
-template<size_t nbytes>
-inline void
-js::jit::RegionLock::acquire(void* addr)
-{
-    (void)spinlock;             // Remove a lot of "unused" warnings.
-    MOZ_CRASH();
-}
-
-template<size_t nbytes>
-inline void
-js::jit::RegionLock::release(void* addr)
-{
-    MOZ_CRASH();
-}
-
-#endif // jit_none_AtomicOperations_none_h
--- a/js/src/jsapi-tests/testAddPropertyPropcache.cpp
+++ b/js/src/jsapi-tests/testAddPropertyPropcache.cpp
@@ -40,26 +40,24 @@ BEGIN_TEST(testAddPropertyHook)
     JS_InitClass(cx, global, obj, &AddPropertyClass, nullptr, 0, nullptr, nullptr, nullptr,
                  nullptr);
 
     obj = JS_NewArrayObject(cx, 0);
     CHECK(obj);
     JS::RootedValue arr(cx, JS::ObjectValue(*obj));
 
     CHECK(JS_DefineProperty(cx, global, "arr", arr,
-                            JSPROP_ENUMERATE,
-                            JS_STUBGETTER, JS_STUBSETTER));
+                            JSPROP_ENUMERATE));
 
     JS::RootedObject arrObj(cx, &arr.toObject());
     for (int i = 0; i < ExpectedCount; ++i) {
         obj = JS_NewObject(cx, &AddPropertyClass);
         CHECK(obj);
         CHECK(JS_DefineElement(cx, arrObj, i, obj,
-                               JSPROP_ENUMERATE,
-                               JS_STUBGETTER, JS_STUBSETTER));
+                               JSPROP_ENUMERATE));
     }
 
     // Now add a prop to each of the objects, but make sure to do
     // so at the same bytecode location so we can hit the propcache.
     EXEC("'use strict';                                     \n"
          "for (var i = 0; i < arr.length; ++i)              \n"
          "  arr[i].prop = 42;                               \n"
          );
--- a/js/src/jsapi-tests/testSetProperty.cpp
+++ b/js/src/jsapi-tests/testSetProperty.cpp
@@ -7,22 +7,21 @@
 
 #include "jsapi-tests/tests.h"
 
 BEGIN_TEST(testSetProperty_NativeGetterStubSetter)
 {
     JS::RootedObject obj(cx, JS_NewPlainObject(cx));
     CHECK(obj);
 
-    CHECK(JS_DefineProperty(cx, global, "globalProp", obj, JSPROP_ENUMERATE,
-                            JS_STUBGETTER, JS_STUBSETTER));
+    CHECK(JS_DefineProperty(cx, global, "globalProp", obj, JSPROP_ENUMERATE));
 
     CHECK(JS_DefineProperty(cx, obj, "prop", JS::UndefinedHandleValue,
                             JSPROP_SHARED | JSPROP_PROPOP_ACCESSORS,
-                            JS_PROPERTYOP_GETTER(NativeGet), JS_STUBSETTER));
+                            JS_PROPERTYOP_GETTER(NativeGet), nullptr));
 
     EXEC("'use strict';                                     \n"
          "var error, passed = false;                        \n"
          "try                                               \n"
          "{                                                 \n"
          "  this.globalProp.prop = 42;                      \n"
          "  throw new Error('setting property succeeded!'); \n"
          "}                                                 \n"
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -1707,29 +1707,16 @@ JS::GetFirstArgumentAsTypeHint(JSContext
     }
 
     JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr, JSMSG_NOT_EXPECTED_TYPE,
                                "Symbol.toPrimitive",
                                "\"string\", \"number\", or \"default\"", source);
     return false;
 }
 
-JS_PUBLIC_API(bool)
-JS_PropertyStub(JSContext* cx, HandleObject obj, HandleId id, MutableHandleValue vp)
-{
-    return true;
-}
-
-JS_PUBLIC_API(bool)
-JS_StrictPropertyStub(JSContext* cx, HandleObject obj, HandleId id, MutableHandleValue vp,
-                      ObjectOpResult& result)
-{
-    return result.succeed();
-}
-
 JS_PUBLIC_API(JSObject*)
 JS_InitClass(JSContext* cx, HandleObject obj, HandleObject parent_proto,
              const JSClass* clasp, JSNative constructor, unsigned nargs,
              const JSPropertySpec* ps, const JSFunctionSpec* fs,
              const JSPropertySpec* static_ps, const JSFunctionSpec* static_fs)
 {
     AssertHeapIsIdle();
     CHECK_REQUEST(cx);
@@ -2180,33 +2167,21 @@ DefinePropertyById(JSContext* cx, Handle
     // its way through the API layer so that we can enforce this internally.
     if (attrs & (JSPROP_GETTER | JSPROP_SETTER))
         attrs &= ~JSPROP_READONLY;
 
     // When we use DefineProperty, we need full scriptable Function objects rather
     // than JSNatives. However, we might be pulling this property descriptor off
     // of something with JSNative property descriptors. If we are, wrap them in
     // JS Function objects.
-    //
-    // But skip doing this if our accessors are the well-known stub
-    // accessors, since those are known to be JSGetterOps.  Assert
-    // some sanity about it, though.
-    MOZ_ASSERT_IF(getter == JS_PropertyStub,
-                  setter == JS_StrictPropertyStub || (attrs & JSPROP_PROPOP_ACCESSORS));
-    MOZ_ASSERT_IF(setter == JS_StrictPropertyStub,
-                  getter == JS_PropertyStub || (attrs & JSPROP_PROPOP_ACCESSORS));
-
-    // If !(attrs & JSPROP_PROPOP_ACCESSORS), then either getter/setter are both
+
+    // If !(attrs & JSPROP_PROPOP_ACCESSORS), then getter/setter are both
     // possibly-null JSNatives (or possibly-null JSFunction* if JSPROP_GETTER or
-    // JSPROP_SETTER is appropriately set), or both are the well-known property
-    // stubs.  The subsequent block must handle only the first of these cases,
-    // so carefully exclude the latter case.
-    if (!(attrs & JSPROP_PROPOP_ACCESSORS) &&
-        getter != JS_PropertyStub && setter != JS_StrictPropertyStub)
-    {
+    // JSPROP_SETTER is appropriately set).
+    if (!(attrs & JSPROP_PROPOP_ACCESSORS)) {
         if (getter && !(attrs & JSPROP_GETTER)) {
             RootedAtom atom(cx, IdToFunctionName(cx, id, FunctionPrefixKind::Get));
             if (!atom)
                 return false;
             JSFunction* getobj = NewNativeFunction(cx, (Native) getter, 0, atom);
             if (!getobj)
                 return false;
 
@@ -2241,20 +2216,16 @@ DefinePropertyById(JSContext* cx, Handle
     assertSameCompartment(cx, obj, id, value,
                           (attrs & JSPROP_GETTER)
                           ? JS_FUNC_TO_DATA_PTR(JSObject*, getter)
                           : nullptr,
                           (attrs & JSPROP_SETTER)
                           ? JS_FUNC_TO_DATA_PTR(JSObject*, setter)
                           : nullptr);
 
-    if (getter == JS_PropertyStub)
-        getter = nullptr;
-    if (setter == JS_StrictPropertyStub)
-        setter = nullptr;
     return DefineProperty(cx, obj, id, value, getter, setter, attrs);
 }
 
 /*
  * Wrapper functions to create wrappers with no corresponding JSJitInfo from API
  * function arguments.
  */
 static JSNativeWrapper
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -2099,24 +2099,16 @@ ToPrimitive(JSContext* cx, JS::HandleObj
  *
  * This can be useful in implementing a @@toPrimitive method.
  */
 extern JS_PUBLIC_API(bool)
 GetFirstArgumentAsTypeHint(JSContext* cx, CallArgs args, JSType *result);
 
 } /* namespace JS */
 
-extern JS_PUBLIC_API(bool)
-JS_PropertyStub(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
-                JS::MutableHandleValue vp);
-
-extern JS_PUBLIC_API(bool)
-JS_StrictPropertyStub(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
-                      JS::MutableHandleValue vp, JS::ObjectOpResult& result);
-
 template<typename T>
 struct JSConstScalarSpec {
     const char* name;
     T val;
 };
 
 typedef JSConstScalarSpec<double> JSConstDoubleSpec;
 typedef JSConstScalarSpec<int32_t> JSConstIntegerSpec;
@@ -2256,20 +2248,16 @@ inline int CheckIsSetterOp(JSSetterOp op
 #define JS_PROPERTYOP_GETTER(v) \
   (static_cast<void>(sizeof(JS::detail::CheckIsGetterOp(v))), \
    reinterpret_cast<JSNative>(v))
 
 #define JS_PROPERTYOP_SETTER(v) \
   (static_cast<void>(sizeof(JS::detail::CheckIsSetterOp(v))), \
    reinterpret_cast<JSNative>(v))
 
-#define JS_STUBGETTER JS_PROPERTYOP_GETTER(JS_PropertyStub)
-
-#define JS_STUBSETTER JS_PROPERTYOP_SETTER(JS_StrictPropertyStub)
-
 #define JS_PS_ACCESSOR_SPEC(name, getter, setter, flags, extraFlags) \
     { name, uint8_t(JS_CHECK_ACCESSOR_FLAGS(flags) | extraFlags), \
       { {  getter, setter  } } }
 #define JS_PS_VALUE_SPEC(name, value, flags) \
     { name, uint8_t(flags | JSPROP_INTERNAL_USE_BIT), \
       { { value, JSNATIVE_WRAPPER(nullptr) } } }
 
 #define SELFHOSTED_WRAPPER(name) \
@@ -2900,18 +2888,16 @@ class WrappedPtrOperations<JS::PropertyD
             MOZ_ASSERT(!has(SHADOWABLE));
             MOZ_ASSERT(value().isUndefined());
             MOZ_ASSERT_IF(!has(JSPROP_GETTER), !getter());
             MOZ_ASSERT_IF(!has(JSPROP_SETTER), !setter());
         } else {
             MOZ_ASSERT(!hasAll(JSPROP_IGNORE_READONLY | JSPROP_READONLY));
             MOZ_ASSERT_IF(has(JSPROP_IGNORE_VALUE), value().isUndefined());
         }
-        MOZ_ASSERT(getter() != JS_PropertyStub);
-        MOZ_ASSERT(setter() != JS_StrictPropertyStub);
 
         MOZ_ASSERT_IF(has(JSPROP_RESOLVING), !has(JSPROP_IGNORE_ENUMERATE));
         MOZ_ASSERT_IF(has(JSPROP_RESOLVING), !has(JSPROP_IGNORE_PERMANENT));
         MOZ_ASSERT_IF(has(JSPROP_RESOLVING), !has(JSPROP_IGNORE_READONLY));
         MOZ_ASSERT_IF(has(JSPROP_RESOLVING), !has(JSPROP_IGNORE_VALUE));
         MOZ_ASSERT_IF(has(JSPROP_RESOLVING), !has(JSPROP_REDEFINE_NONCONFIGURABLE));
 #endif
     }
@@ -2952,19 +2938,16 @@ class MutableWrappedPtrOperations<JS::Pr
         setAttributes(0);
         setGetter(nullptr);
         setSetter(nullptr);
         value().setUndefined();
     }
 
     void initFields(JS::HandleObject obj, JS::HandleValue v, unsigned attrs,
                     JSGetterOp getterOp, JSSetterOp setterOp) {
-        MOZ_ASSERT(getterOp != JS_PropertyStub);
-        MOZ_ASSERT(setterOp != JS_StrictPropertyStub);
-
         object().set(obj);
         value().set(v);
         setAttributes(attrs);
         setGetter(getterOp);
         setSetter(setterOp);
     }
 
     void assign(JS::PropertyDescriptor& other) {
@@ -3015,21 +2998,19 @@ class MutableWrappedPtrOperations<JS::Pr
     void setWritable(bool writable) {
         MOZ_ASSERT(!(desc().attrs & (JSPROP_GETTER | JSPROP_SETTER)));
         setAttributes((desc().attrs & ~(JSPROP_IGNORE_READONLY | JSPROP_READONLY)) |
                       (writable ? 0 : JSPROP_READONLY));
     }
     void setAttributes(unsigned attrs) { desc().attrs = attrs; }
 
     void setGetter(JSGetterOp op) {
-        MOZ_ASSERT(op != JS_PropertyStub);
         desc().getter = op;
     }
     void setSetter(JSSetterOp op) {
-        MOZ_ASSERT(op != JS_StrictPropertyStub);
         desc().setter = op;
     }
     void setGetterObject(JSObject* obj) {
         desc().getter = reinterpret_cast<JSGetterOp>(obj);
         desc().attrs &= ~(JSPROP_IGNORE_VALUE | JSPROP_IGNORE_READONLY | JSPROP_READONLY);
         desc().attrs |= JSPROP_GETTER | JSPROP_SHARED;
     }
     void setSetterObject(JSObject* obj) {
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -227,19 +227,17 @@ JS_TraceObjectGroupCycleCollectorChildre
 }
 
 static bool
 DefineHelpProperty(JSContext* cx, HandleObject obj, const char* prop, const char* value)
 {
     RootedAtom atom(cx, Atomize(cx, value, strlen(value)));
     if (!atom)
         return false;
-    return JS_DefineProperty(cx, obj, prop, atom,
-                             JSPROP_READONLY | JSPROP_PERMANENT,
-                             JS_STUBGETTER, JS_STUBSETTER);
+    return JS_DefineProperty(cx, obj, prop, atom, JSPROP_READONLY | JSPROP_PERMANENT);
 }
 
 JS_FRIEND_API(bool)
 JS_DefineFunctionsWithHelp(JSContext* cx, HandleObject obj, const JSFunctionSpecWithHelp* fs)
 {
     MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
 
     CHECK_REQUEST(cx);
--- a/js/src/jsmath.cpp
+++ b/js/src/jsmath.cpp
@@ -1435,21 +1435,18 @@ js::InitMathClass(JSContext* cx, HandleO
     Handle<GlobalObject*> global = obj.as<GlobalObject>();
     RootedObject proto(cx, GlobalObject::getOrCreateObjectPrototype(cx, global));
     if (!proto)
         return nullptr;
     RootedObject Math(cx, NewObjectWithGivenProto(cx, &MathClass, proto, SingletonObject));
     if (!Math)
         return nullptr;
 
-    if (!JS_DefineProperty(cx, obj, js_Math_str, Math, JSPROP_RESOLVING,
-                           JS_STUBGETTER, JS_STUBSETTER))
-    {
+    if (!JS_DefineProperty(cx, obj, js_Math_str, Math, JSPROP_RESOLVING))
         return nullptr;
-    }
     if (!JS_DefineFunctions(cx, Math, math_static_methods))
         return nullptr;
     if (!JS_DefineConstDoubles(cx, Math, math_constants))
         return nullptr;
     if (!DefineToStringTag(cx, Math, cx->names().Math))
         return nullptr;
 
     obj->as<GlobalObject>().setConstructor(JSProto_Math, ObjectValue(*Math));
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -2810,19 +2810,16 @@ js::DefineProperty(JSContext* cx, Handle
     return DefineProperty(cx, obj, id, value, getter, setter, attrs, result);
 }
 
 bool
 js::DefineElement(JSContext* cx, HandleObject obj, uint32_t index, HandleValue value,
                   JSGetterOp getter, JSSetterOp setter, unsigned attrs,
                   ObjectOpResult& result)
 {
-    MOZ_ASSERT(getter != JS_PropertyStub);
-    MOZ_ASSERT(setter != JS_StrictPropertyStub);
-
     RootedId id(cx);
     if (!IndexToId(cx, index, &id))
         return false;
     return DefineProperty(cx, obj, id, value, getter, setter, attrs, result);
 }
 
 bool
 js::DefineProperty(JSContext* cx, HandleObject obj, HandleId id, HandleValue value,
@@ -2846,19 +2843,16 @@ js::DefineProperty(JSContext* cx, Handle
     RootedId id(cx, NameToId(name));
     return DefineProperty(cx, obj, id, value, getter, setter, attrs);
 }
 
 bool
 js::DefineElement(JSContext* cx, HandleObject obj, uint32_t index, HandleValue value,
                   JSGetterOp getter, JSSetterOp setter, unsigned attrs)
 {
-    MOZ_ASSERT(getter != JS_PropertyStub);
-    MOZ_ASSERT(setter != JS_StrictPropertyStub);
-
     RootedId id(cx);
     if (!IndexToId(cx, index, &id))
         return false;
     return DefineProperty(cx, obj, id, value, getter, setter, attrs);
 }
 
 
 /*** SpiderMonkey nonstandard internal methods ***************************************************/
--- a/js/src/json.cpp
+++ b/js/src/json.cpp
@@ -987,21 +987,18 @@ js::InitJSONClass(JSContext* cx, HandleO
 
     RootedObject proto(cx, GlobalObject::getOrCreateObjectPrototype(cx, global));
     if (!proto)
         return nullptr;
     RootedObject JSON(cx, NewObjectWithGivenProto(cx, &JSONClass, proto, SingletonObject));
     if (!JSON)
         return nullptr;
 
-    if (!JS_DefineProperty(cx, global, js_JSON_str, JSON, JSPROP_RESOLVING,
-                           JS_STUBGETTER, JS_STUBSETTER))
-    {
+    if (!JS_DefineProperty(cx, global, js_JSON_str, JSON, JSPROP_RESOLVING))
         return nullptr;
-    }
 
     if (!JS_DefineFunctions(cx, JSON, json_static_methods))
         return nullptr;
 
     if (!DefineToStringTag(cx, JSON, cx->names().JSON))
         return nullptr;
 
     global->setConstructor(JSProto_JSON, ObjectValue(*JSON));
--- a/js/src/make-source-package.sh
+++ b/js/src/make-source-package.sh
@@ -2,16 +2,17 @@
 
 # Find out ASAP if some command breaks here, because we're copying a lot of
 # files we don't actually maintain ourselves, and requirements could easily be
 # broken.
 set -e
 
 : ${MKDIR:=mkdir}
 : ${TAR:=tar}
+: ${AUTOCONF:=autoconf-2.13}
 : ${SRCDIR:=$(cd $(dirname $0); pwd 2>/dev/null)}
 : ${MOZJS_NAME:=mozjs}
 # The place to gather files to be added to the tarball.
 : ${STAGING:=/tmp/mozjs-src-pkg}
 # The place to put the resulting tarball.
 : ${DIST:=/tmp}
 
 if [[ -f "$SRCDIR/../../config/milestone.txt" ]]; then
@@ -29,16 +30,17 @@ pkg="${version}.tar.bz2"
 pkgpath="${DIST}/${pkg}"
 taropts="-jcf"
 
 # need these environment vars:
 echo "Environment:"
 echo "    MAKE = $MAKE"
 echo "    MKDIR = $MKDIR"
 echo "    TAR = $TAR"
+echo "    AUTOCONF = $AUTOCONF"
 echo "    STAGING = $STAGING"
 echo "    DIST = $DIST"
 echo "    SRCDIR = $SRCDIR"
 echo "    MOZJS_NAME = $MOZJS_NAME"
 echo "    MOZJS_MAJOR_VERSION = $MOZJS_MAJOR_VERSION"
 echo "    MOZJS_MINOR_VERSION = $MOZJS_MINOR_VERSION"
 echo "    MOZJS_PATCH_VERSION = $MOZJS_PATCH_VERSION"
 echo "    MOZJS_ALPHA = $MOZJS_ALPHA"
@@ -93,16 +95,22 @@ case $cmd in
 
     # copy build and config directory.
     cp -pPR ${TOPSRCDIR}/build ${TOPSRCDIR}/config ${tgtpath}
 
     # copy cargo config
     ${MKDIR} -p ${tgtpath}/.cargo
     cp -pPR ${TOPSRCDIR}/.cargo/config.in ${tgtpath}/.cargo
 
+    # generate configure files to avoid build dependency on autoconf-2.13
+    cp -pPR ${TOPSRCDIR}/js/src/configure.in ${tgtpath}/js/src/configure
+    chmod a+x ${tgtpath}/js/src/configure
+    ${AUTOCONF} --localdir=${TOPSRCDIR}/js/src \
+        ${TOPSRCDIR}/js/src/old-configure.in >${tgtpath}/js/src/old-configure
+
     # put in js itself
     cp -pPR ${TOPSRCDIR}/mfbt ${tgtpath}
     cp -p ${SRCDIR}/../moz.configure ${tgtpath}/js
     cp -pPR ${SRCDIR}/../public ${tgtpath}/js
     cp -pPR ${SRCDIR}/../examples ${tgtpath}/js
     find ${SRCDIR} -mindepth 1 -maxdepth 1 -not -path ${STAGING} -a -not -name ${pkg} \
         -exec cp -pPR {} ${tgtpath}/js/src \;
 
--- a/js/src/perf/jsperf.cpp
+++ b/js/src/perf/jsperf.cpp
@@ -256,18 +256,17 @@ RegisterPerfMeasurement(JSContext* cx, H
         return 0;
 
     RootedObject ctor(cx);
     ctor = JS_GetConstructor(cx, prototype);
     if (!ctor)
         return 0;
 
     for (const pm_const* c = pm_consts; c->name; c++) {
-        if (!JS_DefineProperty(cx, ctor, c->name, c->value, PM_CATTRS,
-                               JS_STUBGETTER, JS_STUBSETTER))
+        if (!JS_DefineProperty(cx, ctor, c->name, c->value, PM_CATTRS))
             return 0;
     }
 
     if (!JS_FreezeObject(cx, prototype) ||
         !JS_FreezeObject(cx, ctor)) {
         return 0;
     }
 
--- a/js/src/proxy/BaseProxyHandler.cpp
+++ b/js/src/proxy/BaseProxyHandler.cpp
@@ -190,19 +190,17 @@ js::SetPropertyIgnoringNamedGetter(JSCon
         // Steps 5.a-b.
         if (!ownDesc.writable())
             return result.fail(JSMSG_READ_ONLY);
         if (!receiver.isObject())
             return result.fail(JSMSG_SET_NON_OBJECT_RECEIVER);
         RootedObject receiverObj(cx, &receiver.toObject());
 
         // Nonstandard SpiderMonkey special case: setter ops.
-        SetterOp setter = ownDesc.setter();
-        MOZ_ASSERT(setter != JS_StrictPropertyStub);
-        if (setter && setter != JS_StrictPropertyStub) {
+        if (SetterOp setter = ownDesc.setter()) {
             RootedValue valCopy(cx, v);
             return CallJSSetterOp(cx, setter, receiverObj, id, &valCopy, result);
         }
 
         // Steps 5.c-d.
         Rooted<PropertyDescriptor> existingDescriptor(cx);
         if (!GetOwnPropertyDescriptor(cx, receiverObj, id, &existingDescriptor))
             return false;
--- a/js/src/proxy/Proxy.cpp
+++ b/js/src/proxy/Proxy.cpp
@@ -826,14 +826,14 @@ js::InitProxyClass(JSContext* cx, Handle
     Handle<GlobalObject*> global = obj.as<GlobalObject>();
     RootedFunction ctor(cx);
     ctor = GlobalObject::createConstructor(cx, proxy, cx->names().Proxy, 2);
     if (!ctor)
         return nullptr;
 
     if (!JS_DefineFunctions(cx, ctor, static_methods))
         return nullptr;
-    if (!JS_DefineProperty(cx, obj, "Proxy", ctor, JSPROP_RESOLVING, JS_STUBGETTER, JS_STUBSETTER))
+    if (!JS_DefineProperty(cx, obj, "Proxy", ctor, JSPROP_RESOLVING))
         return nullptr;
 
     global->setConstructor(JSProto_Proxy, ObjectValue(*ctor));
     return ctor;
 }
--- a/js/src/vm/HelperThreads.cpp
+++ b/js/src/vm/HelperThreads.cpp
@@ -1228,17 +1228,18 @@ GlobalHelperThreadState::canStartWasmCom
 
     return true;
 }
 
 bool
 GlobalHelperThreadState::canStartWasmTier2Generator(const AutoLockHelperThreadState& lock)
 {
     return !wasmTier2GeneratorWorklist(lock).empty() &&
-           checkTaskThreadLimit<wasm::Tier2GeneratorTask*>(maxWasmTier2GeneratorThreads());
+           checkTaskThreadLimit<wasm::Tier2GeneratorTask*>(maxWasmTier2GeneratorThreads(),
+                                                           /*isMaster=*/true);
 }
 
 bool
 GlobalHelperThreadState::canStartPromiseHelperTask(const AutoLockHelperThreadState& lock)
 {
     return !promiseHelperTasks(lock).empty();
 }
 
--- a/js/src/vm/Shape-inl.h
+++ b/js/src/vm/Shape-inl.h
@@ -391,18 +391,16 @@ Shape::searchNoHashify(Shape* start, jsi
 }
 
 /* static */ MOZ_ALWAYS_INLINE Shape*
 NativeObject::addProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
                           GetterOp getter, SetterOp setter, uint32_t slot, unsigned attrs,
                           unsigned flags, bool allowDictionary)
 {
     MOZ_ASSERT(!JSID_IS_VOID(id));
-    MOZ_ASSERT(getter != JS_PropertyStub);
-    MOZ_ASSERT(setter != JS_StrictPropertyStub);
     MOZ_ASSERT(obj->uninlinedNonProxyIsExtensible());
     MOZ_ASSERT(!obj->containsPure(id));
 
     AutoKeepShapeTables keep(cx);
     ShapeTable::Entry* entry = nullptr;
     if (obj->inDictionaryMode()) {
         ShapeTable* table = obj->lastProperty()->ensureTableForDictionary(cx, keep);
         if (!table)
--- a/js/src/vm/Shape.cpp
+++ b/js/src/vm/Shape.cpp
@@ -452,18 +452,16 @@ GetBaseShapeForNewShape(JSContext* cx, H
 NativeObject::addPropertyInternal(JSContext* cx,
                                   HandleNativeObject obj, HandleId id,
                                   GetterOp getter, SetterOp setter,
                                   uint32_t slot, unsigned attrs,
                                   unsigned flags, ShapeTable::Entry* entry,
                                   bool allowDictionary, const AutoKeepShapeTables& keep)
 {
     MOZ_ASSERT_IF(!allowDictionary, !obj->inDictionaryMode());
-    MOZ_ASSERT(getter != JS_PropertyStub);
-    MOZ_ASSERT(setter != JS_StrictPropertyStub);
 
     AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
 
     /*
      * The code below deals with either converting obj to dictionary mode or
      * growing an object that's already in dictionary mode. Either way,
      * dictionray operations are safe if thread local.
      */
@@ -601,18 +599,16 @@ CheckCanChangeAttrs(JSContext* cx, JSObj
 }
 
 /* static */ Shape*
 NativeObject::putProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
                           GetterOp getter, SetterOp setter, uint32_t slot, unsigned attrs,
                           unsigned flags)
 {
     MOZ_ASSERT(!JSID_IS_VOID(id));
-    MOZ_ASSERT(getter != JS_PropertyStub);
-    MOZ_ASSERT(setter != JS_StrictPropertyStub);
 
 #ifdef DEBUG
     if (obj->is<ArrayObject>()) {
         ArrayObject* arr = &obj->as<ArrayObject>();
         uint32_t index;
         if (IdIsIndex(id, &index))
             MOZ_ASSERT(index < arr->length() || arr->lengthIsWritable());
     }
@@ -787,18 +783,16 @@ NativeObject::putProperty(JSContext* cx,
     return shape;
 }
 
 /* static */ Shape*
 NativeObject::changeProperty(JSContext* cx, HandleNativeObject obj, HandleShape shape,
                              unsigned attrs, GetterOp getter, SetterOp setter)
 {
     MOZ_ASSERT(obj->containsPure(shape));
-    MOZ_ASSERT(getter != JS_PropertyStub);
-    MOZ_ASSERT(setter != JS_StrictPropertyStub);
     MOZ_ASSERT_IF(attrs & (JSPROP_GETTER | JSPROP_SETTER), attrs & JSPROP_SHARED);
 
     /* Allow only shared (slotless) => unshared (slotful) transition. */
     MOZ_ASSERT(!((attrs ^ shape->attrs) & JSPROP_SHARED) ||
                !(attrs & JSPROP_SHARED));
 
     MarkTypePropertyNonData(cx, obj, shape->propid());
 
--- a/js/src/wasm/WasmBaselineCompile.cpp
+++ b/js/src/wasm/WasmBaselineCompile.cpp
@@ -651,16 +651,17 @@ class BaseCompiler
                  MacroAssembler* masm,
                  CompileMode mode);
 
     MOZ_MUST_USE bool init();
 
     FuncOffsets finish();
 
     MOZ_MUST_USE bool emitFunction();
+    void emitInitStackLocals();
 
     // Used by some of the ScratchRegister implementations.
     operator MacroAssembler&() const { return masm; }
 
 #ifdef DEBUG
     bool scratchRegisterTaken() const {
         return scratchRegisterTaken_;
     }
@@ -2255,36 +2256,18 @@ class BaseCompiler
                 if (i->argInRegister())
                     storeToFrameF32(i->fpu(), l.offs());
                 break;
               default:
                 MOZ_CRASH("Function argument type");
             }
         }
 
-        // Initialize the stack locals to zero.
-        //
-        // The following are all Bug 1316820:
-        //
-        // TODO / OPTIMIZE: on x64, at least, scratch will be a 64-bit
-        // register and we can move 64 bits at a time.
-        //
-        // TODO / OPTIMIZE: On SSE2 or better SIMD systems we may be
-        // able to store 128 bits at a time.  (I suppose on some
-        // systems we have 512-bit SIMD for that matter.)
-        //
-        // TODO / OPTIMIZE: if we have only one initializing store
-        // then it's better to store a zero literal, probably.
-
-        if (varLow_ < varHigh_) {
-            ScratchI32 scratch(*this);
-            masm.mov(ImmWord(0), scratch);
-            for (int32_t i = varLow_ ; i < varHigh_ ; i += 4)
-                storeToFrameI32(scratch, i + 4);
-        }
+        if (varLow_ < varHigh_)
+            emitInitStackLocals();
 
         if (debugEnabled_)
             insertBreakablePoint(CallSiteDesc::EnterFrame);
     }
 
     void saveResult() {
         MOZ_ASSERT(debugEnabled_);
         size_t debugFrameOffset = masm.framePushed() - DebugFrame::offsetOfFrame();
@@ -7492,16 +7475,117 @@ BaseCompiler::emitFunction()
         return false;
 
     if (!endFunction())
         return false;
 
     return true;
 }
 
+void
+BaseCompiler::emitInitStackLocals()
+{
+    MOZ_ASSERT(varLow_ < varHigh_, "there should be stack locals to initialize");
+
+    static const uint32_t wordSize = sizeof(void*);
+
+    // A local's localOffset always points above it in the frame, so that when
+    // translated to a stack address we end up with an address pointing to the
+    // base of the local.  Thus to go from a raw frame offset to an SP offset we
+    // first add K to the frame offset to obtain a localOffset for a slot of
+    // size K, and then map that to an SP offset.  Hence all the adjustments to
+    // `low` in the offset calculations below.
+
+    // On 64-bit systems we may have 32-bit alignment for the local area as it
+    // may be preceded by parameters and prologue/debug data.
+
+    uint32_t low = varLow_;
+    if (low % wordSize) {
+        masm.store32(Imm32(0), Address(StackPointer, localOffsetToSPOffset(low + 4)));
+        low += 4;
+    }
+    MOZ_ASSERT(low % wordSize == 0);
+
+    const uint32_t high = AlignBytes(varHigh_, wordSize);
+    MOZ_ASSERT(high <= uint32_t(localSize_), "localSize_ should be aligned at least that");
+
+    // An unrollLimit of 16 is chosen so that we only need an 8-bit signed
+    // immediate to represent the offset in the store instructions in the loop
+    // on x64.
+
+    const uint32_t unrollLimit = 16;
+    const uint32_t initWords = (high - low) / wordSize;
+    const uint32_t tailWords = initWords % unrollLimit;
+    const uint32_t loopHigh = high - (tailWords * wordSize);
+
+    // With only one word to initialize, just store an immediate zero.
+
+    if (initWords == 1) {
+        masm.storePtr(ImmWord(0), Address(StackPointer, localOffsetToSPOffset(low + wordSize)));
+        return;
+    }
+
+    // For other cases, it's best to have a zero in a register.
+    //
+    // One can do more here with SIMD registers (store 16 bytes at a time) or
+    // with instructions like STRD on ARM (store 8 bytes at a time), but that's
+    // for another day.
+
+    RegI32 zero = needI32();
+    masm.mov(ImmWord(0), zero);
+
+    // For the general case we want to have a loop body of unrollLimit stores
+    // and then a tail of less than unrollLimit stores.  When initWords is less
+    // than 2*unrollLimit the loop trip count is at most 1 and there is no
+    // benefit to having the pointer calculations and the compare-and-branch.
+    // So we completely unroll when we have initWords < 2 * unrollLimit.  (In
+    // this case we'll end up using 32-bit offsets on x64 for up to half of the
+    // stores, though.)
+
+    // Fully-unrolled case.
+
+    if (initWords < 2 * unrollLimit)  {
+        for (uint32_t i = low; i < high; i += wordSize)
+            masm.storePtr(zero, Address(StackPointer, localOffsetToSPOffset(i + wordSize)));
+        freeGPR(zero);
+        return;
+    }
+
+    // Unrolled loop with a tail. Stores will use negative offsets. That's OK
+    // for x86 and ARM, at least.
+
+    // Compute pointer to the highest-addressed slot on the frame.
+    RegI32 p = needI32();
+    masm.computeEffectiveAddress(Address(StackPointer, localOffsetToSPOffset(low + wordSize)),
+                                 p);
+
+    // Compute pointer to the lowest-addressed slot on the frame that will be
+    // initialized by the loop body.
+    RegI32 lim = needI32();
+    masm.computeEffectiveAddress(Address(StackPointer,
+                                         localOffsetToSPOffset(loopHigh + wordSize)),
+                                 lim);
+
+    // The loop body.  Eventually we'll have p == lim and exit the loop.
+    Label again;
+    masm.bind(&again);
+    for (uint32_t i = 0; i < unrollLimit; ++i)
+        masm.storePtr(zero, Address(p, -(wordSize * i)));
+    masm.subPtr(Imm32(unrollLimit * wordSize), p);
+    masm.branchPtr(Assembler::LessThan, lim, p, &again);
+
+    // The tail.
+    for (uint32_t i = 0; i < tailWords; ++i)
+        masm.storePtr(zero, Address(p, -(wordSize * i)));
+
+    freeGPR(p);
+    freeGPR(lim);
+    freeGPR(zero);
+}
+
 BaseCompiler::BaseCompiler(const ModuleEnvironment& env,
                            Decoder& decoder,
                            const FuncBytes& func,
                            const ValTypeVector& locals,
                            bool debugEnabled,
                            TempAllocator* alloc,
                            MacroAssembler* masm,
                            CompileMode mode)
--- a/js/xpconnect/src/ExportHelpers.cpp
+++ b/js/xpconnect/src/ExportHelpers.cpp
@@ -428,18 +428,17 @@ ExportFunction(JSContext* cx, HandleValu
             return false;
         }
 
         // We have the forwarder function in the target compartment. If
         // defineAs was set, we also need to define it as a property on
         // the target.
         if (!JSID_IS_VOID(options.defineAs)) {
             if (!JS_DefinePropertyById(cx, targetScope, id, rval,
-                                       JSPROP_ENUMERATE,
-                                       JS_STUBGETTER, JS_STUBSETTER)) {
+                                       JSPROP_ENUMERATE)) {
                 return false;
             }
         }
     }
 
     // Finally we have to re-wrap the exported function back to the caller compartment.
     if (!JS_WrapValue(cx, rval))
         return false;
@@ -475,18 +474,17 @@ CreateObjectIn(JSContext* cx, HandleValu
         JS_MarkCrossZoneId(cx, options.defineAs);
 
         obj = JS_NewPlainObject(cx);
         if (!obj)
             return false;
 
         if (define) {
             if (!JS_DefinePropertyById(cx, scope, options.defineAs, obj,
-                                       JSPROP_ENUMERATE,
-                                       JS_STUBGETTER, JS_STUBSETTER))
+                                       JSPROP_ENUMERATE))
                 return false;
         }
     }
 
     rval.setObject(*obj);
     if (!WrapperFactory::WaiveXrayAndWrap(cx, rval))
         return false;
 
--- a/mobile/android/app/mobile.js
+++ b/mobile/android/app/mobile.js
@@ -931,8 +931,12 @@ pref("media.openUnsupportedTypeWithExter
 pref("dom.keyboardevent.dispatch_during_composition", true);
 
 #if CPU_ARCH == aarch64
 pref("javascript.options.native_regexp", false);
 #endif
 
 // Ask for permission when enumerating WebRTC devices.
 pref("media.navigator.permission.device", true);
+
+#ifdef NIGHTLY_BUILD
+pref("media.videocontrols.lock-video-orientation", true);
+#endif
--- a/toolkit/components/places/History.cpp
+++ b/toolkit/components/places/History.cpp
@@ -1937,19 +1937,16 @@ History::History()
   }
 }
 
 History::~History()
 {
   UnregisterWeakMemoryReporter(this);
 
   gService = nullptr;
-
-  NS_ASSERTION(mObservers.Count() == 0,
-               "Not all Links were removed before we disappear!");
 }
 
 void
 History::InitMemoryReporter()
 {
   RegisterWeakMemoryReporter(this);
 }
 
@@ -2411,18 +2408,19 @@ History::SizeOfIncludingThis(mozilla::Ma
 History*
 History::GetService()
 {
   if (gService) {
     return gService;
   }
 
   nsCOMPtr<IHistory> service(do_GetService(NS_IHISTORY_CONTRACTID));
-  MOZ_ASSERT(service, "Cannot obtain IHistory service!");
-  NS_ASSERTION(gService, "Our constructor was not run?!");
+  if (service) {
+    NS_ASSERTION(gService, "Our constructor was not run?!");
+  }
 
   return gService;
 }
 
 /* static */
 History*
 History::GetSingleton()
 {
--- a/toolkit/components/places/moz.build
+++ b/toolkit/components/places/moz.build
@@ -27,16 +27,17 @@ if CONFIG['MOZ_PLACES']:
         'nsINavBookmarksService.idl',
         'nsITaggingService.idl',
         'nsPIPlacesDatabase.idl',
     ]
 
     EXPORTS.mozilla.places = [
         'Database.h',
         'History.h',
+        'Shutdown.h',
     ]
 
     UNIFIED_SOURCES += [
         'Database.cpp',
         'FaviconHelpers.cpp',
         'Helpers.cpp',
         'History.cpp',
         'nsAnnoProtocolHandler.cpp',
--- a/toolkit/content/widgets/videocontrols.xml
+++ b/toolkit/content/widgets/videocontrols.xml
@@ -1229,22 +1229,48 @@
         if (this.isVideoInFullScreen()) {
           this.fullscreenButton.setAttribute("fullscreened", "true");
         } else {
           this.fullscreenButton.removeAttribute("fullscreened");
         }
       },
 
       onFullscreenChange() {
+        this.updateOrientationState(this.isVideoInFullScreen());
         if (this.isVideoInFullScreen()) {
           Utils._hideControlsTimeout = setTimeout(this._hideControlsFn, this.HIDE_CONTROLS_TIMEOUT_MS);
         }
         this.setFullscreenButtonState();
       },
 
+      updateOrientationState(lock) {
+        if (!this.video.mozOrientationLockEnabled) {
+          return;
+        }
+        if (lock) {
+          if (this.video.mozIsOrientationLocked) {
+            return;
+          }
+          let dimenDiff = this.video.videoWidth - this.video.videoHeight;
+          if (dimenDiff > 0) {
+            this.video.mozIsOrientationLocked = window.screen.mozLockOrientation("landscape");
+          } else if (dimenDiff < 0) {
+            this.video.mozIsOrientationLocked = window.screen.mozLockOrientation("portrait");
+          } else {
+            this.video.mozIsOrientationLocked = window.screen.mozLockOrientation(window.screen.orientation);
+          }
+        } else {
+          if (!this.video.mozIsOrientationLocked) {
+            return;
+          }
+          window.screen.mozUnlockOrientation();
+          this.video.mozIsOrientationLocked = false;
+        }
+      },
+
       clickToPlayClickHandler(e) {
         if (e.button != 0) {
           return;
         }
         if (this.hasError() && !this.suppressError) {
           // Errors that can be dismissed should be placed here as we discover them.
           if (this.video.error.code != this.video.error.MEDIA_ERR_ABORTED) {
             return;
@@ -1831,16 +1857,17 @@
     };
 
     this.Utils.init(this);
     ]]>
   </constructor>
   <destructor>
     <![CDATA[
     this.Utils.terminateEventListeners();
+    this.Utils.updateOrientationState(false);
     // randomID used to be a <field>, which meant that the XBL machinery
     // undefined the property when the element was unbound. The code in
     // this file actually depends on this, so now that randomID is an
     // expando, we need to make sure to explicitly delete it.
     delete this.randomID;
     ]]>
   </destructor>