Use named exports in more places (#11457)

* Convert EventPlugin{Hub,Registry} to named exports

* Convert EventPluginUtils to named exports

* Convert EventPropagators to named exports

* Convert ReactControlledComponent to named exports

* Convert ReactGenericBatching to named exports

* Convert ReactDOMComponentTree to named exports

* Convert ReactNativeComponentTree to named exports

* Convert ReactNativeRTComponentTree to named exports

* Convert FallbackCompositionState to named exports

* Convert ReactEventEmitterMixin to named exports

* Convert ReactBrowserEventEmitter to named exports

* Convert ReactNativeEventEmitter to named exports

* Convert ReactDOMEventListener to named exports

* Convert DOMMarkupOperations to named exports

* Convert DOMProperty to named exports

* Add suppression for existing Flow violation

Flow didn't see it before.

* Update sizes
This commit is contained in:
Dan Abramov 2017-11-05 11:58:36 +00:00 committed by GitHub
parent 7432013872
commit 92b7b172cc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
56 changed files with 1070 additions and 1357 deletions

View File

@ -8,8 +8,15 @@
import ReactErrorUtils from 'shared/ReactErrorUtils';
import invariant from 'fbjs/lib/invariant';
import EventPluginRegistry from './EventPluginRegistry';
import EventPluginUtils from './EventPluginUtils';
import {
injectEventPluginOrder,
injectEventPluginsByName,
plugins,
} from './EventPluginRegistry';
import {
executeDispatchesInOrder,
getFiberCurrentPropsFromNode,
} from './EventPluginUtils';
import accumulateInto from './accumulateInto';
import forEachAccumulated from './forEachAccumulated';
@ -28,7 +35,7 @@ var eventQueue = null;
*/
var executeDispatchesAndRelease = function(event, simulated) {
if (event) {
EventPluginUtils.executeDispatchesInOrder(event, simulated);
executeDispatchesInOrder(event, simulated);
if (!event.isPersistent()) {
event.constructor.release(event);
@ -91,131 +98,127 @@ function shouldPreventMouseEvent(name, type, props) {
*
* @public
*/
var EventPluginHub = {
/**
* Methods for injecting dependencies.
*/
injection: {
/**
* @param {array} InjectedEventPluginOrder
* @public
*/
injectEventPluginOrder: EventPluginRegistry.injectEventPluginOrder,
/**
* @param {object} injectedNamesToPlugins Map from names to plugin modules.
*/
injectEventPluginsByName: EventPluginRegistry.injectEventPluginsByName,
},
/**
* Methods for injecting dependencies.
*/
export const injection = {
/**
* @param {array} InjectedEventPluginOrder
* @public
*/
injectEventPluginOrder,
/**
* @param {object} inst The instance, which is the source of events.
* @param {string} registrationName Name of listener (e.g. `onClick`).
* @return {?function} The stored callback.
* @param {object} injectedNamesToPlugins Map from names to plugin modules.
*/
getListener: function(inst, registrationName) {
var listener;
// TODO: shouldPreventMouseEvent is DOM-specific and definitely should not
// live here; needs to be moved to a better place soon
const stateNode = inst.stateNode;
if (!stateNode) {
// Work in progress (ex: onload events in incremental mode).
return null;
}
const props = EventPluginUtils.getFiberCurrentPropsFromNode(stateNode);
if (!props) {
// Work in progress.
return null;
}
listener = props[registrationName];
if (shouldPreventMouseEvent(registrationName, inst.type, props)) {
return null;
}
invariant(
!listener || typeof listener === 'function',
'Expected `%s` listener to be a function, instead got a value of `%s` type.',
registrationName,
typeof listener,
);
return listener;
},
/**
* Allows registered plugins an opportunity to extract events from top-level
* native browser events.
*
* @return {*} An accumulation of synthetic events.
* @internal
*/
extractEvents: function(
topLevelType,
targetInst,
nativeEvent,
nativeEventTarget,
) {
var events;
var plugins = EventPluginRegistry.plugins;
for (var i = 0; i < plugins.length; i++) {
// Not every plugin in the ordering may be loaded at runtime.
var possiblePlugin = plugins[i];
if (possiblePlugin) {
var extractedEvents = possiblePlugin.extractEvents(
topLevelType,
targetInst,
nativeEvent,
nativeEventTarget,
);
if (extractedEvents) {
events = accumulateInto(events, extractedEvents);
}
}
}
return events;
},
/**
* Enqueues a synthetic event that should be dispatched when
* `processEventQueue` is invoked.
*
* @param {*} events An accumulation of synthetic events.
* @internal
*/
enqueueEvents: function(events) {
if (events) {
eventQueue = accumulateInto(eventQueue, events);
}
},
/**
* Dispatches all synthetic events on the event queue.
*
* @internal
*/
processEventQueue: function(simulated) {
// Set `eventQueue` to null before processing it so that we can tell if more
// events get enqueued while processing.
var processingEventQueue = eventQueue;
eventQueue = null;
if (simulated) {
forEachAccumulated(
processingEventQueue,
executeDispatchesAndReleaseSimulated,
);
} else {
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.
ReactErrorUtils.rethrowCaughtError();
},
injectEventPluginsByName,
};
export default EventPluginHub;
/**
* @param {object} inst The instance, which is the source of events.
* @param {string} registrationName Name of listener (e.g. `onClick`).
* @return {?function} The stored callback.
*/
export function getListener(inst, registrationName) {
var listener;
// TODO: shouldPreventMouseEvent is DOM-specific and definitely should not
// live here; needs to be moved to a better place soon
const stateNode = inst.stateNode;
if (!stateNode) {
// Work in progress (ex: onload events in incremental mode).
return null;
}
const props = getFiberCurrentPropsFromNode(stateNode);
if (!props) {
// Work in progress.
return null;
}
listener = props[registrationName];
if (shouldPreventMouseEvent(registrationName, inst.type, props)) {
return null;
}
invariant(
!listener || typeof listener === 'function',
'Expected `%s` listener to be a function, instead got a value of `%s` type.',
registrationName,
typeof listener,
);
return listener;
}
/**
* Allows registered plugins an opportunity to extract events from top-level
* native browser events.
*
* @return {*} An accumulation of synthetic events.
* @internal
*/
export function extractEvents(
topLevelType,
targetInst,
nativeEvent,
nativeEventTarget,
) {
var events;
for (var i = 0; i < plugins.length; i++) {
// Not every plugin in the ordering may be loaded at runtime.
var possiblePlugin = plugins[i];
if (possiblePlugin) {
var extractedEvents = possiblePlugin.extractEvents(
topLevelType,
targetInst,
nativeEvent,
nativeEventTarget,
);
if (extractedEvents) {
events = accumulateInto(events, extractedEvents);
}
}
}
return events;
}
/**
* Enqueues a synthetic event that should be dispatched when
* `processEventQueue` is invoked.
*
* @param {*} events An accumulation of synthetic events.
* @internal
*/
export function enqueueEvents(events) {
if (events) {
eventQueue = accumulateInto(eventQueue, events);
}
}
/**
* Dispatches all synthetic events on the event queue.
*
* @internal
*/
export function processEventQueue(simulated) {
// Set `eventQueue` to null before processing it so that we can tell if more
// events get enqueued while processing.
var processingEventQueue = eventQueue;
eventQueue = null;
if (simulated) {
forEachAccumulated(
processingEventQueue,
executeDispatchesAndReleaseSimulated,
);
} else {
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.
ReactErrorUtils.rethrowCaughtError();
}

View File

@ -48,7 +48,7 @@ function recomputePluginOrdering(): void {
'the plugin ordering, `%s`.',
pluginName,
);
if (EventPluginRegistry.plugins[pluginIndex]) {
if (plugins[pluginIndex]) {
continue;
}
invariant(
@ -57,7 +57,7 @@ function recomputePluginOrdering(): void {
'method, but `%s` does not.',
pluginName,
);
EventPluginRegistry.plugins[pluginIndex] = pluginModule;
plugins[pluginIndex] = pluginModule;
var publishedEvents = pluginModule.eventTypes;
for (var eventName in publishedEvents) {
invariant(
@ -88,12 +88,12 @@ function publishEventForPlugin(
eventName: string,
): boolean {
invariant(
!EventPluginRegistry.eventNameDispatchConfigs.hasOwnProperty(eventName),
!eventNameDispatchConfigs.hasOwnProperty(eventName),
'EventPluginHub: More than one plugin attempted to publish the same ' +
'event name, `%s`.',
eventName,
);
EventPluginRegistry.eventNameDispatchConfigs[eventName] = dispatchConfig;
eventNameDispatchConfigs[eventName] = dispatchConfig;
var phasedRegistrationNames = dispatchConfig.phasedRegistrationNames;
if (phasedRegistrationNames) {
@ -132,23 +132,21 @@ function publishRegistrationName(
eventName: string,
): void {
invariant(
!EventPluginRegistry.registrationNameModules[registrationName],
!registrationNameModules[registrationName],
'EventPluginHub: More than one plugin attempted to publish the same ' +
'registration name, `%s`.',
registrationName,
);
EventPluginRegistry.registrationNameModules[registrationName] = pluginModule;
EventPluginRegistry.registrationNameDependencies[registrationName] =
registrationNameModules[registrationName] = pluginModule;
registrationNameDependencies[registrationName] =
pluginModule.eventTypes[eventName].dependencies;
if (__DEV__) {
var lowerCasedName = registrationName.toLowerCase();
EventPluginRegistry.possibleRegistrationNames[
lowerCasedName
] = registrationName;
possibleRegistrationNames[lowerCasedName] = registrationName;
if (registrationName === 'onDoubleClick') {
EventPluginRegistry.possibleRegistrationNames.ondblclick = registrationName;
possibleRegistrationNames.ondblclick = registrationName;
}
}
}
@ -158,95 +156,92 @@ function publishRegistrationName(
*
* @see {EventPluginHub}
*/
var EventPluginRegistry = {
/**
* Ordered list of injected plugins.
*/
plugins: [],
/**
* Mapping from event name to dispatch config
*/
eventNameDispatchConfigs: {},
/**
* Ordered list of injected plugins.
*/
export const plugins = [];
/**
* Mapping from registration name to plugin module
*/
registrationNameModules: {},
/**
* Mapping from event name to dispatch config
*/
export const eventNameDispatchConfigs = {};
/**
* Mapping from registration name to event name
*/
registrationNameDependencies: {},
/**
* Mapping from registration name to plugin module
*/
export const registrationNameModules = {};
/**
* 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}
*/
possibleRegistrationNames: __DEV__ ? {} : (null: any),
// Trust the developer to only use possibleRegistrationNames in __DEV__
/**
* Mapping from registration name to event name
*/
export const registrationNameDependencies = {};
/**
* 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
* @see {EventPluginHub.injection.injectEventPluginOrder}
*/
injectEventPluginOrder: function(
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);
/**
* 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
* @see {EventPluginHub.injection.injectEventPluginOrder}
*/
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 `EventPluginHub`. 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
* @see {EventPluginHub.injection.injectEventPluginsByName}
*/
export function injectEventPluginsByName(
injectedNamesToPlugins: NamesToPlugins,
): void {
var isOrderingDirty = false;
for (var pluginName in injectedNamesToPlugins) {
if (!injectedNamesToPlugins.hasOwnProperty(pluginName)) {
continue;
}
var 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();
},
/**
* Injects plugins to be used by `EventPluginHub`. 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
* @see {EventPluginHub.injection.injectEventPluginsByName}
*/
injectEventPluginsByName: function(
injectedNamesToPlugins: NamesToPlugins,
): void {
var isOrderingDirty = false;
for (var pluginName in injectedNamesToPlugins) {
if (!injectedNamesToPlugins.hasOwnProperty(pluginName)) {
continue;
}
var 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 default EventPluginRegistry;
}
}

View File

@ -9,23 +9,20 @@ import ReactErrorUtils from 'shared/ReactErrorUtils';
import invariant from 'fbjs/lib/invariant';
import warning from 'fbjs/lib/warning';
/**
* Injected dependencies:
*/
export let getFiberCurrentPropsFromNode = null;
export let getInstanceFromNode = null;
export let getNodeFromInstance = null;
/**
* - `ComponentTree`: [required] Module that can convert between React instances
* and actual node references.
*/
var ComponentTree;
var injection = {
export const injection = {
injectComponentTree: function(Injected) {
ComponentTree = Injected;
({
getFiberCurrentPropsFromNode,
getInstanceFromNode,
getNodeFromInstance,
} = Injected);
if (__DEV__) {
warning(
Injected &&
Injected.getNodeFromInstance &&
Injected.getInstanceFromNode,
getNodeFromInstance && getInstanceFromNode,
'EventPluginUtils.injection.injectComponentTree(...): Injected ' +
'module is missing getNodeFromInstance or getInstanceFromNode.',
);
@ -33,7 +30,7 @@ var injection = {
},
};
function isEndish(topLevelType) {
export function isEndish(topLevelType) {
return (
topLevelType === 'topMouseUp' ||
topLevelType === 'topTouchEnd' ||
@ -41,10 +38,10 @@ function isEndish(topLevelType) {
);
}
function isMoveish(topLevelType) {
export function isMoveish(topLevelType) {
return topLevelType === 'topMouseMove' || topLevelType === 'topTouchMove';
}
function isStartish(topLevelType) {
export function isStartish(topLevelType) {
return topLevelType === 'topMouseDown' || topLevelType === 'topTouchStart';
}
@ -80,7 +77,7 @@ if (__DEV__) {
*/
function executeDispatch(event, simulated, listener, inst) {
var type = event.type || 'unknown-event';
event.currentTarget = EventPluginUtils.getNodeFromInstance(inst);
event.currentTarget = getNodeFromInstance(inst);
ReactErrorUtils.invokeGuardedCallbackAndCatchFirstError(
type,
listener,
@ -93,7 +90,7 @@ function executeDispatch(event, simulated, listener, inst) {
/**
* Standard/simple iteration through an event's collected dispatches.
*/
function executeDispatchesInOrder(event, simulated) {
export function executeDispatchesInOrder(event, simulated) {
var dispatchListeners = event._dispatchListeners;
var dispatchInstances = event._dispatchInstances;
if (__DEV__) {
@ -153,7 +150,7 @@ function executeDispatchesInOrderStopAtTrueImpl(event) {
/**
* @see executeDispatchesInOrderStopAtTrueImpl
*/
function executeDispatchesInOrderStopAtTrue(event) {
export function executeDispatchesInOrderStopAtTrue(event) {
var ret = executeDispatchesInOrderStopAtTrueImpl(event);
event._dispatchInstances = null;
event._dispatchListeners = null;
@ -169,7 +166,7 @@ function executeDispatchesInOrderStopAtTrue(event) {
*
* @return {*} The return value of executing the single dispatch.
*/
function executeDirectDispatch(event) {
export function executeDirectDispatch(event) {
if (__DEV__) {
validateEventDispatches(event);
}
@ -180,7 +177,7 @@ function executeDirectDispatch(event) {
'executeDirectDispatch(...): Invalid `event`.',
);
event.currentTarget = dispatchListener
? EventPluginUtils.getNodeFromInstance(dispatchInstance)
? getNodeFromInstance(dispatchInstance)
: null;
var res = dispatchListener ? dispatchListener(event) : null;
event.currentTarget = null;
@ -193,34 +190,6 @@ function executeDirectDispatch(event) {
* @param {SyntheticEvent} event
* @return {boolean} True iff number of dispatches accumulated is greater than 0.
*/
function hasDispatches(event) {
export function hasDispatches(event) {
return !!event._dispatchListeners;
}
/**
* General utilities that are useful in creating custom Event Plugins.
*/
var EventPluginUtils = {
isEndish: isEndish,
isMoveish: isMoveish,
isStartish: isStartish,
executeDirectDispatch: executeDirectDispatch,
executeDispatchesInOrder: executeDispatchesInOrder,
executeDispatchesInOrderStopAtTrue: executeDispatchesInOrderStopAtTrue,
hasDispatches: hasDispatches,
getFiberCurrentPropsFromNode: function(node) {
return ComponentTree.getFiberCurrentPropsFromNode(node);
},
getInstanceFromNode: function(node) {
return ComponentTree.getInstanceFromNode(node);
},
getNodeFromInstance: function(node) {
return ComponentTree.getNodeFromInstance(node);
},
injection: injection,
};
export default EventPluginUtils;

View File

@ -12,14 +12,12 @@ import {
} from 'shared/ReactTreeTraversal';
import warning from 'fbjs/lib/warning';
import EventPluginHub from './EventPluginHub';
import {getListener} from './EventPluginHub';
import accumulateInto from './accumulateInto';
import forEachAccumulated from './forEachAccumulated';
type PropagationPhases = 'bubbled' | 'captured';
var getListener = EventPluginHub.getListener;
/**
* Some event types have a notion of different registration names for different
* "phases" of propagation. This finds listeners by a given phase.
@ -30,6 +28,16 @@ function listenerAtPhase(inst, event, propagationPhase: PropagationPhases) {
return getListener(inst, registrationName);
}
/**
* A small set of propagation patterns, each of which will accept a small amount
* of information, and generate a set of "dispatch ready event objects" - which
* are sets of events that have already been annotated with a set of dispatched
* listener functions/ids. The API is designed this way to discourage these
* propagation strategies from actually executing the dispatches, since we
* always want to collect the entire set of dispatches before executing even a
* single one.
*/
/**
* Tags a `SyntheticEvent` with dispatched listeners. Creating this function
* here, allows us to not have to bind or create functions for each event.
@ -104,38 +112,18 @@ function accumulateDirectDispatchesSingle(event) {
}
}
function accumulateTwoPhaseDispatches(events) {
export function accumulateTwoPhaseDispatches(events) {
forEachAccumulated(events, accumulateTwoPhaseDispatchesSingle);
}
function accumulateTwoPhaseDispatchesSkipTarget(events) {
export function accumulateTwoPhaseDispatchesSkipTarget(events) {
forEachAccumulated(events, accumulateTwoPhaseDispatchesSingleSkipTarget);
}
function accumulateEnterLeaveDispatches(leave, enter, from, to) {
export function accumulateEnterLeaveDispatches(leave, enter, from, to) {
traverseEnterLeave(from, to, accumulateDispatches, leave, enter);
}
function accumulateDirectDispatches(events) {
export function accumulateDirectDispatches(events) {
forEachAccumulated(events, accumulateDirectDispatchesSingle);
}
/**
* A small set of propagation patterns, each of which will accept a small amount
* of information, and generate a set of "dispatch ready event objects" - which
* are sets of events that have already been annotated with a set of dispatched
* listener functions/ids. The API is designed this way to discourage these
* propagation strategies from actually executing the dispatches, since we
* always want to collect the entire set of dispatches before executing even a
* single one.
*
* @constructor EventPropagators
*/
var EventPropagators = {
accumulateTwoPhaseDispatches: accumulateTwoPhaseDispatches,
accumulateTwoPhaseDispatchesSkipTarget: accumulateTwoPhaseDispatchesSkipTarget,
accumulateDirectDispatches: accumulateDirectDispatches,
accumulateEnterLeaveDispatches: accumulateEnterLeaveDispatches,
};
export default EventPropagators;

View File

@ -7,7 +7,10 @@
import invariant from 'fbjs/lib/invariant';
import EventPluginUtils from './EventPluginUtils';
import {
getInstanceFromNode,
getFiberCurrentPropsFromNode,
} from './EventPluginUtils';
// Use to restore controlled state after a change event has fired.
@ -27,7 +30,7 @@ var restoreQueue = null;
function restoreStateOfTarget(target) {
// We perform this translation at the end of the event loop so that we
// always receive the correct fiber here
var internalInstance = EventPluginUtils.getInstanceFromNode(target);
var internalInstance = getInstanceFromNode(target);
if (!internalInstance) {
// Unmounted
return;
@ -38,9 +41,7 @@ function restoreStateOfTarget(target) {
'Fiber needs to be injected to handle a fiber target for controlled ' +
'events. This error is likely caused by a bug in React. Please file an issue.',
);
const props = EventPluginUtils.getFiberCurrentPropsFromNode(
internalInstance.stateNode,
);
const props = getFiberCurrentPropsFromNode(internalInstance.stateNode);
fiberHostComponent.restoreControlledState(
internalInstance.stateNode,
internalInstance.type,
@ -48,37 +49,33 @@ function restoreStateOfTarget(target) {
);
}
var ReactControlledComponent = {
injection: ReactControlledComponentInjection,
export const injection = ReactControlledComponentInjection;
enqueueStateRestore(target) {
if (restoreTarget) {
if (restoreQueue) {
restoreQueue.push(target);
} else {
restoreQueue = [target];
}
export function enqueueStateRestore(target) {
if (restoreTarget) {
if (restoreQueue) {
restoreQueue.push(target);
} else {
restoreTarget = target;
restoreQueue = [target];
}
},
} else {
restoreTarget = target;
}
}
restoreStateIfNeeded() {
if (!restoreTarget) {
return;
export function restoreStateIfNeeded() {
if (!restoreTarget) {
return;
}
var target = restoreTarget;
var queuedTargets = restoreQueue;
restoreTarget = null;
restoreQueue = null;
restoreStateOfTarget(target);
if (queuedTargets) {
for (var i = 0; i < queuedTargets.length; i++) {
restoreStateOfTarget(queuedTargets[i]);
}
var target = restoreTarget;
var queuedTargets = restoreQueue;
restoreTarget = null;
restoreQueue = null;
restoreStateOfTarget(target);
if (queuedTargets) {
for (var i = 0; i < queuedTargets.length; i++) {
restoreStateOfTarget(queuedTargets[i]);
}
}
},
};
export default ReactControlledComponent;
}
}

View File

@ -5,32 +5,32 @@
* LICENSE file in the root directory of this source tree.
*/
import EventPluginHub from './EventPluginHub';
import {
enqueueEvents,
processEventQueue,
extractEvents,
} from './EventPluginHub';
function runEventQueueInBatch(events) {
EventPluginHub.enqueueEvents(events);
EventPluginHub.processEventQueue(false);
enqueueEvents(events);
processEventQueue(false);
}
var ReactEventEmitterMixin = {
/**
* Streams a fired top-level event to `EventPluginHub` where plugins have the
* opportunity to create `ReactEvent`s to be dispatched.
*/
handleTopLevel: function(
/**
* Streams a fired top-level event to `EventPluginHub` where plugins have the
* opportunity to create `ReactEvent`s to be dispatched.
*/
export function handleTopLevel(
topLevelType,
targetInst,
nativeEvent,
nativeEventTarget,
) {
var events = extractEvents(
topLevelType,
targetInst,
nativeEvent,
nativeEventTarget,
) {
var events = EventPluginHub.extractEvents(
topLevelType,
targetInst,
nativeEvent,
nativeEventTarget,
);
runEventQueueInBatch(events);
},
};
export default ReactEventEmitterMixin;
);
runEventQueueInBatch(events);
}

View File

@ -5,7 +5,7 @@
* LICENSE file in the root directory of this source tree.
*/
import ReactControlledComponent from './ReactControlledComponent';
import {restoreStateIfNeeded} from './ReactControlledComponent';
// Used as a way to call batchedUpdates when we don't have a reference to
// the renderer. Such as when we're dispatching events or if third party
@ -18,30 +18,24 @@ var fiberBatchedUpdates = function(fn, bookkeeping) {
return fn(bookkeeping);
};
function batchedUpdates(fn, bookkeeping) {
// If we have Fiber loaded, we need to wrap this in a batching call so that
// Fiber can apply its default priority for this call.
return fiberBatchedUpdates(fn, bookkeeping);
}
var isNestingBatched = false;
function batchedUpdatesWithControlledComponents(fn, bookkeeping) {
export function batchedUpdates(fn, bookkeeping) {
if (isNestingBatched) {
// If we are currently inside another batch, we need to wait until it
// fully completes before restoring state. Therefore, we add the target to
// a queue of work.
return batchedUpdates(fn, bookkeeping);
return fiberBatchedUpdates(fn, bookkeeping);
}
isNestingBatched = true;
try {
return batchedUpdates(fn, bookkeeping);
return fiberBatchedUpdates(fn, bookkeeping);
} finally {
// Here we wait until all updates have propagated, which is important
// when using controlled components within layers:
// https://github.com/facebook/react/issues/1698
// Then we restore state of any controlled component.
isNestingBatched = false;
ReactControlledComponent.restoreStateIfNeeded();
restoreStateIfNeeded();
}
}
@ -51,9 +45,4 @@ var ReactGenericBatchingInjection = {
},
};
var ReactGenericBatching = {
batchedUpdates: batchedUpdatesWithControlledComponents,
injection: ReactGenericBatchingInjection,
};
export default ReactGenericBatching;
export const injection = ReactGenericBatchingInjection;

View File

@ -7,20 +7,24 @@
import {getLowestCommonAncestor, isAncestor} from 'shared/ReactTreeTraversal';
import EventPluginUtils from './EventPluginUtils';
import EventPropagators from './EventPropagators';
import {
isStartish,
isMoveish,
isEndish,
executeDirectDispatch,
hasDispatches,
executeDispatchesInOrderStopAtTrue,
getInstanceFromNode,
} from './EventPluginUtils';
import {
accumulateDirectDispatches,
accumulateTwoPhaseDispatches,
accumulateTwoPhaseDispatchesSkipTarget,
} from './EventPropagators';
import ResponderSyntheticEvent from './ResponderSyntheticEvent';
import ResponderTouchHistoryStore from './ResponderTouchHistoryStore';
import accumulate from './accumulate';
var isStartish = EventPluginUtils.isStartish;
var isMoveish = EventPluginUtils.isMoveish;
var isEndish = EventPluginUtils.isEndish;
var executeDirectDispatch = EventPluginUtils.executeDirectDispatch;
var hasDispatches = EventPluginUtils.hasDispatches;
var executeDispatchesInOrderStopAtTrue =
EventPluginUtils.executeDispatchesInOrderStopAtTrue;
/**
* Instance of element that should respond to touch/move types of interactions,
* as indicated explicitly by relevant callbacks.
@ -340,9 +344,9 @@ function setResponderAndExtractTransfer(
);
shouldSetEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;
if (skipOverBubbleShouldSetFrom) {
EventPropagators.accumulateTwoPhaseDispatchesSkipTarget(shouldSetEvent);
accumulateTwoPhaseDispatchesSkipTarget(shouldSetEvent);
} else {
EventPropagators.accumulateTwoPhaseDispatches(shouldSetEvent);
accumulateTwoPhaseDispatches(shouldSetEvent);
}
var wantsResponderInst = executeDispatchesInOrderStopAtTrue(shouldSetEvent);
if (!shouldSetEvent.isPersistent()) {
@ -361,7 +365,7 @@ function setResponderAndExtractTransfer(
);
grantEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;
EventPropagators.accumulateDirectDispatches(grantEvent);
accumulateDirectDispatches(grantEvent);
var blockHostResponder = executeDirectDispatch(grantEvent) === true;
if (responderInst) {
var terminationRequestEvent = ResponderSyntheticEvent.getPooled(
@ -372,7 +376,7 @@ function setResponderAndExtractTransfer(
);
terminationRequestEvent.touchHistory =
ResponderTouchHistoryStore.touchHistory;
EventPropagators.accumulateDirectDispatches(terminationRequestEvent);
accumulateDirectDispatches(terminationRequestEvent);
var shouldSwitch =
!hasDispatches(terminationRequestEvent) ||
executeDirectDispatch(terminationRequestEvent);
@ -388,7 +392,7 @@ function setResponderAndExtractTransfer(
nativeEventTarget,
);
terminateEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;
EventPropagators.accumulateDirectDispatches(terminateEvent);
accumulateDirectDispatches(terminateEvent);
extracted = accumulate(extracted, [grantEvent, terminateEvent]);
changeResponder(wantsResponderInst, blockHostResponder);
} else {
@ -399,7 +403,7 @@ function setResponderAndExtractTransfer(
nativeEventTarget,
);
rejectEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;
EventPropagators.accumulateDirectDispatches(rejectEvent);
accumulateDirectDispatches(rejectEvent);
extracted = accumulate(extracted, rejectEvent);
}
} else {
@ -447,7 +451,7 @@ function noResponderTouches(nativeEvent) {
var target = activeTouch.target;
if (target !== null && target !== undefined && target !== 0) {
// Is the original touch location inside of the current responder?
var targetInst = EventPluginUtils.getInstanceFromNode(target);
var targetInst = getInstanceFromNode(target);
if (isAncestor(responderInst, targetInst)) {
return false;
}
@ -525,7 +529,7 @@ var ResponderEventPlugin = {
nativeEventTarget,
);
gesture.touchHistory = ResponderTouchHistoryStore.touchHistory;
EventPropagators.accumulateDirectDispatches(gesture);
accumulateDirectDispatches(gesture);
extracted = accumulate(extracted, gesture);
}
@ -547,7 +551,7 @@ var ResponderEventPlugin = {
nativeEventTarget,
);
finalEvent.touchHistory = ResponderTouchHistoryStore.touchHistory;
EventPropagators.accumulateDirectDispatches(finalEvent);
accumulateDirectDispatches(finalEvent);
extracted = accumulate(extracted, finalEvent);
changeResponder(null);
}

View File

@ -10,9 +10,7 @@
import invariant from 'fbjs/lib/invariant';
import warning from 'fbjs/lib/warning';
import EventPluginUtils from './EventPluginUtils';
const {isEndish, isMoveish, isStartish} = EventPluginUtils;
import {isEndish, isMoveish, isStartish} from './EventPluginUtils';
/**
* Tracks the position and time of each active touch by `touch.identifier`. We

View File

@ -16,7 +16,7 @@ describe('EventPluginRegistry', () => {
beforeEach(() => {
jest.resetModuleRegistry();
// TODO: can we express this test with only public API?
EventPluginRegistry = require('events/EventPluginRegistry').default;
EventPluginRegistry = require('events/EventPluginRegistry');
createPlugin = function(properties) {
return Object.assign({extractEvents: function() {}}, properties);

View File

@ -58,13 +58,12 @@ describe('ReactBrowserEventEmitter', () => {
LISTENER.mockClear();
// TODO: can we express this test with only public API?
EventPluginHub = require('events/EventPluginHub').default;
EventPluginRegistry = require('events/EventPluginRegistry').default;
EventPluginHub = require('events/EventPluginHub');
EventPluginRegistry = require('events/EventPluginRegistry');
React = require('react');
ReactDOM = require('react-dom');
ReactDOMComponentTree = require('../client/ReactDOMComponentTree').default;
ReactBrowserEventEmitter = require('../events/ReactBrowserEventEmitter')
.default;
ReactDOMComponentTree = require('../client/ReactDOMComponentTree');
ReactBrowserEventEmitter = require('../events/ReactBrowserEventEmitter');
ReactTestUtils = require('react-dom/test-utils');
TapEventPlugin = require('../events/TapEventPlugin').default;

View File

@ -34,7 +34,7 @@ describe('ReactDOMComponentTree', () => {
React = require('react');
ReactDOM = require('react-dom');
// TODO: can we express this test with only public API?
ReactDOMComponentTree = require('../client/ReactDOMComponentTree').default;
ReactDOMComponentTree = require('../client/ReactDOMComponentTree');
ReactDOMServer = require('react-dom/server');
});

View File

@ -35,7 +35,7 @@ describe('ReactDOMServer', () => {
ReactDOMServer = require('react-dom/server');
// TODO: can we express this test with only public API?
var DOMProperty = require('../shared/DOMProperty').default;
var DOMProperty = require('../shared/DOMProperty');
ROOT_ATTRIBUTE_NAME = DOMProperty.ROOT_ATTRIBUTE_NAME;
});

View File

@ -11,7 +11,7 @@
var React = require('react');
// TODO: can we express this test with only public API?
var ReactDOMComponentTree = require('../client/ReactDOMComponentTree').default;
var ReactDOMComponentTree = require('../client/ReactDOMComponentTree');
var ReactTestUtils = require('react-dom/test-utils');
/**

View File

@ -5,17 +5,20 @@
* LICENSE file in the root directory of this source tree.
*/
import DOMProperty from '../shared/DOMProperty';
import {
ATTRIBUTE_NAME_CHAR,
ATTRIBUTE_NAME_START_CHAR,
ID_ATTRIBUTE_NAME,
ROOT_ATTRIBUTE_NAME,
getPropertyInfo,
shouldSetAttribute,
} from '../shared/DOMProperty';
import warning from 'fbjs/lib/warning';
// isAttributeNameSafe() is currently duplicated in DOMMarkupOperations.
// TODO: Find a better place for this.
var VALID_ATTRIBUTE_NAME_REGEX = new RegExp(
'^[' +
DOMProperty.ATTRIBUTE_NAME_START_CHAR +
'][' +
DOMProperty.ATTRIBUTE_NAME_CHAR +
']*$',
'^[' + ATTRIBUTE_NAME_START_CHAR + '][' + ATTRIBUTE_NAME_CHAR + ']*$',
);
var illegalAttributeNameCache = {};
var validatedAttributeNameCache = {};
@ -54,11 +57,11 @@ function shouldIgnoreValue(propertyInfo, value) {
*/
export function setAttributeForID(node, id) {
node.setAttribute(DOMProperty.ID_ATTRIBUTE_NAME, id);
node.setAttribute(ID_ATTRIBUTE_NAME, id);
}
export function setAttributeForRoot(node) {
node.setAttribute(DOMProperty.ROOT_ATTRIBUTE_NAME, '');
node.setAttribute(ROOT_ATTRIBUTE_NAME, '');
}
/**
@ -68,7 +71,7 @@ export function setAttributeForRoot(node) {
*/
export function getValueForProperty(node, name, expected) {
if (__DEV__) {
var propertyInfo = DOMProperty.getPropertyInfo(name);
var propertyInfo = getPropertyInfo(name);
if (propertyInfo) {
var mutationMethod = propertyInfo.mutationMethod;
if (mutationMethod || propertyInfo.mustUseProperty) {
@ -151,9 +154,9 @@ export function getValueForAttribute(node, name, expected) {
* @param {*} value
*/
export function setValueForProperty(node, name, value) {
var propertyInfo = DOMProperty.getPropertyInfo(name);
var propertyInfo = getPropertyInfo(name);
if (propertyInfo && DOMProperty.shouldSetAttribute(name, value)) {
if (propertyInfo && shouldSetAttribute(name, value)) {
var mutationMethod = propertyInfo.mutationMethod;
if (mutationMethod) {
mutationMethod(node, value);
@ -184,7 +187,7 @@ export function setValueForProperty(node, name, value) {
setValueForAttribute(
node,
name,
DOMProperty.shouldSetAttribute(name, value) ? value : null,
shouldSetAttribute(name, value) ? value : null,
);
return;
}
@ -228,7 +231,7 @@ export function deleteValueForAttribute(node, name) {
* @param {string} name
*/
export function deleteValueForProperty(node, name) {
var propertyInfo = DOMProperty.getPropertyInfo(name);
var propertyInfo = getPropertyInfo(name);
if (propertyInfo) {
var mutationMethod = propertyInfo.mutationMethod;
if (mutationMethod) {

View File

@ -19,11 +19,11 @@ import * as ReactPortal from 'react-reconciler/src/ReactPortal';
// TODO: direct imports like some-package/src/* are bad. Fix me.
import {injectInternals} from 'react-reconciler/src/ReactFiberDevToolsHook';
import ExecutionEnvironment from 'fbjs/lib/ExecutionEnvironment';
import ReactGenericBatching from 'events/ReactGenericBatching';
import ReactControlledComponent from 'events/ReactControlledComponent';
import EventPluginHub from 'events/EventPluginHub';
import EventPluginRegistry from 'events/EventPluginRegistry';
import EventPropagators from 'events/EventPropagators';
import * as ReactGenericBatching from 'events/ReactGenericBatching';
import * as ReactControlledComponent from 'events/ReactControlledComponent';
import * as EventPluginHub from 'events/EventPluginHub';
import * as EventPluginRegistry from 'events/EventPluginRegistry';
import * as EventPropagators from 'events/EventPropagators';
import * as ReactInstanceMap from 'shared/ReactInstanceMap';
import ReactFeatureFlags from 'shared/ReactFeatureFlags';
import ReactVersion from 'shared/ReactVersion';
@ -34,12 +34,12 @@ import invariant from 'fbjs/lib/invariant';
import lowPriorityWarning from 'shared/lowPriorityWarning';
import warning from 'fbjs/lib/warning';
import ReactDOMComponentTree from './ReactDOMComponentTree';
import * as ReactDOMComponentTree from './ReactDOMComponentTree';
import * as ReactDOMFiberComponent from './ReactDOMFiberComponent';
import * as ReactInputSelection from './ReactInputSelection';
import validateDOMNesting from './validateDOMNesting';
import ReactBrowserEventEmitter from '../events/ReactBrowserEventEmitter';
import ReactDOMEventListener from '../events/ReactDOMEventListener';
import * as ReactBrowserEventEmitter from '../events/ReactBrowserEventEmitter';
import * as ReactDOMEventListener from '../events/ReactDOMEventListener';
import {getChildNamespace} from '../shared/DOMNamespaces';
import {
ELEMENT_NODE,
@ -48,9 +48,7 @@ import {
DOCUMENT_NODE,
DOCUMENT_FRAGMENT_NODE,
} from '../shared/HTMLNodeType';
import DOMProperty from '../shared/DOMProperty';
var {ROOT_ATTRIBUTE_NAME} = DOMProperty;
import {ROOT_ATTRIBUTE_NAME} from '../shared/DOMProperty';
var {
createElement,
createTextNode,

View File

@ -5,22 +5,20 @@
* LICENSE file in the root directory of this source tree.
*/
import EventPluginHub from 'events/EventPluginHub';
import EventPluginUtils from 'events/EventPluginUtils';
import * as EventPluginHub from 'events/EventPluginHub';
import * as EventPluginUtils from 'events/EventPluginUtils';
import ReactDOMComponentTree from './ReactDOMComponentTree';
import * as ReactDOMComponentTree from './ReactDOMComponentTree';
import BeforeInputEventPlugin from '../events/BeforeInputEventPlugin';
import ChangeEventPlugin from '../events/ChangeEventPlugin';
import DOMEventPluginOrder from '../events/DOMEventPluginOrder';
import EnterLeaveEventPlugin from '../events/EnterLeaveEventPlugin';
import ReactBrowserEventEmitter from '../events/ReactBrowserEventEmitter';
import ReactDOMEventListener from '../events/ReactDOMEventListener';
import {handleTopLevel} from '../events/ReactBrowserEventEmitter';
import {setHandleTopLevel} from '../events/ReactDOMEventListener';
import SelectEventPlugin from '../events/SelectEventPlugin';
import SimpleEventPlugin from '../events/SimpleEventPlugin';
ReactDOMEventListener.setHandleTopLevel(
ReactBrowserEventEmitter.handleTopLevel,
);
setHandleTopLevel(handleTopLevel);
/**
* Inject modules for resolving DOM hierarchy and plugin ordering.

View File

@ -12,7 +12,7 @@ var randomKey = Math.random().toString(36).slice(2);
var internalInstanceKey = '__reactInternalInstance$' + randomKey;
var internalEventHandlersKey = '__reactEventHandlers$' + randomKey;
function precacheFiberNode(hostInst, node) {
export function precacheFiberNode(hostInst, node) {
node[internalInstanceKey] = hostInst;
}
@ -20,7 +20,7 @@ function precacheFiberNode(hostInst, node) {
* Given a DOM node, return the closest ReactDOMComponent or
* ReactDOMTextComponent instance ancestor.
*/
function getClosestInstanceFromNode(node) {
export function getClosestInstanceFromNode(node) {
if (node[internalInstanceKey]) {
return node[internalInstanceKey];
}
@ -55,7 +55,7 @@ function getClosestInstanceFromNode(node) {
* Given a DOM node, return the ReactDOMComponent or ReactDOMTextComponent
* instance, or null if the node was not rendered by this React.
*/
function getInstanceFromNode(node) {
export function getInstanceFromNode(node) {
var inst = node[internalInstanceKey];
if (inst) {
if (inst.tag === HostComponent || inst.tag === HostText) {
@ -71,7 +71,7 @@ function getInstanceFromNode(node) {
* Given a ReactDOMComponent or ReactDOMTextComponent, return the corresponding
* DOM node.
*/
function getNodeFromInstance(inst) {
export function getNodeFromInstance(inst) {
if (inst.tag === HostComponent || inst.tag === HostText) {
// In Fiber this, is just the state node right now. We assume it will be
// a host component or host text.
@ -83,21 +83,10 @@ function getNodeFromInstance(inst) {
invariant(false, 'getNodeFromInstance: Invalid argument.');
}
function getFiberCurrentPropsFromNode(node) {
export function getFiberCurrentPropsFromNode(node) {
return node[internalEventHandlersKey] || null;
}
function updateFiberProps(node, props) {
export function updateFiberProps(node, props) {
node[internalEventHandlersKey] = props;
}
var ReactDOMComponentTree = {
getClosestInstanceFromNode: getClosestInstanceFromNode,
getInstanceFromNode: getInstanceFromNode,
getNodeFromInstance: getNodeFromInstance,
precacheFiberNode: precacheFiberNode,
getFiberCurrentPropsFromNode,
updateFiberProps,
};
export default ReactDOMComponentTree;

View File

@ -15,8 +15,8 @@ import * as ReactFiberErrorLogger
import ReactErrorUtils from 'shared/ReactErrorUtils';
import ReactDOM from './ReactDOM';
import ReactBrowserEventEmitter from '../events/ReactBrowserEventEmitter';
import ReactDOMComponentTree from './ReactDOMComponentTree';
import * as ReactBrowserEventEmitter from '../events/ReactBrowserEventEmitter';
import * as ReactDOMComponentTree from './ReactDOMComponentTree';
import TapEventPlugin from '../events/TapEventPlugin';
Object.assign(

View File

@ -10,7 +10,7 @@
// TODO: direct imports like some-package/src/* are bad. Fix me.
import ReactDebugCurrentFiber
from 'react-reconciler/src/ReactDebugCurrentFiber';
import EventPluginRegistry from 'events/EventPluginRegistry';
import {registrationNameModules} from 'events/EventPluginRegistry';
import emptyFunction from 'fbjs/lib/emptyFunction';
import warning from 'fbjs/lib/warning';
@ -22,10 +22,10 @@ import * as ReactDOMFiberTextarea from './ReactDOMFiberTextarea';
import * as inputValueTracking from './inputValueTracking';
import setInnerHTML from './setInnerHTML';
import setTextContent from './setTextContent';
import ReactBrowserEventEmitter from '../events/ReactBrowserEventEmitter';
import {listenTo, trapBubbledEvent} from '../events/ReactBrowserEventEmitter';
import * as CSSPropertyOperations from '../shared/CSSPropertyOperations';
import {Namespaces, getIntrinsicNamespace} from '../shared/DOMNamespaces';
import DOMProperty from '../shared/DOMProperty';
import {getPropertyInfo, shouldSetAttribute} from '../shared/DOMProperty';
import assertValidProps from '../shared/assertValidProps';
import {DOCUMENT_NODE, DOCUMENT_FRAGMENT_NODE} from '../shared/HTMLNodeType';
import isCustomComponent from '../shared/isCustomComponent';
@ -46,9 +46,6 @@ var {
var didWarnInvalidHydration = false;
var didWarnShadyDOM = false;
var listenTo = ReactBrowserEventEmitter.listenTo;
var registrationNameModules = EventPluginRegistry.registrationNameModules;
var DANGEROUSLY_SET_INNER_HTML = 'dangerouslySetInnerHTML';
var SUPPRESS_CONTENT_EDITABLE_WARNING = 'suppressContentEditableWarning';
var SUPPRESS_HYDRATION_WARNING = 'suppressHydrationWarning';
@ -467,7 +464,7 @@ export function setInitialProperties(
switch (tag) {
case 'iframe':
case 'object':
ReactBrowserEventEmitter.trapBubbledEvent('topLoad', 'load', domElement);
trapBubbledEvent('topLoad', 'load', domElement);
props = rawProps;
break;
case 'video':
@ -475,62 +472,34 @@ export function setInitialProperties(
// Create listener for each media event
for (var event in mediaEvents) {
if (mediaEvents.hasOwnProperty(event)) {
ReactBrowserEventEmitter.trapBubbledEvent(
event,
mediaEvents[event],
domElement,
);
trapBubbledEvent(event, mediaEvents[event], domElement);
}
}
props = rawProps;
break;
case 'source':
ReactBrowserEventEmitter.trapBubbledEvent(
'topError',
'error',
domElement,
);
trapBubbledEvent('topError', 'error', domElement);
props = rawProps;
break;
case 'img':
case 'image':
ReactBrowserEventEmitter.trapBubbledEvent(
'topError',
'error',
domElement,
);
ReactBrowserEventEmitter.trapBubbledEvent('topLoad', 'load', domElement);
trapBubbledEvent('topError', 'error', domElement);
trapBubbledEvent('topLoad', 'load', domElement);
props = rawProps;
break;
case 'form':
ReactBrowserEventEmitter.trapBubbledEvent(
'topReset',
'reset',
domElement,
);
ReactBrowserEventEmitter.trapBubbledEvent(
'topSubmit',
'submit',
domElement,
);
trapBubbledEvent('topReset', 'reset', domElement);
trapBubbledEvent('topSubmit', 'submit', domElement);
props = rawProps;
break;
case 'details':
ReactBrowserEventEmitter.trapBubbledEvent(
'topToggle',
'toggle',
domElement,
);
trapBubbledEvent('topToggle', 'toggle', domElement);
props = rawProps;
break;
case 'input':
ReactDOMFiberInput.initWrapperState(domElement, rawProps);
props = ReactDOMFiberInput.getHostProps(domElement, rawProps);
ReactBrowserEventEmitter.trapBubbledEvent(
'topInvalid',
'invalid',
domElement,
);
trapBubbledEvent('topInvalid', 'invalid', domElement);
// For controlled components we always need to ensure we're listening
// to onChange. Even if there is no listener.
ensureListeningTo(rootContainerElement, 'onChange');
@ -542,11 +511,7 @@ export function setInitialProperties(
case 'select':
ReactDOMFiberSelect.initWrapperState(domElement, rawProps);
props = ReactDOMFiberSelect.getHostProps(domElement, rawProps);
ReactBrowserEventEmitter.trapBubbledEvent(
'topInvalid',
'invalid',
domElement,
);
trapBubbledEvent('topInvalid', 'invalid', domElement);
// For controlled components we always need to ensure we're listening
// to onChange. Even if there is no listener.
ensureListeningTo(rootContainerElement, 'onChange');
@ -554,11 +519,7 @@ export function setInitialProperties(
case 'textarea':
ReactDOMFiberTextarea.initWrapperState(domElement, rawProps);
props = ReactDOMFiberTextarea.getHostProps(domElement, rawProps);
ReactBrowserEventEmitter.trapBubbledEvent(
'topInvalid',
'invalid',
domElement,
);
trapBubbledEvent('topInvalid', 'invalid', domElement);
// For controlled components we always need to ensure we're listening
// to onChange. Even if there is no listener.
ensureListeningTo(rootContainerElement, 'onChange');
@ -871,63 +832,35 @@ export function diffHydratedProperties(
switch (tag) {
case 'iframe':
case 'object':
ReactBrowserEventEmitter.trapBubbledEvent('topLoad', 'load', domElement);
trapBubbledEvent('topLoad', 'load', domElement);
break;
case 'video':
case 'audio':
// Create listener for each media event
for (var event in mediaEvents) {
if (mediaEvents.hasOwnProperty(event)) {
ReactBrowserEventEmitter.trapBubbledEvent(
event,
mediaEvents[event],
domElement,
);
trapBubbledEvent(event, mediaEvents[event], domElement);
}
}
break;
case 'source':
ReactBrowserEventEmitter.trapBubbledEvent(
'topError',
'error',
domElement,
);
trapBubbledEvent('topError', 'error', domElement);
break;
case 'img':
case 'image':
ReactBrowserEventEmitter.trapBubbledEvent(
'topError',
'error',
domElement,
);
ReactBrowserEventEmitter.trapBubbledEvent('topLoad', 'load', domElement);
trapBubbledEvent('topError', 'error', domElement);
trapBubbledEvent('topLoad', 'load', domElement);
break;
case 'form':
ReactBrowserEventEmitter.trapBubbledEvent(
'topReset',
'reset',
domElement,
);
ReactBrowserEventEmitter.trapBubbledEvent(
'topSubmit',
'submit',
domElement,
);
trapBubbledEvent('topReset', 'reset', domElement);
trapBubbledEvent('topSubmit', 'submit', domElement);
break;
case 'details':
ReactBrowserEventEmitter.trapBubbledEvent(
'topToggle',
'toggle',
domElement,
);
trapBubbledEvent('topToggle', 'toggle', domElement);
break;
case 'input':
ReactDOMFiberInput.initWrapperState(domElement, rawProps);
ReactBrowserEventEmitter.trapBubbledEvent(
'topInvalid',
'invalid',
domElement,
);
trapBubbledEvent('topInvalid', 'invalid', domElement);
// For controlled components we always need to ensure we're listening
// to onChange. Even if there is no listener.
ensureListeningTo(rootContainerElement, 'onChange');
@ -937,22 +870,14 @@ export function diffHydratedProperties(
break;
case 'select':
ReactDOMFiberSelect.initWrapperState(domElement, rawProps);
ReactBrowserEventEmitter.trapBubbledEvent(
'topInvalid',
'invalid',
domElement,
);
trapBubbledEvent('topInvalid', 'invalid', domElement);
// For controlled components we always need to ensure we're listening
// to onChange. Even if there is no listener.
ensureListeningTo(rootContainerElement, 'onChange');
break;
case 'textarea':
ReactDOMFiberTextarea.initWrapperState(domElement, rawProps);
ReactBrowserEventEmitter.trapBubbledEvent(
'topInvalid',
'invalid',
domElement,
);
trapBubbledEvent('topInvalid', 'invalid', domElement);
// For controlled components we always need to ensure we're listening
// to onChange. Even if there is no listener.
ensureListeningTo(rootContainerElement, 'onChange');
@ -1069,8 +994,8 @@ export function diffHydratedProperties(
if (nextProp !== serverValue) {
warnForPropDifference(propKey, serverValue, nextProp);
}
} else if (DOMProperty.shouldSetAttribute(propKey, nextProp)) {
if ((propertyInfo = DOMProperty.getPropertyInfo(propKey))) {
} else if (shouldSetAttribute(propKey, nextProp)) {
if ((propertyInfo = getPropertyInfo(propKey))) {
// $FlowFixMe - Should be inferred as not undefined.
extraAttributeNames.delete(propertyInfo.attributeName);
serverValue = DOMPropertyOperations.getValueForProperty(

View File

@ -14,7 +14,7 @@ import invariant from 'fbjs/lib/invariant';
import warning from 'fbjs/lib/warning';
import * as DOMPropertyOperations from './DOMPropertyOperations';
import ReactDOMComponentTree from './ReactDOMComponentTree';
import {getFiberCurrentPropsFromNode} from './ReactDOMComponentTree';
import ReactControlledValuePropTypes
from '../shared/ReactControlledValuePropTypes';
@ -317,9 +317,7 @@ function updateNamedCousins(rootNode, props) {
// and the same name are rendered into the same form (same as #1939).
// That's probably okay; we don't support it just as we don't support
// mixing React radio buttons with non-React ones.
var otherProps = ReactDOMComponentTree.getFiberCurrentPropsFromNode(
otherNode,
);
var otherProps = getFiberCurrentPropsFromNode(otherNode);
invariant(
otherProps,
'ReactDOMInput: Mixing React and non-React radio inputs with the ' +

View File

@ -7,10 +7,10 @@
import type {TopLevelTypes} from './BrowserEventConstants';
import EventPropagators from 'events/EventPropagators';
import {accumulateTwoPhaseDispatches} from 'events/EventPropagators';
import ExecutionEnvironment from 'fbjs/lib/ExecutionEnvironment';
import FallbackCompositionState from './FallbackCompositionState';
import * as FallbackCompositionState from './FallbackCompositionState';
import SyntheticCompositionEvent from './SyntheticCompositionEvent';
import SyntheticInputEvent from './SyntheticInputEvent';
@ -263,7 +263,7 @@ function extractCompositionEvent(
}
}
EventPropagators.accumulateTwoPhaseDispatches(event);
accumulateTwoPhaseDispatches(event);
return event;
}
@ -422,7 +422,7 @@ function extractBeforeInputEvent(
);
event.data = chars;
EventPropagators.accumulateTwoPhaseDispatches(event);
accumulateTwoPhaseDispatches(event);
return event;
}

View File

@ -5,17 +5,17 @@
* LICENSE file in the root directory of this source tree.
*/
import EventPluginHub from 'events/EventPluginHub';
import EventPropagators from 'events/EventPropagators';
import ReactControlledComponent from 'events/ReactControlledComponent';
import ReactGenericBatching from 'events/ReactGenericBatching';
import {enqueueEvents, processEventQueue} from 'events/EventPluginHub';
import {accumulateTwoPhaseDispatches} from 'events/EventPropagators';
import {enqueueStateRestore} from 'events/ReactControlledComponent';
import {batchedUpdates} from 'events/ReactGenericBatching';
import SyntheticEvent from 'events/SyntheticEvent';
import isTextInputElement from 'shared/isTextInputElement';
import ExecutionEnvironment from 'fbjs/lib/ExecutionEnvironment';
import getEventTarget from './getEventTarget';
import isEventSupported from './isEventSupported';
import ReactDOMComponentTree from '../client/ReactDOMComponentTree';
import {getNodeFromInstance} from '../client/ReactDOMComponentTree';
import * as inputValueTracking from '../client/inputValueTracking';
var eventTypes = {
@ -46,8 +46,8 @@ function createAndAccumulateChangeEvent(inst, nativeEvent, target) {
);
event.type = 'change';
// Flag this event loop as needing state restore.
ReactControlledComponent.enqueueStateRestore(target);
EventPropagators.accumulateTwoPhaseDispatches(event);
enqueueStateRestore(target);
accumulateTwoPhaseDispatches(event);
return event;
}
/**
@ -84,16 +84,16 @@ function manualDispatchChangeEvent(nativeEvent) {
// components don't work properly in conjunction with event bubbling because
// the component is rerendered and the value reverted before all the event
// handlers can run. See https://github.com/facebook/react/issues/708.
ReactGenericBatching.batchedUpdates(runEventInBatch, event);
batchedUpdates(runEventInBatch, event);
}
function runEventInBatch(event) {
EventPluginHub.enqueueEvents(event);
EventPluginHub.processEventQueue(false);
enqueueEvents(event);
processEventQueue(false);
}
function getInstIfValueChanged(targetInst) {
const targetNode = ReactDOMComponentTree.getNodeFromInstance(targetInst);
const targetNode = getNodeFromInstance(targetInst);
if (inputValueTracking.updateValueIfChanged(targetNode)) {
return targetInst;
}
@ -262,9 +262,7 @@ var ChangeEventPlugin = {
nativeEvent,
nativeEventTarget,
) {
var targetNode = targetInst
? ReactDOMComponentTree.getNodeFromInstance(targetInst)
: window;
var targetNode = targetInst ? getNodeFromInstance(targetInst) : window;
var getTargetInstFunc, handleEventFunc;
if (shouldUseChangeEvent(targetNode)) {

View File

@ -5,10 +5,13 @@
* LICENSE file in the root directory of this source tree.
*/
import EventPropagators from 'events/EventPropagators';
import {accumulateEnterLeaveDispatches} from 'events/EventPropagators';
import SyntheticMouseEvent from './SyntheticMouseEvent';
import ReactDOMComponentTree from '../client/ReactDOMComponentTree';
import {
getClosestInstanceFromNode,
getNodeFromInstance,
} from '../client/ReactDOMComponentTree';
var eventTypes = {
mouseEnter: {
@ -67,9 +70,7 @@ var EnterLeaveEventPlugin = {
if (topLevelType === 'topMouseOut') {
from = targetInst;
var related = nativeEvent.relatedTarget || nativeEvent.toElement;
to = related
? ReactDOMComponentTree.getClosestInstanceFromNode(related)
: null;
to = related ? getClosestInstanceFromNode(related) : null;
} else {
// Moving to a node from outside the window.
from = null;
@ -81,12 +82,8 @@ var EnterLeaveEventPlugin = {
return null;
}
var fromNode = from == null
? win
: ReactDOMComponentTree.getNodeFromInstance(from);
var toNode = to == null
? win
: ReactDOMComponentTree.getNodeFromInstance(to);
var fromNode = from == null ? win : getNodeFromInstance(from);
var toNode = to == null ? win : getNodeFromInstance(to);
var leave = SyntheticMouseEvent.getPooled(
eventTypes.mouseLeave,
@ -108,7 +105,7 @@ var EnterLeaveEventPlugin = {
enter.target = toNode;
enter.relatedTarget = fromNode;
EventPropagators.accumulateEnterLeaveDispatches(leave, enter, from, to);
accumulateEnterLeaveDispatches(leave, enter, from, to);
return [leave, enter];
},

View File

@ -24,52 +24,51 @@ var compositionState = {
_fallbackText: null,
};
var FallbackCompositionState = {
initialize(nativeEventTarget) {
compositionState._root = nativeEventTarget;
compositionState._startText = FallbackCompositionState.getText();
return true;
},
reset() {
compositionState._root = null;
compositionState._startText = null;
compositionState._fallbackText = null;
},
getData() {
if (compositionState._fallbackText) {
return compositionState._fallbackText;
}
export function initialize(nativeEventTarget) {
compositionState._root = nativeEventTarget;
compositionState._startText = getText();
return true;
}
var start;
var startValue = compositionState._startText;
var startLength = startValue.length;
var end;
var endValue = FallbackCompositionState.getText();
var endLength = endValue.length;
export function reset() {
compositionState._root = null;
compositionState._startText = null;
compositionState._fallbackText = null;
}
for (start = 0; start < startLength; start++) {
if (startValue[start] !== endValue[start]) {
break;
}
}
var minEnd = startLength - start;
for (end = 1; end <= minEnd; end++) {
if (startValue[startLength - end] !== endValue[endLength - end]) {
break;
}
}
var sliceTail = end > 1 ? 1 - end : undefined;
compositionState._fallbackText = endValue.slice(start, sliceTail);
export function getData() {
if (compositionState._fallbackText) {
return compositionState._fallbackText;
},
getText() {
if ('value' in compositionState._root) {
return compositionState._root.value;
}
return compositionState._root[getTextContentAccessor()];
},
};
}
export default FallbackCompositionState;
var start;
var startValue = compositionState._startText;
var startLength = startValue.length;
var end;
var endValue = getText();
var endLength = endValue.length;
for (start = 0; start < startLength; start++) {
if (startValue[start] !== endValue[start]) {
break;
}
}
var minEnd = startLength - start;
for (end = 1; end <= minEnd; end++) {
if (startValue[startLength - end] !== endValue[endLength - end]) {
break;
}
}
var sliceTail = end > 1 ? 1 - end : undefined;
compositionState._fallbackText = endValue.slice(start, sliceTail);
return compositionState._fallbackText;
}
export function getText() {
if ('value' in compositionState._root) {
return compositionState._root.value;
}
return compositionState._root[getTextContentAccessor()];
}

View File

@ -5,13 +5,19 @@
* LICENSE file in the root directory of this source tree.
*/
import EventPluginRegistry from 'events/EventPluginRegistry';
import ReactEventEmitterMixin from 'events/ReactEventEmitterMixin';
import {registrationNameDependencies} from 'events/EventPluginRegistry';
import ReactDOMEventListener from './ReactDOMEventListener';
import {
setEnabled,
isEnabled,
trapBubbledEvent,
trapCapturedEvent,
} from './ReactDOMEventListener';
import isEventSupported from './isEventSupported';
import BrowserEventConstants from './BrowserEventConstants';
export * from 'events/ReactEventEmitterMixin';
var {topLevelTypes} = BrowserEventConstants;
/**
@ -88,153 +94,83 @@ function getListeningForDocument(mountAt) {
return alreadyListeningTo[mountAt[topListenersIDKey]];
}
var ReactBrowserEventEmitter = Object.assign({}, ReactEventEmitterMixin, {
/**
* Sets whether or not any created callbacks should be enabled.
*
* @param {boolean} enabled True if callbacks should be enabled.
*/
setEnabled: function(enabled) {
if (ReactDOMEventListener) {
ReactDOMEventListener.setEnabled(enabled);
}
},
/**
* We listen for bubbled touch events on the document object.
*
* Firefox v8.01 (and possibly others) exhibited strange behavior when
* mounting `onmousemove` events at some node that was not the document
* element. The symptoms were that if your mouse is not moving over something
* contained within that mount point (for example on the background) the
* top-level listeners for `onmousemove` won't be called. However, if you
* register the `mousemove` on the document object, then it will of course
* catch all `mousemove`s. This along with iOS quirks, justifies restricting
* top-level listeners to the document object only, at least for these
* movement types of events and possibly all events.
*
* @see http://www.quirksmode.org/blog/archives/2010/09/click_event_del.html
*
* Also, `keyup`/`keypress`/`keydown` do not bubble to the window on IE, but
* they bubble to document.
*
* @param {string} registrationName Name of listener (e.g. `onClick`).
* @param {object} contentDocumentHandle Document which owns the container
*/
export function listenTo(registrationName, contentDocumentHandle) {
var mountAt = contentDocumentHandle;
var isListening = getListeningForDocument(mountAt);
var dependencies = registrationNameDependencies[registrationName];
/**
* @return {boolean} True if callbacks are enabled.
*/
isEnabled: function() {
return !!(ReactDOMEventListener && ReactDOMEventListener.isEnabled());
},
/**
* We listen for bubbled touch events on the document object.
*
* Firefox v8.01 (and possibly others) exhibited strange behavior when
* mounting `onmousemove` events at some node that was not the document
* element. The symptoms were that if your mouse is not moving over something
* contained within that mount point (for example on the background) the
* top-level listeners for `onmousemove` won't be called. However, if you
* register the `mousemove` on the document object, then it will of course
* catch all `mousemove`s. This along with iOS quirks, justifies restricting
* top-level listeners to the document object only, at least for these
* movement types of events and possibly all events.
*
* @see http://www.quirksmode.org/blog/archives/2010/09/click_event_del.html
*
* Also, `keyup`/`keypress`/`keydown` do not bubble to the window on IE, but
* they bubble to document.
*
* @param {string} registrationName Name of listener (e.g. `onClick`).
* @param {object} contentDocumentHandle Document which owns the container
*/
listenTo: function(registrationName, contentDocumentHandle) {
var mountAt = contentDocumentHandle;
var isListening = getListeningForDocument(mountAt);
var dependencies =
EventPluginRegistry.registrationNameDependencies[registrationName];
for (var i = 0; i < dependencies.length; i++) {
var dependency = dependencies[i];
if (
!(isListening.hasOwnProperty(dependency) && isListening[dependency])
) {
if (dependency === 'topWheel') {
if (isEventSupported('wheel')) {
ReactDOMEventListener.trapBubbledEvent(
'topWheel',
'wheel',
mountAt,
);
} else if (isEventSupported('mousewheel')) {
ReactDOMEventListener.trapBubbledEvent(
'topWheel',
'mousewheel',
mountAt,
);
} else {
// Firefox needs to capture a different mouse scroll event.
// @see http://www.quirksmode.org/dom/events/tests/scroll.html
ReactDOMEventListener.trapBubbledEvent(
'topWheel',
'DOMMouseScroll',
mountAt,
);
}
} else if (dependency === 'topScroll') {
ReactDOMEventListener.trapCapturedEvent(
'topScroll',
'scroll',
mountAt,
);
} else if (dependency === 'topFocus' || dependency === 'topBlur') {
ReactDOMEventListener.trapCapturedEvent('topFocus', 'focus', mountAt);
ReactDOMEventListener.trapCapturedEvent('topBlur', 'blur', mountAt);
// to make sure blur and focus event listeners are only attached once
isListening.topBlur = true;
isListening.topFocus = true;
} else if (dependency === 'topCancel') {
if (isEventSupported('cancel', true)) {
ReactDOMEventListener.trapCapturedEvent(
'topCancel',
'cancel',
mountAt,
);
}
isListening.topCancel = true;
} else if (dependency === 'topClose') {
if (isEventSupported('close', true)) {
ReactDOMEventListener.trapCapturedEvent(
'topClose',
'close',
mountAt,
);
}
isListening.topClose = true;
} else if (topLevelTypes.hasOwnProperty(dependency)) {
ReactDOMEventListener.trapBubbledEvent(
dependency,
topLevelTypes[dependency],
mountAt,
);
for (var i = 0; i < dependencies.length; i++) {
var dependency = dependencies[i];
if (!(isListening.hasOwnProperty(dependency) && isListening[dependency])) {
if (dependency === 'topWheel') {
if (isEventSupported('wheel')) {
trapBubbledEvent('topWheel', 'wheel', mountAt);
} else if (isEventSupported('mousewheel')) {
trapBubbledEvent('topWheel', 'mousewheel', mountAt);
} else {
// Firefox needs to capture a different mouse scroll event.
// @see http://www.quirksmode.org/dom/events/tests/scroll.html
trapBubbledEvent('topWheel', 'DOMMouseScroll', mountAt);
}
} else if (dependency === 'topScroll') {
trapCapturedEvent('topScroll', 'scroll', mountAt);
} else if (dependency === 'topFocus' || dependency === 'topBlur') {
trapCapturedEvent('topFocus', 'focus', mountAt);
trapCapturedEvent('topBlur', 'blur', mountAt);
isListening[dependency] = true;
// to make sure blur and focus event listeners are only attached once
isListening.topBlur = true;
isListening.topFocus = true;
} else if (dependency === 'topCancel') {
if (isEventSupported('cancel', true)) {
trapCapturedEvent('topCancel', 'cancel', mountAt);
}
isListening.topCancel = true;
} else if (dependency === 'topClose') {
if (isEventSupported('close', true)) {
trapCapturedEvent('topClose', 'close', mountAt);
}
isListening.topClose = true;
} else if (topLevelTypes.hasOwnProperty(dependency)) {
trapBubbledEvent(dependency, topLevelTypes[dependency], mountAt);
}
isListening[dependency] = true;
}
},
}
}
isListeningToAllDependencies: function(registrationName, mountAt) {
var isListening = getListeningForDocument(mountAt);
var dependencies =
EventPluginRegistry.registrationNameDependencies[registrationName];
for (var i = 0; i < dependencies.length; i++) {
var dependency = dependencies[i];
if (
!(isListening.hasOwnProperty(dependency) && isListening[dependency])
) {
return false;
}
export function isListeningToAllDependencies(registrationName, mountAt) {
var isListening = getListeningForDocument(mountAt);
var dependencies = registrationNameDependencies[registrationName];
for (var i = 0; i < dependencies.length; i++) {
var dependency = dependencies[i];
if (!(isListening.hasOwnProperty(dependency) && isListening[dependency])) {
return false;
}
return true;
},
}
return true;
}
trapBubbledEvent: function(topLevelType, handlerBaseName, handle) {
return ReactDOMEventListener.trapBubbledEvent(
topLevelType,
handlerBaseName,
handle,
);
},
trapCapturedEvent: function(topLevelType, handlerBaseName, handle) {
return ReactDOMEventListener.trapCapturedEvent(
topLevelType,
handlerBaseName,
handle,
);
},
});
export default ReactBrowserEventEmitter;
export {setEnabled, isEnabled, trapBubbledEvent, trapCapturedEvent};

View File

@ -5,13 +5,13 @@
* LICENSE file in the root directory of this source tree.
*/
import ReactGenericBatching from 'events/ReactGenericBatching';
import {batchedUpdates} from 'events/ReactGenericBatching';
import {isFiberMounted} from 'shared/ReactFiberTreeReflection';
import {HostRoot} from 'shared/ReactTypeOfWork';
import EventListener from 'fbjs/lib/EventListener';
import getEventTarget from './getEventTarget';
import ReactDOMComponentTree from '../client/ReactDOMComponentTree';
import {getClosestInstanceFromNode} from '../client/ReactDOMComponentTree';
var CALLBACK_BOOKKEEPING_POOL_SIZE = 10;
var callbackBookkeepingPool = [];
@ -80,12 +80,12 @@ function handleTopLevelImpl(bookKeeping) {
break;
}
bookKeeping.ancestors.push(ancestor);
ancestor = ReactDOMComponentTree.getClosestInstanceFromNode(root);
ancestor = getClosestInstanceFromNode(root);
} while (ancestor);
for (var i = 0; i < bookKeeping.ancestors.length; i++) {
targetInst = bookKeeping.ancestors[i];
ReactDOMEventListener._handleTopLevel(
_handleTopLevel(
bookKeeping.topLevelType,
targetInst,
bookKeeping.nativeEvent,
@ -94,99 +94,94 @@ function handleTopLevelImpl(bookKeeping) {
}
}
var ReactDOMEventListener = {
_enabled: true,
_handleTopLevel: null,
// TODO: can we stop exporting these?
export let _enabled = true;
export let _handleTopLevel: null;
setHandleTopLevel: function(handleTopLevel) {
ReactDOMEventListener._handleTopLevel = handleTopLevel;
},
export function setHandleTopLevel(handleTopLevel) {
_handleTopLevel = handleTopLevel;
}
setEnabled: function(enabled) {
ReactDOMEventListener._enabled = !!enabled;
},
export function setEnabled(enabled) {
_enabled = !!enabled;
}
isEnabled: function() {
return ReactDOMEventListener._enabled;
},
export function isEnabled() {
return _enabled;
}
/**
* Traps top-level events by using event bubbling.
*
* @param {string} topLevelType Record from `BrowserEventConstants`.
* @param {string} handlerBaseName Event name (e.g. "click").
* @param {object} element Element on which to attach listener.
* @return {?object} An object with a remove function which will forcefully
* remove the listener.
* @internal
*/
trapBubbledEvent: function(topLevelType, handlerBaseName, element) {
if (!element) {
return null;
}
return EventListener.listen(
element,
handlerBaseName,
ReactDOMEventListener.dispatchEvent.bind(null, topLevelType),
);
},
/**
* Traps top-level events by using event bubbling.
*
* @param {string} topLevelType Record from `BrowserEventConstants`.
* @param {string} handlerBaseName Event name (e.g. "click").
* @param {object} element Element on which to attach listener.
* @return {?object} An object with a remove function which will forcefully
* remove the listener.
* @internal
*/
export function trapBubbledEvent(topLevelType, handlerBaseName, element) {
if (!element) {
return null;
}
return EventListener.listen(
element,
handlerBaseName,
dispatchEvent.bind(null, topLevelType),
);
}
/**
* Traps a top-level event by using event capturing.
*
* @param {string} topLevelType Record from `BrowserEventConstants`.
* @param {string} handlerBaseName Event name (e.g. "click").
* @param {object} element Element on which to attach listener.
* @return {?object} An object with a remove function which will forcefully
* remove the listener.
* @internal
*/
trapCapturedEvent: function(topLevelType, handlerBaseName, element) {
if (!element) {
return null;
}
return EventListener.capture(
element,
handlerBaseName,
ReactDOMEventListener.dispatchEvent.bind(null, topLevelType),
);
},
/**
* Traps a top-level event by using event capturing.
*
* @param {string} topLevelType Record from `BrowserEventConstants`.
* @param {string} handlerBaseName Event name (e.g. "click").
* @param {object} element Element on which to attach listener.
* @return {?object} An object with a remove function which will forcefully
* remove the listener.
* @internal
*/
export function trapCapturedEvent(topLevelType, handlerBaseName, element) {
if (!element) {
return null;
}
return EventListener.capture(
element,
handlerBaseName,
dispatchEvent.bind(null, topLevelType),
);
}
dispatchEvent: function(topLevelType, nativeEvent) {
if (!ReactDOMEventListener._enabled) {
return;
}
export function dispatchEvent(topLevelType, nativeEvent) {
if (!_enabled) {
return;
}
var nativeEventTarget = getEventTarget(nativeEvent);
var targetInst = ReactDOMComponentTree.getClosestInstanceFromNode(
nativeEventTarget,
);
if (
targetInst !== null &&
typeof targetInst.tag === 'number' &&
!isFiberMounted(targetInst)
) {
// If we get an event (ex: img onload) before committing that
// component's mount, ignore it for now (that is, treat it as if it was an
// event on a non-React tree). We might also consider queueing events and
// dispatching them after the mount.
targetInst = null;
}
var nativeEventTarget = getEventTarget(nativeEvent);
var targetInst = getClosestInstanceFromNode(nativeEventTarget);
if (
targetInst !== null &&
typeof targetInst.tag === 'number' &&
!isFiberMounted(targetInst)
) {
// If we get an event (ex: img onload) before committing that
// component's mount, ignore it for now (that is, treat it as if it was an
// event on a non-React tree). We might also consider queueing events and
// dispatching them after the mount.
targetInst = null;
}
var bookKeeping = getTopLevelCallbackBookKeeping(
topLevelType,
nativeEvent,
targetInst,
);
var bookKeeping = getTopLevelCallbackBookKeeping(
topLevelType,
nativeEvent,
targetInst,
);
try {
// Event queue being processed in the same cycle allows
// `preventDefault`.
ReactGenericBatching.batchedUpdates(handleTopLevelImpl, bookKeeping);
} finally {
releaseTopLevelCallbackBookKeeping(bookKeeping);
}
},
};
export default ReactDOMEventListener;
try {
// Event queue being processed in the same cycle allows
// `preventDefault`.
batchedUpdates(handleTopLevelImpl, bookKeeping);
} finally {
releaseTopLevelCallbackBookKeeping(bookKeeping);
}
}

View File

@ -5,15 +5,15 @@
* LICENSE file in the root directory of this source tree.
*/
import EventPropagators from 'events/EventPropagators';
import {accumulateTwoPhaseDispatches} from 'events/EventPropagators';
import ExecutionEnvironment from 'fbjs/lib/ExecutionEnvironment';
import SyntheticEvent from 'events/SyntheticEvent';
import isTextInputElement from 'shared/isTextInputElement';
import getActiveElement from 'fbjs/lib/getActiveElement';
import shallowEqual from 'fbjs/lib/shallowEqual';
import ReactBrowserEventEmitter from './ReactBrowserEventEmitter';
import ReactDOMComponentTree from '../client/ReactDOMComponentTree';
import {isListeningToAllDependencies} from './ReactBrowserEventEmitter';
import {getNodeFromInstance} from '../client/ReactDOMComponentTree';
import * as ReactInputSelection from '../client/ReactInputSelection';
import {DOCUMENT_NODE} from '../shared/HTMLNodeType';
@ -46,11 +46,6 @@ var activeElementInst = null;
var lastSelection = null;
var mouseDown = false;
// Track whether all listeners exists for this plugin. If none exist, we do
// not extract events. See #3639.
var isListeningToAllDependencies =
ReactBrowserEventEmitter.isListeningToAllDependencies;
/**
* Get an object which is a unique representation of the current selection.
*
@ -114,7 +109,7 @@ function constructSelectEvent(nativeEvent, nativeEventTarget) {
syntheticEvent.type = 'select';
syntheticEvent.target = activeElement;
EventPropagators.accumulateTwoPhaseDispatches(syntheticEvent);
accumulateTwoPhaseDispatches(syntheticEvent);
return syntheticEvent;
}
@ -150,13 +145,13 @@ var SelectEventPlugin = {
: nativeEventTarget.nodeType === DOCUMENT_NODE
? nativeEventTarget
: nativeEventTarget.ownerDocument;
// Track whether all listeners exists for this plugin. If none exist, we do
// not extract events. See #3639.
if (!doc || !isListeningToAllDependencies('onSelect', doc)) {
return null;
}
var targetNode = targetInst
? ReactDOMComponentTree.getNodeFromInstance(targetInst)
: window;
var targetNode = targetInst ? getNodeFromInstance(targetInst) : window;
switch (topLevelType) {
// Track the input node that has focus.

View File

@ -15,7 +15,7 @@ import type {
import type {Fiber} from 'react-reconciler/src/ReactFiber';
import type {EventTypes, PluginModule} from 'events/PluginModuleType';
import EventPropagators from 'events/EventPropagators';
import {accumulateTwoPhaseDispatches} from 'events/EventPropagators';
import SyntheticEvent from 'events/SyntheticEvent';
import warning from 'fbjs/lib/warning';
@ -274,7 +274,7 @@ var SimpleEventPlugin: PluginModule<MouseEvent> = {
nativeEvent,
nativeEventTarget,
);
EventPropagators.accumulateTwoPhaseDispatches(event);
accumulateTwoPhaseDispatches(event);
return event;
},
};

View File

@ -7,15 +7,12 @@
* @flow
*/
import EventPluginUtils from 'events/EventPluginUtils';
import EventPropagators from 'events/EventPropagators';
import {isStartish, isEndish} from 'events/EventPluginUtils';
import {accumulateTwoPhaseDispatches} from 'events/EventPropagators';
import TouchEventUtils from 'fbjs/lib/TouchEventUtils';
import SyntheticUIEvent from './SyntheticUIEvent';
var isStartish = EventPluginUtils.isStartish;
var isEndish = EventPluginUtils.isEndish;
/**
* We are extending the Flow 'Touch' declaration to enable using bracket
* notation to access properties.
@ -144,7 +141,7 @@ var TapEventPlugin = {
startCoords.x = 0;
startCoords.y = 0;
}
EventPropagators.accumulateTwoPhaseDispatches(event);
accumulateTwoPhaseDispatches(event);
return event;
},
};

View File

@ -49,7 +49,7 @@ describe('BeforeInputEventPlugin', function() {
this.ReactDOM = require('react-dom');
// TODO: can we express this test with only public API?
this.ReactDOMComponentTree = require('../../client/ReactDOMComponentTree').default;
this.ReactDOMComponentTree = require('../../client/ReactDOMComponentTree');
this.SyntheticCompositionEvent = require('../SyntheticCompositionEvent').default;
this.SyntheticInputEvent = require('../SyntheticInputEvent').default;
this.BeforeInputEventPlugin = require('../BeforeInputEventPlugin').default;

View File

@ -16,7 +16,7 @@ describe('FallbackCompositionState', () => {
beforeEach(() => {
// TODO: can we express this test with only public API?
FallbackCompositionState = require('../FallbackCompositionState').default;
FallbackCompositionState = require('../FallbackCompositionState');
});
function getInput() {

View File

@ -30,8 +30,7 @@ describe('SelectEventPlugin', () => {
ReactDOM = require('react-dom');
ReactTestUtils = require('react-dom/test-utils');
// TODO: can we express this test with only public API?
ReactDOMComponentTree = require('../../client/ReactDOMComponentTree')
.default;
ReactDOMComponentTree = require('../../client/ReactDOMComponentTree');
SelectEventPlugin = require('../SelectEventPlugin').default;
});

View File

@ -5,7 +5,15 @@
* LICENSE file in the root directory of this source tree.
*/
import DOMProperty from '../shared/DOMProperty';
import {
ATTRIBUTE_NAME_CHAR,
ATTRIBUTE_NAME_START_CHAR,
ID_ATTRIBUTE_NAME,
ROOT_ATTRIBUTE_NAME,
getPropertyInfo,
shouldAttributeAcceptBooleanValue,
shouldSetAttribute,
} from '../shared/DOMProperty';
import quoteAttributeValueForBrowser
from '../shared/quoteAttributeValueForBrowser';
import warning from 'fbjs/lib/warning';
@ -13,11 +21,7 @@ import warning from 'fbjs/lib/warning';
// isAttributeNameSafe() is currently duplicated in DOMPropertyOperations.
// TODO: Find a better place for this.
var VALID_ATTRIBUTE_NAME_REGEX = new RegExp(
'^[' +
DOMProperty.ATTRIBUTE_NAME_START_CHAR +
'][' +
DOMProperty.ATTRIBUTE_NAME_CHAR +
']*$',
'^[' + ATTRIBUTE_NAME_START_CHAR + '][' + ATTRIBUTE_NAME_CHAR + ']*$',
);
var illegalAttributeNameCache = {};
var validatedAttributeNameCache = {};
@ -54,70 +58,65 @@ function shouldIgnoreValue(propertyInfo, value) {
/**
* Operations for dealing with DOM properties.
*/
var DOMMarkupOperations = {
/**
* Creates markup for the ID property.
*
* @param {string} id Unescaped ID.
* @return {string} Markup string.
*/
createMarkupForID: function(id) {
return (
DOMProperty.ID_ATTRIBUTE_NAME + '=' + quoteAttributeValueForBrowser(id)
);
},
createMarkupForRoot: function() {
return DOMProperty.ROOT_ATTRIBUTE_NAME + '=""';
},
/**
* Creates markup for the ID property.
*
* @param {string} id Unescaped ID.
* @return {string} Markup string.
*/
export function createMarkupForID(id) {
return ID_ATTRIBUTE_NAME + '=' + quoteAttributeValueForBrowser(id);
}
/**
* Creates markup for a property.
*
* @param {string} name
* @param {*} value
* @return {?string} Markup string, or null if the property was invalid.
*/
createMarkupForProperty: function(name, value) {
var propertyInfo = DOMProperty.getPropertyInfo(name);
if (propertyInfo) {
if (shouldIgnoreValue(propertyInfo, value)) {
return '';
}
var attributeName = propertyInfo.attributeName;
if (
propertyInfo.hasBooleanValue ||
(propertyInfo.hasOverloadedBooleanValue && value === true)
) {
return attributeName + '=""';
} else if (
typeof value !== 'boolean' ||
DOMProperty.shouldAttributeAcceptBooleanValue(name)
) {
return attributeName + '=' + quoteAttributeValueForBrowser(value);
}
} else if (DOMProperty.shouldSetAttribute(name, value)) {
if (value == null) {
return '';
}
return name + '=' + quoteAttributeValueForBrowser(value);
export function createMarkupForRoot() {
return ROOT_ATTRIBUTE_NAME + '=""';
}
/**
* Creates markup for a property.
*
* @param {string} name
* @param {*} value
* @return {?string} Markup string, or null if the property was invalid.
*/
export function createMarkupForProperty(name, value) {
var propertyInfo = getPropertyInfo(name);
if (propertyInfo) {
if (shouldIgnoreValue(propertyInfo, value)) {
return '';
}
return null;
},
/**
* Creates markup for a custom property.
*
* @param {string} name
* @param {*} value
* @return {string} Markup string, or empty string if the property was invalid.
*/
createMarkupForCustomAttribute: function(name, value) {
if (!isAttributeNameSafe(name) || value == null) {
var attributeName = propertyInfo.attributeName;
if (
propertyInfo.hasBooleanValue ||
(propertyInfo.hasOverloadedBooleanValue && value === true)
) {
return attributeName + '=""';
} else if (
typeof value !== 'boolean' ||
shouldAttributeAcceptBooleanValue(name)
) {
return attributeName + '=' + quoteAttributeValueForBrowser(value);
}
} else if (shouldSetAttribute(name, value)) {
if (value == null) {
return '';
}
return name + '=' + quoteAttributeValueForBrowser(value);
},
};
}
return null;
}
export default DOMMarkupOperations;
/**
* Creates markup for a custom property.
*
* @param {string} name
* @param {*} value
* @return {string} Markup string, or empty string if the property was invalid.
*/
export function createMarkupForCustomAttribute(name, value) {
if (!isAttributeNameSafe(name) || value == null) {
return '';
}
return name + '=' + quoteAttributeValueForBrowser(value);
}

View File

@ -20,7 +20,11 @@ import checkPropTypes from 'prop-types/checkPropTypes';
import describeComponentFrame from 'shared/describeComponentFrame';
import {ReactDebugCurrentFrame} from 'shared/ReactGlobalSharedState';
import DOMMarkupOperations from './DOMMarkupOperations';
import {
createMarkupForCustomAttribute,
createMarkupForProperty,
createMarkupForRoot,
} from './DOMMarkupOperations';
import {
Namespaces,
getIntrinsicNamespace,
@ -319,13 +323,10 @@ function createOpenTagMarkup(
var markup = null;
if (isCustomComponent(tagLowercase, props)) {
if (!RESERVED_PROPS.hasOwnProperty(propKey)) {
markup = DOMMarkupOperations.createMarkupForCustomAttribute(
propKey,
propValue,
);
markup = createMarkupForCustomAttribute(propKey, propValue);
}
} else {
markup = DOMMarkupOperations.createMarkupForProperty(propKey, propValue);
markup = createMarkupForProperty(propKey, propValue);
}
if (markup) {
ret += ' ' + markup;
@ -339,7 +340,7 @@ function createOpenTagMarkup(
}
if (isRootElement) {
ret += ' ' + DOMMarkupOperations.createMarkupForRoot();
ret += ' ' + createMarkupForRoot();
}
return ret;
}

View File

@ -68,7 +68,7 @@ var DOMPropertyInjection = {
for (var propName in Properties) {
invariant(
!DOMProperty.properties.hasOwnProperty(propName),
!properties.hasOwnProperty(propName),
"injectDOMPropertyConfig(...): You're trying to inject DOM property " +
"'%s' which has already been injected. You may be accidentally " +
'injecting the same DOM property config twice, or you may be ' +
@ -129,135 +129,114 @@ var DOMPropertyInjection = {
// without case-sensitivity. This allows the whitelist to pick up
// `allowfullscreen`, which should be written using the property configuration
// for `allowFullscreen`
DOMProperty.properties[propName] = propertyInfo;
properties[propName] = propertyInfo;
}
},
};
/* eslint-disable max-len */
var ATTRIBUTE_NAME_START_CHAR =
export const ATTRIBUTE_NAME_START_CHAR =
':A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD';
/* eslint-enable max-len */
export const ATTRIBUTE_NAME_CHAR =
ATTRIBUTE_NAME_START_CHAR + '\\-.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040';
export const ID_ATTRIBUTE_NAME = 'data-reactid';
export const ROOT_ATTRIBUTE_NAME = 'data-reactroot';
/**
* DOMProperty exports lookup objects that can be used like functions:
* Map from property "standard name" to an object with info about how to set
* the property in the DOM. Each object contains:
*
* > DOMProperty.isValid['id']
* true
* > DOMProperty.isValid['foobar']
* undefined
*
* Although this may be confusing, it performs better in general.
*
* @see http://jsperf.com/key-exists
* @see http://jsperf.com/key-missing
* attributeName:
* Used when rendering markup or with `*Attribute()`.
* attributeNamespace
* propertyName:
* Used on DOM node instances. (This includes properties that mutate due to
* external factors.)
* mutationMethod:
* If non-null, used instead of the property or `setAttribute()` after
* initial render.
* mustUseProperty:
* Whether the property must be accessed and mutated as an object property.
* hasBooleanValue:
* Whether the property should be removed when set to a falsey value.
* hasNumericValue:
* Whether the property must be numeric or parse as a numeric and should be
* removed when set to a falsey value.
* hasPositiveNumericValue:
* Whether the property must be positive numeric or parse as a positive
* numeric and should be removed when set to a falsey value.
* hasOverloadedBooleanValue:
* Whether the property can be used as a flag as well as with a value.
* Removed when strictly equal to false; present without a value when
* strictly equal to true; present with a value otherwise.
*/
var DOMProperty = {
ID_ATTRIBUTE_NAME: 'data-reactid',
ROOT_ATTRIBUTE_NAME: 'data-reactroot',
export const properties = {};
ATTRIBUTE_NAME_START_CHAR: ATTRIBUTE_NAME_START_CHAR,
ATTRIBUTE_NAME_CHAR: ATTRIBUTE_NAME_START_CHAR +
'\\-.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040',
/**
* Map from property "standard name" to an object with info about how to set
* the property in the DOM. Each object contains:
*
* attributeName:
* Used when rendering markup or with `*Attribute()`.
* attributeNamespace
* propertyName:
* Used on DOM node instances. (This includes properties that mutate due to
* external factors.)
* mutationMethod:
* If non-null, used instead of the property or `setAttribute()` after
* initial render.
* mustUseProperty:
* Whether the property must be accessed and mutated as an object property.
* hasBooleanValue:
* Whether the property should be removed when set to a falsey value.
* hasNumericValue:
* Whether the property must be numeric or parse as a numeric and should be
* removed when set to a falsey value.
* hasPositiveNumericValue:
* Whether the property must be positive numeric or parse as a positive
* numeric and should be removed when set to a falsey value.
* hasOverloadedBooleanValue:
* Whether the property can be used as a flag as well as with a value.
* Removed when strictly equal to false; present without a value when
* strictly equal to true; present with a value otherwise.
*/
properties: {},
/**
* Checks whether a property name is a writeable attribute.
* @method
*/
shouldSetAttribute: function(name, value) {
if (DOMProperty.isReservedProp(name)) {
return false;
}
if (
(name[0] === 'o' || name[0] === 'O') &&
(name[1] === 'n' || name[1] === 'N') &&
name.length > 2
) {
return false;
}
if (value === null) {
/**
* Checks whether a property name is a writeable attribute.
* @method
*/
export function shouldSetAttribute(name, value) {
if (isReservedProp(name)) {
return false;
}
if (
(name[0] === 'o' || name[0] === 'O') &&
(name[1] === 'n' || name[1] === 'N') &&
name.length > 2
) {
return false;
}
if (value === null) {
return true;
}
switch (typeof value) {
case 'boolean':
return shouldAttributeAcceptBooleanValue(name);
case 'undefined':
case 'number':
case 'string':
case 'object':
return true;
}
switch (typeof value) {
case 'boolean':
return DOMProperty.shouldAttributeAcceptBooleanValue(name);
case 'undefined':
case 'number':
case 'string':
case 'object':
return true;
default:
// function, symbol
return false;
}
},
default:
// function, symbol
return false;
}
}
getPropertyInfo(name) {
return DOMProperty.properties.hasOwnProperty(name)
? DOMProperty.properties[name]
: null;
},
export function getPropertyInfo(name) {
return properties.hasOwnProperty(name) ? properties[name] : null;
}
shouldAttributeAcceptBooleanValue(name) {
if (DOMProperty.isReservedProp(name)) {
return true;
}
let propertyInfo = DOMProperty.getPropertyInfo(name);
if (propertyInfo) {
return (
propertyInfo.hasBooleanValue ||
propertyInfo.hasStringBooleanValue ||
propertyInfo.hasOverloadedBooleanValue
);
}
var prefix = name.toLowerCase().slice(0, 5);
return prefix === 'data-' || prefix === 'aria-';
},
export function shouldAttributeAcceptBooleanValue(name) {
if (isReservedProp(name)) {
return true;
}
let propertyInfo = getPropertyInfo(name);
if (propertyInfo) {
return (
propertyInfo.hasBooleanValue ||
propertyInfo.hasStringBooleanValue ||
propertyInfo.hasOverloadedBooleanValue
);
}
var prefix = name.toLowerCase().slice(0, 5);
return prefix === 'data-' || prefix === 'aria-';
}
/**
* Checks to see if a property name is within the list of properties
* reserved for internal React operations. These properties should
* not be set on an HTML element.
*
* @private
* @param {string} name
* @return {boolean} If the name is within reserved props
*/
isReservedProp(name) {
return RESERVED_PROPS.hasOwnProperty(name);
},
/**
* Checks to see if a property name is within the list of properties
* reserved for internal React operations. These properties should
* not be set on an HTML element.
*
* @private
* @param {string} name
* @return {boolean} If the name is within reserved props
*/
export function isReservedProp(name) {
return RESERVED_PROPS.hasOwnProperty(name);
}
injection: DOMPropertyInjection,
};
export default DOMProperty;
export const injection = DOMPropertyInjection;

View File

@ -5,16 +5,14 @@
* LICENSE file in the root directory of this source tree.
*/
import DOMProperty from './DOMProperty';
import {injection} from './DOMProperty';
var MUST_USE_PROPERTY = DOMProperty.injection.MUST_USE_PROPERTY;
var HAS_BOOLEAN_VALUE = DOMProperty.injection.HAS_BOOLEAN_VALUE;
var HAS_NUMERIC_VALUE = DOMProperty.injection.HAS_NUMERIC_VALUE;
var HAS_POSITIVE_NUMERIC_VALUE =
DOMProperty.injection.HAS_POSITIVE_NUMERIC_VALUE;
var HAS_OVERLOADED_BOOLEAN_VALUE =
DOMProperty.injection.HAS_OVERLOADED_BOOLEAN_VALUE;
var HAS_STRING_BOOLEAN_VALUE = DOMProperty.injection.HAS_STRING_BOOLEAN_VALUE;
var MUST_USE_PROPERTY = injection.MUST_USE_PROPERTY;
var HAS_BOOLEAN_VALUE = injection.HAS_BOOLEAN_VALUE;
var HAS_NUMERIC_VALUE = injection.HAS_NUMERIC_VALUE;
var HAS_POSITIVE_NUMERIC_VALUE = injection.HAS_POSITIVE_NUMERIC_VALUE;
var HAS_OVERLOADED_BOOLEAN_VALUE = injection.HAS_OVERLOADED_BOOLEAN_VALUE;
var HAS_STRING_BOOLEAN_VALUE = injection.HAS_STRING_BOOLEAN_VALUE;
var HTMLDOMPropertyConfig = {
// When adding attributes to this list, be sure to also add them to

View File

@ -5,7 +5,7 @@
* LICENSE file in the root directory of this source tree.
*/
import DOMProperty from './DOMProperty';
import * as DOMProperty from './DOMProperty';
import HTMLDOMPropertyConfig from './HTMLDOMPropertyConfig';
import SVGDOMPropertyConfig from './SVGDOMPropertyConfig';

View File

@ -8,15 +8,13 @@
import warning from 'fbjs/lib/warning';
import {ReactDebugCurrentFrame} from 'shared/ReactGlobalSharedState';
import DOMProperty from './DOMProperty';
import {ATTRIBUTE_NAME_CHAR} from './DOMProperty';
import isCustomComponent from './isCustomComponent';
import validAriaProperties from './validAriaProperties';
var warnedProperties = {};
var rARIA = new RegExp('^(aria)-[' + DOMProperty.ATTRIBUTE_NAME_CHAR + ']*$');
var rARIACamel = new RegExp(
'^(aria)[A-Z][' + DOMProperty.ATTRIBUTE_NAME_CHAR + ']*$',
);
var rARIA = new RegExp('^(aria)-[' + ATTRIBUTE_NAME_CHAR + ']*$');
var rARIACamel = new RegExp('^(aria)[A-Z][' + ATTRIBUTE_NAME_CHAR + ']*$');
var hasOwnProperty = Object.prototype.hasOwnProperty;

View File

@ -5,11 +5,20 @@
* LICENSE file in the root directory of this source tree.
*/
import EventPluginRegistry from 'events/EventPluginRegistry';
import {
registrationNameModules,
plugins,
possibleRegistrationNames,
} from 'events/EventPluginRegistry';
import {ReactDebugCurrentFrame} from 'shared/ReactGlobalSharedState';
import warning from 'fbjs/lib/warning';
import DOMProperty from './DOMProperty';
import {
ATTRIBUTE_NAME_CHAR,
isReservedProp,
shouldAttributeAcceptBooleanValue,
shouldSetAttribute,
} from './DOMProperty';
import isCustomComponent from './isCustomComponent';
import possibleStandardNames from './possibleStandardNames';
@ -22,34 +31,29 @@ if (__DEV__) {
var warnedProperties = {};
var hasOwnProperty = Object.prototype.hasOwnProperty;
var EVENT_NAME_REGEX = /^on[A-Z]/;
var rARIA = new RegExp('^(aria)-[' + DOMProperty.ATTRIBUTE_NAME_CHAR + ']*$');
var rARIACamel = new RegExp(
'^(aria)[A-Z][' + DOMProperty.ATTRIBUTE_NAME_CHAR + ']*$',
);
var rARIA = new RegExp('^(aria)-[' + ATTRIBUTE_NAME_CHAR + ']*$');
var rARIACamel = new RegExp('^(aria)[A-Z][' + ATTRIBUTE_NAME_CHAR + ']*$');
var validateProperty = function(tagName, name, value) {
if (hasOwnProperty.call(warnedProperties, name) && warnedProperties[name]) {
return true;
}
if (EventPluginRegistry.registrationNameModules.hasOwnProperty(name)) {
if (registrationNameModules.hasOwnProperty(name)) {
return true;
}
if (
EventPluginRegistry.plugins.length === 0 &&
EVENT_NAME_REGEX.test(name)
) {
if (plugins.length === 0 && EVENT_NAME_REGEX.test(name)) {
// If no event plugins have been injected, we might be in a server environment.
// Don't check events in this case.
return true;
}
var lowerCasedName = name.toLowerCase();
var registrationName = EventPluginRegistry.possibleRegistrationNames.hasOwnProperty(
var registrationName = possibleRegistrationNames.hasOwnProperty(
lowerCasedName,
)
? EventPluginRegistry.possibleRegistrationNames[lowerCasedName]
? possibleRegistrationNames[lowerCasedName]
: null;
if (registrationName != null) {
@ -140,7 +144,7 @@ if (__DEV__) {
return true;
}
const isReserved = DOMProperty.isReservedProp(name);
const isReserved = isReservedProp(name);
// Known attributes should match the casing specified in the property config.
if (possibleStandardNames.hasOwnProperty(lowerCasedName)) {
@ -176,7 +180,7 @@ if (__DEV__) {
if (
typeof value === 'boolean' &&
!DOMProperty.shouldAttributeAcceptBooleanValue(name)
!shouldAttributeAcceptBooleanValue(name)
) {
if (value) {
warning(
@ -220,7 +224,7 @@ if (__DEV__) {
}
// Warn when a known attribute is a bad type
if (!DOMProperty.shouldSetAttribute(name, value)) {
if (!shouldSetAttribute(name, value)) {
warnedProperties[name] = true;
return false;
}

View File

@ -5,9 +5,9 @@
* LICENSE file in the root directory of this source tree.
*/
import DOMProperty from './DOMProperty';
import {injection} from './DOMProperty';
var {HAS_STRING_BOOLEAN_VALUE} = DOMProperty.injection;
var {HAS_STRING_BOOLEAN_VALUE} = injection;
var NS = {
xlink: 'http://www.w3.org/1999/xlink',

View File

@ -6,7 +6,7 @@
*/
import ReactDOM from 'react-dom';
import EventPluginUtils from 'events/EventPluginUtils';
import * as EventPluginUtils from 'events/EventPluginUtils';
import ResponderEventPlugin from 'events/ResponderEventPlugin';
import ResponderTouchHistoryStore from 'events/ResponderTouchHistoryStore';

View File

@ -9,7 +9,10 @@
import type {ReactNativeBaseComponentViewConfig} from './ReactNativeTypes';
import EventPropagators from 'events/EventPropagators';
import {
accumulateTwoPhaseDispatches,
accumulateDirectDispatches,
} from 'events/EventPropagators';
import SyntheticEvent from 'events/SyntheticEvent';
import invariant from 'fbjs/lib/invariant';
@ -42,9 +45,9 @@ const ReactNativeBridgeEventPlugin = {
nativeEventTarget,
);
if (bubbleDispatchConfig) {
EventPropagators.accumulateTwoPhaseDispatches(event);
accumulateTwoPhaseDispatches(event);
} else if (directDispatchConfig) {
EventPropagators.accumulateDirectDispatches(event);
accumulateDirectDispatches(event);
} else {
return null;
}

View File

@ -10,11 +10,11 @@ import invariant from 'fbjs/lib/invariant';
var instanceCache = {};
var instanceProps = {};
function precacheFiberNode(hostInst, tag) {
export function precacheFiberNode(hostInst, tag) {
instanceCache[tag] = hostInst;
}
function uncacheFiberNode(tag) {
export function uncacheFiberNode(tag) {
delete instanceCache[tag];
delete instanceProps[tag];
}
@ -29,22 +29,16 @@ function getTagFromInstance(inst) {
return tag;
}
function getFiberCurrentPropsFromNode(stateNode) {
export {
getInstanceFromTag as getClosestInstanceFromNode,
getInstanceFromTag as getInstanceFromNode,
getTagFromInstance as getNodeFromInstance,
};
export function getFiberCurrentPropsFromNode(stateNode) {
return instanceProps[stateNode._nativeTag] || null;
}
function updateFiberProps(tag, props) {
export function updateFiberProps(tag, props) {
instanceProps[tag] = props;
}
var ReactNativeComponentTree = {
getClosestInstanceFromNode: getInstanceFromTag,
getInstanceFromNode: getInstanceFromTag,
getNodeFromInstance: getTagFromInstance,
precacheFiberNode,
uncacheFiberNode,
getFiberCurrentPropsFromNode,
updateFiberProps,
};
export default ReactNativeComponentTree;

View File

@ -7,15 +7,18 @@
* @flow
*/
import EventPluginHub from 'events/EventPluginHub';
import EventPluginRegistry from 'events/EventPluginRegistry';
import ReactEventEmitterMixin from 'events/ReactEventEmitterMixin';
import ReactGenericBatching from 'events/ReactGenericBatching';
import {getListener} from 'events/EventPluginHub';
import {registrationNameModules} from 'events/EventPluginRegistry';
import {batchedUpdates} from 'events/ReactGenericBatching';
import {handleTopLevel} from 'events/ReactEventEmitterMixin';
import warning from 'fbjs/lib/warning';
import ReactNativeComponentTree from './ReactNativeComponentTree';
import {getInstanceFromNode} from './ReactNativeComponentTree';
import ReactNativeTagHandles from './ReactNativeTagHandles';
export * from 'events/ReactEventEmitterMixin';
export {getListener, registrationNameModules as registrationNames};
/**
* Version of `ReactBrowserEventEmitter` that works on the receiving side of a
* serialized worker boundary.
@ -74,123 +77,101 @@ var removeTouchesAtIndices = function(
return rippedOut;
};
var ReactNativeEventEmitter = {
...ReactEventEmitterMixin,
/**
* Internal version of `receiveEvent` in terms of normalized (non-tag)
* `rootNodeID`.
*
* @see receiveEvent.
*
* @param {rootNodeID} rootNodeID React root node ID that event occurred on.
* @param {TopLevelType} topLevelType Top level type of event.
* @param {?object} nativeEventParam Object passed from native.
*/
export function _receiveRootNodeIDEvent(
rootNodeID: number,
topLevelType: string,
nativeEventParam: ?Object,
) {
var nativeEvent = nativeEventParam || EMPTY_NATIVE_EVENT;
var inst = getInstanceFromNode(rootNodeID);
batchedUpdates(function() {
handleTopLevel(topLevelType, inst, nativeEvent, nativeEvent.target);
});
// React Native doesn't use ReactControlledComponent but if it did, here's
// where it would do it.
}
registrationNames: EventPluginRegistry.registrationNameModules,
/**
* Publicly exposed method on module for native objc to invoke when a top
* level event is extracted.
* @param {rootNodeID} rootNodeID React root node ID that event occurred on.
* @param {TopLevelType} topLevelType Top level type of event.
* @param {object} nativeEventParam Object passed from native.
*/
export function receiveEvent(
rootNodeID: number,
topLevelType: string,
nativeEventParam: Object,
) {
_receiveRootNodeIDEvent(rootNodeID, topLevelType, nativeEventParam);
}
getListener: EventPluginHub.getListener,
/**
* Simple multi-wrapper around `receiveEvent` that is intended to receive an
* efficient representation of `Touch` objects, and other information that
* can be used to construct W3C compliant `Event` and `Touch` lists.
*
* This may create dispatch behavior that differs than web touch handling. We
* loop through each of the changed touches and receive it as a single event.
* So two `touchStart`/`touchMove`s that occur simultaneously are received as
* two separate touch event dispatches - when they arguably should be one.
*
* This implementation reuses the `Touch` objects themselves as the `Event`s
* since we dispatch an event for each touch (though that might not be spec
* compliant). The main purpose of reusing them is to save allocations.
*
* TODO: Dispatch multiple changed touches in one event. The bubble path
* could be the first common ancestor of all the `changedTouches`.
*
* One difference between this behavior and W3C spec: cancelled touches will
* not appear in `.touches`, or in any future `.touches`, though they may
* still be "actively touching the surface".
*
* Web desktop polyfills only need to construct a fake touch event with
* identifier 0, also abandoning traditional click handlers.
*/
export function receiveTouches(
eventTopLevelType: string,
touches: Array<Object>,
changedIndices: Array<number>,
) {
var changedTouches = eventTopLevelType === 'topTouchEnd' ||
eventTopLevelType === 'topTouchCancel'
? removeTouchesAtIndices(touches, changedIndices)
: touchSubsequence(touches, changedIndices);
/**
* Internal version of `receiveEvent` in terms of normalized (non-tag)
* `rootNodeID`.
*
* @see receiveEvent.
*
* @param {rootNodeID} rootNodeID React root node ID that event occurred on.
* @param {TopLevelType} topLevelType Top level type of event.
* @param {?object} nativeEventParam Object passed from native.
*/
_receiveRootNodeIDEvent: function(
rootNodeID: number,
topLevelType: string,
nativeEventParam: ?Object,
) {
var nativeEvent = nativeEventParam || EMPTY_NATIVE_EVENT;
var inst = ReactNativeComponentTree.getInstanceFromNode(rootNodeID);
ReactGenericBatching.batchedUpdates(function() {
ReactNativeEventEmitter.handleTopLevel(
topLevelType,
inst,
nativeEvent,
nativeEvent.target,
);
});
// React Native doesn't use ReactControlledComponent but if it did, here's
// where it would do it.
},
/**
* Publicly exposed method on module for native objc to invoke when a top
* level event is extracted.
* @param {rootNodeID} rootNodeID React root node ID that event occurred on.
* @param {TopLevelType} topLevelType Top level type of event.
* @param {object} nativeEventParam Object passed from native.
*/
receiveEvent: function(
rootNodeID: number,
topLevelType: string,
nativeEventParam: Object,
) {
ReactNativeEventEmitter._receiveRootNodeIDEvent(
rootNodeID,
topLevelType,
nativeEventParam,
);
},
/**
* Simple multi-wrapper around `receiveEvent` that is intended to receive an
* efficient representation of `Touch` objects, and other information that
* can be used to construct W3C compliant `Event` and `Touch` lists.
*
* This may create dispatch behavior that differs than web touch handling. We
* loop through each of the changed touches and receive it as a single event.
* So two `touchStart`/`touchMove`s that occur simultaneously are received as
* two separate touch event dispatches - when they arguably should be one.
*
* This implementation reuses the `Touch` objects themselves as the `Event`s
* since we dispatch an event for each touch (though that might not be spec
* compliant). The main purpose of reusing them is to save allocations.
*
* TODO: Dispatch multiple changed touches in one event. The bubble path
* could be the first common ancestor of all the `changedTouches`.
*
* One difference between this behavior and W3C spec: cancelled touches will
* not appear in `.touches`, or in any future `.touches`, though they may
* still be "actively touching the surface".
*
* Web desktop polyfills only need to construct a fake touch event with
* identifier 0, also abandoning traditional click handlers.
*/
receiveTouches: function(
eventTopLevelType: string,
touches: Array<Object>,
changedIndices: Array<number>,
) {
var changedTouches = eventTopLevelType === 'topTouchEnd' ||
eventTopLevelType === 'topTouchCancel'
? removeTouchesAtIndices(touches, changedIndices)
: touchSubsequence(touches, changedIndices);
for (var jj = 0; jj < changedTouches.length; jj++) {
var touch = changedTouches[jj];
// Touch objects can fulfill the role of `DOM` `Event` objects if we set
// the `changedTouches`/`touches`. This saves allocations.
touch.changedTouches = changedTouches;
touch.touches = touches;
var nativeEvent = touch;
var rootNodeID = null;
var target = nativeEvent.target;
if (target !== null && target !== undefined) {
if (target < ReactNativeTagHandles.tagsStartAt) {
if (__DEV__) {
warning(
false,
'A view is reporting that a touch occurred on tag zero.',
);
}
} else {
rootNodeID = target;
for (var jj = 0; jj < changedTouches.length; jj++) {
var touch = changedTouches[jj];
// Touch objects can fulfill the role of `DOM` `Event` objects if we set
// the `changedTouches`/`touches`. This saves allocations.
touch.changedTouches = changedTouches;
touch.touches = touches;
var nativeEvent = touch;
var rootNodeID = null;
var target = nativeEvent.target;
if (target !== null && target !== undefined) {
if (target < ReactNativeTagHandles.tagsStartAt) {
if (__DEV__) {
warning(
false,
'A view is reporting that a touch occurred on tag zero.',
);
}
} else {
rootNodeID = target;
}
ReactNativeEventEmitter._receiveRootNodeIDEvent(
rootNodeID,
eventTopLevelType,
nativeEvent,
);
}
},
};
export default ReactNativeEventEmitter;
// $FlowFixMe Shouldn't we *not* call it if rootNodeID is null?
_receiveRootNodeIDEvent(rootNodeID, eventTopLevelType, nativeEvent);
}
}

View File

@ -20,9 +20,8 @@ import invariant from 'fbjs/lib/invariant';
// Module provided by RN:
import UIManager from 'UIManager';
import ReactNativeComponentTree from './ReactNativeComponentTree';
import {getClosestInstanceFromNode} from './ReactNativeComponentTree';
const {getClosestInstanceFromNode} = ReactNativeComponentTree;
let getInspectorDataForViewTag;
if (__DEV__) {

View File

@ -20,16 +20,14 @@ import deepFreezeAndThrowOnMutationInDev
import * as ReactNativeViewConfigRegistry
from './ReactNativeViewConfigRegistry';
import * as ReactNativeAttributePayload from './ReactNativeAttributePayload';
import ReactNativeComponentTree from './ReactNativeComponentTree';
import ReactNativeFiberHostComponent from './ReactNativeFiberHostComponent';
import * as ReactNativeFrameScheduling from './ReactNativeFrameScheduling';
import ReactNativeTagHandles from './ReactNativeTagHandles';
const {
import {
precacheFiberNode,
uncacheFiberNode,
updateFiberProps,
} = ReactNativeComponentTree;
} from './ReactNativeComponentTree';
import ReactNativeFiberHostComponent from './ReactNativeFiberHostComponent';
import * as ReactNativeFrameScheduling from './ReactNativeFrameScheduling';
import ReactNativeTagHandles from './ReactNativeTagHandles';
export type Container = number;
export type Instance = {

View File

@ -16,15 +16,15 @@
// Module provided by RN:
import 'InitializeCore';
import EventPluginHub from 'events/EventPluginHub';
import EventPluginUtils from 'events/EventPluginUtils';
import * as EventPluginHub from 'events/EventPluginHub';
import * as EventPluginUtils from 'events/EventPluginUtils';
import ResponderEventPlugin from 'events/ResponderEventPlugin';
// Module provided by RN:
import RCTEventEmitter from 'RCTEventEmitter';
import ReactNativeBridgeEventPlugin from './ReactNativeBridgeEventPlugin';
import ReactNativeComponentTree from './ReactNativeComponentTree';
import ReactNativeEventEmitter from './ReactNativeEventEmitter';
import * as ReactNativeComponentTree from './ReactNativeComponentTree';
import * as ReactNativeEventEmitter from './ReactNativeEventEmitter';
import ReactNativeEventPluginOrder from './ReactNativeEventPluginOrder';
import ReactNativeGlobalResponderHandler
from './ReactNativeGlobalResponderHandler';

View File

@ -17,7 +17,7 @@ import * as ReactFiberErrorLogger
from 'react-reconciler/src/ReactFiberErrorLogger';
import * as ReactPortal from 'react-reconciler/src/ReactPortal';
import {injectInternals} from 'react-reconciler/src/ReactFiberDevToolsHook';
import ReactGenericBatching from 'events/ReactGenericBatching';
import * as ReactGenericBatching from 'events/ReactGenericBatching';
import TouchHistoryMath from 'events/TouchHistoryMath';
import * as ReactGlobalSharedState from 'shared/ReactGlobalSharedState';
import ReactVersion from 'shared/ReactVersion';
@ -28,7 +28,7 @@ import {showDialog} from './ReactNativeFiberErrorDialog';
import NativeMethodsMixin from './NativeMethodsMixin';
import ReactNativeBridgeEventPlugin from './ReactNativeBridgeEventPlugin';
import ReactNativeComponent from './ReactNativeComponent';
import ReactNativeComponentTree from './ReactNativeComponentTree';
import * as ReactNativeComponentTree from './ReactNativeComponentTree';
import ReactNativeFiberRenderer from './ReactNativeFiberRenderer';
import ReactNativePropRegistry from './ReactNativePropRegistry';
import {getInspectorDataForViewTag} from './ReactNativeFiberInspector';

View File

@ -18,10 +18,10 @@ import {
} from 'react-native-renderer/src/ReactNativeFiberErrorDialog';
import * as ReactPortal from 'react-reconciler/src/ReactPortal';
import {injectInternals} from 'react-reconciler/src/ReactFiberDevToolsHook';
import ReactGenericBatching from 'events/ReactGenericBatching';
import * as ReactGenericBatching from 'events/ReactGenericBatching';
import ReactVersion from 'shared/ReactVersion';
import ReactNativeRTComponentTree from './ReactNativeRTComponentTree';
import {getFiberFromTag} from './ReactNativeRTComponentTree';
import ReactNativeRTFiberRenderer from './ReactNativeRTFiberRenderer';
import ReactNativeRTFiberInspector from './ReactNativeRTFiberInspector';
@ -84,7 +84,7 @@ const ReactNativeRTFiber: ReactNativeRTType = {
};
injectInternals({
findFiberByHostInstance: ReactNativeRTComponentTree.getFiberFromTag,
findFiberByHostInstance: getFiberFromTag,
findHostInstanceByFiber: ReactNativeRTFiberRenderer.findHostInstance,
getInspectorDataForViewTag: ReactNativeRTFiberInspector.getInspectorDataForViewTag,
// This is an enum because we may add more (e.g. profiler build)

View File

@ -12,33 +12,23 @@ import type {Fiber} from 'react-reconciler/src/ReactFiber';
var instanceCache: {[key: number]: Fiber} = {};
var instanceProps: {[key: number]: Object} = {};
function precacheFiberNode(fiber: Fiber, tag: number): void {
export function precacheFiberNode(fiber: Fiber, tag: number): void {
instanceCache[tag] = fiber;
}
function getFiberFromTag(tag: number): null | Fiber {
export function getFiberFromTag(tag: number): null | Fiber {
return instanceCache[tag] || null;
}
function uncacheFiberNode(tag: number): void {
export function uncacheFiberNode(tag: number): void {
delete instanceCache[tag];
delete instanceProps[tag];
}
function getFiberCurrentPropsFromTag(tag: number): null | Object {
export function getFiberCurrentPropsFromTag(tag: number): null | Object {
return instanceProps[tag] || null;
}
function updateFiberProps(tag: number, props: Object): void {
export function updateFiberProps(tag: number, props: Object): void {
instanceProps[tag] = props;
}
var ReactNativeRTComponentTree = {
precacheFiberNode,
uncacheFiberNode,
getFiberFromTag,
getFiberCurrentPropsFromTag,
updateFiberProps,
};
export default ReactNativeRTComponentTree;

View File

@ -7,11 +7,11 @@
* @flow
*/
import ReactGenericBatching from 'events/ReactGenericBatching';
import {batchedUpdates} from 'events/ReactGenericBatching';
// Module provided by RN:
import BatchedBridge from 'BatchedBridge';
import ReactNativeRTComponentTree from './ReactNativeRTComponentTree';
import {getFiberCurrentPropsFromTag} from './ReactNativeRTComponentTree';
var ReactNativeRTEventEmitter = {
/**
@ -27,7 +27,7 @@ var ReactNativeRTEventEmitter = {
nativeEventParam: Object,
) {
var nativeEvent = nativeEventParam;
var props = ReactNativeRTComponentTree.getFiberCurrentPropsFromTag(tag);
var props = getFiberCurrentPropsFromTag(tag);
if (props == null) {
return;
}
@ -35,7 +35,7 @@ var ReactNativeRTEventEmitter = {
if (typeof eventHandler !== 'function') {
return;
}
ReactGenericBatching.batchedUpdates(function() {
batchedUpdates(function() {
eventHandler(nativeEvent);
});
},

View File

@ -16,9 +16,8 @@ import {HostComponent} from 'shared/ReactTypeOfWork';
import emptyObject from 'fbjs/lib/emptyObject';
import invariant from 'fbjs/lib/invariant';
import ReactNativeRTComponentTree from './ReactNativeRTComponentTree';
import {getFiberFromTag} from './ReactNativeRTComponentTree';
const {getFiberFromTag} = ReactNativeRTComponentTree;
let getInspectorDataForViewTag;
if (__DEV__) {

View File

@ -13,7 +13,10 @@ import invariant from 'fbjs/lib/invariant';
// Module provided by RN:
import RTManager from 'RTManager';
import ReactNativeRTComponentTree from './ReactNativeRTComponentTree';
import {
precacheFiberNode,
updateFiberProps,
} from './ReactNativeRTComponentTree';
import ReactNativeRTTagHandles from './ReactNativeRTTagHandles';
export type Container = number;
@ -21,8 +24,6 @@ export type Instance = number;
export type Props = Object;
export type TextInstance = number;
const {precacheFiberNode, updateFiberProps} = ReactNativeRTComponentTree;
function processProps(instance: number, props: Props): Object {
const propsPayload = {};
for (var key in props) {

View File

@ -11,7 +11,7 @@ import type {Fiber} from 'react-reconciler/src/ReactFiber';
import type {FiberRoot} from 'react-reconciler/src/ReactFiberRoot';
import ReactFiberReconciler from 'react-reconciler';
import ReactGenericBatching from 'events/ReactGenericBatching';
import {batchedUpdates} from 'events/ReactGenericBatching';
import {findCurrentFiberUsingSlowPath} from 'shared/ReactFiberTreeReflection';
import emptyObject from 'fbjs/lib/emptyObject';
import {
@ -633,7 +633,7 @@ var ReactTestRendererFiber = {
},
/* eslint-disable camelcase */
unstable_batchedUpdates: ReactGenericBatching.batchedUpdates,
unstable_batchedUpdates: batchedUpdates,
/* eslint-enable camelcase */
};

View File

@ -25,28 +25,28 @@
"gzip": 6870
},
"react-dom.development.js (UMD_DEV)": {
"size": 596493,
"gzip": 134889
"size": 589183,
"gzip": 133823
},
"react-dom.production.min.js (UMD_PROD)": {
"size": 100233,
"gzip": 31848
"size": 96544,
"gzip": 31188
},
"react-dom.development.js (NODE_DEV)": {
"size": 577466,
"gzip": 130187
"size": 570160,
"gzip": 129121
},
"react-dom.production.min.js (NODE_PROD)": {
"size": 98586,
"gzip": 30972
"size": 94731,
"gzip": 30346
},
"ReactDOM-dev.js (FB_DEV)": {
"size": 578317,
"gzip": 130605
"size": 571472,
"gzip": 129612
},
"ReactDOM-prod.js (FB_PROD)": {
"size": 412447,
"gzip": 91219
"size": 405312,
"gzip": 90089
},
"react-dom-test-utils.development.js (NODE_DEV)": {
"size": 37876,
@ -61,60 +61,60 @@
"gzip": 10182
},
"react-dom-unstable-native-dependencies.development.js (UMD_DEV)": {
"size": 86323,
"gzip": 20929
"size": 66641,
"gzip": 16671
},
"react-dom-unstable-native-dependencies.production.min.js (UMD_PROD)": {
"size": 14157,
"gzip": 4583
"size": 11349,
"gzip": 3900
},
"react-dom-unstable-native-dependencies.development.js (NODE_DEV)": {
"size": 81826,
"gzip": 19703
"size": 62184,
"gzip": 15356
},
"react-dom-unstable-native-dependencies.production.min.js (NODE_PROD)": {
"size": 13707,
"gzip": 4458
"size": 10892,
"gzip": 3771
},
"ReactDOMUnstableNativeDependencies-dev.js (FB_DEV)": {
"size": 81123,
"gzip": 19537
"size": 61607,
"gzip": 15197
},
"ReactDOMUnstableNativeDependencies-prod.js (FB_PROD)": {
"size": 65265,
"gzip": 15254
"size": 52139,
"gzip": 12586
},
"react-dom-server.browser.development.js (UMD_DEV)": {
"size": 107196,
"gzip": 27472
"size": 100894,
"gzip": 26193
},
"react-dom-server.browser.production.min.js (UMD_PROD)": {
"size": 15632,
"gzip": 6077
"size": 14713,
"gzip": 5827
},
"react-dom-server.browser.development.js (NODE_DEV)": {
"size": 96125,
"gzip": 24739
"size": 89851,
"gzip": 23452
},
"react-dom-server.browser.production.min.js (NODE_PROD)": {
"size": 15101,
"gzip": 5920
"size": 14188,
"gzip": 5707
},
"ReactDOMServer-dev.js (FB_DEV)": {
"size": 95444,
"gzip": 24574
"size": 89268,
"gzip": 23281
},
"ReactDOMServer-prod.js (FB_PROD)": {
"size": 45835,
"gzip": 12001
"size": 45175,
"gzip": 11989
},
"react-dom-server.node.development.js (NODE_DEV)": {
"size": 98291,
"gzip": 25249
"size": 92017,
"gzip": 23960
},
"react-dom-server.node.production.min.js (NODE_PROD)": {
"size": 15925,
"gzip": 6228
"size": 15013,
"gzip": 6016
},
"react-art.development.js (UMD_DEV)": {
"size": 361363,
@ -141,40 +141,40 @@
"gzip": 43024
},
"ReactNativeRenderer-dev.js (RN_DEV)": {
"size": 268852,
"gzip": 46028
"size": 264248,
"gzip": 45270
},
"ReactNativeRenderer-prod.js (RN_PROD)": {
"size": 206992,
"gzip": 35199
"size": 202770,
"gzip": 34504
},
"ReactRTRenderer-dev.js (RN_DEV)": {
"size": 202141,
"gzip": 33933
"size": 195970,
"gzip": 32882
},
"ReactRTRenderer-prod.js (RN_PROD)": {
"size": 150536,
"gzip": 24872
"size": 143566,
"gzip": 23595
},
"ReactCSRenderer-dev.js (RN_DEV)": {
"size": 189508,
"gzip": 31550
"size": 189548,
"gzip": 31563
},
"ReactCSRenderer-prod.js (RN_PROD)": {
"size": 139346,
"gzip": 22600
"size": 139382,
"gzip": 22608
},
"react-test-renderer.development.js (NODE_DEV)": {
"size": 290743,
"gzip": 60340
"size": 284199,
"gzip": 58944
},
"react-test-renderer.production.min.js (NODE_PROD)": {
"size": 50251,
"gzip": 15366
"size": 47325,
"gzip": 14489
},
"ReactTestRenderer-dev.js (FB_DEV)": {
"size": 288988,
"gzip": 60118
"size": 282462,
"gzip": 58722
},
"react-test-renderer-shallow.development.js (NODE_DEV)": {
"size": 10657,