mirror of
https://github.com/zebrajr/react.git
synced 2026-01-15 12:15:22 +00:00
Remove dead code from modern event system (#19233)
* Remove dead code from modern event system * Remove SSR dependency on EventPluginRegistry
This commit is contained in:
9
packages/react-dom/src/client/ReactDOM.js
vendored
9
packages/react-dom/src/client/ReactDOM.js
vendored
@@ -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,
|
||||
],
|
||||
|
||||
@@ -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,
|
||||
]);
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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';
|
||||
|
||||
/**
|
||||
|
||||
@@ -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,
|
||||
|
||||
151
packages/react-dom/src/events/EventPluginRegistry.js
vendored
Normal file
151
packages/react-dom/src/events/EventPluginRegistry.js
vendored
Normal file
@@ -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<AnyNativeEvent>
|
||||
| ModernPluginModule<AnyNativeEvent>,
|
||||
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<AnyNativeEvent>
|
||||
| ModernPluginModule<AnyNativeEvent>,
|
||||
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<any>): 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);
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 | null> | Fiber,
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
@@ -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',
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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<MouseEvent> = {
|
||||
EventConstructor = SyntheticEvent;
|
||||
break;
|
||||
}
|
||||
const event = EventConstructor.getPooled(
|
||||
const event = new EventConstructor(
|
||||
dispatchConfig,
|
||||
null,
|
||||
nativeEvent,
|
||||
|
||||
@@ -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<AnyNativeEvent>
|
||||
| ModernPluginModule<AnyNativeEvent>,
|
||||
...,
|
||||
};
|
||||
type EventPluginOrder = null | Array<PluginName>;
|
||||
|
||||
/**
|
||||
* 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<AnyNativeEvent>
|
||||
| ModernPluginModule<AnyNativeEvent>,
|
||||
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<AnyNativeEvent>
|
||||
| ModernPluginModule<AnyNativeEvent>,
|
||||
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<AnyNativeEvent>],
|
||||
): 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,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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<T>(
|
||||
current: ?(Array<T> | T),
|
||||
next: T | Array<T>,
|
||||
): T | Array<T> {
|
||||
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;
|
||||
@@ -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<T>(
|
||||
arr: ?(Array<T> | 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;
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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> | 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> | 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,
|
||||
};
|
||||
|
||||
@@ -20,11 +20,9 @@ const [
|
||||
getInstanceFromNode,
|
||||
getNodeFromInstance,
|
||||
getFiberCurrentPropsFromNode,
|
||||
injectEventPluginsByName,
|
||||
eventNameDispatchConfigs,
|
||||
enqueueStateRestore,
|
||||
restoreStateIfNeeded,
|
||||
dispatchEvent,
|
||||
/* eslint-enable no-unused-vars */
|
||||
flushPassiveEffects,
|
||||
IsThisRendererActing,
|
||||
|
||||
Reference in New Issue
Block a user