diff --git a/accessible/tests/mochitest/events.js b/accessible/tests/mochitest/events.js
index 5831e9aa086a..eb2e0f0d0464 100644
--- a/accessible/tests/mochitest/events.js
+++ b/accessible/tests/mochitest/events.js
@@ -70,6 +70,11 @@ function isHTMLElement(aNode) {
aNode.namespaceURI == "http://www.w3.org/1999/xhtml";
}
+function isXULElement(aNode) {
+ return aNode.nodeType == aNode.ELEMENT_NODE &&
+ aNode.namespaceURI == "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
+}
+
/**
* Executes the function when requested event is handled.
*
@@ -1092,17 +1097,18 @@ function synthClick(aNodeOrID, aCheckerOrEventSeq, aArgs) {
// Scroll the node into view, otherwise synth click may fail.
if (isHTMLElement(targetNode)) {
targetNode.scrollIntoView(true);
- } else if (ChromeUtils.getClassName(targetNode) == "XULElement") {
+ } else if (isXULElement(targetNode)) {
var targetAcc = getAccessible(targetNode);
targetAcc.scrollTo(SCROLL_TYPE_ANYWHERE);
}
var x = 1, y = 1;
if (aArgs && ("where" in aArgs) && aArgs.where == "right") {
- if (isHTMLElement(targetNode))
+ if (isHTMLElement(targetNode)) {
x = targetNode.offsetWidth - 1;
- else if (ChromeUtils.getClassName(targetNode) == "XULElement")
+ } else if (isXULElement(targetNode)) {
x = targetNode.boxObject.width - 1;
+ }
}
synthesizeMouse(targetNode, x, y, aArgs ? aArgs : {});
};
diff --git a/browser/base/content/browser-sets.inc b/browser/base/content/browser-sets.inc
index 84c05acb7364..f145d9471454 100644
--- a/browser/base/content/browser-sets.inc
+++ b/browser/base/content/browser-sets.inc
@@ -59,7 +59,6 @@
PlacesCommandHook.updateBookmarkAllTabsCommand() -->
-
@@ -202,7 +201,7 @@
#endif
-
+
#ifndef XP_MACOSX
diff --git a/browser/base/content/test/forms/browser_selectpopup.js b/browser/base/content/test/forms/browser_selectpopup.js
index 560ebb043691..64f1d7297f04 100644
--- a/browser/base/content/test/forms/browser_selectpopup.js
+++ b/browser/base/content/test/forms/browser_selectpopup.js
@@ -145,17 +145,17 @@ async function doSelectTests(contentType, content) {
is(selectPopup.children[1].getAttribute("label"), "One", "option label");
EventUtils.synthesizeKey("KEY_ArrowDown");
- is(menulist.menuBoxObject.activeChild, menulist.getItemAtIndex(2), "Select item 2");
+ is(menulist.activeChild, menulist.getItemAtIndex(2), "Select item 2");
is(menulist.selectedIndex, isWindows ? 2 : 1, "Select item 2 selectedIndex");
EventUtils.synthesizeKey("KEY_ArrowDown");
- is(menulist.menuBoxObject.activeChild, menulist.getItemAtIndex(3), "Select item 3");
+ is(menulist.activeChild, menulist.getItemAtIndex(3), "Select item 3");
is(menulist.selectedIndex, isWindows ? 3 : 1, "Select item 3 selectedIndex");
EventUtils.synthesizeKey("KEY_ArrowDown");
// On Windows, one can navigate on disabled menuitems
- is(menulist.menuBoxObject.activeChild, menulist.getItemAtIndex(9),
+ is(menulist.activeChild, menulist.getItemAtIndex(9),
"Skip optgroup header and disabled items select item 7");
is(menulist.selectedIndex, isWindows ? 9 : 1, "Select or skip disabled item selectedIndex");
@@ -164,7 +164,7 @@ async function doSelectTests(contentType, content) {
}
EventUtils.synthesizeKey("KEY_ArrowUp");
- is(menulist.menuBoxObject.activeChild, menulist.getItemAtIndex(3), "Select item 3 again");
+ is(menulist.activeChild, menulist.getItemAtIndex(3), "Select item 3 again");
is(menulist.selectedIndex, isWindows ? 3 : 1, "Select item 3 selectedIndex");
is((await getInputEvents()), 0, "Before closed - number of input events");
diff --git a/browser/base/content/test/general/browser_bug647886.js b/browser/base/content/test/general/browser_bug647886.js
index fe93f349d40f..dedc4d337d5a 100644
--- a/browser/base/content/test/general/browser_bug647886.js
+++ b/browser/base/content/test/general/browser_bug647886.js
@@ -8,8 +8,10 @@ add_task(async function() {
content.history.pushState({}, "2", "2.html");
});
- var backButton = document.getElementById("back-button");
- var rect = backButton.getBoundingClientRect();
+ await new Promise(resolve => SessionStore.getSessionHistory(gBrowser.selectedTab, resolve));
+
+ let backButton = document.getElementById("back-button");
+ let rect = backButton.getBoundingClientRect();
info("waiting for the history menu to open");
diff --git a/browser/components/uitour/UITour.jsm b/browser/components/uitour/UITour.jsm
index 49453b9014df..95edb825f227 100644
--- a/browser/components/uitour/UITour.jsm
+++ b/browser/components/uitour/UITour.jsm
@@ -1246,14 +1246,14 @@ var UITour = {
showMenu(aWindow, aMenuName, aOpenCallback = null) {
log.debug("showMenu:", aMenuName);
function openMenuButton(aMenuBtn) {
- if (!aMenuBtn || !aMenuBtn.boxObject || aMenuBtn.open) {
+ if (!aMenuBtn || !aMenuBtn.hasMenu() || aMenuBtn.open) {
if (aOpenCallback)
aOpenCallback();
return;
}
if (aOpenCallback)
aMenuBtn.addEventListener("popupshown", aOpenCallback, { once: true });
- aMenuBtn.boxObject.openMenu(true);
+ aMenuBtn.openMenu(true);
}
if (aMenuName == "appMenu" || aMenuName == "pageActionPanel") {
@@ -1342,8 +1342,9 @@ var UITour = {
hideMenu(aWindow, aMenuName) {
log.debug("hideMenu:", aMenuName);
function closeMenuButton(aMenuBtn) {
- if (aMenuBtn && aMenuBtn.boxObject)
- aMenuBtn.boxObject.openMenu(false);
+ if (aMenuBtn && aMenuBtn.hasMenu()) {
+ aMenuBtn.openMenu(false);
+ }
}
if (aMenuName == "appMenu") {
diff --git a/dom/base/CustomElementRegistry.cpp b/dom/base/CustomElementRegistry.cpp
index 2aea3faf6c72..ca8511ac2d9b 100644
--- a/dom/base/CustomElementRegistry.cpp
+++ b/dom/base/CustomElementRegistry.cpp
@@ -1299,33 +1299,22 @@ CustomElementRegistry::CallGetCustomInterface(Element* aElement,
func->Call(aElement, iid, &customInterface);
JS::Rooted funcGlobal(RootingCx(), func->CallbackGlobalOrNull());
if (customInterface && funcGlobal) {
- RefPtr wrappedJS;
AutoJSAPI jsapi;
if (jsapi.Init(funcGlobal)) {
+ nsIXPConnect *xpConnect = nsContentUtils::XPConnect();
JSContext* cx = jsapi.cx();
- nsresult rv =
- nsXPCWrappedJS::GetNewOrUsed(cx, customInterface,
- NS_GET_IID(nsISupports),
- getter_AddRefs(wrappedJS));
- if (NS_SUCCEEDED(rv) && wrappedJS) {
- // Check if the returned object implements the desired interface.
- nsCOMPtr retval;
- if (NS_SUCCEEDED(wrappedJS->QueryInterface(aIID,
- getter_AddRefs(retval)))) {
- return retval.forget();
- }
+
+ nsCOMPtr wrapper;
+ nsresult rv = xpConnect->WrapJSAggregatedToNative(aElement, cx, customInterface,
+ aIID, getter_AddRefs(wrapper));
+ if (NS_SUCCEEDED(rv)) {
+ return wrapper.forget();
}
}
}
}
}
- // Otherwise, check if the element supports the interface directly, and just use that.
- nsCOMPtr supports;
- if (NS_SUCCEEDED(aElement->QueryInterface(aIID, getter_AddRefs(supports)))) {
- return supports.forget();
- }
-
return nullptr;
}
diff --git a/dom/base/CustomElementRegistry.h b/dom/base/CustomElementRegistry.h
index dc1b1303b486..7a483a327d9c 100644
--- a/dom/base/CustomElementRegistry.h
+++ b/dom/base/CustomElementRegistry.h
@@ -441,10 +441,7 @@ public:
* To allow native code to call methods of chrome-implemented custom elements,
* a helper method may be defined in the custom element called
* 'getCustomInterfaceCallback'. This method takes an IID and returns an
- * object which implements an XPCOM interface. If there is no
- * getCustomInterfaceCallback or the callback doesn't return an object,
- * QueryInterface is called on aElement to see if this interface is
- * implemented directly.
+ * object which implements an XPCOM interface.
*
* This returns null if aElement is not from a chrome document.
*/
diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp
index d24c6cf93ce7..422ef10152a9 100644
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -259,7 +259,6 @@
#include "mozilla/dom/DocGroup.h"
#include "mozilla/dom/TabGroup.h"
#ifdef MOZ_XUL
-#include "mozilla/dom/MenuBoxObject.h"
#include "mozilla/dom/TreeBoxObject.h"
#include "nsIXULWindow.h"
#include "nsXULCommandDispatcher.h"
@@ -6549,9 +6548,7 @@ nsIDocument::GetBoxObjectFor(Element* aElement, ErrorResult& aRv)
RefPtr tag = BindingManager()->ResolveTag(aElement, &namespaceID);
#ifdef MOZ_XUL
if (namespaceID == kNameSpaceID_XUL) {
- if (tag == nsGkAtoms::menu) {
- boxObject = new MenuBoxObject();
- } else if (tag == nsGkAtoms::tree) {
+ if (tag == nsGkAtoms::tree) {
boxObject = new TreeBoxObject();
} else {
boxObject = new BoxObject();
diff --git a/dom/bindings/BindingUtils.cpp b/dom/bindings/BindingUtils.cpp
index ae9260f0fc5f..a8d54b4ef820 100644
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -52,6 +52,7 @@
#include "mozilla/dom/HTMLEmbedElementBinding.h"
#include "mozilla/dom/XULElementBinding.h"
#include "mozilla/dom/XULFrameElementBinding.h"
+#include "mozilla/dom/XULMenuElementBinding.h"
#include "mozilla/dom/XULPopupElementBinding.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/ResolveSystemBinding.h"
@@ -3861,6 +3862,9 @@ HTMLConstructor(JSContext* aCx, unsigned aArgc, JS::Value* aVp,
definition->mLocalName == nsGkAtoms::browser ||
definition->mLocalName == nsGkAtoms::editor) {
cb = XULFrameElement_Binding::GetConstructorObject;
+ } else if (definition->mLocalName == nsGkAtoms::menu ||
+ definition->mLocalName == nsGkAtoms::menulist) {
+ cb = XULMenuElement_Binding::GetConstructorObject;
} else if (definition->mLocalName == nsGkAtoms::scrollbox) {
cb = XULScrollElement_Binding::GetConstructorObject;
} else {
diff --git a/dom/webidl/MenuBoxObject.webidl b/dom/chrome-webidl/XULMenuElement.webidl
similarity index 81%
rename from dom/webidl/MenuBoxObject.webidl
rename to dom/chrome-webidl/XULMenuElement.webidl
index 449cadc5967b..8246db7c3d20 100644
--- a/dom/webidl/MenuBoxObject.webidl
+++ b/dom/chrome-webidl/XULMenuElement.webidl
@@ -5,10 +5,8 @@
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-[Func="IsChromeOrXBL"]
-interface MenuBoxObject : BoxObject {
-
- void openMenu(boolean openFlag);
+[HTMLConstructor, Func="IsChromeOrXBL"]
+interface XULMenuElement : XULElement {
attribute Element? activeChild;
diff --git a/dom/chrome-webidl/moz.build b/dom/chrome-webidl/moz.build
index 5514a79f222d..032bca3ff35e 100644
--- a/dom/chrome-webidl/moz.build
+++ b/dom/chrome-webidl/moz.build
@@ -50,6 +50,7 @@ WEBIDL_FILES = [
'WebExtensionContentScript.webidl',
'WebExtensionPolicy.webidl',
'XULFrameElement.webidl',
+ 'XULMenuElement.webidl',
'XULScrollElement.webidl'
]
diff --git a/dom/tests/mochitest/general/test_interfaces.js b/dom/tests/mochitest/general/test_interfaces.js
index 3cde823241c2..7ff4f9697ac6 100644
--- a/dom/tests/mochitest/general/test_interfaces.js
+++ b/dom/tests/mochitest/general/test_interfaces.js
@@ -665,8 +665,6 @@ var interfaceNamesInGlobalScope =
{name: "MediaStreamTrackEvent", insecureContext: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "MediaStreamTrack", insecureContext: true},
-// IMPORTANT: Do not change this list without review from a DOM peer!
- {name: "MenuBoxObject", insecureContext: true, xbl: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "MessageChannel", insecureContext: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
@@ -1261,6 +1259,8 @@ var interfaceNamesInGlobalScope =
{name: "XULElement", insecureContext: true, xbl: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "XULFrameElement", insecureContext: true, xbl: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
+ {name: "XULMenuElement", insecureContext: true, xbl: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "XULPopupElement", insecureContext: true, xbl: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
diff --git a/dom/webidl/XULElement.webidl b/dom/webidl/XULElement.webidl
index 3841c447ad96..72514aae70b7 100644
--- a/dom/webidl/XULElement.webidl
+++ b/dom/webidl/XULElement.webidl
@@ -85,6 +85,14 @@ interface XULElement : Element {
[Constant]
readonly attribute CSSStyleDeclaration style;
+
+ // Returns true if this is a menu-type element that has a menu
+ // frame associated with it.
+ boolean hasMenu();
+
+ // If this is a menu-type element, opens or closes the menu
+ // depending on the argument passed.
+ void openMenu(boolean open);
};
XULElement implements GlobalEventHandlers;
diff --git a/dom/webidl/moz.build b/dom/webidl/moz.build
index b24682a02cc4..7f6f1d135a9a 100644
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -665,7 +665,6 @@ WEBIDL_FILES = [
'MediaTrackConstraintSet.webidl',
'MediaTrackSettings.webidl',
'MediaTrackSupportedConstraints.webidl',
- 'MenuBoxObject.webidl',
'MerchantValidationEvent.webidl',
'MessageChannel.webidl',
'MessageEvent.webidl',
diff --git a/layout/xul/MenuBoxObject.cpp b/dom/xul/XULMenuElement.cpp
similarity index 62%
rename from layout/xul/MenuBoxObject.cpp
rename to dom/xul/XULMenuElement.cpp
index 39481f0b88c0..4c9e8638a518 100644
--- a/layout/xul/MenuBoxObject.cpp
+++ b/dom/xul/XULMenuElement.cpp
@@ -4,9 +4,6 @@
* 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/MenuBoxObject.h"
-#include "mozilla/dom/MenuBoxObjectBinding.h"
-
#include "mozilla/dom/KeyboardEvent.h"
#include "mozilla/dom/KeyboardEventBinding.h"
#include "mozilla/dom/Element.h"
@@ -15,49 +12,36 @@
#include "nsMenuBarListener.h"
#include "nsMenuFrame.h"
#include "nsMenuPopupFrame.h"
+#include "mozilla/dom/XULMenuElement.h"
+#include "mozilla/dom/XULMenuElementBinding.h"
+#include "nsXULPopupManager.h"
namespace mozilla {
namespace dom {
-MenuBoxObject::MenuBoxObject()
+JSObject*
+XULMenuElement::WrapNode(JSContext* aCx, JS::Handle aGivenProto)
{
+ return XULMenuElement_Binding::Wrap(aCx, this, aGivenProto);
}
-MenuBoxObject::~MenuBoxObject()
+nsIFrame*
+XULMenuElement::GetFrame()
{
-}
+ nsCOMPtr kungFuDeathGrip = this; // keep a reference
-JSObject* MenuBoxObject::WrapObject(JSContext* aCx, JS::Handle aGivenProto)
-{
- return MenuBoxObject_Binding::Wrap(aCx, this, aGivenProto);
-}
-
-void MenuBoxObject::OpenMenu(bool aOpenFlag)
-{
- nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
- if (pm) {
- nsIFrame* frame = GetFrame(false);
- if (frame) {
- if (aOpenFlag) {
- nsCOMPtr content = mContent;
- pm->ShowMenu(content, false, false);
- }
- else {
- nsMenuFrame* menu = do_QueryFrame(frame);
- if (menu) {
- nsMenuPopupFrame* popupFrame = menu->GetPopup();
- if (popupFrame)
- pm->HidePopup(popupFrame->GetContent(), false, true, false, false);
- }
- }
- }
+ nsCOMPtr doc = GetUncomposedDoc();
+ if (doc) {
+ doc->FlushPendingNotifications(FlushType::Frames);
}
+
+ return GetPrimaryFrame();
}
already_AddRefed
-MenuBoxObject::GetActiveChild()
+XULMenuElement::GetActiveChild()
{
- nsMenuFrame* menu = do_QueryFrame(GetFrame(false));
+ nsMenuFrame* menu = do_QueryFrame(GetFrame());
if (menu) {
RefPtr el;
menu->GetActiveChild(getter_AddRefs(el));
@@ -66,15 +50,17 @@ MenuBoxObject::GetActiveChild()
return nullptr;
}
-void MenuBoxObject::SetActiveChild(Element* arg)
+void
+XULMenuElement::SetActiveChild(Element* arg)
{
- nsMenuFrame* menu = do_QueryFrame(GetFrame(false));
+ nsMenuFrame* menu = do_QueryFrame(GetFrame());
if (menu) {
menu->SetActiveChild(arg);
}
}
-bool MenuBoxObject::HandleKeyPress(KeyboardEvent& keyEvent)
+bool
+XULMenuElement::HandleKeyPress(KeyboardEvent& keyEvent)
{
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
if (!pm) {
@@ -89,7 +75,7 @@ bool MenuBoxObject::HandleKeyPress(KeyboardEvent& keyEvent)
if (nsMenuBarListener::IsAccessKeyPressed(&keyEvent))
return false;
- nsMenuFrame* menu = do_QueryFrame(GetFrame(false));
+ nsMenuFrame* menu = do_QueryFrame(GetFrame());
if (!menu) {
return false;
}
@@ -115,9 +101,10 @@ bool MenuBoxObject::HandleKeyPress(KeyboardEvent& keyEvent)
}
}
-bool MenuBoxObject::OpenedWithKey()
+bool
+XULMenuElement::OpenedWithKey()
{
- nsMenuFrame* menuframe = do_QueryFrame(GetFrame(false));
+ nsMenuFrame* menuframe = do_QueryFrame(GetFrame());
if (!menuframe) {
return false;
}
diff --git a/dom/xul/XULMenuElement.h b/dom/xul/XULMenuElement.h
new file mode 100644
index 000000000000..8b2f062f1062
--- /dev/null
+++ b/dom/xul/XULMenuElement.h
@@ -0,0 +1,41 @@
+/* -*- 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_XULMenuElement_h
+#define mozilla_dom_XULMenuElement_h
+
+#include "nsXULElement.h"
+
+namespace mozilla {
+namespace dom {
+
+class KeyboardEvent;
+
+class XULMenuElement final : public nsXULElement
+{
+public:
+
+ explicit XULMenuElement(already_AddRefed& aNodeInfo)
+ : nsXULElement(aNodeInfo)
+ {
+ }
+
+ MOZ_CAN_RUN_SCRIPT already_AddRefed GetActiveChild();
+ MOZ_CAN_RUN_SCRIPT void SetActiveChild(Element* arg);
+ MOZ_CAN_RUN_SCRIPT bool HandleKeyPress(KeyboardEvent& keyEvent);
+ MOZ_CAN_RUN_SCRIPT bool OpenedWithKey();
+
+private:
+ virtual ~XULMenuElement() {}
+ JSObject* WrapNode(JSContext *aCx, JS::Handle aGivenProto) final;
+
+ nsIFrame* GetFrame();
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // XULMenuElement_h
diff --git a/dom/xul/moz.build b/dom/xul/moz.build
index 2ffb9ba3e566..5e3cb5b39b25 100644
--- a/dom/xul/moz.build
+++ b/dom/xul/moz.build
@@ -23,6 +23,7 @@ if CONFIG['MOZ_XUL']:
EXPORTS.mozilla.dom += [
'XULFrameElement.h',
+ 'XULMenuElement.h',
'XULPopupElement.h',
'XULScrollElement.h',
]
@@ -38,6 +39,7 @@ if CONFIG['MOZ_XUL']:
'nsXULSortService.cpp',
'XULDocument.cpp',
'XULFrameElement.cpp',
+ 'XULMenuElement.cpp',
'XULPopupElement.cpp',
'XULScrollElement.cpp',
]
diff --git a/dom/xul/nsXULElement.cpp b/dom/xul/nsXULElement.cpp
index aa15c438f936..e9483fad5deb 100644
--- a/dom/xul/nsXULElement.cpp
+++ b/dom/xul/nsXULElement.cpp
@@ -75,6 +75,7 @@
#include "nsICSSDeclaration.h"
#include "nsLayoutUtils.h"
#include "XULFrameElement.h"
+#include "XULMenuElement.h"
#include "XULPopupElement.h"
#include "XULScrollElement.h"
@@ -159,6 +160,12 @@ nsXULElement* nsXULElement::Construct(already_AddRefed&&
return new XULFrameElement(frameni);
}
+ if (nodeInfo->Equals(nsGkAtoms::menu) ||
+ nodeInfo->Equals(nsGkAtoms::menulist)) {
+ already_AddRefed menuni = nodeInfo.forget();
+ return new XULMenuElement(menuni);
+ }
+
if (nodeInfo->Equals(nsGkAtoms::scrollbox)) {
already_AddRefed scrollni = nodeInfo.forget();
return new XULScrollElement(scrollni);
@@ -304,7 +311,17 @@ NS_IMPL_RELEASE_INHERITED(nsXULElement, nsStyledElement)
NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsXULElement)
NS_ELEMENT_INTERFACE_TABLE_TO_MAP_SEGUE
-NS_INTERFACE_MAP_END_INHERITING(nsStyledElement)
+
+ nsCOMPtr iface =
+ CustomElementRegistry::CallGetCustomInterface(this, aIID);
+ if (iface) {
+ iface->QueryInterface(aIID, aInstancePtr);
+ if (*aInstancePtr) {
+ return NS_OK;
+ }
+ }
+
+NS_INTERFACE_MAP_END_INHERITING(Element)
//----------------------------------------------------------------------
// nsINode interface
@@ -496,6 +513,39 @@ nsXULElement::IsFocusableInternal(int32_t *aTabIndex, bool aWithMouse)
return shouldFocus;
}
+bool
+nsXULElement::HasMenu()
+{
+ nsMenuFrame* menu = do_QueryFrame(GetPrimaryFrame());
+ return menu != nullptr;
+}
+
+void
+nsXULElement::OpenMenu(bool aOpenFlag)
+{
+ nsCOMPtr doc = GetUncomposedDoc();
+ if (doc) {
+ doc->FlushPendingNotifications(FlushType::Frames);
+ }
+
+ nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
+ if (pm) {
+ if (aOpenFlag) {
+ // Nothing will happen if this element isn't a menu.
+ pm->ShowMenu(this, false, false);
+ }
+ else {
+ nsMenuFrame* menu = do_QueryFrame(GetPrimaryFrame());
+ if (menu) {
+ nsMenuPopupFrame* popupFrame = menu->GetPopup();
+ if (popupFrame) {
+ pm->HidePopup(popupFrame->GetContent(), false, true, false, false);
+ }
+ }
+ }
+ }
+}
+
bool
nsXULElement::PerformAccesskey(bool aKeyCausesActivation,
bool aIsTrustedEvent)
diff --git a/dom/xul/nsXULElement.h b/dom/xul/nsXULElement.h
index d3f9801c7f86..3bfbacca4237 100644
--- a/dom/xul/nsXULElement.h
+++ b/dom/xul/nsXULElement.h
@@ -375,6 +375,9 @@ public:
}
#endif
+ bool HasMenu();
+ MOZ_CAN_RUN_SCRIPT void OpenMenu(bool aOpenFlag);
+
virtual bool PerformAccesskey(bool aKeyCausesActivation,
bool aIsTrustedEvent) override;
void ClickWithInputSource(uint16_t aInputSource, bool aIsTrustedEvent);
diff --git a/gfx/thebes/gfxMacPlatformFontList.mm b/gfx/thebes/gfxMacPlatformFontList.mm
index 2623fbfb4436..955cf432d983 100644
--- a/gfx/thebes/gfxMacPlatformFontList.mm
+++ b/gfx/thebes/gfxMacPlatformFontList.mm
@@ -334,9 +334,11 @@ MacOSFontEntry::GetVariationAxes(nsTArray& aVariationAxes)
kCTFontVariationAxisNameKey);
if (name) {
CFIndex len = CFStringGetLength(name);
- axis.mName.SetLength(len);
+ nsAutoString nameStr;
+ nameStr.SetLength(len);
CFStringGetCharacters(name, CFRangeMake(0, len),
- (UniChar*)axis.mName.BeginWriting());
+ (UniChar*)nameStr.BeginWriting());
+ AppendUTF16toUTF8(nameStr, axis.mName);
}
axis.mTag = (uint32_t)tag;
axis.mMinValue = minValue;
diff --git a/js/src/frontend/BinSource.cpp b/js/src/frontend/BinSource.cpp
index 6fdff83429a8..2c6bfe83d41b 100644
--- a/js/src/frontend/BinSource.cpp
+++ b/js/src/frontend/BinSource.cpp
@@ -351,17 +351,29 @@ template JS::Result
BinASTParser::checkPositionalParameterIndices(Handle> positionalParams,
ListNode* params)
{
- MOZ_ASSERT(positionalParams.get().length() == params->count());
+#ifdef DEBUG
+ // positionalParams should have the same length as non-rest parameters.
+ size_t paramsCount = params->count();
+ if (paramsCount > 0) {
+ if (params->last()->isKind(ParseNodeKind::Spread)) {
+ paramsCount--;
+ }
+ }
+ MOZ_ASSERT(positionalParams.get().length() == paramsCount);
+#endif
uint32_t i = 0;
for (ParseNode* param : params->contents()) {
if (param->isKind(ParseNodeKind::Assign)) {
param = param->as().left();
}
+ if (param->isKind(ParseNodeKind::Spread)) {
+ continue;
+ }
+
MOZ_ASSERT(param->isKind(ParseNodeKind::Name) ||
param->isKind(ParseNodeKind::Object) ||
- param->isKind(ParseNodeKind::Array) ||
- param->isKind(ParseNodeKind::Spread));
+ param->isKind(ParseNodeKind::Array));
if (JSAtom* name = positionalParams.get()[i]) {
// Simple or default parameter.
diff --git a/js/src/jit-test/tests/basic/recompute-wrappers.js b/js/src/jit-test/tests/basic/recompute-wrappers.js
new file mode 100644
index 000000000000..cf45a3740737
--- /dev/null
+++ b/js/src/jit-test/tests/basic/recompute-wrappers.js
@@ -0,0 +1,5 @@
+var g = newGlobal();
+var w1 = g.Math;
+var w2 = g.evaluate("new Array");
+recomputeWrappers(this, g);
+recomputeWrappers();
diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp
index d110c5b89b7b..02d37504951f 100644
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -6137,6 +6137,46 @@ NukeAllCCWs(JSContext* cx, unsigned argc, Value* vp)
return true;
}
+static bool
+RecomputeWrappers(JSContext* cx, unsigned argc, Value* vp)
+{
+ CallArgs args = CallArgsFromVp(argc, vp);
+
+ if (args.length() > 2) {
+ JS_ReportErrorNumberASCII(cx, my_GetErrorMessage, nullptr, JSSMSG_INVALID_ARGS,
+ "recomputeWrappers");
+ return false;
+ }
+
+ JS::Compartment* sourceComp = nullptr;
+ if (args.get(0).isObject()) {
+ sourceComp = GetObjectCompartment(UncheckedUnwrap(&args[0].toObject()));
+ }
+
+ JS::Compartment* targetComp = nullptr;
+ if (args.get(1).isObject()) {
+ targetComp = GetObjectCompartment(UncheckedUnwrap(&args[1].toObject()));
+ }
+
+ struct SingleOrAllCompartments final : public CompartmentFilter {
+ JS::Compartment* comp;
+ explicit SingleOrAllCompartments(JS::Compartment* c) : comp(c) {}
+ virtual bool match(JS::Compartment* c) const override {
+ return !comp || comp == c;
+ }
+ };
+
+ if (!js::RecomputeWrappers(cx,
+ SingleOrAllCompartments(sourceComp),
+ SingleOrAllCompartments(targetComp)))
+ {
+ return false;
+ }
+
+ args.rval().setUndefined();
+ return true;
+}
+
static bool
GetMaxArgs(JSContext* cx, unsigned argc, Value* vp)
{
@@ -8196,6 +8236,12 @@ JS_FN_HELP("parseBin", BinParse, 1, 0,
"nukeAllCCWs()",
" Like nukeCCW, but for all CrossCompartmentWrappers targeting the current compartment."),
+ JS_FN_HELP("recomputeWrappers", RecomputeWrappers, 2, 0,
+"recomputeWrappers([src, [target]])",
+" Recompute all cross-compartment wrappers. src and target are both optional\n"
+" and can be used to filter source or target compartments: the unwrapped\n"
+" object's compartment is used as CompartmentFilter.\n"),
+
JS_FN_HELP("wrapWithProto", WrapWithProto, 2, 0,
"wrapWithProto(obj)",
" Wrap an object into a noop wrapper with prototype semantics."),
diff --git a/layout/xul/MenuBoxObject.h b/layout/xul/MenuBoxObject.h
deleted file mode 100644
index 1ff6b9db5a74..000000000000
--- a/layout/xul/MenuBoxObject.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/* -*- 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_MenuBoxObject_h
-#define mozilla_dom_MenuBoxObject_h
-
-#include "mozilla/dom/BoxObject.h"
-
-namespace mozilla {
-namespace dom {
-
-class KeyboardEvent;
-
-class MenuBoxObject final : public BoxObject
-{
-public:
-
- MenuBoxObject();
-
- virtual JSObject* WrapObject(JSContext* aCx, JS::Handle aGivenProto) override;
-
- void OpenMenu(bool aOpenFlag);
- already_AddRefed GetActiveChild();
- void SetActiveChild(Element* arg);
- bool HandleKeyPress(KeyboardEvent& keyEvent);
- bool OpenedWithKey();
-
-private:
- ~MenuBoxObject();
-};
-
-} // namespace dom
-} // namespace mozilla
-
-#endif // mozilla_dom_MenuBoxObject_h
diff --git a/layout/xul/moz.build b/layout/xul/moz.build
index 33aac98e8151..9e5a27d2c7b9 100644
--- a/layout/xul/moz.build
+++ b/layout/xul/moz.build
@@ -31,7 +31,6 @@ EXPORTS += [
EXPORTS.mozilla.dom += [
'BoxObject.h',
- 'MenuBoxObject.h',
]
UNIFIED_SOURCES += [
@@ -54,7 +53,6 @@ UNIFIED_SOURCES += [
if CONFIG['MOZ_XUL']:
UNIFIED_SOURCES += [
- 'MenuBoxObject.cpp',
'nsDeckFrame.cpp',
'nsDocElementBoxFrame.cpp',
'nsGroupBoxFrame.cpp',
diff --git a/layout/xul/nsDeckFrame.cpp b/layout/xul/nsDeckFrame.cpp
index 318be910c47d..922e6e394db8 100644
--- a/layout/xul/nsDeckFrame.cpp
+++ b/layout/xul/nsDeckFrame.cpp
@@ -27,6 +27,7 @@
#include "nsDisplayList.h"
#include "nsContainerFrame.h"
#include "nsContentUtils.h"
+#include "nsXULPopupManager.h"
#ifdef ACCESSIBILITY
#include "nsAccessibilityService.h"
diff --git a/layout/xul/nsProgressMeterFrame.cpp b/layout/xul/nsProgressMeterFrame.cpp
index aa46f4e37ad0..9cf51b064acc 100644
--- a/layout/xul/nsProgressMeterFrame.cpp
+++ b/layout/xul/nsProgressMeterFrame.cpp
@@ -64,7 +64,7 @@ nsReflowFrameRunnable::Run()
// Creates a new Toolbar frame and returns it
//
nsIFrame*
-NS_NewProgressMeterFrame (nsIPresShell* aPresShell, ComputedStyle* aStyle)
+NS_NewProgressMeterFrame (nsIPresShell* aPresShell, mozilla::ComputedStyle* aStyle)
{
return new (aPresShell) nsProgressMeterFrame(aStyle);
}
diff --git a/taskcluster/ci/source-test/jsshell.yml b/taskcluster/ci/source-test/jsshell.yml
index 8ec13607c652..ca0587796df4 100644
--- a/taskcluster/ci/source-test/jsshell.yml
+++ b/taskcluster/ci/source-test/jsshell.yml
@@ -3,7 +3,7 @@ job-defaults:
require-build: true
worker-type:
by-platform:
- linux64.*: releng-hardware/gecko-t-linux-talos
+ linux64.*: releng-hardware/gecko-t-linux-talos-tw
worker:
by-platform:
linux64.*:
diff --git a/taskcluster/taskgraph/transforms/tests.py b/taskcluster/taskgraph/transforms/tests.py
index 5661b2dbdd41..244878c645a0 100644
--- a/taskcluster/taskgraph/transforms/tests.py
+++ b/taskcluster/taskgraph/transforms/tests.py
@@ -1008,7 +1008,7 @@ def set_worker_type(config, tests):
elif test_platform.startswith('linux') or test_platform.startswith('android'):
if test.get('suite', '') in ['talos', 'raptor'] and \
not test['build-platform'].startswith('linux64-ccov'):
- test['worker-type'] = 'releng-hardware/gecko-t-linux-talos'
+ test['worker-type'] = 'releng-hardware/gecko-t-linux-talos-tw'
else:
test['worker-type'] = LINUX_WORKER_TYPES[test['instance-size']]
else:
diff --git a/taskcluster/taskgraph/util/workertypes.py b/taskcluster/taskgraph/util/workertypes.py
index 2531868dfa5c..788a332b0201 100644
--- a/taskcluster/taskgraph/util/workertypes.py
+++ b/taskcluster/taskgraph/util/workertypes.py
@@ -36,7 +36,7 @@ WORKER_TYPES = {
'aws-provisioner-v1/taskcluster-generic': ('docker-worker', 'linux'),
'invalid/invalid': ('invalid', None),
'invalid/always-optimized': ('always-optimized', None),
- 'releng-hardware/gecko-t-linux-talos': ('native-engine', 'linux'),
+ 'releng-hardware/gecko-t-linux-talos-tw': ('native-engine', 'linux'),
'scriptworker-prov-v1/balrog-dev': ('balrog', None),
'scriptworker-prov-v1/balrogworker-v1': ('balrog', None),
'scriptworker-prov-v1/beetmoverworker-v1': ('beetmover', None),
diff --git a/toolkit/content/customElements.js b/toolkit/content/customElements.js
index 8a99215980c4..8749dfeca105 100644
--- a/toolkit/content/customElements.js
+++ b/toolkit/content/customElements.js
@@ -110,9 +110,8 @@ class MozXULElement extends XULElement {
}
/**
- * Indicate that a class defining an element implements one or more
- * XPCOM interfaces. The custom element getCustomInterface is added
- * as well as an implementation of QueryInterface.
+ * Indicate that a class defining a XUL element implements one or more
+ * XPCOM interfaces by adding a getCustomInterface implementation to it.
*
* The supplied class should implement the properties and methods of
* all of the interfaces that are specified.
@@ -120,10 +119,9 @@ class MozXULElement extends XULElement {
* @param cls
* The class that implements the interface.
* @param names
- * Array of interface names
+ * Array of interface names.
*/
static implementCustomInterface(cls, ifaces) {
- cls.prototype.QueryInterface = ChromeUtils.generateQI(ifaces);
cls.prototype.getCustomInterfaceCallback = function getCustomInterfaceCallback(iface) {
if (ifaces.includes(Ci[Components.interfacesByID[iface.number]])) {
return getInterfaceProxy(this);
diff --git a/toolkit/content/tests/chrome/popup_trigger.js b/toolkit/content/tests/chrome/popup_trigger.js
index 8d12767f6085..88ecb690bc3a 100644
--- a/toolkit/content/tests/chrome/popup_trigger.js
+++ b/toolkit/content/tests/chrome/popup_trigger.js
@@ -29,7 +29,7 @@ function runTests() {
gMenuPopup = document.getElementById("thepopup");
gTrigger = document.getElementById("trigger");
- gIsMenu = gTrigger.boxObject instanceof MenuBoxObject;
+ gIsMenu = gTrigger.hasMenu();
// a hacky way to get the screen position of the document. Cache the event
// so that we can use it in calls to openPopup.
diff --git a/toolkit/content/tests/chrome/test_contextmenu_list.xul b/toolkit/content/tests/chrome/test_contextmenu_list.xul
index 157831a58160..014b9bc01052 100644
--- a/toolkit/content/tests/chrome/test_contextmenu_list.xul
+++ b/toolkit/content/tests/chrome/test_contextmenu_list.xul
@@ -106,7 +106,7 @@ function menuTests()
is(gContextMenuFired, true, "context menu fired when menu open");
gSelectionStep = 1;
- $("menu").boxObject.activeChild = $("menu2");
+ $("menu").activeChild = $("menu2");
synthesizeMouse(element, 0, 0, { type : "contextmenu", button: 0 });
$("menu").open = false;
diff --git a/toolkit/content/tests/chrome/test_custom_element_base.xul b/toolkit/content/tests/chrome/test_custom_element_base.xul
index 14e7f3509636..e9e3cd6d9c82 100644
--- a/toolkit/content/tests/chrome/test_custom_element_base.xul
+++ b/toolkit/content/tests/chrome/test_custom_element_base.xul
@@ -12,7 +12,10 @@
-
+
+
+
+
diff --git a/toolkit/content/tests/chrome/test_menulist.xul b/toolkit/content/tests/chrome/test_menulist.xul
index 1f034e204d32..b63d83a68705 100644
--- a/toolkit/content/tests/chrome/test_menulist.xul
+++ b/toolkit/content/tests/chrome/test_menulist.xul
@@ -218,7 +218,7 @@ function test_menulist_open(element, scroller)
synthesizeMouse(element.menupopup.childNodes[1], 2, 2, { type: "mousemove" });
synthesizeMouse(element.menupopup.childNodes[1], 6, 6, { type: "mousemove" });
- is(element.menuBoxObject.activeChild, item, "activeChild after menu highlight " + element.id);
+ is(element.activeChild, item, "activeChild after menu highlight " + element.id);
is(element.selectedIndex, 0, "selectedIndex after menu highlight " + element.id);
is(scroller.scrollTop, 0, "scroll position after menu highlight " + element.id);
diff --git a/toolkit/content/tests/chrome/test_menulist_keynav.xul b/toolkit/content/tests/chrome/test_menulist_keynav.xul
index 03c075342ee4..626f6bf9e650 100644
--- a/toolkit/content/tests/chrome/test_menulist_keynav.xul
+++ b/toolkit/content/tests/chrome/test_menulist_keynav.xul
@@ -60,11 +60,11 @@ function runTests()
keyCheck(list, "KEY_ArrowUp", iswin ? 1 : 4, 1, "cursor up wrap");
list.selectedIndex = 4;
- list.menuBoxObject.activeChild = list.selectedItem;
+ list.activeChild = list.selectedItem;
keyCheck(list, "KEY_ArrowDown", iswin ? 4 : 1, 4, "cursor down wrap");
list.selectedIndex = 0;
- list.menuBoxObject.activeChild = list.selectedItem;
+ list.activeChild = list.selectedItem;
}
// check that attempting to open the menulist does not change the selection
@@ -171,7 +171,7 @@ function tabAndScroll()
var item = list.getItemAtIndex(10);
var originalPosition = item.getBoundingClientRect().top;
- list.menuBoxObject.activeChild = item;
+ list.activeChild = item;
ok(item.getBoundingClientRect().top < originalPosition,
"position of item 1: " + item.getBoundingClientRect().top + " -> " + originalPosition);
@@ -257,20 +257,20 @@ function checkCursorNavigation()
// Check whether cursor up and down wraps.
list.selectedIndex = 0;
- list.menuBoxObject.activeChild = list.selectedItem;
+ list.activeChild = list.selectedItem;
synthesizeKey("KEY_ArrowUp");
- is(list.menuBoxObject.activeChild,
+ is(list.activeChild,
document.getElementById(iswin || ismac ? "b1" : "b4"), "cursor up wrap while open");
list.selectedIndex = 3;
- list.menuBoxObject.activeChild = list.selectedItem;
+ list.activeChild = list.selectedItem;
synthesizeKey("KEY_ArrowDown");
- is(list.menuBoxObject.activeChild,
+ is(list.activeChild,
document.getElementById(iswin || ismac ? "b4" : "b1"), "cursor down wrap while open");
synthesizeKey("KEY_ArrowUp", {altKey: true});
is(list.open, ismac, "alt+up closes popup");
-
+
if (ismac) {
list.open = false;
}
diff --git a/toolkit/content/tests/chrome/test_menulist_paging.xul b/toolkit/content/tests/chrome/test_menulist_paging.xul
index c58e0328f185..10ebaa96a650 100644
--- a/toolkit/content/tests/chrome/test_menulist_paging.xul
+++ b/toolkit/content/tests/chrome/test_menulist_paging.xul
@@ -124,7 +124,7 @@ function runTest()
function menulistShown()
{
let menulist = document.getElementById(test.list);
- is(menulist.menuBoxObject.activeChild.label, menulist.getItemAtIndex(test.initial).label, test.list + " initial selection");
+ is(menulist.activeChild.label, menulist.getItemAtIndex(test.initial).label, test.list + " initial selection");
let cs = window.getComputedStyle(menulist.menupopup);
let bpTop = parseFloat(cs.paddingTop) + parseFloat(cs.borderTopWidth);
@@ -138,12 +138,12 @@ function menulistShown()
for (let i = 0; i < test.downs.length; i++) {
sendKey("PAGE_DOWN");
- is(menulist.menuBoxObject.activeChild.label, menulist.getItemAtIndex(test.downs[i]).label, test.list + " page down " + i);
+ is(menulist.activeChild.label, menulist.getItemAtIndex(test.downs[i]).label, test.list + " page down " + i);
}
for (let i = 0; i < test.ups.length; i++) {
sendKey("PAGE_UP");
- is(menulist.menuBoxObject.activeChild.label, menulist.getItemAtIndex(test.ups[i]).label, test.list + " page up " + i);
+ is(menulist.activeChild.label, menulist.getItemAtIndex(test.ups[i]).label, test.list + " page up " + i);
}
menulist.open = false;
diff --git a/toolkit/content/tests/widgets/popup_shared.js b/toolkit/content/tests/widgets/popup_shared.js
index c78bc754792b..ef3921212067 100644
--- a/toolkit/content/tests/widgets/popup_shared.js
+++ b/toolkit/content/tests/widgets/popup_shared.js
@@ -252,24 +252,20 @@ function goNextStepSync() {
function openMenu(menu) {
if ("open" in menu) {
menu.open = true;
+ } else if (menu.hasMenu()) {
+ menu.openMenu(true);
} else {
- var bo = menu.boxObject;
- if (bo instanceof MenuBoxObject)
- bo.openMenu(true);
- else
- synthesizeMouse(menu, 4, 4, { });
+ synthesizeMouse(menu, 4, 4, { });
}
}
function closeMenu(menu, popup) {
if ("open" in menu) {
menu.open = false;
+ } else if (menu.hasMenu()) {
+ menu.openMenu(false);
} else {
- var bo = menu.boxObject;
- if (bo instanceof MenuBoxObject)
- bo.openMenu(false);
- else
- popup.hidePopup();
+ popup.hidePopup();
}
}
@@ -291,7 +287,7 @@ function checkOpen(menuid, testname) {
var menu = document.getElementById(menuid);
if ("open" in menu)
ok(menu.open, testname + " " + menuid + " menu is open");
- else if (menu.boxObject instanceof MenuBoxObject)
+ else if (menu.hasMenu())
ok(menu.getAttribute("open") == "true", testname + " " + menuid + " menu is open");
}
@@ -299,7 +295,7 @@ function checkClosed(menuid, testname) {
var menu = document.getElementById(menuid);
if ("open" in menu)
ok(!menu.open, testname + " " + menuid + " menu is open");
- else if (menu.boxObject instanceof MenuBoxObject)
+ else if (menu.hasMenu())
ok(!menu.hasAttribute("open"), testname + " " + menuid + " menu is closed");
}
diff --git a/toolkit/content/widgets/button.xml b/toolkit/content/widgets/button.xml
index 841d877c555c..7fe63e9b35ec 100644
--- a/toolkit/content/widgets/button.xml
+++ b/toolkit/content/widgets/button.xml
@@ -25,8 +25,8 @@
-
-
-
-
diff --git a/toolkit/content/widgets/menulist.xml b/toolkit/content/widgets/menulist.xml
index eae264022458..3981869d9ed7 100644
--- a/toolkit/content/widgets/menulist.xml
+++ b/toolkit/content/widgets/menulist.xml
@@ -29,11 +29,11 @@
@@ -50,9 +50,9 @@
event.keyCode == KeyEvent.DOM_VK_BACK_SPACE ||
event.charCode > 0)) {
// Moving relative to an item: start from the currently selected item
- this.menuBoxObject.activeChild = this.mSelectedInternal;
- if (this.menuBoxObject.handleKeyPress(event)) {
- this.menuBoxObject.activeChild.doCommand();
+ this.activeChild = this.mSelectedInternal;
+ if (this.handleKeyPress(event)) {
+ this.activeChild.doCommand();
event.preventDefault();
}
}
@@ -64,7 +64,6 @@
this.mSelectedInternal = null;
this.mAttributeObserver = null;
- this.menuBoxObject = this.boxObject;
this.setInitialSelection();
@@ -121,8 +120,7 @@
-