From 634bd74e5b4b2db15c73bcd4a7d67b0114da1b2f Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Wed, 20 Dec 2017 05:09:06 +0000 Subject: [PATCH 1/6] Record sizes --- scripts/rollup/results.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/rollup/results.json b/scripts/rollup/results.json index 02006ce3fb8..4b39192ea91 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": 93733, + "gzip": 30766 }, "react-dom.development.js (NODE_DEV)": { "size": 544502, From c83e0469ffecb39f76dce3ed59a22a69d6b526d4 Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Wed, 20 Dec 2017 05:17:11 +0000 Subject: [PATCH 2/6] Unroll SimpleEventPlugin This undoes #7616 --- .../react-dom/src/events/SimpleEventPlugin.js | 556 ++++++++++++++---- 1 file changed, 456 insertions(+), 100 deletions(-) diff --git a/packages/react-dom/src/events/SimpleEventPlugin.js b/packages/react-dom/src/events/SimpleEventPlugin.js index a6db694d0a3..1986fb8040c 100644 --- a/packages/react-dom/src/events/SimpleEventPlugin.js +++ b/packages/react-dom/src/events/SimpleEventPlugin.js @@ -31,109 +31,465 @@ 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 eventTypes: EventTypes = { + abort: { + phasedRegistrationNames: { + bubbled: 'onAbort', + captured: 'onAbortCapture', + }, + }, + animationEnd: { + phasedRegistrationNames: { + bubbled: 'onAnimationEnd', + captured: 'onAnimationEndCapture', + }, + }, + animationIteration: { + phasedRegistrationNames: { + bubbled: 'onAnimationIteration', + captured: 'onAnimationIterationCapture', + }, + }, + animationStart: { + phasedRegistrationNames: { + bubbled: 'onAnimationStart', + captured: 'onAnimationStartCapture', + }, + }, + blur: { + phasedRegistrationNames: { + bubbled: 'onBlur', + captured: 'onBlurCapture', + }, + }, + cancel: { + phasedRegistrationNames: { + bubbled: 'onCancel', + captured: 'onCancelCapture', + }, + }, + canPlay: { + phasedRegistrationNames: { + bubbled: 'onCanPlay', + captured: 'onCanPlayCapture', + }, + }, + canPlayThrough: { + phasedRegistrationNames: { + bubbled: 'onCanPlayThrough', + captured: 'onCanPlayThroughCapture', + }, + }, + click: { + phasedRegistrationNames: { + bubbled: 'onClick', + captured: 'onClickCapture', + }, + }, + close: { + phasedRegistrationNames: { + bubbled: 'onClose', + captured: 'onCloseCapture', + }, + }, + contextMenu: { + phasedRegistrationNames: { + bubbled: 'onContextMenu', + captured: 'onContextMenuCapture', + }, + }, + copy: { + phasedRegistrationNames: { + bubbled: 'onCopy', + captured: 'onCopyCapture', + }, + }, + cut: { + phasedRegistrationNames: { + bubbled: 'onCut', + captured: 'onCutCapture', + }, + }, + doubleClick: { + phasedRegistrationNames: { + bubbled: 'onDoubleClick', + captured: 'onDoubleClickCapture', + }, + }, + drag: { + phasedRegistrationNames: { + bubbled: 'onDrag', + captured: 'onDragCapture', + }, + }, + dragEnd: { + phasedRegistrationNames: { + bubbled: 'onDragEnd', + captured: 'onDragEndCapture', + }, + }, + dragEnter: { + phasedRegistrationNames: { + bubbled: 'onDragEnter', + captured: 'onDragEnterCapture', + }, + }, + dragExit: { + phasedRegistrationNames: { + bubbled: 'onDragExit', + captured: 'onDragExitCapture', + }, + }, + dragLeave: { + phasedRegistrationNames: { + bubbled: 'onDragLeave', + captured: 'onDragLeaveCapture', + }, + }, + dragOver: { + phasedRegistrationNames: { + bubbled: 'onDragOver', + captured: 'onDragOverCapture', + }, + }, + dragStart: { + phasedRegistrationNames: { + bubbled: 'onDragStart', + captured: 'onDragStartCapture', + }, + }, + drop: { + phasedRegistrationNames: { + bubbled: 'onDrop', + captured: 'onDropCapture', + }, + }, + durationChange: { + phasedRegistrationNames: { + bubbled: 'onDurationChange', + captured: 'onDurationChangeCapture', + }, + }, + emptied: { + phasedRegistrationNames: { + bubbled: 'onEmptied', + captured: 'onEmptiedCapture', + }, + }, + encrypted: { + phasedRegistrationNames: { + bubbled: 'onEncrypted', + captured: 'onEncryptedCapture', + }, + }, + ended: { + phasedRegistrationNames: { + bubbled: 'onEnded', + captured: 'onEndedCapture', + }, + }, + error: { + phasedRegistrationNames: { + bubbled: 'onError', + captured: 'onErrorCapture', + }, + }, + focus: { + phasedRegistrationNames: { + bubbled: 'onFocus', + captured: 'onFocusCapture', + }, + }, + input: { + phasedRegistrationNames: { + bubbled: 'onInput', + captured: 'onInputCapture', + }, + }, + invalid: { + phasedRegistrationNames: { + bubbled: 'onInvalid', + captured: 'onInvalidCapture', + }, + }, + keyDown: { + phasedRegistrationNames: { + bubbled: 'onKeyDown', + captured: 'onKeyDownCapture', + }, + }, + keyPress: { + phasedRegistrationNames: { + bubbled: 'onKeyPress', + captured: 'onKeyPressCapture', + }, + }, + keyUp: { + phasedRegistrationNames: { + bubbled: 'onKeyUp', + captured: 'onKeyUpCapture', + }, + }, + load: { + phasedRegistrationNames: { + bubbled: 'onLoad', + captured: 'onLoadCapture', + }, + }, + loadedData: { + phasedRegistrationNames: { + bubbled: 'onLoadedData', + captured: 'onLoadedDataCapture', + }, + }, + loadedMetadata: { + phasedRegistrationNames: { + bubbled: 'onLoadedMetadata', + captured: 'onLoadedMetadataCapture', + }, + }, + loadStart: { + phasedRegistrationNames: { + bubbled: 'onLoadStart', + captured: 'onLoadStartCapture', + }, + }, + mouseDown: { + phasedRegistrationNames: { + bubbled: 'onMouseDown', + captured: 'onMouseDownCapture', + }, + }, + mouseMove: { + phasedRegistrationNames: { + bubbled: 'onMouseMove', + captured: 'onMouseMoveCapture', + }, + }, + mouseOut: { + phasedRegistrationNames: { + bubbled: 'onMouseOut', + captured: 'onMouseOutCapture', + }, + }, + mouseOver: { + phasedRegistrationNames: { + bubbled: 'onMouseOver', + captured: 'onMouseOverCapture', + }, + }, + mouseUp: { + phasedRegistrationNames: { + bubbled: 'onMouseUp', + captured: 'onMouseUpCapture', + }, + }, + paste: { + phasedRegistrationNames: { + bubbled: 'onPaste', + captured: 'onPasteCapture', + }, + }, + pause: { + phasedRegistrationNames: { + bubbled: 'onPause', + captured: 'onPauseCapture', + }, + }, + play: { + phasedRegistrationNames: { + bubbled: 'onPlay', + captured: 'onPlayCapture', + }, + }, + playing: { + phasedRegistrationNames: { + bubbled: 'onPlaying', + captured: 'onPlayingCapture', + }, + }, + progress: { + phasedRegistrationNames: { + bubbled: 'onProgress', + captured: 'onProgressCapture', + }, + }, + rateChange: { + phasedRegistrationNames: { + bubbled: 'onRateChange', + captured: 'onRateChangeCapture', + }, + }, + reset: { + phasedRegistrationNames: { + bubbled: 'onReset', + captured: 'onResetCapture', + }, + }, + scroll: { + phasedRegistrationNames: { + bubbled: 'onScroll', + captured: 'onScrollCapture', + }, + }, + seeked: { + phasedRegistrationNames: { + bubbled: 'onSeeked', + captured: 'onSeekedCapture', + }, + }, + seeking: { + phasedRegistrationNames: { + bubbled: 'onSeeking', + captured: 'onSeekingCapture', + }, + }, + stalled: { + phasedRegistrationNames: { + bubbled: 'onStalled', + captured: 'onStalledCapture', + }, + }, + submit: { + phasedRegistrationNames: { + bubbled: 'onSubmit', + captured: 'onSubmitCapture', + }, + }, + suspend: { + phasedRegistrationNames: { + bubbled: 'onSuspend', + captured: 'onSuspendCapture', + }, + }, + timeUpdate: { + phasedRegistrationNames: { + bubbled: 'onTimeUpdate', + captured: 'onTimeUpdateCapture', + }, + }, + touchCancel: { + phasedRegistrationNames: { + bubbled: 'onTouchCancel', + captured: 'onTouchCancelCapture', + }, + }, + touchEnd: { + phasedRegistrationNames: { + bubbled: 'onTouchEnd', + captured: 'onTouchEndCapture', + }, + }, + touchMove: { + phasedRegistrationNames: { + bubbled: 'onTouchMove', + captured: 'onTouchMoveCapture', + }, + }, + touchStart: { + phasedRegistrationNames: { + bubbled: 'onTouchStart', + captured: 'onTouchStartCapture', + }, + }, + transitionEnd: { + phasedRegistrationNames: { + bubbled: 'onTransitionEnd', + captured: 'onTransitionEndCapture', + }, + }, + volumeChange: { + phasedRegistrationNames: { + bubbled: 'onVolumeChange', + captured: 'onVolumeChangeCapture', + }, + }, + waiting: { + phasedRegistrationNames: { + bubbled: 'onWaiting', + captured: 'onWaitingCapture', + }, + }, + wheel: { + phasedRegistrationNames: { + bubbled: 'onWheel', + captured: 'onWheelCapture', + }, + }, +}; + 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; +} = { + topAbort: eventTypes.abort, + topAnimationEnd: eventTypes.animationEnd, + topAnimationIteration: eventTypes.animationIteration, + topAnimationStart: eventTypes.animationStart, + topBlur: eventTypes.blur, + topCancel: eventTypes.cancel, + topCanPlay: eventTypes.canPlay, + topCanPlayThrough: eventTypes.canPlayThrough, + topClick: eventTypes.click, + topClose: eventTypes.close, + topContextMenu: eventTypes.contextMenu, + topCopy: eventTypes.copy, + topCut: eventTypes.cut, + topDoubleClick: eventTypes.doubleClick, + topDrag: eventTypes.drag, + topDragEnd: eventTypes.dragEnd, + topDragEnter: eventTypes.dragEnter, + topDragExit: eventTypes.dragExit, + topDragLeave: eventTypes.dragLeave, + topDragOver: eventTypes.dragOver, + topDragStart: eventTypes.dragStart, + topDrop: eventTypes.drop, + topDurationChange: eventTypes.durationChange, + topEmptied: eventTypes.emptied, + topEncrypted: eventTypes.encrypted, + topEnded: eventTypes.ended, + topError: eventTypes.error, + topFocus: eventTypes.focus, + topInput: eventTypes.input, + topInvalid: eventTypes.invalid, + topKeyDown: eventTypes.keyDown, + topKeyPress: eventTypes.keyPress, + topKeyUp: eventTypes.keyUp, + topLoad: eventTypes.load, + topLoadedData: eventTypes.loadedData, + topLoadedMetadata: eventTypes.loadedMetadata, + topLoadStart: eventTypes.loadStart, + topMouseDown: eventTypes.mouseDown, + topMouseMove: eventTypes.mouseMove, + topMouseOut: eventTypes.mouseOut, + topMouseOver: eventTypes.mouseOver, + topMouseUp: eventTypes.mouseUp, + topPaste: eventTypes.paste, + topPause: eventTypes.pause, + topPlay: eventTypes.play, + topPlaying: eventTypes.playing, + topProgress: eventTypes.progress, + topRateChange: eventTypes.rateChange, + topReset: eventTypes.reset, + topScroll: eventTypes.scroll, + topSeeked: eventTypes.seeked, + topSeeking: eventTypes.seeking, + topStalled: eventTypes.stalled, + topSubmit: eventTypes.submit, + topSuspend: eventTypes.suspend, + topTimeUpdate: eventTypes.timeUpdate, + topTouchCancel: eventTypes.touchCancel, + topTouchEnd: eventTypes.touchEnd, + topTouchMove: eventTypes.touchMove, + topTouchStart: eventTypes.touchStart, + topTransitionEnd: eventTypes.transitionEnd, + topVolumeChange: eventTypes.volumeChange, + topWaiting: eventTypes.waiting, + topWheel: eventTypes.wheel, +}; - const type = { - phasedRegistrationNames: { - bubbled: onEvent, - captured: onEvent + 'Capture', - }, - dependencies: [topEvent], - }; - eventTypes[event] = type; - topLevelEventsToDispatchConfig[topEvent] = type; -}); +for (var type in topLevelEventsToDispatchConfig) { + topLevelEventsToDispatchConfig[type].dependencies = [type]; +} // Only used in DEV for exhaustiveness validation. const knownHTMLTopLevelTypes = [ From 12b12083e7ff28f540cb6766bd3f08170221a147 Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Wed, 20 Dec 2017 05:18:50 +0000 Subject: [PATCH 3/6] Record sizes --- scripts/rollup/results.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/rollup/results.json b/scripts/rollup/results.json index 4b39192ea91..a7fb4ea9ad8 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": 93733, - "gzip": 30766 + "size": 100015, + "gzip": 31871 }, "react-dom.development.js (NODE_DEV)": { "size": 544502, From 118464d834bfd85e99913543c7c3368540d95f02 Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Wed, 20 Dec 2017 07:19:04 +0000 Subject: [PATCH 4/6] Use numbers for topLevelTypes --- packages/events/EventPluginUtils.js | 20 +- packages/events/ResponderEventPlugin.js | 13 +- packages/events/TopLevelEventTypes.js | 80 ++++ .../src/client/ReactDOMFiberComponent.js | 141 +++--- .../src/events/BeforeInputEventPlugin.js | 88 ++-- .../src/events/BrowserEventConstants.js | 150 ++++--- .../react-dom/src/events/ChangeEventPlugin.js | 44 +- .../src/events/EnterLeaveEventPlugin.js | 11 +- .../src/events/ReactBrowserEventEmitter.js | 29 +- .../react-dom/src/events/SelectEventPlugin.js | 42 +- .../react-dom/src/events/SimpleEventPlugin.js | 405 +++++++++--------- .../react-dom/src/events/TapEventPlugin.js | 19 +- .../src/ReactNativeEventEmitter.js | 5 +- scripts/rollup/results.json | 4 +- 14 files changed, 621 insertions(+), 430 deletions(-) create mode 100644 packages/events/TopLevelEventTypes.js 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..1a71e9f96f8 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 BrowserEventConstants 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,44 @@ 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, + BrowserEventConstants.topLevelTypes[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 +545,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 +553,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 +875,37 @@ 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, + BrowserEventConstants.topLevelTypes[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 +915,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..12fbf5f62d1 100644 --- a/packages/react-dom/src/events/BrowserEventConstants.js +++ b/packages/react-dom/src/events/BrowserEventConstants.js @@ -6,6 +6,7 @@ */ import getVendorPrefixedEventName from './getVendorPrefixedEventName'; +import * as TopLevelEventTypes from 'events/TopLevelEventTypes'; /** * Types of raw signals from the browser caught at the top level. @@ -14,79 +15,88 @@ 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 topLevelTypes = 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_BLUR, 'blur'], + [TopLevelEventTypes.TOP_CANCEL, 'cancel'], + [TopLevelEventTypes.TOP_CAN_PLAY, 'canplay'], + [TopLevelEventTypes.TOP_CAN_PLAY_THROUGH, 'canplaythrough'], + [TopLevelEventTypes.TOP_CHANGE, 'change'], + [TopLevelEventTypes.TOP_CLICK, 'click'], + [TopLevelEventTypes.TOP_CLOSE, 'close'], + [TopLevelEventTypes.TOP_COMPOSITION_END, 'compositionend'], + [TopLevelEventTypes.TOP_COMPOSITION_START, 'compositionstart'], + [TopLevelEventTypes.TOP_COMPOSITION_UPDATE, 'compositionupdate'], + [TopLevelEventTypes.TOP_CONTEXT_MENU, 'contextmenu'], + [TopLevelEventTypes.TOP_COPY, 'copy'], + [TopLevelEventTypes.TOP_CUT, 'cut'], + [TopLevelEventTypes.TOP_DOUBLE_CLICK, 'dblclick'], + [TopLevelEventTypes.TOP_DRAG, 'drag'], + [TopLevelEventTypes.TOP_DRAG_END, 'dragend'], + [TopLevelEventTypes.TOP_DRAG_ENTER, 'dragenter'], + [TopLevelEventTypes.TOP_DRAG_EXIT, 'dragexit'], + [TopLevelEventTypes.TOP_DRAG_LEAVE, 'dragleave'], + [TopLevelEventTypes.TOP_DRAG_OVER, 'dragover'], + [TopLevelEventTypes.TOP_DRAG_START, 'dragstart'], + [TopLevelEventTypes.TOP_DROP, 'drop'], + [TopLevelEventTypes.TOP_DURATION_CHANGE, 'durationchange'], + [TopLevelEventTypes.TOP_EMPTIED, 'emptied'], + [TopLevelEventTypes.TOP_ENCRYPTED, 'encrypted'], + [TopLevelEventTypes.TOP_ENDED, 'ended'], + [TopLevelEventTypes.TOP_ERROR, 'error'], + [TopLevelEventTypes.TOP_FOCUS, 'focus'], + [TopLevelEventTypes.TOP_INPUT, 'input'], + [TopLevelEventTypes.TOP_KEY_DOWN, 'keydown'], + [TopLevelEventTypes.TOP_KEY_PRESS, 'keypress'], + [TopLevelEventTypes.TOP_KEY_UP, 'keyup'], + [TopLevelEventTypes.TOP_LOADED_DATA, 'loadeddata'], + [TopLevelEventTypes.TOP_LOAD, 'load'], + [TopLevelEventTypes.TOP_LOADED_METADATA, 'loadedmetadata'], + [TopLevelEventTypes.TOP_LOAD_START, 'loadstart'], + [TopLevelEventTypes.TOP_MOUSE_DOWN, 'mousedown'], + [TopLevelEventTypes.TOP_MOUSE_MOVE, 'mousemove'], + [TopLevelEventTypes.TOP_MOUSE_OUT, 'mouseout'], + [TopLevelEventTypes.TOP_MOUSE_OVER, 'mouseover'], + [TopLevelEventTypes.TOP_MOUSE_UP, 'mouseup'], + [TopLevelEventTypes.TOP_PASTE, 'paste'], + [TopLevelEventTypes.TOP_PAUSE, 'pause'], + [TopLevelEventTypes.TOP_PLAY, 'play'], + [TopLevelEventTypes.TOP_PLAYING, 'playing'], + [TopLevelEventTypes.TOP_PROGRESS, 'progress'], + [TopLevelEventTypes.TOP_RATE_CHANGE, 'ratechange'], + [TopLevelEventTypes.TOP_SCROLL, 'scroll'], + [TopLevelEventTypes.TOP_SEEKED, 'seeked'], + [TopLevelEventTypes.TOP_SEEKING, 'seeking'], + [TopLevelEventTypes.TOP_SELECTION_CHANGE, 'selectionchange'], + [TopLevelEventTypes.TOP_STALLED, 'stalled'], + [TopLevelEventTypes.TOP_SUSPEND, 'suspend'], + [TopLevelEventTypes.TOP_TEXT_INPUT, 'textInput'], + [TopLevelEventTypes.TOP_TIME_UPDATE, 'timeupdate'], + [TopLevelEventTypes.TOP_TOGGLE, 'toggle'], + [TopLevelEventTypes.TOP_TOUCH_CANCEL, 'touchcancel'], + [TopLevelEventTypes.TOP_TOUCH_END, 'touchend'], + [TopLevelEventTypes.TOP_TOUCH_MOVE, 'touchmove'], + [TopLevelEventTypes.TOP_TOUCH_START, 'touchstart'], + [ + TopLevelEventTypes.TOP_TRANSITION_END, getVendorPrefixedEventName('transitionend') || 'transitionend', - topVolumeChange: 'volumechange', - topWaiting: 'waiting', - topWheel: 'wheel', -}; + ], + [TopLevelEventTypes.TOP_VOLUME_CHANGE, 'volumechange'], + [TopLevelEventTypes.TOP_WAITING, 'waiting'], + [TopLevelEventTypes.TOP_WHEEL, 'wheel'], +]); 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..f10469d7af0 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, @@ -123,27 +130,27 @@ export function listenTo(registrationName, contentDocumentHandle) { for (let i = 0; i < dependencies.length; i++) { const dependency = dependencies[i]; 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 (topLevelTypes.has(dependency)) { + trapBubbledEvent(dependency, topLevelTypes.get(dependency), 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 1986fb8040c..1bdeec6979e 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,499 +32,499 @@ import SyntheticUIEvent from './SyntheticUIEvent'; import SyntheticWheelEvent from './SyntheticWheelEvent'; import getEventCharCode from './getEventCharCode'; -const eventTypes: EventTypes = { - abort: { +const eventTypes: EventTypes = [ + { + dependencies: [TopLevelEventTypes.TOP_ABORT], phasedRegistrationNames: { bubbled: 'onAbort', captured: 'onAbortCapture', }, }, - animationEnd: { + { + dependencies: [TopLevelEventTypes.TOP_ANIMATION_END], phasedRegistrationNames: { bubbled: 'onAnimationEnd', captured: 'onAnimationEndCapture', }, }, - animationIteration: { + { + dependencies: [TopLevelEventTypes.TOP_ANIMATION_ITERATION], phasedRegistrationNames: { bubbled: 'onAnimationIteration', captured: 'onAnimationIterationCapture', }, }, - animationStart: { + { + dependencies: [TopLevelEventTypes.TOP_ANIMATION_START], phasedRegistrationNames: { bubbled: 'onAnimationStart', captured: 'onAnimationStartCapture', }, }, - blur: { + { + dependencies: [TopLevelEventTypes.TOP_BLUR], phasedRegistrationNames: { bubbled: 'onBlur', captured: 'onBlurCapture', }, }, - cancel: { + { + dependencies: [TopLevelEventTypes.TOP_CANCEL], phasedRegistrationNames: { bubbled: 'onCancel', captured: 'onCancelCapture', }, }, - canPlay: { + { + dependencies: [TopLevelEventTypes.TOP_CAN_PLAY], phasedRegistrationNames: { bubbled: 'onCanPlay', captured: 'onCanPlayCapture', }, }, - canPlayThrough: { + { + dependencies: [TopLevelEventTypes.TOP_CAN_PLAY_THROUGH], phasedRegistrationNames: { bubbled: 'onCanPlayThrough', captured: 'onCanPlayThroughCapture', }, }, - click: { + { + dependencies: [TopLevelEventTypes.TOP_CLICK], phasedRegistrationNames: { bubbled: 'onClick', captured: 'onClickCapture', }, }, - close: { + { + dependencies: [TopLevelEventTypes.TOP_CLOSE], phasedRegistrationNames: { bubbled: 'onClose', captured: 'onCloseCapture', }, }, - contextMenu: { + { + dependencies: [TopLevelEventTypes.TOP_CONTEXT_MENU], phasedRegistrationNames: { bubbled: 'onContextMenu', captured: 'onContextMenuCapture', }, }, - copy: { + { + dependencies: [TopLevelEventTypes.TOP_COPY], phasedRegistrationNames: { bubbled: 'onCopy', captured: 'onCopyCapture', }, }, - cut: { + { + dependencies: [TopLevelEventTypes.TOP_CUT], phasedRegistrationNames: { bubbled: 'onCut', captured: 'onCutCapture', }, }, - doubleClick: { + { + dependencies: [TopLevelEventTypes.TOP_DOUBLE_CLICK], phasedRegistrationNames: { bubbled: 'onDoubleClick', captured: 'onDoubleClickCapture', }, }, - drag: { + { + dependencies: [TopLevelEventTypes.TOP_DRAG], phasedRegistrationNames: { bubbled: 'onDrag', captured: 'onDragCapture', }, }, - dragEnd: { + { + dependencies: [TopLevelEventTypes.TOP_DRAG_END], phasedRegistrationNames: { bubbled: 'onDragEnd', captured: 'onDragEndCapture', }, }, - dragEnter: { + { + dependencies: [TopLevelEventTypes.TOP_DRAG_ENTER], phasedRegistrationNames: { bubbled: 'onDragEnter', captured: 'onDragEnterCapture', }, }, - dragExit: { + { + dependencies: [TopLevelEventTypes.TOP_DRAG_EXIT], phasedRegistrationNames: { bubbled: 'onDragExit', captured: 'onDragExitCapture', }, }, - dragLeave: { + { + dependencies: [TopLevelEventTypes.TOP_DRAG_LEAVE], phasedRegistrationNames: { bubbled: 'onDragLeave', captured: 'onDragLeaveCapture', }, }, - dragOver: { + { + dependencies: [TopLevelEventTypes.TOP_DRAG_OVER], phasedRegistrationNames: { bubbled: 'onDragOver', captured: 'onDragOverCapture', }, }, - dragStart: { + { + dependencies: [TopLevelEventTypes.TOP_DRAG_START], phasedRegistrationNames: { bubbled: 'onDragStart', captured: 'onDragStartCapture', }, }, - drop: { + { + dependencies: [TopLevelEventTypes.TOP_DROP], phasedRegistrationNames: { bubbled: 'onDrop', captured: 'onDropCapture', }, }, - durationChange: { + { + dependencies: [TopLevelEventTypes.TOP_DURATION_CHANGE], phasedRegistrationNames: { bubbled: 'onDurationChange', captured: 'onDurationChangeCapture', }, }, - emptied: { + { + dependencies: [TopLevelEventTypes.TOP_EMPTIED], phasedRegistrationNames: { bubbled: 'onEmptied', captured: 'onEmptiedCapture', }, }, - encrypted: { + { + dependencies: [TopLevelEventTypes.TOP_ENCRYPTED], phasedRegistrationNames: { bubbled: 'onEncrypted', captured: 'onEncryptedCapture', }, }, - ended: { + { + dependencies: [TopLevelEventTypes.TOP_ENDED], phasedRegistrationNames: { bubbled: 'onEnded', captured: 'onEndedCapture', }, }, - error: { + { + dependencies: [TopLevelEventTypes.TOP_ERROR], phasedRegistrationNames: { bubbled: 'onError', captured: 'onErrorCapture', }, }, - focus: { + { + dependencies: [TopLevelEventTypes.TOP_FOCUS], phasedRegistrationNames: { bubbled: 'onFocus', captured: 'onFocusCapture', }, }, - input: { + { + dependencies: [TopLevelEventTypes.TOP_INPUT], phasedRegistrationNames: { bubbled: 'onInput', captured: 'onInputCapture', }, }, - invalid: { + { + dependencies: [TopLevelEventTypes.TOP_INVALID], phasedRegistrationNames: { bubbled: 'onInvalid', captured: 'onInvalidCapture', }, }, - keyDown: { + { + dependencies: [TopLevelEventTypes.TOP_KEY_DOWN], phasedRegistrationNames: { bubbled: 'onKeyDown', captured: 'onKeyDownCapture', }, }, - keyPress: { + { + dependencies: [TopLevelEventTypes.TOP_KEY_PRESS], phasedRegistrationNames: { bubbled: 'onKeyPress', captured: 'onKeyPressCapture', }, }, - keyUp: { + { + dependencies: [TopLevelEventTypes.TOP_KEY_UP], phasedRegistrationNames: { bubbled: 'onKeyUp', captured: 'onKeyUpCapture', }, }, - load: { + { + dependencies: [TopLevelEventTypes.TOP_LOAD], phasedRegistrationNames: { bubbled: 'onLoad', captured: 'onLoadCapture', }, }, - loadedData: { + { + dependencies: [TopLevelEventTypes.TOP_LOADED_DATA], phasedRegistrationNames: { bubbled: 'onLoadedData', captured: 'onLoadedDataCapture', }, }, - loadedMetadata: { + { + dependencies: [TopLevelEventTypes.TOP_LOADED_METADATA], phasedRegistrationNames: { bubbled: 'onLoadedMetadata', captured: 'onLoadedMetadataCapture', }, }, - loadStart: { + { + dependencies: [TopLevelEventTypes.TOP_LOAD_START], phasedRegistrationNames: { bubbled: 'onLoadStart', captured: 'onLoadStartCapture', }, }, - mouseDown: { + { + dependencies: [TopLevelEventTypes.TOP_MOUSE_DOWN], phasedRegistrationNames: { bubbled: 'onMouseDown', captured: 'onMouseDownCapture', }, }, - mouseMove: { + { + dependencies: [TopLevelEventTypes.TOP_MOUSE_MOVE], phasedRegistrationNames: { bubbled: 'onMouseMove', captured: 'onMouseMoveCapture', }, }, - mouseOut: { + { + dependencies: [TopLevelEventTypes.TOP_MOUSE_OUT], phasedRegistrationNames: { bubbled: 'onMouseOut', captured: 'onMouseOutCapture', }, }, - mouseOver: { + { + dependencies: [TopLevelEventTypes.TOP_MOUSE_OVER], phasedRegistrationNames: { bubbled: 'onMouseOver', captured: 'onMouseOverCapture', }, }, - mouseUp: { + { + dependencies: [TopLevelEventTypes.TOP_MOUSE_UP], phasedRegistrationNames: { bubbled: 'onMouseUp', captured: 'onMouseUpCapture', }, }, - paste: { + { + dependencies: [TopLevelEventTypes.TOP_PASTE], phasedRegistrationNames: { bubbled: 'onPaste', captured: 'onPasteCapture', }, }, - pause: { + { + dependencies: [TopLevelEventTypes.TOP_PAUSE], phasedRegistrationNames: { bubbled: 'onPause', captured: 'onPauseCapture', }, }, - play: { + { + dependencies: [TopLevelEventTypes.TOP_PLAY], phasedRegistrationNames: { bubbled: 'onPlay', captured: 'onPlayCapture', }, }, - playing: { + { + dependencies: [TopLevelEventTypes.TOP_PLAYING], phasedRegistrationNames: { bubbled: 'onPlaying', captured: 'onPlayingCapture', }, }, - progress: { + { + dependencies: [TopLevelEventTypes.TOP_PROGRESS], phasedRegistrationNames: { bubbled: 'onProgress', captured: 'onProgressCapture', }, }, - rateChange: { + { + dependencies: [TopLevelEventTypes.TOP_RATE_CHANGE], phasedRegistrationNames: { bubbled: 'onRateChange', captured: 'onRateChangeCapture', }, }, - reset: { + { + dependencies: [TopLevelEventTypes.TOP_RESET], phasedRegistrationNames: { bubbled: 'onReset', captured: 'onResetCapture', }, }, - scroll: { + { + dependencies: [TopLevelEventTypes.TOP_SCROLL], phasedRegistrationNames: { bubbled: 'onScroll', captured: 'onScrollCapture', }, }, - seeked: { + { + dependencies: [TopLevelEventTypes.TOP_SEEKED], phasedRegistrationNames: { bubbled: 'onSeeked', captured: 'onSeekedCapture', }, }, - seeking: { + { + dependencies: [TopLevelEventTypes.TOP_SEEKING], phasedRegistrationNames: { bubbled: 'onSeeking', captured: 'onSeekingCapture', }, }, - stalled: { + { + dependencies: [TopLevelEventTypes.TOP_STALLED], phasedRegistrationNames: { bubbled: 'onStalled', captured: 'onStalledCapture', }, }, - submit: { + { + dependencies: [TopLevelEventTypes.TOP_SUBMIT], phasedRegistrationNames: { bubbled: 'onSubmit', captured: 'onSubmitCapture', }, }, - suspend: { + { + dependencies: [TopLevelEventTypes.TOP_SUSPEND], phasedRegistrationNames: { bubbled: 'onSuspend', captured: 'onSuspendCapture', }, }, - timeUpdate: { + { + dependencies: [TopLevelEventTypes.TOP_TIME_UPDATE], phasedRegistrationNames: { bubbled: 'onTimeUpdate', captured: 'onTimeUpdateCapture', }, }, - touchCancel: { + { + dependencies: [TopLevelEventTypes.TOP_TOUCH_CANCEL], phasedRegistrationNames: { bubbled: 'onTouchCancel', captured: 'onTouchCancelCapture', }, }, - touchEnd: { + { + dependencies: [TopLevelEventTypes.TOP_TOUCH_END], phasedRegistrationNames: { bubbled: 'onTouchEnd', captured: 'onTouchEndCapture', }, }, - touchMove: { + { + dependencies: [TopLevelEventTypes.TOP_TOUCH_MOVE], phasedRegistrationNames: { bubbled: 'onTouchMove', captured: 'onTouchMoveCapture', }, }, - touchStart: { + { + dependencies: [TopLevelEventTypes.TOP_TOUCH_START], phasedRegistrationNames: { bubbled: 'onTouchStart', captured: 'onTouchStartCapture', }, }, - transitionEnd: { + { + dependencies: [TopLevelEventTypes.TOP_TRANSITION_END], phasedRegistrationNames: { bubbled: 'onTransitionEnd', captured: 'onTransitionEndCapture', }, }, - volumeChange: { + { + dependencies: [TopLevelEventTypes.TOP_VOLUME_CHANGE], phasedRegistrationNames: { bubbled: 'onVolumeChange', captured: 'onVolumeChangeCapture', }, }, - waiting: { + { + dependencies: [TopLevelEventTypes.TOP_WAITING], phasedRegistrationNames: { bubbled: 'onWaiting', captured: 'onWaitingCapture', }, }, - wheel: { + { + dependencies: [TopLevelEventTypes.TOP_WHEEL], phasedRegistrationNames: { bubbled: 'onWheel', captured: 'onWheelCapture', }, }, -}; +]; -const topLevelEventsToDispatchConfig: { - [key: TopLevelTypes]: DispatchConfig, -} = { - topAbort: eventTypes.abort, - topAnimationEnd: eventTypes.animationEnd, - topAnimationIteration: eventTypes.animationIteration, - topAnimationStart: eventTypes.animationStart, - topBlur: eventTypes.blur, - topCancel: eventTypes.cancel, - topCanPlay: eventTypes.canPlay, - topCanPlayThrough: eventTypes.canPlayThrough, - topClick: eventTypes.click, - topClose: eventTypes.close, - topContextMenu: eventTypes.contextMenu, - topCopy: eventTypes.copy, - topCut: eventTypes.cut, - topDoubleClick: eventTypes.doubleClick, - topDrag: eventTypes.drag, - topDragEnd: eventTypes.dragEnd, - topDragEnter: eventTypes.dragEnter, - topDragExit: eventTypes.dragExit, - topDragLeave: eventTypes.dragLeave, - topDragOver: eventTypes.dragOver, - topDragStart: eventTypes.dragStart, - topDrop: eventTypes.drop, - topDurationChange: eventTypes.durationChange, - topEmptied: eventTypes.emptied, - topEncrypted: eventTypes.encrypted, - topEnded: eventTypes.ended, - topError: eventTypes.error, - topFocus: eventTypes.focus, - topInput: eventTypes.input, - topInvalid: eventTypes.invalid, - topKeyDown: eventTypes.keyDown, - topKeyPress: eventTypes.keyPress, - topKeyUp: eventTypes.keyUp, - topLoad: eventTypes.load, - topLoadedData: eventTypes.loadedData, - topLoadedMetadata: eventTypes.loadedMetadata, - topLoadStart: eventTypes.loadStart, - topMouseDown: eventTypes.mouseDown, - topMouseMove: eventTypes.mouseMove, - topMouseOut: eventTypes.mouseOut, - topMouseOver: eventTypes.mouseOver, - topMouseUp: eventTypes.mouseUp, - topPaste: eventTypes.paste, - topPause: eventTypes.pause, - topPlay: eventTypes.play, - topPlaying: eventTypes.playing, - topProgress: eventTypes.progress, - topRateChange: eventTypes.rateChange, - topReset: eventTypes.reset, - topScroll: eventTypes.scroll, - topSeeked: eventTypes.seeked, - topSeeking: eventTypes.seeking, - topStalled: eventTypes.stalled, - topSubmit: eventTypes.submit, - topSuspend: eventTypes.suspend, - topTimeUpdate: eventTypes.timeUpdate, - topTouchCancel: eventTypes.touchCancel, - topTouchEnd: eventTypes.touchEnd, - topTouchMove: eventTypes.touchMove, - topTouchStart: eventTypes.touchStart, - topTransitionEnd: eventTypes.transitionEnd, - topVolumeChange: eventTypes.volumeChange, - topWaiting: eventTypes.waiting, - topWheel: eventTypes.wheel, -}; +const topLevelEventsToDispatchConfig = new Map(); -for (var type in topLevelEventsToDispatchConfig) { - topLevelEventsToDispatchConfig[type].dependencies = [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 = { @@ -535,13 +536,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). @@ -549,65 +550,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 a7fb4ea9ad8..fe39bbf5739 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": 100015, - "gzip": 31871 + "size": 94877, + "gzip": 30761 }, "react-dom.development.js (NODE_DEV)": { "size": 544502, From a3666f760ef345fa4813bcd97161e92516868a57 Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Wed, 20 Dec 2017 07:29:15 +0000 Subject: [PATCH 5/6] Add indirection back --- .../react-dom/src/events/SimpleEventPlugin.js | 522 +++--------------- 1 file changed, 73 insertions(+), 449 deletions(-) diff --git a/packages/react-dom/src/events/SimpleEventPlugin.js b/packages/react-dom/src/events/SimpleEventPlugin.js index 1bdeec6979e..5c4d4152f49 100644 --- a/packages/react-dom/src/events/SimpleEventPlugin.js +++ b/packages/react-dom/src/events/SimpleEventPlugin.js @@ -32,457 +32,81 @@ import SyntheticUIEvent from './SyntheticUIEvent'; import SyntheticWheelEvent from './SyntheticWheelEvent'; import getEventCharCode from './getEventCharCode'; -const eventTypes: EventTypes = [ - { - dependencies: [TopLevelEventTypes.TOP_ABORT], - phasedRegistrationNames: { - bubbled: 'onAbort', - captured: 'onAbortCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_ANIMATION_END], - phasedRegistrationNames: { - bubbled: 'onAnimationEnd', - captured: 'onAnimationEndCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_ANIMATION_ITERATION], - phasedRegistrationNames: { - bubbled: 'onAnimationIteration', - captured: 'onAnimationIterationCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_ANIMATION_START], - phasedRegistrationNames: { - bubbled: 'onAnimationStart', - captured: 'onAnimationStartCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_BLUR], - phasedRegistrationNames: { - bubbled: 'onBlur', - captured: 'onBlurCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_CANCEL], - phasedRegistrationNames: { - bubbled: 'onCancel', - captured: 'onCancelCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_CAN_PLAY], - phasedRegistrationNames: { - bubbled: 'onCanPlay', - captured: 'onCanPlayCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_CAN_PLAY_THROUGH], - phasedRegistrationNames: { - bubbled: 'onCanPlayThrough', - captured: 'onCanPlayThroughCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_CLICK], - phasedRegistrationNames: { - bubbled: 'onClick', - captured: 'onClickCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_CLOSE], - phasedRegistrationNames: { - bubbled: 'onClose', - captured: 'onCloseCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_CONTEXT_MENU], - phasedRegistrationNames: { - bubbled: 'onContextMenu', - captured: 'onContextMenuCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_COPY], - phasedRegistrationNames: { - bubbled: 'onCopy', - captured: 'onCopyCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_CUT], - phasedRegistrationNames: { - bubbled: 'onCut', - captured: 'onCutCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_DOUBLE_CLICK], - phasedRegistrationNames: { - bubbled: 'onDoubleClick', - captured: 'onDoubleClickCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_DRAG], - phasedRegistrationNames: { - bubbled: 'onDrag', - captured: 'onDragCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_DRAG_END], - phasedRegistrationNames: { - bubbled: 'onDragEnd', - captured: 'onDragEndCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_DRAG_ENTER], - phasedRegistrationNames: { - bubbled: 'onDragEnter', - captured: 'onDragEnterCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_DRAG_EXIT], - phasedRegistrationNames: { - bubbled: 'onDragExit', - captured: 'onDragExitCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_DRAG_LEAVE], - phasedRegistrationNames: { - bubbled: 'onDragLeave', - captured: 'onDragLeaveCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_DRAG_OVER], - phasedRegistrationNames: { - bubbled: 'onDragOver', - captured: 'onDragOverCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_DRAG_START], - phasedRegistrationNames: { - bubbled: 'onDragStart', - captured: 'onDragStartCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_DROP], - phasedRegistrationNames: { - bubbled: 'onDrop', - captured: 'onDropCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_DURATION_CHANGE], - phasedRegistrationNames: { - bubbled: 'onDurationChange', - captured: 'onDurationChangeCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_EMPTIED], - phasedRegistrationNames: { - bubbled: 'onEmptied', - captured: 'onEmptiedCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_ENCRYPTED], - phasedRegistrationNames: { - bubbled: 'onEncrypted', - captured: 'onEncryptedCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_ENDED], - phasedRegistrationNames: { - bubbled: 'onEnded', - captured: 'onEndedCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_ERROR], - phasedRegistrationNames: { - bubbled: 'onError', - captured: 'onErrorCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_FOCUS], - phasedRegistrationNames: { - bubbled: 'onFocus', - captured: 'onFocusCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_INPUT], - phasedRegistrationNames: { - bubbled: 'onInput', - captured: 'onInputCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_INVALID], - phasedRegistrationNames: { - bubbled: 'onInvalid', - captured: 'onInvalidCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_KEY_DOWN], - phasedRegistrationNames: { - bubbled: 'onKeyDown', - captured: 'onKeyDownCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_KEY_PRESS], - phasedRegistrationNames: { - bubbled: 'onKeyPress', - captured: 'onKeyPressCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_KEY_UP], - phasedRegistrationNames: { - bubbled: 'onKeyUp', - captured: 'onKeyUpCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_LOAD], - phasedRegistrationNames: { - bubbled: 'onLoad', - captured: 'onLoadCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_LOADED_DATA], - phasedRegistrationNames: { - bubbled: 'onLoadedData', - captured: 'onLoadedDataCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_LOADED_METADATA], - phasedRegistrationNames: { - bubbled: 'onLoadedMetadata', - captured: 'onLoadedMetadataCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_LOAD_START], - phasedRegistrationNames: { - bubbled: 'onLoadStart', - captured: 'onLoadStartCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_MOUSE_DOWN], - phasedRegistrationNames: { - bubbled: 'onMouseDown', - captured: 'onMouseDownCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_MOUSE_MOVE], - phasedRegistrationNames: { - bubbled: 'onMouseMove', - captured: 'onMouseMoveCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_MOUSE_OUT], - phasedRegistrationNames: { - bubbled: 'onMouseOut', - captured: 'onMouseOutCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_MOUSE_OVER], - phasedRegistrationNames: { - bubbled: 'onMouseOver', - captured: 'onMouseOverCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_MOUSE_UP], - phasedRegistrationNames: { - bubbled: 'onMouseUp', - captured: 'onMouseUpCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_PASTE], - phasedRegistrationNames: { - bubbled: 'onPaste', - captured: 'onPasteCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_PAUSE], - phasedRegistrationNames: { - bubbled: 'onPause', - captured: 'onPauseCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_PLAY], - phasedRegistrationNames: { - bubbled: 'onPlay', - captured: 'onPlayCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_PLAYING], - phasedRegistrationNames: { - bubbled: 'onPlaying', - captured: 'onPlayingCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_PROGRESS], - phasedRegistrationNames: { - bubbled: 'onProgress', - captured: 'onProgressCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_RATE_CHANGE], - phasedRegistrationNames: { - bubbled: 'onRateChange', - captured: 'onRateChangeCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_RESET], - phasedRegistrationNames: { - bubbled: 'onReset', - captured: 'onResetCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_SCROLL], - phasedRegistrationNames: { - bubbled: 'onScroll', - captured: 'onScrollCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_SEEKED], - phasedRegistrationNames: { - bubbled: 'onSeeked', - captured: 'onSeekedCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_SEEKING], - phasedRegistrationNames: { - bubbled: 'onSeeking', - captured: 'onSeekingCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_STALLED], - phasedRegistrationNames: { - bubbled: 'onStalled', - captured: 'onStalledCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_SUBMIT], - phasedRegistrationNames: { - bubbled: 'onSubmit', - captured: 'onSubmitCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_SUSPEND], - phasedRegistrationNames: { - bubbled: 'onSuspend', - captured: 'onSuspendCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_TIME_UPDATE], - phasedRegistrationNames: { - bubbled: 'onTimeUpdate', - captured: 'onTimeUpdateCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_TOUCH_CANCEL], - phasedRegistrationNames: { - bubbled: 'onTouchCancel', - captured: 'onTouchCancelCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_TOUCH_END], - phasedRegistrationNames: { - bubbled: 'onTouchEnd', - captured: 'onTouchEndCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_TOUCH_MOVE], - phasedRegistrationNames: { - bubbled: 'onTouchMove', - captured: 'onTouchMoveCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_TOUCH_START], - phasedRegistrationNames: { - bubbled: 'onTouchStart', - captured: 'onTouchStartCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_TRANSITION_END], - phasedRegistrationNames: { - bubbled: 'onTransitionEnd', - captured: 'onTransitionEndCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_VOLUME_CHANGE], - phasedRegistrationNames: { - bubbled: 'onVolumeChange', - captured: 'onVolumeChangeCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_WAITING], - phasedRegistrationNames: { - bubbled: 'onWaiting', - captured: 'onWaitingCapture', - }, - }, - { - dependencies: [TopLevelEventTypes.TOP_WHEEL], - phasedRegistrationNames: { - bubbled: 'onWheel', - captured: 'onWheelCapture', - }, - }, +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', + }, +})); + const topLevelEventsToDispatchConfig = new Map(); for (let i = 0; i < eventTypes.length; i++) { From e5eff60615b932343a691d56e995a28857f06c4d Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Wed, 20 Dec 2017 07:48:22 +0000 Subject: [PATCH 6/6] Reduce duplication --- .../src/client/ReactDOMFiberComponent.js | 14 +--- .../src/events/BrowserEventConstants.js | 78 ++++--------------- .../src/events/ReactBrowserEventEmitter.js | 9 +-- .../react-dom/src/events/SimpleEventPlugin.js | 2 +- scripts/rollup/results.json | 4 +- 5 files changed, 26 insertions(+), 81 deletions(-) diff --git a/packages/react-dom/src/client/ReactDOMFiberComponent.js b/packages/react-dom/src/client/ReactDOMFiberComponent.js index 1a71e9f96f8..e55300bfb54 100644 --- a/packages/react-dom/src/client/ReactDOMFiberComponent.js +++ b/packages/react-dom/src/client/ReactDOMFiberComponent.js @@ -52,7 +52,7 @@ import * as inputValueTracking from './inputValueTracking'; import setInnerHTML from './setInnerHTML'; import setTextContent from './setTextContent'; import {listenTo, trapBubbledEvent} from '../events/ReactBrowserEventEmitter'; -import BrowserEventConstants from '../events/BrowserEventConstants'; +import {getRawEventName} from '../events/BrowserEventConstants'; import * as CSSPropertyOperations from '../shared/CSSPropertyOperations'; import {Namespaces, getIntrinsicNamespace} from '../shared/DOMNamespaces'; import { @@ -503,11 +503,7 @@ export function setInitialProperties( case 'audio': // Create listener for each media event for (let i = 0; i < mediaEvents.length; i++) { - trapBubbledEvent( - event, - BrowserEventConstants.topLevelTypes[mediaEvents[i]], - domElement, - ); + trapBubbledEvent(event, getRawEventName(mediaEvents[i]), domElement); } props = rawProps; break; @@ -881,11 +877,7 @@ export function diffHydratedProperties( case 'audio': // Create listener for each media event for (let i = 0; i < mediaEvents.length; i++) { - trapBubbledEvent( - event, - BrowserEventConstants.topLevelTypes[mediaEvents[i]], - domElement, - ); + trapBubbledEvent(event, getRawEventName(mediaEvents[i]), domElement); } break; case 'source': diff --git a/packages/react-dom/src/events/BrowserEventConstants.js b/packages/react-dom/src/events/BrowserEventConstants.js index 12fbf5f62d1..4be9197116f 100644 --- a/packages/react-dom/src/events/BrowserEventConstants.js +++ b/packages/react-dom/src/events/BrowserEventConstants.js @@ -6,6 +6,7 @@ */ import getVendorPrefixedEventName from './getVendorPrefixedEventName'; +import {topLevelEventsToDispatchConfig} from './SimpleEventPlugin'; import * as TopLevelEventTypes from 'events/TopLevelEventTypes'; /** @@ -15,7 +16,7 @@ import * as TopLevelEventTypes from 'events/TopLevelEventTypes'; * trap at a lower node than `document`), binding at `document` would * cause duplicate events so we don't include them here. */ -const topLevelTypes = new Map([ +const cache = new Map([ [TopLevelEventTypes.TOP_ABORT, 'abort'], [ TopLevelEventTypes.TOP_ANIMATION_END, @@ -29,79 +30,32 @@ const topLevelTypes = new Map([ TopLevelEventTypes.TOP_ANIMATION_START, getVendorPrefixedEventName('animationstart') || 'animationstart', ], - [TopLevelEventTypes.TOP_BLUR, 'blur'], - [TopLevelEventTypes.TOP_CANCEL, 'cancel'], - [TopLevelEventTypes.TOP_CAN_PLAY, 'canplay'], - [TopLevelEventTypes.TOP_CAN_PLAY_THROUGH, 'canplaythrough'], [TopLevelEventTypes.TOP_CHANGE, 'change'], - [TopLevelEventTypes.TOP_CLICK, 'click'], - [TopLevelEventTypes.TOP_CLOSE, 'close'], [TopLevelEventTypes.TOP_COMPOSITION_END, 'compositionend'], [TopLevelEventTypes.TOP_COMPOSITION_START, 'compositionstart'], [TopLevelEventTypes.TOP_COMPOSITION_UPDATE, 'compositionupdate'], - [TopLevelEventTypes.TOP_CONTEXT_MENU, 'contextmenu'], - [TopLevelEventTypes.TOP_COPY, 'copy'], - [TopLevelEventTypes.TOP_CUT, 'cut'], [TopLevelEventTypes.TOP_DOUBLE_CLICK, 'dblclick'], - [TopLevelEventTypes.TOP_DRAG, 'drag'], - [TopLevelEventTypes.TOP_DRAG_END, 'dragend'], - [TopLevelEventTypes.TOP_DRAG_ENTER, 'dragenter'], - [TopLevelEventTypes.TOP_DRAG_EXIT, 'dragexit'], - [TopLevelEventTypes.TOP_DRAG_LEAVE, 'dragleave'], - [TopLevelEventTypes.TOP_DRAG_OVER, 'dragover'], - [TopLevelEventTypes.TOP_DRAG_START, 'dragstart'], - [TopLevelEventTypes.TOP_DROP, 'drop'], - [TopLevelEventTypes.TOP_DURATION_CHANGE, 'durationchange'], - [TopLevelEventTypes.TOP_EMPTIED, 'emptied'], - [TopLevelEventTypes.TOP_ENCRYPTED, 'encrypted'], - [TopLevelEventTypes.TOP_ENDED, 'ended'], - [TopLevelEventTypes.TOP_ERROR, 'error'], - [TopLevelEventTypes.TOP_FOCUS, 'focus'], - [TopLevelEventTypes.TOP_INPUT, 'input'], - [TopLevelEventTypes.TOP_KEY_DOWN, 'keydown'], - [TopLevelEventTypes.TOP_KEY_PRESS, 'keypress'], - [TopLevelEventTypes.TOP_KEY_UP, 'keyup'], - [TopLevelEventTypes.TOP_LOADED_DATA, 'loadeddata'], - [TopLevelEventTypes.TOP_LOAD, 'load'], - [TopLevelEventTypes.TOP_LOADED_METADATA, 'loadedmetadata'], - [TopLevelEventTypes.TOP_LOAD_START, 'loadstart'], - [TopLevelEventTypes.TOP_MOUSE_DOWN, 'mousedown'], - [TopLevelEventTypes.TOP_MOUSE_MOVE, 'mousemove'], - [TopLevelEventTypes.TOP_MOUSE_OUT, 'mouseout'], - [TopLevelEventTypes.TOP_MOUSE_OVER, 'mouseover'], - [TopLevelEventTypes.TOP_MOUSE_UP, 'mouseup'], - [TopLevelEventTypes.TOP_PASTE, 'paste'], - [TopLevelEventTypes.TOP_PAUSE, 'pause'], - [TopLevelEventTypes.TOP_PLAY, 'play'], - [TopLevelEventTypes.TOP_PLAYING, 'playing'], - [TopLevelEventTypes.TOP_PROGRESS, 'progress'], - [TopLevelEventTypes.TOP_RATE_CHANGE, 'ratechange'], - [TopLevelEventTypes.TOP_SCROLL, 'scroll'], - [TopLevelEventTypes.TOP_SEEKED, 'seeked'], - [TopLevelEventTypes.TOP_SEEKING, 'seeking'], [TopLevelEventTypes.TOP_SELECTION_CHANGE, 'selectionchange'], - [TopLevelEventTypes.TOP_STALLED, 'stalled'], - [TopLevelEventTypes.TOP_SUSPEND, 'suspend'], [TopLevelEventTypes.TOP_TEXT_INPUT, 'textInput'], - [TopLevelEventTypes.TOP_TIME_UPDATE, 'timeupdate'], [TopLevelEventTypes.TOP_TOGGLE, 'toggle'], - [TopLevelEventTypes.TOP_TOUCH_CANCEL, 'touchcancel'], - [TopLevelEventTypes.TOP_TOUCH_END, 'touchend'], - [TopLevelEventTypes.TOP_TOUCH_MOVE, 'touchmove'], - [TopLevelEventTypes.TOP_TOUCH_START, 'touchstart'], [ TopLevelEventTypes.TOP_TRANSITION_END, getVendorPrefixedEventName('transitionend') || 'transitionend', ], - [TopLevelEventTypes.TOP_VOLUME_CHANGE, 'volumechange'], - [TopLevelEventTypes.TOP_WAITING, 'waiting'], - [TopLevelEventTypes.TOP_WHEEL, '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/ReactBrowserEventEmitter.js b/packages/react-dom/src/events/ReactBrowserEventEmitter.js index f10469d7af0..749a42bdc7a 100644 --- a/packages/react-dom/src/events/ReactBrowserEventEmitter.js +++ b/packages/react-dom/src/events/ReactBrowserEventEmitter.js @@ -21,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: * @@ -129,6 +127,7 @@ 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 === TOP_SCROLL) { trapCapturedEvent(TOP_SCROLL, 'scroll', mountAt); @@ -149,8 +148,8 @@ export function listenTo(registrationName, contentDocumentHandle) { trapCapturedEvent(TOP_CLOSE, 'close', mountAt); } isListening.topClose = true; - } else if (topLevelTypes.has(dependency)) { - trapBubbledEvent(dependency, topLevelTypes.get(dependency), mountAt); + } else if ((rawName = getRawEventName(dependency))) { + trapBubbledEvent(dependency, rawName, mountAt); } isListening[dependency] = true; diff --git a/packages/react-dom/src/events/SimpleEventPlugin.js b/packages/react-dom/src/events/SimpleEventPlugin.js index 5c4d4152f49..8b2f75e468e 100644 --- a/packages/react-dom/src/events/SimpleEventPlugin.js +++ b/packages/react-dom/src/events/SimpleEventPlugin.js @@ -107,7 +107,7 @@ const eventTypes = shortTypes.map(t => ({ }, })); -const topLevelEventsToDispatchConfig = new Map(); +export const topLevelEventsToDispatchConfig = new Map(); for (let i = 0; i < eventTypes.length; i++) { topLevelEventsToDispatchConfig.set( diff --git a/scripts/rollup/results.json b/scripts/rollup/results.json index fe39bbf5739..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": 94877, - "gzip": 30761 + "size": 91054, + "gzip": 30230 }, "react-dom.development.js (NODE_DEV)": { "size": 544502,