diff --git a/packages/events/EventPluginUtils.js b/packages/events/EventPluginUtils.js index d5e5a5e8477..dbb2c7fa335 100644 --- a/packages/events/EventPluginUtils.js +++ b/packages/events/EventPluginUtils.js @@ -9,6 +9,16 @@ import ReactErrorUtils from 'shared/ReactErrorUtils'; import invariant from 'fbjs/lib/invariant'; import warning from 'fbjs/lib/warning'; +import { + TOP_MOUSE_DOWN, + TOP_MOUSE_MOVE, + TOP_MOUSE_UP, + TOP_TOUCH_CANCEL, + TOP_TOUCH_END, + TOP_TOUCH_MOVE, + TOP_TOUCH_START, +} from './TopLevelEventTypes'; + export let getFiberCurrentPropsFromNode = null; export let getInstanceFromNode = null; export let getNodeFromInstance = null; @@ -32,17 +42,17 @@ export const injection = { export function isEndish(topLevelType) { return ( - topLevelType === 'topMouseUp' || - topLevelType === 'topTouchEnd' || - topLevelType === 'topTouchCancel' + topLevelType === TOP_MOUSE_UP || + topLevelType === TOP_TOUCH_END || + topLevelType === TOP_TOUCH_CANCEL ); } export function isMoveish(topLevelType) { - return topLevelType === 'topMouseMove' || topLevelType === 'topTouchMove'; + return topLevelType === TOP_MOUSE_MOVE || topLevelType === TOP_TOUCH_MOVE; } export function isStartish(topLevelType) { - return topLevelType === 'topMouseDown' || topLevelType === 'topTouchStart'; + return topLevelType === TOP_MOUSE_DOWN || topLevelType === TOP_TOUCH_START; } let validateEventDispatches; diff --git a/packages/events/ResponderEventPlugin.js b/packages/events/ResponderEventPlugin.js index 202f8931f99..7ec1ff3d066 100644 --- a/packages/events/ResponderEventPlugin.js +++ b/packages/events/ResponderEventPlugin.js @@ -23,6 +23,11 @@ import { } from './EventPropagators'; import ResponderSyntheticEvent from './ResponderSyntheticEvent'; import ResponderTouchHistoryStore from './ResponderTouchHistoryStore'; +import { + TOP_SCROLL, + TOP_SELECTION_CHANGE, + TOP_TOUCH_CANCEL, +} from './TopLevelEventTypes'; import accumulate from './accumulate'; /** @@ -322,7 +327,7 @@ function setResponderAndExtractTransfer( ? eventTypes.startShouldSetResponder : isMoveish(topLevelType) ? eventTypes.moveShouldSetResponder - : topLevelType === 'topSelectionChange' + : topLevelType === TOP_SELECTION_CHANGE ? eventTypes.selectionChangeShouldSetResponder : eventTypes.scrollShouldSetResponder; @@ -427,8 +432,8 @@ function canTriggerTransfer(topLevelType, topLevelInst, nativeEvent) { // responderIgnoreScroll: We are trying to migrate away from specifically // tracking native scroll events here and responderIgnoreScroll indicates we // will send topTouchCancel to handle canceling touch events instead - ((topLevelType === 'topScroll' && !nativeEvent.responderIgnoreScroll) || - (trackedTouchCount > 0 && topLevelType === 'topSelectionChange') || + ((topLevelType === TOP_SCROLL && !nativeEvent.responderIgnoreScroll) || + (trackedTouchCount > 0 && topLevelType === TOP_SELECTION_CHANGE) || isStartish(topLevelType) || isMoveish(topLevelType)) ); @@ -534,7 +539,7 @@ const ResponderEventPlugin = { } const isResponderTerminate = - responderInst && topLevelType === 'topTouchCancel'; + responderInst && topLevelType === TOP_TOUCH_CANCEL; const isResponderRelease = responderInst && !isResponderTerminate && diff --git a/packages/events/TopLevelEventTypes.js b/packages/events/TopLevelEventTypes.js new file mode 100644 index 00000000000..5e81961a2f4 --- /dev/null +++ b/packages/events/TopLevelEventTypes.js @@ -0,0 +1,80 @@ +/** + * Copyright (c) 2013-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + */ + +export const TOP_ABORT = 0; +export const TOP_ANIMATION_END = 1; +export const TOP_ANIMATION_ITERATION = 2; +export const TOP_ANIMATION_START = 3; +export const TOP_BLUR = 4; +export const TOP_CANCEL = 5; +export const TOP_CAN_PLAY = 6; +export const TOP_CAN_PLAY_THROUGH = 7; +export const TOP_CHANGE = 8; +export const TOP_CLICK = 9; +export const TOP_CLOSE = 10; +export const TOP_COMPOSITION_END = 11; +export const TOP_COMPOSITION_START = 12; +export const TOP_COMPOSITION_UPDATE = 13; +export const TOP_CONTEXT_MENU = 14; +export const TOP_COPY = 15; +export const TOP_CUT = 16; +export const TOP_DOUBLE_CLICK = 17; +export const TOP_DRAG = 18; +export const TOP_DRAG_END = 19; +export const TOP_DRAG_ENTER = 20; +export const TOP_DRAG_EXIT = 21; +export const TOP_DRAG_LEAVE = 22; +export const TOP_DRAG_OVER = 23; +export const TOP_DRAG_START = 24; +export const TOP_DROP = 25; +export const TOP_DURATION_CHANGE = 26; +export const TOP_EMPTIED = 27; +export const TOP_ENCRYPTED = 28; +export const TOP_ENDED = 29; +export const TOP_ERROR = 30; +export const TOP_FOCUS = 31; +export const TOP_INPUT = 32; +export const TOP_INVALID = 33; +export const TOP_KEY_DOWN = 34; +export const TOP_KEY_PRESS = 35; +export const TOP_KEY_UP = 36; +export const TOP_LOADED_DATA = 37; +export const TOP_LOAD = 38; +export const TOP_LOADED_METADATA = 39; +export const TOP_LOAD_START = 40; +export const TOP_MOUSE_DOWN = 41; +export const TOP_MOUSE_MOVE = 42; +export const TOP_MOUSE_OUT = 43; +export const TOP_MOUSE_OVER = 44; +export const TOP_MOUSE_UP = 45; +export const TOP_PASTE = 46; +export const TOP_PAUSE = 47; +export const TOP_PLAY = 48; +export const TOP_PLAYING = 49; +export const TOP_PROGRESS = 50; +export const TOP_RATE_CHANGE = 51; +export const TOP_RESET = 52; +export const TOP_SCROLL = 53; +export const TOP_SEEKED = 54; +export const TOP_SEEKING = 55; +export const TOP_SELECTION_CHANGE = 56; +export const TOP_STALLED = 57; +export const TOP_SUBMIT = 58; +export const TOP_SUSPEND = 59; +export const TOP_TEXT_INPUT = 60; +export const TOP_TIME_UPDATE = 61; +export const TOP_TOGGLE = 62; +export const TOP_TOUCH_CANCEL = 63; +export const TOP_TOUCH_END = 64; +export const TOP_TOUCH_MOVE = 65; +export const TOP_TOUCH_START = 66; +export const TOP_TRANSITION_END = 67; +export const TOP_VOLUME_CHANGE = 68; +export const TOP_WAITING = 69; +export const TOP_WHEEL = 70; diff --git a/packages/react-dom/src/client/ReactDOMFiberComponent.js b/packages/react-dom/src/client/ReactDOMFiberComponent.js index 2319866823f..e55300bfb54 100644 --- a/packages/react-dom/src/client/ReactDOMFiberComponent.js +++ b/packages/react-dom/src/client/ReactDOMFiberComponent.js @@ -10,6 +10,36 @@ // TODO: direct imports like some-package/src/* are bad. Fix me. import ReactDebugCurrentFiber from 'react-reconciler/src/ReactDebugCurrentFiber'; import {registrationNameModules} from 'events/EventPluginRegistry'; +import { + TOP_ABORT, + TOP_CAN_PLAY, + TOP_CAN_PLAY_THROUGH, + TOP_DURATION_CHANGE, + TOP_EMPTIED, + TOP_ENCRYPTED, + TOP_ENDED, + TOP_ERROR, + TOP_INVALID, + TOP_LOAD, + TOP_LOADED_DATA, + TOP_LOADED_METADATA, + TOP_LOAD_START, + TOP_PAUSE, + TOP_PLAY, + TOP_PLAYING, + TOP_PROGRESS, + TOP_RATE_CHANGE, + TOP_RESET, + TOP_SEEKED, + TOP_SEEKING, + TOP_STALLED, + TOP_SUBMIT, + TOP_SUSPEND, + TOP_TIME_UPDATE, + TOP_TOGGLE, + TOP_VOLUME_CHANGE, + TOP_WAITING, +} from 'events/TopLevelEventTypes'; import emptyFunction from 'fbjs/lib/emptyFunction'; import warning from 'fbjs/lib/warning'; @@ -22,6 +52,7 @@ import * as inputValueTracking from './inputValueTracking'; import setInnerHTML from './setInnerHTML'; import setTextContent from './setTextContent'; import {listenTo, trapBubbledEvent} from '../events/ReactBrowserEventEmitter'; +import {getRawEventName} from '../events/BrowserEventConstants'; import * as CSSPropertyOperations from '../shared/CSSPropertyOperations'; import {Namespaces, getIntrinsicNamespace} from '../shared/DOMNamespaces'; import { @@ -224,31 +255,31 @@ function getOwnerDocumentFromRootContainer( // There are so many media events, it makes sense to just // maintain a list rather than create a `trapBubbledEvent` for each -const mediaEvents = { - topAbort: 'abort', - topCanPlay: 'canplay', - topCanPlayThrough: 'canplaythrough', - topDurationChange: 'durationchange', - topEmptied: 'emptied', - topEncrypted: 'encrypted', - topEnded: 'ended', - topError: 'error', - topLoadedData: 'loadeddata', - topLoadedMetadata: 'loadedmetadata', - topLoadStart: 'loadstart', - topPause: 'pause', - topPlay: 'play', - topPlaying: 'playing', - topProgress: 'progress', - topRateChange: 'ratechange', - topSeeked: 'seeked', - topSeeking: 'seeking', - topStalled: 'stalled', - topSuspend: 'suspend', - topTimeUpdate: 'timeupdate', - topVolumeChange: 'volumechange', - topWaiting: 'waiting', -}; +const mediaEvents = [ + TOP_ABORT, + TOP_CAN_PLAY, + TOP_CAN_PLAY_THROUGH, + TOP_DURATION_CHANGE, + TOP_EMPTIED, + TOP_ENCRYPTED, + TOP_ENDED, + TOP_ERROR, + TOP_LOADED_DATA, + TOP_LOADED_METADATA, + TOP_LOAD_START, + TOP_PAUSE, + TOP_PLAY, + TOP_PLAYING, + TOP_PROGRESS, + TOP_RATE_CHANGE, + TOP_SEEKED, + TOP_SEEKING, + TOP_STALLED, + TOP_SUSPEND, + TOP_TIME_UPDATE, + TOP_VOLUME_CHANGE, + TOP_WAITING, +]; function trapClickOnNonInteractiveElement(node: HTMLElement) { // Mobile Safari does not fire properly bubble click events on @@ -465,42 +496,40 @@ export function setInitialProperties( switch (tag) { case 'iframe': case 'object': - trapBubbledEvent('topLoad', 'load', domElement); + trapBubbledEvent(TOP_LOAD, 'load', domElement); props = rawProps; break; case 'video': case 'audio': // Create listener for each media event - for (const event in mediaEvents) { - if (mediaEvents.hasOwnProperty(event)) { - trapBubbledEvent(event, mediaEvents[event], domElement); - } + for (let i = 0; i < mediaEvents.length; i++) { + trapBubbledEvent(event, getRawEventName(mediaEvents[i]), domElement); } props = rawProps; break; case 'source': - trapBubbledEvent('topError', 'error', domElement); + trapBubbledEvent(TOP_ERROR, 'error', domElement); props = rawProps; break; case 'img': case 'image': - trapBubbledEvent('topError', 'error', domElement); - trapBubbledEvent('topLoad', 'load', domElement); + trapBubbledEvent(TOP_ERROR, 'error', domElement); + trapBubbledEvent(TOP_LOAD, 'load', domElement); props = rawProps; break; case 'form': - trapBubbledEvent('topReset', 'reset', domElement); - trapBubbledEvent('topSubmit', 'submit', domElement); + trapBubbledEvent(TOP_RESET, 'reset', domElement); + trapBubbledEvent(TOP_SUBMIT, 'submit', domElement); props = rawProps; break; case 'details': - trapBubbledEvent('topToggle', 'toggle', domElement); + trapBubbledEvent(TOP_TOGGLE, 'toggle', domElement); props = rawProps; break; case 'input': ReactDOMFiberInput.initWrapperState(domElement, rawProps); props = ReactDOMFiberInput.getHostProps(domElement, rawProps); - trapBubbledEvent('topInvalid', 'invalid', domElement); + trapBubbledEvent(TOP_INVALID, 'invalid', domElement); // For controlled components we always need to ensure we're listening // to onChange. Even if there is no listener. ensureListeningTo(rootContainerElement, 'onChange'); @@ -512,7 +541,7 @@ export function setInitialProperties( case 'select': ReactDOMFiberSelect.initWrapperState(domElement, rawProps); props = ReactDOMFiberSelect.getHostProps(domElement, rawProps); - trapBubbledEvent('topInvalid', 'invalid', domElement); + trapBubbledEvent(TOP_INVALID, 'invalid', domElement); // For controlled components we always need to ensure we're listening // to onChange. Even if there is no listener. ensureListeningTo(rootContainerElement, 'onChange'); @@ -520,7 +549,7 @@ export function setInitialProperties( case 'textarea': ReactDOMFiberTextarea.initWrapperState(domElement, rawProps); props = ReactDOMFiberTextarea.getHostProps(domElement, rawProps); - trapBubbledEvent('topInvalid', 'invalid', domElement); + trapBubbledEvent(TOP_INVALID, 'invalid', domElement); // For controlled components we always need to ensure we're listening // to onChange. Even if there is no listener. ensureListeningTo(rootContainerElement, 'onChange'); @@ -842,35 +871,33 @@ export function diffHydratedProperties( switch (tag) { case 'iframe': case 'object': - trapBubbledEvent('topLoad', 'load', domElement); + trapBubbledEvent(TOP_LOAD, 'load', domElement); break; case 'video': case 'audio': // Create listener for each media event - for (const event in mediaEvents) { - if (mediaEvents.hasOwnProperty(event)) { - trapBubbledEvent(event, mediaEvents[event], domElement); - } + for (let i = 0; i < mediaEvents.length; i++) { + trapBubbledEvent(event, getRawEventName(mediaEvents[i]), domElement); } break; case 'source': - trapBubbledEvent('topError', 'error', domElement); + trapBubbledEvent(TOP_ERROR, 'error', domElement); break; case 'img': case 'image': - trapBubbledEvent('topError', 'error', domElement); - trapBubbledEvent('topLoad', 'load', domElement); + trapBubbledEvent(TOP_ERROR, 'error', domElement); + trapBubbledEvent(TOP_LOAD, 'load', domElement); break; case 'form': - trapBubbledEvent('topReset', 'reset', domElement); - trapBubbledEvent('topSubmit', 'submit', domElement); + trapBubbledEvent(TOP_RESET, 'reset', domElement); + trapBubbledEvent(TOP_SUBMIT, 'submit', domElement); break; case 'details': - trapBubbledEvent('topToggle', 'toggle', domElement); + trapBubbledEvent(TOP_TOGGLE, 'toggle', domElement); break; case 'input': ReactDOMFiberInput.initWrapperState(domElement, rawProps); - trapBubbledEvent('topInvalid', 'invalid', domElement); + trapBubbledEvent(TOP_INVALID, 'invalid', domElement); // For controlled components we always need to ensure we're listening // to onChange. Even if there is no listener. ensureListeningTo(rootContainerElement, 'onChange'); @@ -880,14 +907,14 @@ export function diffHydratedProperties( break; case 'select': ReactDOMFiberSelect.initWrapperState(domElement, rawProps); - trapBubbledEvent('topInvalid', 'invalid', domElement); + trapBubbledEvent(TOP_INVALID, 'invalid', domElement); // For controlled components we always need to ensure we're listening // to onChange. Even if there is no listener. ensureListeningTo(rootContainerElement, 'onChange'); break; case 'textarea': ReactDOMFiberTextarea.initWrapperState(domElement, rawProps); - trapBubbledEvent('topInvalid', 'invalid', domElement); + trapBubbledEvent(TOP_INVALID, 'invalid', domElement); // For controlled components we always need to ensure we're listening // to onChange. Even if there is no listener. ensureListeningTo(rootContainerElement, 'onChange'); diff --git a/packages/react-dom/src/events/BeforeInputEventPlugin.js b/packages/react-dom/src/events/BeforeInputEventPlugin.js index fc5e2ef26c3..e80648c9cd9 100644 --- a/packages/react-dom/src/events/BeforeInputEventPlugin.js +++ b/packages/react-dom/src/events/BeforeInputEventPlugin.js @@ -8,6 +8,18 @@ import type {TopLevelTypes} from './BrowserEventConstants'; import {accumulateTwoPhaseDispatches} from 'events/EventPropagators'; +import { + TOP_BLUR, + TOP_COMPOSITION_START, + TOP_COMPOSITION_END, + TOP_COMPOSITION_UPDATE, + TOP_KEY_DOWN, + TOP_KEY_PRESS, + TOP_KEY_UP, + TOP_MOUSE_DOWN, + TOP_TEXT_INPUT, + TOP_PASTE, +} from 'events/TopLevelEventTypes'; import ExecutionEnvironment from 'fbjs/lib/ExecutionEnvironment'; import * as FallbackCompositionState from './FallbackCompositionState'; @@ -67,10 +79,10 @@ const eventTypes = { captured: 'onBeforeInputCapture', }, dependencies: [ - 'topCompositionEnd', - 'topKeyPress', - 'topTextInput', - 'topPaste', + TOP_COMPOSITION_END, + TOP_KEY_PRESS, + TOP_TEXT_INPUT, + TOP_PASTE, ], }, compositionEnd: { @@ -79,12 +91,12 @@ const eventTypes = { captured: 'onCompositionEndCapture', }, dependencies: [ - 'topBlur', - 'topCompositionEnd', - 'topKeyDown', - 'topKeyPress', - 'topKeyUp', - 'topMouseDown', + TOP_BLUR, + TOP_COMPOSITION_END, + TOP_KEY_DOWN, + TOP_KEY_PRESS, + TOP_KEY_UP, + TOP_MOUSE_DOWN, ], }, compositionStart: { @@ -93,12 +105,12 @@ const eventTypes = { captured: 'onCompositionStartCapture', }, dependencies: [ - 'topBlur', - 'topCompositionStart', - 'topKeyDown', - 'topKeyPress', - 'topKeyUp', - 'topMouseDown', + TOP_BLUR, + TOP_COMPOSITION_START, + TOP_KEY_DOWN, + TOP_KEY_PRESS, + TOP_KEY_UP, + TOP_MOUSE_DOWN, ], }, compositionUpdate: { @@ -107,12 +119,12 @@ const eventTypes = { captured: 'onCompositionUpdateCapture', }, dependencies: [ - 'topBlur', - 'topCompositionUpdate', - 'topKeyDown', - 'topKeyPress', - 'topKeyUp', - 'topMouseDown', + TOP_BLUR, + TOP_COMPOSITION_UPDATE, + TOP_KEY_DOWN, + TOP_KEY_PRESS, + TOP_KEY_UP, + TOP_MOUSE_DOWN, ], }, }; @@ -141,11 +153,11 @@ function isKeypressCommand(nativeEvent) { */ function getCompositionEventType(topLevelType) { switch (topLevelType) { - case 'topCompositionStart': + case TOP_COMPOSITION_START: return eventTypes.compositionStart; - case 'topCompositionEnd': + case TOP_COMPOSITION_END: return eventTypes.compositionEnd; - case 'topCompositionUpdate': + case TOP_COMPOSITION_UPDATE: return eventTypes.compositionUpdate; } } @@ -159,7 +171,7 @@ function getCompositionEventType(topLevelType) { * @return {boolean} */ function isFallbackCompositionStart(topLevelType, nativeEvent) { - return topLevelType === 'topKeyDown' && nativeEvent.keyCode === START_KEYCODE; + return topLevelType === TOP_KEY_DOWN && nativeEvent.keyCode === START_KEYCODE; } /** @@ -171,16 +183,16 @@ function isFallbackCompositionStart(topLevelType, nativeEvent) { */ function isFallbackCompositionEnd(topLevelType, nativeEvent) { switch (topLevelType) { - case 'topKeyUp': + case TOP_KEY_UP: // Command keys insert or clear IME input. return END_KEYCODES.indexOf(nativeEvent.keyCode) !== -1; - case 'topKeyDown': + case TOP_KEY_DOWN: // Expect IME keyCode on each keydown. If we get any other // code we must have exited earlier. return nativeEvent.keyCode !== START_KEYCODE; - case 'topKeyPress': - case 'topMouseDown': - case 'topBlur': + case TOP_KEY_PRESS: + case TOP_MOUSE_DOWN: + case TOP_BLUR: // Events are not possible without cancelling IME. return true; default: @@ -275,9 +287,9 @@ function extractCompositionEvent( */ function getNativeBeforeInputChars(topLevelType: TopLevelTypes, nativeEvent) { switch (topLevelType) { - case 'topCompositionEnd': + case TOP_COMPOSITION_END: return getDataFromCustomEvent(nativeEvent); - case 'topKeyPress': + case TOP_KEY_PRESS: /** * If native `textInput` events are available, our goal is to make * use of them. However, there is a special case: the spacebar key. @@ -300,7 +312,7 @@ function getNativeBeforeInputChars(topLevelType: TopLevelTypes, nativeEvent) { hasSpaceKeypress = true; return SPACEBAR_CHAR; - case 'topTextInput': + case TOP_TEXT_INPUT: // Record the characters to be added to the DOM. const chars = nativeEvent.data; @@ -334,7 +346,7 @@ function getFallbackBeforeInputChars(topLevelType: TopLevelTypes, nativeEvent) { // compositionevent, otherwise extract it at fallback events. if (isComposing) { if ( - topLevelType === 'topCompositionEnd' || + topLevelType === TOP_COMPOSITION_END || (!canUseCompositionEvent && isFallbackCompositionEnd(topLevelType, nativeEvent)) ) { @@ -347,11 +359,11 @@ function getFallbackBeforeInputChars(topLevelType: TopLevelTypes, nativeEvent) { } switch (topLevelType) { - case 'topPaste': + case TOP_PASTE: // If a paste event occurs after a keypress, throw out the input // chars. Paste events should not lead to BeforeInput events. return null; - case 'topKeyPress': + case TOP_KEY_PRESS: /** * As of v27, Firefox may fire keypress events even when no character * will be inserted. A few possibilities: @@ -382,7 +394,7 @@ function getFallbackBeforeInputChars(topLevelType: TopLevelTypes, nativeEvent) { } } return null; - case 'topCompositionEnd': + case TOP_COMPOSITION_END: return useFallbackCompositionData ? null : nativeEvent.data; default: return null; diff --git a/packages/react-dom/src/events/BrowserEventConstants.js b/packages/react-dom/src/events/BrowserEventConstants.js index 9d185cc3262..4be9197116f 100644 --- a/packages/react-dom/src/events/BrowserEventConstants.js +++ b/packages/react-dom/src/events/BrowserEventConstants.js @@ -6,6 +6,8 @@ */ import getVendorPrefixedEventName from './getVendorPrefixedEventName'; +import {topLevelEventsToDispatchConfig} from './SimpleEventPlugin'; +import * as TopLevelEventTypes from 'events/TopLevelEventTypes'; /** * Types of raw signals from the browser caught at the top level. @@ -14,84 +16,46 @@ import getVendorPrefixedEventName from './getVendorPrefixedEventName'; * trap at a lower node than `document`), binding at `document` would * cause duplicate events so we don't include them here. */ -const topLevelTypes = { - topAbort: 'abort', - topAnimationEnd: getVendorPrefixedEventName('animationend') || 'animationend', - topAnimationIteration: +const cache = new Map([ + [TopLevelEventTypes.TOP_ABORT, 'abort'], + [ + TopLevelEventTypes.TOP_ANIMATION_END, + getVendorPrefixedEventName('animationend') || 'animationend', + ], + [ + TopLevelEventTypes.TOP_ANIMATION_ITERATION, getVendorPrefixedEventName('animationiteration') || 'animationiteration', - topAnimationStart: + ], + [ + TopLevelEventTypes.TOP_ANIMATION_START, getVendorPrefixedEventName('animationstart') || 'animationstart', - topBlur: 'blur', - topCancel: 'cancel', - topCanPlay: 'canplay', - topCanPlayThrough: 'canplaythrough', - topChange: 'change', - topClick: 'click', - topClose: 'close', - topCompositionEnd: 'compositionend', - topCompositionStart: 'compositionstart', - topCompositionUpdate: 'compositionupdate', - topContextMenu: 'contextmenu', - topCopy: 'copy', - topCut: 'cut', - topDoubleClick: 'dblclick', - topDrag: 'drag', - topDragEnd: 'dragend', - topDragEnter: 'dragenter', - topDragExit: 'dragexit', - topDragLeave: 'dragleave', - topDragOver: 'dragover', - topDragStart: 'dragstart', - topDrop: 'drop', - topDurationChange: 'durationchange', - topEmptied: 'emptied', - topEncrypted: 'encrypted', - topEnded: 'ended', - topError: 'error', - topFocus: 'focus', - topInput: 'input', - topKeyDown: 'keydown', - topKeyPress: 'keypress', - topKeyUp: 'keyup', - topLoadedData: 'loadeddata', - topLoad: 'load', - topLoadedMetadata: 'loadedmetadata', - topLoadStart: 'loadstart', - topMouseDown: 'mousedown', - topMouseMove: 'mousemove', - topMouseOut: 'mouseout', - topMouseOver: 'mouseover', - topMouseUp: 'mouseup', - topPaste: 'paste', - topPause: 'pause', - topPlay: 'play', - topPlaying: 'playing', - topProgress: 'progress', - topRateChange: 'ratechange', - topScroll: 'scroll', - topSeeked: 'seeked', - topSeeking: 'seeking', - topSelectionChange: 'selectionchange', - topStalled: 'stalled', - topSuspend: 'suspend', - topTextInput: 'textInput', - topTimeUpdate: 'timeupdate', - topToggle: 'toggle', - topTouchCancel: 'touchcancel', - topTouchEnd: 'touchend', - topTouchMove: 'touchmove', - topTouchStart: 'touchstart', - topTransitionEnd: + ], + [TopLevelEventTypes.TOP_CHANGE, 'change'], + [TopLevelEventTypes.TOP_COMPOSITION_END, 'compositionend'], + [TopLevelEventTypes.TOP_COMPOSITION_START, 'compositionstart'], + [TopLevelEventTypes.TOP_COMPOSITION_UPDATE, 'compositionupdate'], + [TopLevelEventTypes.TOP_DOUBLE_CLICK, 'dblclick'], + [TopLevelEventTypes.TOP_SELECTION_CHANGE, 'selectionchange'], + [TopLevelEventTypes.TOP_TEXT_INPUT, 'textInput'], + [TopLevelEventTypes.TOP_TOGGLE, 'toggle'], + [ + TopLevelEventTypes.TOP_TRANSITION_END, getVendorPrefixedEventName('transitionend') || 'transitionend', - topVolumeChange: 'volumechange', - topWaiting: 'waiting', - topWheel: 'wheel', -}; + ], +]); -export type TopLevelTypes = $Enum; - -const BrowserEventConstants = { - topLevelTypes, -}; +export function getRawEventName(topLevelType) { + const maybeName = cache.get(topLevelType); + if (typeof maybeName === 'string') { + return maybeName; + } + // Fallback + const config = topLevelEventsToDispatchConfig.get(topLevelTypes); + const name = phasedRegistrationNames.bubbled.slice(2); + cache.set(topLevelType, name); + // TODO: this is not exactly the same because we used to + // intentionally skip over some events? + return name; +} -export default BrowserEventConstants; +export type TopLevelTypes = $Enum; diff --git a/packages/react-dom/src/events/ChangeEventPlugin.js b/packages/react-dom/src/events/ChangeEventPlugin.js index 392beab1be4..9c5b4e3fd20 100644 --- a/packages/react-dom/src/events/ChangeEventPlugin.js +++ b/packages/react-dom/src/events/ChangeEventPlugin.js @@ -10,6 +10,16 @@ import {accumulateTwoPhaseDispatches} from 'events/EventPropagators'; import {enqueueStateRestore} from 'events/ReactControlledComponent'; import {batchedUpdates} from 'events/ReactGenericBatching'; import SyntheticEvent from 'events/SyntheticEvent'; +import { + TOP_BLUR, + TOP_CHANGE, + TOP_CLICK, + TOP_FOCUS, + TOP_INPUT, + TOP_KEY_DOWN, + TOP_KEY_UP, + TOP_SELECTION_CHANGE, +} from 'events/TopLevelEventTypes'; import isTextInputElement from 'shared/isTextInputElement'; import ExecutionEnvironment from 'fbjs/lib/ExecutionEnvironment'; @@ -26,14 +36,14 @@ const eventTypes = { captured: 'onChangeCapture', }, dependencies: [ - 'topBlur', - 'topChange', - 'topClick', - 'topFocus', - 'topInput', - 'topKeyDown', - 'topKeyUp', - 'topSelectionChange', + TOP_BLUR, + TOP_CHANGE, + TOP_CLICK, + TOP_FOCUS, + TOP_INPUT, + TOP_KEY_DOWN, + TOP_KEY_UP, + TOP_SELECTION_CHANGE, ], }, }; @@ -101,7 +111,7 @@ function getInstIfValueChanged(targetInst) { } function getTargetInstForChangeEvent(topLevelType, targetInst) { - if (topLevelType === 'topChange') { + if (topLevelType === TOP_CHANGE) { return targetInst; } } @@ -156,7 +166,7 @@ function handlePropertyChange(nativeEvent) { } function handleEventsForInputEventPolyfill(topLevelType, target, targetInst) { - if (topLevelType === 'topFocus') { + if (topLevelType === TOP_FOCUS) { // In IE9, propertychange fires for most input events but is buggy and // doesn't fire when text is deleted, but conveniently, selectionchange // appears to fire in all of the remaining cases so we catch those and @@ -169,7 +179,7 @@ function handleEventsForInputEventPolyfill(topLevelType, target, targetInst) { // missed a blur event somehow. stopWatchingForValueChange(); startWatchingForValueChange(target, targetInst); - } else if (topLevelType === 'topBlur') { + } else if (topLevelType === TOP_BLUR) { stopWatchingForValueChange(); } } @@ -177,9 +187,9 @@ function handleEventsForInputEventPolyfill(topLevelType, target, targetInst) { // For IE8 and IE9. function getTargetInstForInputEventPolyfill(topLevelType, targetInst) { if ( - topLevelType === 'topSelectionChange' || - topLevelType === 'topKeyUp' || - topLevelType === 'topKeyDown' + topLevelType === TOP_SELECTION_CHANGE || + topLevelType === TOP_KEY_UP || + topLevelType === TOP_KEY_DOWN ) { // On the selectionchange event, the target is just document which isn't // helpful for us so just check activeElement instead. @@ -211,13 +221,13 @@ function shouldUseClickEvent(elem) { } function getTargetInstForClickEvent(topLevelType, targetInst) { - if (topLevelType === 'topClick') { + if (topLevelType === TOP_CLICK) { return getInstIfValueChanged(targetInst); } } function getTargetInstForInputOrChangeEvent(topLevelType, targetInst) { - if (topLevelType === 'topInput' || topLevelType === 'topChange') { + if (topLevelType === TOP_INPUT || topLevelType === TOP_CHANGE) { return getInstIfValueChanged(targetInst); } } @@ -293,7 +303,7 @@ const ChangeEventPlugin = { } // When blurring, set the value attribute for number inputs - if (topLevelType === 'topBlur') { + if (topLevelType === TOP_BLUR) { handleControlledInputBlur(targetInst, targetNode); } }, diff --git a/packages/react-dom/src/events/EnterLeaveEventPlugin.js b/packages/react-dom/src/events/EnterLeaveEventPlugin.js index 9a2be568c10..4841095b69d 100644 --- a/packages/react-dom/src/events/EnterLeaveEventPlugin.js +++ b/packages/react-dom/src/events/EnterLeaveEventPlugin.js @@ -6,6 +6,7 @@ */ import {accumulateEnterLeaveDispatches} from 'events/EventPropagators'; +import {TOP_MOUSE_OUT, TOP_MOUSE_OVER} from 'events/TopLevelEventTypes'; import SyntheticMouseEvent from './SyntheticMouseEvent'; import { @@ -16,11 +17,11 @@ import { const eventTypes = { mouseEnter: { registrationName: 'onMouseEnter', - dependencies: ['topMouseOut', 'topMouseOver'], + dependencies: [TOP_MOUSE_OUT, TOP_MOUSE_OVER], }, mouseLeave: { registrationName: 'onMouseLeave', - dependencies: ['topMouseOut', 'topMouseOver'], + dependencies: [TOP_MOUSE_OUT, TOP_MOUSE_OVER], }, }; @@ -41,12 +42,12 @@ const EnterLeaveEventPlugin = { nativeEventTarget, ) { if ( - topLevelType === 'topMouseOver' && + topLevelType === TOP_MOUSE_OVER && (nativeEvent.relatedTarget || nativeEvent.fromElement) ) { return null; } - if (topLevelType !== 'topMouseOut' && topLevelType !== 'topMouseOver') { + if (topLevelType !== TOP_MOUSE_OUT && topLevelType !== TOP_MOUSE_OVER) { // Must not be a mouse in or mouse out - ignoring. return null; } @@ -67,7 +68,7 @@ const EnterLeaveEventPlugin = { let from; let to; - if (topLevelType === 'topMouseOut') { + if (topLevelType === TOP_MOUSE_OUT) { from = targetInst; const related = nativeEvent.relatedTarget || nativeEvent.toElement; to = related ? getClosestInstanceFromNode(related) : null; diff --git a/packages/react-dom/src/events/ReactBrowserEventEmitter.js b/packages/react-dom/src/events/ReactBrowserEventEmitter.js index a9181b3fe9f..749a42bdc7a 100644 --- a/packages/react-dom/src/events/ReactBrowserEventEmitter.js +++ b/packages/react-dom/src/events/ReactBrowserEventEmitter.js @@ -6,6 +6,13 @@ */ import {registrationNameDependencies} from 'events/EventPluginRegistry'; +import { + TOP_BLUR, + TOP_CANCEL, + TOP_CLOSE, + TOP_FOCUS, + TOP_SCROLL, +} from 'events/TopLevelEventTypes'; import { setEnabled, @@ -14,12 +21,10 @@ import { trapCapturedEvent, } from './ReactDOMEventListener'; import isEventSupported from './isEventSupported'; -import BrowserEventConstants from './BrowserEventConstants'; +import {getRawEventName} from './BrowserEventConstants'; export * from 'events/ReactEventEmitterMixin'; -const {topLevelTypes} = BrowserEventConstants; - /** * Summary of `ReactBrowserEventEmitter` event handling: * @@ -122,28 +127,29 @@ export function listenTo(registrationName, contentDocumentHandle) { for (let i = 0; i < dependencies.length; i++) { const dependency = dependencies[i]; + let rawName = null; if (!(isListening.hasOwnProperty(dependency) && isListening[dependency])) { - if (dependency === 'topScroll') { - trapCapturedEvent('topScroll', 'scroll', mountAt); - } else if (dependency === 'topFocus' || dependency === 'topBlur') { - trapCapturedEvent('topFocus', 'focus', mountAt); - trapCapturedEvent('topBlur', 'blur', mountAt); + if (dependency === TOP_SCROLL) { + trapCapturedEvent(TOP_SCROLL, 'scroll', mountAt); + } else if (dependency === TOP_FOCUS || dependency === TOP_BLUR) { + trapCapturedEvent(TOP_FOCUS, 'focus', mountAt); + trapCapturedEvent(TOP_BLUR, 'blur', mountAt); // to make sure blur and focus event listeners are only attached once isListening.topBlur = true; isListening.topFocus = true; - } else if (dependency === 'topCancel') { + } else if (dependency === TOP_CANCEL) { if (isEventSupported('cancel', true)) { - trapCapturedEvent('topCancel', 'cancel', mountAt); + trapCapturedEvent(TOP_CANCEL, 'cancel', mountAt); } isListening.topCancel = true; - } else if (dependency === 'topClose') { + } else if (dependency === TOP_CLOSE) { if (isEventSupported('close', true)) { - trapCapturedEvent('topClose', 'close', mountAt); + trapCapturedEvent(TOP_CLOSE, 'close', mountAt); } isListening.topClose = true; - } else if (topLevelTypes.hasOwnProperty(dependency)) { - trapBubbledEvent(dependency, topLevelTypes[dependency], mountAt); + } else if ((rawName = getRawEventName(dependency))) { + trapBubbledEvent(dependency, rawName, mountAt); } isListening[dependency] = true; diff --git a/packages/react-dom/src/events/SelectEventPlugin.js b/packages/react-dom/src/events/SelectEventPlugin.js index e6193c7973a..8cbcf4c208d 100644 --- a/packages/react-dom/src/events/SelectEventPlugin.js +++ b/packages/react-dom/src/events/SelectEventPlugin.js @@ -8,6 +8,16 @@ import {accumulateTwoPhaseDispatches} from 'events/EventPropagators'; import ExecutionEnvironment from 'fbjs/lib/ExecutionEnvironment'; import SyntheticEvent from 'events/SyntheticEvent'; +import { + TOP_BLUR, + TOP_CONTEXT_MENU, + TOP_FOCUS, + TOP_KEY_DOWN, + TOP_KEY_UP, + TOP_MOUSE_DOWN, + TOP_MOUSE_UP, + TOP_SELECTION_CHANGE, +} from 'events/TopLevelEventTypes'; import isTextInputElement from 'shared/isTextInputElement'; import getActiveElement from 'fbjs/lib/getActiveElement'; import shallowEqual from 'fbjs/lib/shallowEqual'; @@ -29,14 +39,14 @@ const eventTypes = { captured: 'onSelectCapture', }, dependencies: [ - 'topBlur', - 'topContextMenu', - 'topFocus', - 'topKeyDown', - 'topKeyUp', - 'topMouseDown', - 'topMouseUp', - 'topSelectionChange', + TOP_BLUR, + TOP_CONTEXT_MENU, + TOP_FOCUS, + TOP_KEY_DOWN, + TOP_KEY_UP, + TOP_MOUSE_DOWN, + TOP_MOUSE_UP, + TOP_SELECTION_CHANGE, ], }, }; @@ -156,7 +166,7 @@ const SelectEventPlugin = { switch (topLevelType) { // Track the input node that has focus. - case 'topFocus': + case TOP_FOCUS: if ( isTextInputElement(targetNode) || targetNode.contentEditable === 'true' @@ -166,18 +176,18 @@ const SelectEventPlugin = { lastSelection = null; } break; - case 'topBlur': + case TOP_BLUR: activeElement = null; activeElementInst = null; lastSelection = null; break; // Don't fire the event while the user is dragging. This matches the // semantics of the native select event. - case 'topMouseDown': + case TOP_MOUSE_DOWN: mouseDown = true; break; - case 'topContextMenu': - case 'topMouseUp': + case TOP_CONTEXT_MENU: + case TOP_MOUSE_UP: mouseDown = false; return constructSelectEvent(nativeEvent, nativeEventTarget); // Chrome and IE fire non-standard event when selection is changed (and @@ -189,13 +199,13 @@ const SelectEventPlugin = { // keyup, but we check on keydown as well in the case of holding down a // key, when multiple keydown events are fired but only one keyup is. // This is also our approach for IE handling, for the reason above. - case 'topSelectionChange': + case TOP_SELECTION_CHANGE: if (skipSelectionChangeEvent) { break; } // falls through - case 'topKeyDown': - case 'topKeyUp': + case TOP_KEY_DOWN: + case TOP_KEY_UP: return constructSelectEvent(nativeEvent, nativeEventTarget); } diff --git a/packages/react-dom/src/events/SimpleEventPlugin.js b/packages/react-dom/src/events/SimpleEventPlugin.js index a6db694d0a3..8b2f75e468e 100644 --- a/packages/react-dom/src/events/SimpleEventPlugin.js +++ b/packages/react-dom/src/events/SimpleEventPlugin.js @@ -17,6 +17,7 @@ import type {EventTypes, PluginModule} from 'events/PluginModuleType'; import {accumulateTwoPhaseDispatches} from 'events/EventPropagators'; import SyntheticEvent from 'events/SyntheticEvent'; +import * as TopLevelEventTypes from 'events/TopLevelEventTypes'; import warning from 'fbjs/lib/warning'; import SyntheticAnimationEvent from './SyntheticAnimationEvent'; @@ -31,143 +32,123 @@ import SyntheticUIEvent from './SyntheticUIEvent'; import SyntheticWheelEvent from './SyntheticWheelEvent'; import getEventCharCode from './getEventCharCode'; -/** - * Turns - * ['abort', ...] - * into - * eventTypes = { - * 'abort': { - * phasedRegistrationNames: { - * bubbled: 'onAbort', - * captured: 'onAbortCapture', - * }, - * dependencies: ['topAbort'], - * }, - * ... - * }; - * topLevelEventsToDispatchConfig = { - * 'topAbort': { sameConfig } - * }; - */ -const eventTypes: EventTypes = {}; -const topLevelEventsToDispatchConfig: { - [key: TopLevelTypes]: DispatchConfig, -} = {}; -[ - 'abort', - 'animationEnd', - 'animationIteration', - 'animationStart', - 'blur', - 'cancel', - 'canPlay', - 'canPlayThrough', - 'click', - 'close', - 'contextMenu', - 'copy', - 'cut', - 'doubleClick', - 'drag', - 'dragEnd', - 'dragEnter', - 'dragExit', - 'dragLeave', - 'dragOver', - 'dragStart', - 'drop', - 'durationChange', - 'emptied', - 'encrypted', - 'ended', - 'error', - 'focus', - 'input', - 'invalid', - 'keyDown', - 'keyPress', - 'keyUp', - 'load', - 'loadedData', - 'loadedMetadata', - 'loadStart', - 'mouseDown', - 'mouseMove', - 'mouseOut', - 'mouseOver', - 'mouseUp', - 'paste', - 'pause', - 'play', - 'playing', - 'progress', - 'rateChange', - 'reset', - 'scroll', - 'seeked', - 'seeking', - 'stalled', - 'submit', - 'suspend', - 'timeUpdate', - 'toggle', - 'touchCancel', - 'touchEnd', - 'touchMove', - 'touchStart', - 'transitionEnd', - 'volumeChange', - 'waiting', - 'wheel', -].forEach(event => { - const capitalizedEvent = event[0].toUpperCase() + event.slice(1); - const onEvent = 'on' + capitalizedEvent; - const topEvent = 'top' + capitalizedEvent; +const shortTypes = [ + [TopLevelEventTypes.TOP_ABORT, 'onAbort'], + [TopLevelEventTypes.TOP_ANIMATION_END, 'onAnimationEnd'], + [TopLevelEventTypes.TOP_ANIMATION_ITERATION, 'onAnimationIteration'], + [TopLevelEventTypes.TOP_ANIMATION_START, 'onAnimationStart'], + [TopLevelEventTypes.TOP_BLUR, 'onBlur'], + [TopLevelEventTypes.TOP_CANCEL, 'onCancel'], + [TopLevelEventTypes.TOP_CAN_PLAY, 'onCanPlay'], + [TopLevelEventTypes.TOP_CAN_PLAY_THROUGH, 'onCanPlayThrough'], + [TopLevelEventTypes.TOP_CLICK, 'onClick'], + [TopLevelEventTypes.TOP_CLOSE, 'onClose'], + [TopLevelEventTypes.TOP_CONTEXT_MENU, 'onContextMenu'], + [TopLevelEventTypes.TOP_COPY, 'onCopy'], + [TopLevelEventTypes.TOP_CUT, 'onCut'], + [TopLevelEventTypes.TOP_DOUBLE_CLICK, 'onDoubleClick'], + [TopLevelEventTypes.TOP_DRAG, 'onDrag'], + [TopLevelEventTypes.TOP_DRAG_END, 'onDragEnd'], + [TopLevelEventTypes.TOP_DRAG_ENTER, 'onDragEnter'], + [TopLevelEventTypes.TOP_DRAG_EXIT, 'onDragExit'], + [TopLevelEventTypes.TOP_DRAG_LEAVE, 'onDragLeave'], + [TopLevelEventTypes.TOP_DRAG_OVER, 'onDragOver'], + [TopLevelEventTypes.TOP_DRAG_START, 'onDragStart'], + [TopLevelEventTypes.TOP_DROP, 'onDrop'], + [TopLevelEventTypes.TOP_DURATION_CHANGE, 'onDurationChange'], + [TopLevelEventTypes.TOP_EMPTIED, 'onEmptied'], + [TopLevelEventTypes.TOP_ENCRYPTED, 'onEncrypted'], + [TopLevelEventTypes.TOP_ENDED, 'onEnded'], + [TopLevelEventTypes.TOP_ERROR, 'onError'], + [TopLevelEventTypes.TOP_FOCUS, 'onFocus'], + [TopLevelEventTypes.TOP_INPUT, 'onInput'], + [TopLevelEventTypes.TOP_INVALID, 'onInvalid'], + [TopLevelEventTypes.TOP_KEY_DOWN, 'onKeyDown'], + [TopLevelEventTypes.TOP_KEY_PRESS, 'onKeyPress'], + [TopLevelEventTypes.TOP_KEY_UP, 'onKeyUp'], + [TopLevelEventTypes.TOP_LOAD, 'onLoad'], + [TopLevelEventTypes.TOP_LOADED_DATA, 'onLoadedData'], + [TopLevelEventTypes.TOP_LOADED_METADATA, 'onLoadedMetadata'], + [TopLevelEventTypes.TOP_LOAD_START, 'onLoadStart'], + [TopLevelEventTypes.TOP_MOUSE_DOWN, 'onMouseDown'], + [TopLevelEventTypes.TOP_MOUSE_MOVE, 'onMouseMove'], + [TopLevelEventTypes.TOP_MOUSE_OUT, 'onMouseOut'], + [TopLevelEventTypes.TOP_MOUSE_OVER, 'onMouseOver'], + [TopLevelEventTypes.TOP_MOUSE_UP, 'onMouseUp'], + [TopLevelEventTypes.TOP_PASTE, 'onPaste'], + [TopLevelEventTypes.TOP_PAUSE, 'onPause'], + [TopLevelEventTypes.TOP_PLAY, 'onPlay'], + [TopLevelEventTypes.TOP_PLAYING, 'onPlaying'], + [TopLevelEventTypes.TOP_PROGRESS, 'onProgress'], + [TopLevelEventTypes.TOP_RATE_CHANGE, 'onRateChange'], + [TopLevelEventTypes.TOP_RESET, 'onReset'], + [TopLevelEventTypes.TOP_SCROLL, 'onScroll'], + [TopLevelEventTypes.TOP_SEEKED, 'onSeeked'], + [TopLevelEventTypes.TOP_SEEKING, 'onSeeking'], + [TopLevelEventTypes.TOP_STALLED, 'onStalled'], + [TopLevelEventTypes.TOP_SUBMIT, 'onSubmit'], + [TopLevelEventTypes.TOP_SUSPEND, 'onSuspend'], + [TopLevelEventTypes.TOP_TIME_UPDATE, 'onTimeUpdate'], + [TopLevelEventTypes.TOP_TOUCH_CANCEL, 'onTouchCancel'], + [TopLevelEventTypes.TOP_TOUCH_END, 'onTouchEnd'], + [TopLevelEventTypes.TOP_TOUCH_MOVE, 'onTouchMove'], + [TopLevelEventTypes.TOP_TOUCH_START, 'onTouchStart'], + [TopLevelEventTypes.TOP_TRANSITION_END, 'onTransitionEnd'], + [TopLevelEventTypes.TOP_VOLUME_CHANGE, 'onVolumeChange'], + [TopLevelEventTypes.TOP_WAITING, 'onWaiting'], + [TopLevelEventTypes.TOP_WHEEL, 'onWheel'], +]; + +const eventTypes = shortTypes.map(t => ({ + dependencies: [t[0]], + phasedRegistrationNames: { + bubbled: t[1], + captured: t[1] + 'Capture', + }, +})); + +export const topLevelEventsToDispatchConfig = new Map(); - const type = { - phasedRegistrationNames: { - bubbled: onEvent, - captured: onEvent + 'Capture', - }, - dependencies: [topEvent], - }; - eventTypes[event] = type; - topLevelEventsToDispatchConfig[topEvent] = type; -}); +for (let i = 0; i < eventTypes.length; i++) { + topLevelEventsToDispatchConfig.set( + eventTypes[i].dependencies[0], + eventTypes[i], + ); +} // Only used in DEV for exhaustiveness validation. const knownHTMLTopLevelTypes = [ - 'topAbort', - 'topCancel', - 'topCanPlay', - 'topCanPlayThrough', - 'topClose', - 'topDurationChange', - 'topEmptied', - 'topEncrypted', - 'topEnded', - 'topError', - 'topInput', - 'topInvalid', - 'topLoad', - 'topLoadedData', - 'topLoadedMetadata', - 'topLoadStart', - 'topPause', - 'topPlay', - 'topPlaying', - 'topProgress', - 'topRateChange', - 'topReset', - 'topSeeked', - 'topSeeking', - 'topStalled', - 'topSubmit', - 'topSuspend', - 'topTimeUpdate', - 'topToggle', - 'topVolumeChange', - 'topWaiting', + TopLevelEventTypes.TOP_ABORT, + TopLevelEventTypes.TOP_CANCEL, + TopLevelEventTypes.TOP_CAN_PLAY, + TopLevelEventTypes.TOP_CAN_PLAY_THROUGH, + TopLevelEventTypes.TOP_CLOSE, + TopLevelEventTypes.TOP_DURATION_CHANGE, + TopLevelEventTypes.TOP_EMPTIED, + TopLevelEventTypes.TOP_ENCRYPTED, + TopLevelEventTypes.TOP_ENDED, + TopLevelEventTypes.TOP_ERROR, + TopLevelEventTypes.TOP_INPUT, + TopLevelEventTypes.TOP_INVALID, + TopLevelEventTypes.TOP_LOAD, + TopLevelEventTypes.TOP_LOADED_DATA, + TopLevelEventTypes.TOP_LOADED_METADATA, + TopLevelEventTypes.TOP_LOAD_START, + TopLevelEventTypes.TOP_PAUSE, + TopLevelEventTypes.TOP_PLAY, + TopLevelEventTypes.TOP_PLAYING, + TopLevelEventTypes.TOP_PROGRESS, + TopLevelEventTypes.TOP_RATE_CHANGE, + TopLevelEventTypes.TOP_RESET, + TopLevelEventTypes.TOP_SEEKED, + TopLevelEventTypes.TOP_SEEKING, + TopLevelEventTypes.TOP_STALLED, + TopLevelEventTypes.TOP_SUBMIT, + TopLevelEventTypes.TOP_SUSPEND, + TopLevelEventTypes.TOP_TIME_UPDATE, + TopLevelEventTypes.TOP_TOGGLE, + TopLevelEventTypes.TOP_VOLUME_CHANGE, + TopLevelEventTypes.TOP_WAITING, ]; const SimpleEventPlugin: PluginModule = { @@ -179,13 +160,13 @@ const SimpleEventPlugin: PluginModule = { nativeEvent: MouseEvent, nativeEventTarget: EventTarget, ): null | ReactSyntheticEvent { - const dispatchConfig = topLevelEventsToDispatchConfig[topLevelType]; + const dispatchConfig = topLevelEventsToDispatchConfig.get(topLevelType); if (!dispatchConfig) { return null; } let EventConstructor; switch (topLevelType) { - case 'topKeyPress': + case TopLevelEventTypes.TOP_KEY_PRESS: // Firefox creates a keypress event for function keys too. This removes // the unwanted keypress events. Enter is however both printable and // non-printable. One would expect Tab to be as well (but it isn't). @@ -193,65 +174,65 @@ const SimpleEventPlugin: PluginModule = { return null; } /* falls through */ - case 'topKeyDown': - case 'topKeyUp': + case TopLevelEventTypes.TOP_KEY_DOWN: + case TopLevelEventTypes.TOP_KEY_UP: EventConstructor = SyntheticKeyboardEvent; break; - case 'topBlur': - case 'topFocus': + case TopLevelEventTypes.TOP_BLUR: + case TopLevelEventTypes.TOP_FOCUS: EventConstructor = SyntheticFocusEvent; break; - case 'topClick': + case TopLevelEventTypes.TOP_CLICK: // Firefox creates a click event on right mouse clicks. This removes the // unwanted click events. if (nativeEvent.button === 2) { return null; } /* falls through */ - case 'topDoubleClick': - case 'topMouseDown': - case 'topMouseMove': - case 'topMouseUp': + case TopLevelEventTypes.TOP_DOUBLE_CLICK: + case TopLevelEventTypes.TOP_MOUSE_DOWN: + case TopLevelEventTypes.TOP_MOUSE_MOVE: + case TopLevelEventTypes.TOP_MOUSE_UP: // TODO: Disabled elements should not respond to mouse events /* falls through */ - case 'topMouseOut': - case 'topMouseOver': - case 'topContextMenu': + case TopLevelEventTypes.TOP_MOUSE_OUT: + case TopLevelEventTypes.TOP_MOUSE_OVER: + case TopLevelEventTypes.TOP_CONTEXT_MENU: EventConstructor = SyntheticMouseEvent; break; - case 'topDrag': - case 'topDragEnd': - case 'topDragEnter': - case 'topDragExit': - case 'topDragLeave': - case 'topDragOver': - case 'topDragStart': - case 'topDrop': + case TopLevelEventTypes.TOP_DRAG: + case TopLevelEventTypes.TOP_DRAG_END: + case TopLevelEventTypes.TOP_DRAG_ENTER: + case TopLevelEventTypes.TOP_DRAG_EXIT: + case TopLevelEventTypes.TOP_DRAG_LEAVE: + case TopLevelEventTypes.TOP_DRAG_OVER: + case TopLevelEventTypes.TOP_DRAG_START: + case TopLevelEventTypes.TOP_DROP: EventConstructor = SyntheticDragEvent; break; - case 'topTouchCancel': - case 'topTouchEnd': - case 'topTouchMove': - case 'topTouchStart': + case TopLevelEventTypes.TOP_TOUCH_CANCEL: + case TopLevelEventTypes.TOP_TOUCH_END: + case TopLevelEventTypes.TOP_TOUCH_MOVE: + case TopLevelEventTypes.TOP_TOUCH_START: EventConstructor = SyntheticTouchEvent; break; - case 'topAnimationEnd': - case 'topAnimationIteration': - case 'topAnimationStart': + case TopLevelEventTypes.TOP_ANIMATION_END: + case TopLevelEventTypes.TOP_ANIMATION_ITERATION: + case TopLevelEventTypes.TOP_ANIMATION_START: EventConstructor = SyntheticAnimationEvent; break; - case 'topTransitionEnd': + case TopLevelEventTypes.TOP_TRANSITION_END: EventConstructor = SyntheticTransitionEvent; break; - case 'topScroll': + case TopLevelEventTypes.TOP_SCROLL: EventConstructor = SyntheticUIEvent; break; - case 'topWheel': + case TopLevelEventTypes.TOP_WHEEL: EventConstructor = SyntheticWheelEvent; break; - case 'topCopy': - case 'topCut': - case 'topPaste': + case TopLevelEventTypes.TOP_COPY: + case TopLevelEventTypes.TOP_CUT: + case TopLevelEventTypes.TOP_PASTE: EventConstructor = SyntheticClipboardEvent; break; default: diff --git a/packages/react-dom/src/events/TapEventPlugin.js b/packages/react-dom/src/events/TapEventPlugin.js index e1e67a5d70e..7b5f7891d6a 100644 --- a/packages/react-dom/src/events/TapEventPlugin.js +++ b/packages/react-dom/src/events/TapEventPlugin.js @@ -9,6 +9,15 @@ import {isStartish, isEndish} from 'events/EventPluginUtils'; import {accumulateTwoPhaseDispatches} from 'events/EventPropagators'; +import { + TOP_MOUSE_DOWN, + TOP_MOUSE_MOVE, + TOP_MOUSE_UP, + TOP_TOUCH_CANCEL, + TOP_TOUCH_END, + TOP_TOUCH_MOVE, + TOP_TOUCH_START, +} from 'events/TopLevelEventTypes'; import TouchEventUtils from 'fbjs/lib/TouchEventUtils'; import SyntheticUIEvent from './SyntheticUIEvent'; @@ -75,13 +84,13 @@ function getDistance(coords: CoordinatesType, nativeEvent: _Touch): number { } const touchEvents = [ - 'topTouchStart', - 'topTouchCancel', - 'topTouchEnd', - 'topTouchMove', + TOP_TOUCH_START, + TOP_TOUCH_CANCEL, + TOP_TOUCH_END, + TOP_TOUCH_MOVE, ]; -const dependencies = ['topMouseDown', 'topMouseMove', 'topMouseUp'].concat( +const dependencies = [TOP_MOUSE_DOWN, TOP_MOUSE_MOVE, TOP_MOUSE_UP].concat( touchEvents, ); diff --git a/packages/react-native-renderer/src/ReactNativeEventEmitter.js b/packages/react-native-renderer/src/ReactNativeEventEmitter.js index c978f4e14ac..c215d25ab26 100644 --- a/packages/react-native-renderer/src/ReactNativeEventEmitter.js +++ b/packages/react-native-renderer/src/ReactNativeEventEmitter.js @@ -11,6 +11,7 @@ import {getListener} from 'events/EventPluginHub'; import {registrationNameModules} from 'events/EventPluginRegistry'; import {batchedUpdates} from 'events/ReactGenericBatching'; import {handleTopLevel} from 'events/ReactEventEmitterMixin'; +import {TOP_TOUCH_CANCEL, TOP_TOUCH_END} from 'events/TopLevelEventTypes'; import warning from 'fbjs/lib/warning'; import {getInstanceFromNode} from './ReactNativeComponentTree'; @@ -146,8 +147,8 @@ export function receiveTouches( changedIndices: Array, ) { const changedTouches = - eventTopLevelType === 'topTouchEnd' || - eventTopLevelType === 'topTouchCancel' + eventTopLevelType === TOP_TOUCH_END || + eventTopLevelType === TOP_TOUCH_CANCEL ? removeTouchesAtIndices(touches, changedIndices) : touchSubsequence(touches, changedIndices); diff --git a/scripts/rollup/results.json b/scripts/rollup/results.json index 02006ce3fb8..42311a0d790 100644 --- a/scripts/rollup/results.json +++ b/scripts/rollup/results.json @@ -29,8 +29,8 @@ "gzip": 132774 }, "react-dom.production.min.js (UMD_PROD)": { - "size": 93699, - "gzip": 30755 + "size": 91054, + "gzip": 30230 }, "react-dom.development.js (NODE_DEV)": { "size": 544502,