Merge autoland to mozilla-central a=merge
authorRazvan Maries <rmaries@mozilla.com>
Mon, 21 Jan 2019 19:48:03 +0200
changeset 454673 4977d02e11915a93c6c80a51f3e7bdc99d5e2f08
parent 454639 e43944736829dc575bb12821f0e28bf1bc02c285 (current diff)
parent 454672 d536f45f5b166c4b9562caf0c41991cb5df831cc (diff)
child 454684 44369796f148630ff496be99f77a5eeea41c7d23
push id35409
push userrmaries@mozilla.com
push dateMon, 21 Jan 2019 17:48:45 +0000
treeherdermozilla-central@4977d02e1191 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone66.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 autoland to mozilla-central a=merge
--- a/accessible/windows/msaa/AccessibleWrap.cpp
+++ b/accessible/windows/msaa/AccessibleWrap.cpp
@@ -735,27 +735,35 @@ STDMETHODIMP
 AccessibleWrap::get_accSelection(VARIANT __RPC_FAR* pvarChildren) {
   if (!pvarChildren) return E_INVALIDARG;
 
   VariantInit(pvarChildren);
   pvarChildren->vt = VT_EMPTY;
 
   if (IsDefunct()) return CO_E_OBJNOTCONNECTED;
 
-  if (IsSelect()) {
-    AutoTArray<Accessible*, 10> selectedItems;
-    SelectedItems(&selectedItems);
+  if (!IsSelect()) {
+    return S_OK;
+  }
 
-    // 1) Create and initialize the enumeration
+  AutoTArray<Accessible*, 10> selectedItems;
+  SelectedItems(&selectedItems);
+  uint32_t count = selectedItems.Length();
+  if (count == 1) {
+    pvarChildren->vt = VT_DISPATCH;
+    pvarChildren->pdispVal = NativeAccessible(selectedItems[0]);
+  } else if (count > 1) {
     RefPtr<AccessibleEnumerator> pEnum =
         new AccessibleEnumerator(selectedItems);
     pvarChildren->vt =
         VT_UNKNOWN;  // this must be VT_UNKNOWN for an IEnumVARIANT
     NS_ADDREF(pvarChildren->punkVal = pEnum);
   }
+  // If count == 0, vt is already VT_EMPTY, so there's nothing else to do.
+
   return S_OK;
 }
 
 STDMETHODIMP
 AccessibleWrap::get_accDefaultAction(
     /* [optional][in] */ VARIANT varChild,
     /* [retval][out] */ BSTR __RPC_FAR* pszDefaultAction) {
   if (!pszDefaultAction) return E_INVALIDARG;
--- a/browser/app/winlauncher/ErrorHandler.cpp
+++ b/browser/app/winlauncher/ErrorHandler.cpp
@@ -2,18 +2,18 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
 
 #include "ErrorHandler.h"
 
 #if defined(MOZ_LAUNCHER_PROCESS)
-#include "mozilla/LauncherRegistryInfo.h"
-#include "mozilla/Unused.h"
+#  include "mozilla/LauncherRegistryInfo.h"
+#  include "mozilla/Unused.h"
 #endif  // defined(MOZ_LAUNCHER_PROCESS)
 
 namespace mozilla {
 
 void HandleLauncherError(const LauncherError& aError) {
   // This is a placeholder error handler. We'll add telemetry and a fallback
   // error log in future revisions.
 
--- a/browser/base/content/browser-contentblocking.js
+++ b/browser/base/content/browser-contentblocking.js
@@ -786,17 +786,17 @@ var ContentBlocking = {
     }).catch(Cu.reportError);
   },
 
   showReportBreakageSubview() {
     // Save this URI to make sure that the user really only submits the location
     // they see in the report breakage dialog.
     this.reportURI = gBrowser.currentURI;
     let urlWithoutQuery = this.reportURI.asciiSpec.replace("?" + this.reportURI.query, "");
-    this.reportBreakageURL.textContent = urlWithoutQuery;
+    this.reportBreakageURL.value = urlWithoutQuery;
     this.identityPopupMultiView.showSubView("identity-popup-breakageReportView");
   },
 
   async showTrackersSubview() {
     await TrackingProtection.updateSubView();
     this.identityPopupMultiView.showSubView("identity-popup-trackersView");
   },
 
--- a/browser/base/content/test/trackingUI/browser_trackingUI_report_breakage.js
+++ b/browser/base/content/test/trackingUI/browser_trackingUI_report_breakage.js
@@ -153,17 +153,17 @@ add_task(async function testReportBreaka
     let reportBreakageButton = document.getElementById("identity-popup-content-blocking-report-breakage");
     ok(BrowserTestUtils.is_visible(reportBreakageButton), "report breakage button is visible");
     let reportBreakageView = document.getElementById("identity-popup-breakageReportView");
     let viewShown = BrowserTestUtils.waitForEvent(reportBreakageView, "ViewShown");
     reportBreakageButton.click();
     await viewShown;
 
     let submitButton = document.getElementById("identity-popup-breakageReportView-submit");
-    let reportURL = document.getElementById("identity-popup-breakageReportView-collection-url").textContent;
+    let reportURL = document.getElementById("identity-popup-breakageReportView-collection-url").value;
 
     is(reportURL, TRACKING_PAGE, "Shows the correct URL in the report UI.");
 
     // Make sure that sending the report closes the identity popup.
     let popuphidden = BrowserTestUtils.waitForEvent(gIdentityHandler._identityPopup, "popuphidden");
 
     // Check that we're receiving a good report.
     await new Promise(resolve => {
--- a/browser/components/controlcenter/content/panel.inc.xul
+++ b/browser/components/controlcenter/content/panel.inc.xul
@@ -275,21 +275,21 @@
                descriptionheightworkaround="true">
         <vbox id="identity-popup-breakageReportView-heading">
           <description>&contentBlocking.breakageReportView2.description;</description>
           <label id="identity-popup-breakageReportView-learn-more"
                  class="text-link">&contentBlocking.breakageReportView.learnMore;</label>
         </vbox>
         <vbox id="identity-popup-breakageReportView-body" class="panel-view-body-unscrollable">
           <vbox class="identity-popup-breakageReportView-collection-section">
-            <label class="identity-popup-breakageReportView-collection-label">&contentBlocking.breakageReportView.collection.url.label;</label>
-            <label id="identity-popup-breakageReportView-collection-url"/>
+            <label>&contentBlocking.breakageReportView.collection.url.label;</label>
+            <textbox readonly="true" id="identity-popup-breakageReportView-collection-url"/>
           </vbox>
           <vbox class="identity-popup-breakageReportView-collection-section">
-            <label class="identity-popup-breakageReportView-collection-label">&contentBlocking.breakageReportView.collection.comments.label;</label>
+            <label>&contentBlocking.breakageReportView.collection.comments.label;</label>
             <textbox multiline="true" id="identity-popup-breakageReportView-collection-comments"/>
           </vbox>
         </vbox>
         <vbox id="identity-popup-breakageReportView-footer"
               class="panel-footer">
           <button id="identity-popup-breakageReportView-cancel"
                   label="&contentBlocking.breakageReportView.cancel.label;"
                   oncommand="ContentBlocking.backToMainView();"/>
--- a/browser/themes/shared/controlcenter/panel.inc.css
+++ b/browser/themes/shared/controlcenter/panel.inc.css
@@ -340,24 +340,16 @@ description#identity-popup-content-verif
 }
 
 #identity-popup-breakageReportView-heading,
 #identity-popup-breakageReportView-body {
   padding: 16px;
   font-size: 110%;
 }
 
-.identity-popup-breakageReportView-collection-label {
-  color: graytext;
-}
-
-#identity-popup-breakageReportView-collection-url {
-  word-wrap: break-word;
-}
-
 .identity-popup-breakageReportView-collection-section {
   margin-bottom: 16px;
 }
 
 #identity-popup-breakageReportView-body {
   border-top: 1px solid var(--panel-separator-color);
 }
 
--- a/devtools/client/themes/webconsole.css
+++ b/devtools/client/themes/webconsole.css
@@ -65,16 +65,22 @@ a {
   padding-inline-start: 1px;
   padding-inline-end: 8px;
   border-inline-start: solid 3px transparent;
   font-size: var(--console-output-font-size);
   line-height: var(--console-output-line-height);
   position: relative;
 }
 
+@media (min-width: 1000px) {
+  .message {
+    padding-inline-end: 12px;
+  }
+}
+
 /*
  * By default, prevent any element in message to overflow.
  * This makes console reflows faster (See Bug 1487457).
  */
 .message * {
   overflow: hidden;
 }
 
@@ -255,49 +261,39 @@ a {
 .message-repeats[value="1"] {
   display: none;
 }
 
 .message-location {
   max-width: 40vw;
   flex-shrink: 0;
   color: var(--frame-link-source);
-  margin-inline-start: 5px;
-  margin-inline-end: 10px;
+  margin-inline-start: 1ch;
 }
 
-.stack-trace {
-  /* The markup contains extra whitespace to improve formatting of clipboard text.
-     Make sure this whitespace doesn't affect the HTML rendering */
-  white-space: normal;
+.message-location:empty {
+  display: none;
 }
 
-.message-location,
-.stack-trace .frame-link-source {
+.message-location .frame-link-source {
   /* Makes the file name truncated (and ellipsis shown) on the left side */
   direction: rtl;
+  display: block;
   white-space: nowrap;
   overflow: hidden;
   text-overflow: ellipsis;
   text-align: end;
 }
 
-.stack-trace .frame-link-source-inner,
 .message-location .frame-link-source-inner {
   /* Enforce LTR direction for the file name - fixes bug 1290056 */
   direction: ltr;
   unicode-bidi: embed;
 }
 
-.stack-trace .frame-link-function-display-name {
-  white-space: nowrap;
-  overflow: hidden;
-  text-overflow: ellipsis;
-}
-
 .message-flex-body {
   display: flex;
 }
 
 .message-body {
   white-space: pre-wrap;
   word-wrap: break-word;
 }
@@ -337,28 +333,28 @@ a {
   white-space: nowrap;
   overflow: hidden;
   text-overflow: ellipsis;
   cursor: default;
 }
 
 .message.network .status {
   flex: none;
-  margin-inline-start: 6px;
+  margin-inline-start: 1ch;
   cursor: default;
 }
 
 .message.network.mixed-content .url {
   color: var(--theme-highlight-red);
   cursor: default;
 }
 
 .message .learn-more-link {
   color: var(--theme-highlight-blue);
-  margin: 0 6px;
+  margin: 0 1ch;
 }
 
 .message.network .xhr {
   background-color: var(--theme-body-color-alt);
   color: var(--theme-body-background);
   border-radius: 3px;
   font-weight: bold;
   font-size: 10px;
@@ -692,17 +688,17 @@ a.learn-more-link.webconsole-learn-more-
 /* Prefix text that can be set by ConsoleAPI option */
 .webconsole-output-wrapper .console-message-prefix {
   color: var(--theme-comment);
 }
 
 /* Network Messages */
 
 .webconsole-output-wrapper .message.network .method {
-  margin-inline-end: 5px;
+  margin-inline-end: 1ch;
 }
 
 .webconsole-output-wrapper .message.network .xhr {
   background-color: var(--theme-comment);
   color: white;
   border-radius: 2px;
   font-weight: normal;
   line-height: inherit;
--- a/devtools/client/webconsole/test/mochitest/browser_jsterm_await_error.js
+++ b/devtools/client/webconsole/test/mochitest/browser_jsterm_await_error.js
@@ -84,9 +84,14 @@ async function performTests() {
   info("Check that we have as many errors as commands");
   const expectedErrorsNumber = expectedInputsNumber;
   is(hud.ui.outputNode.querySelectorAll(".message.error").length, expectedErrorsNumber,
     "There is the expected number of error messages");
 
   info("Check that there's no result message");
   is(hud.ui.outputNode.querySelectorAll(".message.result").length, 0,
     "There is no result messages");
+
+  info("Check that malformed await expressions displays a meaningful error");
+  res = await executeAndWaitForErrorMessage(
+    `await new Promise())`, `SyntaxError: unexpected token: ')'`);
+  ok(res.node, "awaiting for a malformed expression displays a meaningful error");
 }
--- a/devtools/client/webconsole/test/mochitest/browser_jsterm_middle_click_paste.js
+++ b/devtools/client/webconsole/test/mochitest/browser_jsterm_middle_click_paste.js
@@ -3,16 +3,18 @@
 
 // Test that pasting clipboard content into input with middle-click works.
 
 "use strict";
 
 const TEST_URI = `data:text/html;charset=utf-8,Web Console test paste on middle-click`;
 
 add_task(async function() {
+  await pushPref("devtools.selfxss.count", 5);
+
   // Enable pasting with middle-click.
   await pushPref("middlemouse.paste", true);
 
   // Run test with legacy JsTerm
   await pushPref("devtools.webconsole.jsterm.codeMirror", false);
   await performTests();
   // And then run it with the CodeMirror-powered one.
   await pushPref("devtools.webconsole.jsterm.codeMirror", true);
--- a/docshell/build/nsDocShellModule.cpp
+++ b/docshell/build/nsDocShellModule.cpp
@@ -184,18 +184,19 @@ const mozilla::Module::ContractIDEntry k
   { NS_EXTERNALURLHANDLERSERVICE_CONTRACTID, &kNS_EXTERNALURLHANDLERSERVICE_CID },
 #endif
   { NS_SHENTRY_CONTRACTID, &kNS_SHENTRY_CID },
   { NS_OSPERMISSIONREQUEST_CONTRACTID, &kNS_OSPERMISSIONREQUEST_CID, mozilla::Module::MAIN_PROCESS_ONLY },
   { nullptr }
     // clang-format on
 };
 
-static const mozilla::Module kDocShellModule = {mozilla::Module::kVersion,
-                                                kDocShellCIDs,
-                                                kDocShellContracts,
-                                                nullptr,
-                                                nullptr,
-                                                Initialize,
-                                                Shutdown,
-                                                mozilla::Module::ALLOW_IN_SOCKET_PROCESS};
+static const mozilla::Module kDocShellModule = {
+    mozilla::Module::kVersion,
+    kDocShellCIDs,
+    kDocShellContracts,
+    nullptr,
+    nullptr,
+    Initialize,
+    Shutdown,
+    mozilla::Module::ALLOW_IN_SOCKET_PROCESS};
 
 NSMODULE_DEFN(docshell_provider) = &kDocShellModule;
new file mode 100644
--- /dev/null
+++ b/dom/base/MaybeCrossOriginObject.cpp
@@ -0,0 +1,438 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/dom/MaybeCrossOriginObject.h"
+
+#include "mozilla/BasePrincipal.h"
+#include "mozilla/dom/BindingUtils.h"
+#include "mozilla/dom/DOMJSProxyHandler.h"
+#include "mozilla/dom/RemoteObjectProxy.h"
+#include "js/Proxy.h"
+#include "js/RootingAPI.h"
+#include "js/Wrapper.h"
+#include "jsfriendapi.h"
+#include "AccessCheck.h"
+#include "nsContentUtils.h"
+
+#ifdef DEBUG
+static bool IsLocation(JSObject* obj) {
+  return strcmp(js::GetObjectClass(obj)->name, "Location") == 0;
+}
+#endif  // DEBUG
+
+namespace mozilla {
+namespace dom {
+
+/* static */
+bool MaybeCrossOriginObjectMixins::IsPlatformObjectSameOrigin(
+    JSContext* cx, JS::Handle<JSObject*> obj) {
+  MOZ_ASSERT(!js::IsCrossCompartmentWrapper(obj));
+  // WindowProxy and Window must always be same-Realm, so we can do
+  // our IsPlatformObjectSameOrigin check against either one.  But verify that
+  // in case we have a WindowProxy the right things happen.
+  MOZ_ASSERT(js::GetNonCCWObjectRealm(obj) ==
+                 // "true" for second arg means to unwrap WindowProxy to
+                 // get at the Window.
+                 js::GetNonCCWObjectRealm(js::UncheckedUnwrap(obj, true)),
+             "WindowProxy not same-Realm as Window?");
+
+  BasePrincipal* subjectPrincipal =
+      BasePrincipal::Cast(nsContentUtils::SubjectPrincipal(cx));
+  nsIPrincipal* objectPrincipal = nsContentUtils::ObjectPrincipal(obj);
+
+  // The spec effectively has an EqualsConsideringDomain check here,
+  // because the spec has no concept of asymmetric security
+  // relationships.  But we shouldn't ever end up here in the
+  // asymmetric case anyway: That case should end up with Xrays, which
+  // don't call into this code.
+  //
+  // Let's assert that EqualsConsideringDomain and
+  // SubsumesConsideringDomain give the same results and use
+  // EqualsConsideringDomain for the check we actually do, since it's
+  // stricter and more closely matches the spec.
+  MOZ_ASSERT(
+      subjectPrincipal->FastEqualsConsideringDomain(objectPrincipal) ==
+          subjectPrincipal->FastSubsumesConsideringDomain(objectPrincipal),
+      "Why are we in an asymmetric case here?");
+  return subjectPrincipal->FastEqualsConsideringDomain(objectPrincipal);
+}
+
+bool MaybeCrossOriginObjectMixins::CrossOriginGetOwnPropertyHelper(
+    JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
+    JS::MutableHandle<JS::PropertyDescriptor> desc) const {
+  MOZ_ASSERT(!IsPlatformObjectSameOrigin(cx, obj) || IsRemoteObjectProxy(obj),
+             "Why did we get called?");
+  // First check for an IDL-defined cross-origin property with the given name.
+  // This corresponds to
+  // https://html.spec.whatwg.org/multipage/browsers.html#crossorigingetownpropertyhelper-(-o,-p-)
+  // step 2.
+  JS::Rooted<JSObject*> holder(cx);
+  if (!EnsureHolder(cx, obj, &holder)) {
+    return false;
+  }
+
+  if (!JS_GetOwnPropertyDescriptorById(cx, holder, id, desc)) {
+    return false;
+  }
+
+  if (desc.object()) {
+    desc.object().set(obj);
+  }
+
+  return true;
+}
+
+/* static */
+bool MaybeCrossOriginObjectMixins::CrossOriginPropertyFallback(
+    JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
+    JS::MutableHandle<JS::PropertyDescriptor> desc) {
+  MOZ_ASSERT(!desc.object(), "Why are we being called?");
+
+  // Step 1.
+  if (xpc::IsCrossOriginWhitelistedProp(cx, id)) {
+    // Spec says to return PropertyDescriptor {
+    //   [[Value]]: undefined, [[Writable]]: false, [[Enumerable]]: false,
+    //   [[Configurable]]: true
+    // }.
+    desc.setDataDescriptor(JS::UndefinedHandleValue, JSPROP_READONLY);
+    desc.object().set(obj);
+    return true;
+  }
+
+  // Step 2.
+  return ReportCrossOriginDenial(cx, id, NS_LITERAL_CSTRING("access"));
+}
+
+/* static */
+bool MaybeCrossOriginObjectMixins::CrossOriginGet(
+    JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<JS::Value> receiver,
+    JS::Handle<jsid> id, JS::MutableHandle<JS::Value> vp) {
+  // This is fairly similar to BaseProxyHandler::get, but there are some
+  // differences.  Most importantly, we want to throw if we have a descriptor
+  // with no getter, while BaseProxyHandler::get returns undefined.  The other
+  // big difference is that we don't have to worry about prototypes (ours is
+  // always null).
+
+  // We want to invoke [[GetOwnProperty]] on "obj", but _without_ entering its
+  // compartment, because for the proxies we have here [[GetOwnProperty]] will
+  // do security checks based on the current Realm.  Unfortunately,
+  // JS_GetPropertyDescriptorById asserts that compartments match.  Luckily, we
+  // know that "obj" is a proxy here, so we can directly call its
+  // getOwnPropertyDescriptor() hook.
+  //
+  // It looks like Proxy::getOwnPropertyDescriptor is not public, so just grab
+  // the handler and call its getOwnPropertyDescriptor hook directly.
+  MOZ_ASSERT(js::IsProxy(obj), "How did we get a bogus object here?");
+  MOZ_ASSERT(
+      js::IsWindowProxy(obj) || IsLocation(obj) || IsRemoteObjectProxy(obj),
+      "Unexpected proxy");
+  MOZ_ASSERT(!IsPlatformObjectSameOrigin(cx, obj) || IsRemoteObjectProxy(obj),
+             "Why did we get called?");
+  js::AssertSameCompartment(cx, receiver);
+
+  // Step 1.
+  JS::Rooted<JS::PropertyDescriptor> desc(cx);
+  if (!js::GetProxyHandler(obj)->getOwnPropertyDescriptor(cx, obj, id, &desc)) {
+    return false;
+  }
+  desc.assertCompleteIfFound();
+
+  // Step 2.
+  MOZ_ASSERT(desc.object(),
+             "Callees should throw in all cases when they are not finding a "
+             "property decriptor");
+
+  // Step 3.
+  if (desc.isDataDescriptor()) {
+    vp.set(desc.value());
+    return true;
+  }
+
+  // Step 4.
+  MOZ_ASSERT(desc.isAccessorDescriptor());
+
+  // Step 5.
+  JS::Rooted<JSObject*> getter(cx);
+  if (!desc.hasGetterObject() || !(getter = desc.getterObject())) {
+    // Step 6.
+    return ReportCrossOriginDenial(cx, id, NS_LITERAL_CSTRING("get"));
+  }
+
+  // Step 7.
+  return JS::Call(cx, receiver, getter, JS::HandleValueArray::empty(), vp);
+}
+
+/* static */
+bool MaybeCrossOriginObjectMixins::CrossOriginSet(
+    JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
+    JS::Handle<JS::Value> v, JS::Handle<JS::Value> receiver,
+    JS::ObjectOpResult& result) {
+  // We want to invoke [[GetOwnProperty]] on "obj", but _without_ entering its
+  // compartment, because for the proxies we have here [[GetOwnProperty]] will
+  // do security checks based on the current Realm.  Unfortunately,
+  // JS_GetPropertyDescriptorById asserts that compartments match.  Luckily, we
+  // know that "obj" is a proxy here, so we can directly call its
+  // getOwnPropertyDescriptor() hook.
+  //
+  // It looks like Proxy::getOwnPropertyDescriptor is not public, so just grab
+  // the handler and call its getOwnPropertyDescriptor hook directly.
+  MOZ_ASSERT(js::IsProxy(obj), "How did we get a bogus object here?");
+  MOZ_ASSERT(
+      js::IsWindowProxy(obj) || IsLocation(obj) || IsRemoteObjectProxy(obj),
+      "Unexpected proxy");
+  MOZ_ASSERT(!IsPlatformObjectSameOrigin(cx, obj) || IsRemoteObjectProxy(obj),
+             "Why did we get called?");
+  js::AssertSameCompartment(cx, receiver);
+  js::AssertSameCompartment(cx, v);
+
+  // Step 1.
+  JS::Rooted<JS::PropertyDescriptor> desc(cx);
+  if (!js::GetProxyHandler(obj)->getOwnPropertyDescriptor(cx, obj, id, &desc)) {
+    return false;
+  }
+  desc.assertCompleteIfFound();
+
+  // Step 2.
+  MOZ_ASSERT(desc.object(),
+             "Callees should throw in all cases when they are not finding a "
+             "property decriptor");
+
+  // Step 3.
+  JS::Rooted<JSObject*> setter(cx);
+  if (desc.hasSetterObject() && (setter = desc.setterObject())) {
+    JS::Rooted<JS::Value> ignored(cx);
+    // Step 3.1.
+    if (!JS::Call(cx, receiver, setter, JS::HandleValueArray(v), &ignored)) {
+      return false;
+    }
+
+    // Step 3.2.
+    return result.succeed();
+  }
+
+  // Step 4.
+  return ReportCrossOriginDenial(cx, id, NS_LITERAL_CSTRING("set"));
+}
+
+/* static */
+bool MaybeCrossOriginObjectMixins::EnsureHolder(
+    JSContext* cx, JS::Handle<JSObject*> obj, size_t slot,
+    JSPropertySpec* attributes, JSFunctionSpec* methods,
+    JS::MutableHandle<JSObject*> holder) {
+  MOZ_ASSERT(!IsPlatformObjectSameOrigin(cx, obj) || IsRemoteObjectProxy(obj),
+             "Why are we calling this at all in same-origin cases?");
+  // We store the holders in a weakmap stored in obj's slot.  Our object is
+  // always a proxy, so we can just go ahead and use GetProxyReservedSlot here.
+  JS::Rooted<JS::Value> weakMapVal(cx, js::GetProxyReservedSlot(obj, slot));
+  if (weakMapVal.isUndefined()) {
+    // Enter the Realm of "obj" when we allocate the WeakMap, since we are going
+    // to store it in a slot on "obj" and in general we may not be
+    // same-compartment with "obj" here.
+    JSAutoRealm ar(cx, obj);
+    JSObject* newMap = JS::NewWeakMapObject(cx);
+    if (!newMap) {
+      return false;
+    }
+    weakMapVal.setObject(*newMap);
+    js::SetProxyReservedSlot(obj, slot, weakMapVal);
+  }
+  MOZ_ASSERT(weakMapVal.isObject(),
+             "How did a non-object else end up in this slot?");
+
+  JS::Rooted<JSObject*> map(cx, &weakMapVal.toObject());
+  MOZ_ASSERT(JS::IsWeakMapObject(map),
+             "How did something else end up in this slot?");
+
+  // We need to be in "map"'s compartment to work with it.  Per spec, the key
+  // for this map is supposed to be the pair (current settings, relevant
+  // settings).  The current settings corresponds to the current Realm of cx.
+  // The relevant settings corresponds to the Realm of "obj", but since all of
+  // our objects are per-Realm singletons, we are basically using "obj" itself
+  // as part of the key.
+  //
+  // To represent the current settings, we use the current-Realm
+  // Object.prototype.  We can't use the current global, because we can't get a
+  // useful cross-compartment wrapper for it; such wrappers would always go
+  // through a WindowProxy and would not be guarantee to keep pointing to a
+  // single Realm when unwrapped.  We want to grab this key before we start
+  // changing Realms.
+  JS::Rooted<JSObject*> key(cx, JS::GetRealmObjectPrototype(cx));
+  if (!key) {
+    return false;
+  }
+
+  JS::Rooted<JS::Value> holderVal(cx);
+  {  // Scope for working with the map
+    JSAutoRealm ar(cx, map);
+    if (!MaybeWrapObject(cx, &key)) {
+      return false;
+    }
+
+    if (!JS::GetWeakMapEntry(cx, map, key, &holderVal)) {
+      return false;
+    }
+  }
+
+  if (holderVal.isObject()) {
+    // We want to do an unchecked unwrap, because the holder (and the current
+    // caller) may actually be more privileged than our map.
+    holder.set(js::UncheckedUnwrap(&holderVal.toObject()));
+
+    // holder might be a dead object proxy if things got nuked.
+    if (!JS_IsDeadWrapper(holder)) {
+      MOZ_ASSERT(js::GetContextRealm(cx) == js::GetNonCCWObjectRealm(holder),
+                 "How did we end up with a key/value mismatch?");
+      return true;
+    }
+  }
+
+  // We didn't find a usable holder.  Go ahead and allocate one.  At this point
+  // we have two options: we could allocate the holder in the current Realm and
+  // store a cross-compartment wrapper for it in the map as needed, or we could
+  // allocate the holder in the Realm of the map and have it hold
+  // cross-compartment references to all the methods it holds, since those
+  // methods need to be in our current Realm.  It seems better to allocate the
+  // holder in our current Realm.
+  holder.set(JS_NewObjectWithGivenProto(cx, nullptr, nullptr));
+  if (!holder || !JS_DefineProperties(cx, holder, attributes) ||
+      !JS_DefineFunctions(cx, holder, methods)) {
+    return false;
+  }
+
+  holderVal.setObject(*holder);
+  {  // Scope for working with the map
+    JSAutoRealm ar(cx, map);
+
+    // Key is already in the right Realm, but we need to wrap the value.
+    if (!MaybeWrapValue(cx, &holderVal)) {
+      return false;
+    }
+
+    if (!JS::SetWeakMapEntry(cx, map, key, holderVal)) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+/* static */
+bool MaybeCrossOriginObjectMixins::ReportCrossOriginDenial(
+    JSContext* aCx, JS::Handle<jsid> aId, const nsACString& aAccessType) {
+  xpc::AccessCheck::reportCrossOriginDenial(aCx, aId, aAccessType);
+  return false;
+}
+
+template <typename Base>
+bool MaybeCrossOriginObject<Base>::getPrototype(
+    JSContext* cx, JS::Handle<JSObject*> proxy,
+    JS::MutableHandle<JSObject*> protop) const {
+  if (!IsPlatformObjectSameOrigin(cx, proxy)) {
+    protop.set(nullptr);
+    return true;
+  }
+
+  {  // Scope for JSAutoRealm
+    JSAutoRealm ar(cx, proxy);
+    protop.set(getSameOriginPrototype(cx));
+    if (!protop) {
+      return false;
+    }
+  }
+
+  return MaybeWrapObject(cx, protop);
+}
+
+template <typename Base>
+bool MaybeCrossOriginObject<Base>::setPrototype(
+    JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<JSObject*> proto,
+    JS::ObjectOpResult& result) const {
+  // Inlined version of
+  // https://tc39.github.io/ecma262/#sec-set-immutable-prototype
+  js::AssertSameCompartment(cx, proto);
+
+  // We have to be careful how we get the prototype.  In particular, we do _NOT_
+  // want to enter the Realm of "proxy" to do that, in case we're not
+  // same-origin with it here.
+  JS::Rooted<JSObject*> wrappedProxy(cx, proxy);
+  if (!MaybeWrapObject(cx, &wrappedProxy)) {
+    return false;
+  }
+
+  JS::Rooted<JSObject*> currentProto(cx);
+  if (!js::GetObjectProto(cx, wrappedProxy, &currentProto)) {
+    return false;
+  }
+
+  if (currentProto != proto) {
+    return result.failCantSetProto();
+  }
+
+  return result.succeed();
+}
+
+template <typename Base>
+bool MaybeCrossOriginObject<Base>::getPrototypeIfOrdinary(
+    JSContext* cx, JS::Handle<JSObject*> proxy, bool* isOrdinary,
+    JS::MutableHandle<JSObject*> protop) const {
+  // We have a custom [[GetPrototypeOf]]
+  *isOrdinary = false;
+  return true;
+}
+
+template <typename Base>
+bool MaybeCrossOriginObject<Base>::isExtensible(JSContext* cx,
+                                                JS::Handle<JSObject*> proxy,
+                                                bool* extensible) const {
+  // We never allow [[PreventExtensions]] to succeed.
+  *extensible = true;
+  return true;
+}
+
+template <typename Base>
+bool MaybeCrossOriginObject<Base>::preventExtensions(
+    JSContext* cx, JS::Handle<JSObject*> proxy,
+    JS::ObjectOpResult& result) const {
+  return result.failCantPreventExtensions();
+}
+
+template <typename Base>
+bool MaybeCrossOriginObject<Base>::defineProperty(
+    JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
+    JS::Handle<JS::PropertyDescriptor> desc, JS::ObjectOpResult& result) const {
+  if (!IsPlatformObjectSameOrigin(cx, proxy)) {
+    return ReportCrossOriginDenial(cx, id, NS_LITERAL_CSTRING("define"));
+  }
+
+  // Enter the Realm of proxy and do the remaining work in there.
+  JSAutoRealm ar(cx, proxy);
+  JS::Rooted<JS::PropertyDescriptor> descCopy(cx, desc);
+  if (!JS_WrapPropertyDescriptor(cx, &descCopy)) {
+    return false;
+  }
+
+  JS_MarkCrossZoneId(cx, id);
+
+  return definePropertySameOrigin(cx, proxy, id, descCopy, result);
+}
+
+template <typename Base>
+JSObject* MaybeCrossOriginObject<Base>::enumerate(
+    JSContext* cx, JS::Handle<JSObject*> proxy) const {
+  // We want to avoid any possible magic here and just do the BaseProxyHandler
+  // thing of using our property keys to enumerate.
+  //
+  // Note that we do not need to enter the Realm of "proxy" here, nor do we want
+  // to: if this is a cross-origin access we want to handle it appropriately.
+  return js::BaseProxyHandler::enumerate(cx, proxy);
+}
+
+// Force instantiations of the out-of-line template methods we need.
+template class MaybeCrossOriginObject<js::Wrapper>;
+template class MaybeCrossOriginObject<DOMProxyHandler>;
+
+}  // namespace dom
+}  // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/base/MaybeCrossOriginObject.h
@@ -0,0 +1,332 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_MaybeCrossOriginObject_h
+#define mozilla_dom_MaybeCrossOriginObject_h
+
+/**
+ * Shared infrastructure for WindowProxy and Location objects.  These
+ * are the objects that can be accessed cross-origin in the HTML
+ * specification.
+ *
+ * This class can be inherited from by the relevant proxy handlers to
+ * help implement spec algorithms.
+ *
+ * The algorithms this class implements come from
+ * <https://html.spec.whatwg.org/multipage/browsers.html#shared-abstract-operations>,
+ * <https://html.spec.whatwg.org/multipage/window-object.html#the-windowproxy-exotic-object>,
+ * and
+ * <https://html.spec.whatwg.org/multipage/history.html#the-location-interface>.
+ *
+ * The class is templated on its base so we can directly implement the things
+ * that should have identical implementations for WindowProxy and Location.  The
+ * templating is needed because WindowProxy needs to be a wrapper and Location
+ * shouldn't be one.
+ */
+
+#include "js/Class.h"
+#include "js/TypeDecls.h"
+#include "nsStringFwd.h"
+
+namespace mozilla {
+namespace dom {
+
+// Methods that MaybeCrossOriginObject wants that do not depend on the "Base"
+// template parameter.  We can avoid having multiple instantiations of them by
+// pulling them out into this helper class.
+class MaybeCrossOriginObjectMixins {
+ protected:
+  /**
+   * Implementation of
+   * <https://html.spec.whatwg.org/multipage/browsers.html#isplatformobjectsameorigin-(-o-)>.
+   * "cx" and "obj" may or may not be same-compartment and even when
+   * same-compartment may not be same-Realm.  "obj" can be a WindowProxy, a
+   * Window, or a Location.
+   */
+  static bool IsPlatformObjectSameOrigin(JSContext* cx,
+                                         JS::Handle<JSObject*> obj);
+
+  /**
+   * Implementation of
+   * <https://html.spec.whatwg.org/multipage/browsers.html#crossorigingetownpropertyhelper-(-o,-p-)>.
+   *
+   * "cx" and "obj" are expected to be different-Realm here, and may be
+   * different-compartment.  "obj" can be a "WindowProxy" or a "Location" or a
+   * cross-process proxy for one of those.
+   */
+  bool CrossOriginGetOwnPropertyHelper(
+      JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
+      JS::MutableHandle<JS::PropertyDescriptor> desc) const;
+
+  /**
+   * Implementation of
+   * <https://html.spec.whatwg.org/multipage/browsers.html#crossoriginpropertyfallback-(-p-)>.
+   *
+   * This should be called at the end of getOwnPropertyDescriptor
+   * methods in the cross-origin case.
+   *
+   * "cx" and "obj" are expected to be different-Realm here, and may
+   * be different-compartment.  "obj" can be a "WindowProxy" or a
+   * "Location" or a cross-process proxy for one of those.
+   */
+  static bool CrossOriginPropertyFallback(
+      JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
+      JS::MutableHandle<JS::PropertyDescriptor> desc);
+
+  /**
+   * Implementation of
+   * <https://html.spec.whatwg.org/multipage/browsers.html#crossoriginget-(-o,-p,-receiver-)>.
+   *
+   * "cx" and "obj" are expected to be different-Realm here and may be
+   * different-compartment.  "obj" can be a "WindowProxy" or a
+   * "Location" or a cross-process proxy for one of those.
+   *
+   * "receiver" will be in the compartment of "cx".  The return value will
+   * be in the compartment of "cx".
+   */
+  static bool CrossOriginGet(JSContext* cx, JS::Handle<JSObject*> obj,
+                             JS::Handle<JS::Value> receiver,
+                             JS::Handle<jsid> id,
+                             JS::MutableHandle<JS::Value> vp);
+
+  /**
+   * Implementation of
+   * <https://html.spec.whatwg.org/multipage/browsers.html#crossoriginset-(-o,-p,-v,-receiver-)>.
+   *
+   * "cx" and "obj" are expected to be different-Realm here and may be
+   * different-compartment.  "obj" can be a "WindowProxy" or a
+   * "Location" or a cross-process proxy for one of those.
+   *
+   * "receiver" and "v" will be in the compartment of "cx".
+   */
+  static bool CrossOriginSet(JSContext* cx, JS::Handle<JSObject*> obj,
+                             JS::Handle<jsid> id, JS::Handle<JS::Value> v,
+                             JS::Handle<JS::Value> receiver,
+                             JS::ObjectOpResult& result);
+
+  /**
+   * Utility method to ensure a holder for cross-origin properties for the
+   * current global of the JSContext.
+   *
+   * When this is called, "cx" and "obj" are _always_ different-Realm, because
+   * this is only used in cross-origin situations.  The "holder" return value is
+   * always in the Realm of "cx".
+   *
+   * "obj" is the object which has space to store the collection of holders in
+   * the given slot.
+   *
+   * "attributes" and "methods" are the cross-origin attributes and methods we
+   * care about, which should get defined on holders.
+   */
+  static bool EnsureHolder(JSContext* cx, JS::Handle<JSObject*> obj,
+                           size_t slot, JSPropertySpec* attributes,
+                           JSFunctionSpec* methods,
+                           JS::MutableHandle<JSObject*> holder);
+
+  /**
+   * Ensures we have a holder object for the current Realm.  When this is
+   * called, "obj" is guaranteed to not be same-Realm with "cx", because this
+   * is only used for cross-origin cases.
+   *
+   * Subclasses are expected to implement this by calling our static
+   * EnsureHolder with the appropriate arguments.
+   */
+  virtual bool EnsureHolder(JSContext* cx, JS::Handle<JSObject*> proxy,
+                            JS::MutableHandle<JSObject*> holder) const = 0;
+
+  /**
+   * Report a cross-origin denial for a property named by aId.  Always
+   * returns false, so it can be used as "return
+   * ReportCrossOriginDenial(...);".
+   */
+  static bool ReportCrossOriginDenial(JSContext* aCx, JS::Handle<jsid> aId,
+                                      const nsACString& aAccessType);
+};
+
+// A proxy handler for objects that may be cross-origin objects.  Whether they
+// actually _are_ cross-origin objects can change dynamically if document.domain
+// is set.
+template <typename Base>
+class MaybeCrossOriginObject : public Base,
+                               public MaybeCrossOriginObjectMixins {
+ protected:
+  template <typename... Args>
+  constexpr MaybeCrossOriginObject(Args&&... aArgs)
+      : Base(std::forward<Args>(aArgs)...) {}
+
+  /**
+   * Implementation of [[GetPrototypeOf]] as defined in
+   * <https://html.spec.whatwg.org/multipage/window-object.html#windowproxy-getprototypeof>
+   * and
+   * <https://html.spec.whatwg.org/multipage/history.html#location-getprototypeof>.
+   *
+   * Our prototype-storage model looks quite different from the spec's, so we
+   * need to implement some hooks that don't directly map to the spec.
+   *
+   * "proxy" is the WindowProxy or Location involved.  It may or may not be
+   * same-compartment with cx.
+   *
+   * "protop" is the prototype value (possibly null).  It is guaranteed to be
+   * same-compartment with cx after this function returns successfully.
+   */
+  bool getPrototype(JSContext* cx, JS::Handle<JSObject*> proxy,
+                    JS::MutableHandle<JSObject*> protop) const final;
+
+  /**
+   * Hook for doing the OrdinaryGetPrototypeOf bits that [[GetPrototypeOf]] does
+   * in the spec.  Location and WindowProxy store that information somewhat
+   * differently.
+   *
+   * The prototype should come from the Realm of "cx".
+   */
+  virtual JSObject* getSameOriginPrototype(JSContext* cx) const = 0;
+
+  /**
+   * Implementation of [[SetPrototypeOf]] as defined in
+   * <https://html.spec.whatwg.org/multipage/window-object.html#windowproxy-setprototypeof>
+   * and
+   * <https://html.spec.whatwg.org/multipage/history.html#location-setprototypeof>.
+   *
+   * "proxy" is the WindowProxy or Location object involved.  It may or may not
+   * be same-compartment with "cx".
+   *
+   * "proto" is the new prototype object (possibly null).  It must be
+   * same-compartment with "cx".
+   */
+  bool setPrototype(JSContext* cx, JS::Handle<JSObject*> proxy,
+                    JS::Handle<JSObject*> proto,
+                    JS::ObjectOpResult& result) const final;
+
+  /**
+   * Our non-standard getPrototypeIfOrdinary hook.  We don't need to implement
+   * setImmutablePrototype, because the default behavior of not allowing it is
+   * fine for us.
+   */
+  bool getPrototypeIfOrdinary(JSContext* cx, JS::Handle<JSObject*> proxy,
+                              bool* isOrdinary,
+                              JS::MutableHandle<JSObject*> protop) const final;
+
+  /**
+   * Implementation of [[IsExtensible]] as defined in
+   * <https://html.spec.whatwg.org/multipage/window-object.html#windowproxy-isextensible>
+   * and
+   * <https://html.spec.whatwg.org/multipage/history.html#location-isextensible>.
+   */
+  bool isExtensible(JSContext* cx, JS::Handle<JSObject*> proxy,
+                    bool* extensible) const final;
+
+  /**
+   * Implementation of [[PreventExtensions]] as defined in
+   * <https://html.spec.whatwg.org/multipage/window-object.html#windowproxy-preventextensions>
+   * and
+   * <https://html.spec.whatwg.org/multipage/history.html#location-preventextensions>.
+   */
+  bool preventExtensions(JSContext* cx, JS::Handle<JSObject*> proxy,
+                         JS::ObjectOpResult& result) const final;
+
+  /**
+   * Implementation of [[GetOwnProperty]] is completely delegated to subclasses.
+   *
+   * "proxy" is the WindowProxy or Location object involved.  It may or may not
+   * be same-compartment with cx.
+   */
+  bool getOwnPropertyDescriptor(
+      JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
+      JS::MutableHandle<JS::PropertyDescriptor> desc) const override = 0;
+
+  /**
+   * Implementation of [[DefineOwnProperty]] as defined in
+   * <https://html.spec.whatwg.org/multipage/window-object.html#windowproxy-defineownproperty>
+   * and
+   * <https://html.spec.whatwg.org/multipage/history.html#location-defineownproperty>.
+   * "proxy" is the WindowProxy or Location object involved.  It may or may not
+   * be same-compartment with cx.
+   *
+   */
+  bool defineProperty(JSContext* cx, JS::Handle<JSObject*> proxy,
+                      JS::Handle<jsid> id,
+                      JS::Handle<JS::PropertyDescriptor> desc,
+                      JS::ObjectOpResult& result) const final;
+
+  /**
+   * Some of our base classes define _another_ virtual defineProperty, and we
+   * get overloaded-virtual warnings as a result due to us hiding it, if we
+   * don't pull it in here.
+   */
+  using Base::defineProperty;
+
+  /**
+   * Hook for handling the same-origin case in defineProperty.
+   *
+   * "proxy" is the WindowProxy or Location object involved.  It will be
+   * same-compartment with cx.
+   *
+   * "desc" is a the descriptor being defined.  It will be same-compartment with
+   * cx.
+   */
+  virtual bool definePropertySameOrigin(JSContext* cx,
+                                        JS::Handle<JSObject*> proxy,
+                                        JS::Handle<jsid> id,
+                                        JS::Handle<JS::PropertyDescriptor> desc,
+                                        JS::ObjectOpResult& result) const = 0;
+
+  /**
+   * Implementation of [[Get]] is completely delegated to subclasses.
+   *
+   * "proxy" is the WindowProxy or Location object involved.  It may or may not
+   * be same-compartment with "cx".
+   *
+   * "receiver" is the receiver ("this") for the get.  It will be
+   * same-compartment with "cx"
+   *
+   * "vp" is the return value.  It will be same-compartment with "cx".
+   */
+  bool get(JSContext* cx, JS::Handle<JSObject*> proxy,
+           JS::Handle<JS::Value> receiver, JS::Handle<jsid> id,
+           JS::MutableHandle<JS::Value> vp) const override = 0;
+
+  /**
+   * Implementation of [[Set]] is completely delegated to subclasses.
+   *
+   * "proxy" is the WindowProxy or Location object involved.  It may or may not
+   * be same-compartment with "cx".
+   *
+   * "v" is the value being set.  It will be same-compartment with "cx".
+   *
+   * "receiver" is the receiver ("this") for the set.  It will be
+   * same-compartment with "cx".
+   */
+  bool set(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
+           JS::Handle<JS::Value> v, JS::Handle<JS::Value> receiver,
+           JS::ObjectOpResult& result) const override = 0;
+
+  /**
+   * Implementation of [[Delete]] is completely delegated to subclasses.
+   *
+   * "proxy" is the WindowProxy or Location object involved.  It may or may not
+   * be same-compartment with "cx".
+   */
+  bool delete_(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
+               JS::ObjectOpResult& result) const override = 0;
+
+  /**
+   * Spidermonkey-internal hook for enumerating objects.
+   */
+  JSObject* enumerate(JSContext* cx, JS::Handle<JSObject*> proxy) const final;
+
+  /**
+   * Spidermonkey-internal hook used by Object.prototype.toString.  Subclasses
+   * need to implement this, because we don't know what className they want.
+   * Except in the cross-origin case, when we could maybe handle it...
+   */
+  const char* className(JSContext* cx,
+                        JS::Handle<JSObject*> proxy) const override = 0;
+};
+
+}  // namespace dom
+}  // namespace mozilla
+
+#endif /* mozilla_dom_MaybeCrossOriginObject_h */
--- a/dom/base/RemoteOuterWindowProxy.cpp
+++ b/dom/base/RemoteOuterWindowProxy.cpp
@@ -116,18 +116,17 @@ bool RemoteOuterWindowProxy::getOwnPrope
     const BrowsingContext::Children& children = bc->GetChildren();
     if (index < children.Length()) {
       return WrapResult(aCx, aProxy, children[index],
                         JSPROP_READONLY | JSPROP_ENUMERATE, aDesc);
     }
     return ReportCrossOriginDenial(aCx, aId, NS_LITERAL_CSTRING("access"));
   }
 
-  bool ok = RemoteObjectProxy::getOwnPropertyDescriptorInternal(aCx, aProxy,
-                                                                aId, aDesc);
+  bool ok = CrossOriginGetOwnPropertyHelper(aCx, aProxy, aId, aDesc);
   if (!ok || aDesc.object()) {
     return ok;
   }
 
   if (JSID_IS_STRING(aId)) {
     nsAutoJSString str;
     if (!str.init(aCx, JSID_TO_STRING(aId))) {
       return false;
@@ -135,17 +134,17 @@ bool RemoteOuterWindowProxy::getOwnPrope
 
     for (BrowsingContext* child : bc->GetChildren()) {
       if (child->NameEquals(str)) {
         return WrapResult(aCx, aProxy, child, JSPROP_READONLY, aDesc);
       }
     }
   }
 
-  return getOwnPropertyDescriptorTail(aCx, aProxy, aId, aDesc);
+  return CrossOriginPropertyFallback(aCx, aProxy, aId, aDesc);
 }
 
 bool AppendIndexedPropertyNames(JSContext* aCx, BrowsingContext* aContext,
                                 JS::AutoIdVector& aIndexedProps) {
   int32_t length = aContext->GetChildren().Length();
   if (!aIndexedProps.reserve(aIndexedProps.length() + length)) {
     return false;
   }
--- a/dom/base/moz.build
+++ b/dom/base/moz.build
@@ -188,16 +188,17 @@ EXPORTS.mozilla.dom += [
     'IdleDeadline.h',
     'IdleRequest.h',
     'IDTracker.h',
     'ImageEncoder.h',
     'ImageTracker.h',
     'IntlUtils.h',
     'Link.h',
     'Location.h',
+    'MaybeCrossOriginObject.h',
     'MessageBroadcaster.h',
     'MessageListenerManager.h',
     'MessageManagerGlobal.h',
     'MessageSender.h',
     'MimeType.h',
     'MozQueryInterface.h',
     'NameSpaceConstants.h',
     'Navigator.h',
@@ -293,16 +294,17 @@ UNIFIED_SOURCES += [
     'IdleRequest.cpp',
     'IDTracker.cpp',
     'ImageEncoder.cpp',
     'ImageTracker.cpp',
     'InProcessTabChildMessageManager.cpp',
     'IntlUtils.cpp',
     'Link.cpp',
     'Location.cpp',
+    'MaybeCrossOriginObject.cpp',
     'MessageBroadcaster.cpp',
     'MessageListenerManager.cpp',
     'MessageManagerGlobal.cpp',
     'MessageSender.cpp',
     'MimeType.cpp',
     'MozQueryInterface.cpp',
     'Navigator.cpp',
     'NodeInfo.cpp',
--- a/dom/base/nsGlobalWindowOuter.cpp
+++ b/dom/base/nsGlobalWindowOuter.cpp
@@ -25,16 +25,17 @@
 #include "nsIWebProgressListener.h"
 #include "mozilla/AntiTrackingCommon.h"
 #include "mozilla/dom/ContentFrameMessageManager.h"
 #include "mozilla/dom/EventTarget.h"
 #include "mozilla/dom/LocalStorage.h"
 #include "mozilla/dom/LSObject.h"
 #include "mozilla/dom/Storage.h"
 #include "mozilla/dom/IdleRequest.h"
+#include "mozilla/dom/MaybeCrossOriginObject.h"
 #include "mozilla/dom/Performance.h"
 #include "mozilla/dom/StorageEvent.h"
 #include "mozilla/dom/StorageEventBinding.h"
 #include "mozilla/dom/StorageNotifierService.h"
 #include "mozilla/dom/StorageUtils.h"
 #include "mozilla/dom/Timeout.h"
 #include "mozilla/dom/TimeoutHandler.h"
 #include "mozilla/dom/TimeoutManager.h"
@@ -335,108 +336,221 @@ nsPIDOMWindowOuter* nsPIDOMWindowOuter::
 
   return outer;
 }
 
 //*****************************************************************************
 // nsOuterWindowProxy: Outer Window Proxy
 //*****************************************************************************
 
-class nsOuterWindowProxy : public js::Wrapper {
+// Give OuterWindowProxyClass 2 reserved slots, like the other wrappers, so
+// JSObject::swap can swap it with CrossCompartmentWrappers without requiring
+// malloc.
+//
+// We store the nsGlobalWindowOuter* in our first slot.
+//
+// We store our holder weakmap in the second slot.
+const js::Class OuterWindowProxyClass = PROXY_CLASS_DEF(
+    "Proxy", JSCLASS_HAS_RESERVED_SLOTS(2)); /* additional class flags */
+
+static const size_t OUTER_WINDOW_SLOT = 0;
+static const size_t HOLDER_WEAKMAP_SLOT = 1;
+
+class nsOuterWindowProxy : public MaybeCrossOriginObject<js::Wrapper> {
+  typedef MaybeCrossOriginObject<js::Wrapper> Base;
+
  public:
-  constexpr nsOuterWindowProxy() : js::Wrapper(0) {}
+  constexpr nsOuterWindowProxy() : Base(0) {}
 
   bool finalizeInBackground(const JS::Value& priv) const override {
     return false;
   }
 
   // Standard internal methods
+  /**
+   * Implementation of [[GetOwnProperty]] as defined at
+   * https://html.spec.whatwg.org/multipage/window-object.html#windowproxy-getownproperty
+   *
+   * "proxy" is the WindowProxy object involved.  It may not be same-compartment
+   * with cx.
+   */
   bool getOwnPropertyDescriptor(
       JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
       JS::MutableHandle<JS::PropertyDescriptor> desc) const override;
-  bool defineProperty(JSContext* cx, JS::Handle<JSObject*> proxy,
-                      JS::Handle<jsid> id,
-                      JS::Handle<JS::PropertyDescriptor> desc,
-                      JS::ObjectOpResult& result) const override;
+
+  /*
+   * Implementation of the same-origin case of
+   * <https://html.spec.whatwg.org/multipage/window-object.html#windowproxy-getownproperty>.
+   */
+  bool definePropertySameOrigin(JSContext* cx, JS::Handle<JSObject*> proxy,
+                                JS::Handle<jsid> id,
+                                JS::Handle<JS::PropertyDescriptor> desc,
+                                JS::ObjectOpResult& result) const override;
+
+  /**
+   * Implementation of [[OwnPropertyKeys]] as defined at
+   *
+   * https://html.spec.whatwg.org/multipage/window-object.html#windowproxy-ownpropertykeys
+   *
+   * "proxy" is the WindowProxy object involved.  It may not be same-compartment
+   * with cx.
+   */
   bool ownPropertyKeys(JSContext* cx, JS::Handle<JSObject*> proxy,
                        JS::AutoIdVector& props) const override;
+  /**
+   * Implementation of [[Delete]] as defined at
+   * https://html.spec.whatwg.org/multipage/window-object.html#windowproxy-delete
+   *
+   * "proxy" is the WindowProxy object involved.  It may not be same-compartment
+   * with cx.
+   */
   bool delete_(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
                JS::ObjectOpResult& result) const override;
 
-  bool getPrototypeIfOrdinary(
-      JSContext* cx, JS::Handle<JSObject*> proxy, bool* isOrdinary,
-      JS::MutableHandle<JSObject*> protop) const override;
-
-  JSObject* enumerate(JSContext* cx,
-                      JS::Handle<JSObject*> proxy) const override;
-  bool preventExtensions(JSContext* cx, JS::Handle<JSObject*> proxy,
-                         JS::ObjectOpResult& result) const override;
-  bool isExtensible(JSContext* cx, JS::Handle<JSObject*> proxy,
-                    bool* extensible) const override;
+  /**
+   * Implementaton of hook for superclass getPrototype() method.
+   */
+  JSObject* getSameOriginPrototype(JSContext* cx) const override;
+
+  /**
+   * Implementation of [[HasProperty]] internal method as defined at
+   * https://tc39.github.io/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-hasproperty-p
+   *
+   * "proxy" is the WindowProxy object involved.  It may not be same-compartment
+   * with cx.
+   *
+   * Note that the HTML spec does not define an override for this internal
+   * method, so we just want the "normal object" behavior.  We have to override
+   * it, because js::Wrapper also overrides, with "not normal" behavior.
+   */
   bool has(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
            bool* bp) const override;
+
+  /**
+   * Implementation of [[Get]] internal method as defined at
+   * <https://html.spec.whatwg.org/multipage/window-object.html#windowproxy-get>.
+   *
+   * "proxy" is the WindowProxy object involved.  It may or may not be
+   * same-compartment with "cx".
+   *
+   * "receiver" is the receiver ("this") for the get.  It will be
+   * same-compartment with "cx".
+   *
+   * "vp" is the return value.  It will be same-compartment with "cx".
+   */
   bool get(JSContext* cx, JS::Handle<JSObject*> proxy,
            JS::Handle<JS::Value> receiver, JS::Handle<jsid> id,
            JS::MutableHandle<JS::Value> vp) const override;
+
+  /**
+   * Implementation of [[Set]] internal method as defined at
+   * <https://html.spec.whatwg.org/multipage/window-object.html#windowproxy-set>.
+   *
+   * "proxy" is the WindowProxy object involved.  It may or may not be
+   * same-compartment with "cx".
+   *
+   * "v" is the value being set.  It will be same-compartment with "cx".
+   *
+   * "receiver" is the receiver ("this") for the set.  It will be
+   * same-compartment with "cx".
+   */
   bool set(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
            JS::Handle<JS::Value> v, JS::Handle<JS::Value> receiver,
            JS::ObjectOpResult& result) const override;
 
   // SpiderMonkey extensions
+  /**
+   * Non-standard method we want to get rid of.
+   *
+   * "proxy" is the WindowProxy object involved.  It may not be same-compartment
+   * with cx.
+   *
+   * The only reason we implement this is because js::Wrapper does and we want
+   * different behavior from the js::Wrapper implementation.
+   */
   bool getPropertyDescriptor(
       JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
       JS::MutableHandle<JS::PropertyDescriptor> desc) const override;
+
+  /**
+   * Implementation of SpiderMonkey extension which just checks whether this
+   * object has the property.  Basically Object.getOwnPropertyDescriptor(obj,
+   * prop) !== undefined. but does not require reifying the descriptor.
+   *
+   * We have to override this because js::Wrapper overrides it, but we want
+   * different behavior from js::Wrapper.
+   *
+   * "proxy" is the WindowProxy object involved.  It may not be same-compartment
+   * with cx.
+   */
   bool hasOwn(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
               bool* bp) const override;
+
+  /**
+   * Implementation of SpiderMonkey extension which is used as a fast path for
+   * enumerating.
+   *
+   * We have to override this because js::Wrapper overrides it, but we want
+   * different behavior from js::Wrapper.
+   *
+   * "proxy" is the WindowProxy object involved.  It may not be same-compartment
+   * with cx.
+   */
   bool getOwnEnumerablePropertyKeys(JSContext* cx, JS::Handle<JSObject*> proxy,
                                     JS::AutoIdVector& props) const override;
+
+  /**
+   * Hook used by SpiderMonkey to implement Object.prototype.toString.
+   */
   const char* className(JSContext* cx,
                         JS::Handle<JSObject*> wrapper) const override;
 
   void finalize(JSFreeOp* fop, JSObject* proxy) const override;
   size_t objectMoved(JSObject* proxy, JSObject* old) const override;
 
   bool isCallable(JSObject* obj) const override { return false; }
   bool isConstructor(JSObject* obj) const override { return false; }
 
   static const nsOuterWindowProxy singleton;
 
  protected:
   static nsGlobalWindowOuter* GetOuterWindow(JSObject* proxy) {
     nsGlobalWindowOuter* outerWindow =
         nsGlobalWindowOuter::FromSupports(static_cast<nsISupports*>(
-            js::GetProxyReservedSlot(proxy, 0).toPrivate()));
+            js::GetProxyReservedSlot(proxy, OUTER_WINDOW_SLOT).toPrivate()));
     return outerWindow;
   }
 
   // False return value means we threw an exception.  True return value
   // but false "found" means we didn't have a subframe at that index.
   bool GetSubframeWindow(JSContext* cx, JS::Handle<JSObject*> proxy,
                          JS::Handle<jsid> id, JS::MutableHandle<JS::Value> vp,
                          bool& found) const;
 
   // Returns a non-null window only if id is an index and we have a
   // window at that index.
   already_AddRefed<nsPIDOMWindowOuter> GetSubframeWindow(
       JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id) const;
 
-  bool AppendIndexedPropertyNames(JSContext* cx, JSObject* proxy,
+  bool AppendIndexedPropertyNames(JSObject* proxy,
                                   JS::AutoIdVector& props) const;
+
+  using MaybeCrossOriginObjectMixins::EnsureHolder;
+  bool EnsureHolder(JSContext* cx, JS::Handle<JSObject*> proxy,
+                    JS::MutableHandle<JSObject*> holder) const override;
 };
 
-// Give OuterWindowProxyClass 2 reserved slots, like the other wrappers, so
-// JSObject::swap can swap it with CrossCompartmentWrappers without requiring
-// malloc.
-const js::Class OuterWindowProxyClass = PROXY_CLASS_DEF(
-    "Proxy", JSCLASS_HAS_RESERVED_SLOTS(2)); /* additional class flags */
-
 const char* nsOuterWindowProxy::className(JSContext* cx,
                                           JS::Handle<JSObject*> proxy) const {
   MOZ_ASSERT(js::IsProxy(proxy));
 
+  if (!IsPlatformObjectSameOrigin(cx, proxy)) {
+    return "Object";
+  }
+
   return "Window";
 }
 
 void nsOuterWindowProxy::finalize(JSFreeOp* fop, JSObject* proxy) const {
   nsGlobalWindowOuter* outerWindow = GetOuterWindow(proxy);
   if (outerWindow) {
     outerWindow->ClearWrapper(proxy);
     BrowsingContext* bc = outerWindow->GetBrowsingContext();
@@ -450,29 +564,48 @@ void nsOuterWindowProxy::finalize(JSFree
     // write a non-null value that will reliably crash when dereferenced.
     outerWindow->PoisonOuterWindowProxy(proxy);
   }
 }
 
 bool nsOuterWindowProxy::getPropertyDescriptor(
     JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
     JS::MutableHandle<JS::PropertyDescriptor> desc) const {
-  // The only thing we can do differently from js::Wrapper is shadow stuff with
-  // our indexed properties, so we can just try getOwnPropertyDescriptor and if
-  // that gives us nothing call on through to js::Wrapper.
+  // In the same-origin case the only thing we can do differently from
+  // js::Wrapper is shadow stuff with our indexed properties, so we can just try
+  // getOwnPropertyDescriptor and if that gives us nothing call on through to
+  // js::Wrapper.
+  //
+  // In the cross-origin case, we can only have own properties, so don't even
+  // need to worry about the js::Proxy bit.
   desc.object().set(nullptr);
   if (!getOwnPropertyDescriptor(cx, proxy, id, desc)) {
     return false;
   }
 
   if (desc.object()) {
     return true;
   }
 
-  return js::Wrapper::getPropertyDescriptor(cx, proxy, id, desc);
+  if (!IsPlatformObjectSameOrigin(cx, proxy)) {
+    return true;
+  }
+
+  // When forwarding to js::Wrapper, we should just enter the Realm of proxy
+  // for now.  That's what js::Wrapper expects, and since we're same-origin
+  // anyway this is not changing any security behavior.
+  {
+    JSAutoRealm ar(cx, proxy);
+    JS_MarkCrossZoneId(cx, id);
+    if (!js::Wrapper::getPropertyDescriptor(cx, proxy, id, desc)) {
+      return false;
+    }
+  }
+
+  return JS_WrapPropertyDescriptor(cx, desc);
 }
 
 /**
  * IsNonConfigurableReadonlyPrimitiveGlobalProp returns true for
  * property names that fit the following criteria:
  *
  * 1) The ES spec defines a property with that name on globals.
  * 2) The property is non-configurable.
@@ -490,45 +623,105 @@ static bool IsNonConfigurableReadonlyPri
          id == GetJSIDByIndex(cx, XPCJSContext::IDX_UNDEFINED) ||
          id == GetJSIDByIndex(cx, XPCJSContext::IDX_INFINITY);
 }
 #endif
 
 bool nsOuterWindowProxy::getOwnPropertyDescriptor(
     JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
     JS::MutableHandle<JS::PropertyDescriptor> desc) const {
+  // First check for indexed access.  This is
+  // https://html.spec.whatwg.org/multipage/window-object.html#windowproxy-getownproperty
+  // step 2, mostly.
   bool found;
   if (!GetSubframeWindow(cx, proxy, id, desc.value(), found)) {
     return false;
   }
   if (found) {
+    // Step 2.4.
     FillPropertyDescriptor(desc, proxy, true);
     return true;
   }
-  // else fall through to js::Wrapper
-
-  bool ok = js::Wrapper::getOwnPropertyDescriptor(cx, proxy, id, desc);
-  if (!ok) {
-    return false;
-  }
+
+  bool isSameOrigin = IsPlatformObjectSameOrigin(cx, proxy);
+
+  // If we did not find a subframe, we could still have an indexed property
+  // access.  In that case we should throw a SecurityError in the cross-origin
+  // case.
+  if (!isSameOrigin && IsArrayIndex(GetArrayIndexFromId(id))) {
+    // Step 2.5.2.
+    return ReportCrossOriginDenial(cx, id, NS_LITERAL_CSTRING("access"));
+  }
+
+  // Step 2.5.1 is handled via the forwarding to js::Wrapper; it saves us an
+  // IsArrayIndex(GetArrayIndexFromId(id)) here.  We'll never have a property on
+  // the Window whose name is an index, because our defineProperty doesn't pass
+  // those on to the Window.
+
+  // Step 3.
+  if (isSameOrigin) {
+    // Fall through to js::Wrapper.
+    {  // Scope for JSAutoRealm while we are dealing with js::Wrapper.
+      // When forwarding to js::Wrapper, we should just enter the Realm of proxy
+      // for now.  That's what js::Wrapper expects, and since we're same-origin
+      // anyway this is not changing any security behavior.
+      JSAutoRealm ar(cx, proxy);
+      JS_MarkCrossZoneId(cx, id);
+      bool ok = js::Wrapper::getOwnPropertyDescriptor(cx, proxy, id, desc);
+      if (!ok) {
+        return false;
+      }
 
 #ifndef RELEASE_OR_BETA  // To be turned on in bug 1496510.
-  if (!IsNonConfigurableReadonlyPrimitiveGlobalProp(cx, id)) {
-    desc.setConfigurable(true);
-  }
+      if (!IsNonConfigurableReadonlyPrimitiveGlobalProp(cx, id)) {
+        desc.setConfigurable(true);
+      }
 #endif
-
-  return true;
-}
-
-bool nsOuterWindowProxy::defineProperty(JSContext* cx,
-                                        JS::Handle<JSObject*> proxy,
-                                        JS::Handle<jsid> id,
-                                        JS::Handle<JS::PropertyDescriptor> desc,
-                                        JS::ObjectOpResult& result) const {
+    }
+
+    // Now wrap our descriptor back into the Realm that asked for it.
+    return JS_WrapPropertyDescriptor(cx, desc);
+  }
+
+  // Step 4.
+  if (!CrossOriginGetOwnPropertyHelper(cx, proxy, id, desc)) {
+    return false;
+  }
+
+  // Step 5
+  if (desc.object()) {
+    return true;
+  }
+
+  // Step 6 -- check for named subframes.
+  if (JSID_IS_STRING(id)) {
+    nsAutoJSString name;
+    if (!name.init(cx, JSID_TO_STRING(id))) {
+      return false;
+    }
+    nsGlobalWindowOuter* win = GetOuterWindow(proxy);
+    if (RefPtr<BrowsingContext> childDOMWin = win->GetChildWindow(name)) {
+      JS::Rooted<JS::Value> childValue(cx);
+      if (!ToJSValue(cx, WindowProxyHolder(childDOMWin), &childValue)) {
+        return false;
+      }
+      FillPropertyDescriptor(desc, proxy, childValue,
+                             /* readonly = */ true,
+                             /* enumerable = */ false);
+      return true;
+    }
+  }
+
+  // And step 7.
+  return CrossOriginPropertyFallback(cx, proxy, id, desc);
+}
+
+bool nsOuterWindowProxy::definePropertySameOrigin(
+    JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
+    JS::Handle<JS::PropertyDescriptor> desc, JS::ObjectOpResult& result) const {
   if (IsArrayIndex(GetArrayIndexFromId(id))) {
     // Spec says to Reject whether this is a supported index or not,
     // since we have no indexed setter or indexed creator.  It is up
     // to the caller to decide whether to throw a TypeError.
     return result.failCantDefineWindowElement();
   }
 
   JS::ObjectOpResult ourResult;
@@ -594,160 +787,254 @@ bool nsOuterWindowProxy::defineProperty(
   result.succeed();
   return true;
 }
 
 bool nsOuterWindowProxy::ownPropertyKeys(JSContext* cx,
                                          JS::Handle<JSObject*> proxy,
                                          JS::AutoIdVector& props) const {
   // Just our indexed stuff followed by our "normal" own property names.
-  if (!AppendIndexedPropertyNames(cx, proxy, props)) {
+  if (!AppendIndexedPropertyNames(proxy, props)) {
     return false;
   }
 
-  JS::AutoIdVector innerProps(cx);
-  if (!js::Wrapper::ownPropertyKeys(cx, proxy, innerProps)) {
+  if (IsPlatformObjectSameOrigin(cx, proxy)) {
+    // When forwarding to js::Wrapper, we should just enter the Realm of proxy
+    // for now.  That's what js::Wrapper expects, and since we're same-origin
+    // anyway this is not changing any security behavior.
+    JS::AutoIdVector innerProps(cx);
+    {  // Scope for JSAutoRealm so we can mark the ids once we exit it
+      JSAutoRealm ar(cx, proxy);
+      if (!js::Wrapper::ownPropertyKeys(cx, proxy, innerProps)) {
+        return false;
+      }
+    }
+    for (auto& id : innerProps) {
+      JS_MarkCrossZoneId(cx, id);
+    }
+    return js::AppendUnique(cx, props, innerProps);
+  }
+
+  // In the cross-origin case we purposefully exclude subframe names from the
+  // list of property names we report here.
+  JS::Rooted<JSObject*> holder(cx);
+  if (!EnsureHolder(cx, proxy, &holder)) {
     return false;
   }
-  return js::AppendUnique(cx, props, innerProps);
+
+  JS::AutoIdVector crossOriginProps(cx);
+  if (!js::GetPropertyKeys(cx, holder,
+                           JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS,
+                           &crossOriginProps) ||
+      !js::AppendUnique(cx, props, crossOriginProps)) {
+    return false;
+  }
+
+  return xpc::AppendCrossOriginWhitelistedPropNames(cx, props);
 }
 
 bool nsOuterWindowProxy::delete_(JSContext* cx, JS::Handle<JSObject*> proxy,
                                  JS::Handle<jsid> id,
                                  JS::ObjectOpResult& result) const {
+  if (!IsPlatformObjectSameOrigin(cx, proxy)) {
+    return ReportCrossOriginDenial(cx, id, NS_LITERAL_CSTRING("delete"));
+  }
+
   if (nsCOMPtr<nsPIDOMWindowOuter> frame = GetSubframeWindow(cx, proxy, id)) {
     // Fail (which means throw if strict, else return false).
     return result.failCantDeleteWindowElement();
   }
 
   if (IsArrayIndex(GetArrayIndexFromId(id))) {
     // Indexed, but not supported.  Spec says return true.
     return result.succeed();
   }
 
+  // We're same-origin, so it should be safe to enter the Realm of "proxy".
+  // Let's do that, just in case, to avoid cross-compartment issues in our
+  // js::Wrapper caller..
+  JSAutoRealm ar(cx, proxy);
+  JS_MarkCrossZoneId(cx, id);
   return js::Wrapper::delete_(cx, proxy, id, result);
 }
 
-bool nsOuterWindowProxy::getPrototypeIfOrdinary(
-    JSContext* cx, JS::Handle<JSObject*> proxy, bool* isOrdinary,
-    JS::MutableHandle<JSObject*> protop) const {
-  // Window's [[GetPrototypeOf]] trap isn't the ordinary definition:
-  //
-  //   https://html.spec.whatwg.org/multipage/browsers.html#windowproxy-getprototypeof
-  //
-  // We nonetheless can implement it with a static [[Prototype]], because
-  // wrapper-class handlers (particularly, XOW in FilteringWrapper.cpp) supply
-  // all non-ordinary behavior.
-  //
-  // But from a spec point of view, it's the exact same object in both cases --
-  // only the observer's changed.  So this getPrototypeIfOrdinary trap on the
-  // non-wrapper object *must* report non-ordinary, even if static [[Prototype]]
-  // usually means ordinary.
-  *isOrdinary = false;
-  return true;
-}
-
-bool nsOuterWindowProxy::preventExtensions(JSContext* cx,
-                                           JS::Handle<JSObject*> proxy,
-                                           JS::ObjectOpResult& result) const {
-  // If [[Extensible]] could be false, then navigating a window could navigate
-  // to a window that's [[Extensible]] after being at one that wasn't: an
-  // invariant violation.  So never change a window's extensibility.
-  return result.failCantPreventExtensions();
-}
-
-bool nsOuterWindowProxy::isExtensible(JSContext* cx,
-                                      JS::Handle<JSObject*> proxy,
-                                      bool* extensible) const {
-  // See above.
-  *extensible = true;
-  return true;
+JSObject* nsOuterWindowProxy::getSameOriginPrototype(JSContext* cx) const {
+  return Window_Binding::GetProtoObjectHandle(cx);
 }
 
 bool nsOuterWindowProxy::has(JSContext* cx, JS::Handle<JSObject*> proxy,
                              JS::Handle<jsid> id, bool* bp) const {
+  // We could just directly forward this method to js::BaseProxyHandler, but
+  // that involves reifying the actual property descriptor, which might be more
+  // work than we have to do for has() on the Window.
+
+  if (!IsPlatformObjectSameOrigin(cx, proxy)) {
+    // In the cross-origin case we only have own properties.  Just call hasOwn
+    // directly.
+    return hasOwn(cx, proxy, id, bp);
+  }
+
   if (nsCOMPtr<nsPIDOMWindowOuter> frame = GetSubframeWindow(cx, proxy, id)) {
     *bp = true;
     return true;
   }
 
+  // Just to be safe in terms of compartment asserts, enter the Realm of
+  // "proxy".  We're same-origin with it, so this should be safe.
+  JSAutoRealm ar(cx, proxy);
+  JS_MarkCrossZoneId(cx, id);
   return js::Wrapper::has(cx, proxy, id, bp);
 }
 
 bool nsOuterWindowProxy::hasOwn(JSContext* cx, JS::Handle<JSObject*> proxy,
                                 JS::Handle<jsid> id, bool* bp) const {
+  // We could just directly forward this method to js::BaseProxyHandler, but
+  // that involves reifying the actual property descriptor, which might be more
+  // work than we have to do for hasOwn() on the Window.
+
+  if (!IsPlatformObjectSameOrigin(cx, proxy)) {
+    // Avoiding reifying the property descriptor here would require duplicating
+    // a bunch of "is this property exposed cross-origin" logic, which is
+    // probably not worth it.  Just forward this along to the base
+    // implementation.
+    //
+    // It's very important to not forward this to js::Wrapper, because that will
+    // not do the right security and cross-origin checks and will pass through
+    // the call to the Window.
+    //
+    // The BaseProxyHandler code is OK with this happening without entering the
+    // compartment of "proxy".
+    return js::BaseProxyHandler::hasOwn(cx, proxy, id, bp);
+  }
+
   if (nsCOMPtr<nsPIDOMWindowOuter> frame = GetSubframeWindow(cx, proxy, id)) {
     *bp = true;
     return true;
   }
 
+  // Just to be safe in terms of compartment asserts, enter the Realm of
+  // "proxy".  We're same-origin with it, so this should be safe.
+  JSAutoRealm ar(cx, proxy);
+  JS_MarkCrossZoneId(cx, id);
   return js::Wrapper::hasOwn(cx, proxy, id, bp);
 }
 
 bool nsOuterWindowProxy::get(JSContext* cx, JS::Handle<JSObject*> proxy,
                              JS::Handle<JS::Value> receiver,
                              JS::Handle<jsid> id,
                              JS::MutableHandle<JS::Value> vp) const {
   if (id == GetJSIDByIndex(cx, XPCJSContext::IDX_WRAPPED_JSOBJECT) &&
       xpc::AccessCheck::isChrome(js::GetContextCompartment(cx))) {
     vp.set(JS::ObjectValue(*proxy));
-    return true;
+    return MaybeWrapValue(cx, vp);
+  }
+
+  if (!IsPlatformObjectSameOrigin(cx, proxy)) {
+    return CrossOriginGet(cx, proxy, receiver, id, vp);
   }
 
   bool found;
   if (!GetSubframeWindow(cx, proxy, id, vp, found)) {
     return false;
   }
+
   if (found) {
     return true;
   }
-  // Else fall through to js::Wrapper
-
-  return js::Wrapper::get(cx, proxy, receiver, id, vp);
+
+  {  // Scope for JSAutoRealm
+    // Enter "proxy"'s Realm.  We're in the same-origin case, so this should be
+    // safe.
+    JSAutoRealm ar(cx, proxy);
+
+    JS_MarkCrossZoneId(cx, id);
+
+    JS::Rooted<JS::Value> wrappedReceiver(cx, receiver);
+    if (!MaybeWrapValue(cx, &wrappedReceiver)) {
+      return false;
+    }
+
+    // Fall through to js::Wrapper.
+    if (!js::Wrapper::get(cx, proxy, wrappedReceiver, id, vp)) {
+      return false;
+    }
+  }
+
+  // Make sure our return value is in the caller compartment.
+  return MaybeWrapValue(cx, vp);
 }
 
 bool nsOuterWindowProxy::set(JSContext* cx, JS::Handle<JSObject*> proxy,
                              JS::Handle<jsid> id, JS::Handle<JS::Value> v,
                              JS::Handle<JS::Value> receiver,
                              JS::ObjectOpResult& result) const {
+  if (!IsPlatformObjectSameOrigin(cx, proxy)) {
+    return CrossOriginSet(cx, proxy, id, v, receiver, result);
+  }
+
   if (IsArrayIndex(GetArrayIndexFromId(id))) {
     // Reject the set.  It's up to the caller to decide whether to throw a
     // TypeError.  If the caller is strict mode JS code, it'll throw.
     return result.failReadOnly();
   }
 
-  return js::Wrapper::set(cx, proxy, id, v, receiver, result);
+  // Do the rest in the Realm of "proxy", since we're in the same-origin case.
+  JSAutoRealm ar(cx, proxy);
+  JS::Rooted<JS::Value> wrappedArg(cx, v);
+  if (!MaybeWrapValue(cx, &wrappedArg)) {
+    return false;
+  }
+  JS::Rooted<JS::Value> wrappedReceiver(cx, receiver);
+  if (!MaybeWrapValue(cx, &wrappedReceiver)) {
+    return false;
+  }
+
+  JS_MarkCrossZoneId(cx, id);
+
+  return js::Wrapper::set(cx, proxy, id, wrappedArg, wrappedReceiver, result);
 }
 
 bool nsOuterWindowProxy::getOwnEnumerablePropertyKeys(
     JSContext* cx, JS::Handle<JSObject*> proxy, JS::AutoIdVector& props) const {
+  // We could just stop overring getOwnEnumerablePropertyKeys and let our
+  // superclasses deal (by falling back on the BaseProxyHandler implementation
+  // that uses a combination of ownPropertyKeys and getOwnPropertyDescriptor to
+  // only return the enumerable ones.  But maybe there's value in having
+  // somewhat faster for-in iteration on Window objects...
+
   // Like ownPropertyKeys, our indexed stuff followed by our "normal" enumerable
   // own property names.
-  //
-  // Note that this does not match current spec per
-  // https://github.com/whatwg/html/issues/2753 but as that issue says I believe
-  // the spec is wrong.
-  if (!AppendIndexedPropertyNames(cx, proxy, props)) {
+  if (!AppendIndexedPropertyNames(proxy, props)) {
     return false;
   }
 
+  if (!IsPlatformObjectSameOrigin(cx, proxy)) {
+    // All the cross-origin properties other than the indexed props are
+    // non-enumerable, so we're done here.
+    return true;
+  }
+
+  // When forwarding to js::Wrapper, we should just enter the Realm of proxy
+  // for now.  That's what js::Wrapper expects, and since we're same-origin
+  // anyway this is not changing any security behavior.
   JS::AutoIdVector innerProps(cx);
-  if (!js::Wrapper::getOwnEnumerablePropertyKeys(cx, proxy, innerProps)) {
-    return false;
-  }
+  {  // Scope for JSAutoRealm so we can mark the ids once we exit it.
+    JSAutoRealm ar(cx, proxy);
+    if (!js::Wrapper::getOwnEnumerablePropertyKeys(cx, proxy, innerProps)) {
+      return false;
+    }
+  }
+
+  for (auto& id : innerProps) {
+    JS_MarkCrossZoneId(cx, id);
+  }
+
   return js::AppendUnique(cx, props, innerProps);
 }
 
-JSObject* nsOuterWindowProxy::enumerate(JSContext* cx,
-                                        JS::Handle<JSObject*> proxy) const {
-  // BaseProxyHandler::enumerate seems to do what we want here: fall
-  // back on the property names returned from js::GetPropertyKeys()
-  return js::BaseProxyHandler::enumerate(cx, proxy);
-}
-
 bool nsOuterWindowProxy::GetSubframeWindow(JSContext* cx,
                                            JS::Handle<JSObject*> proxy,
                                            JS::Handle<jsid> id,
                                            JS::MutableHandle<JS::Value> vp,
                                            bool& found) const {
   nsCOMPtr<nsPIDOMWindowOuter> frame = GetSubframeWindow(cx, proxy, id);
   if (!frame) {
     found = false;
@@ -777,31 +1064,39 @@ already_AddRefed<nsPIDOMWindowOuter> nsO
     return nullptr;
   }
 
   nsGlobalWindowOuter* win = GetOuterWindow(proxy);
   return win->IndexedGetterOuter(index);
 }
 
 bool nsOuterWindowProxy::AppendIndexedPropertyNames(
-    JSContext* cx, JSObject* proxy, JS::AutoIdVector& props) const {
+    JSObject* proxy, JS::AutoIdVector& props) const {
   uint32_t length = GetOuterWindow(proxy)->Length();
   MOZ_ASSERT(int32_t(length) >= 0);
   if (!props.reserve(props.length() + length)) {
     return false;
   }
   for (int32_t i = 0; i < int32_t(length); ++i) {
     if (!props.append(INT_TO_JSID(i))) {
       return false;
     }
   }
 
   return true;
 }
 
+bool nsOuterWindowProxy::EnsureHolder(
+    JSContext* cx, JS::Handle<JSObject*> proxy,
+    JS::MutableHandle<JSObject*> holder) const {
+  return EnsureHolder(cx, proxy, HOLDER_WEAKMAP_SLOT,
+                      Window_Binding::sCrossOriginAttributes,
+                      Window_Binding::sCrossOriginMethods, holder);
+}
+
 size_t nsOuterWindowProxy::objectMoved(JSObject* obj, JSObject* old) const {
   nsGlobalWindowOuter* outerWindow = GetOuterWindow(obj);
   if (outerWindow) {
     outerWindow->UpdateWrapper(obj, old);
     BrowsingContext* bc = outerWindow->GetBrowsingContext();
     if (bc) {
       bc->UpdateWindowProxy(obj, old);
     }
@@ -981,17 +1276,18 @@ nsGlobalWindowOuter::~nsGlobalWindowOute
   MOZ_LOG(gDOMLeakPRLogOuter, LogLevel::Debug,
           ("DOMWINDOW %p destroyed", this));
 
   JSObject* proxy = GetWrapperMaybeDead();
   if (proxy) {
     if (mBrowsingContext) {
       mBrowsingContext->ClearWindowProxy();
     }
-    js::SetProxyReservedSlot(proxy, 0, js::PrivateValue(nullptr));
+    js::SetProxyReservedSlot(proxy, OUTER_WINDOW_SLOT,
+                             js::PrivateValue(nullptr));
   }
 
   // An outer window is destroyed with inner windows still possibly
   // alive, iterate through the inner windows and null out their
   // back pointer to this outer, and pull them out of the list of
   // inner windows.
   //
   // Our linked list of inner windows both contains (an nsGlobalWindowOuter),
@@ -1808,17 +2104,18 @@ nsresult nsGlobalWindowOuter::SetNewDocu
     MOZ_ASSERT(mInnerWindow);
     mInnerWindow->TryToCacheTopInnerWindow();
 
     if (!GetWrapperPreserveColor()) {
       JS::Rooted<JSObject*> outer(
           cx, NewOuterWindowProxy(cx, newInnerGlobal, thisChrome));
       NS_ENSURE_TRUE(outer, NS_ERROR_FAILURE);
 
-      js::SetProxyReservedSlot(outer, 0, js::PrivateValue(ToSupports(this)));
+      js::SetProxyReservedSlot(outer, OUTER_WINDOW_SLOT,
+                               js::PrivateValue(ToSupports(this)));
 
       // Inform the nsJSContext, which is the canonical holder of the outer.
       mContext->SetWindowProxy(outer);
       mContext->DidInitializeContext();
 
       SetWrapper(mContext->GetWindowProxy());
     } else {
       JS::ExposeObjectToActiveJS(newInnerGlobal);
@@ -1826,27 +2123,29 @@ nsresult nsGlobalWindowOuter::SetNewDocu
           cx, NewOuterWindowProxy(cx, newInnerGlobal, thisChrome));
       if (!outerObject) {
         NS_ERROR("out of memory");
         return NS_ERROR_FAILURE;
       }
 
       JS::Rooted<JSObject*> obj(cx, GetWrapperPreserveColor());
 
-      js::SetProxyReservedSlot(obj, 0, js::PrivateValue(nullptr));
-      js::SetProxyReservedSlot(outerObject, 0, js::PrivateValue(nullptr));
+      js::SetProxyReservedSlot(obj, OUTER_WINDOW_SLOT,
+                               js::PrivateValue(nullptr));
+      js::SetProxyReservedSlot(outerObject, OUTER_WINDOW_SLOT,
+                               js::PrivateValue(nullptr));
 
       outerObject = xpc::TransplantObject(cx, obj, outerObject);
       if (!outerObject) {
         mBrowsingContext->ClearWindowProxy();
         NS_ERROR("unable to transplant wrappers, probably OOM");
         return NS_ERROR_FAILURE;
       }
 
-      js::SetProxyReservedSlot(outerObject, 0,
+      js::SetProxyReservedSlot(outerObject, OUTER_WINDOW_SLOT,
                                js::PrivateValue(ToSupports(this)));
 
       SetWrapper(outerObject);
 
       MOZ_ASSERT(JS::GetNonCCWObjectGlobal(outerObject) == newInnerGlobal);
 
       // Inform the nsJSContext, which is the canonical holder of the outer.
       mContext->SetWindowProxy(outerObject);
--- a/dom/base/nsXHTMLContentSerializer.cpp
+++ b/dom/base/nsXHTMLContentSerializer.cpp
@@ -28,16 +28,17 @@
 #include "nsCRT.h"
 #include "nsContentUtils.h"
 #include "nsIScriptElement.h"
 #include "nsStubMutationObserver.h"
 #include "nsAttrName.h"
 #include "nsComputedDOMStyle.h"
 
 using namespace mozilla;
+using namespace mozilla::dom;
 
 static const int32_t kLongLineLen = 128;
 
 #define kXMLNS "xmlns"
 
 nsresult NS_NewXHTMLContentSerializer(nsIContentSerializer** aSerializer) {
   RefPtr<nsXHTMLContentSerializer> it = new nsXHTMLContentSerializer();
   it.forget(aSerializer);
@@ -414,17 +415,17 @@ bool nsXHTMLContentSerializer::CheckElem
 
   if (aElement->IsHTMLElement(nsGkAtoms::body)) {
     ++mInBody;
   }
 
   return true;
 }
 
-bool nsXHTMLContentSerializer::CheckElementEnd(dom::Element* aElement,
+bool nsXHTMLContentSerializer::CheckElementEnd(Element* aElement,
                                                bool& aForceFormat,
                                                nsAString& aStr) {
   NS_ASSERTION(!mIsHTMLSerializer,
                "nsHTMLContentSerializer shouldn't call this method !");
 
   aForceFormat = !(mFlags & nsIDocumentEncoder::OutputIgnoreMozDirty) &&
                  aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::mozdirty);
 
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -2898,17 +2898,17 @@ struct LenientThisPolicy : public MaybeG
 // There are some cross-origin things on globals, so we inherit from
 // MaybeGlobalThisPolicy.
 struct CrossOriginThisPolicy : public MaybeGlobalThisPolicy {
   // We want the HasValidThisValue of MaybeGlobalThisPolicy.
 
   // We want the ExtractThisObject of MaybeGlobalThisPolicy.
 
   static MOZ_ALWAYS_INLINE JSObject* MaybeUnwrapThisObject(JSObject* aObj) {
-    if (xpc::WrapperFactory::IsXrayWrapper(aObj)) {
+    if (xpc::WrapperFactory::IsCrossOriginWrapper(aObj)) {
       return js::UncheckedUnwrap(aObj);
     }
 
     // Else just return aObj; our UnwrapThisObject call will try to
     // CheckedUnwrap it, and either succeed or get a security error as needed.
     return aObj;
   }
 
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -777,16 +777,26 @@ inline bool TryToOuterize(JS::MutableHan
     JSObject* obj = js::ToWindowProxyIfWindow(&rval.toObject());
     MOZ_ASSERT(obj);
     rval.set(JS::ObjectValue(*obj));
   }
 
   return true;
 }
 
+inline bool TryToOuterize(JS::MutableHandle<JSObject*> obj) {
+  if (js::IsWindow(obj)) {
+    JSObject* proxy = js::ToWindowProxyIfWindow(obj);
+    MOZ_ASSERT(proxy);
+    obj.set(proxy);
+  }
+
+  return true;
+}
+
 // Make sure to wrap the given string value into the right compartment, as
 // needed.
 MOZ_ALWAYS_INLINE
 bool MaybeWrapStringValue(JSContext* cx, JS::MutableHandle<JS::Value> rval) {
   MOZ_ASSERT(rval.isString());
   JSString* str = rval.toString();
   if (JS::GetStringZone(str) != js::GetContextZone(cx)) {
     return JS_WrapValue(cx, rval);
@@ -812,16 +822,35 @@ bool MaybeWrapObjectValue(JSContext* cx,
     return TryToOuterize(rval);
   }
 
   // It's not a WebIDL object, so it's OK to just leave it as-is: only WebIDL
   // objects (specifically only windows) require outerization.
   return true;
 }
 
+// Like MaybeWrapObjectValue, but working with a
+// JS::MutableHandle<JSObject*> which must be non-null.
+MOZ_ALWAYS_INLINE
+bool MaybeWrapObject(JSContext* cx, JS::MutableHandle<JSObject*> obj) {
+  if (js::GetObjectCompartment(obj) != js::GetContextCompartment(cx)) {
+    return JS_WrapObject(cx, obj);
+  }
+
+  // We're same-compartment, but even then we might need to wrap
+  // objects specially.  Check for that.
+  if (IsDOMObject(obj)) {
+    return TryToOuterize(obj);
+  }
+
+  // It's not a WebIDL object, so it's OK to just leave it as-is: only WebIDL
+  // objects (specifically only windows) require outerization.
+  return true;
+}
+
 // Like MaybeWrapObjectValue, but also allows null
 MOZ_ALWAYS_INLINE
 bool MaybeWrapObjectOrNullValue(JSContext* cx,
                                 JS::MutableHandle<JS::Value> rval) {
   MOZ_ASSERT(rval.isObjectOrNull());
   if (rval.isNull()) {
     return true;
   }
@@ -2462,21 +2491,23 @@ class MOZ_STACK_CLASS BindingJSObjectCre
   ~BindingJSObjectCreator() {
     if (mReflector) {
       js::SetReservedSlot(mReflector, DOM_OBJECT_SLOT, JS::UndefinedValue());
     }
   }
 
   void CreateProxyObject(JSContext* aCx, const js::Class* aClass,
                          const DOMProxyHandler* aHandler,
-                         JS::Handle<JSObject*> aProto, T* aNative,
-                         JS::Handle<JS::Value> aExpandoValue,
+                         JS::Handle<JSObject*> aProto, bool aLazyProto,
+                         T* aNative, JS::Handle<JS::Value> aExpandoValue,
                          JS::MutableHandle<JSObject*> aReflector) {
     js::ProxyOptions options;
     options.setClass(aClass);
+    options.setLazyProto(aLazyProto);
+
     aReflector.set(
         js::NewProxyObject(aCx, aHandler, aExpandoValue, aProto, options));
     if (aReflector) {
       js::SetProxyReservedSlot(aReflector, DOM_OBJECT_SLOT,
                                JS::PrivateValue(aNative));
       mNative = aNative;
       mReflector = aReflector;
     }
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -351,17 +351,19 @@ class CGNativePropertyHooks(CGThing):
             // then induce static constructors.  Lots of static constructors.
             extern const NativePropertyHooks sNativePropertyHooks[];
             """)
 
     def define(self):
         if not self.descriptor.wantsXrays:
             return ""
         deleteNamedProperty = "nullptr"
-        if self.descriptor.concrete and self.descriptor.proxy:
+        if (self.descriptor.concrete and
+            self.descriptor.proxy and
+            not self.descriptor.isMaybeCrossOriginObject()):
             resolveOwnProperty = "ResolveOwnProperty"
             enumerateOwnProperties = "EnumerateOwnProperties"
             if self.descriptor.needsXrayNamedDeleterHook():
                 deleteNamedProperty = "DeleteNamedProperty"
         elif self.descriptor.needsXrayResolveHooks():
             resolveOwnProperty = "ResolveOwnPropertyViaResolve"
             enumerateOwnProperties = "EnumerateOwnPropertiesViaGetOwnPropertyNames"
         else:
@@ -440,17 +442,24 @@ def DOMClass(descriptor):
           GetCCParticipant<${nativeType}>::Get()
         """,
         protoChain=', '.join(protoList),
         nativeType=descriptor.nativeType,
         hooks=NativePropertyHooks(descriptor))
 
 
 def InstanceReservedSlots(descriptor):
-    return INSTANCE_RESERVED_SLOTS + descriptor.interface.totalMembersInSlots
+    slots = INSTANCE_RESERVED_SLOTS + descriptor.interface.totalMembersInSlots
+    if descriptor.isMaybeCrossOriginObject():
+        # We need a slot for the cross-origin holder too.
+        if descriptor.interface.hasChildInterfaces():
+            raise TypeError("We don't support non-leaf cross-origin interfaces "
+                            "like %s" % descriptor.interface.identifier.name)
+        slots += 1
+    return slots
 
 
 class CGDOMJSClass(CGThing):
     """
     Generate a DOMJSClass for a given descriptor
     """
     def __init__(self, descriptor):
         CGThing.__init__(self)
@@ -3577,29 +3586,40 @@ class CGConstructorEnabled(CGAbstractMet
 
 def CreateBindingJSObject(descriptor, properties):
     objDecl = "BindingJSObjectCreator<%s> creator(aCx);\n" % descriptor.nativeType
 
     # We don't always need to root obj, but there are a variety
     # of cases where we do, so for simplicity, just always root it.
     if descriptor.proxy:
         if descriptor.interface.getExtendedAttribute('OverrideBuiltins'):
+            assert not descriptor.isMaybeCrossOriginObject()
             create = dedent(
                 """
                 aObject->mExpandoAndGeneration.expando.setUndefined();
                 JS::Rooted<JS::Value> expandoValue(aCx, JS::PrivateValue(&aObject->mExpandoAndGeneration));
                 creator.CreateProxyObject(aCx, &sClass.mBase, DOMProxyHandler::getInstance(),
-                                          proto, aObject, expandoValue, aReflector);
+                                          proto, /* aLazyProto = */ false, aObject,
+                                          expandoValue, aReflector);
                 """)
         else:
-            create = dedent(
+            if descriptor.isMaybeCrossOriginObject():
+                proto = "nullptr"
+                lazyProto = "true"
+            else:
+                proto = "proto"
+                lazyProto = "false"
+            create = fill(
                 """
                 creator.CreateProxyObject(aCx, &sClass.mBase, DOMProxyHandler::getInstance(),
-                                          proto, aObject, JS::UndefinedHandleValue, aReflector);
-                """)
+                                          ${proto}, /* aLazyProto = */ ${lazyProto},
+                                          aObject, JS::UndefinedHandleValue, aReflector);
+                """,
+                proto=proto,
+                lazyProto=lazyProto)
     else:
         create = dedent(
             """
             creator.CreateObject(aCx, sClass.ToJSClass(), proto, aObject, aReflector);
             """)
     return objDecl + create + dedent(
         """
         if (!aReflector) {
@@ -3752,45 +3772,40 @@ def InitMemberSlots(descriptor, failureC
         """
         if (!UpdateMemberSlots(aCx, aReflector, aObject)) {
           $*{failureCode}
         }
         """,
         failureCode=failureCode)
 
 
-def SetImmutablePrototype(descriptor, failureCode):
-    if not descriptor.hasNonOrdinaryGetPrototypeOf():
-        return ""
-
-    return fill(
-        """
-        bool succeeded;
-        if (!JS_SetImmutablePrototype(aCx, aReflector, &succeeded)) {
-          ${failureCode}
-        }
-        MOZ_ASSERT(succeeded,
-                   "Making a fresh reflector instance have an immutable "
-                   "prototype can internally fail, but it should never be "
-                   "unsuccessful");
-        """,
-        failureCode=failureCode)
-
-
-def DeclareProto():
+def DeclareProto(descriptor):
     """
     Declare the canonicalProto and proto we have for our wrapping operation.
     """
-    return dedent(
+    preamble = dedent(
         """
         JS::Handle<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
         if (!canonicalProto) {
           return false;
         }
         JS::Rooted<JSObject*> proto(aCx);
+        """)
+    if descriptor.isMaybeCrossOriginObject():
+        return preamble + dedent(
+            """
+            MOZ_ASSERT(!aGivenProto,
+                       "Shouldn't have constructors on cross-origin objects");
+            // Set proto to canonicalProto to avoid preserving our wrapper if
+            // we don't have to.
+            proto = canonicalProto;
+            """)
+
+    return preamble + dedent(
+        """
         if (aGivenProto) {
           proto = aGivenProto;
           // Unfortunately, while aGivenProto was in the compartment of aCx
           // coming in, we changed compartments to that of "parent" so may need
           // to wrap the proto here.
           if (js::GetContextCompartment(aCx) != js::GetObjectCompartment(proto)) {
             if (!JS_WrapObject(aCx, &proto)) {
               return false;
@@ -3859,17 +3874,16 @@ class CGWrapWithCacheMethod(CGAbstractMe
             JSAutoRealm ar(aCx, global);
             $*{declareProto}
 
             $*{createObject}
 
             aCache->SetWrapper(aReflector);
             $*{unforgeable}
             $*{slots}
-            $*{setImmutablePrototype}
             creator.InitializationSucceeded();
 
             MOZ_ASSERT(aCache->GetWrapperPreserveColor() &&
                        aCache->GetWrapperPreserveColor() == aReflector);
             // If proto != canonicalProto, we have to preserve our wrapper;
             // otherwise we won't be able to properly recreate it later, since
             // we won't know what proto to use.  Note that we don't check
             // aGivenProto here, since it's entirely possible (and even
@@ -3878,23 +3892,21 @@ class CGWrapWithCacheMethod(CGAbstractMe
             if (proto != canonicalProto) {
               PreserveWrapper(aObject);
             }
 
             return true;
             """,
             nativeType=self.descriptor.nativeType,
             assertInheritance=AssertInheritanceChain(self.descriptor),
-            declareProto=DeclareProto(),
+            declareProto=DeclareProto(self.descriptor),
             createObject=CreateBindingJSObject(self.descriptor, self.properties),
             unforgeable=CopyUnforgeablePropertiesToInstance(self.descriptor,
                                                             failureCode),
-            slots=InitMemberSlots(self.descriptor, failureCode),
-            setImmutablePrototype=SetImmutablePrototype(self.descriptor,
-                                                        failureCode))
+            slots=InitMemberSlots(self.descriptor, failureCode))
 
 
 class CGWrapMethod(CGAbstractMethod):
     def __init__(self, descriptor):
         # XXX can we wrap if we don't have an interface prototype object?
         assert descriptor.interface.hasInterfacePrototypeObject()
         args = [Argument('JSContext*', 'aCx'),
                 Argument('T*', 'aObject'),
@@ -3938,28 +3950,25 @@ class CGWrapNonWrapperCacheMethod(CGAbst
             $*{declareProto}
 
             $*{createObject}
 
             $*{unforgeable}
 
             $*{slots}
 
-            $*{setImmutablePrototype}
             creator.InitializationSucceeded();
             return true;
             """,
             assertions=AssertInheritanceChain(self.descriptor),
-            declareProto=DeclareProto(),
+            declareProto=DeclareProto(self.descriptor),
             createObject=CreateBindingJSObject(self.descriptor, self.properties),
             unforgeable=CopyUnforgeablePropertiesToInstance(self.descriptor,
                                                             failureCode),
-            slots=InitMemberSlots(self.descriptor, failureCode),
-            setImmutablePrototype=SetImmutablePrototype(self.descriptor,
-                                                        failureCode))
+            slots=InitMemberSlots(self.descriptor, failureCode))
 
 
 class CGWrapGlobalMethod(CGAbstractMethod):
     """
     Create a wrapper JSObject for a global.  The global must implement
     nsWrapperCache.
 
     properties should be a PropertyArrays instance.
@@ -4216,58 +4225,16 @@ class CGCrossOriginProperties(CGThing):
             #if defined(__clang__)
             #pragma clang diagnostic pop
             #endif
             """,
             attributeSpecs=",\n".join(self.attributeSpecs),
             methodSpecs=",\n".join(self.methodSpecs))
 
 
-class CGIsPermittedMethod(CGAbstractMethod):
-    """
-    crossOriginGetters/Setters/Methods are sets of names of the relevant members.
-    """
-    def __init__(self, descriptor, crossOriginGetters, crossOriginSetters,
-                 crossOriginMethods):
-        self.crossOriginGetters = crossOriginGetters
-        self.crossOriginSetters = crossOriginSetters
-        self.crossOriginMethods = crossOriginMethods
-        args = [Argument("JSFlatString*", "prop"),
-                Argument("char16_t", "propFirstChar"),
-                Argument("bool", "set")]
-        CGAbstractMethod.__init__(self, descriptor, "IsPermitted", "bool", args,
-                                  inline=True)
-
-    def definition_body(self):
-        allNames = self.crossOriginGetters | self.crossOriginSetters | self.crossOriginMethods
-        readwrite = self.crossOriginGetters & self.crossOriginSetters
-        readonly = (self.crossOriginGetters - self.crossOriginSetters) | self.crossOriginMethods
-        writeonly = self.crossOriginSetters - self.crossOriginGetters
-        cases = {}
-        for name in sorted(allNames):
-            cond = 'JS_FlatStringEqualsAscii(prop, "%s")' % name
-            if name in readonly:
-                cond = "!set && %s" % cond
-            elif name in writeonly:
-                cond = "set && %s" % cond
-            else:
-                assert name in readwrite
-            firstLetter = name[0]
-            case = cases.get(firstLetter, CGList([]))
-            case.append(CGGeneric("if (%s) {\n"
-                                  "  return true;\n"
-                                  "}\n" % cond))
-            cases[firstLetter] = case
-        caseList = []
-        for firstLetter in sorted(cases.keys()):
-            caseList.append(CGCase("'%s'" % firstLetter, cases[firstLetter]))
-        switch = CGSwitch("propFirstChar", caseList)
-        return switch.define() + "\nreturn false;\n"
-
-
 class CGCycleCollectionTraverseForOwningUnionMethod(CGAbstractMethod):
     """
     ImplCycleCollectionUnlink for owning union type.
     """
     def __init__(self, type):
         self.type = type
         args = [Argument("nsCycleCollectionTraversalCallback&", "aCallback"),
                 Argument("%s&" % CGUnionStruct.unionTypeName(type, True), "aUnion"),
@@ -11665,16 +11632,31 @@ class CGDOMJSProxyHandler_getOwnPropDesc
         ClassMethod.__init__(self, "getOwnPropDescriptor", "bool", args,
                              virtual=True, override=True, const=True)
         self.descriptor = descriptor
 
     def getBody(self):
         indexedGetter = self.descriptor.operations['IndexedGetter']
         indexedSetter = self.descriptor.operations['IndexedSetter']
 
+        if self.descriptor.isMaybeCrossOriginObject():
+            xrayDecl = dedent(
+                """
+                MOZ_ASSERT(!xpc::WrapperFactory::IsXrayWrapper(proxy));
+                MOZ_ASSERT(IsPlatformObjectSameOrigin(cx, proxy),
+                           "getOwnPropertyDescriptor() and set() should have dealt");
+                MOZ_ASSERT(js::IsObjectInContextCompartment(proxy, cx),
+                           "getOwnPropertyDescriptor() and set() should have dealt");
+
+                """)
+            xrayCheck = ""
+        else:
+            xrayDecl = "bool isXray = xpc::WrapperFactory::IsXrayWrapper(proxy);\n"
+            xrayCheck = "!isXray &&"
+
         if self.descriptor.supportsIndexedProperties():
             readonly = toStringBool(indexedSetter is None)
             fillDescriptor = "FillPropertyDescriptor(desc, proxy, %s);\nreturn true;\n" % readonly
             templateValues = {
                 'jsvalRef': 'desc.value()',
                 'jsvalHandle': 'desc.value()',
                 'obj': 'proxy',
                 'successCode': fillDescriptor
@@ -11739,34 +11721,36 @@ class CGDOMJSProxyHandler_getOwnPropDesc
                             computeCondition=computeCondition,
                             namedGetCode=namedGetCode)
             namedGet += "\n"
         else:
             namedGet = ""
 
         return fill(
             """
-            bool isXray = xpc::WrapperFactory::IsXrayWrapper(proxy);
+            $*{xrayDecl}
             $*{getIndexed}
             JS::Rooted<JSObject*> expando(cx);
-            if (!isXray && (expando = GetExpandoObject(proxy))) {
+            if (${xrayCheck}(expando = GetExpandoObject(proxy))) {
               if (!JS_GetOwnPropertyDescriptorById(cx, expando, id, desc)) {
                 return false;
               }
               if (desc.object()) {
                 // Pretend the property lives on the wrapper.
                 desc.object().set(proxy);
                 return true;
               }
             }
 
             $*{namedGet}
             desc.object().set(nullptr);
             return true;
             """,
+            xrayDecl=xrayDecl,
+            xrayCheck=xrayCheck,
             getIndexed=getIndexed,
             namedGet=namedGet)
 
 
 class CGDOMJSProxyHandler_defineProperty(ClassMethod):
     def __init__(self, descriptor):
         # The usual convention is to name the ObjectOpResult out-parameter
         # `result`, but that name is a bit overloaded around here.
@@ -11843,16 +11827,24 @@ class CGDOMJSProxyHandler_defineProperty
                     $*{presenceChecker}
 
                     if (found) {
                       *defined = true;
                       return opresult.failNoNamedSetter();
                     }
                     """,
                     presenceChecker=CGProxyNamedPresenceChecker(self.descriptor, foundVar="found").define())
+            if self.descriptor.isMaybeCrossOriginObject():
+                set += dedent(
+                    """
+                    MOZ_ASSERT(IsPlatformObjectSameOrigin(cx, proxy),
+                               "Why did the MaybeCrossOriginObject defineProperty override fail?");
+                    MOZ_ASSERT(js::IsObjectInContextCompartment(proxy, cx),
+                               "Why did the MaybeCrossOriginObject defineProperty override fail?");
+                    """)
             set += ("return mozilla::dom::DOMProxyHandler::defineProperty(%s);\n" %
                     ", ".join(a.name for a in self.args))
         return set
 
 
 def getDeleterBody(descriptor, type, foundVar=None):
     """
     type should be "Named" or "Indexed"
@@ -11954,18 +11946,32 @@ class CGDOMJSProxyHandler_delete(ClassMe
 
     def getBody(self):
         delete = dedent("""
             MOZ_ASSERT(!xpc::WrapperFactory::IsXrayWrapper(proxy),
                       "Should not have a XrayWrapper here");
 
             """)
 
+        if self.descriptor.isMaybeCrossOriginObject():
+            delete += dedent(
+                """
+                if (!IsPlatformObjectSameOrigin(cx, proxy)) {
+                  return ReportCrossOriginDenial(cx, id, NS_LITERAL_CSTRING("delete"));
+                }
+
+                // Safe to enter the Realm of proxy now.
+                JSAutoRealm ar(cx, proxy);
+                JS_MarkCrossZoneId(cx, id);
+                """)
+
         indexedBody = getDeleterBody(self.descriptor, "Indexed")
         if indexedBody is not None:
+            # Can't handle cross-origin objects here.
+            assert not self.descriptor.isMaybeCrossOriginObject();
             delete += fill(
                 """
                 uint32_t index = GetArrayIndexFromId(id);
                 if (IsArrayIndex(index)) {
                   bool deleteSucceeded;
                   $*{indexedBody}
                   return deleteSucceeded ? opresult.succeed() : opresult.failCantDelete();
                 }
@@ -12033,16 +12039,44 @@ class CGDOMJSProxyHandler_ownPropNames(C
                 Argument('JS::Handle<JSObject*>', 'proxy'),
                 Argument('unsigned', 'flags'),
                 Argument('JS::AutoIdVector&', 'props')]
         ClassMethod.__init__(self, "ownPropNames", "bool", args,
                              virtual=True, override=True, const=True)
         self.descriptor = descriptor
 
     def getBody(self):
+        if self.descriptor.isMaybeCrossOriginObject():
+            xrayDecl = dedent(
+                """
+                MOZ_ASSERT(!xpc::WrapperFactory::IsXrayWrapper(proxy));
+                if (!IsPlatformObjectSameOrigin(cx, proxy)) {
+                  if (!(flags & JSITER_HIDDEN)) {
+                    // There are no enumerable cross-origin props, so we're done.
+                    return true;
+                  }
+
+                  JS::Rooted<JSObject*> holder(cx);
+                  if (!EnsureHolder(cx, proxy, &holder)) {
+                    return false;
+                  }
+
+                  if (!js::GetPropertyKeys(cx, holder, flags, &props)) {
+                    return false;
+                  }
+
+                  return xpc::AppendCrossOriginWhitelistedPropNames(cx, props);
+                }
+
+                """)
+            xrayCheck = ""
+        else:
+            xrayDecl = "bool isXray = xpc::WrapperFactory::IsXrayWrapper(proxy);\n"
+            xrayCheck = "!isXray &&"
+
         # Per spec, we do indices, then named props, then everything else.
         if self.descriptor.supportsIndexedProperties():
             if self.descriptor.lengthNeedsCallerType():
                 callerType = callerTypeGetterForDescriptor(self.descriptor)
             else:
                 callerType = ""
             addIndices = fill(
                 """
@@ -12082,45 +12116,86 @@ class CGDOMJSProxyHandler_ownPropNames(C
                 shadow=shadow)
             if not self.descriptor.namedPropertiesEnumerable:
                 addNames = CGIfWrapper(CGGeneric(addNames),
                                        "flags & JSITER_HIDDEN").define()
             addNames = "\n" + addNames
         else:
             addNames = ""
 
+        addExpandoProps = fill(
+            """
+            JS::Rooted<JSObject*> expando(cx);
+            if (${xrayCheck}(expando = DOMProxyHandler::GetExpandoObject(proxy)) &&
+                !js::GetPropertyKeys(cx, expando, flags, &props)) {
+              return false;
+            }
+            """,
+            xrayCheck=xrayCheck)
+            
+        if self.descriptor.isMaybeCrossOriginObject():
+            # We need to enter our compartment (which we might not be
+            # in right now) to get the expando props.
+            addExpandoProps = fill(
+                """
+                {  // Scope for accessing the expando.
+                  // Safe to enter our compartment, because IsPlatformObjectSameOrigin tested true.
+                  JSAutoRealm ar(cx, proxy);
+                  $*{addExpandoProps}
+                }
+                for (auto& id : props) {
+                  JS_MarkCrossZoneId(cx, id);
+                }
+                """,
+                addExpandoProps=addExpandoProps)
+
         return fill(
             """
-            bool isXray = xpc::WrapperFactory::IsXrayWrapper(proxy);
+            $*{xrayDecl}
             $*{addIndices}
             $*{addNames}
 
-            JS::Rooted<JSObject*> expando(cx);
-            if (!isXray && (expando = DOMProxyHandler::GetExpandoObject(proxy)) &&
-                !js::GetPropertyKeys(cx, expando, flags, &props)) {
-              return false;
-            }
+            $*{addExpandoProps}
 
             return true;
             """,
+            xrayDecl=xrayDecl,
             addIndices=addIndices,
-            addNames=addNames)
+            addNames=addNames,
+            addExpandoProps=addExpandoProps)
 
 
 class CGDOMJSProxyHandler_hasOwn(ClassMethod):
     def __init__(self, descriptor):
         args = [Argument('JSContext*', 'cx'),
                 Argument('JS::Handle<JSObject*>', 'proxy'),
                 Argument('JS::Handle<jsid>', 'id'),
                 Argument('bool*', 'bp')]
         ClassMethod.__init__(self, "hasOwn", "bool", args,
                              virtual=True, override=True, const=True)
         self.descriptor = descriptor
 
     def getBody(self):
+        if self.descriptor.isMaybeCrossOriginObject():
+            maybeCrossOrigin = dedent(
+                """
+                if (!IsPlatformObjectSameOrigin(cx, proxy)) {
+                  // Just hand this off to BaseProxyHandler to do the slow-path thing.
+                  // The BaseProxyHandler code is OK with this happening without entering the
+                  // compartment of "proxy", which is important to get the right answers.
+                  return js::BaseProxyHandler::hasOwn(cx, proxy, id, bp);
+                }
+
+                // Now safe to enter the Realm of proxy and do the rest of the work there.
+                JSAutoRealm ar(cx, proxy);
+                JS_MarkCrossZoneId(cx, id);
+                """)
+        else:
+            maybeCrossOrigin = ""
+
         if self.descriptor.supportsIndexedProperties():
             indexed = fill(
                 """
                 uint32_t index = GetArrayIndexFromId(id);
                 if (IsArrayIndex(index)) {
                   bool found = false;
                   $*{presenceChecker}
 
@@ -12162,69 +12237,120 @@ class CGDOMJSProxyHandler_hasOwn(ClassMe
                 named += "\n"
         else:
             named = "*bp = false;\n"
 
         return fill(
             """
             MOZ_ASSERT(!xpc::WrapperFactory::IsXrayWrapper(proxy),
                       "Should not have a XrayWrapper here");
-
+            $*{maybeCrossOrigin}
             $*{indexed}
 
             JS::Rooted<JSObject*> expando(cx, GetExpandoObject(proxy));
             if (expando) {
               bool b = true;
               bool ok = JS_HasPropertyById(cx, expando, id, &b);
               *bp = !!b;
               if (!ok || *bp) {
                 return ok;
               }
             }
 
             $*{named}
             return true;
             """,
+            maybeCrossOrigin=maybeCrossOrigin,
             indexed=indexed,
             named=named)
 
 
 class CGDOMJSProxyHandler_get(ClassMethod):
     def __init__(self, descriptor):
         args = [Argument('JSContext*', 'cx'),
                 Argument('JS::Handle<JSObject*>', 'proxy'),
                 Argument('JS::Handle<JS::Value>', 'receiver'),
                 Argument('JS::Handle<jsid>', 'id'),
                 Argument('JS::MutableHandle<JS::Value>', 'vp')]
         ClassMethod.__init__(self, "get", "bool", args,
                              virtual=True, override=True, const=True)
         self.descriptor = descriptor
 
     def getBody(self):
+        if self.descriptor.isMaybeCrossOriginObject():
+            maybeCrossOriginGet = dedent(
+                """
+                if (!IsPlatformObjectSameOrigin(cx, proxy)) {
+                  return CrossOriginGet(cx, proxy, receiver, id, vp);
+                }
+
+                """)
+        else:
+            maybeCrossOriginGet = ""
+
         getUnforgeableOrExpando = dedent("""
             { // Scope for expando
               JS::Rooted<JSObject*> expando(cx, DOMProxyHandler::GetExpandoObject(proxy));
               if (expando) {
-                bool hasProp;
-                if (!JS_HasPropertyById(cx, expando, id, &hasProp)) {
+                if (!JS_HasPropertyById(cx, expando, id, &expandoHasProp)) {
                   return false;
                 }
 
-                if (hasProp) {
+                if (expandoHasProp) {
                   // Forward the get to the expando object, but our receiver is whatever our
                   // receiver is.
-                  return JS_ForwardGetPropertyTo(cx, expando, id, receiver, vp);
+                  if (!JS_ForwardGetPropertyTo(cx, expando, id, rootedReceiver, vp)) {
+                    return false;
+                  }
                 }
               }
             }
             """)
 
+        if self.descriptor.isMaybeCrossOriginObject():
+            getUnforgeableOrExpando = fill(
+                """
+                { // Scope for the JSAutoRealm accessing expando
+                  JSAutoRealm ar(cx, proxy);
+                  if (!MaybeWrapValue(cx, &rootedReceiver)) {
+                    return false;
+                  }
+                  JS_MarkCrossZoneId(cx, id);
+
+                  $*{getUnforgeableOrExpando}
+                }
+                if (expandoHasProp) {
+                  return MaybeWrapValue(cx, vp);
+                }
+                """,
+                getUnforgeableOrExpando=getUnforgeableOrExpando)
+        else:
+            getUnforgeableOrExpando = fill(
+                """
+                $*{getUnforgeableOrExpando}
+
+                if (expandoHasProp) {
+                  return true;
+                }
+                """,
+                getUnforgeableOrExpando=getUnforgeableOrExpando)
+
+        getUnforgeableOrExpando = fill(
+            """
+            bool expandoHasProp = false;
+            $*{getUnforgeableOrExpando}
+            """,
+            getUnforgeableOrExpando=getUnforgeableOrExpando)
+
         templateValues = {'jsvalRef': 'vp', 'jsvalHandle': 'vp', 'obj': 'proxy'}
 
         if self.descriptor.supportsIndexedProperties():
+            # We can't handle this for cross-origin objects
+            assert not self.descriptor.isMaybeCrossOriginObject()
+
             getIndexedOrExpando = fill(
                 """
                 uint32_t index = GetArrayIndexFromId(id);
                 if (IsArrayIndex(index)) {
                   $*{callGetter}
                   // Even if we don't have this index, we don't forward the
                   // get on to our expando object.
                 } else {
@@ -12232,50 +12358,84 @@ class CGDOMJSProxyHandler_get(ClassMetho
                 }
                 """,
                 callGetter=CGProxyIndexedGetter(self.descriptor, templateValues).define(),
                 getUnforgeableOrExpando=getUnforgeableOrExpando)
         else:
             getIndexedOrExpando = getUnforgeableOrExpando
 
         if self.descriptor.supportsNamedProperties():
+            # We can't handle this for cross-origin objects
+            assert not self.descriptor.isMaybeCrossOriginObject()
+
             getNamed = CGProxyNamedGetter(self.descriptor, templateValues)
             if self.descriptor.supportsIndexedProperties():
                 getNamed = CGIfWrapper(getNamed, "!IsArrayIndex(index)")
             getNamed = getNamed.define() + "\n"
         else:
             getNamed = ""
 
         getOnPrototype = dedent("""
-            bool foundOnPrototype;
-            if (!GetPropertyOnPrototype(cx, proxy, receiver, id, &foundOnPrototype, vp)) {
+            if (!GetPropertyOnPrototype(cx, proxy, rootedReceiver, id, &foundOnPrototype, vp)) {
               return false;
             }
 
-            if (foundOnPrototype) {
-              return true;
-            }
-
             """)
+
+        if self.descriptor.isMaybeCrossOriginObject():
+            getOnPrototype = fill(
+                """
+                bool foundOnPrototype;
+                { // Scope for JSAutoRealm
+                  JSAutoRealm ar(cx, proxy);
+                  // We already wrapped rootedReceiver
+                  MOZ_ASSERT_IF(rootedReceiver.isObject(),
+                                js::IsObjectInContextCompartment(&rootedReceiver.toObject(), cx));
+                  JS_MarkCrossZoneId(cx, id);
+                  $*{getOnPrototype}
+                }
+
+                if (foundOnPrototype) {
+                  return MaybeWrapValue(cx, vp);
+                }
+
+                """,
+                getOnPrototype=getOnPrototype)
+        else:
+            getOnPrototype = fill(
+                """
+                bool foundOnPrototype;
+                $*{getOnPrototype}
+                if (foundOnPrototype) {
+                  return true;
+                }
+
+                """,
+                getOnPrototype=getOnPrototype)
+
         if self.descriptor.interface.getExtendedAttribute('OverrideBuiltins'):
             getNamed = getNamed + getOnPrototype
         else:
             getNamed = getOnPrototype + getNamed
 
         return fill(
             """
             MOZ_ASSERT(!xpc::WrapperFactory::IsXrayWrapper(proxy),
                         "Should not have a XrayWrapper here");
 
+            $*{maybeCrossOriginGet}
+            JS::Rooted<JS::Value> rootedReceiver(cx, receiver);
+
             $*{indexedOrExpando}
 
             $*{named}
             vp.setUndefined();
             return true;
             """,
+            maybeCrossOriginGet=maybeCrossOriginGet,
             indexedOrExpando=getIndexedOrExpando,
             named=getNamed)
 
 
 class CGDOMJSProxyHandler_setCustom(ClassMethod):
     def __init__(self, descriptor):
         args = [Argument('JSContext*', 'cx'),
                 Argument('JS::Handle<JSObject*>', 'proxy'),
@@ -12337,17 +12497,33 @@ class CGDOMJSProxyHandler_className(Clas
     def __init__(self, descriptor):
         args = [Argument('JSContext*', 'cx'),
                 Argument('JS::Handle<JSObject*>', 'proxy')]
         ClassMethod.__init__(self, "className", "const char*", args,
                              virtual=True, override=True, const=True)
         self.descriptor = descriptor
 
     def getBody(self):
-        return 'return "%s";\n' % self.descriptor.name
+        if self.descriptor.isMaybeCrossOriginObject():
+            crossOrigin = dedent(
+                """
+                if (!IsPlatformObjectSameOrigin(cx, proxy)) {
+                  return "Object";
+                }
+                
+                """)
+        else:
+            crossOrigin = ""
+        return fill(
+            """
+            $*{crossOrigin}
+            return "${name}";
+            """,
+            crossOrigin=crossOrigin,
+            name=self.descriptor.name)
 
 
 class CGDOMJSProxyHandler_finalizeInBackground(ClassMethod):
     def __init__(self, descriptor):
         args = [Argument('const JS::Value&', 'priv')]
         ClassMethod.__init__(self, "finalizeInBackground", "bool", args,
                              virtual=True, override=True, const=True)
         self.descriptor = descriptor
@@ -12452,33 +12628,16 @@ class CGDOMJSProxyHandler_getInstance(Cl
 
     def getBody(self):
         return dedent("""
             static const DOMProxyHandler instance;
             return &instance;
             """)
 
 
-class CGDOMJSProxyHandler_getPrototypeIfOrdinary(ClassMethod):
-    def __init__(self):
-        args = [Argument('JSContext*', 'cx'),
-                Argument('JS::Handle<JSObject*>', 'proxy'),
-                Argument('bool*', 'isOrdinary'),
-                Argument('JS::MutableHandle<JSObject*>', 'proto')]
-
-        ClassMethod.__init__(self, "getPrototypeIfOrdinary", "bool", args,
-                             virtual=True, override=True, const=True)
-
-    def getBody(self):
-        return dedent("""
-            *isOrdinary = false;
-            return true;
-            """)
-
-
 class CGDOMJSProxyHandler_call(ClassMethod):
     def __init__(self):
         args = [Argument('JSContext*', 'cx'),
                 Argument('JS::Handle<JSObject*>', 'proxy'),
                 Argument('const JS::CallArgs&', 'args')]
 
         ClassMethod.__init__(self, "call", "bool", args, virtual=True, override=True, const=True)
 
@@ -12513,21 +12672,186 @@ class CGDOMJSProxyHandler_canNurseryAllo
                              virtual=True, override=True, const=True)
 
     def getBody(self):
         return dedent("""
             return true;
         """)
 
 
+class CGDOMJSProxyHandler_getOwnPropertyDescriptor(ClassMethod):
+    """
+    Implementation of getOwnPropertyDescriptor.  We only use this for
+    cross-origin objects. 
+    """
+    def __init__(self, descriptor):
+        assert descriptor.isMaybeCrossOriginObject()
+
+        args = [Argument('JSContext*', 'cx'),
+                Argument('JS::Handle<JSObject*>', 'proxy'),
+                Argument('JS::Handle<jsid>', 'id'),
+                Argument('JS::MutableHandle<JS::PropertyDescriptor>', 'desc')]
+        ClassMethod.__init__(self, "getOwnPropertyDescriptor", "bool", args,
+                             virtual=True, override=True, const=True)
+        self.descriptor = descriptor
+
+    def getBody(self):
+        return dedent(
+            """
+            // Implementation of <https://html.spec.whatwg.org/multipage/history.html#location-getownproperty>.
+            MOZ_ASSERT(!xpc::WrapperFactory::IsXrayWrapper(proxy));
+
+            // Step 1.
+            if (IsPlatformObjectSameOrigin(cx, proxy)) {
+              { // Scope so we can wrap our PropertyDescriptor back into
+                // the caller compartment.
+                // Enter the Realm of "proxy" so we can work with it.
+                JSAutoRealm ar(cx, proxy);
+
+                JS_MarkCrossZoneId(cx, id);
+
+                // The spec messes around with configurability of the returned
+                // descriptor here, but it's not clear what should actually happen
+                // here.  See <https://github.com/whatwg/html/issues/4157>.  For
+                // now, keep our old behavior and don't do any magic.
+                if (!dom::DOMProxyHandler::getOwnPropertyDescriptor(cx, proxy, id, desc)) {
+                  return false;
+                }
+              }
+              return JS_WrapPropertyDescriptor(cx, desc);
+            }
+
+            // Step 2.
+            if (!CrossOriginGetOwnPropertyHelper(cx, proxy, id, desc)) {
+              return false;
+            }
+
+            // Step 3.
+            if (desc.object()) {
+              return true;
+            }
+
+            // And step 4.
+            return CrossOriginPropertyFallback(cx, proxy, id, desc);
+            """)
+
+
+class CGDOMJSProxyHandler_getSameOriginPrototype(ClassMethod):
+    """
+    Implementation of getSameOriginPrototype.  We only use this for
+    cross-origin objects. 
+    """
+    def __init__(self, descriptor):
+        assert descriptor.isMaybeCrossOriginObject()
+
+        args = [Argument('JSContext*', 'cx')]
+        ClassMethod.__init__(self, "getSameOriginPrototype", "JSObject*", args,
+                             virtual=True, override=True, const=True)
+        self.descriptor = descriptor
+
+    def getBody(self):
+        return dedent(
+            """
+            return GetProtoObjectHandle(cx);
+            """)
+
+
+class CGDOMJSProxyHandler_definePropertySameOrigin(ClassMethod):
+    """
+    Implementation of definePropertySameOrigin.  We only use this for
+    cross-origin objects. 
+    """
+    def __init__(self, descriptor):
+        assert descriptor.isMaybeCrossOriginObject()
+
+        args = [Argument('JSContext*', 'cx'),
+                Argument('JS::Handle<JSObject*>', 'proxy'),
+                Argument('JS::Handle<jsid>', 'id'),
+                Argument('JS::Handle<JS::PropertyDescriptor>', 'desc'),
+                Argument('JS::ObjectOpResult&', 'result')]
+        ClassMethod.__init__(self, "definePropertySameOrigin", "bool", args,
+                             virtual=True, override=True, const=True)
+        self.descriptor = descriptor
+
+    def getBody(self):
+        return dedent(
+            """
+            return dom::DOMProxyHandler::defineProperty(cx, proxy, id, desc, result);
+            """)
+
+
+class CGDOMJSProxyHandler_set(ClassMethod):
+    """
+    Implementation of set().  We only use this for cross-origin objects. 
+    """
+    def __init__(self, descriptor):
+        assert descriptor.isMaybeCrossOriginObject()
+
+        args = [Argument('JSContext*', 'cx'),
+                Argument('JS::Handle<JSObject*>', 'proxy'),
+                Argument('JS::Handle<jsid>', 'id'),
+                Argument('JS::Handle<JS::Value>', 'v'),
+                Argument('JS::Handle<JS::Value>', 'receiver'),
+                Argument('JS::ObjectOpResult&', 'result')]
+        ClassMethod.__init__(self, "set", "bool", args,
+                             virtual=True, override=True, const=True)
+        self.descriptor = descriptor
+
+    def getBody(self):
+        return dedent(
+            """
+            if (!IsPlatformObjectSameOrigin(cx, proxy)) {
+              return CrossOriginSet(cx, proxy, id, v, receiver, result);
+            }
+
+            // Safe to enter the Realm of proxy now, since it's same-origin with us.
+            JSAutoRealm ar(cx, proxy);
+            JS::Rooted<JS::Value> wrappedReceiver(cx, receiver);
+            if (!MaybeWrapValue(cx, &wrappedReceiver)) {
+              return false;
+            }
+
+            JS::Rooted<JS::Value> wrappedValue(cx, v);
+            if (!MaybeWrapValue(cx, &wrappedValue)) {
+              return false;
+            }
+
+            JS_MarkCrossZoneId(cx, id);
+            
+            return dom::DOMProxyHandler::set(cx, proxy, id, wrappedValue, wrappedReceiver, result);
+            """)
+
+
+class CGDOMJSProxyHandler_EnsureHolder(ClassMethod):
+    """
+    Implementation of set().  We only use this for cross-origin objects. 
+    """
+    def __init__(self, descriptor):
+        args = [Argument('JSContext*', 'cx'),
+                Argument('JS::Handle<JSObject*>', 'proxy'),
+                Argument('JS::MutableHandle<JSObject*>', 'holder')]
+        ClassMethod.__init__(self, "EnsureHolder", "bool", args,
+                             virtual=True, override=True, const=True)
+        self.descriptor = descriptor
+
+    def getBody(self):
+        return dedent(
+            """
+            // Our holder slot is our last slot.
+            return EnsureHolder(cx, proxy,
+                                JSCLASS_RESERVED_SLOTS(js::GetObjectClass(proxy)) - 1,
+                                sCrossOriginAttributes, sCrossOriginMethods, holder);
+            """)
+
+
 class CGDOMJSProxyHandler(CGClass):
     def __init__(self, descriptor):
         assert (descriptor.supportsIndexedProperties() or
                 descriptor.supportsNamedProperties() or
-                descriptor.hasNonOrdinaryGetPrototypeOf())
+                descriptor.isMaybeCrossOriginObject())
         methods = [CGDOMJSProxyHandler_getOwnPropDescriptor(descriptor),
                    CGDOMJSProxyHandler_defineProperty(descriptor),
                    ClassUsingDeclaration("mozilla::dom::DOMProxyHandler",
                                          "defineProperty"),
                    CGDOMJSProxyHandler_ownPropNames(descriptor),
                    CGDOMJSProxyHandler_hasOwn(descriptor),
                    CGDOMJSProxyHandler_get(descriptor),
                    CGDOMJSProxyHandler_className(descriptor),
@@ -12544,31 +12868,43 @@ class CGDOMJSProxyHandler(CGClass):
         ]
 
         if descriptor.supportsIndexedProperties():
             methods.append(CGDOMJSProxyHandler_getElements(descriptor))
         if (descriptor.operations['IndexedSetter'] is not None or
             (descriptor.operations['NamedSetter'] is not None and
              descriptor.interface.getExtendedAttribute('OverrideBuiltins'))):
             methods.append(CGDOMJSProxyHandler_setCustom(descriptor))
-        if descriptor.hasNonOrdinaryGetPrototypeOf():
-            methods.append(CGDOMJSProxyHandler_getPrototypeIfOrdinary())
         if descriptor.operations['LegacyCaller']:
             methods.append(CGDOMJSProxyHandler_call())
             methods.append(CGDOMJSProxyHandler_isCallable())
         if descriptor.interface.hasProbablyShortLivingWrapper():
             if not descriptor.wrapperCache:
                 raise TypeError("Need a wrapper cache to support nursery "
                                 "allocation of DOM objects")
             methods.append(CGDOMJSProxyHandler_canNurseryAllocate())
         if descriptor.wrapperCache:
             methods.append(CGDOMJSProxyHandler_objectMoved(descriptor))
 
+        if descriptor.isMaybeCrossOriginObject():
+            methods.extend([
+                CGDOMJSProxyHandler_getOwnPropertyDescriptor(descriptor),
+                CGDOMJSProxyHandler_getSameOriginPrototype(descriptor),
+                CGDOMJSProxyHandler_definePropertySameOrigin(descriptor),
+                CGDOMJSProxyHandler_set(descriptor),
+                CGDOMJSProxyHandler_EnsureHolder(descriptor),
+                ClassUsingDeclaration("MaybeCrossOriginObjectMixins",
+                                      "EnsureHolder")
+                ])
+
         if descriptor.interface.getExtendedAttribute('OverrideBuiltins'):
+            assert not descriptor.isMaybeCrossOriginObject()
             parentClass = 'ShadowingDOMProxyHandler'
+        elif descriptor.isMaybeCrossOriginObject():
+            parentClass = 'MaybeCrossOriginObject<mozilla::dom::DOMProxyHandler>'
         else:
             parentClass = 'mozilla::dom::DOMProxyHandler'
 
         CGClass.__init__(self, 'DOMProxyHandler',
                          bases=[ClassBase(parentClass)],
                          constructors=constructors,
                          methods=methods)
 
@@ -12654,17 +12990,17 @@ class CGDescriptor(CGThing):
                                   descriptor.nativeType))
         parent = descriptor.interface.parent
         if parent:
             cgThings.append(CGGeneric("static_assert(IsRefcounted<NativeType>::value == IsRefcounted<%s::NativeType>::value,\n"
                                       "              \"Can't inherit from an interface with a different ownership model.\");\n" %
                                       toBindingNamespace(descriptor.parentPrototypeName)))
 
         defaultToJSONMethod = None
-        crossOriginMethods, crossOriginGetters, crossOriginSetters = set(), set(), set()
+        needCrossOriginPropertyArrays = False
         unscopableNames = list()
         for n in descriptor.interface.namedConstructors:
             cgThings.append(CGClassConstructor(descriptor, n,
                                                NamedConstructorName(n)))
         for m in descriptor.interface.members:
             if m.isMethod() and m.identifier.name == 'QueryInterface':
                 continue
 
@@ -12684,17 +13020,17 @@ class CGDescriptor(CGThing):
                             cgThings.append(CGStaticMethodJitinfo(m))
                     elif descriptor.interface.hasInterfacePrototypeObject():
                         specializedMethod = CGSpecializedMethod(descriptor, m)
                         cgThings.append(specializedMethod)
                         if m.returnsPromise():
                             cgThings.append(CGMethodPromiseWrapper(descriptor, specializedMethod))
                         cgThings.append(CGMemberJITInfo(descriptor, m))
                         if props.isCrossOriginMethod:
-                            crossOriginMethods.add(m.identifier.name)
+                            needCrossOriginPropertyArrays = True
             # If we've hit the maplike/setlike member itself, go ahead and
             # generate its convenience functions.
             elif m.isMaplikeOrSetlike():
                 cgThings.append(CGMaplikeOrSetlikeHelperGenerator(descriptor, m))
             elif m.isAttr():
                 if m.stringifier:
                     raise TypeError("Stringifier attributes not supported yet. "
                                     "See bug 824857.\n"
@@ -12708,29 +13044,29 @@ class CGDescriptor(CGThing):
                 elif descriptor.interface.hasInterfacePrototypeObject():
                     if isNonExposedNavigatorObjectGetter(m, descriptor):
                         continue
                     specializedGetter = CGSpecializedGetter(descriptor, m)
                     cgThings.append(specializedGetter)
                     if m.type.isPromise():
                         cgThings.append(CGGetterPromiseWrapper(descriptor, specializedGetter))
                     if props.isCrossOriginGetter:
-                        crossOriginGetters.add(m.identifier.name)
+                        needCrossOriginPropertyArrays = True
                 if not m.readonly:
                     if m.isStatic():
                         assert descriptor.interface.hasInterfaceObject()
                         cgThings.append(CGStaticSetter(descriptor, m))
                     elif descriptor.interface.hasInterfacePrototypeObject():
                         cgThings.append(CGSpecializedSetter(descriptor, m))
                         if props.isCrossOriginSetter:
-                            crossOriginSetters.add(m.identifier.name)
+                            needCrossOriginPropertyArrays = True
                 elif m.getExtendedAttribute("PutForwards"):
                     cgThings.append(CGSpecializedForwardingSetter(descriptor, m))
                     if props.isCrossOriginSetter:
-                        crossOriginSetters.add(m.identifier.name)
+                        needCrossOriginPropertyArrays = True
                 elif m.getExtendedAttribute("Replaceable"):
                     cgThings.append(CGSpecializedReplaceableSetter(descriptor, m))
                 elif m.getExtendedAttribute("LenientSetter"):
                     cgThings.append(CGSpecializedLenientSetter(descriptor, m))
                 if (not m.isStatic() and
                     descriptor.interface.hasInterfacePrototypeObject()):
                     cgThings.append(CGMemberJITInfo(descriptor, m))
             if m.isConst() and m.type.isPrimitive():
@@ -12826,18 +13162,19 @@ class CGDescriptor(CGThing):
             else:
                 cgThings.append(CGWrapNonWrapperCacheMethod(descriptor,
                                                             properties))
 
         # Set up our Xray callbacks as needed.  This needs to come
         # after we have our DOMProxyHandler defined.
         if descriptor.wantsXrays:
             if descriptor.concrete and descriptor.proxy:
-                cgThings.append(CGResolveOwnProperty(descriptor))
-                cgThings.append(CGEnumerateOwnProperties(descriptor))
+                if not descriptor.isMaybeCrossOriginObject():
+                    cgThings.append(CGResolveOwnProperty(descriptor))
+                    cgThings.append(CGEnumerateOwnProperties(descriptor))
                 if descriptor.needsXrayNamedDeleterHook():
                     cgThings.append(CGDeleteNamedProperty(descriptor))
             elif descriptor.needsXrayResolveHooks():
                 cgThings.append(CGResolveOwnPropertyViaResolve(descriptor))
                 cgThings.append(CGEnumerateOwnPropertiesViaGetOwnPropertyNames(descriptor))
             if descriptor.wantsXrayExpandoClass:
                 cgThings.append(CGXrayExpandoJSClass(descriptor))
 
@@ -12871,23 +13208,19 @@ class CGDescriptor(CGThing):
         if descriptor.interface.hasInterfacePrototypeObject():
             cgThings.append(CGGetProtoObjectHandleMethod(descriptor))
             if descriptor.interface.hasChildInterfaces():
                 cgThings.append(CGGetProtoObjectMethod(descriptor))
         if descriptor.interface.hasInterfaceObject():
             cgThings.append(CGGetConstructorObjectHandleMethod(descriptor))
             cgThings.append(CGGetConstructorObjectMethod(descriptor))
 
-        # See whether we need we need to generate an IsPermitted method
-        if crossOriginGetters or crossOriginSetters or crossOriginMethods:
+        # See whether we need to generate cross-origin property arrays.
+        if needCrossOriginPropertyArrays:
             cgThings.append(CGCrossOriginProperties(descriptor))
-            cgThings.append(CGIsPermittedMethod(descriptor,
-                                                crossOriginGetters,
-                                                crossOriginSetters,
-                                                crossOriginMethods))
 
         cgThings = CGList((CGIndenter(t, declareOnly=True) for t in cgThings), "\n")
         cgThings = CGWrapper(cgThings, pre='\n', post='\n')
         self.cgRoot = CGWrapper(CGNamespace(toBindingNamespace(descriptor.name),
                                             cgThings),
                                 post='\n')
 
     def declare(self):
@@ -14201,16 +14534,20 @@ class CGBindingRoot(CGThing):
             return any(m.getExtendedAttribute("Deprecated") for m in iface.members + [iface])
 
         bindingHeaders["mozilla/dom/Document.h"] = any(
             descriptorDeprecated(d) for d in descriptors)
         bindingHeaders["mozilla/Preferences.h"] = any(
             descriptorRequiresPreferences(d) for d in descriptors)
         bindingHeaders["mozilla/dom/DOMJSProxyHandler.h"] = any(
             d.concrete and d.proxy for d in descriptors)
+        hasCrossOriginObjects = any(
+            d.concrete and d.isMaybeCrossOriginObject() for d in descriptors)
+        bindingHeaders["mozilla/dom/MaybeCrossOriginObject.h"] = hasCrossOriginObjects
+        bindingHeaders["AccessCheck.h"] = hasCrossOriginObjects
         hasCEReactions = any(d.hasCEReactions() for d in descriptors)
         bindingHeaders["mozilla/dom/CustomElementRegistry.h"] = hasCEReactions
         bindingHeaders["mozilla/dom/DocGroup.h"] = hasCEReactions
 
         def descriptorHasChromeOnly(desc):
             ctor = desc.interface.ctor()
 
             return (any(isChromeOnly(a) or needsContainsHack(a) or
--- a/dom/bindings/Configuration.py
+++ b/dom/bindings/Configuration.py
@@ -437,33 +437,42 @@ class Descriptor(DescriptorProvider):
             for m in self.interface.members:
                 if m.isMethod() and m.isStringifier():
                     addOperation('Stringifier', m)
                 if m.isMethod() and m.isDefaultToJSON():
                     self.hasDefaultToJSON = True
 
         if self.concrete:
             self.proxy = False
+            self.hasCrossOriginMembers = False
             iface = self.interface
             for m in iface.members:
                 # Don't worry about inheriting legacycallers either: in
                 # practice these are on most-derived prototypes.
                 if m.isMethod() and m.isLegacycaller():
                     if not m.isIdentifierLess():
                         raise TypeError("We don't support legacycaller with "
                                         "identifier.\n%s" % m.location)
                     if len(m.signatures()) != 1:
                         raise TypeError("We don't support overloaded "
                                         "legacycaller.\n%s" % m.location)
                     addOperation('LegacyCaller', m)
             while iface:
                 for m in iface.members:
+                    if (m.isAttr() and
+                        (m.getExtendedAttribute("CrossOriginReadable") or
+                         m.getExtendedAttribute("CrossOriginWritable"))):
+                        self.hasCrossOriginMembers = True
+
                     if not m.isMethod():
                         continue
 
+                    if m.getExtendedAttribute("CrossOriginCallable"):
+                        self.hasCrossOriginMembers = True
+
                     def addIndexedOrNamedOperation(operation, m):
                         if m.isIndexed():
                             operation = 'Indexed' + operation
                         else:
                             assert m.isNamed()
                             operation = 'Named' + operation
                         addOperation(operation, m)
 
@@ -479,19 +488,29 @@ class Descriptor(DescriptorProvider):
                                         (iface, iface.location))
 
                 iface.setUserData('hasConcreteDescendant', True)
                 iface = iface.parent
 
             self.proxy = (self.supportsIndexedProperties() or
                           (self.supportsNamedProperties() and
                            not self.hasNamedPropertiesObject) or
-                          self.hasNonOrdinaryGetPrototypeOf())
+                          self.isMaybeCrossOriginObject())
 
             if self.proxy:
+                if (self.isMaybeCrossOriginObject() and
+                    (self.supportsIndexedProperties() or
+                     self.supportsNamedProperties())):
+                    raise TypeError("We don't support named or indexed "
+                                    "properties on maybe-cross-origin objects. "
+                                    "This lets us assume that their proxy "
+                                    "hooks are never called via Xrays.  "
+                                    "Fix %s.\n%s" %
+                                    (self.interface, self.interface.location))
+                    
                 if (not self.operations['IndexedGetter'] and
                     (self.operations['IndexedSetter'] or
                      self.operations['IndexedDeleter'])):
                     raise SyntaxError("%s supports indexed properties but does "
                                       "not have an indexed getter.\n%s" %
                                       (self.interface, self.interface.location))
                 if (not self.operations['NamedGetter'] and
                     (self.operations['NamedSetter'] or
@@ -703,18 +722,20 @@ class Descriptor(DescriptorProvider):
         Determine whether our GetSupportedNames call needs a caller type.  The
         idea is that if your named getter needs a caller type, then so does
         GetSupportedNames.
         """
         assert self.supportsNamedProperties()
         namedGetter = self.operations['NamedGetter']
         return namedGetter.getExtendedAttribute("NeedsCallerType")
 
-    def hasNonOrdinaryGetPrototypeOf(self):
-        return self.interface.getExtendedAttribute("NonOrdinaryGetPrototypeOf")
+    def isMaybeCrossOriginObject(self):
+        # If we're isGlobal and have cross-origin members, we're a Window, and
+        # that's not a cross-origin object.  The WindowProxy is.
+        return self.hasCrossOriginMembers and not self.isGlobal()
 
     def needsHeaderInclude(self):
         """
         An interface doesn't need a header file if it is not concrete, not
         pref-controlled, has no prototype object, has no static methods or
         attributes and has no parent.  The parent matters because we assert
         things about refcounting that depend on the actual underlying type if we
         have a parent.
--- a/dom/bindings/RemoteObjectProxy.cpp
+++ b/dom/bindings/RemoteObjectProxy.cpp
@@ -15,22 +15,22 @@ namespace dom {
 // JSObject::swap can swap it with CrossCompartmentWrappers without requiring
 // malloc.
 const js::Class RemoteObjectProxyClass =
     PROXY_CLASS_DEF("Proxy", JSCLASS_HAS_RESERVED_SLOTS(2));
 
 bool RemoteObjectProxyBase::getOwnPropertyDescriptor(
     JSContext* aCx, JS::Handle<JSObject*> aProxy, JS::Handle<jsid> aId,
     JS::MutableHandle<JS::PropertyDescriptor> aDesc) const {
-  bool ok = getOwnPropertyDescriptorInternal(aCx, aProxy, aId, aDesc);
+  bool ok = CrossOriginGetOwnPropertyHelper(aCx, aProxy, aId, aDesc);
   if (!ok || aDesc.object()) {
     return ok;
   }
 
-  return getOwnPropertyDescriptorTail(aCx, aProxy, aId, aDesc);
+  return CrossOriginPropertyFallback(aCx, aProxy, aId, aDesc);
 }
 
 bool RemoteObjectProxyBase::defineProperty(
     JSContext* aCx, JS::Handle<JSObject*> aProxy, JS::Handle<jsid> aId,
     JS::Handle<JS::PropertyDescriptor> aDesc,
     JS::ObjectOpResult& aResult) const {
   // https://html.spec.whatwg.org/multipage/browsers.html#windowproxy-defineownproperty
   // step 3 and
@@ -132,56 +132,25 @@ bool RemoteObjectProxyBase::isExtensible
   *aExtensible = true;
   return true;
 }
 
 bool RemoteObjectProxyBase::get(JSContext* aCx, JS::Handle<JSObject*> aProxy,
                                 JS::Handle<JS::Value> aReceiver,
                                 JS::Handle<jsid> aId,
                                 JS::MutableHandle<JS::Value> aVp) const {
-  Rooted<PropertyDescriptor> desc(aCx);
-  if (!getOwnPropertyDescriptor(aCx, aProxy, aId, &desc)) {
-    return false;
-  }
-
-  MOZ_ASSERT(desc.object());
-
-  if (desc.isDataDescriptor()) {
-    aVp.set(desc.value());
-    return true;
-  }
-
-  JS::Rooted<JSObject*> getter(aCx);
-  if (!desc.hasGetterObject() || !(getter = desc.getterObject())) {
-    return ReportCrossOriginDenial(aCx, aId, NS_LITERAL_CSTRING("get"));
-  }
-
-  return JS::Call(aCx, aReceiver, getter, JS::HandleValueArray::empty(), aVp);
+  return CrossOriginGet(aCx, aProxy, aReceiver, aId, aVp);
 }
 
 bool RemoteObjectProxyBase::set(JSContext* aCx, JS::Handle<JSObject*> aProxy,
                                 JS::Handle<jsid> aId,
                                 JS::Handle<JS::Value> aValue,
                                 JS::Handle<JS::Value> aReceiver,
                                 JS::ObjectOpResult& aResult) const {
-  Rooted<PropertyDescriptor> desc(aCx);
-  if (!getOwnPropertyDescriptor(aCx, aProxy, aId, &desc)) {
-    return false;
-  }
-
-  MOZ_ASSERT(desc.object());
-
-  JS::Rooted<JSObject*> setter(aCx);
-  if (!desc.hasSetterObject() || !(setter = desc.setterObject())) {
-    return ReportCrossOriginDenial(aCx, aId, NS_LITERAL_CSTRING("set"));
-  }
-
-  JS::Rooted<JS::Value> rv(aCx);
-  return JS::Call(aCx, aReceiver, setter, JS::HandleValueArray(aValue), &rv) &&
-         aResult.succeed();
+  return CrossOriginSet(aCx, aProxy, aId, aValue, aReceiver, aResult);
 }
 
 bool RemoteObjectProxyBase::hasOwn(JSContext* aCx, JS::Handle<JSObject*> aProxy,
                                    JS::Handle<jsid> aId, bool* aBp) const {
   JS::Rooted<JSObject*> holder(aCx);
   if (!EnsureHolder(aCx, aProxy, &holder) ||
       !JS_AlreadyHasOwnPropertyById(aCx, holder, aId, aBp)) {
     return false;
@@ -203,38 +172,12 @@ bool RemoteObjectProxyBase::getOwnEnumer
 JSObject* RemoteObjectProxyBase::CreateProxyObject(
     JSContext* aCx, void* aNative, const js::Class* aClasp) const {
   js::ProxyOptions options;
   options.setClass(aClasp);
   JS::Rooted<JS::Value> native(aCx, JS::PrivateValue(aNative));
   return js::NewProxyObject(aCx, this, native, nullptr, options);
 }
 
-/* static */
-bool RemoteObjectProxyBase::getOwnPropertyDescriptorTail(
-    JSContext* aCx, JS::Handle<JSObject*> aProxy, JS::Handle<jsid> aId,
-    JS::MutableHandle<JS::PropertyDescriptor> aDesc) {
-  if (xpc::IsCrossOriginWhitelistedProp(aCx, aId)) {
-    // https://html.spec.whatwg.org/multipage/browsers.html#crossorigingetownpropertyhelper-(-o,-p-)
-    // step 3 says to return PropertyDescriptor {
-    //   [[Value]]: undefined, [[Writable]]: false, [[Enumerable]]: false,
-    //   [[Configurable]]: true
-    // }.
-    //
-    aDesc.setDataDescriptor(JS::UndefinedHandleValue, JSPROP_READONLY);
-    aDesc.object().set(aProxy);
-    return true;
-  }
-
-  return ReportCrossOriginDenial(aCx, aId, NS_LITERAL_CSTRING("access"));
-}
-
-/* static */
-bool RemoteObjectProxyBase::ReportCrossOriginDenial(
-    JSContext* aCx, JS::Handle<jsid> aId, const nsACString& aAccessType) {
-  xpc::AccessCheck::reportCrossOriginDenial(aCx, aId, aAccessType);
-  return false;
-}
-
 const char RemoteObjectProxyBase::sCrossOriginProxyFamily = 0;
 
 }  // namespace dom
 }  // namespace mozilla
--- a/dom/bindings/RemoteObjectProxy.h
+++ b/dom/bindings/RemoteObjectProxy.h
@@ -3,28 +3,30 @@
 /* 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_RemoteObjectProxy_h
 #define mozilla_dom_RemoteObjectProxy_h
 
 #include "js/Proxy.h"
+#include "mozilla/dom/MaybeCrossOriginObject.h"
 #include "mozilla/dom/PrototypeList.h"
 #include "xpcpublic.h"
 
 namespace mozilla {
 namespace dom {
 
 /**
  * Base class for RemoteObjectProxy. Implements the pieces of the handler that
  * don't depend on properties/methods of the specific WebIDL interface that this
  * proxy implements.
  */
-class RemoteObjectProxyBase : public js::BaseProxyHandler {
+class RemoteObjectProxyBase : public js::BaseProxyHandler,
+                              public MaybeCrossOriginObjectMixins {
  protected:
   explicit constexpr RemoteObjectProxyBase(prototypes::ID aPrototypeID)
       : BaseProxyHandler(&sCrossOriginProxyFamily, false),
         mPrototypeID(aPrototypeID) {}
 
  public:
   bool finalizeInBackground(const JS::Value& priv) const final { return false; }
 
@@ -72,83 +74,41 @@ class RemoteObjectProxyBase : public js:
   bool isCallable(JSObject* aObj) const final { return false; }
   bool isConstructor(JSObject* aObj) const final { return false; }
 
   static void* GetNative(JSObject* aProxy) {
     return js::GetProxyPrivate(aProxy).toPrivate();
   }
 
   /**
-   * Returns true if aProxy represents an object implementing the WebIDL
-   * interface for aProtoID. aProxy should be a proxy object.
+   * Returns true if aProxy is a cross-process proxy that represents
+   * an object implementing the WebIDL interface for aProtoID. aProxy
+   * should be a proxy object.
    */
   static inline bool IsRemoteObjectProxy(JSObject* aProxy,
                                          prototypes::ID aProtoID) {
     const js::BaseProxyHandler* handler = js::GetProxyHandler(aProxy);
     return handler->family() == &sCrossOriginProxyFamily &&
            static_cast<const RemoteObjectProxyBase*>(handler)->mPrototypeID ==
                aProtoID;
   }
 
- protected:
-  bool getOwnPropertyDescriptorInternal(
-      JSContext* aCx, JS::Handle<JSObject*> aProxy, JS::Handle<jsid> aId,
-      JS::MutableHandle<JS::PropertyDescriptor> aDesc) const {
-    JS::Rooted<JSObject*> holder(aCx);
-    if (!EnsureHolder(aCx, aProxy, &holder) ||
-        !JS_GetOwnPropertyDescriptorById(aCx, holder, aId, aDesc)) {
-      return false;
-    }
-
-    if (aDesc.object()) {
-      aDesc.object().set(aProxy);
-    }
-
-    return true;
+  /**
+   * Returns true if aProxy is a cross-process proxy, no matter which
+   * interface it represents.  aProxy should be a proxy object.
+   */
+  static inline bool IsRemoteObjectProxy(JSObject* aProxy) {
+    const js::BaseProxyHandler* handler = js::GetProxyHandler(aProxy);
+    return handler->family() == &sCrossOriginProxyFamily;
   }
 
+ protected:
   JSObject* CreateProxyObject(JSContext* aCx, void* aNative,
                               const js::Class* aClasp) const;
 
-  /**
-   * Implements the tail of getOwnPropertyDescriptor, dealing in particular with
-   * properties that are whitelisted by xpc::IsCrossOriginWhitelistedProp.
-   */
-  static bool getOwnPropertyDescriptorTail(
-      JSContext* aCx, JS::Handle<JSObject*> aProxy, JS::Handle<jsid> aId,
-      JS::MutableHandle<JS::PropertyDescriptor> aDesc);
-  static bool ReportCrossOriginDenial(JSContext* aCx, JS::Handle<jsid> aId,
-                                      const nsACString& aAccessType);
-
-  /**
-   * This gets a cached, or creates and caches, a holder object that contains
-   * the WebIDL properties for this proxy.
-   */
-  bool EnsureHolder(JSContext* aCx, JS::Handle<JSObject*> aProxy,
-                    JS::MutableHandle<JSObject*> aHolder) const {
-    // FIXME Need to have a holder per realm, should store a weakmap in the
-    //       reserved slot.
-    JS::Value v = js::GetProxyReservedSlot(aProxy, 0);
-    if (v.isObject()) {
-      aHolder.set(&v.toObject());
-      return true;
-    }
-
-    aHolder.set(JS_NewObjectWithGivenProto(aCx, nullptr, nullptr));
-    if (!aHolder || !DefinePropertiesAndFunctions(aCx, aHolder)) {
-      return false;
-    }
-
-    js::SetProxyReservedSlot(aProxy, 0, JS::ObjectValue(*aHolder));
-    return true;
-  }
-
-  virtual bool DefinePropertiesAndFunctions(
-      JSContext* aCx, JS::Handle<JSObject*> aHolder) const = 0;
-
   const prototypes::ID mPrototypeID;
 
   static const char sCrossOriginProxyFamily;
 };
 
 /**
  * Proxy handler for proxy objects that represent an object implementing a
  * WebIDL interface that has cross-origin accessible properties/methods, and
@@ -170,31 +130,43 @@ class RemoteObjectProxy : public RemoteO
                               const js::Class* aClasp) const {
     return RemoteObjectProxyBase::CreateProxyObject(aCx, aNative, aClasp);
   }
 
  protected:
   using RemoteObjectProxyBase::RemoteObjectProxyBase;
 
  private:
-  bool DefinePropertiesAndFunctions(JSContext* aCx,
-                                    JS::Handle<JSObject*> aHolder) const final {
-    return JS_DefineProperties(aCx, aHolder, P) &&
-           JS_DefineFunctions(aCx, aHolder, F);
+  bool EnsureHolder(JSContext* aCx, JS::Handle<JSObject*> aProxy,
+                    JS::MutableHandle<JSObject*> aHolder) const final {
+    return MaybeCrossOriginObjectMixins::EnsureHolder(
+        aCx, aProxy, /* slot = */ 0, P, F, aHolder);
   }
 };
 
 /**
- * Returns true if aObj is a proxy object that represents an object implementing
- * the WebIDL interface for aProtoID.
+ * Returns true if aObj is a cross-process proxy object that
+ * represents an object implementing the WebIDL interface for
+ * aProtoID.
  */
 static inline bool IsRemoteObjectProxy(JSObject* aObj,
                                        prototypes::ID aProtoID) {
   if (!js::IsProxy(aObj)) {
     return false;
   }
   return RemoteObjectProxyBase::IsRemoteObjectProxy(aObj, aProtoID);
 }
 
+/**
+ * Returns true if aObj is a cross-process proxy object, no matter
+ * which WebIDL interface it corresponds to.
+ */
+static inline bool IsRemoteObjectProxy(JSObject* aObj) {
+  if (!js::IsProxy(aObj)) {
+    return false;
+  }
+  return RemoteObjectProxyBase::IsRemoteObjectProxy(aObj);
+}
+
 }  // namespace dom
 }  // namespace mozilla
 
 #endif /* mozilla_dom_RemoteObjectProxy_h */
--- a/dom/bindings/parser/WebIDL.py
+++ b/dom/bindings/parser/WebIDL.py
@@ -1781,18 +1781,17 @@ class IDLInterface(IDLInterfaceOrNamespa
             elif (identifier == "NeedResolve" or
                   identifier == "OverrideBuiltins" or
                   identifier == "ChromeOnly" or
                   identifier == "Unforgeable" or
                   identifier == "LegacyEventInit" or
                   identifier == "ProbablyShortLivingWrapper" or
                   identifier == "LegacyUnenumerableNamedProperties" or
                   identifier == "RunConstructorInCallerCompartment" or
-                  identifier == "WantsEventListenerHooks" or
-                  identifier == "NonOrdinaryGetPrototypeOf"):
+                  identifier == "WantsEventListenerHooks"):
                 # Known extended attributes that do not take values
                 if not attr.noArguments():
                     raise WebIDLError("[%s] must take no arguments" % identifier,
                                       [attr.location])
             elif identifier == "Exposed":
                 convertExposedAttrToGlobalNameSet(attr,
                                                   self._exposureGlobalNames)
             elif (identifier == "Pref" or
--- a/dom/script/LoadedScript.cpp
+++ b/dom/script/LoadedScript.cpp
@@ -51,17 +51,18 @@ void LoadedScript::AssociateWithScript(J
   // Set a JSScript's private value to point to this object. The JS engine will
   // increment our reference count by calling HostAddRefTopLevelScript(). This
   // is decremented by HostReleaseTopLevelScript() below when the JSScript dies.
 
   MOZ_ASSERT(JS::GetScriptPrivate(aScript).isUndefined());
   JS::SetScriptPrivate(aScript, JS::PrivateValue(this));
 }
 
-inline void CheckModuleScriptPrivate(LoadedScript* script, const JS::Value& aPrivate) {
+inline void CheckModuleScriptPrivate(LoadedScript* script,
+                                     const JS::Value& aPrivate) {
 #ifdef DEBUG
   if (script->IsModuleScript()) {
     JSObject* module = script->AsModuleScript()->mModuleRecord.unbarrieredGet();
     MOZ_ASSERT_IF(module, JS::GetModulePrivate(module) == aPrivate);
   }
 #endif
 }
 
--- a/dom/script/ScriptLoader.cpp
+++ b/dom/script/ScriptLoader.cpp
@@ -961,18 +961,17 @@ void ScriptLoader::EnsureModuleHooksInit
   jsapi.Init();
   JSRuntime* rt = JS_GetRuntime(jsapi.cx());
   if (JS::GetModuleResolveHook(rt)) {
     return;
   }
 
   JS::SetModuleResolveHook(rt, HostResolveImportedModule);
   JS::SetModuleMetadataHook(rt, HostPopulateImportMeta);
-  JS::SetScriptPrivateReferenceHooks(rt,
-                                     HostAddRefTopLevelScript,
+  JS::SetScriptPrivateReferenceHooks(rt, HostAddRefTopLevelScript,
                                      HostReleaseTopLevelScript);
 
   Preferences::RegisterCallbackAndCall(DynamicImportPrefChangedCallback,
                                        "javascript.options.dynamicImport",
                                        (void*)nullptr);
 }
 
 void ScriptLoader::CheckModuleDependenciesLoaded(ModuleLoadRequest* aRequest) {
--- a/dom/security/nsMixedContentBlocker.cpp
+++ b/dom/security/nsMixedContentBlocker.cpp
@@ -361,17 +361,17 @@ nsMixedContentBlocker::ShouldLoad(nsIURI
                                   nsILoadInfo* aLoadInfo,
                                   const nsACString& aMimeGuess,
                                   int16_t* aDecision) {
   uint32_t contentType = aLoadInfo->InternalContentPolicyType();
   nsCOMPtr<nsISupports> requestingContext = aLoadInfo->GetLoadingContext();
   nsCOMPtr<nsIPrincipal> requestPrincipal = aLoadInfo->TriggeringPrincipal();
   nsCOMPtr<nsIURI> requestingLocation;
   nsCOMPtr<nsIPrincipal> loadingPrincipal = aLoadInfo->LoadingPrincipal();
-  if (loadingPrincipal && loadingPrincipal->GetIsCodebasePrincipal()) {
+  if (loadingPrincipal) {
     loadingPrincipal->GetURI(getter_AddRefs(requestingLocation));
   }
 
   // We pass in false as the first parameter to ShouldLoad(), because the
   // callers of this method don't know whether the load went through cached
   // image redirects.  This is handled by direct callers of the static
   // ShouldLoad.
   nsresult rv =
--- a/dom/tests/mochitest/bugs/test_bug440572.html
+++ b/dom/tests/mochitest/bugs/test_bug440572.html
@@ -22,24 +22,30 @@ function receiveMessage(e)
   is(e.origin, "http://example.org", "wrong sender!");
   messages.set(e.data.from, e.data.result);
 }
 
 window.addEventListener("message", receiveMessage);
 
 function runtests()
 {
-  is(messages.size, 2, "received the right number of messages.");
+  is(messages.size, 4, "received the right number of messages.");
   is(messages.get("test"), "success", "test in frame failed.");
-  isnot(messages.get("dump"), "success", "parent[\"dump\"] should be the WebIDL property of Window.");
+  is(messages.get("dump"), "success", '"dump" in frame failed.');
+  is(messages.get("open"), "success", '"open" in frame failed.');
+  isnot(messages.get("close"), "success", "parent[\"close\"] should be the WebIDL property of Window.");
 
   SimpleTest.finish();
 }
 
 SimpleTest.waitForExplicitFinish();
 </script>
 <br>
 <iframe name="test" src="http://example.org:80/tests/dom/tests/mochitest/bugs/iframe_bug440572.html"></iframe>
 <br>
 <iframe name="dump" src="http://example.org:80/tests/dom/tests/mochitest/bugs/iframe_bug440572.html"></iframe>
+<br>
+<iframe name="open" src="http://example.org:80/tests/dom/tests/mochitest/bugs/iframe_bug440572.html"></iframe>
+<br>
+<iframe name="close" src="http://example.org:80/tests/dom/tests/mochitest/bugs/iframe_bug440572.html"></iframe>
 </body>
 </html>
 
--- a/dom/webidl/Location.webidl
+++ b/dom/webidl/Location.webidl
@@ -6,17 +6,17 @@
  * The origin of this IDL file is
  * http://www.whatwg.org/specs/web-apps/current-work/#the-location-interface
  *
  * © Copyright 2004-2011 Apple Computer, Inc., Mozilla Foundation, and
  * Opera Software ASA. You are granted a license to use, reproduce
  * and create derivative works of this document.
  */
 
-[Unforgeable, NonOrdinaryGetPrototypeOf]
+[Unforgeable]
 interface Location {
   // Bug 824857: no support for stringifier attributes yet.
   //  stringifier attribute USVString href;
 
   // Bug 824857 should remove this.
   [Throws, NeedsSubjectPrincipal]
   stringifier;
 
--- a/gfx/layers/wr/WebRenderUserData.cpp
+++ b/gfx/layers/wr/WebRenderUserData.cpp
@@ -97,18 +97,18 @@ bool WebRenderImageData::UsingSharedSurf
   if (!mContainer || !mKey || mOwnsKey) {
     return false;
   }
 
   // If this is just an update with the same image key, then we know that the
   // share request initiated an asynchronous update so that we don't need to
   // rebuild the scene.
   wr::ImageKey key;
-  nsresult rv = SharedSurfacesChild::Share(mContainer, mManager,
-      mManager->AsyncResourceUpdates(), key);
+  nsresult rv = SharedSurfacesChild::Share(
+      mContainer, mManager, mManager->AsyncResourceUpdates(), key);
   return NS_SUCCEEDED(rv) && mKey.ref() == key;
 }
 
 void WebRenderImageData::ClearImageKey() {
   if (mKey) {
     // If we don't own the key, then the owner is responsible for discarding the
     // key when appropriate.
     if (mOwnsKey) {
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -684,17 +684,17 @@ static void FinishAsyncMemoryReport() {
 
 // clang-format off
 // (For some reason, clang-format gets the second macro right, but totally mangles the first).
 #define REPORT_INTERNER(id)                      \
   helper.Report(aReport.interning.interners.id, \
                 "interning/" #id "/interners");
 // clang-format on
 
-#define REPORT_DATA_STORE(id)                      \
+#define REPORT_DATA_STORE(id)                     \
   helper.Report(aReport.interning.data_stores.id, \
                 "interning/" #id "/data-stores");
 
 NS_IMPL_ISUPPORTS(WebRenderMemoryReporter, nsIMemoryReporter)
 
 NS_IMETHODIMP
 WebRenderMemoryReporter::CollectReports(nsIHandleReportCallback* aHandleReport,
                                         nsISupports* aData, bool aAnonymize) {
--- a/gfx/webrender_bindings/WebRenderAPI.cpp
+++ b/gfx/webrender_bindings/WebRenderAPI.cpp
@@ -671,17 +671,18 @@ void DisplayListBuilder::Finalize(wr::La
   wr_api_finalize_builder(mWrState, &aOutContentSize, &aOutDisplayList.dl_desc,
                           &aOutDisplayList.dl.inner);
 }
 
 Maybe<wr::WrSpatialId> DisplayListBuilder::PushStackingContext(
     const wr::LayoutRect& aBounds, const wr::WrStackingContextClip& aClip,
     const WrAnimationProperty* aAnimation, const float* aOpacity,
     const gfx::Matrix4x4* aTransform, wr::TransformStyle aTransformStyle,
-    const wr::ReferenceFrameKind aReferenceFrameKind, const wr::MixBlendMode& aMixBlendMode,
+    const wr::ReferenceFrameKind aReferenceFrameKind,
+    const wr::MixBlendMode& aMixBlendMode,
     const nsTArray<wr::FilterOp>& aFilters, bool aIsBackfaceVisible,
     const wr::RasterSpace& aRasterSpace) {
   MOZ_ASSERT(mClipChainLeaf.isNothing(),
              "Non-empty leaf from clip chain given, but not used with SC!");
 
   wr::LayoutTransform matrix;
   if (aTransform) {
     matrix = ToLayoutTransform(*aTransform);
--- a/image/imgLoader.cpp
+++ b/image/imgLoader.cpp
@@ -679,18 +679,17 @@ static bool ShouldLoadCachedImage(imgReq
       if (document && document->GetUpgradeInsecureRequests(false)) {
         return false;
       }
     }
 
     if (!nsContentUtils::IsSystemPrincipal(aTriggeringPrincipal)) {
       // Set the requestingLocation from the aTriggeringPrincipal.
       nsCOMPtr<nsIURI> requestingLocation;
-      if (aTriggeringPrincipal &&
-          aTriggeringPrincipal->GetIsCodebasePrincipal()) {
+      if (aTriggeringPrincipal) {
         rv = aTriggeringPrincipal->GetURI(getter_AddRefs(requestingLocation));
         NS_ENSURE_SUCCESS(rv, false);
       }
 
       // reset the decision for mixed content blocker check
       decision = nsIContentPolicy::REJECT_REQUEST;
       rv = nsMixedContentBlocker::ShouldLoad(
           insecureRedirect, aPolicyType, contentLocation, requestingLocation,
--- a/js/public/CompileOptions.h
+++ b/js/public/CompileOptions.h
@@ -246,19 +246,17 @@ class JS_PUBLIC_API OwningCompileOptions
 
   JSObject* element() const override { return elementRoot; }
   JSString* elementAttributeName() const override {
     return elementAttributeNameRoot;
   }
   JSScript* introductionScript() const override {
     return introductionScriptRoot;
   }
-  JSScript* scriptOrModule() const override {
-    return scriptOrModuleRoot;
-  }
+  JSScript* scriptOrModule() const override { return scriptOrModuleRoot; }
 
   /** Set this to a copy of |rhs|.  Return false on OOM. */
   bool copy(JSContext* cx, const ReadOnlyCompileOptions& rhs);
 
   /* These setters make copies of their string arguments and are fallible. */
   MOZ_MUST_USE bool setFile(JSContext* cx, const char* f);
   MOZ_MUST_USE bool setFileAndLine(JSContext* cx, const char* f, unsigned l);
   MOZ_MUST_USE bool setSourceMapURL(JSContext* cx, const char16_t* s);
@@ -424,19 +422,17 @@ class MOZ_STACK_CLASS JS_PUBLIC_API Comp
   JSString* elementAttributeName() const override {
     return elementAttributeNameRoot;
   }
 
   JSScript* introductionScript() const override {
     return introductionScriptRoot;
   }
 
-  JSScript* scriptOrModule() const override {
-    return scriptOrModuleRoot;
-  }
+  JSScript* scriptOrModule() const override { return scriptOrModuleRoot; }
 
   CompileOptions& setFile(const char* f) {
     filename_ = f;
     return *this;
   }
 
   CompileOptions& setLine(unsigned l) {
     lineno = l;
--- a/js/src/builtin/ModuleObject.cpp
+++ b/js/src/builtin/ModuleObject.cpp
@@ -1679,17 +1679,17 @@ JSObject* js::CallModuleResolveHook(JSCo
 }
 
 JSObject* js::StartDynamicModuleImport(JSContext* cx,
                                        HandleObject referencingScriptSource,
                                        HandleValue specifierArg) {
   RootedValue referencingPrivate(cx);
   if (referencingScriptSource) {
     ScriptSourceObject* sso =
-      &UncheckedUnwrap(referencingScriptSource)->as<ScriptSourceObject>();
+        &UncheckedUnwrap(referencingScriptSource)->as<ScriptSourceObject>();
     referencingPrivate = sso->canonicalPrivate();
   }
 
   RootedObject promiseConstructor(cx, JS::GetPromiseConstructor(cx));
   if (!promiseConstructor) {
     return nullptr;
   }
 
--- a/js/src/gc/GC.cpp
+++ b/js/src/gc/GC.cpp
@@ -8588,18 +8588,18 @@ JS::dbg::GarbageCollectionEvent::Ptr JS:
     JSContext* cx) const {
   return JS::dbg::GarbageCollectionEvent::Create(
       cx->runtime(), cx->runtime()->gc.stats(),
       cx->runtime()->gc.majorGCCount());
 }
 
 char16_t* JS::GCDescription::formatJSONTelemetry(JSContext* cx,
                                                  uint64_t timestamp) const {
-  UniqueChars cstr = cx->runtime()->gc.stats().renderJsonMessage(timestamp,
-      gcstats::Statistics::JSONUse::TELEMETRY);
+  UniqueChars cstr = cx->runtime()->gc.stats().renderJsonMessage(
+      timestamp, gcstats::Statistics::JSONUse::TELEMETRY);
 
   size_t nchars = strlen(cstr.get());
   UniqueTwoByteChars out(js_pod_malloc<char16_t>(nchars + 1));
   if (!out) {
     return nullptr;
   }
   out.get()[nchars] = 0;
 
@@ -8625,18 +8625,18 @@ TimeStamp JS::GCDescription::lastSliceEn
 
 JS::UniqueChars JS::GCDescription::sliceToJSONProfiler(JSContext* cx) const {
   size_t slices = cx->runtime()->gc.stats().slices().length();
   MOZ_ASSERT(slices > 0);
   return cx->runtime()->gc.stats().renderJsonSlice(slices - 1);
 }
 
 JS::UniqueChars JS::GCDescription::formatJSONProfiler(JSContext* cx) const {
-  return cx->runtime()->gc.stats().renderJsonMessage(0,
-      js::gcstats::Statistics::JSONUse::PROFILER);
+  return cx->runtime()->gc.stats().renderJsonMessage(
+      0, js::gcstats::Statistics::JSONUse::PROFILER);
 }
 
 JS_PUBLIC_API JS::UniqueChars JS::MinorGcToJSON(JSContext* cx) {
   JSRuntime* rt = cx->runtime();
   return rt->gc.stats().renderNurseryJson(rt);
 }
 
 JS_PUBLIC_API JS::GCSliceCallback JS::SetGCSliceCallback(
--- a/js/src/gc/Statistics.cpp
+++ b/js/src/gc/Statistics.cpp
@@ -580,17 +580,18 @@ void Statistics::writeLogMessage(const c
     vfprintf(gcDebugFile, fmt, args);
     fprintf(gcDebugFile, "\n");
     fflush(gcDebugFile);
   }
   va_end(args);
 }
 #endif
 
-UniqueChars Statistics::renderJsonMessage(uint64_t timestamp, Statistics::JSONUse use) const {
+UniqueChars Statistics::renderJsonMessage(uint64_t timestamp,
+                                          Statistics::JSONUse use) const {
   /*
    * The format of the JSON message is specified by the GCMajorMarkerPayload
    * type in perf.html
    * https://github.com/devtools-html/perf.html/blob/master/src/types/markers.js#L62
    *
    * All the properties listed here are created within the timings property
    * of the GCMajor marker.
    */
@@ -600,17 +601,17 @@ UniqueChars Statistics::renderJsonMessag
 
   Sprinter printer(nullptr, false);
   if (!printer.init()) {
     return UniqueChars(nullptr);
   }
   JSONPrinter json(printer);
 
   json.beginObject();
-  json.property("status", "completed");    // JSON Key #1
+  json.property("status", "completed");         // JSON Key #1
   formatJsonDescription(timestamp, json, use);  // #2-22
 
   if (use == Statistics::JSONUse::TELEMETRY) {
     json.beginListProperty("slices_list");  // #23
     for (unsigned i = 0; i < slices_.length(); i++) {
       formatJsonSlice(i, json);
     }
     json.endList();
@@ -620,18 +621,17 @@ UniqueChars Statistics::renderJsonMessag
   formatJsonPhaseTimes(phaseTimes, json);
   json.endObject();
 
   json.endObject();
 
   return printer.release();
 }
 
-void Statistics::formatJsonDescription(uint64_t timestamp,
-                                       JSONPrinter& json,
+void Statistics::formatJsonDescription(uint64_t timestamp, JSONPrinter& json,
                                        JSONUse use) const {
   // If you change JSON properties here, please update:
   // Telemetry ping code:
   //   toolkit/components/telemetry/other/GCTelemetry.jsm
   // Telemetry documentation:
   //   toolkit/components/telemetry/docs/data/main-ping.rst
   // Telemetry tests:
   //   toolkit/components/telemetry/tests/browser/browser_TelemetryGC.js,
--- a/js/src/gc/Statistics.h
+++ b/js/src/gc/Statistics.h
@@ -281,20 +281,17 @@ struct Statistics {
   void maybePrintProfileHeaders();
 
   // Print header line for profile times.
   void printProfileHeader();
 
   // Print total profile times on shutdown.
   void printTotalProfileTimes();
 
-  enum JSONUse {
-    TELEMETRY,
-    PROFILER
-  };
+  enum JSONUse { TELEMETRY, PROFILER };
 
   // Return JSON for a whole major GC.  If use == PROFILER then
   // detailed per-slice data and some other fields will be included.
   UniqueChars renderJsonMessage(uint64_t timestamp, JSONUse use) const;
 
   // Return JSON for the timings of just the given slice.
   UniqueChars renderJsonSlice(size_t sliceNum) const;
 
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -13674,17 +13674,18 @@ AbortReasonOr<Ok> IonBuilder::jsop_impor
   return resumeAfter(meta);
 }
 
 AbortReasonOr<Ok> IonBuilder::jsop_dynamic_import() {
   JSObject* referencingScriptSource = script()->sourceObject();
 
   MDefinition* specifier = current->pop();
 
-  MDynamicImport* ins = MDynamicImport::New(alloc(), referencingScriptSource, specifier);
+  MDynamicImport* ins =
+      MDynamicImport::New(alloc(), referencingScriptSource, specifier);
   current->add(ins);
   current->push(ins);
   return resumeAfter(ins);
 }
 
 MInstruction* IonBuilder::addConvertElementsToDoubles(MDefinition* elements) {
   MInstruction* convert = MConvertElementsToDoubles::New(alloc(), elements);
   current->add(convert);
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -3750,19 +3750,18 @@ JS_PUBLIC_API JS::Value JS::GetScriptedC
   if (iter.done() || !iter.hasScript()) {
     return UndefinedValue();
   }
 
   return iter.script()->sourceObject()->canonicalPrivate();
 }
 
 JS_PUBLIC_API void JS::SetScriptPrivateReferenceHooks(
-  JSRuntime* rt,
-  JS::ScriptPrivateReferenceHook addRefHook,
-  JS::ScriptPrivateReferenceHook releaseHook) {
+    JSRuntime* rt, JS::ScriptPrivateReferenceHook addRefHook,
+    JS::ScriptPrivateReferenceHook releaseHook) {
   AssertHeapIsIdle();
   rt->scriptPrivateAddRefHook = addRefHook;
   rt->scriptPrivateReleaseHook = releaseHook;
 }
 
 JS_PUBLIC_API bool JS::ModuleInstantiate(JSContext* cx,
                                          JS::HandleObject moduleArg) {
   AssertHeapIsIdle();
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -2580,19 +2580,18 @@ extern JS_PUBLIC_API JS::Value GetScript
  * script private.
  */
 using ScriptPrivateReferenceHook = void (*)(const JS::Value&);
 
 /**
  * Set the script private finalize hook for the runtime to the given function.
  */
 extern JS_PUBLIC_API void SetScriptPrivateReferenceHooks(
-  JSRuntime* rt,
-  ScriptPrivateReferenceHook addRefHook,
-  ScriptPrivateReferenceHook releaseHook);
+    JSRuntime* rt, ScriptPrivateReferenceHook addRefHook,
+    ScriptPrivateReferenceHook releaseHook);
 
 /*
  * Perform the ModuleInstantiate operation on the given source text module
  * record.
  *
  * This transitively resolves all module dependencies (calling the
  * HostResolveImportedModule hook) and initializes the environment record for
  * the module.
--- a/js/src/vm/SavedStacks.cpp
+++ b/js/src/vm/SavedStacks.cpp
@@ -1320,19 +1320,20 @@ bool SavedStacks::insertFrames(JSContext
       // cache miss, if the frame's pc doesn't match the cache entry's, or if
       // the cache was emptied due to a realm mismatch.
       if (parent) {
         break;
       }
 
       // This frame doesn't have a cache entry, despite its hasCachedSavedFrame
       // flag being set. If this was due to a pc mismatch, we can clear the flag
-      // here and set things right. If the cache was emptied due to a realm mismatch,
-      // we should clear all the frames' flags as we walk to the bottom of the stack,
-      // so that they are all clear before we start pushing any new entries.
+      // here and set things right. If the cache was emptied due to a realm
+      // mismatch, we should clear all the frames' flags as we walk to the
+      // bottom of the stack, so that they are all clear before we start pushing
+      // any new entries.
       framePtr->clearHasCachedSavedFrame();
     }
 
     // We'll be pushing this frame onto stackChain. Gather the information
     // needed to construct the SavedFrame::Lookup.
     Rooted<LocationValue> location(cx);
     {
       AutoRealmUnchecked ar(cx, iter.realm());
--- a/js/xpconnect/tests/chrome/test_bug860494.xul
+++ b/js/xpconnect/tests/chrome/test_bug860494.xul
@@ -39,18 +39,18 @@ https://bugzilla.mozilla.org/show_bug.cg
     sb.topWin = top;
     sb.parentWin = window;
     sb.is = is;
     sb.ok = ok;
     Cu.evalInSandbox('ok(win.top === topWin, "iframe names shouldnt shadow |top| via cross-origin Xray");', sb);
     Cu.evalInSandbox('ok(win.parent === parentWin, "iframe names shouldnt shadow |parent| via cross-origin Xray");', sb);
     Cu.evalInSandbox('is(win.length, 7, "iframe names shouldnt shadow |length| via cross-origin Xray");', sb);
     Cu.evalInSandbox('ok(win.window === win, "iframe names shouldnt shadow |window| via cross-origin Xray");', sb);
-    Cu.evalInSandbox('var exn = "nothrow"; try { win.navigator; } catch (e) { exn = e; } ok(!!/denied/.exec(exn), "cross-origin Xray blocks subframes that shadow: navigator: " + exn);', sb);
-    Cu.evalInSandbox('var exn = "nothrow"; try { win.alert; } catch (e) { exn = e; } ok(!!/denied/.exec(exn), "cross-origin Xray blocks subframes that shadow: alert: " + exn);', sb);
+    Cu.evalInSandbox('ok(win.navigator === win[5], "iframe names that correspond to non-cross-origin-visible properties should expose the subframe: navigator");', sb);
+    Cu.evalInSandbox('ok(win.alert === win[6], "iframe names that correspond to non-cross-origin-visible properties should expose the subframe: alert");', sb);
 
     SimpleTest.finish();
   }
 
   ]]>
   </script>
   <iframe id="ifr" type="content" onload="go();" src="http://example.org/tests/js/xpconnect/tests/mochitest/file_bug860494.html" />
 </window>
--- a/js/xpconnect/wrappers/AccessCheck.cpp
+++ b/js/xpconnect/wrappers/AccessCheck.cpp
@@ -84,145 +84,30 @@ bool AccessCheck::wrapperSubsumes(JSObje
 bool AccessCheck::isChrome(JS::Compartment* compartment) {
   return js::IsSystemCompartment(compartment);
 }
 
 bool AccessCheck::isChrome(JSObject* obj) {
   return isChrome(js::GetObjectCompartment(obj));
 }
 
-// Hardcoded policy for cross origin property access. See the HTML5 Spec.
-static bool IsPermitted(CrossOriginObjectType type, JSFlatString* prop,
-                        bool set) {
-  size_t propLength = JS_GetStringLength(JS_FORGET_STRING_FLATNESS(prop));
-  if (!propLength) {
-    return false;
-  }
-
-  char16_t propChar0 = JS_GetFlatStringCharAt(prop, 0);
-  if (type == CrossOriginLocation) {
-    return dom::Location_Binding::IsPermitted(prop, propChar0, set);
-  }
-  if (type == CrossOriginWindow) {
-    return dom::Window_Binding::IsPermitted(prop, propChar0, set);
-  }
-
-  return false;
-}
-
-static bool IsFrameId(JSContext* cx, JSObject* obj, jsid idArg) {
-  MOZ_ASSERT(!js::IsWrapper(obj));
-  RootedId id(cx, idArg);
-
-  nsGlobalWindowInner* win = WindowOrNull(obj);
-  if (!win) {
-    return false;
-  }
-
-  nsDOMWindowList* col = win->GetFrames();
-  if (!col) {
-    return false;
-  }
-
-  nsCOMPtr<mozIDOMWindowProxy> domwin;
-  if (JSID_IS_INT(id)) {
-    domwin = col->IndexedGetter(JSID_TO_INT(id));
-  } else if (JSID_IS_STRING(id)) {
-    nsAutoJSString idAsString;
-    if (!idAsString.init(cx, JSID_TO_STRING(id))) {
-      return false;
-    }
-    domwin = col->NamedItem(idAsString);
-  }
-
-  return domwin != nullptr;
-}
-
 CrossOriginObjectType IdentifyCrossOriginObject(JSObject* obj) {
   obj = js::UncheckedUnwrap(obj, /* stopAtWindowProxy = */ false);
   const js::Class* clasp = js::GetObjectClass(obj);
 
   if (clasp->name[0] == 'L' && !strcmp(clasp->name, "Location")) {
     return CrossOriginLocation;
   }
   if (clasp->name[0] == 'W' && !strcmp(clasp->name, "Window")) {
     return CrossOriginWindow;
   }
 
   return CrossOriginOpaque;
 }
 
-bool AccessCheck::isCrossOriginAccessPermitted(JSContext* cx,
-                                               HandleObject wrapper,
-                                               HandleId id,
-                                               Wrapper::Action act) {
-  if (act == Wrapper::CALL) {
-    return false;
-  }
-
-  if (act == Wrapper::ENUMERATE) {
-    return true;
-  }
-
-  // For the case of getting a property descriptor, we allow if either GET or
-  // SET is allowed, and rely on FilteringWrapper to filter out any disallowed
-  // accessors.
-  if (act == Wrapper::GET_PROPERTY_DESCRIPTOR) {
-    return isCrossOriginAccessPermitted(cx, wrapper, id, Wrapper::GET) ||
-           isCrossOriginAccessPermitted(cx, wrapper, id, Wrapper::SET);
-  }
-
-  RootedObject obj(
-      cx, js::UncheckedUnwrap(wrapper, /* stopAtWindowProxy = */ false));
-  CrossOriginObjectType type = IdentifyCrossOriginObject(obj);
-  if (JSID_IS_STRING(id)) {
-    if (IsPermitted(type, JSID_TO_FLAT_STRING(id), act == Wrapper::SET)) {
-      return true;
-    }
-  }
-
-  if (type != CrossOriginOpaque && IsCrossOriginWhitelistedProp(cx, id)) {
-    // We always allow access to "then", @@toStringTag, @@hasInstance, and
-    // @@isConcatSpreadable.  But then we nerf them to be a value descriptor
-    // with value undefined in CrossOriginXrayWrapper.
-    return true;
-  }
-
-  if (act != Wrapper::GET) {
-    return false;
-  }
-
-  // Check for frame IDs. If we're resolving named frames, make sure to only
-  // resolve ones that don't shadow native properties. See bug 860494.
-  if (type == CrossOriginWindow) {
-    if (JSID_IS_STRING(id)) {
-      bool wouldShadow = false;
-      if (!XrayUtils::HasNativeProperty(cx, wrapper, id, &wouldShadow) ||
-          wouldShadow) {
-        // If the named subframe matches the name of a DOM constructor,
-        // the global resolve triggered by the HasNativeProperty call
-        // above will try to perform a CheckedUnwrap on |wrapper|, and
-        // throw a security error if it fails. That exception isn't
-        // really useful for our callers, so we silence it and just
-        // deny access to the property (since it matched a builtin).
-        //
-        // Note that this would be a problem if the resolve code ever
-        // tried to CheckedUnwrap the wrapper _before_ concluding that
-        // the name corresponds to a builtin global property, since it
-        // would mean that we'd never permit cross-origin named subframe
-        // access (something we regrettably need to support).
-        JS_ClearPendingException(cx);
-        return false;
-      }
-    }
-    return IsFrameId(cx, obj, id);
-  }
-  return false;
-}
-
 bool AccessCheck::checkPassToPrivilegedCode(JSContext* cx, HandleObject wrapper,
                                             HandleValue v) {
   // Primitives are fine.
   if (!v.isObject()) {
     return true;
   }
   RootedObject obj(cx, &v.toObject());
 
--- a/js/xpconnect/wrappers/AccessCheck.h
+++ b/js/xpconnect/wrappers/AccessCheck.h
@@ -19,19 +19,16 @@ class AccessCheck {
  public:
   static bool subsumes(JSObject* a, JSObject* b);
   static bool wrapperSubsumes(JSObject* wrapper);
   static bool subsumesConsideringDomain(JS::Compartment* a, JS::Compartment* b);
   static bool subsumesConsideringDomainIgnoringFPD(JS::Compartment* a,
                                                    JS::Compartment* b);
   static bool isChrome(JS::Compartment* compartment);
   static bool isChrome(JSObject* obj);
-  static bool isCrossOriginAccessPermitted(JSContext* cx, JS::HandleObject obj,
-                                           JS::HandleId id,
-                                           js::Wrapper::Action act);
   static bool checkPassToPrivilegedCode(JSContext* cx, JS::HandleObject wrapper,
                                         JS::HandleValue value);
   static bool checkPassToPrivilegedCode(JSContext* cx, JS::HandleObject wrapper,
                                         const JS::CallArgs& args);
   // Called to report the correct sort of exception when our policy denies and
   // should throw.  The accessType argument should be one of "access",
   // "define", "delete", depending on which operation is being denied.
   static void reportCrossOriginDenial(JSContext* cx, JS::HandleId id,
@@ -84,41 +81,16 @@ struct OpaqueWithCall : public Policy {
     return false;
   }
   static bool checkCall(JSContext* cx, JS::HandleObject wrapper,
                         const JS::CallArgs& args) {
     return AccessCheck::checkPassToPrivilegedCode(cx, wrapper, args);
   }
 };
 
-// This policy only permits access to properties that are safe to be used
-// across origins.
-struct CrossOriginAccessiblePropertiesOnly : public Policy {
-  static bool check(JSContext* cx, JS::HandleObject wrapper, JS::HandleId id,
-                    js::Wrapper::Action act) {
-    return AccessCheck::isCrossOriginAccessPermitted(cx, wrapper, id, act);
-  }
-  static bool deny(JSContext* cx, js::Wrapper::Action act, JS::HandleId id,
-                   bool mayThrow) {
-    // Silently fail for enumerate-like operations.
-    if (act == js::Wrapper::ENUMERATE) {
-      return true;
-    }
-    if (mayThrow) {
-      AccessCheck::reportCrossOriginDenial(cx, id,
-                                           NS_LITERAL_CSTRING("access"));
-    }
-    return false;
-  }
-  static bool allowNativeCall(JSContext* cx, JS::IsAcceptableThis test,
-                              JS::NativeImpl impl) {
-    return false;
-  }
-};
-
 // This class used to support permitting access to properties if they
 // appeared in an access list on the object, but now it acts like an
 // Opaque wrapper, with the exception that it fails silently for GET,
 // ENUMERATE, and GET_PROPERTY_DESCRIPTOR. This is done for backwards
 // compatibility. See bug 1397513.
 struct OpaqueWithSilentFailing : public Policy {
   static bool check(JSContext* cx, JS::HandleObject wrapper, JS::HandleId id,
                     js::Wrapper::Action act) {
--- a/js/xpconnect/wrappers/FilteringWrapper.cpp
+++ b/js/xpconnect/wrappers/FilteringWrapper.cpp
@@ -232,122 +232,20 @@ bool FilteringWrapper<Base, Policy>::ent
     *bp =
         JS_IsExceptionPending(cx) ? false : Policy::deny(cx, act, id, mayThrow);
     return false;
   }
   *bp = true;
   return true;
 }
 
-bool CrossOriginXrayWrapper::getPropertyDescriptor(
-    JSContext* cx, JS::Handle<JSObject*> wrapper, JS::Handle<jsid> id,
-    JS::MutableHandle<PropertyDescriptor> desc) const {
-  if (!SecurityXrayDOM::getPropertyDescriptor(cx, wrapper, id, desc)) {
-    return false;
-  }
-  if (desc.object()) {
-    // Cross-origin DOM objects do not have symbol-named properties apart
-    // from the ones we add ourselves here.
-    MOZ_ASSERT(!JSID_IS_SYMBOL(id),
-               "What's this symbol-named property that appeared on a "
-               "Window or Location instance?");
-
-    // All properties on cross-origin DOM objects are |own|.
-    desc.object().set(wrapper);
-
-    // All properties on cross-origin DOM objects are "configurable". Any
-    // value attributes are read-only.  Indexed properties are enumerable,
-    // but nothing else is.
-    if (!JSID_IS_INT(id)) {
-      desc.attributesRef() &= ~JSPROP_ENUMERATE;
-    }
-    desc.attributesRef() &= ~JSPROP_PERMANENT;
-    if (!desc.getter() && !desc.setter()) {
-      desc.attributesRef() |= JSPROP_READONLY;
-    }
-  } else if (IsCrossOriginWhitelistedProp(cx, id)) {
-    // Spec says to return PropertyDescriptor {
-    //   [[Value]]: undefined, [[Writable]]: false, [[Enumerable]]: false,
-    //   [[Configurable]]: true
-    // }.
-    //
-    desc.setDataDescriptor(JS::UndefinedHandleValue, JSPROP_READONLY);
-    desc.object().set(wrapper);
-  }
-
-  return true;
-}
-
-bool CrossOriginXrayWrapper::getOwnPropertyDescriptor(
-    JSContext* cx, JS::Handle<JSObject*> wrapper, JS::Handle<jsid> id,
-    JS::MutableHandle<PropertyDescriptor> desc) const {
-  // All properties on cross-origin DOM objects are |own|.
-  return getPropertyDescriptor(cx, wrapper, id, desc);
-}
-
-bool CrossOriginXrayWrapper::ownPropertyKeys(JSContext* cx,
-                                             JS::Handle<JSObject*> wrapper,
-                                             JS::AutoIdVector& props) const {
-  // All properties on cross-origin objects are supposed |own|, despite what
-  // the underlying native object may report. Override the inherited trap to
-  // avoid passing JSITER_OWNONLY as a flag.
-  if (!SecurityXrayDOM::getPropertyKeys(cx, wrapper, JSITER_HIDDEN, props)) {
-    return false;
-  }
-
-  return AppendCrossOriginWhitelistedPropNames(cx, props);
-}
-
-bool CrossOriginXrayWrapper::defineProperty(JSContext* cx,
-                                            JS::Handle<JSObject*> wrapper,
-                                            JS::Handle<jsid> id,
-                                            JS::Handle<PropertyDescriptor> desc,
-                                            JS::ObjectOpResult& result) const {
-  AccessCheck::reportCrossOriginDenial(cx, id, NS_LITERAL_CSTRING("define"));
-  return false;
-}
-
-bool CrossOriginXrayWrapper::delete_(JSContext* cx,
-                                     JS::Handle<JSObject*> wrapper,
-                                     JS::Handle<jsid> id,
-                                     JS::ObjectOpResult& result) const {
-  AccessCheck::reportCrossOriginDenial(cx, id, NS_LITERAL_CSTRING("delete"));
-  return false;
-}
-
-bool CrossOriginXrayWrapper::setPrototype(JSContext* cx,
-                                          JS::HandleObject wrapper,
-                                          JS::HandleObject proto,
-                                          JS::ObjectOpResult& result) const {
-  // https://html.spec.whatwg.org/multipage/browsers.html#windowproxy-setprototypeof
-  // and
-  // https://html.spec.whatwg.org/multipage/browsers.html#location-setprototypeof
-  // both say to call SetImmutablePrototype, which does nothing and just
-  // returns whether the passed-in value equals the current prototype.  Our
-  // current prototype is always null, so this just comes down to returning
-  // whether null was passed in.
-  //
-  // In terms of ObjectOpResult that means calling one of the fail*() things
-  // on it if non-null was passed, and it's got one that does just what we
-  // want.
-  if (!proto) {
-    return result.succeed();
-  }
-  return result.failCantSetProto();
-}
-
-#define XOW \
-  FilteringWrapper<CrossOriginXrayWrapper, CrossOriginAccessiblePropertiesOnly>
 #define NNXOW FilteringWrapper<CrossCompartmentSecurityWrapper, Opaque>
 #define NNXOWC FilteringWrapper<CrossCompartmentSecurityWrapper, OpaqueWithCall>
 
 template <>
-const XOW XOW::singleton(0);
-template <>
 const NNXOW NNXOW::singleton(0);
 template <>
 const NNXOWC NNXOWC::singleton(0);
 
-template class XOW;
 template class NNXOW;
 template class NNXOWC;
 template class ChromeObjectWrapperBase;
 }  // namespace xpc
--- a/js/xpconnect/wrappers/FilteringWrapper.h
+++ b/js/xpconnect/wrappers/FilteringWrapper.h
@@ -48,43 +48,11 @@ class FilteringWrapper : public Base {
                           const JS::CallArgs& args) const override;
 
   virtual bool getPrototype(JSContext* cx, JS::HandleObject wrapper,
                             JS::MutableHandleObject protop) const override;
 
   static const FilteringWrapper singleton;
 };
 
-/*
- * The HTML5 spec mandates very particular object behavior for cross-origin DOM
- * objects (Window and Location), some of which runs contrary to the way that
- * other XrayWrappers behave. We use this class to implement those semantics.
- */
-class CrossOriginXrayWrapper : public SecurityXrayDOM {
- public:
-  constexpr explicit CrossOriginXrayWrapper(unsigned flags)
-      : SecurityXrayDOM(flags) {}
-
-  virtual bool getOwnPropertyDescriptor(
-      JSContext* cx, JS::Handle<JSObject*> wrapper, JS::Handle<jsid> id,
-      JS::MutableHandle<JS::PropertyDescriptor> desc) const override;
-  virtual bool defineProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
-                              JS::Handle<jsid> id,
-                              JS::Handle<JS::PropertyDescriptor> desc,
-                              JS::ObjectOpResult& result) const override;
-  virtual bool ownPropertyKeys(JSContext* cx, JS::Handle<JSObject*> wrapper,
-                               JS::AutoIdVector& props) const override;
-  virtual bool delete_(JSContext* cx, JS::Handle<JSObject*> wrapper,
-                       JS::Handle<jsid> id,
-                       JS::ObjectOpResult& result) const override;
-
-  virtual bool getPropertyDescriptor(
-      JSContext* cx, JS::Handle<JSObject*> wrapper, JS::Handle<jsid> id,
-      JS::MutableHandle<JS::PropertyDescriptor> desc) const override;
-
-  virtual bool setPrototype(JSContext* cx, JS::HandleObject wrapper,
-                            JS::HandleObject proto,
-                            JS::ObjectOpResult& result) const override;
-};
-
 }  // namespace xpc
 
 #endif /* __FilteringWrapper_h__ */
--- a/js/xpconnect/wrappers/WrapperFactory.cpp
+++ b/js/xpconnect/wrappers/WrapperFactory.cpp
@@ -356,16 +356,18 @@ static void DEBUG_CheckUnwrapSafety(Hand
     MOZ_ASSERT(handler->hasSecurityPolicy() == !subsumes);
   }
 }
 #else
 #  define DEBUG_CheckUnwrapSafety(obj, handler, origin, target) \
     {}
 #endif
 
+const CrossOriginObjectWrapper CrossOriginObjectWrapper::singleton;
+
 static const Wrapper* SelectWrapper(bool securityWrapper, XrayType xrayType,
                                     bool waiveXrays, JSObject* obj) {
   // Waived Xray uses a modified CCW that has transparent behavior but
   // transitively waives Xrays on arguments.
   if (waiveXrays) {
     MOZ_ASSERT(!securityWrapper);
     return &WaiveXrayWrapper::singleton;
   }
@@ -390,18 +392,17 @@ static const Wrapper* SelectWrapper(bool
     }
     MOZ_ASSERT(xrayType == XrayForOpaqueObject);
     return &PermissiveXrayOpaque::singleton;
   }
 
   // This is a security wrapper. Use the security versions and filter.
   if (xrayType == XrayForDOMObject &&
       IdentifyCrossOriginObject(obj) != CrossOriginOpaque) {
-    return &FilteringWrapper<CrossOriginXrayWrapper,
-                             CrossOriginAccessiblePropertiesOnly>::singleton;
+    return &CrossOriginObjectWrapper::singleton;
   }
 
   // There's never any reason to expose other objects to non-subsuming actors.
   // Just use an opaque wrapper in these cases.
   //
   // In general, we don't want opaque function wrappers to be callable.
   // But in the case of XBL, we rely on content being able to invoke
   // functions exposed from the XBL scope. We could remove this exception,
--- a/js/xpconnect/wrappers/WrapperFactory.h
+++ b/js/xpconnect/wrappers/WrapperFactory.h
@@ -6,16 +6,46 @@
 
 #ifndef _xpc_WRAPPERFACTORY_H
 #define _xpc_WRAPPERFACTORY_H
 
 #include "js/Wrapper.h"
 
 namespace xpc {
 
+/**
+ * A wrapper that's only used for cross-origin objects. This should be
+ * just like a CrossCompartmentWrapper but (as an implementation
+ * detail) doesn't actually do any compartment-entering and (as an
+ * implementation detail) delegates all the security decisions and
+ * compartment-entering to the target object, which is always a
+ * proxy.
+ *
+ * We could also inherit from CrossCompartmentWrapper but then we
+ * would need to override all the proxy hooks to avoid the
+ * compartment-entering bits.
+ */
+class CrossOriginObjectWrapper : public js::Wrapper {
+ public:
+  // We want to claim to have a security policy, so code doesn't just
+  // CheckedUnwrap us willy-nilly.  But we're OK with the BaseProxyHandler
+  // implementation of enter(), which allows entering.  Our target is what
+  // really does the security checks.
+  //
+  // We don't want to inherit from CrossCompartmentWrapper, because we don't
+  // want the compartment-entering behavior it has.  But we do want to set the
+  // CROSS_COMPARTMENT flag on js::Wrapper so that we test true for
+  // is<js::CrossCompartmentWrapperObject> and so forth.
+  constexpr explicit CrossOriginObjectWrapper()
+      : js::Wrapper(CROSS_COMPARTMENT, /* aHasPrototype = */ false,
+                    /* aHasSecurityPolicy = */ true) {}
+
+  static const CrossOriginObjectWrapper singleton;
+};
+
 class WrapperFactory {
  public:
   enum {
     WAIVE_XRAY_WRAPPER_FLAG = js::Wrapper::LAST_USED_FLAG << 1,
     IS_XRAY_WRAPPER_FLAG = WAIVE_XRAY_WRAPPER_FLAG << 1
   };
 
   // Return true if any of any of the nested wrappers have the flag set.
@@ -24,16 +54,21 @@ class WrapperFactory {
     js::UncheckedUnwrap(wrapper, true, &flags);
     return !!(flags & flag);
   }
 
   static bool IsXrayWrapper(JSObject* wrapper) {
     return HasWrapperFlag(wrapper, IS_XRAY_WRAPPER_FLAG);
   }
 
+  static bool IsCrossOriginWrapper(JSObject* obj) {
+    return (js::IsProxy(obj) &&
+            js::GetProxyHandler(obj) == &CrossOriginObjectWrapper::singleton);
+  }
+
   static bool HasWaiveXrayFlag(JSObject* wrapper) {
     return HasWrapperFlag(wrapper, WAIVE_XRAY_WRAPPER_FLAG);
   }
 
   static bool IsCOW(JSObject* wrapper);
 
   static JSObject* GetXrayWaiver(JS::HandleObject obj);
   static JSObject* CreateXrayWaiver(JSContext* cx, JS::HandleObject obj);
--- a/js/xpconnect/wrappers/XrayWrapper.cpp
+++ b/js/xpconnect/wrappers/XrayWrapper.cpp
@@ -1869,18 +1869,17 @@ bool XrayWrapper<Base, Traits>::isExtens
   *extensible = true;
   return true;
 }
 
 template <typename Base, typename Traits>
 bool XrayWrapper<Base, Traits>::getPropertyDescriptor(
     JSContext* cx, HandleObject wrapper, HandleId id,
     JS::MutableHandle<PropertyDescriptor> desc) const {
-  // CrossOriginXrayWrapper::getOwnPropertyDescriptor calls this.
-
+  // FIXME: This method is unused.  Will get sorted out in bug 1160757.
   assertEnteredPolicy(cx, wrapper, id,
                       BaseProxyHandler::GET | BaseProxyHandler::SET |
                           BaseProxyHandler::GET_PROPERTY_DESCRIPTOR);
   RootedObject target(cx, Traits::getTargetObject(wrapper));
   RootedObject holder(cx, Traits::singleton.ensureHolder(cx, wrapper));
 
   if (!holder) {
     return false;
@@ -1907,49 +1906,17 @@ bool XrayWrapper<Base, Traits>::getPrope
 
   // Check the holder.
   if (!desc.object() &&
       !JS_GetOwnPropertyDescriptorById(cx, holder, id, desc)) {
     return false;
   }
   if (desc.object()) {
     desc.object().set(wrapper);
-    return true;
   }
-
-  // We need to handle named access on the Window somewhere other than
-  // Traits::resolveOwnProperty, because per spec it happens on the Global
-  // Scope Polluter and thus the resulting properties are non-|own|. However,
-  // we're set up (above) to cache (on the holder),
-  // which we don't want for something dynamic like named access.
-  // So we just handle it separately here.  Note that this is
-  // only relevant for CrossOriginXrayWrapper, which calls
-  // getPropertyDescriptor from getOwnPropertyDescriptor.
-  nsGlobalWindowInner* win = nullptr;
-  if (!desc.object() && JSID_IS_STRING(id) && (win = AsWindow(cx, wrapper))) {
-    nsAutoJSString name;
-    if (!name.init(cx, JSID_TO_STRING(id))) {
-      return false;
-    }
-    RefPtr<BrowsingContext> childDOMWin(win->GetChildWindow(name));
-    if (childDOMWin) {
-      auto* cwin = nsGlobalWindowOuter::Cast(childDOMWin->GetDOMWindow());
-      JSObject* childObj = cwin->FastGetGlobalJSObject();
-      if (MOZ_UNLIKELY(!childObj)) {
-        return xpc::Throw(cx, NS_ERROR_FAILURE);
-      }
-      ExposeObjectToActiveJS(childObj);
-      FillPropertyDescriptor(desc, wrapper, ObjectValue(*childObj),
-                             /* readOnly = */ true);
-      return JS_WrapPropertyDescriptor(cx, desc);
-    }
-  }
-
-  // We found nothing, we're done.
-  MOZ_ASSERT(!desc.object());
   return true;
 }
 
 template <typename Base, typename Traits>
 bool XrayWrapper<Base, Traits>::getOwnPropertyDescriptor(
     JSContext* cx, HandleObject wrapper, HandleId id,
     JS::MutableHandle<PropertyDescriptor> desc) const {
   assertEnteredPolicy(cx, wrapper, id,
@@ -2403,17 +2370,16 @@ bool XrayWrapper<Base, Traits>::getPrope
  * unwrap the wrapper).
  */
 
 template <typename Base, typename Traits>
 const xpc::XrayWrapper<Base, Traits> xpc::XrayWrapper<Base, Traits>::singleton(
     0);
 
 template class PermissiveXrayDOM;
-template class SecurityXrayDOM;
 template class PermissiveXrayJS;
 template class PermissiveXrayOpaque;
 
 /*
  * This callback is used by the JS engine to test if a proxy handler is for a
  * cross compartment xray with no security requirements.
  */
 static bool IsCrossCompartmentXrayCallback(
--- a/js/xpconnect/wrappers/XrayWrapper.h
+++ b/js/xpconnect/wrappers/XrayWrapper.h
@@ -441,25 +441,22 @@ class XrayWrapper : public Base {
 
  protected:
   bool getPropertyKeys(JSContext* cx, JS::Handle<JSObject*> wrapper,
                        unsigned flags, JS::AutoIdVector& props) const;
 };
 
 #define PermissiveXrayDOM \
   xpc::XrayWrapper<js::CrossCompartmentWrapper, xpc::DOMXrayTraits>
-#define SecurityXrayDOM \
-  xpc::XrayWrapper<js::CrossCompartmentSecurityWrapper, xpc::DOMXrayTraits>
 #define PermissiveXrayJS \
   xpc::XrayWrapper<js::CrossCompartmentWrapper, xpc::JSXrayTraits>
 #define PermissiveXrayOpaque \
   xpc::XrayWrapper<js::CrossCompartmentWrapper, xpc::OpaqueXrayTraits>
 
 extern template class PermissiveXrayDOM;
-extern template class SecurityXrayDOM;
 extern template class PermissiveXrayJS;
 extern template class PermissiveXrayOpaque;
 
 /*
  * Slots for Xray expando objects.  See comments in XrayWrapper.cpp for details
  * of how these get used; we mostly want the value of JSSLOT_EXPANDO_COUNT here.
  */
 enum ExpandoSlots {
--- a/layout/base/nsStyleSheetService.cpp
+++ b/layout/base/nsStyleSheetService.cpp
@@ -90,19 +90,16 @@ int32_t nsStyleSheetService::FindSheetBy
       return i;
     }
   }
 
   return -1;
 }
 
 nsresult nsStyleSheetService::Init() {
-  // If you make changes here, consider whether
-  // SVGDocument::EnsureNonSVGUserAgentStyleSheetsLoaded should be updated too.
-
   // Child processes get their style sheets from the ContentParent.
   if (XRE_IsContentProcess()) {
     return NS_OK;
   }
 
   // Enumerate all of the style sheet URIs registered in the category
   // manager and load them.
 
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -6510,24 +6510,24 @@ void nsBlockFrame::BuildDisplayList(nsDi
       lineCount++;
     }
 
     if (nonDecreasingYs && lineCount >= MIN_LINES_NEEDING_CURSOR) {
       SetupLineCursor();
     }
   }
 
-  // Pick up the resulting text-overflow markers.  We append them to
-  // PositionedDescendants just before we append the lines' display items,
-  // so that our text-overflow markers will appear on top of this block's
-  // normal content but below any of its its' positioned children.
+  linesDisplayListCollection.MoveTo(aLists);
+
   if (textOverflow.isSome()) {
-    aLists.PositionedDescendants()->AppendToTop(&textOverflow->GetMarkers());
-  }
-  linesDisplayListCollection.MoveTo(aLists);
+    // Put any text-overflow:ellipsis markers on top of the non-positioned
+    // content of the block's lines. (If we ever start sorting the Content()
+    // list this will end up in the wrong place.)
+    aLists.Content()->AppendToTop(&textOverflow->GetMarkers());
+  }
 
   if (HasOutsideBullet()) {
     // Display outside bullets manually
     nsIFrame* bullet = GetOutsideBullet();
     BuildDisplayListForChild(aBuilder, bullet, aLists);
   }
 
 #ifdef DEBUG
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -7889,19 +7889,19 @@ bool nsDisplayTransform::CreateWebRender
   bool animated =
       ActiveLayerTracker::IsStyleMaybeAnimated(Frame(), eCSSProperty_transform);
 
   bool preserve3D = mFrame->Extend3DContext() && !mIsTransformSeparator;
 
   StackingContextHelper sc(
       aSc, GetActiveScrolledRoot(), mFrame, this, aBuilder, filters,
       LayoutDeviceRect(position, LayoutDeviceSize()), &newTransformMatrix,
-      animationsId ? &prop : nullptr, nullptr, transformForSC, 
-      wr::ReferenceFrameKind::Transform, gfx::CompositionOp::OP_OVER, 
-      !BackfaceIsHidden(), preserve3D, deferredTransformItem, 
+      animationsId ? &prop : nullptr, nullptr, transformForSC,
+      wr::ReferenceFrameKind::Transform, gfx::CompositionOp::OP_OVER,
+      !BackfaceIsHidden(), preserve3D, deferredTransformItem,
       wr::WrStackingContextClip::None(), animated);
 
   return mStoredList.CreateWebRenderCommands(aBuilder, aResources, sc, aManager,
                                              aDisplayListBuilder);
 }
 
 bool nsDisplayTransform::UpdateScrollData(
     mozilla::layers::WebRenderScrollData* aData,
--- a/layout/painting/nsDisplayList.h
+++ b/layout/painting/nsDisplayList.h
@@ -672,17 +672,19 @@ class nsDisplayListBuilder {
   /**
    * Call this if we're doing normal painting to the window.
    */
   void SetPaintingToWindow(bool aToWindow) { mIsPaintingToWindow = aToWindow; }
   bool IsPaintingToWindow() const { return mIsPaintingToWindow; }
   /**
    * Call this if we're doing painting for WebRender
    */
-  void SetPaintingForWebRender(bool aForWebRender) { mIsPaintingForWebRender = true; }
+  void SetPaintingForWebRender(bool aForWebRender) {
+    mIsPaintingForWebRender = true;
+  }
   bool IsPaintingForWebRender() const { return mIsPaintingForWebRender; }
   /**
    * Call this to prevent descending into subdocuments.
    */
   void SetDescendIntoSubdocuments(bool aDescend) {
     mDescendIntoSubdocuments = aDescend;
   }
 
--- a/layout/reftests/forms/input/datetime/reftest.list
+++ b/layout/reftests/forms/input/datetime/reftest.list
@@ -14,8 +14,9 @@ default-preferences pref(dom.forms.datet
 == time-small-height.html time-small-height-ref.html
 == time-small-width-height.html time-small-width-height-ref.html
 
 # content (text) should be left aligned
 fuzzy-if(Android,0-4,0-8) == time-content-left-aligned.html time-content-left-aligned-ref.html
 
 # reset button should be right aligned
 skip-if(Android) == time-reset-button-right-aligned.html time-reset-button-right-aligned-ref.html # bug 1372062
+== reset-button-visibility-hidden.html reset-button-visibility-hidden-ref.html
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/input/datetime/reset-button-visibility-hidden-ref.html
@@ -0,0 +1,2 @@
+<!doctype html>
+<!-- intentionally blank -->
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/input/datetime/reset-button-visibility-hidden.html
@@ -0,0 +1,3 @@
+<!doctype html>
+<input type="date" value="2019-01-18" style="visibility: hidden">
+<input type="time" value="16:30" style="visibility: hidden">
--- a/layout/style/FontFaceSet.cpp
+++ b/layout/style/FontFaceSet.cpp
@@ -576,16 +576,17 @@ nsresult FontFaceSet::StartLoad(gfxUserF
       principal ? principal->get() : nullptr,
       nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS, nsIContentPolicy::TYPE_FONT,
       nullptr,  // PerformanceStorage
       loadGroup);
   NS_ENSURE_SUCCESS(rv, rv);
 
   RefPtr<nsFontFaceLoader> fontLoader = new nsFontFaceLoader(
       aUserFontEntry, aFontFaceSrc->mURI->get(), this, channel);
+  mLoaders.PutEntry(fontLoader);
 
   if (LOG_ENABLED()) {
     LOG(
         ("userfonts (%p) download start - font uri: (%s) "
          "referrer uri: (%s)\n",
          fontLoader.get(), aFontFaceSrc->mURI->GetSpecOrDefault().get(),
          aFontFaceSrc->mReferrer
              ? aFontFaceSrc->mReferrer->GetSpecOrDefault().get()
@@ -633,17 +634,16 @@ nsresult FontFaceSet::StartLoad(gfxUserF
       nsINetworkPredictor::LEARN_LOAD_SUBRESOURCE, loadGroup);
 
   rv = channel->AsyncOpen2(streamLoader);
   if (NS_FAILED(rv)) {
     fontLoader->DropChannel();  // explicitly need to break ref cycle
   }
 
   if (NS_SUCCEEDED(rv)) {
-    mLoaders.PutEntry(fontLoader);
     fontLoader->StartedLoading(streamLoader);
     // let the font entry remember the loader, in case we need to cancel it
     aUserFontEntry->SetLoader(fontLoader);
   }
 
   return rv;
 }
 
--- a/layout/style/nsFontFaceLoader.cpp
+++ b/layout/style/nsFontFaceLoader.cpp
@@ -186,16 +186,18 @@ NS_IMPL_ISUPPORTS(nsFontFaceLoader, nsIS
 // nsIStreamLoaderObserver
 NS_IMETHODIMP
 nsFontFaceLoader::OnStreamComplete(nsIStreamLoader* aLoader,
                                    nsISupports* aContext, nsresult aStatus,
                                    uint32_t aStringLen,
                                    const uint8_t* aString) {
   MOZ_ASSERT(NS_IsMainThread());
 
+  DropChannel();
+
   if (!mFontFaceSet) {
     // We've been canceled
     return aStatus;
   }
 
   mFontFaceSet->RemoveLoader(this);
 
   TimeStamp doneTime = TimeStamp::Now();
@@ -293,27 +295,29 @@ nsFontFaceLoader::OnStartRequest(nsIRequ
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsFontFaceLoader::OnStopRequest(nsIRequest* aRequest, nsISupports* aContext,
                                 nsresult aStatusCode) {
   MOZ_ASSERT(NS_IsMainThread());
+  DropChannel();
   return NS_OK;
 }
 
 void nsFontFaceLoader::Cancel() {
   mUserFontEntry->LoadCanceled();
   mFontFaceSet = nullptr;
   if (mLoadTimer) {
     mLoadTimer->Cancel();
     mLoadTimer = nullptr;
   }
-  mChannel->Cancel(NS_BINDING_ABORTED);
+  nsCOMPtr<nsIChannel> channel = mChannel.forget();
+  channel->Cancel(NS_BINDING_ABORTED);
 }
 
 StyleFontDisplay nsFontFaceLoader::GetFontDisplay() {
   if (!StaticPrefs::layout_css_font_display_enabled()) {
     return StyleFontDisplay::Auto;
   }
   return mUserFontEntry->GetFontDisplay();
 }
--- a/layout/style/nsFontFaceLoader.h
+++ b/layout/style/nsFontFaceLoader.h
@@ -50,16 +50,17 @@ class nsFontFaceLoader final : public ns
   virtual ~nsFontFaceLoader();
 
   // helper method for determining the font-display value
   mozilla::StyleFontDisplay GetFontDisplay();
 
  private:
   RefPtr<gfxUserFontEntry> mUserFontEntry;
   nsCOMPtr<nsIURI> mFontURI;
-  RefPtr<mozilla::dom::FontFaceSet> mFontFaceSet;
+  // Cleared in FontFaceSet::~FontFaceSet, and on cancelation and such too.
+  mozilla::dom::FontFaceSet* MOZ_NON_OWNING_REF mFontFaceSet;
   nsCOMPtr<nsIChannel> mChannel;
   nsCOMPtr<nsITimer> mLoadTimer;
   mozilla::TimeStamp mStartTime;
   nsIStreamLoader* mStreamLoader;
 };
 
 #endif /* !defined(nsFontFaceLoader_h_) */
--- a/media/libdav1d/asm/moz.build
+++ b/media/libdav1d/asm/moz.build
@@ -21,31 +21,28 @@ CFLAGS += [
     '-I%s/dist/include/dav1d/' % TOPOBJDIR,
 ]
 
 # This is Linux only for now
 
 # Attaching config.asm file
 if CONFIG['CPU_ARCH'] == 'x86':
     ASFLAGS += ['-I%s/media/libdav1d/asm/x86_32/' % TOPSRCDIR]
-    SOURCES += ['x86_32/config.asm']
 
 if CONFIG['CPU_ARCH'] == 'x86_64':
     # Change the default stack aligment (16) to 32
     if CONFIG['CC_TYPE'] == 'clang':
         CFLAGS += ['-mstack-alignment=32']
     elif CONFIG['CC_TYPE'] == 'gcc':
         CFLAGS += ['-mpreferred-stack-boundary=5']
 
     if CONFIG['OS_TARGET'] == 'Darwin':
         ASFLAGS += ['-I%s/media/libdav1d/asm/x86_64/osx/' % TOPSRCDIR]
-        SOURCES += ['x86_64/osx/config.asm']
     else:
         ASFLAGS += ['-I%s/media/libdav1d/asm/x86_64/' % TOPSRCDIR]
-        SOURCES += ['x86_64/config.asm']
 
 if CONFIG['CPU_ARCH'] in ('x86', 'x86_64'):
     SOURCES += [
         '../../../third_party/dav1d/src/x86/cpu.c',
     ]
 
     EXPORTS.dav1d += [
         '../../../third_party/dav1d/src/x86/cpu.h',
new file mode 100644
--- /dev/null
+++ b/media/libvpx/config/linux/arm64/vp8_rtcd.h
@@ -0,0 +1,201 @@
+// This file is generated. Do not edit.
+#ifndef VP8_RTCD_H_
+#define VP8_RTCD_H_
+
+#ifdef RTCD_C
+#define RTCD_EXTERN
+#else
+#define RTCD_EXTERN extern
+#endif
+
+/*
+ * VP8
+ */
+
+struct blockd;
+struct macroblockd;
+struct loop_filter_info;
+
+/* Encoder forward decls */
+struct block;
+struct macroblock;
+struct variance_vtable;
+union int_mv;
+struct yv12_buffer_config;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void vp8_bilinear_predict16x16_c(unsigned char *src, int src_pitch, int xofst, int yofst, unsigned char *dst, int dst_pitch);
+void vp8_bilinear_predict16x16_neon(unsigned char *src, int src_pitch, int xofst, int yofst, unsigned char *dst, int dst_pitch);
+#define vp8_bilinear_predict16x16 vp8_bilinear_predict16x16_neon
+
+void vp8_bilinear_predict4x4_c(unsigned char *src, int src_pitch, int xofst, int yofst, unsigned char *dst, int dst_pitch);
+void vp8_bilinear_predict4x4_neon(unsigned char *src, int src_pitch, int xofst, int yofst, unsigned char *dst, int dst_pitch);
+#define vp8_bilinear_predict4x4 vp8_bilinear_predict4x4_neon
+
+void vp8_bilinear_predict8x4_c(unsigned char *src, int src_pitch, int xofst, int yofst, unsigned char *dst, int dst_pitch);
+void vp8_bilinear_predict8x4_neon(unsigned char *src, int src_pitch, int xofst, int yofst, unsigned char *dst, int dst_pitch);
+#define vp8_bilinear_predict8x4 vp8_bilinear_predict8x4_neon
+
+void vp8_bilinear_predict8x8_c(unsigned char *src, int src_pitch, int xofst, int yofst, unsigned char *dst, int dst_pitch);
+void vp8_bilinear_predict8x8_neon(unsigned char *src, int src_pitch, int xofst, int yofst, unsigned char *dst, int dst_pitch);
+#define vp8_bilinear_predict8x8 vp8_bilinear_predict8x8_neon
+
+int vp8_block_error_c(short *coeff, short *dqcoeff);
+#define vp8_block_error vp8_block_error_c
+
+void vp8_copy_mem16x16_c(unsigned char *src, int src_pitch, unsigned char *dst, int dst_pitch);
+void vp8_copy_mem16x16_neon(unsigned char *src, int src_pitch, unsigned char *dst, int dst_pitch);
+#define vp8_copy_mem16x16 vp8_copy_mem16x16_neon
+
+void vp8_copy_mem8x4_c(unsigned char *src, int src_pitch, unsigned char *dst, int dst_pitch);
+void vp8_copy_mem8x4_neon(unsigned char *src, int src_pitch, unsigned char *dst, int dst_pitch);
+#define vp8_copy_mem8x4 vp8_copy_mem8x4_neon
+
+void vp8_copy_mem8x8_c(unsigned char *src, int src_pitch, unsigned char *dst, int dst_pitch);
+void vp8_copy_mem8x8_neon(unsigned char *src, int src_pitch, unsigned char *dst, int dst_pitch);
+#define vp8_copy_mem8x8 vp8_copy_mem8x8_neon
+
+void vp8_dc_only_idct_add_c(short input, unsigned char *pred, int pred_stride, unsigned char *dst, int dst_stride);
+void vp8_dc_only_idct_add_neon(short input, unsigned char *pred, int pred_stride, unsigned char *dst, int dst_stride);
+#define vp8_dc_only_idct_add vp8_dc_only_idct_add_neon
+
+int vp8_denoiser_filter_c(unsigned char *mc_running_avg_y, int mc_avg_y_stride, unsigned char *running_avg_y, int avg_y_stride, unsigned char *sig, int sig_stride, unsigned int motion_magnitude, int increase_denoising);
+int vp8_denoiser_filter_neon(unsigned char *mc_running_avg_y, int mc_avg_y_stride, unsigned char *running_avg_y, int avg_y_stride, unsigned char *sig, int sig_stride, unsigned int motion_magnitude, int increase_denoising);
+#define vp8_denoiser_filter vp8_denoiser_filter_neon
+
+int vp8_denoiser_filter_uv_c(unsigned char *mc_running_avg, int mc_avg_stride, unsigned char *running_avg, int avg_stride, unsigned char *sig, int sig_stride, unsigned int motion_magnitude, int increase_denoising);
+int vp8_denoiser_filter_uv_neon(unsigned char *mc_running_avg, int mc_avg_stride, unsigned char *running_avg, int avg_stride, unsigned char *sig, int sig_stride, unsigned int motion_magnitude, int increase_denoising);
+#define vp8_denoiser_filter_uv vp8_denoiser_filter_uv_neon
+
+void vp8_dequant_idct_add_c(short *input, short *dq, unsigned char *output, int stride);
+void vp8_dequant_idct_add_neon(short *input, short *dq, unsigned char *output, int stride);
+#define vp8_dequant_idct_add vp8_dequant_idct_add_neon
+
+void vp8_dequant_idct_add_uv_block_c(short *q, short *dq, unsigned char *dst_u, unsigned char *dst_v, int stride, char *eobs);
+void vp8_dequant_idct_add_uv_block_neon(short *q, short *dq, unsigned char *dst_u, unsigned char *dst_v, int stride, char *eobs);
+#define vp8_dequant_idct_add_uv_block vp8_dequant_idct_add_uv_block_neon
+
+void vp8_dequant_idct_add_y_block_c(short *q, short *dq, unsigned char *dst, int stride, char *eobs);
+void vp8_dequant_idct_add_y_block_neon(short *q, short *dq, unsigned char *dst, int stride, char *eobs);
+#define vp8_dequant_idct_add_y_block vp8_dequant_idct_add_y_block_neon
+
+void vp8_dequantize_b_c(struct blockd*, short *dqc);
+void vp8_dequantize_b_neon(struct blockd*, short *dqc);
+#define vp8_dequantize_b vp8_dequantize_b_neon
+
+int vp8_diamond_search_sad_c(struct macroblock *x, struct block *b, struct blockd *d, union int_mv *ref_mv, union int_mv *best_mv, int search_param, int sad_per_bit, int *num00, struct variance_vtable *fn_ptr, int *mvcost[2], union int_mv *center_mv);
+#define vp8_diamond_search_sad vp8_diamond_search_sad_c
+
+void vp8_fast_quantize_b_c(struct block *, struct blockd *);
+void vp8_fast_quantize_b_neon(struct block *, struct blockd *);
+#define vp8_fast_quantize_b vp8_fast_quantize_b_neon
+
+int vp8_full_search_sad_c(struct macroblock *x, struct block *b, struct blockd *d, union int_mv *ref_mv, int sad_per_bit, int distance, struct variance_vtable *fn_ptr, int *mvcost[2], union int_mv *center_mv);
+#define vp8_full_search_sad vp8_full_search_sad_c
+
+void vp8_loop_filter_bh_c(unsigned char *y, unsigned char *u, unsigned char *v, int ystride, int uv_stride, struct loop_filter_info *lfi);
+void vp8_loop_filter_bh_neon(unsigned char *y, unsigned char *u, unsigned char *v, int ystride, int uv_stride, struct loop_filter_info *lfi);
+#define vp8_loop_filter_bh vp8_loop_filter_bh_neon
+
+void vp8_loop_filter_bv_c(unsigned char *y, unsigned char *u, unsigned char *v, int ystride, int uv_stride, struct loop_filter_info *lfi);
+void vp8_loop_filter_bv_neon(unsigned char *y, unsigned char *u, unsigned char *v, int ystride, int uv_stride, struct loop_filter_info *lfi);
+#define vp8_loop_filter_bv vp8_loop_filter_bv_neon
+
+void vp8_loop_filter_mbh_c(unsigned char *y, unsigned char *u, unsigned char *v, int ystride, int uv_stride, struct loop_filter_info *lfi);
+void vp8_loop_filter_mbh_neon(unsigned char *y, unsigned char *u, unsigned char *v, int ystride, int uv_stride, struct loop_filter_info *lfi);
+#define vp8_loop_filter_mbh vp8_loop_filter_mbh_neon
+
+void vp8_loop_filter_mbv_c(unsigned char *y, unsigned char *u, unsigned char *v, int ystride, int uv_stride, struct loop_filter_info *lfi);
+void vp8_loop_filter_mbv_neon(unsigned char *y, unsigned char *u, unsigned char *v, int ystride, int uv_stride, struct loop_filter_info *lfi);
+#define vp8_loop_filter_mbv vp8_loop_filter_mbv_neon
+
+void vp8_loop_filter_bhs_c(unsigned char *y, int ystride, const unsigned char *blimit);
+void vp8_loop_filter_bhs_neon(unsigned char *y, int ystride, const unsigned char *blimit);
+#define vp8_loop_filter_simple_bh vp8_loop_filter_bhs_neon
+
+void vp8_loop_filter_bvs_c(unsigned char *y, int ystride, const unsigned char *blimit);
+void vp8_loop_filter_bvs_neon(unsigned char *y, int ystride, const unsigned char *blimit);
+#define vp8_loop_filter_simple_bv vp8_loop_filter_bvs_neon
+
+void vp8_loop_filter_simple_horizontal_edge_c(unsigned char *y, int ystride, const unsigned char *blimit);
+void vp8_loop_filter_mbhs_neon(unsigned char *y, int ystride, const unsigned char *blimit);
+#define vp8_loop_filter_simple_mbh vp8_loop_filter_mbhs_neon
+
+void vp8_loop_filter_simple_vertical_edge_c(unsigned char *y, int ystride, const unsigned char *blimit);
+void vp8_loop_filter_mbvs_neon(unsigned char *y, int ystride, const unsigned char *blimit);
+#define vp8_loop_filter_simple_mbv vp8_loop_filter_mbvs_neon
+
+int vp8_mbblock_error_c(struct macroblock *mb, int dc);
+#define vp8_mbblock_error vp8_mbblock_error_c
+
+int vp8_mbuverror_c(struct macroblock *mb);
+#define vp8_mbuverror vp8_mbuverror_c
+
+int vp8_refining_search_sad_c(struct macroblock *x, struct block *b, struct blockd *d, union int_mv *ref_mv, int sad_per_bit, int distance, struct variance_vtable *fn_ptr, int *mvcost[2], union int_mv *center_mv);
+#define vp8_refining_search_sad vp8_refining_search_sad_c
+
+void vp8_regular_quantize_b_c(struct block *, struct blockd *);
+#define vp8_regular_quantize_b vp8_regular_quantize_b_c
+
+void vp8_short_fdct4x4_c(short *input, short *output, int pitch);
+void vp8_short_fdct4x4_neon(short *input, short *output, int pitch);
+#define vp8_short_fdct4x4 vp8_short_fdct4x4_neon
+
+void vp8_short_fdct8x4_c(short *input, short *output, int pitch);
+void vp8_short_fdct8x4_neon(short *input, short *output, int pitch);
+#define vp8_short_fdct8x4 vp8_short_fdct8x4_neon
+
+void vp8_short_idct4x4llm_c(short *input, unsigned char *pred, int pitch, unsigned char *dst, int dst_stride);
+void vp8_short_idct4x4llm_neon(short *input, unsigned char *pred, int pitch, unsigned char *dst, int dst_stride);
+#define vp8_short_idct4x4llm vp8_short_idct4x4llm_neon
+
+void vp8_short_inv_walsh4x4_c(short *input, short *output);
+void vp8_short_inv_walsh4x4_neon(short *input, short *output);
+#define vp8_short_inv_walsh4x4 vp8_short_inv_walsh4x4_neon
+
+void vp8_short_inv_walsh4x4_1_c(short *input, short *output);
+#define vp8_short_inv_walsh4x4_1 vp8_short_inv_walsh4x4_1_c
+
+void vp8_short_walsh4x4_c(short *input, short *output, int pitch);
+void vp8_short_walsh4x4_neon(short *input, short *output, int pitch);
+#define vp8_short_walsh4x4 vp8_short_walsh4x4_neon
+
+void vp8_sixtap_predict16x16_c(unsigned char *src, int src_pitch, int xofst, int yofst, unsigned char *dst, int dst_pitch);
+void vp8_sixtap_predict16x16_neon(unsigned char *src, int src_pitch, int xofst, int yofst, unsigned char *dst, int dst_pitch);
+#define vp8_sixtap_predict16x16 vp8_sixtap_predict16x16_neon
+
+void vp8_sixtap_predict4x4_c(unsigned char *src, int src_pitch, int xofst, int yofst, unsigned char *dst, int dst_pitch);
+void vp8_sixtap_predict4x4_neon(unsigned char *src, int src_pitch, int xofst, int yofst, unsigned char *dst, int dst_pitch);
+#define vp8_sixtap_predict4x4 vp8_sixtap_predict4x4_neon
+
+void vp8_sixtap_predict8x4_c(unsigned char *src, int src_pitch, int xofst, int yofst, unsigned char *dst, int dst_pitch);
+void vp8_sixtap_predict8x4_neon(unsigned char *src, int src_pitch, int xofst, int yofst, unsigned char *dst, int dst_pitch);
+#define vp8_sixtap_predict8x4 vp8_sixtap_predict8x4_neon
+
+void vp8_sixtap_predict8x8_c(unsigned char *src, int src_pitch, int xofst, int yofst, unsigned char *dst, int dst_pitch);
+void vp8_sixtap_predict8x8_neon(unsigned char *src, int src_pitch, int xofst, int yofst, unsigned char *dst, int dst_pitch);
+#define vp8_sixtap_predict8x8 vp8_sixtap_predict8x8_neon
+
+void vp8_rtcd(void);
+
+#include "vpx_config.h"
+
+#ifdef RTCD_C
+#include "vpx_ports/arm.h"
+static void setup_rtcd_internal(void)
+{
+    int flags = arm_cpu_caps();
+
+    (void)flags;
+
+}
+#endif
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif
new file mode 100644
--- /dev/null
+++ b/media/libvpx/config/linux/arm64/vp9_rtcd.h
@@ -0,0 +1,102 @@
+// This file is generated. Do not edit.
+#ifndef VP9_RTCD_H_
+#define VP9_RTCD_H_
+
+#ifdef RTCD_C
+#define RTCD_EXTERN
+#else
+#define RTCD_EXTERN extern
+#endif
+
+/*
+ * VP9
+ */
+
+#include "vpx/vpx_integer.h"
+#include "vp9/common/vp9_common.h"
+#include "vp9/common/vp9_enums.h"
+#include "vp9/common/vp9_filter.h"
+
+struct macroblockd;
+
+/* Encoder forward decls */
+struct macroblock;
+struct vp9_variance_vtable;
+struct search_site_config;
+struct mv;
+union int_mv;
+struct yv12_buffer_config;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int64_t vp9_block_error_c(const tran_low_t *coeff, const tran_low_t *dqcoeff, intptr_t block_size, int64_t *ssz);
+#define vp9_block_error vp9_block_error_c
+
+int64_t vp9_block_error_fp_c(const tran_low_t *coeff, const tran_low_t *dqcoeff, int block_size);
+int64_t vp9_block_error_fp_neon(const tran_low_t *coeff, const tran_low_t *dqcoeff, int block_size);
+#define vp9_block_error_fp vp9_block_error_fp_neon
+
+int vp9_diamond_search_sad_c(const struct macroblock *x, const struct search_site_config *cfg,  struct mv *ref_mv, struct mv *best_mv, int search_param, int sad_per_bit, int *num00, const struct vp9_variance_vtable *fn_ptr, const struct mv *center_mv);
+#define vp9_diamond_search_sad vp9_diamond_search_sad_c
+
+void vp9_fdct8x8_quant_c(const int16_t *input, int stride, tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block, const int16_t *round_ptr, const int16_t *quant_ptr, tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan);
+void vp9_fdct8x8_quant_neon(const int16_t *input, int stride, tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block, const int16_t *round_ptr, const int16_t *quant_ptr, tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan);
+#define vp9_fdct8x8_quant vp9_fdct8x8_quant_neon
+
+void vp9_fht16x16_c(const int16_t *input, tran_low_t *output, int stride, int tx_type);
+#define vp9_fht16x16 vp9_fht16x16_c
+
+void vp9_fht4x4_c(const int16_t *input, tran_low_t *output, int stride, int tx_type);
+#define vp9_fht4x4 vp9_fht4x4_c
+
+void vp9_fht8x8_c(const int16_t *input, tran_low_t *output, int stride, int tx_type);
+#define vp9_fht8x8 vp9_fht8x8_c
+
+void vp9_fwht4x4_c(const int16_t *input, tran_low_t *output, int stride);
+#define vp9_fwht4x4 vp9_fwht4x4_c
+
+void vp9_iht16x16_256_add_c(const tran_low_t *input, uint8_t *output, int pitch, int tx_type);
+#define vp9_iht16x16_256_add vp9_iht16x16_256_add_c
+
+void vp9_iht4x4_16_add_c(const tran_low_t *input, uint8_t *dest, int stride, int tx_type);
+void vp9_iht4x4_16_add_neon(const tran_low_t *input, uint8_t *dest, int stride, int tx_type);
+#define vp9_iht4x4_16_add vp9_iht4x4_16_add_neon
+
+void vp9_iht8x8_64_add_c(const tran_low_t *input, uint8_t *dest, int stride, int tx_type);
+void vp9_iht8x8_64_add_neon(const tran_low_t *input, uint8_t *dest, int stride, int tx_type);
+#define vp9_iht8x8_64_add vp9_iht8x8_64_add_neon
+
+void vp9_quantize_fp_c(const tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block, const int16_t *round_ptr, const int16_t *quant_ptr, tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan);
+void vp9_quantize_fp_neon(const tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block, const int16_t *round_ptr, const int16_t *quant_ptr, tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan);
+#define vp9_quantize_fp vp9_quantize_fp_neon
+
+void vp9_quantize_fp_32x32_c(const tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block, const int16_t *round_ptr, const int16_t *quant_ptr, tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan);
+void vp9_quantize_fp_32x32_neon(const tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block, const int16_t *round_ptr, const int16_t *quant_ptr, tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan);
+#define vp9_quantize_fp_32x32 vp9_quantize_fp_32x32_neon
+
+void vp9_scale_and_extend_frame_c(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, INTERP_FILTER filter_type, int phase_scaler);
+void vp9_scale_and_extend_frame_neon(const struct yv12_buffer_config *src, struct yv12_buffer_config *dst, INTERP_FILTER filter_type, int phase_scaler);
+#define vp9_scale_and_extend_frame vp9_scale_and_extend_frame_neon
+
+void vp9_rtcd(void);
+
+#include "vpx_config.h"
+
+#ifdef RTCD_C
+#include "vpx_ports/arm.h"
+static void setup_rtcd_internal(void)
+{
+    int flags = arm_cpu_caps();
+
+    (void)flags;
+
+}
+#endif
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif
new file mode 100644
--- /dev/null
+++ b/media/libvpx/config/linux/arm64/vpx_config.asm
@@ -0,0 +1,86 @@
+@ This file was created from a .asm file
+@  using the ads2gas.pl script.
+	.equ DO1STROUNDING, 0
+.equ ARCH_ARM ,  1
+.equ ARCH_MIPS ,  0
+.equ ARCH_X86 ,  0
+.equ ARCH_X86_64 ,  0
+.equ ARCH_PPC ,  0
+.equ HAVE_NEON ,  1
+.equ HAVE_NEON_ASM ,  0
+.equ HAVE_MIPS32 ,  0
+.equ HAVE_DSPR2 ,  0
+.equ HAVE_MSA ,  0
+.equ HAVE_MIPS64 ,  0
+.equ HAVE_MMX ,  0
+.equ HAVE_SSE ,  0
+.equ HAVE_SSE2 ,  0
+.equ HAVE_SSE3 ,  0
+.equ HAVE_SSSE3 ,  0
+.equ HAVE_SSE4_1 ,  0
+.equ HAVE_AVX ,  0
+.equ HAVE_AVX2 ,  0
+.equ HAVE_AVX512 ,  0
+.equ HAVE_VSX ,  0
+.equ HAVE_MMI ,  0
+.equ HAVE_VPX_PORTS ,  1
+.equ HAVE_PTHREAD_H ,  1
+.equ CONFIG_DEPENDENCY_TRACKING ,  1
+.equ CONFIG_EXTERNAL_BUILD ,  1
+.equ CONFIG_INSTALL_DOCS ,  0
+.equ CONFIG_INSTALL_BINS ,  1
+.equ CONFIG_INSTALL_LIBS ,  1
+.equ CONFIG_INSTALL_SRCS ,  0
+.equ CONFIG_DEBUG ,  0
+.equ CONFIG_GPROF ,  0
+.equ CONFIG_GCOV ,  0
+.equ CONFIG_RVCT ,  0
+.equ CONFIG_GCC ,  1
+.equ CONFIG_MSVS ,  0
+.equ CONFIG_PIC ,  1
+.equ CONFIG_BIG_ENDIAN ,  0
+.equ CONFIG_CODEC_SRCS ,  0
+.equ CONFIG_DEBUG_LIBS ,  0
+.equ CONFIG_DEQUANT_TOKENS ,  0
+.equ CONFIG_DC_RECON ,  0
+.equ CONFIG_RUNTIME_CPU_DETECT ,  0
+.equ CONFIG_POSTPROC ,  0
+.equ CONFIG_VP9_POSTPROC ,  0
+.equ CONFIG_MULTITHREAD ,  1
+.equ CONFIG_INTERNAL_STATS ,  0
+.equ CONFIG_VP8_ENCODER ,  1
+.equ CONFIG_VP8_DECODER ,  1
+.equ CONFIG_VP9_ENCODER ,  1
+.equ CONFIG_VP9_DECODER ,  1
+.equ CONFIG_VP8 ,  1
+.equ CONFIG_VP9 ,  1
+.equ CONFIG_ENCODERS ,  1
+.equ CONFIG_DECODERS ,  1
+.equ CONFIG_STATIC_MSVCRT ,  0
+.equ CONFIG_SPATIAL_RESAMPLING ,  1
+.equ CONFIG_REALTIME_ONLY ,  1
+.equ CONFIG_ONTHEFLY_BITPACKING ,  0
+.equ CONFIG_ERROR_CONCEALMENT ,  0
+.equ CONFIG_SHARED ,  0
+.equ CONFIG_STATIC ,  1
+.equ CONFIG_SMALL ,  0
+.equ CONFIG_POSTPROC_VISUALIZER ,  0
+.equ CONFIG_OS_SUPPORT ,  1
+.equ CONFIG_UNIT_TESTS ,  0
+.equ CONFIG_WEBM_IO ,  1
+.equ CONFIG_LIBYUV ,  1
+.equ CONFIG_DECODE_PERF_TESTS ,  0
+.equ CONFIG_ENCODE_PERF_TESTS ,  0
+.equ CONFIG_MULTI_RES_ENCODING ,  1
+.equ CONFIG_TEMPORAL_DENOISING ,  1
+.equ CONFIG_VP9_TEMPORAL_DENOISING ,  0
+.equ CONFIG_COEFFICIENT_RANGE_CHECKING ,  0
+.equ CONFIG_VP9_HIGHBITDEPTH ,  0
+.equ CONFIG_BETTER_HW_COMPATIBILITY ,  0
+.equ CONFIG_EXPERIMENTAL ,  0
+.equ CONFIG_SIZE_LIMIT ,  1
+.equ CONFIG_ALWAYS_ADJUST_BPM ,  0
+.equ CONFIG_SPATIAL_SVC ,  0
+.equ CONFIG_FP_MB_STATS ,  0
+.equ CONFIG_EMULATE_HARDWARE ,  0
+	.section	.note.GNU-stack,"",%progbits
new file mode 100644
--- /dev/null
+++ b/media/libvpx/config/linux/arm64/vpx_config.c
@@ -0,0 +1,10 @@
+/* Copyright (c) 2011 The WebM project authors. All Rights Reserved. */
+/*  */
+/* Use of this source code is governed by a BSD-style license */
+/* that can be found in the LICENSE file in the root of the source */
+/* tree. An additional intellectual property rights grant can be found */
+/* in the file PATENTS.  All contributing project authors may */
+/* be found in the AUTHORS file in the root of the source tree. */
+#include "vpx/vpx_codec.h"
+static const char* const cfg = "--target=arm64-linux-gcc --enable-external-build --disable-examples --disable-install-docs --disable-unit-tests --enable-multi-res-encoding --size-limit=8192x4608 --enable-pic --disable-avx512 --enable-realtime-only";
+const char *vpx_codec_build_config(void) {return cfg;}
new file mode 100644
--- /dev/null
+++ b/media/libvpx/config/linux/arm64/vpx_config.h
@@ -0,0 +1,97 @@
+/* Copyright (c) 2011 The WebM project authors. All Rights Reserved. */
+/*  */
+/* Use of this source code is governed by a BSD-style license */
+/* that can be found in the LICENSE file in the root of the source */
+/* tree. An additional intellectual property rights grant can be found */
+/* in the file PATENTS.  All contributing project authors may */
+/* be found in the AUTHORS file in the root of the source tree. */
+/* This file automatically generated by configure. Do not edit! */
+#ifndef VPX_CONFIG_H
+#define VPX_CONFIG_H
+#define RESTRICT    
+#define INLINE      inline
+#define ARCH_ARM 1
+#define ARCH_MIPS 0
+#define ARCH_X86 0
+#define ARCH_X86_64 0
+#define ARCH_PPC 0
+#define HAVE_NEON 1
+#define HAVE_NEON_ASM 0
+#define HAVE_MIPS32 0
+#define HAVE_DSPR2 0
+#define HAVE_MSA 0
+#define HAVE_MIPS64 0
+#define HAVE_MMX 0
+#define HAVE_SSE 0
+#define HAVE_SSE2 0
+#define HAVE_SSE3 0
+#define HAVE_SSSE3 0
+#define HAVE_SSE4_1 0
+#define HAVE_AVX 0
+#define HAVE_AVX2 0
+#define HAVE_AVX512 0
+#define HAVE_VSX 0
+#define HAVE_MMI 0
+#define HAVE_VPX_PORTS 1
+#define HAVE_PTHREAD_H 1
+#define CONFIG_DEPENDENCY_TRACKING 1
+#define CONFIG_EXTERNAL_BUILD 1
+#define CONFIG_INSTALL_DOCS 0
+#define CONFIG_INSTALL_BINS 1
+#define CONFIG_INSTALL_LIBS 1
+#define CONFIG_INSTALL_SRCS 0
+#define CONFIG_DEBUG 0
+#define CONFIG_GPROF 0
+#define CONFIG_GCOV 0
+#define CONFIG_RVCT 0
+#define CONFIG_GCC 1
+#define CONFIG_MSVS 0
+#define CONFIG_PIC 1
+#define CONFIG_BIG_ENDIAN 0
+#define CONFIG_CODEC_SRCS 0
+#define CONFIG_DEBUG_LIBS 0
+#define CONFIG_DEQUANT_TOKENS 0
+#define CONFIG_DC_RECON 0
+#define CONFIG_RUNTIME_CPU_DETECT 0
+#define CONFIG_POSTPROC 0
+#define CONFIG_VP9_POSTPROC 0
+#define CONFIG_MULTITHREAD 1
+#define CONFIG_INTERNAL_STATS 0
+#define CONFIG_VP8_ENCODER 1
+#define CONFIG_VP8_DECODER 1
+#define CONFIG_VP9_ENCODER 1
+#define CONFIG_VP9_DECODER 1
+#define CONFIG_VP8 1
+#define CONFIG_VP9 1
+#define CONFIG_ENCODERS 1
+#define CONFIG_DECODERS 1
+#define CONFIG_STATIC_MSVCRT 0
+#define CONFIG_SPATIAL_RESAMPLING 1
+#define CONFIG_REALTIME_ONLY 1
+#define CONFIG_ONTHEFLY_BITPACKING 0
+#define CONFIG_ERROR_CONCEALMENT 0
+#define CONFIG_SHARED 0
+#define CONFIG_STATIC 1
+#define CONFIG_SMALL 0
+#define CONFIG_POSTPROC_VISUALIZER 0
+#define CONFIG_OS_SUPPORT 1
+#define CONFIG_UNIT_TESTS 0
+#define CONFIG_WEBM_IO 1
+#define CONFIG_LIBYUV 1
+#define CONFIG_DECODE_PERF_TESTS 0
+#define CONFIG_ENCODE_PERF_TESTS 0
+#define CONFIG_MULTI_RES_ENCODING 1
+#define CONFIG_TEMPORAL_DENOISING 1
+#define CONFIG_VP9_TEMPORAL_DENOISING 0
+#define CONFIG_COEFFICIENT_RANGE_CHECKING 0
+#define CONFIG_VP9_HIGHBITDEPTH 0
+#define CONFIG_BETTER_HW_COMPATIBILITY 0
+#define CONFIG_EXPERIMENTAL 0
+#define CONFIG_SIZE_LIMIT 1
+#define CONFIG_ALWAYS_ADJUST_BPM 0
+#define CONFIG_SPATIAL_SVC 0
+#define CONFIG_FP_MB_STATS 0
+#define CONFIG_EMULATE_HARDWARE 0
+#define DECODE_WIDTH_LIMIT 8192
+#define DECODE_HEIGHT_LIMIT 4608
+#endif /* VPX_CONFIG_H */
new file mode 100644
--- /dev/null
+++ b/media/libvpx/config/linux/arm64/vpx_dsp_rtcd.h
@@ -0,0 +1,865 @@
+// This file is generated. Do not edit.
+#ifndef VPX_DSP_RTCD_H_
+#define VPX_DSP_RTCD_H_
+
+#ifdef RTCD_C
+#define RTCD_EXTERN
+#else
+#define RTCD_EXTERN extern
+#endif
+
+/*
+ * DSP
+ */
+
+#include "vpx/vpx_integer.h"
+#include "vpx_dsp/vpx_dsp_common.h"
+#include "vpx_dsp/vpx_filter.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+unsigned int vpx_avg_4x4_c(const uint8_t *, int p);
+unsigned int vpx_avg_4x4_neon(const uint8_t *, int p);
+#define vpx_avg_4x4 vpx_avg_4x4_neon
+
+unsigned int vpx_avg_8x8_c(const uint8_t *, int p);
+unsigned int vpx_avg_8x8_neon(const uint8_t *, int p);
+#define vpx_avg_8x8 vpx_avg_8x8_neon
+
+void vpx_comp_avg_pred_c(uint8_t *comp_pred, const uint8_t *pred, int width, int height, const uint8_t *ref, int ref_stride);
+void vpx_comp_avg_pred_neon(uint8_t *comp_pred, const uint8_t *pred, int width, int height, const uint8_t *ref, int ref_stride);
+#define vpx_comp_avg_pred vpx_comp_avg_pred_neon
+
+void vpx_convolve8_c(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const InterpKernel *filter, int x0_q4, int x_step_q4, int y0_q4, int y_step_q4, int w, int h);
+void vpx_convolve8_neon(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const InterpKernel *filter, int x0_q4, int x_step_q4, int y0_q4, int y_step_q4, int w, int h);
+#define vpx_convolve8 vpx_convolve8_neon
+
+void vpx_convolve8_avg_c(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const InterpKernel *filter, int x0_q4, int x_step_q4, int y0_q4, int y_step_q4, int w, int h);
+void vpx_convolve8_avg_neon(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const InterpKernel *filter, int x0_q4, int x_step_q4, int y0_q4, int y_step_q4, int w, int h);
+#define vpx_convolve8_avg vpx_convolve8_avg_neon
+
+void vpx_convolve8_avg_horiz_c(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const InterpKernel *filter, int x0_q4, int x_step_q4, int y0_q4, int y_step_q4, int w, int h);
+void vpx_convolve8_avg_horiz_neon(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const InterpKernel *filter, int x0_q4, int x_step_q4, int y0_q4, int y_step_q4, int w, int h);
+#define vpx_convolve8_avg_horiz vpx_convolve8_avg_horiz_neon
+
+void vpx_convolve8_avg_vert_c(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const InterpKernel *filter, int x0_q4, int x_step_q4, int y0_q4, int y_step_q4, int w, int h);
+void vpx_convolve8_avg_vert_neon(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const InterpKernel *filter, int x0_q4, int x_step_q4, int y0_q4, int y_step_q4, int w, int h);
+#define vpx_convolve8_avg_vert vpx_convolve8_avg_vert_neon
+
+void vpx_convolve8_horiz_c(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const InterpKernel *filter, int x0_q4, int x_step_q4, int y0_q4, int y_step_q4, int w, int h);
+void vpx_convolve8_horiz_neon(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const InterpKernel *filter, int x0_q4, int x_step_q4, int y0_q4, int y_step_q4, int w, int h);
+#define vpx_convolve8_horiz vpx_convolve8_horiz_neon
+
+void vpx_convolve8_vert_c(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const InterpKernel *filter, int x0_q4, int x_step_q4, int y0_q4, int y_step_q4, int w, int h);
+void vpx_convolve8_vert_neon(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const InterpKernel *filter, int x0_q4, int x_step_q4, int y0_q4, int y_step_q4, int w, int h);
+#define vpx_convolve8_vert vpx_convolve8_vert_neon
+
+void vpx_convolve_avg_c(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const InterpKernel *filter, int x0_q4, int x_step_q4, int y0_q4, int y_step_q4, int w, int h);
+void vpx_convolve_avg_neon(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const InterpKernel *filter, int x0_q4, int x_step_q4, int y0_q4, int y_step_q4, int w, int h);
+#define vpx_convolve_avg vpx_convolve_avg_neon
+
+void vpx_convolve_copy_c(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const InterpKernel *filter, int x0_q4, int x_step_q4, int y0_q4, int y_step_q4, int w, int h);
+void vpx_convolve_copy_neon(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const InterpKernel *filter, int x0_q4, int x_step_q4, int y0_q4, int y_step_q4, int w, int h);
+#define vpx_convolve_copy vpx_convolve_copy_neon
+
+void vpx_d117_predictor_16x16_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_d117_predictor_16x16 vpx_d117_predictor_16x16_c
+
+void vpx_d117_predictor_32x32_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_d117_predictor_32x32 vpx_d117_predictor_32x32_c
+
+void vpx_d117_predictor_4x4_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_d117_predictor_4x4 vpx_d117_predictor_4x4_c
+
+void vpx_d117_predictor_8x8_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_d117_predictor_8x8 vpx_d117_predictor_8x8_c
+
+void vpx_d135_predictor_16x16_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+void vpx_d135_predictor_16x16_neon(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_d135_predictor_16x16 vpx_d135_predictor_16x16_neon
+
+void vpx_d135_predictor_32x32_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+void vpx_d135_predictor_32x32_neon(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_d135_predictor_32x32 vpx_d135_predictor_32x32_neon
+
+void vpx_d135_predictor_4x4_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+void vpx_d135_predictor_4x4_neon(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_d135_predictor_4x4 vpx_d135_predictor_4x4_neon
+
+void vpx_d135_predictor_8x8_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+void vpx_d135_predictor_8x8_neon(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_d135_predictor_8x8 vpx_d135_predictor_8x8_neon
+
+void vpx_d153_predictor_16x16_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_d153_predictor_16x16 vpx_d153_predictor_16x16_c
+
+void vpx_d153_predictor_32x32_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_d153_predictor_32x32 vpx_d153_predictor_32x32_c
+
+void vpx_d153_predictor_4x4_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_d153_predictor_4x4 vpx_d153_predictor_4x4_c
+
+void vpx_d153_predictor_8x8_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_d153_predictor_8x8 vpx_d153_predictor_8x8_c
+
+void vpx_d207_predictor_16x16_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_d207_predictor_16x16 vpx_d207_predictor_16x16_c
+
+void vpx_d207_predictor_32x32_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_d207_predictor_32x32 vpx_d207_predictor_32x32_c
+
+void vpx_d207_predictor_4x4_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_d207_predictor_4x4 vpx_d207_predictor_4x4_c
+
+void vpx_d207_predictor_8x8_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_d207_predictor_8x8 vpx_d207_predictor_8x8_c
+
+void vpx_d45_predictor_16x16_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+void vpx_d45_predictor_16x16_neon(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_d45_predictor_16x16 vpx_d45_predictor_16x16_neon
+
+void vpx_d45_predictor_32x32_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+void vpx_d45_predictor_32x32_neon(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_d45_predictor_32x32 vpx_d45_predictor_32x32_neon
+
+void vpx_d45_predictor_4x4_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+void vpx_d45_predictor_4x4_neon(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_d45_predictor_4x4 vpx_d45_predictor_4x4_neon
+
+void vpx_d45_predictor_8x8_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+void vpx_d45_predictor_8x8_neon(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_d45_predictor_8x8 vpx_d45_predictor_8x8_neon
+
+void vpx_d45e_predictor_4x4_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_d45e_predictor_4x4 vpx_d45e_predictor_4x4_c
+
+void vpx_d63_predictor_16x16_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_d63_predictor_16x16 vpx_d63_predictor_16x16_c
+
+void vpx_d63_predictor_32x32_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_d63_predictor_32x32 vpx_d63_predictor_32x32_c
+
+void vpx_d63_predictor_4x4_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_d63_predictor_4x4 vpx_d63_predictor_4x4_c
+
+void vpx_d63_predictor_8x8_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_d63_predictor_8x8 vpx_d63_predictor_8x8_c
+
+void vpx_d63e_predictor_4x4_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_d63e_predictor_4x4 vpx_d63e_predictor_4x4_c
+
+void vpx_dc_128_predictor_16x16_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+void vpx_dc_128_predictor_16x16_neon(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_dc_128_predictor_16x16 vpx_dc_128_predictor_16x16_neon
+
+void vpx_dc_128_predictor_32x32_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+void vpx_dc_128_predictor_32x32_neon(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_dc_128_predictor_32x32 vpx_dc_128_predictor_32x32_neon
+
+void vpx_dc_128_predictor_4x4_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+void vpx_dc_128_predictor_4x4_neon(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_dc_128_predictor_4x4 vpx_dc_128_predictor_4x4_neon
+
+void vpx_dc_128_predictor_8x8_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+void vpx_dc_128_predictor_8x8_neon(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_dc_128_predictor_8x8 vpx_dc_128_predictor_8x8_neon
+
+void vpx_dc_left_predictor_16x16_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+void vpx_dc_left_predictor_16x16_neon(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_dc_left_predictor_16x16 vpx_dc_left_predictor_16x16_neon
+
+void vpx_dc_left_predictor_32x32_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+void vpx_dc_left_predictor_32x32_neon(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_dc_left_predictor_32x32 vpx_dc_left_predictor_32x32_neon
+
+void vpx_dc_left_predictor_4x4_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+void vpx_dc_left_predictor_4x4_neon(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_dc_left_predictor_4x4 vpx_dc_left_predictor_4x4_neon
+
+void vpx_dc_left_predictor_8x8_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+void vpx_dc_left_predictor_8x8_neon(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_dc_left_predictor_8x8 vpx_dc_left_predictor_8x8_neon
+
+void vpx_dc_predictor_16x16_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+void vpx_dc_predictor_16x16_neon(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_dc_predictor_16x16 vpx_dc_predictor_16x16_neon
+
+void vpx_dc_predictor_32x32_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+void vpx_dc_predictor_32x32_neon(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_dc_predictor_32x32 vpx_dc_predictor_32x32_neon
+
+void vpx_dc_predictor_4x4_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+void vpx_dc_predictor_4x4_neon(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_dc_predictor_4x4 vpx_dc_predictor_4x4_neon
+
+void vpx_dc_predictor_8x8_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+void vpx_dc_predictor_8x8_neon(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_dc_predictor_8x8 vpx_dc_predictor_8x8_neon
+
+void vpx_dc_top_predictor_16x16_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+void vpx_dc_top_predictor_16x16_neon(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_dc_top_predictor_16x16 vpx_dc_top_predictor_16x16_neon
+
+void vpx_dc_top_predictor_32x32_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+void vpx_dc_top_predictor_32x32_neon(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_dc_top_predictor_32x32 vpx_dc_top_predictor_32x32_neon
+
+void vpx_dc_top_predictor_4x4_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+void vpx_dc_top_predictor_4x4_neon(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_dc_top_predictor_4x4 vpx_dc_top_predictor_4x4_neon
+
+void vpx_dc_top_predictor_8x8_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+void vpx_dc_top_predictor_8x8_neon(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_dc_top_predictor_8x8 vpx_dc_top_predictor_8x8_neon
+
+void vpx_fdct16x16_c(const int16_t *input, tran_low_t *output, int stride);
+void vpx_fdct16x16_neon(const int16_t *input, tran_low_t *output, int stride);
+#define vpx_fdct16x16 vpx_fdct16x16_neon
+
+void vpx_fdct16x16_1_c(const int16_t *input, tran_low_t *output, int stride);
+void vpx_fdct16x16_1_neon(const int16_t *input, tran_low_t *output, int stride);
+#define vpx_fdct16x16_1 vpx_fdct16x16_1_neon
+
+void vpx_fdct32x32_c(const int16_t *input, tran_low_t *output, int stride);
+void vpx_fdct32x32_neon(const int16_t *input, tran_low_t *output, int stride);
+#define vpx_fdct32x32 vpx_fdct32x32_neon
+
+void vpx_fdct32x32_1_c(const int16_t *input, tran_low_t *output, int stride);
+void vpx_fdct32x32_1_neon(const int16_t *input, tran_low_t *output, int stride);
+#define vpx_fdct32x32_1 vpx_fdct32x32_1_neon
+
+void vpx_fdct32x32_rd_c(const int16_t *input, tran_low_t *output, int stride);
+void vpx_fdct32x32_rd_neon(const int16_t *input, tran_low_t *output, int stride);
+#define vpx_fdct32x32_rd vpx_fdct32x32_rd_neon
+
+void vpx_fdct4x4_c(const int16_t *input, tran_low_t *output, int stride);
+void vpx_fdct4x4_neon(const int16_t *input, tran_low_t *output, int stride);
+#define vpx_fdct4x4 vpx_fdct4x4_neon
+
+void vpx_fdct4x4_1_c(const int16_t *input, tran_low_t *output, int stride);
+void vpx_fdct4x4_1_neon(const int16_t *input, tran_low_t *output, int stride);
+#define vpx_fdct4x4_1 vpx_fdct4x4_1_neon
+
+void vpx_fdct8x8_c(const int16_t *input, tran_low_t *output, int stride);
+void vpx_fdct8x8_neon(const int16_t *input, tran_low_t *output, int stride);
+#define vpx_fdct8x8 vpx_fdct8x8_neon
+
+void vpx_fdct8x8_1_c(const int16_t *input, tran_low_t *output, int stride);
+void vpx_fdct8x8_1_neon(const int16_t *input, tran_low_t *output, int stride);
+#define vpx_fdct8x8_1 vpx_fdct8x8_1_neon
+
+void vpx_get16x16var_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse, int *sum);
+void vpx_get16x16var_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse, int *sum);
+#define vpx_get16x16var vpx_get16x16var_neon
+
+unsigned int vpx_get4x4sse_cs_c(const unsigned char *src_ptr, int source_stride, const unsigned char *ref_ptr, int  ref_stride);
+unsigned int vpx_get4x4sse_cs_neon(const unsigned char *src_ptr, int source_stride, const unsigned char *ref_ptr, int  ref_stride);
+#define vpx_get4x4sse_cs vpx_get4x4sse_cs_neon
+
+void vpx_get8x8var_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse, int *sum);
+void vpx_get8x8var_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse, int *sum);
+#define vpx_get8x8var vpx_get8x8var_neon
+
+unsigned int vpx_get_mb_ss_c(const int16_t *);
+#define vpx_get_mb_ss vpx_get_mb_ss_c
+
+void vpx_h_predictor_16x16_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+void vpx_h_predictor_16x16_neon(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_h_predictor_16x16 vpx_h_predictor_16x16_neon
+
+void vpx_h_predictor_32x32_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+void vpx_h_predictor_32x32_neon(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_h_predictor_32x32 vpx_h_predictor_32x32_neon
+
+void vpx_h_predictor_4x4_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+void vpx_h_predictor_4x4_neon(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_h_predictor_4x4 vpx_h_predictor_4x4_neon
+
+void vpx_h_predictor_8x8_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+void vpx_h_predictor_8x8_neon(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_h_predictor_8x8 vpx_h_predictor_8x8_neon
+
+void vpx_hadamard_16x16_c(const int16_t *src_diff, ptrdiff_t src_stride, int16_t *coeff);
+void vpx_hadamard_16x16_neon(const int16_t *src_diff, ptrdiff_t src_stride, int16_t *coeff);
+#define vpx_hadamard_16x16 vpx_hadamard_16x16_neon
+
+void vpx_hadamard_8x8_c(const int16_t *src_diff, ptrdiff_t src_stride, int16_t *coeff);
+void vpx_hadamard_8x8_neon(const int16_t *src_diff, ptrdiff_t src_stride, int16_t *coeff);
+#define vpx_hadamard_8x8 vpx_hadamard_8x8_neon
+
+void vpx_he_predictor_4x4_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_he_predictor_4x4 vpx_he_predictor_4x4_c
+
+void vpx_idct16x16_10_add_c(const tran_low_t *input, uint8_t *dest, int stride);
+void vpx_idct16x16_10_add_neon(const tran_low_t *input, uint8_t *dest, int stride);
+#define vpx_idct16x16_10_add vpx_idct16x16_10_add_neon
+
+void vpx_idct16x16_1_add_c(const tran_low_t *input, uint8_t *dest, int stride);
+void vpx_idct16x16_1_add_neon(const tran_low_t *input, uint8_t *dest, int stride);
+#define vpx_idct16x16_1_add vpx_idct16x16_1_add_neon
+
+void vpx_idct16x16_256_add_c(const tran_low_t *input, uint8_t *dest, int stride);
+void vpx_idct16x16_256_add_neon(const tran_low_t *input, uint8_t *dest, int stride);
+#define vpx_idct16x16_256_add vpx_idct16x16_256_add_neon
+
+void vpx_idct16x16_38_add_c(const tran_low_t *input, uint8_t *dest, int stride);
+void vpx_idct16x16_38_add_neon(const tran_low_t *input, uint8_t *dest, int stride);
+#define vpx_idct16x16_38_add vpx_idct16x16_38_add_neon
+
+void vpx_idct32x32_1024_add_c(const tran_low_t *input, uint8_t *dest, int stride);
+void vpx_idct32x32_1024_add_neon(const tran_low_t *input, uint8_t *dest, int stride);
+#define vpx_idct32x32_1024_add vpx_idct32x32_1024_add_neon
+
+void vpx_idct32x32_135_add_c(const tran_low_t *input, uint8_t *dest, int stride);
+void vpx_idct32x32_135_add_neon(const tran_low_t *input, uint8_t *dest, int stride);
+#define vpx_idct32x32_135_add vpx_idct32x32_135_add_neon
+
+void vpx_idct32x32_1_add_c(const tran_low_t *input, uint8_t *dest, int stride);
+void vpx_idct32x32_1_add_neon(const tran_low_t *input, uint8_t *dest, int stride);
+#define vpx_idct32x32_1_add vpx_idct32x32_1_add_neon
+
+void vpx_idct32x32_34_add_c(const tran_low_t *input, uint8_t *dest, int stride);
+void vpx_idct32x32_34_add_neon(const tran_low_t *input, uint8_t *dest, int stride);
+#define vpx_idct32x32_34_add vpx_idct32x32_34_add_neon
+
+void vpx_idct4x4_16_add_c(const tran_low_t *input, uint8_t *dest, int stride);
+void vpx_idct4x4_16_add_neon(const tran_low_t *input, uint8_t *dest, int stride);
+#define vpx_idct4x4_16_add vpx_idct4x4_16_add_neon
+
+void vpx_idct4x4_1_add_c(const tran_low_t *input, uint8_t *dest, int stride);
+void vpx_idct4x4_1_add_neon(const tran_low_t *input, uint8_t *dest, int stride);
+#define vpx_idct4x4_1_add vpx_idct4x4_1_add_neon
+
+void vpx_idct8x8_12_add_c(const tran_low_t *input, uint8_t *dest, int stride);
+void vpx_idct8x8_12_add_neon(const tran_low_t *input, uint8_t *dest, int stride);
+#define vpx_idct8x8_12_add vpx_idct8x8_12_add_neon
+
+void vpx_idct8x8_1_add_c(const tran_low_t *input, uint8_t *dest, int stride);
+void vpx_idct8x8_1_add_neon(const tran_low_t *input, uint8_t *dest, int stride);
+#define vpx_idct8x8_1_add vpx_idct8x8_1_add_neon
+
+void vpx_idct8x8_64_add_c(const tran_low_t *input, uint8_t *dest, int stride);
+void vpx_idct8x8_64_add_neon(const tran_low_t *input, uint8_t *dest, int stride);
+#define vpx_idct8x8_64_add vpx_idct8x8_64_add_neon
+
+int16_t vpx_int_pro_col_c(const uint8_t *ref, const int width);
+int16_t vpx_int_pro_col_neon(const uint8_t *ref, const int width);
+#define vpx_int_pro_col vpx_int_pro_col_neon
+
+void vpx_int_pro_row_c(int16_t *hbuf, const uint8_t *ref, const int ref_stride, const int height);
+void vpx_int_pro_row_neon(int16_t *hbuf, const uint8_t *ref, const int ref_stride, const int height);
+#define vpx_int_pro_row vpx_int_pro_row_neon
+
+void vpx_iwht4x4_16_add_c(const tran_low_t *input, uint8_t *dest, int stride);
+#define vpx_iwht4x4_16_add vpx_iwht4x4_16_add_c
+
+void vpx_iwht4x4_1_add_c(const tran_low_t *input, uint8_t *dest, int stride);
+#define vpx_iwht4x4_1_add vpx_iwht4x4_1_add_c
+
+void vpx_lpf_horizontal_16_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_16_neon(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+#define vpx_lpf_horizontal_16 vpx_lpf_horizontal_16_neon
+
+void vpx_lpf_horizontal_16_dual_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_16_dual_neon(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+#define vpx_lpf_horizontal_16_dual vpx_lpf_horizontal_16_dual_neon
+
+void vpx_lpf_horizontal_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_4_neon(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+#define vpx_lpf_horizontal_4 vpx_lpf_horizontal_4_neon
+
+void vpx_lpf_horizontal_4_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
+void vpx_lpf_horizontal_4_dual_neon(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
+#define vpx_lpf_horizontal_4_dual vpx_lpf_horizontal_4_dual_neon
+
+void vpx_lpf_horizontal_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_horizontal_8_neon(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+#define vpx_lpf_horizontal_8 vpx_lpf_horizontal_8_neon
+
+void vpx_lpf_horizontal_8_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
+void vpx_lpf_horizontal_8_dual_neon(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
+#define vpx_lpf_horizontal_8_dual vpx_lpf_horizontal_8_dual_neon
+
+void vpx_lpf_vertical_16_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_vertical_16_neon(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+#define vpx_lpf_vertical_16 vpx_lpf_vertical_16_neon
+
+void vpx_lpf_vertical_16_dual_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_vertical_16_dual_neon(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+#define vpx_lpf_vertical_16_dual vpx_lpf_vertical_16_dual_neon
+
+void vpx_lpf_vertical_4_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_vertical_4_neon(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+#define vpx_lpf_vertical_4 vpx_lpf_vertical_4_neon
+
+void vpx_lpf_vertical_4_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
+void vpx_lpf_vertical_4_dual_neon(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
+#define vpx_lpf_vertical_4_dual vpx_lpf_vertical_4_dual_neon
+
+void vpx_lpf_vertical_8_c(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+void vpx_lpf_vertical_8_neon(uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh);
+#define vpx_lpf_vertical_8 vpx_lpf_vertical_8_neon
+
+void vpx_lpf_vertical_8_dual_c(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
+void vpx_lpf_vertical_8_dual_neon(uint8_t *s, int pitch, const uint8_t *blimit0, const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1, const uint8_t *limit1, const uint8_t *thresh1);
+#define vpx_lpf_vertical_8_dual vpx_lpf_vertical_8_dual_neon
+
+void vpx_minmax_8x8_c(const uint8_t *s, int p, const uint8_t *d, int dp, int *min, int *max);
+void vpx_minmax_8x8_neon(const uint8_t *s, int p, const uint8_t *d, int dp, int *min, int *max);
+#define vpx_minmax_8x8 vpx_minmax_8x8_neon
+
+unsigned int vpx_mse16x16_c(const uint8_t *src_ptr, int  source_stride, const uint8_t *ref_ptr, int  recon_stride, unsigned int *sse);
+unsigned int vpx_mse16x16_neon(const uint8_t *src_ptr, int  source_stride, const uint8_t *ref_ptr, int  recon_stride, unsigned int *sse);
+#define vpx_mse16x16 vpx_mse16x16_neon
+
+unsigned int vpx_mse16x8_c(const uint8_t *src_ptr, int  source_stride, const uint8_t *ref_ptr, int  recon_stride, unsigned int *sse);
+#define vpx_mse16x8 vpx_mse16x8_c
+
+unsigned int vpx_mse8x16_c(const uint8_t *src_ptr, int  source_stride, const uint8_t *ref_ptr, int  recon_stride, unsigned int *sse);
+#define vpx_mse8x16 vpx_mse8x16_c
+
+unsigned int vpx_mse8x8_c(const uint8_t *src_ptr, int  source_stride, const uint8_t *ref_ptr, int  recon_stride, unsigned int *sse);
+#define vpx_mse8x8 vpx_mse8x8_c
+
+void vpx_quantize_b_c(const tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block, const int16_t *zbin_ptr, const int16_t *round_ptr, const int16_t *quant_ptr, const int16_t *quant_shift_ptr, tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan);
+void vpx_quantize_b_neon(const tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block, const int16_t *zbin_ptr, const int16_t *round_ptr, const int16_t *quant_ptr, const int16_t *quant_shift_ptr, tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan);
+#define vpx_quantize_b vpx_quantize_b_neon
+
+void vpx_quantize_b_32x32_c(const tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block, const int16_t *zbin_ptr, const int16_t *round_ptr, const int16_t *quant_ptr, const int16_t *quant_shift_ptr, tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan);
+void vpx_quantize_b_32x32_neon(const tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block, const int16_t *zbin_ptr, const int16_t *round_ptr, const int16_t *quant_ptr, const int16_t *quant_shift_ptr, tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan);
+#define vpx_quantize_b_32x32 vpx_quantize_b_32x32_neon
+
+unsigned int vpx_sad16x16_c(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride);
+unsigned int vpx_sad16x16_neon(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride);
+#define vpx_sad16x16 vpx_sad16x16_neon
+
+unsigned int vpx_sad16x16_avg_c(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *second_pred);
+unsigned int vpx_sad16x16_avg_neon(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *second_pred);
+#define vpx_sad16x16_avg vpx_sad16x16_avg_neon
+
+void vpx_sad16x16x3_c(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride, uint32_t *sad_array);
+#define vpx_sad16x16x3 vpx_sad16x16x3_c
+
+void vpx_sad16x16x4d_c(const uint8_t *src_ptr, int src_stride, const uint8_t * const ref_ptr[], int ref_stride, uint32_t *sad_array);
+void vpx_sad16x16x4d_neon(const uint8_t *src_ptr, int src_stride, const uint8_t * const ref_ptr[], int ref_stride, uint32_t *sad_array);
+#define vpx_sad16x16x4d vpx_sad16x16x4d_neon
+
+void vpx_sad16x16x8_c(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride, uint32_t *sad_array);
+#define vpx_sad16x16x8 vpx_sad16x16x8_c
+
+unsigned int vpx_sad16x32_c(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride);
+unsigned int vpx_sad16x32_neon(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride);
+#define vpx_sad16x32 vpx_sad16x32_neon
+
+unsigned int vpx_sad16x32_avg_c(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *second_pred);
+unsigned int vpx_sad16x32_avg_neon(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *second_pred);
+#define vpx_sad16x32_avg vpx_sad16x32_avg_neon
+
+void vpx_sad16x32x4d_c(const uint8_t *src_ptr, int src_stride, const uint8_t * const ref_ptr[], int ref_stride, uint32_t *sad_array);
+void vpx_sad16x32x4d_neon(const uint8_t *src_ptr, int src_stride, const uint8_t * const ref_ptr[], int ref_stride, uint32_t *sad_array);
+#define vpx_sad16x32x4d vpx_sad16x32x4d_neon
+
+unsigned int vpx_sad16x8_c(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride);
+unsigned int vpx_sad16x8_neon(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride);
+#define vpx_sad16x8 vpx_sad16x8_neon
+
+unsigned int vpx_sad16x8_avg_c(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *second_pred);
+unsigned int vpx_sad16x8_avg_neon(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *second_pred);
+#define vpx_sad16x8_avg vpx_sad16x8_avg_neon
+
+void vpx_sad16x8x3_c(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride, uint32_t *sad_array);
+#define vpx_sad16x8x3 vpx_sad16x8x3_c
+
+void vpx_sad16x8x4d_c(const uint8_t *src_ptr, int src_stride, const uint8_t * const ref_ptr[], int ref_stride, uint32_t *sad_array);
+void vpx_sad16x8x4d_neon(const uint8_t *src_ptr, int src_stride, const uint8_t * const ref_ptr[], int ref_stride, uint32_t *sad_array);
+#define vpx_sad16x8x4d vpx_sad16x8x4d_neon
+
+void vpx_sad16x8x8_c(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride, uint32_t *sad_array);
+#define vpx_sad16x8x8 vpx_sad16x8x8_c
+
+unsigned int vpx_sad32x16_c(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride);
+unsigned int vpx_sad32x16_neon(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride);
+#define vpx_sad32x16 vpx_sad32x16_neon
+
+unsigned int vpx_sad32x16_avg_c(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *second_pred);
+unsigned int vpx_sad32x16_avg_neon(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *second_pred);
+#define vpx_sad32x16_avg vpx_sad32x16_avg_neon
+
+void vpx_sad32x16x4d_c(const uint8_t *src_ptr, int src_stride, const uint8_t * const ref_ptr[], int ref_stride, uint32_t *sad_array);
+void vpx_sad32x16x4d_neon(const uint8_t *src_ptr, int src_stride, const uint8_t * const ref_ptr[], int ref_stride, uint32_t *sad_array);
+#define vpx_sad32x16x4d vpx_sad32x16x4d_neon
+
+unsigned int vpx_sad32x32_c(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride);
+unsigned int vpx_sad32x32_neon(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride);
+#define vpx_sad32x32 vpx_sad32x32_neon
+
+unsigned int vpx_sad32x32_avg_c(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *second_pred);
+unsigned int vpx_sad32x32_avg_neon(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *second_pred);
+#define vpx_sad32x32_avg vpx_sad32x32_avg_neon
+
+void vpx_sad32x32x4d_c(const uint8_t *src_ptr, int src_stride, const uint8_t * const ref_ptr[], int ref_stride, uint32_t *sad_array);
+void vpx_sad32x32x4d_neon(const uint8_t *src_ptr, int src_stride, const uint8_t * const ref_ptr[], int ref_stride, uint32_t *sad_array);
+#define vpx_sad32x32x4d vpx_sad32x32x4d_neon
+
+unsigned int vpx_sad32x64_c(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride);
+unsigned int vpx_sad32x64_neon(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride);
+#define vpx_sad32x64 vpx_sad32x64_neon
+
+unsigned int vpx_sad32x64_avg_c(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *second_pred);
+unsigned int vpx_sad32x64_avg_neon(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *second_pred);
+#define vpx_sad32x64_avg vpx_sad32x64_avg_neon
+
+void vpx_sad32x64x4d_c(const uint8_t *src_ptr, int src_stride, const uint8_t * const ref_ptr[], int ref_stride, uint32_t *sad_array);
+void vpx_sad32x64x4d_neon(const uint8_t *src_ptr, int src_stride, const uint8_t * const ref_ptr[], int ref_stride, uint32_t *sad_array);
+#define vpx_sad32x64x4d vpx_sad32x64x4d_neon
+
+unsigned int vpx_sad4x4_c(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride);
+unsigned int vpx_sad4x4_neon(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride);
+#define vpx_sad4x4 vpx_sad4x4_neon
+
+unsigned int vpx_sad4x4_avg_c(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *second_pred);
+unsigned int vpx_sad4x4_avg_neon(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *second_pred);
+#define vpx_sad4x4_avg vpx_sad4x4_avg_neon
+
+void vpx_sad4x4x3_c(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride, uint32_t *sad_array);
+#define vpx_sad4x4x3 vpx_sad4x4x3_c
+
+void vpx_sad4x4x4d_c(const uint8_t *src_ptr, int src_stride, const uint8_t * const ref_ptr[], int ref_stride, uint32_t *sad_array);
+void vpx_sad4x4x4d_neon(const uint8_t *src_ptr, int src_stride, const uint8_t * const ref_ptr[], int ref_stride, uint32_t *sad_array);
+#define vpx_sad4x4x4d vpx_sad4x4x4d_neon
+
+void vpx_sad4x4x8_c(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride, uint32_t *sad_array);
+#define vpx_sad4x4x8 vpx_sad4x4x8_c
+
+unsigned int vpx_sad4x8_c(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride);
+unsigned int vpx_sad4x8_neon(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride);
+#define vpx_sad4x8 vpx_sad4x8_neon
+
+unsigned int vpx_sad4x8_avg_c(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *second_pred);
+unsigned int vpx_sad4x8_avg_neon(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *second_pred);
+#define vpx_sad4x8_avg vpx_sad4x8_avg_neon
+
+void vpx_sad4x8x4d_c(const uint8_t *src_ptr, int src_stride, const uint8_t * const ref_ptr[], int ref_stride, uint32_t *sad_array);
+void vpx_sad4x8x4d_neon(const uint8_t *src_ptr, int src_stride, const uint8_t * const ref_ptr[], int ref_stride, uint32_t *sad_array);
+#define vpx_sad4x8x4d vpx_sad4x8x4d_neon
+
+unsigned int vpx_sad64x32_c(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride);
+unsigned int vpx_sad64x32_neon(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride);
+#define vpx_sad64x32 vpx_sad64x32_neon
+
+unsigned int vpx_sad64x32_avg_c(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *second_pred);
+unsigned int vpx_sad64x32_avg_neon(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *second_pred);
+#define vpx_sad64x32_avg vpx_sad64x32_avg_neon
+
+void vpx_sad64x32x4d_c(const uint8_t *src_ptr, int src_stride, const uint8_t * const ref_ptr[], int ref_stride, uint32_t *sad_array);
+void vpx_sad64x32x4d_neon(const uint8_t *src_ptr, int src_stride, const uint8_t * const ref_ptr[], int ref_stride, uint32_t *sad_array);
+#define vpx_sad64x32x4d vpx_sad64x32x4d_neon
+
+unsigned int vpx_sad64x64_c(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride);
+unsigned int vpx_sad64x64_neon(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride);
+#define vpx_sad64x64 vpx_sad64x64_neon
+
+unsigned int vpx_sad64x64_avg_c(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *second_pred);
+unsigned int vpx_sad64x64_avg_neon(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *second_pred);
+#define vpx_sad64x64_avg vpx_sad64x64_avg_neon
+
+void vpx_sad64x64x4d_c(const uint8_t *src_ptr, int src_stride, const uint8_t * const ref_ptr[], int ref_stride, uint32_t *sad_array);
+void vpx_sad64x64x4d_neon(const uint8_t *src_ptr, int src_stride, const uint8_t * const ref_ptr[], int ref_stride, uint32_t *sad_array);
+#define vpx_sad64x64x4d vpx_sad64x64x4d_neon
+
+unsigned int vpx_sad8x16_c(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride);
+unsigned int vpx_sad8x16_neon(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride);
+#define vpx_sad8x16 vpx_sad8x16_neon
+
+unsigned int vpx_sad8x16_avg_c(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *second_pred);
+unsigned int vpx_sad8x16_avg_neon(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *second_pred);
+#define vpx_sad8x16_avg vpx_sad8x16_avg_neon
+
+void vpx_sad8x16x3_c(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride, uint32_t *sad_array);
+#define vpx_sad8x16x3 vpx_sad8x16x3_c
+
+void vpx_sad8x16x4d_c(const uint8_t *src_ptr, int src_stride, const uint8_t * const ref_ptr[], int ref_stride, uint32_t *sad_array);
+void vpx_sad8x16x4d_neon(const uint8_t *src_ptr, int src_stride, const uint8_t * const ref_ptr[], int ref_stride, uint32_t *sad_array);
+#define vpx_sad8x16x4d vpx_sad8x16x4d_neon
+
+void vpx_sad8x16x8_c(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride, uint32_t *sad_array);
+#define vpx_sad8x16x8 vpx_sad8x16x8_c
+
+unsigned int vpx_sad8x4_c(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride);
+unsigned int vpx_sad8x4_neon(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride);
+#define vpx_sad8x4 vpx_sad8x4_neon
+
+unsigned int vpx_sad8x4_avg_c(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *second_pred);
+unsigned int vpx_sad8x4_avg_neon(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *second_pred);
+#define vpx_sad8x4_avg vpx_sad8x4_avg_neon
+
+void vpx_sad8x4x4d_c(const uint8_t *src_ptr, int src_stride, const uint8_t * const ref_ptr[], int ref_stride, uint32_t *sad_array);
+void vpx_sad8x4x4d_neon(const uint8_t *src_ptr, int src_stride, const uint8_t * const ref_ptr[], int ref_stride, uint32_t *sad_array);
+#define vpx_sad8x4x4d vpx_sad8x4x4d_neon
+
+unsigned int vpx_sad8x8_c(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride);
+unsigned int vpx_sad8x8_neon(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride);
+#define vpx_sad8x8 vpx_sad8x8_neon
+
+unsigned int vpx_sad8x8_avg_c(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *second_pred);
+unsigned int vpx_sad8x8_avg_neon(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *second_pred);
+#define vpx_sad8x8_avg vpx_sad8x8_avg_neon
+
+void vpx_sad8x8x3_c(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride, uint32_t *sad_array);
+#define vpx_sad8x8x3 vpx_sad8x8x3_c
+
+void vpx_sad8x8x4d_c(const uint8_t *src_ptr, int src_stride, const uint8_t * const ref_ptr[], int ref_stride, uint32_t *sad_array);
+void vpx_sad8x8x4d_neon(const uint8_t *src_ptr, int src_stride, const uint8_t * const ref_ptr[], int ref_stride, uint32_t *sad_array);
+#define vpx_sad8x8x4d vpx_sad8x8x4d_neon
+
+void vpx_sad8x8x8_c(const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, int ref_stride, uint32_t *sad_array);
+#define vpx_sad8x8x8 vpx_sad8x8x8_c
+
+int vpx_satd_c(const int16_t *coeff, int length);
+int vpx_satd_neon(const int16_t *coeff, int length);
+#define vpx_satd vpx_satd_neon
+
+void vpx_scaled_2d_c(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const InterpKernel *filter, int x0_q4, int x_step_q4, int y0_q4, int y_step_q4, int w, int h);
+void vpx_scaled_2d_neon(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const InterpKernel *filter, int x0_q4, int x_step_q4, int y0_q4, int y_step_q4, int w, int h);
+#define vpx_scaled_2d vpx_scaled_2d_neon
+
+void vpx_scaled_avg_2d_c(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const InterpKernel *filter, int x0_q4, int x_step_q4, int y0_q4, int y_step_q4, int w, int h);
+#define vpx_scaled_avg_2d vpx_scaled_avg_2d_c
+
+void vpx_scaled_avg_horiz_c(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const InterpKernel *filter, int x0_q4, int x_step_q4, int y0_q4, int y_step_q4, int w, int h);
+#define vpx_scaled_avg_horiz vpx_scaled_avg_horiz_c
+
+void vpx_scaled_avg_vert_c(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const InterpKernel *filter, int x0_q4, int x_step_q4, int y0_q4, int y_step_q4, int w, int h);
+#define vpx_scaled_avg_vert vpx_scaled_avg_vert_c
+
+void vpx_scaled_horiz_c(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const InterpKernel *filter, int x0_q4, int x_step_q4, int y0_q4, int y_step_q4, int w, int h);
+#define vpx_scaled_horiz vpx_scaled_horiz_c
+
+void vpx_scaled_vert_c(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const InterpKernel *filter, int x0_q4, int x_step_q4, int y0_q4, int y_step_q4, int w, int h);
+#define vpx_scaled_vert vpx_scaled_vert_c
+
+uint32_t vpx_sub_pixel_avg_variance16x16_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+uint32_t vpx_sub_pixel_avg_variance16x16_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance16x16 vpx_sub_pixel_avg_variance16x16_neon
+
+uint32_t vpx_sub_pixel_avg_variance16x32_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+uint32_t vpx_sub_pixel_avg_variance16x32_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance16x32 vpx_sub_pixel_avg_variance16x32_neon
+
+uint32_t vpx_sub_pixel_avg_variance16x8_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+uint32_t vpx_sub_pixel_avg_variance16x8_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance16x8 vpx_sub_pixel_avg_variance16x8_neon
+
+uint32_t vpx_sub_pixel_avg_variance32x16_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+uint32_t vpx_sub_pixel_avg_variance32x16_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance32x16 vpx_sub_pixel_avg_variance32x16_neon
+
+uint32_t vpx_sub_pixel_avg_variance32x32_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+uint32_t vpx_sub_pixel_avg_variance32x32_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance32x32 vpx_sub_pixel_avg_variance32x32_neon
+
+uint32_t vpx_sub_pixel_avg_variance32x64_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+uint32_t vpx_sub_pixel_avg_variance32x64_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance32x64 vpx_sub_pixel_avg_variance32x64_neon
+
+uint32_t vpx_sub_pixel_avg_variance4x4_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+uint32_t vpx_sub_pixel_avg_variance4x4_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance4x4 vpx_sub_pixel_avg_variance4x4_neon
+
+uint32_t vpx_sub_pixel_avg_variance4x8_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+uint32_t vpx_sub_pixel_avg_variance4x8_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance4x8 vpx_sub_pixel_avg_variance4x8_neon
+
+uint32_t vpx_sub_pixel_avg_variance64x32_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+uint32_t vpx_sub_pixel_avg_variance64x32_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance64x32 vpx_sub_pixel_avg_variance64x32_neon
+
+uint32_t vpx_sub_pixel_avg_variance64x64_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+uint32_t vpx_sub_pixel_avg_variance64x64_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance64x64 vpx_sub_pixel_avg_variance64x64_neon
+
+uint32_t vpx_sub_pixel_avg_variance8x16_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+uint32_t vpx_sub_pixel_avg_variance8x16_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance8x16 vpx_sub_pixel_avg_variance8x16_neon
+
+uint32_t vpx_sub_pixel_avg_variance8x4_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+uint32_t vpx_sub_pixel_avg_variance8x4_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance8x4 vpx_sub_pixel_avg_variance8x4_neon
+
+uint32_t vpx_sub_pixel_avg_variance8x8_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+uint32_t vpx_sub_pixel_avg_variance8x8_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse, const uint8_t *second_pred);
+#define vpx_sub_pixel_avg_variance8x8 vpx_sub_pixel_avg_variance8x8_neon
+
+uint32_t vpx_sub_pixel_variance16x16_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+uint32_t vpx_sub_pixel_variance16x16_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+#define vpx_sub_pixel_variance16x16 vpx_sub_pixel_variance16x16_neon
+
+uint32_t vpx_sub_pixel_variance16x32_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+uint32_t vpx_sub_pixel_variance16x32_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+#define vpx_sub_pixel_variance16x32 vpx_sub_pixel_variance16x32_neon
+
+uint32_t vpx_sub_pixel_variance16x8_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+uint32_t vpx_sub_pixel_variance16x8_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+#define vpx_sub_pixel_variance16x8 vpx_sub_pixel_variance16x8_neon
+
+uint32_t vpx_sub_pixel_variance32x16_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+uint32_t vpx_sub_pixel_variance32x16_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+#define vpx_sub_pixel_variance32x16 vpx_sub_pixel_variance32x16_neon
+
+uint32_t vpx_sub_pixel_variance32x32_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+uint32_t vpx_sub_pixel_variance32x32_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+#define vpx_sub_pixel_variance32x32 vpx_sub_pixel_variance32x32_neon
+
+uint32_t vpx_sub_pixel_variance32x64_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+uint32_t vpx_sub_pixel_variance32x64_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+#define vpx_sub_pixel_variance32x64 vpx_sub_pixel_variance32x64_neon
+
+uint32_t vpx_sub_pixel_variance4x4_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+uint32_t vpx_sub_pixel_variance4x4_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+#define vpx_sub_pixel_variance4x4 vpx_sub_pixel_variance4x4_neon
+
+uint32_t vpx_sub_pixel_variance4x8_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+uint32_t vpx_sub_pixel_variance4x8_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+#define vpx_sub_pixel_variance4x8 vpx_sub_pixel_variance4x8_neon
+
+uint32_t vpx_sub_pixel_variance64x32_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+uint32_t vpx_sub_pixel_variance64x32_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+#define vpx_sub_pixel_variance64x32 vpx_sub_pixel_variance64x32_neon
+
+uint32_t vpx_sub_pixel_variance64x64_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+uint32_t vpx_sub_pixel_variance64x64_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+#define vpx_sub_pixel_variance64x64 vpx_sub_pixel_variance64x64_neon
+
+uint32_t vpx_sub_pixel_variance8x16_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+uint32_t vpx_sub_pixel_variance8x16_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+#define vpx_sub_pixel_variance8x16 vpx_sub_pixel_variance8x16_neon
+
+uint32_t vpx_sub_pixel_variance8x4_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+uint32_t vpx_sub_pixel_variance8x4_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+#define vpx_sub_pixel_variance8x4 vpx_sub_pixel_variance8x4_neon
+
+uint32_t vpx_sub_pixel_variance8x8_c(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+uint32_t vpx_sub_pixel_variance8x8_neon(const uint8_t *src_ptr, int source_stride, int xoffset, int  yoffset, const uint8_t *ref_ptr, int ref_stride, uint32_t *sse);
+#define vpx_sub_pixel_variance8x8 vpx_sub_pixel_variance8x8_neon
+
+void vpx_subtract_block_c(int rows, int cols, int16_t *diff_ptr, ptrdiff_t diff_stride, const uint8_t *src_ptr, ptrdiff_t src_stride, const uint8_t *pred_ptr, ptrdiff_t pred_stride);
+void vpx_subtract_block_neon(int rows, int cols, int16_t *diff_ptr, ptrdiff_t diff_stride, const uint8_t *src_ptr, ptrdiff_t src_stride, const uint8_t *pred_ptr, ptrdiff_t pred_stride);
+#define vpx_subtract_block vpx_subtract_block_neon
+
+uint64_t vpx_sum_squares_2d_i16_c(const int16_t *src, int stride, int size);
+#define vpx_sum_squares_2d_i16 vpx_sum_squares_2d_i16_c
+
+void vpx_tm_predictor_16x16_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+void vpx_tm_predictor_16x16_neon(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_tm_predictor_16x16 vpx_tm_predictor_16x16_neon
+
+void vpx_tm_predictor_32x32_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+void vpx_tm_predictor_32x32_neon(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_tm_predictor_32x32 vpx_tm_predictor_32x32_neon
+
+void vpx_tm_predictor_4x4_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+void vpx_tm_predictor_4x4_neon(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_tm_predictor_4x4 vpx_tm_predictor_4x4_neon
+
+void vpx_tm_predictor_8x8_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+void vpx_tm_predictor_8x8_neon(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_tm_predictor_8x8 vpx_tm_predictor_8x8_neon
+
+void vpx_v_predictor_16x16_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+void vpx_v_predictor_16x16_neon(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_v_predictor_16x16 vpx_v_predictor_16x16_neon
+
+void vpx_v_predictor_32x32_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+void vpx_v_predictor_32x32_neon(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_v_predictor_32x32 vpx_v_predictor_32x32_neon
+
+void vpx_v_predictor_4x4_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+void vpx_v_predictor_4x4_neon(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_v_predictor_4x4 vpx_v_predictor_4x4_neon
+
+void vpx_v_predictor_8x8_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+void vpx_v_predictor_8x8_neon(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_v_predictor_8x8 vpx_v_predictor_8x8_neon
+
+unsigned int vpx_variance16x16_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+unsigned int vpx_variance16x16_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+#define vpx_variance16x16 vpx_variance16x16_neon
+
+unsigned int vpx_variance16x32_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+unsigned int vpx_variance16x32_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+#define vpx_variance16x32 vpx_variance16x32_neon
+
+unsigned int vpx_variance16x8_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+unsigned int vpx_variance16x8_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+#define vpx_variance16x8 vpx_variance16x8_neon
+
+unsigned int vpx_variance32x16_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+unsigned int vpx_variance32x16_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+#define vpx_variance32x16 vpx_variance32x16_neon
+
+unsigned int vpx_variance32x32_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+unsigned int vpx_variance32x32_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+#define vpx_variance32x32 vpx_variance32x32_neon
+
+unsigned int vpx_variance32x64_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+unsigned int vpx_variance32x64_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+#define vpx_variance32x64 vpx_variance32x64_neon
+
+unsigned int vpx_variance4x4_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+unsigned int vpx_variance4x4_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+#define vpx_variance4x4 vpx_variance4x4_neon
+
+unsigned int vpx_variance4x8_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+unsigned int vpx_variance4x8_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+#define vpx_variance4x8 vpx_variance4x8_neon
+
+unsigned int vpx_variance64x32_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+unsigned int vpx_variance64x32_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+#define vpx_variance64x32 vpx_variance64x32_neon
+
+unsigned int vpx_variance64x64_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+unsigned int vpx_variance64x64_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+#define vpx_variance64x64 vpx_variance64x64_neon
+
+unsigned int vpx_variance8x16_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+unsigned int vpx_variance8x16_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+#define vpx_variance8x16 vpx_variance8x16_neon
+
+unsigned int vpx_variance8x4_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+unsigned int vpx_variance8x4_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+#define vpx_variance8x4 vpx_variance8x4_neon
+
+unsigned int vpx_variance8x8_c(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+unsigned int vpx_variance8x8_neon(const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse);
+#define vpx_variance8x8 vpx_variance8x8_neon
+
+void vpx_ve_predictor_4x4_c(uint8_t *dst, ptrdiff_t y_stride, const uint8_t *above, const uint8_t *left);
+#define vpx_ve_predictor_4x4 vpx_ve_predictor_4x4_c
+
+int vpx_vector_var_c(const int16_t *ref, const int16_t *src, const int bwl);
+int vpx_vector_var_neon(const int16_t *ref, const int16_t *src, const int bwl);
+#define vpx_vector_var vpx_vector_var_neon
+
+void vpx_dsp_rtcd(void);
+
+#include "vpx_config.h"
+
+#ifdef RTCD_C
+#include "vpx_ports/arm.h"
+static void setup_rtcd_internal(void)
+{
+    int flags = arm_cpu_caps();
+
+    (void)flags;
+
+}
+#endif
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif
new file mode 100644
--- /dev/null
+++ b/media/libvpx/config/linux/arm64/vpx_scale_rtcd.h
@@ -0,0 +1,75 @@
+// This file is generated. Do not edit.
+#ifndef VPX_SCALE_RTCD_H_
+#define VPX_SCALE_RTCD_H_
+
+#ifdef RTCD_C
+#define RTCD_EXTERN
+#else
+#define RTCD_EXTERN extern
+#endif
+
+struct yv12_buffer_config;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void vp8_horizontal_line_2_1_scale_c(const unsigned char *source, unsigned int source_width, unsigned char *dest, unsigned int dest_width);
+#define vp8_horizontal_line_2_1_scale vp8_horizontal_line_2_1_scale_c
+
+void vp8_horizontal_line_5_3_scale_c(const unsigned char *source, unsigned int source_width, unsigned char *dest, unsigned int dest_width);
+#define vp8_horizontal_line_5_3_scale vp8_horizontal_line_5_3_scale_c
+
+void vp8_horizontal_line_5_4_scale_c(const unsigned char *source, unsigned int source_width, unsigned char *dest, unsigned int dest_width);
+#define vp8_horizontal_line_5_4_scale vp8_horizontal_line_5_4_scale_c
+
+void vp8_vertical_band_2_1_scale_c(unsigned char *source, unsigned int src_pitch, unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width);
+#define vp8_vertical_band_2_1_scale vp8_vertical_band_2_1_scale_c
+
+void vp8_vertical_band_2_1_scale_i_c(unsigned char *source, unsigned int src_pitch, unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width);
+#define vp8_vertical_band_2_1_scale_i vp8_vertical_band_2_1_scale_i_c
+
+void vp8_vertical_band_5_3_scale_c(unsigned char *source, unsigned int src_pitch, unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width);
+#define vp8_vertical_band_5_3_scale vp8_vertical_band_5_3_scale_c
+
+void vp8_vertical_band_5_4_scale_c(unsigned char *source, unsigned int src_pitch, unsigned char *dest, unsigned int dest_pitch, unsigned int dest_width);
+#define vp8_vertical_band_5_4_scale vp8_vertical_band_5_4_scale_c
+
+void vp8_yv12_copy_frame_c(const struct yv12_buffer_config *src_ybc, struct yv12_buffer_config *dst_ybc);
+#define vp8_yv12_copy_frame vp8_yv12_copy_frame_c
+
+void vp8_yv12_extend_frame_borders_c(struct yv12_buffer_config *ybf);
+#define vp8_yv12_extend_frame_borders vp8_yv12_extend_frame_borders_c
+
+void vpx_extend_frame_borders_c(struct yv12_buffer_config *ybf);
+#define vpx_extend_frame_borders vpx_extend_frame_borders_c
+
+void vpx_extend_frame_inner_borders_c(struct yv12_buffer_config *ybf);
+#define vpx_extend_frame_inner_borders vpx_extend_frame_inner_borders_c
+
+void vpx_yv12_copy_frame_c(const struct yv12_buffer_config *src_ybc, struct yv12_buffer_config *dst_ybc);
+#define vpx_yv12_copy_frame vpx_yv12_copy_frame_c
+
+void vpx_yv12_copy_y_c(const struct yv12_buffer_config *src_ybc, struct yv12_buffer_config *dst_ybc);
+#define vpx_yv12_copy_y vpx_yv12_copy_y_c
+
+void vpx_scale_rtcd(void);
+
+#include "vpx_config.h"
+
+#ifdef RTCD_C
+#include "vpx_ports/arm.h"
+static void setup_rtcd_internal(void)
+{
+    int flags = arm_cpu_caps();
+
+    (void)flags;
+
+}
+#endif
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif
--- a/media/libvpx/generate_sources_mozbuild.sh
+++ b/media/libvpx/generate_sources_mozbuild.sh
@@ -75,16 +75,17 @@ function convert_srcs_to_project_files {
 
   local source_list=$(grep -E '(\.c|\.h|\.S|\.s|\.asm)$' $1)
 
   # Remove vpx_config.c.
   source_list=$(echo "$source_list" | grep -v 'vpx_config\.c')
 
   # Remove include-only asm files (no object code emitted)
   source_list=$(echo "$source_list" | grep -v 'x86_abi_support\.asm')
+  source_list=$(echo "$source_list" | grep -v 'config\.asm')
 
   # The actual ARM files end in .asm. We have rules to translate them to .S
   source_list=$(echo "$source_list" | sed s/\.asm\.s$/.asm/)
 
   # Exports - everything in vpx, vpx_mem, vpx_ports, vpx_scale
   local exports_list=$(echo "$source_list" | \
     egrep '^(vpx|vpx_mem|vpx_ports|vpx_scale)/.*h$')
   # but not anything in one level down, like 'internal'
@@ -194,27 +195,29 @@ cp -R $LIBVPX_SRC_DIR $TEMP_DIR
 cd $TEMP_DIR
 
 echo "Generate config files."
 all_platforms="--enable-external-build --disable-examples --disable-install-docs --disable-unit-tests"
 all_platforms="${all_platforms} --enable-multi-res-encoding --size-limit=8192x4608 --enable-pic"
 all_platforms="${all_platforms} --disable-avx512"
 x86_platforms="--enable-postproc --enable-vp9-postproc --as=yasm"
 arm_platforms="--enable-runtime-cpu-detect --enable-realtime-only"
+arm64_platforms="--enable-realtime-only"
 
 gen_config_files linux/x64 "--target=x86_64-linux-gcc ${all_platforms} ${x86_platforms}"
 gen_config_files linux/ia32 "--target=x86-linux-gcc ${all_platforms} ${x86_platforms}"
 gen_config_files mac/x64 "--target=x86_64-darwin9-gcc ${all_platforms} ${x86_platforms}"
 gen_config_files mac/ia32 "--target=x86-darwin9-gcc ${all_platforms} ${x86_platforms}"
 gen_config_files win/x64 "--target=x86_64-win64-vs12 ${all_platforms} ${x86_platforms}"
 gen_config_files win/ia32 "--target=x86-win32-gcc ${all_platforms} ${x86_platforms}"
 gen_config_files win/mingw32 "--target=x86-win32-gcc ${all_platforms} ${x86_platforms}"
 gen_config_files win/aarch64 "--target=aarch64-win64-vs12 ${all_platforms}"
 
 gen_config_files linux/arm "--target=armv7-linux-gcc ${all_platforms} ${arm_platforms}"
+gen_config_files linux/arm64 "--target=arm64-linux-gcc ${all_platforms} ${arm64_platforms}"
 
 gen_config_files generic "--target=generic-gnu ${all_platforms}"
 
 # vpx doesn't know if mingw32 has winpthreads or not, and doesn't try to detect it.
 sed -i 's/HAVE_PTHREAD_H 0/HAVE_PTHREAD_H 1/' $BASE_DIR/$LIBVPX_CONFIG_DIR/win/mingw32/vpx_config.asm
 sed -i 's/HAVE_PTHREAD_H 0/HAVE_PTHREAD_H 1/' $BASE_DIR/$LIBVPX_CONFIG_DIR/win/mingw32/vpx_config.h
 
 echo "Remove temporary directory."
@@ -233,16 +236,17 @@ gen_rtcd_header mac/x64 x86_64
 gen_rtcd_header mac/ia32 x86
 gen_rtcd_header win/x64 x86_64
 gen_rtcd_header win/ia32 x86
 gen_rtcd_header win/mingw32 x86
 gen_rtcd_header win/aarch64 aarch64
 
 
 gen_rtcd_header linux/arm armv7
+gen_rtcd_header linux/arm64 arm64
 
 gen_rtcd_header generic generic
 
 echo "Prepare Makefile."
 ./configure --target=generic-gnu > /dev/null
 make_clean
 
 # Remove existing source files.
@@ -266,16 +270,22 @@ make libvpx_srcs.txt target=libs $config
 convert_srcs_to_project_files libvpx_srcs.txt IA32
 
 echo "Generate ARM source list."
 config=$(print_config linux/arm)
 make_clean
 make libvpx_srcs.txt target=libs $config > /dev/null
 convert_srcs_to_project_files libvpx_srcs.txt ARM
 
+echo "Generate ARM64 source list."
+config=$(print_config linux/arm64)
+make_clean
+make libvpx_srcs.txt target=libs $config > /dev/null
+convert_srcs_to_project_files libvpx_srcs.txt ARM64
+
 echo "Generate generic source list."
 config=$(print_config generic)
 make_clean
 make libvpx_srcs.txt target=libs $config > /dev/null
 convert_srcs_to_project_files libvpx_srcs.txt GENERIC
 
 echo "}" >> $BASE_DIR/sources.mozbuild
 
--- a/media/libvpx/moz.build
+++ b/media/libvpx/moz.build
@@ -76,16 +76,21 @@ elif CONFIG['CPU_ARCH'] == 'arm':
             '-no-integrated-as',
         ]
 elif CONFIG['CPU_ARCH'] == 'aarch64' and CONFIG['OS_TARGET'] == 'WINNT':
     # Generic C-only configuration
     EXPORTS.vpx += files['GENERIC_EXPORTS']
     SOURCES += files['GENERIC_SOURCES']
     ASFLAGS += [ '-I%s/media/libvpx/config/win/aarch64/' % TOPSRCDIR ]
     LOCAL_INCLUDES += [ '/media/libvpx/config/win/aarch64/' ]
+elif CONFIG['CPU_ARCH'] == 'aarch64':
+    EXPORTS.vpx += files['ARM64_EXPORTS']
+    SOURCES += files['ARM64_SOURCES']
+    ASFLAGS += [ '-I%s/media/libvpx/config/linux/arm64/' % TOPSRCDIR ]
+    LOCAL_INCLUDES += [ '/media/libvpx/config/linux/arm64/' ]
 else:
     # Generic C-only configuration
     EXPORTS.vpx += files['GENERIC_EXPORTS']
     SOURCES += files['GENERIC_SOURCES']
     ASFLAGS += [ '-I%s/media/libvpx/config/generic/' % TOPSRCDIR ]
     LOCAL_INCLUDES += [ '/media/libvpx/config/generic/' ]
 
 # We allow warnings for third-party code that can be updated from upstream.
--- a/media/libvpx/sources.mozbuild
+++ b/media/libvpx/sources.mozbuild
@@ -752,16 +752,245 @@ files = {
     'libvpx/vpx_scale/generic/gen_scalers.c',
     'libvpx/vpx_scale/generic/vpx_scale.c',
     'libvpx/vpx_scale/generic/yv12config.c',
     'libvpx/vpx_scale/generic/yv12extend.c',
     'libvpx/vpx_scale/vpx_scale_rtcd.c',
     'libvpx/vpx_util/vpx_thread.c',
     'libvpx/vpx_util/vpx_write_yuv_frame.c',
 ],
+  'ARM64_EXPORTS': [
+    'libvpx/vpx/vp8.h',
+    'libvpx/vpx/vp8cx.h',
+    'libvpx/vpx/vp8dx.h',
+    'libvpx/vpx/vpx_codec.h',
+    'libvpx/vpx/vpx_decoder.h',
+    'libvpx/vpx/vpx_encoder.h',
+    'libvpx/vpx/vpx_frame_buffer.h',
+    'libvpx/vpx/vpx_image.h',
+    'libvpx/vpx/vpx_integer.h',
+    'libvpx/vpx_mem/include/vpx_mem_intrnl.h',
+    'libvpx/vpx_mem/vpx_mem.h',
+    'libvpx/vpx_ports/arm.h',
+    'libvpx/vpx_ports/bitops.h',
+    'libvpx/vpx_ports/mem.h',
+    'libvpx/vpx_ports/system_state.h',
+    'libvpx/vpx_ports/vpx_timer.h',
+    'libvpx/vpx_scale/vpx_scale.h',
+    'libvpx/vpx_scale/yv12config.h',
+],
+  'ARM64_SOURCES': [
+    'libvpx/vp8/common/alloccommon.c',
+    'libvpx/vp8/common/arm/loopfilter_arm.c',
+    'libvpx/vp8/common/arm/neon/bilinearpredict_neon.c',
+    'libvpx/vp8/common/arm/neon/copymem_neon.c',
+    'libvpx/vp8/common/arm/neon/dc_only_idct_add_neon.c',
+    'libvpx/vp8/common/arm/neon/dequant_idct_neon.c',
+    'libvpx/vp8/common/arm/neon/dequantizeb_neon.c',
+    'libvpx/vp8/common/arm/neon/idct_blk_neon.c',
+    'libvpx/vp8/common/arm/neon/idct_dequant_0_2x_neon.c',
+    'libvpx/vp8/common/arm/neon/idct_dequant_full_2x_neon.c',
+    'libvpx/vp8/common/arm/neon/iwalsh_neon.c',
+    'libvpx/vp8/common/arm/neon/loopfiltersimplehorizontaledge_neon.c',
+    'libvpx/vp8/common/arm/neon/loopfiltersimpleverticaledge_neon.c',
+    'libvpx/vp8/common/arm/neon/mbloopfilter_neon.c',
+    'libvpx/vp8/common/arm/neon/shortidct4x4llm_neon.c',
+    'libvpx/vp8/common/arm/neon/sixtappredict_neon.c',
+    'libvpx/vp8/common/arm/neon/vp8_loopfilter_neon.c',
+    'libvpx/vp8/common/blockd.c',
+    'libvpx/vp8/common/copy_c.c',
+    'libvpx/vp8/common/dequantize.c',
+    'libvpx/vp8/common/entropy.c',
+    'libvpx/vp8/common/entropymode.c',
+    'libvpx/vp8/common/entropymv.c',
+    'libvpx/vp8/common/extend.c',
+    'libvpx/vp8/common/filter.c',
+    'libvpx/vp8/common/findnearmv.c',
+    'libvpx/vp8/common/generic/systemdependent.c',
+    'libvpx/vp8/common/idct_blk.c',
+    'libvpx/vp8/common/idctllm.c',
+    'libvpx/vp8/common/loopfilter_filters.c',
+    'libvpx/vp8/common/mbpitch.c',
+    'libvpx/vp8/common/modecont.c',
+    'libvpx/vp8/common/quant_common.c',
+    'libvpx/vp8/common/reconinter.c',
+    'libvpx/vp8/common/reconintra.c',
+    'libvpx/vp8/common/reconintra4x4.c',
+    'libvpx/vp8/common/rtcd.c',
+    'libvpx/vp8/common/setupintrarecon.c',
+    'libvpx/vp8/common/swapyv12buffer.c',
+    'libvpx/vp8/common/treecoder.c',
+    'libvpx/vp8/common/vp8_loopfilter.c',
+    'libvpx/vp8/common/vp8_skin_detection.c',
+    'libvpx/vp8/decoder/dboolhuff.c',
+    'libvpx/vp8/decoder/decodeframe.c',
+    'libvpx/vp8/decoder/decodemv.c',
+    'libvpx/vp8/decoder/detokenize.c',
+    'libvpx/vp8/decoder/onyxd_if.c',
+    'libvpx/vp8/decoder/threading.c',
+    'libvpx/vp8/encoder/arm/neon/denoising_neon.c',
+    'libvpx/vp8/encoder/arm/neon/fastquantizeb_neon.c',
+    'libvpx/vp8/encoder/arm/neon/shortfdct_neon.c',
+    'libvpx/vp8/encoder/arm/neon/vp8_shortwalsh4x4_neon.c',
+    'libvpx/vp8/encoder/bitstream.c',
+    'libvpx/vp8/encoder/boolhuff.c',
+    'libvpx/vp8/encoder/dct.c',
+    'libvpx/vp8/encoder/denoising.c',
+    'libvpx/vp8/encoder/encodeframe.c',
+    'libvpx/vp8/encoder/encodeintra.c',
+    'libvpx/vp8/encoder/encodemb.c',
+    'libvpx/vp8/encoder/encodemv.c',
+    'libvpx/vp8/encoder/ethreading.c',
+    'libvpx/vp8/encoder/lookahead.c',
+    'libvpx/vp8/encoder/mcomp.c',
+    'libvpx/vp8/encoder/modecosts.c',
+    'libvpx/vp8/encoder/mr_dissim.c',
+    'libvpx/vp8/encoder/onyx_if.c',
+    'libvpx/vp8/encoder/pickinter.c',
+    'libvpx/vp8/encoder/picklpf.c',
+    'libvpx/vp8/encoder/ratectrl.c',
+    'libvpx/vp8/encoder/rdopt.c',
+    'libvpx/vp8/encoder/segmentation.c',
+    'libvpx/vp8/encoder/tokenize.c',
+    'libvpx/vp8/encoder/treewriter.c',
+    'libvpx/vp8/encoder/vp8_quantize.c',
+    'libvpx/vp8/vp8_cx_iface.c',
+    'libvpx/vp8/vp8_dx_iface.c',
+    'libvpx/vp9/common/arm/neon/vp9_iht4x4_add_neon.c',
+    'libvpx/vp9/common/arm/neon/vp9_iht8x8_add_neon.c',
+    'libvpx/vp9/common/vp9_alloccommon.c',
+    'libvpx/vp9/common/vp9_blockd.c',
+    'libvpx/vp9/common/vp9_common_data.c',
+    'libvpx/vp9/common/vp9_entropy.c',
+    'libvpx/vp9/common/vp9_entropymode.c',
+    'libvpx/vp9/common/vp9_entropymv.c',
+    'libvpx/vp9/common/vp9_filter.c',
+    'libvpx/vp9/common/vp9_frame_buffers.c',
+    'libvpx/vp9/common/vp9_idct.c',
+    'libvpx/vp9/common/vp9_loopfilter.c',
+    'libvpx/vp9/common/vp9_mvref_common.c',
+    'libvpx/vp9/common/vp9_pred_common.c',
+    'libvpx/vp9/common/vp9_quant_common.c',
+    'libvpx/vp9/common/vp9_reconinter.c',
+    'libvpx/vp9/common/vp9_reconintra.c',
+    'libvpx/vp9/common/vp9_rtcd.c',
+    'libvpx/vp9/common/vp9_scale.c',
+    'libvpx/vp9/common/vp9_scan.c',
+    'libvpx/vp9/common/vp9_seg_common.c',
+    'libvpx/vp9/common/vp9_thread_common.c',
+    'libvpx/vp9/common/vp9_tile_common.c',
+    'libvpx/vp9/decoder/vp9_decodeframe.c',
+    'libvpx/vp9/decoder/vp9_decodemv.c',
+    'libvpx/vp9/decoder/vp9_decoder.c',
+    'libvpx/vp9/decoder/vp9_detokenize.c',
+    'libvpx/vp9/decoder/vp9_dsubexp.c',
+    'libvpx/vp9/encoder/arm/neon/vp9_dct_neon.c',
+    'libvpx/vp9/encoder/arm/neon/vp9_error_neon.c',
+    'libvpx/vp9/encoder/arm/neon/vp9_frame_scale_neon.c',
+    'libvpx/vp9/encoder/arm/neon/vp9_quantize_neon.c',
+    'libvpx/vp9/encoder/vp9_alt_ref_aq.c',
+    'libvpx/vp9/encoder/vp9_aq_360.c',
+    'libvpx/vp9/encoder/vp9_aq_complexity.c',
+    'libvpx/vp9/encoder/vp9_aq_cyclicrefresh.c',
+    'libvpx/vp9/encoder/vp9_aq_variance.c',
+    'libvpx/vp9/encoder/vp9_bitstream.c',
+    'libvpx/vp9/encoder/vp9_context_tree.c',
+    'libvpx/vp9/encoder/vp9_cost.c',
+    'libvpx/vp9/encoder/vp9_dct.c',
+    'libvpx/vp9/encoder/vp9_encodeframe.c',
+    'libvpx/vp9/encoder/vp9_encodemb.c',
+    'libvpx/vp9/encoder/vp9_encodemv.c',
+    'libvpx/vp9/encoder/vp9_encoder.c',
+    'libvpx/vp9/encoder/vp9_ethread.c',
+    'libvpx/vp9/encoder/vp9_extend.c',
+    'libvpx/vp9/encoder/vp9_frame_scale.c',
+    'libvpx/vp9/encoder/vp9_lookahead.c',
+    'libvpx/vp9/encoder/vp9_mcomp.c',
+    'libvpx/vp9/encoder/vp9_multi_thread.c',
+    'libvpx/vp9/encoder/vp9_noise_estimate.c',
+    'libvpx/vp9/encoder/vp9_picklpf.c',
+    'libvpx/vp9/encoder/vp9_pickmode.c',
+    'libvpx/vp9/encoder/vp9_quantize.c',
+    'libvpx/vp9/encoder/vp9_ratectrl.c',
+    'libvpx/vp9/encoder/vp9_rd.c',
+    'libvpx/vp9/encoder/vp9_rdopt.c',
+    'libvpx/vp9/encoder/vp9_resize.c',
+    'libvpx/vp9/encoder/vp9_segmentation.c',
+    'libvpx/vp9/encoder/vp9_skin_detection.c',
+    'libvpx/vp9/encoder/vp9_speed_features.c',
+    'libvpx/vp9/encoder/vp9_subexp.c',
+    'libvpx/vp9/encoder/vp9_svc_layercontext.c',
+    'libvpx/vp9/encoder/vp9_tokenize.c',
+    'libvpx/vp9/encoder/vp9_treewriter.c',
+    'libvpx/vp9/vp9_cx_iface.c',
+    'libvpx/vp9/vp9_dx_iface.c',
+    'libvpx/vpx/src/vpx_codec.c',
+    'libvpx/vpx/src/vpx_decoder.c',
+    'libvpx/vpx/src/vpx_encoder.c',
+    'libvpx/vpx/src/vpx_image.c',
+    'libvpx/vpx_dsp/arm/avg_neon.c',
+    'libvpx/vpx_dsp/arm/avg_pred_neon.c',
+    'libvpx/vpx_dsp/arm/fdct16x16_neon.c',
+    'libvpx/vpx_dsp/arm/fdct32x32_neon.c',
+    'libvpx/vpx_dsp/arm/fdct_neon.c',
+    'libvpx/vpx_dsp/arm/fdct_partial_neon.c',
+    'libvpx/vpx_dsp/arm/fwd_txfm_neon.c',
+    'libvpx/vpx_dsp/arm/hadamard_neon.c',
+    'libvpx/vpx_dsp/arm/idct16x16_1_add_neon.c',
+    'libvpx/vpx_dsp/arm/idct16x16_add_neon.c',
+    'libvpx/vpx_dsp/arm/idct32x32_135_add_neon.c',
+    'libvpx/vpx_dsp/arm/idct32x32_1_add_neon.c',
+    'libvpx/vpx_dsp/arm/idct32x32_34_add_neon.c',
+    'libvpx/vpx_dsp/arm/idct32x32_add_neon.c',
+    'libvpx/vpx_dsp/arm/idct4x4_1_add_neon.c',
+    'libvpx/vpx_dsp/arm/idct4x4_add_neon.c',
+    'libvpx/vpx_dsp/arm/idct8x8_1_add_neon.c',
+    'libvpx/vpx_dsp/arm/idct8x8_add_neon.c',
+    'libvpx/vpx_dsp/arm/intrapred_neon.c',
+    'libvpx/vpx_dsp/arm/loopfilter_neon.c',
+    'libvpx/vpx_dsp/arm/quantize_neon.c',
+    'libvpx/vpx_dsp/arm/sad4d_neon.c',
+    'libvpx/vpx_dsp/arm/sad_neon.c',
+    'libvpx/vpx_dsp/arm/subpel_variance_neon.c',
+    'libvpx/vpx_dsp/arm/subtract_neon.c',
+    'libvpx/vpx_dsp/arm/variance_neon.c',
+    'libvpx/vpx_dsp/arm/vpx_convolve8_neon.c',
+    'libvpx/vpx_dsp/arm/vpx_convolve_avg_neon.c',
+    'libvpx/vpx_dsp/arm/vpx_convolve_copy_neon.c',
+    'libvpx/vpx_dsp/arm/vpx_convolve_neon.c',
+    'libvpx/vpx_dsp/arm/vpx_scaled_convolve8_neon.c',
+    'libvpx/vpx_dsp/avg.c',
+    'libvpx/vpx_dsp/bitreader.c',
+    'libvpx/vpx_dsp/bitreader_buffer.c',
+    'libvpx/vpx_dsp/bitwriter.c',
+    'libvpx/vpx_dsp/bitwriter_buffer.c',
+    'libvpx/vpx_dsp/fwd_txfm.c',
+    'libvpx/vpx_dsp/intrapred.c',
+    'libvpx/vpx_dsp/inv_txfm.c',
+    'libvpx/vpx_dsp/loopfilter.c',
+    'libvpx/vpx_dsp/prob.c',
+    'libvpx/vpx_dsp/psnr.c',
+    'libvpx/vpx_dsp/quantize.c',
+    'libvpx/vpx_dsp/sad.c',
+    'libvpx/vpx_dsp/skin_detection.c',
+    'libvpx/vpx_dsp/subtract.c',
+    'libvpx/vpx_dsp/sum_squares.c',
+    'libvpx/vpx_dsp/variance.c',
+    'libvpx/vpx_dsp/vpx_convolve.c',
+    'libvpx/vpx_dsp/vpx_dsp_rtcd.c',
+    'libvpx/vpx_mem/vpx_mem.c',
+    'libvpx/vpx_ports/arm_cpudetect.c',
+    'libvpx/vpx_scale/generic/gen_scalers.c',
+    'libvpx/vpx_scale/generic/vpx_scale.c',
+    'libvpx/vpx_scale/generic/yv12config.c',
+    'libvpx/vpx_scale/generic/yv12extend.c',
+    'libvpx/vpx_scale/vpx_scale_rtcd.c',
+    'libvpx/vpx_util/vpx_thread.c',
+    'libvpx/vpx_util/vpx_write_yuv_frame.c',
+],
   'GENERIC_EXPORTS': [
     'libvpx/vpx/vp8.h',
     'libvpx/vpx/vp8cx.h',
     'libvpx/vpx/vp8dx.h',
     'libvpx/vpx/vpx_codec.h',
     'libvpx/vpx/vpx_decoder.h',
     'libvpx/vpx/vpx_encoder.h',
     'libvpx/vpx/vpx_frame_buffer.h',
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/mixed-content/classic-data-worker-fetch/http-csp/cross-origin-http/top-level/keep-scheme-redirect/blockable/opt-in-blocks.https.html.ini
@@ -0,0 +1,4 @@
+[opt-in-blocks.https.html]
+  [opt_in_method: http-csp\n                                 origin: cross-origin-http\n                                 source_scheme: https\n                                 context_nesting: top-level\n                                 redirection: keep-scheme-redirect\n                                 subresource: classic-data-worker-fetch\n                                 expectation: blocked]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/mixed-content/classic-data-worker-fetch/http-csp/cross-origin-http/top-level/no-redirect/blockable/opt-in-blocks.https.html.ini
@@ -0,0 +1,4 @@
+[opt-in-blocks.https.html]
+  [opt_in_method: http-csp\n                                 origin: cross-origin-http\n                                 source_scheme: https\n                                 context_nesting: top-level\n                                 redirection: no-redirect\n                                 subresource: classic-data-worker-fetch\n                                 expectation: blocked]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/mixed-content/classic-data-worker-fetch/http-csp/cross-origin-http/top-level/swap-scheme-redirect/blockable/opt-in-blocks.https.html.ini
@@ -0,0 +1,4 @@
+[opt-in-blocks.https.html]
+  [opt_in_method: http-csp\n                                 origin: cross-origin-http\n                                 source_scheme: https\n                                 context_nesting: top-level\n                                 redirection: swap-scheme-redirect\n                                 subresource: classic-data-worker-fetch\n                                 expectation: blocked]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/mixed-content/classic-data-worker-fetch/http-csp/same-host-http/top-level/keep-scheme-redirect/blockable/opt-in-blocks.https.html.ini
@@ -0,0 +1,4 @@
+[opt-in-blocks.https.html]
+  [opt_in_method: http-csp\n                                 origin: same-host-http\n                                 source_scheme: https\n                                 context_nesting: top-level\n                                 redirection: keep-scheme-redirect\n                                 subresource: classic-data-worker-fetch\n                                 expectation: blocked]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/mixed-content/classic-data-worker-fetch/http-csp/same-host-http/top-level/no-redirect/blockable/opt-in-blocks.https.html.ini
@@ -0,0 +1,4 @@
+[opt-in-blocks.https.html]
+  [opt_in_method: http-csp\n                                 origin: same-host-http\n                                 source_scheme: https\n                                 context_nesting: top-level\n                                 redirection: no-redirect\n                                 subresource: classic-data-worker-fetch\n                                 expectation: blocked]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/mixed-content/classic-data-worker-fetch/http-csp/same-host-http/top-level/swap-scheme-redirect/blockable/opt-in-blocks.https.html.ini
@@ -0,0 +1,4 @@
+[opt-in-blocks.https.html]
+  [opt_in_method: http-csp\n                                 origin: same-host-http\n                                 source_scheme: https\n                                 context_nesting: top-level\n                                 redirection: swap-scheme-redirect\n                                 subresource: classic-data-worker-fetch\n                                 expectation: blocked]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/mixed-content/classic-data-worker-fetch/meta-csp/cross-origin-http/top-level/no-redirect/blockable/opt-in-blocks.https.html.ini
@@ -0,0 +1,4 @@
+[opt-in-blocks.https.html]
+  [opt_in_method: meta-csp\n                                 origin: cross-origin-http\n                                 source_scheme: https\n                                 context_nesting: top-level\n                                 redirection: no-redirect\n                                 subresource: classic-data-worker-fetch\n                                 expectation: blocked]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/mixed-content/classic-data-worker-fetch/meta-csp/same-host-http/top-level/no-redirect/blockable/opt-in-blocks.https.html.ini
@@ -0,0 +1,4 @@
+[opt-in-blocks.https.html]
+  [opt_in_method: meta-csp\n                                 origin: same-host-http\n                                 source_scheme: https\n                                 context_nesting: top-level\n                                 redirection: no-redirect\n                                 subresource: classic-data-worker-fetch\n                                 expectation: blocked]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/mixed-content/classic-data-worker-fetch/no-opt-in/cross-origin-http/top-level/keep-scheme-redirect/blockable/no-opt-in-blocks.https.html.ini
@@ -0,0 +1,4 @@
+[no-opt-in-blocks.https.html]
+  [opt_in_method: no-opt-in\n                                 origin: cross-origin-http\n                                 source_scheme: https\n                                 context_nesting: top-level\n                                 redirection: keep-scheme-redirect\n                                 subresource: classic-data-worker-fetch\n                                 expectation: blocked]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/mixed-content/classic-data-worker-fetch/no-opt-in/cross-origin-http/top-level/no-redirect/blockable/no-opt-in-blocks.https.html.ini
@@ -0,0 +1,4 @@
+[no-opt-in-blocks.https.html]
+  [opt_in_method: no-opt-in\n                                 origin: cross-origin-http\n                                 source_scheme: https\n                                 context_nesting: top-level\n                                 redirection: no-redirect\n                                 subresource: classic-data-worker-fetch\n                                 expectation: blocked]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/mixed-content/classic-data-worker-fetch/no-opt-in/cross-origin-http/top-level/swap-scheme-redirect/blockable/no-opt-in-blocks.https.html.ini
@@ -0,0 +1,4 @@
+[no-opt-in-blocks.https.html]
+  [opt_in_method: no-opt-in\n                                 origin: cross-origin-http\n                                 source_scheme: https\n                                 context_nesting: top-level\n                                 redirection: swap-scheme-redirect\n                                 subresource: classic-data-worker-fetch\n                                 expectation: blocked]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/mixed-content/classic-data-worker-fetch/no-opt-in/same-host-http/top-level/keep-scheme-redirect/blockable/no-opt-in-blocks.https.html.ini
@@ -0,0 +1,4 @@
+[no-opt-in-blocks.https.html]
+  [opt_in_method: no-opt-in\n                                 origin: same-host-http\n                                 source_scheme: https\n                                 context_nesting: top-level\n                                 redirection: keep-scheme-redirect\n                                 subresource: classic-data-worker-fetch\n                                 expectation: blocked]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/mixed-content/classic-data-worker-fetch/no-opt-in/same-host-http/top-level/no-redirect/blockable/no-opt-in-blocks.https.html.ini
@@ -0,0 +1,4 @@
+[no-opt-in-blocks.https.html]
+  [opt_in_method: no-opt-in\n                                 origin: same-host-http\n                                 source_scheme: https\n                                 context_nesting: top-level\n                                 redirection: no-redirect\n                                 subresource: classic-data-worker-fetch\n                                 expectation: blocked]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/mixed-content/classic-data-worker-fetch/no-opt-in/same-host-http/top-level/swap-scheme-redirect/blockable/no-opt-in-blocks.https.html.ini
@@ -0,0 +1,4 @@
+[no-opt-in-blocks.https.html]
+  [opt_in_method: no-opt-in\n                                 origin: same-host-http\n                                 source_scheme: https\n                                 context_nesting: top-level\n                                 redirection: swap-scheme-redirect\n                                 subresource: classic-data-worker-fetch\n                                 expectation: blocked]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-ui/reference/text-overflow-030-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+.positioned {
+  background-color: green;
+  position: absolute;
+  width: 100px;
+  height: 100px;
+}
+</style>
+<p>Test passes if there is a green rectangle and no red.</p>
+<div class="positioned"></div>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-ui/text-overflow-030.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Basic User Interface Test: ellipsis should render under other positioned content</title>
+<link rel="author" title="Cameron McCormack" href="mailto:cam@mcc.id.au">
+<link rel="help" href="http://www.w3.org/TR/css3-ui/#text-overflow">
+<link rel="match" href="reference/text-overflow-030-ref.html">
+<style>
+.positioned {
+  background-color: green;
+  position: absolute;
+  width: 100px;
+  height: 100px;
+}
+.ellipsis {
+  color: red;
+  overflow-x: hidden;
+  text-overflow: ellipsis;
+  white-space: pre;
+  width: 100px;
+  font: 50px sans-serif;
+}
+</style>
+<p>Test passes if there is a green rectangle and no red.</p>
+<div class="positioned"></div>
+<div class="ellipsis">         </div>
--- a/testing/web-platform/tests/html/browsers/origin/cross-origin-objects/cross-origin-objects.html
+++ b/testing/web-platform/tests/html/browsers/origin/cross-origin-objects/cross-origin-objects.html
@@ -101,26 +101,32 @@ addTest(function() {
     if (prop != 'location')
       assert_throws("SecurityError", function() { C[prop] = undefined; }, "Should throw when writing to " + prop + " on Window");
   }
   for (var prop in location) {
     if (prop == 'replace') {
       C.location[prop]; // Shouldn't throw.
       Object.getOwnPropertyDescriptor(C.location, prop); // Shouldn't throw.
       assert_true(Object.prototype.hasOwnProperty.call(C.location, prop), "hasOwnProperty for " + prop);
+      assert_throws("SecurityError", function() { C.location[prop] = undefined; }, "Should throw when writing to " + prop + " on Location");
+    }
+    else if (prop == 'href') {
+      Object.getOwnPropertyDescriptor(C.location, prop); // Shouldn't throw.
+      assert_true(Object.prototype.hasOwnProperty.call(C.location, prop), "hasOwnProperty for " + prop);
+      assert_throws("SecurityError", function() { C.location[prop] },
+                    "Should throw reading href on Location");
     }
     else {
-      assert_throws("SecurityError", function() { C[prop]; }, "Should throw when accessing " + prop + " on Location");
-      assert_throws("SecurityError", function() { Object.getOwnPropertyDescriptor(C, prop); },
+      assert_throws("SecurityError", function() { C.location[prop]; }, "Should throw when accessing " + prop + " on Location");
+      assert_throws("SecurityError", function() { Object.getOwnPropertyDescriptor(C.location, prop); },
                     "Should throw when accessing property descriptor for " + prop + " on Location");
-      assert_throws("SecurityError", function() { Object.prototype.hasOwnProperty.call(C, prop); },
+      assert_throws("SecurityError", function() { Object.prototype.hasOwnProperty.call(C.location, prop); },
                     "Should throw when invoking hasOwnProperty for " + prop + " on Location");
+      assert_throws("SecurityError", function() { C.location[prop] = undefined; }, "Should throw when writing to " + prop + " on Location");
     }
-    if (prop != 'href')
-      assert_throws("SecurityError", function() { C[prop] = undefined; }, "Should throw when writing to " + prop + " on Location");
   }
 }, "Only whitelisted properties are accessible cross-origin");
 
 /*
  * ES Internal Methods.
  */
 
 /*
@@ -145,21 +151,32 @@ addTest(function() {
   assert_throws("SecurityError", function() { C.location.__proto__ = new Object(); }, "proto set on cross-origin Location");
   var setters = [Object.getOwnPropertyDescriptor(Object.prototype, '__proto__').set];
   if (Object.setPrototypeOf)
     setters.push(function(p) { Object.setPrototypeOf(this, p); });
   setters.forEach(function(protoSetter) {
     assert_throws(new TypeError, function() { protoSetter.call(C, new Object()); }, "proto setter |call| on cross-origin Window");
     assert_throws(new TypeError, function() { protoSetter.call(C.location, new Object()); }, "proto setter |call| on cross-origin Location");
   });
+  // Hack to avoid "duplicate test name" harness issues.
+  setters.forEach(function(protoSetter) {
+    test(function() { protoSetter.call(C, null); },
+         "proto setter |call| on cross-origin Window with null (" + protoSetter + ")");
+    test(function() { protoSetter.call(C.location, null); },
+         "proto setter |call| on cross-origin Location with null (" + protoSetter + ")");
+  });
   if (Reflect.setPrototypeOf) {
     assert_false(Reflect.setPrototypeOf(C, new Object()),
                  "Reflect.setPrototypeOf on cross-origin Window");
+    assert_true(Reflect.setPrototypeOf(C, null),
+                "Reflect.setPrototypeOf on cross-origin Window with null");
     assert_false(Reflect.setPrototypeOf(C.location, new Object()),
                 "Reflect.setPrototypeOf on cross-origin Location");
+    assert_true(Reflect.setPrototypeOf(C.location, null),
+                "Reflect.setPrototypeOf on cross-origin Location with null");
   }
 }, "[[SetPrototypeOf]] should return false");
 
 /*
  * [[IsExtensible]]
  */
 addTest(function() {
   assert_true(Object.isExtensible(C), "cross-origin Window should be extensible");
@@ -225,16 +242,29 @@ addTest(function() {
     checkPropertyDescriptor(desc, prop, false);
   });
 }, "[[GetOwnProperty]] - Property descriptors for cross-origin properties should be set up correctly");
 
 addTest(function() {
   assert_equals(typeof D.then, "object");
 }, "[[GetOwnProperty]] - Subframe named 'then' should shadow the default 'then' value");
 
+addTest(function() {
+  assert_equals(typeof D.close, "function");
+  assert_equals(typeof D.open, "object");
+}, "[[GetOwnProperty]] - Subframes should be visible cross-origin only if their names don't match the names of cross-origin-exposed IDL properties");
+
+addTest(function() {
+  assert_equals(typeof Object.getOwnPropertyDescriptor(C, '0').value, "object");
+  assert_equals(typeof Object.getOwnPropertyDescriptor(C, '1').value, "object");
+  assert_throws("SecurityError", function() {
+    Object.getOwnPropertyDescriptor(C, '2');
+  });
+}, "[[GetOwnProperty]] - Should be able to get a property descriptor for an indexed property only if it corresponds to a child window.");
+
 /*
  * [[Delete]]
  */
 addTest(function() {
   assert_throws("SecurityError", function() { delete C[0]; }, "Can't delete cross-origin indexed property");
   assert_throws("SecurityError", function() { delete C[100]; }, "Can't delete cross-origin indexed property");
   assert_throws("SecurityError", function() { delete C.location; }, "Can't delete cross-origin property");
   assert_throws("SecurityError", function() { delete C.parent; }, "Can't delete cross-origin property");
--- a/testing/web-platform/tests/html/browsers/origin/cross-origin-objects/frame-with-then.html
+++ b/testing/web-platform/tests/html/browsers/origin/cross-origin-objects/frame-with-then.html
@@ -1,10 +1,14 @@
 <!doctype html>
 <html>
   <body>
     <!--- Some frames to test ordering -->
     <iframe name="a"></iframe>
     <!-- A subframe to test "then" behavior -->
     <iframe name="then"></iframe>
     <iframe name="b"></iframe>
+    <!-- Two subframes with names corresponding to IDL-defined properties; one
+         a cross-origin-exposed property and one not exposed cross-origin -->
+    <iframe name="close"></iframe>
+    <iframe name="open"></iframe>
   </body>
 </html>
--- a/toolkit/components/url-classifier/nsUrlClassifierDBService.cpp
+++ b/toolkit/components/url-classifier/nsUrlClassifierDBService.cpp
@@ -2071,19 +2071,21 @@ nsUrlClassifierDBService::Lookup(nsIPrin
                                  const nsACString& tables,
                                  nsIUrlClassifierCallback* c) {
   NS_ENSURE_TRUE(gDbBackgroundThread, NS_ERROR_NOT_INITIALIZED);
 
   bool dummy;
   return LookupURI(aPrincipal, tables, c, true, &dummy);
 }
 
-nsresult nsUrlClassifierDBService::LookupURI(
-    nsIPrincipal* aPrincipal, const nsACString& tables,
-    nsIUrlClassifierCallback* c, bool forceLookup, bool* didLookup) {
+nsresult nsUrlClassifierDBService::LookupURI(nsIPrincipal* aPrincipal,
+                                             const nsACString& tables,
+                                             nsIUrlClassifierCallback* c,
+                                             bool forceLookup,
+                                             bool* didLookup) {
   NS_ENSURE_TRUE(gDbBackgroundThread, NS_ERROR_NOT_INITIALIZED);
   NS_ENSURE_ARG(aPrincipal);
 
   if (nsContentUtils::IsSystemPrincipal(aPrincipal)) {
     *didLookup = false;
     return NS_OK;
   }
 
--- a/toolkit/content/widgets/datetimebox.js
+++ b/toolkit/content/widgets/datetimebox.js
@@ -303,17 +303,17 @@ this.DateTimeInputBaseImplWidget = class
       field.setAttribute("role", "textbox");
     }
 
     return field;
   }
 
   updateResetButtonVisibility() {
     if (this.isAnyFieldAvailable(false)) {
-      this.mResetButton.style.visibility = "visible";
+      this.mResetButton.style.visibility = "";
     } else {
       this.mResetButton.style.visibility = "hidden";
     }
   }
 
   focusInnerTextBox() {
     this.log("Focus inner editable field.");
 
--- a/tools/profiler/public/GeckoProfiler.h
+++ b/tools/profiler/public/GeckoProfiler.h
@@ -44,27 +44,27 @@
 #  define AUTO_PROFILER_LABEL(label, category)
 #  define AUTO_PROFILER_LABEL_DYNAMIC_CSTR(label, category, cStr)
 #  define AUTO_PROFILER_LABEL_DYNAMIC_NSCSTRING(label, category, nsCStr)
 #  define AUTO_PROFILER_LABEL_DYNAMIC_LOSSY_NSSTRING(label, category, nsStr)
 #  define AUTO_PROFILER_LABEL_FAST(label, category, ctx)
 #  define AUTO_PROFILER_LABEL_DYNAMIC_FAST(label, dynamicString, category, \
                                            ctx, flags)
 
-#define PROFILER_ADD_MARKER(markerName, category)
-#define PROFILER_ADD_NETWORK_MARKER(uri, pri, channel, type, start, end, \
-                                    count, cache, timings, redirect)
+#  define PROFILER_ADD_MARKER(markerName, category)
+#  define PROFILER_ADD_NETWORK_MARKER(uri, pri, channel, type, start, end, \
+                                      count, cache, timings, redirect)
 
-#define DECLARE_DOCSHELL_AND_HISTORY_ID(docShell)
-#define PROFILER_TRACING(categoryString, markerName, category, kind)
-#define PROFILER_TRACING_DOCSHELL(categoryString, markerName, category, kind, \
-                                  docshell)
-#define AUTO_PROFILER_TRACING(categoryString, markerName, category)
-#define AUTO_PROFILER_TRACING_DOCSHELL(categoryString, markerName, category, \
-                                       docShell)
+#  define DECLARE_DOCSHELL_AND_HISTORY_ID(docShell)
+#  define PROFILER_TRACING(categoryString, markerName, category, kind)
+#  define PROFILER_TRACING_DOCSHELL(categoryString, markerName, category, \
+                                    kind, docshell)
+#  define AUTO_PROFILER_TRACING(categoryString, markerName, category)
+#  define AUTO_PROFILER_TRACING_DOCSHELL(categoryString, markerName, category, \
+                                         docShell)
 
 #else  // !MOZ_GECKO_PROFILER
 
 #  include <functional>
 #  include <signal.h>
 #  include <stdarg.h>
 #  include <stdint.h>
 #  include <stdlib.h>
@@ -608,18 +608,18 @@ mozilla::Maybe<ProfilerBufferInfo> profi
 // Insert a marker in the profile timeline. This is useful to delimit something
 // important happening such as the first paint. Unlike labels, which are only
 // recorded in the profile buffer if a sample is collected while the label is
 // on the label stack, markers will always be recorded in the profile buffer.
 // aMarkerName is copied, so the caller does not need to ensure it lives for a
 // certain length of time. A no-op if the profiler is inactive or in privacy
 // mode.
 
-#define PROFILER_ADD_MARKER(markerName, category) \
-  profiler_add_marker(markerName, js::ProfilingStackFrame::Category::category)
+#  define PROFILER_ADD_MARKER(markerName, category) \
+    profiler_add_marker(markerName, js::ProfilingStackFrame::Category::category)
 
 void profiler_add_marker(const char* aMarkerName,
                          js::ProfilingStackFrame::Category aCategory);
 void profiler_add_marker(const char* aMarkerName,
                          js::ProfilingStackFrame::Category aCategory,
                          mozilla::UniquePtr<ProfilerMarkerPayload> aPayload);
 void profiler_add_js_marker(const char* aMarkerName);
 
@@ -665,49 +665,51 @@ enum TracingKind {
     } else {                                        \
       docShellId = Nothing();                       \
       docShellHistoryId = Nothing();                \
     }
 
 // Adds a tracing marker to the profile. A no-op if the profiler is inactive or
 // in privacy mode.
 
-#define PROFILER_TRACING(categoryString, markerName, category, kind) \
-  profiler_tracing(categoryString, markerName,                       \
-                   js::ProfilingStackFrame::Category::category, kind)
-#define PROFILER_TRACING_DOCSHELL(categoryString, markerName, category, kind, \
-                                  docShell)                                   \
-  DECLARE_DOCSHELL_AND_HISTORY_ID(docShell);                                  \
-  profiler_tracing(categoryString, markerName,                                \
-                   js::ProfilingStackFrame::Category::category, kind,         \
-                   docShellId, docShellHistoryId)
+#  define PROFILER_TRACING(categoryString, markerName, category, kind) \
+    profiler_tracing(categoryString, markerName,                       \
+                     js::ProfilingStackFrame::Category::category, kind)
+#  define PROFILER_TRACING_DOCSHELL(categoryString, markerName, category, \
+                                    kind, docShell)                       \
+    DECLARE_DOCSHELL_AND_HISTORY_ID(docShell);                            \
+    profiler_tracing(categoryString, markerName,                          \
+                     js::ProfilingStackFrame::Category::category, kind,   \
+                     docShellId, docShellHistoryId)
 
 void profiler_tracing(
     const char* aCategoryString, const char* aMarkerName,
     js::ProfilingStackFrame::Category aCategory, TracingKind aKind,
     const mozilla::Maybe<nsID>& aDocShellId = mozilla::Nothing(),
     const mozilla::Maybe<uint32_t>& aDocShellHistoryId = mozilla::Nothing());
 void profiler_tracing(
     const char* aCategoryString, const char* aMarkerName,
     js::ProfilingStackFrame::Category aCategory, TracingKind aKind,
     UniqueProfilerBacktrace aCause,
     const mozilla::Maybe<nsID>& aDocShellId = mozilla::Nothing(),
     const mozilla::Maybe<uint32_t>& aDocShellHistoryId = mozilla::Nothing());
 
 // Adds a START/END pair of tracing markers.
-#define AUTO_PROFILER_TRACING(categoryString, markerName, category)            \
-  mozilla::AutoProfilerTracing PROFILER_RAII(                                  \
-      categoryString, markerName, js::ProfilingStackFrame::Category::category, \
-      mozilla::Nothing(), mozilla::Nothing())
-#define AUTO_PROFILER_TRACING_DOCSHELL(categoryString, markerName, category,   \
-                                       docShell)                               \
-  DECLARE_DOCSHELL_AND_HISTORY_ID(docShell);                                   \
-  mozilla::AutoProfilerTracing PROFILER_RAII(                                  \
-      categoryString, markerName, js::ProfilingStackFrame::Category::category, \
-      docShellId, docShellHistoryId)
+#  define AUTO_PROFILER_TRACING(categoryString, markerName, category)    \
+    mozilla::AutoProfilerTracing PROFILER_RAII(                          \
+        categoryString, markerName,                                      \
+        js::ProfilingStackFrame::Category::category, mozilla::Nothing(), \
+        mozilla::Nothing())
+#  define AUTO_PROFILER_TRACING_DOCSHELL(categoryString, markerName, category, \
+                                         docShell)                             \
+    DECLARE_DOCSHELL_AND_HISTORY_ID(docShell);                                 \
+    mozilla::AutoProfilerTracing PROFILER_RAII(                                \
+        categoryString, markerName,                                            \
+        js::ProfilingStackFrame::Category::category, docShellId,               \
+        docShellHistoryId)
 
 //---------------------------------------------------------------------------
 // Output profiles
 //---------------------------------------------------------------------------
 
 // Get the profile encoded as a JSON string. A no-op (returning nullptr) if the
 // profiler is inactive.
 // If aIsShuttingDown is true, the current time is included as the process
--- a/widget/android/GeckoEditableSupport.cpp
+++ b/widget/android/GeckoEditableSupport.cpp
@@ -1444,31 +1444,29 @@ nsresult GeckoEditableSupport::NotifyIME
       //
       if (mIsRemote) {
         OnNotifyIMEOfCompositionEventHandled();
       } else {
         // Also, when receiving this event, mIMEDelaySynchronizeReply won't
         // update yet on non-e10s case since IME event is posted before updating
         // it. So we have to delay handling of this event.
         RefPtr<GeckoEditableSupport> self(this);
-        nsAppShell::PostEvent([this, self] {
-          OnNotifyIMEOfCompositionEventHandled();
-        });
+        nsAppShell::PostEvent(
+            [this, self] { OnNotifyIMEOfCompositionEventHandled(); });
       }
       break;
     }
 
     default:
       break;
   }
   return NS_OK;
 }
 
-void GeckoEditableSupport::OnNotifyIMEOfCompositionEventHandled()
-{
+void GeckoEditableSupport::OnNotifyIMEOfCompositionEventHandled() {
   // NOTIFY_IME_OF_COMPOSITION_EVENT_HANDLED may be merged with multiple events,
   // so reset count.
   mIMEActiveCompositionCount = 0;
   if (mIMEDelaySynchronizeReply) {
     FlushIMEChanges();
   }
 
   // Hardware keyboard support requires each string rect.
--- a/xpcom/threads/DataMutex.h
+++ b/xpcom/threads/DataMutex.h
@@ -80,17 +80,18 @@ class DataMutex {
     }
 
     DataMutex<T>* mOwner;
   };
 
  public:
   explicit DataMutex(const char* aName) : mMutex(aName) {}
 
-  DataMutex(T&& aValue, const char* aName) : mMutex(aName), mValue(std::move(aValue)) {}
+  DataMutex(T&& aValue, const char* aName)
+      : mMutex(aName), mValue(std::move(aValue)) {}
 
   AutoLock Lock() { return AutoLock(this); }
 
  private:
   Mutex mMutex;
   T mValue;
 };