Skip to content

Commit

Permalink
The beforeinput event should fire before textInput
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=268988

Reviewed by NOBODY (OOPS!).

This change (controlled by the ConformantBeforeinputEventFiringOrderEnabled,
preference, also introduced in this change) makes WebKit fire the beforeinput
and textInput events in the order: beforeinput first, textInput after —
conforming to the requirements at w3c/uievents#362 and
https://w3c.github.io/uievents/event-algo.html#fire%20key%20input%20events
and consistent with the order in which the events are fired in Blink.

Otherwise, without this change, WebKit fires the events in the order:
textInput first, beforeinput after — which breaks conformance with the
spec requirements, and breaks compatibility with Blink.

Note also that this change makes WebKit conform to the requirements in
https://w3c.github.io/uievents/event-algo.html#fire%20key%20input%20events,
https://w3c.github.io/uievents/event-algo.html#handle%20native%20paste, and
https://w3c.github.io/uievents/event-algo.html#end%20composition — limiting
textInput to being fired only when ending a composition or when the input
type is insertText, insertParagraph, insertLineBreak, or insertFromPaste.

* LayoutTests/editing/execCommand/break-out-of-empty-list-item.html:
* LayoutTests/editing/inserting/typing-space-to-trigger-smart-link.html:
* LayoutTests/editing/pasteboard/paste-text-events-expected.txt:
* LayoutTests/editing/pasteboard/paste-text-events.html:
* LayoutTests/editing/style/highlight-insert-paragraph.html:
* LayoutTests/fast/events/input-events-fired-when-typing-expected.txt:
* LayoutTests/fast/events/input-events-fired-when-typing-nonconforming-expected.txt: Copied from LayoutTests/fast/events/input-events-fired-when-typing-expected.txt.
* LayoutTests/fast/events/input-events-fired-when-typing-nonconforming.html: Copied from LayoutTests/fast/events/input-events-fired-when-typing.html.
* LayoutTests/fast/events/input-events-fired-when-typing.html:
* LayoutTests/fast/events/ios/submit-form-target-blank-using-return-key-old-code-path-expected.txt: Added.
* LayoutTests/fast/events/ios/submit-form-target-blank-using-return-key-old-code-path.html: Added.
* LayoutTests/fast/forms/onchange-change-type.html:
* LayoutTests/http/tests/navigation/keyboard-events-during-provisional-navigation-expected.txt:
* LayoutTests/http/tests/navigation/keyboard-events-during-provisional-subframe-navigation-expected.txt:
* LayoutTests/platform/ios/TestExpectations:
* LayoutTests/platform/mac-wk2/http/tests/navigation/keyboard-events-during-provisional-navigation-expected.txt:
* Source/WTF/Scripts/Preferences/UnifiedWebPreferences.yaml:
* Source/WebCore/editing/AlternativeTextController.cpp:
(WebCore::AlternativeTextController::insertDictatedText):
* Source/WebCore/editing/Editor.cpp:
(WebCore::dispatchTextInputEvent):
(WebCore::Editor::selectionForCommand):
(WebCore::Editor::handleTextEvent):
(WebCore::Editor::pasteAsPlainText):
(WebCore::Editor::pasteAsFragment):
(WebCore::dispatchTextInputEvents):
(WebCore::Editor::appliedEditing):
(WebCore::Editor::insertText):
(WebCore::Editor::insertTextForConfirmedComposition):
(WebCore::Editor::insertTextWithoutSendingTextEventNew):
(WebCore::Editor::insertTextWithoutSendingTextEventOld):
(WebCore::Editor::setComposition):
(WebCore::Editor::insertTextWithoutSendingTextEvent): Deleted.
* Source/WebCore/editing/Editor.h:
* Source/WebCore/editing/EditorCommand.cpp:
(WebCore::executeInsertBacktab):
(WebCore::executeInsertLineBreak):
(WebCore::executeInsertNewline):
(WebCore::executeInsertTab):
(WebCore::executeYank):
(WebCore::executeYankAndSelect):
(WebCore::enabledVisibleSelection):
(WebCore::enabledVisibleSelectionAndMark):
(WebCore::enableCaretInEditableText):
(WebCore::enabledInEditableText):
* Source/WebCore/html/HTMLInputElement.cpp:
(WebCore::HTMLInputElement::defaultEventHandler):
* Source/WebCore/page/EventHandler.cpp:
(WebCore::EventHandler::handleTextInput):
* Source/WebCore/page/EventHandler.h:
  • Loading branch information
