author | Margareta Eliza Balazs <ebalazs@mozilla.com> |
Thu, 12 Apr 2018 12:38:56 +0300 | |
changeset 412936 | 246c614e160586c1eb3167cff866dd550be35e03 |
parent 412907 | abd91e812e7e0c85b4943bdd94f0a1326320d777 (current diff) |
parent 412935 | 1e9190687c32a0fba7c3c5d2ad2b8ec2f1da2e8e (diff) |
child 412937 | ee1d1bf1dc8a83eec16967ddb61dd5024c8d6058 |
child 412966 | e4e3e42d46838df5d0702d2eab6273449902ee98 |
child 412991 | 2655ff95e4ff89b252aea31795e067e3c976e222 |
push id | 33824 |
push user | ebalazs@mozilla.com |
push date | Thu, 12 Apr 2018 09:39:57 +0000 |
treeherder | mozilla-central@246c614e1605 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | merge |
milestone | 61.0a1 |
first release with | nightly linux32
246c614e1605
/
61.0a1
/
20180412100111
/
files
nightly linux64
246c614e1605
/
61.0a1
/
20180412100111
/
files
nightly mac
246c614e1605
/
61.0a1
/
20180412100111
/
files
nightly win32
246c614e1605
/
61.0a1
/
20180412100111
/
files
nightly win64
246c614e1605
/
61.0a1
/
20180412100111
/
files
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
releases | nightly linux32
61.0a1
/
20180412100111
/
pushlog to previous
nightly linux64
61.0a1
/
20180412100111
/
pushlog to previous
nightly mac
61.0a1
/
20180412100111
/
pushlog to previous
nightly win32
61.0a1
/
20180412100111
/
pushlog to previous
nightly win64
61.0a1
/
20180412100111
/
pushlog to previous
|
toolkit/content/select-child.js | file | annotate | diff | comparison | revisions |
--- a/accessible/tests/mochitest/events/test_focus_autocomplete.xul +++ b/accessible/tests/mochitest/events/test_focus_autocomplete.xul @@ -254,17 +254,17 @@ } // XUL autocomplete var popupNode = autocompleteNode.popup; if (!popupNode) { // HTML form autocomplete var controller = Cc["@mozilla.org/autocomplete/controller;1"]. getService(Ci.nsIAutoCompleteController); - popupNode = controller.input.popup.QueryInterface(nsIDOMNode); + popupNode = controller.input.popup; } if (popupNode) { if ("richlistbox" in popupNode) { var list = getAccessible(popupNode.richlistbox); return list.getChildAt(aItemObj.index); }
--- a/accessible/tests/mochitest/relations/a11y.ini +++ b/accessible/tests/mochitest/relations/a11y.ini @@ -1,12 +1,13 @@ [DEFAULT] support-files = !/accessible/tests/mochitest/*.js [test_bindings.xhtml] [test_embeds.xul] +skip-if = os == 'linux' && !debug # bug 1411145 [test_general.html] [test_general.xul] [test_tabbrowser.xul] [test_tree.xul] [test_ui_modalprompt.html] [test_update.html]
--- a/browser/base/content/browser-fullZoom.js +++ b/browser/base/content/browser-fullZoom.js @@ -34,18 +34,17 @@ var FullZoom = { !Services.prefs.getBoolPref("privacy.resistFingerprinting") && Services.prefs.getBoolPref("browser.zoom.siteSpecific"); } return this._siteSpecificPref; }, // nsISupports - QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMEventListener, - Ci.nsIObserver, + QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsIContentPrefObserver, Ci.nsISupportsWeakReference, Ci.nsISupports]), // Initialization & Destruction init: function FullZoom_init() { gBrowser.addEventListener("ZoomChangeUsingMouseWheel", this); @@ -82,17 +81,17 @@ var FullZoom = { Services.prefs.removeObserver("browser.zoom.", this); this._cps2.removeObserverForName(this.name, this); gBrowser.removeEventListener("ZoomChangeUsingMouseWheel", this); }, // Event Handlers - // nsIDOMEventListener + // EventListener handleEvent: function FullZoom_handleEvent(event) { switch (event.type) { case "ZoomChangeUsingMouseWheel": let browser = this._getTargetedBrowser(event); this._ignorePendingZoomAccesses(browser); this._applyZoomToPref(browser); break;
--- a/browser/base/content/tabbrowser.xml +++ b/browser/base/content/tabbrowser.xml @@ -95,17 +95,17 @@ command="cmd_newNavigatorTab" onclick="checkForMiddleClick(this, event);" tooltip="dynamic-shortcut-tooltip"/> <xul:spacer class="closing-tabs-spacer" anonid="closing-tabs-spacer" style="width: 0;"/> </xul:arrowscrollbox> </content> - <implementation implements="nsIDOMEventListener, nsIObserver"> + <implementation implements="nsIObserver"> <constructor> <![CDATA[ this._tabClipWidth = Services.prefs.getIntPref("browser.tabs.tabClipWidth"); let strId = PrivateBrowsingUtils.isWindowPrivate(window) ? "emptyPrivateTabTitle" : "emptyTabTitle"; this.emptyTabTitle = gTabBrowserBundle.GetStringFromName("tabs." + strId); @@ -1960,17 +1960,17 @@ } ]]> </handler> </handlers> </binding> <binding id="tabbrowser-alltabs-popup" extends="chrome://global/content/bindings/popup.xml#popup"> - <implementation implements="nsIDOMEventListener"> + <implementation> <method name="_tabOnAttrModified"> <parameter name="aEvent"/> <body><![CDATA[ var tab = aEvent.target; if (tab.mCorrespondingMenuitem) this._setMenuitemAttributes(tab.mCorrespondingMenuitem, tab); ]]></body> </method>
--- a/browser/base/content/urlbarBindings.xml +++ b/browser/base/content/urlbarBindings.xml @@ -48,17 +48,17 @@ file, You can obtain one at http://mozil xbl:inherits="open,parentfocused=focused,usertyping"/> <children includes="hbox"/> </xul:hbox> <xul:popupset anonid="popupset" class="autocomplete-result-popupset"/> <children includes="toolbarbutton"/> </content> - <implementation implements="nsIObserver, nsIDOMEventListener"> + <implementation implements="nsIObserver"> <field name="ExtensionSearchHandler" readonly="true"> (ChromeUtils.import("resource://gre/modules/ExtensionSearchHandler.jsm", {})).ExtensionSearchHandler; </field> <constructor><![CDATA[ this._prefs = Cc["@mozilla.org/preferences-service;1"] .getService(Ci.nsIPrefService) .getBranch("browser.urlbar.");
--- a/browser/components/feeds/FeedWriter.js +++ b/browser/components/feeds/FeedWriter.js @@ -541,17 +541,17 @@ FeedWriter.prototype = { } else { LOG("FeedWriter._setAlwaysUseLabel: Expected textNode as lastChild of alwaysUse label"); let textNode = this._document.createTextNode(label); checkboxText.appendChild(textNode); } } }, - // nsIDomEventListener + // EventListener handleEvent(event) { if (event.target.ownerDocument != this._document) { LOG("FeedWriter.handleEvent: Someone passed the feed writer as a listener to the events of another document!"); return; } switch (event.type) { case "click": @@ -976,13 +976,13 @@ FeedWriter.prototype = { } }); } else { subscribeCallback(); } }, classID: FEEDWRITER_CID, - QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMEventListener, Ci.nsIObserver, + QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsIDOMGlobalPropertyInitializer]) }; this.NSGetFactory = XPCOMUtils.generateNSGetFactory([FeedWriter]);
--- a/browser/components/places/content/bookmarkProperties.js +++ b/browser/components/places/content/bookmarkProperties.js @@ -344,17 +344,17 @@ var BookmarkPropertiesPanel = { .addEventListener("input", this); } } } // Only enable the accept button once we've finished everything. acceptButton.disabled = acceptButtonDisabled; }, - // nsIDOMEventListener + // EventListener handleEvent: function BPP_handleEvent(aEvent) { var target = aEvent.target; switch (aEvent.type) { case "input": if (target.id == "editBMPanel_locationField" || target.id == "editBMPanel_keywordField") { // Check uri fields to enable accept button if input is valid document.documentElement @@ -368,18 +368,17 @@ var BookmarkPropertiesPanel = { elementsHeight.set(id, newHeight); } break; } }, // nsISupports QueryInterface: function BPP_QueryInterface(aIID) { - if (aIID.equals(Ci.nsIDOMEventListener) || - aIID.equals(Ci.nsISupports)) + if (aIID.equals(Ci.nsISupports)) return this; throw Cr.NS_NOINTERFACE; }, _element: function BPP__element(aID) { return document.getElementById("editBMPanel_" + aID); },
--- a/browser/components/places/content/browserPlacesViews.js +++ b/browser/components/places/content/browserPlacesViews.js @@ -1004,18 +1004,17 @@ function PlacesToolbar(aPlace) { PlacesToolbar.prototype = { __proto__: PlacesViewBase.prototype, _cbEvents: ["dragstart", "dragover", "dragexit", "dragend", "drop", "mousemove", "mouseover", "mouseout"], QueryInterface: function PT_QueryInterface(aIID) { - if (aIID.equals(Ci.nsIDOMEventListener) || - aIID.equals(Ci.nsITimerCallback)) + if (aIID.equals(Ci.nsITimerCallback)) return this; return PlacesViewBase.prototype.QueryInterface.apply(this, arguments); }, uninit: function PT_uninit() { this._removeEventListeners(this._viewElt, this._cbEvents, false); this._removeEventListeners(this._rootElt, ["popupshowing", "popuphidden"], @@ -1906,23 +1905,16 @@ function PlacesMenu(aPopupShowingEvent, PlacesViewBase.call(this, aPlace, aOptions); this._onPopupShowing(aPopupShowingEvent); } PlacesMenu.prototype = { __proto__: PlacesViewBase.prototype, - QueryInterface: function PM_QueryInterface(aIID) { - if (aIID.equals(Ci.nsIDOMEventListener)) - return this; - - return PlacesViewBase.prototype.QueryInterface.apply(this, arguments); - }, - _removeChild: function PM_removeChild(aChild) { PlacesViewBase.prototype._removeChild.apply(this, arguments); }, uninit: function PM_uninit() { this._removeEventListeners(this._rootElt, ["popupshowing", "popuphidden"], true); this._removeEventListeners(window, ["unload"], false);
--- a/browser/components/places/content/editBookmark.js +++ b/browser/components/places/content/editBookmark.js @@ -460,18 +460,17 @@ var gEditItemOverlay = { this._folderMenuList.selectedIndex); // Hide the folders-separator if no folder is annotated as recently-used this._element("foldersSeparator").hidden = (menupopup.childNodes.length <= 6); this._folderMenuList.disabled = this.readOnly; }, QueryInterface: - XPCOMUtils.generateQI([Ci.nsIDOMEventListener, - Ci.nsINavBookmarkObserver]), + XPCOMUtils.generateQI([Ci.nsINavBookmarkObserver]), _element(aID) { return document.getElementById("editBMPanel_" + aID); }, uninitPanel(aHideCollapsibleElements) { if (aHideCollapsibleElements) { // Hide the folder tree if it was previously visible. @@ -950,17 +949,17 @@ var gEditItemOverlay = { this._folderTree.focus(); this._folderTree.selectItems([ip.itemId]); PlacesUtils.asContainer(this._folderTree.selectedNode).containerOpen = true; this._folderTree.selectItems([this._lastNewItem]); this._folderTree.startEditing(this._folderTree.view.selection.currentIndex, this._folderTree.columns.getFirstColumn()); }, - // nsIDOMEventListener + // EventListener handleEvent(aEvent) { switch (aEvent.type) { case "CheckboxStateChange": // Update the tags field when items are checked/unchecked in the listbox let tags = this._getTagsArrayFromTagsInputField(); let tagCheckbox = aEvent.target; let curTagIndex = tags.indexOf(tagCheckbox.label);
--- a/browser/components/places/content/places.js +++ b/browser/components/places/content/places.js @@ -192,18 +192,17 @@ var PlacesOrganizer = { if (!Services.policies.isAllowed("profileImport")) { document.getElementById("OrganizerCommand_browserImport").setAttribute("disabled", true); } ContentArea.focus(); }, QueryInterface: function PO_QueryInterface(aIID) { - if (aIID.equals(Ci.nsIDOMEventListener) || - aIID.equals(Ci.nsISupports)) + if (aIID.equals(Ci.nsISupports)) return this; throw Cr.NS_NOINTERFACE; }, handleEvent: function PO_handleEvent(aEvent) { if (aEvent.type != "AppCommand") return;
--- a/browser/components/preferences/in-content/main.js +++ b/browser/components/preferences/in-content/main.js @@ -1290,17 +1290,17 @@ var gMainPane = { Services.prefs.removeObserver(PREF_AUDIO_FEED_SELECTED_READER, this); Services.prefs.removeObserver(PREF_CONTAINERS_EXTENSION, this); }, // nsISupports - QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsIDOMEventListener]), + QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]), // nsIObserver async observe(aSubject, aTopic, aData) { if (aTopic == "nsPref:changed") { if (aData == PREF_CONTAINERS_EXTENSION) { this.readBrowserContainersCheckbox(); return; @@ -1322,17 +1322,17 @@ var gMainPane = { } if (AppConstants.MOZ_UPDATER) { this.updateReadPrefs(); } } }, - // nsIDOMEventListener + // EventListener handleEvent(aEvent) { if (aEvent.type == "unload") { this.destroy(); } },
--- a/browser/components/search/content/search.xml +++ b/browser/components/search/content/search.xml @@ -1112,17 +1112,17 @@ label="&searchInNewTab.label;" accesskey="&searchInNewTab.accesskey;"/> <xul:menuitem anonid="search-one-offs-context-set-default" label="&searchSetAsDefault.label;" accesskey="&searchSetAsDefault.accesskey;"/> </xul:menupopup> </content> - <implementation implements="nsIDOMEventListener,nsIObserver,nsIWeakReference"> + <implementation implements="nsIObserver,nsIWeakReference"> <!-- Width in pixels of the one-off buttons. 49px is the min-width of each search engine button, adapt this const when changing the css. It's actually 48px + 1px of right border. --> <property name="buttonWidth" readonly="true" onget="return 49;"/> <field name="_popup">null</field>
--- a/browser/components/sessionstore/SessionStore.jsm +++ b/browser/components/sessionstore/SessionStore.jsm @@ -424,17 +424,16 @@ var SessionStore = { }, }; // Freeze the SessionStore object. We don't want anyone to modify it. Object.freeze(SessionStore); var SessionStoreInternal = { QueryInterface: XPCOMUtils.generateQI([ - Ci.nsIDOMEventListener, Ci.nsIObserver, Ci.nsISupportsWeakReference ]), _globalState: new GlobalState(), // A counter to be used to generate a unique ID for each closed tab or window. _nextClosedId: 0, @@ -994,17 +993,17 @@ var SessionStoreInternal = { default: throw new Error(`received unknown message '${aMessage.name}'`); } }, /* ........ Window Event Handlers .............. */ /** - * Implement nsIDOMEventListener for handling various window and tab events + * Implement EventListener for handling various window and tab events */ handleEvent: function ssi_handleEvent(aEvent) { let win = aEvent.currentTarget.ownerGlobal; let target = aEvent.originalTarget; switch (aEvent.type) { case "TabOpen": this.onTabAdd(win); break;
--- a/browser/components/sessionstore/content/content-sessionStore.js +++ b/browser/components/sessionstore/content/content-sessionStore.js @@ -46,16 +46,19 @@ const DOM_STORAGE_LIMIT_PREF = "browser. // or not, and should only be used for tests or debugging. const TIMEOUT_DISABLED_PREF = "browser.sessionstore.debug.no_auto_updates"; const PREF_INTERVAL = "browser.sessionstore.interval"; const kNoIndex = Number.MAX_SAFE_INTEGER; const kLastIndex = Number.MAX_SAFE_INTEGER - 1; +// Grab our global so we can access it in functions below. +const global = this; + /** * A function that will recursively call |cb| to collected data for all * non-dynamic frames in the current frame/docShell tree. */ function mapFrameTree(callback) { return (function map(frame, cb) { // Collect data for the current frame. let obj = cb(frame) || {}; @@ -145,17 +148,17 @@ var StateChangeNotifier = { /** * Listens for and handles content events that we need for the * session store service to be notified of state changes in content. */ var EventListener = { init() { - addEventListener("load", ssu.createDynamicFrameEventFilter(this), true); + ssu.addDynamicFrameFilteredListener(global, "load", this, true); }, handleEvent(event) { // Ignore load events from subframes. if (event.target != content.document) { return; } @@ -459,17 +462,17 @@ var SessionHistoryListener = { * is scrolled this will return null so that we don't tack a property onto * the tabData object in the parent process. * * Example: * {scroll: "100,100", children: [null, null, {scroll: "200,200"}]} */ var ScrollPositionListener = { init() { - addEventListener("scroll", ssu.createDynamicFrameEventFilter(this)); + ssu.addDynamicFrameFilteredListener(global, "scroll", this, false); StateChangeNotifier.addObserver(this); }, handleEvent() { MessageQueue.push("scroll", () => this.collect()); }, onPageLoadCompleted() { @@ -499,17 +502,17 @@ var ScrollPositionListener = { * children: [ * null, * {url: "http://sub.mozilla.org/", id: {input_id: "input value 2"}} * ] * } */ var FormDataListener = { init() { - addEventListener("input", ssu.createDynamicFrameEventFilter(this), true); + ssu.addDynamicFrameFilteredListener(global, "input", this, true); StateChangeNotifier.addObserver(this); }, handleEvent() { MessageQueue.push("formdata", () => this.collect()); }, onPageLoadStarted() { @@ -591,23 +594,25 @@ var SessionStorageListener = { this._changes = undefined; }, // The event listener waiting for MozSessionStorageChanged events. _listener: null, resetEventListener() { if (!this._listener) { - this._listener = ssu.createDynamicFrameEventFilter(this); - addEventListener("MozSessionStorageChanged", this._listener, true); + this._listener = + ssu.addDynamicFrameFilteredListener(global, "MozSessionStorageChanged", + this, true); } }, removeEventListener() { - removeEventListener("MozSessionStorageChanged", this._listener, true); + ssu.removeDynamicFrameFilteredListener(global, "MozSessionStorageChanged", + this._listener, true); this._listener = null; }, handleEvent(event) { if (!docShell) { return; }
--- a/browser/components/sessionstore/nsISessionStoreUtils.idl +++ b/browser/components/sessionstore/nsISessionStoreUtils.idl @@ -1,16 +1,16 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsISupports.idl" interface mozIDOMWindowProxy; -interface nsIDOMEventListener; +interface nsIDOMEventTarget; /** * A callback passed to nsISessionStoreUtils.forEachNonDynamicChildFrame(). */ [function, scriptable, uuid(8199ebf7-76c0-43d6-bcbe-913dd3de3ebf)] interface nsISessionStoreUtilsFrameCallback : nsISupports { /** @@ -30,17 +30,40 @@ interface nsISessionStoreUtils : nsISupp /** * Calls the given |callback| once for each non-dynamic child frame of the * given |window|. */ void forEachNonDynamicChildFrame(in mozIDOMWindowProxy window, in nsISessionStoreUtilsFrameCallback callback); /** - * Creates and returns an event listener that filters events from dynamic - * docShells. It forwards those from non-dynamic docShells to the given - * |listener|. + * Takes the given listener, wraps it in a filter that filters out events from + * dynamic docShells, and adds that filter as a listener for the given event + * type on the given event target. The listener that was added is returned + * (as nsISupports) so that it can later be removed via + * removeDynamicFrameFilteredListener. * * This is implemented as a native filter, rather than a JS-based one, for * performance reasons. + * + * Once bug 1444991 is fixed, this should start taking an EventTarget. */ - nsIDOMEventListener createDynamicFrameEventFilter(in nsIDOMEventListener listener); + [implicit_jscontext] + nsISupports addDynamicFrameFilteredListener(in nsIDOMEventTarget target, + in AString type, + in jsval listener, + in boolean useCapture); + + /** + * Remove the passed-in filtered listener from the given event target, if it's + * currently a listener for the given event type there. The 'listener' + * argument must be something that was returned by + * addDynamicFrameFilteredListener. + * + * This is needed, instead of the normal removeEventListener, because the + * caller doesn't actually have something that WebIDL considers an + * EventListener. + */ + void removeDynamicFrameFilteredListener(in nsIDOMEventTarget target, + in AString type, + in nsISupports listener, + in boolean useCapture); };
--- a/browser/components/sessionstore/nsSessionStoreUtils.cpp +++ b/browser/components/sessionstore/nsSessionStoreUtils.cpp @@ -1,36 +1,39 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsSessionStoreUtils.h" #include "mozilla/dom/Event.h" +#include "mozilla/dom/EventListenerBinding.h" +#include "mozilla/dom/EventTarget.h" +#include "mozilla/dom/ScriptSettings.h" #include "nsPIDOMWindow.h" #include "nsIDocShell.h" using namespace mozilla::dom; namespace { class DynamicFrameEventFilter final : public nsIDOMEventListener { public: NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_CYCLE_COLLECTION_CLASS(DynamicFrameEventFilter) - explicit DynamicFrameEventFilter(nsIDOMEventListener* aListener) + explicit DynamicFrameEventFilter(EventListener* aListener) : mListener(aListener) { } NS_IMETHODIMP HandleEvent(nsIDOMEvent* aEvent) override { if (mListener && TargetInNonDynamicDocShell(aEvent)) { - mListener->HandleEvent(aEvent); + mListener->HandleEvent(*aEvent->InternalDOMEvent()); } return NS_OK; } private: ~DynamicFrameEventFilter() { } @@ -51,17 +54,17 @@ private: return false; } bool isDynamic = false; nsresult rv = docShell->GetCreatedDynamically(&isDynamic); return NS_SUCCEEDED(rv) && !isDynamic; } - nsCOMPtr<nsIDOMEventListener> mListener; + RefPtr<EventListener> mListener; }; NS_IMPL_CYCLE_COLLECTION(DynamicFrameEventFilter, mListener) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DynamicFrameEventFilter) NS_INTERFACE_MAP_ENTRY(nsISupports) NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener) NS_INTERFACE_MAP_END @@ -109,18 +112,50 @@ nsSessionStoreUtils::ForEachNonDynamicCh aCallback->HandleFrame(item->GetWindow(), childOffset); } return NS_OK; } NS_IMETHODIMP -nsSessionStoreUtils::CreateDynamicFrameEventFilter(nsIDOMEventListener* aListener, - nsIDOMEventListener** aResult) +nsSessionStoreUtils::AddDynamicFrameFilteredListener(nsIDOMEventTarget* aTarget, + const nsAString& aType, + JS::Handle<JS::Value> aListener, + bool aUseCapture, + JSContext* aCx, + nsISupports** aResult) { - NS_ENSURE_TRUE(aListener, NS_ERROR_INVALID_ARG); + if (NS_WARN_IF(!aListener.isObject())) { + return NS_ERROR_INVALID_ARG; + } + + nsCOMPtr<EventTarget> target = do_QueryInterface(aTarget); + NS_ENSURE_TRUE(target, NS_ERROR_NO_INTERFACE); - nsCOMPtr<nsIDOMEventListener> filter(new DynamicFrameEventFilter(aListener)); + JS::Rooted<JSObject*> obj(aCx, &aListener.toObject()); + RefPtr<EventListener> listener = + new EventListener(aCx, obj, GetIncumbentGlobal()); + + nsCOMPtr<nsIDOMEventListener> filter(new DynamicFrameEventFilter(listener)); + + nsresult rv = target->AddEventListener(aType, filter, aUseCapture); + NS_ENSURE_SUCCESS(rv, rv); + filter.forget(aResult); - return NS_OK; } + +NS_IMETHODIMP +nsSessionStoreUtils::RemoveDynamicFrameFilteredListener(nsIDOMEventTarget* aTarget, + const nsAString& aType, + nsISupports* aListener, + bool aUseCapture) +{ + nsCOMPtr<EventTarget> target = do_QueryInterface(aTarget); + NS_ENSURE_TRUE(target, NS_ERROR_NO_INTERFACE); + + nsCOMPtr<nsIDOMEventListener> listener = do_QueryInterface(aListener); + NS_ENSURE_TRUE(listener, NS_ERROR_NO_INTERFACE); + + target->RemoveEventListener(aType, listener, aUseCapture); + return NS_OK; +}
--- a/browser/modules/WindowsPreviewPerTab.jsm +++ b/browser/modules/WindowsPreviewPerTab.jsm @@ -150,18 +150,17 @@ function PreviewController(win, tab) { XPCOMUtils.defineLazyGetter(this, "canvasPreview", function() { let canvas = PageThumbs.createCanvas(); canvas.mozOpaque = true; return canvas; }); } PreviewController.prototype = { - QueryInterface: XPCOMUtils.generateQI([Ci.nsITaskbarPreviewController, - Ci.nsIDOMEventListener]), + QueryInterface: XPCOMUtils.generateQI([Ci.nsITaskbarPreviewController]), destroy() { this.tab.removeEventListener("TabAttrModified", this); // Break cycles, otherwise we end up leaking the window with everything // attached to it. delete this.win; delete this.preview; @@ -328,17 +327,17 @@ PreviewController.prototype = { onActivate() { this.win.tabbrowser.selectedTab = this.tab; // Accept activation - this will restore the browser window // if it's minimized return true; }, - // nsIDOMEventListener + // EventListener handleEvent(evt) { switch (evt.type) { case "TabAttrModified": this.updateTitleAndTooltip(); break; } } }; @@ -491,17 +490,17 @@ TabWindow.prototype = { // on it the sorting order of our local array. To do so we must walk // the local array backwards, otherwise we would send move requests in the // wrong order. See bug 522610 for details. for (let i = inorder.length - 1; i >= 0; i--) { inorder[i].move(inorder[i + 1] || null); } }, - // nsIDOMEventListener + // EventListener handleEvent(evt) { let tab = evt.originalTarget; switch (evt.type) { case "TabOpen": this.newTab(tab); this.updateTabOrdering(); break; case "TabClose":
--- a/devtools/client/debugger/new/README.mozilla +++ b/devtools/client/debugger/new/README.mozilla @@ -1,13 +1,13 @@ This is the debugger.html project output. See https://github.com/devtools-html/debugger.html -Version 33.0 +Version 34.0 -Comparison: https://github.com/devtools-html/debugger.html/compare/release-32...release-33 +Comparison: https://github.com/devtools-html/debugger.html/compare/release-33...release-34 Packages: - babel-plugin-transform-es2015-modules-commonjs @6.26.0 - babel-preset-react @6.24.1 - react @16.2.0 - react-dom @16.2.0 - webpack @3.11.0
--- a/devtools/client/debugger/new/debugger.css +++ b/devtools/client/debugger/new/debugger.css @@ -321,28 +321,16 @@ menuseparator { --object-color: var(--theme-body-color); --caption-color: var(--theme-highlight-blue); --location-color: var(--theme-content-color1); --source-link-color: var(--theme-highlight-blue); --node-color: var(--theme-highlight-bluegrey); --reference-color: var(--theme-highlight-purple); } -.theme-firebug { - --number-color: #000088; - --string-color: #ff0000; - --null-color: #787878; - --object-color: DarkGreen; - --caption-color: #444444; - --location-color: #555555; - --source-link-color: blue; - --node-color: rgb(0, 0, 136); - --reference-color: rgb(102, 102, 255); -} - /******************************************************************************/ .objectLink:hover { text-decoration: underline; } .inline { display: inline; @@ -1073,32 +1061,24 @@ html[dir="rtl"] .tree-node img.arrow { .project-text-search .matches-summary { margin-left: 5px; } .project-text-search .result { font-family: Menlo, monospace; } -.project-text-search .result.focused { - background-color: var(--search-overlays-semitransparent); -} - .project-text-search .result .query-match { background-color: var(--theme-selection-background); color: white; padding: 1px 4px; margin: 0 2px 0 2px; border-radius: 2px; } -.project-text-search .result.focused .line-number { - font-weight: bolder; -} - .project-text-search .result .line-number { margin-right: 1em; width: 2em; margin-left: 0.8em; } .project-text-search .no-result-msg { color: var(--theme-body-color-inactive); @@ -1116,20 +1096,16 @@ html[dir="rtl"] .tree-node img.arrow { padding: 2px 0 2px 5px; font-size: 12px; } .project-text-search .file-result .arrow { margin: 2px 0 2px 0; } -.project-text-search .file-result.focused { - background-color: var(--search-overlays-semitransparent); -} - .project-text-search .line-match { display: "flex"; flex-grow: 1; } .project-text-search .search-field { display: flex; align-self: stretch; @@ -1143,16 +1119,32 @@ html[dir="rtl"] .tree-node img.arrow { .project-text-search .managed-tree { overflow-y: auto; height: 100%; } .project-text-search .managed-tree .tree { height: 100%; } + +/* Focus values */ + +.project-text-search .file-result.focused, +.project-text-search .result.focused { + background-color: var(--theme-selection-background); +} + +.project-text-search .result.focused .line-number { + font-weight: bolder; +} + +.project-text-search .result.focused .query-match { + background-color: #ffffff; + color: #000000; +} /* 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/>. */ .sources-panel { background-color: var(--theme-sidebar-background); display: flex; flex: 1; @@ -2920,17 +2912,18 @@ html[dir="rtl"] .breakpoints-list .break .CodeMirror.cm-s-mozilla-breakpoint .CodeMirror-line span[role=presentation] { max-width: 100%; overflow: hidden; text-overflow: ellipsis; display: inline-block; } -.CodeMirror.cm-s-mozilla-breakpoint .CodeMirror-code { +.CodeMirror.cm-s-mozilla-breakpoint .CodeMirror-code, +.CodeMirror.cm-s-mozilla-breakpoint .CodeMirror-scroll { cursor: default; } /* 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/>. */ .expression-input-form { width: 100%; @@ -3004,20 +2997,16 @@ html[dir="rtl"] .breakpoints-list .break :root.theme-light .expression-container:hover { background-color: var(--theme-selection-background-hover); } :root.theme-dark .expression-container:hover { background-color: var(--theme-selection-background-hover); } -:root.theme-firebug .expression-container:hover { - background-color: var(--theme-selection-background-hover); -} - .tree .tree-node:not(.focused):hover { background-color: transparent; } .expression-container__close-btn { position: absolute; offset-inline-end: 0px; top: 0px; @@ -3153,18 +3142,17 @@ html[dir="rtl"] .breakpoints-list .break display: flex; justify-content: space-between; flex-direction: row; align-items: center; margin: 0; flex-shrink: 0; } -.theme-light .frames .location, -.theme-firebug .frames .location { +.theme-light .frames .location { color: var(--theme-comment); } :root.theme-dark .frames .location { color: var(--theme-body-color); opacity: 0.6; } @@ -3189,17 +3177,16 @@ html[dir="rtl"] .breakpoints-list .break color: white; } .frames ul li.selected i.annotation-logo svg path { fill: white; } :root.theme-light .frames ul li.selected .location, -:root.theme-firebug .frames ul li.selected .location, :root.theme-dark .frames ul li.selected .location { color: white; } .show-more-container { display: flex; } @@ -4062,17 +4049,16 @@ html .welcomebox .toggle-button-end.coll .theme-dark .result-list li.selected { background: var(--grey-70); } .result-list li .title { line-height: 1.5em; word-break: break-all; text-overflow: ellipsis; - overflow: hidden; white-space: nowrap; } .result-list li.selected .title { color: white; } .result-list.big li.selected {
--- a/devtools/client/debugger/new/debugger.js +++ b/devtools/client/debugger/new/debugger.js @@ -5108,16 +5108,24 @@ function toggleFrameworkGrouping(toggleV }); }; } function showSource(sourceId) { return ({ dispatch, getState }) => { const source = (0, _selectors.getSource)(getState(), sourceId); + if ((0, _selectors.getPaneCollapse)(getState(), "start")) { + dispatch({ + type: "TOGGLE_PANE", + position: "start", + paneCollapsed: false + }); + } + dispatch(setPrimaryPaneTab("sources")); dispatch({ type: "SHOW_SOURCE", sourceUrl: "" }); dispatch({ type: "SHOW_SOURCE", @@ -6428,20 +6436,17 @@ function evaluateExpression(expression) */ function getMappedExpression(expression) { return async function ({ dispatch, getState, client, sourceMaps }) { const mappings = (0, _selectors.getSelectedScopeMappings)(getState()); if (!mappings) { return expression; } - return await dispatch({ - type: "MAP_EXPRESSION_RESULT", - [_promise.PROMISE]: parser.mapOriginalExpression(expression, mappings) - }); + return parser.mapOriginalExpression(expression, mappings); }; } /***/ }), /***/ 1399: /***/ (function(module, exports, __webpack_require__) { @@ -6611,24 +6616,41 @@ var _WasmParser = __webpack_require__(67 var _WasmDis = __webpack_require__(678); /* 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/>. */ var wasmStates = Object.create(null); +function maybeWasmSectionNameResolver(data) { + try { + const parser = new _WasmParser.BinaryReader(); + parser.setData(data.buffer, 0, data.length); + const reader = new _WasmDis.NameSectionReader(); + reader.read(parser); + return reader.hasValidNames() ? reader.getNameResolver() : null; + } catch (ex) { + // Ignoring any errors during names section retrival. + return null; + } +} + /** * @memberof utils/wasm * @static */ function getWasmText(sourceId, data) { + const nameResolver = maybeWasmSectionNameResolver(data); const parser = new _WasmParser.BinaryReader(); parser.setData(data.buffer, 0, data.length); const dis = new _WasmDis.WasmDisassembler(); + if (nameResolver) { + dis.nameResolver = nameResolver; + } dis.addOffsets = true; const done = dis.disassembleChunk(parser); let result = dis.getResult(); if (result.lines.length === 0) { result = { lines: ["No luck with wast conversion"], offsets: [0], done }; } const offsets = result.offsets; @@ -7014,19 +7036,28 @@ class ManagedTree extends _react.Compone } highlightItem(highlightItems) { const { expanded } = this.state; // This file is visible, so we highlight it. if (expanded.has(this.props.getPath(highlightItems[0]))) { this.focusItem(highlightItems[0]); } else { - // Look at folders starting from the top-level until finds a - // closed folder and highlights this folder - const index = highlightItems.reverse().findIndex(item => !expanded.has(this.props.getPath(item))); + // Look at folders starting from the top-level and expand all the items + // which lie in the path of the item to be highlighted + highlightItems.reverse(); + let index = highlightItems.findIndex(item => !expanded.has(this.props.getPath(item))); + + if (this.props.autoExpandOnHighlight) { + while (index < highlightItems.length - 1) { + this.setExpanded(highlightItems[index], true, false); + index++; + } + } + this.focusItem(highlightItems[index]); } } render() { const { expanded, focusedItem } = this.state; return _react2.default.createElement( "div", @@ -7098,25 +7129,25 @@ function getURL(sourceUrl, debuggeeUrl = case "javascript:": // Ignore `javascript:` URLs for now return def; case "webpack:": // A Webpack source is a special case return (0, _lodash.merge)(def, { path: path, - group: "Webpack", + group: "webpack://", filename: filename }); case "ng:": // An Angular source is a special case return (0, _lodash.merge)(def, { path: path, - group: "Angular", + group: "ng://", filename: filename }); case "about:": // An about page is a special case return (0, _lodash.merge)(def, { path: "/", group: url, @@ -9887,17 +9918,17 @@ var _treeOrder = __webpack_require__(154 var _getURL = __webpack_require__(1405); function isUnderRoot(url, projectRoot) { if (!projectRoot) { return true; } - return `/${url.group}${url.path}`.startsWith(projectRoot); + return `${url.group}${url.path}`.startsWith(projectRoot); } /* 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/>. */ function removeProjectRoot(parts, projectRoot) { const rootParts = projectRoot.replace("://", "").split("/"); return parts.splice(0, rootParts.length - 2); } @@ -9953,17 +9984,17 @@ function traverseTree(url, tree, debugge parts.unshift(url.group); if (projectRoot) { removeProjectRoot(parts, projectRoot); } let path = ""; return parts.reduce((subTree, part, index) => { - path = `${path}/${part}`; + path = path ? `${path}/${part}` : part; const debuggeeHostIfRoot = index === 0 ? debuggeeHost : null; return findOrCreateNode(parts, subTree, path, part, index, url, debuggeeHostIfRoot); }, tree); } /* * Add a source file to a directory node in the tree */ @@ -12869,18 +12900,22 @@ Object.defineProperty(exports, "__esModu exports.isSelectedFrameVisible = isSelectedFrameVisible; var _devtoolsSourceMap = __webpack_require__(1360); var _pause = __webpack_require__(1394); var _sources = __webpack_require__(1369); -function visibleSourceId(location) { - return (0, _devtoolsSourceMap.isOriginalId)(location.sourceId) ? (0, _devtoolsSourceMap.originalToGeneratedId)(location.sourceId) : location.sourceId; +function getGeneratedId(sourceId) { + if ((0, _devtoolsSourceMap.isOriginalId)(sourceId)) { + return (0, _devtoolsSourceMap.originalToGeneratedId)(sourceId); + } + + return sourceId; } /* * Checks to if the selected frame's source is currently * selected. */ /* 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 @@ -12889,17 +12924,21 @@ function visibleSourceId(location) { function isSelectedFrameVisible(state) { const selectedLocation = (0, _sources.getSelectedLocation)(state); const selectedFrame = (0, _pause.getSelectedFrame)(state); if (!selectedFrame || !selectedLocation) { return false; } - return visibleSourceId(selectedLocation) === visibleSourceId(selectedFrame.location); + if ((0, _devtoolsSourceMap.isOriginalId)(selectedLocation.sourceId)) { + return selectedLocation.sourceId === selectedFrame.location.sourceId; + } + + return selectedLocation.sourceId === getGeneratedId(selectedFrame.location.sourceId); } /***/ }), /***/ 1506: /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -16154,17 +16193,17 @@ function findSource(sourceTree, sourceUr return sourceTree; } return returnTarget; } function getDirectories(sourceUrl, sourceTree) { const url = (0, _getURL.getURL)(sourceUrl); - const fullUrl = `/${url.group}${url.path}`; + const fullUrl = `${url.group}${url.path}`; const parentMap = (0, _utils.createParentMap)(sourceTree); const source = findSource(sourceTree, fullUrl); if (!source) { return []; } let node = source; const directories = []; @@ -16732,16 +16771,25 @@ class SourcesTree extends _react.Compone debuggeeUrl, projectRoot, uncollapsedTree, sourceTree })); } } + renderItemName(name) { + const hosts = { + "ng://": "Angular", + "webpack://": "Webpack" + }; + + return hosts[name] || name; + } + renderEmptyElement(message) { return _react2.default.createElement( "div", { className: "no-sources-message" }, message ); } @@ -16798,16 +16846,17 @@ class SourcesTree extends _react.Compone if (isEmpty && !isCustomRoot) { return this.renderEmptyElement(L10N.getStr("sources.noSourcesAvailable")); } const treeProps = { autoExpandAll: false, autoExpandDepth: expanded ? 0 : 1, + autoExpandOnHighlight: true, expanded, getChildren: item => (0, _sourcesTree.nodeHasChildren)(item) ? item.contents : [], getParent: item => parentMap.get(item), getPath: this.getPath, getRoots: roots, highlightItems, itemHeight: 21, key: isEmpty ? "empty" : "full", @@ -16869,17 +16918,17 @@ var _initialiseProps = function () { } return `${item.path}/${item.name}/${blackBoxedPart}`; }; this.getIcon = (sources, item, depth) => { const { debuggeeUrl, projectRoot } = this.props; - if (item.path === "/Webpack") { + if (item.path === "webpack://") { return _react2.default.createElement(_Svg2.default, { name: "webpack" }); } if (item.path === "/Angular") { return _react2.default.createElement(_Svg2.default, { name: "angular" }); } if (depth === 0 && projectRoot === "") { return _react2.default.createElement("img", { @@ -16981,17 +17030,17 @@ var _initialiseProps = function () { onContextMenu: e => this.onContextMenu(e, item) }, arrow, icon, _react2.default.createElement( "span", { className: "label" }, " ", - item.name, + this.renderItemName(item.name), " " ) ); }; }; const mapStateToProps = state => { return { @@ -18290,19 +18339,17 @@ var _editor = __webpack_require__(1358); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } class Preview extends _react.PureComponent { constructor(props) { super(props); this.onMouseOver = e => { const { target } = e; - if (this.props.selectedFrameVisible) { - this.props.updatePreview(target, this.props.editor); - } + this.props.updatePreview(target, this.props.editor); }; this.onMouseUp = () => { this.setState({ selecting: false }); return true; }; this.onMouseDown = () => { @@ -18379,18 +18426,17 @@ const { addExpression, setPopupObjectProperties, updatePreview, clearPreview } = _actions2.default; exports.default = (0, _reactRedux.connect)(state => ({ preview: (0, _selectors.getPreview)(state), - selectedSource: (0, _selectors.getSelectedSource)(state), - selectedFrameVisible: (0, _selectors.isSelectedFrameVisible)(state) + selectedSource: (0, _selectors.getSelectedSource)(state) }), { addExpression, setPopupObjectProperties, updatePreview, clearPreview })(Preview); /***/ }), @@ -30457,17 +30503,17 @@ function updatePreview(target, editor) { dispatch(clearPreview()); } } if (isInvalidTarget(target)) { return; } - if (!(0, _selectors.isLineInScope)(getState(), tokenPos.line)) { + if (!(0, _selectors.isSelectedFrameVisible)(getState()) || !(0, _selectors.isLineInScope)(getState(), tokenPos.line)) { return; } const source = (0, _selectors.getSelectedSource)(getState()); const symbols = (0, _selectors.getSymbols)(getState(), source); let match; if (!symbols || symbols.loading) { @@ -38772,17 +38818,16 @@ function formatSource(source, root) { } /* * Gets the sources that are below a project root */ function getRelativeSources(state) { const sources = (0, _selectors.getSources)(state); const root = (0, _selectors.getProjectDirectoryRoot)(state); - return sources.valueSeq().toJS().filter(({ url }) => url && url.includes(root)).map(source => formatSource(source, root)); } /***/ }), /***/ 3626: /***/ (function(module, exports) { @@ -38981,16 +39026,17 @@ class BreakpointItem extends _react.Comp const node = _reactDom2.default.findDOMNode(this); if (node instanceof HTMLElement) { const mountNode = node.querySelector(".breakpoint-label"); if (node instanceof HTMLElement) { // $FlowIgnore mountNode.innerHTML = ""; this.editor.appendToLocalElement(mountNode); + this.editor.codeMirror.on("mousedown", (_, e) => e.preventDefault()); } } } render() { const { breakpoint, onClick,
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-asm.js +++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-asm.js @@ -4,20 +4,16 @@ add_task(async function() { // After reload() we are getting getSources notifiction for old sources, // using the debugger statement to really stop are reloaded page. await waitForPaused(dbg); await resume(dbg); await waitForSources(dbg, "doc-asm.html", "asm.js"); - // Expand nodes and make sure more sources appear. - is(findAllElements(dbg, "sourceNodes").length, 2); - - await clickElement(dbg, "sourceDirectoryLabel", 2); is(findAllElements(dbg, "sourceNodes").length, 4); await selectSource(dbg, "asm.js"); await addBreakpoint(dbg, "asm.js", 7); invokeInTab("runAsm"); await waitForPaused(dbg);
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-babel-preview.js +++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-babel-preview.js @@ -1,11 +1,14 @@ /* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ +// Tests for preview through Babel's compile output. +requestLongerTimeout(3); + function getCoordsFromPosition(cm, { line, ch }) { return cm.charCoords({ line: ~~line, ch: ~~ch }); } async function assertPreviews(dbg, previews) { for (const { line, column, expression, result, fields } of previews) { hoverAtPos(dbg, { line, ch: column });
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-babel-scopes.js +++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-babel-scopes.js @@ -1,13 +1,13 @@ /* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ // This test can be really slow on debug platforms and should be split. -requestLongerTimeout(4); +requestLongerTimeout(6); // Tests loading sourcemapped sources for Babel's compile output. async function breakpointScopes(dbg, fixture, { line, column }, scopes) { const { selectors: { getBreakpoint, getBreakpoints }, getState } = dbg; const filename = `fixtures/${fixture}/input.js`; await waitForSources(dbg, filename);
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-preview-source-maps.js +++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-preview-source-maps.js @@ -1,29 +1,16 @@ /* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ -function getCoordsFromPosition(cm, { line, ch }) { - return cm.charCoords({ line: ~~line, ch: ~~ch }); -} -function hoverAtPos(dbg, { line, ch }) { - info(`Hovering at (${line}, ${ch})\n`); - const cm = getCM(dbg); - const coords = getCoordsFromPosition(cm, { line: line - 1, ch }); - const tokenEl = dbg.win.document.elementFromPoint(coords.left, coords.top); - const previewed = waitForDispatch(dbg, "SET_PREVIEW"); - tokenEl.dispatchEvent( - new MouseEvent("mouseover", { - bubbles: true, - cancelable: true, - view: dbg.win - }) - ); - return previewed; +async function assertNoTooltip(dbg) { + await waitForTime(200); + const el = findElement(dbg, "tooltip"); + is(el, null, "Tooltip should not exist") } function assertPreviewTooltip(dbg, { result, expression }) { const previewEl = findElement(dbg, "tooltip"); is(previewEl.innerText, result, "Preview text shown to user"); const preview = dbg.selectors.getPreview(dbg.getState()); is(`${preview.result}`, result, "Preview.result"); @@ -53,17 +40,26 @@ add_task(async function() { await waitForSources(dbg, "entry.js", "output.js", "times2.js", "opts.js"); await selectSource(dbg, "times2"); await addBreakpoint(dbg, "times2", 2); invokeInTab("keepMeAlive"); await waitForPaused(dbg); await waitForSelectedSource(dbg, "times2"); - await hoverAtPos(dbg, { line: 2, ch: 9 }); - assertPreviewTooltip(dbg, { result: 4, expression: "x" }); + info(`Test previewing in the original location`) + await assertPreviews(dbg, [ + { line: 2, column: 10, result: 4, expression: "x" } + ]); + info(`Test previewing in the generated location`) await dbg.actions.jumpToMappedSelectedLocation(); await waitForSelectedSource(dbg, "bundle.js"); + await assertPreviews(dbg, [ + { line: 70, column: 11, result: 4, expression: "x" } + ]); - await hoverAtPos(dbg, { line: 70, ch: 10 }); - assertPreviewTooltip(dbg, { result: 4, expression: "x" }); + + info(`Test that you can not preview in another original file`); + await selectSource(dbg, "output"); + await hoverAtPos(dbg, { line: 2, ch: 16 }); + await assertNoTooltip(dbg) });
--- a/devtools/client/debugger/new/test/mochitest/browser_dbg-sources.js +++ b/devtools/client/debugger/new/test/mochitest/browser_dbg-sources.js @@ -19,16 +19,33 @@ async function assertSourceCount(dbg, co function getLabel(dbg, index) { return findElement(dbg, "sourceNode", index) .textContent.trim() .replace(/^[\s\u200b]*/g, ""); } add_task(async function() { const dbg = await initDebugger("doc-sources.html"); + const { selectors: { getSelectedSource, getExpandedState }, getState } = dbg; + + await waitForSources(dbg, "nested-source"); + await selectSource(dbg, "nested-source"); + + const expanded = getExpandedState(getState()); + + ok( + expanded.has( + `example.com/browser/devtools/client/debugger/new/test/mochitest/examples/nested/nested/` + ), + "Nodes in path are automatically expanded" + ); +}); + +add_task(async function() { + const dbg = await initDebugger("doc-sources.html"); const { selectors: { getSelectedSource }, getState } = dbg; await waitForSources(dbg, "simple1", "simple2", "nested-source", "long.js"); // Expand nodes and make sure more sources appear. await assertSourceCount(dbg, 2); await clickElement(dbg, "sourceDirectoryLabel", 2);
--- a/devtools/client/inspector/rules/test/browser.ini +++ b/devtools/client/inspector/rules/test/browser.ini @@ -11,16 +11,17 @@ support-files = doc_content_stylesheet_script.css doc_copystyles.css doc_copystyles.html doc_cssom.html doc_custom.html doc_edit_imported_selector.html doc_filter.html doc_frame_script.js + doc_grid_names.html doc_inline_sourcemap.html doc_invalid_sourcemap.css doc_invalid_sourcemap.html doc_keyframeanimation.css doc_keyframeanimation.html doc_keyframeLineNumbers.html doc_media_queries.html doc_pseudoelement.html @@ -171,16 +172,17 @@ skip-if = (os == "win" && debug) # bug 9 [browser_rules_grid-highlighter-on-navigate.js] [browser_rules_grid-highlighter-on-reload.js] [browser_rules_grid-highlighter-restored-after-reload.js] [browser_rules_grid-toggle_01.js] [browser_rules_grid-toggle_01b.js] [browser_rules_grid-toggle_02.js] [browser_rules_grid-toggle_03.js] [browser_rules_grid-toggle_04.js] +[browser_rules_gridline-names-autocomplete.js] [browser_rules_guessIndentation.js] [browser_rules_highlight-used-fonts.js] [browser_rules_inherited-properties_01.js] [browser_rules_inherited-properties_02.js] [browser_rules_inherited-properties_03.js] [browser_rules_inherited-properties_04.js] [browser_rules_inline-source-map.js] [browser_rules_invalid.js]
new file mode 100644 --- /dev/null +++ b/devtools/client/inspector/rules/test/browser_rules_gridline-names-autocomplete.js @@ -0,0 +1,169 @@ +/* vim: set ft=javascript ts=2 et sw=2 tw=80: */ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Tests that CSS property values are autocompleted and cycled +// correctly when editing an existing property in the rule view. + +// format : +// [ +// what key to press, +// modifers, +// expected input box value after keypress, +// is the popup open, +// is a suggestion selected in the popup, +// expect ruleview-changed, +// ] + +const OPEN = true, SELECTED = true, CHANGE = true; +const changeTestData = [ + ["c", {}, "col1-start", OPEN, SELECTED, CHANGE], + ["o", {}, "col1-start", OPEN, SELECTED, CHANGE], + ["l", {}, "col1-start", OPEN, SELECTED, CHANGE], + ["VK_DOWN", {}, "col2-start", OPEN, SELECTED, CHANGE], + ["VK_RIGHT", {}, "col2-start", !OPEN, !SELECTED, !CHANGE], +]; + +// Creates a new CSS property value. +// Checks that grid-area autocompletes column and row names. +const newAreaTestData = [ + ["g", {}, "grid", OPEN, SELECTED, !CHANGE], + ["VK_DOWN", {}, "grid-area", OPEN, SELECTED, !CHANGE], + ["VK_TAB", {}, "", !OPEN, !SELECTED, !CHANGE], + "grid-line-names-updated", + ["c", {}, "col1-start", OPEN, SELECTED, CHANGE], + ["VK_BACK_SPACE", {}, "c", !OPEN, !SELECTED, CHANGE], + ["VK_BACK_SPACE", {}, "", !OPEN, !SELECTED, CHANGE], + ["r", {}, "row1-start", OPEN, SELECTED, CHANGE], + ["r", {}, "rr", !OPEN, !SELECTED, CHANGE], + ["VK_BACK_SPACE", {}, "r", !OPEN, !SELECTED, CHANGE], + ["o", {}, "row1-start", OPEN, SELECTED, CHANGE], + ["VK_RETURN", {}, "", !OPEN, !SELECTED, CHANGE], +]; + +// Creates a new CSS property value. +// Checks that grid-row only autocompletes row names. +const newRowTestData = [ + ["g", {}, "grid", OPEN, SELECTED, !CHANGE], + ["r", {}, "grid", OPEN, SELECTED, !CHANGE], + ["i", {}, "grid", OPEN, SELECTED, !CHANGE], + ["d", {}, "grid", OPEN, SELECTED, !CHANGE], + ["-", {}, "grid-area", OPEN, SELECTED, !CHANGE], + ["r", {}, "grid-row", OPEN, SELECTED, !CHANGE], + ["VK_RETURN", {}, "", !OPEN, !SELECTED, !CHANGE], + "grid-line-names-updated", + ["c", {}, "c", !OPEN, !SELECTED, CHANGE], + ["VK_BACK_SPACE", {}, "", !OPEN, !SELECTED, CHANGE], + ["r", {}, "row1-start", OPEN, SELECTED, CHANGE], + ["VK_TAB", {}, "", !OPEN, !SELECTED, CHANGE], +]; + +const TEST_URL = URL_ROOT + "doc_grid_names.html"; + +add_task(async function() { + await addTab(TEST_URL); + let {toolbox, inspector, view} = await openRuleView(); + + info("Test autocompletion changing a preexisting property"); + await runChangePropertyAutocompletionTest(toolbox, inspector, view, changeTestData); + + info("Test autocompletion creating a new property"); + await runNewPropertyAutocompletionTest(toolbox, inspector, view, newAreaTestData); + + info("Test autocompletion creating a new property"); + await runNewPropertyAutocompletionTest(toolbox, inspector, view, newRowTestData); +}); + +async function runNewPropertyAutocompletionTest(toolbox, inspector, view, testData) { + info("Selecting the test node"); + await selectNode("#cell2", inspector); + + info("Focusing the css property editable field"); + let ruleEditor = getRuleViewRuleEditor(view, 0); + let editor = await focusNewRuleViewProperty(ruleEditor); + let gridLineNamesUpdated = inspector.once("grid-line-names-updated"); + + info("Starting to test for css property completion"); + for (let data of testData) { + if (data == "grid-line-names-updated") { + await gridLineNamesUpdated; + continue; + } + await testCompletion(data, editor, view); + } +} + +async function runChangePropertyAutocompletionTest(toolbox, inspector, view, testData) { + info("Selecting the test node"); + await selectNode("#cell3", inspector); + + let ruleEditor = getRuleViewRuleEditor(view, 1).rule; + let prop = ruleEditor.textProps[0]; + + info("Focusing the css property editable value"); + let gridLineNamesUpdated = inspector.once("grid-line-names-updated"); + let editor = await focusEditableField(view, prop.editor.valueSpan); + await gridLineNamesUpdated; + + info("Starting to test for css property completion"); + for (let data of testData) { + // Re-define the editor at each iteration, because the focus may have moved + // from property to value and back + editor = inplaceEditor(view.styleDocument.activeElement); + await testCompletion(data, editor, view); + } +} + +async function testCompletion([key, modifiers, completion, open, selected, change], + editor, view) { + info("Pressing key " + key); + info("Expecting " + completion); + info("Is popup opened: " + open); + info("Is item selected: " + selected); + + let onDone; + if (change) { + // If the key triggers a ruleview-changed, wait for that event, it will + // always be the last to be triggered and tells us when the preview has + // been done. + onDone = view.once("ruleview-changed"); + } else { + // Otherwise, expect an after-suggest event (except if the popup gets + // closed). + onDone = key !== "VK_RIGHT" && key !== "VK_BACK_SPACE" + ? editor.once("after-suggest") + : null; + } + + // Also listening for popup opened/closed events if needed. + let popupEvent = open ? "popup-opened" : "popup-closed"; + let onPopupEvent = editor.popup.isOpen !== open ? once(editor.popup, popupEvent) : null; + + info("Synthesizing key " + key + ", modifiers: " + Object.keys(modifiers)); + + EventUtils.synthesizeKey(key, modifiers, view.styleWindow); + + // Flush the debounce for the preview text. + view.debounce.flush(); + + await onDone; + await onPopupEvent; + + // The key might have been a TAB or shift-TAB, in which case the editor will + // be a new one + editor = inplaceEditor(view.styleDocument.activeElement); + + info("Checking the state"); + if (completion !== null) { + is(editor.input.value, completion, "Correct value is autocompleted"); + } + + if (!open) { + ok(!(editor.popup && editor.popup.isOpen), "Popup is closed"); + } else { + ok(editor.popup.isOpen, "Popup is open"); + is(editor.popup.selectedIndex !== -1, selected, "An item is selected"); + } +}
new file mode 100644 --- /dev/null +++ b/devtools/client/inspector/rules/test/doc_grid_names.html @@ -0,0 +1,17 @@ +<!doctype html> +<style type='text/css'> + #grid { + display: grid; + grid-template-rows: [row1-start] auto [row2-start] auto [row2-end]; + grid-template-columns: [col1-start] 100px [col2-start] 100px [col3-start] 100px [col3-end]; + } + #cell3 { + grid-column: "col3-start"; + grid-row: "row2-start"; + } +</style> +<div id="grid"> + <div>cell1</div> + <div id="cell2">cell2</div> + <div id="cell3">cell3</div> +</div> \ No newline at end of file
--- a/devtools/client/inspector/rules/views/text-property-editor.js +++ b/devtools/client/inspector/rules/views/text-property-editor.js @@ -79,27 +79,28 @@ function TextPropertyEditor(ruleEditor, this.browserWindow = this.doc.defaultView.top; this._populatedComputed = false; this._hasPendingClick = false; this._clickedElementOptions = null; const toolbox = this.ruleView.inspector.toolbox; this.cssProperties = getCssProperties(toolbox); + this.getGridlineNames = this.getGridlineNames.bind(this); + this.update = this.update.bind(this); + this.updatePropertyState = this.updatePropertyState.bind(this); this._onEnableClicked = this._onEnableClicked.bind(this); this._onExpandClicked = this._onExpandClicked.bind(this); + this._onNameDone = this._onNameDone.bind(this); this._onStartEditing = this._onStartEditing.bind(this); - this._onNameDone = this._onNameDone.bind(this); - this._onValueDone = this._onValueDone.bind(this); this._onSwatchCommit = this._onSwatchCommit.bind(this); this._onSwatchPreview = this._onSwatchPreview.bind(this); this._onSwatchRevert = this._onSwatchRevert.bind(this); this._onValidate = this.ruleView.debounce(this._previewValue, 10, this); - this.update = this.update.bind(this); - this.updatePropertyState = this.updatePropertyState.bind(this); + this._onValueDone = this._onValueDone.bind(this); this._create(); this.update(); } TextPropertyEditor.prototype = { /** * Boolean indicating if the name or value is being currently edited. @@ -311,21 +312,53 @@ TextPropertyEditor.prototype = { contentType: InplaceEditor.CONTENT_TYPES.CSS_VALUE, property: this.prop, defaultIncrement: this.prop.name === "opacity" ? 0.1 : 1, popup: this.popup, multiline: true, maxWidth: () => this.container.getBoundingClientRect().width, cssProperties: this.cssProperties, cssVariables: this.rule.elementStyle.variables, + getGridLineNames: this.getGridlineNames, }); } }, /** + * Get the grid line names of the grid that the currently selected element is + * contained in. + * + * @return {Object} Contains the names of the cols and rows as arrays + * {cols: [], rows: []}. + */ + getGridlineNames: async function() { + let gridLineNames = {cols: [], rows: []}; + let layoutInspector = await this.ruleView.inspector.walker.getLayoutInspector(); + let gridFront = await layoutInspector.getCurrentGrid( + this.ruleView.inspector.selection.nodeFront); + + if (gridFront) { + let gridFragments = gridFront.gridFragments; + + for (let gridFragment of gridFragments) { + for (let rowLine of gridFragment.rows.lines) { + gridLineNames.rows = gridLineNames.rows.concat(rowLine.names); + } + for (let colLine of gridFragment.cols.lines) { + gridLineNames.cols = gridLineNames.cols.concat(colLine.names); + } + } + } + + // Emit message for test files + this.ruleView.inspector.emit("grid-line-names-updated"); + return gridLineNames; + }, + + /** * Get the path from which to resolve requests for this * rule's stylesheet. * * @return {String} the stylesheet's href. */ get sheetHref() { let domRule = this.rule.domRule; if (domRule) {
--- a/devtools/client/locales/en-US/netmonitor.properties +++ b/devtools/client/locales/en-US/netmonitor.properties @@ -53,20 +53,16 @@ netmonitor.security.hostHeader=Host %S: # defined: # Organization: <Not Available> netmonitor.security.notAvailable=<Not Available> # LOCALIZATION NOTE (collapseDetailsPane): This is the tooltip for the button # that collapses the network details pane in the UI. collapseDetailsPane=Hide request details -# LOCALIZATION NOTE (expandDetailsPane): This is the tooltip for the button -# that expands the network details pane in the UI. -expandDetailsPane=Show request details - # LOCALIZATION NOTE (headersEmptyText): This is the text displayed in the # headers tab of the network details pane when there are no headers available. headersEmptyText=No headers for this request # LOCALIZATION NOTE (headersFilterText): This is the text displayed in the # headers tab of the network details pane for the filtering input. headersFilterText=Filter headers
--- a/devtools/client/netmonitor/src/assets/styles/Toolbar.css +++ b/devtools/client/netmonitor/src/assets/styles/Toolbar.css @@ -40,32 +40,8 @@ bottom: 1px; } .devtools-checkbox-label { margin-inline-start: 10px; margin-inline-end: 3px; white-space: nowrap; } - -/* Network details panel toggle */ - -.network-details-panel-toggle:dir(ltr)::before, -.network-details-panel-toggle.pane-collapsed:dir(rtl)::before { - background-image: var(--theme-pane-collapse-image); -} - -.network-details-panel-toggle.pane-collapsed:dir(ltr)::before, -.network-details-panel-toggle:dir(rtl)::before { - background-image: var(--theme-pane-expand-image); -} - -/* Responsive web design support */ - -@media (max-width: 700px) { - .network-details-panel-toggle:dir(ltr)::before { - transform: rotate(90deg); - } - - .network-details-panel-toggle:dir(rtl)::before { - transform: rotate(-90deg); - } -}
--- a/devtools/client/netmonitor/src/assets/styles/netmonitor.css +++ b/devtools/client/netmonitor/src/assets/styles/netmonitor.css @@ -1,12 +1,13 @@ /* 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/. */ +@import "resource://devtools/client/shared/components/SidebarToggle.css"; @import "resource://devtools/client/shared/components/splitter/SplitBox.css"; @import "resource://devtools/client/shared/components/tree/TreeView.css"; @import "resource://devtools/client/shared/components/tabs/Tabs.css"; @import "resource://devtools/client/shared/components/tabs/TabBar.css"; @import "chrome://devtools/skin/components-frame.css"; @import "chrome://devtools/content/sourceeditor/codemirror/lib/codemirror.css"; @import "chrome://devtools/content/sourceeditor/codemirror/addon/dialog/dialog.css"; @import "chrome://devtools/content/sourceeditor/codemirror/mozilla.css";
--- a/devtools/client/netmonitor/src/components/NetworkDetailsPanel.js +++ b/devtools/client/netmonitor/src/components/NetworkDetailsPanel.js @@ -26,16 +26,17 @@ const { div } = dom; */ function NetworkDetailsPanel({ connector, activeTabId, cloneSelectedRequest, request, selectTab, sourceMapService, + toggleNetworkDetails, openLink, }) { if (!request) { return null; } return ( div({ className: "network-details-panel" }, @@ -43,16 +44,17 @@ function NetworkDetailsPanel({ TabboxPanel({ activeTabId, cloneSelectedRequest, connector, openLink, request, selectTab, sourceMapService, + toggleNetworkDetails, }) : CustomRequestPanel({ connector, request, }) ) ); } @@ -62,21 +64,23 @@ NetworkDetailsPanel.displayName = "Netwo NetworkDetailsPanel.propTypes = { connector: PropTypes.object.isRequired, activeTabId: PropTypes.string, cloneSelectedRequest: PropTypes.func.isRequired, open: PropTypes.bool, request: PropTypes.object, selectTab: PropTypes.func.isRequired, sourceMapService: PropTypes.object, + toggleNetworkDetails: PropTypes.func.isRequired, openLink: PropTypes.func, }; module.exports = connect( (state) => ({ activeTabId: state.ui.detailsPanelSelectedTab, request: getSelectedRequest(state), }), (dispatch) => ({ cloneSelectedRequest: () => dispatch(Actions.cloneSelectedRequest()), selectTab: (tabId) => dispatch(Actions.selectDetailsPanelTab(tabId)), + toggleNetworkDetails: () => dispatch(Actions.toggleNetworkDetails()), }), )(NetworkDetailsPanel);
--- a/devtools/client/netmonitor/src/components/TabboxPanel.js +++ b/devtools/client/netmonitor/src/components/TabboxPanel.js @@ -15,16 +15,17 @@ const TabPanel = createFactory(require(" const CookiesPanel = createFactory(require("./CookiesPanel")); const HeadersPanel = createFactory(require("./HeadersPanel")); const ParamsPanel = createFactory(require("./ParamsPanel")); const ResponsePanel = createFactory(require("./ResponsePanel")); const SecurityPanel = createFactory(require("./SecurityPanel")); const StackTracePanel = createFactory(require("./StackTracePanel")); const TimingsPanel = createFactory(require("./TimingsPanel")); +const COLLAPSE_DETAILS_PANE = L10N.getStr("collapseDetailsPane"); const COOKIES_TITLE = L10N.getStr("netmonitor.tab.cookies"); const HEADERS_TITLE = L10N.getStr("netmonitor.tab.headers"); const PARAMS_TITLE = L10N.getStr("netmonitor.tab.params"); const RESPONSE_TITLE = L10N.getStr("netmonitor.tab.response"); const SECURITY_TITLE = L10N.getStr("netmonitor.tab.security"); const STACK_TRACE_TITLE = L10N.getStr("netmonitor.tab.stackTrace"); const TIMINGS_TITLE = L10N.getStr("netmonitor.tab.timings"); @@ -35,28 +36,35 @@ const TIMINGS_TITLE = L10N.getStr("netmo function TabboxPanel({ activeTabId, cloneSelectedRequest = () => {}, connector, openLink, request, selectTab, sourceMapService, + toggleNetworkDetails, }) { if (!request) { return null; } return ( Tabbar({ activeTabId, menuDocument: window.parent.document, onSelect: selectTab, renderOnlySelected: true, showAllTabsMenu: true, + sidebarToggleButton: { + collapsed: false, + collapsePaneTitle: COLLAPSE_DETAILS_PANE, + expandPaneTitle: "", + onClick: toggleNetworkDetails, + }, }, TabPanel({ id: PANELS.HEADERS, title: HEADERS_TITLE, }, HeadersPanel({ cloneSelectedRequest, connector,
--- a/devtools/client/netmonitor/src/components/Toolbar.js +++ b/devtools/client/netmonitor/src/components/Toolbar.js @@ -10,30 +10,27 @@ const dom = require("devtools/client/sha const PropTypes = require("devtools/client/shared/vendor/react-prop-types"); const { connect } = require("devtools/client/shared/redux/visibility-handler-connect"); const Actions = require("../actions/index"); const { FILTER_SEARCH_DELAY, FILTER_TAGS } = require("../constants"); const { getRecordingState, getTypeFilteredRequests, - isNetworkDetailsToggleButtonDisabled, } = require("../selectors/index"); const { autocompleteProvider } = require("../utils/filter-autocomplete-provider"); const { L10N } = require("../utils/l10n"); const { fetchNetworkUpdatePacket } = require("../utils/request-utils"); // Components const SearchBox = createFactory(require("devtools/client/shared/components/SearchBox")); const { button, div, input, label, span } = dom; // Localization -const COLLAPSE_DETAILS_PANE = L10N.getStr("collapseDetailsPane"); -const EXPAND_DETAILS_PANE = L10N.getStr("expandDetailsPane"); const SEARCH_KEY_SHORTCUT = L10N.getStr("netmonitor.toolbar.filterFreetext.key"); const SEARCH_PLACE_HOLDER = L10N.getStr("netmonitor.toolbar.filterFreetext.label"); const TOOLBAR_CLEAR = L10N.getStr("netmonitor.toolbar.clear"); const TOOLBAR_TOGGLE_RECORDING = L10N.getStr("netmonitor.toolbar.toggleRecording"); // Preferences const DEVTOOLS_DISABLE_CACHE_PREF = "devtools.cache.disabled"; const DEVTOOLS_ENABLE_PERSISTENT_LOG_PREF = "devtools.netmonitor.persistlog"; @@ -56,19 +53,16 @@ class Toolbar extends Component { static get propTypes() { return { connector: PropTypes.object.isRequired, toggleRecording: PropTypes.func.isRequired, recording: PropTypes.bool.isRequired, clearRequests: PropTypes.func.isRequired, requestFilterTypes: PropTypes.object.isRequired, setRequestFilterText: PropTypes.func.isRequired, - networkDetailsToggleDisabled: PropTypes.bool.isRequired, - networkDetailsOpen: PropTypes.bool.isRequired, - toggleNetworkDetails: PropTypes.func.isRequired, enablePersistentLogs: PropTypes.func.isRequired, togglePersistentLogs: PropTypes.func.isRequired, persistentLogsEnabled: PropTypes.bool.isRequired, disableBrowserCache: PropTypes.func.isRequired, toggleBrowserCache: PropTypes.func.isRequired, browserCacheDisabled: PropTypes.bool.isRequired, toggleRequestFilterType: PropTypes.func.isRequired, filteredRequests: PropTypes.array.isRequired, @@ -87,19 +81,17 @@ class Toolbar extends Component { componentDidMount() { Services.prefs.addObserver(DEVTOOLS_ENABLE_PERSISTENT_LOG_PREF, this.updatePersistentLogsEnabled); Services.prefs.addObserver(DEVTOOLS_DISABLE_CACHE_PREF, this.updateBrowserCacheDisabled); } shouldComponentUpdate(nextProps) { - return this.props.networkDetailsOpen !== nextProps.networkDetailsOpen - || this.props.networkDetailsToggleDisabled !== nextProps.networkDetailsToggleDisabled - || this.props.persistentLogsEnabled !== nextProps.persistentLogsEnabled + return this.props.persistentLogsEnabled !== nextProps.persistentLogsEnabled || this.props.browserCacheDisabled !== nextProps.browserCacheDisabled || this.props.recording !== nextProps.recording || !Object.is(this.props.requestFilterTypes, nextProps.requestFilterTypes) // Filtered requests are useful only when searchbox is focused || !!(this.refs.searchbox && this.refs.searchbox.focused); } @@ -144,19 +136,16 @@ class Toolbar extends Component { } render() { let { toggleRecording, clearRequests, requestFilterTypes, setRequestFilterText, - networkDetailsToggleDisabled, - networkDetailsOpen, - toggleNetworkDetails, togglePersistentLogs, persistentLogsEnabled, toggleBrowserCache, browserCacheDisabled, recording, } = this.props; // Render list of filter-buttons. @@ -181,29 +170,16 @@ class Toolbar extends Component { // Calculate class-list for toggle recording button. The button // has two states: pause/play. let toggleRecordingButtonClass = [ "devtools-button", "requests-list-pause-button", recording ? "devtools-pause-icon" : "devtools-play-icon", ].join(" "); - // Detail toggle button - let toggleDetailButtonClassList = [ - "network-details-panel-toggle", - "devtools-button", - ]; - - if (!networkDetailsOpen) { - toggleDetailButtonClassList.push("pane-collapsed"); - } - let toggleDetailButtonClass = toggleDetailButtonClassList.join(" "); - let toggleDetailButtonTitle = networkDetailsOpen ? COLLAPSE_DETAILS_PANE : - EXPAND_DETAILS_PANE; - // Render the entire toolbar. return ( span({ className: "devtools-toolbar devtools-toolbar-container" }, span({ className: "devtools-toolbar-group" }, button({ className: toggleRecordingButtonClass, title: TOOLBAR_TOGGLE_RECORDING, onClick: toggleRecording, @@ -248,44 +224,34 @@ class Toolbar extends Component { delay: FILTER_SEARCH_DELAY, keyShortcut: SEARCH_KEY_SHORTCUT, placeholder: SEARCH_PLACE_HOLDER, type: "filter", ref: "searchbox", onChange: setRequestFilterText, onFocus: this.onSearchBoxFocus, autocompleteProvider: this.autocompleteProvider, - }), - button({ - className: toggleDetailButtonClass, - title: toggleDetailButtonTitle, - disabled: networkDetailsToggleDisabled, - tabIndex: "0", - onClick: toggleNetworkDetails, - }), + }) ) ) ); } } module.exports = connect( (state) => ({ browserCacheDisabled: state.ui.browserCacheDisabled, filteredRequests: getTypeFilteredRequests(state), - networkDetailsToggleDisabled: isNetworkDetailsToggleButtonDisabled(state), - networkDetailsOpen: state.ui.networkDetailsOpen, persistentLogsEnabled: state.ui.persistentLogsEnabled, recording: getRecordingState(state), requestFilterTypes: state.filters.requestFilterTypes, }), (dispatch) => ({ clearRequests: () => dispatch(Actions.clearRequests()), disableBrowserCache: (disabled) => dispatch(Actions.disableBrowserCache(disabled)), enablePersistentLogs: (enabled) => dispatch(Actions.enablePersistentLogs(enabled)), setRequestFilterText: (text) => dispatch(Actions.setRequestFilterText(text)), toggleBrowserCache: () => dispatch(Actions.toggleBrowserCache()), - toggleNetworkDetails: () => dispatch(Actions.toggleNetworkDetails()), toggleRecording: () => dispatch(Actions.toggleRecording()), togglePersistentLogs: () => dispatch(Actions.togglePersistentLogs()), toggleRequestFilterType: (type) => dispatch(Actions.toggleRequestFilterType(type)), }), )(Toolbar);
--- a/devtools/client/netmonitor/src/selectors/ui.js +++ b/devtools/client/netmonitor/src/selectors/ui.js @@ -1,24 +1,19 @@ /* 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/. */ "use strict"; const { createSelector } = require("devtools/client/shared/vendor/reselect"); const { REQUESTS_WATERFALL } = require("../constants"); -const { getDisplayedRequests } = require("./requests"); const EPSILON = 0.001; -function isNetworkDetailsToggleButtonDisabled(state) { - return getDisplayedRequests(state).length == 0; -} - const getWaterfallScale = createSelector( state => state.requests, state => state.timingMarkers, state => state.ui, (requests, timingMarkers, ui) => { if (requests.firstStartedMillis === +Infinity || ui.waterfallWidth === null) { return null; } @@ -31,11 +26,10 @@ const getWaterfallScale = createSelector // Reduce 20px for the last request's requests-list-timings-total return Math.min(Math.max( (ui.waterfallWidth - REQUESTS_WATERFALL.LABEL_WIDTH - 20) / longestWidth, EPSILON), 1); } ); module.exports = { - isNetworkDetailsToggleButtonDisabled, getWaterfallScale, };
--- a/devtools/client/netmonitor/test/browser_net_brotli.js +++ b/devtools/client/netmonitor/test/browser_net_brotli.js @@ -44,18 +44,17 @@ add_task(async function() { fullMimeType: "text/plain", transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeB", 60), size: L10N.getFormatStrWithNumbers("networkMenu.sizeB", 64), time: true }); wait = waitForDOM(document, ".CodeMirror-code"); let onResponseContent = monitor.panelWin.once(EVENTS.RECEIVED_RESPONSE_CONTENT); - EventUtils.sendMouseEvent({ type: "click" }, - document.querySelector(".network-details-panel-toggle")); + store.dispatch(Actions.toggleNetworkDetails()); EventUtils.sendMouseEvent({ type: "click" }, document.querySelector("#response-tab")); await wait; await onResponseContent; await testResponse("br"); await teardown(monitor); function testResponse(type) {
--- a/devtools/client/netmonitor/test/browser_net_clear.js +++ b/devtools/client/netmonitor/test/browser_net_clear.js @@ -8,17 +8,16 @@ */ add_task(async function() { let { tab, monitor } = await initNetMonitor(SIMPLE_URL); info("Starting test... "); let { document, store, windowRequire } = monitor.panelWin; let Actions = windowRequire("devtools/client/netmonitor/src/actions/index"); - let detailsPanelToggleButton = document.querySelector(".network-details-panel-toggle"); let clearButton = document.querySelector(".requests-list-clear-button"); store.dispatch(Actions.batchEnable(false)); // Make sure we start in a sane state assertNoRequestState(); // Load one request and assert it shows up in the list @@ -35,43 +34,39 @@ add_task(async function() { // Load a second request and make sure they still show up onMonitorUpdated = waitForAllRequestsFinished(monitor); tab.linkedBrowser.reload(); await onMonitorUpdated; assertSingleRequestState(); // Make sure we can now open the network details panel - EventUtils.sendMouseEvent({ type: "click" }, detailsPanelToggleButton); - - ok(document.querySelector(".network-details-panel") && + store.dispatch(Actions.toggleNetworkDetails()); + let detailsPanelToggleButton = document.querySelector(".sidebar-toggle"); + ok(detailsPanelToggleButton && !detailsPanelToggleButton.classList.contains("pane-collapsed"), - "The details pane should be visible after clicking the toggle button."); + "The details pane should be visible."); // Click clear and make sure the details pane closes EventUtils.sendMouseEvent({ type: "click" }, clearButton); assertNoRequestState(); ok(!document.querySelector(".network-details-panel"), "The details pane should not be visible clicking 'clear'."); return teardown(monitor); /** * Asserts the state of the network monitor when one request has loaded */ function assertSingleRequestState() { is(store.getState().requests.requests.size, 1, "The request menu should have one item at this point."); - is(detailsPanelToggleButton.hasAttribute("disabled"), false, - "The pane toggle button should be enabled after a request is made."); } /** * Asserts the state of the network monitor when no requests have loaded */ function assertNoRequestState() { is(store.getState().requests.requests.size, 0, "The request menu should be empty at this point."); - is(detailsPanelToggleButton.hasAttribute("disabled"), true, - "The pane toggle button should be disabled when the request menu is cleared."); } });
--- a/devtools/client/netmonitor/test/browser_net_json-b64.js +++ b/devtools/client/netmonitor/test/browser_net_json-b64.js @@ -16,18 +16,17 @@ add_task(async function() { let Actions = windowRequire("devtools/client/netmonitor/src/actions/index"); store.dispatch(Actions.batchEnable(false)); // Execute requests. await performRequests(monitor, tab, 1); wait = waitForDOM(document, "#response-panel .CodeMirror-code"); - EventUtils.sendMouseEvent({ type: "click" }, - document.querySelector(".network-details-panel-toggle")); + store.dispatch(Actions.toggleNetworkDetails()); EventUtils.sendMouseEvent({ type: "click" }, document.querySelector("#response-tab")); await wait; let tabpanel = document.querySelector("#response-panel"); is(tabpanel.querySelector(".response-error-header") === null, true, "The response error header doesn't have the intended visibility.");
--- a/devtools/client/netmonitor/test/browser_net_json-long.js +++ b/devtools/client/netmonitor/test/browser_net_json-long.js @@ -46,18 +46,17 @@ add_task(async function() { type: "json", fullMimeType: "text/json; charset=utf-8", size: L10N.getFormatStr("networkMenu.sizeKB", L10N.numberWithDecimals(85975 / 1024, 2)), time: true }); wait = waitForDOM(document, "#response-panel .CodeMirror-code"); - EventUtils.sendMouseEvent({ type: "click" }, - document.querySelector(".network-details-panel-toggle")); + store.dispatch(Actions.toggleNetworkDetails()); EventUtils.sendMouseEvent({ type: "click" }, document.querySelector("#response-tab")); await wait; testResponseTab(); await teardown(monitor);
--- a/devtools/client/netmonitor/test/browser_net_json-malformed.js +++ b/devtools/client/netmonitor/test/browser_net_json-malformed.js @@ -38,18 +38,17 @@ add_task(async function() { { status: 200, statusText: "OK", type: "json", fullMimeType: "text/json; charset=utf-8" }); wait = waitForDOM(document, "#response-panel .CodeMirror-code"); - EventUtils.sendMouseEvent({ type: "click" }, - document.querySelector(".network-details-panel-toggle")); + store.dispatch(Actions.toggleNetworkDetails()); EventUtils.sendMouseEvent({ type: "click" }, document.querySelector("#response-tab")); await wait; let tabpanel = document.querySelector("#response-panel"); is(tabpanel.querySelector(".response-error-header") === null, false, "The response error header doesn't have the intended visibility."); is(tabpanel.querySelector(".response-error-header").textContent,
--- a/devtools/client/netmonitor/test/browser_net_json-null.js +++ b/devtools/client/netmonitor/test/browser_net_json-null.js @@ -15,17 +15,22 @@ add_task(async function() { let { L10N } = windowRequire("devtools/client/netmonitor/src/utils/l10n"); let Actions = windowRequire("devtools/client/netmonitor/src/actions/index"); store.dispatch(Actions.batchEnable(false)); // Execute requests. await performRequests(monitor, tab, 1); - await openResponsePanel(); + let onReponsePanelReady = waitForDOM(document, "#response-panel .CodeMirror-code"); + store.dispatch(Actions.toggleNetworkDetails()); + EventUtils.sendMouseEvent({ type: "click" }, + document.querySelector("#response-tab")); + await onReponsePanelReady; + checkResponsePanelDisplaysJSON(); let tabpanel = document.querySelector("#response-panel"); is(tabpanel.querySelectorAll(".tree-section").length, 2, "There should be 2 tree sections displayed in this tabpanel."); is(tabpanel.querySelectorAll(".treeRow:not(.tree-section)").length, 1, "There should be 1 json properties displayed in this tabpanel."); is(tabpanel.querySelectorAll(".empty-notice").length, 0, @@ -52,22 +57,9 @@ add_task(async function() { let jsonView = panel.querySelector(".tree-section .treeLabel") || {}; is(jsonView.textContent === L10N.getStr("jsonScopeName"), true, "The response json view has the intended visibility."); is(panel.querySelector(".CodeMirror-code") === null, false, "The response editor has the intended visibility."); is(panel.querySelector(".response-image-box") === null, true, "The response image box doesn't have the intended visibility."); } - - /** - * Open the netmonitor details panel and switch to the response tab. - * Returns a promise that will resolve when the response panel DOM element is available. - */ - function openResponsePanel() { - let onReponsePanelReady = waitForDOM(document, "#response-panel .CodeMirror-code"); - EventUtils.sendMouseEvent({ type: "click" }, - document.querySelector(".network-details-panel-toggle")); - EventUtils.sendMouseEvent({ type: "click" }, - document.querySelector("#response-tab")); - return onReponsePanelReady; - } });
--- a/devtools/client/netmonitor/test/browser_net_json_custom_mime.js +++ b/devtools/client/netmonitor/test/browser_net_json_custom_mime.js @@ -40,18 +40,17 @@ add_task(async function() { statusText: "OK", type: "x-bigcorp-json", fullMimeType: "text/x-bigcorp-json; charset=utf-8", size: L10N.getFormatStrWithNumbers("networkMenu.sizeB", 41), time: true }); wait = waitForDOM(document, "#response-panel .CodeMirror-code"); - EventUtils.sendMouseEvent({ type: "click" }, - document.querySelector(".network-details-panel-toggle")); + store.dispatch(Actions.toggleNetworkDetails()); EventUtils.sendMouseEvent({ type: "click" }, document.querySelector("#response-tab")); await wait; testResponseTab(); await teardown(monitor);
--- a/devtools/client/netmonitor/test/browser_net_json_text_mime.js +++ b/devtools/client/netmonitor/test/browser_net_json_text_mime.js @@ -41,18 +41,17 @@ add_task(async function() { statusText: "OK", type: "plain", fullMimeType: "text/plain; charset=utf-8", size: L10N.getFormatStrWithNumbers("networkMenu.sizeB", 41), time: true }); wait = waitForDOM(document, "#response-panel .CodeMirror-code"); - EventUtils.sendMouseEvent({ type: "click" }, - document.querySelector(".network-details-panel-toggle")); + store.dispatch(Actions.toggleNetworkDetails()); EventUtils.sendMouseEvent({ type: "click" }, document.querySelector("#response-tab")); await wait; testResponseTab(); await teardown(monitor);
--- a/devtools/client/netmonitor/test/browser_net_jsonp.js +++ b/devtools/client/netmonitor/test/browser_net_jsonp.js @@ -59,18 +59,17 @@ add_task(async function() { type: "json", fullMimeType: "text/json; charset=utf-8", size: L10N.getFormatStrWithNumbers("networkMenu.sizeB", 54), time: true }); info("Testing first request"); wait = waitForDOM(document, "#response-panel .CodeMirror-code"); - EventUtils.sendMouseEvent({ type: "click" }, - document.querySelector(".network-details-panel-toggle")); + store.dispatch(Actions.toggleNetworkDetails()); EventUtils.sendMouseEvent({ type: "click" }, document.querySelector("#response-tab")); await wait; testResponseTab("$_0123Fun", "Hello JSONP!"); info("Testing second request"); wait = waitForDOM(document, "#response-panel .CodeMirror-code");
--- a/devtools/client/netmonitor/test/browser_net_large-response.js +++ b/devtools/client/netmonitor/test/browser_net_large-response.js @@ -45,18 +45,17 @@ add_task(async function() { "GET", CONTENT_TYPE_SJS + "?fmt=html-long", { status: 200, statusText: "OK" }); wait = waitForDOM(document, "#response-panel .CodeMirror-code"); - EventUtils.sendMouseEvent({ type: "click" }, - document.querySelector(".network-details-panel-toggle")); + store.dispatch(Actions.toggleNetworkDetails()); EventUtils.sendMouseEvent({ type: "click" }, document.querySelector("#response-tab")); await wait; let text = document.querySelector(".CodeMirror-line").textContent; ok(text.match(/^<p>/), "The text shown in the source editor is incorrect.");
--- a/devtools/client/netmonitor/test/browser_net_pane-collapse.js +++ b/devtools/client/netmonitor/test/browser_net_pane-collapse.js @@ -6,46 +6,47 @@ /** * Tests if the network monitor panes collapse properly. */ add_task(async function() { let { tab, monitor } = await initNetMonitor(SIMPLE_URL); info("Starting test... "); - let { document, windowRequire } = monitor.panelWin; + let { document, store, windowRequire } = monitor.panelWin; + let Actions = windowRequire("devtools/client/netmonitor/src/actions/index"); let { Prefs } = windowRequire("devtools/client/netmonitor/src/utils/prefs"); - let detailsPaneToggleButton = document.querySelector(".network-details-panel-toggle"); let wait = waitForNetworkEvents(monitor, 1); tab.linkedBrowser.reload(); await wait; ok(!document.querySelector(".network-details-panel") && - detailsPaneToggleButton.classList.contains("pane-collapsed"), + !document.querySelector(".sidebar-toggle"), "The details panel should initially be hidden."); - EventUtils.sendMouseEvent({ type: "click" }, detailsPaneToggleButton); + store.dispatch(Actions.toggleNetworkDetails()); is(~~(document.querySelector(".network-details-panel").clientWidth), Prefs.networkDetailsWidth, "The details panel has an incorrect width."); ok(document.querySelector(".network-details-panel") && - !detailsPaneToggleButton.classList.contains("pane-collapsed"), + document.querySelector(".sidebar-toggle"), "The details panel should at this point be visible."); - EventUtils.sendMouseEvent({ type: "click" }, detailsPaneToggleButton); + EventUtils.sendMouseEvent({ type: "click" }, + document.querySelector(".sidebar-toggle")); ok(!document.querySelector(".network-details-panel") && - detailsPaneToggleButton.classList.contains("pane-collapsed"), + !document.querySelector(".sidebar-toggle"), "The details panel should not be visible after collapsing."); - EventUtils.sendMouseEvent({ type: "click" }, detailsPaneToggleButton); + store.dispatch(Actions.toggleNetworkDetails()); is(~~(document.querySelector(".network-details-panel").clientWidth), Prefs.networkDetailsWidth, "The details panel has an incorrect width after uncollapsing."); ok(document.querySelector(".network-details-panel") && - !detailsPaneToggleButton.classList.contains("pane-collapsed"), + document.querySelector(".sidebar-toggle"), "The details panel should be visible again after uncollapsing."); await teardown(monitor); });
--- a/devtools/client/netmonitor/test/browser_net_pane-network-details.js +++ b/devtools/client/netmonitor/test/browser_net_pane-network-details.js @@ -40,88 +40,72 @@ add_task(async function() { info("Starting test... "); let wait = waitForNetworkEvents(monitor, 9); loadFrameScriptUtils(); await performRequestsInContent(REQUESTS_WITH_MEDIA_AND_FLASH_AND_WS); await wait; - let toggleButton = document.querySelector(".network-details-panel-toggle"); - info("Test with the first request in the list visible"); EventUtils.sendMouseEvent({ type: "click" }, - document.querySelector(".requests-list-filter-all-button")); + document.querySelector(".requests-list-filter-all-button")); testDetailsPanel(true, 0); info("Test with first request in the list not visible"); EventUtils.sendMouseEvent({ type: "click" }, - document.querySelector(".requests-list-filter-all-button")); + document.querySelector(".requests-list-filter-all-button")); EventUtils.sendMouseEvent({ type: "click" }, - document.querySelector(".requests-list-filter-js-button")); + document.querySelector(".requests-list-filter-js-button")); testFilterButtons(monitor, "js"); testDetailsPanel(true, 2); info("Test with no request in the list visible i.e. no request match the filters"); EventUtils.sendMouseEvent({ type: "click" }, - document.querySelector(".requests-list-filter-all-button")); + document.querySelector(".requests-list-filter-all-button")); setFreetextFilter("foobar"); // The network details panel should not open as there are no available requests visible testDetailsPanel(false); await teardown(monitor); function getSelectedIndex(state) { if (!state.requests.selectedId) { return -1; } return getSortedRequests(state).findIndex(r => r.id === state.requests.selectedId); } async function testDetailsPanel(shouldPanelOpen, selectedItemIndex = 0) { // Expected default state should be panel closed - if (shouldPanelOpen) { - // Toggle switch should be enabled only when there are visible requests - is(toggleButton.hasAttribute("disabled"), false, - "The pane toggle button should be enabled."); - } else { - is(toggleButton.hasAttribute("disabled"), true, - "The pane toggle button should be disabled."); - } - - is(toggleButton.classList.contains("pane-collapsed"), true, - "The pane toggle button should still indicate that the details pane is " + - "collapsed."); + ok(!document.querySelector(".sidebar-toggle"), + "The pane toggle button should not be visible."); is(!!document.querySelector(".network-details-panel"), false, - "The details pane should still be hidden."); + "The details pane should still be hidden."); is(getSelectedRequest(store.getState()), null, - "There should still be no selected item in the requests menu."); + "There should still be no selected item in the requests menu."); // Trigger the details panel toggle action - EventUtils.sendMouseEvent({ type: "click" }, toggleButton); + store.dispatch(Actions.toggleNetworkDetails()); + + let toggleButton = document.querySelector(".sidebar-toggle"); if (shouldPanelOpen) { - is(toggleButton.hasAttribute("disabled"), false, - "The pane toggle button should still be enabled after being pressed."); is(toggleButton.classList.contains("pane-collapsed"), false, - "The pane toggle button should now indicate that the details pane is " + - "not collapsed anymore after being pressed."); + "The pane toggle button should now indicate that the details pane is " + + "not collapsed anymore after being pressed."); is(!!document.querySelector(".network-details-panel"), true, - "The details pane should not be hidden after toggle button was pressed."); + "The details pane should not be hidden after toggle button was pressed."); isnot(getSelectedRequest(store.getState()), null, - "There should be a selected item in the requests menu."); + "There should be a selected item in the requests menu."); is(getSelectedIndex(store.getState()), selectedItemIndex, - `The item index ${selectedItemIndex} should be selected in the requests menu.`); + `The item index ${selectedItemIndex} should be selected in the requests menu.`); // Close the panel EventUtils.sendMouseEvent({ type: "click" }, toggleButton); } else { - is(toggleButton.hasAttribute("disabled"), true, - "The pane toggle button should be disabled."); - is(toggleButton.classList.contains("pane-collapsed"), true, - "The pane toggle button should still indicate that the details pane is " + - "collapsed."); + ok(!toggleButton, "The pane toggle button should be not visible."); is(!!document.querySelector(".network-details-panel"), false, - "The details pane should still be hidden."); + "The details pane should still be hidden."); is(getSelectedRequest(store.getState()), null, - "There should still be no selected item in the requests menu."); + "There should still be no selected item in the requests menu."); } } });
--- a/devtools/client/netmonitor/test/browser_net_pane-toggle.js +++ b/devtools/client/netmonitor/test/browser_net_pane-toggle.js @@ -16,63 +16,50 @@ add_task(async function() { let { EVENTS } = windowRequire("devtools/client/netmonitor/src/constants"); let { getSelectedRequest, getSortedRequests, } = windowRequire("devtools/client/netmonitor/src/selectors/index"); store.dispatch(Actions.batchEnable(false)); - let toggleButton = document.querySelector(".network-details-panel-toggle"); - - is(toggleButton.hasAttribute("disabled"), true, - "The pane toggle button should be disabled when the frontend is opened."); - is(toggleButton.classList.contains("pane-collapsed"), true, - "The pane toggle button should indicate that the details pane is " + - "collapsed when the frontend is opened."); + ok(!document.querySelector(".sidebar-toggle"), + "The pane toggle button should not be visible."); is(!!document.querySelector(".network-details-panel"), false, "The details pane should be hidden when the frontend is opened."); is(getSelectedRequest(store.getState()), null, "There should be no selected item in the requests menu."); let networkEvent = monitor.panelWin.once(EVENTS.NETWORK_EVENT); tab.linkedBrowser.reload(); await networkEvent; - is(toggleButton.hasAttribute("disabled"), false, - "The pane toggle button should be enabled after the first request."); - is(toggleButton.classList.contains("pane-collapsed"), true, - "The pane toggle button should still indicate that the details pane is " + - "collapsed after the first request."); + ok(!document.querySelector(".sidebar-toggle"), + "The pane toggle button should not be visible after the first request."); is(!!document.querySelector(".network-details-panel"), false, "The details pane should still be hidden after the first request."); is(getSelectedRequest(store.getState()), null, "There should still be no selected item in the requests menu."); - EventUtils.sendMouseEvent({ type: "click" }, toggleButton); + store.dispatch(Actions.toggleNetworkDetails()); - is(toggleButton.hasAttribute("disabled"), false, - "The pane toggle button should still be enabled after being pressed."); + let toggleButton = document.querySelector(".sidebar-toggle"); + is(toggleButton.classList.contains("pane-collapsed"), false, "The pane toggle button should now indicate that the details pane is " + - "not collapsed anymore after being pressed."); + "not collapsed anymore."); is(!!document.querySelector(".network-details-panel"), true, "The details pane should not be hidden after toggle button was pressed."); isnot(getSelectedRequest(store.getState()), null, "There should be a selected item in the requests menu."); is(getSelectedIndex(store.getState()), 0, "The first item should be selected in the requests menu."); EventUtils.sendMouseEvent({ type: "click" }, toggleButton); - is(toggleButton.hasAttribute("disabled"), false, - "The pane toggle button should still be enabled after being pressed again."); - is(toggleButton.classList.contains("pane-collapsed"), true, - "The pane toggle button should now indicate that the details pane is " + - "collapsed after being pressed again."); is(!!document.querySelector(".network-details-panel"), false, "The details pane should now be hidden after the toggle button was pressed again."); is(getSelectedRequest(store.getState()), null, "There should now be no selected item in the requests menu."); await teardown(monitor); function getSelectedIndex(state) {
--- a/devtools/client/netmonitor/test/browser_net_post-data-03.js +++ b/devtools/client/netmonitor/test/browser_net_post-data-03.js @@ -19,18 +19,17 @@ add_task(async function() { store.dispatch(Actions.batchEnable(false)); // Execute requests. await performRequests(monitor, tab, 1); // Wait for all tree view updated by react wait = waitForDOM(document, "#headers-panel .tree-section .treeLabel", 3); - EventUtils.sendMouseEvent({ type: "click" }, - document.querySelector(".network-details-panel-toggle")); + store.dispatch(Actions.toggleNetworkDetails()); EventUtils.sendMouseEvent({ type: "click" }, document.querySelector("#headers-tab")); await wait; let tabpanel = document.querySelector("#headers-panel"); is(tabpanel.querySelectorAll(".tree-section .treeLabel").length, 3, "There should be 3 header sections displayed in this tabpanel.");
--- a/devtools/client/netmonitor/test/browser_net_post-data-04.js +++ b/devtools/client/netmonitor/test/browser_net_post-data-04.js @@ -19,18 +19,17 @@ add_task(async function() { store.dispatch(Actions.batchEnable(false)); // Execute requests. await performRequests(monitor, tab, 1); // Wait for all tree view updated by react wait = waitForDOM(document, "#params-panel .tree-section"); - EventUtils.sendMouseEvent({ type: "click" }, - document.querySelector(".network-details-panel-toggle")); + store.dispatch(Actions.toggleNetworkDetails()); EventUtils.sendMouseEvent({ type: "click" }, document.querySelector("#params-tab")); await wait; let tabpanel = document.querySelector("#params-panel"); ok(tabpanel.querySelector(".treeTable"), "The request params doesn't have the indended visibility.");
--- a/devtools/client/netmonitor/test/browser_net_prefs-reload.js +++ b/devtools/client/netmonitor/test/browser_net_prefs-reload.js @@ -179,18 +179,17 @@ add_task(async function() { let newMonitor = await restartNetMonitor(monitor); monitor = newMonitor.monitor; let networkEvent = waitForNetworkEvents(monitor, 1); newMonitor.tab.linkedBrowser.reload(); await networkEvent; let wait = waitForDOM(getDoc(), ".network-details-panel"); - EventUtils.sendMouseEvent({ type: "click" }, - getDoc().querySelector(".network-details-panel-toggle")); + getStore().dispatch(Actions.toggleNetworkDetails()); await wait; } async function testBottom() { await restartNetMonitorAndSetupEnv(); info("Testing prefs reload for a bottom host."); storeFirstPrefValues();
--- a/devtools/client/netmonitor/test/browser_net_security-details.js +++ b/devtools/client/netmonitor/test/browser_net_security-details.js @@ -19,18 +19,17 @@ add_task(async function() { info("Performing a secure request."); const REQUESTS_URL = "https://example.com" + CORS_SJS_PATH; let wait = waitForNetworkEvents(monitor, 1); await ContentTask.spawn(tab.linkedBrowser, REQUESTS_URL, async function(url) { content.wrappedJSObject.performRequests(1, url); }); await wait; - EventUtils.sendMouseEvent({ type: "click" }, - document.querySelector(".network-details-panel-toggle")); + store.dispatch(Actions.toggleNetworkDetails()); EventUtils.sendMouseEvent({ type: "click" }, document.querySelector("#security-tab")); await waitUntil(() => document.querySelector( "#security-panel .security-info-value")); let tabpanel = document.querySelector("#security-panel"); let textboxes = tabpanel.querySelectorAll(".textbox-input");
--- a/devtools/client/netmonitor/test/browser_net_security-error.js +++ b/devtools/client/netmonitor/test/browser_net_security-error.js @@ -18,18 +18,17 @@ add_task(async function() { let requestsDone = waitForNetworkEvents(monitor, 1); await ContentTask.spawn(tab.linkedBrowser, {}, async function() { content.wrappedJSObject.performRequests(1, "https://nocert.example.com"); }); await requestsDone; let securityInfoLoaded = waitForDOM(document, ".security-info-value"); - EventUtils.sendMouseEvent({ type: "click" }, - document.querySelector(".network-details-panel-toggle")); + store.dispatch(Actions.toggleNetworkDetails()); await waitUntil(() => document.querySelector("#security-tab")); EventUtils.sendMouseEvent({ type: "click" }, document.querySelector("#security-tab")); await securityInfoLoaded; let errormsg = document.querySelector(".security-info-value"); isnot(errormsg.textContent, "", "Error message is not empty.");
--- a/devtools/client/netmonitor/test/browser_net_simple-request-details.js +++ b/devtools/client/netmonitor/test/browser_net_simple-request-details.js @@ -30,18 +30,17 @@ add_task(async function() { is(getSelectedRequest(store.getState()), undefined, "There shouldn't be any selected item in the requests menu."); is(store.getState().requests.requests.size, 1, "The requests menu should not be empty after the first request."); is(!!document.querySelector(".network-details-panel"), false, "The network details panel should still be hidden after first request."); - EventUtils.sendMouseEvent({ type: "click" }, - document.querySelector(".network-details-panel-toggle")); + store.dispatch(Actions.toggleNetworkDetails()); isnot(getSelectedRequest(store.getState()), undefined, "There should be a selected item in the requests menu."); is(getSelectedIndex(store.getState()), 0, "The first item should be selected in the requests menu."); is(!!document.querySelector(".network-details-panel"), true, "The network details panel should not be hidden after toggle button was pressed.");
--- a/devtools/client/netmonitor/test/browser_net_simple-request.js +++ b/devtools/client/netmonitor/test/browser_net_simple-request.js @@ -16,55 +16,43 @@ add_task(async function() { let { tab, monitor } = await initNetMonitor(SIMPLE_URL); info("Starting test... "); let { document, store, windowRequire } = monitor.panelWin; let Actions = windowRequire("devtools/client/netmonitor/src/actions/index"); store.dispatch(Actions.batchEnable(false)); - is(document.querySelector(".network-details-panel-toggle").hasAttribute("disabled"), - true, - "The pane toggle button should be disabled when the frontend is opened."); ok(document.querySelector(".request-list-empty-notice"), "An empty notice should be displayed when the frontend is opened."); is(store.getState().requests.requests.size, 0, "The requests menu should be empty when the frontend is opened."); is(!!document.querySelector(".network-details-panel"), false, "The network details panel should be hidden when the frontend is opened."); await reloadAndWait(); - is(document.querySelector(".network-details-panel-toggle").hasAttribute("disabled"), - false, - "The pane toggle button should be enabled after the first request."); ok(!document.querySelector(".request-list-empty-notice"), "The empty notice should be hidden after the first request."); is(store.getState().requests.requests.size, 1, "The requests menu should not be empty after the first request."); is(!!document.querySelector(".network-details-panel"), false, "The network details panel should still be hidden after the first request."); await reloadAndWait(); - is(document.querySelector(".network-details-panel-toggle").hasAttribute("disabled"), - false, - "The pane toggle button should be still be enabled after a reload."); ok(!document.querySelector(".request-list-empty-notice"), "The empty notice should be still hidden after a reload."); is(store.getState().requests.requests.size, 1, "The requests menu should not be empty after a reload."); is(!!document.querySelector(".network-details-panel"), false, "The network details panel should still be hidden after a reload."); store.dispatch(Actions.clearRequests()); - is(document.querySelector(".network-details-panel-toggle").hasAttribute("disabled"), - true, - "The pane toggle button should be disabled when after clear."); ok(document.querySelector(".request-list-empty-notice"), "An empty notice should be displayed again after clear."); is(store.getState().requests.requests.size, 0, "The requests menu should be empty after clear."); is(!!document.querySelector(".network-details-panel"), false, "The network details panel should still be hidden after clear."); return teardown(monitor);
--- a/devtools/client/netmonitor/test/browser_net_sort-01.js +++ b/devtools/client/netmonitor/test/browser_net_sort-01.js @@ -46,18 +46,17 @@ add_task(async function() { url: "sjs_sorting-test-server.sjs?index=3&" + Math.random(), method: "GET3" }]; let wait = waitForNetworkEvents(monitor, 5); await performRequestsInContent(requests); await wait; - EventUtils.sendMouseEvent({ type: "click" }, - document.querySelector(".network-details-panel-toggle")); + store.dispatch(Actions.toggleNetworkDetails()); isnot(getSelectedRequest(store.getState()), undefined, "There should be a selected item in the requests menu."); is(getSelectedIndex(store.getState()), 0, "The first item should be selected in the requests menu."); is(!!document.querySelector(".network-details-panel"), true, "The network details panel should be visible after toggle button was pressed.");
--- a/devtools/client/netmonitor/test/browser_net_sort-02.js +++ b/devtools/client/netmonitor/test/browser_net_sort-02.js @@ -46,18 +46,17 @@ add_task(async function() { url: "sjs_sorting-test-server.sjs?index=3&" + Math.random(), method: "GET3" }]; let wait = waitForNetworkEvents(monitor, 5); await performRequestsInContent(requests); await wait; - EventUtils.sendMouseEvent({ type: "click" }, - document.querySelector(".network-details-panel-toggle")); + store.dispatch(Actions.toggleNetworkDetails()); isnot(getSelectedRequest(store.getState()), undefined, "There should be a selected item in the requests menu."); is(getSelectedIndex(store.getState()), 0, "The first item should be selected in the requests menu."); is(!!document.querySelector(".network-details-panel"), true, "The network details panel should be visible after toggle button was pressed.");
--- a/devtools/client/netmonitor/test/browser_net_streaming-response.js +++ b/devtools/client/netmonitor/test/browser_net_streaming-response.js @@ -52,18 +52,17 @@ add_task(async function() { CONTENT_TYPE_SJS + "?fmt=" + fmt, { status: 200, statusText: "OK" }); }); wait = waitForDOM(document, "#response-panel"); - EventUtils.sendMouseEvent({ type: "click" }, - document.querySelector(".network-details-panel-toggle")); + store.dispatch(Actions.toggleNetworkDetails()); EventUtils.sendMouseEvent({ type: "click" }, document.querySelector("#response-tab")); await wait; store.dispatch(Actions.selectRequest(null)); await selectIndexAndWaitForSourceEditor(monitor, 0); // the hls-m3u8 part
--- a/devtools/client/shared/inplace-editor.js +++ b/devtools/client/shared/inplace-editor.js @@ -46,16 +46,24 @@ const MAX_POPUP_ENTRIES = 500; const FOCUS_FORWARD = focusManager.MOVEFOCUS_FORWARD; const FOCUS_BACKWARD = focusManager.MOVEFOCUS_BACKWARD; const WORD_REGEXP = /\w/; const isWordChar = function(str) { return str && WORD_REGEXP.test(str); }; +const GRID_PROPERTY_NAMES = ["grid-area", "grid-row", "grid-row-start", + "grid-row-end", "grid-column", "grid-column-start", + "grid-column-end"]; +const GRID_ROW_PROPERTY_NAMES = ["grid-area", "grid-row", "grid-row-start", + "grid-row-end"]; +const GRID_COL_PROPERTY_NAMES = ["grid-area", "grid-column", "grid-column-start", + "grid-column-end"]; + /** * Helper to check if the provided key matches one of the expected keys. * Keys will be prefixed with DOM_VK_ and should match a key in KeyCodes. * * @param {String} key * the key to check (can be a keyCode). * @param {...String} keys * list of possible keys allowed. @@ -126,16 +134,19 @@ function isKeyIn(key, ...keys) { * defaults to true * {Boolean} preserveTextStyles: If true, do not copy text-related styles * from `element` to the new input. * defaults to false * {Object} cssProperties: An instance of CSSProperties. * {Object} cssVariables: A Map object containing all CSS variables. * {Number} defaultIncrement: The value by which the input is incremented * or decremented by default (0.1 for properties like opacity and 1 by default) + * {Function} getGridLineNames: + * Will be called before offering autocomplete sugestions, if the property is + * a member of GRID_PROPERTY_NAMES. */ function editableField(options) { return editableItem(options, function(element, event) { if (!options.element.inplaceEditor) { new InplaceEditor(options, event); } }); } @@ -290,20 +301,16 @@ function InplaceEditor(options, event) { } this.input.focus(); if (typeof options.selectAll == "undefined" || options.selectAll) { this.input.select(); } - if (this.contentType == CONTENT_TYPES.CSS_VALUE && this.input.value == "") { - this._maybeSuggestCompletion(false); - } - this.input.addEventListener("blur", this._onBlur); this.input.addEventListener("keypress", this._onKeyPress); this.input.addEventListener("input", this._onInput); this.input.addEventListener("dblclick", this._stopEventPropagation); this.input.addEventListener("click", this._stopEventPropagation); this.input.addEventListener("mousedown", this._stopEventPropagation); this.input.addEventListener("contextmenu", this._onContextMenu); this.doc.defaultView.addEventListener("blur", this._onWindowBlur); @@ -316,16 +323,18 @@ function InplaceEditor(options, event) { this._updateSize(); EventEmitter.decorate(this); if (options.start) { options.start(this, event); } + + this._getGridNamesBeforeCompletion(options.getGridLineNames); } exports.InplaceEditor = InplaceEditor; InplaceEditor.CONTENT_TYPES = CONTENT_TYPES; InplaceEditor.prototype = { @@ -988,16 +997,35 @@ InplaceEditor.prototype = { this._acceptPopupSuggestion(); } else { this._apply(); this._clear(); } }, /** + * Before offering autocomplete, set this.gridLineNames as the line names + * of the current grid, if they exist. + * + * @param {Function} getGridLineNames + * A function which gets the line names of the current grid. + */ + _getGridNamesBeforeCompletion: async function(getGridLineNames) { + if (getGridLineNames && this.property && + GRID_PROPERTY_NAMES.includes(this.property.name)) { + this.gridLineNames = await getGridLineNames(); + } + + if (this.contentType == CONTENT_TYPES.CSS_VALUE && this.input && + this.input.value == "") { + this._maybeSuggestCompletion(false); + } + }, + + /** * Event handler called by the autocomplete popup when receiving a click * event. */ _onAutocompletePopupClick: function() { this._acceptPopupSuggestion(); }, _acceptPopupSuggestion: function() { @@ -1562,17 +1590,28 @@ InplaceEditor.prototype = { * Returns a list of CSS values valid for a provided property name to use for * the autocompletion. This method is overridden by tests in order to use * mocked suggestion lists. * * @param {String} propertyName * @return {Array} array of CSS property values (Strings) */ _getCSSValuesForPropertyName: function(propertyName) { - return this.cssProperties.getValues(propertyName); + let gridLineList = []; + if (this.gridLineNames) { + if (GRID_ROW_PROPERTY_NAMES.includes(this.property.name)) { + gridLineList.push(...this.gridLineNames.rows); + } + if (GRID_COL_PROPERTY_NAMES.includes(this.property.name)) { + gridLineList.push(...this.gridLineNames.cols); + } + } + // Must be alphabetically sorted before comparing the results with + // the user input, otherwise we will lose some results. + return gridLineList.concat(this.cssProperties.getValues(propertyName)).sort(); }, /** * Returns the list of all CSS variables to use for the autocompletion. * * @return {Array} array of CSS variable names (Strings) */ _getCSSVariableNames: function() {
--- a/devtools/client/shared/vendor/WASMPARSER_UPGRADING +++ b/devtools/client/shared/vendor/WASMPARSER_UPGRADING @@ -1,14 +1,14 @@ # wasmparser version -Current vesion is: 0.5.3 +Current vesion is: 0.6.0 # Upgrade process 1. Pull latest release from npm and extract WasmDis.js and WasmParser.js, e.g. ``` -curl https://registry.npmjs.org/wasmparser/-/wasmparser-0.5.3.tgz | tar -x --strip-components 2 package/dist/{WasmDis,WasmParser}.js +curl https://registry.npmjs.org/wasmparser/-/wasmparser-0.6.0.tgz | tar -x --strip-components 2 package/dist/{WasmDis,WasmParser}.js ``` 2. Remove reference to source maps (last line)
--- a/devtools/client/shared/vendor/WasmDis.js +++ b/devtools/client/shared/vendor/WasmDis.js @@ -1,9 +1,19 @@ "use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); Object.defineProperty(exports, "__esModule", { value: true }); /* Copyright 2016 Mozilla Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 @@ -976,8 +986,124 @@ var WasmDisassembler = /** @class */ (fu default: throw new Error("Expectected state: " + reader.state); } } }; return WasmDisassembler; }()); exports.WasmDisassembler = WasmDisassembler; +var UNKNOWN_FUNCTION_PREFIX = "unknown"; +var NameSectionNameResolver = /** @class */ (function (_super) { + __extends(NameSectionNameResolver, _super); + function NameSectionNameResolver(names) { + var _this = _super.call(this) || this; + _this._names = names; + return _this; + } + NameSectionNameResolver.prototype.getFunctionName = function (index, isImport, isRef) { + var name = this._names[index]; + if (!name) + return "$" + UNKNOWN_FUNCTION_PREFIX + index; + return isRef ? "$" + name : "$" + name + " (;" + index + ";)"; + }; + return NameSectionNameResolver; +}(DefaultNameResolver)); +var NameSectionReader = /** @class */ (function () { + function NameSectionReader() { + this._done = false; + this._functionsCount = 0; + this._functionImportsCount = 0; + this._functionNames = null; + this._hasNames = false; + } + NameSectionReader.prototype.read = function (reader) { + var _this = this; + if (this._done) + throw new Error('Invalid state: disassembly process was already finished.'); + while (true) { + if (!reader.read()) + return false; + switch (reader.state) { + case 2 /* END_WASM */: + if (!reader.hasMoreBytes()) { + this._done = true; + return true; + } + break; + case -1 /* ERROR */: + throw reader.error; + case 1 /* BEGIN_WASM */: + this._functionsCount = 0; + this._functionImportsCount = 0; + this._functionNames = []; + this._hasNames = false; + break; + case 4 /* END_SECTION */: + break; + case 3 /* BEGIN_SECTION */: + var sectionInfo = reader.result; + if (sectionInfo.id === 0 /* Custom */ && + WasmParser_1.bytesToString(sectionInfo.name) === "name") { + break; + } + if (sectionInfo.id === 3 /* Function */ || + sectionInfo.id === 2 /* Import */) { + break; + } + reader.skipSection(); + break; + case 12 /* IMPORT_SECTION_ENTRY */: + var importInfo = reader.result; + if (importInfo.kind === 0 /* Function */) + this._functionImportsCount++; + break; + case 13 /* FUNCTION_SECTION_ENTRY */: + this._functionsCount++; + break; + case 19 /* NAME_SECTION_ENTRY */: + var nameInfo = reader.result; + if (nameInfo.type !== 1 /* Function */) + break; + var functionNameInfo = nameInfo; + functionNameInfo.names.forEach(function (naming) { + _this._functionNames[naming.index] = WasmParser_1.bytesToString(naming.name); + }); + this._hasNames = true; + break; + default: + throw new Error("Expectected state: " + reader.state); + } + } + }; + NameSectionReader.prototype.hasValidNames = function () { + return this._hasNames; + }; + NameSectionReader.prototype.getNameResolver = function () { + if (!this.hasValidNames()) + throw new Error("Has no valid name section"); + // Fix bad names. + var functionNamesLength = this._functionImportsCount + this._functionsCount; + var functionNames = this._functionNames.slice(0, functionNamesLength); + var usedNameAt = Object.create(null); + for (var i = 0; i < functionNames.length; i++) { + var name_1 = functionNames[i]; + if (!name_1) + continue; + var goodName = !(name_1 in usedNameAt) && + !/[^0-9A-Za-z!#$%&'*+.:<=>?@^_`|~\/\-]/.test(name_1) && + name_1.indexOf(UNKNOWN_FUNCTION_PREFIX) !== 0; + if (!goodName) { + if (usedNameAt[name_1] >= 0) { + // Remove all non-unique names. + functionNames[usedNameAt[name_1]] = null; + usedNameAt[name_1] = -1; + } + functionNames[i] = null; + continue; + } + usedNameAt[name_1] = i; + } + return new NameSectionNameResolver(functionNames); + }; + return NameSectionReader; +}()); +exports.NameSectionReader = NameSectionReader;
--- a/devtools/server/actors/layout.js +++ b/devtools/server/actors/layout.js @@ -137,27 +137,30 @@ const LayoutActor = ActorClassWithSpec(l destroy() { Actor.prototype.destroy.call(this); this.tabActor = null; this.walker = null; }, /** - * Returns the flex container found by iterating on the given selected node. The current - * node can be a flex container or flex item. If it is a flex item, returns the parent - * flex container. Otherwise, return null if the current or parent node is not a flex - * container. + * Helper function for getCurrentGrid and getCurrentFlexbox. Returns the grid or + * flex container (whichever is requested) found by iterating on the given selected + * node. The current node can be a grid/flex container or grid/flex item. If it is a + * grid/flex item, returns the parent grid/flex container. Otherwise, returns null + * if the current or parent node is not a grid/flex container. * * @param {Node|NodeActor} node * The node to start iterating at. - * @return {FlexboxActor|Null} The FlexboxActor of the flex container of the give node. - * Otherwise, returns null. + * @param {String} type + * Can be "grid" or "flex", the display type we are searching for. + * @return {GridActor|FlexboxActor|Null} The GridActor or FlexboxActor of the + * grid/flex container of the give node. Otherwise, returns null. */ - getCurrentFlexbox(node) { + getCurrentDisplay(node, type) { if (isNodeDead(node)) { return null; } // Given node can either be a Node or a NodeActor. if (node.rawNode) { node = node.rawNode; } @@ -166,45 +169,80 @@ const LayoutActor = ActorClassWithSpec(l nodeFilterConstants.SHOW_ELEMENT); let currentNode = treeWalker.currentNode; let displayType = this.walker.getNode(currentNode).displayType; if (!displayType) { return null; } - // Check if the current node is a flex container. - if (displayType == "inline-flex" || displayType == "flex") { - return new FlexboxActor(this, treeWalker.currentNode); + if (type == "flex" && + (displayType == "inline-flex" || displayType == "flex")) { + return new FlexboxActor(this, currentNode); + } else if (type == "grid" && + (displayType == "inline-grid" || displayType == "grid")) { + return new GridActor(this, currentNode); } // Otherwise, check if this is a flex item or the parent node is a flex container. while ((currentNode = treeWalker.parentNode())) { if (!currentNode) { break; } displayType = this.walker.getNode(currentNode).displayType; - switch (displayType) { - case "inline-flex": - case "flex": - return new FlexboxActor(this, currentNode); - case "contents": - // Continue walking up the tree since the parent node is a content element. - continue; + if (type == "flex" && + (displayType == "inline-flex" || displayType == "flex")) { + return new FlexboxActor(this, currentNode); + } else if (type == "grid" && + (displayType == "inline-grid" || displayType == "grid")) { + return new GridActor(this, currentNode); + } else if (displayType == "contents") { + // Continue walking up the tree since the parent node is a content element. + continue; } break; } return null; }, /** + * Returns the grid container found by iterating on the given selected node. The current + * node can be a grid container or grid item. If it is a grid item, returns the parent + * grid container. Otherwise, return null if the current or parent node is not a grid + * container. + * + * @param {Node|NodeActor} node + * The node to start iterating at. + * @return {GridActor|Null} The GridActor of the grid container of the give node. + * Otherwise, returns null. + */ + getCurrentGrid(node) { + return this.getCurrentDisplay(node, "grid"); + }, + + /** + * Returns the flex container found by iterating on the given selected node. The current + * node can be a flex container or flex item. If it is a flex item, returns the parent + * flex container. Otherwise, return null if the current or parent node is not a flex + * container. + * + * @param {Node|NodeActor} node + * The node to start iterating at. + * @return {FlexboxActor|Null} The FlexboxActor of the flex container of the give node. + * Otherwise, returns null. + */ + getCurrentFlexbox(node) { + return this.getCurrentDisplay(node, "flex"); + }, + + /** * Returns an array of GridActor objects for all the grid elements contained in the * given root node. * * @param {Node|NodeActor} node * The root node for grid elements * @return {Array} An array of GridActor objects. */ getGrids(node) {
--- a/devtools/server/tests/mochitest/setup-in-parent.js +++ b/devtools/server/tests/mochitest/setup-in-parent.js @@ -1,12 +1,12 @@ "use strict"; -var {Ci} = require("chrome"); var Services = require("Services"); +var ChromeUtils = require("ChromeUtils"); exports.setupParent = function({mm, prefix}) { let args = [ - !!mm.QueryInterface(Ci.nsIMessageSender), + ChromeUtils.getClassName(mm) == "ChromeMessageSender", prefix ]; Services.obs.notifyObservers(null, "test:setupParent", JSON.stringify(args)); };
--- a/devtools/shared/specs/layout.js +++ b/devtools/shared/specs/layout.js @@ -26,16 +26,25 @@ const layoutSpec = generateActorSpec({ request: { node: Arg(0, "domnode"), }, response: { flexbox: RetVal("nullable:flexbox") } }, + getCurrentGrid: { + request: { + node: Arg(0, "domnode"), + }, + response: { + grid: RetVal("nullable:grid") + } + }, + getGrids: { request: { rootNode: Arg(0, "domnode") }, response: { grids: RetVal("array:grid") } },
--- a/dom/base/test/chrome/cpows_parent.xul +++ b/dom/base/test/chrome/cpows_parent.xul @@ -206,18 +206,16 @@ } let savedElement = null; function recvDomTest(message) { savedElement = message.objects.element; is(savedElement.QueryInterface(Ci.nsISupports), savedElement, "QI to nsISupports works"); - is(savedElement.QueryInterface(Ci.nsIDOMNode), savedElement, - "QI to a random (implemented) interface works"); function testNoInterface(savedElement, i) { try { savedElement.QueryInterface(i); ok(false, "should have thrown an exception"); } catch (e) { is(e.result, Cr.NS_ERROR_NO_INTERFACE, "threw the right exception"); }
--- a/dom/base/test/unit/test_isequalnode.js +++ b/dom/base/test/unit/test_isequalnode.js @@ -41,20 +41,20 @@ function test_isEqualNode_setAttribute() // NOTE: 0, 2 are whitespace var test1 = doc.getElementById("test_setAttribute"); var node1 = test1.childNodes.item(1); var node2 = test1.childNodes.item(3); check_eq_nodes(node1, node2); - el(node1).setAttribute("bar", "baz"); + node1.setAttribute("bar", "baz"); check_neq_nodes(node1, node2); - el(node2).setAttribute("bar", "baz"); + node2.setAttribute("bar", "baz"); check_eq_nodes(node1, node2); // the null namespace is equivalent to no namespace -- section 1.3.3 // (XML Namespaces) of DOM 3 Core node1.setAttributeNS(null, "quux", "17"); check_neq_nodes(node1, node2); @@ -80,17 +80,17 @@ function test_isEqualNode_setAttribute() } function test_isEqualNode_clones() { // tests all elements and attributes in the document var all_elts = doc.getElementsByTagName("*"); for (var i = 0; i < all_elts.length; i++) { - var elt = el(all_elts.item(i)); + var elt = all_elts.item(i); check_eq_nodes(elt, elt.cloneNode(true)); var attrs = elt.attributes; for (var j = 0; j < attrs.length; j++) { var attr = attrs.item(j); check_eq_nodes(attr, attr.cloneNode(true)); } @@ -381,22 +381,16 @@ function test_isEqualNode_wholeDoc() doc2.createTreeWalker(doc2, NodeFilter.SHOW_ALL, null); do { check_eq_nodes(tw1.currentNode, tw2.currentNode); tw1.nextNode(); } while(tw2.nextNode()); } -// UTILITY FUNCTIONS - -function n(node) { return node ? node.QueryInterface(nsIDOMNode) : null; } -function el(node) { return node ? node.QueryInterface(nsIDOMElement) : null; } - - // TESTING FUNCTIONS /** * Compares the first and third (zero-indexed) child nodes of the element * (typically to allow whitespace) referenced by parentId for isEqualNode * equality or inequality based on the value of areEqual. * * Note that this means that the contents of the element referenced by parentId
--- a/dom/bindings/BindingUtils.cpp +++ b/dom/bindings/BindingUtils.cpp @@ -741,17 +741,17 @@ DefineConstructor(JSContext* cx, JS::Han static JSObject* CreateInterfaceObject(JSContext* cx, JS::Handle<JSObject*> global, JS::Handle<JSObject*> constructorProto, const js::Class* constructorClass, unsigned ctorNargs, const NamedConstructor* namedConstructors, JS::Handle<JSObject*> proto, const NativeProperties* properties, const NativeProperties* chromeOnlyProperties, - const char* name, bool defineOnGlobal) + const char* name, bool isChrome, bool defineOnGlobal) { JS::Rooted<JSObject*> constructor(cx); MOZ_ASSERT(constructorProto); MOZ_ASSERT(constructorClass); constructor = JS_NewObjectWithGivenProto(cx, Jsvalify(constructorClass), constructorProto); if (!constructor) { return nullptr; @@ -778,16 +778,23 @@ CreateInterfaceObject(JSContext* cx, JS: JS::Rooted<jsid> hasInstanceId(cx, SYMBOL_TO_JSID(JS::GetWellKnownSymbol(cx, JS::SymbolCode::hasInstance))); if (!JS_DefineFunctionById(cx, constructor, hasInstanceId, InterfaceHasInstance, 1, // Flags match those of Function[Symbol.hasInstance] JSPROP_READONLY | JSPROP_PERMANENT)) { return nullptr; } + + if (isChrome && !JS_DefineFunction(cx, constructor, "isInstance", + InterfaceHasInstance, 1, + // Don't bother making it enumerable + 0)) { + return nullptr; + } } if (properties) { if (properties->HasStaticMethods() && !DefinePrefable(cx, constructor, properties->StaticMethods())) { return nullptr; } @@ -797,17 +804,17 @@ CreateInterfaceObject(JSContext* cx, JS: } if (properties->HasConstants() && !DefinePrefable(cx, constructor, properties->Constants())) { return nullptr; } } - if (chromeOnlyProperties) { + if (chromeOnlyProperties && isChrome) { if (chromeOnlyProperties->HasStaticMethods() && !DefinePrefable(cx, constructor, chromeOnlyProperties->StaticMethods())) { return nullptr; } if (chromeOnlyProperties->HasStaticAttributes() && !DefinePrefable(cx, constructor, @@ -978,21 +985,24 @@ CreateInterfaceObjects(JSContext* cx, JS "to cache it"); MOZ_ASSERT(bool(constructorClass) == bool(constructorCache), "If, and only if, there is an interface object we need to cache " "it"); MOZ_ASSERT(constructorProto || !constructorClass, "Must have a constructor proto if we plan to create a constructor " "object"); + bool isChrome = nsContentUtils::ThreadsafeIsSystemCaller(cx); + JS::Rooted<JSObject*> proto(cx); if (protoClass) { proto = CreateInterfacePrototypeObject(cx, global, protoProto, protoClass, - properties, chromeOnlyProperties, + properties, + isChrome ? chromeOnlyProperties : nullptr, unscopableNames, isGlobal); if (!proto) { return; } *protoCache = proto; } else { @@ -1000,16 +1010,17 @@ CreateInterfaceObjects(JSContext* cx, JS } JSObject* interface; if (constructorClass) { interface = CreateInterfaceObject(cx, global, constructorProto, constructorClass, ctorNargs, namedConstructors, proto, properties, chromeOnlyProperties, name, + isChrome, defineOnGlobal); if (!interface) { if (protoCache) { // If we fail we need to make sure to clear the value of protoCache we // set above. *protoCache = nullptr; } return; @@ -1743,16 +1754,36 @@ XrayResolveOwnProperty(JSContext* cx, JS if (id == GetJSIDByIndex(cx, XPCJSContext::IDX_PROTOTYPE)) { return nativePropertyHooks->mPrototypeID == prototypes::id::_ID_Count || ResolvePrototypeOrConstructor(cx, wrapper, obj, nativePropertyHooks->mPrototypeID, JSPROP_PERMANENT | JSPROP_READONLY, desc, cacheOnHolder); } + if (id == GetJSIDByIndex(cx, XPCJSContext::IDX_ISINSTANCE) && + DOMIfaceAndProtoJSClass::FromJSClass(js::GetObjectClass(obj))-> + wantsInterfaceHasInstance) { + cacheOnHolder = true; + JSNativeWrapper interfaceIsInstanceWrapper = { InterfaceIsInstance, + nullptr }; + JSObject* funObj = XrayCreateFunction(cx, wrapper, + interfaceIsInstanceWrapper, 1, id); + if (!funObj) { + return false; + } + + desc.value().setObject(*funObj); + desc.setAttributes(0); + desc.object().set(wrapper); + desc.setSetter(nullptr); + desc.setGetter(nullptr); + return true; + } + if (id == SYMBOL_TO_JSID(JS::GetWellKnownSymbol(cx, JS::SymbolCode::hasInstance)) && DOMIfaceAndProtoJSClass::FromJSClass(js::GetObjectClass(obj))-> wantsInterfaceHasInstance) { cacheOnHolder = true; JSNativeWrapper interfaceHasInstanceWrapper = { InterfaceHasInstance, nullptr }; JSObject* funObj = XrayCreateFunction(cx, wrapper, interfaceHasInstanceWrapper, 1, id); @@ -2495,43 +2526,63 @@ InterfaceHasInstance(JSContext* cx, int "Why do we have a hasInstance hook if we don't have a prototype " "ID?"); *bp = (domClass && domClass->mInterfaceChain[depth] == prototypeID); return true; } bool -InterfaceIsInstance(JSContext* cx, unsigned argc, JS::Value* vp, - prototypes::ID prototypeID, int depth) +InterfaceIsInstance(JSContext* cx, unsigned argc, JS::Value* vp) { JS::CallArgs args = JS::CallArgsFromVp(argc, vp); - if (MOZ_UNLIKELY(args.length() < 1)) { - nsPrintfCString message("%s.isInstance", - NamesOfInterfacesWithProtos(prototypeID)); - return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, message.get()); + + // If the thing we were passed is not an object, return false. + if (!args.get(0).isObject()) { + args.rval().setBoolean(false); + return true; + } + + // If "this" isn't a DOM constructor or is a constructor for an interface + // without a prototype, return false. + if (!args.thisv().isObject()) { + args.rval().setBoolean(false); + return true; } - if (!args[0].isObject()) { - nsPrintfCString message("Argument 1 of %s.isInstance", - NamesOfInterfacesWithProtos(prototypeID)); - return ThrowErrorMessage(cx, MSG_NOT_OBJECT, message.get()); + JS::Rooted<JSObject*> thisObj(cx, js::CheckedUnwrap(&args.thisv().toObject())); + if (!thisObj) { + args.rval().setBoolean(false); + return true; + } + + const js::Class* thisClass = js::GetObjectClass(thisObj); + if (!IsDOMIfaceAndProtoClass(thisClass)) { + args.rval().setBoolean(false); + return true; + } + + const DOMIfaceAndProtoJSClass* clasp = + DOMIfaceAndProtoJSClass::FromJSClass(thisClass); + + if (clasp->mType != eInterface || + clasp->mPrototypeID == prototypes::id::_ID_Count) { + args.rval().setBoolean(false); + return true; } JS::Rooted<JSObject*> instance(cx, &args[0].toObject()); - const DOMJSClass* domClass = GetDOMClass(js::UncheckedUnwrap(instance, /* stopAtWindowProxy = */ false)); - if (domClass && domClass->mInterfaceChain[depth] == prototypeID) { - args.rval().setBoolean(true); - return true; - } - - args.rval().setBoolean(false); + bool isInstance = + domClass && + domClass->mInterfaceChain[clasp->mDepth] == clasp->mPrototypeID; + + args.rval().setBoolean(isInstance); return true; } bool ReportLenientThisUnwrappingFailure(JSContext* cx, JSObject* obj) { JS::Rooted<JSObject*> rootedObj(cx, obj); GlobalObject global(cx, rootedObj);
--- a/dom/bindings/BindingUtils.h +++ b/dom/bindings/BindingUtils.h @@ -2704,18 +2704,17 @@ InterfaceHasInstance(JSContext* cx, unsi bool InterfaceHasInstance(JSContext* cx, int prototypeID, int depth, JS::Handle<JSObject*> instance, bool* bp); // Used to implement the cross-context <Interface>.isInstance static method. bool -InterfaceIsInstance(JSContext* cx, unsigned argc, JS::Value* vp, - prototypes::ID prototypeID, int depth); +InterfaceIsInstance(JSContext* cx, unsigned argc, JS::Value* vp); // Helper for lenient getters/setters to report to console. If this // returns false, we couldn't even get a global. bool ReportLenientThisUnwrappingFailure(JSContext* cx, JSObject* obj); // Given a JSObject* that represents the chrome side of a JS-implemented WebIDL // interface, get the nsIGlobalObject corresponding to the content side, if any.
--- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -1767,33 +1767,16 @@ class CGClassObjectMovedHook(CGAbstractC def JSNativeArguments(): return [Argument('JSContext*', 'cx'), Argument('unsigned', 'argc'), Argument('JS::Value*', 'vp')] -class CGIsInstanceMethod(CGAbstractStaticMethod): - """ - A class for generating the static isInstance method. - """ - def __init__(self, descriptor): - assert descriptor.interface.hasInterfacePrototypeObject() - CGAbstractStaticMethod.__init__(self, descriptor, "isInstance", "bool", - JSNativeArguments()) - - def definition_body(self): - return fill( - """ - return InterfaceIsInstance(cx, argc, vp, prototypes::id::${name}, - PrototypeTraits<prototypes::id::${name}>::Depth); - """, - name=self.descriptor.name) - class CGClassConstructor(CGAbstractStaticMethod): """ JS-visible constructor for our objects """ def __init__(self, descriptor, ctor, name=CONSTRUCT_HOOK_NAME): CGAbstractStaticMethod.__init__(self, descriptor, name, 'bool', JSNativeArguments()) self._ctor = ctor @@ -2331,28 +2314,16 @@ class MethodDefiner(PropertyDefiner): if m.isStatic(): method["nativeName"] = CppKeywords.checkMethodName(IDLToCIdentifier(m.identifier.name)) if isChromeOnly(m): self.chrome.append(method) else: self.regular.append(method) - # Generate the isInstance static method. - if (static and - (self.descriptor.interface.hasInterfaceObject() and - self.descriptor.interface.hasInterfacePrototypeObject())): - self.chrome.append({ - "name": "isInstance", - "methodInfo": False, - "length": 1, - "flags": "JSPROP_ENUMERATE", - "condition": MemberCondition(), - }) - # TODO: Once iterable is implemented, use tiebreak rules instead of # failing. Also, may be more tiebreak rules to implement once spec bug # is resolved. # https://www.w3.org/Bugs/Public/show_bug.cgi?id=28592 def hasIterator(methods, regular): return (any("@@iterator" in m.aliases for m in methods) or any("@@iterator" == r["name"] for r in regular)) @@ -2727,17 +2698,16 @@ class ConstDefiner(PropertyDefiner): lambda fields: ' { "%s", %s }' % fields, ' { 0, JS::UndefinedValue() }', 'ConstantSpec', PropertyDefiner.getControllingCondition, specData) class PropertyArrays(): def __init__(self, descriptor): - self.descriptor = descriptor self.staticMethods = MethodDefiner(descriptor, "StaticMethods", static=True) self.staticAttrs = AttrDefiner(descriptor, "StaticAttributes", static=True) self.methods = MethodDefiner(descriptor, "Methods", static=False) self.attrs = AttrDefiner(descriptor, "Attributes", static=False) self.unforgeableMethods = MethodDefiner(descriptor, "UnforgeableMethods", static=False, unforgeable=True) @@ -2746,21 +2716,17 @@ class PropertyArrays(): self.consts = ConstDefiner(descriptor, "Constants") @staticmethod def arrayNames(): return ["staticMethods", "staticAttrs", "methods", "attrs", "unforgeableMethods", "unforgeableAttrs", "consts"] def hasChromeOnly(self): - # All interfaces that generate an interface object and interface - # prototype object have a chrome only isInstance static method. - return ((self.staticMethods.descriptor.interface.hasInterfaceObject() and - self.staticMethods.descriptor.interface.hasInterfacePrototypeObject()) or - any(getattr(self, a).hasChromeOnly() for a in self.arrayNames())) + return any(getattr(self, a).hasChromeOnly() for a in self.arrayNames()) def hasNonChromeOnly(self): return any(getattr(self, a).hasNonChromeOnly() for a in self.arrayNames()) def __str__(self): define = "" for array in self.arrayNames(): define += str(getattr(self, array)) @@ -3074,17 +3040,17 @@ class CGCreateInterfaceObjectsMethod(CGA constructorProto = "nullptr" isGlobal = self.descriptor.isGlobal() is not None if self.properties.hasNonChromeOnly(): properties = "sNativeProperties.Upcast()" else: properties = "nullptr" if self.properties.hasChromeOnly(): - chromeProperties = "nsContentUtils::ThreadsafeIsSystemCaller(aCx) ? sChromeOnlyNativeProperties.Upcast() : nullptr" + chromeProperties = "sChromeOnlyNativeProperties.Upcast()" else: chromeProperties = "nullptr" call = fill( """ JS::Heap<JSObject*>* protoCache = ${protoCache}; JS::Heap<JSObject*>* interfaceCache = ${interfaceCache}; dom::CreateInterfaceObjects(aCx, aGlobal, ${parentProto}, @@ -12316,19 +12282,16 @@ class CGDescriptor(CGThing): toBindingNamespace(descriptor.parentPrototypeName))) jsonifierMethod = None crossOriginMethods, crossOriginGetters, crossOriginSetters = set(), set(), set() unscopableNames = list() for n in descriptor.interface.namedConstructors: cgThings.append(CGClassConstructor(descriptor, n, NamedConstructorName(n))) - if (descriptor.interface.hasInterfaceObject() and - descriptor.interface.hasInterfacePrototypeObject()): - cgThings.append(CGIsInstanceMethod(descriptor)) for m in descriptor.interface.members: if m.isMethod() and m.identifier.name == 'QueryInterface': continue props = memberProperties(m, descriptor) if m.isMethod(): if m.getExtendedAttribute("Unscopable"): @@ -13864,23 +13827,19 @@ class CGBindingRoot(CGThing): return (any(isChromeOnly(a) or needsContainsHack(a) or needsCallerType(a) for a in desc.interface.members) or desc.interface.getExtendedAttribute("ChromeOnly") is not None or # JS-implemented interfaces with an interface object get a # chromeonly _create method. And interfaces with an # interface object might have a ChromeOnly constructor. - # Also interfaces whose interface prototype object is - # generated (which is most of them) for the isInstance - # method. (desc.interface.hasInterfaceObject() and (desc.interface.isJSImplemented() or - (ctor and isChromeOnly(ctor)) or - desc.interface.hasInterfacePrototypeObject())) or + (ctor and isChromeOnly(ctor)))) or # JS-implemented interfaces with clearable cached # attrs have chromeonly _clearFoo methods. (desc.interface.isJSImplemented() and any(clearableCachedAttrs(desc)))) # XXXkhuey ugly hack but this is going away soon. bindingHeaders['xpcprivate.h'] = webIDLFile.endswith("EventTarget.webidl")
--- a/dom/events/EventListenerManager.cpp +++ b/dom/events/EventListenerManager.cpp @@ -17,16 +17,17 @@ #include "mozilla/JSEventHandler.h" #include "mozilla/Maybe.h" #include "mozilla/MemoryReporting.h" #include "mozilla/Preferences.h" #include "mozilla/dom/BindingUtils.h" #include "mozilla/dom/Element.h" #include "mozilla/dom/Event.h" #include "mozilla/dom/EventTargetBinding.h" +#include "mozilla/dom/ScriptSettings.h" #include "mozilla/dom/TouchEvent.h" #include "mozilla/TimelineConsumers.h" #include "mozilla/EventTimelineMarker.h" #include "mozilla/TimeStamp.h" #include "EventListenerService.h" #include "GeckoProfiler.h" #include "nsCOMArray.h" @@ -287,24 +288,21 @@ EventListenerManager::AddEventListenerIn listener->mFlags = aFlags; listener->mListenerIsHandler = aHandler; listener->mHandlerIsString = false; listener->mAllEvents = aAllEvents; listener->mIsChrome = mIsMainThreadELM && nsContentUtils::LegacyIsCallerChromeOrNativeCode(); // Detect the type of event listener. - nsCOMPtr<nsIXPConnectWrappedJS> wjs; if (aFlags.mListenerIsJSListener) { MOZ_ASSERT(!aListenerHolder.HasWebIDLCallback()); listener->mListenerType = Listener::eJSEventListener; } else if (aListenerHolder.HasWebIDLCallback()) { listener->mListenerType = Listener::eWebIDLListener; - } else if ((wjs = do_QueryInterface(aListenerHolder.GetXPCOMCallback()))) { - listener->mListenerType = Listener::eWrappedJSListener; } else { listener->mListenerType = Listener::eNativeListener; } listener->mListener = Move(aListenerHolder); if (aFlags.mInSystemGroup) { mMayHaveSystemGroupListeners = true; @@ -1567,26 +1565,38 @@ EventListenerManager::GetListenerInfo(ns nsAutoString eventType; if (listener.mAllEvents) { eventType.SetIsVoid(true); } else if (listener.mListenerType == Listener::eNoListener) { continue; } else { eventType.Assign(Substring(nsDependentAtomString(listener.mTypeAtom), 2)); } - nsCOMPtr<nsIDOMEventListener> callback = listener.mListener.ToXPCOMCallback(); - if (!callback) { - // This will be null for cross-compartment event listeners which have been - // destroyed. - continue; + + JS::Rooted<JSObject*> callback(RootingCx()); + if (JSEventHandler* handler = listener.GetJSEventHandler()) { + if (handler->GetTypedEventHandler().HasEventHandler()) { + callback = handler->GetTypedEventHandler().Ptr()->CallableOrNull(); + if (!callback) { + // This will be null for cross-compartment event listeners + // which have been destroyed. + continue; + } + } + } else if (listener.mListenerType == Listener::eWebIDLListener) { + callback = listener.mListener.GetWebIDLCallback()->CallbackOrNull(); + if (!callback) { + // This will be null for cross-compartment event listeners + // which have been destroyed. + continue; + } } - // EventListenerInfo is defined in XPCOM, so we have to go ahead - // and convert to an XPCOM callback here... + RefPtr<EventListenerInfo> info = - new EventListenerInfo(eventType, callback.forget(), + new EventListenerInfo(eventType, callback, listener.mFlags.mCapture, listener.mFlags.mAllowUntrustedEvents, listener.mFlags.mInSystemGroup); aList->AppendElement(info.forget()); } return NS_OK; } @@ -1710,18 +1720,16 @@ EventListenerManager::MarkForCC() const Listener& listener = mListeners.ElementAt(i); JSEventHandler* jsEventHandler = listener.GetJSEventHandler(); if (jsEventHandler) { const TypedEventHandler& typedHandler = jsEventHandler->GetTypedEventHandler(); if (typedHandler.HasEventHandler()) { typedHandler.Ptr()->MarkForCC(); } - } else if (listener.mListenerType == Listener::eWrappedJSListener) { - xpc_TryUnmarkWrappedGrayObject(listener.mListener.GetXPCOMCallback()); } else if (listener.mListenerType == Listener::eWebIDLListener) { listener.mListener.GetWebIDLCallback()->MarkForCC(); } } if (mRefCnt.IsPurple()) { mRefCnt.RemovePurple(); } }
--- a/dom/events/EventListenerManager.h +++ b/dom/events/EventListenerManager.h @@ -184,20 +184,23 @@ public: { EventListenerHolder mListener; RefPtr<nsAtom> mTypeAtom; // for the main thread nsString mTypeString; // for non-main-threads EventMessage mEventMessage; enum ListenerType : uint8_t { + // No listener. eNoListener, + // A generic C++ implementation of nsIDOMEventListener. eNativeListener, + // An event handler attribute using JSEventHandler. eJSEventListener, - eWrappedJSListener, + // A scripted EventListener. eWebIDLListener, }; ListenerType mListenerType; bool mListenerIsHandler : 1; bool mHandlerIsString : 1; bool mAllEvents : 1; bool mIsChrome : 1;
--- a/dom/events/EventListenerService.cpp +++ b/dom/events/EventListenerService.cpp @@ -75,17 +75,47 @@ EventListenerChange::GetCountOfEventList return NS_OK; } /****************************************************************************** * mozilla::EventListenerInfo ******************************************************************************/ -NS_IMPL_CYCLE_COLLECTION(EventListenerInfo, mListener) +EventListenerInfo::EventListenerInfo(const nsAString& aType, + JS::Handle<JSObject*> aScriptedListener, + bool aCapturing, + bool aAllowsUntrusted, + bool aInSystemEventGroup) + : mType(aType) + , mScriptedListener(aScriptedListener) + , mCapturing(aCapturing) + , mAllowsUntrusted(aAllowsUntrusted) + , mInSystemEventGroup(aInSystemEventGroup) +{ + HoldJSObjects(this); +} + +EventListenerInfo::~EventListenerInfo() +{ + DropJSObjects(this); +} + +NS_IMPL_CYCLE_COLLECTION_CLASS(EventListenerInfo) + +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(EventListenerInfo) +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END + +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(EventListenerInfo) + tmp->mScriptedListener = nullptr; +NS_IMPL_CYCLE_COLLECTION_UNLINK_END + +NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(EventListenerInfo) + NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mScriptedListener) +NS_IMPL_CYCLE_COLLECTION_TRACE_END NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(EventListenerInfo) NS_INTERFACE_MAP_ENTRY(nsIEventListenerInfo) NS_INTERFACE_MAP_ENTRY(nsISupports) NS_INTERFACE_MAP_END NS_IMPL_CYCLE_COLLECTING_ADDREF(EventListenerInfo) NS_IMPL_CYCLE_COLLECTING_RELEASE(EventListenerInfo) @@ -133,38 +163,23 @@ EventListenerInfo::GetListenerObject(JSC NS_IMPL_ISUPPORTS(EventListenerService, nsIEventListenerService) bool EventListenerInfo::GetJSVal(JSContext* aCx, Maybe<JSAutoCompartment>& aAc, JS::MutableHandle<JS::Value> aJSVal) { - aJSVal.setNull(); - nsCOMPtr<nsIXPConnectWrappedJS> wrappedJS = do_QueryInterface(mListener); - if (wrappedJS) { - JS::Rooted<JSObject*> object(aCx, wrappedJS->GetJSObject()); - if (!object) { - return false; - } - aAc.emplace(aCx, object); - aJSVal.setObject(*object); + if (mScriptedListener) { + aJSVal.setObject(*mScriptedListener); + aAc.emplace(aCx, mScriptedListener); return true; } - nsCOMPtr<JSEventHandler> jsHandler = do_QueryInterface(mListener); - if (jsHandler && jsHandler->GetTypedEventHandler().HasEventHandler()) { - JS::Handle<JSObject*> handler = - jsHandler->GetTypedEventHandler().Ptr()->CallableOrNull(); - if (handler) { - aAc.emplace(aCx, handler); - aJSVal.setObject(*handler); - return true; - } - } + aJSVal.setNull(); return false; } NS_IMETHODIMP EventListenerInfo::ToSource(nsAString& aResult) { aResult.SetIsVoid(true);
--- a/dom/events/EventListenerService.h +++ b/dom/events/EventListenerService.h @@ -43,42 +43,34 @@ protected: nsCOMPtr<dom::EventTarget> mTarget; nsTArray<RefPtr<nsAtom>> mChangedListenerNames; }; class EventListenerInfo final : public nsIEventListenerInfo { public: EventListenerInfo(const nsAString& aType, - already_AddRefed<nsIDOMEventListener> aListener, + JS::Handle<JSObject*> aScriptedListener, bool aCapturing, bool aAllowsUntrusted, - bool aInSystemEventGroup) - : mType(aType) - , mListener(aListener) - , mCapturing(aCapturing) - , mAllowsUntrusted(aAllowsUntrusted) - , mInSystemEventGroup(aInSystemEventGroup) - { - } + bool aInSystemEventGroup); NS_DECL_CYCLE_COLLECTING_ISUPPORTS - NS_DECL_CYCLE_COLLECTION_CLASS(EventListenerInfo) + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(EventListenerInfo) NS_DECL_NSIEVENTLISTENERINFO protected: - virtual ~EventListenerInfo() {} + virtual ~EventListenerInfo(); bool GetJSVal(JSContext* aCx, Maybe<JSAutoCompartment>& aAc, JS::MutableHandle<JS::Value> aJSVal); nsString mType; - // nsReftPtr because that is what nsListenerStruct uses too. - RefPtr<nsIDOMEventListener> mListener; + JS::Heap<JSObject*> mScriptedListener; // May be null. bool mCapturing; bool mAllowsUntrusted; bool mInSystemEventGroup; }; class EventListenerService final : public nsIEventListenerService { ~EventListenerService();
--- a/dom/interfaces/events/nsIDOMEventListener.idl +++ b/dom/interfaces/events/nsIDOMEventListener.idl @@ -8,17 +8,17 @@ /** * The nsIDOMEventListener interface is a callback interface for * listening to events in the Document Object Model. * * For more information on this interface please see * http://www.w3.org/TR/DOM-Level-2-Events/ */ -[scriptable, function, uuid(df31c120-ded6-11d1-bd85-00805f8ae3f4)] +[uuid(df31c120-ded6-11d1-bd85-00805f8ae3f4)] interface nsIDOMEventListener : nsISupports { /** * This method is called whenever an event occurs of the type for which * the EventListener interface was registered. * * @param evt The Event contains contextual information about the * event. It also contains the stopPropagation and
--- a/dom/webidl/LegacyQueryInterface.webidl +++ b/dom/webidl/LegacyQueryInterface.webidl @@ -12,29 +12,19 @@ interface IID; // that are exposed in workers. Exposed=(Window,Worker,System)] interface LegacyQueryInterface { // Legacy QueryInterface, only exposed to chrome code on the main thread. [Exposed=(Window,System), ChromeOnly] nsISupports QueryInterface(IID iid); }; -Attr implements LegacyQueryInterface; BoxObject implements LegacyQueryInterface; -ChildProcessMessageManager implements LegacyQueryInterface; -ChromeMessageBroadcaster implements LegacyQueryInterface; -ChromeMessageSender implements LegacyQueryInterface; -Comment implements LegacyQueryInterface; -ContentFrameMessageManager implements LegacyQueryInterface; -ContentProcessMessageManager implements LegacyQueryInterface; DOMParser implements LegacyQueryInterface; Document implements LegacyQueryInterface; DocumentFragment implements LegacyQueryInterface; -DocumentType implements LegacyQueryInterface; Element implements LegacyQueryInterface; Event implements LegacyQueryInterface; -ProcessingInstruction implements LegacyQueryInterface; Selection implements LegacyQueryInterface; -Text implements LegacyQueryInterface; TreeColumns implements LegacyQueryInterface; TreeContentView implements LegacyQueryInterface; Window implements LegacyQueryInterface; XMLHttpRequest implements LegacyQueryInterface;
--- a/gfx/layers/ipc/CompositorBridgeParent.cpp +++ b/gfx/layers/ipc/CompositorBridgeParent.cpp @@ -550,32 +550,32 @@ mozilla::ipc::IPCResult CompositorBridgeParent::RecvWaitOnTransactionProcessed() { return IPC_OK(); } mozilla::ipc::IPCResult CompositorBridgeParent::RecvFlushRendering() { - if (mOptions.UseWebRender()) { + if (mWrBridge) { mWrBridge->FlushRendering(); return IPC_OK(); } if (mCompositorScheduler->NeedsComposite()) { CancelCurrentCompositeTask(); ForceComposeToTarget(nullptr); } return IPC_OK(); } mozilla::ipc::IPCResult CompositorBridgeParent::RecvFlushRenderingAsync() { - if (mOptions.UseWebRender()) { + if (mWrBridge) { mWrBridge->FlushRenderingAsync(); return IPC_OK(); } return RecvFlushRendering(); } mozilla::ipc::IPCResult @@ -693,19 +693,19 @@ CompositorBridgeParent::PauseComposition MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread(), "PauseComposition() can only be called on the compositor thread"); MonitorAutoLock lock(mPauseCompositionMonitor); if (!mPaused) { mPaused = true; - if (!mOptions.UseWebRender()) { + if (mCompositor) { mCompositor->Pause(); - } else { + } else if (mWrBridge) { mWrBridge->Pause(); } TimeStamp now = TimeStamp::Now(); DidComposite(now, now); } // if anyone's waiting to make sure that composition really got paused, tell them lock.NotifyAll();
--- a/js/xpconnect/src/XPCJSRuntime.cpp +++ b/js/xpconnect/src/XPCJSRuntime.cpp @@ -101,17 +101,18 @@ const char* const XPCJSRuntime::mStrings "undefined", // IDX_UNDEFINED "", // IDX_EMPTYSTRING "fileName", // IDX_FILENAME "lineNumber", // IDX_LINENUMBER "columnNumber", // IDX_COLUMNNUMBER "stack", // IDX_STACK "message", // IDX_MESSAGE "lastIndex", // IDX_LASTINDEX - "then" // IDX_THEN + "then", // IDX_THEN + "isInstance", // IDX_ISINSTANCE }; /***************************************************************************/ // *Some* NativeSets are referenced from mClassInfo2NativeSetMap. // *All* NativeSets are referenced from mNativeSetMap. // So, in mClassInfo2NativeSetMap we just clear references to the unmarked. // In mNativeSetMap we clear the references to the unmarked *and* delete them.
--- a/js/xpconnect/src/xpcprivate.h +++ b/js/xpconnect/src/xpcprivate.h @@ -457,16 +457,17 @@ public: IDX_EMPTYSTRING , IDX_FILENAME , IDX_LINENUMBER , IDX_COLUMNNUMBER , IDX_STACK , IDX_MESSAGE , IDX_LASTINDEX , IDX_THEN , + IDX_ISINSTANCE , IDX_TOTAL_COUNT // just a count of the above }; inline JS::HandleId GetStringID(unsigned index) const; inline const char* GetStringName(unsigned index) const; ShortLivedStringBuffer<nsString> mScratchStrings; ShortLivedStringBuffer<nsCString> mScratchCStrings;
--- a/js/xpconnect/tests/unit/test_xpcomutils.js +++ b/js/xpconnect/tests/unit/test_xpcomutils.js @@ -14,32 +14,32 @@ ChromeUtils.import("resource://gre/modul //////////////////////////////////////////////////////////////////////////////// //// Tests add_test(function test_generateQI_string_names() { var x = { QueryInterface: XPCOMUtils.generateQI([ Ci.nsIClassInfo, - "nsIDOMNode" + "nsIObserver" ]) }; try { x.QueryInterface(Ci.nsIClassInfo); } catch(e) { do_throw("Should QI to nsIClassInfo"); } try { - x.QueryInterface(Ci.nsIDOMNode); + x.QueryInterface(Ci.nsIObserver); } catch(e) { - do_throw("Should QI to nsIDOMNode"); + do_throw("Should QI to nsIObserver"); } try { - x.QueryInterface(Ci.nsIDOMDocument); + x.QueryInterface(Ci.nsIObserverService); do_throw("QI should not have succeeded!"); } catch(e) {} run_next_test(); }); add_test(function test_generateCI() {
--- a/media/libaom/moz.build +++ b/media/libaom/moz.build @@ -39,16 +39,17 @@ elif CONFIG['CPU_ARCH'] == 'x86': if CONFIG['CC_TYPE'] == 'gcc': ASFLAGS += [ '-I%s/media/libaom/config/win/mingw32/' % TOPSRCDIR ] LOCAL_INCLUDES += [ '/media/libaom/config/win/mingw32/' ] EXPORTS.aom += [ 'config/win/mingw32/aom_config.h' ] else: ASFLAGS += [ '-I%s/media/libaom/config/win/ia32/' % TOPSRCDIR ] LOCAL_INCLUDES += [ '/media/libaom/config/win/ia32/' ] EXPORTS.aom += [ 'config/win/ia32/aom_config.h' ] + NO_PGO = True # Compiler OOMs, bug 1445922 else: # Android, Linux, BSDs, etc. ASFLAGS += [ '-I%s/media/libaom/config/linux/ia32/' % TOPSRCDIR ] LOCAL_INCLUDES += [ '/media/libaom/config/linux/ia32/' ] EXPORTS.aom += [ 'config/linux/ia32/aom_config.h' ] elif CONFIG['CPU_ARCH'] == 'arm': EXPORTS.aom += files['ARM_EXPORTS'] ASFLAGS += [ '-I%s/media/libaom/config/linux/arm/' % TOPSRCDIR,
--- a/mobile/android/chrome/geckoview/GeckoViewPromptContent.js +++ b/mobile/android/chrome/geckoview/GeckoViewPromptContent.js @@ -2,14 +2,14 @@ /* 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/. */ ChromeUtils.import("resource://gre/modules/GeckoViewUtils.jsm"); GeckoViewUtils.addLazyEventListener(this, ["click", "contextmenu"], { handler: _ => - Cc["@mozilla.org/prompter;1"].getService(Ci.nsIDOMEventListener), + Cc["@mozilla.org/prompter;1"].getService().wrappedJSObject, options: { capture: false, mozSystemGroup: true, }, });
--- a/mobile/android/components/SessionStore.js +++ b/mobile/android/components/SessionStore.js @@ -58,17 +58,16 @@ function sendEvent(browser, event) { browser.dispatchEvent(evt); } SessionStore.prototype = { classID: Components.ID("{8c1f07d6-cba3-4226-a315-8bd43d67d032}"), QueryInterface: XPCOMUtils.generateQI([Ci.nsISessionStore, - Ci.nsIDOMEventListener, Ci.nsIObserver, Ci.nsISupportsWeakReference]), _windows: {}, _lastSaveTime: 0, _lastQueuedSaveTime: 0, _lastBackupTime: 0, _interval: 10000,
--- a/mobile/android/components/geckoview/GeckoViewPrompt.js +++ b/mobile/android/components/geckoview/GeckoViewPrompt.js @@ -17,17 +17,17 @@ XPCOMUtils.defineLazyServiceGetter(this, function PromptFactory() { this.wrappedJSObject = this; } PromptFactory.prototype = { classID: Components.ID("{076ac188-23c1-4390-aa08-7ef1f78ca5d9}"), QueryInterface: XPCOMUtils.generateQI([ - Ci.nsIDOMEventListener, Ci.nsIPromptFactory, Ci.nsIPromptService]), + Ci.nsIPromptFactory, Ci.nsIPromptService]), handleEvent: function(aEvent) { switch (aEvent.type) { case "click": this._handleClick(aEvent); break; case "contextmenu": this._handleContextMenu(aEvent);
--- a/netwerk/test/httpserver/test/test_default_index_handler.js +++ b/netwerk/test/httpserver/test/test_default_index_handler.js @@ -103,53 +103,43 @@ function hiddenDataCheck(bytes, uri, pat { var doc = parser.parseFromString(data, "application/xml"); } catch (e) { do_throw("document failed to parse as XML"); } - // See all the .QueryInterface()s and .item()s happening here? That's because - // xpcshell sucks and doesn't have classinfo, so no automatic interface - // flattening or array-style access to items in NodeLists. Suck. - var body = doc.documentElement.getElementsByTagName("body"); Assert.equal(body.length, 1); - body = body.item(0); + body = body[0]; // header - var header = body.QueryInterface(Ci.nsIDOMElement) - .getElementsByTagName("h1"); + var header = body.getElementsByTagName("h1"); Assert.equal(header.length, 1); - Assert.equal(header.item(0).QueryInterface(Ci.nsIDOMNode).textContent, path); + Assert.equal(header[0].textContent, path); // files var lst = body.getElementsByTagName("ol"); Assert.equal(lst.length, 1); - var items = lst.item(0).QueryInterface(Ci.nsIDOMElement) - .getElementsByTagName("li"); + var items = lst[0].getElementsByTagName("li"); var ios = Cc["@mozilla.org/network/io-service;1"] .getService(Ci.nsIIOService); var top = ios.newURI(uri); // N.B. No ERROR_IF_SEE_THIS.txt^ file! var dirEntries = [{name: "file.txt", isDirectory: false}, {name: "SHOULD_SEE_THIS.txt^", isDirectory: false}]; for (var i = 0; i < items.length; i++) { - var link = items.item(i) - .childNodes - .item(0) - .QueryInterface(Ci.nsIDOMNode) - .QueryInterface(Ci.nsIDOMElement); + var link = items[i].childNodes[0]; var f = dirEntries[i]; var sep = f.isDirectory ? "/" : ""; Assert.equal(link.textContent, f.name + sep); uri = ios.newURI(link.getAttribute("href"), null, top); Assert.equal(decodeURIComponent(uri.pathQueryRef), path + f.name + sep); @@ -187,49 +177,39 @@ function dataCheck(bytes, uri, path, dir { var doc = parser.parseFromString(data, "application/xml"); } catch (e) { do_throw("document failed to parse as XML"); } - // See all the .QueryInterface()s and .item()s happening here? That's because - // xpcshell sucks and doesn't have classinfo, so no automatic interface - // flattening or array-style access to items in NodeLists. Suck. - var body = doc.documentElement.getElementsByTagName("body"); Assert.equal(body.length, 1); - body = body.item(0); + body = body[0]; // header - var header = body.QueryInterface(Ci.nsIDOMElement) - .getElementsByTagName("h1"); + var header = body.getElementsByTagName("h1"); Assert.equal(header.length, 1); - Assert.equal(header.item(0).QueryInterface(Ci.nsIDOMNode).textContent, path); + Assert.equal(header[0].textContent, path); // files var lst = body.getElementsByTagName("ol"); Assert.equal(lst.length, 1); - var items = lst.item(0).QueryInterface(Ci.nsIDOMElement) - .getElementsByTagName("li"); + var items = lst[0].getElementsByTagName("li"); var ios = Cc["@mozilla.org/network/io-service;1"] .getService(Ci.nsIIOService); var dirURI = ios.newURI(uri); for (var i = 0; i < items.length; i++) { - var link = items.item(i) - .childNodes - .item(0) - .QueryInterface(Ci.nsIDOMNode) - .QueryInterface(Ci.nsIDOMElement); + var link = items[i].childNodes[0]; var f = dirEntries[i]; var sep = f.isDirectory ? "/" : ""; Assert.equal(link.textContent, f.name + sep); uri = ios.newURI(link.getAttribute("href"), null, top); Assert.equal(decodeURIComponent(uri.pathQueryRef), path + f.name + sep);
--- a/toolkit/components/extensions/ExtensionUtils.jsm +++ b/toolkit/components/extensions/ExtensionUtils.jsm @@ -387,17 +387,17 @@ function promiseObserved(topic, test = ( Services.obs.addObserver(observer, topic); }); } function getMessageManager(target) { if (target.frameLoader) { return target.frameLoader.messageManager; } - return target.QueryInterface(Ci.nsIMessageSender); + return target; } function flushJarCache(jarPath) { Services.obs.notifyObservers(null, "flush-cache-entry", jarPath); } /** * Convert any of several different representations of a date/time to a Date object.
--- a/toolkit/components/passwordmgr/LoginManagerContent.jsm +++ b/toolkit/components/passwordmgr/LoginManagerContent.jsm @@ -43,17 +43,16 @@ Services.cpmm.addMessageListener("clearR // These mirror signon.* prefs. var gEnabled, gAutofillForms, gStoreWhenAutocompleteOff; var gLastRightClickTimeStamp = Number.NEGATIVE_INFINITY; var observer = { QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsIFormSubmitObserver, Ci.nsIWebProgressListener, - Ci.nsIDOMEventListener, Ci.nsISupportsWeakReference]), // nsIFormSubmitObserver notify(formElement, aWindow, actionURI) { log("observer notified for form submission."); // We're invoked before the content's |onsubmit| handlers, so we // can grab form data before it might be modified (see bug 257781).
--- a/toolkit/components/passwordmgr/test/pwmgr_common.js +++ b/toolkit/components/passwordmgr/test/pwmgr_common.js @@ -156,17 +156,17 @@ function registerRunTests() { username.name = "testuser"; form.appendChild(username); var password = document.createElement("input"); password.name = "testpass"; password.type = "password"; form.appendChild(password); var observer = SpecialPowers.wrapCallback(function(subject, topic, data) { - var formLikeRoot = subject.QueryInterface(SpecialPowers.Ci.nsIDOMNode); + var formLikeRoot = subject; if (formLikeRoot.id !== "observerforcer") return; SpecialPowers.removeObserver(observer, "passwordmgr-processed-form"); formLikeRoot.remove(); SimpleTest.executeSoon(() => { var runTestEvent = new Event("runTests"); window.dispatchEvent(runTestEvent); resolve();
--- a/toolkit/components/prompts/content/tabprompts.xml +++ b/toolkit/components/prompts/content/tabprompts.xml @@ -79,17 +79,17 @@ <button anonid="button1" label="&cancelButton.label;"/> #endif </hbox> </vbox> </hbox> <spacer flex="2"/> </xbl:content> - <implementation implements="nsIDOMEventListener"> + <implementation> <constructor> <![CDATA[ let self = this; function getElement(anonid) { return document.getAnonymousElementByAttribute(self, "anonid", anonid); } this.ui = {
deleted file mode 100644 --- a/toolkit/content/select-child.js +++ /dev/null @@ -1,26 +0,0 @@ -/* 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/. */ - -ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm"); - -ChromeUtils.defineModuleGetter(this, "SelectContentHelper", - "resource://gre/modules/SelectContentHelper.jsm"); - -addEventListener("mozshowdropdown", event => { - if (!event.isTrusted) - return; - - if (!SelectContentHelper.open) { - new SelectContentHelper(event.target, {isOpenedViaTouch: false}, this); - } -}); - -addEventListener("mozshowdropdown-sourcetouch", event => { - if (!event.isTrusted) - return; - - if (!SelectContentHelper.open) { - new SelectContentHelper(event.target, {isOpenedViaTouch: true}, this); - } -});
--- a/toolkit/content/widgets/browser.xml +++ b/toolkit/content/widgets/browser.xml @@ -7,17 +7,17 @@ <bindings id="browserBindings" xmlns="http://www.mozilla.org/xbl" xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> <binding id="browser"> <content clickthrough="never"> <children/> </content> - <implementation type="application/javascript" implements="nsIObserver, nsIDOMEventListener, nsIBrowser"> + <implementation type="application/javascript" implements="nsIObserver, nsIBrowser"> <property name="autoscrollEnabled"> <getter> <![CDATA[ if (this.getAttribute("autoscroll") == "false") return false; return this.mPrefs.getBoolPref("general.autoScroll", true); ]]>
--- a/toolkit/content/widgets/button.xml +++ b/toolkit/content/widgets/button.xml @@ -256,17 +256,17 @@ event.preventDefault(); ]]> </handler> </handlers> </binding> <binding id="menu-button-base" extends="chrome://global/content/bindings/button.xml#button-base"> - <implementation implements="nsIDOMEventListener"> + <implementation> <constructor> this.init(); </constructor> <method name="init"> <body> <![CDATA[ var btn = document.getAnonymousElementByAttribute(this, "anonid", "button");
--- a/toolkit/content/widgets/colorpicker.xml +++ b/toolkit/content/widgets/colorpicker.xml @@ -102,17 +102,17 @@ <xul:image class="colorpickertile" color="#330033"/> </xul:hbox> </xul:vbox> <!-- Something to take tab focus <button style="border : 0px; width: 0px; height: 0px;"/> --> </content> - <implementation implements="nsIDOMEventListener"> + <implementation> <property name="color"> <getter><![CDATA[ return this.mSelectedCell ? this.mSelectedCell.getAttribute("color") : null; ]]></getter> <setter><![CDATA[ if (!val) return val; var uppercaseVal = val.toUpperCase();
--- a/toolkit/content/widgets/remote-browser.xml +++ b/toolkit/content/widgets/remote-browser.xml @@ -6,17 +6,17 @@ <bindings id="firefoxBrowserBindings" xmlns="http://www.mozilla.org/xbl" xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> <binding id="remote-browser" extends="chrome://global/content/bindings/browser.xml#browser"> <implementation type="application/javascript" - implements="nsIObserver, nsIDOMEventListener, nsIRemoteBrowser"> + implements="nsIObserver, nsIRemoteBrowser"> <field name="_securityUI">null</field> <property name="securityUI" readonly="true"> <getter><![CDATA[ if (!this._securityUI) { // Don't attempt to create the remote web progress if the
--- a/toolkit/content/widgets/scrollbox.xml +++ b/toolkit/content/widgets/scrollbox.xml @@ -609,17 +609,17 @@ xbl:inherits="orient,collapsed=notoverflowing,disabled=scrolledtoend" anonid="scrollbutton-down" onclick="_distanceScroll(event);" onmousedown="if (event.button == 0) _startScroll(1);" onmouseup="if (event.button == 0) _stopScroll();" onmouseover="_continueScroll(1);" onmouseout="_pauseScroll();"/> </content> - <implementation implements="nsITimerCallback, nsIDOMEventListener"> + <implementation implements="nsITimerCallback"> <constructor><![CDATA[ this._scrollDelay = this._prefBranch.getIntPref("toolkit.scrollbox.clickToScroll.scrollDelay", this._scrollDelay); ]]></constructor> <destructor><![CDATA[ // Release timer to avoid reference cycles.
--- a/toolkit/content/widgets/tabbox.xml +++ b/toolkit/content/widgets/tabbox.xml @@ -12,17 +12,17 @@ <binding id="tab-base"> <resources> <stylesheet src="chrome://global/skin/tabbox.css"/> </resources> </binding> <binding id="tabbox" extends="chrome://global/content/bindings/tabbox.xml#tab-base"> - <implementation implements="nsIDOMEventListener"> + <implementation> <property name="handleCtrlTab"> <setter> <![CDATA[ this.setAttribute("handleCtrlTab", val); return val; ]]> </setter> <getter>
--- a/toolkit/mozapps/extensions/test/browser/browser.ini +++ b/toolkit/mozapps/extensions/test/browser/browser.ini @@ -58,16 +58,17 @@ skip-if = os == "linux" && !debug # Bug [browser_checkAddonCompatibility.js] [browser_details.js] [browser_discovery.js] [browser_dragdrop.js] skip-if = buildapp == 'mulet' [browser_dragdrop_incompat.js] [browser_experiments.js] [browser_file_xpi_no_process_switch.js] +skip-if = !debug && ((os == 'linux' && bits == '64') || (os == 'win' && os_version == '6.1')) # Bug 1449071 - disable on Linux64 and Windows 7 due to frequent failures [browser_getmorethemes.js] [browser_globalwarnings.js] [browser_gmpProvider.js] skip-if = os == 'linux' && !debug # Bug 1398766 [browser_inlinesettings_browser.js] [browser_installssl.js] [browser_langpack_signing.js] [browser_legacy.js]