<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[207010] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/207010">207010</a></dd>
<dt>Author</dt> <dd>wenson_hsieh@apple.com</dd>
<dt>Date</dt> <dd>2016-10-10 11:30:03 -0700 (Mon, 10 Oct 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Support InputEvent.data for the new InputEvent spec
https://bugs.webkit.org/show_bug.cgi?id=163113
&lt;rdar://problem/28681935&gt;

Reviewed by Darin Adler.

Source/WebCore:

Introduces InputEvent.data, a string attribute that, if non-null, indicates the text to be inserted by an input
event. For text areas and text inputs, the 'insertText', 'insertFromPaste', 'insertFromDrop', and
'insertReplacementText' input types should cause subsequent `input` and `beforeinput` events to have non-null
data. However, for contenteditable areas, only 'insertText' leads to having data in resulting InputEvents.

To implement this, we introduce a new virtual method, CompositeEditCommand::inputEventData, which gives
composite editing commands the chance to vend a data string for input events they might fire (by default, this
is null).

Tests: fast/events/input-events-paste-data.html
       fast/events/input-events-typing-data.html

* dom/InputEvent.cpp:
(WebCore::InputEvent::InputEvent):
* dom/InputEvent.h:
* dom/InputEvent.idl:

Currently, our InputEventInit struct is wrong. According to the UI-Events spec at www.w3.org/TR/uievents/, the
init struct for an InputEvent should contain a data string (added in this patch) as well as an isComposing flag
(to be added in a future patch along with composition support). While adding support for the data attribute, we
tweak the InputEvent IDL and headers slightly to adjust for this.

* dom/Node.cpp:
(WebCore::Node::dispatchInputEvent):
* dom/Node.h:
* editing/CompositeEditCommand.h:
(WebCore::CompositeEditCommand::inputEventData):
* editing/EditCommand.cpp:
(WebCore::EditCommand::isEditingTextAreaOrTextInput):
* editing/EditCommand.h:
* editing/Editor.cpp:
(WebCore::dispatchBeforeInputEvent):
(WebCore::dispatchInputEvent):
(WebCore::dispatchBeforeInputEvents):
(WebCore::dispatchInputEvents):
(WebCore::Editor::willApplyEditing):
(WebCore::Editor::appliedEditing):
(WebCore::Editor::setBaseWritingDirection):
(WebCore::Editor::computeAndSetTypingStyle):
* editing/ReplaceRangeWithTextCommand.cpp:
(WebCore::ReplaceRangeWithTextCommand::inputEventData):
* editing/ReplaceRangeWithTextCommand.h:
* editing/ReplaceSelectionCommand.cpp:
(WebCore::ReplaceSelectionCommand::inputEventData):
* editing/ReplaceSelectionCommand.h:
* editing/SpellingCorrectionCommand.cpp:
(WebCore::SpellingCorrectionCommand::inputEventData):
* editing/SpellingCorrectionCommand.h:
* editing/TypingCommand.cpp:
(WebCore::TypingCommand::TypingCommand):
(WebCore::TypingCommand::inputEventData):
(WebCore::TypingCommand::willAddTypingToOpenCommand):
(WebCore::TypingCommand::insertTextRunWithoutNewlines):
* editing/TypingCommand.h:
* html/HTMLFormControlElement.cpp:
(WebCore::HTMLFormControlElement::dispatchFormControlInputEvent):
* html/HTMLInputElement.cpp:
(WebCore::HTMLInputElement::setEditingValue):
(WebCore::HTMLInputElement::setValueFromRenderer):
* html/HTMLSelectElement.cpp:
(WebCore::HTMLSelectElement::listBoxOnChange):
(WebCore::HTMLSelectElement::dispatchChangeEventForMenuList):

LayoutTests:

Adds 2 new layout tests verifying the data attribute of `beforeinput` and `input` events when typing, pasting,
and selecting candidate replacements in plain text and contenteditable areas.

Also tweaks an existing test to ensure that `data` is an attribute of an InputEvent.

* fast/events/input-events-fired-when-typing-expected.txt:
* fast/events/input-events-fired-when-typing.html:
* fast/events/input-events-paste-data-expected.txt: Added.
* fast/events/input-events-paste-data.html: Added.
* fast/events/input-events-typing-data-expected.txt: Added.
* fast/events/input-events-typing-data.html: Added.
* platform/ios-simulator/TestExpectations:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsfasteventsinputeventsfiredwhentypingexpectedtxt">trunk/LayoutTests/fast/events/input-events-fired-when-typing-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfasteventsinputeventsfiredwhentypinghtml">trunk/LayoutTests/fast/events/input-events-fired-when-typing.html</a></li>
<li><a href="#trunkLayoutTestsplatformiossimulatorTestExpectations">trunk/LayoutTests/platform/ios-simulator/TestExpectations</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoredomInputEventcpp">trunk/Source/WebCore/dom/InputEvent.cpp</a></li>
<li><a href="#trunkSourceWebCoredomInputEventh">trunk/Source/WebCore/dom/InputEvent.h</a></li>
<li><a href="#trunkSourceWebCoredomInputEventidl">trunk/Source/WebCore/dom/InputEvent.idl</a></li>
<li><a href="#trunkSourceWebCoredomNodecpp">trunk/Source/WebCore/dom/Node.cpp</a></li>
<li><a href="#trunkSourceWebCoredomNodeh">trunk/Source/WebCore/dom/Node.h</a></li>
<li><a href="#trunkSourceWebCoreeditingCompositeEditCommandh">trunk/Source/WebCore/editing/CompositeEditCommand.h</a></li>
<li><a href="#trunkSourceWebCoreeditingEditCommandcpp">trunk/Source/WebCore/editing/EditCommand.cpp</a></li>
<li><a href="#trunkSourceWebCoreeditingEditCommandh">trunk/Source/WebCore/editing/EditCommand.h</a></li>
<li><a href="#trunkSourceWebCoreeditingEditorcpp">trunk/Source/WebCore/editing/Editor.cpp</a></li>
<li><a href="#trunkSourceWebCoreeditingReplaceRangeWithTextCommandcpp">trunk/Source/WebCore/editing/ReplaceRangeWithTextCommand.cpp</a></li>
<li><a href="#trunkSourceWebCoreeditingReplaceRangeWithTextCommandh">trunk/Source/WebCore/editing/ReplaceRangeWithTextCommand.h</a></li>
<li><a href="#trunkSourceWebCoreeditingReplaceSelectionCommandcpp">trunk/Source/WebCore/editing/ReplaceSelectionCommand.cpp</a></li>
<li><a href="#trunkSourceWebCoreeditingReplaceSelectionCommandh">trunk/Source/WebCore/editing/ReplaceSelectionCommand.h</a></li>
<li><a href="#trunkSourceWebCoreeditingSpellingCorrectionCommandcpp">trunk/Source/WebCore/editing/SpellingCorrectionCommand.cpp</a></li>
<li><a href="#trunkSourceWebCoreeditingSpellingCorrectionCommandh">trunk/Source/WebCore/editing/SpellingCorrectionCommand.h</a></li>
<li><a href="#trunkSourceWebCoreeditingTypingCommandcpp">trunk/Source/WebCore/editing/TypingCommand.cpp</a></li>
<li><a href="#trunkSourceWebCoreeditingTypingCommandh">trunk/Source/WebCore/editing/TypingCommand.h</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLFormControlElementcpp">trunk/Source/WebCore/html/HTMLFormControlElement.cpp</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLInputElementcpp">trunk/Source/WebCore/html/HTMLInputElement.cpp</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLSelectElementcpp">trunk/Source/WebCore/html/HTMLSelectElement.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsfasteventsinputeventspastedataexpectedtxt">trunk/LayoutTests/fast/events/input-events-paste-data-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfasteventsinputeventspastedatahtml">trunk/LayoutTests/fast/events/input-events-paste-data.html</a></li>
<li><a href="#trunkLayoutTestsfasteventsinputeventstypingdataexpectedtxt">trunk/LayoutTests/fast/events/input-events-typing-data-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfasteventsinputeventstypingdatahtml">trunk/LayoutTests/fast/events/input-events-typing-data.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (207009 => 207010)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/LayoutTests/ChangeLog        2016-10-10 18:30:03 UTC (rev 207010)
</span><span class="lines">@@ -1,3 +1,24 @@
</span><ins>+2016-10-10  Wenson Hsieh  &lt;wenson_hsieh@apple.com&gt;
+
+        Support InputEvent.data for the new InputEvent spec
+        https://bugs.webkit.org/show_bug.cgi?id=163113
+        &lt;rdar://problem/28681935&gt;
+
+        Reviewed by Darin Adler.
+
+        Adds 2 new layout tests verifying the data attribute of `beforeinput` and `input` events when typing, pasting,
+        and selecting candidate replacements in plain text and contenteditable areas.
+
+        Also tweaks an existing test to ensure that `data` is an attribute of an InputEvent.
+
+        * fast/events/input-events-fired-when-typing-expected.txt:
+        * fast/events/input-events-fired-when-typing.html:
+        * fast/events/input-events-paste-data-expected.txt: Added.
+        * fast/events/input-events-paste-data.html: Added.
+        * fast/events/input-events-typing-data-expected.txt: Added.
+        * fast/events/input-events-typing-data.html: Added.
+        * platform/ios-simulator/TestExpectations:
+
</ins><span class="cx"> 2016-10-10  Ryan Haddad  &lt;ryanhaddad@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Marking storage/indexeddb/modern/abort-requests-cancelled* tests as flaky on mac.
</span></span></pre></div>
<a id="trunkLayoutTestsfasteventsinputeventsfiredwhentypingexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/events/input-events-fired-when-typing-expected.txt (207009 => 207010)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/events/input-events-fired-when-typing-expected.txt        2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/LayoutTests/fast/events/input-events-fired-when-typing-expected.txt        2016-10-10 18:30:03 UTC (rev 207010)
</span><span class="lines">@@ -3,6 +3,7 @@
</span><span class="cx"> TEST COMPLETE
</span><span class="cx"> Fired `onbeforeinput`!
</span><span class="cx"> PASS event.__lookupGetter__('inputType') is defined.
</span><ins>+PASS event.__lookupGetter__('data') is defined.
</ins><span class="cx"> PASS Object.getPrototypeOf(event) is InputEvent.prototype
</span><span class="cx"> PASS event.target.id is expectedTargetID
</span><span class="cx"> PASS event.bubbles is true
</span><span class="lines">@@ -10,6 +11,7 @@
</span><span class="cx"> PASS event.composed is true
</span><span class="cx"> Fired `oninput`!
</span><span class="cx"> PASS event.__lookupGetter__('inputType') is defined.
</span><ins>+PASS event.__lookupGetter__('data') is defined.
</ins><span class="cx"> PASS Object.getPrototypeOf(event) is InputEvent.prototype
</span><span class="cx"> PASS event.target.id is expectedTargetID
</span><span class="cx"> PASS event.bubbles is true
</span><span class="lines">@@ -17,6 +19,7 @@
</span><span class="cx"> PASS event.composed is true
</span><span class="cx"> Fired `onbeforeinput`!
</span><span class="cx"> PASS event.__lookupGetter__('inputType') is defined.
</span><ins>+PASS event.__lookupGetter__('data') is defined.
</ins><span class="cx"> PASS Object.getPrototypeOf(event) is InputEvent.prototype
</span><span class="cx"> PASS event.target.id is expectedTargetID
</span><span class="cx"> PASS event.bubbles is true
</span><span class="lines">@@ -24,6 +27,7 @@
</span><span class="cx"> PASS event.composed is true
</span><span class="cx"> Fired `oninput`!
</span><span class="cx"> PASS event.__lookupGetter__('inputType') is defined.
</span><ins>+PASS event.__lookupGetter__('data') is defined.
</ins><span class="cx"> PASS Object.getPrototypeOf(event) is InputEvent.prototype
</span><span class="cx"> PASS event.target.id is expectedTargetID
</span><span class="cx"> PASS event.bubbles is true
</span></span></pre></div>
<a id="trunkLayoutTestsfasteventsinputeventsfiredwhentypinghtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/events/input-events-fired-when-typing.html (207009 => 207010)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/events/input-events-fired-when-typing.html        2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/LayoutTests/fast/events/input-events-fired-when-typing.html        2016-10-10 18:30:03 UTC (rev 207010)
</span><span class="lines">@@ -35,6 +35,7 @@
</span><span class="cx">         {
</span><span class="cx">             debug(&quot;Fired `oninput`!&quot;);
</span><span class="cx">             shouldBeDefined(&quot;event.__lookupGetter__('inputType')&quot;);
</span><ins>+            shouldBeDefined(&quot;event.__lookupGetter__('data')&quot;);
</ins><span class="cx">             shouldBe(&quot;Object.getPrototypeOf(event)&quot;, &quot;InputEvent.prototype&quot;);
</span><span class="cx">             shouldBe(&quot;event.target.id&quot;, &quot;expectedTargetID&quot;);
</span><span class="cx">             shouldBe(&quot;event.bubbles&quot;, &quot;true&quot;);
</span><span class="lines">@@ -46,6 +47,7 @@
</span><span class="cx">         {
</span><span class="cx">             debug(&quot;Fired `onbeforeinput`!&quot;);
</span><span class="cx">             shouldBeDefined(&quot;event.__lookupGetter__('inputType')&quot;);
</span><ins>+            shouldBeDefined(&quot;event.__lookupGetter__('data')&quot;);
</ins><span class="cx">             shouldBe(&quot;Object.getPrototypeOf(event)&quot;, &quot;InputEvent.prototype&quot;);
</span><span class="cx">             shouldBe(&quot;event.target.id&quot;, &quot;expectedTargetID&quot;);
</span><span class="cx">             shouldBe(&quot;event.bubbles&quot;, &quot;true&quot;);
</span></span></pre></div>
<a id="trunkLayoutTestsfasteventsinputeventspastedataexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/events/input-events-paste-data-expected.txt (0 => 207010)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/events/input-events-paste-data-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/events/input-events-paste-data-expected.txt        2016-10-10 18:30:03 UTC (rev 207010)
</span><span class="lines">@@ -0,0 +1,16 @@
</span><ins>+To manually test this, copy the word 'testing' and paste into both the textarea and contenteditable. Verify that two PASS messages are printed out per paste (one for the beforeinput, the other for input).
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+pasting 'testing' in the plain textarea. data should be nonnull
+PASS event.data is 'testing'
+PASS event.data is 'testing'
+pasting 'testing' in the rich contenteditable. data should be null
+PASS event.data is null
+PASS event.data is null
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
+testing
</ins></span></pre></div>
<a id="trunkLayoutTestsfasteventsinputeventspastedatahtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/events/input-events-paste-data.html (0 => 207010)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/events/input-events-paste-data.html                                (rev 0)
+++ trunk/LayoutTests/fast/events/input-events-paste-data.html        2016-10-10 18:30:03 UTC (rev 207010)
</span><span class="lines">@@ -0,0 +1,47 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;head&gt;
+    &lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;/head&gt;
+&lt;body&gt;
+    &lt;textarea onfocus=handleFocus() id=&quot;plain&quot; onbeforeinput=handlePlainInput(event,true) oninput=handlePlainInput(event,false)&gt;testing&lt;/textarea&gt;
+    &lt;div id=&quot;rich&quot; contenteditable onbeforeinput=handleRichInput(event,true) oninput=handleRichInput(event,false)&gt;&lt;/div&gt;
+    &lt;script type=&quot;text/javascript&quot;&gt;
+        description(`To manually test this, copy the word 'testing' and paste into both the textarea and contenteditable. Verify that two PASS messages are printed out per paste (one for the beforeinput, the other for input).`);
+        (function() {
+            if (!window.internals || !window.eventSender || !window.testRunner)
+                return;
+
+            internals.settings.setInputEventsEnabled(true);
+            document.querySelector(&quot;#plain&quot;).focus();
+        })();
+
+        function handleFocus()
+        {
+            document.querySelector(&quot;#plain&quot;).select();
+            testRunner.execCommand(&quot;Cut&quot;);
+
+            debug(&quot;pasting 'testing' in the plain textarea. data should be nonnull&quot;);
+            testRunner.execCommand(&quot;Paste&quot;);
+
+            document.querySelector(&quot;#rich&quot;).focus();
+            debug(&quot;pasting 'testing' in the rich contenteditable. data should be null&quot;);
+            testRunner.execCommand(&quot;Paste&quot;);
+        }
+
+        function handleRichInput(event, isbefore)
+        {
+            if (event.inputType === &quot;insertFromPaste&quot;)
+                shouldBeNull(&quot;event.data&quot;);
+        }
+
+        function handlePlainInput(event, isbefore)
+        {
+            if (event.inputType === &quot;insertFromPaste&quot;)
+                shouldBe(&quot;event.data&quot;, &quot;'testing'&quot;);
+        }
+    &lt;/script&gt;
+    &lt;script src=&quot;../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/body&gt;
+
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsfasteventsinputeventstypingdataexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/events/input-events-typing-data-expected.txt (0 => 207010)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/events/input-events-typing-data-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/events/input-events-typing-data-expected.txt        2016-10-10 18:30:03 UTC (rev 207010)
</span><span class="lines">@@ -0,0 +1,30 @@
</span><ins>+To manually test this, type in both the rich contenteditable and plain textarea and/or insert candidates/autocorrections. Both elements should have data when typing normally, but only the plain textarea should have data when inserting a replacement.
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+Plain textarea received 'beforeinput' with inputType: 'insertText' and data: 'h'
+Plain textarea received 'input' with inputType: 'insertText' and data: 'h'
+Plain textarea received 'beforeinput' with inputType: 'insertText' and data: 'e'
+Plain textarea received 'input' with inputType: 'insertText' and data: 'e'
+Plain textarea received 'beforeinput' with inputType: 'insertText' and data: 'l'
+Plain textarea received 'input' with inputType: 'insertText' and data: 'l'
+Plain textarea received 'beforeinput' with inputType: 'insertText' and data: 'o'
+Plain textarea received 'input' with inputType: 'insertText' and data: 'o'
+Plain textarea received 'beforeinput' with inputType: 'insertReplacementText' and data: 'hello'
+Plain textarea received 'input' with inputType: 'insertReplacementText' and data: 'hello'
+Rich contenteditable received 'beforeinput' with inputType: 'insertText' and data: 'h'
+Rich contenteditable received 'input' with inputType: 'insertText' and data: 'h'
+Rich contenteditable received 'beforeinput' with inputType: 'insertText' and data: 'e'
+Rich contenteditable received 'input' with inputType: 'insertText' and data: 'e'
+Rich contenteditable received 'beforeinput' with inputType: 'insertText' and data: 'l'
+Rich contenteditable received 'input' with inputType: 'insertText' and data: 'l'
+Rich contenteditable received 'beforeinput' with inputType: 'insertText' and data: 'o'
+Rich contenteditable received 'input' with inputType: 'insertText' and data: 'o'
+Rich contenteditable received 'beforeinput' with inputType: 'insertReplacementText' and data: 'null'
+Rich contenteditable received 'input' with inputType: 'insertReplacementText' and data: 'null'
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
+hello
</ins></span></pre></div>
<a id="trunkLayoutTestsfasteventsinputeventstypingdatahtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/events/input-events-typing-data.html (0 => 207010)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/events/input-events-typing-data.html                                (rev 0)
+++ trunk/LayoutTests/fast/events/input-events-typing-data.html        2016-10-10 18:30:03 UTC (rev 207010)
</span><span class="lines">@@ -0,0 +1,49 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;head&gt;
+    &lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;/head&gt;
+&lt;body&gt;
+    &lt;textarea id=&quot;plain&quot; onbeforeinput=handlePlainInput(event) oninput=handlePlainInput(event)&gt;&lt;/textarea&gt;
+    &lt;div id=&quot;rich&quot; contenteditable onbeforeinput=handleRichInput(event) oninput=handleRichInput(event)&gt;&lt;/div&gt;
+    &lt;script type=&quot;text/javascript&quot;&gt;
+        description(`To manually test this, type in both the rich contenteditable and plain textarea and/or insert candidates/autocorrections.
+            Both elements should have data when typing normally, but only the plain textarea should have data when inserting a replacement.`);
+        (function() {
+            if (!window.internals || !window.eventSender || !window.testRunner)
+                return;
+
+            internals.settings.setInputEventsEnabled(true);
+
+            document.querySelector(&quot;#plain&quot;).focus();
+            simulateTypingWithReplacement(false);
+
+            document.querySelector(&quot;#rich&quot;).focus();
+            simulateTypingWithReplacement(true);
+        })();
+
+        function simulateTypingWithReplacement(isRich)
+        {
+            eventSender.keyDown(&quot;h&quot;, []);
+            eventSender.keyDown(&quot;e&quot;, []);
+            eventSender.keyDown(&quot;l&quot;, []);
+            eventSender.keyDown(&quot;o&quot;, []);
+            internals.handleAcceptedCandidate(&quot;hello&quot;, 0, 4);
+        }
+
+        function handleRichInput(event)
+        {
+            if (event.inputType === &quot;insertText&quot; || event.inputType === &quot;insertReplacementText&quot;)
+                debug(`Rich contenteditable received '${event.type}' with inputType: '${event.inputType}' and data: '${event.data}'`);
+        }
+
+        function handlePlainInput(event)
+        {
+            if (event.inputType === &quot;insertText&quot; || event.inputType === &quot;insertReplacementText&quot;)
+                debug(`Plain textarea received '${event.type}' with inputType: '${event.inputType}' and data: '${event.data}'`);
+        }
+    &lt;/script&gt;
+    &lt;script src=&quot;../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/body&gt;
+
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsplatformiossimulatorTestExpectations"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/platform/ios-simulator/TestExpectations (207009 => 207010)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/ios-simulator/TestExpectations        2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/LayoutTests/platform/ios-simulator/TestExpectations        2016-10-10 18:30:03 UTC (rev 207010)
</span><span class="lines">@@ -1198,6 +1198,8 @@
</span><span class="cx"> fast/events/ime-composition-events-001.html [ Failure ]
</span><span class="cx"> fast/events/inputText-never-fired-on-keydown-cancel.html [ Failure ]
</span><span class="cx"> fast/events/input-events-fired-when-typing.html [ Failure ]
</span><ins>+fast/events/input-events-paste-data.html [ Failure ]
+fast/events/input-events-typing-data.html [ Failure ]
</ins><span class="cx"> fast/events/before-input-events-prevent-default.html [ Failure ]
</span><span class="cx"> fast/events/before-input-events-prevent-default-in-textfield.html [ Failure ]
</span><span class="cx"> fast/events/before-input-events-different-start-end-elements.html [ Failure ]
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (207009 => 207010)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/Source/WebCore/ChangeLog        2016-10-10 18:30:03 UTC (rev 207010)
</span><span class="lines">@@ -1,3 +1,74 @@
</span><ins>+2016-10-10  Wenson Hsieh  &lt;wenson_hsieh@apple.com&gt;
+
+        Support InputEvent.data for the new InputEvent spec
+        https://bugs.webkit.org/show_bug.cgi?id=163113
+        &lt;rdar://problem/28681935&gt;
+
+        Reviewed by Darin Adler.
+
+        Introduces InputEvent.data, a string attribute that, if non-null, indicates the text to be inserted by an input
+        event. For text areas and text inputs, the 'insertText', 'insertFromPaste', 'insertFromDrop', and
+        'insertReplacementText' input types should cause subsequent `input` and `beforeinput` events to have non-null
+        data. However, for contenteditable areas, only 'insertText' leads to having data in resulting InputEvents.
+
+        To implement this, we introduce a new virtual method, CompositeEditCommand::inputEventData, which gives
+        composite editing commands the chance to vend a data string for input events they might fire (by default, this
+        is null).
+
+        Tests: fast/events/input-events-paste-data.html
+               fast/events/input-events-typing-data.html
+
+        * dom/InputEvent.cpp:
+        (WebCore::InputEvent::InputEvent):
+        * dom/InputEvent.h:
+        * dom/InputEvent.idl:
+
+        Currently, our InputEventInit struct is wrong. According to the UI-Events spec at www.w3.org/TR/uievents/, the
+        init struct for an InputEvent should contain a data string (added in this patch) as well as an isComposing flag
+        (to be added in a future patch along with composition support). While adding support for the data attribute, we
+        tweak the InputEvent IDL and headers slightly to adjust for this.
+
+        * dom/Node.cpp:
+        (WebCore::Node::dispatchInputEvent):
+        * dom/Node.h:
+        * editing/CompositeEditCommand.h:
+        (WebCore::CompositeEditCommand::inputEventData):
+        * editing/EditCommand.cpp:
+        (WebCore::EditCommand::isEditingTextAreaOrTextInput):
+        * editing/EditCommand.h:
+        * editing/Editor.cpp:
+        (WebCore::dispatchBeforeInputEvent):
+        (WebCore::dispatchInputEvent):
+        (WebCore::dispatchBeforeInputEvents):
+        (WebCore::dispatchInputEvents):
+        (WebCore::Editor::willApplyEditing):
+        (WebCore::Editor::appliedEditing):
+        (WebCore::Editor::setBaseWritingDirection):
+        (WebCore::Editor::computeAndSetTypingStyle):
+        * editing/ReplaceRangeWithTextCommand.cpp:
+        (WebCore::ReplaceRangeWithTextCommand::inputEventData):
+        * editing/ReplaceRangeWithTextCommand.h:
+        * editing/ReplaceSelectionCommand.cpp:
+        (WebCore::ReplaceSelectionCommand::inputEventData):
+        * editing/ReplaceSelectionCommand.h:
+        * editing/SpellingCorrectionCommand.cpp:
+        (WebCore::SpellingCorrectionCommand::inputEventData):
+        * editing/SpellingCorrectionCommand.h:
+        * editing/TypingCommand.cpp:
+        (WebCore::TypingCommand::TypingCommand):
+        (WebCore::TypingCommand::inputEventData):
+        (WebCore::TypingCommand::willAddTypingToOpenCommand):
+        (WebCore::TypingCommand::insertTextRunWithoutNewlines):
+        * editing/TypingCommand.h:
+        * html/HTMLFormControlElement.cpp:
+        (WebCore::HTMLFormControlElement::dispatchFormControlInputEvent):
+        * html/HTMLInputElement.cpp:
+        (WebCore::HTMLInputElement::setEditingValue):
+        (WebCore::HTMLInputElement::setValueFromRenderer):
+        * html/HTMLSelectElement.cpp:
+        (WebCore::HTMLSelectElement::listBoxOnChange):
+        (WebCore::HTMLSelectElement::dispatchChangeEventForMenuList):
+
</ins><span class="cx"> 2016-10-10  Commit Queue  &lt;commit-queue@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Unreviewed, rolling out r206972.
</span></span></pre></div>
<a id="trunkSourceWebCoredomInputEventcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/InputEvent.cpp (207009 => 207010)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/InputEvent.cpp        2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/Source/WebCore/dom/InputEvent.cpp        2016-10-10 18:30:03 UTC (rev 207010)
</span><span class="lines">@@ -34,15 +34,17 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-InputEvent::InputEvent(const AtomicString&amp; eventType, const String&amp; inputType, bool canBubble, bool cancelable, DOMWindow* view, int detail)
</del><ins>+InputEvent::InputEvent(const AtomicString&amp; eventType, const String&amp; inputType, bool canBubble, bool cancelable, DOMWindow* view, const String&amp; data, int detail)
</ins><span class="cx">     : UIEvent(eventType, canBubble, cancelable, view, detail)
</span><span class="cx">     , m_inputType(inputType)
</span><ins>+    , m_data(data)
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> InputEvent::InputEvent(const AtomicString&amp; eventType, const InputEventInit&amp; initializer)
</span><span class="cx">     : UIEvent(eventType, initializer)
</span><del>-    , m_inputType(initializer.inputType)
</del><ins>+    , m_inputType(emptyString())
+    , m_data(initializer.data)
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoredomInputEventh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/InputEvent.h (207009 => 207010)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/InputEvent.h        2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/Source/WebCore/dom/InputEvent.h        2016-10-10 18:30:03 UTC (rev 207010)
</span><span class="lines">@@ -32,15 +32,16 @@
</span><span class="cx"> class DOMWindow;
</span><span class="cx"> class DataTransfer;
</span><span class="cx"> 
</span><del>-struct InputEventInit : public UIEventInit {
-    String inputType;
</del><ins>+struct InputEventInit : UIEventInit {
+    String data;
+    bool isComposing;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> class InputEvent final : public UIEvent {
</span><span class="cx"> public:
</span><del>-    static Ref&lt;InputEvent&gt; create(const AtomicString&amp; eventType, const String&amp; inputType, bool canBubble, bool cancelable, DOMWindow* view, int detail)
</del><ins>+    static Ref&lt;InputEvent&gt; create(const AtomicString&amp; eventType, const String&amp; inputType, bool canBubble, bool cancelable, DOMWindow* view, const String&amp; data, int detail)
</ins><span class="cx">     {
</span><del>-        return adoptRef(*new InputEvent(eventType, inputType, canBubble, cancelable, view, detail));
</del><ins>+        return adoptRef(*new InputEvent(eventType, inputType, canBubble, cancelable, view, data, detail));
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     static Ref&lt;InputEvent&gt; createForBindings(const AtomicString&amp; type, const InputEventInit&amp; initializer)
</span><span class="lines">@@ -48,7 +49,7 @@
</span><span class="cx">         return adoptRef(*new InputEvent(type, initializer));
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    InputEvent(const AtomicString&amp; eventType, const String&amp; inputType, bool canBubble, bool cancelable, DOMWindow*, int detail);
</del><ins>+    InputEvent(const AtomicString&amp; eventType, const String&amp; inputType, bool canBubble, bool cancelable, DOMWindow*, const String&amp; data, int detail);
</ins><span class="cx">     InputEvent(const AtomicString&amp; eventType, const InputEventInit&amp;);
</span><span class="cx"> 
</span><span class="cx">     virtual ~InputEvent() { }
</span><span class="lines">@@ -55,10 +56,12 @@
</span><span class="cx"> 
</span><span class="cx">     bool isInputEvent() const override { return true; }
</span><span class="cx">     EventInterface eventInterface() const final { return InputEventInterfaceType; }
</span><del>-    String inputType() const { return m_inputType; }
</del><ins>+    const String&amp; inputType() const { return m_inputType; }
+    const String&amp; data() const { return m_data; }
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     String m_inputType;
</span><ins>+    String m_data;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoredomInputEventidl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/InputEvent.idl (207009 => 207010)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/InputEvent.idl        2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/Source/WebCore/dom/InputEvent.idl        2016-10-10 18:30:03 UTC (rev 207010)
</span><span class="lines">@@ -26,5 +26,6 @@
</span><span class="cx"> [
</span><span class="cx">     ConstructorTemplate=Event
</span><span class="cx"> ] interface InputEvent : UIEvent {
</span><del>-    [InitializedByEventConstructor] readonly attribute DOMString inputType;
</del><ins>+    readonly attribute DOMString inputType;
+    [InitializedByEventConstructor] readonly attribute DOMString? data;
</ins><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebCoredomNodecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Node.cpp (207009 => 207010)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/Node.cpp        2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/Source/WebCore/dom/Node.cpp        2016-10-10 18:30:03 UTC (rev 207010)
</span><span class="lines">@@ -2198,13 +2198,9 @@
</span><span class="cx">     return !beforeLoadEvent-&gt;defaultPrevented();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Node::dispatchInputEvent(const String&amp; inputType)
</del><ins>+void Node::dispatchInputEvent()
</ins><span class="cx"> {
</span><del>-    auto* settings = document().settings();
-    if (settings &amp;&amp; settings-&gt;inputEventsEnabled())
-        dispatchScopedEvent(InputEvent::create(eventNames().inputEvent, inputType, true, false, document().defaultView(), 0));
-    else
-        dispatchScopedEvent(Event::create(eventNames().inputEvent, true, false));
</del><ins>+    dispatchScopedEvent(Event::create(eventNames().inputEvent, true, false));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void Node::defaultEventHandler(Event&amp; event)
</span></span></pre></div>
<a id="trunkSourceWebCoredomNodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Node.h (207009 => 207010)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/Node.h        2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/Source/WebCore/dom/Node.h        2016-10-10 18:30:03 UTC (rev 207010)
</span><span class="lines">@@ -525,7 +525,7 @@
</span><span class="cx"> 
</span><span class="cx">     bool dispatchBeforeLoadEvent(const String&amp; sourceURL);
</span><span class="cx"> 
</span><del>-    virtual void dispatchInputEvent(const String&amp; inputType);
</del><ins>+    void dispatchInputEvent();
</ins><span class="cx"> 
</span><span class="cx">     // Perform the default action for an event.
</span><span class="cx">     virtual void defaultEventHandler(Event&amp;);
</span></span></pre></div>
<a id="trunkSourceWebCoreeditingCompositeEditCommandh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/CompositeEditCommand.h (207009 => 207010)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/CompositeEditCommand.h        2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/Source/WebCore/editing/CompositeEditCommand.h        2016-10-10 18:30:03 UTC (rev 207010)
</span><span class="lines">@@ -114,6 +114,7 @@
</span><span class="cx">     virtual void setShouldRetainAutocorrectionIndicator(bool);
</span><span class="cx">     virtual bool shouldStopCaretBlinking() const { return false; }
</span><span class="cx">     virtual String inputEventTypeName() const;
</span><ins>+    virtual String inputEventData() const { return { }; }
</ins><span class="cx"> 
</span><span class="cx"> protected:
</span><span class="cx">     explicit CompositeEditCommand(Document&amp;, EditAction = EditActionUnspecified);
</span></span></pre></div>
<a id="trunkSourceWebCoreeditingEditCommandcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/EditCommand.cpp (207009 => 207010)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/EditCommand.cpp        2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/Source/WebCore/editing/EditCommand.cpp        2016-10-10 18:30:03 UTC (rev 207010)
</span><span class="lines">@@ -33,6 +33,8 @@
</span><span class="cx"> #include &quot;Element.h&quot;
</span><span class="cx"> #include &quot;EventNames.h&quot;
</span><span class="cx"> #include &quot;Frame.h&quot;
</span><ins>+#include &quot;HTMLInputElement.h&quot;
+#include &quot;HTMLTextAreaElement.h&quot;
</ins><span class="cx"> #include &quot;NodeTraversal.h&quot;
</span><span class="cx"> #include &quot;htmlediting.h&quot;
</span><span class="cx"> 
</span><span class="lines">@@ -140,6 +142,23 @@
</span><span class="cx">     return toCompositeEditCommand(command)-&gt;composition();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool EditCommand::isEditingTextAreaOrTextInput() const
+{
+    auto* frame = m_document-&gt;frame();
+    if (!frame)
+        return false;
+
+    auto* container = frame-&gt;selection().selection().start().containerNode();
+    if (!container)
+        return false;
+
+    auto* ancestor = container-&gt;shadowHost();
+    if (!ancestor)
+        return false;
+
+    return is&lt;HTMLTextAreaElement&gt;(*ancestor) || (is&lt;HTMLInputElement&gt;(*ancestor) &amp;&amp; downcast&lt;HTMLInputElement&gt;(*ancestor).isText());
+}
+
</ins><span class="cx"> void EditCommand::setStartingSelection(const VisibleSelection&amp; s)
</span><span class="cx"> {
</span><span class="cx">     for (EditCommand* cmd = this; ; cmd = cmd-&gt;m_parent) {
</span></span></pre></div>
<a id="trunkSourceWebCoreeditingEditCommandh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/EditCommand.h (207009 => 207010)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/EditCommand.h        2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/Source/WebCore/editing/EditCommand.h        2016-10-10 18:30:03 UTC (rev 207010)
</span><span class="lines">@@ -72,6 +72,8 @@
</span><span class="cx">     void setStartingSelection(const VisibleSelection&amp;);
</span><span class="cx">     WEBCORE_EXPORT void setEndingSelection(const VisibleSelection&amp;);
</span><span class="cx"> 
</span><ins>+    bool isEditingTextAreaOrTextInput() const;
+
</ins><span class="cx">     void postTextStateChangeNotification(AXTextEditType, const String&amp;);
</span><span class="cx">     void postTextStateChangeNotification(AXTextEditType, const String&amp;, const VisiblePosition&amp;);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreeditingEditorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/Editor.cpp (207009 => 207010)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/Editor.cpp        2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/Source/WebCore/editing/Editor.cpp        2016-10-10 18:30:03 UTC (rev 207010)
</span><span class="lines">@@ -111,18 +111,27 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-static bool dispatchBeforeInputEvent(Element&amp; element, const AtomicString&amp; inputType)
</del><ins>+static bool dispatchBeforeInputEvent(Element&amp; element, const AtomicString&amp; inputType, const String&amp; data = { })
</ins><span class="cx"> {
</span><span class="cx">     auto* settings = element.document().settings();
</span><span class="cx">     if (!settings || !settings-&gt;inputEventsEnabled())
</span><span class="cx">         return true;
</span><span class="cx"> 
</span><del>-    auto event = InputEvent::create(eventNames().beforeinputEvent, inputType, true, true, element.document().defaultView(), 0);
</del><ins>+    auto event = InputEvent::create(eventNames().beforeinputEvent, inputType, true, true, element.document().defaultView(), data, 0);
</ins><span class="cx">     element.dispatchScopedEvent(event);
</span><span class="cx"> 
</span><span class="cx">     return !event-&gt;defaultPrevented();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static void dispatchInputEvent(Element&amp; element, const AtomicString&amp; inputType, const String&amp; data = { })
+{
+    auto* settings = element.document().settings();
+    if (settings &amp;&amp; settings-&gt;inputEventsEnabled())
+        element.dispatchScopedEvent(InputEvent::create(eventNames().inputEvent, inputType, true, false, element.document().defaultView(), data, 0));
+    else
+        element.dispatchInputEvent();
+}
+
</ins><span class="cx"> class ClearTextCommand : public DeleteSelectionCommand {
</span><span class="cx"> public:
</span><span class="cx">     ClearTextCommand(Document&amp; document);
</span><span class="lines">@@ -1043,22 +1052,22 @@
</span><span class="cx">         endingTextControl-&gt;didEditInnerTextValue();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static bool dispatchBeforeInputEvents(RefPtr&lt;Element&gt; startRoot, RefPtr&lt;Element&gt; endRoot, const AtomicString&amp; inputTypeName)
</del><ins>+static bool dispatchBeforeInputEvents(RefPtr&lt;Element&gt; startRoot, RefPtr&lt;Element&gt; endRoot, const AtomicString&amp; inputTypeName, const String&amp; data = { })
</ins><span class="cx"> {
</span><span class="cx">     bool continueWithDefaultBehavior = true;
</span><span class="cx">     if (startRoot)
</span><del>-        continueWithDefaultBehavior &amp;= dispatchBeforeInputEvent(*startRoot, inputTypeName);
</del><ins>+        continueWithDefaultBehavior &amp;= dispatchBeforeInputEvent(*startRoot, inputTypeName, data);
</ins><span class="cx">     if (endRoot &amp;&amp; endRoot != startRoot)
</span><del>-        continueWithDefaultBehavior &amp;= dispatchBeforeInputEvent(*endRoot, inputTypeName);
</del><ins>+        continueWithDefaultBehavior &amp;= dispatchBeforeInputEvent(*endRoot, inputTypeName, data);
</ins><span class="cx">     return continueWithDefaultBehavior;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static void dispatchInputEvents(RefPtr&lt;Element&gt; startRoot, RefPtr&lt;Element&gt; endRoot, const AtomicString&amp; inputTypeName)
</del><ins>+static void dispatchInputEvents(RefPtr&lt;Element&gt; startRoot, RefPtr&lt;Element&gt; endRoot, const AtomicString&amp; inputTypeName, const String&amp; data = { })
</ins><span class="cx"> {
</span><span class="cx">     if (startRoot)
</span><del>-        startRoot-&gt;dispatchInputEvent(inputTypeName);
</del><ins>+        dispatchInputEvent(*startRoot, inputTypeName, data);
</ins><span class="cx">     if (endRoot &amp;&amp; endRoot != startRoot)
</span><del>-        endRoot-&gt;dispatchInputEvent(inputTypeName);
</del><ins>+        dispatchInputEvent(*endRoot, inputTypeName, data);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool Editor::willApplyEditing(CompositeEditCommand&amp; command) const
</span><span class="lines">@@ -1067,7 +1076,7 @@
</span><span class="cx">     if (!composition)
</span><span class="cx">         return true;
</span><span class="cx"> 
</span><del>-    return dispatchBeforeInputEvents(composition-&gt;startingRootEditableElement(), composition-&gt;endingRootEditableElement(), command.inputEventTypeName());
</del><ins>+    return dispatchBeforeInputEvents(composition-&gt;startingRootEditableElement(), composition-&gt;endingRootEditableElement(), command.inputEventTypeName(), command.inputEventData());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void Editor::appliedEditing(PassRefPtr&lt;CompositeEditCommand&gt; cmd)
</span><span class="lines">@@ -1086,7 +1095,7 @@
</span><span class="cx">     FrameSelection::SetSelectionOptions options = cmd-&gt;isDictationCommand() ? FrameSelection::DictationTriggered : 0;
</span><span class="cx">     
</span><span class="cx">     changeSelectionAfterCommand(newSelection, options);
</span><del>-    dispatchInputEvents(composition-&gt;startingRootEditableElement(), composition-&gt;endingRootEditableElement(), cmd-&gt;inputEventTypeName());
</del><ins>+    dispatchInputEvents(composition-&gt;startingRootEditableElement(), composition-&gt;endingRootEditableElement(), cmd-&gt;inputEventTypeName(), cmd-&gt;inputEventData());
</ins><span class="cx"> 
</span><span class="cx">     updateEditorUINowIfScheduled();
</span><span class="cx">     
</span><span class="lines">@@ -1705,7 +1714,7 @@
</span><span class="cx">         if (direction == NaturalWritingDirection)
</span><span class="cx">             return;
</span><span class="cx">         downcast&lt;HTMLTextFormControlElement&gt;(*focusedElement).setAttributeWithoutSynchronization(dirAttr, direction == LeftToRightWritingDirection ? &quot;ltr&quot; : &quot;rtl&quot;);
</span><del>-        focusedElement-&gt;dispatchInputEvent(emptyString());
</del><ins>+        focusedElement-&gt;dispatchInputEvent();
</ins><span class="cx">         document().updateStyleIfNeeded();
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="lines">@@ -3116,7 +3125,7 @@
</span><span class="cx">         applyCommand(ApplyStyleCommand::create(document(), blockStyle.get(), editingAction));
</span><span class="cx"> 
</span><span class="cx">     if (element)
</span><del>-        element-&gt;dispatchInputEvent(inputTypeName);
</del><ins>+        dispatchInputEvent(*element, inputTypeName);
</ins><span class="cx"> 
</span><span class="cx">     // Set the remaining style as the typing style.
</span><span class="cx">     m_frame.selection().setTypingStyle(typingStyle);
</span></span></pre></div>
<a id="trunkSourceWebCoreeditingReplaceRangeWithTextCommandcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/ReplaceRangeWithTextCommand.cpp (207009 => 207010)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/ReplaceRangeWithTextCommand.cpp        2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/Source/WebCore/editing/ReplaceRangeWithTextCommand.cpp        2016-10-10 18:30:03 UTC (rev 207010)
</span><span class="lines">@@ -65,4 +65,12 @@
</span><span class="cx">     applyCommandToComposite(ReplaceSelectionCommand::create(document(), WTFMove(fragment), ReplaceSelectionCommand::MatchStyle, EditActionPaste));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+String ReplaceRangeWithTextCommand::inputEventData() const
+{
+    if (isEditingTextAreaOrTextInput())
+        return m_text;
+
+    return CompositeEditCommand::inputEventData();
+}
+
</ins><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoreeditingReplaceRangeWithTextCommandh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/ReplaceRangeWithTextCommand.h (207009 => 207010)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/ReplaceRangeWithTextCommand.h        2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/Source/WebCore/editing/ReplaceRangeWithTextCommand.h        2016-10-10 18:30:03 UTC (rev 207010)
</span><span class="lines">@@ -40,6 +40,7 @@
</span><span class="cx"> private:
</span><span class="cx">     ReplaceRangeWithTextCommand(RefPtr&lt;Range&gt; rangeToBeReplaced, const String&amp; text);
</span><span class="cx">     void doApply() override;
</span><ins>+    String inputEventData() const final;
</ins><span class="cx"> 
</span><span class="cx">     RefPtr&lt;Range&gt; m_rangeToBeReplaced;
</span><span class="cx">     String m_text;
</span></span></pre></div>
<a id="trunkSourceWebCoreeditingReplaceSelectionCommandcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/ReplaceSelectionCommand.cpp (207009 => 207010)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/ReplaceSelectionCommand.cpp        2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/Source/WebCore/editing/ReplaceSelectionCommand.cpp        2016-10-10 18:30:03 UTC (rev 207010)
</span><span class="lines">@@ -1254,6 +1254,14 @@
</span><span class="cx">     completeHTMLReplacement(lastPositionToSelect);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+String ReplaceSelectionCommand::inputEventData() const
+{
+    if (isEditingTextAreaOrTextInput())
+        return m_documentFragment-&gt;textContent();
+
+    return CompositeEditCommand::inputEventData();
+}
+
</ins><span class="cx"> bool ReplaceSelectionCommand::shouldRemoveEndBR(Node* endBR, const VisiblePosition&amp; originalVisPosBeforeEndBR)
</span><span class="cx"> {
</span><span class="cx">     if (!endBR || !endBR-&gt;inDocument())
</span></span></pre></div>
<a id="trunkSourceWebCoreeditingReplaceSelectionCommandh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/ReplaceSelectionCommand.h (207009 => 207010)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/ReplaceSelectionCommand.h        2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/Source/WebCore/editing/ReplaceSelectionCommand.h        2016-10-10 18:30:03 UTC (rev 207010)
</span><span class="lines">@@ -58,6 +58,7 @@
</span><span class="cx"> private:
</span><span class="cx">     ReplaceSelectionCommand(Document&amp;, RefPtr&lt;DocumentFragment&gt;&amp;&amp;, CommandOptions, EditAction);
</span><span class="cx"> 
</span><ins>+    String inputEventData() const final;
</ins><span class="cx">     virtual void doApply();
</span><span class="cx"> 
</span><span class="cx">     class InsertedNodes {
</span></span></pre></div>
<a id="trunkSourceWebCoreeditingSpellingCorrectionCommandcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/SpellingCorrectionCommand.cpp (207009 => 207010)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/SpellingCorrectionCommand.cpp        2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/Source/WebCore/editing/SpellingCorrectionCommand.cpp        2016-10-10 18:30:03 UTC (rev 207010)
</span><span class="lines">@@ -111,6 +111,14 @@
</span><span class="cx">     applyCommandToComposite(ReplaceSelectionCommand::create(document(), WTFMove(fragment), ReplaceSelectionCommand::MatchStyle, EditActionPaste));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+String SpellingCorrectionCommand::inputEventData() const
+{
+    if (isEditingTextAreaOrTextInput())
+        return m_correction;
+
+    return CompositeEditCommand::inputEventData();
+}
+
</ins><span class="cx"> bool SpellingCorrectionCommand::shouldRetainAutocorrectionIndicator() const
</span><span class="cx"> {
</span><span class="cx">     return true;
</span></span></pre></div>
<a id="trunkSourceWebCoreeditingSpellingCorrectionCommandh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/SpellingCorrectionCommand.h (207009 => 207010)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/SpellingCorrectionCommand.h        2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/Source/WebCore/editing/SpellingCorrectionCommand.h        2016-10-10 18:30:03 UTC (rev 207010)
</span><span class="lines">@@ -42,6 +42,8 @@
</span><span class="cx">     void doApply() override;
</span><span class="cx">     bool shouldRetainAutocorrectionIndicator() const override;
</span><span class="cx"> 
</span><ins>+    String inputEventData() const final;
+
</ins><span class="cx">     RefPtr&lt;Range&gt; m_rangeToBeCorrected;
</span><span class="cx">     VisibleSelection m_selectionToBeCorrected;
</span><span class="cx">     String m_corrected;
</span></span></pre></div>
<a id="trunkSourceWebCoreeditingTypingCommandcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/TypingCommand.cpp (207009 => 207010)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/TypingCommand.cpp        2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/Source/WebCore/editing/TypingCommand.cpp        2016-10-10 18:30:03 UTC (rev 207010)
</span><span class="lines">@@ -110,6 +110,7 @@
</span><span class="cx">     : TextInsertionBaseCommand(document, editActionForTypingCommand(commandType, granularity))
</span><span class="cx">     , m_commandType(commandType)
</span><span class="cx">     , m_textToInsert(textToInsert)
</span><ins>+    , m_currentTextToInsert(textToInsert)
</ins><span class="cx">     , m_openForMoreTyping(true)
</span><span class="cx">     , m_selectInsertedText(options &amp; SelectInsertedText)
</span><span class="cx">     , m_smartDelete(options &amp; SmartDelete)
</span><span class="lines">@@ -344,6 +345,14 @@
</span><span class="cx">     return inputTypeNameForEditingAction(m_currentTypingEditAction);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+String TypingCommand::inputEventData() const
+{
+    if (m_currentTypingEditAction == EditActionTypingInsertText)
+        return m_currentTextToInsert;
+
+    return CompositeEditCommand::inputEventData();
+}
+
</ins><span class="cx"> void TypingCommand::didApplyCommand()
</span><span class="cx"> {
</span><span class="cx">     // TypingCommands handle applied editing separately (see TypingCommand::typingAddedToOpenCommand).
</span><span class="lines">@@ -404,13 +413,12 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool TypingCommand::willAddTypingToOpenCommand(ETypingCommand commandType, TextGranularity granularity)
</del><ins>+bool TypingCommand::willAddTypingToOpenCommand(ETypingCommand commandType, TextGranularity granularity, const String&amp; text)
</ins><span class="cx"> {
</span><span class="cx">     if (m_isHandlingInitialTypingCommand)
</span><span class="cx">         return true;
</span><span class="cx"> 
</span><del>-    // FIXME: Use the newly added typing command and granularity to ensure that an InputEvent with the
-    // correct inputType is dispatched.
</del><ins>+    m_currentTextToInsert = text;
</ins><span class="cx">     m_currentTypingEditAction = editActionForTypingCommand(commandType, granularity);
</span><span class="cx">     return frame().editor().willApplyEditing(*this);
</span><span class="cx"> }
</span><span class="lines">@@ -456,7 +464,7 @@
</span><span class="cx"> 
</span><span class="cx"> void TypingCommand::insertTextRunWithoutNewlines(const String &amp;text, bool selectInsertedText)
</span><span class="cx"> {
</span><del>-    if (!willAddTypingToOpenCommand(InsertText, CharacterGranularity))
</del><ins>+    if (!willAddTypingToOpenCommand(InsertText, CharacterGranularity, text))
</ins><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     RefPtr&lt;InsertTextCommand&gt; command = InsertTextCommand::create(document(), text, selectInsertedText,
</span></span></pre></div>
<a id="trunkSourceWebCoreeditingTypingCommandh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/TypingCommand.h (207009 => 207010)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/TypingCommand.h        2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/Source/WebCore/editing/TypingCommand.h        2016-10-10 18:30:03 UTC (rev 207010)
</span><span class="lines">@@ -117,11 +117,12 @@
</span><span class="cx">     void setShouldPreventSpellChecking(bool prevent) { m_shouldPreventSpellChecking = prevent; }
</span><span class="cx"> 
</span><span class="cx">     String inputEventTypeName() const final;
</span><ins>+    String inputEventData() const final;
</ins><span class="cx"> 
</span><span class="cx">     static void updateSelectionIfDifferentFromCurrentSelection(TypingCommand*, Frame*);
</span><span class="cx"> 
</span><span class="cx">     void updatePreservesTypingStyle(ETypingCommand);
</span><del>-    bool willAddTypingToOpenCommand(ETypingCommand, TextGranularity);
</del><ins>+    bool willAddTypingToOpenCommand(ETypingCommand, TextGranularity, const String&amp; = emptyString());
</ins><span class="cx">     void markMisspellingsAfterTyping(ETypingCommand);
</span><span class="cx">     void typingAddedToOpenCommand(ETypingCommand);
</span><span class="cx">     bool makeEditableRootEmpty();
</span><span class="lines">@@ -138,6 +139,7 @@
</span><span class="cx">     ETypingCommand m_commandType;
</span><span class="cx">     EditAction m_currentTypingEditAction;
</span><span class="cx">     String m_textToInsert;
</span><ins>+    String m_currentTextToInsert;
</ins><span class="cx">     bool m_openForMoreTyping;
</span><span class="cx">     bool m_selectInsertedText;
</span><span class="cx">     bool m_smartDelete;
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLFormControlElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLFormControlElement.cpp (207009 => 207010)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLFormControlElement.cpp        2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/Source/WebCore/html/HTMLFormControlElement.cpp        2016-10-10 18:30:03 UTC (rev 207010)
</span><span class="lines">@@ -326,7 +326,7 @@
</span><span class="cx"> void HTMLFormControlElement::dispatchFormControlInputEvent()
</span><span class="cx"> {
</span><span class="cx">     setChangedSinceLastFormControlChangeEvent(true);
</span><del>-    HTMLElement::dispatchInputEvent(emptyString());
</del><ins>+    HTMLElement::dispatchInputEvent();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool HTMLFormControlElement::isDisabledFormControl() const
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLInputElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLInputElement.cpp (207009 => 207010)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLInputElement.cpp        2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/Source/WebCore/html/HTMLInputElement.cpp        2016-10-10 18:30:03 UTC (rev 207010)
</span><span class="lines">@@ -1015,7 +1015,7 @@
</span><span class="cx">     else
</span><span class="cx">         cacheSelectionInResponseToSetValue(max);
</span><span class="cx"> 
</span><del>-    dispatchInputEvent(emptyString());
</del><ins>+    dispatchInputEvent();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void HTMLInputElement::setValue(const String&amp; value, ExceptionCode&amp; ec, TextFieldEventBehavior eventBehavior)
</span><span class="lines">@@ -1095,7 +1095,7 @@
</span><span class="cx"> 
</span><span class="cx">     // Input event is fired by the Node::defaultEventHandler for editable controls.
</span><span class="cx">     if (!isTextField())
</span><del>-        dispatchInputEvent(emptyString());
</del><ins>+        dispatchInputEvent();
</ins><span class="cx"> 
</span><span class="cx">     updateValidity();
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLSelectElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLSelectElement.cpp (207009 => 207010)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLSelectElement.cpp        2016-10-10 18:29:27 UTC (rev 207009)
+++ trunk/Source/WebCore/html/HTMLSelectElement.cpp        2016-10-10 18:30:03 UTC (rev 207010)
</span><span class="lines">@@ -669,7 +669,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (fireOnChange) {
</span><del>-        dispatchInputEvent(emptyString());
</del><ins>+        dispatchInputEvent();
</ins><span class="cx">         dispatchFormControlChangeEvent();
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="lines">@@ -682,7 +682,7 @@
</span><span class="cx">     if (m_lastOnChangeIndex != selected &amp;&amp; m_isProcessingUserDrivenChange) {
</span><span class="cx">         m_lastOnChangeIndex = selected;
</span><span class="cx">         m_isProcessingUserDrivenChange = false;
</span><del>-        dispatchInputEvent(emptyString());
</del><ins>+        dispatchInputEvent();
</ins><span class="cx">         dispatchFormControlChangeEvent();
</span><span class="cx">     }
</span><span class="cx"> }
</span></span></pre>
</div>
</div>

</body>
</html>