sideshowbarker committed May 28, 2024
1 parent ade27f1 commit 3349026
Show file tree
Hide file tree
Showing 24 changed files with 568 additions and 128 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,6 @@
testContainer.contentEditable = true;
document.body.appendChild(testContainer);

function pressKey(key)
{
if (window.KeyEvent) {
var ev = document.createEvent("KeyboardEvent");
ev.initKeyEvent("keypress", true, true, window, 0,0,0,0, 0, key.charCodeAt(0));
document.body.dispatchEvent(ev);
}
else {
var ev = document.createEvent("TextEvent");
ev.initTextEvent('textInput', true, true, null, key.charAt(0));
document.body.dispatchEvent(ev);
}
}

function enterAtTarget(initialContent)
{
testContainer.innerHTML = initialContent;
Expand All @@ -39,8 +25,7 @@
s.removeAllRanges();
s.addRange(r);

pressKey('\n');

document.execCommand("InsertParagraph");
return testContainer.innerHTML;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
var testTypeSpaceDiv = document.getElementById('testTypeSpace');
var targetText = testTypeSpaceDiv.firstChild;
window.getSelection().setPosition(targetText, 15);
pressKey(" ");
document.execCommand("InsertText", false, " ");
var expectedContents = "The <a href=\"http://www.foo.com\">www.foo.com</a> should be underlined and there is an anchor node created for it.";
if (expectedContents == testTypeSpaceDiv.innerHTML)
document.getElementById('log').textContent = "PASS: the anchor for 'www.foo.com' has been created.\n"
Expand All @@ -22,18 +22,18 @@
var testTypeLinkDiv = document.getElementById('testTypeLink');
targetText = testTypeLinkDiv.firstChild;
window.getSelection().setPosition(targetText, 4);
pressKey("w");
pressKey("w");
pressKey("w");
pressKey(".");
pressKey("b");
pressKey("a");
pressKey("r");
pressKey(".");
pressKey("c");
pressKey("o");
pressKey("m");
pressKey(" ");
document.execCommand("InsertText", false, "w");
document.execCommand("InsertText", false, "w");
document.execCommand("InsertText", false, "w");
document.execCommand("InsertText", false, ".");
document.execCommand("InsertText", false, "b");
document.execCommand("InsertText", false, "a");
document.execCommand("InsertText", false, "r");
document.execCommand("InsertText", false, ".");
document.execCommand("InsertText", false, "c");
document.execCommand("InsertText", false, "o");
document.execCommand("InsertText", false, "m");
document.execCommand("InsertText", false, " ");
expectedContents = "The <a href=\"http://www.bar.com\">www.bar.com</a> should be underlined and there is an anchor node created for it.";
if (expectedContents == testTypeLinkDiv.innerHTML)
document.getElementById('log').textContent += "PASS: the anchor for 'www.bar.com' has been created."
Expand All @@ -43,19 +43,6 @@
if (window.internals)
internals.setAutomaticLinkDetectionEnabled(false);
}

function pressKey(key)
{
if (window.KeyEvent) {
var ev = document.createEvent("KeyboardEvent");
ev.initKeyEvent("keypress", true, true, window, 0,0,0,0, 0, key.charCodeAt(0));
document.body.dispatchEvent(ev);
} else {
var ev = document.createEvent("TextEvent");
ev.initTextEvent('textInput', true, true, null, key.charAt(0));
document.body.dispatchEvent(ev);
}
}
</script>
</head>
<body>
Expand Down
13 changes: 0 additions & 13 deletions LayoutTests/editing/pasteboard/paste-text-events-expected.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,6 @@ PASS testTargetInput.value is 'RichHello'
PASS event.data is ''
PASS testTargetEditable.innerHTML is '<b>Rich</b>Hello'
PASS textInputCount is proceedingTestCases.length
PASS event.data is 'PlainHello'
PASS testTargetTextarea.value is ''
PASS event.data is 'PlainHello'
PASS testTargetInput.value is ''
PASS event.data is ''
PASS testTargetEditable.innerHTML is ''
PASS event.data is 'RichHello'
PASS testTargetTextarea.value is ''
PASS event.data is 'RichHello'
PASS testTargetInput.value is ''
PASS event.data is ''
PASS testTargetEditable.innerHTML is ''
PASS textInputCount is cancelingTestCases.length
PASS successfullyParsed is true

