Skip to content

Commit d2f3dc1

Browse files
committed
Bug 1357142: Kill PresShell::RecreateFramesFor. r=bz
It's not only inefficient, but also prone to buggyness. Since styles may not be up-to-date when it happens. Post a reconstruct instead, which ensures a style flush happens before running frame construction. MozReview-Commit-ID: DrakHsJv5fY Signed-off-by: Emilio Cobos Álvarez <emilio@crisal.io> --HG-- extra : rebase_source : 11900af908654336cc2391ab9480542c5474e38f
1 parent e17c529 commit d2f3dc1

8 files changed

+34
-69
lines changed

dom/base/nsObjectLoadingContent.cpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2674,28 +2674,32 @@ nsObjectLoadingContent::NotifyStateChanged(ObjectType aOldType,
26742674

26752675
EventStates newState = ObjectState();
26762676

2677+
if (newState == aOldState && mType == aOldType) {
2678+
return; // Also done.
2679+
}
2680+
26772681
if (newState != aOldState) {
26782682
NS_ASSERTION(thisContent->IsInComposedDoc(), "Something is confused");
26792683
// This will trigger frame construction
26802684
EventStates changedBits = aOldState ^ newState;
2681-
26822685
{
26832686
nsAutoScriptBlocker scriptBlocker;
26842687
doc->ContentStateChanged(thisContent, changedBits);
26852688
}
2686-
if (aSync) {
2687-
NS_ASSERTION(InActiveDocument(thisContent), "Something is confused");
2688-
// Make sure that frames are actually constructed immediately.
2689-
doc->FlushPendingNotifications(FlushType::Frames);
2690-
}
26912689
} else if (aOldType != mType) {
26922690
// If our state changed, then we already recreated frames
26932691
// Otherwise, need to do that here
26942692
nsCOMPtr<nsIPresShell> shell = doc->GetShell();
26952693
if (shell) {
2696-
shell->RecreateFramesFor(thisContent);
2694+
shell->PostRecreateFramesFor(thisContent->AsElement());
26972695
}
26982696
}
2697+
2698+
if (aSync) {
2699+
NS_ASSERTION(InActiveDocument(thisContent), "Something is confused");
2700+
// Make sure that frames are actually constructed immediately.
2701+
doc->FlushPendingNotifications(FlushType::Frames);
2702+
}
26992703
}
27002704

27012705
nsObjectLoadingContent::ObjectType

dom/xbl/nsBindingManager.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -255,11 +255,11 @@ nsBindingManager::GetAnonymousNodesFor(nsIContent* aContent)
255255
}
256256

