diff --git a/addon-sdk/source/lib/sdk/tabs/utils.js b/addon-sdk/source/lib/sdk/tabs/utils.js index eae3d41fe647..9edf35314976 100644 --- a/addon-sdk/source/lib/sdk/tabs/utils.js +++ b/addon-sdk/source/lib/sdk/tabs/utils.js @@ -207,7 +207,7 @@ function getTabId(tab) { if (tab.browser) // fennec return tab.id - return String.split(tab.linkedPanel, 'panel').pop(); + return String(tab.linkedPanel).split('panel').pop(); } exports.getTabId = getTabId; diff --git a/addon-sdk/source/lib/sdk/url.js b/addon-sdk/source/lib/sdk/url.js index ae16ac4a8cad..cfce03354cac 100644 --- a/addon-sdk/source/lib/sdk/url.js +++ b/addon-sdk/source/lib/sdk/url.js @@ -336,7 +336,7 @@ var isValidURI = exports.isValidURI = function (uri) { } function isLocalURL(url) { - if (String.indexOf(url, './') === 0) + if (String(url).indexOf('./') === 0) return true; try { diff --git a/browser/base/content/browser-media.js b/browser/base/content/browser-media.js index f57ce1f42958..7d10635df286 100644 --- a/browser/base/content/browser-media.js +++ b/browser/base/content/browser-media.js @@ -303,9 +303,9 @@ let gDecoderDoctorHandler = { histogram.add(decoderDoctorReportId, TELEMETRY_DDSTAT_SHOWN_FIRST); } else { // Split existing formats into an array of strings. - let existing = formatsInPref.split(",").map(String.trim); + let existing = formatsInPref.split(",").map(x => x.trim()); // Keep given formats that were not already recorded. - let newbies = formats.split(",").map(String.trim) + let newbies = formats.split(",").map(x => x.trim()) .filter(x => !existing.includes(x)); // And rewrite pref with the added new formats (if any). if (newbies.length) { diff --git a/browser/components/extensions/ext-utils.js b/browser/components/extensions/ext-utils.js index 571dfc6ac901..5b99909f76ca 100644 --- a/browser/components/extensions/ext-utils.js +++ b/browser/components/extensions/ext-utils.js @@ -320,7 +320,9 @@ class BasePopup { this.viewNode.style.maxHeight = `${height}px`; } else { this.browser.style.width = `${width}px`; + this.browser.style.minWidth = `${width}px`; this.browser.style.height = `${height}px`; + this.browser.style.minHeight = `${height}px`; } let event = new this.window.CustomEvent("WebExtPopupResized", {detail}); @@ -488,11 +490,12 @@ class ViewPopup extends BasePopup { let browser = this.browser; yield this.createBrowser(this.viewNode); + this.ignoreResizes = false; + this.browser.swapDocShells(browser); this.destroyBrowser(browser); - this.ignoreResizes = false; - if (this.dimensions) { + if (this.dimensions && !this.fixedWidth) { this.resizeBrowser(this.dimensions); } diff --git a/browser/components/extensions/test/browser/browser-common.ini b/browser/components/extensions/test/browser/browser-common.ini index 455572e2db7f..87b792a746b3 100644 --- a/browser/components/extensions/test/browser/browser-common.ini +++ b/browser/components/extensions/test/browser/browser-common.ini @@ -46,6 +46,7 @@ support-files = [browser_ext_incognito_views.js] [browser_ext_incognito_popup.js] [browser_ext_lastError.js] +[browser_ext_omnibox.js] [browser_ext_optionsPage_privileges.js] [browser_ext_pageAction_context.js] [browser_ext_pageAction_popup.js] @@ -97,12 +98,14 @@ support-files = [browser_ext_webRequest.js] [browser_ext_webNavigation_frameId0.js] [browser_ext_webNavigation_getFrames.js] +[browser_ext_webNavigation_urlbar_transitions.js] [browser_ext_windows.js] [browser_ext_windows_create.js] tags = fullscreen [browser_ext_windows_create_params.js] [browser_ext_windows_create_tabId.js] [browser_ext_windows_create_url.js] +[browser_ext_windows_events.js] [browser_ext_windows_size.js] skip-if = os == 'mac' # Fails when windows are randomly opened in fullscreen mode [browser_ext_windows_update.js] diff --git a/browser/components/extensions/test/browser/browser.ini b/browser/components/extensions/test/browser/browser.ini index a5e12c5a1e0c..ca173c22b3e9 100644 --- a/browser/components/extensions/test/browser/browser.ini +++ b/browser/components/extensions/test/browser/browser.ini @@ -2,10 +2,7 @@ tags = webextensions in-process-webextensions [browser_ext_legacy_extension_context_contentscript.js] -[browser_ext_omnibox.js] -[browser_ext_webNavigation_urlbar_transitions.js] [browser_ext_windows_allowScriptsToClose.js] -[browser_ext_windows_events.js] [include:browser-common.ini] [parent:browser-common.ini] diff --git a/browser/components/extensions/test/browser/browser_ext_browserAction_popup_resize.js b/browser/components/extensions/test/browser/browser_ext_browserAction_popup_resize.js index 3a2d2f52e9be..6b2229ab3e2e 100644 --- a/browser/components/extensions/test/browser/browser_ext_browserAction_popup_resize.js +++ b/browser/components/extensions/test/browser/browser_ext_browserAction_popup_resize.js @@ -180,7 +180,7 @@ function* testPopupSize(standardsMode, browserWin = window, arrowSide = "top") { // Wait long enough to make sure the initial resize debouncing timer has // expired. - yield new Promise(resolve => setTimeout(resolve, 100)); + yield delay(100); let dims = yield promiseContentDimensions(browser); @@ -295,9 +295,11 @@ add_task(function* testBrowserActionMenuResizeBottomArrow() { break; } - yield new Promise(resolve => setTimeout(resolve, 100)); + yield delay(100); } + yield SimpleTest.promiseFocus(win); + yield testPopupSize(true, win, "bottom"); yield BrowserTestUtils.closeWindow(win); diff --git a/browser/components/extensions/test/browser/browser_ext_commands_execute_browser_action.js b/browser/components/extensions/test/browser/browser_ext_commands_execute_browser_action.js index 04f8751de61a..8a49111e0c59 100644 --- a/browser/components/extensions/test/browser/browser_ext_commands_execute_browser_action.js +++ b/browser/components/extensions/test/browser/browser_ext_commands_execute_browser_action.js @@ -73,6 +73,8 @@ function* testExecuteBrowserActionWithOptions(options = {}) { yield extension.startup(); + yield SimpleTest.promiseFocus(window); + if (options.inArea) { let widget = getBrowserActionWidget(extension); CustomizableUI.addWidgetToArea(widget.id, options.inArea); diff --git a/browser/components/extensions/test/browser/browser_ext_omnibox.js b/browser/components/extensions/test/browser/browser_ext_omnibox.js index 05aca4c272f1..b8d8f63d91f1 100644 --- a/browser/components/extensions/test/browser/browser_ext_omnibox.js +++ b/browser/components/extensions/test/browser/browser_ext_omnibox.js @@ -228,6 +228,8 @@ add_task(function* () { yield setup(); yield extension.startup(); + yield SimpleTest.promiseFocus(window); + yield testInputEvents(); // Test the heuristic result with default suggestions. diff --git a/browser/components/extensions/test/browser/browser_ext_pageAction_popup_resize.js b/browser/components/extensions/test/browser/browser_ext_pageAction_popup_resize.js index 03b1655400b7..67c77075eb62 100644 --- a/browser/components/extensions/test/browser/browser_ext_pageAction_popup_resize.js +++ b/browser/components/extensions/test/browser/browser_ext_pageAction_popup_resize.js @@ -2,10 +2,6 @@ /* vim: set sts=2 sw=2 et tw=80: */ "use strict"; -let delay = ms => new Promise(resolve => { - setTimeout(resolve, ms); -}); - add_task(function* testPageActionPopupResize() { let browser; @@ -39,17 +35,8 @@ add_task(function* testPageActionPopupResize() { browser = yield awaitExtensionPanel(extension); - function* waitForSize(size) { - let dims = yield promiseContentDimensions(browser); - for (let i = 0; i < 100 && dims.window.innerWidth != size; i++) { - yield delay(50); - dims = yield promiseContentDimensions(browser); - } - return dims; - } - function* checkSize(expected) { - let dims = yield waitForSize(expected); + let dims = yield promiseContentDimensions(browser); let {body, root} = dims; is(dims.window.innerHeight, expected, `Panel window should be ${expected}px tall`); @@ -83,9 +70,7 @@ add_task(function* testPageActionPopupResize() { yield checkSize(size); } - yield alterContent(browser, setSize, 1400); - - let dims = yield waitForSize(800); + let dims = yield alterContent(browser, setSize, 1400); let {body, root} = dims; is(dims.window.innerWidth, 800, "Panel window width"); @@ -147,13 +132,6 @@ add_task(function* testPageActionPopupReflow() { let dims = yield alterContent(browser, setSize, 18); - if (AppConstants.platform == "win") { - while (dims.window.innerWidth < 800) { - yield delay(50); - dims = yield promiseContentDimensions(browser); - } - } - is(dims.window.innerWidth, 800, "Panel window should be 800px wide"); is(dims.body.clientWidth, 800, "Panel body should be 800px wide"); is(dims.body.clientWidth, dims.body.scrollWidth, diff --git a/browser/components/extensions/test/browser/browser_ext_webNavigation_urlbar_transitions.js b/browser/components/extensions/test/browser/browser_ext_webNavigation_urlbar_transitions.js index f2ea0d901b0c..3a1c02cbbd84 100644 --- a/browser/components/extensions/test/browser/browser_ext_webNavigation_urlbar_transitions.js +++ b/browser/components/extensions/test/browser/browser_ext_webNavigation_urlbar_transitions.js @@ -105,6 +105,7 @@ add_task(function* test_webnavigation_urlbar_typed_transitions() { }); yield extension.startup(); + yield SimpleTest.promiseFocus(window); yield extension.awaitMessage("ready"); @@ -150,6 +151,7 @@ add_task(function* test_webnavigation_urlbar_bookmark_transitions() { }); yield extension.startup(); + yield SimpleTest.promiseFocus(window); yield extension.awaitMessage("ready"); @@ -195,6 +197,7 @@ add_task(function* test_webnavigation_urlbar_keyword_transition() { }); yield extension.startup(); + yield SimpleTest.promiseFocus(window); yield extension.awaitMessage("ready"); @@ -235,6 +238,7 @@ add_task(function* test_webnavigation_urlbar_search_transitions() { }); yield extension.startup(); + yield SimpleTest.promiseFocus(window); yield extension.awaitMessage("ready"); diff --git a/browser/components/extensions/test/browser/browser_ext_windows_events.js b/browser/components/extensions/test/browser/browser_ext_windows_events.js index dc3485b98149..6cc32be272e0 100644 --- a/browser/components/extensions/test/browser/browser_ext_windows_events.js +++ b/browser/components/extensions/test/browser/browser_ext_windows_events.js @@ -104,6 +104,8 @@ add_task(function* testWindowsEvents() { info(`Close browser window 1`); yield BrowserTestUtils.closeWindow(win1); + currentWindow.focus(); + winId = yield extension.awaitMessage(`window-removed`); is(winId, win1Id, "Got removed event for the correct window ID."); diff --git a/browser/components/extensions/test/browser/head.js b/browser/components/extensions/test/browser/head.js index 1848e62acbbe..791992c7c398 100644 --- a/browser/components/extensions/test/browser/head.js +++ b/browser/components/extensions/test/browser/head.js @@ -97,7 +97,7 @@ function promisePopupHidden(popup) { }); } -function promiseContentDimensions(browser) { +function promisePossiblyInaccurateContentDimensions(browser) { return ContentTask.spawn(browser, null, function* () { function copyProps(obj, props) { let res = {}; @@ -121,18 +121,39 @@ function promiseContentDimensions(browser) { }); } -function* awaitPopupResize(browser) { - return BrowserTestUtils.waitForEvent(browser, "WebExtPopupResized", - event => event.detail === "delayed"); +function delay(ms = 0) { + return new Promise(resolve => setTimeout(resolve, ms)); +} + +async function promiseContentDimensions(browser) { + // For remote browsers, each resize operation requires an asynchronous + // round-trip to resize the content window. Since there's a certain amount of + // unpredictability in the timing, mainly due to the unpredictability of + // reflows, we need to wait until the content window dimensions match the + // dimensions before returning data. + + let dims = await promisePossiblyInaccurateContentDimensions(browser); + while (browser.clientWidth !== dims.window.innerWidth || + browser.clientHeight !== dims.window.innerHeight) { + await delay(50); + dims = await promisePossiblyInaccurateContentDimensions(browser); + } + + return dims; +} + +async function awaitPopupResize(browser) { + await BrowserTestUtils.waitForEvent(browser, "WebExtPopupResized", + event => event.detail === "delayed"); + + return promiseContentDimensions(browser); } function alterContent(browser, task, arg = null) { return Promise.all([ ContentTask.spawn(browser, arg, task), awaitPopupResize(browser), - ]).then(() => { - return promiseContentDimensions(browser); - }); + ]).then(([, dims]) => dims); } function getPanelForNode(node) { diff --git a/browser/components/sessionstore/test/browser_privatetabs.js b/browser/components/sessionstore/test/browser_privatetabs.js index 625046478758..cc02e56cfa71 100644 --- a/browser/components/sessionstore/test/browser_privatetabs.js +++ b/browser/components/sessionstore/test/browser_privatetabs.js @@ -15,13 +15,15 @@ add_task(function() { try { // Setup a public tab and a private tab info("Setting up public tab"); - tab1 = yield BrowserTestUtils.openNewForegroundTab(gBrowser, URL_PUBLIC); + tab1 = gBrowser.addTab(URL_PUBLIC); + yield promiseBrowserLoaded(tab1.linkedBrowser); info("Setting up private tab"); - tab2 = yield BrowserTestUtils.openNewForegroundTab(gBrowser); + tab2 = gBrowser.addTab(); + yield promiseBrowserLoaded(tab2.linkedBrowser); yield setUsePrivateBrowsing(tab2.linkedBrowser, true); tab2.linkedBrowser.loadURI(URL_PRIVATE); - yield BrowserTestUtils.browserLoaded(tab2.linkedBrowser, false, URL_PRIVATE); + yield promiseBrowserLoaded(tab2.linkedBrowser); info("Flush to make sure chrome received all data."); yield TabStateFlusher.flush(tab1.linkedBrowser); @@ -30,15 +32,16 @@ add_task(function() { info("Checking out state"); let state = yield promiseRecoveryFileContents(); + info("State: " + state); // Ensure that sessionstore.js only knows about the public tab ok(state.indexOf(URL_PUBLIC) != -1, "State contains public tab"); ok(state.indexOf(URL_PRIVATE) == -1, "State does not contain private tab"); // Ensure that we can close and undo close the public tab but not the private tab - yield BrowserTestUtils.removeTab(tab2); + gBrowser.removeTab(tab2); tab2 = null; - yield BrowserTestUtils.removeTab(tab1); + gBrowser.removeTab(tab1); tab1 = null; tab1 = ss.undoCloseTab(window, 0); @@ -48,10 +51,10 @@ add_task(function() { } finally { if (tab1) { - yield BrowserTestUtils.removeTab(tab1); + gBrowser.removeTab(tab1); } if (tab2) { - yield BrowserTestUtils.removeTab(tab2); + gBrowser.removeTab(tab2); } } }); @@ -64,13 +67,14 @@ add_task(function () { forgetClosedWindows(); // Create a new window to attach our frame script to. - let win = yield BrowserTestUtils.openNewBrowserWindow(); + let win = yield promiseNewWindowLoaded(); let mm = win.getGroupMessageManager("browsers"); mm.loadFrameScript(FRAME_SCRIPT, true); // Create a new tab in the new window that will load the frame script. - let tab = yield BrowserTestUtils.openNewForegroundTab(win.gBrowser, "about:mozilla"); + let tab = win.gBrowser.addTab("about:mozilla"); let browser = tab.linkedBrowser; + yield promiseBrowserLoaded(browser); yield TabStateFlusher.flush(browser); // Check that we consider the tab as private. @@ -78,12 +82,13 @@ add_task(function () { ok(state.isPrivate, "tab considered private"); // Ensure we don't allow restoring closed private tabs in non-private windows. - yield BrowserTestUtils.removeTab(tab); + win.gBrowser.removeTab(tab); is(ss.getClosedTabCount(win), 0, "no tabs to restore"); // Create a new tab in the new window that will load the frame script. - tab = yield BrowserTestUtils.openNewForegroundTab(win.gBrowser, "about:mozilla"); + tab = win.gBrowser.addTab("about:mozilla"); browser = tab.linkedBrowser; + yield promiseBrowserLoaded(browser); yield TabStateFlusher.flush(browser); // Check that we consider the tab as private. @@ -101,11 +106,12 @@ add_task(function () { forgetClosedWindows(); // Create a new window to attach our frame script to. - let win = yield BrowserTestUtils.openNewBrowserWindow({private: true}); + let win = yield promiseNewWindowLoaded({private: true}); // Create a new tab in the new window that will load the frame script. - let tab = yield BrowserTestUtils.openNewForegroundTab(win.gBrowser, "about:mozilla"); + let tab = win.gBrowser.addTab("about:mozilla"); let browser = tab.linkedBrowser; + yield promiseBrowserLoaded(browser); yield TabStateFlusher.flush(browser); // Check that we consider the tab as private. @@ -113,7 +119,7 @@ add_task(function () { ok(state.isPrivate, "tab considered private"); // Ensure that closed tabs in a private windows can be restored. - yield BrowserTestUtils.removeTab(tab); + win.gBrowser.removeTab(tab); is(ss.getClosedTabCount(win), 1, "there is a single tab to restore"); // Ensure that closed private windows can never be restored. diff --git a/browser/components/sessionstore/test/head.js b/browser/components/sessionstore/test/head.js index 5ed7160c2370..565baaeb7461 100644 --- a/browser/components/sessionstore/test/head.js +++ b/browser/components/sessionstore/test/head.js @@ -23,10 +23,6 @@ registerCleanupFunction(() => { for (let script of FRAME_SCRIPTS) { mm.removeDelayedFrameScript(script, true); } - - // Force a garbage collect after the end of each test run, to make sure that it - // won't interfere with the timing of the next test to be run from the suite. - window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils).garbageCollect(); }); const {Promise} = Cu.import("resource://gre/modules/Promise.jsm", {}); diff --git a/devtools/client/webconsole/test/browser_webconsole_bug_1006027_message_timestamps_incorrect.js b/devtools/client/webconsole/test/browser_webconsole_bug_1006027_message_timestamps_incorrect.js index ee141a72f5d4..7894ddc93f7a 100644 --- a/devtools/client/webconsole/test/browser_webconsole_bug_1006027_message_timestamps_incorrect.js +++ b/devtools/client/webconsole/test/browser_webconsole_bug_1006027_message_timestamps_incorrect.js @@ -34,7 +34,7 @@ function test() { // the epoch. // This is not the correct value of the timestamp, but good enough for // comparison. - return Date.parse("T" + String.trim(value.textContent)); + return Date.parse("T" + String(value.textContent).trim()); }); let minTimestamp = Math.min.apply(null, aTimestampMilliseconds); diff --git a/devtools/shared/gcli/commands/addon.js b/devtools/shared/gcli/commands/addon.js index 9a38142a3997..824cf7f04911 100644 --- a/devtools/shared/gcli/commands/addon.js +++ b/devtools/shared/gcli/commands/addon.js @@ -176,7 +176,7 @@ var items = [ }); function compareAddonNames(nameA, nameB) { - return String.localeCompare(nameA.name, nameB.name); + return String(nameA.name).localeCompare(nameB.name); } enabledAddons.sort(compareAddonNames); disabledAddons.sort(compareAddonNames); diff --git a/dom/bindings/test/test_interfaceToString.html b/dom/bindings/test/test_interfaceToString.html index c97b2f63b5b7..5c14fced828c 100644 --- a/dom/bindings/test/test_interfaceToString.html +++ b/dom/bindings/test/test_interfaceToString.html @@ -20,7 +20,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=742156 /** Test for Bug 742156 **/ -var nativeToString = ("" + String.replace).replace("replace", "EventTarget"); +var nativeToString = ("" + String).replace("String", "EventTarget"); try { var eventTargetToString = "" + EventTarget; is(eventTargetToString, nativeToString, diff --git a/dom/encoding/test/test_TextEncoder.js b/dom/encoding/test/test_TextEncoder.js index 7aa521398dad..531937effb2f 100644 --- a/dom/encoding/test/test_TextEncoder.js +++ b/dom/encoding/test/test_TextEncoder.js @@ -182,7 +182,7 @@ function testStreamingOptions() } function arrayFromString(s) { - return s.split('').map(function(c){return String.charCodeAt(c)}); + return s.split('').map(function(c){return c.charCodeAt(0)}); } function testArrayOfStrings(test) diff --git a/dom/events/EventStateManager.cpp b/dom/events/EventStateManager.cpp index de280cff0b05..e3472323bca0 100644 --- a/dom/events/EventStateManager.cpp +++ b/dom/events/EventStateManager.cpp @@ -2906,12 +2906,14 @@ EventStateManager::PostHandleEvent(nsPresContext* aPresContext, NS_ENSURE_ARG(aPresContext); NS_ENSURE_ARG_POINTER(aStatus); - bool dispatchedToContentProcess = HandleCrossProcessEvent(aEvent, - aStatus); - mCurrentTarget = aTargetFrame; mCurrentTargetContent = nullptr; + bool dispatchedToContentProcess = HandleCrossProcessEvent(aEvent, aStatus); + // NOTE: the above call may have destroyed aTargetFrame, please use + // mCurrentTarget henceforth. This is to avoid using it accidentally: + aTargetFrame = nullptr; + // Most of the events we handle below require a frame. // Add special cases here. if (!mCurrentTarget && aEvent->mMessage != eMouseUp && @@ -3168,7 +3170,7 @@ EventStateManager::PostHandleEvent(nsPresContext* aPresContext, ScrollbarsForWheel::MayInactivate(); WidgetWheelEvent* wheelEvent = aEvent->AsWheelEvent(); nsIScrollableFrame* scrollTarget = - do_QueryFrame(ComputeScrollTarget(aTargetFrame, wheelEvent, + do_QueryFrame(ComputeScrollTarget(mCurrentTarget, wheelEvent, COMPUTE_DEFAULT_ACTION_TARGET)); if (scrollTarget) { scrollTarget->ScrollSnap(); @@ -3191,7 +3193,7 @@ EventStateManager::PostHandleEvent(nsPresContext* aPresContext, // because if the scroll target is a plugin, the default action should be // chosen by the plugin rather than by our prefs. nsIFrame* frameToScroll = - ComputeScrollTarget(aTargetFrame, wheelEvent, + ComputeScrollTarget(mCurrentTarget, wheelEvent, COMPUTE_DEFAULT_ACTION_TARGET); nsPluginFrame* pluginFrame = do_QueryFrame(frameToScroll); @@ -3211,7 +3213,7 @@ EventStateManager::PostHandleEvent(nsPresContext* aPresContext, // For scrolling of default action, we should honor the mouse wheel // transaction. - ScrollbarsForWheel::PrepareToScrollText(this, aTargetFrame, wheelEvent); + ScrollbarsForWheel::PrepareToScrollText(this, mCurrentTarget, wheelEvent); if (aEvent->mMessage != eWheel || (!wheelEvent->mDeltaX && !wheelEvent->mDeltaY)) { @@ -3221,8 +3223,8 @@ EventStateManager::PostHandleEvent(nsPresContext* aPresContext, nsIScrollableFrame* scrollTarget = do_QueryFrame(frameToScroll); ScrollbarsForWheel::SetActiveScrollTarget(scrollTarget); - nsIFrame* rootScrollFrame = !aTargetFrame ? nullptr : - aTargetFrame->PresContext()->PresShell()->GetRootScrollFrame(); + nsIFrame* rootScrollFrame = !mCurrentTarget ? nullptr : + mCurrentTarget->PresContext()->PresShell()->GetRootScrollFrame(); nsIScrollableFrame* rootScrollableFrame = nullptr; if (rootScrollFrame) { rootScrollableFrame = do_QueryFrame(rootScrollFrame); @@ -3259,7 +3261,7 @@ EventStateManager::PostHandleEvent(nsPresContext* aPresContext, if (!intDelta) { break; } - DoScrollZoom(aTargetFrame, intDelta); + DoScrollZoom(mCurrentTarget, intDelta); break; } case WheelPrefs::ACTION_SEND_TO_PLUGIN: @@ -3289,7 +3291,7 @@ EventStateManager::PostHandleEvent(nsPresContext* aPresContext, // by looking at the scroll overflow values on mCanTriggerSwipe // events after they have been processed. allDeltaOverflown = - !ComputeScrollTarget(aTargetFrame, wheelEvent, + !ComputeScrollTarget(mCurrentTarget, wheelEvent, COMPUTE_DEFAULT_ACTION_TARGET); } } else { diff --git a/dom/html/HTMLSelectElement.cpp b/dom/html/HTMLSelectElement.cpp index fc5b77eb0f8e..3ef0614b7ae3 100644 --- a/dom/html/HTMLSelectElement.cpp +++ b/dom/html/HTMLSelectElement.cpp @@ -57,8 +57,11 @@ SafeOptionListMutation::SafeOptionListMutation(nsIContent* aSelect, : mSelect(HTMLSelectElement::FromContentOrNull(aSelect)) , mTopLevelMutation(false) , mNeedsRebuild(false) + , mNotify(aNotify) + , mInitialSelectedIndex(-1) { if (mSelect) { + mInitialSelectedIndex = mSelect->SelectedIndex(); mTopLevelMutation = !mSelect->mMutating; if (mTopLevelMutation) { mSelect->mMutating = true; @@ -67,13 +70,13 @@ SafeOptionListMutation::SafeOptionListMutation(nsIContent* aSelect, // option list must be up-to-date before inserting or removing options. // Fortunately this is called only if mutation event listener // adds or removes options. - mSelect->RebuildOptionsArray(aNotify); + mSelect->RebuildOptionsArray(mNotify); } nsresult rv; if (aKid) { - rv = mSelect->WillAddOptions(aKid, aParent, aIndex, aNotify); + rv = mSelect->WillAddOptions(aKid, aParent, aIndex, mNotify); } else { - rv = mSelect->WillRemoveOptions(aParent, aIndex, aNotify); + rv = mSelect->WillRemoveOptions(aParent, aIndex, mNotify); } mNeedsRebuild = NS_FAILED(rv); } @@ -88,6 +91,16 @@ SafeOptionListMutation::~SafeOptionListMutation() if (mTopLevelMutation) { mSelect->mMutating = false; } + if (mSelect->SelectedIndex() != mInitialSelectedIndex) { + // We must have triggered the SelectSomething() codepath, which can cause + // our validity to change. Unfortunately, our attempt to update validity + // in that case may not have worked correctly, because we actually call it + // before we have inserted the new