@@ -23,6 +23,7 @@ const Keys = require('Keys');
2323const getEntityKeyForSelection = require ( 'getEntityKeyForSelection' ) ;
2424const isEventHandled = require ( 'isEventHandled' ) ;
2525const isSelectionAtLeafStart = require ( 'isSelectionAtLeafStart' ) ;
26+ const onInput = require ( 'editOnInput' ) ;
2627
2728/**
2829 * Millisecond delay to allow `compositionstart` to fire again upon
@@ -44,11 +45,13 @@ const RESOLVE_DELAY = 20;
4445 */
4546let resolved = false ;
4647let stillComposing = false ;
47- let textInputData = '' ;
48+ let beforeInputData = null ;
49+ let compositionUpdateData = null ;
50+ let compositionEndData = null ;
4851
4952var DraftEditorCompositionHandler = {
5053 onBeforeInput : function ( editor : DraftEditor , e : SyntheticInputEvent < > ) : void {
51- textInputData = ( textInputData || '' ) + e . data ;
54+ beforeInputData = ( beforeInputData || '' ) + e . data ;
5255 } ,
5356
5457 /**
@@ -59,6 +62,17 @@ var DraftEditorCompositionHandler = {
5962 stillComposing = true ;
6063 } ,
6164
65+ /**
66+ * A `compositionupdate` event has fired. Update the current composition
67+ * session.
68+ */
69+ onCompositionUpdate : function (
70+ editor : DraftEditor ,
71+ e : SyntheticInputEvent < > ,
72+ ) : void {
73+ compositionUpdateData = e . data ;
74+ } ,
75+
6276 /**
6377 * Attempt to end the current composition session.
6478 *
@@ -73,9 +87,13 @@ var DraftEditorCompositionHandler = {
7387 * twice could break the DOM, we only use the first event. Example: Arabic
7488 * Google Input Tools on Windows 8.1 fires `compositionend` three times.
7589 */
76- onCompositionEnd : function ( editor : DraftEditor ) : void {
90+ onCompositionEnd : function (
91+ editor : DraftEditor ,
92+ e : SyntheticInputEvent < > ,
93+ ) : void {
7794 resolved = false ;
7895 stillComposing = false ;
96+ compositionEndData = compositionEndData || e . data ;
7997 setTimeout ( ( ) => {
8098 if ( ! resolved ) {
8199 DraftEditorCompositionHandler . resolveComposition ( editor ) ;
@@ -115,6 +133,34 @@ var DraftEditorCompositionHandler = {
115133 }
116134 } ,
117135
136+ /**
137+ * Normalizes platform inconsistencies with input event data.
138+ *
139+ * When beforeInputData is present, it is only preferred if its length
140+ * is greater than that of the last compositionUpdate event data. This is
141+ * meant to resolve IME incosistencies where compositionUpdate may contain
142+ * only the last character or the entire composition depending on language
143+ * (e.g. Korean vs. Japanese).
144+ *
145+ * When beforeInputData is not present, compositionUpdate data is preferred.
146+ * This resolves issues with some platforms where beforeInput is never fired
147+ * (e.g. Android with certain keyboard and browser combinations).
148+ *
149+ * Lastly, if neither beforeInput nor compositionUpdate events are fired, use
150+ * the data in the compositionEnd event
151+ */
152+ normalizeCompositionInput : function ( ) : ?string {
153+ const beforeInputDataLength = beforeInputData ? beforeInputData . length : 0 ;
154+ const compositionUpdateDataLength = compositionUpdateData
155+ ? compositionUpdateData . length
156+ : 0 ;
157+ const updateData =
158+ beforeInputDataLength > compositionUpdateDataLength
159+ ? beforeInputData
160+ : compositionUpdateData ;
161+ return updateData || compositionEndData ;
162+ } ,
163+
118164 /**
119165 * Attempt to insert composed characters into the document.
120166 *
@@ -136,13 +182,13 @@ var DraftEditorCompositionHandler = {
136182 }
137183
138184 resolved = true ;
139- const composedChars = textInputData ;
140- textInputData = '' ;
141-
142- const editorState = EditorState . set ( editor . _latestEditorState , {
143- inCompositionMode : false ,
144- } ) ;
185+ let composedChars ;
186+ composedChars = this . normalizeCompositionInput ( ) ;
187+ beforeInputData = null ;
188+ compositionUpdateData = null ;
189+ compositionEndData = null ;
145190
191+ const editorState = editor . _latestEditorState ;
146192 const currentStyle = editorState . getCurrentInlineStyle ( ) ;
147193 const entityKey = getEntityKeyForSelection (
148194 editorState . getCurrentContent ( ) ,
@@ -186,6 +232,15 @@ var DraftEditorCompositionHandler = {
186232 return ;
187233 }
188234
235+ onInput ( editor ) ;
236+ editor . restoreEditorDOM ( ) ;
237+ editor . update (
238+ EditorState . set ( editorState , {
239+ nativelyRenderedContent : null ,
240+ inCompositionMode : false ,
241+ } ) ,
242+ ) ;
243+
189244 if ( mustReset ) {
190245 editor . update (
191246 EditorState . set ( editorState , {
0 commit comments