TEST COMPLETE
Expand Down
18 changes: 0 additions & 18 deletions LayoutTests/editing/pasteboard/paste-text-events.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@
{
shouldBe("event.data", toStringLiteral(expectedTextEventData));
textInputCount++;
if (willCancelTextInput)
evt.preventDefault();
}

var testSourceRoot = document.createElement("div");
Expand Down Expand Up @@ -112,15 +110,6 @@
[copyRichText, pasteToTargetEditable, targetEditableShouldHave, "<b>Rich</b>Hello", ""],
];

var cancelingTestCases = [
[copyPlainText, pasteToTargetTextarea, targetTextareaShouldHave, "", "PlainHello"],
[copyPlainText, pasteToTargetInput, targetInputShouldHave, "", "PlainHello"],
[copyPlainText, pasteToTargetEditable, targetEditableShouldHave, "", ""],
[copyRichText, pasteToTargetTextarea, targetTextareaShouldHave, "", "RichHello"],
[copyRichText, pasteToTargetInput, targetInputShouldHave, "", "RichHello"],
[copyRichText, pasteToTargetEditable, targetEditableShouldHave, "", ""],
];

function runSingleTest(caseData)
{
var copy = caseData[0];
Expand All @@ -136,17 +125,10 @@
}

textInputCount = 0;
willCancelTextInput = false;
for (var i = 0; i < proceedingTestCases.length; ++i)
runSingleTest(proceedingTestCases[i]);
shouldBe("textInputCount", "proceedingTestCases.length");

textInputCount = 0;
willCancelTextInput = true;
for (var i = 0; i < cancelingTestCases.length; ++i)
runSingleTest(cancelingTestCases[i]);
shouldBe("textInputCount", "cancelingTestCases.length");

// Hides dataset to make dump clean.
testTargetRoot.style.display = "none";
testSourceRoot.style.display = "none";
Expand Down
18 changes: 2 additions & 16 deletions LayoutTests/editing/style/highlight-insert-paragraph.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,6 @@
<div id="console"></div>

<script type="text/javascript">

function pressKey( key ) {
if (window.KeyEvent) {
var ev = document.createEvent("KeyboardEvent");
ev.initKeyEvent("keypress", true, true, window, 0,0,0,0, 0, key.charCodeAt(0));
document.body.dispatchEvent(ev);
}
else {
var ev = document.createEvent("TextEvent");
ev.initTextEvent('textInput', true, true, null, key.charAt(0));
document.body.dispatchEvent(ev);
}
}

if (window.testRunner)
testRunner.dumpAsText();

Expand All @@ -41,8 +27,8 @@
r.setEnd(e.firstChild.firstChild,5);
s.removeAllRanges();
s.addRange(r);
pressKey('\n');
pressKey('e');
document.execCommand("InsertParagraph");
document.execCommand('InsertText', false, 'e')

document.getElementById('console').appendChild(document.createTextNode(e.innerHTML));

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
PASS successfullyParsed is true

TEST COMPLETE
Typing into contenteditable div element
Fired `onbeforeinput`!
PASS event.__lookupGetter__('inputType') is defined.
PASS event.__lookupGetter__('data') is defined.
Expand All @@ -11,6 +12,12 @@ PASS event.bubbles is true
PASS event.cancelable is true
PASS event.composed is true
PASS event.isComposing is false
Fired `textInput`!
PASS event.__lookupGetter__('data') is defined.
PASS event.target.id is expectedTargetID
PASS event.bubbles is true
PASS event.cancelable is true
PASS event.composed is true
Fired `oninput`!
PASS event.__lookupGetter__('inputType') is defined.
PASS event.__lookupGetter__('data') is defined.
Expand All @@ -21,6 +28,7 @@ PASS event.bubbles is true
PASS event.cancelable is false
PASS event.composed is true
PASS event.isComposing is false
Typing into input element
Fired `onbeforeinput`!
PASS event.__lookupGetter__('inputType') is defined.
PASS event.__lookupGetter__('data') is defined.
Expand All @@ -31,6 +39,39 @@ PASS event.bubbles is true
PASS event.cancelable is true
PASS event.composed is true
PASS event.isComposing is false
Fired `textInput`!
PASS event.__lookupGetter__('data') is defined.
PASS event.target.id is expectedTargetID
PASS event.bubbles is true
PASS event.cancelable is true
PASS event.composed is true
Fired `oninput`!
PASS event.__lookupGetter__('inputType') is defined.
PASS event.__lookupGetter__('data') is defined.
PASS event.__lookupGetter__('dataTransfer') is defined.
PASS event.getTargetRanges is defined.
PASS event.target.id is expectedTargetID
PASS event.bubbles is true
PASS event.cancelable is false
PASS event.composed is true
PASS event.isComposing is false
Typing into textarea element
Fired `onbeforeinput`!
PASS event.__lookupGetter__('inputType') is defined.
PASS event.__lookupGetter__('data') is defined.
PASS event.__lookupGetter__('dataTransfer') is defined.
PASS event.getTargetRanges is defined.
PASS event.target.id is expectedTargetID
PASS event.bubbles is true
PASS event.cancelable is true
PASS event.composed is true
PASS event.isComposing is false
Fired `textInput`!
PASS event.__lookupGetter__('data') is defined.
PASS event.target.id is expectedTargetID
PASS event.bubbles is true
PASS event.cancelable is true
PASS event.composed is true
Fired `oninput`!
PASS event.__lookupGetter__('inputType') is defined.
PASS event.__lookupGetter__('data') is defined.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
PASS successfullyParsed is true

