diff --git a/packages/react-dom/src/client/ReactDOM.js b/packages/react-dom/src/client/ReactDOM.js index 2016fbe9d6..606569f8b8 100644 --- a/packages/react-dom/src/client/ReactDOM.js +++ b/packages/react-dom/src/client/ReactDOM.js @@ -11,7 +11,6 @@ import type {ReactNodeList} from 'shared/ReactTypes'; import type {Container} from './ReactDOMHostConfig'; import '../shared/checkReact'; -import './ReactDOMClientInjection'; import { findDOMNode, render, @@ -39,10 +38,7 @@ import { } from 'react-reconciler/src/ReactFiberReconciler'; import {createPortal as createPortalImpl} from 'react-reconciler/src/ReactPortal'; import {canUseDOM} from 'shared/ExecutionEnvironment'; -import { - eventNameDispatchConfigs, - injectEventPluginsByName, -} from '../legacy-events/EventPluginRegistry'; +import {eventNameDispatchConfigs} from '../events/EventPluginRegistry'; import ReactVersion from 'shared/ReactVersion'; import invariant from 'shared/invariant'; import { @@ -57,7 +53,6 @@ import { getClosestInstanceFromNode, } from './ReactDOMComponentTree'; import {restoreControlledState} from './ReactDOMComponent'; -import {dispatchEvent} from '../events/ReactDOMEventListener'; import { setAttemptSynchronousHydration, setAttemptUserBlockingHydration, @@ -180,11 +175,9 @@ const Internals = { getInstanceFromNode, getNodeFromInstance, getFiberCurrentPropsFromNode, - injectEventPluginsByName, eventNameDispatchConfigs, enqueueStateRestore, restoreStateIfNeeded, - dispatchEvent, flushPassiveEffects, IsThisRendererActing, ], diff --git a/packages/react-dom/src/client/ReactDOMClientInjection.js b/packages/react-dom/src/client/ReactDOMClientInjection.js deleted file mode 100644 index 0f2532c1b6..0000000000 --- a/packages/react-dom/src/client/ReactDOMClientInjection.js +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -// TODO: remove this injection altogether. - -import ModernBeforeInputEventPlugin from '../events/plugins/ModernBeforeInputEventPlugin'; -import ModernChangeEventPlugin from '../events/plugins/ModernChangeEventPlugin'; -import ModernEnterLeaveEventPlugin from '../events/plugins/ModernEnterLeaveEventPlugin'; -import ModernSelectEventPlugin from '../events/plugins/ModernSelectEventPlugin'; -import ModernSimpleEventPlugin from '../events/plugins/ModernSimpleEventPlugin'; - -import {injectEventPlugins} from '../legacy-events/EventPluginRegistry'; - -injectEventPlugins([ - ModernSimpleEventPlugin, - ModernEnterLeaveEventPlugin, - ModernChangeEventPlugin, - ModernSelectEventPlugin, - ModernBeforeInputEventPlugin, -]); diff --git a/packages/react-dom/src/client/ReactDOMComponent.js b/packages/react-dom/src/client/ReactDOMComponent.js index af1f118491..ad476a94d7 100644 --- a/packages/react-dom/src/client/ReactDOMComponent.js +++ b/packages/react-dom/src/client/ReactDOMComponent.js @@ -7,7 +7,10 @@ * @flow */ -import {registrationNameModules} from '../legacy-events/EventPluginRegistry'; +import { + registrationNameModules, + possibleRegistrationNames, +} from '../events/EventPluginRegistry'; import {canUseDOM} from 'shared/ExecutionEnvironment'; import invariant from 'shared/invariant'; import { @@ -129,7 +132,10 @@ if (__DEV__) { validatePropertiesInDevelopment = function(type, props) { validateARIAProperties(type, props); validateInputProperties(type, props); - validateUnknownProperties(type, props, /* canUseEventSystem */ true); + validateUnknownProperties(type, props, { + registrationNameModules, + possibleRegistrationNames, + }); }; // IE 11 parses & normalizes the style attribute as opposed to other diff --git a/packages/react-dom/src/client/ReactDOMComponentTree.js b/packages/react-dom/src/client/ReactDOMComponentTree.js index 9d2822f60d..5381083e4c 100644 --- a/packages/react-dom/src/client/ReactDOMComponentTree.js +++ b/packages/react-dom/src/client/ReactDOMComponentTree.js @@ -17,7 +17,7 @@ import type { SuspenseInstance, Props, } from './ReactDOMHostConfig'; -import type {DOMTopLevelEventType} from '../legacy-events/TopLevelEventTypes'; +import type {DOMTopLevelEventType} from '../events/TopLevelEventTypes'; import { HostComponent, diff --git a/packages/react-dom/src/client/ReactDOMEventHandle.js b/packages/react-dom/src/client/ReactDOMEventHandle.js index b477685c17..ae9b40d130 100644 --- a/packages/react-dom/src/client/ReactDOMEventHandle.js +++ b/packages/react-dom/src/client/ReactDOMEventHandle.js @@ -7,7 +7,7 @@ * @flow */ -import type {DOMTopLevelEventType} from '../legacy-events/TopLevelEventTypes'; +import type {DOMTopLevelEventType} from '../events/TopLevelEventTypes'; import type {EventPriority, ReactScopeInstance} from 'shared/ReactTypes'; import type { ReactDOMEventHandle, diff --git a/packages/react-dom/src/client/ReactDOMHostConfig.js b/packages/react-dom/src/client/ReactDOMHostConfig.js index 2c09646696..f064b0f9c2 100644 --- a/packages/react-dom/src/client/ReactDOMHostConfig.js +++ b/packages/react-dom/src/client/ReactDOMHostConfig.js @@ -7,7 +7,7 @@ * @flow */ -import type {TopLevelType} from '../legacy-events/TopLevelEventTypes'; +import type {TopLevelType} from '../events/TopLevelEventTypes'; import type {Fiber, FiberRoot} from 'react-reconciler/src/ReactInternalTypes'; import type { BoundingRect, diff --git a/packages/react-dom/src/events/DOMEventProperties.js b/packages/react-dom/src/events/DOMEventProperties.js index 747fd4278e..2135fdc167 100644 --- a/packages/react-dom/src/events/DOMEventProperties.js +++ b/packages/react-dom/src/events/DOMEventProperties.js @@ -11,11 +11,11 @@ import type {EventPriority} from 'shared/ReactTypes'; import type { TopLevelType, DOMTopLevelEventType, -} from '../legacy-events/TopLevelEventTypes'; +} from '../events/TopLevelEventTypes'; import type { DispatchConfig, CustomDispatchConfig, -} from '../legacy-events/ReactSyntheticEventType'; +} from '../events/ReactSyntheticEventType'; import * as DOMTopLevelEventTypes from './DOMTopLevelEventTypes'; import { diff --git a/packages/react-dom/src/events/DOMModernPluginEventSystem.js b/packages/react-dom/src/events/DOMModernPluginEventSystem.js index 5cebb608e4..4caecefcfe 100644 --- a/packages/react-dom/src/events/DOMModernPluginEventSystem.js +++ b/packages/react-dom/src/events/DOMModernPluginEventSystem.js @@ -7,8 +7,8 @@ * @flow */ -import type {AnyNativeEvent} from '../legacy-events/PluginModuleType'; -import type {DOMTopLevelEventType} from '../legacy-events/TopLevelEventTypes'; +import type {AnyNativeEvent} from '../events/PluginModuleType'; +import type {DOMTopLevelEventType} from '../events/TopLevelEventTypes'; import type { ElementListenerMap, ElementListenerMapEntry, @@ -22,14 +22,14 @@ import type { DispatchQueueItem, DispatchQueueItemPhase, DispatchQueueItemPhaseEntry, -} from '../legacy-events/PluginModuleType'; +} from '../events/PluginModuleType'; import type { ReactSyntheticEvent, CustomDispatchConfig, -} from '../legacy-events/ReactSyntheticEventType'; +} from '../events/ReactSyntheticEventType'; -import {registrationNameDependencies} from '../legacy-events/EventPluginRegistry'; -import {plugins} from '../legacy-events/EventPluginRegistry'; +import {registrationNameDependencies} from '../events/EventPluginRegistry'; +import {plugins} from '../events/EventPluginRegistry'; import { PLUGIN_EVENT_SYSTEM, LEGACY_FB_SUPPORT, diff --git a/packages/react-dom/src/events/DOMTopLevelEventTypes.js b/packages/react-dom/src/events/DOMTopLevelEventTypes.js index 69e0a1e319..86fcb713a4 100644 --- a/packages/react-dom/src/events/DOMTopLevelEventTypes.js +++ b/packages/react-dom/src/events/DOMTopLevelEventTypes.js @@ -7,12 +7,12 @@ * @flow */ -import type {DOMTopLevelEventType} from '../legacy-events/TopLevelEventTypes'; +import type {DOMTopLevelEventType} from '../events/TopLevelEventTypes'; import { unsafeCastStringToDOMTopLevelType, unsafeCastDOMTopLevelTypeToString, -} from '../legacy-events/TopLevelEventTypes'; +} from '../events/TopLevelEventTypes'; import getVendorPrefixedEventName from './getVendorPrefixedEventName'; /** diff --git a/packages/react-dom/src/events/DeprecatedDOMEventResponderSystem.js b/packages/react-dom/src/events/DeprecatedDOMEventResponderSystem.js index 878015ebc0..8f59811678 100644 --- a/packages/react-dom/src/events/DeprecatedDOMEventResponderSystem.js +++ b/packages/react-dom/src/events/DeprecatedDOMEventResponderSystem.js @@ -12,7 +12,7 @@ import { PASSIVE_NOT_SUPPORTED, RESPONDER_EVENT_SYSTEM, } from './EventSystemFlags'; -import type {AnyNativeEvent} from '../legacy-events/PluginModuleType'; +import type {AnyNativeEvent} from '../events/PluginModuleType'; import { HostComponent, ScopeComponent, @@ -25,7 +25,7 @@ import type { ReactDOMResponderContext, ReactDOMResponderEvent, } from '../shared/ReactDOMTypes'; -import type {DOMTopLevelEventType} from '../legacy-events/TopLevelEventTypes'; +import type {DOMTopLevelEventType} from '../events/TopLevelEventTypes'; import { batchedEventUpdates, discreteUpdates, diff --git a/packages/react-dom/src/events/EventPluginRegistry.js b/packages/react-dom/src/events/EventPluginRegistry.js new file mode 100644 index 0000000000..27ec25c378 --- /dev/null +++ b/packages/react-dom/src/events/EventPluginRegistry.js @@ -0,0 +1,151 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + */ + +import type {DispatchConfig} from './ReactSyntheticEventType'; +import type { + AnyNativeEvent, + LegacyPluginModule, + ModernPluginModule, +} from './PluginModuleType'; +import ModernBeforeInputEventPlugin from '../events/plugins/ModernBeforeInputEventPlugin'; +import ModernChangeEventPlugin from '../events/plugins/ModernChangeEventPlugin'; +import ModernEnterLeaveEventPlugin from '../events/plugins/ModernEnterLeaveEventPlugin'; +import ModernSelectEventPlugin from '../events/plugins/ModernSelectEventPlugin'; +import ModernSimpleEventPlugin from '../events/plugins/ModernSimpleEventPlugin'; + +import invariant from 'shared/invariant'; + +/** + * Publishes an event so that it can be dispatched by the supplied plugin. + * + * @param {object} dispatchConfig Dispatch configuration for the event. + * @param {object} PluginModule Plugin publishing the event. + * @return {boolean} True if the event was successfully published. + * @private + */ +function publishEventForPlugin( + dispatchConfig: DispatchConfig, + pluginModule: + | LegacyPluginModule + | ModernPluginModule, + eventName: string, +): boolean { + invariant( + !eventNameDispatchConfigs.hasOwnProperty(eventName), + 'EventPluginRegistry: More than one plugin attempted to publish the same ' + + 'event name, `%s`.', + eventName, + ); + eventNameDispatchConfigs[eventName] = dispatchConfig; + + const phasedRegistrationNames = dispatchConfig.phasedRegistrationNames; + if (phasedRegistrationNames) { + for (const phaseName in phasedRegistrationNames) { + if (phasedRegistrationNames.hasOwnProperty(phaseName)) { + const phasedRegistrationName = phasedRegistrationNames[phaseName]; + publishRegistrationName( + phasedRegistrationName, + pluginModule, + eventName, + ); + } + } + return true; + } else if (dispatchConfig.registrationName) { + publishRegistrationName( + dispatchConfig.registrationName, + pluginModule, + eventName, + ); + return true; + } + return false; +} + +/** + * Publishes a registration name that is used to identify dispatched events. + * + * @param {string} registrationName Registration name to add. + * @param {object} PluginModule Plugin publishing the event. + * @private + */ +function publishRegistrationName( + registrationName: string, + pluginModule: + | LegacyPluginModule + | ModernPluginModule, + eventName: string, +): void { + invariant( + !registrationNameModules[registrationName], + 'EventPluginRegistry: More than one plugin attempted to publish the same ' + + 'registration name, `%s`.', + registrationName, + ); + registrationNameModules[registrationName] = pluginModule; + registrationNameDependencies[registrationName] = + pluginModule.eventTypes[eventName].dependencies; + + if (__DEV__) { + const lowerCasedName = registrationName.toLowerCase(); + possibleRegistrationNames[lowerCasedName] = registrationName; + + if (registrationName === 'onDoubleClick') { + possibleRegistrationNames.ondblclick = registrationName; + } + } +} + +/** + * Registers plugins so that they can extract and dispatch events. + */ + +/** + * Ordered list of injected plugins. + */ +export const plugins = []; + +/** + * Mapping from event name to dispatch config + */ +export const eventNameDispatchConfigs = {}; + +/** + * Mapping from registration name to plugin module + */ +export const registrationNameModules = {}; + +/** + * Mapping from registration name to event name + */ +export const registrationNameDependencies = {}; + +/** + * Mapping from lowercase registration names to the properly cased version, + * used to warn in the case of missing event handlers. Available + * only in __DEV__. + * @type {Object} + */ +export const possibleRegistrationNames = __DEV__ ? {} : (null: any); +// Trust the developer to only use possibleRegistrationNames in __DEV__ + +function injectEventPlugin(pluginModule: ModernPluginModule): void { + plugins.push(pluginModule); + const publishedEvents = pluginModule.eventTypes; + for (const eventName in publishedEvents) { + publishEventForPlugin(publishedEvents[eventName], pluginModule, eventName); + } +} + +// TODO: remove top-level side effect. +injectEventPlugin(ModernSimpleEventPlugin); +injectEventPlugin(ModernEnterLeaveEventPlugin); +injectEventPlugin(ModernChangeEventPlugin); +injectEventPlugin(ModernSelectEventPlugin); +injectEventPlugin(ModernBeforeInputEventPlugin); diff --git a/packages/react-dom/src/legacy-events/PluginModuleType.js b/packages/react-dom/src/events/PluginModuleType.js similarity index 100% rename from packages/react-dom/src/legacy-events/PluginModuleType.js rename to packages/react-dom/src/events/PluginModuleType.js diff --git a/packages/react-dom/src/events/ReactDOMEventListener.js b/packages/react-dom/src/events/ReactDOMEventListener.js index c83e3cd284..5dcfb77050 100644 --- a/packages/react-dom/src/events/ReactDOMEventListener.js +++ b/packages/react-dom/src/events/ReactDOMEventListener.js @@ -7,11 +7,11 @@ * @flow */ -import type {AnyNativeEvent} from '../legacy-events/PluginModuleType'; +import type {AnyNativeEvent} from '../events/PluginModuleType'; import type {EventPriority} from 'shared/ReactTypes'; import type {FiberRoot} from 'react-reconciler/src/ReactInternalTypes'; import type {Container, SuspenseInstance} from '../client/ReactDOMHostConfig'; -import type {DOMTopLevelEventType} from '../legacy-events/TopLevelEventTypes'; +import type {DOMTopLevelEventType} from '../events/TopLevelEventTypes'; // Intentionally not named imports because Rollup would use dynamic dispatch for // CommonJS interop named imports. diff --git a/packages/react-dom/src/events/ReactDOMEventReplaying.js b/packages/react-dom/src/events/ReactDOMEventReplaying.js index 9d4cd1a9e3..d69d9684a7 100644 --- a/packages/react-dom/src/events/ReactDOMEventReplaying.js +++ b/packages/react-dom/src/events/ReactDOMEventReplaying.js @@ -7,9 +7,9 @@ * @flow */ -import type {AnyNativeEvent} from '../legacy-events/PluginModuleType'; +import type {AnyNativeEvent} from '../events/PluginModuleType'; import type {Container, SuspenseInstance} from '../client/ReactDOMHostConfig'; -import type {DOMTopLevelEventType} from '../legacy-events/TopLevelEventTypes'; +import type {DOMTopLevelEventType} from '../events/TopLevelEventTypes'; import type {ElementListenerMap} from '../client/ReactDOMComponentTree'; import type {EventSystemFlags} from './EventSystemFlags'; import type {FiberRoot} from 'react-reconciler/src/ReactInternalTypes'; @@ -35,7 +35,7 @@ import { getClosestInstanceFromNode, getEventListenerMap, } from '../client/ReactDOMComponentTree'; -import {unsafeCastDOMTopLevelTypeToString} from '../legacy-events/TopLevelEventTypes'; +import {unsafeCastDOMTopLevelTypeToString} from '../events/TopLevelEventTypes'; import {HostRoot, SuspenseComponent} from 'react-reconciler/src/ReactWorkTags'; let attemptSynchronousHydration: (fiber: Object) => void; diff --git a/packages/react-dom/src/legacy-events/ReactSyntheticEventType.js b/packages/react-dom/src/events/ReactSyntheticEventType.js similarity index 86% rename from packages/react-dom/src/legacy-events/ReactSyntheticEventType.js rename to packages/react-dom/src/events/ReactSyntheticEventType.js index 1bc167afe0..7777a11c8c 100644 --- a/packages/react-dom/src/legacy-events/ReactSyntheticEventType.js +++ b/packages/react-dom/src/events/ReactSyntheticEventType.js @@ -33,12 +33,6 @@ export type CustomDispatchConfig = {| export type ReactSyntheticEvent = {| dispatchConfig: DispatchConfig | CustomDispatchConfig, - getPooled: ( - dispatchConfig: DispatchConfig | CustomDispatchConfig, - targetInst: Fiber, - nativeTarget: Event, - nativeEventTarget: EventTarget, - ) => ReactSyntheticEvent, isPersistent: () => boolean, isPropagationStopped: () => boolean, _dispatchInstances?: null | Array | Fiber, diff --git a/packages/react-dom/src/events/SyntheticAnimationEvent.js b/packages/react-dom/src/events/SyntheticAnimationEvent.js index e5a161cb6f..9409bd129c 100644 --- a/packages/react-dom/src/events/SyntheticAnimationEvent.js +++ b/packages/react-dom/src/events/SyntheticAnimationEvent.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import SyntheticEvent from '../legacy-events/SyntheticEvent'; +import SyntheticEvent from '../events/SyntheticEvent'; /** * @interface Event diff --git a/packages/react-dom/src/events/SyntheticClipboardEvent.js b/packages/react-dom/src/events/SyntheticClipboardEvent.js index bcab0e926c..f886c9ced7 100644 --- a/packages/react-dom/src/events/SyntheticClipboardEvent.js +++ b/packages/react-dom/src/events/SyntheticClipboardEvent.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import SyntheticEvent from '../legacy-events/SyntheticEvent'; +import SyntheticEvent from '../events/SyntheticEvent'; /** * @interface Event diff --git a/packages/react-dom/src/events/SyntheticCompositionEvent.js b/packages/react-dom/src/events/SyntheticCompositionEvent.js index afe88b4028..556c6e5f79 100644 --- a/packages/react-dom/src/events/SyntheticCompositionEvent.js +++ b/packages/react-dom/src/events/SyntheticCompositionEvent.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import SyntheticEvent from '../legacy-events/SyntheticEvent'; +import SyntheticEvent from '../events/SyntheticEvent'; /** * @interface Event diff --git a/packages/react-dom/src/legacy-events/SyntheticEvent.js b/packages/react-dom/src/events/SyntheticEvent.js similarity index 81% rename from packages/react-dom/src/legacy-events/SyntheticEvent.js rename to packages/react-dom/src/events/SyntheticEvent.js index de8b2cfc31..950fee5942 100644 --- a/packages/react-dom/src/legacy-events/SyntheticEvent.js +++ b/packages/react-dom/src/events/SyntheticEvent.js @@ -60,15 +60,6 @@ function SyntheticEvent( nativeEvent, nativeEventTarget, ) { - if (__DEV__) { - // these have a getter/setter for warnings - delete this.nativeEvent; - delete this.preventDefault; - delete this.stopPropagation; - delete this.isDefaultPrevented; - delete this.isPropagationStopped; - } - this.dispatchConfig = dispatchConfig; this._targetInst = targetInst; this.nativeEvent = nativeEvent; @@ -78,9 +69,6 @@ function SyntheticEvent( if (!Interface.hasOwnProperty(propName)) { continue; } - if (__DEV__) { - delete this[propName]; // this has a getter/setter for warnings - } const normalize = Interface[propName]; if (normalize) { this[propName] = normalize(nativeEvent); @@ -157,14 +145,6 @@ Object.assign(SyntheticEvent.prototype, { * @return {boolean} True if this should not be released, false otherwise. */ isPersistent: functionThatReturnsTrue, - - /** - * `PooledClass` looks for `destructor` on each instance it releases. - */ - destructor: function() { - // Modern event system doesn't use pooling. - // TODO: remove calls to this. - }, }); SyntheticEvent.Interface = EventInterface; @@ -188,34 +168,8 @@ SyntheticEvent.extend = function(Interface) { Class.Interface = Object.assign({}, Super.Interface, Interface); Class.extend = Super.extend; - addEventPoolingTo(Class); return Class; }; -addEventPoolingTo(SyntheticEvent); - -function createOrGetPooledEvent( - dispatchConfig, - targetInst, - nativeEvent, - nativeInst, -) { - const EventConstructor = this; - // Modern event system doesn't use pooling. - // TODO: remove this indirection. - return new EventConstructor( - dispatchConfig, - targetInst, - nativeEvent, - nativeInst, - ); -} - -function addEventPoolingTo(EventConstructor) { - EventConstructor.getPooled = createOrGetPooledEvent; - // Modern event system doesn't use pooling. - // TODO: remove calls to this. -} - export default SyntheticEvent; diff --git a/packages/react-dom/src/events/SyntheticInputEvent.js b/packages/react-dom/src/events/SyntheticInputEvent.js index 1e98175935..e4803b17aa 100644 --- a/packages/react-dom/src/events/SyntheticInputEvent.js +++ b/packages/react-dom/src/events/SyntheticInputEvent.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import SyntheticEvent from '../legacy-events/SyntheticEvent'; +import SyntheticEvent from '../events/SyntheticEvent'; /** * @interface Event diff --git a/packages/react-dom/src/events/SyntheticTransitionEvent.js b/packages/react-dom/src/events/SyntheticTransitionEvent.js index 654d846d9a..cffd41f6af 100644 --- a/packages/react-dom/src/events/SyntheticTransitionEvent.js +++ b/packages/react-dom/src/events/SyntheticTransitionEvent.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import SyntheticEvent from '../legacy-events/SyntheticEvent'; +import SyntheticEvent from '../events/SyntheticEvent'; /** * @interface Event diff --git a/packages/react-dom/src/events/SyntheticUIEvent.js b/packages/react-dom/src/events/SyntheticUIEvent.js index 488ab41190..9eb2561e5d 100644 --- a/packages/react-dom/src/events/SyntheticUIEvent.js +++ b/packages/react-dom/src/events/SyntheticUIEvent.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import SyntheticEvent from '../legacy-events/SyntheticEvent'; +import SyntheticEvent from '../events/SyntheticEvent'; const SyntheticUIEvent = SyntheticEvent.extend({ view: null, diff --git a/packages/react-dom/src/legacy-events/TopLevelEventTypes.js b/packages/react-dom/src/events/TopLevelEventTypes.js similarity index 71% rename from packages/react-dom/src/legacy-events/TopLevelEventTypes.js rename to packages/react-dom/src/events/TopLevelEventTypes.js index ce64f7a8e5..e4f2aefa90 100644 --- a/packages/react-dom/src/legacy-events/TopLevelEventTypes.js +++ b/packages/react-dom/src/events/TopLevelEventTypes.js @@ -7,17 +7,6 @@ * @flow */ -export type RNTopLevelEventType = - | 'topMouseDown' - | 'topMouseMove' - | 'topMouseUp' - | 'topScroll' - | 'topSelectionChange' - | 'topTouchCancel' - | 'topTouchEnd' - | 'topTouchMove' - | 'topTouchStart'; - export opaque type DOMTopLevelEventType = string; // Do not use the below two methods directly! @@ -36,4 +25,4 @@ export function unsafeCastDOMTopLevelTypeToString( return topLevelType; } -export type TopLevelType = DOMTopLevelEventType | RNTopLevelEventType; +export type TopLevelType = DOMTopLevelEventType; diff --git a/packages/react-dom/src/events/getEventModifierState.js b/packages/react-dom/src/events/getEventModifierState.js index 8a3f2f29f6..74f4f94049 100644 --- a/packages/react-dom/src/events/getEventModifierState.js +++ b/packages/react-dom/src/events/getEventModifierState.js @@ -12,7 +12,7 @@ * @see http://www.w3.org/TR/DOM-Level-3-Events/#keys-Modifiers */ -import type {AnyNativeEvent} from '../legacy-events/PluginModuleType'; +import type {AnyNativeEvent} from '../events/PluginModuleType'; const modifierKeyToProp = { Alt: 'altKey', diff --git a/packages/react-dom/src/events/plugins/ModernBeforeInputEventPlugin.js b/packages/react-dom/src/events/plugins/ModernBeforeInputEventPlugin.js index 1bbf54bde9..b8627d9261 100644 --- a/packages/react-dom/src/events/plugins/ModernBeforeInputEventPlugin.js +++ b/packages/react-dom/src/events/plugins/ModernBeforeInputEventPlugin.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import type {TopLevelType} from '../../legacy-events/TopLevelEventTypes'; +import type {TopLevelType} from '../../events/TopLevelEventTypes'; import {canUseDOM} from 'shared/ExecutionEnvironment'; @@ -259,7 +259,7 @@ function extractCompositionEvent( } } - const event = SyntheticCompositionEvent.getPooled( + const event = new SyntheticCompositionEvent( eventType, null, nativeEvent, @@ -429,7 +429,7 @@ function extractBeforeInputEvent( return null; } - const event = SyntheticInputEvent.getPooled( + const event = new SyntheticInputEvent( eventTypes.beforeInput, null, nativeEvent, diff --git a/packages/react-dom/src/events/plugins/ModernChangeEventPlugin.js b/packages/react-dom/src/events/plugins/ModernChangeEventPlugin.js index ee47a22806..3c6d1442f9 100644 --- a/packages/react-dom/src/events/plugins/ModernChangeEventPlugin.js +++ b/packages/react-dom/src/events/plugins/ModernChangeEventPlugin.js @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import SyntheticEvent from '../../legacy-events/SyntheticEvent'; +import SyntheticEvent from '../../events/SyntheticEvent'; import isTextInputElement from '../isTextInputElement'; import {canUseDOM} from 'shared/ExecutionEnvironment'; @@ -58,7 +58,7 @@ function createAndAccumulateChangeEvent( nativeEvent, target, ) { - const event = SyntheticEvent.getPooled( + const event = new SyntheticEvent( eventTypes.change, null, nativeEvent, diff --git a/packages/react-dom/src/events/plugins/ModernEnterLeaveEventPlugin.js b/packages/react-dom/src/events/plugins/ModernEnterLeaveEventPlugin.js index 679d3897d2..545df1e475 100644 --- a/packages/react-dom/src/events/plugins/ModernEnterLeaveEventPlugin.js +++ b/packages/react-dom/src/events/plugins/ModernEnterLeaveEventPlugin.js @@ -145,7 +145,7 @@ const EnterLeaveEventPlugin = { const fromNode = from == null ? win : getNodeFromInstance(from); const toNode = to == null ? win : getNodeFromInstance(to); - const leave = eventInterface.getPooled( + const leave = new eventInterface( leaveEventType, from, nativeEvent, @@ -155,7 +155,7 @@ const EnterLeaveEventPlugin = { leave.target = fromNode; leave.relatedTarget = toNode; - let enter = eventInterface.getPooled( + let enter = new eventInterface( enterEventType, to, nativeEvent, diff --git a/packages/react-dom/src/events/plugins/ModernSelectEventPlugin.js b/packages/react-dom/src/events/plugins/ModernSelectEventPlugin.js index 9761593a28..d272fec09e 100644 --- a/packages/react-dom/src/events/plugins/ModernSelectEventPlugin.js +++ b/packages/react-dom/src/events/plugins/ModernSelectEventPlugin.js @@ -6,7 +6,7 @@ */ import {canUseDOM} from 'shared/ExecutionEnvironment'; -import SyntheticEvent from '../../legacy-events/SyntheticEvent'; +import SyntheticEvent from '../../events/SyntheticEvent'; import isTextInputElement from '../isTextInputElement'; import shallowEqual from 'shared/shallowEqual'; @@ -132,7 +132,7 @@ function constructSelectEvent(dispatchQueue, nativeEvent, nativeEventTarget) { if (!lastSelection || !shallowEqual(lastSelection, currentSelection)) { lastSelection = currentSelection; - const syntheticEvent = SyntheticEvent.getPooled( + const syntheticEvent = new SyntheticEvent( eventTypes.select, null, nativeEvent, diff --git a/packages/react-dom/src/events/plugins/ModernSimpleEventPlugin.js b/packages/react-dom/src/events/plugins/ModernSimpleEventPlugin.js index 27db617a5b..7aa1bf0ac3 100644 --- a/packages/react-dom/src/events/plugins/ModernSimpleEventPlugin.js +++ b/packages/react-dom/src/events/plugins/ModernSimpleEventPlugin.js @@ -10,15 +10,15 @@ import type { TopLevelType, DOMTopLevelEventType, -} from '../../legacy-events/TopLevelEventTypes'; +} from '../../events/TopLevelEventTypes'; import type {Fiber} from 'react-reconciler/src/ReactInternalTypes'; import type { ModernPluginModule, DispatchQueue, -} from '../../legacy-events/PluginModuleType'; +} from '../../events/PluginModuleType'; import type {EventSystemFlags} from '../EventSystemFlags'; -import SyntheticEvent from '../../legacy-events/SyntheticEvent'; +import SyntheticEvent from '../../events/SyntheticEvent'; import * as DOMTopLevelEventTypes from '../DOMTopLevelEventTypes'; import { @@ -200,7 +200,7 @@ const SimpleEventPlugin: ModernPluginModule = { EventConstructor = SyntheticEvent; break; } - const event = EventConstructor.getPooled( + const event = new EventConstructor( dispatchConfig, null, nativeEvent, diff --git a/packages/react-dom/src/legacy-events/EventPluginRegistry.js b/packages/react-dom/src/legacy-events/EventPluginRegistry.js deleted file mode 100644 index 7c22ebbcbc..0000000000 --- a/packages/react-dom/src/legacy-events/EventPluginRegistry.js +++ /dev/null @@ -1,270 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - */ - -import type {DispatchConfig} from './ReactSyntheticEventType'; -import type { - AnyNativeEvent, - PluginName, - LegacyPluginModule, - ModernPluginModule, -} from './PluginModuleType'; - -import invariant from 'shared/invariant'; - -type NamesToPlugins = { - [key: PluginName]: - | LegacyPluginModule - | ModernPluginModule, - ..., -}; -type EventPluginOrder = null | Array; - -/** - * Injectable ordering of event plugins. - */ -let eventPluginOrder: EventPluginOrder = null; - -/** - * Injectable mapping from names to event plugin modules. - */ -const namesToPlugins: NamesToPlugins = {}; - -/** - * Recomputes the plugin list using the injected plugins and plugin ordering. - * - * @private - */ -function recomputePluginOrdering(): void { - if (!eventPluginOrder) { - // Wait until an `eventPluginOrder` is injected. - return; - } - for (const pluginName in namesToPlugins) { - const pluginModule = namesToPlugins[pluginName]; - const pluginIndex = eventPluginOrder.indexOf(pluginName); - invariant( - pluginIndex > -1, - 'EventPluginRegistry: Cannot inject event plugins that do not exist in ' + - 'the plugin ordering, `%s`.', - pluginName, - ); - if (plugins[pluginIndex]) { - continue; - } - invariant( - pluginModule.extractEvents, - 'EventPluginRegistry: Event plugins must implement an `extractEvents` ' + - 'method, but `%s` does not.', - pluginName, - ); - plugins[pluginIndex] = pluginModule; - const publishedEvents = pluginModule.eventTypes; - for (const eventName in publishedEvents) { - invariant( - publishEventForPlugin( - publishedEvents[eventName], - pluginModule, - eventName, - ), - 'EventPluginRegistry: Failed to publish event `%s` for plugin `%s`.', - eventName, - pluginName, - ); - } - } -} - -/** - * Publishes an event so that it can be dispatched by the supplied plugin. - * - * @param {object} dispatchConfig Dispatch configuration for the event. - * @param {object} PluginModule Plugin publishing the event. - * @return {boolean} True if the event was successfully published. - * @private - */ -function publishEventForPlugin( - dispatchConfig: DispatchConfig, - pluginModule: - | LegacyPluginModule - | ModernPluginModule, - eventName: string, -): boolean { - invariant( - !eventNameDispatchConfigs.hasOwnProperty(eventName), - 'EventPluginRegistry: More than one plugin attempted to publish the same ' + - 'event name, `%s`.', - eventName, - ); - eventNameDispatchConfigs[eventName] = dispatchConfig; - - const phasedRegistrationNames = dispatchConfig.phasedRegistrationNames; - if (phasedRegistrationNames) { - for (const phaseName in phasedRegistrationNames) { - if (phasedRegistrationNames.hasOwnProperty(phaseName)) { - const phasedRegistrationName = phasedRegistrationNames[phaseName]; - publishRegistrationName( - phasedRegistrationName, - pluginModule, - eventName, - ); - } - } - return true; - } else if (dispatchConfig.registrationName) { - publishRegistrationName( - dispatchConfig.registrationName, - pluginModule, - eventName, - ); - return true; - } - return false; -} - -/** - * Publishes a registration name that is used to identify dispatched events. - * - * @param {string} registrationName Registration name to add. - * @param {object} PluginModule Plugin publishing the event. - * @private - */ -function publishRegistrationName( - registrationName: string, - pluginModule: - | LegacyPluginModule - | ModernPluginModule, - eventName: string, -): void { - invariant( - !registrationNameModules[registrationName], - 'EventPluginRegistry: More than one plugin attempted to publish the same ' + - 'registration name, `%s`.', - registrationName, - ); - registrationNameModules[registrationName] = pluginModule; - registrationNameDependencies[registrationName] = - pluginModule.eventTypes[eventName].dependencies; - - if (__DEV__) { - const lowerCasedName = registrationName.toLowerCase(); - possibleRegistrationNames[lowerCasedName] = registrationName; - - if (registrationName === 'onDoubleClick') { - possibleRegistrationNames.ondblclick = registrationName; - } - } -} - -/** - * Registers plugins so that they can extract and dispatch events. - */ - -/** - * Ordered list of injected plugins. - */ -export const plugins = []; - -/** - * Mapping from event name to dispatch config - */ -export const eventNameDispatchConfigs = {}; - -/** - * Mapping from registration name to plugin module - */ -export const registrationNameModules = {}; - -/** - * Mapping from registration name to event name - */ -export const registrationNameDependencies = {}; - -/** - * Mapping from lowercase registration names to the properly cased version, - * used to warn in the case of missing event handlers. Available - * only in __DEV__. - * @type {Object} - */ -export const possibleRegistrationNames = __DEV__ ? {} : (null: any); -// Trust the developer to only use possibleRegistrationNames in __DEV__ - -/** - * Injects an ordering of plugins (by plugin name). This allows the ordering - * to be decoupled from injection of the actual plugins so that ordering is - * always deterministic regardless of packaging, on-the-fly injection, etc. - * - * @param {array} InjectedEventPluginOrder - * @internal - */ -export function injectEventPluginOrder( - injectedEventPluginOrder: EventPluginOrder, -): void { - invariant( - !eventPluginOrder, - 'EventPluginRegistry: Cannot inject event plugin ordering more than ' + - 'once. You are likely trying to load more than one copy of React.', - ); - // Clone the ordering so it cannot be dynamically mutated. - eventPluginOrder = Array.prototype.slice.call(injectedEventPluginOrder); - recomputePluginOrdering(); -} - -/** - * Injects plugins to be used by plugin event system. The plugin names must be - * in the ordering injected by `injectEventPluginOrder`. - * - * Plugins can be injected as part of page initialization or on-the-fly. - * - * @param {object} injectedNamesToPlugins Map from names to plugin modules. - * @internal - */ -export function injectEventPluginsByName( - injectedNamesToPlugins: NamesToPlugins, -): void { - let isOrderingDirty = false; - for (const pluginName in injectedNamesToPlugins) { - if (!injectedNamesToPlugins.hasOwnProperty(pluginName)) { - continue; - } - const pluginModule = injectedNamesToPlugins[pluginName]; - if ( - !namesToPlugins.hasOwnProperty(pluginName) || - namesToPlugins[pluginName] !== pluginModule - ) { - invariant( - !namesToPlugins[pluginName], - 'EventPluginRegistry: Cannot inject two different event plugins ' + - 'using the same name, `%s`.', - pluginName, - ); - namesToPlugins[pluginName] = pluginModule; - isOrderingDirty = true; - } - } - if (isOrderingDirty) { - recomputePluginOrdering(); - } -} - -export function injectEventPlugins( - eventPlugins: [ModernPluginModule], -): void { - for (let i = 0; i < eventPlugins.length; i++) { - const pluginModule = eventPlugins[i]; - plugins.push(pluginModule); - const publishedEvents = pluginModule.eventTypes; - for (const eventName in publishedEvents) { - publishEventForPlugin( - publishedEvents[eventName], - pluginModule, - eventName, - ); - } - } -} diff --git a/packages/react-dom/src/legacy-events/EventPluginUtils.js b/packages/react-dom/src/legacy-events/EventPluginUtils.js deleted file mode 100644 index abba8e9a3d..0000000000 --- a/packages/react-dom/src/legacy-events/EventPluginUtils.js +++ /dev/null @@ -1,172 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -import {invokeGuardedCallbackAndCatchFirstError} from 'shared/ReactErrorUtils'; -import invariant from 'shared/invariant'; - -export let getFiberCurrentPropsFromNode = null; -export let getInstanceFromNode = null; -export let getNodeFromInstance = null; - -export function setComponentTree( - getFiberCurrentPropsFromNodeImpl, - getInstanceFromNodeImpl, - getNodeFromInstanceImpl, -) { - getFiberCurrentPropsFromNode = getFiberCurrentPropsFromNodeImpl; - getInstanceFromNode = getInstanceFromNodeImpl; - getNodeFromInstance = getNodeFromInstanceImpl; - if (__DEV__) { - if (!getNodeFromInstance || !getInstanceFromNode) { - console.error( - 'EventPluginUtils.setComponentTree(...): Injected ' + - 'module is missing getNodeFromInstance or getInstanceFromNode.', - ); - } - } -} - -let validateEventDispatches; -if (__DEV__) { - validateEventDispatches = function(event) { - const dispatchListeners = event._dispatchListeners; - const dispatchInstances = event._dispatchInstances; - - const listenersIsArr = Array.isArray(dispatchListeners); - const listenersLen = listenersIsArr - ? dispatchListeners.length - : dispatchListeners - ? 1 - : 0; - - const instancesIsArr = Array.isArray(dispatchInstances); - const instancesLen = instancesIsArr - ? dispatchInstances.length - : dispatchInstances - ? 1 - : 0; - - if (instancesIsArr !== listenersIsArr || instancesLen !== listenersLen) { - console.error('EventPluginUtils: Invalid `event`.'); - } - }; -} - -/** - * Dispatch the event to the listener. - * @param {SyntheticEvent} event SyntheticEvent to handle - * @param {function} listener Application-level callback - * @param {*} inst Internal component instance - */ -export function executeDispatch(event, listener, inst) { - const type = event.type || 'unknown-event'; - event.currentTarget = getNodeFromInstance(inst); - invokeGuardedCallbackAndCatchFirstError(type, listener, undefined, event); - event.currentTarget = null; -} - -/** - * Standard/simple iteration through an event's collected dispatches. - */ -export function executeDispatchesInOrder(event) { - const dispatchListeners = event._dispatchListeners; - const dispatchInstances = event._dispatchInstances; - if (__DEV__) { - validateEventDispatches(event); - } - if (Array.isArray(dispatchListeners)) { - for (let i = 0; i < dispatchListeners.length; i++) { - if (event.isPropagationStopped()) { - break; - } - // Listeners and Instances are two parallel arrays that are always in sync. - executeDispatch(event, dispatchListeners[i], dispatchInstances[i]); - } - } else if (dispatchListeners) { - executeDispatch(event, dispatchListeners, dispatchInstances); - } - event._dispatchListeners = null; - event._dispatchInstances = null; -} - -/** - * Standard/simple iteration through an event's collected dispatches, but stops - * at the first dispatch execution returning true, and returns that id. - * - * @return {?string} id of the first dispatch execution who's listener returns - * true, or null if no listener returned true. - */ -function executeDispatchesInOrderStopAtTrueImpl(event) { - const dispatchListeners = event._dispatchListeners; - const dispatchInstances = event._dispatchInstances; - if (__DEV__) { - validateEventDispatches(event); - } - if (Array.isArray(dispatchListeners)) { - for (let i = 0; i < dispatchListeners.length; i++) { - if (event.isPropagationStopped()) { - break; - } - // Listeners and Instances are two parallel arrays that are always in sync. - if (dispatchListeners[i](event, dispatchInstances[i])) { - return dispatchInstances[i]; - } - } - } else if (dispatchListeners) { - if (dispatchListeners(event, dispatchInstances)) { - return dispatchInstances; - } - } - return null; -} - -/** - * @see executeDispatchesInOrderStopAtTrueImpl - */ -export function executeDispatchesInOrderStopAtTrue(event) { - const ret = executeDispatchesInOrderStopAtTrueImpl(event); - event._dispatchInstances = null; - event._dispatchListeners = null; - return ret; -} - -/** - * Execution of a "direct" dispatch - there must be at most one dispatch - * accumulated on the event or it is considered an error. It doesn't really make - * sense for an event with multiple dispatches (bubbled) to keep track of the - * return values at each dispatch execution, but it does tend to make sense when - * dealing with "direct" dispatches. - * - * @return {*} The return value of executing the single dispatch. - */ -export function executeDirectDispatch(event) { - if (__DEV__) { - validateEventDispatches(event); - } - const dispatchListener = event._dispatchListeners; - const dispatchInstance = event._dispatchInstances; - invariant( - !Array.isArray(dispatchListener), - 'executeDirectDispatch(...): Invalid `event`.', - ); - event.currentTarget = dispatchListener - ? getNodeFromInstance(dispatchInstance) - : null; - const res = dispatchListener ? dispatchListener(event) : null; - event.currentTarget = null; - event._dispatchListeners = null; - event._dispatchInstances = null; - return res; -} - -/** - * @param {SyntheticEvent} event - * @return {boolean} True iff number of dispatches accumulated is greater than 0. - */ -export function hasDispatches(event) { - return !!event._dispatchListeners; -} diff --git a/packages/react-dom/src/legacy-events/accumulateInto.js b/packages/react-dom/src/legacy-events/accumulateInto.js deleted file mode 100644 index 35625311da..0000000000 --- a/packages/react-dom/src/legacy-events/accumulateInto.js +++ /dev/null @@ -1,57 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - */ - -import invariant from 'shared/invariant'; - -/** - * Accumulates items that must not be null or undefined into the first one. This - * is used to conserve memory by avoiding array allocations, and thus sacrifices - * API cleanness. Since `current` can be null before being passed in and not - * null after this function, make sure to assign it back to `current`: - * - * `a = accumulateInto(a, b);` - * - * This API should be sparingly used. Try `accumulate` for something cleaner. - * - * @return {*|array<*>} An accumulation of items. - */ - -function accumulateInto( - current: ?(Array | T), - next: T | Array, -): T | Array { - invariant( - next != null, - 'accumulateInto(...): Accumulated items must not be null or undefined.', - ); - - if (current == null) { - return next; - } - - // Both are not empty. Warning: Never call x.concat(y) when you are not - // certain that x is an Array (x could be a string with concat method). - if (Array.isArray(current)) { - if (Array.isArray(next)) { - current.push.apply(current, next); - return current; - } - current.push(next); - return current; - } - - if (Array.isArray(next)) { - // A bit too dangerous to mutate `next`. - return [current].concat(next); - } - - return [current, next]; -} - -export default accumulateInto; diff --git a/packages/react-dom/src/legacy-events/forEachAccumulated.js b/packages/react-dom/src/legacy-events/forEachAccumulated.js deleted file mode 100644 index 369be5605c..0000000000 --- a/packages/react-dom/src/legacy-events/forEachAccumulated.js +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - */ - -/** - * @param {array} arr an "accumulation" of items which is either an Array or - * a single item. Useful when paired with the `accumulate` module. This is a - * simple utility that allows us to reason about a collection of items, but - * handling the case when there is exactly one item (and we do not need to - * allocate an array). - * @param {function} cb Callback invoked with each element or a collection. - * @param {?} [scope] Scope used as `this` in a callback. - */ -function forEachAccumulated( - arr: ?(Array | T), - cb: (elem: T) => void, - scope: ?any, -) { - if (Array.isArray(arr)) { - arr.forEach(cb, scope); - } else if (arr) { - cb.call(scope, arr); - } -} - -export default forEachAccumulated; diff --git a/packages/react-dom/src/server/ReactPartialRenderer.js b/packages/react-dom/src/server/ReactPartialRenderer.js index 63693ed1b5..79e411d7f0 100644 --- a/packages/react-dom/src/server/ReactPartialRenderer.js +++ b/packages/react-dom/src/server/ReactPartialRenderer.js @@ -114,7 +114,7 @@ if (__DEV__) { validatePropertiesInDevelopment = function(type, props) { validateARIAProperties(type, props); validateInputProperties(type, props); - validateUnknownProperties(type, props, /* canUseEventSystem */ false); + validateUnknownProperties(type, props, null); }; describeStackFrame = function(element): string { diff --git a/packages/react-dom/src/shared/ReactDOMTypes.js b/packages/react-dom/src/shared/ReactDOMTypes.js index f1f548c82e..3a04da5201 100644 --- a/packages/react-dom/src/shared/ReactDOMTypes.js +++ b/packages/react-dom/src/shared/ReactDOMTypes.js @@ -14,7 +14,7 @@ import type { EventPriority, ReactScopeInstance, } from 'shared/ReactTypes'; -import type {DOMTopLevelEventType} from '../legacy-events/TopLevelEventTypes'; +import type {DOMTopLevelEventType} from '../events/TopLevelEventTypes'; type AnyNativeEvent = Event | KeyboardEvent | MouseEvent | Touch; diff --git a/packages/react-dom/src/shared/ReactDOMUnknownPropertyHook.js b/packages/react-dom/src/shared/ReactDOMUnknownPropertyHook.js index f1eb971e2b..eab24b20d7 100644 --- a/packages/react-dom/src/shared/ReactDOMUnknownPropertyHook.js +++ b/packages/react-dom/src/shared/ReactDOMUnknownPropertyHook.js @@ -5,11 +5,6 @@ * LICENSE file in the root directory of this source tree. */ -import { - registrationNameModules, - possibleRegistrationNames, -} from '../legacy-events/EventPluginRegistry'; - import { ATTRIBUTE_NAME_CHAR, BOOLEAN, @@ -30,7 +25,7 @@ if (__DEV__) { const rARIA = new RegExp('^(aria)-[' + ATTRIBUTE_NAME_CHAR + ']*$'); const rARIACamel = new RegExp('^(aria)[A-Z][' + ATTRIBUTE_NAME_CHAR + ']*$'); - validateProperty = function(tagName, name, value, canUseEventSystem) { + validateProperty = function(tagName, name, value, eventRegistry) { if (hasOwnProperty.call(warnedProperties, name) && warnedProperties[name]) { return true; } @@ -47,7 +42,11 @@ if (__DEV__) { } // We can't rely on the event system being injected on the server. - if (canUseEventSystem) { + if (eventRegistry != null) { + const { + registrationNameModules, + possibleRegistrationNames, + } = eventRegistry; if (registrationNameModules.hasOwnProperty(name)) { return true; } @@ -240,16 +239,11 @@ if (__DEV__) { }; } -const warnUnknownProperties = function(type, props, canUseEventSystem) { +const warnUnknownProperties = function(type, props, eventRegistry) { if (__DEV__) { const unknownProps = []; for (const key in props) { - const isValid = validateProperty( - type, - key, - props[key], - canUseEventSystem, - ); + const isValid = validateProperty(type, key, props[key], eventRegistry); if (!isValid) { unknownProps.push(key); } @@ -278,9 +272,9 @@ const warnUnknownProperties = function(type, props, canUseEventSystem) { } }; -export function validateProperties(type, props, canUseEventSystem) { +export function validateProperties(type, props, eventRegistry) { if (isCustomComponent(type, props)) { return; } - warnUnknownProperties(type, props, canUseEventSystem); + warnUnknownProperties(type, props, eventRegistry); } diff --git a/packages/react-dom/src/test-utils/ReactTestUtils.js b/packages/react-dom/src/test-utils/ReactTestUtils.js index a42df39b31..54de14b032 100644 --- a/packages/react-dom/src/test-utils/ReactTestUtils.js +++ b/packages/react-dom/src/test-utils/ReactTestUtils.js @@ -15,12 +15,10 @@ import { HostComponent, HostText, } from 'react-reconciler/src/ReactWorkTags'; -import SyntheticEvent from '../legacy-events/SyntheticEvent'; +import SyntheticEvent from '../events/SyntheticEvent'; import invariant from 'shared/invariant'; import {ELEMENT_NODE} from '../shared/HTMLNodeType'; import act from './ReactTestUtilsAct'; -import forEachAccumulated from '../legacy-events/forEachAccumulated'; -import accumulateInto from '../legacy-events/accumulateInto'; import { rethrowCaughtError, invokeGuardedCallbackAndCatchFirstError, @@ -32,13 +30,12 @@ const [ /* eslint-disable no-unused-vars */ getNodeFromInstance, getFiberCurrentPropsFromNode, - injectEventPluginsByName, /* eslint-enable no-unused-vars */ eventNameDispatchConfigs, enqueueStateRestore, - restoreStateIfNeeded /* eslint-disable no-unused-vars */, // TODO: remove. - , - /* dispatchEvent */ flushPassiveEffects, + restoreStateIfNeeded, + /* eslint-disable no-unused-vars */ + flushPassiveEffects, IsThisRendererActing, /* eslint-enable no-unused-vars */ ] = ReactDOM.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.Events; @@ -386,12 +383,6 @@ function executeDispatchesInOrder(event) { event._dispatchInstances = null; } -/** - * Internal queue of events that have accumulated their dispatches and are - * waiting to have their dispatches executed. - */ -let eventQueue: ?(Array | ReactSyntheticEvent) = null; - /** * Dispatches an event and releases it back into the pool, unless persistent. * @@ -408,36 +399,6 @@ const executeDispatchesAndRelease = function(event: ReactSyntheticEvent) { } }; -const executeDispatchesAndReleaseTopLevel = function(e) { - return executeDispatchesAndRelease(e); -}; - -function runEventsInBatch( - events: Array | ReactSyntheticEvent | null, -) { - if (events !== null) { - eventQueue = accumulateInto(eventQueue, events); - } - - // Set `eventQueue` to null before processing it so that we can tell if more - // events get enqueued while processing. - const processingEventQueue = eventQueue; - eventQueue = null; - - if (!processingEventQueue) { - return; - } - - forEachAccumulated(processingEventQueue, executeDispatchesAndReleaseTopLevel); - invariant( - !eventQueue, - 'processEventQueue(): Additional events were enqueued while processing ' + - 'an event queue. Support for this has not yet been implemented.', - ); - // This would be a good time to rethrow if any of the event handlers threw. - rethrowCaughtError(); -} - function isInteractive(tag) { return ( tag === 'button' || @@ -541,11 +502,14 @@ function accumulateDispatches(inst, ignoredDirection, event) { const registrationName = event.dispatchConfig.registrationName; const listener = getListener(inst, registrationName); if (listener) { - event._dispatchListeners = accumulateInto( - event._dispatchListeners, - listener, - ); - event._dispatchInstances = accumulateInto(event._dispatchInstances, inst); + if (event._dispatchListeners == null) { + event._dispatchListeners = []; + } + if (event._dispatchInstances == null) { + event._dispatchInstances = []; + } + event._dispatchListeners.push(listener); + event._dispatchInstances.push(inst); } } } @@ -558,11 +522,14 @@ function accumulateDirectionalDispatches(inst, phase, event) { } const listener = listenerAtPhase(inst, event, phase); if (listener) { - event._dispatchListeners = accumulateInto( - event._dispatchListeners, - listener, - ); - event._dispatchInstances = accumulateInto(event._dispatchInstances, inst); + if (event._dispatchListeners == null) { + event._dispatchListeners = []; + } + if (event._dispatchInstances == null) { + event._dispatchInstances = []; + } + event._dispatchListeners.push(listener); + event._dispatchInstances.push(inst); } } @@ -572,23 +539,15 @@ function accumulateDirectDispatchesSingle(event) { } } -function accumulateDirectDispatches(events) { - forEachAccumulated(events, accumulateDirectDispatchesSingle); -} - function accumulateTwoPhaseDispatchesSingle(event) { if (event && event.dispatchConfig.phasedRegistrationNames) { traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event); } } -function accumulateTwoPhaseDispatches(events) { - forEachAccumulated(events, accumulateTwoPhaseDispatchesSingle); -} // End of inline const Simulate = {}; -let SimulateNative; /** * Exports: @@ -618,8 +577,6 @@ function makeSimulator(eventType) { fakeNativeEvent.target = domNode; fakeNativeEvent.type = eventType.toLowerCase(); - // We don't use SyntheticEvent.getPooled in order to not have to worry about - // properly destroying any properties assigned from `eventData` upon release const targetInst = getInstanceFromNode(domNode); const event = new SyntheticEvent( dispatchConfig, @@ -634,16 +591,17 @@ function makeSimulator(eventType) { Object.assign(event, eventData); if (dispatchConfig.phasedRegistrationNames) { - accumulateTwoPhaseDispatches(event); + accumulateTwoPhaseDispatchesSingle(event); } else { - accumulateDirectDispatches(event); + accumulateDirectDispatchesSingle(event); } ReactDOM.unstable_batchedUpdates(function() { // Normally extractEvent enqueues a state restore, but we'll just always // do that since we're by-passing it here. enqueueStateRestore(domNode); - runEventsInBatch(event); + executeDispatchesAndRelease(event); + rethrowCaughtError(); }); restoreStateIfNeeded(); }; @@ -680,6 +638,5 @@ export { mockComponent, nativeTouchData, Simulate, - SimulateNative, act, }; diff --git a/packages/react-dom/src/test-utils/ReactTestUtilsAct.js b/packages/react-dom/src/test-utils/ReactTestUtilsAct.js index 39a249a098..6f43182171 100644 --- a/packages/react-dom/src/test-utils/ReactTestUtilsAct.js +++ b/packages/react-dom/src/test-utils/ReactTestUtilsAct.js @@ -20,11 +20,9 @@ const [ getInstanceFromNode, getNodeFromInstance, getFiberCurrentPropsFromNode, - injectEventPluginsByName, eventNameDispatchConfigs, enqueueStateRestore, restoreStateIfNeeded, - dispatchEvent, /* eslint-enable no-unused-vars */ flushPassiveEffects, IsThisRendererActing,