/** @license React v16.6.1 * react-dom.production.min.js * * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree.
*/
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('resource://devtools/client/shared/vendor/react.js')) : typeof define === 'function' && define.amd ? define(['resource://devtools/client/shared/vendor/react.js'], factory) :
(global.ReactDOM = factory(global.React));
}(this, (function (React) { 'use strict';
/** * Use invariant() to assert state which your program assumes to be true. * * Provide sprintf-style format (only %s is supported) and arguments * to provide information about what broke and what you were * expecting. * * The invariant message will be stripped in production, but the invariant * will remain to ensure logic does not differ in production.
*/
function invariant(condition, format, a, b, c, d, e, f) { if (!condition) { var error = void 0; if (format === undefined) {
error = new Error('Minified exception occurred; use the non-minified dev environment ' + 'for the full error message and additional helpful warnings.');
} else { var args = [a, b, c, d, e, f]; var argIndex = 0;
error = new Error(format.replace(/%s/g, function () { return args[argIndex++];
}));
error.name = 'Invariant Violation';
}
error.framesToPop = 1; // we don't care about invariant's own frame throw error;
}
}
// Relying on the `invariant()` implementation lets us // preserve the format and params in the www builds. /** * WARNING: DO NOT manually require this module. * This is a replacement for `invariant(...)` used by the error code system * and will _only_ be required by the corresponding babel pass. * It always throws.
*/ function reactProdInvariant(code) { var argCount = arguments.length - 1; var url = 'https://reactjs.org/docs/error-decoder.html?invariant=' + code; for (var argIdx = 0; argIdx < argCount; argIdx++) {
url += '&args[]=' + encodeURIComponent(arguments[argIdx + 1]);
} // Rename it so that our build transform doesn't attempt // to replace this invariant() call with reactProdInvariant(). var i = invariant;
i(false, // The error code is intentionally part of the message (and // not the format argument) so that we could deduplicate // different errors in logs based on the code. 'Minified React error #' + code + '; visit %s ' + 'for the full message or use the non-minified dev environment ' + 'for full errors and additional helpful warnings. ', url);
}
!React ? reactProdInvariant('227') : void 0;
var invokeGuardedCallbackImpl = function (name, func, context, a, b, c, d, e, f) { var funcArgs = Array.prototype.slice.call(arguments, 3); try {
func.apply(context, funcArgs);
} catch (error) { this.onError(error);
}
};
// Used by Fiber to simulate a try-catch. var hasError = false; var caughtError = null;
// Used by event system to capture/rethrow the first error. var hasRethrowError = false; var rethrowError = null;
var reporter = {
onError: function (error) {
hasError = true;
caughtError = error;
}
};
/** * Call a function while guarding against errors that happens within it. * Returns an error if it throws, otherwise null. * * In production, this is implemented using a try-catch. The reason we don't * use a try-catch directly is so that we can swap out a different * implementation in DEV mode. * * @param {String} name of the guard to use for logging or debugging * @param {Function} func The function to invoke * @param {*} context The context to use when calling the function * @param {...*} args Arguments for function
*/ function invokeGuardedCallback(name, func, context, a, b, c, d, e, f) {
hasError = false;
caughtError = null;
invokeGuardedCallbackImpl.apply(reporter, arguments);
}
/** * Same as invokeGuardedCallback, but instead of returning an error, it stores * it in a global so it can be rethrown by `rethrowCaughtError` later. * TODO: See if caughtError and rethrowError can be unified. * * @param {String} name of the guard to use for logging or debugging * @param {Function} func The function to invoke * @param {*} context The context to use when calling the function * @param {...*} args Arguments for function
*/ function invokeGuardedCallbackAndCatchFirstError(name, func, context, a, b, c, d, e, f) {
invokeGuardedCallback.apply(this, arguments); if (hasError) { var error = clearCaughtError(); if (!hasRethrowError) {
hasRethrowError = true;
rethrowError = error;
}
}
}
/** * During execution of guarded functions we will capture the first error which * we will rethrow to be handled by the top level error handler.
*/ function rethrowCaughtError() { if (hasRethrowError) { var error = rethrowError;
hasRethrowError = false;
rethrowError = null; throw error;
}
}
function clearCaughtError() { if (hasError) { var error = caughtError;
hasError = false;
caughtError = null; return error;
} else {
reactProdInvariant('198');
}
}
/** * Injectable ordering of event plugins.
*/ var eventPluginOrder = null;
/** * Injectable mapping from names to event plugin modules.
*/ var namesToPlugins = {};
/** * Recomputes the plugin list using the injected plugins and plugin ordering. * * @private
*/ function recomputePluginOrdering() { if (!eventPluginOrder) { // Wait until an `eventPluginOrder` is injected. return;
} for (var pluginName in namesToPlugins) { var pluginModule = namesToPlugins[pluginName]; var pluginIndex = eventPluginOrder.indexOf(pluginName);
!(pluginIndex > -1) ? reactProdInvariant('96', pluginName) : void 0; if (plugins[pluginIndex]) { continue;
}
!pluginModule.extractEvents ? reactProdInvariant('97', pluginName) : void 0;
plugins[pluginIndex] = pluginModule; var publishedEvents = pluginModule.eventTypes; for (var eventName in publishedEvents) {
!publishEventForPlugin(publishedEvents[eventName], pluginModule, eventName) ? reactProdInvariant('98', eventName, pluginName) : void 0;
}
}
}
/** * Publishes an event so that it can be dispatched by the supplied plugin. * * @param {object} dispatchConfig Dispatch configuration for the event. * @param {object} PluginModule Plugin publishing the event. * @return {boolean} True if the event was successfully published. * @private
*/ function publishEventForPlugin(dispatchConfig, pluginModule, eventName) {
!!eventNameDispatchConfigs.hasOwnProperty(eventName) ? reactProdInvariant('99', eventName) : void 0;
eventNameDispatchConfigs[eventName] = dispatchConfig;
var phasedRegistrationNames = dispatchConfig.phasedRegistrationNames; if (phasedRegistrationNames) { for (var phaseName in phasedRegistrationNames) { if (phasedRegistrationNames.hasOwnProperty(phaseName)) { var phasedRegistrationName = phasedRegistrationNames[phaseName];
publishRegistrationName(phasedRegistrationName, pluginModule, eventName);
}
} returntrue;
} elseif (dispatchConfig.registrationName) {
publishRegistrationName(dispatchConfig.registrationName, pluginModule, eventName); returntrue;
} returnfalse;
}
/** * Publishes a registration name that is used to identify dispatched events. * * @param {string} registrationName Registration name to add. * @param {object} PluginModule Plugin publishing the event. * @private
*/ function publishRegistrationName(registrationName, pluginModule, eventName) {
!!registrationNameModules[registrationName] ? reactProdInvariant('100', registrationName) : void 0;
registrationNameModules[registrationName] = pluginModule;
registrationNameDependencies[registrationName] = pluginModule.eventTypes[eventName].dependencies;
}
/** * Registers plugins so that they can extract and dispatch events. * * @see {EventPluginHub}
*/
/** * Ordered list of injected plugins.
*/ var plugins = [];
/** * Mapping from event name to dispatch config
*/ var eventNameDispatchConfigs = {};
/** * Mapping from registration name to plugin module
*/ var registrationNameModules = {};
/** * Mapping from registration name to event name
*/ var registrationNameDependencies = {};
/** * Mapping from lowercase registration names to the properly cased version, * used to warn in the case of missing event handlers. Available * only in false. * @type {Object}
*/
// Trust the developer to only use possibleRegistrationNames in false
/** * 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}
*/ function injectEventPluginOrder(injectedEventPluginOrder) {
!!eventPluginOrder ? reactProdInvariant('101') : void 0; // 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}
*/ function injectEventPluginsByName(injectedNamesToPlugins) { var isOrderingDirty = false; for (var pluginName in injectedNamesToPlugins) { if (!injectedNamesToPlugins.hasOwnProperty(pluginName)) { continue;
} var pluginModule = injectedNamesToPlugins[pluginName]; if (!namesToPlugins.hasOwnProperty(pluginName) || namesToPlugins[pluginName] !== pluginModule) {
!!namesToPlugins[pluginName] ? reactProdInvariant('102', pluginName) : void 0;
namesToPlugins[pluginName] = pluginModule;
isOrderingDirty = true;
}
} if (isOrderingDirty) {
recomputePluginOrdering();
}
}
/** * Similar to invariant but only logs a warning if the condition is not met. * This can be used to log issues in development environments in critical * paths. Removing the logging code for production environments will keep the * same logic and follow the same code paths.
*/
var getFiberCurrentPropsFromNode = null; var getInstanceFromNode = null; var getNodeFromInstance = null;
/** * Dispatch the event to the listener. * @param {SyntheticEvent} event SyntheticEvent to handle * @param {function} listener Application-level callback * @param {*} inst Internal component instance
*/ function executeDispatch(event, listener, inst) { var type = event.type || 'unknown-event';
event.currentTarget = getNodeFromInstance(inst);
invokeGuardedCallbackAndCatchFirstError(type, listener, undefined, event);
event.currentTarget = null;
}
/** * Standard/simple iteration through an event's collected dispatches.
*/ function executeDispatchesInOrder(event) { var dispatchListeners = event._dispatchListeners; var dispatchInstances = event._dispatchInstances; if (Array.isArray(dispatchListeners)) { for (var i = 0; i < dispatchListeners.length; i++) { if (event.isPropagationStopped()) { break;
} // Listeners and Instances are two parallel arrays that are always in sync.
executeDispatch(event, dispatchListeners[i], dispatchInstances[i]);
}
} elseif (dispatchListeners) {
executeDispatch(event, dispatchListeners, dispatchInstances);
}
event._dispatchListeners = null;
event._dispatchInstances = null;
}
/** * Execution of a "direct" dispatch - there must be at most one dispatch * accumulated on the event or it is considered an error. It doesn't really make * sense for an event with multiple dispatches (bubbled) to keep track of the * return values at each dispatch execution, but it does tend to make sense when * dealing with "direct" dispatches. * * @return {*} The return value of executing the single dispatch.
*/
/** * @param {SyntheticEvent} event * @return {boolean} True iff number of dispatches accumulated is greater than 0.
*/
/** * Accumulates items that must not be null or undefined into the first one. This * is used to conserve memory by avoiding array allocations, and thus sacrifices * API cleanness. Since `current` can be null before being passed in and not * null after this function, make sure to assign it back to `current`: * * `a = accumulateInto(a, b);` * * This API should be sparingly used. Try `accumulate` for something cleaner. * * @return {*|array<*>} An accumulation of items.
*/
// Both are not empty. Warning: Never call x.concat(y) when you are not // certain that x is an Array (x could be a string with concat method). if (Array.isArray(current)) { if (Array.isArray(next)) {
current.push.apply(current, next); return current;
}
current.push(next); return current;
}
if (Array.isArray(next)) { // A bit too dangerous to mutate `next`. return [current].concat(next);
}
return [current, next];
}
/** * @param {array} arr an "accumulation" of items which is either an Array or * a single item. Useful when paired with the `accumulate` module. This is a * simple utility that allows us to reason about a collection of items, but * handling the case when there is exactly one item (and we do not need to * allocate an array). * @param {function} cb Callback invoked with each element or a collection. * @param {?} [scope] Scope used as `this` in a callback.
*/ function forEachAccumulated(arr, cb, scope) { if (Array.isArray(arr)) {
arr.forEach(cb, scope);
} elseif (arr) {
cb.call(scope, arr);
}
}
/** * Internal queue of events that have accumulated their dispatches and are * waiting to have their dispatches executed.
*/ var eventQueue = null;
/** * Dispatches an event and releases it back into the pool, unless persistent. * * @param {?object} event Synthetic event to be dispatched. * @private
*/ var executeDispatchesAndRelease = function (event) { if (event) {
executeDispatchesInOrder(event);
if (!event.isPersistent()) {
event.constructor.release(event);
}
}
}; var executeDispatchesAndReleaseTopLevel = function (e) { return executeDispatchesAndRelease(e);
};
function isInteractive(tag) { return tag === 'button' || tag === 'input' || tag === 'select' || tag === 'textarea';
}
/** * This is a unified interface for event plugins to be installed and configured. * * Event plugins can implement the following properties: * * `extractEvents` {function(string, DOMEventTarget, string, object): *} * Required. When a top-level event is fired, this method is expected to * extract synthetic events that will in turn be queued and dispatched. * * `eventTypes` {object} * Optional, plugins that fire events must publish a mapping of registration * names that are used to register listeners. Values of this mapping must * be objects that contain `registrationName` or `phasedRegistrationNames`. * * `executeDispatch` {function(object, function, string)} * Optional, allows plugins to override how an event gets dispatched. By * default, the listener is simply invoked. * * Each plugin that is injected into `EventsPluginHub` is immediately operable. * * @public
*/
/** * @param {object} injectedNamesToPlugins Map from names to plugin modules.
*/
injectEventPluginsByName: injectEventPluginsByName
};
/** * @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.
*/ function getListener(inst, registrationName) { var listener = void 0;
// TODO: shouldPreventMouseEvent is DOM-specific and definitely should not // live here; needs to be moved to a better place soon var stateNode = inst.stateNode; if (!stateNode) { // Work in progress (ex: onload events in incremental mode). returnnull;
} var props = getFiberCurrentPropsFromNode(stateNode); if (!props) { // Work in progress. returnnull;
}
listener = props[registrationName]; if (shouldPreventMouseEvent(registrationName, inst.type, props)) { returnnull;
}
!(!listener || typeof listener === 'function') ? reactProdInvariant('231', registrationName, typeof listener) : void 0; return listener;
}
/** * Allows registered plugins an opportunity to extract events from top-level * native browser events. * * @return {*} An accumulation of synthetic events. * @internal
*/ function extractEvents(topLevelType, targetInst, nativeEvent, nativeEventTarget) { var events = null; 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;
}
function runEventsInBatch(events) { if (events !== null) {
eventQueue = accumulateInto(eventQueue, events);
}
// Set `eventQueue` to null before processing it so that we can tell if more // events get enqueued while processing. var processingEventQueue = eventQueue;
eventQueue = null;
if (!processingEventQueue) { return;
}
forEachAccumulated(processingEventQueue, executeDispatchesAndReleaseTopLevel);
!!eventQueue ? reactProdInvariant('95') : void 0; // This would be a good time to rethrow if any of the event handlers threw.
rethrowCaughtError();
}
function runExtractedEventsInBatch(topLevelType, targetInst, nativeEvent, nativeEventTarget) { var events = extractEvents(topLevelType, targetInst, nativeEvent, nativeEventTarget);
runEventsInBatch(events);
}
var FunctionComponent = 0; var ClassComponent = 1; var IndeterminateComponent = 2; // Before we know whether it is function or class var HostRoot = 3; // Root of a host tree. Could be nested inside another node. var HostPortal = 4; // A subtree. Could be an entry point to a different renderer. var HostComponent = 5; var HostText = 6; var Fragment = 7; var Mode = 8; var ContextConsumer = 9; var ContextProvider = 10; var ForwardRef = 11; var Profiler = 12; var SuspenseComponent = 13; var MemoComponent = 14; var SimpleMemoComponent = 15; var LazyComponent = 16; var IncompleteClassComponent = 17; var DehydratedSuspenseComponent = 18;
var randomKey = Math.random().toString(36).slice(2); var internalInstanceKey = '__reactInternalInstance$' + randomKey; var internalEventHandlersKey = '__reactEventHandlers$' + randomKey;
function precacheFiberNode(hostInst, node) {
node[internalInstanceKey] = hostInst;
}
/** * Given a DOM node, return the closest ReactDOMComponent or * ReactDOMTextComponent instance ancestor.
*/ function getClosestInstanceFromNode(node) { if (node[internalInstanceKey]) { return node[internalInstanceKey];
}
while (!node[internalInstanceKey]) { if (node.parentNode) {
node = node.parentNode;
} else { // Top of the tree. This node must not be part of a React tree (or is // unmounted, potentially). returnnull;
}
}
var inst = node[internalInstanceKey]; if (inst.tag === HostComponent || inst.tag === HostText) { // In Fiber, this will always be the deepest root. return inst;
}
returnnull;
}
/** * Given a DOM node, return the ReactDOMComponent or ReactDOMTextComponent * instance, or null if the node was not rendered by this React.
*/ function getInstanceFromNode$1(node) { var inst = node[internalInstanceKey]; if (inst) { if (inst.tag === HostComponent || inst.tag === HostText) { return inst;
} else { returnnull;
}
} returnnull;
}
/** * Given a ReactDOMComponent or ReactDOMTextComponent, return the corresponding * DOM node.
*/ function getNodeFromInstance$1(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. return inst.stateNode;
}
// Without this first invariant, passing a non-DOM-component triggers the next // invariant for a missing parent, which is super confusing.
reactProdInvariant('33');
}
function getFiberCurrentPropsFromNode$1(node) { return node[internalEventHandlersKey] || null;
}
function updateFiberProps(node, props) {
node[internalEventHandlersKey] = props;
}
function getParent(inst) { do {
inst = inst.return; // TODO: If this is a HostRoot we might want to bail out. // That is depending on if we want nested subtrees (layers) to bubble // events to their parent. We could also go through parentNode on the // host node but that wouldn't work for React Native and doesn't let us // do the portal feature.
} while (inst && inst.tag !== HostComponent); if (inst) { return inst;
} returnnull;
}
/** * Return the lowest common ancestor of A and B, or null if they are in * different trees.
*/ function getLowestCommonAncestor(instA, instB) { var depthA = 0; for (var tempA = instA; tempA; tempA = getParent(tempA)) {
depthA++;
} var depthB = 0; for (var tempB = instB; tempB; tempB = getParent(tempB)) {
depthB++;
}
// If A is deeper, crawl up. while (depthA - depthB > 0) {
instA = getParent(instA);
depthA--;
}
// If B is deeper, crawl up. while (depthB - depthA > 0) {
instB = getParent(instB);
depthB--;
}
// Walk in lockstep until we find a match. var depth = depthA; while (depth--) { if (instA === instB || instA === instB.alternate) { return instA;
}
instA = getParent(instA);
instB = getParent(instB);
} returnnull;
}
/** * Return if A is an ancestor of B.
*/
/** * Return the parent instance of the passed-in instance.
*/
/** * Simulates the traversal of a two-phase, capture/bubble event dispatch.
*/ function traverseTwoPhase(inst, fn, arg) { var path = []; while (inst) {
path.push(inst);
inst = getParent(inst);
} var i = void 0; for (i = path.length; i-- > 0;) {
fn(path[i], 'captured', arg);
} for (i = 0; i < path.length; i++) {
fn(path[i], 'bubbled', arg);
}
}
/** * Traverses the ID hierarchy and invokes the supplied `cb` on any IDs that * should would receive a `mouseEnter` or `mouseLeave` event. * * Does not invoke the callback on the nearest common ancestor because nothing * "entered" or "left" that element.
*/ function traverseEnterLeave(from, to, fn, argFrom, argTo) { var common = from && to ? getLowestCommonAncestor(from, to) : null; var pathFrom = []; while (true) { if (!from) { break;
} if (from === common) { break;
} var alternate = from.alternate; if (alternate !== null && alternate === common) { break;
}
pathFrom.push(from);
from = getParent(from);
} var pathTo = []; while (true) { if (!to) { break;
} if (to === common) { break;
} var _alternate = to.alternate; if (_alternate !== null && _alternate === common) { break;
}
pathTo.push(to);
to = getParent(to);
} for (var i = 0; i < pathFrom.length; i++) {
fn(pathFrom[i], 'bubbled', argFrom);
} for (var _i = pathTo.length; _i-- > 0;) {
fn(pathTo[_i], 'captured', argTo);
}
}
/** * Some event types have a notion of different registration names for different * "phases" of propagation. This finds listeners by a given phase.
*/ function listenerAtPhase(inst, event, propagationPhase) { var registrationName = event.dispatchConfig.phasedRegistrationNames[propagationPhase]; 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. * Mutating the event's members allows us to not have to create a wrapping * "dispatch" object that pairs the event with the listener.
*/ function accumulateDirectionalDispatches(inst, phase, event) { var listener = listenerAtPhase(inst, event, phase); if (listener) {
event._dispatchListeners = accumulateInto(event._dispatchListeners, listener);
event._dispatchInstances = accumulateInto(event._dispatchInstances, inst);
}
}
/** * Collect dispatches (must be entirely collected before dispatching - see unit * tests). Lazily allocate the array to conserve memory. We must loop through * each event and perform the traversal for each one. We cannot perform a * single traversal for the entire collection of events because each event may * have a different target.
*/ function accumulateTwoPhaseDispatchesSingle(event) { if (event && event.dispatchConfig.phasedRegistrationNames) {
traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event);
}
}
/** * Accumulates without regard to direction, does not look for phased * registration names. Same as `accumulateDirectDispatchesSingle` but without * requiring that the `dispatchMarker` be the same as the dispatched ID.
*/ function accumulateDispatches(inst, ignoredDirection, event) { if (inst && event && event.dispatchConfig.registrationName) { var registrationName = event.dispatchConfig.registrationName; var listener = getListener(inst, registrationName); if (listener) {
event._dispatchListeners = accumulateInto(event._dispatchListeners, listener);
event._dispatchInstances = accumulateInto(event._dispatchInstances, inst);
}
}
}
/** * Accumulates dispatches on an `SyntheticEvent`, but only for the * `dispatchMarker`. * @param {SyntheticEvent} event
*/ function accumulateDirectDispatchesSingle(event) { if (event && event.dispatchConfig.registrationName) {
accumulateDispatches(event._targetInst, null, event);
}
}
function accumulateTwoPhaseDispatches(events) {
forEachAccumulated(events, accumulateTwoPhaseDispatchesSingle);
}
function accumulateEnterLeaveDispatches(leave, enter, from, to) {
traverseEnterLeave(from, to, accumulateDispatches, leave, enter);
}
function accumulateDirectDispatches(events) {
forEachAccumulated(events, accumulateDirectDispatchesSingle);
}
// Do not uses the below two methods directly! // Instead use constants exported from DOMTopLevelEventTypes in ReactDOM. // (It is the only module that is allowed to access these methods.)
function unsafeCastStringToDOMTopLevelType(topLevelType) { return topLevelType;
}
function unsafeCastDOMTopLevelTypeToString(topLevelType) { return topLevelType;
}
/** * Generate a mapping of standard vendor prefixes using the defined style property and event name. * * @param {string} styleProp * @param {string} eventName * @returns {object}
*/ function makePrefixMap(styleProp, eventName) { var prefixes = {};
/** * A list of event names to a configurable list of vendor prefixes.
*/ var vendorPrefixes = {
animationend: makePrefixMap('Animation', 'AnimationEnd'),
animationiteration: makePrefixMap('Animation', 'AnimationIteration'),
animationstart: makePrefixMap('Animation', 'AnimationStart'),
transitionend: makePrefixMap('Transition', 'TransitionEnd')
};
/** * Event names that have already been detected and prefixed (if applicable).
*/ var prefixedEventNames = {};
/** * Element to check for prefixes on.
*/ var style = {};
/** * Bootstrap if a DOM exists.
*/ if (canUseDOM) {
style = document.createElementNS('http://www.w3.org/1999/xhtml', 'div').style;
// On some platforms, in particular some releases of Android 4.x, // the un-prefixed "animation" and "transition" properties are defined on the // style object but the events that fire will still be prefixed, so we need // to check if the un-prefixed events are usable, and if not remove them from the map. if (!('AnimationEvent' in window)) { delete vendorPrefixes.animationend.animation; delete vendorPrefixes.animationiteration.animation; delete vendorPrefixes.animationstart.animation;
}
// Same as above if (!('TransitionEvent' in window)) { delete vendorPrefixes.transitionend.transition;
}
}
/** * Attempts to determine the correct vendor prefixed event name. * * @param {string} eventName * @returns {string}
*/ function getVendorPrefixedEventName(eventName) { if (prefixedEventNames[eventName]) { return prefixedEventNames[eventName];
} elseif (!vendorPrefixes[eventName]) { return eventName;
}
var prefixMap = vendorPrefixes[eventName];
for (var styleProp in prefixMap) { if (prefixMap.hasOwnProperty(styleProp) && styleProp in style) { return prefixedEventNames[eventName] = prefixMap[styleProp];
}
}
return eventName;
}
/** * To identify top level events in ReactDOM, we use constants defined by this * module. This is the only module that uses the unsafe* methods to express * that the constants actually correspond to the browser event names. This lets * us save some bundle size by avoiding a top level type -> event name map. * The rest of ReactDOM code should import top level types from this file.
*/ var TOP_ABORT = unsafeCastStringToDOMTopLevelType('abort'); var TOP_ANIMATION_END = unsafeCastStringToDOMTopLevelType(getVendorPrefixedEventName('animationend')); var TOP_ANIMATION_ITERATION = unsafeCastStringToDOMTopLevelType(getVendorPrefixedEventName('animationiteration')); var TOP_ANIMATION_START = unsafeCastStringToDOMTopLevelType(getVendorPrefixedEventName('animationstart')); var TOP_BLUR = unsafeCastStringToDOMTopLevelType('blur'); var TOP_CAN_PLAY = unsafeCastStringToDOMTopLevelType('canplay'); var TOP_CAN_PLAY_THROUGH = unsafeCastStringToDOMTopLevelType('canplaythrough'); var TOP_CANCEL = unsafeCastStringToDOMTopLevelType('cancel'); var TOP_CHANGE = unsafeCastStringToDOMTopLevelType('change'); var TOP_CLICK = unsafeCastStringToDOMTopLevelType('click'); var TOP_CLOSE = unsafeCastStringToDOMTopLevelType('close'); var TOP_COMPOSITION_END = unsafeCastStringToDOMTopLevelType('compositionend'); var TOP_COMPOSITION_START = unsafeCastStringToDOMTopLevelType('compositionstart'); var TOP_COMPOSITION_UPDATE = unsafeCastStringToDOMTopLevelType('compositionupdate'); var TOP_CONTEXT_MENU = unsafeCastStringToDOMTopLevelType('contextmenu'); var TOP_COPY = unsafeCastStringToDOMTopLevelType('copy'); var TOP_CUT = unsafeCastStringToDOMTopLevelType('cut'); var TOP_DOUBLE_CLICK = unsafeCastStringToDOMTopLevelType('dblclick'); var TOP_AUX_CLICK = unsafeCastStringToDOMTopLevelType('auxclick'); var TOP_DRAG = unsafeCastStringToDOMTopLevelType('drag'); var TOP_DRAG_END = unsafeCastStringToDOMTopLevelType('dragend'); var TOP_DRAG_ENTER = unsafeCastStringToDOMTopLevelType('dragenter'); var TOP_DRAG_EXIT = unsafeCastStringToDOMTopLevelType('dragexit'); var TOP_DRAG_LEAVE = unsafeCastStringToDOMTopLevelType('dragleave'); var TOP_DRAG_OVER = unsafeCastStringToDOMTopLevelType('dragover'); var TOP_DRAG_START = unsafeCastStringToDOMTopLevelType('dragstart'); var TOP_DROP = unsafeCastStringToDOMTopLevelType('drop'); var TOP_DURATION_CHANGE = unsafeCastStringToDOMTopLevelType('durationchange'); var TOP_EMPTIED = unsafeCastStringToDOMTopLevelType('emptied'); var TOP_ENCRYPTED = unsafeCastStringToDOMTopLevelType('encrypted'); var TOP_ENDED = unsafeCastStringToDOMTopLevelType('ended'); var TOP_ERROR = unsafeCastStringToDOMTopLevelType('error'); var TOP_FOCUS = unsafeCastStringToDOMTopLevelType('focus'); var TOP_GOT_POINTER_CAPTURE = unsafeCastStringToDOMTopLevelType('gotpointercapture'); var TOP_INPUT = unsafeCastStringToDOMTopLevelType('input'); var TOP_INVALID = unsafeCastStringToDOMTopLevelType('invalid'); var TOP_KEY_DOWN = unsafeCastStringToDOMTopLevelType('keydown'); var TOP_KEY_PRESS = unsafeCastStringToDOMTopLevelType('keypress'); var TOP_KEY_UP = unsafeCastStringToDOMTopLevelType('keyup'); var TOP_LOAD = unsafeCastStringToDOMTopLevelType('load'); var TOP_LOAD_START = unsafeCastStringToDOMTopLevelType('loadstart'); var TOP_LOADED_DATA = unsafeCastStringToDOMTopLevelType('loadeddata'); var TOP_LOADED_METADATA = unsafeCastStringToDOMTopLevelType('loadedmetadata'); var TOP_LOST_POINTER_CAPTURE = unsafeCastStringToDOMTopLevelType('lostpointercapture'); var TOP_MOUSE_DOWN = unsafeCastStringToDOMTopLevelType('mousedown'); var TOP_MOUSE_MOVE = unsafeCastStringToDOMTopLevelType('mousemove'); var TOP_MOUSE_OUT = unsafeCastStringToDOMTopLevelType('mouseout'); var TOP_MOUSE_OVER = unsafeCastStringToDOMTopLevelType('mouseover'); var TOP_MOUSE_UP = unsafeCastStringToDOMTopLevelType('mouseup'); var TOP_PASTE = unsafeCastStringToDOMTopLevelType('paste'); var TOP_PAUSE = unsafeCastStringToDOMTopLevelType('pause'); var TOP_PLAY = unsafeCastStringToDOMTopLevelType('play'); var TOP_PLAYING = unsafeCastStringToDOMTopLevelType('playing'); var TOP_POINTER_CANCEL = unsafeCastStringToDOMTopLevelType('pointercancel'); var TOP_POINTER_DOWN = unsafeCastStringToDOMTopLevelType('pointerdown');
var TOP_POINTER_MOVE = unsafeCastStringToDOMTopLevelType('pointermove'); var TOP_POINTER_OUT = unsafeCastStringToDOMTopLevelType('pointerout'); var TOP_POINTER_OVER = unsafeCastStringToDOMTopLevelType('pointerover'); var TOP_POINTER_UP = unsafeCastStringToDOMTopLevelType('pointerup'); var TOP_PROGRESS = unsafeCastStringToDOMTopLevelType('progress'); var TOP_RATE_CHANGE = unsafeCastStringToDOMTopLevelType('ratechange'); var TOP_RESET = unsafeCastStringToDOMTopLevelType('reset'); var TOP_SCROLL = unsafeCastStringToDOMTopLevelType('scroll'); var TOP_SEEKED = unsafeCastStringToDOMTopLevelType('seeked'); var TOP_SEEKING = unsafeCastStringToDOMTopLevelType('seeking'); var TOP_SELECTION_CHANGE = unsafeCastStringToDOMTopLevelType('selectionchange'); var TOP_STALLED = unsafeCastStringToDOMTopLevelType('stalled'); var TOP_SUBMIT = unsafeCastStringToDOMTopLevelType('submit'); var TOP_SUSPEND = unsafeCastStringToDOMTopLevelType('suspend'); var TOP_TEXT_INPUT = unsafeCastStringToDOMTopLevelType('textInput'); var TOP_TIME_UPDATE = unsafeCastStringToDOMTopLevelType('timeupdate'); var TOP_TOGGLE = unsafeCastStringToDOMTopLevelType('toggle'); var TOP_TOUCH_CANCEL = unsafeCastStringToDOMTopLevelType('touchcancel'); var TOP_TOUCH_END = unsafeCastStringToDOMTopLevelType('touchend'); var TOP_TOUCH_MOVE = unsafeCastStringToDOMTopLevelType('touchmove'); var TOP_TOUCH_START = unsafeCastStringToDOMTopLevelType('touchstart'); var TOP_TRANSITION_END = unsafeCastStringToDOMTopLevelType(getVendorPrefixedEventName('transitionend')); var TOP_VOLUME_CHANGE = unsafeCastStringToDOMTopLevelType('volumechange'); var TOP_WAITING = unsafeCastStringToDOMTopLevelType('waiting'); var TOP_WHEEL = unsafeCastStringToDOMTopLevelType('wheel');
// List of events that need to be individually attached to media elements. // Note that events in this list will *not* be listened to at the top level // unless they're explicitly whitelisted in `ReactBrowserEventEmitter.listenTo`. var mediaEventTypes = [TOP_ABORT, TOP_CAN_PLAY, TOP_CAN_PLAY_THROUGH, TOP_DURATION_CHANGE, TOP_EMPTIED, TOP_ENCRYPTED, TOP_ENDED, TOP_ERROR, TOP_LOADED_DATA, TOP_LOADED_METADATA, TOP_LOAD_START, TOP_PAUSE, TOP_PLAY, TOP_PLAYING, TOP_PROGRESS, TOP_RATE_CHANGE, TOP_SEEKED, TOP_SEEKING, TOP_STALLED, TOP_SUSPEND, TOP_TIME_UPDATE, TOP_VOLUME_CHANGE, TOP_WAITING];
function getRawEventName(topLevelType) { return unsafeCastDOMTopLevelTypeToString(topLevelType);
}
/** * These variables store information about text content of a target node, * allowing comparison of content before and after a given event. * * Identify the node where selection currently begins, then observe * both its text content and its current position in the DOM. Since the * browser may natively replace the target node during composition, we can * use its position to find its replacement. * *
*/
var root = null; var startText = null; var fallbackText = null;
function getData() { if (fallbackText) { return fallbackText;
}
var start = void 0; var startValue = startText; var startLength = startValue.length; var end = void 0; 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;
fallbackText = endValue.slice(start, sliceTail); return fallbackText;
}
function getText() { if ('value' in root) { return root.value;
} return root.textContent;
}
var ReactInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
var _assign = ReactInternals.assign;
/* eslint valid-typeof: 0 */
var EVENT_POOL_SIZE = 10;
/** * @interface Event * @see http://www.w3.org/TR/DOM-Level-3-Events/
*/ var EventInterface = {
type: null,
target: null, // currentTarget is set when dispatching; no use in copying it here
currentTarget: function () { returnnull;
},
eventPhase: null,
bubbles: null,
cancelable: null,
timeStamp: function (event) { return event.timeStamp || Date.now();
},
defaultPrevented: null,
isTrusted: null
};
function functionThatReturnsTrue() { returntrue;
}
function functionThatReturnsFalse() { returnfalse;
}
/** * Synthetic events are dispatched by event plugins, typically in response to a * top-level event delegation handler. * * These systems should generally use pooling to reduce the frequency of garbage * collection. The system should check `isPersistent` to determine whether the * event should be released into the pool after being dispatched. Users that * need a persisted event should invoke `persist`. * * Synthetic events (and subclasses) implement the DOM Level 3 Events API by * normalizing browser quirks. Subclasses do not necessarily have to implement a * DOM interface; custom application-specific events can also subclass this. * * @param {object} dispatchConfig Configuration used to dispatch this event. * @param {*} targetInst Marker identifying the event target. * @param {object} nativeEvent Native browser event. * @param {DOMEventTarget} nativeEventTarget Target node.
*/ function SyntheticEvent(dispatchConfig, targetInst, nativeEvent, nativeEventTarget) { this.dispatchConfig = dispatchConfig; this._targetInst = targetInst; this.nativeEvent = nativeEvent;
varInterface = this.constructor.Interface; for (var propName in Interface) { if (!Interface.hasOwnProperty(propName)) { continue;
} var normalize = Interface[propName]; if (normalize) { this[propName] = normalize(nativeEvent);
} else { if (propName === 'target') { this.target = nativeEventTarget;
} else { this[propName] = nativeEvent[propName];
}
}
}
stopPropagation: function () { var event = this.nativeEvent; if (!event) { return;
}
if (event.stopPropagation) {
event.stopPropagation();
} elseif (typeof event.cancelBubble !== 'unknown') { // The ChangeEventPlugin registers a "propertychange" event for // IE. This event does not support bubbling or cancelling, and // any references to cancelBubble throw "Member not found". A // typeof check of "unknown" circumvents this issue (and is also // IE specific).
event.cancelBubble = true;
}
/** * We release all dispatched `SyntheticEvent`s after each event loop, adding * them back into the pool. This allows a way to hold onto a reference that * won't be added back into the pool.
*/
persist: function () { this.isPersistent = functionThatReturnsTrue;
},
/** * Checks if this event should be released back into the pool. * * @return {boolean} True if this should not be released, false otherwise.
*/
isPersistent: functionThatReturnsFalse,
/** * `PooledClass` looks for `destructor` on each instance it releases.
*/
destructor: function () { varInterface = this.constructor.Interface; for (var propName in Interface) {
{ this[propName] = null;
}
} this.dispatchConfig = null; this._targetInst = null; this.nativeEvent = null; this.isDefaultPrevented = functionThatReturnsFalse; this.isPropagationStopped = functionThatReturnsFalse; this._dispatchListeners = null; this._dispatchInstances = null;
}
});
SyntheticEvent.Interface = EventInterface;
/** * Helper to reduce boilerplate when creating subclasses.
*/
SyntheticEvent.extend = function (Interface) { varSuper = this;
var E = function () {};
E.prototype = Super.prototype; var prototype = new E();
var END_KEYCODES = [9, 13, 27, 32]; // Tab, Return, Esc, Space var START_KEYCODE = 229;
var canUseCompositionEvent = canUseDOM && 'CompositionEvent' in window;
var documentMode = null; if (canUseDOM && 'documentMode' in document) {
documentMode = document.documentMode;
}
// Webkit offers a very useful `textInput` event that can be used to // directly represent `beforeInput`. The IE `textinput` event is not as // useful, so we don't use it. var canUseTextInputEvent = canUseDOM && 'TextEvent' in window && !documentMode;
// In IE9+, we have access to composition events, but the data supplied // by the native compositionend event may be incorrect. Japanese ideographic // spaces, for instance (\u3000) are not recorded correctly. var useFallbackCompositionData = canUseDOM && (!canUseCompositionEvent || documentMode && documentMode > 8 && documentMode <= 11);
var SPACEBAR_CODE = 32; var SPACEBAR_CHAR = String.fromCharCode(SPACEBAR_CODE);
// Track whether we've ever handled a keypress on the space key. var hasSpaceKeypress = false;
/** * Return whether a native keypress event is assumed to be a command. * This is required because Firefox fires `keypress` events for key commands * (cut, copy, select-all, etc.) even though no character is inserted.
*/ function isKeypressCommand(nativeEvent) { return (nativeEvent.ctrlKey || nativeEvent.altKey || nativeEvent.metaKey) && // ctrlKey && altKey is equivalent to AltGr, and is not a command.
!(nativeEvent.ctrlKey && nativeEvent.altKey);
}
/** * Translate native top level events into event types. * * @param {string} topLevelType * @return {object}
*/ function getCompositionEventType(topLevelType) { switch (topLevelType) { case TOP_COMPOSITION_START: return eventTypes.compositionStart; case TOP_COMPOSITION_END: return eventTypes.compositionEnd; case TOP_COMPOSITION_UPDATE: return eventTypes.compositionUpdate;
}
}
/** * Does our fallback best-guess model think this event signifies that * composition has begun? * * @param {string} topLevelType * @param {object} nativeEvent * @return {boolean}
*/ function isFallbackCompositionStart(topLevelType, nativeEvent) { return topLevelType === TOP_KEY_DOWN && nativeEvent.keyCode === START_KEYCODE;
}
/** * Does our fallback mode think that this event is the end of composition? * * @param {string} topLevelType * @param {object} nativeEvent * @return {boolean}
*/ function isFallbackCompositionEnd(topLevelType, nativeEvent) { switch (topLevelType) { case TOP_KEY_UP: // Command keys insert or clear IME input. return END_KEYCODES.indexOf(nativeEvent.keyCode) !== -1; case TOP_KEY_DOWN: // Expect IME keyCode on each keydown. If we get any other // code we must have exited earlier. return nativeEvent.keyCode !== START_KEYCODE; case TOP_KEY_PRESS: case TOP_MOUSE_DOWN: case TOP_BLUR: // Events are not possible without cancelling IME. returntrue; default: returnfalse;
}
}
/** * Google Input Tools provides composition data via a CustomEvent, * with the `data` property populated in the `detail` object. If this * is available on the event object, use it. If not, this is a plain * composition event and we have nothing special to extract. * * @param {object} nativeEvent * @return {?string}
*/ function getDataFromCustomEvent(nativeEvent) { var detail = nativeEvent.detail; if (typeof detail === 'object' && 'data' in detail) { return detail.data;
} returnnull;
}
/** * Check if a composition event was triggered by Korean IME. * Our fallback mode does not work well with IE's Korean IME, * so just use native composition events when Korean IME is used. * Although CompositionEvent.locale property is deprecated, * it is available in IE, where our fallback mode is enabled. * * @param {object} nativeEvent * @return {boolean}
*/ function isUsingKoreanIME(nativeEvent) { return nativeEvent.locale === 'ko';
}
// Track the current IME composition status, if any. var isComposing = false;
/** * @return {?object} A SyntheticCompositionEvent.
*/ function extractCompositionEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget) { var eventType = void 0; var fallbackData = void 0;
if (useFallbackCompositionData && !isUsingKoreanIME(nativeEvent)) { // The current composition is stored statically and must not be // overwritten while composition continues. if (!isComposing && eventType === eventTypes.compositionStart) {
isComposing = initialize(nativeEventTarget);
} elseif (eventType === eventTypes.compositionEnd) { if (isComposing) {
fallbackData = getData();
}
}
}
var event = SyntheticCompositionEvent.getPooled(eventType, targetInst, nativeEvent, nativeEventTarget);
if (fallbackData) { // Inject data generated from fallback path into the synthetic event. // This matches the property of native CompositionEventInterface.
event.data = fallbackData;
} else { var customData = getDataFromCustomEvent(nativeEvent); if (customData !== null) {
event.data = customData;
}
}
/** * @param {TopLevelType} topLevelType Number from `TopLevelType`. * @param {object} nativeEvent Native browser event. * @return {?string} The string corresponding to this `beforeInput` event.
*/ function getNativeBeforeInputChars(topLevelType, nativeEvent) { switch (topLevelType) { case TOP_COMPOSITION_END: return getDataFromCustomEvent(nativeEvent); case TOP_KEY_PRESS: /** * If native `textInput` events are available, our goal is to make * use of them. However, there is a special case: the spacebar key. * In Webkit, preventing default on a spacebar `textInput` event * cancels character insertion, but it *also* causes the browser * to fall back to its default spacebar behavior of scrolling the * page. * * Tracking at: * https://code.google.com/p/chromium/issues/detail?id=355103 * * To avoid this issue, use the keypress event as if no `textInput` * event is available.
*/ var which = nativeEvent.which; if (which !== SPACEBAR_CODE) { returnnull;
}
hasSpaceKeypress = true; return SPACEBAR_CHAR;
case TOP_TEXT_INPUT: // Record the characters to be added to the DOM. var chars = nativeEvent.data;
// If it's a spacebar character, assume that we have already handled // it at the keypress level and bail immediately. Android Chrome // doesn't give us keycodes, so we need to ignore it. if (chars === SPACEBAR_CHAR && hasSpaceKeypress) { returnnull;
}
return chars;
default: // For other native event types, do nothing. returnnull;
}
}
/** * For browsers that do not provide the `textInput` event, extract the * appropriate string to use for SyntheticInputEvent. * * @param {number} topLevelType Number from `TopLevelEventTypes`. * @param {object} nativeEvent Native browser event. * @return {?string} The fallback string for this `beforeInput` event.
*/ function getFallbackBeforeInputChars(topLevelType, nativeEvent) { // If we are currently composing (IME) and using a fallback to do so, // try to extract the composed characters from the fallback object. // If composition event is available, we extract a string only at // compositionevent, otherwise extract it at fallback events. if (isComposing) { if (topLevelType === TOP_COMPOSITION_END || !canUseCompositionEvent && isFallbackCompositionEnd(topLevelType, nativeEvent)) { var chars = getData();
reset();
isComposing = false; return chars;
} returnnull;
}
switch (topLevelType) { case TOP_PASTE: // If a paste event occurs after a keypress, throw out the input // chars. Paste events should not lead to BeforeInput events. returnnull; case TOP_KEY_PRESS: /** * As of v27, Firefox may fire keypress events even when no character * will be inserted. A few possibilities: * * - `which` is `0`. Arrow keys, Esc key, etc. * * - `which` is the pressed key code, but no char is available. * Ex: 'AltGr + d` in Polish. There is no modified character for * this key combination and no character is inserted into the * document, but FF fires the keypress for char code `100` anyway. * No `input` event will occur. * * - `which` is the pressed key code, but a command combination is * being used. Ex: `Cmd+C`. No character is inserted, and no * `input` event will occur.
*/ if (!isKeypressCommand(nativeEvent)) { // IE fires the `keypress` event when a user types an emoji via // Touch keyboard of Windows. In such a case, the `char` property // holds an emoji character like `\uD83D\uDE0A`. Because its length // is 2, the property `which` does not represent an emoji correctly. // In such a case, we directly return the `char` property instead of // using `which`. if (nativeEvent.char && nativeEvent.char.length > 1) { return nativeEvent.char;
} elseif (nativeEvent.which) { return String.fromCharCode(nativeEvent.which);
}
} returnnull; case TOP_COMPOSITION_END: return useFallbackCompositionData && !isUsingKoreanIME(nativeEvent) ? null : nativeEvent.data; default: returnnull;
}
}
/** * Extract a SyntheticInputEvent for `beforeInput`, based on either native * `textInput` or fallback behavior. * * @return {?object} A SyntheticInputEvent.
*/ function extractBeforeInputEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget) { var chars = void 0;
/** * Create an `onBeforeInput` event to match * http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105/#events-inputevents. * * This event plugin is based on the native `textInput` event * available in Chrome, Safari, Opera, and IE. This event fires after * `onKeyPress` and `onCompositionEnd`, but before `onInput`. * * `beforeInput` is spec'd but not implemented in any browsers, and * the `input` event does not provide any useful information about what has * actually been added, contrary to the spec. Thus, `textInput` is the best * available event to identify the characters that have actually been inserted * into the target node. * * This plugin is also responsible for emitting `composition` events, thus * allowing us to share composition fallback code for both `beforeInput` and * `composition` event types.
*/ var BeforeInputEventPlugin = {
eventTypes: eventTypes,
extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) { var composition = extractCompositionEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget);
var beforeInput = extractBeforeInputEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget);
if (composition === null) { return beforeInput;
}
if (beforeInput === null) { return composition;
}
return [composition, beforeInput];
}
};
// Use to restore controlled state after a change event has fired.
var restoreImpl = null; var restoreTarget = null; 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 = getInstanceFromNode(target); if (!internalInstance) { // Unmounted return;
}
!(typeof restoreImpl === 'function') ? reactProdInvariant('280') : void 0; var props = getFiberCurrentPropsFromNode(internalInstance.stateNode);
restoreImpl(internalInstance.stateNode, internalInstance.type, props);
}
function setRestoreImplementation(impl) {
restoreImpl = impl;
}
function enqueueStateRestore(target) { if (restoreTarget) { if (restoreQueue) {
restoreQueue.push(target);
} else {
restoreQueue = [target];
}
} else {
restoreTarget = target;
}
}
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]);
}
}
}
// 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 // libraries need to call batchedUpdates. Eventually, this API will go away when // everything is batched by default. We'll then have a similar API to opt-out of // scheduled work and instead do synchronous work.
// Defaults var _batchedUpdatesImpl = function (fn, bookkeeping) { return fn(bookkeeping);
}; var _interactiveUpdatesImpl = function (fn, a, b) { return fn(a, b);
}; var _flushInteractiveUpdatesImpl = function () {};
var isBatching = false; function batchedUpdates(fn, bookkeeping) { if (isBatching) { // If we are currently inside another batch, we need to wait until it // fully completes before restoring state. return fn(bookkeeping);
}
isBatching = true; try { return _batchedUpdatesImpl(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.
isBatching = false; var controlledComponentsHavePendingUpdates = needsStateRestore(); if (controlledComponentsHavePendingUpdates) { // If a controlled event was fired, we may need to restore the state of // the DOM node back to the controlled value. This is necessary when React // bails out of the update without touching the DOM.
_flushInteractiveUpdatesImpl();
restoreStateIfNeeded();
}
}
}
function interactiveUpdates(fn, a, b) { return _interactiveUpdatesImpl(fn, a, b);
}
function isTextInputElement(elem) { var nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase();
if (nodeName === 'input') { return !!supportedInputTypes[elem.type];
}
if (nodeName === 'textarea') { returntrue;
}
returnfalse;
}
/** * HTML nodeType values that represent the type of the node
*/
var ELEMENT_NODE = 1; var TEXT_NODE = 3; var COMMENT_NODE = 8; var DOCUMENT_NODE = 9; var DOCUMENT_FRAGMENT_NODE = 11;
/** * Gets the target node from a native browser event by accounting for * inconsistencies in browser DOM APIs. * * @param {object} nativeEvent Native browser event. * @return {DOMEventTarget} Target node.
*/ function getEventTarget(nativeEvent) { // Fallback to nativeEvent.srcElement for IE9 // https://github.com/facebook/react/issues/12506 var target = nativeEvent.target || nativeEvent.srcElement || window;
// Normalize SVG <use> element events #4963 if (target.correspondingUseElement) {
target = target.correspondingUseElement;
}
/** * Checks if an event is supported in the current execution environment. * * NOTE: This will not work correctly for non-generic events such as `change`, * `reset`, `load`, `error`, and `select`. * * Borrows from Modernizr. * * @param {string} eventNameSuffix Event name, e.g. "click". * @return {boolean} True if the event is supported. * @internal * @license Modernizr 3.0.0pre (Custom Build) | MIT
*/ function isEventSupported(eventNameSuffix) { if (!canUseDOM) { returnfalse;
}
var eventName = 'on' + eventNameSuffix; var isSupported = eventName in document;
if (!isSupported) { var element = document.createElementNS('http://www.w3.org/1999/xhtml', 'div');
element.setAttribute(eventName, 'return;');
isSupported = typeof element[eventName] === 'function';
}
return isSupported;
}
function isCheckable(elem) { var type = elem.type; var nodeName = elem.nodeName; return nodeName && nodeName.toLowerCase() === 'input' && (type === 'checkbox' || type === 'radio');
}
function getTracker(node) { return node._valueTracker;
}
function detachTracker(node) {
node._valueTracker = null;
}
function getValueFromNode(node) { var value = ''; if (!node) { return value;
}
if (isCheckable(node)) {
value = node.checked ? 'true' : 'false';
} else {
value = node.value;
}
return value;
}
function trackValueOnNode(node) { var valueField = isCheckable(node) ? 'checked' : 'value';
--> --------------------
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.