TEST COMPLETE
Typing into contenteditable div element
Fired `textInput`!
PASS event.__lookupGetter__('data') is defined.
PASS event.target.id is expectedTargetID
PASS event.bubbles is true
PASS event.cancelable is true
PASS event.composed is true
Fired `onbeforeinput`!
PASS event.__lookupGetter__('inputType') is defined.
PASS event.__lookupGetter__('data') is defined.
PASS event.__lookupGetter__('dataTransfer') is defined.
PASS event.getTargetRanges is defined.
PASS event.target.id is expectedTargetID
PASS event.bubbles is true
PASS event.cancelable is true
PASS event.composed is true
PASS event.isComposing is false
Fired `oninput`!
PASS event.__lookupGetter__('inputType') is defined.
PASS event.__lookupGetter__('data') is defined.
PASS event.__lookupGetter__('dataTransfer') is defined.
PASS event.getTargetRanges is defined.
PASS event.target.id is expectedTargetID
PASS event.bubbles is true
PASS event.cancelable is false
PASS event.composed is true
PASS event.isComposing is false
Typing into input element
Fired `textInput`!
PASS event.__lookupGetter__('data') is defined.
PASS event.target.id is expectedTargetID
PASS event.bubbles is true
PASS event.cancelable is true
PASS event.composed is true
Fired `onbeforeinput`!
PASS event.__lookupGetter__('inputType') is defined.
PASS event.__lookupGetter__('data') is defined.
PASS event.__lookupGetter__('dataTransfer') is defined.
PASS event.getTargetRanges is defined.
PASS event.target.id is expectedTargetID
PASS event.bubbles is true
PASS event.cancelable is true
PASS event.composed is true
PASS event.isComposing is false
Fired `oninput`!
PASS event.__lookupGetter__('inputType') is defined.
PASS event.__lookupGetter__('data') is defined.
PASS event.__lookupGetter__('dataTransfer') is defined.
PASS event.getTargetRanges is defined.
PASS event.target.id is expectedTargetID
PASS event.bubbles is true
PASS event.cancelable is false
PASS event.composed is true
PASS event.isComposing is false
Typing into textarea element
Fired `textInput`!
PASS event.__lookupGetter__('data') is defined.
PASS event.target.id is expectedTargetID
PASS event.bubbles is true
PASS event.cancelable is true
PASS event.composed is true
Fired `onbeforeinput`!
PASS event.__lookupGetter__('inputType') is defined.
PASS event.__lookupGetter__('data') is defined.
PASS event.__lookupGetter__('dataTransfer') is defined.
PASS event.getTargetRanges is defined.
PASS event.target.id is expectedTargetID
PASS event.bubbles is true
PASS event.cancelable is true
PASS event.composed is true
PASS event.isComposing is false
Fired `oninput`!
PASS event.__lookupGetter__('inputType') is defined.
PASS event.__lookupGetter__('data') is defined.
PASS event.__lookupGetter__('dataTransfer') is defined.
PASS event.getTargetRanges is defined.
PASS event.target.id is expectedTargetID
PASS event.bubbles is true
PASS event.cancelable is false
PASS event.composed is true
PASS event.isComposing is false
a

Loading

0 comments on commit 3349026

Please sign in to comment.