NEW327694
[GTK][WPE] Input method delete-surrounding can be applied before text committed just before it
https://bugs.webkit.org/show_bug.cgi?id=327694
Summary [GTK][WPE] Input method delete-surrounding can be applied before text committ...
Simon Pena
Reported 2026-10-15 07:10:49 PDT
When an input method commits text and then deletes surrounding text with no gap in between, WebKit can apply the delete first. Commits are turned into synthesized key presses (webkitWebViewConfirmComposition()), so they wait in the key event queue until the previous key event has been handled by the web process. Delete-surrounding is sent to the web process right away (webkitWebViewDeleteSurrounding()). So a delete can overtake a commit that is still queued. For example, in an empty textarea: commit "x", commit "y", delete-surrounding (-1, 1). The expected result is "x". The page gets the edits as insert "x", delete, insert "y", and the result is "y". This can happen with a keyboard that replaces text quickly, for example deleting part of a word and committing a suggestion while the previous commit has not been handled yet. The API test below reproduces it on WPE, 10 runs out of 10 (Release build, 323811@main plus unrelated local changes). GTK goes through the same path (webkitWebViewBaseSynthesizeCompositionKeyPress() calls WebPageProxy::handleKeyboardEvent()), but I did not run the test there: static void testWebKitInputMethodContextCommitThenDeleteSurrounding(InputMethodTest* test, gconstpointer) { test->loadHtml(testHTML, nullptr); test->waitUntilLoadFinished(); test->focusEditableAndWaitUntilInputMethodEnabled(); test->runJavaScriptAndWaitUntilFinished("window.inputEvents = [];" "input.addEventListener('input', event => inputEvents.push(event.inputType + ':' + input.value));", nullptr); g_signal_emit_by_name(test->m_context.get(), "committed", "x", nullptr); g_signal_emit_by_name(test->m_context.get(), "committed", "y", nullptr); test->deleteSurrounding(-1, 1); test->assertJavaScriptBecomesTrue("inputEvents.filter(event => event.startsWith('insertText:')).length === 2"); auto editableValue = test->editableValue(); g_assert_cmpstr(editableValue.get(), ==, "x"); } Result: input events: ["insertText:x","deleteContent:","insertText:y"] assertion failed (editableValue.get() == "x"): ("y" == "x")
Attachments
Note You need to log in before you can comment on or make changes to this bug.