257257
nsresult
258-
nsBindingManager::ClearBinding(nsIContent* aContent)
258+
nsBindingManager::ClearBinding(Element* aElement)
259259
{
260260
// Hold a ref to the binding so it won't die when we remove it from our table
261261
RefPtr<nsXBLBinding> binding =
262-
aContent ? aContent->GetXBLBinding() : nullptr;
262+
aElement ? aElement->GetXBLBinding() : nullptr;
263263

264264
if (!binding) {
265265
return NS_OK;
@@ -273,14 +273,14 @@ nsBindingManager::ClearBinding(nsIContent* aContent)
273273
// XXXbz should that be ownerdoc? Wouldn't we need a ref to the
274274
// currentdoc too? What's the one that should be passed to
275275
// ChangeDocument?
276-
nsCOMPtr<nsIDocument> doc = aContent->OwnerDoc();
276+
nsCOMPtr<nsIDocument> doc = aElement->OwnerDoc();
277277

278278
// Finally remove the binding...
279279
// XXXbz this doesn't remove the implementation! Should fix! Until
280280
// then we need the explicit UnhookEventHandlers here.
281281
binding->UnhookEventHandlers();
282282
binding->ChangeDocument(doc, nullptr);
283-
aContent->SetXBLBinding(nullptr, this);
283+
aElement->SetXBLBinding(nullptr, this);
284284
binding->MarkForDeath();
285285

286286
// ...and recreate its frames. We need to do this since the frames may have
@@ -290,7 +290,8 @@ nsBindingManager::ClearBinding(nsIContent* aContent)
290290
nsIPresShell *presShell = doc->GetShell();
291291
NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
292292

293-
return presShell->RecreateFramesFor(aContent);;
293+
presShell->PostRecreateFramesFor(aElement);
294+
return NS_OK;
294295
}
295296

296297
nsresult

dom/xbl/nsBindingManager.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ class nsBindingManager final : public nsStubMutationObserver
9090
nsresult GetAnonymousNodesFor(nsIContent* aContent, nsIDOMNodeList** aResult);
9191
nsINodeList* GetAnonymousNodesFor(nsIContent* aContent);
9292

93-
nsresult ClearBinding(nsIContent* aContent);
93+
nsresult ClearBinding(mozilla::dom::Element* aElement);
9494
nsresult LoadBindingDocument(nsIDocument* aBoundDoc, nsIURI* aURL,
9595
nsIPrincipal* aOriginPrincipal);
9696

dom/xbl/nsXBLResourceLoader.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -221,15 +221,16 @@ nsXBLResourceLoader::NotifyBoundElements()
221221
uint32_t eltCount = mBoundElements.Count();
222222
for (uint32_t j = 0; j < eltCount; j++) {
223223
nsCOMPtr<nsIContent> content = mBoundElements.ObjectAt(j);
224-
224+
MOZ_ASSERT(content->IsElement());
225+
225226
bool ready = false;
226227
xblService->BindingReady(content, bindingURI, &ready);
227228

228229
if (ready) {
229230
// We need the document to flush out frame construction and
230231
// such, so we want to use the current document.
231232
nsIDocument* doc = content->GetUncomposedDoc();
232-
233+
233234
if (doc) {
234235
// Flush first to make sure we can get the frame for content
235236
doc->FlushPendingNotifications(FlushType::Frames);
@@ -248,11 +249,14 @@ nsXBLResourceLoader::NotifyBoundElements()
248249
nsIFrame* childFrame = content->GetPrimaryFrame();
249250
if (!childFrame) {
250251
// Check to see if it's in the undisplayed content map.
252+
//
253+
// FIXME(emilio, bug 1359384): What about display: contents stuff?
254+
// Looks like this would be inefficient in that case?
251255
nsStyleContext* sc =
252256
shell->FrameManager()->GetUndisplayedContent(content);
253257

254258
if (!sc) {
255-
shell->RecreateFramesFor(content);
259+
shell->PostRecreateFramesFor(content->AsElement());
256260
}
257261
}
258262
}

editor/libeditor/HTMLAnonymousNodeEditor.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -233,16 +233,16 @@ HTMLEditor::CreateAnonymousElement(nsIAtom* aTag,
233233
newContent->AddMutationObserver(observer);
234234

235235
#ifdef DEBUG
236-
// Editor anonymous content gets passed to RecreateFramesFor... which can't
237-
// _really_ deal with anonymous content (because it can't get the frame tree
238-
// ordering right). But for us the ordering doesn't matter so this is sort of
239-
// ok.
236+
// Editor anonymous content gets passed to PostRecreateFramesFor... which
237+
// can't _really_ deal with anonymous content (because it can't get the frame
238+
// tree ordering right). But for us the ordering doesn't matter so this is
239+
// sort of ok.
240240
newContent->SetProperty(nsGkAtoms::restylableAnonymousNode,
241241
reinterpret_cast<void*>(true));
242242
#endif // DEBUG
243243

244244
// display the element
245-
ps->RecreateFramesFor(newContent);
245+
ps->PostRecreateFramesFor(newContent);
246246

247247
return newContent.forget();
248248
}

layout/base/PresShell.cpp

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -2946,44 +2946,6 @@ PresShell::CreateFramesFor(nsIContent* aContent)
29462946
--mChangeNestCount;
29472947
}
29482948

2949-
nsresult
2950-
PresShell::RecreateFramesFor(nsIContent* aContent)
2951-
{
2952-
NS_ENSURE_TRUE(mPresContext, NS_ERROR_FAILURE);
2953-
if (!mDidInitialize) {
2954-
// Nothing to do here. In fact, if we proceed and aContent is the
2955-
// root we will crash.
2956-
return NS_OK;
2957-
}
2958-
2959-
// Don't call RecreateFramesForContent since that is not exported and we want
2960-
// to keep the number of entrypoints down.
2961-
2962-
NS_ASSERTION(mViewManager, "Should have view manager");
2963-
2964-
// Have to make sure that the content notifications are flushed before we
2965-
// start messing with the frame model; otherwise we can get content doubling.
2966-
mDocument->FlushPendingNotifications(FlushType::ContentAndNotify);
2967-
2968-
nsAutoScriptBlocker scriptBlocker;
2969-
2970-
nsStyleChangeList changeList(mPresContext->StyleSet()->BackendType());
2971-
changeList.AppendChange(nullptr, aContent, nsChangeHint_ReconstructFrame);
2972-
2973-
// We might have restyles pending when we're asked to recreate frames.
2974-
// Record that we're OK with stale styles being returned, to avoid assertions.
2975-
ServoStyleSet::AutoAllowStaleStyles guard(mStyleSet->GetAsServo());
2976-
2977-
// Mark ourselves as not safe to flush while we're doing frame construction.
2978-
++mChangeNestCount;
2979-
RestyleManager* restyleManager = mPresContext->RestyleManager();
2980-
restyleManager->ProcessRestyledFrames(changeList);
2981-
restyleManager->FlushOverflowChangedTracker();
2982-
--mChangeNestCount;
2983-
2984-
return NS_OK;
2985-
}
2986-
29872949
void
29882950
nsIPresShell::PostRecreateFramesFor(Element* aElement)
29892951
{

layout/base/PresShell.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ class nsAutoCauseReflowNotifier;
5656

5757
namespace mozilla {
5858

59+
namespace dom {
60+
class Element;
61+
} // namespace dom
62+
5963
class EventDispatchingCallback;
6064

6165
// A set type for tracking visible frames, for use by the visibility code in
@@ -132,11 +136,6 @@ class PresShell final : public nsIPresShell,
132136
nsIContent** aDestroyedFramesFor) override;
133137
virtual void CreateFramesFor(nsIContent* aContent) override;
134138

135-
/**
136-
* Recreates the frames for a node
137-
*/
138-
virtual nsresult RecreateFramesFor(nsIContent* aContent) override;
139-
140139
/**
141140
* Post a callback that should be handled after reflow has finished.
142141
*/

layout/base/nsIPresShell.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -549,11 +549,6 @@ class nsIPresShell : public nsISupports
549549
*/
550550
virtual void CreateFramesFor(nsIContent* aContent) = 0;
551551

552-
/**
553-
* Recreates the frames for a node
554-
*/
555-
virtual nsresult RecreateFramesFor(nsIContent* aContent) = 0;
556-
557552
void PostRecreateFramesFor(mozilla::dom::Element* aElement);
558553
void RestyleForAnimation(mozilla::dom::Element* aElement,
559554
nsRestyleHint aHint);

0 commit comments

Comments
 (0)