diff --git a/content/base/public/nsIDocument.h b/content/base/public/nsIDocument.h index a671217a583..74ac4b104b6 100644 --- a/content/base/public/nsIDocument.h +++ b/content/base/public/nsIDocument.h @@ -53,7 +53,6 @@ #include "nsILoadGroup.h" #include "nsReadableUtils.h" #include "nsCRT.h" -#include // for FILE definition class nsIAtom; class nsIContent; diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index d783714c8a9..4957c8352ed 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -1519,7 +1519,9 @@ nsDocument::SetStyleSheetApplicableState(nsIStyleSheet* aSheet, } } else { // We still need to notify the style set of the state change, because - // this will invalidate some of the rule processor data. + // this will invalidate some of the rule processor data. We do this + // here instead of in the pres shell because we _don't_ want to do this + // for document style sheets. PRInt32 count = mPresShells.Count(); PRInt32 indx; @@ -1647,14 +1649,6 @@ nsDocument::RemoveObserver(nsIDocumentObserver* aObserver) void nsDocument::BeginUpdate(nsUpdateType aUpdateType) { - if (aUpdateType & UPDATE_STYLE) { - PRInt32 shellCount = mPresShells.Count(); - for (PRInt32 j = 0; j < shellCount; ++j) { - NS_STATIC_CAST(nsIPresShell*, mPresShells.ElementAt(j))->StyleSet()-> - BeginUpdate(); - } - } - PRInt32 i; for (i = mObservers.Count() - 1; i >= 0; --i) { nsIDocumentObserver* observer = (nsIDocumentObserver*) mObservers[i]; @@ -1665,14 +1659,6 @@ nsDocument::BeginUpdate(nsUpdateType aUpdateType) void nsDocument::EndUpdate(nsUpdateType aUpdateType) { - if (aUpdateType & UPDATE_STYLE) { - PRInt32 shellCount = mPresShells.Count(); - for (PRInt32 j = 0; j < shellCount; ++j) { - NS_STATIC_CAST(nsIPresShell*, mPresShells.ElementAt(j))->StyleSet()-> - EndUpdate(); - } - } - PRInt32 i; for (i = mObservers.Count() - 1; i >= 0; --i) { nsIDocumentObserver* observer = (nsIDocumentObserver*) mObservers[i]; diff --git a/content/base/src/nsDocumentViewer.cpp b/content/base/src/nsDocumentViewer.cpp index 3e01343df94..ec28baeaf64 100644 --- a/content/base/src/nsDocumentViewer.cpp +++ b/content/base/src/nsDocumentViewer.cpp @@ -639,8 +639,8 @@ nsresult DocumentViewerImpl::InitPresentationStuff(PRBool aDoInitialReflow) { // Create the style set... - nsStyleSet *styleSet; - nsresult rv = CreateStyleSet(mDocument, &styleSet); + nsAutoPtr styleSet; + nsresult rv = CreateStyleSet(mDocument, getter_Transfers(styleSet)); NS_ENSURE_SUCCESS(rv, rv); // Now make the shell for the document @@ -649,6 +649,9 @@ DocumentViewerImpl::InitPresentationStuff(PRBool aDoInitialReflow) NS_ENSURE_SUCCESS(rv, rv); + // The pres shell owns the style set now. + styleSet.forget(); + if (aDoInitialReflow) { // Since InitialReflow() will create frames for *all* items // that are currently in the document tree, we need to flush @@ -1191,8 +1194,8 @@ DocumentViewerImpl::SetDOMDocument(nsIDOMDocument *aDocument) if (mPresContext) { // 3) Create a new style set for the document - nsStyleSet *styleSet; - rv = CreateStyleSet(mDocument, &styleSet); + nsAutoPtr styleSet; + rv = CreateStyleSet(mDocument, getter_Transfers(styleSet)); if (NS_FAILED(rv)) return rv; @@ -1200,6 +1203,9 @@ DocumentViewerImpl::SetDOMDocument(nsIDOMDocument *aDocument) getter_AddRefs(mPresShell)); NS_ENSURE_SUCCESS(rv, rv); + // The pres shell owns the style set now. + styleSet.forget(); + mPresShell->BeginObservingDocument(); // 4) Register the focus listener on the new document @@ -1594,7 +1600,7 @@ DocumentViewerImpl::CreateStyleSet(nsIDocument* aDocument, NS_WARNING("unable to load UA style sheet"); } - nsStyleSet *styleSet = new nsStyleSet(); + nsAutoPtr styleSet(new nsStyleSet()); if (!styleSet) { return NS_ERROR_OUT_OF_MEMORY; } @@ -1663,6 +1669,7 @@ DocumentViewerImpl::CreateStyleSet(nsIDocument* aDocument, styleSet->EndUpdate(); *aStyleSet = styleSet; + styleSet.forget(); return NS_OK; } diff --git a/content/base/src/nsPrintEngine.cpp b/content/base/src/nsPrintEngine.cpp index 151e4cc9e08..a4c8dc21387 100644 --- a/content/base/src/nsPrintEngine.cpp +++ b/content/base/src/nsPrintEngine.cpp @@ -2608,7 +2608,8 @@ nsPrintEngine::ReflowPrintObject(nsPrintObject * aPO, PRBool aDoCalcShrink) // init it with the DC (aPO->mPresContext)->Init(mPrt->mPrintDocDC); - rv = mDocViewerPrint->CreateStyleSet(aPO->mDocument, &aPO->mStyleSet); + rv = mDocViewerPrint->CreateStyleSet(aPO->mDocument, + getter_Transfers(aPO->mStyleSet)); NS_ENSURE_SUCCESS(rv, rv); aPO->mViewManager = do_CreateInstance(kViewManagerCID, &rv); diff --git a/content/base/src/nsPrintObject.h b/content/base/src/nsPrintObject.h index 06cd9638010..d0b732607ed 100644 --- a/content/base/src/nsPrintObject.h +++ b/content/base/src/nsPrintObject.h @@ -81,7 +81,7 @@ public: PrintObjectType mFrameType; nsCOMPtr mPresContext; - nsStyleSet *mStyleSet; + nsAutoPtr mStyleSet; nsCOMPtr mPresShell; nsCOMPtr mViewManager; nsCOMPtr mWindow; diff --git a/content/base/src/nsRuleNode.cpp b/content/base/src/nsRuleNode.cpp index 54972c6ad12..ccb28d4acfd 100644 --- a/content/base/src/nsRuleNode.cpp +++ b/content/base/src/nsRuleNode.cpp @@ -4358,6 +4358,9 @@ PRBool nsRuleNode::Sweep() { // If we're not marked, then we have to delete ourself. + // However, we never allow the root node to GC itself, because nsStyleSet + // wants to hold onto the root node and not worry about re-creating a + // rule walker if the root node is deleted. if (!(mDependentBits & NS_RULE_NODE_GC_MARK) && !IsRoot()) { Destroy(); return PR_TRUE; diff --git a/content/base/src/nsStyleSet.cpp b/content/base/src/nsStyleSet.cpp index 460ac7e944e..f2d7978bdc5 100644 --- a/content/base/src/nsStyleSet.cpp +++ b/content/base/src/nsStyleSet.cpp @@ -55,7 +55,7 @@ nsStyleSet::nsStyleSet() : mRuleTree(nsnull), mRuleWalker(nsnull), mDestroyedCount(0), - mBatching(PR_FALSE), + mBatching(0), mInShutdown(PR_FALSE), mDirty(0) { @@ -70,8 +70,10 @@ nsStyleSet::Init(nsIPresContext *aPresContext) NS_ENSURE_TRUE(gQuirkURI, NS_ERROR_OUT_OF_MEMORY); } - if (!BuildDefaultStyleData(aPresContext)) - return NS_ERROR_FAILURE; + if (!BuildDefaultStyleData(aPresContext)) { + mDefaultStyleData.Destroy(0, aPresContext); + return NS_ERROR_OUT_OF_MEMORY; + } mRuleTree = nsRuleNode::CreateRootNode(aPresContext); if (!mRuleTree) { @@ -195,10 +197,8 @@ nsStyleSet::ReplaceSheets(sheetType aType, const nsCOMArray &aNewSheets) { mSheets[aType].Clear(); - for (PRInt32 i = 0; i < aNewSheets.Count(); ++i) { - if (!mSheets[aType].AppendObject(aNewSheets.ObjectAt(i))) - return NS_ERROR_OUT_OF_MEMORY; - } + if (!mSheets[aType].AppendObjects(aNewSheets)) + return NS_ERROR_OUT_OF_MEMORY; if (!mBatching) return GatherRuleProcessors(aType); @@ -212,7 +212,7 @@ nsStyleSet::ReplaceSheets(sheetType aType, nsresult nsStyleSet::AddDocStyleSheet(nsIStyleSheet* aSheet, nsIDocument* aDocument) { - NS_PRECONDITION((nsnull != aSheet) && (nsnull != aDocument), "null arg"); + NS_PRECONDITION(aSheet && aDocument, "null arg"); CHECK_APPLICABLE; nsCOMArray& docSheets = mSheets[eDocSheet]; @@ -248,21 +248,26 @@ nsStyleSet::AddDocStyleSheet(nsIStyleSheet* aSheet, nsIDocument* aDocument) void nsStyleSet::BeginUpdate() { - mBatching = 1; + ++mBatching; } nsresult nsStyleSet::EndUpdate() { + NS_ASSERTION(mBatching > 0, "Unbalanced EndUpdate"); + if (--mBatching) { + // We're not completely done yet. + return NS_OK; + } + for (int i = 0; i < eSheetTypeCount; ++i) { - if (mDirty & 1 << i) { + if (mDirty & (1 << i)) { nsresult rv = GatherRuleProcessors(i); NS_ENSURE_SUCCESS(rv, rv); } } mDirty = 0; - mBatching = 0; return NS_OK; } @@ -721,7 +726,7 @@ nsStyleSet::NotifyStyleContextDestroyed(nsIPresContext* aPresContext, #endif mRuleTree->Sweep(); - NS_ASSERTION(deleted, "Root not must not be gc'd"); + NS_ASSERTION(!deleted, "Root node must not be gc'd"); } } diff --git a/content/base/src/nsStyleSet.h b/content/base/src/nsStyleSet.h index 31cd29049f5..2de04e13a5c 100644 --- a/content/base/src/nsStyleSet.h +++ b/content/base/src/nsStyleSet.h @@ -49,6 +49,10 @@ class nsIURI; +// The style set object is created by the document viewer and ownership is +// then handed off to the PresShell. Only the PresShell should delete a +// style set. + class nsStyleSet { public: @@ -156,12 +160,13 @@ class nsStyleSet // Free global data at module shutdown static void FreeGlobals() { NS_IF_RELEASE(gQuirkURI); } - // APIs to manipulate the style sheet lists + // APIs to manipulate the style sheet lists. + // All sheet types are ordered most-significant-first. enum sheetType { eAgentSheet, eUserSheet, eDocSheet, - eOverrideSheet, // override sheets are ordered most significant first + eOverrideSheet, eSheetTypeCount }; @@ -237,9 +242,10 @@ class nsStyleSet PRInt32 mDestroyedCount; // used to batch style context GC nsVoidArray mRoots; // style contexts with no parent - unsigned mBatching : 1; + PRUint16 mBatching; + unsigned mInShutdown : 1; - unsigned mDirty : 6; // one dirty bit is used per sheet type + unsigned mDirty : 7; // one dirty bit is used per sheet type }; #endif diff --git a/layout/base/nsDocumentViewer.cpp b/layout/base/nsDocumentViewer.cpp index 3e01343df94..ec28baeaf64 100644 --- a/layout/base/nsDocumentViewer.cpp +++ b/layout/base/nsDocumentViewer.cpp @@ -639,8 +639,8 @@ nsresult DocumentViewerImpl::InitPresentationStuff(PRBool aDoInitialReflow) { // Create the style set... - nsStyleSet *styleSet; - nsresult rv = CreateStyleSet(mDocument, &styleSet); + nsAutoPtr styleSet; + nsresult rv = CreateStyleSet(mDocument, getter_Transfers(styleSet)); NS_ENSURE_SUCCESS(rv, rv); // Now make the shell for the document @@ -649,6 +649,9 @@ DocumentViewerImpl::InitPresentationStuff(PRBool aDoInitialReflow) NS_ENSURE_SUCCESS(rv, rv); + // The pres shell owns the style set now. + styleSet.forget(); + if (aDoInitialReflow) { // Since InitialReflow() will create frames for *all* items // that are currently in the document tree, we need to flush @@ -1191,8 +1194,8 @@ DocumentViewerImpl::SetDOMDocument(nsIDOMDocument *aDocument) if (mPresContext) { // 3) Create a new style set for the document - nsStyleSet *styleSet; - rv = CreateStyleSet(mDocument, &styleSet); + nsAutoPtr styleSet; + rv = CreateStyleSet(mDocument, getter_Transfers(styleSet)); if (NS_FAILED(rv)) return rv; @@ -1200,6 +1203,9 @@ DocumentViewerImpl::SetDOMDocument(nsIDOMDocument *aDocument) getter_AddRefs(mPresShell)); NS_ENSURE_SUCCESS(rv, rv); + // The pres shell owns the style set now. + styleSet.forget(); + mPresShell->BeginObservingDocument(); // 4) Register the focus listener on the new document @@ -1594,7 +1600,7 @@ DocumentViewerImpl::CreateStyleSet(nsIDocument* aDocument, NS_WARNING("unable to load UA style sheet"); } - nsStyleSet *styleSet = new nsStyleSet(); + nsAutoPtr styleSet(new nsStyleSet()); if (!styleSet) { return NS_ERROR_OUT_OF_MEMORY; } @@ -1663,6 +1669,7 @@ DocumentViewerImpl::CreateStyleSet(nsIDocument* aDocument, styleSet->EndUpdate(); *aStyleSet = styleSet; + styleSet.forget(); return NS_OK; } diff --git a/layout/base/nsIPresShell.h b/layout/base/nsIPresShell.h index b24f2e82b5c..db839805d79 100644 --- a/layout/base/nsIPresShell.h +++ b/layout/base/nsIPresShell.h @@ -649,7 +649,7 @@ protected: // we must share ownership. nsIDocument* mDocument; // [STRONG] nsIPresContext* mPresContext; // [STRONG] - nsStyleSet* mStyleSet; // [STRONG] + nsStyleSet* mStyleSet; // [OWNS] nsIStyleFrameConstruction* mFrameConstructor; // [STRONG] nsIViewManager* mViewManager; // [WEAK] docViewer owns it so I don't have to nsIFrameManager* mFrameManager; // [STRONG] diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index 3b981265bd6..9ccc808178e 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -1644,9 +1644,7 @@ PresShell::Init(nsIDocument* aDocument, // before creating any frames. SetPreferenceStyleRules(PR_FALSE); - result = nsComponentManager::CreateInstance(kFrameSelectionCID, nsnull, - NS_GET_IID(nsIFrameSelection), - getter_AddRefs(mSelection)); + mSelection = do_CreateInstance(kFrameSelectionCID, &result); if (NS_FAILED(result)) return result; @@ -3541,6 +3539,9 @@ PresShell::BeginUpdate(nsIDocument *aDocument, nsUpdateType aUpdateType) #ifdef DEBUG mUpdateCount++; #endif + if (aUpdateType & UPDATE_STYLE) + mStyleSet->BeginUpdate(); + return NS_OK; } @@ -3552,6 +3553,9 @@ PresShell::EndUpdate(nsIDocument *aDocument, nsUpdateType aUpdateType) --mUpdateCount; #endif + if (aUpdateType & UPDATE_STYLE) + mStyleSet->EndUpdate(); + if (mStylesHaveChanged && (aUpdateType & UPDATE_STYLE)) return ReconstructStyleData(); @@ -7097,7 +7101,7 @@ PresShell::VerifyIncrementalReflow() // Create a new presentation shell to view the document. Use the // exact same style information that this document has. - nsStyleSet *newSet; + nsAutoPtr newSet; rv = CloneStyleSet(mStyleSet, &newSet); NS_ASSERTION(NS_SUCCEEDED(rv), "failed to clone style set"); rv = mDocument->CreateShell(cx, vm, newSet, &sh); diff --git a/layout/base/public/nsIPresShell.h b/layout/base/public/nsIPresShell.h index b24f2e82b5c..db839805d79 100644 --- a/layout/base/public/nsIPresShell.h +++ b/layout/base/public/nsIPresShell.h @@ -649,7 +649,7 @@ protected: // we must share ownership. nsIDocument* mDocument; // [STRONG] nsIPresContext* mPresContext; // [STRONG] - nsStyleSet* mStyleSet; // [STRONG] + nsStyleSet* mStyleSet; // [OWNS] nsIStyleFrameConstruction* mFrameConstructor; // [STRONG] nsIViewManager* mViewManager; // [WEAK] docViewer owns it so I don't have to nsIFrameManager* mFrameManager; // [STRONG] diff --git a/layout/base/public/nsIStyleFrameConstruction.h b/layout/base/public/nsIStyleFrameConstruction.h index 0d56b2cbff4..e69de29bb2d 100644 --- a/layout/base/public/nsIStyleFrameConstruction.h +++ b/layout/base/public/nsIStyleFrameConstruction.h @@ -1,331 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: NPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Netscape Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/NPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the NPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the NPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -#ifndef nsIStyleFrameConstruction_h___ -#define nsIStyleFrameConstruction_h___ - -#include "nsISupports.h" -#include "nsChangeHint.h" - -class nsIPresShell; -class nsIPresContext; -class nsIContent; -class nsIFrame; -class nsIAtom; -class nsIStyleSheet; -class nsIStyleRule; -class nsStyleChangeList; -class nsIFrameManager; -class nsILayoutHistoryState; - -// IID for the nsIStyleFrameConstruction interface {a6cf9066-15b3-11d2-932e-00805f8add32} -#define NS_ISTYLE_FRAME_CONSTRUCTION_IID \ -{0xa6cf9066, 0x15b3, 0x11d2, {0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32}} - -/** a simple struct (that may someday be expanded) - * that contains data supplied by the caller to help - * the style set find a frame for a content node - */ -struct nsFindFrameHint -{ - nsIFrame *mPrimaryFrameForPrevSibling; // weak ref to the primary frame for the content for which we need a frame - nsFindFrameHint() { - mPrimaryFrameForPrevSibling = nsnull; - }; -}; - -/** Interface for objects that handle frame construction based on style. - * All frame construction goes through an object that implements this interface. - * Frames are built based on the state of the content model and the style model. - * Changes to either content or style can cause changes to the frame model. - */ -class nsIStyleFrameConstruction : public nsISupports { -public: - NS_DEFINE_STATIC_IID_ACCESSOR(NS_ISTYLE_FRAME_CONSTRUCTION_IID) - - /** - * Create frames for the root content element and its child content. - * - * @param aPresShell the presentation shell for which we will consturct a root frame - * @param aPresContext the presentation context - * @param aDocElement the content node to map into a root frame - * @param aFrameSubTree [OUT] the resulting frame tree (a root frame and its children) - * - * @return NS_OK - */ - NS_IMETHOD ConstructRootFrame(nsIPresShell* aPresShell, - nsIPresContext* aPresContext, - nsIContent* aDocElement, - nsIFrame*& aFrameSubTree) = 0; - - /** - * Causes reconstruction of a frame hierarchy rooted by the - * document element frame. This is often called when radical style - * change precludes incremental reflow. - * - * @param aPresContext the presentation context - * - * @return NS_OK - */ - NS_IMETHOD ReconstructDocElementHierarchy(nsIPresContext* aPresContext) = 0; - - - /////////////// Content change notifications ////////////////// - - /** - * Notification that content was appended in the content tree. - * This may have the side effect of creating frames for the new content. - * - * @param aPresContext the presentation context - * @param aContainer the content node into which content was appended - * @param aNewIndexInContainer the index in aContainer at which the first - * content node was appended. - * @return NS_OK - * @see nsIDocumentObserver - */ - NS_IMETHOD ContentAppended(nsIPresContext* aPresContext, - nsIContent* aContainer, - PRInt32 aNewIndexInContainer) = 0; - - /** - * Notification that content was inserted in the content tree. - * This may have the side effect of creating frames for the new content. - * - * @param aPresContext the presentation context - * @param aContainer the content node into which content was appended - * @param aContainerFrame the frame which the content will be inserted under if - * aContainer has more than one frame; may be null, in which - * case primary frame is used. - * @param aChild the content node that was inserted - * @param aNewIndexInContainer the index of aChild in aContainer - * @param aFrameState the layout history object used to initialize the new frame(s) - * @param aInContentReplaced PR_TRUE must be passed in if this is called from ContentReplaced - * - this will prevent calling ReframeContainingBlock when a special - * inline block situation is detected - * - * @return NS_OK - * @see nsIDocumentObserver - */ - NS_IMETHOD ContentInserted(nsIPresContext* aPresContext, - nsIContent* aContainer, - nsIFrame* aContainerFrame, - nsIContent* aChild, - PRInt32 aIndexInContainer, - nsILayoutHistoryState* aFrameState, - PRBool aInContentReplaced) = 0; - - /** - * Notification that content was replaced in the content tree. - * This may have the side effect of creating frames for the new content. - * - * @param aPresContext the presentation context - * @param aContainer the content node into which content was appended - * @param aOldChild the content node that was replaced - * @param aNewChild the new content node that replaced aOldChild - * @param aNewIndexInContainer the index of aNewChild in aContainer - * - * @return NS_OK - * @see nsIDocumentObserver - */ - NS_IMETHOD ContentReplaced(nsIPresContext* aPresContext, - nsIContent* aContainer, - nsIContent* aOldChild, - nsIContent* aNewChild, - PRInt32 aIndexInContainer) = 0; - - /** - * Notification that content was inserted in the content tree. - * This may have the side effect of changing the frame tree - * - * @param aPresContext the presentation context - * @param aContainer the content node into which content was appended - * @param aChild the content node that was inserted - * @param aNewIndexInContainer the index of aChild in aContainer - * @param aInContentReplaced PR_TRUE must be passed in if this is called from ContentReplaced - * - this will prevent calling ReframeContainingBlock when a special - * inline block situation is detected - * - * @return NS_OK - * @see nsIDocumentObserver - */ - NS_IMETHOD ContentRemoved(nsIPresContext* aPresContext, - nsIContent* aContainer, - nsIContent* aChild, - PRInt32 aIndexInContainer, - PRBool aInContentReplaced) = 0; - - /** - * Notification that content was changed in the content tree. - * This may have the side effect of changing the frame tree - * - * @param aPresContext the presentation context - * @param aContent the content node that was changed - * @param aSubContent a hint to the frame system about the change - * - * @return NS_OK - * @see nsIDocumentObserver - */ - NS_IMETHOD ContentChanged(nsIPresContext* aPresContext, - nsIContent* aContent, - nsISupports* aSubContent) = 0; - - - /** - * Notification that the state of a content node has changed. - * (ie: gained or lost focus, became active or hovered over) - * - * @param aPresContext the presentation context - * @param aContent1 the content node whose state was changed - * @param aContent2 an optional second content node whose state - * has also changed. The meaning of aContent2 - * depends on the type of state change. - * - * @return NS_OK - * @see nsIDocumentObserver - */ - NS_IMETHOD ContentStatesChanged(nsIPresContext* aPresContext, - nsIContent* aContent1, - nsIContent* aContent2, - PRInt32 aStateMask) = 0; - - /** - * Notification that an attribute was changed for a content node - * This may have the side effect of changing the frame tree - * - * @param aPresContext the presentation context - * @param aContent the content node on which an attribute was changed - * @param aNameSpaceID the name space for the changed attribute - * @param aAttribute the attribute that was changed - * @param aHint a hint about the effect of the change - * see nsStyleConsts.h for legal values - * any of the consts of the form NS_STYLE_HINT_* - * - * @return NS_OK - * @see nsIDocumentObserver - */ - NS_IMETHOD AttributeChanged(nsIPresContext* aPresContext, - nsIContent* aContent, - PRInt32 aNameSpaceID, - nsIAtom* aAttribute, - PRInt32 aModType) = 0; - - - /** - * Method that actually handles style changes for effected frames. - * Note: this may not need to be a public method. Use with extreme caution. - * - * @param aRestyleArray A list of effected frames. - * @param aPresContext The presentation context. - * - * @return NS_OK - */ - NS_IMETHOD ProcessRestyledFrames(nsStyleChangeList& aRestyleArray, - nsIPresContext* aPresContext) = 0; - - /////////////// misc methods ////////////////////// - - /** - * Notification that we were unable to render a replaced element. - * Called when the replaced element can not be rendered, and we should - * instead render the element's contents. - * For HTML, the content object associated with aFrame should either be a IMG - * element or an OBJECT element. - * This may have the side effect of changing the frame tree. - * - * @param aPresShell the presentation shell - * @param aPresContext the presentation context - * @param aFrame the frame constructed for the replaced element - * - * @return NS_OK - */ - NS_IMETHOD CantRenderReplacedElement(nsIPresShell* aPresShell, - nsIPresContext* aPresContext, - nsIFrame* aFrame) = 0; - - /** - * Request to create a continuing frame - * - * @param aPresShell the presentation shell - * @param aPresContext the presentation context - * @param aFrame the frame for which we need a continuation - * @param aParentFrame the parent of aFrame - * @param aContinuingFrame [OUT] the resulting frame - * - * @return NS_OK - */ - NS_IMETHOD CreateContinuingFrame(nsIPresContext* aPresContext, - nsIFrame* aFrame, - nsIFrame* aParentFrame, - nsIFrame** aContinuingFrame) = 0; - - /** Request to find the primary frame associated with a given content object. - * This is typically called by the pres shell when there is no mapping in - * the pres shell hash table - * - * @param aPresContext the presentation context - * @param aFrameManager the frame manager for the frame being sought - * @param aContent the content node for which we seek a frame - * @param aFrame [OUT] the resulting frame, if any. may be null, - * indicating that no frame maps aContent - * @param aHint an optional hint used to make the search for aFrame faster - */ - NS_IMETHOD FindPrimaryFrameFor(nsIPresContext* aPresContext, - nsIFrameManager* aFrameManager, - nsIContent* aContent, - nsIFrame** aFrame, - nsFindFrameHint* aHint=nsnull) = 0; - - - /** - * Return the point in the frame hierarchy where the frame that - * will be constructed for |aChildContent| ought be inserted. - * - * @param aPresShell the presentation shell - * @param aParentFrame the frame that will parent the frame that is - * created for aChildContent - * @param aChildContent the child content for which a frame is to be - * created - * @param aInsertionPoint [OUT] the frame that should parent the frame - * for |aChildContent|. - */ - NS_IMETHOD GetInsertionPoint(nsIPresShell* aPresShell, - nsIFrame* aParentFrame, - nsIContent* aChildContent, - nsIFrame** aInsertionPoint, - PRBool* aMultiple = nsnull) = 0; -}; - -#endif /* nsIStyleFrameConstruction_h___ */ diff --git a/layout/html/base/src/nsPresShell.cpp b/layout/html/base/src/nsPresShell.cpp index 3b981265bd6..9ccc808178e 100644 --- a/layout/html/base/src/nsPresShell.cpp +++ b/layout/html/base/src/nsPresShell.cpp @@ -1644,9 +1644,7 @@ PresShell::Init(nsIDocument* aDocument, // before creating any frames. SetPreferenceStyleRules(PR_FALSE); - result = nsComponentManager::CreateInstance(kFrameSelectionCID, nsnull, - NS_GET_IID(nsIFrameSelection), - getter_AddRefs(mSelection)); + mSelection = do_CreateInstance(kFrameSelectionCID, &result); if (NS_FAILED(result)) return result; @@ -3541,6 +3539,9 @@ PresShell::BeginUpdate(nsIDocument *aDocument, nsUpdateType aUpdateType) #ifdef DEBUG mUpdateCount++; #endif + if (aUpdateType & UPDATE_STYLE) + mStyleSet->BeginUpdate(); + return NS_OK; } @@ -3552,6 +3553,9 @@ PresShell::EndUpdate(nsIDocument *aDocument, nsUpdateType aUpdateType) --mUpdateCount; #endif + if (aUpdateType & UPDATE_STYLE) + mStyleSet->EndUpdate(); + if (mStylesHaveChanged && (aUpdateType & UPDATE_STYLE)) return ReconstructStyleData(); @@ -7097,7 +7101,7 @@ PresShell::VerifyIncrementalReflow() // Create a new presentation shell to view the document. Use the // exact same style information that this document has. - nsStyleSet *newSet; + nsAutoPtr newSet; rv = CloneStyleSet(mStyleSet, &newSet); NS_ASSERTION(NS_SUCCEEDED(rv), "failed to clone style set"); rv = mDocument->CreateShell(cx, vm, newSet, &sh); diff --git a/layout/printing/nsPrintEngine.cpp b/layout/printing/nsPrintEngine.cpp index 151e4cc9e08..a4c8dc21387 100644 --- a/layout/printing/nsPrintEngine.cpp +++ b/layout/printing/nsPrintEngine.cpp @@ -2608,7 +2608,8 @@ nsPrintEngine::ReflowPrintObject(nsPrintObject * aPO, PRBool aDoCalcShrink) // init it with the DC (aPO->mPresContext)->Init(mPrt->mPrintDocDC); - rv = mDocViewerPrint->CreateStyleSet(aPO->mDocument, &aPO->mStyleSet); + rv = mDocViewerPrint->CreateStyleSet(aPO->mDocument, + getter_Transfers(aPO->mStyleSet)); NS_ENSURE_SUCCESS(rv, rv); aPO->mViewManager = do_CreateInstance(kViewManagerCID, &rv); diff --git a/layout/printing/nsPrintObject.h b/layout/printing/nsPrintObject.h index 06cd9638010..d0b732607ed 100644 --- a/layout/printing/nsPrintObject.h +++ b/layout/printing/nsPrintObject.h @@ -81,7 +81,7 @@ public: PrintObjectType mFrameType; nsCOMPtr mPresContext; - nsStyleSet *mStyleSet; + nsAutoPtr mStyleSet; nsCOMPtr mPresShell; nsCOMPtr mViewManager; nsCOMPtr mWindow; diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp index 54972c6ad12..ccb28d4acfd 100644 --- a/layout/style/nsRuleNode.cpp +++ b/layout/style/nsRuleNode.cpp @@ -4358,6 +4358,9 @@ PRBool nsRuleNode::Sweep() { // If we're not marked, then we have to delete ourself. + // However, we never allow the root node to GC itself, because nsStyleSet + // wants to hold onto the root node and not worry about re-creating a + // rule walker if the root node is deleted. if (!(mDependentBits & NS_RULE_NODE_GC_MARK) && !IsRoot()) { Destroy(); return PR_TRUE; diff --git a/layout/style/nsStyleSet.cpp b/layout/style/nsStyleSet.cpp index 460ac7e944e..f2d7978bdc5 100644 --- a/layout/style/nsStyleSet.cpp +++ b/layout/style/nsStyleSet.cpp @@ -55,7 +55,7 @@ nsStyleSet::nsStyleSet() : mRuleTree(nsnull), mRuleWalker(nsnull), mDestroyedCount(0), - mBatching(PR_FALSE), + mBatching(0), mInShutdown(PR_FALSE), mDirty(0) { @@ -70,8 +70,10 @@ nsStyleSet::Init(nsIPresContext *aPresContext) NS_ENSURE_TRUE(gQuirkURI, NS_ERROR_OUT_OF_MEMORY); } - if (!BuildDefaultStyleData(aPresContext)) - return NS_ERROR_FAILURE; + if (!BuildDefaultStyleData(aPresContext)) { + mDefaultStyleData.Destroy(0, aPresContext); + return NS_ERROR_OUT_OF_MEMORY; + } mRuleTree = nsRuleNode::CreateRootNode(aPresContext); if (!mRuleTree) { @@ -195,10 +197,8 @@ nsStyleSet::ReplaceSheets(sheetType aType, const nsCOMArray &aNewSheets) { mSheets[aType].Clear(); - for (PRInt32 i = 0; i < aNewSheets.Count(); ++i) { - if (!mSheets[aType].AppendObject(aNewSheets.ObjectAt(i))) - return NS_ERROR_OUT_OF_MEMORY; - } + if (!mSheets[aType].AppendObjects(aNewSheets)) + return NS_ERROR_OUT_OF_MEMORY; if (!mBatching) return GatherRuleProcessors(aType); @@ -212,7 +212,7 @@ nsStyleSet::ReplaceSheets(sheetType aType, nsresult nsStyleSet::AddDocStyleSheet(nsIStyleSheet* aSheet, nsIDocument* aDocument) { - NS_PRECONDITION((nsnull != aSheet) && (nsnull != aDocument), "null arg"); + NS_PRECONDITION(aSheet && aDocument, "null arg"); CHECK_APPLICABLE; nsCOMArray& docSheets = mSheets[eDocSheet]; @@ -248,21 +248,26 @@ nsStyleSet::AddDocStyleSheet(nsIStyleSheet* aSheet, nsIDocument* aDocument) void nsStyleSet::BeginUpdate() { - mBatching = 1; + ++mBatching; } nsresult nsStyleSet::EndUpdate() { + NS_ASSERTION(mBatching > 0, "Unbalanced EndUpdate"); + if (--mBatching) { + // We're not completely done yet. + return NS_OK; + } + for (int i = 0; i < eSheetTypeCount; ++i) { - if (mDirty & 1 << i) { + if (mDirty & (1 << i)) { nsresult rv = GatherRuleProcessors(i); NS_ENSURE_SUCCESS(rv, rv); } } mDirty = 0; - mBatching = 0; return NS_OK; } @@ -721,7 +726,7 @@ nsStyleSet::NotifyStyleContextDestroyed(nsIPresContext* aPresContext, #endif mRuleTree->Sweep(); - NS_ASSERTION(deleted, "Root not must not be gc'd"); + NS_ASSERTION(!deleted, "Root node must not be gc'd"); } } diff --git a/layout/style/nsStyleSet.h b/layout/style/nsStyleSet.h index 31cd29049f5..2de04e13a5c 100644 --- a/layout/style/nsStyleSet.h +++ b/layout/style/nsStyleSet.h @@ -49,6 +49,10 @@ class nsIURI; +// The style set object is created by the document viewer and ownership is +// then handed off to the PresShell. Only the PresShell should delete a +// style set. + class nsStyleSet { public: @@ -156,12 +160,13 @@ class nsStyleSet // Free global data at module shutdown static void FreeGlobals() { NS_IF_RELEASE(gQuirkURI); } - // APIs to manipulate the style sheet lists + // APIs to manipulate the style sheet lists. + // All sheet types are ordered most-significant-first. enum sheetType { eAgentSheet, eUserSheet, eDocSheet, - eOverrideSheet, // override sheets are ordered most significant first + eOverrideSheet, eSheetTypeCount }; @@ -237,9 +242,10 @@ class nsStyleSet PRInt32 mDestroyedCount; // used to batch style context GC nsVoidArray mRoots; // style contexts with no parent - unsigned mBatching : 1; + PRUint16 mBatching; + unsigned mInShutdown : 1; - unsigned mDirty : 6; // one dirty bit is used per sheet type + unsigned mDirty : 7; // one dirty bit is used per sheet type }; #endif