From e3c3846fa5dea20dc42a42340083cf2a767668b5 Mon Sep 17 00:00:00 2001 From: Tim Taubert Date: Tue, 21 May 2013 18:32:24 +0200 Subject: [PATCH 01/20] Bug 873771 - TabRestoreQueue should keep track of and evaluate restore_on_demand prefs; r=yoric --- .../sessionstore/src/SessionStore.jsm | 96 ++++++++++--------- 1 file changed, 53 insertions(+), 43 deletions(-) diff --git a/browser/components/sessionstore/src/SessionStore.jsm b/browser/components/sessionstore/src/SessionStore.jsm index b1f9118b73e..13c28f601a9 100644 --- a/browser/components/sessionstore/src/SessionStore.jsm +++ b/browser/components/sessionstore/src/SessionStore.jsm @@ -290,12 +290,6 @@ let SessionStoreInternal = { // number of tabs currently restoring _tabsRestoringCount: 0, - // overrides MAX_CONCURRENT_TAB_RESTORES and restore_hidden_tabs when true - _restoreOnDemand: false, - - // whether to restore app tabs on demand or not, pref controlled. - _restorePinnedTabsOnDemand: null, - // The state from the previous session (after restoring pinned tabs). This // state is persisted and passed through to the next session during an app // restart to make the third party add-on warning not trash the deferred @@ -371,14 +365,6 @@ let SessionStoreInternal = { this._sessionhistory_max_entries = this._prefBranch.getIntPref("sessionhistory.max_entries"); - this._restoreOnDemand = - this._prefBranch.getBoolPref("sessionstore.restore_on_demand"); - this._prefBranch.addObserver("sessionstore.restore_on_demand", this, true); - - this._restorePinnedTabsOnDemand = - this._prefBranch.getBoolPref("sessionstore.restore_pinned_tabs_on_demand"); - this._prefBranch.addObserver("sessionstore.restore_pinned_tabs_on_demand", this, true); - gSessionStartup.onceInitialized.then( this.initSession.bind(this) ); @@ -1188,14 +1174,6 @@ let SessionStoreInternal = { _SessionFile.wipe(); this.saveState(true); break; - case "sessionstore.restore_on_demand": - this._restoreOnDemand = - this._prefBranch.getBoolPref("sessionstore.restore_on_demand"); - break; - case "sessionstore.restore_pinned_tabs_on_demand": - this._restorePinnedTabsOnDemand = - this._prefBranch.getBoolPref("sessionstore.restore_pinned_tabs_on_demand"); - break; } }, @@ -3266,10 +3244,8 @@ let SessionStoreInternal = { if (this._loadState == STATE_QUITTING) return; - // If it's not possible to restore anything, then just bail out. - if ((this._restoreOnDemand && - (this._restorePinnedTabsOnDemand || !TabRestoreQueue.hasPriorityTabs)) || - this._tabsRestoringCount >= MAX_CONCURRENT_TAB_RESTORES) + // Don't exceed the maximum number of concurrent tab restores. + if (this._tabsRestoringCount >= MAX_CONCURRENT_TAB_RESTORES) return; let tab = TabRestoreQueue.shift(); @@ -4496,20 +4472,50 @@ let TabRestoreQueue = { // The separate buckets used to store tabs. tabs: {priority: [], visible: [], hidden: []}, - // Returns whether we have any high priority tabs in the queue. - get hasPriorityTabs() !!this.tabs.priority.length, + // Preferences used by the TabRestoreQueue to determine which tabs + // are restored automatically and which tabs will be on-demand. + prefs: { + // Lazy getter that returns whether tabs are restored on demand. + get restoreOnDemand() { + let updateValue = () => { + let value = Services.prefs.getBoolPref(PREF); + let definition = {value: value, configurable: true}; + Object.defineProperty(this, "restoreOnDemand", definition); + return value; + } - // Lazy getter that returns whether we should restore hidden tabs. - get restoreHiddenTabs() { - let updateValue = () => { - let value = Services.prefs.getBoolPref(PREF); - let definition = {value: value, configurable: true}; - Object.defineProperty(this, "restoreHiddenTabs", definition); + const PREF = "browser.sessionstore.restore_on_demand"; + Services.prefs.addObserver(PREF, updateValue, false); + return updateValue(); + }, + + // Lazy getter that returns whether pinned tabs are restored on demand. + get restorePinnedTabsOnDemand() { + let updateValue = () => { + let value = Services.prefs.getBoolPref(PREF); + let definition = {value: value, configurable: true}; + Object.defineProperty(this, "restorePinnedTabsOnDemand", definition); + return value; + } + + const PREF = "browser.sessionstore.restore_pinned_tabs_on_demand"; + Services.prefs.addObserver(PREF, updateValue, false); + return updateValue(); + }, + + // Lazy getter that returns whether we should restore hidden tabs. + get restoreHiddenTabs() { + let updateValue = () => { + let value = Services.prefs.getBoolPref(PREF); + let definition = {value: value, configurable: true}; + Object.defineProperty(this, "restoreHiddenTabs", definition); + return value; + } + + const PREF = "browser.sessionstore.restore_hidden_tabs"; + Services.prefs.addObserver(PREF, updateValue, false); + return updateValue(); } - - const PREF = "browser.sessionstore.restore_hidden_tabs"; - Services.prefs.addObserver(PREF, updateValue, false); - updateValue(); }, // Resets the queue and removes all tabs. @@ -4554,12 +4560,16 @@ let TabRestoreQueue = { let set; let {priority, hidden, visible} = this.tabs; - if (priority.length) { + let {restoreOnDemand, restorePinnedTabsOnDemand} = this.prefs; + let restorePinned = !(restoreOnDemand && restorePinnedTabsOnDemand); + if (restorePinned && priority.length) { set = priority; - } else if (visible.length) { - set = visible; - } else if (this.restoreHiddenTabs && hidden.length) { - set = hidden; + } else if (!restoreOnDemand) { + if (visible.length) { + set = visible; + } else if (this.prefs.restoreHiddenTabs && hidden.length) { + set = hidden; + } } return set && set.shift(); From 0f6e4cb9d0725c120026247f6a9a6bce21363d09 Mon Sep 17 00:00:00 2001 From: "Francesco Lodolo [:flod]" Date: Wed, 22 May 2013 01:35:00 -0700 Subject: [PATCH 02/20] Bug 874785 - Web Console: rewrite localization comments and use ordered arguments for multiple parameters, r=mratcliffe --- .../browser/devtools/webconsole.properties | 179 +++++++++--------- 1 file changed, 87 insertions(+), 92 deletions(-) diff --git a/browser/locales/en-US/chrome/browser/devtools/webconsole.properties b/browser/locales/en-US/chrome/browser/devtools/webconsole.properties index ffa4e76a6d1..2c3d5b3b87f 100644 --- a/browser/locales/en-US/chrome/browser/devtools/webconsole.properties +++ b/browser/locales/en-US/chrome/browser/devtools/webconsole.properties @@ -41,154 +41,149 @@ timestampFormat=%02S:%02S:%02S.%03S helperFuncUnsupportedTypeError=Can't call pprint on this type of object. NetworkPanel.label=Inspect Network Request -# LOCALIZATION NOTE (NetworkPanel.deltaDurationMS): -# -# This string is used to show the duration between two network events (e.g -# request and response header or response header and response body). + +# LOCALIZATION NOTE (NetworkPanel.deltaDurationMS): this string is used to +# show the duration between two network events (e.g request and response +# header or response header and response body). Parameters: %S is the duration. NetworkPanel.durationMS=%Sms -# LOCALIZATION NOTE (NetworkPanel.imageSizeDeltaDurationMS): -# This string is used to show the duration between the response header and the -# response body event. It also shows the size of the received or cached image. -# -# The first %S is replace by the width of the inspected image. -# The second %S is replaced by the height of the inspected image. -# The third %S is replaced by the duration between the response header and the -# response body event. -NetworkPanel.imageSizeDeltaDurationMS=%Sx%Spx, Δ%Sms -# LOCALIZATION NOTE (NetworkPanel.responseBodyUnableToDisplay.content): -# -# This string is displayed within the response body section of the NetworkPanel -# if the content type of the network request can't be displayed in the -# NetworkPanel. E.g. any kind of text is easy to display, but some audio or -# flash data received from the server can't be displayed. -# -# The %S is replaced by the content type, that can't be displayed, examples are -# o application/x-shockwave-flash -# o music/crescendo + +# LOCALIZATION NOTE (NetworkPanel.imageSizeDeltaDurationMS): this string is +# used to show the duration between the response header and the response body +# event. It also shows the size of the received or cached image. Parameters: +# %1$S is the width of the inspected image, %2$S is the height of the +# inspected image, %3$S is the duration between the response header and the +# response body event. Example: 150x100px, Δ50ms. +NetworkPanel.imageSizeDeltaDurationMS=%1$Sx%2$Spx, Δ%3$Sms + +# LOCALIZATION NOTE (NetworkPanel.responseBodyUnableToDisplay.content): this +# string is displayed within the response body section of the NetworkPanel if +# the content type of the network request can't be displayed. E.g. any kind of +# text is easy to display, but some audio or flash data received from the +# server can't be displayed. Parameters: %S is the content type that can't be +# displayed, examples are application/x-shockwave-flash, music/crescendo. NetworkPanel.responseBodyUnableToDisplay.content=Unable to display responses of type "%S" + ConsoleAPIDisabled=The Web Console logging API (console.log, console.info, console.warn, console.error) has been disabled by a script on this page. -# LOCALIZATION NOTE (webConsoleWindowTitleAndURL): The Web Console floating -# panel title, followed by the web page URL. -# For RTL languages you need to set the LRM in the string to give the URL -# the correct direction. +# LOCALIZATION NOTE (webConsoleWindowTitleAndURL): the Web Console floating +# panel title. For RTL languages you need to set the LRM in the string to give +# the URL the correct direction. Parameters: %S is the web page URL. webConsoleWindowTitleAndURL=Web Console - %S -# LOCALIZATION NOTE (webConsoleMixedContentWarning): Message displayed after a -# URL in the Web Console that has been flagged for Mixed Content (i.e. http -# content in an https page) +# LOCALIZATION NOTE (webConsoleMixedContentWarning): the message displayed +# after a URL in the Web Console that has been flagged for Mixed Content (i.e. +# http content in an https page). webConsoleMixedContentWarning=Mixed Content -# LOCALIZATION NOTE (scratchpad.linkText): -# The text used in the right hand side of the web console command line when -# JavaScript is being entered, to indicate how to jump into scratchpad mode +# LOCALIZATION NOTE (scratchpad.linkText): the text used in the right hand +# side of the Web Console command line when JavaScript is being entered, to +# indicate how to jump into scratchpad mode. scratchpad.linkText=Shift+RETURN - Open in Scratchpad -# LOCALIZATION NOTE (gcliterm.instanceLabel): The console displays -# objects using their type (from the constructor function) in this descriptive -# string +# LOCALIZATION NOTE (gcliterm.instanceLabel): the console displays objects +# using their type (from the constructor function) in this descriptive string. +# Parameters: %S is the object type. gcliterm.instanceLabel=Instance of %S -# LOCALIZATION NOTE (stacktrace.anonymousFunction): -# This string is used to display JavaScript functions that have no given name - -# they are said to be anonymous. See stacktrace.outputMessage. +# LOCALIZATION NOTE (stacktrace.anonymousFunction): this string is used to +# display JavaScript functions that have no given name - they are said to be +# anonymous. See also stacktrace.outputMessage. stacktrace.anonymousFunction= -# LOCALIZATION NOTE (stacktrace.outputMessage): -# This string is used in the Web Console output to identify a web developer call -# to console.trace(). The stack trace of JavaScript function calls is displayed. -# In this minimal message we only show the last call. -stacktrace.outputMessage=Stack trace from %S, function %S, line %S. +# LOCALIZATION NOTE (stacktrace.outputMessage): this string is used in the Web +# Console output to identify a web developer call to console.trace(). The +# stack trace of JavaScript function calls is displayed. In this minimal +# message we only show the last call. Parameters: %1$S is the file name, %2$S +# is the function name, %3$S is the line number. +stacktrace.outputMessage=Stack trace from %1$S, function %2$S, line %3$S. -# LOCALIZATION NOTE (timerStarted): -# This string is used to display the result of the console.time() call. -# %S=name of timer +# LOCALIZATION NOTE (timerStarted): this string is used to display the result +# of the console.time() call. Parameters: %S is the name of the timer. timerStarted=%S: timer started -# LOCALIZATION NOTE (timeEnd): -# This string is used to display the result of the console.timeEnd() call. -# %1$S=name of timer, %2$S=number of milliseconds +# LOCALIZATION NOTE (timeEnd): this string is used to display the result of +# the console.timeEnd() call. Parameters: %1$S is the name of the timer, %2$S +# is the number of milliseconds. timeEnd=%1$S: %2$Sms -# LOCALIZATION NOTE (Autocomplete.blank): -# This string is used when inputnode string containing anchor doesn't -# doesn't matches to any property in the content. +# LOCALIZATION NOTE (Autocomplete.blank): this string is used when inputnode +# string containing anchor doesn't matches to any property in the content. Autocomplete.blank= <- no result maxTimersExceeded=The maximum allowed number of timers in this page was exceeded. -# LOCALIZATION NOTE (JSTerm.updateNotInspectable): -# This string is used when the user inspects an evaluation result in the Web -# Console and tries the Update button, but the new result no longer returns an -# object that can be inspected. +# LOCALIZATION NOTE (JSTerm.updateNotInspectable): this string is used when +# the user inspects an evaluation result in the Web Console and tries the +# Update button, but the new result no longer returns an object that can be +# inspected. JSTerm.updateNotInspectable=After your input has been re-evaluated the result is no longer inspectable. -# LOCALIZATION NOTE (remoteWebConsolePromptTitle): The title displayed on the +# LOCALIZATION NOTE (remoteWebConsolePromptTitle): the title displayed on the # Web Console prompt asking for the remote host and port to connect to. remoteWebConsolePromptTitle=Remote Connection -# LOCALIZATION NOTE (remoteWebConsolePromptMessage): The message displayed on the -# Web Console prompt asking for the remote host and port to connect to. +# LOCALIZATION NOTE (remoteWebConsolePromptMessage): the message displayed on +# the Web Console prompt asking for the remote host and port to connect to. remoteWebConsolePromptMessage=Enter hostname and port number (host:port) -# LOCALIZATION NOTE (remoteWebConsoleSelectTabTitle): The title displayed on the -# Web Console prompt asking the user to pick a tab to attach to. +# LOCALIZATION NOTE (remoteWebConsoleSelectTabTitle): the title displayed on +# the Web Console prompt asking the user to pick a tab to attach to. remoteWebConsoleSelectTabTitle=Tab list - Remote Connection -# LOCALIZATION NOTE (remoteWebConsoleSelectTabMessage): The message displayed on the -# Web Console prompt asking the user to pick a tab to attach to. +# LOCALIZATION NOTE (remoteWebConsoleSelectTabMessage): the message displayed +# on the Web Console prompt asking the user to pick a tab to attach to. remoteWebConsoleSelectTabMessage=Select one of the tabs you want to attach to, or select the global console. -# LOCALIZATION NOTE (listTabs.globalConsoleActor): The string displayed for the -# global console in the tabs selection. +# LOCALIZATION NOTE (listTabs.globalConsoleActor): the string displayed for +# the global console in the tabs selection. listTabs.globalConsoleActor=*Global Console* -# LOCALIZATION NOTE (MenuWebconsole.label): -# This string is displayed in the Tools menu as a shortcut to open the devtools -# with the web console tab selected. +# LOCALIZATION NOTE (MenuWebconsole.label): the string displayed in the Tools +# menu as a shortcut to open the devtools with the Web Console tab selected. MenuWebconsole.label=Web Console -# LOCALIZATION NOTE (ToolboxTabWebconsole.label): -# This string is displayed as the label of the tab in the devtools window. +# LOCALIZATION NOTE (ToolboxTabWebconsole.label): the string displayed as the +# label of the tab in the devtools window. ToolboxTabWebconsole.label=Console -# LOCALIZATION NOTE (ToolboxWebconsole.tooltip): -# This string is displayed in the tooltip of the tab when the web console is -# displayed inside the developer tools window. +# LOCALIZATION NOTE (ToolboxWebconsole.tooltip): the string displayed in the +# tooltip of the tab when the Web Console is displayed inside the developer +# tools window. ToolboxWebconsole.tooltip=Web Console -# LOCALIZATION NOTE (longStringEllipsis): The string displayed after a long -# string. This string is clickable such that the rest of the string is retrieved -# from the server. +# LOCALIZATION NOTE (longStringEllipsis): the string displayed after a long +# string. This string is clickable such that the rest of the string is +# retrieved from the server. longStringEllipsis=[…] -# LOCALIZATION NOTE (longStringTooLong): The string displayed after the user +# LOCALIZATION NOTE (longStringTooLong): the string displayed after the user # tries to expand a long string. longStringTooLong=The string you are trying to view is too long to be displayed by the Web Console. -# LOCALIZATION NOTE (executeEmptyInput): This is displayed when the user tries -# to execute code, but the input is empty. +# LOCALIZATION NOTE (executeEmptyInput): the string displayed when the user +# tries to execute code, but the input is empty. executeEmptyInput=No value to execute. -# LOCALIZATION NOTE (NetworkPanel.fetchRemainingResponseContentLink): This is -# displayed in the network panel when the response body is only partially -# available. -NetworkPanel.fetchRemainingResponseContentLink=Fetch the remaining %1$S bytes +# LOCALIZATION NOTE (NetworkPanel.fetchRemainingResponseContentLink): the +# string displayed in the network panel when the response body is only +# partially available. Parameters: %S is the amount of bytes that need to be +# fetched. +NetworkPanel.fetchRemainingResponseContentLink=Fetch the remaining %S bytes -# LOCALIZATION NOTE (NetworkPanel.fetchRemainingRequestContentLink): This is -# displayed in the network panel when the request body is only partially -# available. -NetworkPanel.fetchRemainingRequestContentLink=Fetch the request body (%1$S bytes) +# LOCALIZATION NOTE (NetworkPanel.fetchRemainingRequestContentLink): the +# string displayed in the network panel when the request body is only +# partially available. Parameters: %S is the amount of bytes that need to be +# fetched. +NetworkPanel.fetchRemainingRequestContentLink=Fetch the request body (%S bytes) -# LOCALIZATION NOTE (connectionTimeout): Message displayed when the Remote Web +# LOCALIZATION NOTE (connectionTimeout): message displayed when the Remote Web # Console fails to connect to the server due to a timeout. connectionTimeout=Connection timeout. Check the Error Console on both ends for potential error messages. Reopen the Web Console to try again. -# LOCALIZATION NOTE (propertiesFilterPlaceholder): This is the text that +# LOCALIZATION NOTE (propertiesFilterPlaceholder): this is the text that # appears in the filter text box for the properties view container. propertiesFilterPlaceholder=Filter properties -# LOCALIZATION NOTE (emptyPropertiesList): The text that is displayed in the +# LOCALIZATION NOTE (emptyPropertiesList): the text that is displayed in the # properties pane when there are no properties to display. emptyPropertiesList=No properties to display - From e41e125889119f616d75714b79cb8f8e6a250fe9 Mon Sep 17 00:00:00 2001 From: Stephen Pohl Date: Sun, 26 May 2013 14:40:16 -0700 Subject: [PATCH 03/20] Bug 869314: Fix missing dropmarkers in non-native styled combobox controls when overlay scrollbars are used. --- gfx/src/nsThemeConstants.h | 3 +++ layout/forms/nsComboboxControlFrame.cpp | 18 +++++++++---- layout/generic/nsGfxScrollFrame.cpp | 34 +++++++++++++++++++++++++ layout/generic/nsGfxScrollFrame.h | 11 ++++++++ layout/generic/nsIScrollableFrame.h | 6 ++++- widget/cocoa/nsNativeThemeCocoa.mm | 5 ++++ 6 files changed, 71 insertions(+), 6 deletions(-) diff --git a/gfx/src/nsThemeConstants.h b/gfx/src/nsThemeConstants.h index 0f6fdc9311d..8e11e8af206 100644 --- a/gfx/src/nsThemeConstants.h +++ b/gfx/src/nsThemeConstants.h @@ -157,6 +157,9 @@ #define NS_THEME_SCROLLBAR_THUMB_HORIZONTAL 88 #define NS_THEME_SCROLLBAR_THUMB_VERTICAL 89 +// A non-disappearing scrollbar. +#define NS_THEME_SCROLLBAR_NON_DISAPPEARING 90 + // A textfield or text area #define NS_THEME_TEXTFIELD 95 diff --git a/layout/forms/nsComboboxControlFrame.cpp b/layout/forms/nsComboboxControlFrame.cpp index 2bd08d56cfb..3edd8c98aee 100644 --- a/layout/forms/nsComboboxControlFrame.cpp +++ b/layout/forms/nsComboboxControlFrame.cpp @@ -56,6 +56,7 @@ #include "mozilla/Likely.h" #include #include "nsTextNode.h" +#include "mozilla/LookAndFeel.h" using namespace mozilla; @@ -738,8 +739,8 @@ nsComboboxControlFrame::GetIntrinsicWidth(nsRenderingContext* aRenderingContext, if (mListControlFrame) { nsIScrollableFrame* scrollable = do_QueryFrame(mListControlFrame); NS_ASSERTION(scrollable, "List must be a scrollable frame"); - scrollbarWidth = - scrollable->GetDesiredScrollbarSizes(presContext, aRenderingContext).LeftRight(); + scrollbarWidth = scrollable->GetNondisappearingScrollbarWidth( + presContext, aRenderingContext); } nscoord displayWidth = 0; @@ -751,11 +752,19 @@ nsComboboxControlFrame::GetIntrinsicWidth(nsRenderingContext* aRenderingContext, if (mDropdownFrame) { nscoord dropdownContentWidth; + bool isUsingOverlayScrollbars = + LookAndFeel::GetInt(LookAndFeel::eIntID_UseOverlayScrollbars) != 0; if (aType == nsLayoutUtils::MIN_WIDTH) { dropdownContentWidth = mDropdownFrame->GetMinWidth(aRenderingContext); + if (isUsingOverlayScrollbars) { + dropdownContentWidth += scrollbarWidth; + } } else { NS_ASSERTION(aType == nsLayoutUtils::PREF_WIDTH, "Unexpected type"); dropdownContentWidth = mDropdownFrame->GetPrefWidth(aRenderingContext); + if (isUsingOverlayScrollbars) { + dropdownContentWidth += scrollbarWidth; + } } dropdownContentWidth = NSCoordSaturatingSubtract(dropdownContentWidth, scrollbarWidth, @@ -850,9 +859,8 @@ nsComboboxControlFrame::Reflow(nsPresContext* aPresContext, else { nsIScrollableFrame* scrollable = do_QueryFrame(mListControlFrame); NS_ASSERTION(scrollable, "List must be a scrollable frame"); - buttonWidth = - scrollable->GetDesiredScrollbarSizes(PresContext(), - aReflowState.rendContext).LeftRight(); + buttonWidth = scrollable->GetNondisappearingScrollbarWidth( + PresContext(), aReflowState.rendContext); if (buttonWidth > aReflowState.ComputedWidth()) { buttonWidth = 0; } diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index 6bb36924331..f6333dc1157 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -932,6 +932,40 @@ nsGfxScrollFrameInner::GetDesiredScrollbarSizes(nsBoxLayoutState* aState) return result; } +nscoord +nsGfxScrollFrameInner::GetNondisappearingScrollbarWidth(nsBoxLayoutState* aState) +{ + NS_ASSERTION(aState && aState->GetRenderingContext(), + "Must have rendering context in layout state for size " + "computations"); + + if (LookAndFeel::GetInt(LookAndFeel::eIntID_UseOverlayScrollbars) != 0) { + // We're using overlay scrollbars, so we need to get the width that + // non-disappearing scrollbars would have. + nsITheme* theme = aState->PresContext()->GetTheme(); + if (theme && + theme->ThemeSupportsWidget(aState->PresContext(), + mVScrollbarBox, + NS_THEME_SCROLLBAR_NON_DISAPPEARING)) { + nsIntSize size; + nsRenderingContext* rendContext = aState->GetRenderingContext(); + if (rendContext) { + bool canOverride = true; + theme->GetMinimumWidgetSize(rendContext, + mVScrollbarBox, + NS_THEME_SCROLLBAR_NON_DISAPPEARING, + &size, + &canOverride); + if (size.width) { + return aState->PresContext()->DevPixelsToAppUnits(size.width); + } + } + } + } + + return GetDesiredScrollbarSizes(aState).LeftRight(); +} + nsresult nsXULScrollFrame::CreateAnonymousContent(nsTArray& aElements) { diff --git a/layout/generic/nsGfxScrollFrame.h b/layout/generic/nsGfxScrollFrame.h index 38dd5d6b3c2..ca4d274ed01 100644 --- a/layout/generic/nsGfxScrollFrame.h +++ b/layout/generic/nsGfxScrollFrame.h @@ -235,6 +235,7 @@ public: } nsMargin GetActualScrollbarSizes() const; nsMargin GetDesiredScrollbarSizes(nsBoxLayoutState* aState); + nscoord GetNondisappearingScrollbarWidth(nsBoxLayoutState* aState); bool IsLTR() const; bool IsScrollbarOnRight() const; bool IsScrollingActive() const { return mScrollingActive || ShouldBuildLayer(); } @@ -486,6 +487,11 @@ public: nsBoxLayoutState bls(aPresContext, aRC, 0); return GetDesiredScrollbarSizes(&bls); } + virtual nscoord GetNondisappearingScrollbarWidth(nsPresContext* aPresContext, + nsRenderingContext* aRC) MOZ_OVERRIDE { + nsBoxLayoutState bls(aPresContext, aRC, 0); + return mInner.GetNondisappearingScrollbarWidth(&bls); + } virtual nsRect GetScrollPortRect() const MOZ_OVERRIDE { return mInner.GetScrollPortRect(); } @@ -744,6 +750,11 @@ public: nsBoxLayoutState bls(aPresContext, aRC, 0); return GetDesiredScrollbarSizes(&bls); } + virtual nscoord GetNondisappearingScrollbarWidth(nsPresContext* aPresContext, + nsRenderingContext* aRC) MOZ_OVERRIDE { + nsBoxLayoutState bls(aPresContext, aRC, 0); + return mInner.GetNondisappearingScrollbarWidth(&bls); + } virtual nsRect GetScrollPortRect() const MOZ_OVERRIDE { return mInner.GetScrollPortRect(); } diff --git a/layout/generic/nsIScrollableFrame.h b/layout/generic/nsIScrollableFrame.h index 725d5f51c4d..b149b510dcc 100644 --- a/layout/generic/nsIScrollableFrame.h +++ b/layout/generic/nsIScrollableFrame.h @@ -81,7 +81,11 @@ public: */ virtual nsMargin GetDesiredScrollbarSizes(nsPresContext* aPresContext, nsRenderingContext* aRC) = 0; - + /** + * Return the width for non-disappearing scrollbars. + */ + virtual nscoord GetNondisappearingScrollbarWidth(nsPresContext* aPresContext, + nsRenderingContext* aRC) = 0; /** * Get the area of the scrollport relative to the origin of this frame's * border-box. diff --git a/widget/cocoa/nsNativeThemeCocoa.mm b/widget/cocoa/nsNativeThemeCocoa.mm index ae11394f6d6..4a2760a3c58 100644 --- a/widget/cocoa/nsNativeThemeCocoa.mm +++ b/widget/cocoa/nsNativeThemeCocoa.mm @@ -2846,7 +2846,11 @@ nsNativeThemeCocoa::GetMinimumWidgetSize(nsRenderingContext* aContext, aResult->SizeTo(16, 16); break; } + // Intentional fallthrough to next case. + } + case NS_THEME_SCROLLBAR_NON_DISAPPEARING: + { // yeah, i know i'm cheating a little here, but i figure that it // really doesn't matter if the scrollbar is vertical or horizontal // and the width metric is a really good metric for every piece @@ -3056,6 +3060,7 @@ nsNativeThemeCocoa::ThemeSupportsWidget(nsPresContext* aPresContext, nsIFrame* a case NS_THEME_SCROLLBAR_THUMB_VERTICAL: case NS_THEME_SCROLLBAR_TRACK_VERTICAL: case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL: + case NS_THEME_SCROLLBAR_NON_DISAPPEARING: case NS_THEME_DROPDOWN: case NS_THEME_DROPDOWN_BUTTON: From 641baa78c1749ca645b9988e758a8d85c654f86f Mon Sep 17 00:00:00 2001 From: Stephen Pohl Date: Sun, 26 May 2013 14:40:25 -0700 Subject: [PATCH 04/20] Bug 869314 - Test for availability of dropmarkers in non-native styled comboboxes when overlay scrollbars are used. --- layout/forms/test/Makefile.in | 1 + layout/forms/test/test_bug869314.html | 54 +++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 layout/forms/test/test_bug869314.html diff --git a/layout/forms/test/Makefile.in b/layout/forms/test/Makefile.in index 7e5f80895ee..c7c91b119f7 100644 --- a/layout/forms/test/Makefile.in +++ b/layout/forms/test/Makefile.in @@ -43,6 +43,7 @@ MOCHITEST_FILES = test_bug231389.html \ test_bug644542.html \ test_bug672810.html \ test_bug704049.html \ + test_bug869314.html \ test_listcontrol_search.html \ $(NULL) diff --git a/layout/forms/test/test_bug869314.html b/layout/forms/test/test_bug869314.html new file mode 100644 index 00000000000..9116884d66f --- /dev/null +++ b/layout/forms/test/test_bug869314.html @@ -0,0 +1,54 @@ + + + + + + Test for Bug 869314 + + + + + + + +Mozilla Bug 869314 +

+
+ + + + + + + +
+
+
+ + From 2acc2dfcba0b329cea24d7f6c685b9d567570790 Mon Sep 17 00:00:00 2001 From: Stephen Pohl Date: Sun, 26 May 2013 15:00:17 -0700 Subject: [PATCH 05/20] Back out bug 869314 for missing r='s. --- gfx/src/nsThemeConstants.h | 3 -- layout/forms/nsComboboxControlFrame.cpp | 18 +++------ layout/forms/test/Makefile.in | 1 - layout/forms/test/test_bug869314.html | 54 ------------------------- layout/generic/nsGfxScrollFrame.cpp | 34 ---------------- layout/generic/nsGfxScrollFrame.h | 11 ----- layout/generic/nsIScrollableFrame.h | 6 +-- widget/cocoa/nsNativeThemeCocoa.mm | 5 --- 8 files changed, 6 insertions(+), 126 deletions(-) delete mode 100644 layout/forms/test/test_bug869314.html diff --git a/gfx/src/nsThemeConstants.h b/gfx/src/nsThemeConstants.h index 8e11e8af206..0f6fdc9311d 100644 --- a/gfx/src/nsThemeConstants.h +++ b/gfx/src/nsThemeConstants.h @@ -157,9 +157,6 @@ #define NS_THEME_SCROLLBAR_THUMB_HORIZONTAL 88 #define NS_THEME_SCROLLBAR_THUMB_VERTICAL 89 -// A non-disappearing scrollbar. -#define NS_THEME_SCROLLBAR_NON_DISAPPEARING 90 - // A textfield or text area #define NS_THEME_TEXTFIELD 95 diff --git a/layout/forms/nsComboboxControlFrame.cpp b/layout/forms/nsComboboxControlFrame.cpp index 3edd8c98aee..2bd08d56cfb 100644 --- a/layout/forms/nsComboboxControlFrame.cpp +++ b/layout/forms/nsComboboxControlFrame.cpp @@ -56,7 +56,6 @@ #include "mozilla/Likely.h" #include #include "nsTextNode.h" -#include "mozilla/LookAndFeel.h" using namespace mozilla; @@ -739,8 +738,8 @@ nsComboboxControlFrame::GetIntrinsicWidth(nsRenderingContext* aRenderingContext, if (mListControlFrame) { nsIScrollableFrame* scrollable = do_QueryFrame(mListControlFrame); NS_ASSERTION(scrollable, "List must be a scrollable frame"); - scrollbarWidth = scrollable->GetNondisappearingScrollbarWidth( - presContext, aRenderingContext); + scrollbarWidth = + scrollable->GetDesiredScrollbarSizes(presContext, aRenderingContext).LeftRight(); } nscoord displayWidth = 0; @@ -752,19 +751,11 @@ nsComboboxControlFrame::GetIntrinsicWidth(nsRenderingContext* aRenderingContext, if (mDropdownFrame) { nscoord dropdownContentWidth; - bool isUsingOverlayScrollbars = - LookAndFeel::GetInt(LookAndFeel::eIntID_UseOverlayScrollbars) != 0; if (aType == nsLayoutUtils::MIN_WIDTH) { dropdownContentWidth = mDropdownFrame->GetMinWidth(aRenderingContext); - if (isUsingOverlayScrollbars) { - dropdownContentWidth += scrollbarWidth; - } } else { NS_ASSERTION(aType == nsLayoutUtils::PREF_WIDTH, "Unexpected type"); dropdownContentWidth = mDropdownFrame->GetPrefWidth(aRenderingContext); - if (isUsingOverlayScrollbars) { - dropdownContentWidth += scrollbarWidth; - } } dropdownContentWidth = NSCoordSaturatingSubtract(dropdownContentWidth, scrollbarWidth, @@ -859,8 +850,9 @@ nsComboboxControlFrame::Reflow(nsPresContext* aPresContext, else { nsIScrollableFrame* scrollable = do_QueryFrame(mListControlFrame); NS_ASSERTION(scrollable, "List must be a scrollable frame"); - buttonWidth = scrollable->GetNondisappearingScrollbarWidth( - PresContext(), aReflowState.rendContext); + buttonWidth = + scrollable->GetDesiredScrollbarSizes(PresContext(), + aReflowState.rendContext).LeftRight(); if (buttonWidth > aReflowState.ComputedWidth()) { buttonWidth = 0; } diff --git a/layout/forms/test/Makefile.in b/layout/forms/test/Makefile.in index c7c91b119f7..7e5f80895ee 100644 --- a/layout/forms/test/Makefile.in +++ b/layout/forms/test/Makefile.in @@ -43,7 +43,6 @@ MOCHITEST_FILES = test_bug231389.html \ test_bug644542.html \ test_bug672810.html \ test_bug704049.html \ - test_bug869314.html \ test_listcontrol_search.html \ $(NULL) diff --git a/layout/forms/test/test_bug869314.html b/layout/forms/test/test_bug869314.html deleted file mode 100644 index 9116884d66f..00000000000 --- a/layout/forms/test/test_bug869314.html +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - Test for Bug 869314 - - - - - - - -Mozilla Bug 869314 -

-
- - - - - - - -
-
-
- - diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index f6333dc1157..6bb36924331 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -932,40 +932,6 @@ nsGfxScrollFrameInner::GetDesiredScrollbarSizes(nsBoxLayoutState* aState) return result; } -nscoord -nsGfxScrollFrameInner::GetNondisappearingScrollbarWidth(nsBoxLayoutState* aState) -{ - NS_ASSERTION(aState && aState->GetRenderingContext(), - "Must have rendering context in layout state for size " - "computations"); - - if (LookAndFeel::GetInt(LookAndFeel::eIntID_UseOverlayScrollbars) != 0) { - // We're using overlay scrollbars, so we need to get the width that - // non-disappearing scrollbars would have. - nsITheme* theme = aState->PresContext()->GetTheme(); - if (theme && - theme->ThemeSupportsWidget(aState->PresContext(), - mVScrollbarBox, - NS_THEME_SCROLLBAR_NON_DISAPPEARING)) { - nsIntSize size; - nsRenderingContext* rendContext = aState->GetRenderingContext(); - if (rendContext) { - bool canOverride = true; - theme->GetMinimumWidgetSize(rendContext, - mVScrollbarBox, - NS_THEME_SCROLLBAR_NON_DISAPPEARING, - &size, - &canOverride); - if (size.width) { - return aState->PresContext()->DevPixelsToAppUnits(size.width); - } - } - } - } - - return GetDesiredScrollbarSizes(aState).LeftRight(); -} - nsresult nsXULScrollFrame::CreateAnonymousContent(nsTArray& aElements) { diff --git a/layout/generic/nsGfxScrollFrame.h b/layout/generic/nsGfxScrollFrame.h index ca4d274ed01..38dd5d6b3c2 100644 --- a/layout/generic/nsGfxScrollFrame.h +++ b/layout/generic/nsGfxScrollFrame.h @@ -235,7 +235,6 @@ public: } nsMargin GetActualScrollbarSizes() const; nsMargin GetDesiredScrollbarSizes(nsBoxLayoutState* aState); - nscoord GetNondisappearingScrollbarWidth(nsBoxLayoutState* aState); bool IsLTR() const; bool IsScrollbarOnRight() const; bool IsScrollingActive() const { return mScrollingActive || ShouldBuildLayer(); } @@ -487,11 +486,6 @@ public: nsBoxLayoutState bls(aPresContext, aRC, 0); return GetDesiredScrollbarSizes(&bls); } - virtual nscoord GetNondisappearingScrollbarWidth(nsPresContext* aPresContext, - nsRenderingContext* aRC) MOZ_OVERRIDE { - nsBoxLayoutState bls(aPresContext, aRC, 0); - return mInner.GetNondisappearingScrollbarWidth(&bls); - } virtual nsRect GetScrollPortRect() const MOZ_OVERRIDE { return mInner.GetScrollPortRect(); } @@ -750,11 +744,6 @@ public: nsBoxLayoutState bls(aPresContext, aRC, 0); return GetDesiredScrollbarSizes(&bls); } - virtual nscoord GetNondisappearingScrollbarWidth(nsPresContext* aPresContext, - nsRenderingContext* aRC) MOZ_OVERRIDE { - nsBoxLayoutState bls(aPresContext, aRC, 0); - return mInner.GetNondisappearingScrollbarWidth(&bls); - } virtual nsRect GetScrollPortRect() const MOZ_OVERRIDE { return mInner.GetScrollPortRect(); } diff --git a/layout/generic/nsIScrollableFrame.h b/layout/generic/nsIScrollableFrame.h index b149b510dcc..725d5f51c4d 100644 --- a/layout/generic/nsIScrollableFrame.h +++ b/layout/generic/nsIScrollableFrame.h @@ -81,11 +81,7 @@ public: */ virtual nsMargin GetDesiredScrollbarSizes(nsPresContext* aPresContext, nsRenderingContext* aRC) = 0; - /** - * Return the width for non-disappearing scrollbars. - */ - virtual nscoord GetNondisappearingScrollbarWidth(nsPresContext* aPresContext, - nsRenderingContext* aRC) = 0; + /** * Get the area of the scrollport relative to the origin of this frame's * border-box. diff --git a/widget/cocoa/nsNativeThemeCocoa.mm b/widget/cocoa/nsNativeThemeCocoa.mm index 4a2760a3c58..ae11394f6d6 100644 --- a/widget/cocoa/nsNativeThemeCocoa.mm +++ b/widget/cocoa/nsNativeThemeCocoa.mm @@ -2846,11 +2846,7 @@ nsNativeThemeCocoa::GetMinimumWidgetSize(nsRenderingContext* aContext, aResult->SizeTo(16, 16); break; } - // Intentional fallthrough to next case. - } - case NS_THEME_SCROLLBAR_NON_DISAPPEARING: - { // yeah, i know i'm cheating a little here, but i figure that it // really doesn't matter if the scrollbar is vertical or horizontal // and the width metric is a really good metric for every piece @@ -3060,7 +3056,6 @@ nsNativeThemeCocoa::ThemeSupportsWidget(nsPresContext* aPresContext, nsIFrame* a case NS_THEME_SCROLLBAR_THUMB_VERTICAL: case NS_THEME_SCROLLBAR_TRACK_VERTICAL: case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL: - case NS_THEME_SCROLLBAR_NON_DISAPPEARING: case NS_THEME_DROPDOWN: case NS_THEME_DROPDOWN_BUTTON: From 0cf8e749453cf6ee097c03bc403bb9b34d6ce2fa Mon Sep 17 00:00:00 2001 From: Stephen Pohl Date: Sun, 26 May 2013 15:05:10 -0700 Subject: [PATCH 06/20] Bug 869314: Fix missing dropmarkers in non-native styled combobox controls when overlay scrollbars are used. r=roc --- gfx/src/nsThemeConstants.h | 3 +++ layout/forms/nsComboboxControlFrame.cpp | 18 +++++++++---- layout/generic/nsGfxScrollFrame.cpp | 34 +++++++++++++++++++++++++ layout/generic/nsGfxScrollFrame.h | 11 ++++++++ layout/generic/nsIScrollableFrame.h | 6 ++++- widget/cocoa/nsNativeThemeCocoa.mm | 5 ++++ 6 files changed, 71 insertions(+), 6 deletions(-) diff --git a/gfx/src/nsThemeConstants.h b/gfx/src/nsThemeConstants.h index 0f6fdc9311d..8e11e8af206 100644 --- a/gfx/src/nsThemeConstants.h +++ b/gfx/src/nsThemeConstants.h @@ -157,6 +157,9 @@ #define NS_THEME_SCROLLBAR_THUMB_HORIZONTAL 88 #define NS_THEME_SCROLLBAR_THUMB_VERTICAL 89 +// A non-disappearing scrollbar. +#define NS_THEME_SCROLLBAR_NON_DISAPPEARING 90 + // A textfield or text area #define NS_THEME_TEXTFIELD 95 diff --git a/layout/forms/nsComboboxControlFrame.cpp b/layout/forms/nsComboboxControlFrame.cpp index 2bd08d56cfb..3edd8c98aee 100644 --- a/layout/forms/nsComboboxControlFrame.cpp +++ b/layout/forms/nsComboboxControlFrame.cpp @@ -56,6 +56,7 @@ #include "mozilla/Likely.h" #include #include "nsTextNode.h" +#include "mozilla/LookAndFeel.h" using namespace mozilla; @@ -738,8 +739,8 @@ nsComboboxControlFrame::GetIntrinsicWidth(nsRenderingContext* aRenderingContext, if (mListControlFrame) { nsIScrollableFrame* scrollable = do_QueryFrame(mListControlFrame); NS_ASSERTION(scrollable, "List must be a scrollable frame"); - scrollbarWidth = - scrollable->GetDesiredScrollbarSizes(presContext, aRenderingContext).LeftRight(); + scrollbarWidth = scrollable->GetNondisappearingScrollbarWidth( + presContext, aRenderingContext); } nscoord displayWidth = 0; @@ -751,11 +752,19 @@ nsComboboxControlFrame::GetIntrinsicWidth(nsRenderingContext* aRenderingContext, if (mDropdownFrame) { nscoord dropdownContentWidth; + bool isUsingOverlayScrollbars = + LookAndFeel::GetInt(LookAndFeel::eIntID_UseOverlayScrollbars) != 0; if (aType == nsLayoutUtils::MIN_WIDTH) { dropdownContentWidth = mDropdownFrame->GetMinWidth(aRenderingContext); + if (isUsingOverlayScrollbars) { + dropdownContentWidth += scrollbarWidth; + } } else { NS_ASSERTION(aType == nsLayoutUtils::PREF_WIDTH, "Unexpected type"); dropdownContentWidth = mDropdownFrame->GetPrefWidth(aRenderingContext); + if (isUsingOverlayScrollbars) { + dropdownContentWidth += scrollbarWidth; + } } dropdownContentWidth = NSCoordSaturatingSubtract(dropdownContentWidth, scrollbarWidth, @@ -850,9 +859,8 @@ nsComboboxControlFrame::Reflow(nsPresContext* aPresContext, else { nsIScrollableFrame* scrollable = do_QueryFrame(mListControlFrame); NS_ASSERTION(scrollable, "List must be a scrollable frame"); - buttonWidth = - scrollable->GetDesiredScrollbarSizes(PresContext(), - aReflowState.rendContext).LeftRight(); + buttonWidth = scrollable->GetNondisappearingScrollbarWidth( + PresContext(), aReflowState.rendContext); if (buttonWidth > aReflowState.ComputedWidth()) { buttonWidth = 0; } diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index 6bb36924331..f6333dc1157 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -932,6 +932,40 @@ nsGfxScrollFrameInner::GetDesiredScrollbarSizes(nsBoxLayoutState* aState) return result; } +nscoord +nsGfxScrollFrameInner::GetNondisappearingScrollbarWidth(nsBoxLayoutState* aState) +{ + NS_ASSERTION(aState && aState->GetRenderingContext(), + "Must have rendering context in layout state for size " + "computations"); + + if (LookAndFeel::GetInt(LookAndFeel::eIntID_UseOverlayScrollbars) != 0) { + // We're using overlay scrollbars, so we need to get the width that + // non-disappearing scrollbars would have. + nsITheme* theme = aState->PresContext()->GetTheme(); + if (theme && + theme->ThemeSupportsWidget(aState->PresContext(), + mVScrollbarBox, + NS_THEME_SCROLLBAR_NON_DISAPPEARING)) { + nsIntSize size; + nsRenderingContext* rendContext = aState->GetRenderingContext(); + if (rendContext) { + bool canOverride = true; + theme->GetMinimumWidgetSize(rendContext, + mVScrollbarBox, + NS_THEME_SCROLLBAR_NON_DISAPPEARING, + &size, + &canOverride); + if (size.width) { + return aState->PresContext()->DevPixelsToAppUnits(size.width); + } + } + } + } + + return GetDesiredScrollbarSizes(aState).LeftRight(); +} + nsresult nsXULScrollFrame::CreateAnonymousContent(nsTArray& aElements) { diff --git a/layout/generic/nsGfxScrollFrame.h b/layout/generic/nsGfxScrollFrame.h index 38dd5d6b3c2..ca4d274ed01 100644 --- a/layout/generic/nsGfxScrollFrame.h +++ b/layout/generic/nsGfxScrollFrame.h @@ -235,6 +235,7 @@ public: } nsMargin GetActualScrollbarSizes() const; nsMargin GetDesiredScrollbarSizes(nsBoxLayoutState* aState); + nscoord GetNondisappearingScrollbarWidth(nsBoxLayoutState* aState); bool IsLTR() const; bool IsScrollbarOnRight() const; bool IsScrollingActive() const { return mScrollingActive || ShouldBuildLayer(); } @@ -486,6 +487,11 @@ public: nsBoxLayoutState bls(aPresContext, aRC, 0); return GetDesiredScrollbarSizes(&bls); } + virtual nscoord GetNondisappearingScrollbarWidth(nsPresContext* aPresContext, + nsRenderingContext* aRC) MOZ_OVERRIDE { + nsBoxLayoutState bls(aPresContext, aRC, 0); + return mInner.GetNondisappearingScrollbarWidth(&bls); + } virtual nsRect GetScrollPortRect() const MOZ_OVERRIDE { return mInner.GetScrollPortRect(); } @@ -744,6 +750,11 @@ public: nsBoxLayoutState bls(aPresContext, aRC, 0); return GetDesiredScrollbarSizes(&bls); } + virtual nscoord GetNondisappearingScrollbarWidth(nsPresContext* aPresContext, + nsRenderingContext* aRC) MOZ_OVERRIDE { + nsBoxLayoutState bls(aPresContext, aRC, 0); + return mInner.GetNondisappearingScrollbarWidth(&bls); + } virtual nsRect GetScrollPortRect() const MOZ_OVERRIDE { return mInner.GetScrollPortRect(); } diff --git a/layout/generic/nsIScrollableFrame.h b/layout/generic/nsIScrollableFrame.h index 725d5f51c4d..b149b510dcc 100644 --- a/layout/generic/nsIScrollableFrame.h +++ b/layout/generic/nsIScrollableFrame.h @@ -81,7 +81,11 @@ public: */ virtual nsMargin GetDesiredScrollbarSizes(nsPresContext* aPresContext, nsRenderingContext* aRC) = 0; - + /** + * Return the width for non-disappearing scrollbars. + */ + virtual nscoord GetNondisappearingScrollbarWidth(nsPresContext* aPresContext, + nsRenderingContext* aRC) = 0; /** * Get the area of the scrollport relative to the origin of this frame's * border-box. diff --git a/widget/cocoa/nsNativeThemeCocoa.mm b/widget/cocoa/nsNativeThemeCocoa.mm index ae11394f6d6..4a2760a3c58 100644 --- a/widget/cocoa/nsNativeThemeCocoa.mm +++ b/widget/cocoa/nsNativeThemeCocoa.mm @@ -2846,7 +2846,11 @@ nsNativeThemeCocoa::GetMinimumWidgetSize(nsRenderingContext* aContext, aResult->SizeTo(16, 16); break; } + // Intentional fallthrough to next case. + } + case NS_THEME_SCROLLBAR_NON_DISAPPEARING: + { // yeah, i know i'm cheating a little here, but i figure that it // really doesn't matter if the scrollbar is vertical or horizontal // and the width metric is a really good metric for every piece @@ -3056,6 +3060,7 @@ nsNativeThemeCocoa::ThemeSupportsWidget(nsPresContext* aPresContext, nsIFrame* a case NS_THEME_SCROLLBAR_THUMB_VERTICAL: case NS_THEME_SCROLLBAR_TRACK_VERTICAL: case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL: + case NS_THEME_SCROLLBAR_NON_DISAPPEARING: case NS_THEME_DROPDOWN: case NS_THEME_DROPDOWN_BUTTON: From 10459bc0a0d73319cc2051020dfb83149c763a8c Mon Sep 17 00:00:00 2001 From: Stephen Pohl Date: Sun, 26 May 2013 15:05:14 -0700 Subject: [PATCH 07/20] Bug 869314: Test for availability of dropmarkers in non-native styled comboboxes when overlay scrollbars are used. r=roc --- layout/forms/test/Makefile.in | 1 + layout/forms/test/test_bug869314.html | 54 +++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 layout/forms/test/test_bug869314.html diff --git a/layout/forms/test/Makefile.in b/layout/forms/test/Makefile.in index 7e5f80895ee..c7c91b119f7 100644 --- a/layout/forms/test/Makefile.in +++ b/layout/forms/test/Makefile.in @@ -43,6 +43,7 @@ MOCHITEST_FILES = test_bug231389.html \ test_bug644542.html \ test_bug672810.html \ test_bug704049.html \ + test_bug869314.html \ test_listcontrol_search.html \ $(NULL) diff --git a/layout/forms/test/test_bug869314.html b/layout/forms/test/test_bug869314.html new file mode 100644 index 00000000000..9116884d66f --- /dev/null +++ b/layout/forms/test/test_bug869314.html @@ -0,0 +1,54 @@ + + + + + + Test for Bug 869314 + + + + + + + +Mozilla Bug 869314 +

+
+ + + + + + + +
+
+
+ + From b409b3449cbd8b112c2050ab429a652c9ff8a6e0 Mon Sep 17 00:00:00 2001 From: Chris Peterson Date: Sat, 25 May 2013 12:03:42 -0700 Subject: [PATCH 08/20] Bug 849589 - Catch and log intermittent NativeZip exception. r=glandium --- mobile/android/base/util/GeckoJarReader.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/mobile/android/base/util/GeckoJarReader.java b/mobile/android/base/util/GeckoJarReader.java index a4521d14a5c..a8727787a0e 100644 --- a/mobile/android/base/util/GeckoJarReader.java +++ b/mobile/android/base/util/GeckoJarReader.java @@ -40,7 +40,7 @@ public final class GeckoJarReader { try { // Load the initial jar file as a zip zip = getZipFile(jarUrls.pop()); - inputStream = getStream(zip, jarUrls); + inputStream = getStream(zip, jarUrls, url); if (inputStream != null) { bitmap = new BitmapDrawable(resources, inputStream); } @@ -70,7 +70,7 @@ public final class GeckoJarReader { String text = null; try { zip = getZipFile(jarUrls.pop()); - InputStream input = getStream(zip, jarUrls); + InputStream input = getStream(zip, jarUrls, url); if (input != null) { reader = new BufferedReader(new InputStreamReader(input)); text = reader.readLine(); @@ -98,7 +98,7 @@ public final class GeckoJarReader { return new NativeZip(fileUrl.getPath()); } - private static InputStream getStream(NativeZip zip, Stack jarUrls) { + private static InputStream getStream(NativeZip zip, Stack jarUrls, String origUrl) { InputStream inputStream = null; // loop through children jar files until we reach the innermost one @@ -107,7 +107,12 @@ public final class GeckoJarReader { if (inputStream != null) { // intermediate NativeZips and InputStreams will be garbage collected. - zip = new NativeZip(inputStream); + try { + zip = new NativeZip(inputStream); + } catch (IllegalArgumentException e) { + Log.e(LOGTAG, "!!! BUG 849589 !!! origUrl=" + origUrl, e); + return null; + } } inputStream = zip.getInputStream(fileName); From c292bec6ecf857ac7d1ce7268876fc52cb738232 Mon Sep 17 00:00:00 2001 From: Chris Peterson Date: Sat, 25 May 2013 12:03:42 -0700 Subject: [PATCH 09/20] Bug 849589 - Rethrow intermittent NativeZip exception with more debugging info. r=glandium --- mobile/android/base/util/GeckoJarReader.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mobile/android/base/util/GeckoJarReader.java b/mobile/android/base/util/GeckoJarReader.java index a8727787a0e..8baeab7375e 100644 --- a/mobile/android/base/util/GeckoJarReader.java +++ b/mobile/android/base/util/GeckoJarReader.java @@ -110,8 +110,9 @@ public final class GeckoJarReader { try { zip = new NativeZip(inputStream); } catch (IllegalArgumentException e) { - Log.e(LOGTAG, "!!! BUG 849589 !!! origUrl=" + origUrl, e); - return null; + String description = "!!! BUG 849589 !!! origUrl=" + origUrl; + Log.e(LOGTAG, description, e); + throw new IllegalArgumentException(description); } } From 30f3e235ca92e229dda2fb29548864d3f893e863 Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Thu, 23 May 2013 03:59:00 -0700 Subject: [PATCH 10/20] Bug 869002 - DocumentFragment should be constructable, r=Ms2ger --- content/base/src/DocumentFragment.cpp | 12 ++++++++++ content/base/src/DocumentFragment.h | 3 +++ content/base/test/Makefile.in | 1 + content/base/test/test_bug869002.html | 32 +++++++++++++++++++++++++++ dom/webidl/DocumentFragment.webidl | 1 + 5 files changed, 49 insertions(+) create mode 100644 content/base/test/test_bug869002.html diff --git a/content/base/src/DocumentFragment.cpp b/content/base/src/DocumentFragment.cpp index 24ec3feec72..86859b44d2b 100644 --- a/content/base/src/DocumentFragment.cpp +++ b/content/base/src/DocumentFragment.cpp @@ -107,6 +107,18 @@ DocumentFragment::DumpContent(FILE* out, int32_t aIndent, } #endif +/* static */ already_AddRefed +DocumentFragment::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv) +{ + nsCOMPtr window = do_QueryInterface(aGlobal.Get()); + if (!window || !window->GetDoc()) { + aRv.Throw(NS_ERROR_FAILURE); + return nullptr; + } + + return window->GetDoc()->CreateDocumentFragment(); +} + // QueryInterface implementation for DocumentFragment NS_INTERFACE_MAP_BEGIN(DocumentFragment) NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY diff --git a/content/base/src/DocumentFragment.h b/content/base/src/DocumentFragment.h index c64e3fe29fb..2efb3fed986 100644 --- a/content/base/src/DocumentFragment.h +++ b/content/base/src/DocumentFragment.h @@ -141,6 +141,9 @@ public: mHost = aHost; } + static already_AddRefed + Constructor(const GlobalObject& aGlobal, ErrorResult& aRv); + #ifdef DEBUG virtual void List(FILE* out, int32_t aIndent) const; virtual void DumpContent(FILE* out, int32_t aIndent, bool aDumpAll) const; diff --git a/content/base/test/Makefile.in b/content/base/test/Makefile.in index 75449f97c54..8bb5f9baece 100644 --- a/content/base/test/Makefile.in +++ b/content/base/test/Makefile.in @@ -628,6 +628,7 @@ MOCHITEST_FILES_C= \ test_bug869006.html \ test_bug868999.html \ test_bug869000.html \ + test_bug869002.html \ $(NULL) # OOP tests don't work on Windows (bug 763081) or native-fennec diff --git a/content/base/test/test_bug869002.html b/content/base/test/test_bug869002.html new file mode 100644 index 00000000000..a93200a1bf4 --- /dev/null +++ b/content/base/test/test_bug869002.html @@ -0,0 +1,32 @@ + + + + + + Test for Bug 868999 + + + + +Mozilla Bug 869002 +

+ +
+
+
+ + diff --git a/dom/webidl/DocumentFragment.webidl b/dom/webidl/DocumentFragment.webidl index b33a2749bc7..8034ea468d5 100644 --- a/dom/webidl/DocumentFragment.webidl +++ b/dom/webidl/DocumentFragment.webidl @@ -11,6 +11,7 @@ * liability, trademark and document use rules apply. */ +[Constructor] interface DocumentFragment : Node { // NEW /* From c429a32f93b821ffd80dcaedd62e796b8073310b Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Thu, 23 May 2013 15:38:00 -0700 Subject: [PATCH 11/20] Bug 874090 - Crash in mozilla::dom::Notification::GetPermissionInternal, r=wchen --- dom/src/notification/Notification.cpp | 39 ++++++--- dom/tests/mochitest/notification/Makefile.in | 4 + .../notification/test_system_principal.xul | 81 +++++++++++++++++++ 3 files changed, 111 insertions(+), 13 deletions(-) create mode 100644 dom/tests/mochitest/notification/test_system_principal.xul diff --git a/dom/src/notification/Notification.cpp b/dom/src/notification/Notification.cpp index cb8f856d81e..429b059a9e1 100644 --- a/dom/src/notification/Notification.cpp +++ b/dom/src/notification/Notification.cpp @@ -105,13 +105,20 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(NotificationPermissionRequest) NS_IMETHODIMP NotificationPermissionRequest::Run() { - // File are automatically granted permission. - nsCOMPtr uri; - mPrincipal->GetURI(getter_AddRefs(uri)); - bool isFile; - uri->SchemeIs("file", &isFile); - if (isFile) { + if (nsContentUtils::IsSystemPrincipal(mPrincipal)) { mPermission = NotificationPermission::Granted; + } else { + // File are automatically granted permission. + nsCOMPtr uri; + mPrincipal->GetURI(getter_AddRefs(uri)); + + if (uri) { + bool isFile; + uri->SchemeIs("file", &isFile); + if (isFile) { + mPermission = NotificationPermission::Granted; + } + } } // Grant permission if pref'ed on. @@ -398,15 +405,21 @@ Notification::GetPermissionInternal(nsISupports* aGlobal, ErrorResult& aRv) aRv.Throw(NS_ERROR_UNEXPECTED); return NotificationPermission::Denied; } - nsCOMPtr principal = sop->GetPrincipal(); - // Allow files to show notifications by default. - nsCOMPtr uri; - principal->GetURI(getter_AddRefs(uri)); - bool isFile; - uri->SchemeIs("file", &isFile); - if (isFile) { + nsCOMPtr principal = sop->GetPrincipal(); + if (nsContentUtils::IsSystemPrincipal(principal)) { return NotificationPermission::Granted; + } else { + // Allow files to show notifications by default. + nsCOMPtr uri; + principal->GetURI(getter_AddRefs(uri)); + if (uri) { + bool isFile; + uri->SchemeIs("file", &isFile); + if (isFile) { + return NotificationPermission::Granted; + } + } } // We also allow notifications is they are pref'ed on. diff --git a/dom/tests/mochitest/notification/Makefile.in b/dom/tests/mochitest/notification/Makefile.in index 70cc0632799..1992c32c377 100644 --- a/dom/tests/mochitest/notification/Makefile.in +++ b/dom/tests/mochitest/notification/Makefile.in @@ -10,6 +10,10 @@ relativesrcdir = @relativesrcdir@ include $(DEPTH)/config/autoconf.mk +MOCHITEST_CHROME_FILES = \ + test_system_principal.xul \ + $(NULL) + MOCHITEST_FILES = \ test_basic_notification.html \ test_basic_notification_click.html \ diff --git a/dom/tests/mochitest/notification/test_system_principal.xul b/dom/tests/mochitest/notification/test_system_principal.xul new file mode 100644 index 00000000000..60f9d56bca9 --- /dev/null +++ b/dom/tests/mochitest/notification/test_system_principal.xul @@ -0,0 +1,81 @@ + + + + + + + From b3f9ceb38ab29164234931d6bbc2265127799098 Mon Sep 17 00:00:00 2001 From: Phil Ringnalda Date: Sun, 26 May 2013 22:00:38 -0700 Subject: [PATCH 12/20] CLOBBER for bug 869002 --- CLOBBER | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CLOBBER b/CLOBBER index 81c97ce7ecd..2ac003cbb98 100644 --- a/CLOBBER +++ b/CLOBBER @@ -17,7 +17,7 @@ # # Modifying this file will now automatically clobber the buildbot machines \o/ # -Bug 874640 touched webidl, so Windows needs to clobber + Bug 854517: Integrate valgrind into B2G builds +Bug 869002 touched webidl, so Windows needs to clobber Alternative to clobber is to run ./config.status from the objdir and to touch the CLOBBER file in the objdir. From 94905a3054295f48b570c0fa2a7bfeada080b9d4 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Mon, 27 May 2013 17:13:05 +1200 Subject: [PATCH 13/20] Bug 876133. Ensure output audio volume is updated when 'volume' attribute is set on media element. r=cpearce --HG-- extra : rebase_source : defbb7d13b70349d321006db37f005888fb6a79e --- content/html/content/public/HTMLMediaElement.h | 5 +++++ content/html/content/src/HTMLMediaElement.cpp | 7 ++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/content/html/content/public/HTMLMediaElement.h b/content/html/content/public/HTMLMediaElement.h index 3d91c0afcdd..889a77859e6 100644 --- a/content/html/content/public/HTMLMediaElement.h +++ b/content/html/content/public/HTMLMediaElement.h @@ -796,6 +796,11 @@ protected: * Mute or unmute the audio and change the value that the |muted| map. */ void SetMutedInternal(uint32_t aMuted); + /** + * Update the volume of the output audio stream to match the element's + * current mMuted/mVolume state. + */ + void SetVolumeInternal(); /** * Suspend (if aPauseForInactiveDocument) or resume element playback and diff --git a/content/html/content/src/HTMLMediaElement.cpp b/content/html/content/src/HTMLMediaElement.cpp index 4ef7c937332..eb6d852b877 100644 --- a/content/html/content/src/HTMLMediaElement.cpp +++ b/content/html/content/src/HTMLMediaElement.cpp @@ -1509,7 +1509,7 @@ HTMLMediaElement::SetVolume(double aVolume, ErrorResult& aRv) mVolume = aVolume; // Here we want just to update the volume. - SetMutedInternal(mMuted); + SetVolumeInternal(); DispatchAsyncEvent(NS_LITERAL_STRING("volumechange")); } @@ -1687,6 +1687,11 @@ void HTMLMediaElement::SetMutedInternal(uint32_t aMuted) return; } + SetVolumeInternal(); +} + +void HTMLMediaElement::SetVolumeInternal() +{ float effectiveVolume = mMuted ? 0.0f : float(mVolume); if (mDecoder) { From 89eacf7637df59e8f1d5d3111e09a6c97b6d60a0 Mon Sep 17 00:00:00 2001 From: Cameron McCormack Date: Mon, 27 May 2013 16:48:19 +1000 Subject: [PATCH 14/20] Bug 876127 - Assert if we do not look at all style structs in nsStyleContext::CalcStyleDifference. r=dbaron --- layout/style/nsStyleContext.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/layout/style/nsStyleContext.cpp b/layout/style/nsStyleContext.cpp index 0aacc3cabeb..b956fdeb36a 100644 --- a/layout/style/nsStyleContext.cpp +++ b/layout/style/nsStyleContext.cpp @@ -440,6 +440,7 @@ nsStyleContext::CalcStyleDifference(nsStyleContext* aOther, // by font-size changing, so we don't need to worry about them like // we worry about 'inherit' values.) bool compare = mRuleNode != aOther->mRuleNode; + DebugOnly styleStructCount = 0; #define DO_STRUCT_DIFFERENCE(struct_) \ PR_BEGIN_MACRO \ @@ -458,6 +459,7 @@ nsStyleContext::CalcStyleDifference(nsStyleContext* aOther, NS_UpdateHint(hint, this##struct_->CalcDifference(*other##struct_)); \ } \ } \ + styleStructCount++; \ PR_END_MACRO // In general, we want to examine structs starting with those that can @@ -491,6 +493,9 @@ nsStyleContext::CalcStyleDifference(nsStyleContext* aOther, #undef DO_STRUCT_DIFFERENCE + MOZ_ASSERT(styleStructCount == nsStyleStructID_Length, + "missing a call to DO_STRUCT_DIFFERENCE"); + // Note that we do not check whether this->RelevantLinkVisited() != // aOther->RelevantLinkVisited(); we don't need to since // nsCSSFrameConstructor::DoContentStateChanged always adds From ddccab29b841d9958f613e9a6c2b63bdfca3563e Mon Sep 17 00:00:00 2001 From: Jonathan Watt Date: Mon, 27 May 2013 08:31:39 +0100 Subject: [PATCH 15/20] Bug 876157 - Avoid expensive nsSVGGradientFrame::GetGradientTransform calls when gradients paint only a single color. r=roc --- layout/svg/nsSVGGradientFrame.cpp | 39 +++++++++++++++++-------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/layout/svg/nsSVGGradientFrame.cpp b/layout/svg/nsSVGGradientFrame.cpp index c89fd4acdf3..4cae80e14ce 100644 --- a/layout/svg/nsSVGGradientFrame.cpp +++ b/layout/svg/nsSVGGradientFrame.cpp @@ -174,18 +174,9 @@ nsSVGGradientFrame::GetGradientTransform(nsIFrame *aSource, gfxMatrix bboxMatrix; uint16_t gradientUnits = GetGradientUnits(); - if (gradientUnits == SVG_UNIT_TYPE_USERSPACEONUSE) { - // If this gradient is applied to text, our caller - // will be the glyph, which is not a container, so we - // need to get the parent - if (aSource->GetContent()->IsNodeOfType(nsINode::eTEXT)) - mSource = aSource->GetParent(); - else - mSource = aSource; - } else { - NS_ASSERTION( - gradientUnits == SVG_UNIT_TYPE_OBJECTBOUNDINGBOX, - "Unknown gradientUnits type"); + if (gradientUnits != SVG_UNIT_TYPE_USERSPACEONUSE) { + NS_ASSERTION(gradientUnits == SVG_UNIT_TYPE_OBJECTBOUNDINGBOX, + "Unknown gradientUnits type"); // objectBoundingBox is the default anyway gfxRect bbox = @@ -242,11 +233,16 @@ nsSVGGradientFrame::GetPaintServerPattern(nsIFrame *aSource, float aGraphicOpacity, const gfxRect *aOverrideBounds) { - // Get the transform list (if there is one) - gfxMatrix patternMatrix = GetGradientTransform(aSource, aOverrideBounds); - - if (patternMatrix.IsSingular()) - return nullptr; + uint16_t gradientUnits = GetGradientUnits(); + MOZ_ASSERT(gradientUnits == SVG_UNIT_TYPE_OBJECTBOUNDINGBOX || + gradientUnits == SVG_UNIT_TYPE_USERSPACEONUSE); + if (gradientUnits == SVG_UNIT_TYPE_USERSPACEONUSE) { + // Set mSource for this consumer. + // If this gradient is applied to text, our caller will be the glyph, which + // is not an element, so we need to get the parent + mSource = aSource->GetContent()->IsNodeOfType(nsINode::eTEXT) ? + aSource->GetParent() : aSource; + } uint32_t nStops = GetStopCount(); @@ -272,6 +268,15 @@ nsSVGGradientFrame::GetPaintServerPattern(nsIFrame *aSource, return pattern.forget(); } + // Get the transform list (if there is one). We do this after the returns + // above since this call can be expensive when "gradientUnits" is set to + // "objectBoundingBox" (since that requiring a GetBBox() call). + gfxMatrix patternMatrix = GetGradientTransform(aSource, aOverrideBounds); + + if (patternMatrix.IsSingular()) { + return nullptr; + } + // revert the vector effect transform so that the gradient appears unchanged if (aFillOrStroke == &nsStyleSVG::mStroke) { patternMatrix.Multiply(nsSVGUtils::GetStrokeTransform(aSource).Invert()); From 81db085aa480a28b0c1e6c218edecec9910a347d Mon Sep 17 00:00:00 2001 From: Jonathan Watt Date: Mon, 27 May 2013 08:34:01 +0100 Subject: [PATCH 16/20] Bug 876175 - Fix O(n^2) behavior and other perf issues with nsSVGGradientFrame::GetPaintServerPattern. r=roc --- layout/svg/nsSVGGradientFrame.cpp | 116 ++++++++++++------------------ layout/svg/nsSVGGradientFrame.h | 12 ++-- 2 files changed, 48 insertions(+), 80 deletions(-) diff --git a/layout/svg/nsSVGGradientFrame.cpp b/layout/svg/nsSVGGradientFrame.cpp index 4cae80e14ce..13a7b7d3f41 100644 --- a/layout/svg/nsSVGGradientFrame.cpp +++ b/layout/svg/nsSVGGradientFrame.cpp @@ -82,44 +82,6 @@ nsSVGGradientFrame::AttributeChanged(int32_t aNameSpaceID, //---------------------------------------------------------------------- -uint32_t -nsSVGGradientFrame::GetStopCount() -{ - return GetStopFrame(-1, nullptr); -} - -void -nsSVGGradientFrame::GetStopInformation(int32_t aIndex, - float *aOffset, - nscolor *aStopColor, - float *aStopOpacity) -{ - *aOffset = 0.0f; - *aStopColor = NS_RGBA(0, 0, 0, 0); - *aStopOpacity = 1.0f; - - nsIFrame *stopFrame = nullptr; - GetStopFrame(aIndex, &stopFrame); - - nsIContent* stopContent = stopFrame->GetContent(); - - if (stopContent) { - MOZ_ASSERT(stopContent->IsSVG(nsGkAtoms::stop)); - SVGStopElement* stopElement = nullptr; - stopElement = static_cast(stopContent); - nsCOMPtr aNum = stopElement->Offset(); - - aNum->GetAnimVal(aOffset); - if (*aOffset < 0.0f) - *aOffset = 0.0f; - else if (*aOffset > 1.0f) - *aOffset = 1.0f; - } - - *aStopColor = stopFrame->StyleSVGReset()->mStopColor; - *aStopOpacity = stopFrame->StyleSVGReset()->mStopOpacity; -} - uint16_t nsSVGGradientFrame::GetEnumValue(uint32_t aIndex, nsIContent *aDefault) { @@ -226,6 +188,23 @@ nsSVGGradientFrame::GetRadialGradientWithLength(uint32_t aIndex, //---------------------------------------------------------------------- // nsSVGPaintServerFrame methods: +//helper +static void GetStopInformation(nsIFrame* aStopFrame, + float *aOffset, + nscolor *aStopColor, + float *aStopOpacity) +{ + nsIContent* stopContent = aStopFrame->GetContent(); + MOZ_ASSERT(stopContent && stopContent->IsSVG(nsGkAtoms::stop)); + + static_cast(stopContent)-> + GetAnimatedNumberValues(aOffset, nullptr); + + *aOffset = mozilla::clamped(*aOffset, 0.0f, 1.0f); + *aStopColor = aStopFrame->StyleSVGReset()->mStopColor; + *aStopOpacity = aStopFrame->StyleSVGReset()->mStopOpacity; +} + already_AddRefed nsSVGGradientFrame::GetPaintServerPattern(nsIFrame *aSource, const gfxMatrix& aContextMatrix, @@ -244,7 +223,10 @@ nsSVGGradientFrame::GetPaintServerPattern(nsIFrame *aSource, aSource->GetParent() : aSource; } - uint32_t nStops = GetStopCount(); + nsAutoTArray stopFrames; + GetStopFrames(&stopFrames); + + uint32_t nStops = stopFrames.Length(); // SVG specification says that no stops should be treated like // the corresponding fill or stroke had "none" specified. @@ -252,13 +234,13 @@ nsSVGGradientFrame::GetPaintServerPattern(nsIFrame *aSource, nsRefPtr pattern = new gfxPattern(gfxRGBA(0, 0, 0, 0)); return pattern.forget(); } - // If the gradient is a single colour, - // use the last gradient stop colour as the colour. - if (IsSingleColour(nStops)) { - float offset, stopOpacity; - nscolor stopColor; - GetStopInformation(nStops - 1, &offset, &stopColor, &stopOpacity); + if (nStops == 1 || GradientVectorLengthIsZero()) { + // The gradient paints a single colour, using the stop-color of the last + // gradient step if there are more than one. + float stopOpacity = stopFrames[nStops-1]->StyleSVGReset()->mStopOpacity; + nscolor stopColor = stopFrames[nStops-1]->StyleSVGReset()->mStopColor; + nsRefPtr pattern = new gfxPattern( gfxRGBA(NS_GET_R(stopColor)/255.0, NS_GET_G(stopColor)/255.0, @@ -305,7 +287,7 @@ nsSVGGradientFrame::GetPaintServerPattern(nsIFrame *aSource, float offset, stopOpacity; nscolor stopColor; - GetStopInformation(i, &offset, &stopColor, &stopOpacity); + GetStopInformation(stopFrames[i], &offset, &stopColor, &stopOpacity); if (offset < lastOffset) offset = lastOffset; @@ -384,33 +366,29 @@ nsSVGGradientFrame::GetReferencedGradientIfNotInUse() return referenced; } -int32_t -nsSVGGradientFrame::GetStopFrame(int32_t aIndex, nsIFrame * *aStopFrame) +void +nsSVGGradientFrame::GetStopFrames(nsTArray* aStopFrames) { - int32_t stopCount = 0; nsIFrame *stopFrame = nullptr; for (stopFrame = mFrames.FirstChild(); stopFrame; stopFrame = stopFrame->GetNextSibling()) { if (stopFrame->GetType() == nsGkAtoms::svgStopFrame) { - // Is this the one we're looking for? - if (stopCount++ == aIndex) - break; // Yes, break out of the loop + aStopFrames->AppendElement(stopFrame); } } - if (stopCount > 0) { - if (aStopFrame) - *aStopFrame = stopFrame; - return stopCount; + if (aStopFrames->Length() > 0) { + return; } // Our gradient element doesn't have stops - try to "inherit" them AutoGradientReferencer gradientRef(this); nsSVGGradientFrame* next = GetReferencedGradientIfNotInUse(); - if (!next) - return 0; + if (!next) { + return; + } - return next->GetStopFrame(aIndex, aStopFrame); + return next->GetStopFrames(aStopFrames); } // ------------------------------------------------------------------------- @@ -500,15 +478,12 @@ nsSVGLinearGradientFrame::GetLinearGradientWithLength(uint32_t aIndex, } bool -nsSVGLinearGradientFrame::IsSingleColour(uint32_t nStops) +nsSVGLinearGradientFrame::GradientVectorLengthIsZero() { - NS_ABORT_IF_FALSE(nStops == GetStopCount(), "Unexpected number of stops"); - - return nStops == 1 || - (GetLengthValue(dom::SVGLinearGradientElement::ATTR_X1) == - GetLengthValue(dom::SVGLinearGradientElement::ATTR_X2) && - GetLengthValue(dom::SVGLinearGradientElement::ATTR_Y1) == - GetLengthValue(dom::SVGLinearGradientElement::ATTR_Y2)); + return GetLengthValue(dom::SVGLinearGradientElement::ATTR_X1) == + GetLengthValue(dom::SVGLinearGradientElement::ATTR_X2) && + GetLengthValue(dom::SVGLinearGradientElement::ATTR_Y1) == + GetLengthValue(dom::SVGLinearGradientElement::ATTR_Y2); } already_AddRefed @@ -630,12 +605,9 @@ nsSVGRadialGradientFrame::GetRadialGradientWithLength(uint32_t aIndex, } bool -nsSVGRadialGradientFrame::IsSingleColour(uint32_t nStops) +nsSVGRadialGradientFrame::GradientVectorLengthIsZero() { - NS_ABORT_IF_FALSE(nStops == GetStopCount(), "Unexpected number of stops"); - - return nStops == 1 || - GetLengthValue(dom::SVGRadialGradientElement::ATTR_R) == 0; + return GetLengthValue(dom::SVGRadialGradientElement::ATTR_R) == 0; } already_AddRefed diff --git a/layout/svg/nsSVGGradientFrame.h b/layout/svg/nsSVGGradientFrame.h index 203d7fd1d6c..efae068d551 100644 --- a/layout/svg/nsSVGGradientFrame.h +++ b/layout/svg/nsSVGGradientFrame.h @@ -72,10 +72,7 @@ private: nsSVGGradientFrame* GetReferencedGradient(); // Optionally get a stop frame (returns stop index/count) - int32_t GetStopFrame(int32_t aIndex, nsIFrame * *aStopFrame); - - void GetStopInformation(int32_t aIndex, - float *aOffset, nscolor *aColor, float *aStopOpacity); + void GetStopFrames(nsTArray* aStopFrames); const mozilla::nsSVGAnimatedTransformList* GetGradientTransformList( nsIContent* aDefault); @@ -84,8 +81,7 @@ private: const gfxRect *aOverrideBounds); protected: - uint32_t GetStopCount(); - virtual bool IsSingleColour(uint32_t nStops) = 0; + virtual bool GradientVectorLengthIsZero() = 0; virtual already_AddRefed CreateGradient() = 0; // Internal methods for handling referenced gradients @@ -163,7 +159,7 @@ protected: float GetLengthValue(uint32_t aIndex); virtual mozilla::dom::SVGLinearGradientElement* GetLinearGradientWithLength( uint32_t aIndex, mozilla::dom::SVGLinearGradientElement* aDefault); - virtual bool IsSingleColour(uint32_t nStops); + virtual bool GradientVectorLengthIsZero(); virtual already_AddRefed CreateGradient(); }; @@ -211,7 +207,7 @@ protected: mozilla::dom::SVGRadialGradientElement& aElement); virtual mozilla::dom::SVGRadialGradientElement* GetRadialGradientWithLength( uint32_t aIndex, mozilla::dom::SVGRadialGradientElement* aDefault); - virtual bool IsSingleColour(uint32_t nStops); + virtual bool GradientVectorLengthIsZero(); virtual already_AddRefed CreateGradient(); }; From 8a68ce4b842fb7c4cc034dad77e63f2ee99cec43 Mon Sep 17 00:00:00 2001 From: Jon Coppeard Date: Mon, 27 May 2013 12:50:49 +0100 Subject: [PATCH 17/20] Bug 874691 - Make CC participant tracing indirect r=mccr8 r=smaug r=bz --- content/base/public/nsContentUtils.h | 2 - content/base/public/nsINode.h | 4 +- content/base/src/Attr.cpp | 2 +- content/base/src/FragmentOrElement.cpp | 2 +- content/base/src/nsContentUtils.cpp | 15 +- content/base/src/nsDocument.cpp | 12 +- content/base/src/nsGenericDOMDataNode.cpp | 2 +- content/base/src/nsINode.cpp | 4 +- content/xbl/src/nsXBLDocumentInfo.cpp | 8 +- content/xbl/src/nsXBLProtoImpl.cpp | 4 +- content/xbl/src/nsXBLProtoImpl.h | 2 +- content/xbl/src/nsXBLProtoImplMember.h | 2 +- content/xbl/src/nsXBLProtoImplMethod.cpp | 4 +- content/xbl/src/nsXBLProtoImplMethod.h | 2 +- content/xbl/src/nsXBLProtoImplProperty.cpp | 8 +- content/xbl/src/nsXBLProtoImplProperty.h | 2 +- content/xbl/src/nsXBLPrototypeBinding.cpp | 4 +- content/xbl/src/nsXBLPrototypeBinding.h | 2 +- content/xul/content/src/nsXULElement.cpp | 4 +- content/xul/content/src/nsXULElement.h | 7 + dom/base/nsGlobalWindow.cpp | 13 +- dom/base/nsJSEnvironment.cpp | 12 +- dom/base/nsWrapperCache.h | 14 +- dom/base/nsWrapperCacheInlines.h | 2 +- js/xpconnect/src/XPCJSRuntime.cpp | 28 ++-- layout/style/StyleRule.cpp | 2 +- layout/style/nsCSSRules.cpp | 2 +- xpcom/glue/nsCycleCollectionParticipant.cpp | 36 ++++- xpcom/glue/nsCycleCollectionParticipant.h | 143 ++++++++++++-------- 29 files changed, 210 insertions(+), 134 deletions(-) diff --git a/content/base/public/nsContentUtils.h b/content/base/public/nsContentUtils.h index edad732f581..8f7797e4940 100644 --- a/content/base/public/nsContentUtils.h +++ b/content/base/public/nsContentUtils.h @@ -1306,8 +1306,6 @@ public: } static void ReleaseWrapper(void* aScriptObjectHolder, nsWrapperCache* aCache); - static void TraceWrapper(nsWrapperCache* aCache, TraceCallback aCallback, - void *aClosure); /* * Notify when the first XUL menu is opened and when the all XUL menus are diff --git a/content/base/public/nsINode.h b/content/base/public/nsINode.h index cb579efe0f9..ec0b699eae3 100644 --- a/content/base/public/nsINode.h +++ b/content/base/public/nsINode.h @@ -1725,10 +1725,10 @@ public: #include "nsEventNameList.h" #undef DOCUMENT_ONLY_EVENT #undef TOUCH_EVENT -#undef EVENT +#undef EVENT protected: - static void Trace(nsINode *tmp, TraceCallback cb, void *closure); + static void Trace(nsINode *tmp, const TraceCallbacks &cb, void *closure); static bool Traverse(nsINode *tmp, nsCycleCollectionTraversalCallback &cb); static void Unlink(nsINode *tmp); diff --git a/content/base/src/Attr.cpp b/content/base/src/Attr.cpp index 1ea7e5d3579..84b85e195db 100644 --- a/content/base/src/Attr.cpp +++ b/content/base/src/Attr.cpp @@ -67,7 +67,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Attr) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(Attr) - nsINode::Trace(tmp, aCallback, aClosure); + nsINode::Trace(tmp, aCallbacks, aClosure); NS_IMPL_CYCLE_COLLECTION_TRACE_END NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Attr) diff --git a/content/base/src/FragmentOrElement.cpp b/content/base/src/FragmentOrElement.cpp index ee55537c961..0d44596c28a 100644 --- a/content/base/src/FragmentOrElement.cpp +++ b/content/base/src/FragmentOrElement.cpp @@ -1157,7 +1157,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(FragmentOrElement) NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(FragmentOrElement) - nsINode::Trace(tmp, aCallback, aClosure); + nsINode::Trace(tmp, aCallbacks, aClosure); NS_IMPL_CYCLE_COLLECTION_TRACE_END void diff --git a/content/base/src/nsContentUtils.cpp b/content/base/src/nsContentUtils.cpp index 8ca51a35d43..858fb3e020f 100644 --- a/content/base/src/nsContentUtils.cpp +++ b/content/base/src/nsContentUtils.cpp @@ -5909,7 +5909,7 @@ nsContentUtils::CheckCCWrapperTraversal(void* aScriptObjectHolder, "wrapper! This will probably crash."); callback.mFound = false; - aTracer->Trace(aScriptObjectHolder, DebugWrapperTraceCallback, &callback); + aTracer->Trace(aScriptObjectHolder, TraceCallbackFunc(DebugWrapperTraceCallback), &callback); MOZ_ASSERT(callback.mFound, "Cycle collection participant didn't trace preserved wrapper! " "This will probably crash."); @@ -6436,19 +6436,6 @@ nsContentUtils::ReleaseWrapper(void* aScriptObjectHolder, } } -// static -void -nsContentUtils::TraceWrapper(nsWrapperCache* aCache, TraceCallback aCallback, - void *aClosure) -{ - if (aCache->PreservingWrapper()) { - JSObject *wrapper = aCache->GetWrapperPreserveColor(); - if (wrapper) { - aCallback(wrapper, "Preserved wrapper", aClosure); - } - } -} - // static int32_t nsContentUtils::GetAdjustedOffsetInTextControl(nsIFrame* aOffsetFrame, diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index 80a75c381b4..03cff518802 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -1782,28 +1782,28 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END struct CustomPrototypeTraceArgs { - TraceCallback callback; + const TraceCallbacks& callbacks; void* closure; }; static PLDHashOperator -CustomPrototypeTrace(const nsAString& aName, JSObject* aObject, void *aArg) +CustomPrototypeTrace(const nsAString& aName, JSObject*& aObject, void *aArg) { CustomPrototypeTraceArgs* traceArgs = static_cast(aArg); MOZ_ASSERT(aObject, "Protocol object value must not be null"); - traceArgs->callback(aObject, "mCustomPrototypes entry", traceArgs->closure); + traceArgs->callbacks.Trace(&aObject, "mCustomPrototypes entry", traceArgs->closure); return PL_DHASH_NEXT; } NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsDocument) - CustomPrototypeTraceArgs customPrototypeArgs = { aCallback, aClosure }; - tmp->mCustomPrototypes.EnumerateRead(CustomPrototypeTrace, &customPrototypeArgs); + CustomPrototypeTraceArgs customPrototypeArgs = { aCallbacks, aClosure }; + tmp->mCustomPrototypes.Enumerate(CustomPrototypeTrace, &customPrototypeArgs); if (tmp->PreservingWrapper()) { NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK(mExpandoAndGeneration.expando); } - nsINode::Trace(tmp, aCallback, aClosure); + nsINode::Trace(tmp, aCallbacks, aClosure); NS_IMPL_CYCLE_COLLECTION_TRACE_END diff --git a/content/base/src/nsGenericDOMDataNode.cpp b/content/base/src/nsGenericDOMDataNode.cpp index 0ad37548bd1..ccfb78081e0 100644 --- a/content/base/src/nsGenericDOMDataNode.cpp +++ b/content/base/src/nsGenericDOMDataNode.cpp @@ -63,7 +63,7 @@ nsGenericDOMDataNode::~nsGenericDOMDataNode() } NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsGenericDOMDataNode) - nsINode::Trace(tmp, aCallback, aClosure); + nsINode::Trace(tmp, aCallbacks, aClosure); NS_IMPL_CYCLE_COLLECTION_TRACE_END NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsGenericDOMDataNode) diff --git a/content/base/src/nsINode.cpp b/content/base/src/nsINode.cpp index b9ee345e9d2..845e01165ec 100644 --- a/content/base/src/nsINode.cpp +++ b/content/base/src/nsINode.cpp @@ -1165,9 +1165,9 @@ nsINode::GetContextForEventHandlers(nsresult* aRv) /* static */ void -nsINode::Trace(nsINode *tmp, TraceCallback cb, void *closure) +nsINode::Trace(nsINode *tmp, const TraceCallbacks& cb, void *closure) { - nsContentUtils::TraceWrapper(tmp, cb, closure); + tmp->TraceWrapper(cb, closure); } diff --git a/content/xbl/src/nsXBLDocumentInfo.cpp b/content/xbl/src/nsXBLDocumentInfo.cpp index 096eea486f5..c74df251619 100644 --- a/content/xbl/src/nsXBLDocumentInfo.cpp +++ b/content/xbl/src/nsXBLDocumentInfo.cpp @@ -412,7 +412,7 @@ UnlinkProtoJSObjects(nsHashKey *aKey, void *aData, void* aClosure) struct ProtoTracer { - TraceCallback mCallback; + const TraceCallbacks &mCallbacks; void *mClosure; }; @@ -421,7 +421,7 @@ TraceProtos(nsHashKey *aKey, void *aData, void* aClosure) { ProtoTracer* closure = static_cast(aClosure); nsXBLPrototypeBinding *proto = static_cast(aData); - proto->Trace(closure->mCallback, closure->mClosure); + proto->Trace(closure->mCallbacks, closure->mClosure); return kHashEnumerateNext; } @@ -448,7 +448,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXBLDocumentInfo) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsXBLDocumentInfo) if (tmp->mBindingTable) { - ProtoTracer closure = { aCallback, aClosure }; + ProtoTracer closure = { aCallbacks, aClosure }; tmp->mBindingTable->Enumerate(TraceProtos, &closure); } NS_IMPL_CYCLE_COLLECTION_TRACE_END @@ -463,7 +463,7 @@ static bool UnmarkProtos(nsHashKey* aKey, void* aData, void* aClosure) { nsXBLPrototypeBinding* proto = static_cast(aData); - proto->Trace(UnmarkXBLJSObject, nullptr); + proto->Trace(TraceCallbackFunc(UnmarkXBLJSObject), nullptr); return kHashEnumerateNext; } diff --git a/content/xbl/src/nsXBLProtoImpl.cpp b/content/xbl/src/nsXBLProtoImpl.cpp index 82d30984f6a..9d97766c2f3 100644 --- a/content/xbl/src/nsXBLProtoImpl.cpp +++ b/content/xbl/src/nsXBLProtoImpl.cpp @@ -261,7 +261,7 @@ nsXBLProtoImpl::LookupMember(JSContext* aCx, nsString& aName, } void -nsXBLProtoImpl::Trace(TraceCallback aCallback, void *aClosure) const +nsXBLProtoImpl::Trace(const TraceCallbacks& aCallbacks, void *aClosure) { // If we don't have a class object then we either didn't compile members // or we only have fields, in both cases there are no cycles through our @@ -272,7 +272,7 @@ nsXBLProtoImpl::Trace(TraceCallback aCallback, void *aClosure) const nsXBLProtoImplMember *member; for (member = mMembers; member; member = member->GetNext()) { - member->Trace(aCallback, aClosure); + member->Trace(aCallbacks, aClosure); } } diff --git a/content/xbl/src/nsXBLProtoImpl.h b/content/xbl/src/nsXBLProtoImpl.h index 5da8d8aad47..96349d8d951 100644 --- a/content/xbl/src/nsXBLProtoImpl.h +++ b/content/xbl/src/nsXBLProtoImpl.h @@ -60,7 +60,7 @@ public: mFields = aFieldList; } - void Trace(TraceCallback aCallback, void *aClosure) const; + void Trace(const TraceCallbacks& aCallbacks, void *aClosure); void UnlinkJSObjects(); nsXBLProtoImplField* FindField(const nsString& aFieldName) const; diff --git a/content/xbl/src/nsXBLProtoImplMember.h b/content/xbl/src/nsXBLProtoImplMember.h index 7732eb1974a..8f3134dabb3 100644 --- a/content/xbl/src/nsXBLProtoImplMember.h +++ b/content/xbl/src/nsXBLProtoImplMember.h @@ -79,7 +79,7 @@ public: const nsCString& aClassStr, JS::Handle aClassObject) = 0; - virtual void Trace(TraceCallback aCallback, void *aClosure) const = 0; + virtual void Trace(const TraceCallbacks& aCallbacks, void *aClosure) = 0; virtual nsresult Write(nsIScriptContext* aContext, nsIObjectOutputStream* aStream) diff --git a/content/xbl/src/nsXBLProtoImplMethod.cpp b/content/xbl/src/nsXBLProtoImplMethod.cpp index fe427aa6cf1..bac7d5df57d 100644 --- a/content/xbl/src/nsXBLProtoImplMethod.cpp +++ b/content/xbl/src/nsXBLProtoImplMethod.cpp @@ -225,10 +225,10 @@ nsXBLProtoImplMethod::CompileMember(nsIScriptContext* aContext, const nsCString& } void -nsXBLProtoImplMethod::Trace(TraceCallback aCallback, void *aClosure) const +nsXBLProtoImplMethod::Trace(const TraceCallbacks& aCallbacks, void *aClosure) { if (IsCompiled() && mJSMethodObject) { - aCallback(mJSMethodObject, "mJSMethodObject", aClosure); + aCallbacks.Trace(&mJSMethodObject, "mJSMethodObject", aClosure); } } diff --git a/content/xbl/src/nsXBLProtoImplMethod.h b/content/xbl/src/nsXBLProtoImplMethod.h index 9ddd40dd14d..59e745bd211 100644 --- a/content/xbl/src/nsXBLProtoImplMethod.h +++ b/content/xbl/src/nsXBLProtoImplMethod.h @@ -94,7 +94,7 @@ public: const nsCString& aClassStr, JS::Handle aClassObject); - virtual void Trace(TraceCallback aCallback, void *aClosure) const; + virtual void Trace(const TraceCallbacks& aCallbacks, void *aClosure); nsresult Read(nsIScriptContext* aContext, nsIObjectInputStream* aStream); virtual nsresult Write(nsIScriptContext* aContext, nsIObjectOutputStream* aStream); diff --git a/content/xbl/src/nsXBLProtoImplProperty.cpp b/content/xbl/src/nsXBLProtoImplProperty.cpp index 91ad1ae77e7..422ad9d4c20 100644 --- a/content/xbl/src/nsXBLProtoImplProperty.cpp +++ b/content/xbl/src/nsXBLProtoImplProperty.cpp @@ -295,19 +295,19 @@ nsXBLProtoImplProperty::CompileMember(nsIScriptContext* aContext, const nsCStrin #ifdef DEBUG mIsCompiled = NS_SUCCEEDED(rv); #endif - + return rv; } void -nsXBLProtoImplProperty::Trace(TraceCallback aCallback, void *aClosure) const +nsXBLProtoImplProperty::Trace(const TraceCallbacks& aCallbacks, void *aClosure) { if (mJSAttributes & JSPROP_GETTER) { - aCallback(mJSGetterObject, "mJSGetterObject", aClosure); + aCallbacks.Trace(&mJSGetterObject, "mJSGetterObject", aClosure); } if (mJSAttributes & JSPROP_SETTER) { - aCallback(mJSSetterObject, "mJSSetterObject", aClosure); + aCallbacks.Trace(&mJSSetterObject, "mJSSetterObject", aClosure); } } diff --git a/content/xbl/src/nsXBLProtoImplProperty.h b/content/xbl/src/nsXBLProtoImplProperty.h index d087a914033..087b2d1cddb 100644 --- a/content/xbl/src/nsXBLProtoImplProperty.h +++ b/content/xbl/src/nsXBLProtoImplProperty.h @@ -38,7 +38,7 @@ public: const nsCString& aClassStr, JS::Handle aClassObject); - virtual void Trace(TraceCallback aCallback, void *aClosure) const; + virtual void Trace(const TraceCallbacks& aCallback, void *aClosure); nsresult Read(nsIScriptContext* aContext, nsIObjectInputStream* aStream, diff --git a/content/xbl/src/nsXBLPrototypeBinding.cpp b/content/xbl/src/nsXBLPrototypeBinding.cpp index 9c802e7ac8a..e5023c97b8b 100644 --- a/content/xbl/src/nsXBLPrototypeBinding.cpp +++ b/content/xbl/src/nsXBLPrototypeBinding.cpp @@ -271,10 +271,10 @@ nsXBLPrototypeBinding::UnlinkJSObjects() } void -nsXBLPrototypeBinding::Trace(TraceCallback aCallback, void *aClosure) const +nsXBLPrototypeBinding::Trace(const TraceCallbacks& aCallbacks, void *aClosure) const { if (mImplementation) - mImplementation->Trace(aCallback, aClosure); + mImplementation->Trace(aCallbacks, aClosure); } void diff --git a/content/xbl/src/nsXBLPrototypeBinding.h b/content/xbl/src/nsXBLPrototypeBinding.h index d143a8b9d20..da6deeeee1d 100644 --- a/content/xbl/src/nsXBLPrototypeBinding.h +++ b/content/xbl/src/nsXBLPrototypeBinding.h @@ -283,7 +283,7 @@ public: void Traverse(nsCycleCollectionTraversalCallback &cb) const; void UnlinkJSObjects(); - void Trace(TraceCallback aCallback, void *aClosure) const; + void Trace(const TraceCallbacks& aCallbacks, void *aClosure) const; // Internal member functions. // XXXbz GetImmediateChild needs to be public to be called by SetAttrs, diff --git a/content/xul/content/src/nsXULElement.cpp b/content/xul/content/src/nsXULElement.cpp index bbece95c99d..73c6d07e631 100644 --- a/content/xul/content/src/nsXULElement.cpp +++ b/content/xul/content/src/nsXULElement.cpp @@ -1966,9 +1966,7 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsXULPrototypeNode) if (tmp->mType == nsXULPrototypeNode::eType_Script) { nsXULPrototypeScript *script = static_cast(tmp); - NS_IMPL_CYCLE_COLLECTION_TRACE_JS_CALLBACK(script->GetScriptObject(), - "mScriptObject") - + script->Trace(aCallbacks, aClosure); } NS_IMPL_CYCLE_COLLECTION_TRACE_END diff --git a/content/xul/content/src/nsXULElement.h b/content/xul/content/src/nsXULElement.h index 16b927cf449..89ea4c7f56f 100644 --- a/content/xul/content/src/nsXULElement.h +++ b/content/xul/content/src/nsXULElement.h @@ -252,6 +252,13 @@ public: } } + void Trace(const TraceCallbacks& aCallbacks, void* aClosure) + { + if (mScriptObject) { + aCallbacks.Trace(&mScriptObject, "mScriptObject", aClosure); + } + } + nsCOMPtr mSrcURI; uint32_t mLineNo; bool mSrcLoading; diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index af35cffc3aa..a490b44c6e3 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -1728,25 +1728,22 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END struct TraceData { - TraceData(TraceCallback& aCallback, void* aClosure) : - callback(aCallback), closure(aClosure) {} - - TraceCallback& callback; + const TraceCallbacks& callbacks; void* closure; }; static PLDHashOperator -TraceXBLHandlers(nsXBLPrototypeHandler* aKey, JSObject* aData, void* aClosure) +TraceXBLHandlers(nsXBLPrototypeHandler* aKey, JSObject*& aData, void* aClosure) { TraceData* data = static_cast(aClosure); - data->callback(aData, "Cached XBL prototype handler", data->closure); + data->callbacks.Trace(&aData, "Cached XBL prototype handler", data->closure); return PL_DHASH_NEXT; } NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsGlobalWindow) if (tmp->mCachedXBLPrototypeHandlers.IsInitialized()) { - TraceData data(aCallback, aClosure); - tmp->mCachedXBLPrototypeHandlers.EnumerateRead(TraceXBLHandlers, &data); + TraceData data = { aCallbacks, aClosure }; + tmp->mCachedXBLPrototypeHandlers.Enumerate(TraceXBLHandlers, &data); } NS_IMPL_CYCLE_COLLECTION_TRACE_END diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index 66597996435..2c534877826 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -3581,14 +3581,10 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsJSArgArray) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsJSArgArray) - JS::Value *argv = tmp->mArgv; - if (argv) { - JS::Value *end; - for (end = argv + tmp->mArgc; argv < end; ++argv) { - if (JSVAL_IS_GCTHING(*argv)) - NS_IMPL_CYCLE_COLLECTION_TRACE_JS_CALLBACK(JSVAL_TO_GCTHING(*argv), - "mArgv[i]") - } + if (tmp->mArgv) { + for (uint32_t i = 0; i < tmp->mArgc; ++i) { + NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK(mArgv[i]) + } } NS_IMPL_CYCLE_COLLECTION_TRACE_END diff --git a/dom/base/nsWrapperCache.h b/dom/base/nsWrapperCache.h index 64fcb9f82e8..515a95aa28c 100644 --- a/dom/base/nsWrapperCache.h +++ b/dom/base/nsWrapperCache.h @@ -179,6 +179,18 @@ public: } } + void TraceWrapper(const TraceCallbacks& aCallbacks, void* aClosure) + { + if (PreservingWrapper()) { + JSObject *wrapper = GetWrapperPreserveColor(); + if (wrapper) { + uintptr_t flags = mWrapperPtrBits & kWrapperBitMask; + aCallbacks.Trace(&wrapper, "Preserved wrapper", aClosure); + mWrapperPtrBits = reinterpret_cast(wrapper) | flags; + } + } + } + private: JSObject *GetJSObjectFromBits() const { @@ -236,7 +248,7 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsWrapperCache, NS_WRAPPERCACHE_IID) // Cycle collector macros for wrapper caches. #define NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER \ - nsContentUtils::TraceWrapper(tmp, aCallback, aClosure); + tmp->TraceWrapper(aCallbacks, aClosure); #define NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER \ nsContentUtils::ReleaseWrapper(p, tmp); diff --git a/dom/base/nsWrapperCacheInlines.h b/dom/base/nsWrapperCacheInlines.h index b2280ead7f9..1f3dabd32da 100644 --- a/dom/base/nsWrapperCacheInlines.h +++ b/dom/base/nsWrapperCacheInlines.h @@ -51,7 +51,7 @@ nsWrapperCache::IsBlackAndDoesNotNeedTracing(nsISupports* aThis) nsXPCOMCycleCollectionParticipant* participant = nullptr; CallQueryInterface(aThis, &participant); bool hasGrayObjects = false; - participant->Trace(aThis, SearchGray, &hasGrayObjects); + participant->Trace(aThis, TraceCallbackFunc(SearchGray), &hasGrayObjects); return !hasGrayObjects; } return false; diff --git a/js/xpconnect/src/XPCJSRuntime.cpp b/js/xpconnect/src/XPCJSRuntime.cpp index 51fa079f4fd..1b6cede0433 100644 --- a/js/xpconnect/src/XPCJSRuntime.cpp +++ b/js/xpconnect/src/XPCJSRuntime.cpp @@ -345,7 +345,7 @@ XPCJSRuntime::AssertNoObjectsToTrace(void* aPossibleJSHolder) { nsScriptObjectTracer* tracer = mJSHolders.Get(aPossibleJSHolder); if (tracer && tracer->Trace) { - tracer->Trace(aPossibleJSHolder, AssertNoGcThing, nullptr); + tracer->Trace(aPossibleJSHolder, TraceCallbackFunc(AssertNoGcThing), nullptr); } } #endif @@ -411,16 +411,29 @@ void XPCJSRuntime::TraceGrayJS(JSTracer* trc, void* data) self->TraceXPConnectRoots(trc); } -static void -TraceJSObject(void *aScriptThing, const char *name, void *aClosure) +struct JsGcTracer : public TraceCallbacks { - JS_CallGenericTracer(static_cast(aClosure), aScriptThing, name); -} + virtual void Trace(JS::Value *p, const char *name, void *closure) const MOZ_OVERRIDE { + JS_CallValueTracer(static_cast(closure), p, name); + } + virtual void Trace(jsid *p, const char *name, void *closure) const MOZ_OVERRIDE { + JS_CallIdTracer(static_cast(closure), p, name); + } + virtual void Trace(JSObject **p, const char *name, void *closure) const MOZ_OVERRIDE { + JS_CallObjectTracer(static_cast(closure), p, name); + } + virtual void Trace(JSString **p, const char *name, void *closure) const MOZ_OVERRIDE { + JS_CallStringTracer(static_cast(closure), p, name); + } + virtual void Trace(JSScript **p, const char *name, void *closure) const MOZ_OVERRIDE { + JS_CallScriptTracer(static_cast(closure), p, name); + } +}; static PLDHashOperator TraceJSHolder(void *holder, nsScriptObjectTracer *&tracer, void *arg) { - tracer->Trace(holder, TraceJSObject, arg); + tracer->Trace(holder, JsGcTracer(), arg); return PL_DHASH_NEXT; } @@ -474,8 +487,7 @@ NoteJSHolder(void *holder, nsScriptObjectTracer *&tracer, void *arg) Closure *closure = static_cast(arg); closure->cycleCollectionEnabled = false; - tracer->Trace(holder, CheckParticipatesInCycleCollection, - closure); + tracer->Trace(holder, TraceCallbackFunc(CheckParticipatesInCycleCollection), closure); if (closure->cycleCollectionEnabled) closure->cb->NoteNativeRoot(holder, tracer); diff --git a/layout/style/StyleRule.cpp b/layout/style/StyleRule.cpp index 3e070a680d8..69f67a61f2b 100644 --- a/layout/style/StyleRule.cpp +++ b/layout/style/StyleRule.cpp @@ -1164,7 +1164,7 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(DOMCSSStyleRule) // Trace the wrapper for our declaration. This just expands out // NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER which we can't use // directly because the wrapper is on the declaration, not on us. - nsContentUtils::TraceWrapper(tmp->DOMDeclaration(), aCallback, aClosure); + tmp->DOMDeclaration()->TraceWrapper(aCallbacks, aClosure); NS_IMPL_CYCLE_COLLECTION_TRACE_END NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMCSSStyleRule) diff --git a/layout/style/nsCSSRules.cpp b/layout/style/nsCSSRules.cpp index c5efbc0af69..1016bf9d2db 100644 --- a/layout/style/nsCSSRules.cpp +++ b/layout/style/nsCSSRules.cpp @@ -1766,7 +1766,7 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsCSSFontFaceRule) // Trace the wrapper for our declaration. This just expands out // NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER which we can't use // directly because the wrapper is on the declaration, not on us. - nsContentUtils::TraceWrapper(&tmp->mDecl, aCallback, aClosure); + tmp->mDecl.TraceWrapper(aCallbacks, aClosure); NS_IMPL_CYCLE_COLLECTION_TRACE_END NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsCSSFontFaceRule) diff --git a/xpcom/glue/nsCycleCollectionParticipant.cpp b/xpcom/glue/nsCycleCollectionParticipant.cpp index ebbbed97a5c..7577c101f74 100644 --- a/xpcom/glue/nsCycleCollectionParticipant.cpp +++ b/xpcom/glue/nsCycleCollectionParticipant.cpp @@ -5,6 +5,7 @@ #include "nsCycleCollectionParticipant.h" #include "nsCOMPtr.h" +#include "jsapi.h" #ifdef MOZILLA_INTERNAL_API #include "nsString.h" @@ -41,7 +42,7 @@ nsXPCOMCycleCollectionParticipant::UnrootImpl(void *p) // We define a default trace function because some participants don't need // to trace anything, so it is okay for them not to define one. NS_IMETHODIMP_(void) -nsXPCOMCycleCollectionParticipant::TraceImpl(void *p, TraceCallback cb, +nsXPCOMCycleCollectionParticipant::TraceImpl(void *p, const TraceCallbacks &cb, void *closure) { } @@ -66,3 +67,36 @@ CycleCollectionNoteEdgeNameImpl(nsCycleCollectionTraversalCallback& aCallback, } aCallback.NoteNextEdgeName(arrayEdgeName.get()); } + +void +TraceCallbackFunc::Trace(JS::Value* p, const char* name, void* closure) const +{ + mCallback(JSVAL_TO_TRACEABLE(*p), name, closure); +} + +void +TraceCallbackFunc::Trace(jsid* p, const char* name, void* closure) const +{ + void *thing = JSID_TO_GCTHING(*p); + if (thing) { + mCallback(thing, name, closure); + } +} + +void +TraceCallbackFunc::Trace(JSObject** p, const char* name, void* closure) const +{ + mCallback(*p, name, closure); +} + +void +TraceCallbackFunc::Trace(JSString** p, const char* name, void* closure) const +{ + mCallback(*p, name, closure); +} + +void +TraceCallbackFunc::Trace(JSScript** p, const char* name, void* closure) const +{ + mCallback(*p, name, closure); +} diff --git a/xpcom/glue/nsCycleCollectionParticipant.h b/xpcom/glue/nsCycleCollectionParticipant.h index 6b60adeefe6..59576a185b1 100644 --- a/xpcom/glue/nsCycleCollectionParticipant.h +++ b/xpcom/glue/nsCycleCollectionParticipant.h @@ -7,6 +7,7 @@ #define nsCycleCollectionParticipant_h__ #include "nsCycleCollectionNoteChild.h" +#include "jspubtd.h" #define NS_CYCLECOLLECTIONPARTICIPANT_IID \ { \ @@ -40,7 +41,7 @@ public: NS_DECLARE_STATIC_IID_ACCESSOR(NS_CYCLECOLLECTIONISUPPORTS_IID) }; -NS_DEFINE_STATIC_IID_ACCESSOR(nsCycleCollectionISupports, +NS_DEFINE_STATIC_IID_ACCESSOR(nsCycleCollectionISupports, NS_CYCLECOLLECTIONISUPPORTS_IID) /** @@ -50,8 +51,43 @@ class nsCycleCollectionParticipant; class nsScriptObjectTracer; class nsXPCOMCycleCollectionParticipant; -typedef void -(* TraceCallback)(void *p, const char* name, void *closure); +/* + * A struct defining pure virtual methods which are called when tracing cycle + * collection paticipants. The appropriate method is called depending on the + * type of JS GC thing. + */ +struct TraceCallbacks +{ + virtual void Trace(JS::Value* p, const char* name, void* closure) const = 0; + virtual void Trace(jsid* p, const char* name, void* closure) const = 0; + virtual void Trace(JSObject** p, const char* name, void* closure) const = 0; + virtual void Trace(JSString** p, const char* name, void* closure) const = 0; + virtual void Trace(JSScript** p, const char* name, void* closure) const = 0; + + void Trace(JSFlatString** p, const char* name, void* closure) const { + Trace(reinterpret_cast(p), name, closure); + } +}; + +/* + * An implementation of TraceCallbacks that calls a single function for all JS + * GC thing types encountered. + */ +struct TraceCallbackFunc : public TraceCallbacks +{ + typedef void (* Func)(void* p, const char* name, void* closure); + + explicit TraceCallbackFunc(Func cb) : mCallback(cb) {} + + virtual void Trace(JS::Value* p, const char* name, void* closure) const MOZ_OVERRIDE; + virtual void Trace(jsid* p, const char* name, void* closure) const MOZ_OVERRIDE; + virtual void Trace(JSObject** p, const char* name, void* closure) const MOZ_OVERRIDE; + virtual void Trace(JSString** p, const char* name, void* closure) const MOZ_OVERRIDE; + virtual void Trace(JSScript** p, const char* name, void* closure) const MOZ_OVERRIDE; + + private: + Func mCallback; +}; /** * VTables @@ -100,7 +136,7 @@ typedef nsCycleCollectionParticipantVTableCommon /* Additional functions for nsScriptObjectTracer */ struct nsScriptObjectTracerVTable { - void (NS_STDCALL *Trace)(void *p, TraceCallback cb, void *closure); + void (NS_STDCALL *Trace)(void *p, const TraceCallbacks &cb, void *closure); }; /** @@ -226,7 +262,7 @@ public: } }; -NS_DEFINE_STATIC_IID_ACCESSOR(nsCycleCollectionParticipant, +NS_DEFINE_STATIC_IID_ACCESSOR(nsCycleCollectionParticipant, NS_CYCLECOLLECTIONPARTICIPANT_IID) class nsScriptObjectTracer @@ -243,7 +279,7 @@ public: static NS_METHOD RootImpl(void *p); static NS_METHOD UnrootImpl(void *p); - static NS_METHOD_(void) TraceImpl(void *p, TraceCallback cb, void *closure); + static NS_METHOD_(void) TraceImpl(void *p, const TraceCallbacks &cb, void *closure); static bool CheckForRightISupports(nsISupports *s); }; @@ -458,7 +494,10 @@ T* DowncastCCParticipant(void *p) CycleCollectionNoteChild(cb, tmp->_field, #_field); #define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS \ - that->Trace(p, &nsScriptObjectTracer::NoteJSChild, &cb); + { \ + TraceCallbackFunc noteJsChild(&nsScriptObjectTracer::NoteJSChild); \ + that->Trace(p, noteJsChild, &cb); \ + } #define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END \ (void)tmp; \ @@ -469,32 +508,28 @@ T* DowncastCCParticipant(void *p) // Helpers for implementing nsScriptObjectTracer::Trace /////////////////////////////////////////////////////////////////////////////// -#define NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(_class) \ - void \ - NS_CYCLE_COLLECTION_CLASSNAME(_class)::TraceImpl(void *p, \ - TraceCallback aCallback, \ - void *aClosure) \ - { \ +#define NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(_class) \ + void \ + NS_CYCLE_COLLECTION_CLASSNAME(_class)::TraceImpl(void *p, \ + const TraceCallbacks &aCallbacks, \ + void *aClosure) \ + { \ _class *tmp = DowncastCCParticipant<_class >(p); #define NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(_class, _base_class) \ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(_class) \ nsISupports *s = static_cast(p); \ NS_CYCLE_COLLECTION_CLASSNAME(_base_class)::TraceImpl(s, \ - aCallback, \ + aCallbacks, \ aClosure); -#define NS_IMPL_CYCLE_COLLECTION_TRACE_JS_CALLBACK(_object, _name) \ - if (_object) \ - aCallback(_object, _name, aClosure); - #define NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(_field) \ - NS_IMPL_CYCLE_COLLECTION_TRACE_JS_CALLBACK(tmp->_field, #_field) + if (tmp->_field) \ + aCallbacks.Trace(&tmp->_field, #_field, aClosure); #define NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK(_field) \ if (JSVAL_IS_TRACEABLE(tmp->_field)) { \ - void *gcThing = JSVAL_TO_TRACEABLE(tmp->_field); \ - aCallback(gcThing, #_field, aClosure); \ + aCallbacks.Trace(&tmp->_field, #_field, aClosure); \ } // NB: The (void)tmp; hack in the TRACE_END macro exists to support @@ -505,7 +540,7 @@ T* DowncastCCParticipant(void *p) } /////////////////////////////////////////////////////////////////////////////// -// Helpers for implementing a concrete nsCycleCollectionParticipant +// Helpers for implementing a concrete nsCycleCollectionParticipant /////////////////////////////////////////////////////////////////////////////// #define NS_DECL_CYCLE_COLLECTION_CLASS_BODY_NO_UNLINK(_class, _base) \ @@ -586,14 +621,14 @@ NOT_INHERITED_CANT_OVERRIDE #define NS_DECL_CYCLE_COLLECTION_SKIPPABLE_CLASS(_class) \ NS_DECL_CYCLE_COLLECTION_SKIPPABLE_CLASS_AMBIGUOUS(_class, _class) -#define NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(_class, _base) \ -class NS_CYCLE_COLLECTION_INNERCLASS \ - : public nsXPCOMCycleCollectionParticipant \ -{ \ - NS_DECL_CYCLE_COLLECTION_CLASS_BODY(_class, _base) \ - static NS_METHOD_(void) TraceImpl(void *p, TraceCallback cb, void *closure); \ - NS_IMPL_GET_XPCOM_CYCLE_COLLECTION_PARTICIPANT(_class) \ -}; \ +#define NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(_class, _base) \ +class NS_CYCLE_COLLECTION_INNERCLASS \ + : public nsXPCOMCycleCollectionParticipant \ +{ \ + NS_DECL_CYCLE_COLLECTION_CLASS_BODY(_class, _base) \ + static NS_METHOD_(void) TraceImpl(void *p, const TraceCallbacks &cb, void *closure); \ + NS_IMPL_GET_XPCOM_CYCLE_COLLECTION_PARTICIPANT(_class) \ +}; \ NOT_INHERITED_CANT_OVERRIDE #define NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_AMBIGUOUS(_class, _base) \ @@ -602,29 +637,29 @@ class NS_CYCLE_COLLECTION_INNERCLASS { \ NS_DECL_CYCLE_COLLECTION_CLASS_BODY(_class, _base) \ static const bool isSkippable = true; \ - static NS_METHOD_(void) TraceImpl(void *p, TraceCallback cb, void *closure); \ + static NS_METHOD_(void) TraceImpl(void *p, const TraceCallbacks &cb, void *closure); \ static NS_METHOD_(bool) CanSkipImpl(void *p, bool aRemovingAllowed); \ static NS_METHOD_(bool) CanSkipInCCImpl(void *p); \ static NS_METHOD_(bool) CanSkipThisImpl(void *p); \ - NS_IMPL_GET_XPCOM_CYCLE_COLLECTION_PARTICIPANT(_class) \ -}; \ + NS_IMPL_GET_XPCOM_CYCLE_COLLECTION_PARTICIPANT(_class) \ +}; \ NOT_INHERITED_CANT_OVERRIDE #define NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS(_class) \ NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_AMBIGUOUS(_class, _class) -#define NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_INHERITED(_class, \ - _base_class) \ -class NS_CYCLE_COLLECTION_INNERCLASS \ - : public NS_CYCLE_COLLECTION_CLASSNAME(_base_class) \ -{ \ - NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_BODY(_class, _base_class) \ - static const bool isSkippable = true; \ - static NS_METHOD_(void) TraceImpl(void *p, TraceCallback cb, void *closure); \ - static NS_METHOD_(bool) CanSkipImpl(void *p, bool aRemovingAllowed); \ - static NS_METHOD_(bool) CanSkipInCCImpl(void *p); \ - static NS_METHOD_(bool) CanSkipThisImpl(void *p); \ - NS_IMPL_GET_XPCOM_CYCLE_COLLECTION_PARTICIPANT(_class) \ +#define NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_INHERITED(_class, \ + _base_class) \ +class NS_CYCLE_COLLECTION_INNERCLASS \ + : public NS_CYCLE_COLLECTION_CLASSNAME(_base_class) \ +{ \ + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_BODY(_class, _base_class) \ + static const bool isSkippable = true; \ + static NS_METHOD_(void) TraceImpl(void *p, const TraceCallbacks &cb, void *closure); \ + static NS_METHOD_(bool) CanSkipImpl(void *p, bool aRemovingAllowed); \ + static NS_METHOD_(bool) CanSkipInCCImpl(void *p); \ + static NS_METHOD_(bool) CanSkipThisImpl(void *p); \ + NS_IMPL_GET_XPCOM_CYCLE_COLLECTION_PARTICIPANT(_class) \ }; #define NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(_class) \ @@ -664,14 +699,14 @@ public: \ NS_IMPL_GET_XPCOM_CYCLE_COLLECTION_PARTICIPANT(_class) \ }; -#define NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(_class, \ - _base_class) \ -class NS_CYCLE_COLLECTION_INNERCLASS \ - : public NS_CYCLE_COLLECTION_CLASSNAME(_base_class) \ -{ \ - NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_BODY(_class, _base_class) \ - static NS_METHOD_(void) TraceImpl(void *p, TraceCallback cb, void *closure); \ - NS_IMPL_GET_XPCOM_CYCLE_COLLECTION_PARTICIPANT(_class) \ +#define NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(_class, \ + _base_class) \ +class NS_CYCLE_COLLECTION_INNERCLASS \ + : public NS_CYCLE_COLLECTION_CLASSNAME(_base_class) \ +{ \ + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_BODY(_class, _base_class) \ + static NS_METHOD_(void) TraceImpl(void *p, const TraceCallbacks &cb, void *closure); \ + NS_IMPL_GET_XPCOM_CYCLE_COLLECTION_PARTICIPANT(_class) \ }; /** @@ -772,7 +807,7 @@ struct Skippable { \ NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS_BODY(_class) \ NS_DECL_CYCLE_COLLECTION_NATIVE_UNMARK_IF_PURPLE(_class) \ - static NS_METHOD_(void) TraceImpl(void *p, TraceCallback cb, \ + static NS_METHOD_(void) TraceImpl(void *p, const TraceCallbacks &cb, \ void *closure); \ static nsScriptObjectTracer* GetParticipant() \ { \ From c437a3a2c016d2d6be7d684b796d2952c71df921 Mon Sep 17 00:00:00 2001 From: Jon Coppeard Date: Mon, 27 May 2013 12:51:25 +0100 Subject: [PATCH 18/20] Bug 875872 - Add public Heap class for implementing post-barriers in the browser r=terrence --- js/public/RootingAPI.h | 92 +++++++++++++++++++++++++++++++++++++-- js/public/Value.h | 25 +++++++++++ js/src/gc/StoreBuffer.cpp | 34 +++++++++++++++ js/src/jsapi.cpp | 30 +++++++++++++ js/src/jsapi.h | 20 +++++++++ js/src/jsfriendapi.cpp | 2 +- 6 files changed, 198 insertions(+), 5 deletions(-) diff --git a/js/public/RootingAPI.h b/js/public/RootingAPI.h index d9b89719d06..df4b8f96d0f 100644 --- a/js/public/RootingAPI.h +++ b/js/public/RootingAPI.h @@ -113,6 +113,9 @@ class HandleBase {}; template class MutableHandleBase {}; +template +class HeapBase {}; + /* * js::NullPtr acts like a NULL pointer in contexts that require a Handle. * @@ -131,6 +134,10 @@ struct NullPtr static void * const constNullValue; }; +namespace gc { +struct Cell; +} /* namespace gc */ + } /* namespace js */ namespace JS { @@ -162,6 +169,69 @@ struct JS_PUBLIC_API(NullPtr) static void * const constNullValue; }; +/* + * Encapsulated pointer class for use on the heap. + * + * Implements post barriers for heap-based GC thing pointers outside the engine. + */ +template +class Heap : public js::HeapBase +{ + public: + Heap() { set(js::RootMethods::initial()); } + explicit Heap(T p) { set(p); } + explicit Heap(const Heap &p) { set(p.ptr); } + + ~Heap() { + if (js::RootMethods::needsPostBarrier(ptr)) + relocate(); + } + + bool operator!=(const T &other) { return *ptr != other; } + bool operator==(const T &other) { return *ptr == other; } + + operator T() const { return ptr; } + T operator->() const { return ptr; } + const T *address() const { return &ptr; } + const T &get() const { return ptr; } + + T *unsafeGet() { return &ptr; } + + Heap &operator=(T p) { + set(p); + return *this; + } + + void set(T newPtr) { + JS_ASSERT(!js::RootMethods::poisoned(newPtr)); + if (js::RootMethods::needsPostBarrier(newPtr)) { + ptr = newPtr; + post(); + } else if (js::RootMethods::needsPostBarrier(ptr)) { + relocate(); /* Called before overwriting ptr. */ + ptr = newPtr; + } else { + ptr = newPtr; + } + } + + private: + void post() { +#ifdef JSGC_GENERATIONAL + JS_ASSERT(js::RootMethods::needsPostBarrier(ptr)); + js::RootMethods::postBarrier(&ptr); +#endif + } + + void relocate() { +#ifdef JSGC_GENERATIONAL + js::RootMethods::relocate(&ptr); +#endif + } + + T ptr; +}; + /* * Reference to a T that has been rooted elsewhere. This is most useful * as a parameter type, which guarantees that the T lvalue is properly @@ -202,6 +272,10 @@ class MOZ_STACK_CLASS Handle : public js::HandleBase ptr = handle.address(); } + Handle(const Heap &heapPtr) { + ptr = heapPtr.address(); + } + /* * This may be called only if the location of the T is guaranteed * to be marked (for some reason other than being a Rooted), @@ -315,6 +389,11 @@ typedef MutableHandle MutableHandleString; typedef MutableHandle MutableHandleId; typedef MutableHandle MutableHandleValue; +#ifdef JSGC_GENERATIONAL +JS_PUBLIC_API(void) HeapCellPostBarrier(js::gc::Cell **cellp); +JS_PUBLIC_API(void) HeapCellRelocate(js::gc::Cell **cellp); +#endif + } /* namespace JS */ namespace js { @@ -394,6 +473,15 @@ struct RootMethods static T *initial() { return NULL; } static ThingRootKind kind() { return RootKind::rootKind(); } static bool poisoned(T *v) { return JS::IsPoisonedPtr(v); } + static bool needsPostBarrier(T *v) { return v; } +#ifdef JSGC_GENERATIONAL + static void postBarrier(T **vp) { + JS::HeapCellPostBarrier(reinterpret_cast(vp)); + } + static void relocate(T **vp) { + JS::HeapCellRelocate(reinterpret_cast(vp)); + } +#endif }; } /* namespace js */ @@ -790,10 +878,6 @@ inline void MaybeCheckStackRoots(JSContext *cx) #endif } -namespace gc { -struct Cell; -} /* namespace gc */ - /* Base class for automatic read-only object rooting during compilation. */ class CompilerRootNode { diff --git a/js/public/Value.h b/js/public/Value.h index 2c7fa1a600f..6395b8b0668 100644 --- a/js/public/Value.h +++ b/js/public/Value.h @@ -1393,6 +1393,13 @@ SameType(const Value &lhs, const Value &rhs) /************************************************************************/ +#ifdef JSGC_GENERATIONAL +namespace JS { +JS_PUBLIC_API(void) HeapValuePostBarrier(Value *valuep); +JS_PUBLIC_API(void) HeapValueRelocate(Value *valuep); +} +#endif + namespace js { template <> struct RootMethods @@ -1407,6 +1414,11 @@ template <> struct RootMethods static JS::Value initial() { return JS::UndefinedValue(); } static ThingRootKind kind() { return THING_ROOT_VALUE; } static bool poisoned(const JS::Value &v) { return JS::IsPoisonedValue(v); } + static bool needsPostBarrier(const JS::Value &v) { return v.isMarkable(); } +#ifdef JSGC_GENERATIONAL + static void postBarrier(JS::Value *v) { JS::HeapValuePostBarrier(v); } + static void relocate(JS::Value *v) { JS::HeapValueRelocate(v); } +#endif }; template class MutableValueOperations; @@ -1483,6 +1495,19 @@ class MutableValueOperations : public ValueOperations void setObjectOrNull(JSObject *arg) { value()->setObjectOrNull(arg); } }; +/* + * Augment the generic Heap interface when T = Value with type-querying + * and value-extracting operations. + */ +template <> +class HeapBase : public ValueOperations > +{ + friend class ValueOperations >; + const JS::Value * extract() const { + return static_cast*>(this)->address(); + } +}; + /* * Augment the generic Handle interface when T = Value with type-querying * and value-extracting operations. diff --git a/js/src/gc/StoreBuffer.cpp b/js/src/gc/StoreBuffer.cpp index 7b885148601..5e95b8f7938 100644 --- a/js/src/gc/StoreBuffer.cpp +++ b/js/src/gc/StoreBuffer.cpp @@ -473,6 +473,40 @@ StoreBuffer::releaseVerificationData() edgeSet.finish(); } +JS_PUBLIC_API(void) +JS::HeapCellPostBarrier(js::gc::Cell **cellp) +{ + JS_ASSERT(*cellp); + JSRuntime *runtime = (*cellp)->runtime(); + runtime->gcStoreBuffer.putRelocatableCell(cellp); +} + +JS_PUBLIC_API(void) +JS::HeapCellRelocate(js::gc::Cell **cellp) +{ + /* Called with old contents of *pp before overwriting. */ + JS_ASSERT(*cellp); + JSRuntime *runtime = (*cellp)->runtime(); + runtime->gcStoreBuffer.removeRelocatableCell(cellp); +} + +JS_PUBLIC_API(void) +JS::HeapValuePostBarrier(JS::Value *valuep) +{ + JS_ASSERT(JSVAL_IS_TRACEABLE(*valuep)); + JSRuntime *runtime = static_cast(valuep->toGCThing())->runtime(); + runtime->gcStoreBuffer.putRelocatableValue(valuep); +} + +JS_PUBLIC_API(void) +JS::HeapValueRelocate(JS::Value *valuep) +{ + /* Called with old contents of *valuep before overwriting. */ + JS_ASSERT(JSVAL_IS_TRACEABLE(*valuep)); + JSRuntime *runtime = static_cast(valuep->toGCThing())->runtime(); + runtime->gcStoreBuffer.removeRelocatableValue(valuep); +} + template class StoreBuffer::MonoTypeBuffer; template class StoreBuffer::MonoTypeBuffer; template class StoreBuffer::MonoTypeBuffer; diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 8c3dcd222a8..a43b71baeae 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -2521,6 +2521,36 @@ JS_CallGenericTracer(JSTracer *trc, void *gcthingArg, const char *name) JS_ASSERT(gcthing == gcthingArg); } +JS_PUBLIC_API(void) +JS_CallHeapValueTracer(JSTracer *trc, JS::Heap *valuep, const char *name) +{ + MarkValueUnbarriered(trc, valuep->unsafeGet(), name); +} + +JS_PUBLIC_API(void) +JS_CallHeapIdTracer(JSTracer *trc, JS::Heap *idp, const char *name) +{ + MarkIdUnbarriered(trc, idp->unsafeGet(), name); +} + +JS_PUBLIC_API(void) +JS_CallHeapObjectTracer(JSTracer *trc, JS::Heap *objp, const char *name) +{ + MarkObjectUnbarriered(trc, objp->unsafeGet(), name); +} + +JS_PUBLIC_API(void) +JS_CallHeapStringTracer(JSTracer *trc, JS::Heap *strp, const char *name) +{ + MarkStringUnbarriered(trc, strp->unsafeGet(), name); +} + +JS_PUBLIC_API(void) +JS_CallHeapScriptTracer(JSTracer *trc, JS::Heap *scriptp, const char *name) +{ + MarkScriptUnbarriered(trc, scriptp->unsafeGet(), name); +} + JS_PUBLIC_API(void) JS_TracerInit(JSTracer *trc, JSRuntime *rt, JSTraceCallback callback) { diff --git a/js/src/jsapi.h b/js/src/jsapi.h index 0c38f844334..99f4e7b9541 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -1796,6 +1796,11 @@ template <> struct RootMethods static jsid initial() { return JSID_VOID; } static ThingRootKind kind() { return THING_ROOT_ID; } static bool poisoned(jsid id) { return JS::IsPoisonedId(id); } + static bool needsPostBarrier(jsid id) { return false; } +#ifdef JSGC_GENERATIONAL + static void postBarrier(jsid *idp) {} + static void relocate(jsid *idp) {} +#endif }; } /* namespace js */ @@ -2530,6 +2535,21 @@ JS_CallStringTracer(JSTracer *trc, JSString **strp, const char *name); extern JS_PUBLIC_API(void) JS_CallScriptTracer(JSTracer *trc, JSScript **scriptp, const char *name); +extern JS_PUBLIC_API(void) +JS_CallHeapValueTracer(JSTracer *trc, JS::Heap *valuep, const char *name); + +extern JS_PUBLIC_API(void) +JS_CallHeapIdTracer(JSTracer *trc, JS::Heap *idp, const char *name); + +extern JS_PUBLIC_API(void) +JS_CallHeapObjectTracer(JSTracer *trc, JS::Heap *objp, const char *name); + +extern JS_PUBLIC_API(void) +JS_CallHeapStringTracer(JSTracer *trc, JS::Heap *strp, const char *name); + +extern JS_PUBLIC_API(void) +JS_CallHeapScriptTracer(JSTracer *trc, JS::Heap *scriptp, const char *name); + extern JS_PUBLIC_API(void) JS_CallGenericTracer(JSTracer *trc, void *gcthing, const char *name); diff --git a/js/src/jsfriendapi.cpp b/js/src/jsfriendapi.cpp index 0c555ff4f12..95f093d7c68 100644 --- a/js/src/jsfriendapi.cpp +++ b/js/src/jsfriendapi.cpp @@ -934,7 +934,7 @@ JS::IncrementalReferenceBarrier(void *ptr, JSGCTraceKind kind) JS_FRIEND_API(void) JS::IncrementalValueBarrier(const Value &v) { - HeapValue::writeBarrierPre(v); + js::HeapValue::writeBarrierPre(v); } JS_FRIEND_API(void) From e2c9b549715faab3f1c1fd7eabe6d8a5bfd5ad59 Mon Sep 17 00:00:00 2001 From: Markus Stange Date: Mon, 27 May 2013 14:48:15 +0200 Subject: [PATCH 19/20] Bug 876256 - Restore the previous scissor rect at the end of CompositorOGL::DrawQuad. r=mattwoodrow --- gfx/layers/opengl/CompositorOGL.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/gfx/layers/opengl/CompositorOGL.cpp b/gfx/layers/opengl/CompositorOGL.cpp index 2ec5bfd8e73..86efafefb5e 100644 --- a/gfx/layers/opengl/CompositorOGL.cpp +++ b/gfx/layers/opengl/CompositorOGL.cpp @@ -962,8 +962,8 @@ CompositorOGL::DrawQuad(const Rect& aRect, const Rect& aClipRect, IntRect intClipRect; aClipRect.ToIntRect(&intClipRect); - mGLContext->fScissor(intClipRect.x, intClipRect.y, - intClipRect.width, intClipRect.height); + mGLContext->PushScissorRect(nsIntRect(intClipRect.x, intClipRect.y, + intClipRect.width, intClipRect.height)); MaskType maskType; EffectMask* effectMask; @@ -1198,6 +1198,7 @@ CompositorOGL::DrawQuad(const Rect& aRect, const Rect& aClipRect, break; } + mGLContext->PopScissorRect(); mGLContext->fActiveTexture(LOCAL_GL_TEXTURE0); // in case rendering has used some other GL context MakeCurrent(); From ee81a84ae693e18c020d1f3cb0d51a23fd0880e9 Mon Sep 17 00:00:00 2001 From: "octoploid@yandex.com" Date: Mon, 27 May 2013 06:40:37 -0700 Subject: [PATCH 20/20] Bug 875790 - Revert AutoPushJSContext change in nsJSContext::CompileScript due to crashes. r=bholley --- dom/base/nsJSEnvironment.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index 66597996435..b8ad40d39a6 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -1319,7 +1319,8 @@ nsJSContext::CompileScript(const PRUnichar* aText, NS_ENSURE_ARG_POINTER(aPrincipal); - AutoPushJSContext cx(mContext); + JSContext* cx = mContext; + JSAutoRequest ar(cx); JS::Rooted scopeObject(mContext, GetNativeGlobal()); xpc_UnmarkGrayObject(scopeObject);