mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 655084 - Remove nsWeakFrame's from editor scripts and the nsTextInputListener to improve perf on pages with lots of text widgets. r=ehsan
This commit is contained in:
parent
969b71d749
commit
f9901669f2
@ -84,7 +84,6 @@ public:
|
||||
RestoreSelectionState(nsTextEditorState *aState, nsTextControlFrame *aFrame,
|
||||
PRInt32 aStart, PRInt32 aEnd)
|
||||
: mFrame(aFrame),
|
||||
mWeakFrame(aFrame),
|
||||
mStart(aStart),
|
||||
mEnd(aEnd),
|
||||
mTextEditorState(aState)
|
||||
@ -92,19 +91,24 @@ public:
|
||||
}
|
||||
|
||||
NS_IMETHOD Run() {
|
||||
if (mWeakFrame.IsAlive()) {
|
||||
if (mFrame) {
|
||||
// SetSelectionRange leads to Selection::AddRange which flushes Layout -
|
||||
// need to block script to avoid nested PrepareEditor calls (bug 642800).
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
mFrame->SetSelectionRange(mStart, mEnd);
|
||||
mTextEditorState->HideSelectionIfBlurred();
|
||||
}
|
||||
mTextEditorState->FinishedRestoringSelection();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Let the text editor tell us we're no longer relevant - avoids use of nsWeakFrame
|
||||
void Revoke() {
|
||||
mFrame = nsnull;
|
||||
}
|
||||
|
||||
private:
|
||||
nsTextControlFrame* mFrame;
|
||||
nsWeakFrame mWeakFrame;
|
||||
PRInt32 mStart;
|
||||
PRInt32 mEnd;
|
||||
nsTextEditorState* mTextEditorState;
|
||||
@ -645,7 +649,7 @@ protected:
|
||||
|
||||
protected:
|
||||
|
||||
nsWeakFrame mFrame;
|
||||
nsIFrame* mFrame;
|
||||
|
||||
nsITextControlElement* const mTxtCtrlElement;
|
||||
|
||||
@ -673,7 +677,8 @@ protected:
|
||||
*/
|
||||
|
||||
nsTextInputListener::nsTextInputListener(nsITextControlElement* aTxtCtrlElement)
|
||||
: mTxtCtrlElement(aTxtCtrlElement)
|
||||
: mFrame(nsnull)
|
||||
, mTxtCtrlElement(aTxtCtrlElement)
|
||||
, mSelectionWasCollapsed(PR_TRUE)
|
||||
, mHadUndoItems(PR_FALSE)
|
||||
, mHadRedoItems(PR_FALSE)
|
||||
@ -703,7 +708,9 @@ NS_IMETHODIMP
|
||||
nsTextInputListener::NotifySelectionChanged(nsIDOMDocument* aDoc, nsISelection* aSel, PRInt16 aReason)
|
||||
{
|
||||
PRBool collapsed;
|
||||
if (!mFrame.IsAlive() || !aDoc || !aSel || NS_FAILED(aSel->GetIsCollapsed(&collapsed)))
|
||||
nsWeakFrame weakFrame = mFrame;
|
||||
|
||||
if (!aDoc || !aSel || NS_FAILED(aSel->GetIsCollapsed(&collapsed)))
|
||||
return NS_OK;
|
||||
|
||||
// Fire the select event
|
||||
@ -748,7 +755,7 @@ nsTextInputListener::NotifySelectionChanged(nsIDOMDocument* aDoc, nsISelection*
|
||||
|
||||
mSelectionWasCollapsed = collapsed;
|
||||
|
||||
if (!mFrame.IsAlive() || !nsContentUtils::IsFocusedContent(mFrame->GetContent()))
|
||||
if (!weakFrame.IsAlive() || !nsContentUtils::IsFocusedContent(mFrame->GetContent()))
|
||||
return NS_OK;
|
||||
|
||||
return UpdateTextInputCommands(NS_LITERAL_STRING("select"));
|
||||
@ -799,7 +806,6 @@ DoCommandCallback(const char *aCommand, void *aData)
|
||||
NS_IMETHODIMP
|
||||
nsTextInputListener::KeyDown(nsIDOMEvent *aDOMEvent)
|
||||
{
|
||||
NS_ENSURE_STATE(mFrame.IsAlive());
|
||||
nsCOMPtr<nsIDOMKeyEvent> keyEvent(do_QueryInterface(aDOMEvent));
|
||||
NS_ENSURE_TRUE(keyEvent, NS_ERROR_INVALID_ARG);
|
||||
|
||||
@ -818,7 +824,6 @@ nsTextInputListener::KeyDown(nsIDOMEvent *aDOMEvent)
|
||||
NS_IMETHODIMP
|
||||
nsTextInputListener::KeyPress(nsIDOMEvent *aDOMEvent)
|
||||
{
|
||||
NS_ENSURE_STATE(mFrame.IsAlive());
|
||||
nsCOMPtr<nsIDOMKeyEvent> keyEvent(do_QueryInterface(aDOMEvent));
|
||||
NS_ENSURE_TRUE(keyEvent, NS_ERROR_INVALID_ARG);
|
||||
|
||||
@ -837,7 +842,6 @@ nsTextInputListener::KeyPress(nsIDOMEvent *aDOMEvent)
|
||||
NS_IMETHODIMP
|
||||
nsTextInputListener::KeyUp(nsIDOMEvent *aDOMEvent)
|
||||
{
|
||||
NS_ENSURE_STATE(mFrame.IsAlive());
|
||||
nsCOMPtr<nsIDOMKeyEvent> keyEvent(do_QueryInterface(aDOMEvent));
|
||||
NS_ENSURE_TRUE(keyEvent, NS_ERROR_INVALID_ARG);
|
||||
|
||||
@ -859,8 +863,9 @@ nsTextInputListener::KeyUp(nsIDOMEvent *aDOMEvent)
|
||||
NS_IMETHODIMP
|
||||
nsTextInputListener::EditAction()
|
||||
{
|
||||
NS_ENSURE_STATE(mFrame.IsAlive());
|
||||
nsITextControlFrame* frameBase = do_QueryFrame(mFrame.GetFrame());
|
||||
nsWeakFrame weakFrame = mFrame;
|
||||
|
||||
nsITextControlFrame* frameBase = do_QueryFrame(mFrame);
|
||||
nsTextControlFrame* frame = static_cast<nsTextControlFrame*> (frameBase);
|
||||
NS_ASSERTION(frame, "Where is our frame?");
|
||||
//
|
||||
@ -887,7 +892,7 @@ nsTextInputListener::EditAction()
|
||||
mHadRedoItems = numRedoItems != 0;
|
||||
}
|
||||
|
||||
if (!mFrame.IsAlive()) {
|
||||
if (!weakFrame.IsAlive()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -916,8 +921,6 @@ nsTextInputListener::EditAction()
|
||||
nsresult
|
||||
nsTextInputListener::UpdateTextInputCommands(const nsAString& commandsToUpdate)
|
||||
{
|
||||
NS_ENSURE_STATE(mFrame.IsAlive());
|
||||
|
||||
nsIContent* content = mFrame->GetContent();
|
||||
NS_ENSURE_TRUE(content, NS_ERROR_FAILURE);
|
||||
|
||||
@ -967,6 +970,7 @@ nsTextInputListener::GetKeyBindings()
|
||||
|
||||
nsTextEditorState::nsTextEditorState(nsITextControlElement* aOwningElement)
|
||||
: mTextCtrlElement(aOwningElement),
|
||||
mRestoringSelection(nsnull),
|
||||
mBoundFrame(nsnull),
|
||||
mTextListener(nsnull),
|
||||
mEditorInitialized(PR_FALSE),
|
||||
@ -1385,8 +1389,13 @@ nsTextEditorState::PrepareEditor(const nsAString *aValue)
|
||||
|
||||
// Restore our selection after being bound to a new frame
|
||||
if (mSelState) {
|
||||
nsContentUtils::AddScriptRunner(new RestoreSelectionState(this, mBoundFrame, mSelState->mStart, mSelState->mEnd));
|
||||
mSelState = nsnull;
|
||||
if (mRestoringSelection) // paranoia
|
||||
mRestoringSelection->Revoke();
|
||||
mRestoringSelection = new RestoreSelectionState(this, mBoundFrame, mSelState->mStart, mSelState->mEnd);
|
||||
if (mRestoringSelection) {
|
||||
nsContentUtils::AddScriptRunner(mRestoringSelection);
|
||||
mSelState = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
@ -1419,6 +1428,11 @@ nsTextEditorState::UnbindFromFrame(nsTextControlFrame* aFrame)
|
||||
nsAutoString value;
|
||||
GetValue(value, PR_TRUE);
|
||||
|
||||
if (mRestoringSelection) {
|
||||
mRestoringSelection->Revoke();
|
||||
mRestoringSelection = nsnull;
|
||||
}
|
||||
|
||||
// Save our selection state if needed.
|
||||
// Note that nsTextControlFrame::GetSelectionRange attempts to initialize the
|
||||
// editor before grabbing the range, and because this is not an acceptable
|
||||
|
@ -140,6 +140,8 @@ struct SelectionState;
|
||||
* frame is bound to the text editor state object.
|
||||
*/
|
||||
|
||||
class RestoreSelectionState;
|
||||
|
||||
class nsTextEditorState {
|
||||
public:
|
||||
explicit nsTextEditorState(nsITextControlElement* aOwningElement);
|
||||
@ -213,6 +215,8 @@ public:
|
||||
void HideSelectionIfBlurred();
|
||||
|
||||
private:
|
||||
friend class RestoreSelectionState;
|
||||
|
||||
// not copy constructible
|
||||
nsTextEditorState(const nsTextEditorState&);
|
||||
// not assignable
|
||||
@ -225,6 +229,8 @@ private:
|
||||
void DestroyEditor();
|
||||
void Clear();
|
||||
|
||||
void FinishedRestoringSelection() { mRestoringSelection = nsnull; }
|
||||
|
||||
class InitializationGuard {
|
||||
public:
|
||||
explicit InitializationGuard(nsTextEditorState& aState) :
|
||||
@ -253,6 +259,7 @@ private:
|
||||
nsITextControlElement* const mTextCtrlElement;
|
||||
nsRefPtr<nsTextInputSelectionImpl> mSelCon;
|
||||
nsAutoPtr<SelectionState> mSelState;
|
||||
RestoreSelectionState* mRestoringSelection;
|
||||
nsCOMPtr<nsIEditor> mEditor;
|
||||
nsCOMPtr<nsIContent> mRootNode;
|
||||
nsCOMPtr<nsIContent> mPlaceholderDiv;
|
||||
|
@ -201,6 +201,12 @@ nsTextControlFrame::DestroyFrom(nsIFrame* aDestructRoot)
|
||||
{
|
||||
mScrollEvent.Revoke();
|
||||
|
||||
EditorInitializer* initializer = (EditorInitializer*) Properties().Get(TextControlInitializer());
|
||||
if (initializer) {
|
||||
initializer->Revoke();
|
||||
Properties().Delete(TextControlInitializer());
|
||||
}
|
||||
|
||||
// Unbind the text editor state object from the frame. The editor will live
|
||||
// on, but things like controllers will be released.
|
||||
nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent());
|
||||
@ -445,10 +451,17 @@ nsTextControlFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
|
||||
if (initEagerly) {
|
||||
NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
|
||||
"Someone forgot a script blocker?");
|
||||
|
||||
if (!nsContentUtils::AddScriptRunner(new EditorInitializer(this))) {
|
||||
EditorInitializer* initializer = (EditorInitializer*) Properties().Get(TextControlInitializer());
|
||||
if (initializer) {
|
||||
initializer->Revoke();
|
||||
}
|
||||
initializer = new EditorInitializer(this);
|
||||
if (!nsContentUtils::AddScriptRunner(initializer)) {
|
||||
initializer->Revoke(); // paranoia
|
||||
delete initializer;
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
Properties().Set(TextControlInitializer(),initializer);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -180,6 +180,11 @@ public:
|
||||
|
||||
NS_DECL_QUERYFRAME
|
||||
|
||||
// Temp reference to scriptrunner
|
||||
// We could make these auto-Revoking via the "delete" entry for safety
|
||||
NS_DECLARE_FRAME_PROPERTY(TextControlInitializer, nsnull)
|
||||
|
||||
|
||||
public: //for methods who access nsTextControlFrame directly
|
||||
void FireOnInput(PRBool aTrusted);
|
||||
void SetValueChanged(PRBool aValueChanged);
|
||||
@ -286,23 +291,27 @@ protected:
|
||||
class EditorInitializer : public nsRunnable {
|
||||
public:
|
||||
EditorInitializer(nsTextControlFrame* aFrame) :
|
||||
mWeakFrame(aFrame),
|
||||
mFrame(aFrame) {}
|
||||
|
||||
NS_IMETHOD Run() {
|
||||
if (mWeakFrame) {
|
||||
if (mFrame) {
|
||||
nsCOMPtr<nsIPresShell> shell =
|
||||
mWeakFrame.GetFrame()->PresContext()->GetPresShell();
|
||||
mFrame->PresContext()->GetPresShell();
|
||||
PRBool observes = shell->ObservesNativeAnonMutationsForPrint();
|
||||
shell->ObserveNativeAnonMutationsForPrint(PR_TRUE);
|
||||
mFrame->EnsureEditorInitialized();
|
||||
shell->ObserveNativeAnonMutationsForPrint(observes);
|
||||
mFrame->FinishedInitializer();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// avoids use of nsWeakFrame
|
||||
void Revoke() {
|
||||
mFrame = nsnull;
|
||||
}
|
||||
|
||||
private:
|
||||
nsWeakFrame mWeakFrame;
|
||||
nsTextControlFrame* mFrame;
|
||||
};
|
||||
|
||||
@ -388,6 +397,10 @@ private:
|
||||
*/
|
||||
nsresult GetRootNodeAndInitializeEditor(nsIDOMElement **aRootElement);
|
||||
|
||||
void FinishedInitializer() {
|
||||
Properties().Delete(TextControlInitializer());
|
||||
}
|
||||
|
||||
private:
|
||||
// these packed bools could instead use the high order bits on mState, saving 4 bytes
|
||||
PRPackedBool mUseEditor;
|
||||
|
Loading…
Reference in New Issue
Block a user