From aa3e389fe2792279e18795770d1b2cd25c53158d Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Wed, 19 Sep 2018 09:25:58 +0100 Subject: [PATCH 01/10] Bug 1492220 - Fix encoding-form mismatch in macOS impl of GetVariationAxes. r=lsalzman --- gfx/thebes/gfxMacPlatformFontList.mm | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) 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; From 9128abf5f6a83510d58e3b87052530a309b9a334 Mon Sep 17 00:00:00 2001 From: Dragos Crisan Date: Wed, 19 Sep 2018 11:55:36 +0300 Subject: [PATCH 02/10] Bug 1474570 - migrate talos linux tasks from worker type gecko-t-linux-talos to gecko-t-linux-talos-tw,r=pmoore --- taskcluster/ci/source-test/jsshell.yml | 2 +- taskcluster/taskgraph/transforms/tests.py | 2 +- taskcluster/taskgraph/util/workertypes.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) 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), From a9798b144a27ea3637f780482f8401d9bc3c79c4 Mon Sep 17 00:00:00 2001 From: Jan de Mooij Date: Wed, 19 Sep 2018 11:42:45 +0200 Subject: [PATCH 03/10] Bug 1492406 - Add a recomputeWrappers function to the JS shell for js::RecomputeWrappers. r=jonco --HG-- extra : amend_source : dff657235d26ed6d6a8c187691a546c9d37cd2ee --- .../tests/basic/recompute-wrappers.js | 5 ++ js/src/shell/js.cpp | 46 +++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 js/src/jit-test/tests/basic/recompute-wrappers.js 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 942a12808bc6..b70e43126be8 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."), From 696ceb303fcff577ba8e854e360691a1607c6cd0 Mon Sep 17 00:00:00 2001 From: Emma Malysz Date: Tue, 31 Jul 2018 12:30:17 -0700 Subject: [PATCH 04/10] Bug 1465219, use XULMenuElement, a subclass of nsXULElement, instead of MenuBoxObject for menu and menulist elements, r=paolo,bz MozReview-Commit-ID: 5253hAlxbhw --HG-- rename : dom/webidl/MenuBoxObject.webidl => dom/chrome-webidl/XULMenuElement.webidl rename : layout/xul/MenuBoxObject.cpp => dom/xul/XULMenuElement.cpp rename : layout/xul/MenuBoxObject.h => dom/xul/XULMenuElement.h --- accessible/tests/mochitest/events.js | 12 +++- .../content/test/forms/browser_selectpopup.js | 8 +-- .../content/test/general/browser_bug647886.js | 6 +- browser/components/uitour/UITour.jsm | 9 +-- dom/base/nsDocument.cpp | 5 +- dom/bindings/BindingUtils.cpp | 4 ++ .../XULMenuElement.webidl} | 6 +- dom/chrome-webidl/moz.build | 1 + .../mochitest/general/test_interfaces.js | 4 +- dom/webidl/XULElement.webidl | 8 +++ dom/webidl/moz.build | 1 - .../xul/XULMenuElement.cpp | 63 ++++++++----------- dom/xul/XULMenuElement.h | 41 ++++++++++++ dom/xul/moz.build | 2 + dom/xul/nsXULElement.cpp | 40 ++++++++++++ dom/xul/nsXULElement.h | 3 + layout/xul/MenuBoxObject.h | 38 ----------- layout/xul/moz.build | 2 - layout/xul/nsDeckFrame.cpp | 1 + layout/xul/nsProgressMeterFrame.cpp | 2 +- toolkit/content/tests/chrome/popup_trigger.js | 2 +- .../tests/chrome/test_contextmenu_list.xul | 2 +- .../content/tests/chrome/test_menulist.xul | 2 +- .../tests/chrome/test_menulist_keynav.xul | 16 ++--- .../tests/chrome/test_menulist_paging.xul | 6 +- toolkit/content/tests/widgets/popup_shared.js | 20 +++--- toolkit/content/widgets/button.xml | 6 +- toolkit/content/widgets/menu.xml | 8 +-- toolkit/content/widgets/menulist.xml | 14 ++--- toolkit/modules/SelectParentHelper.jsm | 8 +-- 30 files changed, 189 insertions(+), 151 deletions(-) rename dom/{webidl/MenuBoxObject.webidl => chrome-webidl/XULMenuElement.webidl} (81%) rename layout/xul/MenuBoxObject.cpp => dom/xul/XULMenuElement.cpp (62%) create mode 100644 dom/xul/XULMenuElement.h delete mode 100644 layout/xul/MenuBoxObject.h 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/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/nsDocument.cpp b/dom/base/nsDocument.cpp index bac1f65d1095..4430c1cad4d0 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" @@ -6546,9 +6545,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..5b96c1103341 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); @@ -496,6 +503,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/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/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_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 @@ - Date: Wed, 19 Sep 2018 06:46:41 -0400 Subject: [PATCH 05/10] Bug 1478372, allow QueryInterface to be used for custom element implemented interfaces, r=bz,bgrins --- dom/base/CustomElementRegistry.cpp | 25 +++----- dom/base/CustomElementRegistry.h | 5 +- dom/xul/nsXULElement.cpp | 12 +++- .../tests/chrome/test_custom_element_base.xul | 62 ++++++++++++++++--- 4 files changed, 72 insertions(+), 32 deletions(-) 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/xul/nsXULElement.cpp b/dom/xul/nsXULElement.cpp index 5b96c1103341..e9483fad5deb 100644 --- a/dom/xul/nsXULElement.cpp +++ b/dom/xul/nsXULElement.cpp @@ -311,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 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 @@ - +