Issue #2388 - Part 2: move focus at every selection change when it's called by JS

This commit is contained in:
Moonchild 2024-01-16 21:28:04 +01:00 • committed by roytam1
commit 681193a256
4 changed files with 202 additions and 16 deletions

View file

@ -998,7 +998,16 @@ nsRange::DoSetRange(nsINode* aStartN, uint32_t aStartOffset,
// Notify any selection listeners. This has to occur last because otherwise the world
// could be observed by a selection listener while the range was in an invalid state.
if (mSelection) {
mSelection->NotifySelectionListeners(mCalledByJS);
// Our internal code should not move focus with using this instance while
// it's calling Selection::NotifySelectionListeners() which may move focus
// or calls selection listeners. So, let's set mCalledByJS to false here
// since non-*JS() methods don't set it to false.
AutoCalledByJSRestore calledByJSRestorer(*this);
mCalledByJS = false;
// Be aware, this range may be modified or stop being a range for selection
// after this call. Additionally, the selection instance may have gone.
RefPtr<Selection> selection = mSelection;
selection->NotifySelectionListeners(calledByJSRestorer.SavedValue());
}
}
@ -1228,7 +1237,8 @@ nsRange::IsValidBoundary(nsINode* aNode)
void
nsRange::SetStartJS(nsINode& aNode, uint32_t aOffset, ErrorResult& aErr)
{
AutoCalledByJSSetter markAsCalledByJS(*this);
AutoCalledByJSRestore calledByJSRestorer(*this);
mCalledByJS = true;
SetStart(aNode, aOffset, aErr);
}
@ -1290,7 +1300,8 @@ nsRange::SetStart(nsINode* aParent, uint32_t aOffset)
void
nsRange::SetStartBeforeJS(nsINode& aNode, ErrorResult& aErr)
{
AutoCalledByJSSetter markAsCalledByJS(*this);
AutoCalledByJSRestore calledByJSRestorer(*this);
mCalledByJS = true;
SetStartBefore(aNode, aErr);
}
@ -1328,7 +1339,8 @@ nsRange::SetStartBefore(nsIDOMNode* aSibling)
void
nsRange::SetStartAfterJS(nsINode& aNode, ErrorResult& aErr)
{
AutoCalledByJSSetter markAsCalledByJS(*this);
AutoCalledByJSRestore calledByJSRestorer(*this);
mCalledByJS = true;
SetStartAfter(aNode, aErr);
}
@ -1366,7 +1378,8 @@ nsRange::SetStartAfter(nsIDOMNode* aSibling)
void
nsRange::SetEndJS(nsINode& aNode, uint32_t aOffset, ErrorResult& aErr)
{
AutoCalledByJSSetter markAsCalledByJS(*this);
AutoCalledByJSRestore calledByJSRestorer(*this);
mCalledByJS = true;
SetEnd(aNode, aOffset, aErr);
}
@ -1487,7 +1500,8 @@ nsRange::SetStartAndEnd(nsINode* aStartParent, uint32_t aStartOffset,
void
nsRange::SetEndBeforeJS(nsINode& aNode, ErrorResult& aErr)
{
AutoCalledByJSSetter markAsCalledByJS(*this);
AutoCalledByJSRestore calledByJSRestorer(*this);
mCalledByJS = true;
SetEndBefore(aNode, aErr);
}
@ -1525,7 +1539,8 @@ nsRange::SetEndBefore(nsIDOMNode* aSibling)
void
nsRange::SetEndAfterJS(nsINode& aNode, ErrorResult& aErr)
{
AutoCalledByJSSetter markAsCalledByJS(*this);
AutoCalledByJSRestore calledByJSRestorer(*this);
mCalledByJS = true;
SetEndAfter(aNode, aErr);
}
@ -1578,7 +1593,8 @@ nsRange::Collapse(bool aToStart)
void
nsRange::CollapseJS(bool aToStart)
{
AutoCalledByJSSetter markAsCalledByJS(*this);
AutoCalledByJSRestore calledByJSRestorer(*this);
mCalledByJS = true;
Unused << Collapse(aToStart);
}
@ -1596,7 +1612,8 @@ nsRange::SelectNode(nsIDOMNode* aN)
void
nsRange::SelectNodeJS(nsINode& aNode, ErrorResult& aErr)
{
AutoCalledByJSSetter markAsCalledByJS(*this);
AutoCalledByJSRestore calledByJSRestorer(*this);
mCalledByJS = true;
SelectNode(aNode, aErr);
}
@ -1642,7 +1659,8 @@ nsRange::SelectNodeContents(nsIDOMNode* aN)
void
nsRange::SelectNodeContentsJS(nsINode& aNode, ErrorResult& aErr)
{
AutoCalledByJSSetter markAsCalledByJS(*this);
AutoCalledByJSRestore calledByJSRestorer(*this);
mCalledByJS = true;
SelectNodeContents(aNode, aErr);
}

View file

@ -413,7 +413,7 @@ protected:
// Assume that this is guaranteed that this is held by the caller when
// this is used. (Note that we cannot use AutoRestore for mCalledByJS
// due to a bit field.)
class MOZ_RAII AutoCalledByJSSetter final
class MOZ_RAII AutoCalledByJSRestore final
{
private:
nsRange& mRange;
@ -421,18 +421,18 @@ protected:
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
public:
explicit AutoCalledByJSSetter(nsRange& aRange
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
explicit AutoCalledByJSRestore(nsRange& aRange
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: mRange(aRange)
, mOldValue(aRange.mCalledByJS)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
mRange.mCalledByJS = true;
}
~AutoCalledByJSSetter()
~AutoCalledByJSRestore()
{
mRange.mCalledByJS = mOldValue;
}
bool SavedValue() const { return mOldValue; }
};
struct MOZ_STACK_CLASS AutoInvalidateSelection