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 @@ - +