diff --git a/layout/forms/HTMLSelectEventListener.cpp b/layout/forms/HTMLSelectEventListener.cpp index 93bbab2f2399..8ab77f9c40ad 100644 --- a/layout/forms/HTMLSelectEventListener.cpp +++ b/layout/forms/HTMLSelectEventListener.cpp @@ -54,9 +54,11 @@ namespace mozilla { static StaticAutoPtr sIncrementalString; static DOMTimeStamp gLastKeyTime = 0; +static uintptr_t sLastKeyListener = 0; static constexpr int32_t kNothingSelected = -1; static nsString& GetIncrementalString() { + MOZ_ASSERT(sLastKeyListener != 0); if (!sIncrementalString) { sIncrementalString = new nsString(); ClearOnShutdown(&sIncrementalString); @@ -64,24 +66,33 @@ static nsString& GetIncrementalString() { return *sIncrementalString; } -class MOZ_RAII AutoIncrementalSearchResetter { +class MOZ_RAII AutoIncrementalSearchHandler { public: - AutoIncrementalSearchResetter() = default; - ~AutoIncrementalSearchResetter() { - if (!mCancelled) { + explicit AutoIncrementalSearchHandler(HTMLSelectEventListener& aListener) { + if (sLastKeyListener != uintptr_t(&aListener)) { + sLastKeyListener = uintptr_t(&aListener); GetIncrementalString().Truncate(); } } - void Cancel() { mCancelled = true; } + ~AutoIncrementalSearchHandler() { + if (!mResettingCancelled) { + GetIncrementalString().Truncate(); + } + } + void CancelResetting() { mResettingCancelled = true; } private: - bool mCancelled = false; + bool mResettingCancelled = false; }; NS_IMPL_ISUPPORTS(HTMLSelectEventListener, nsIMutationObserver, nsIDOMEventListener) -HTMLSelectEventListener::~HTMLSelectEventListener() = default; +HTMLSelectEventListener::~HTMLSelectEventListener() { + if (sLastKeyListener == uintptr_t(this)) { + sLastKeyListener = 0; + } +} nsListControlFrame* HTMLSelectEventListener::GetListControlFrame() const { if (mIsCombobox) { @@ -484,7 +495,7 @@ nsresult HTMLSelectEventListener::KeyPress(dom::Event* aKeyEvent) { return NS_OK; } - AutoIncrementalSearchResetter incrementalSearchResetter; + AutoIncrementalSearchHandler incrementalHandler(*this); const WidgetKeyboardEvent* keyEvent = aKeyEvent->WidgetEventPtr()->AsKeyboardEvent(); @@ -521,7 +532,7 @@ nsresult HTMLSelectEventListener::KeyPress(dom::Event* aKeyEvent) { // Backspace key will delete the last char in the string. Otherwise, // non-printable keypress should reset incremental search. if (keyEvent->mKeyCode == NS_VK_BACK) { - incrementalSearchResetter.Cancel(); + incrementalHandler.CancelResetting(); if (!GetIncrementalString().IsEmpty()) { GetIncrementalString().Truncate(GetIncrementalString().Length() - 1); } @@ -535,7 +546,7 @@ nsresult HTMLSelectEventListener::KeyPress(dom::Event* aKeyEvent) { return NS_OK; } - incrementalSearchResetter.Cancel(); + incrementalHandler.CancelResetting(); // We ate the key if we got this far. aKeyEvent->PreventDefault(); @@ -647,7 +658,7 @@ nsresult HTMLSelectEventListener::KeyDown(dom::Event* aKeyEvent) { return NS_OK; } - AutoIncrementalSearchResetter incrementalSearchResetter; + AutoIncrementalSearchHandler incrementalHandler(*this); if (aKeyEvent->DefaultPrevented()) { return NS_OK; @@ -760,7 +771,7 @@ nsresult HTMLSelectEventListener::KeyDown(dom::Event* aKeyEvent) { } break; default: // printable key will be handled by keypress event. - incrementalSearchResetter.Cancel(); + incrementalHandler.CancelResetting(); return NS_OK; }