diff --git a/src/renderers/dom/client/eventPlugins/BeforeInputEventPlugin.js b/src/renderers/dom/client/eventPlugins/BeforeInputEventPlugin.js index e1163835feee5..a433da3607f41 100644 --- a/src/renderers/dom/client/eventPlugins/BeforeInputEventPlugin.js +++ b/src/renderers/dom/client/eventPlugins/BeforeInputEventPlugin.js @@ -221,6 +221,7 @@ function getDataFromCustomEvent(nativeEvent) { // Track the current IME composition fallback object, if any. var currentComposition = null; +var compositionWithoutEvent = null; /** * @return {?object} A SyntheticCompositionEvent. @@ -244,6 +245,16 @@ function extractCompositionEvent( eventType = eventTypes.compositionEnd; } + // Even when composition events are available, in some cases IE will still not always produce these. + // Try to detect such cases so we can still produce a beforeInput event. + if (canUseCompositionEvent && !eventType && !currentComposition + && useFallbackCompositionData && isFallbackCompositionStart(topLevelType, nativeEvent)) { + compositionWithoutEvent = FallbackCompositionState.getPooled(nativeEventTarget); + } else if (eventType || currentComposition) { + compositionWithoutEvent = null; + } + + if (!eventType) { return null; } @@ -357,6 +368,11 @@ function getFallbackBeforeInputChars(topLevelType: TopLevelTypes, nativeEvent) { return chars; } return null; + } else if (compositionWithoutEvent && topLevelType === 'topKeyUp') { + var data = compositionWithoutEvent.getData(); + FallbackCompositionState.release(compositionWithoutEvent); + compositionWithoutEvent = null; + return data; } switch (topLevelType) { diff --git a/src/renderers/dom/client/eventPlugins/__tests__/BeforeInputEventPlugin-test.js b/src/renderers/dom/client/eventPlugins/__tests__/BeforeInputEventPlugin-test.js index d39527f5c0a04..7c48da25ec094 100644 --- a/src/renderers/dom/client/eventPlugins/__tests__/BeforeInputEventPlugin-test.js +++ b/src/renderers/dom/client/eventPlugins/__tests__/BeforeInputEventPlugin-test.js @@ -197,13 +197,34 @@ describe('BeforeInputEventPlugin', function() { verifyEvents(events, ExpectedResult()); } - it('extract onBeforeInput from native textinput events', function() { + it('extracts onBeforeInput from native textinput events', function() { TestEditableReactComponent( simulateWebkit, Scenario_Composition, Expected_Webkit); }); - it('extract onBeforeInput from fallback objects', function() { + it('extracts onBeforeInput from fallback objects', function() { TestEditableReactComponent( simulateIE11, Scenario_Composition, Expected_IE11); }); + + + var buggyIEScenario = [ + {run: accumulateEvents, arg: ['keydown', {keyCode: 229}]}, + {run: setElementText, arg: ['。']}, + {run: accumulateEvents, arg: ['keyup', {keyCode: 190}]}, + ]; + + var buggyIEScenarioExpectations = () => [ + {type: null}, {type: null}, // keyDown of 229 + {type: null}, // keyUp of 190 + {type: ModuleCache.SyntheticInputEvent, data: {data: '。'}}, + ]; + + // In some cases, such as when entering full-width Chinese punctuation on IE with Sogou Wubi, + // the composition event is missing. In this case, we still expect a proper input event. + it('extracts onBeforeInput from buggy IE interaction without composition events', function() { + TestEditableReactComponent( + simulateIE11, buggyIEScenario, buggyIEScenarioExpectations); + }); + });