--- a/devtools/client/shared/vendor/react-dev.js
+++ b/devtools/client/shared/vendor/react-dev.js
@@ -1,133 +1,58 @@
/**
- * React (with addons) v0.14.6
+ * React (with addons) v15.3.2
*/
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.React = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
/**
- * Copyright 2013-2015, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under the BSD-style license found in the
- * LICENSE file in the root directory of this source tree. An additional grant
- * of patent rights can be found in the PATENTS file in the same directory.
- *
- * @providesModule ReactWithAddons
- */
-
-/**
- * This module exists purely in the open source project, and is meant as a way
- * to create a separate standalone build of React. This build has "addons", or
- * functionality we've built and think might be useful but doesn't have a good
- * place to live inside React core.
- */
-
-'use strict';
-
-var LinkedStateMixin = _dereq_(22);
-var React = _dereq_(26);
-var ReactComponentWithPureRenderMixin = _dereq_(37);
-var ReactCSSTransitionGroup = _dereq_(29);
-var ReactFragment = _dereq_(64);
-var ReactTransitionGroup = _dereq_(94);
-var ReactUpdates = _dereq_(96);
-
-var cloneWithProps = _dereq_(118);
-var shallowCompare = _dereq_(140);
-var update = _dereq_(143);
-var warning = _dereq_(173);
-
-var warnedAboutBatchedUpdates = false;
-
-React.addons = {
- CSSTransitionGroup: ReactCSSTransitionGroup,
- LinkedStateMixin: LinkedStateMixin,
- PureRenderMixin: ReactComponentWithPureRenderMixin,
- TransitionGroup: ReactTransitionGroup,
-
- batchedUpdates: function () {
- if ("development" !== 'production') {
- "development" !== 'production' ? warning(warnedAboutBatchedUpdates, 'React.addons.batchedUpdates is deprecated. Use ' + 'ReactDOM.unstable_batchedUpdates instead.') : undefined;
- warnedAboutBatchedUpdates = true;
- }
- return ReactUpdates.batchedUpdates.apply(this, arguments);
- },
- cloneWithProps: cloneWithProps,
- createFragment: ReactFragment.create,
- shallowCompare: shallowCompare,
- update: update
-};
-
-React.addons.TestUtils = _dereq_(91);
-
-if ("development" !== 'production') {
- React.addons.Perf = _dereq_(55);
-}
-
-module.exports = React;
-},{"118":118,"140":140,"143":143,"173":173,"22":22,"26":26,"29":29,"37":37,"55":55,"64":64,"91":91,"94":94,"96":96}],2:[function(_dereq_,module,exports){
-/**
- * Copyright 2013-2015, Facebook, Inc.
+ * Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule AutoFocusUtils
- * @typechecks static-only
- */
-
-'use strict';
-
-var ReactMount = _dereq_(72);
-
-var findDOMNode = _dereq_(122);
-var focusNode = _dereq_(155);
-
-var Mixin = {
- componentDidMount: function () {
- if (this.props.autoFocus) {
- focusNode(findDOMNode(this));
- }
- }
-};
+ */
+
+'use strict';
+
+var ReactDOMComponentTree = _dereq_(46);
+
+var focusNode = _dereq_(172);
var AutoFocusUtils = {
- Mixin: Mixin,
-
focusDOMComponent: function () {
- focusNode(ReactMount.getNode(this._rootNodeID));
+ focusNode(ReactDOMComponentTree.getNodeFromInstance(this));
}
};
module.exports = AutoFocusUtils;
-},{"122":122,"155":155,"72":72}],3:[function(_dereq_,module,exports){
-/**
- * Copyright 2013-2015 Facebook, Inc.
+},{"172":172,"46":46}],2:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule BeforeInputEventPlugin
- * @typechecks static-only
- */
-
-'use strict';
-
-var EventConstants = _dereq_(15);
-var EventPropagators = _dereq_(19);
-var ExecutionEnvironment = _dereq_(147);
-var FallbackCompositionState = _dereq_(20);
-var SyntheticCompositionEvent = _dereq_(103);
-var SyntheticInputEvent = _dereq_(107);
-
-var keyOf = _dereq_(166);
+ */
+
+'use strict';
+
+var EventConstants = _dereq_(16);
+var EventPropagators = _dereq_(20);
+var ExecutionEnvironment = _dereq_(164);
+var FallbackCompositionState = _dereq_(21);
+var SyntheticCompositionEvent = _dereq_(116);
+var SyntheticInputEvent = _dereq_(120);
+
+var keyOf = _dereq_(182);
var END_KEYCODES = [9, 13, 27, 32]; // Tab, Return, Esc, Space
var START_KEYCODE = 229;
var canUseCompositionEvent = ExecutionEnvironment.canUseDOM && 'CompositionEvent' in window;
var documentMode = null;
if (ExecutionEnvironment.canUseDOM && 'documentMode' in document) {
@@ -275,23 +200,19 @@ function getDataFromCustomEvent(nativeEv
}
return null;
}
// Track the current IME composition fallback object, if any.
var currentComposition = null;
/**
- * @param {string} topLevelType Record from `EventConstants`.
- * @param {DOMEventTarget} topLevelTarget The listening component root node.
- * @param {string} topLevelTargetID ID of `topLevelTarget`.
- * @param {object} nativeEvent Native browser event.
* @return {?object} A SyntheticCompositionEvent.
*/
-function extractCompositionEvent(topLevelType, topLevelTarget, topLevelTargetID, nativeEvent, nativeEventTarget) {
+function extractCompositionEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget) {
var eventType;
var fallbackData;
if (canUseCompositionEvent) {
eventType = getCompositionEventType(topLevelType);
} else if (!currentComposition) {
if (isFallbackCompositionStart(topLevelType, nativeEvent)) {
eventType = eventTypes.compositionStart;
@@ -303,25 +224,25 @@ function extractCompositionEvent(topLeve
if (!eventType) {
return null;
}
if (useFallbackCompositionData) {
// The current composition is stored statically and must not be
// overwritten while composition continues.
if (!currentComposition && eventType === eventTypes.compositionStart) {
- currentComposition = FallbackCompositionState.getPooled(topLevelTarget);
+ currentComposition = FallbackCompositionState.getPooled(nativeEventTarget);
} else if (eventType === eventTypes.compositionEnd) {
if (currentComposition) {
fallbackData = currentComposition.getData();
}
}
}
- var event = SyntheticCompositionEvent.getPooled(eventType, topLevelTargetID, nativeEvent, nativeEventTarget);
+ 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) {
@@ -390,18 +311,20 @@ function getNativeBeforeInputChars(topLe
*
* @param {string} topLevelType Record from `EventConstants`.
* @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 (currentComposition) {
- if (topLevelType === topLevelTypes.topCompositionEnd || isFallbackCompositionEnd(topLevelType, nativeEvent)) {
+ if (topLevelType === topLevelTypes.topCompositionEnd || !canUseCompositionEvent && isFallbackCompositionEnd(topLevelType, nativeEvent)) {
var chars = currentComposition.getData();
FallbackCompositionState.release(currentComposition);
currentComposition = null;
return chars;
}
return null;
}
@@ -437,38 +360,34 @@ function getFallbackBeforeInputChars(top
return null;
}
}
/**
* Extract a SyntheticInputEvent for `beforeInput`, based on either native
* `textInput` or fallback behavior.
*
- * @param {string} topLevelType Record from `EventConstants`.
- * @param {DOMEventTarget} topLevelTarget The listening component root node.
- * @param {string} topLevelTargetID ID of `topLevelTarget`.
- * @param {object} nativeEvent Native browser event.
* @return {?object} A SyntheticInputEvent.
*/
-function extractBeforeInputEvent(topLevelType, topLevelTarget, topLevelTargetID, nativeEvent, nativeEventTarget) {
+function extractBeforeInputEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget) {
var chars;
if (canUseTextInputEvent) {
chars = getNativeBeforeInputChars(topLevelType, nativeEvent);
} else {
chars = getFallbackBeforeInputChars(topLevelType, nativeEvent);
}
// If no characters are being inserted, no BeforeInput event should
// be fired.
if (!chars) {
return null;
}
- var event = SyntheticInputEvent.getPooled(eventTypes.beforeInput, topLevelTargetID, nativeEvent, nativeEventTarget);
+ var event = SyntheticInputEvent.getPooled(eventTypes.beforeInput, targetInst, nativeEvent, nativeEventTarget);
event.data = chars;
EventPropagators.accumulateTwoPhaseDispatches(event);
return event;
}
/**
* Create an `onBeforeInput` event to match
@@ -487,74 +406,75 @@ function extractBeforeInputEvent(topLeve
* 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,
- /**
- * @param {string} topLevelType Record from `EventConstants`.
- * @param {DOMEventTarget} topLevelTarget The listening component root node.
- * @param {string} topLevelTargetID ID of `topLevelTarget`.
- * @param {object} nativeEvent Native browser event.
- * @return {*} An accumulation of synthetic events.
- * @see {EventPluginHub.extractEvents}
- */
- extractEvents: function (topLevelType, topLevelTarget, topLevelTargetID, nativeEvent, nativeEventTarget) {
- return [extractCompositionEvent(topLevelType, topLevelTarget, topLevelTargetID, nativeEvent, nativeEventTarget), extractBeforeInputEvent(topLevelType, topLevelTarget, topLevelTargetID, nativeEvent, nativeEventTarget)];
+ extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {
+ return [extractCompositionEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget), extractBeforeInputEvent(topLevelType, targetInst, nativeEvent, nativeEventTarget)];
}
};
module.exports = BeforeInputEventPlugin;
-},{"103":103,"107":107,"147":147,"15":15,"166":166,"19":19,"20":20}],4:[function(_dereq_,module,exports){
-/**
- * Copyright 2013-2015, Facebook, Inc.
+},{"116":116,"120":120,"16":16,"164":164,"182":182,"20":20,"21":21}],3:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule CSSProperty
*/
'use strict';
/**
* CSS properties which accept numbers but are not in units of "px".
*/
+
var isUnitlessNumber = {
animationIterationCount: true,
+ borderImageOutset: true,
+ borderImageSlice: true,
+ borderImageWidth: true,
boxFlex: true,
boxFlexGroup: true,
boxOrdinalGroup: true,
columnCount: true,
flex: true,
flexGrow: true,
flexPositive: true,
flexShrink: true,
flexNegative: true,
flexOrder: true,
+ gridRow: true,
+ gridColumn: true,
fontWeight: true,
lineClamp: true,
lineHeight: true,
opacity: true,
order: true,
orphans: true,
tabSize: true,
widows: true,
zIndex: true,
zoom: true,
// SVG-related properties
fillOpacity: true,
+ floodOpacity: true,
stopOpacity: true,
+ strokeDasharray: true,
strokeDashoffset: true,
+ strokeMiterlimit: true,
strokeOpacity: true,
strokeWidth: true
};
/**
* @param {string} prefix vendor-specific prefix, eg: Webkit
* @param {string} key style name, eg: transitionDuration
* @return {string} style name prefixed with `prefix`, properly camelCased, eg:
@@ -641,49 +561,48 @@ var shorthandPropertyExpansions = {
};
var CSSProperty = {
isUnitlessNumber: isUnitlessNumber,
shorthandPropertyExpansions: shorthandPropertyExpansions
};
module.exports = CSSProperty;
-},{}],5:[function(_dereq_,module,exports){
-/**
- * Copyright 2013-2015, Facebook, Inc.
+},{}],4:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule CSSPropertyOperations
- * @typechecks static-only
- */
-
-'use strict';
-
-var CSSProperty = _dereq_(4);
-var ExecutionEnvironment = _dereq_(147);
-var ReactPerf = _dereq_(78);
-
-var camelizeStyleName = _dereq_(149);
-var dangerousStyleValue = _dereq_(119);
-var hyphenateStyleName = _dereq_(160);
-var memoizeStringOnly = _dereq_(168);
-var warning = _dereq_(173);
+ */
+
+'use strict';
+
+var CSSProperty = _dereq_(3);
+var ExecutionEnvironment = _dereq_(164);
+var ReactInstrumentation = _dereq_(78);
+
+var camelizeStyleName = _dereq_(166);
+var dangerousStyleValue = _dereq_(134);
+var hyphenateStyleName = _dereq_(177);
+var memoizeStringOnly = _dereq_(183);
+var warning = _dereq_(187);
var processStyleName = memoizeStringOnly(function (styleName) {
return hyphenateStyleName(styleName);
});
var hasShorthandPropertyBug = false;
var styleFloatAccessor = 'cssFloat';
if (ExecutionEnvironment.canUseDOM) {
- var tempStyle = document.createElementNS('http://www.w3.org/1999/xhtml', 'div').style;
+ var tempStyle = document.createElementNS('http://www.w3.org/1999/xhtml','div').style;
try {
// IE8 throws "Invalid argument." if resetting shorthand style properties.
tempStyle.font = '';
} catch (e) {
hasShorthandPropertyBug = true;
}
// IE8 only supports accessing cssFloat (standard) as styleFloat
if (document.documentElement.style.cssFloat === undefined) {
@@ -695,55 +614,84 @@ if ("development" !== 'production') {
// 'msTransform' is correct, but the other prefixes should be capitalized
var badVendoredStyleNamePattern = /^(?:webkit|moz|o)[A-Z]/;
// style values shouldn't contain a semicolon
var badStyleValueWithSemicolonPattern = /;\s*$/;
var warnedStyleNames = {};
var warnedStyleValues = {};
-
- var warnHyphenatedStyleName = function (name) {
+ var warnedForNaNValue = false;
+
+ var warnHyphenatedStyleName = function (name, owner) {
if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) {
return;
}
warnedStyleNames[name] = true;
- "development" !== 'production' ? warning(false, 'Unsupported style property %s. Did you mean %s?', name, camelizeStyleName(name)) : undefined;
- };
-
- var warnBadVendoredStyleName = function (name) {
+ "development" !== 'production' ? warning(false, 'Unsupported style property %s. Did you mean %s?%s', name, camelizeStyleName(name), checkRenderMessage(owner)) : void 0;
+ };
+
+ var warnBadVendoredStyleName = function (name, owner) {
if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) {
return;
}
warnedStyleNames[name] = true;
- "development" !== 'production' ? warning(false, 'Unsupported vendor-prefixed style property %s. Did you mean %s?', name, name.charAt(0).toUpperCase() + name.slice(1)) : undefined;
- };
-
- var warnStyleValueWithSemicolon = function (name, value) {
+ "development" !== 'production' ? warning(false, 'Unsupported vendor-prefixed style property %s. Did you mean %s?%s', name, name.charAt(0).toUpperCase() + name.slice(1), checkRenderMessage(owner)) : void 0;
+ };
+
+ var warnStyleValueWithSemicolon = function (name, value, owner) {
if (warnedStyleValues.hasOwnProperty(value) && warnedStyleValues[value]) {
return;
}
warnedStyleValues[value] = true;
- "development" !== 'production' ? warning(false, 'Style property values shouldn\'t contain a semicolon. ' + 'Try "%s: %s" instead.', name, value.replace(badStyleValueWithSemicolonPattern, '')) : undefined;
+ "development" !== 'production' ? warning(false, 'Style property values shouldn\'t contain a semicolon.%s ' + 'Try "%s: %s" instead.', checkRenderMessage(owner), name, value.replace(badStyleValueWithSemicolonPattern, '')) : void 0;
+ };
+
+ var warnStyleValueIsNaN = function (name, value, owner) {
+ if (warnedForNaNValue) {
+ return;
+ }
+
+ warnedForNaNValue = true;
+ "development" !== 'production' ? warning(false, '`NaN` is an invalid value for the `%s` css style property.%s', name, checkRenderMessage(owner)) : void 0;
+ };
+
+ var checkRenderMessage = function (owner) {
+ if (owner) {
+ var name = owner.getName();
+ if (name) {
+ return ' Check the render method of `' + name + '`.';
+ }
+ }
+ return '';
};
/**
* @param {string} name
* @param {*} value
- */
- var warnValidStyle = function (name, value) {
+ * @param {ReactDOMComponent} component
+ */
+ var warnValidStyle = function (name, value, component) {
+ var owner;
+ if (component) {
+ owner = component._currentElement._owner;
+ }
if (name.indexOf('-') > -1) {
- warnHyphenatedStyleName(name);
+ warnHyphenatedStyleName(name, owner);
} else if (badVendoredStyleNamePattern.test(name)) {
- warnBadVendoredStyleName(name);
+ warnBadVendoredStyleName(name, owner);
} else if (badStyleValueWithSemicolonPattern.test(value)) {
- warnStyleValueWithSemicolon(name, value);
+ warnStyleValueWithSemicolon(name, value, owner);
+ }
+
+ if (typeof value === 'number' && isNaN(value)) {
+ warnStyleValueIsNaN(name, value, owner);
}
};
}
/**
* Operations for dealing with CSS properties.
*/
var CSSPropertyOperations = {
@@ -753,54 +701,60 @@ var CSSPropertyOperations = {
*
* > createMarkupForStyles({width: '200px', height: 0})
* "width:200px;height:0;"
*
* Undefined values are ignored so that declarative programming is easier.
* The result should be HTML-escaped before insertion into the DOM.
*
* @param {object} styles
+ * @param {ReactDOMComponent} component
* @return {?string}
*/
- createMarkupForStyles: function (styles) {
+ createMarkupForStyles: function (styles, component) {
var serialized = '';
for (var styleName in styles) {
if (!styles.hasOwnProperty(styleName)) {
continue;
}
var styleValue = styles[styleName];
if ("development" !== 'production') {
- warnValidStyle(styleName, styleValue);
+ warnValidStyle(styleName, styleValue, component);
}
if (styleValue != null) {
serialized += processStyleName(styleName) + ':';
- serialized += dangerousStyleValue(styleName, styleValue) + ';';
+ serialized += dangerousStyleValue(styleName, styleValue, component) + ';';
}
}
return serialized || null;
},
/**
* Sets the value for multiple styles on a node. If a value is specified as
* '' (empty string), the corresponding style property will be unset.
*
* @param {DOMElement} node
* @param {object} styles
- */
- setValueForStyles: function (node, styles) {
+ * @param {ReactDOMComponent} component
+ */
+ setValueForStyles: function (node, styles, component) {
+ if ("development" !== 'production') {
+ ReactInstrumentation.debugTool.onHostOperation(component._debugID, 'update styles', styles);
+ }
+
var style = node.style;
for (var styleName in styles) {
if (!styles.hasOwnProperty(styleName)) {
continue;
}
if ("development" !== 'production') {
- warnValidStyle(styleName, styles[styleName]);
- }
- var styleValue = dangerousStyleValue(styleName, styles[styleName]);
- if (styleName === 'float') {
+ warnValidStyle(styleName, styles[styleName], component);
+ }
+ var styleValue = dangerousStyleValue(styleName, styles[styleName], component);
+ if (styleName === 'float' || styleName === 'cssFloat') {
styleName = styleFloatAccessor;
}
if (styleValue) {
style[styleName] = styleValue;
} else {
var expansion = hasShorthandPropertyBug && CSSProperty.shorthandPropertyExpansions[styleName];
if (expansion) {
// Shorthand property that IE8 won't like unsetting, so unset each
@@ -812,39 +766,37 @@ var CSSPropertyOperations = {
style[styleName] = '';
}
}
}
}
};
-ReactPerf.measureMethods(CSSPropertyOperations, 'CSSPropertyOperations', {
- setValueForStyles: 'setValueForStyles'
-});
-
module.exports = CSSPropertyOperations;
-},{"119":119,"147":147,"149":149,"160":160,"168":168,"173":173,"4":4,"78":78}],6:[function(_dereq_,module,exports){
-/**
- * Copyright 2013-2015, Facebook, Inc.
+},{"134":134,"164":164,"166":166,"177":177,"183":183,"187":187,"3":3,"78":78}],5:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule CallbackQueue
*/
'use strict';
-var PooledClass = _dereq_(25);
-
-var assign = _dereq_(24);
-var invariant = _dereq_(161);
+var _prodInvariant = _dereq_(153),
+ _assign = _dereq_(188);
+
+var PooledClass = _dereq_(26);
+
+var invariant = _dereq_(178);
/**
* A specialized pseudo-event module to help keep track of components waiting to
* be notified when their DOM representations are available for use.
*
* This implements `PooledClass`, so you should never need to instantiate this.
* Instead, use `CallbackQueue.getPooled()`.
*
@@ -852,17 +804,17 @@ var invariant = _dereq_(161);
* @implements PooledClass
* @internal
*/
function CallbackQueue() {
this._callbacks = null;
this._contexts = null;
}
-assign(CallbackQueue.prototype, {
+_assign(CallbackQueue.prototype, {
/**
* Enqueues a callback to be invoked when `notifyAll` is invoked.
*
* @param {function} callback Invoked when `notifyAll` is invoked.
* @param {?object} context Context to call `callback` with.
* @internal
*/
@@ -878,27 +830,38 @@ assign(CallbackQueue.prototype, {
* the DOM representation of a component has been created or updated.
*
* @internal
*/
notifyAll: function () {
var callbacks = this._callbacks;
var contexts = this._contexts;
if (callbacks) {
- !(callbacks.length === contexts.length) ? "development" !== 'production' ? invariant(false, 'Mismatched list of contexts in callback queue') : invariant(false) : undefined;
+ !(callbacks.length === contexts.length) ? "development" !== 'production' ? invariant(false, 'Mismatched list of contexts in callback queue') : _prodInvariant('24') : void 0;
this._callbacks = null;
this._contexts = null;
for (var i = 0; i < callbacks.length; i++) {
callbacks[i].call(contexts[i]);
}
callbacks.length = 0;
contexts.length = 0;
}
},
+ checkpoint: function () {
+ return this._callbacks ? this._callbacks.length : 0;
+ },
+
+ rollback: function (len) {
+ if (this._callbacks) {
+ this._callbacks.length = len;
+ this._contexts.length = len;
+ }
+ },
+
/**
* Resets the internal queue.
*
* @internal
*/
reset: function () {
this._callbacks = null;
this._contexts = null;
@@ -911,41 +874,42 @@ assign(CallbackQueue.prototype, {
this.reset();
}
});
PooledClass.addPoolingTo(CallbackQueue);
module.exports = CallbackQueue;
-},{"161":161,"24":24,"25":25}],7:[function(_dereq_,module,exports){
-/**
- * Copyright 2013-2015, Facebook, Inc.
+},{"153":153,"178":178,"188":188,"26":26}],6:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ChangeEventPlugin
*/
'use strict';
-var EventConstants = _dereq_(15);
-var EventPluginHub = _dereq_(16);
-var EventPropagators = _dereq_(19);
-var ExecutionEnvironment = _dereq_(147);
-var ReactUpdates = _dereq_(96);
-var SyntheticEvent = _dereq_(105);
-
-var getEventTarget = _dereq_(128);
-var isEventSupported = _dereq_(133);
-var isTextInputElement = _dereq_(134);
-var keyOf = _dereq_(166);
+var EventConstants = _dereq_(16);
+var EventPluginHub = _dereq_(17);
+var EventPropagators = _dereq_(20);
+var ExecutionEnvironment = _dereq_(164);
+var ReactDOMComponentTree = _dereq_(46);
+var ReactUpdates = _dereq_(107);
+var SyntheticEvent = _dereq_(118);
+
+var getEventTarget = _dereq_(142);
+var isEventSupported = _dereq_(149);
+var isTextInputElement = _dereq_(150);
+var keyOf = _dereq_(182);
var topLevelTypes = EventConstants.topLevelTypes;
var eventTypes = {
change: {
phasedRegistrationNames: {
bubbled: keyOf({ onChange: null }),
captured: keyOf({ onChangeCapture: null })
@@ -953,36 +917,36 @@ var eventTypes = {
dependencies: [topLevelTypes.topBlur, topLevelTypes.topChange, topLevelTypes.topClick, topLevelTypes.topFocus, topLevelTypes.topInput, topLevelTypes.topKeyDown, topLevelTypes.topKeyUp, topLevelTypes.topSelectionChange]
}
};
/**
* For IE shims
*/
var activeElement = null;
-var activeElementID = null;
+var activeElementInst = null;
var activeElementValue = null;
var activeElementValueProp = null;
/**
* SECTION: handle `change` event
*/
function shouldUseChangeEvent(elem) {
var nodeName = elem.nodeName && elem.nodeName.toLowerCase();
return nodeName === 'select' || nodeName === 'input' && elem.type === 'file';
}
var doesChangeEventBubble = false;
if (ExecutionEnvironment.canUseDOM) {
// See `handleChange` comment below
- doesChangeEventBubble = isEventSupported('change') && (!('documentMode' in document) || document.documentMode > 8);
+ doesChangeEventBubble = isEventSupported('change') && (!document.documentMode || document.documentMode > 8);
}
function manualDispatchChangeEvent(nativeEvent) {
- var event = SyntheticEvent.getPooled(eventTypes.change, activeElementID, nativeEvent, getEventTarget(nativeEvent));
+ var event = SyntheticEvent.getPooled(eventTypes.change, activeElementInst, nativeEvent, getEventTarget(nativeEvent));
EventPropagators.accumulateTwoPhaseDispatches(event);
// If change and propertychange bubbled, we'd just bind to it like all the
// other events and have it go through ReactBrowserEventEmitter. Since it
// doesn't, we manually listen for the events and so we have to enqueue and
// process the abstract event manually.
//
// Batching is necessary here in order to ensure that all event handlers run
@@ -994,110 +958,121 @@ function manualDispatchChangeEvent(nativ
ReactUpdates.batchedUpdates(runEventInBatch, event);
}
function runEventInBatch(event) {
EventPluginHub.enqueueEvents(event);
EventPluginHub.processEventQueue(false);
}
-function startWatchingForChangeEventIE8(target, targetID) {
+function startWatchingForChangeEventIE8(target, targetInst) {
activeElement = target;
- activeElementID = targetID;
+ activeElementInst = targetInst;
activeElement.attachEvent('onchange', manualDispatchChangeEvent);
}
function stopWatchingForChangeEventIE8() {
if (!activeElement) {
return;
}
activeElement.detachEvent('onchange', manualDispatchChangeEvent);
activeElement = null;
- activeElementID = null;
-}
-
-function getTargetIDForChangeEvent(topLevelType, topLevelTarget, topLevelTargetID) {
+ activeElementInst = null;
+}
+
+function getTargetInstForChangeEvent(topLevelType, targetInst) {
if (topLevelType === topLevelTypes.topChange) {
- return topLevelTargetID;
- }
-}
-function handleEventsForChangeEventIE8(topLevelType, topLevelTarget, topLevelTargetID) {
+ return targetInst;
+ }
+}
+function handleEventsForChangeEventIE8(topLevelType, target, targetInst) {
if (topLevelType === topLevelTypes.topFocus) {
// stopWatching() should be a noop here but we call it just in case we
// missed a blur event somehow.
stopWatchingForChangeEventIE8();
- startWatchingForChangeEventIE8(topLevelTarget, topLevelTargetID);
+ startWatchingForChangeEventIE8(target, targetInst);
} else if (topLevelType === topLevelTypes.topBlur) {
stopWatchingForChangeEventIE8();
}
}
/**
* SECTION: handle `input` event
*/
var isInputEventSupported = false;
if (ExecutionEnvironment.canUseDOM) {
// IE9 claims to support the input event but fails to trigger it when
- // deleting text, so we ignore its input events
- isInputEventSupported = isEventSupported('input') && (!('documentMode' in document) || document.documentMode > 9);
-}
-
-/**
- * (For old IE.) Replacement getter/setter for the `value` property that gets
+ // deleting text, so we ignore its input events.
+ // IE10+ fire input events to often, such when a placeholder
+ // changes or when an input with a placeholder is focused.
+ isInputEventSupported = isEventSupported('input') && (!document.documentMode || document.documentMode > 11);
+}
+
+/**
+ * (For IE <=11) Replacement getter/setter for the `value` property that gets
* set on the active element.
*/
var newValueProp = {
get: function () {
return activeElementValueProp.get.call(this);
},
set: function (val) {
// Cast to a string so we can do equality checks.
activeElementValue = '' + val;
activeElementValueProp.set.call(this, val);
}
};
/**
- * (For old IE.) Starts tracking propertychange events on the passed-in element
+ * (For IE <=11) Starts tracking propertychange events on the passed-in element
* and override the value property so that we can distinguish user events from
* value changes in JS.
*/
-function startWatchingForValueChange(target, targetID) {
+function startWatchingForValueChange(target, targetInst) {
activeElement = target;
- activeElementID = targetID;
+ activeElementInst = targetInst;
activeElementValue = target.value;
activeElementValueProp = Object.getOwnPropertyDescriptor(target.constructor.prototype, 'value');
// Not guarded in a canDefineProperty check: IE8 supports defineProperty only
// on DOM elements
Object.defineProperty(activeElement, 'value', newValueProp);
- activeElement.attachEvent('onpropertychange', handlePropertyChange);
-}
-
-/**
- * (For old IE.) Removes the event listeners from the currently-tracked element,
+ if (activeElement.attachEvent) {
+ activeElement.attachEvent('onpropertychange', handlePropertyChange);
+ } else {
+ activeElement.addEventListener('propertychange', handlePropertyChange, false);
+ }
+}
+
+/**
+ * (For IE <=11) Removes the event listeners from the currently-tracked element,
* if any exists.
*/
function stopWatchingForValueChange() {
if (!activeElement) {
return;
}
// delete restores the original property definition
delete activeElement.value;
- activeElement.detachEvent('onpropertychange', handlePropertyChange);
+
+ if (activeElement.detachEvent) {
+ activeElement.detachEvent('onpropertychange', handlePropertyChange);
+ } else {
+ activeElement.removeEventListener('propertychange', handlePropertyChange, false);
+ }
activeElement = null;
- activeElementID = null;
+ activeElementInst = null;
activeElementValue = null;
activeElementValueProp = null;
}
/**
- * (For old IE.) Handles a propertychange event, sending a `change` event if
+ * (For IE <=11) Handles a propertychange event, sending a `change` event if
* the value of the active element has changed.
*/
function handlePropertyChange(nativeEvent) {
if (nativeEvent.propertyName !== 'value') {
return;
}
var value = nativeEvent.srcElement.value;
if (value === activeElementValue) {
@@ -1106,80 +1081,79 @@ function handlePropertyChange(nativeEven
activeElementValue = value;
manualDispatchChangeEvent(nativeEvent);
}
/**
* If a `change` event should be fired, returns the target's ID.
*/
-function getTargetIDForInputEvent(topLevelType, topLevelTarget, topLevelTargetID) {
+function getTargetInstForInputEvent(topLevelType, targetInst) {
if (topLevelType === topLevelTypes.topInput) {
// In modern browsers (i.e., not IE8 or IE9), the input event is exactly
// what we want so fall through here and trigger an abstract event
- return topLevelTargetID;
- }
-}
-
-// For IE8 and IE9.
-function handleEventsForInputEventIE(topLevelType, topLevelTarget, topLevelTargetID) {
+ return targetInst;
+ }
+}
+
+function handleEventsForInputEventIE(topLevelType, target, targetInst) {
if (topLevelType === topLevelTypes.topFocus) {
// In IE8, we can capture almost all .value changes by adding a
// propertychange handler and looking for events with propertyName
// equal to 'value'
- // In IE9, propertychange fires for most input events but is buggy and
+ // In IE9-11, propertychange fires for most input events but is buggy and
// doesn't fire when text is deleted, but conveniently, selectionchange
// appears to fire in all of the remaining cases so we catch those and
// forward the event if the value has changed
// In either case, we don't want to call the event handler if the value
// is changed from JS so we redefine a setter for `.value` that updates
// our activeElementValue variable, allowing us to ignore those changes
//
// stopWatching() should be a noop here but we call it just in case we
// missed a blur event somehow.
stopWatchingForValueChange();
- startWatchingForValueChange(topLevelTarget, topLevelTargetID);
+ startWatchingForValueChange(target, targetInst);
} else if (topLevelType === topLevelTypes.topBlur) {
stopWatchingForValueChange();
}
}
// For IE8 and IE9.
-function getTargetIDForInputEventIE(topLevelType, topLevelTarget, topLevelTargetID) {
+function getTargetInstForInputEventIE(topLevelType, targetInst) {
if (topLevelType === topLevelTypes.topSelectionChange || topLevelType === topLevelTypes.topKeyUp || topLevelType === topLevelTypes.topKeyDown) {
// On the selectionchange event, the target is just document which isn't
// helpful for us so just check activeElement instead.
//
// 99% of the time, keydown and keyup aren't necessary. IE8 fails to fire
// propertychange on the first input event after setting `value` from a
// script and fires only keydown, keypress, keyup. Catching keyup usually
// gets it and catching keydown lets us fire an event for the first
// keystroke if user does a key repeat (it'll be a little delayed: right
// before the second keystroke). Other input methods (e.g., paste) seem to
// fire selectionchange normally.
if (activeElement && activeElement.value !== activeElementValue) {
activeElementValue = activeElement.value;
- return activeElementID;
+ return activeElementInst;
}
}
}
/**
* SECTION: handle `click` event
*/
function shouldUseClickEvent(elem) {
// Use the `click` event to detect changes to checkbox and radio inputs.
// This approach works across all browsers, whereas `change` does not fire
// until `blur` in IE8.
return elem.nodeName && elem.nodeName.toLowerCase() === 'input' && (elem.type === 'checkbox' || elem.type === 'radio');
}
-function getTargetIDForClickEvent(topLevelType, topLevelTarget, topLevelTargetID) {
+function getTargetInstForClickEvent(topLevelType, targetInst) {
if (topLevelType === topLevelTypes.topClick) {
- return topLevelTargetID;
+ return targetInst;
}
}
/**
* This plugin creates an `onChange` event that normalizes change events
* across form elements. This event fires at a time when it's possible to
* change the element's value without seeing a flicker.
*
@@ -1187,249 +1161,422 @@ function getTargetIDForClickEvent(topLev
* - input (see `isTextInputElement`)
* - textarea
* - select
*/
var ChangeEventPlugin = {
eventTypes: eventTypes,
- /**
- * @param {string} topLevelType Record from `EventConstants`.
- * @param {DOMEventTarget} topLevelTarget The listening component root node.
- * @param {string} topLevelTargetID ID of `topLevelTarget`.
- * @param {object} nativeEvent Native browser event.
- * @return {*} An accumulation of synthetic events.
- * @see {EventPluginHub.extractEvents}
- */
- extractEvents: function (topLevelType, topLevelTarget, topLevelTargetID, nativeEvent, nativeEventTarget) {
-
- var getTargetIDFunc, handleEventFunc;
- if (shouldUseChangeEvent(topLevelTarget)) {
+ extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {
+ var targetNode = targetInst ? ReactDOMComponentTree.getNodeFromInstance(targetInst) : window;
+
+ var getTargetInstFunc, handleEventFunc;
+ if (shouldUseChangeEvent(targetNode)) {
if (doesChangeEventBubble) {
- getTargetIDFunc = getTargetIDForChangeEvent;
+ getTargetInstFunc = getTargetInstForChangeEvent;
} else {
handleEventFunc = handleEventsForChangeEventIE8;
}
- } else if (isTextInputElement(topLevelTarget)) {
+ } else if (isTextInputElement(targetNode)) {
if (isInputEventSupported) {
- getTargetIDFunc = getTargetIDForInputEvent;
+ getTargetInstFunc = getTargetInstForInputEvent;
} else {
- getTargetIDFunc = getTargetIDForInputEventIE;
+ getTargetInstFunc = getTargetInstForInputEventIE;
handleEventFunc = handleEventsForInputEventIE;
}
- } else if (shouldUseClickEvent(topLevelTarget)) {
- getTargetIDFunc = getTargetIDForClickEvent;
- }
-
- if (getTargetIDFunc) {
- var targetID = getTargetIDFunc(topLevelType, topLevelTarget, topLevelTargetID);
- if (targetID) {
- var event = SyntheticEvent.getPooled(eventTypes.change, targetID, nativeEvent, nativeEventTarget);
+ } else if (shouldUseClickEvent(targetNode)) {
+ getTargetInstFunc = getTargetInstForClickEvent;
+ }
+
+ if (getTargetInstFunc) {
+ var inst = getTargetInstFunc(topLevelType, targetInst);
+ if (inst) {
+ var event = SyntheticEvent.getPooled(eventTypes.change, inst, nativeEvent, nativeEventTarget);
event.type = 'change';
EventPropagators.accumulateTwoPhaseDispatches(event);
return event;
}
}
if (handleEventFunc) {
- handleEventFunc(topLevelType, topLevelTarget, topLevelTargetID);
+ handleEventFunc(topLevelType, targetNode, targetInst);
}
}
};
module.exports = ChangeEventPlugin;
-},{"105":105,"128":128,"133":133,"134":134,"147":147,"15":15,"16":16,"166":166,"19":19,"96":96}],8:[function(_dereq_,module,exports){
-/**
- * Copyright 2013-2015, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under the BSD-style license found in the
- * LICENSE file in the root directory of this source tree. An additional grant
- * of patent rights can be found in the PATENTS file in the same directory.
- *
- * @providesModule ClientReactRootIndex
- * @typechecks
- */
-
-'use strict';
-
-var nextReactRootIndex = 0;
-
-var ClientReactRootIndex = {
- createReactRootIndex: function () {
- return nextReactRootIndex++;
- }
-};
-
-module.exports = ClientReactRootIndex;
-},{}],9:[function(_dereq_,module,exports){
-/**
- * Copyright 2013-2015, Facebook, Inc.
+},{"107":107,"118":118,"142":142,"149":149,"150":150,"16":16,"164":164,"17":17,"182":182,"20":20,"46":46}],7:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule DOMChildrenOperations
- * @typechecks static-only
- */
-
-'use strict';
-
+ */
+
+'use strict';
+
+var DOMLazyTree = _dereq_(8);
var Danger = _dereq_(12);
-var ReactMultiChildUpdateTypes = _dereq_(74);
-var ReactPerf = _dereq_(78);
-
-var setInnerHTML = _dereq_(138);
-var setTextContent = _dereq_(139);
-var invariant = _dereq_(161);
+var ReactMultiChildUpdateTypes = _dereq_(84);
+var ReactDOMComponentTree = _dereq_(46);
+var ReactInstrumentation = _dereq_(78);
+
+var createMicrosoftUnsafeLocalFunction = _dereq_(133);
+var setInnerHTML = _dereq_(155);
+var setTextContent = _dereq_(156);
+
+function getNodeAfter(parentNode, node) {
+ // Special case for text components, which return [open, close] comments
+ // from getHostNode.
+ if (Array.isArray(node)) {
+ node = node[1];
+ }
+ return node ? node.nextSibling : parentNode.firstChild;
+}
/**
* Inserts `childNode` as a child of `parentNode` at the `index`.
*
* @param {DOMElement} parentNode Parent node in which to insert.
* @param {DOMElement} childNode Child node to insert.
* @param {number} index Index at which to insert the child.
* @internal
*/
-function insertChildAt(parentNode, childNode, index) {
- // By exploiting arrays returning `undefined` for an undefined index, we can
- // rely exclusively on `insertBefore(node, null)` instead of also using
- // `appendChild(node)`. However, using `undefined` is not allowed by all
- // browsers so we must replace it with `null`.
-
- // fix render order error in safari
- // IE8 will throw error when index out of list size.
- var beforeChild = index >= parentNode.childNodes.length ? null : parentNode.childNodes.item(index);
-
- parentNode.insertBefore(childNode, beforeChild);
+var insertChildAt = createMicrosoftUnsafeLocalFunction(function (parentNode, childNode, referenceNode) {
+ // We rely exclusively on `insertBefore(node, null)` instead of also using
+ // `appendChild(node)`. (Using `undefined` is not allowed by all browsers so
+ // we are careful to use `null`.)
+ parentNode.insertBefore(childNode, referenceNode);
+});
+
+function insertLazyTreeChildAt(parentNode, childTree, referenceNode) {
+ DOMLazyTree.insertTreeBefore(parentNode, childTree, referenceNode);
+}
+
+function moveChild(parentNode, childNode, referenceNode) {
+ if (Array.isArray(childNode)) {
+ moveDelimitedText(parentNode, childNode[0], childNode[1], referenceNode);
+ } else {
+ insertChildAt(parentNode, childNode, referenceNode);
+ }
+}
+
+function removeChild(parentNode, childNode) {
+ if (Array.isArray(childNode)) {
+ var closingComment = childNode[1];
+ childNode = childNode[0];
+ removeDelimitedText(parentNode, childNode, closingComment);
+ parentNode.removeChild(closingComment);
+ }
+ parentNode.removeChild(childNode);
+}
+
+function moveDelimitedText(parentNode, openingComment, closingComment, referenceNode) {
+ var node = openingComment;
+ while (true) {
+ var nextNode = node.nextSibling;
+ insertChildAt(parentNode, node, referenceNode);
+ if (node === closingComment) {
+ break;
+ }
+ node = nextNode;
+ }
+}
+
+function removeDelimitedText(parentNode, startNode, closingComment) {
+ while (true) {
+ var node = startNode.nextSibling;
+ if (node === closingComment) {
+ // The closing comment is removed by ReactMultiChild.
+ break;
+ } else {
+ parentNode.removeChild(node);
+ }
+ }
+}
+
+function replaceDelimitedText(openingComment, closingComment, stringText) {
+ var parentNode = openingComment.parentNode;
+ var nodeAfterComment = openingComment.nextSibling;
+ if (nodeAfterComment === closingComment) {
+ // There are no text nodes between the opening and closing comments; insert
+ // a new one if stringText isn't empty.
+ if (stringText) {
+ insertChildAt(parentNode, document.createTextNode(stringText), nodeAfterComment);
+ }
+ } else {
+ if (stringText) {
+ // Set the text content of the first node after the opening comment, and
+ // remove all following nodes up until the closing comment.
+ setTextContent(nodeAfterComment, stringText);
+ removeDelimitedText(parentNode, nodeAfterComment, closingComment);
+ } else {
+ removeDelimitedText(parentNode, openingComment, closingComment);
+ }
+ }
+
+ if ("development" !== 'production') {
+ ReactInstrumentation.debugTool.onHostOperation(ReactDOMComponentTree.getInstanceFromNode(openingComment)._debugID, 'replace text', stringText);
+ }
+}
+
+var dangerouslyReplaceNodeWithMarkup = Danger.dangerouslyReplaceNodeWithMarkup;
+if ("development" !== 'production') {
+ dangerouslyReplaceNodeWithMarkup = function (oldChild, markup, prevInstance) {
+ Danger.dangerouslyReplaceNodeWithMarkup(oldChild, markup);
+ if (prevInstance._debugID !== 0) {
+ ReactInstrumentation.debugTool.onHostOperation(prevInstance._debugID, 'replace with', markup.toString());
+ } else {
+ var nextInstance = ReactDOMComponentTree.getInstanceFromNode(markup.node);
+ if (nextInstance._debugID !== 0) {
+ ReactInstrumentation.debugTool.onHostOperation(nextInstance._debugID, 'mount', markup.toString());
+ }
+ }
+ };
}
/**
* Operations for updating with DOM children.
*/
var DOMChildrenOperations = {
- dangerouslyReplaceNodeWithMarkup: Danger.dangerouslyReplaceNodeWithMarkup,
-
- updateTextContent: setTextContent,
+ dangerouslyReplaceNodeWithMarkup: dangerouslyReplaceNodeWithMarkup,
+
+ replaceDelimitedText: replaceDelimitedText,
/**
* Updates a component's children by processing a series of updates. The
* update configurations are each expected to have a `parentNode` property.
*
* @param {array<object>} updates List of update configurations.
- * @param {array<string>} markupList List of markup strings.
- * @internal
- */
- processUpdates: function (updates, markupList) {
- var update;
- // Mapping from parent IDs to initial child orderings.
- var initialChildren = null;
- // List of children that will be moved or removed.
- var updatedChildren = null;
-
- for (var i = 0; i < updates.length; i++) {
- update = updates[i];
- if (update.type === ReactMultiChildUpdateTypes.MOVE_EXISTING || update.type === ReactMultiChildUpdateTypes.REMOVE_NODE) {
- var updatedIndex = update.fromIndex;
- var updatedChild = update.parentNode.childNodes[updatedIndex];
- var parentID = update.parentID;
-
- !updatedChild ? "development" !== 'production' ? invariant(false, 'processUpdates(): Unable to find child %s of element. This ' + 'probably means the DOM was unexpectedly mutated (e.g., by the ' + 'browser), usually due to forgetting a <tbody> when using tables, ' + 'nesting tags like <form>, <p>, or <a>, or using non-SVG elements ' + 'in an <svg> parent. Try inspecting the child nodes of the element ' + 'with React ID `%s`.', updatedIndex, parentID) : invariant(false) : undefined;
-
- initialChildren = initialChildren || {};
- initialChildren[parentID] = initialChildren[parentID] || [];
- initialChildren[parentID][updatedIndex] = updatedChild;
-
- updatedChildren = updatedChildren || [];
- updatedChildren.push(updatedChild);
- }
- }
-
- var renderedMarkup;
- // markupList is either a list of markup or just a list of elements
- if (markupList.length && typeof markupList[0] === 'string') {
- renderedMarkup = Danger.dangerouslyRenderMarkup(markupList);
- } else {
- renderedMarkup = markupList;
- }
-
- // Remove updated children first so that `toIndex` is consistent.
- if (updatedChildren) {
- for (var j = 0; j < updatedChildren.length; j++) {
- updatedChildren[j].parentNode.removeChild(updatedChildren[j]);
- }
+ * @internal
+ */
+ processUpdates: function (parentNode, updates) {
+ if ("development" !== 'production') {
+ var parentNodeDebugID = ReactDOMComponentTree.getInstanceFromNode(parentNode)._debugID;
}
for (var k = 0; k < updates.length; k++) {
- update = updates[k];
+ var update = updates[k];
switch (update.type) {
case ReactMultiChildUpdateTypes.INSERT_MARKUP:
- insertChildAt(update.parentNode, renderedMarkup[update.markupIndex], update.toIndex);
+ insertLazyTreeChildAt(parentNode, update.content, getNodeAfter(parentNode, update.afterNode));
+ if ("development" !== 'production') {
+ ReactInstrumentation.debugTool.onHostOperation(parentNodeDebugID, 'insert child', { toIndex: update.toIndex, content: update.content.toString() });
+ }
break;
case ReactMultiChildUpdateTypes.MOVE_EXISTING:
- insertChildAt(update.parentNode, initialChildren[update.parentID][update.fromIndex], update.toIndex);
+ moveChild(parentNode, update.fromNode, getNodeAfter(parentNode, update.afterNode));
+ if ("development" !== 'production') {
+ ReactInstrumentation.debugTool.onHostOperation(parentNodeDebugID, 'move child', { fromIndex: update.fromIndex, toIndex: update.toIndex });
+ }
break;
case ReactMultiChildUpdateTypes.SET_MARKUP:
- setInnerHTML(update.parentNode, update.content);
+ setInnerHTML(parentNode, update.content);
+ if ("development" !== 'production') {
+ ReactInstrumentation.debugTool.onHostOperation(parentNodeDebugID, 'replace children', update.content.toString());
+ }
break;
case ReactMultiChildUpdateTypes.TEXT_CONTENT:
- setTextContent(update.parentNode, update.content);
+ setTextContent(parentNode, update.content);
+ if ("development" !== 'production') {
+ ReactInstrumentation.debugTool.onHostOperation(parentNodeDebugID, 'replace text', update.content.toString());
+ }
break;
case ReactMultiChildUpdateTypes.REMOVE_NODE:
- // Already removed by the for-loop above.
+ removeChild(parentNode, update.fromNode);
+ if ("development" !== 'production') {
+ ReactInstrumentation.debugTool.onHostOperation(parentNodeDebugID, 'remove child', { fromIndex: update.fromIndex });
+ }
break;
}
}
}
};
-ReactPerf.measureMethods(DOMChildrenOperations, 'DOMChildrenOperations', {
- updateTextContent: 'updateTextContent'
-});
-
module.exports = DOMChildrenOperations;
-},{"12":12,"138":138,"139":139,"161":161,"74":74,"78":78}],10:[function(_dereq_,module,exports){
-/**
- * Copyright 2013-2015, Facebook, Inc.
+},{"12":12,"133":133,"155":155,"156":156,"46":46,"78":78,"8":8,"84":84}],8:[function(_dereq_,module,exports){
+/**
+ * Copyright 2015-present, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
+ * @providesModule DOMLazyTree
+ */
+
+'use strict';
+
+var DOMNamespaces = _dereq_(9);
+var setInnerHTML = _dereq_(155);
+
+var createMicrosoftUnsafeLocalFunction = _dereq_(133);
+var setTextContent = _dereq_(156);
+
+var ELEMENT_NODE_TYPE = 1;
+var DOCUMENT_FRAGMENT_NODE_TYPE = 11;
+
+/**
+ * In IE (8-11) and Edge, appending nodes with no children is dramatically
+ * faster than appending a full subtree, so we essentially queue up the
+ * .appendChild calls here and apply them so each node is added to its parent
+ * before any children are added.
+ *
+ * In other browsers, doing so is slower or neutral compared to the other order
+ * (in Firefox, twice as slow) so we only do this inversion in IE.
+ *
+ * See https://github.com/spicyj/innerhtml-vs-createelement-vs-clonenode.
+ */
+var enableLazy = typeof document !== 'undefined' && typeof document.documentMode === 'number' || typeof navigator !== 'undefined' && typeof navigator.userAgent === 'string' && /\bEdge\/\d/.test(navigator.userAgent);
+
+function insertTreeChildren(tree) {
+ if (!enableLazy) {
+ return;
+ }
+ var node = tree.node;
+ var children = tree.children;
+ if (children.length) {
+ for (var i = 0; i < children.length; i++) {
+ insertTreeBefore(node, children[i], null);
+ }
+ } else if (tree.html != null) {
+ setInnerHTML(node, tree.html);
+ } else if (tree.text != null) {
+ setTextContent(node, tree.text);
+ }
+}
+
+var insertTreeBefore = createMicrosoftUnsafeLocalFunction(function (parentNode, tree, referenceNode) {
+ // DocumentFragments aren't actually part of the DOM after insertion so
+ // appending children won't update the DOM. We need to ensure the fragment
+ // is properly populated first, breaking out of our lazy approach for just
+ // this level. Also, some <object> plugins (like Flash Player) will read
+ // <param> nodes immediately upon insertion into the DOM, so <object>
+ // must also be populated prior to insertion into the DOM.
+ if (tree.node.nodeType === DOCUMENT_FRAGMENT_NODE_TYPE || tree.node.nodeType === ELEMENT_NODE_TYPE && tree.node.nodeName.toLowerCase() === 'object' && (tree.node.namespaceURI == null || tree.node.namespaceURI === DOMNamespaces.html)) {
+ insertTreeChildren(tree);
+ parentNode.insertBefore(tree.node, referenceNode);
+ } else {
+ parentNode.insertBefore(tree.node, referenceNode);
+ insertTreeChildren(tree);
+ }
+});
+
+function replaceChildWithTree(oldNode, newTree) {
+ oldNode.parentNode.replaceChild(newTree.node, oldNode);
+ insertTreeChildren(newTree);
+}
+
+function queueChild(parentTree, childTree) {
+ if (enableLazy) {
+ parentTree.children.push(childTree);
+ } else {
+ parentTree.node.appendChild(childTree.node);
+ }
+}
+
+function queueHTML(tree, html) {
+ if (enableLazy) {
+ tree.html = html;
+ } else {
+ setInnerHTML(tree.node, html);
+ }
+}
+
+function queueText(tree, text) {
+ if (enableLazy) {
+ tree.text = text;
+ } else {
+ setTextContent(tree.node, text);
+ }
+}
+
+function toString() {
+ return this.node.nodeName;
+}
+
+function DOMLazyTree(node) {
+ return {
+ node: node,
+ children: [],
+ html: null,
+ text: null,
+ toString: toString
+ };
+}
+
+DOMLazyTree.insertTreeBefore = insertTreeBefore;
+DOMLazyTree.replaceChildWithTree = replaceChildWithTree;
+DOMLazyTree.queueChild = queueChild;
+DOMLazyTree.queueHTML = queueHTML;
+DOMLazyTree.queueText = queueText;
+
+module.exports = DOMLazyTree;
+},{"133":133,"155":155,"156":156,"9":9}],9:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-present, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
+ * @providesModule DOMNamespaces
+ */
+
+'use strict';
+
+var DOMNamespaces = {
+ html: 'http://www.w3.org/1999/xhtml',
+ mathml: 'http://www.w3.org/1998/Math/MathML',
+ svg: 'http://www.w3.org/2000/svg'
+};
+
+module.exports = DOMNamespaces;
+},{}],10:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule DOMProperty
- * @typechecks static-only
- */
-
-'use strict';
-
-var invariant = _dereq_(161);
+ */
+
+'use strict';
+
+var _prodInvariant = _dereq_(153);
+
+var invariant = _dereq_(178);
function checkMask(value, bitmask) {
return (value & bitmask) === bitmask;
}
var DOMPropertyInjection = {
/**
* Mapping from normalized, camelcased property names to a configuration that
* specifies how the associated DOM property should be accessed or rendered.
*/
- MUST_USE_ATTRIBUTE: 0x1,
- MUST_USE_PROPERTY: 0x2,
- HAS_SIDE_EFFECTS: 0x4,
- HAS_BOOLEAN_VALUE: 0x8,
- HAS_NUMERIC_VALUE: 0x10,
- HAS_POSITIVE_NUMERIC_VALUE: 0x20 | 0x10,
- HAS_OVERLOADED_BOOLEAN_VALUE: 0x40,
+ MUST_USE_PROPERTY: 0x1,
+ HAS_BOOLEAN_VALUE: 0x4,
+ HAS_NUMERIC_VALUE: 0x8,
+ HAS_POSITIVE_NUMERIC_VALUE: 0x10 | 0x8,
+ HAS_OVERLOADED_BOOLEAN_VALUE: 0x20,
/**
* Inject some specialized knowledge about the DOM. This takes a config object
* with the following properties:
*
* isCustomAttribute: function that given an attribute name will return true
* if it can be inserted into the DOM verbatim. Useful for data-* or aria-*
* attributes where it's impossible to enumerate all of the possible
@@ -1462,39 +1609,34 @@ var DOMPropertyInjection = {
var DOMPropertyNames = domPropertyConfig.DOMPropertyNames || {};
var DOMMutationMethods = domPropertyConfig.DOMMutationMethods || {};
if (domPropertyConfig.isCustomAttribute) {
DOMProperty._isCustomAttributeFunctions.push(domPropertyConfig.isCustomAttribute);
}
for (var propName in Properties) {
- !!DOMProperty.properties.hasOwnProperty(propName) ? "development" !== 'production' ? invariant(false, '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 ' + 'injecting two configs that have conflicting property names.', propName) : invariant(false) : undefined;
+ !!DOMProperty.properties.hasOwnProperty(propName) ? "development" !== 'production' ? invariant(false, '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 injecting two configs that have conflicting property names.', propName) : _prodInvariant('48', propName) : void 0;
var lowerCased = propName.toLowerCase();
var propConfig = Properties[propName];
var propertyInfo = {
attributeName: lowerCased,
attributeNamespace: null,
propertyName: propName,
mutationMethod: null,
- mustUseAttribute: checkMask(propConfig, Injection.MUST_USE_ATTRIBUTE),
mustUseProperty: checkMask(propConfig, Injection.MUST_USE_PROPERTY),
- hasSideEffects: checkMask(propConfig, Injection.HAS_SIDE_EFFECTS),
hasBooleanValue: checkMask(propConfig, Injection.HAS_BOOLEAN_VALUE),
hasNumericValue: checkMask(propConfig, Injection.HAS_NUMERIC_VALUE),
hasPositiveNumericValue: checkMask(propConfig, Injection.HAS_POSITIVE_NUMERIC_VALUE),
hasOverloadedBooleanValue: checkMask(propConfig, Injection.HAS_OVERLOADED_BOOLEAN_VALUE)
};
-
- !(!propertyInfo.mustUseAttribute || !propertyInfo.mustUseProperty) ? "development" !== 'production' ? invariant(false, 'DOMProperty: Cannot require using both attribute and property: %s', propName) : invariant(false) : undefined;
- !(propertyInfo.mustUseProperty || !propertyInfo.hasSideEffects) ? "development" !== 'production' ? invariant(false, 'DOMProperty: Properties that have side effects must use property: %s', propName) : invariant(false) : undefined;
- !(propertyInfo.hasBooleanValue + propertyInfo.hasNumericValue + propertyInfo.hasOverloadedBooleanValue <= 1) ? "development" !== 'production' ? invariant(false, 'DOMProperty: Value can be one of boolean, overloaded boolean, or ' + 'numeric value, but not a combination: %s', propName) : invariant(false) : undefined;
+ !(propertyInfo.hasBooleanValue + propertyInfo.hasNumericValue + propertyInfo.hasOverloadedBooleanValue <= 1) ? "development" !== 'production' ? invariant(false, 'DOMProperty: Value can be one of boolean, overloaded boolean, or numeric value, but not a combination: %s', propName) : _prodInvariant('50', propName) : void 0;
if ("development" !== 'production') {
DOMProperty.getPossibleStandardName[lowerCased] = propName;
}
if (DOMAttributeNames.hasOwnProperty(propName)) {
var attributeName = DOMAttributeNames[propName];
propertyInfo.attributeName = attributeName;
@@ -1514,17 +1656,20 @@ var DOMPropertyInjection = {
if (DOMMutationMethods.hasOwnProperty(propName)) {
propertyInfo.mutationMethod = DOMMutationMethods[propName];
}
DOMProperty.properties[propName] = propertyInfo;
}
}
};
-var defaultValueCache = {};
+
+/* eslint-disable max-len */
+var 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 */
/**
* DOMProperty exports lookup objects that can be used like functions:
*
* > DOMProperty.isValid['id']
* true
* > DOMProperty.isValid['foobar']
* undefined
@@ -1532,40 +1677,36 @@ var defaultValueCache = {};
* Although this may be confusing, it performs better in general.
*
* @see http://jsperf.com/key-exists
* @see http://jsperf.com/key-missing
*/
var DOMProperty = {
ID_ATTRIBUTE_NAME: 'data-reactid',
+ ROOT_ATTRIBUTE_NAME: 'data-reactroot',
+
+ 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.
- * mustUseAttribute:
- * Whether the property must be accessed and mutated using `*Attribute()`.
- * (This includes anything that fails `<propName> in <element>`.)
* mustUseProperty:
* Whether the property must be accessed and mutated as an object property.
- * hasSideEffects:
- * Whether or not setting a value causes side effects such as triggering
- * resources to be loaded or text selection changes. If true, we read from
- * the DOM before updating to ensure that the value is only set if it has
- * changed.
* 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.
@@ -1597,113 +1738,65 @@ var DOMProperty = {
var isCustomAttributeFn = DOMProperty._isCustomAttributeFunctions[i];
if (isCustomAttributeFn(attributeName)) {
return true;
}
}
return false;
},
- /**
- * Returns the default property value for a DOM property (i.e., not an
- * attribute). Most default values are '' or false, but not all. Worse yet,
- * some (in particular, `type`) vary depending on the type of element.
- *
- * TODO: Is it better to grab all the possible properties when creating an
- * element to avoid having to create the same element twice?
- */
- getDefaultValueForProperty: function (nodeName, prop) {
- var nodeDefaults = defaultValueCache[nodeName];
- var testElement;
- if (!nodeDefaults) {
- defaultValueCache[nodeName] = nodeDefaults = {};
- }
- if (!(prop in nodeDefaults)) {
- testElement = document.createElementNS('http://www.w3.org/1999/xhtml', nodeName);
- nodeDefaults[prop] = testElement[prop];
- }
- return nodeDefaults[prop];
- },
-
injection: DOMPropertyInjection
};
module.exports = DOMProperty;
-},{"161":161}],11:[function(_dereq_,module,exports){
-/**
- * Copyright 2013-2015, Facebook, Inc.
+},{"153":153,"178":178}],11:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule DOMPropertyOperations
- * @typechecks static-only
*/
'use strict';
var DOMProperty = _dereq_(10);
-var ReactPerf = _dereq_(78);
-
-var quoteAttributeValueForBrowser = _dereq_(136);
-var warning = _dereq_(173);
-
-// Simplified subset
-var VALID_ATTRIBUTE_NAME_REGEX = /^[a-zA-Z_][\w\.\-]*$/;
+var ReactDOMComponentTree = _dereq_(46);
+var ReactInstrumentation = _dereq_(78);
+
+var quoteAttributeValueForBrowser = _dereq_(152);
+var warning = _dereq_(187);
+
+var VALID_ATTRIBUTE_NAME_REGEX = new RegExp('^[' + DOMProperty.ATTRIBUTE_NAME_START_CHAR + '][' + DOMProperty.ATTRIBUTE_NAME_CHAR + ']*$');
var illegalAttributeNameCache = {};
var validatedAttributeNameCache = {};
function isAttributeNameSafe(attributeName) {
if (validatedAttributeNameCache.hasOwnProperty(attributeName)) {
return true;
}
if (illegalAttributeNameCache.hasOwnProperty(attributeName)) {
return false;
}
if (VALID_ATTRIBUTE_NAME_REGEX.test(attributeName)) {
validatedAttributeNameCache[attributeName] = true;
return true;
}
illegalAttributeNameCache[attributeName] = true;
- "development" !== 'production' ? warning(false, 'Invalid attribute name: `%s`', attributeName) : undefined;
+ "development" !== 'production' ? warning(false, 'Invalid attribute name: `%s`', attributeName) : void 0;
return false;
}
function shouldIgnoreValue(propertyInfo, value) {
return value == null || propertyInfo.hasBooleanValue && !value || propertyInfo.hasNumericValue && isNaN(value) || propertyInfo.hasPositiveNumericValue && value < 1 || propertyInfo.hasOverloadedBooleanValue && value === false;
}
-if ("development" !== 'production') {
- var reactProps = {
- children: true,
- dangerouslySetInnerHTML: true,
- key: true,
- ref: true
- };
- var warnedProperties = {};
-
- var warnUnknownProperty = function (name) {
- if (reactProps.hasOwnProperty(name) && reactProps[name] || warnedProperties.hasOwnProperty(name) && warnedProperties[name]) {
- return;
- }
-
- warnedProperties[name] = true;
- var lowerCasedName = name.toLowerCase();
-
- // data-* attributes should be lowercase; suggest the lowercase version
- var standardName = DOMProperty.isCustomAttribute(lowerCasedName) ? lowerCasedName : DOMProperty.getPossibleStandardName.hasOwnProperty(lowerCasedName) ? DOMProperty.getPossibleStandardName[lowerCasedName] : null;
-
- // For now, only warn when we have a suggested correction. This prevents
- // logging too much when using transferPropsTo.
- "development" !== 'production' ? warning(standardName == null, 'Unknown DOM property %s. Did you mean %s?', name, standardName) : undefined;
- };
-}
-
/**
* Operations for dealing with DOM properties.
*/
var DOMPropertyOperations = {
/**
* Creates markup for the ID property.
*
@@ -1713,16 +1806,24 @@ var DOMPropertyOperations = {
createMarkupForID: function (id) {
return DOMProperty.ID_ATTRIBUTE_NAME + '=' + quoteAttributeValueForBrowser(id);
},
setAttributeForID: function (node, id) {
node.setAttribute(DOMProperty.ID_ATTRIBUTE_NAME, id);
},
+ createMarkupForRoot: function () {
+ return DOMProperty.ROOT_ATTRIBUTE_NAME + '=""';
+ },
+
+ setAttributeForRoot: function (node) {
+ node.setAttribute(DOMProperty.ROOT_ATTRIBUTE_NAME, '');
+ },
+
/**
* 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) {
@@ -1736,18 +1837,16 @@ var DOMPropertyOperations = {
return attributeName + '=""';
}
return attributeName + '=' + quoteAttributeValueForBrowser(value);
} else if (DOMProperty.isCustomAttribute(name)) {
if (value == null) {
return '';
}
return name + '=' + quoteAttributeValueForBrowser(value);
- } else if ("development" !== 'production') {
- warnUnknownProperty(name);
}
return null;
},
/**
* Creates markup for a custom property.
*
* @param {string} name
@@ -1771,415 +1870,370 @@ var DOMPropertyOperations = {
setValueForProperty: function (node, name, value) {
var propertyInfo = DOMProperty.properties.hasOwnProperty(name) ? DOMProperty.properties[name] : null;
if (propertyInfo) {
var mutationMethod = propertyInfo.mutationMethod;
if (mutationMethod) {
mutationMethod(node, value);
} else if (shouldIgnoreValue(propertyInfo, value)) {
this.deleteValueForProperty(node, name);
- } else if (propertyInfo.mustUseAttribute) {
+ return;
+ } else if (propertyInfo.mustUseProperty) {
+ // Contrary to `setAttribute`, object properties are properly
+ // `toString`ed by IE8/9.
+ node[propertyInfo.propertyName] = value;
+ } else {
var attributeName = propertyInfo.attributeName;
var namespace = propertyInfo.attributeNamespace;
// `setAttribute` with objects becomes only `[object]` in IE8/9,
// ('' + value) makes it output the correct toString()-value.
if (namespace) {
node.setAttributeNS(namespace, attributeName, '' + value);
} else if (propertyInfo.hasBooleanValue || propertyInfo.hasOverloadedBooleanValue && value === true) {
node.setAttribute(attributeName, '');
} else {
node.setAttribute(attributeName, '' + value);
}
- } else {
- var propName = propertyInfo.propertyName;
- // Must explicitly cast values for HAS_SIDE_EFFECTS-properties to the
- // property type before comparing; only `value` does and is string.
- if (!propertyInfo.hasSideEffects || '' + node[propName] !== '' + value) {
- // Contrary to `setAttribute`, object properties are properly
- // `toString`ed by IE8/9.
- node[propName] = value;
- }
}
} else if (DOMProperty.isCustomAttribute(name)) {
DOMPropertyOperations.setValueForAttribute(node, name, value);
- } else if ("development" !== 'production') {
- warnUnknownProperty(name);
+ return;
+ }
+
+ if ("development" !== 'production') {
+ var payload = {};
+ payload[name] = value;
+ ReactInstrumentation.debugTool.onHostOperation(ReactDOMComponentTree.getInstanceFromNode(node)._debugID, 'update attribute', payload);
}
},
setValueForAttribute: function (node, name, value) {
if (!isAttributeNameSafe(name)) {
return;
}
if (value == null) {
node.removeAttribute(name);
} else {
node.setAttribute(name, '' + value);
}
+
+ if ("development" !== 'production') {
+ var payload = {};
+ payload[name] = value;
+ ReactInstrumentation.debugTool.onHostOperation(ReactDOMComponentTree.getInstanceFromNode(node)._debugID, 'update attribute', payload);
+ }
+ },
+
+ /**
+ * Deletes an attributes from a node.
+ *
+ * @param {DOMElement} node
+ * @param {string} name
+ */
+ deleteValueForAttribute: function (node, name) {
+ node.removeAttribute(name);
+ if ("development" !== 'production') {
+ ReactInstrumentation.debugTool.onHostOperation(ReactDOMComponentTree.getInstanceFromNode(node)._debugID, 'remove attribute', name);
+ }
},
/**
* Deletes the value for a property on a node.
*
* @param {DOMElement} node
* @param {string} name
*/
deleteValueForProperty: function (node, name) {
var propertyInfo = DOMProperty.properties.hasOwnProperty(name) ? DOMProperty.properties[name] : null;
if (propertyInfo) {
var mutationMethod = propertyInfo.mutationMethod;
if (mutationMethod) {
mutationMethod(node, undefined);
- } else if (propertyInfo.mustUseAttribute) {
- node.removeAttribute(propertyInfo.attributeName);
- } else {
+ } else if (propertyInfo.mustUseProperty) {
var propName = propertyInfo.propertyName;
- var defaultValue = DOMProperty.getDefaultValueForProperty(node.nodeName, propName);
- if (!propertyInfo.hasSideEffects || '' + node[propName] !== defaultValue) {
- node[propName] = defaultValue;
- }
+ if (propertyInfo.hasBooleanValue) {
+ node[propName] = false;
+ } else {
+ node[propName] = '';
+ }
+ } else {
+ node.removeAttribute(propertyInfo.attributeName);
}
} else if (DOMProperty.isCustomAttribute(name)) {
node.removeAttribute(name);
- } else if ("development" !== 'production') {
- warnUnknownProperty(name);
- }
- }
-
-};
-
-ReactPerf.measureMethods(DOMPropertyOperations, 'DOMPropertyOperations', {
- setValueForProperty: 'setValueForProperty',
- setValueForAttribute: 'setValueForAttribute',
- deleteValueForProperty: 'deleteValueForProperty'
-});
+ }
+
+ if ("development" !== 'production') {
+ ReactInstrumentation.debugTool.onHostOperation(ReactDOMComponentTree.getInstanceFromNode(node)._debugID, 'remove attribute', name);
+ }
+ }
+
+};
module.exports = DOMPropertyOperations;
-},{"10":10,"136":136,"173":173,"78":78}],12:[function(_dereq_,module,exports){
-/**
- * Copyright 2013-2015, Facebook, Inc.
+},{"10":10,"152":152,"187":187,"46":46,"78":78}],12:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule Danger
- * @typechecks static-only
- */
-
-'use strict';
-
-var ExecutionEnvironment = _dereq_(147);
-
-var createNodesFromMarkup = _dereq_(152);
-var emptyFunction = _dereq_(153);
-var getMarkupWrap = _dereq_(157);
-var invariant = _dereq_(161);
-
-var OPEN_TAG_NAME_EXP = /^(<[^ \/>]+)/;
-var RESULT_INDEX_ATTR = 'data-danger-index';
-
-/**
- * Extracts the `nodeName` from a string of markup.
- *
- * NOTE: Extracting the `nodeName` does not require a regular expression match
- * because we make assumptions about React-generated markup (i.e. there are no
- * spaces surrounding the opening tag and there is at least one attribute).
- *
- * @param {string} markup String of markup.
- * @return {string} Node name of the supplied markup.
- * @see http://jsperf.com/extract-nodename
- */
-function getNodeName(markup) {
- return markup.substring(1, markup.indexOf(' '));
-}
+ */
+
+'use strict';
+
+var _prodInvariant = _dereq_(153);
+
+var DOMLazyTree = _dereq_(8);
+var ExecutionEnvironment = _dereq_(164);
+
+var createNodesFromMarkup = _dereq_(169);
+var emptyFunction = _dereq_(170);
+var invariant = _dereq_(178);
var Danger = {
/**
- * Renders markup into an array of nodes. The markup is expected to render
- * into a list of root nodes. Also, the length of `resultList` and
- * `markupList` should be the same.
- *
- * @param {array<string>} markupList List of markup strings to render.
- * @return {array<DOMElement>} List of rendered nodes.
- * @internal
- */
- dangerouslyRenderMarkup: function (markupList) {
- !ExecutionEnvironment.canUseDOM ? "development" !== 'production' ? invariant(false, 'dangerouslyRenderMarkup(...): Cannot render markup in a worker ' + 'thread. Make sure `window` and `document` are available globally ' + 'before requiring React when unit testing or use ' + 'ReactDOMServer.renderToString for server rendering.') : invariant(false) : undefined;
- var nodeName;
- var markupByNodeName = {};
- // Group markup by `nodeName` if a wrap is necessary, else by '*'.
- for (var i = 0; i < markupList.length; i++) {
- !markupList[i] ? "development" !== 'production' ? invariant(false, 'dangerouslyRenderMarkup(...): Missing markup.') : invariant(false) : undefined;
- nodeName = getNodeName(markupList[i]);
- nodeName = getMarkupWrap(nodeName) ? nodeName : '*';
- markupByNodeName[nodeName] = markupByNodeName[nodeName] || [];
- markupByNodeName[nodeName][i] = markupList[i];
- }
- var resultList = [];
- var resultListAssignmentCount = 0;
- for (nodeName in markupByNodeName) {
- if (!markupByNodeName.hasOwnProperty(nodeName)) {
- continue;
- }
- var markupListByNodeName = markupByNodeName[nodeName];
-
- // This for-in loop skips the holes of the sparse array. The order of
- // iteration should follow the order of assignment, which happens to match
- // numerical index order, but we don't rely on that.
- var resultIndex;
- for (resultIndex in markupListByNodeName) {
- if (markupListByNodeName.hasOwnProperty(resultIndex)) {
- var markup = markupListByNodeName[resultIndex];
-
- // Push the requested markup with an additional RESULT_INDEX_ATTR
- // attribute. If the markup does not start with a < character, it
- // will be discarded below (with an appropriate console.error).
- markupListByNodeName[resultIndex] = markup.replace(OPEN_TAG_NAME_EXP,
- // This index will be parsed back out below.
- '$1 ' + RESULT_INDEX_ATTR + '="' + resultIndex + '" ');
- }
- }
-
- // Render each group of markup with similar wrapping `nodeName`.
- var renderNodes = createNodesFromMarkup(markupListByNodeName.join(''), emptyFunction // Do nothing special with <script> tags.
- );
-
- for (var j = 0; j < renderNodes.length; ++j) {
- var renderNode = renderNodes[j];
- if (renderNode.hasAttribute && renderNode.hasAttribute(RESULT_INDEX_ATTR)) {
-
- resultIndex = +renderNode.getAttribute(RESULT_INDEX_ATTR);
- renderNode.removeAttribute(RESULT_INDEX_ATTR);
-
- !!resultList.hasOwnProperty(resultIndex) ? "development" !== 'production' ? invariant(false, 'Danger: Assigning to an already-occupied result index.') : invariant(false) : undefined;
-
- resultList[resultIndex] = renderNode;
-
- // This should match resultList.length and markupList.length when
- // we're done.
- resultListAssignmentCount += 1;
- } else if ("development" !== 'production') {
- console.error('Danger: Discarding unexpected node:', renderNode);
- }
- }
- }
-
- // Although resultList was populated out of order, it should now be a dense
- // array.
- !(resultListAssignmentCount === resultList.length) ? "development" !== 'production' ? invariant(false, 'Danger: Did not assign to every index of resultList.') : invariant(false) : undefined;
-
- !(resultList.length === markupList.length) ? "development" !== 'production' ? invariant(false, 'Danger: Expected markup to render %s nodes, but rendered %s.', markupList.length, resultList.length) : invariant(false) : undefined;
-
- return resultList;
- },
-
- /**
* Replaces a node with a string of markup at its current position within its
* parent. The markup must render into a single root node.
*
* @param {DOMElement} oldChild Child node to replace.
* @param {string} markup Markup to render in place of the child node.
* @internal
*/
dangerouslyReplaceNodeWithMarkup: function (oldChild, markup) {
- !ExecutionEnvironment.canUseDOM ? "development" !== 'production' ? invariant(false, 'dangerouslyReplaceNodeWithMarkup(...): Cannot render markup in a ' + 'worker thread. Make sure `window` and `document` are available ' + 'globally before requiring React when unit testing or use ' + 'ReactDOMServer.renderToString() for server rendering.') : invariant(false) : undefined;
- !markup ? "development" !== 'production' ? invariant(false, 'dangerouslyReplaceNodeWithMarkup(...): Missing markup.') : invariant(false) : undefined;
- !(oldChild.tagName.toLowerCase() !== 'html') ? "development" !== 'production' ? invariant(false, 'dangerouslyReplaceNodeWithMarkup(...): Cannot replace markup of the ' + '<html> node. This is because browser quirks make this unreliable ' + 'and/or slow. If you want to render to the root you must use ' + 'server rendering. See ReactDOMServer.renderToString().') : invariant(false) : undefined;
-
- var newChild;
+ !ExecutionEnvironment.canUseDOM ? "development" !== 'production' ? invariant(false, 'dangerouslyReplaceNodeWithMarkup(...): Cannot render markup in a worker thread. Make sure `window` and `document` are available globally before requiring React when unit testing or use ReactDOMServer.renderToString() for server rendering.') : _prodInvariant('56') : void 0;
+ !markup ? "development" !== 'production' ? invariant(false, 'dangerouslyReplaceNodeWithMarkup(...): Missing markup.') : _prodInvariant('57') : void 0;
+ !(oldChild.nodeName !== 'HTML') ? "development" !== 'production' ? invariant(false, 'dangerouslyReplaceNodeWithMarkup(...): Cannot replace markup of the <html> node. This is because browser quirks make this unreliable and/or slow. If you want to render to the root you must use server rendering. See ReactDOMServer.renderToString().') : _prodInvariant('58') : void 0;
+
if (typeof markup === 'string') {
- newChild = createNodesFromMarkup(markup, emptyFunction)[0];
- } else {
- newChild = markup;
- }
- oldChild.parentNode.replaceChild(newChild, oldChild);
+ var newChild = createNodesFromMarkup(markup, emptyFunction)[0];
+ oldChild.parentNode.replaceChild(newChild, oldChild);
+ } else {
+ DOMLazyTree.replaceChildWithTree(oldChild, markup);
+ }
}
};
module.exports = Danger;
-},{"147":147,"152":152,"153":153,"157":157,"161":161}],13:[function(_dereq_,module,exports){
-/**
- * Copyright 2013-2015, Facebook, Inc.
+},{"153":153,"164":164,"169":169,"170":170,"178":178,"8":8}],13:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule DefaultEventPluginOrder
*/
'use strict';
-var keyOf = _dereq_(166);
+var keyOf = _dereq_(182);
/**
* Module that is injectable into `EventPluginHub`, that specifies a
* deterministic ordering of `EventPlugin`s. A convenient way to reason about
* plugins, without having to package every one of them. This is better than
* having plugins be ordered in the same order that they are injected because
* that ordering would be influenced by the packaging order.
* `ResponderEventPlugin` must occur before `SimpleEventPlugin` so that
* preventing default on events is convenient in `SimpleEventPlugin` handlers.
*/
var DefaultEventPluginOrder = [keyOf({ ResponderEventPlugin: null }), keyOf({ SimpleEventPlugin: null }), keyOf({ TapEventPlugin: null }), keyOf({ EnterLeaveEventPlugin: null }), keyOf({ ChangeEventPlugin: null }), keyOf({ SelectEventPlugin: null }), keyOf({ BeforeInputEventPlugin: null })];
module.exports = DefaultEventPluginOrder;
-},{"166":166}],14:[function(_dereq_,module,exports){
-/**
- * Copyright 2013-2015, Facebook, Inc.
+},{"182":182}],14:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-present, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
+ * @providesModule DisabledInputUtils
+ */
+
+'use strict';
+
+var disableableMouseListenerNames = {
+ onClick: true,
+ onDoubleClick: true,
+ onMouseDown: true,
+ onMouseMove: true,
+ onMouseUp: true,
+
+ onClickCapture: true,
+ onDoubleClickCapture: true,
+ onMouseDownCapture: true,
+ onMouseMoveCapture: true,
+ onMouseUpCapture: true
+};
+
+/**
+ * Implements a host component that does not receive mouse events
+ * when `disabled` is set.
+ */
+var DisabledInputUtils = {
+ getHostProps: function (inst, props) {
+ if (!props.disabled) {
+ return props;
+ }
+
+ // Copy the props, except the mouse listeners
+ var hostProps = {};
+ for (var key in props) {
+ if (!disableableMouseListenerNames[key] && props.hasOwnProperty(key)) {
+ hostProps[key] = props[key];
+ }
+ }
+
+ return hostProps;
+ }
+};
+
+module.exports = DisabledInputUtils;
+},{}],15:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule EnterLeaveEventPlugin
- * @typechecks static-only
- */
-
-'use strict';
-
-var EventConstants = _dereq_(15);
-var EventPropagators = _dereq_(19);
-var SyntheticMouseEvent = _dereq_(109);
-
-var ReactMount = _dereq_(72);
-var keyOf = _dereq_(166);
+ */
+
+'use strict';
+
+var EventConstants = _dereq_(16);
+var EventPropagators = _dereq_(20);
+var ReactDOMComponentTree = _dereq_(46);
+var SyntheticMouseEvent = _dereq_(122);
+
+var keyOf = _dereq_(182);
var topLevelTypes = EventConstants.topLevelTypes;
-var getFirstReactDOM = ReactMount.getFirstReactDOM;
var eventTypes = {
mouseEnter: {
registrationName: keyOf({ onMouseEnter: null }),
dependencies: [topLevelTypes.topMouseOut, topLevelTypes.topMouseOver]
},
mouseLeave: {
registrationName: keyOf({ onMouseLeave: null }),
dependencies: [topLevelTypes.topMouseOut, topLevelTypes.topMouseOver]
}
};
-var extractedEvents = [null, null];
-
var EnterLeaveEventPlugin = {
eventTypes: eventTypes,
/**
* For almost every interaction we care about, there will be both a top-level
* `mouseover` and `mouseout` event that occurs. Only use `mouseout` so that
* we do not extract duplicate events. However, moving the mouse into the
* browser from outside will not fire a `mouseout` event. In this case, we use
* the `mouseover` top-level event.
- *
- * @param {string} topLevelType Record from `EventConstants`.
- * @param {DOMEventTarget} topLevelTarget The listening component root node.
- * @param {string} topLevelTargetID ID of `topLevelTarget`.
- * @param {object} nativeEvent Native browser event.
- * @return {*} An accumulation of synthetic events.
- * @see {EventPluginHub.extractEvents}
- */
- extractEvents: function (topLevelType, topLevelTarget, topLevelTargetID, nativeEvent, nativeEventTarget) {
+ */
+ extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) {
if (topLevelType === topLevelTypes.topMouseOver && (nativeEvent.relatedTarget || nativeEvent.fromElement)) {
return null;
}
if (topLevelType !== topLevelTypes.topMouseOut && topLevelType !== topLevelTypes.topMouseOver) {
// Must not be a mouse in or mouse out - ignoring.
return null;
}
var win;
- if (topLevelTarget.window === topLevelTarget) {
- // `topLevelTarget` is probably a window object.
- win = topLevelTarget;
+ if (nativeEventTarget.window === nativeEventTarget) {
+ // `nativeEventTarget` is probably a window object.
+ win = nativeEventTarget;
} else {
// TODO: Figure out why `ownerDocument` is sometimes undefined in IE8.
- var doc = topLevelTarget.ownerDocument;
+ var doc = nativeEventTarget.ownerDocument;
if (doc) {
win = doc.defaultView || doc.parentWindow;
} else {
win = window;
}
}
var from;
var to;
- var fromID = '';
- var toID = '';
if (topLevelType === topLevelTypes.topMouseOut) {
- from = topLevelTarget;
- fromID = topLevelTargetID;
- to = getFirstReactDOM(nativeEvent.relatedTarget || nativeEvent.toElement);
- if (to) {
- toID = ReactMount.getID(to);
- } else {
- to = win;
- }
- to = to || win;
- } else {
- from = win;
- to = topLevelTarget;
- toID = topLevelTargetID;
+ from = targetInst;
+ var related = nativeEvent.relatedTarget || nativeEvent.toElement;
+ to = related ? ReactDOMComponentTree.getClosestInstanceFromNode(related) : null;
+ } else {
+ // Moving to a node from outside the window.
+ from = null;
+ to = targetInst;
}
if (from === to) {
// Nothing pertains to our managed components.
return null;
}
- var leave = SyntheticMouseEvent.getPooled(eventTypes.mouseLeave, fromID, nativeEvent, nativeEventTarget);
+ var fromNode = from == null ? win : ReactDOMComponentTree.getNodeFromInstance(from);
+ var toNode = to == null ? win : ReactDOMComponentTree.getNodeFromInstance(to);
+
+ var leave = SyntheticMouseEvent.getPooled(eventTypes.mouseLeave, from, nativeEvent, nativeEventTarget);
leave.type = 'mouseleave';
- leave.target = from;
- leave.relatedTarget = to;
-
- var enter = SyntheticMouseEvent.getPooled(eventTypes.mouseEnter, toID, nativeEvent, nativeEventTarget);
+ leave.target = fromNode;
+ leave.relatedTarget = toNode;
+
+ var enter = SyntheticMouseEvent.getPooled(eventTypes.mouseEnter, to, nativeEvent, nativeEventTarget);
enter.type = 'mouseenter';
- enter.target = to;
- enter.relatedTarget = from;
-
- EventPropagators.accumulateEnterLeaveDispatches(leave, enter, fromID, toID);
-
- extractedEvents[0] = leave;
- extractedEvents[1] = enter;
-
- return extractedEvents;
+ enter.target = toNode;
+ enter.relatedTarget = fromNode;
+
+ EventPropagators.accumulateEnterLeaveDispatches(leave, enter, from, to);
+
+ return [leave, enter];
}
};
module.exports = EnterLeaveEventPlugin;
-},{"109":109,"15":15,"166":166,"19":19,"72":72}],15:[function(_dereq_,module,exports){
-/**
- * Copyright 2013-2015, Facebook, Inc.
+},{"122":122,"16":16,"182":182,"20":20,"46":46}],16:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule EventConstants
*/
'use strict';
-var keyMirror = _dereq_(165);
+var keyMirror = _dereq_(181);
var PropagationPhases = keyMirror({ bubbled: null, captured: null });
/**
* Types of raw signals from the browser caught at the top level.
*/
var topLevelTypes = keyMirror({
topAbort: null,
+ topAnimationEnd: null,
+ topAnimationIteration: null,
+ topAnimationStart: null,
topBlur: null,
topCanPlay: null,
topCanPlayThrough: null,
topChange: null,
topClick: null,
topCompositionEnd: null,
topCompositionStart: null,
topCompositionUpdate: null,
@@ -2197,16 +2251,17 @@ var topLevelTypes = keyMirror({
topDrop: null,
topDurationChange: null,
topEmptied: null,
topEncrypted: null,
topEnded: null,
topError: null,
topFocus: null,
topInput: null,
+ topInvalid: null,
topKeyDown: null,
topKeyPress: null,
topKeyUp: null,
topLoad: null,
topLoadedData: null,
topLoadedMetadata: null,
topLoadStart: null,
topMouseDown: null,
@@ -2229,49 +2284,51 @@ var topLevelTypes = keyMirror({
topSubmit: null,
topSuspend: null,
topTextInput: null,
topTimeUpdate: null,
topTouchCancel: null,
topTouchEnd: null,
topTouchMove: null,
topTouchStart: null,
+ topTransitionEnd: null,
topVolumeChange: null,
topWaiting: null,
topWheel: null
});
var EventConstants = {
topLevelTypes: topLevelTypes,
PropagationPhases: PropagationPhases
};
module.exports = EventConstants;
-},{"165":165}],16:[function(_dereq_,module,exports){
-/**
- * Copyright 2013-2015, Facebook, Inc.
+},{"181":181}],17:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule EventPluginHub
*/
'use strict';
-var EventPluginRegistry = _dereq_(17);
-var EventPluginUtils = _dereq_(18);
-var ReactErrorUtils = _dereq_(61);
-
-var accumulateInto = _dereq_(115);
-var forEachAccumulated = _dereq_(124);
-var invariant = _dereq_(161);
-var warning = _dereq_(173);
+var _prodInvariant = _dereq_(153);
+
+var EventPluginRegistry = _dereq_(18);
+var EventPluginUtils = _dereq_(19);
+var ReactErrorUtils = _dereq_(68);
+
+var accumulateInto = _dereq_(129);
+var forEachAccumulated = _dereq_(138);
+var invariant = _dereq_(178);
/**
* Internal store for event listeners
*/
var listenerBank = {};
/**
* Internal queue of events that have accumulated their dispatches and are
@@ -2297,26 +2354,21 @@ var executeDispatchesAndRelease = functi
};
var executeDispatchesAndReleaseSimulated = function (e) {
return executeDispatchesAndRelease(e, true);
};
var executeDispatchesAndReleaseTopLevel = function (e) {
return executeDispatchesAndRelease(e, false);
};
-/**
- * - `InstanceHandle`: [required] Module that performs logical traversals of DOM
- * hierarchy given ids of the logical DOM elements involved.
- */
-var InstanceHandle = null;
-
-function validateInstanceHandle() {
- var valid = InstanceHandle && InstanceHandle.traverseTwoPhase && InstanceHandle.traverseEnterLeave;
- "development" !== 'production' ? warning(valid, 'InstanceHandle not injected before use!') : undefined;
-}
+var getDictionaryKey = function (inst) {
+ // Prevents V8 performance issue:
+ // https://github.com/facebook/react/pull/7232
+ return '.' + inst._rootNodeID;
+};
/**
* 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
@@ -2338,143 +2390,119 @@ function validateInstanceHandle() {
var EventPluginHub = {
/**
* Methods for injecting dependencies.
*/
injection: {
/**
- * @param {object} InjectedMount
- * @public
- */
- injectMount: EventPluginUtils.injection.injectMount,
-
- /**
- * @param {object} InjectedInstanceHandle
- * @public
- */
- injectInstanceHandle: function (InjectedInstanceHandle) {
- InstanceHandle = InjectedInstanceHandle;
- if ("development" !== 'production') {
- validateInstanceHandle();
- }
- },
-
- getInstanceHandle: function () {
- if ("development" !== 'production') {
- validateInstanceHandle();
- }
- return InstanceHandle;
- },
-
- /**
* @param {array} InjectedEventPluginOrder
* @public
*/
injectEventPluginOrder: EventPluginRegistry.injectEventPluginOrder,
/**
* @param {object} injectedNamesToPlugins Map from names to plugin modules.
*/
injectEventPluginsByName: EventPluginRegistry.injectEventPluginsByName
},
- eventNameDispatchConfigs: EventPluginRegistry.eventNameDispatchConfigs,
-
- registrationNameModules: EventPluginRegistry.registrationNameModules,
-
- /**
- * Stores `listener` at `listenerBank[registrationName][id]`. Is idempotent.
- *
- * @param {string} id ID of the DOM element.
+ /**
+ * Stores `listener` at `listenerBank[registrationName][key]`. Is idempotent.
+ *
+ * @param {object} inst The instance, which is the source of events.
* @param {string} registrationName Name of listener (e.g. `onClick`).
- * @param {?function} listener The callback to store.
- */
- putListener: function (id, registrationName, listener) {
- !(typeof listener === 'function') ? "development" !== 'production' ? invariant(false, 'Expected %s listener to be a function, instead got type %s', registrationName, typeof listener) : invariant(false) : undefined;
-
+ * @param {function} listener The callback to store.
+ */
+ putListener: function (inst, registrationName, listener) {
+ !(typeof listener === 'function') ? "development" !== 'production' ? invariant(false, 'Expected %s listener to be a function, instead got type %s', registrationName, typeof listener) : _prodInvariant('94', registrationName, typeof listener) : void 0;
+
+ var key = getDictionaryKey(inst);
var bankForRegistrationName = listenerBank[registrationName] || (listenerBank[registrationName] = {});
- bankForRegistrationName[id] = listener;
+ bankForRegistrationName[key] = listener;
var PluginModule = EventPluginRegistry.registrationNameModules[registrationName];
if (PluginModule && PluginModule.didPutListener) {
- PluginModule.didPutListener(id, registrationName, listener);
- }
- },
-
- /**
- * @param {string} id ID of the DOM element.
+ PluginModule.didPutListener(inst, registrationName, listener);
+ }
+ },
+
+ /**
+ * @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.
*/
- getListener: function (id, registrationName) {
+ getListener: function (inst, registrationName) {
var bankForRegistrationName = listenerBank[registrationName];
- return bankForRegistrationName && bankForRegistrationName[id];
+ var key = getDictionaryKey(inst);
+ return bankForRegistrationName && bankForRegistrationName[key];
},
/**
* Deletes a listener from the registration bank.
*
- * @param {string} id ID of the DOM element.
+ * @param {object} inst The instance, which is the source of events.
* @param {string} registrationName Name of listener (e.g. `onClick`).
*/
- deleteListener: function (id, registrationName) {
+ deleteListener: function (inst, registrationName) {
var PluginModule = EventPluginRegistry.registrationNameModules[registrationName];
if (PluginModule && PluginModule.willDeleteListener) {
- PluginModule.willDeleteListener(id, registrationName);
+ PluginModule.willDeleteListener(inst, registrationName);
}
var bankForRegistrationName = listenerBank[registrationName];
// TODO: This should never be null -- when is it?
if (bankForRegistrationName) {
- delete bankForRegistrationName[id];
+ var key = getDictionaryKey(inst);
+ delete bankForRegistrationName[key];
}
},
/**
* Deletes all listeners for the DOM element with the supplied ID.
*
- * @param {string} id ID of the DOM element.
- */
- deleteAllListeners: function (id) {
+ * @param {object} inst The instance, which is the source of events.
+ */
+ deleteAllListeners: function (inst) {
+ var key = getDictionaryKey(inst);
for (var registrationName in listenerBank) {
- if (!listenerBank[registrationName][id]) {
+ if (!listenerBank.hasOwnProperty(registrationName)) {
+ continue;
+ }
+
+ if (!listenerBank[registrationName][key]) {
continue;
}
var PluginModule = EventPluginRegistry.registrationNameModules[registrationName];
if (PluginModule && PluginModule.willDeleteListener) {
- PluginModule.willDeleteListener(id, registrationName);
- }
-
- delete listenerBank[registrationName][id];
+ PluginModule.willDeleteListener(inst, registrationName);
+ }
+
+ delete listenerBank[registrationName][key];
}
},
/**
* Allows registered plugins an opportunity to extract events from top-level
* native browser events.
*
- * @param {string} topLevelType Record from `EventConstants`.
- * @param {DOMEventTarget} topLevelTarget The listening component root node.
- * @param {string} topLevelTargetID ID of `topLevelTarget`.
- * @param {object} nativeEvent Native browser event.
* @return {*} An accumulation of synthetic events.
* @internal
*/
- extractEvents: function (topLevelType, topLevelTarget, topLevelTargetID, nativeEvent, nativeEventTarget) {
+ 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, topLevelTarget, topLevelTargetID, nativeEvent, nativeEventTarget);
+ var extractedEvents = possiblePlugin.extractEvents(topLevelType, targetInst, nativeEvent, nativeEventTarget);
if (extractedEvents) {
events = accumulateInto(events, extractedEvents);
}
}
}
return events;
},
@@ -2501,17 +2529,17 @@ var EventPluginHub = {
// events get enqueued while processing.
var processingEventQueue = eventQueue;
eventQueue = null;
if (simulated) {
forEachAccumulated(processingEventQueue, executeDispatchesAndReleaseSimulated);
} else {
forEachAccumulated(processingEventQueue, executeDispatchesAndReleaseTopLevel);
}
- !!eventQueue ? "development" !== 'production' ? invariant(false, 'processEventQueue(): Additional events were enqueued while processing ' + 'an event queue. Support for this has not yet been implemented.') : invariant(false) : undefined;
+ !!eventQueue ? "development" !== 'production' ? invariant(false, 'processEventQueue(): Additional events were enqueued while processing an event queue. Support for this has not yet been implemented.') : _prodInvariant('95') : void 0;
// This would be a good time to rethrow if any of the event handlers threw.
ReactErrorUtils.rethrowCaughtError();
},
/**
* These are needed for tests only. Do not use!
*/
__purge: function () {
@@ -2520,32 +2548,33 @@ var EventPluginHub = {
__getListenerBank: function () {
return listenerBank;
}
};
module.exports = EventPluginHub;
-},{"115":115,"124":124,"161":161,"17":17,"173":173,"18":18,"61":61}],17:[function(_dereq_,module,exports){
-/**
- * Copyright 2013-2015, Facebook, Inc.
+},{"129":129,"138":138,"153":153,"178":178,"18":18,"19":19,"68":68}],18:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule EventPluginRegistry
- * @typechecks static-only
- */
-
-'use strict';
-
-var invariant = _dereq_(161);
+ */
+
+'use strict';
+
+var _prodInvariant = _dereq_(153);
+
+var invariant = _dereq_(178);
/**
* Injectable ordering of event plugins.
*/
var EventPluginOrder = null;
/**
* Injectable mapping from names to event plugin modules.
@@ -2560,39 +2589,39 @@ var namesToPlugins = {};
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) ? "development" !== 'production' ? invariant(false, 'EventPluginRegistry: Cannot inject event plugins that do not exist in ' + 'the plugin ordering, `%s`.', pluginName) : invariant(false) : undefined;
+ !(pluginIndex > -1) ? "development" !== 'production' ? invariant(false, 'EventPluginRegistry: Cannot inject event plugins that do not exist in the plugin ordering, `%s`.', pluginName) : _prodInvariant('96', pluginName) : void 0;
if (EventPluginRegistry.plugins[pluginIndex]) {
continue;
}
- !PluginModule.extractEvents ? "development" !== 'production' ? invariant(false, 'EventPluginRegistry: Event plugins must implement an `extractEvents` ' + 'method, but `%s` does not.', pluginName) : invariant(false) : undefined;
+ !PluginModule.extractEvents ? "development" !== 'production' ? invariant(false, 'EventPluginRegistry: Event plugins must implement an `extractEvents` method, but `%s` does not.', pluginName) : _prodInvariant('97', pluginName) : void 0;
EventPluginRegistry.plugins[pluginIndex] = PluginModule;
var publishedEvents = PluginModule.eventTypes;
for (var eventName in publishedEvents) {
- !publishEventForPlugin(publishedEvents[eventName], PluginModule, eventName) ? "development" !== 'production' ? invariant(false, 'EventPluginRegistry: Failed to publish event `%s` for plugin `%s`.', eventName, pluginName) : invariant(false) : undefined;
+ !publishEventForPlugin(publishedEvents[eventName], PluginModule, eventName) ? "development" !== 'production' ? invariant(false, 'EventPluginRegistry: Failed to publish event `%s` for plugin `%s`.', eventName, pluginName) : _prodInvariant('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) {
- !!EventPluginRegistry.eventNameDispatchConfigs.hasOwnProperty(eventName) ? "development" !== 'production' ? invariant(false, 'EventPluginHub: More than one plugin attempted to publish the same ' + 'event name, `%s`.', eventName) : invariant(false) : undefined;
+ !!EventPluginRegistry.eventNameDispatchConfigs.hasOwnProperty(eventName) ? "development" !== 'production' ? invariant(false, 'EventPluginHub: More than one plugin attempted to publish the same event name, `%s`.', eventName) : _prodInvariant('99', eventName) : void 0;
EventPluginRegistry.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);
@@ -2610,19 +2639,28 @@ function publishEventForPlugin(dispatchC
* Publishes a registration name that is used to identify dispatched events and
* can be used with `EventPluginHub.putListener` to register listeners.
*
* @param {string} registrationName Registration name to add.
* @param {object} PluginModule Plugin publishing the event.
* @private
*/
function publishRegistrationName(registrationName, PluginModule, eventName) {
- !!EventPluginRegistry.registrationNameModules[registrationName] ? "development" !== 'production' ? invariant(false, 'EventPluginHub: More than one plugin attempted to publish the same ' + 'registration name, `%s`.', registrationName) : invariant(false) : undefined;
+ !!EventPluginRegistry.registrationNameModules[registrationName] ? "development" !== 'production' ? invariant(false, 'EventPluginHub: More than one plugin attempted to publish the same registration name, `%s`.', registrationName) : _prodInvariant('100', registrationName) : void 0;
EventPluginRegistry.registrationNameModules[registrationName] = PluginModule;
EventPluginRegistry.registrationNameDependencies[registrationName] = PluginModule.eventTypes[eventName].dependencies;
+
+ if ("development" !== 'production') {
+ var lowerCasedName = registrationName.toLowerCase();
+ EventPluginRegistry.possibleRegistrationNames[lowerCasedName] = registrationName;
+
+ if (registrationName === 'onDoubleClick') {
+ EventPluginRegistry.possibleRegistrationNames.ondblclick = registrationName;
+ }
+ }
}
/**
* Registers plugins so that they can extract and dispatch events.
*
* @see {EventPluginHub}
*/
var EventPluginRegistry = {
@@ -2643,26 +2681,34 @@ var EventPluginRegistry = {
registrationNameModules: {},
/**
* Mapping from registration name to event name
*/
registrationNameDependencies: {},
/**
+ * Mapping from lowercase registration names to the properly cased version,
+ * used to warn in the case of missing event handlers. Available
+ * only in __DEV__.
+ * @type {Object}
+ */
+ possibleRegistrationNames: "development" !== 'production' ? {} : null,
+
+ /**
* 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 ? "development" !== 'production' ? invariant(false, 'EventPluginRegistry: Cannot inject event plugin ordering more than ' + 'once. You are likely trying to load more than one copy of React.') : invariant(false) : undefined;
+ !!EventPluginOrder ? "development" !== 'production' ? invariant(false, 'EventPluginRegistry: Cannot inject event plugin ordering more than once. You are likely trying to load more than one copy of React.') : _prodInvariant('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`.
@@ -2676,17 +2722,17 @@ var EventPluginRegistry = {
injectEventPluginsByName: function (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] ? "development" !== 'production' ? invariant(false, 'EventPluginRegistry: Cannot inject two different event plugins ' + 'using the same name, `%s`.', pluginName) : invariant(false) : undefined;
+ !!namesToPlugins[pluginName] ? "development" !== 'production' ? invariant(false, 'EventPluginRegistry: Cannot inject two different event plugins using the same name, `%s`.', pluginName) : _prodInvariant('102', pluginName) : void 0;
namesToPlugins[pluginName] = PluginModule;
isOrderingDirty = true;
}
}
if (isOrderingDirty) {
recomputePluginOrdering();
}
},
@@ -2736,55 +2782,73 @@ var EventPluginRegistry = {
}
var registrationNameModules = EventPluginRegistry.registrationNameModules;
for (var registrationName in registrationNameModules) {
if (registrationNameModules.hasOwnProperty(registrationName)) {
delete registrationNameModules[registrationName];
}
}
+
+ if ("development" !== 'production') {
+ var possibleRegistrationNames = EventPluginRegistry.possibleRegistrationNames;
+ for (var lowerCasedName in possibleRegistrationNames) {
+ if (possibleRegistrationNames.hasOwnProperty(lowerCasedName)) {
+ delete possibleRegistrationNames[lowerCasedName];
+ }
+ }
+ }
}
};
module.exports = EventPluginRegistry;
-},{"161":161}],18:[function(_dereq_,module,exports){
-/**
- * Copyright 2013-2015, Facebook, Inc.
+},{"153":153,"178":178}],19:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule EventPluginUtils
*/
'use strict';
-var EventConstants = _dereq_(15);
-var ReactErrorUtils = _dereq_(61);
-
-var invariant = _dereq_(161);
-var warning = _dereq_(173);
+var _prodInvariant = _dereq_(153);
+
+var EventConstants = _dereq_(16);
+var ReactErrorUtils = _dereq_(68);
+
+var invariant = _dereq_(178);
+var warning = _dereq_(187);
/**
* Injected dependencies:
*/
/**
- * - `Mount`: [required] Module that can convert between React dom IDs and
- * actual node references.
- */
+ * - `ComponentTree`: [required] Module that can convert between React instances
+ * and actual node references.
+ */
+var ComponentTree;
+var TreeTraversal;
var injection = {
- Mount: null,
- injectMount: function (InjectedMount) {
- injection.Mount = InjectedMount;
- if ("development" !== 'production') {
- "development" !== 'production' ? warning(InjectedMount && InjectedMount.getNode && InjectedMount.getID, 'EventPluginUtils.injection.injectMount(...): Injected Mount ' + 'module is missing getNode or getID.') : undefined;
+ injectComponentTree: function (Injected) {
+ ComponentTree = Injected;
+ if ("development" !== 'production') {
+ "development" !== 'production' ? warning(Injected && Injected.getNodeFromInstance && Injected.getInstanceFromNode, 'EventPluginUtils.injection.injectComponentTree(...): Injected ' + 'module is missing getNodeFromInstance or getInstanceFromNode.') : void 0;
+ }
+ },
+ injectTreeTraversal: function (Injected) {
+ TreeTraversal = Injected;
+ if ("development" !== 'production') {
+ "development" !== 'production' ? warning(Injected && Injected.isAncestor && Injected.getLowestCommonAncestor, 'EventPluginUtils.injection.injectTreeTraversal(...): Injected ' + 'module is missing isAncestor or getLowestCommonAncestor.') : void 0;
}
}
};
var topLevelTypes = EventConstants.topLevelTypes;
function isEndish(topLevelType) {
return topLevelType === topLevelTypes.topMouseUp || topLevelType === topLevelTypes.topTouchEnd || topLevelType === topLevelTypes.topTouchCancel;
@@ -2796,106 +2860,107 @@ function isMoveish(topLevelType) {
function isStartish(topLevelType) {
return topLevelType === topLevelTypes.topMouseDown || topLevelType === topLevelTypes.topTouchStart;
}
var validateEventDispatches;
if ("development" !== 'production') {
validateEventDispatches = function (event) {
var dispatchListeners = event._dispatchListeners;
- var dispatchIDs = event._dispatchIDs;
+ var dispatchInstances = event._dispatchInstances;
var listenersIsArr = Array.isArray(dispatchListeners);
- var idsIsArr = Array.isArray(dispatchIDs);
- var IDsLen = idsIsArr ? dispatchIDs.length : dispatchIDs ? 1 : 0;
var listenersLen = listenersIsArr ? dispatchListeners.length : dispatchListeners ? 1 : 0;
- "development" !== 'production' ? warning(idsIsArr === listenersIsArr && IDsLen === listenersLen, 'EventPluginUtils: Invalid `event`.') : undefined;
+ var instancesIsArr = Array.isArray(dispatchInstances);
+ var instancesLen = instancesIsArr ? dispatchInstances.length : dispatchInstances ? 1 : 0;
+
+ "development" !== 'production' ? warning(instancesIsArr === listenersIsArr && instancesLen === listenersLen, 'EventPluginUtils: Invalid `event`.') : void 0;
};
}
/**
* Dispatch the event to the listener.
* @param {SyntheticEvent} event SyntheticEvent to handle
* @param {boolean} simulated If the event is simulated (changes exn behavior)
* @param {function} listener Application-level callback
- * @param {string} domID DOM id to pass to the callback.
- */
-function executeDispatch(event, simulated, listener, domID) {
+ * @param {*} inst Internal component instance
+ */
+function executeDispatch(event, simulated, listener, inst) {
var type = event.type || 'unknown-event';
- event.currentTarget = injection.Mount.getNode(domID);
+ event.currentTarget = EventPluginUtils.getNodeFromInstance(inst);
if (simulated) {
- ReactErrorUtils.invokeGuardedCallbackWithCatch(type, listener, event, domID);
- } else {
- ReactErrorUtils.invokeGuardedCallback(type, listener, event, domID);
+ ReactErrorUtils.invokeGuardedCallbackWithCatch(type, listener, event);
+ } else {
+ ReactErrorUtils.invokeGuardedCallback(type, listener, event);
}
event.currentTarget = null;
}
/**
* Standard/simple iteration through an event's collected dispatches.
*/
function executeDispatchesInOrder(event, simulated) {
var dispatchListeners = event._dispatchListeners;
- var dispatchIDs = event._dispatchIDs;
+ var dispatchInstances = event._dispatchInstances;
if ("development" !== 'production') {
validateEventDispatches(event);
}
if (Array.isArray(dispatchListeners)) {
for (var i = 0; i < dispatchListeners.length; i++) {
if (event.isPropagationStopped()) {
break;
}
- // Listeners and IDs are two parallel arrays that are always in sync.
- executeDispatch(event, simulated, dispatchListeners[i], dispatchIDs[i]);
+ // Listeners and Instances are two parallel arrays that are always in sync.
+ executeDispatch(event, simulated, dispatchListeners[i], dispatchInstances[i]);
}
} else if (dispatchListeners) {
- executeDispatch(event, simulated, dispatchListeners, dispatchIDs);
+ executeDispatch(event, simulated, dispatchListeners, dispatchInstances);
}
event._dispatchListeners = null;
- event._dispatchIDs = null;
+ event._dispatchInstances = null;
}
/**
* Standard/simple iteration through an event's collected dispatches, but stops
* at the first dispatch execution returning true, and returns that id.
*
* @return {?string} id of the first dispatch execution who's listener returns
* true, or null if no listener returned true.
*/
function executeDispatchesInOrderStopAtTrueImpl(event) {
var dispatchListeners = event._dispatchListeners;
- var dispatchIDs = event._dispatchIDs;
+ var dispatchInstances = event._dispatchInstances;
if ("development" !== 'production') {
validateEventDispatches(event);
}
if (Array.isArray(dispatchListeners)) {
for (var i = 0; i < dispatchListeners.length; i++) {
if (event.isPropagationStopped()) {
break;
}
- // Listeners and IDs are two parallel arrays that are always in sync.
- if (dispatchListeners[i](event, dispatchIDs[i])) {
- return dispatchIDs[i];
+ // Listeners and Instances are two parallel arrays that are always in sync.
+ if (dispatchListeners[i](event, dispatchInstances[i])) {
+ return dispatchInstances[i];
}
}
} else if (dispatchListeners) {
- if (dispatchListeners(event, dispatchIDs)) {
- return dispatchIDs;
+ if (dispatchListeners(event, dispatchInstances)) {
+ return dispatchInstances;
}
}
return null;
}
/**
* @see executeDispatchesInOrderStopAtTrueImpl
*/
function executeDispatchesInOrderStopAtTrue(event) {
var ret = executeDispatchesInOrderStopAtTrueImpl(event);
- event._dispatchIDs = null;
+ event._dispatchInstances = null;
event._dispatchListeners = null;
return ret;
}
/**
* Execution of a "direct" dispatch - there must be at most one dispatch
* accumulated on the event or it is considered an error. It doesn't really make
* sense for an event with multiple dispatches (bubbled) to keep track of the
@@ -2904,21 +2969,23 @@ function executeDispatchesInOrderStopAtT
*
* @return {*} The return value of executing the single dispatch.
*/
function executeDirectDispatch(event) {
if ("development" !== 'production') {
validateEventDispatches(event);
}
var dispatchListener = event._dispatchListeners;
- var dispatchID = event._dispatchIDs;
- !!Array.isArray(dispatchListener) ? "development" !== 'production' ? invariant(false, 'executeDirectDispatch(...): Invalid `event`.') : invariant(false) : undefined;
- var res = dispatchListener ? dispatchListener(event, dispatchID) : null;
+ var dispatchInstance = event._dispatchInstances;
+ !!Array.isArray(dispatchListener) ? "development" !== 'production' ? invariant(false, 'executeDirectDispatch(...): Invalid `event`.') : _prodInvariant('103') : void 0;
+ event.currentTarget = dispatchListener ? EventPluginUtils.getNodeFromInstance(dispatchInstance) : null;
+ var res = dispatchListener ? dispatchListener(event) : null;
+ event.currentTarget = null;
event._dispatchListeners = null;
- event._dispatchIDs = null;
+ event._dispatchInstances = null;
return res;
}
/**
* @param {SyntheticEvent} event
* @return {boolean} True iff number of dispatches accumulated is greater than 0.
*/
function hasDispatches(event) {
@@ -2933,138 +3000,155 @@ var EventPluginUtils = {
isMoveish: isMoveish,
isStartish: isStartish,
executeDirectDispatch: executeDirectDispatch,
executeDispatchesInOrder: executeDispatchesInOrder,
executeDispatchesInOrderStopAtTrue: executeDispatchesInOrderStopAtTrue,
hasDispatches: hasDispatches,
- getNode: function (id) {
- return injection.Mount.getNode(id);
- },
- getID: function (node) {
- return injection.Mount.getID(node);
+ getInstanceFromNode: function (node) {
+ return ComponentTree.getInstanceFromNode(node);
+ },
+ getNodeFromInstance: function (node) {
+ return ComponentTree.getNodeFromInstance(node);
+ },
+ isAncestor: function (a, b) {
+ return TreeTraversal.isAncestor(a, b);
+ },
+ getLowestCommonAncestor: function (a, b) {
+ return TreeTraversal.getLowestCommonAncestor(a, b);
+ },
+ getParentInstance: function (inst) {
+ return TreeTraversal.getParentInstance(inst);
+ },
+ traverseTwoPhase: function (target, fn, arg) {
+ return TreeTraversal.traverseTwoPhase(target, fn, arg);
+ },
+ traverseEnterLeave: function (from, to, fn, argFrom, argTo) {
+ return TreeTraversal.traverseEnterLeave(from, to, fn, argFrom, argTo);
},
injection: injection
};
module.exports = EventPluginUtils;
-},{"15":15,"161":161,"173":173,"61":61}],19:[function(_dereq_,module,exports){
-/**
- * Copyright 2013-2015, Facebook, Inc.
+},{"153":153,"16":16,"178":178,"187":187,"68":68}],20:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule EventPropagators
*/
'use strict';
-var EventConstants = _dereq_(15);
-var EventPluginHub = _dereq_(16);
-
-var warning = _dereq_(173);
-
-var accumulateInto = _dereq_(115);
-var forEachAccumulated = _dereq_(124);
+var EventConstants = _dereq_(16);
+var EventPluginHub = _dereq_(17);
+var EventPluginUtils = _dereq_(19);
+
+var accumulateInto = _dereq_(129);
+var forEachAccumulated = _dereq_(138);
+var warning = _dereq_(187);
var PropagationPhases = EventConstants.PropagationPhases;
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.
*/
-function listenerAtPhase(id, event, propagationPhase) {
+function listenerAtPhase(inst, event, propagationPhase) {
var registrationName = event.dispatchConfig.phasedRegistrationNames[propagationPhase];
- return getListener(id, registrationName);
+ return getListener(inst, registrationName);
}
/**
* 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(domID, upwards, event) {
+function accumulateDirectionalDispatches(inst, upwards, event) {
if ("development" !== 'production') {
- "development" !== 'production' ? warning(domID, 'Dispatching id must not be null') : undefined;
+ "development" !== 'production' ? warning(inst, 'Dispatching inst must not be null') : void 0;
}
var phase = upwards ? PropagationPhases.bubbled : PropagationPhases.captured;
- var listener = listenerAtPhase(domID, event, phase);
+ var listener = listenerAtPhase(inst, event, phase);
if (listener) {
event._dispatchListeners = accumulateInto(event._dispatchListeners, listener);
- event._dispatchIDs = accumulateInto(event._dispatchIDs, domID);
+ 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) {
- EventPluginHub.injection.getInstanceHandle().traverseTwoPhase(event.dispatchMarker, accumulateDirectionalDispatches, event);
+ EventPluginUtils.traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event);
}
}
/**
* Same as `accumulateTwoPhaseDispatchesSingle`, but skips over the targetID.
*/
function accumulateTwoPhaseDispatchesSingleSkipTarget(event) {
if (event && event.dispatchConfig.phasedRegistrationNames) {
- EventPluginHub.injection.getInstanceHandle().traverseTwoPhaseSkipTarget(event.dispatchMarker, accumulateDirectionalDispatches, event);
+ var targetInst = event._targetInst;
+ var parentInst = targetInst ? EventPluginUtils.getParentInstance(targetInst) : null;
+ EventPluginUtils.traverseTwoPhase(parentInst, 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(id, ignoredDirection, event) {
+function accumulateDispatches(inst, ignoredDirection, event) {
if (event && event.dispatchConfig.registrationName) {
var registrationName = event.dispatchConfig.registrationName;
- var listener = getListener(id, registrationName);
+ var listener = getListener(inst, registrationName);
if (listener) {
event._dispatchListeners = accumulateInto(event._dispatchListeners, listener);
- event._dispatchIDs = accumulateInto(event._dispatchIDs, id);
+ 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.dispatchMarker, null, event);
+ accumulateDispatches(event._targetInst, null, event);
}
}
function accumulateTwoPhaseDispatches(events) {
forEachAccumulated(events, accumulateTwoPhaseDispatchesSingle);
}
function accumulateTwoPhaseDispatchesSkipTarget(events) {
forEachAccumulated(events, accumulateTwoPhaseDispatchesSingleSkipTarget);
}
-function accumulateEnterLeaveDispatches(leave, enter, fromID, toID) {
- EventPluginHub.injection.getInstanceHandle().traverseEnterLeave(fromID, toID, accumulateDispatches, leave, enter);
+function accumulateEnterLeaveDispatches(leave, enter, from, to) {
+ EventPluginUtils.traverseEnterLeave(from, to, accumulateDispatches, leave, enter);
}
function accumulateDirectDispatches(events) {
forEachAccumulated(events, accumulateDirectDispatchesSingle);
}
/**
* A small set of propagation patterns, each of which will accept a small amount
@@ -3080,35 +3164,35 @@ function accumulateDirectDispatches(even
var EventPropagators = {
accumulateTwoPhaseDispatches: accumulateTwoPhaseDispatches,
accumulateTwoPhaseDispatchesSkipTarget: accumulateTwoPhaseDispatchesSkipTarget,
accumulateDirectDispatches: accumulateDirectDispatches,
accumulateEnterLeaveDispatches: accumulateEnterLeaveDispatches
};
module.exports = EventPropagators;
-},{"115":115,"124":124,"15":15,"16":16,"173":173}],20:[function(_dereq_,module,exports){
-/**
- * Copyright 2013-2015, Facebook, Inc.
+},{"129":129,"138":138,"16":16,"17":17,"187":187,"19":19}],21:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule FallbackCompositionState
- * @typechecks static-only
- */
-
-'use strict';
-
-var PooledClass = _dereq_(25);
-
-var assign = _dereq_(24);
-var getTextContentAccessor = _dereq_(131);
+ */
+
+'use strict';
+
+var _assign = _dereq_(188);
+
+var PooledClass = _dereq_(26);
+
+var getTextContentAccessor = _dereq_(146);
/**
* This helper class stores 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
@@ -3117,17 +3201,17 @@ var getTextContentAccessor = _dereq_(131
* @param {DOMEventTarget} root
*/
function FallbackCompositionState(root) {
this._root = root;
this._startText = this.getText();
this._fallbackText = null;
}
-assign(FallbackCompositionState.prototype, {
+_assign(FallbackCompositionState.prototype, {
destructor: function () {
this._root = null;
this._startText = null;
this._fallbackText = null;
},
/**
* Get current text of input.
@@ -3176,267 +3260,309 @@ assign(FallbackCompositionState.prototyp
this._fallbackText = endValue.slice(start, sliceTail);
return this._fallbackText;
}
});
PooledClass.addPoolingTo(FallbackCompositionState);
module.exports = FallbackCompositionState;
-},{"131":131,"24":24,"25":25}],21:[function(_dereq_,module,exports){
-/**
- * Copyright 2013-2015, Facebook, Inc.
+},{"146":146,"188":188,"26":26}],22:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule HTMLDOMPropertyConfig
*/
'use strict';
var DOMProperty = _dereq_(10);
-var ExecutionEnvironment = _dereq_(147);
-
-var MUST_USE_ATTRIBUTE = DOMProperty.injection.MUST_USE_ATTRIBUTE;
+
var MUST_USE_PROPERTY = DOMProperty.injection.MUST_USE_PROPERTY;
var HAS_BOOLEAN_VALUE = DOMProperty.injection.HAS_BOOLEAN_VALUE;
-var HAS_SIDE_EFFECTS = DOMProperty.injection.HAS_SIDE_EFFECTS;
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 hasSVG;
-if (ExecutionEnvironment.canUseDOM) {
- var implementation = document.implementation;
- hasSVG = implementation && implementation.hasFeature && implementation.hasFeature('http://www.w3.org/TR/SVG11/feature#BasicStructure', '1.1');
-}
-
var HTMLDOMPropertyConfig = {
- isCustomAttribute: RegExp.prototype.test.bind(/^(data|aria)-[a-z_][a-z\d_.\-]*$/),
+ isCustomAttribute: RegExp.prototype.test.bind(new RegExp('^(data|aria)-[' + DOMProperty.ATTRIBUTE_NAME_CHAR + ']*$')),
Properties: {
/**
* Standard Properties
*/
- accept: null,
- acceptCharset: null,
- accessKey: null,
- action: null,
- allowFullScreen: MUST_USE_ATTRIBUTE | HAS_BOOLEAN_VALUE,
- allowTransparency: MUST_USE_ATTRIBUTE,
- alt: null,
+ accept: 0,
+ acceptCharset: 0,
+ accessKey: 0,
+ action: 0,
+ allowFullScreen: HAS_BOOLEAN_VALUE,
+ allowTransparency: 0,
+ alt: 0,
+ // specifies target context for links with `preload` type
+ as: 0,
async: HAS_BOOLEAN_VALUE,
- autoComplete: null,
+ autoComplete: 0,
// autoFocus is polyfilled/normalized by AutoFocusUtils
// autoFocus: HAS_BOOLEAN_VALUE,
autoPlay: HAS_BOOLEAN_VALUE,
- capture: MUST_USE_ATTRIBUTE | HAS_BOOLEAN_VALUE,
- cellPadding: null,
- cellSpacing: null,
- charSet: MUST_USE_ATTRIBUTE,
- challenge: MUST_USE_ATTRIBUTE,
+ capture: HAS_BOOLEAN_VALUE,
+ cellPadding: 0,
+ cellSpacing: 0,
+ charSet: 0,
+ challenge: 0,
checked: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
- classID: MUST_USE_ATTRIBUTE,
- // To set className on SVG elements, it's necessary to use .setAttribute;
- // this works on HTML elements too in all browsers except IE8. Conveniently,
- // IE8 doesn't support SVG and so we can simply use the attribute in
- // browsers that support SVG and the property in browsers that don't,
- // regardless of whether the element is HTML or SVG.
- className: hasSVG ? MUST_USE_ATTRIBUTE : MUST_USE_PROPERTY,
- cols: MUST_USE_ATTRIBUTE | HAS_POSITIVE_NUMERIC_VALUE,
- colSpan: null,
- content: null,
- contentEditable: null,
- contextMenu: MUST_USE_ATTRIBUTE,
- controls: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
- coords: null,
- crossOrigin: null,
- data: null, // For `<object />` acts as `src`.
- dateTime: MUST_USE_ATTRIBUTE,
+ cite: 0,
+ classID: 0,
+ className: 0,
+ cols: HAS_POSITIVE_NUMERIC_VALUE,
+ colSpan: 0,
+ content: 0,
+ contentEditable: 0,
+ contextMenu: 0,
+ controls: HAS_BOOLEAN_VALUE,
+ coords: 0,
+ crossOrigin: 0,
+ data: 0, // For `<object />` acts as `src`.
+ dateTime: 0,
'default': HAS_BOOLEAN_VALUE,
defer: HAS_BOOLEAN_VALUE,
- dir: null,
- disabled: MUST_USE_ATTRIBUTE | HAS_BOOLEAN_VALUE,
+ dir: 0,
+ disabled: HAS_BOOLEAN_VALUE,
download: HAS_OVERLOADED_BOOLEAN_VALUE,
- draggable: null,
- encType: null,
- form: MUST_USE_ATTRIBUTE,
- formAction: MUST_USE_ATTRIBUTE,
- formEncType: MUST_USE_ATTRIBUTE,
- formMethod: MUST_USE_ATTRIBUTE,
+ draggable: 0,
+ encType: 0,
+ form: 0,
+ formAction: 0,
+ formEncType: 0,
+ formMethod: 0,
formNoValidate: HAS_BOOLEAN_VALUE,
- formTarget: MUST_USE_ATTRIBUTE,
- frameBorder: MUST_USE_ATTRIBUTE,
- headers: null,
- height: MUST_USE_ATTRIBUTE,
- hidden: MUST_USE_ATTRIBUTE | HAS_BOOLEAN_VALUE,
- high: null,
- href: null,
- hrefLang: null,
- htmlFor: null,
- httpEquiv: null,
- icon: null,
- id: MUST_USE_PROPERTY,
- inputMode: MUST_USE_ATTRIBUTE,
- integrity: null,
- is: MUST_USE_ATTRIBUTE,
- keyParams: MUST_USE_ATTRIBUTE,
- keyType: MUST_USE_ATTRIBUTE,
- kind: null,
- label: null,
- lang: null,
- list: MUST_USE_ATTRIBUTE,
- loop: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
- low: null,
- manifest: MUST_USE_ATTRIBUTE,
- marginHeight: null,
- marginWidth: null,
- max: null,
- maxLength: MUST_USE_ATTRIBUTE,
- media: MUST_USE_ATTRIBUTE,
- mediaGroup: null,
- method: null,
- min: null,
- minLength: MUST_USE_ATTRIBUTE,
+ formTarget: 0,
+ frameBorder: 0,
+ headers: 0,
+ height: 0,
+ hidden: HAS_BOOLEAN_VALUE,
+ high: 0,
+ href: 0,
+ hrefLang: 0,
+ htmlFor: 0,
+ httpEquiv: 0,
+ icon: 0,
+ id: 0,
+ inputMode: 0,
+ integrity: 0,
+ is: 0,
+ keyParams: 0,
+ keyType: 0,
+ kind: 0,
+ label: 0,
+ lang: 0,
+ list: 0,
+ loop: HAS_BOOLEAN_VALUE,
+ low: 0,
+ manifest: 0,
+ marginHeight: 0,
+ marginWidth: 0,
+ max: 0,
+ maxLength: 0,
+ media: 0,
+ mediaGroup: 0,
+ method: 0,
+ min: 0,
+ minLength: 0,
+ // Caution; `option.selected` is not updated if `select.multiple` is
+ // disabled with `removeAttribute`.
multiple: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
muted: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
- name: null,
- nonce: MUST_USE_ATTRIBUTE,
+ name: 0,
+ nonce: 0,
noValidate: HAS_BOOLEAN_VALUE,
open: HAS_BOOLEAN_VALUE,
- optimum: null,
- pattern: null,
- placeholder: null,
- poster: null,
- preload: null,
- radioGroup: null,
- readOnly: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
- rel: null,
+ optimum: 0,
+ pattern: 0,
+ placeholder: 0,
+ playsInline: HAS_BOOLEAN_VALUE,
+ poster: 0,
+ preload: 0,
+ profile: 0,
+ radioGroup: 0,
+ readOnly: HAS_BOOLEAN_VALUE,
+ referrerPolicy: 0,
+ rel: 0,
required: HAS_BOOLEAN_VALUE,
reversed: HAS_BOOLEAN_VALUE,
- role: MUST_USE_ATTRIBUTE,
- rows: MUST_USE_ATTRIBUTE | HAS_POSITIVE_NUMERIC_VALUE,
- rowSpan: null,
- sandbox: null,
- scope: null,
+ role: 0,
+ rows: HAS_POSITIVE_NUMERIC_VALUE,
+ rowSpan: HAS_NUMERIC_VALUE,
+ sandbox: 0,
+ scope: 0,
scoped: HAS_BOOLEAN_VALUE,
- scrolling: null,
- seamless: MUST_USE_ATTRIBUTE | HAS_BOOLEAN_VALUE,
+ scrolling: 0,
+ seamless: HAS_BOOLEAN_VALUE,
selected: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
- shape: null,
- size: MUST_USE_ATTRIBUTE | HAS_POSITIVE_NUMERIC_VALUE,
- sizes: MUST_USE_ATTRIBUTE,
+ shape: 0,
+ size: HAS_POSITIVE_NUMERIC_VALUE,
+ sizes: 0,
span: HAS_POSITIVE_NUMERIC_VALUE,
- spellCheck: null,
- src: null,
- srcDoc: MUST_USE_PROPERTY,
- srcLang: null,
- srcSet: MUST_USE_ATTRIBUTE,
+ spellCheck: 0,
+ src: 0,
+ srcDoc: 0,
+ srcLang: 0,
+ srcSet: 0,
start: HAS_NUMERIC_VALUE,
- step: null,
- style: null,
- summary: null,
- tabIndex: null,
- target: null,
- title: null,
- type: null,
- useMap: null,
- value: MUST_USE_PROPERTY | HAS_SIDE_EFFECTS,
- width: MUST_USE_ATTRIBUTE,
- wmode: MUST_USE_ATTRIBUTE,
- wrap: null,
+ step: 0,
+ style: 0,
+ summary: 0,
+ tabIndex: 0,
+ target: 0,
+ title: 0,
+ // Setting .type throws on non-<input> tags
+ type: 0,
+ useMap: 0,
+ value: 0,
+ width: 0,
+ wmode: 0,
+ wrap: 0,
/**
* RDFa Properties
*/
- about: MUST_USE_ATTRIBUTE,
- datatype: MUST_USE_ATTRIBUTE,
- inlist: MUST_USE_ATTRIBUTE,
- prefix: MUST_USE_ATTRIBUTE,
+ about: 0,
+ datatype: 0,
+ inlist: 0,
+ prefix: 0,
// property is also supported for OpenGraph in meta tags.
- property: MUST_USE_ATTRIBUTE,
- resource: MUST_USE_ATTRIBUTE,
- 'typeof': MUST_USE_ATTRIBUTE,
- vocab: MUST_USE_ATTRIBUTE,
+ property: 0,
+ resource: 0,
+ 'typeof': 0,
+ vocab: 0,
/**
* Non-standard Properties
*/
// autoCapitalize and autoCorrect are supported in Mobile Safari for
// keyboard hints.
- autoCapitalize: MUST_USE_ATTRIBUTE,
- autoCorrect: MUST_USE_ATTRIBUTE,
+ autoCapitalize: 0,
+ autoCorrect: 0,
// autoSave allows WebKit/Blink to persist values of input fields on page reloads
- autoSave: null,
+ autoSave: 0,
// color is for Safari mask-icon link
- color: null,
+ color: 0,
// itemProp, itemScope, itemType are for
// Microdata support. See http://schema.org/docs/gs.html
- itemProp: MUST_USE_ATTRIBUTE,
- itemScope: MUST_USE_ATTRIBUTE | HAS_BOOLEAN_VALUE,
- itemType: MUST_USE_ATTRIBUTE,
+ itemProp: 0,
+ itemScope: HAS_BOOLEAN_VALUE,
+ itemType: 0,
// itemID and itemRef are for Microdata support as well but
- // only specified in the the WHATWG spec document. See
+ // only specified in the WHATWG spec document. See
// https://html.spec.whatwg.org/multipage/microdata.html#microdata-dom-api
- itemID: MUST_USE_ATTRIBUTE,
- itemRef: MUST_USE_ATTRIBUTE,
+ itemID: 0,
+ itemRef: 0,
// results show looking glass icon and recent searches on input
// search fields in WebKit/Blink
- results: null,
+ results: 0,
// IE-only attribute that specifies security restrictions on an iframe
// as an alternative to the sandbox attribute on IE<10
- security: MUST_USE_ATTRIBUTE,
+ security: 0,
// IE-only attribute that controls focus behavior
- unselectable: MUST_USE_ATTRIBUTE
+ unselectable: 0
},
DOMAttributeNames: {
acceptCharset: 'accept-charset',
className: 'class',
htmlFor: 'for',
httpEquiv: 'http-equiv'
},
- DOMPropertyNames: {
- autoComplete: 'autocomplete',
- autoFocus: 'autofocus',
- autoPlay: 'autoplay',
- autoSave: 'autosave',
- // `encoding` is equivalent to `enctype`, IE8 lacks an `enctype` setter.
- // http://www.w3.org/TR/html5/forms.html#dom-fs-encoding
- encType: 'encoding',
- hrefLang: 'hreflang',
- radioGroup: 'radiogroup',
- spellCheck: 'spellcheck',
- srcDoc: 'srcdoc',
- srcSet: 'srcset'
- }
+ DOMPropertyNames: {}
};
module.exports = HTMLDOMPropertyConfig;
-},{"10":10,"147":147}],22:[function(_dereq_,module,exports){
-/**
- * Copyright 2013-2015, Facebook, Inc.
+},{"10":10}],23:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-present, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
+ * @providesModule KeyEscapeUtils
+ *
+ */
+
+'use strict';
+
+/**
+ * Escape and wrap key so it is safe to use as a reactid
+ *
+ * @param {string} key to be escaped.
+ * @return {string} the escaped key.
+ */
+
+function escape(key) {
+ var escapeRegex = /[=:]/g;
+ var escaperLookup = {
+ '=': '=0',
+ ':': '=2'
+ };
+ var escapedString = ('' + key).replace(escapeRegex, function (match) {
+ return escaperLookup[match];
+ });
+
+ return '$' + escapedString;
+}
+
+/**
+ * Unescape and unwrap key for human-readable display
+ *
+ * @param {string} key to unescape.
+ * @return {string} the unescaped key.
+ */
+function unescape(key) {
+ var unescapeRegex = /(=0|=2)/g;
+ var unescaperLookup = {
+ '=0': '=',
+ '=2': ':'
+ };
+ var keySubstring = key[0] === '.' && key[1] === '$' ? key.substring(2) : key.substring(1);
+
+ return ('' + keySubstring).replace(unescapeRegex, function (match) {
+ return unescaperLookup[match];
+ });
+}
+
+var KeyEscapeUtils = {
+ escape: escape,
+ unescape: unescape
+};
+
+module.exports = KeyEscapeUtils;
+},{}],24:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule LinkedStateMixin
- * @typechecks static-only
- */
-
-'use strict';
-
-var ReactLink = _dereq_(70);
-var ReactStateSetters = _dereq_(90);
+ */
+
+'use strict';
+
+var ReactLink = _dereq_(80);
+var ReactStateSetters = _dereq_(101);
/**
* A simple mixin around ReactLink.forState().
+ * See https://facebook.github.io/react/docs/two-way-binding-helpers.html
*/
var LinkedStateMixin = {
/**
* Create a ReactLink that's linked to part of this component's state. The
* ReactLink will have the current value of this.state[key] and will call
* setState() when a change is requested.
*
* @param {string} key state key to update. Note: you may want to use keyOf()
@@ -3444,58 +3570,60 @@ var LinkedStateMixin = {
* @return {ReactLink} ReactLink instance linking to the state.
*/
linkState: function (key) {
return new ReactLink(this.state[key], ReactStateSetters.createStateKeySetter(this, key));
}
};
module.exports = LinkedStateMixin;
-},{"70":70,"90":90}],23:[function(_dereq_,module,exports){
-/**
- * Copyright 2013-2015, Facebook, Inc.
+},{"101":101,"80":80}],25:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule LinkedValueUtils
- * @typechecks static-only
- */
-
-'use strict';
-
-var ReactPropTypes = _dereq_(82);
-var ReactPropTypeLocations = _dereq_(81);
-
-var invariant = _dereq_(161);
-var warning = _dereq_(173);
+ */
+
+'use strict';
+
+var _prodInvariant = _dereq_(153);
+
+var ReactPropTypes = _dereq_(91);
+var ReactPropTypeLocations = _dereq_(90);
+var ReactPropTypesSecret = _dereq_(92);
+
+var invariant = _dereq_(178);
+var warning = _dereq_(187);
var hasReadOnlyValue = {
'button': true,
'checkbox': true,
'image': true,
'hidden': true,
'radio': true,
'reset': true,
'submit': true
};
function _assertSingleLink(inputProps) {
- !(inputProps.checkedLink == null || inputProps.valueLink == null) ? "development" !== 'production' ? invariant(false, 'Cannot provide a checkedLink and a valueLink. If you want to use ' + 'checkedLink, you probably don\'t want to use valueLink and vice versa.') : invariant(false) : undefined;
+ !(inputProps.checkedLink == null || inputProps.valueLink == null) ? "development" !== 'production' ? invariant(false, 'Cannot provide a checkedLink and a valueLink. If you want to use checkedLink, you probably don\'t want to use valueLink and vice versa.') : _prodInvariant('87') : void 0;
}
function _assertValueLink(inputProps) {
_assertSingleLink(inputProps);
- !(inputProps.value == null && inputProps.onChange == null) ? "development" !== 'production' ? invariant(false, 'Cannot provide a valueLink and a value or onChange event. If you want ' + 'to use value or onChange, you probably don\'t want to use valueLink.') : invariant(false) : undefined;
+ !(inputProps.value == null && inputProps.onChange == null) ? "development" !== 'production' ? invariant(false, 'Cannot provide a valueLink and a value or onChange event. If you want to use value or onChange, you probably don\'t want to use valueLink.') : _prodInvariant('88') : void 0;
}
function _assertCheckedLink(inputProps) {
_assertSingleLink(inputProps);
- !(inputProps.checked == null && inputProps.onChange == null) ? "development" !== 'production' ? invariant(false, 'Cannot provide a checkedLink and a checked property or onChange event. ' + 'If you want to use checked or onChange, you probably don\'t want to ' + 'use checkedLink') : invariant(false) : undefined;
+ !(inputProps.checked == null && inputProps.onChange == null) ? "development" !== 'production' ? invariant(false, 'Cannot provide a checkedLink and a checked property or onChange event. If you want to use checked or onChange, you probably don\'t want to use checkedLink') : _prodInvariant('89') : void 0;
}
var propTypes = {
value: function (props, propName, componentName) {
if (!props[propName] || hasReadOnlyValue[props.type] || props.onChange || props.readOnly || props.disabled) {
return null;
}
return new Error('You provided a `value` prop to a form field without an ' + '`onChange` handler. This will render a read-only field. If ' + 'the field should be mutable use `defaultValue`. Otherwise, ' + 'set either `onChange` or `readOnly`.');
@@ -3523,25 +3651,25 @@ function getDeclarationErrorAddendum(own
/**
* Provide a linked `value` attribute for controlled forms. You should not use
* this outside of the ReactDOM controlled form components.
*/
var LinkedValueUtils = {
checkPropTypes: function (tagName, props, owner) {
for (var propName in propTypes) {
if (propTypes.hasOwnProperty(propName)) {
- var error = propTypes[propName](props, propName, tagName, ReactPropTypeLocations.prop);
+ var error = propTypes[propName](props, propName, tagName, ReactPropTypeLocations.prop, null, ReactPropTypesSecret);
}
if (error instanceof Error && !(error.message in loggedTypeFailures)) {
// Only monitor this failure once because there tends to be a lot of the
// same error.
loggedTypeFailures[error.message] = true;
var addendum = getDeclarationErrorAddendum(owner);
- "development" !== 'production' ? warning(false, 'Failed form propType: %s%s', error.message, addendum) : undefined;
+ "development" !== 'production' ? warning(false, 'Failed form propType: %s%s', error.message, addendum) : void 0;
}
}
},
/**
* @param {object} inputProps Props for form component
* @return {*} current value of the input either from value prop or link.
*/
@@ -3579,79 +3707,33 @@ var LinkedValueUtils = {
return inputProps.checkedLink.requestChange(event.target.checked);
} else if (inputProps.onChange) {
return inputProps.onChange.call(undefined, event);
}
}
};
module.exports = LinkedValueUtils;
-},{"161":161,"173":173,"81":81,"82":82}],24:[function(_dereq_,module,exports){
-/**
- * Copyright 2014-2015, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under the BSD-style license found in the
- * LICENSE file in the root directory of this source tree. An additional grant
- * of patent rights can be found in the PATENTS file in the same directory.
- *
- * @providesModule Object.assign
- */
-
-// https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.assign
-
-'use strict';
-
-function assign(target, sources) {
- if (target == null) {
- throw new TypeError('Object.assign target cannot be null or undefined');
- }
-
- var to = Object(target);
- var hasOwnProperty = Object.prototype.hasOwnProperty;
-
- for (var nextIndex = 1; nextIndex < arguments.length; nextIndex++) {
- var nextSource = arguments[nextIndex];
- if (nextSource == null) {
- continue;
- }
-
- var from = Object(nextSource);
-
- // We don't currently support accessors nor proxies. Therefore this
- // copy cannot throw. If we ever supported this then we must handle
- // exceptions and side-effects. We don't support symbols so they won't
- // be transferred.
-
- for (var key in from) {
- if (hasOwnProperty.call(from, key)) {
- to[key] = from[key];
- }
- }
- }
-
- return to;
-}
-
-module.exports = assign;
-},{}],25:[function(_dereq_,module,exports){
-/**
- * Copyright 2013-2015, Facebook, Inc.
+},{"153":153,"178":178,"187":187,"90":90,"91":91,"92":92}],26:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule PooledClass
*/
'use strict';
-var invariant = _dereq_(161);
+var _prodInvariant = _dereq_(153);
+
+var invariant = _dereq_(178);
/**
* Static poolers. Several custom versions for each potential number of
* arguments. A completely generic pooler is easy to implement, but would
* require accessing the `arguments` object. In each of these, `this` refers to
* the Class itself, not an instance. If any others are needed, simply add them
* here, or in their own files.
*/
@@ -3707,31 +3789,31 @@ var fiveArgumentPooler = function (a1, a
return instance;
} else {
return new Klass(a1, a2, a3, a4, a5);
}
};
var standardReleaser = function (instance) {
var Klass = this;
- !(instance instanceof Klass) ? "development" !== 'production' ? invariant(false, 'Trying to release an instance into a pool of a different type.') : invariant(false) : undefined;
+ !(instance instanceof Klass) ? "development" !== 'production' ? invariant(false, 'Trying to release an instance into a pool of a different type.') : _prodInvariant('25') : void 0;
instance.destructor();
if (Klass.instancePool.length < Klass.poolSize) {
Klass.instancePool.push(instance);
}
};
var DEFAULT_POOL_SIZE = 10;
var DEFAULT_POOLER = oneArgumentPooler;
/**
* Augments `CopyConstructor` to be a poolable class, augmenting only the class
* itself (statically) not adding any prototypical fields. Any CopyConstructor
* you give this may have a `poolSize` property, and will look for a
- * prototypical `destructor` on instances (optional).
+ * prototypical `destructor` on instances.
*
* @param {Function} CopyConstructor Constructor that can be used to reset.
* @param {Function} pooler Customizable pooler.
*/
var addPoolingTo = function (CopyConstructor, pooler) {
var NewKlass = CopyConstructor;
NewKlass.instancePool = [];
NewKlass.getPooled = pooler || DEFAULT_POOLER;
@@ -3747,118 +3829,129 @@ var PooledClass = {
oneArgumentPooler: oneArgumentPooler,
twoArgumentPooler: twoArgumentPooler,
threeArgumentPooler: threeArgumentPooler,
fourArgumentPooler: fourArgumentPooler,
fiveArgumentPooler: fiveArgumentPooler
};
module.exports = PooledClass;
-},{"161":161}],26:[function(_dereq_,module,exports){
-/**
- * Copyright 2013-2015, Facebook, Inc.
+},{"153":153,"178":178}],27:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule React
*/
'use strict';
-var ReactDOM = _dereq_(40);
-var ReactDOMServer = _dereq_(50);
-var ReactIsomorphic = _dereq_(69);
-
-var assign = _dereq_(24);
-var deprecated = _dereq_(120);
-
-// `version` will be added here by ReactIsomorphic.
-var React = {};
-
-assign(React, ReactIsomorphic);
-
-assign(React, {
- // ReactDOM
- findDOMNode: deprecated('findDOMNode', 'ReactDOM', 'react-dom', ReactDOM, ReactDOM.findDOMNode),
- render: deprecated('render', 'ReactDOM', 'react-dom', ReactDOM, ReactDOM.render),
- unmountComponentAtNode: deprecated('unmountComponentAtNode', 'ReactDOM', 'react-dom', ReactDOM, ReactDOM.unmountComponentAtNode),
-
- // ReactDOMServer
- renderToString: deprecated('renderToString', 'ReactDOMServer', 'react-dom/server', ReactDOMServer, ReactDOMServer.renderToString),
- renderToStaticMarkup: deprecated('renderToStaticMarkup', 'ReactDOMServer', 'react-dom/server', ReactDOMServer, ReactDOMServer.renderToStaticMarkup)
-});
-
-React.__SECRET_DOM_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = ReactDOM;
-React.__SECRET_DOM_SERVER_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = ReactDOMServer;
+var _assign = _dereq_(188);
+
+var ReactChildren = _dereq_(32);
+var ReactComponent = _dereq_(35);
+var ReactPureComponent = _dereq_(93);
+var ReactClass = _dereq_(34);
+var ReactDOMFactories = _dereq_(49);
+var ReactElement = _dereq_(65);
+var ReactPropTypes = _dereq_(91);
+var ReactVersion = _dereq_(108);
+
+var onlyChild = _dereq_(151);
+var warning = _dereq_(187);
+
+var createElement = ReactElement.createElement;
+var createFactory = ReactElement.createFactory;
+var cloneElement = ReactElement.cloneElement;
+
+if ("development" !== 'production') {
+ var ReactElementValidator = _dereq_(66);
+ createElement = ReactElementValidator.createElement;
+ createFactory = ReactElementValidator.createFactory;
+ cloneElement = ReactElementValidator.cloneElement;
+}
+
+var __spread = _assign;
+
+if ("development" !== 'production') {
+ var warned = false;
+ __spread = function () {
+ "development" !== 'production' ? warning(warned, 'React.__spread is deprecated and should not be used. Use ' + 'Object.assign directly or another helper function with similar ' + 'semantics. You may be seeing this warning due to your compiler. ' + 'See https://fb.me/react-spread-deprecation for more details.') : void 0;
+ warned = true;
+ return _assign.apply(null, arguments);
+ };
+}
+
+var React = {
+
+ // Modern
+
+ Children: {
+ map: ReactChildren.map,
+ forEach: ReactChildren.forEach,
+ count: ReactChildren.count,
+ toArray: ReactChildren.toArray,
+ only: onlyChild
+ },
+
+ Component: ReactComponent,
+ PureComponent: ReactPureComponent,
+
+ createElement: createElement,
+ cloneElement: cloneElement,
+ isValidElement: ReactElement.isValidElement,
+
+ // Classic
+
+ PropTypes: ReactPropTypes,
+ createClass: ReactClass.createClass,
+ createFactory: createFactory,
+ createMixin: function (mixin) {
+ // Currently a noop. Will be used to validate and trace mixins.
+ return mixin;
+ },
+
+ // This looks DOM specific but these are actually isomorphic helpers
+ // since they are just generating DOM strings.
+ DOM: ReactDOMFactories,
+
+ version: ReactVersion,
+
+ // Deprecated hook for JSX spread, don't use this for anything.
+ __spread: __spread
+};
module.exports = React;
-},{"120":120,"24":24,"40":40,"50":50,"69":69}],27:[function(_dereq_,module,exports){
-/**
- * Copyright 2013-2015, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under the BSD-style license found in the
- * LICENSE file in the root directory of this source tree. An additional grant
- * of patent rights can be found in the PATENTS file in the same directory.
- *
- * @providesModule ReactBrowserComponentMixin
- */
-
-'use strict';
-
-var ReactInstanceMap = _dereq_(68);
-
-var findDOMNode = _dereq_(122);
-var warning = _dereq_(173);
-
-var didWarnKey = '_getDOMNodeDidWarn';
-
-var ReactBrowserComponentMixin = {
- /**
- * Returns the DOM node rendered by this component.
- *
- * @return {DOMElement} The root node of this component.
- * @final
- * @protected
- */
- getDOMNode: function () {
- "development" !== 'production' ? warning(this.constructor[didWarnKey], '%s.getDOMNode(...) is deprecated. Please use ' + 'ReactDOM.findDOMNode(instance) instead.', ReactInstanceMap.get(this).getName() || this.tagName || 'Unknown') : undefined;
- this.constructor[didWarnKey] = true;
- return findDOMNode(this);
- }
-};
-
-module.exports = ReactBrowserComponentMixin;
-},{"122":122,"173":173,"68":68}],28:[function(_dereq_,module,exports){
-/**
- * Copyright 2013-2015, Facebook, Inc.
+},{"108":108,"151":151,"187":187,"188":188,"32":32,"34":34,"35":35,"49":49,"65":65,"66":66,"91":91,"93":93}],28:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactBrowserEventEmitter
- * @typechecks static-only
- */
-
-'use strict';
-
-var EventConstants = _dereq_(15);
-var EventPluginHub = _dereq_(16);
-var EventPluginRegistry = _dereq_(17);
-var ReactEventEmitterMixin = _dereq_(62);
-var ReactPerf = _dereq_(78);
-var ViewportMetrics = _dereq_(114);
-
-var assign = _dereq_(24);
-var isEventSupported = _dereq_(133);
+ */
+
+'use strict';
+
+var _assign = _dereq_(188);
+
+var EventConstants = _dereq_(16);
+var EventPluginRegistry = _dereq_(18);
+var ReactEventEmitterMixin = _dereq_(69);
+var ViewportMetrics = _dereq_(128);
+
+var getVendorPrefixedEventName = _dereq_(147);
+var isEventSupported = _dereq_(149);
/**
* Summary of `ReactBrowserEventEmitter` event handling:
*
* - Top-level delegation is used to trap most native browser events. This
* may only occur in the main thread and is the responsibility of
* ReactEventListener, which is injected and can therefore support pluggable
* event sources. This is the only work that occurs in the main thread.
@@ -3905,25 +3998,29 @@ var isEventSupported = _dereq_(133);
* |-------------| .
* | | .
* | | .
* +-------------+ .
* .
* React Core . General Purpose Event Plugin System
*/
+var hasEventPageXY;
var alreadyListeningTo = {};
var isMonitoringScrollValue = false;
var reactTopListenersCounter = 0;
// For events like 'submit' which don't consistently bubble (which we trap at a
// lower node than `document`), binding at `document` would cause duplicate
// events so we don't include them here
var topEventMapping = {
topAbort: 'abort',
+ topAnimationEnd: getVendorPrefixedEventName('animationend') || 'animationend',
+ topAnimationIteration: getVendorPrefixedEventName('animationiteration') || 'animationiteration',
+ topAnimationStart: getVendorPrefixedEventName('animationstart') || 'animationstart',
topBlur: 'blur',
topCanPlay: 'canplay',
topCanPlayThrough: 'canplaythrough',
topChange: 'change',
topClick: 'click',
topCompositionEnd: 'compositionend',
topCompositionStart: 'compositionstart',
topCompositionUpdate: 'compositionupdate',
@@ -3970,16 +4067,17 @@ var topEventMapping = {
topStalled: 'stalled',
topSuspend: 'suspend',
topTextInput: 'textInput',
topTimeUpdate: 'timeupdate',
topTouchCancel: 'touchcancel',
topTouchEnd: 'touchend',
topTouchMove: 'touchmove',
topTouchStart: 'touchstart',
+ topTransitionEnd: getVendorPrefixedEventName('transitionend') || 'transitionend',
topVolumeChange: 'volumechange',
topWaiting: 'waiting',
topWheel: 'wheel'
};
/**
* To ensure no conflicts with other potential React instances on the page
*/
@@ -3994,23 +4092,23 @@ function getListeningForDocument(mountAt
}
return alreadyListeningTo[mountAt[topListenersIDKey]];
}
/**
* `ReactBrowserEventEmitter` is used to attach top-level event listeners. For
* example:
*
- * ReactBrowserEventEmitter.putListener('myID', 'onClick', myFunction);
+ * EventPluginHub.putListener('myID', 'onClick', myFunction);
*
* This would allocate a "registration" of `('onClick', myFunction)` on 'myID'.
*
* @internal
*/
-var ReactBrowserEventEmitter = assign({}, ReactEventEmitterMixin, {
+var ReactBrowserEventEmitter = _assign({}, ReactEventEmitterMixin, {
/**
* Injectable event backend
*/
ReactEventListener: null,
injection: {
/**
@@ -4115,92 +4213,98 @@ var ReactBrowserEventEmitter = assign({}
return ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(topLevelType, handlerBaseName, handle);
},
trapCapturedEvent: function (topLevelType, handlerBaseName, handle) {
return ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent(topLevelType, handlerBaseName, handle);
},
/**
+ * Protect against document.createEvent() returning null
+ * Some popup blocker extensions appear to do this:
+ * https://github.com/facebook/react/issues/6887
+ */
+ supportsEventPageXY: function () {
+ if (!document.createEvent) {
+ return false;
+ }
+ var ev = document.createEvent('MouseEvent');
+ return ev != null && 'pageX' in ev;
+ },
+
+ /**
* Listens to window scroll and resize events. We cache scroll values so that
* application code can access them without triggering reflows.
*
+ * ViewportMetrics is only used by SyntheticMouse/TouchEvent and only when
+ * pageX/pageY isn't supported (legacy browsers).
+ *
* NOTE: Scroll events do not bubble.
*
* @see http://www.quirksmode.org/dom/events/scroll.html
*/
ensureScrollValueMonitoring: function () {
- if (!isMonitoringScrollValue) {
+ if (hasEventPageXY === undefined) {
+ hasEventPageXY = ReactBrowserEventEmitter.supportsEventPageXY();
+ }
+ if (!hasEventPageXY && !isMonitoringScrollValue) {
var refresh = ViewportMetrics.refreshScrollValues;
ReactBrowserEventEmitter.ReactEventListener.monitorScrollValue(refresh);
isMonitoringScrollValue = true;
}
- },
-
- eventNameDispatchConfigs: EventPluginHub.eventNameDispatchConfigs,
-
- registrationNameModules: EventPluginHub.registrationNameModules,
-
- putListener: EventPluginHub.putListener,
-
- getListener: EventPluginHub.getListener,
-
- deleteListener: EventPluginHub.deleteListener,
-
- deleteAllListeners: EventPluginHub.deleteAllListeners
-
-});
-
-ReactPerf.measureMethods(ReactBrowserEventEmitter, 'ReactBrowserEventEmitter', {
- putListener: 'putListener',
- deleteListener: 'deleteListener'
+ }
+
});
module.exports = ReactBrowserEventEmitter;
-},{"114":114,"133":133,"15":15,"16":16,"17":17,"24":24,"62":62,"78":78}],29:[function(_dereq_,module,exports){
-/**
- * Copyright 2013-2015, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under the BSD-style license found in the
- * LICENSE file in the root directory of this source tree. An additional grant
- * of patent rights can be found in the PATENTS file in the same directory.
- *
- * @typechecks
+},{"128":128,"147":147,"149":149,"16":16,"18":18,"188":188,"69":69}],29:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-present, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
* @providesModule ReactCSSTransitionGroup
*/
'use strict';
-var React = _dereq_(26);
-
-var assign = _dereq_(24);
-
-var ReactTransitionGroup = _dereq_(94);
+var _assign = _dereq_(188);
+
+var React = _dereq_(27);
+
+var ReactTransitionGroup = _dereq_(105);
var ReactCSSTransitionGroupChild = _dereq_(30);
function createTransitionTimeoutPropValidator(transitionType) {
var timeoutPropName = 'transition' + transitionType + 'Timeout';
var enabledPropName = 'transition' + transitionType;
return function (props) {
// If the transition is enabled
if (props[enabledPropName]) {
// If no timeout duration is provided
if (props[timeoutPropName] == null) {
return new Error(timeoutPropName + ' wasn\'t supplied to ReactCSSTransitionGroup: ' + 'this can cause unreliable animations and won\'t be supported in ' + 'a future version of React. See ' + 'https://fb.me/react-animation-transition-group-timeout for more ' + 'information.');
// If the duration isn't a number
} else if (typeof props[timeoutPropName] !== 'number') {
- return new Error(timeoutPropName + ' must be a number (in milliseconds)');
- }
- }
- };
-}
-
+ return new Error(timeoutPropName + ' must be a number (in milliseconds)');
+ }
+ }
+ };
+}
+
+/**
+ * An easy way to perform CSS transitions and animations when a React component
+ * enters or leaves the DOM.
+ * See https://facebook.github.io/react/docs/animation.html#high-level-api-reactcsstransitiongroup
+ */
var ReactCSSTransitionGroup = React.createClass({
displayName: 'ReactCSSTransitionGroup',
propTypes: {
transitionName: ReactCSSTransitionGroupChild.propTypes.name,
transitionAppear: React.PropTypes.bool,
transitionEnter: React.PropTypes.bool,
@@ -4229,48 +4333,43 @@ var ReactCSSTransitionGroup = React.crea
leave: this.props.transitionLeave,
appearTimeout: this.props.transitionAppearTimeout,
enterTimeout: this.props.transitionEnterTimeout,
leaveTimeout: this.props.transitionLeaveTimeout
}, child);
},
render: function () {
- return React.createElement(ReactTransitionGroup, assign({}, this.props, { childFactory: this._wrapChild }));
+ return React.createElement(ReactTransitionGroup, _assign({}, this.props, { childFactory: this._wrapChild }));
}
});
module.exports = ReactCSSTransitionGroup;
-},{"24":24,"26":26,"30":30,"94":94}],30:[function(_dereq_,module,exports){
-/**
- * Copyright 2013-2015, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under the BSD-style license found in the
- * LICENSE file in the root directory of this source tree. An additional grant
- * of patent rights can be found in the PATENTS file in the same directory.
- *
- * @typechecks
+},{"105":105,"188":188,"27":27,"30":30}],30:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-present, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
* @providesModule ReactCSSTransitionGroupChild
*/
'use strict';
-var React = _dereq_(26);
-var ReactDOM = _dereq_(40);
-
-var CSSCore = _dereq_(145);
-var ReactTransitionEvents = _dereq_(93);
-
-var onlyChild = _dereq_(135);
-
-// We don't remove the element from the DOM until we receive an animationend or
-// transitionend event. If the user screws up and forgets to add an animation
-// their node will be stuck in the DOM forever, so we detect if an animation
-// does not start and if it doesn't, we just call the end listener immediately.
+var React = _dereq_(27);
+var ReactDOM = _dereq_(42);
+
+var CSSCore = _dereq_(162);
+var ReactTransitionEvents = _dereq_(104);
+
+var onlyChild = _dereq_(151);
+
var TICK = 17;
var ReactCSSTransitionGroupChild = React.createClass({
displayName: 'ReactCSSTransitionGroupChild',
propTypes: {
name: React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.shape({
enter: React.PropTypes.string,
@@ -4327,57 +4426,64 @@ var ReactCSSTransitionGroupChild = React
if (finishCallback) {
finishCallback();
}
};
CSSCore.addClass(node, className);
// Need to do this to actually trigger a transition.
- this.queueClass(activeClassName);
+ this.queueClassAndNode(activeClassName, node);
// If the user specified a timeout delay.
if (userSpecifiedDelay) {
// Clean-up the animation after the specified delay
timeout = setTimeout(endListener, userSpecifiedDelay);
this.transitionTimeouts.push(timeout);
} else {
// DEPRECATED: this listener will be removed in a future version of react
ReactTransitionEvents.addEndEventListener(node, endListener);
}
},
- queueClass: function (className) {
- this.classNameQueue.push(className);
+ queueClassAndNode: function (className, node) {
+ this.classNameAndNodeQueue.push({
+ className: className,
+ node: node
+ });
if (!this.timeout) {
- this.timeout = setTimeout(this.flushClassNameQueue, TICK);
- }
- },
-
- flushClassNameQueue: function () {
+ this.timeout = setTimeout(this.flushClassNameAndNodeQueue, TICK);
+ }
+ },
+
+ flushClassNameAndNodeQueue: function () {
if (this.isMounted()) {
- this.classNameQueue.forEach(CSSCore.addClass.bind(CSSCore, ReactDOM.findDOMNode(this)));
- }
- this.classNameQueue.length = 0;
+ this.classNameAndNodeQueue.forEach(function (obj) {
+ CSSCore.addClass(obj.node, obj.className);
+ });
+ }
+ this.classNameAndNodeQueue.length = 0;
this.timeout = null;
},
componentWillMount: function () {
- this.classNameQueue = [];
+ this.classNameAndNodeQueue = [];
this.transitionTimeouts = [];
},
componentWillUnmount: function () {
if (this.timeout) {
clearTimeout(this.timeout);
}
this.transitionTimeouts.forEach(function (timeout) {
clearTimeout(timeout);
});
+
+ this.classNameAndNodeQueue.length = 0;
},
componentWillAppear: function (done) {
if (this.props.appear) {
this.transition('appear', done, this.props.appearTimeout);
} else {
done();
}
@@ -4400,46 +4506,63 @@ var ReactCSSTransitionGroupChild = React
},
render: function () {
return onlyChild(this.props.children);
}
});
module.exports = ReactCSSTransitionGroupChild;
-},{"135":135,"145":145,"26":26,"40":40,"93":93}],31:[function(_dereq_,module,exports){
-/**
- * Copyright 2014-2015, Facebook, Inc.
+},{"104":104,"151":151,"162":162,"27":27,"42":42}],31:[function(_dereq_,module,exports){
+(function (process){
+/**
+ * Copyright 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactChildReconciler
- * @typechecks static-only
- */
-
-'use strict';
-
-var ReactReconciler = _dereq_(84);
-
-var instantiateReactComponent = _dereq_(132);
-var shouldUpdateReactComponent = _dereq_(141);
-var traverseAllChildren = _dereq_(142);
-var warning = _dereq_(173);
-
-function instantiateChild(childInstances, child, name) {
+ */
+
+'use strict';
+
+var ReactReconciler = _dereq_(95);
+
+var instantiateReactComponent = _dereq_(148);
+var KeyEscapeUtils = _dereq_(23);
+var shouldUpdateReactComponent = _dereq_(158);
+var traverseAllChildren = _dereq_(159);
+var warning = _dereq_(187);
+
+var ReactComponentTreeHook;
+
+if (typeof process !== 'undefined' && process.env && "development" === 'test') {
+ // Temporary hack.
+ // Inline requires don't work well with Jest:
+ // https://github.com/facebook/react/issues/7240
+ // Remove the inline requires when we don't need them anymore:
+ // https://github.com/facebook/react/pull/7178
+ ReactComponentTreeHook = _dereq_(38);
+}
+
+function instantiateChild(childInstances, child, name, selfDebugID) {
// We found a component instance.
var keyUnique = childInstances[name] === undefined;
if ("development" !== 'production') {
- "development" !== 'production' ? warning(keyUnique, 'flattenChildren(...): Encountered two children with the same key, ' + '`%s`. Child keys must be unique; when two children share a key, only ' + 'the first child will be used.', name) : undefined;
+ if (!ReactComponentTreeHook) {
+ ReactComponentTreeHook = _dereq_(38);
+ }
+ if (!keyUnique) {
+ "development" !== 'production' ? warning(false, 'flattenChildren(...): Encountered two children with the same key, ' + '`%s`. Child keys must be unique; when two children share a key, only ' + 'the first child will be used.%s', KeyEscapeUtils.unescape(name), ReactComponentTreeHook.getStackAddendumByID(selfDebugID)) : void 0;
+ }
}
if (child != null && keyUnique) {
- childInstances[name] = instantiateReactComponent(child, null);
+ childInstances[name] = instantiateReactComponent(child, true);
}
}
/**
* ReactChildReconciler provides helpers for initializing or updating a set of
* children. Its output is suitable for passing it onto ReactMultiChild which
* does diffed reordering and insertion.
*/
@@ -4447,118 +4570,135 @@ var ReactChildReconciler = {
/**
* Generates a "mount image" for each of the supplied children. In the case
* of `ReactDOMComponent`, a mount image is a string of markup.
*
* @param {?object} nestedChildNodes Nested child maps.
* @return {?object} A set of child instances.
* @internal
*/
- instantiateChildren: function (nestedChildNodes, transaction, context) {
+ instantiateChildren: function (nestedChildNodes, transaction, context, selfDebugID // 0 in production and for roots
+ ) {
if (nestedChildNodes == null) {
return null;
}
var childInstances = {};
- traverseAllChildren(nestedChildNodes, instantiateChild, childInstances);
+
+ if ("development" !== 'production') {
+ traverseAllChildren(nestedChildNodes, function (childInsts, child, name) {
+ return instantiateChild(childInsts, child, name, selfDebugID);
+ }, childInstances);
+ } else {
+ traverseAllChildren(nestedChildNodes, instantiateChild, childInstances);
+ }
return childInstances;
},
/**
* Updates the rendered children and returns a new set of children.
*
* @param {?object} prevChildren Previously initialized set of children.
* @param {?object} nextChildren Flat child element maps.
* @param {ReactReconcileTransaction} transaction
* @param {object} context
* @return {?object} A new set of child instances.
* @internal
*/
- updateChildren: function (prevChildren, nextChildren, transaction, context) {
+ updateChildren: function (prevChildren, nextChildren, mountImages, removedNodes, transaction, hostParent, hostContainerInfo, context, selfDebugID // 0 in production and for roots
+ ) {
// We currently don't have a way to track moves here but if we use iterators
// instead of for..in we can zip the iterators and check if an item has
// moved.
// TODO: If nothing has changed, return the prevChildren object so that we
// can quickly bailout if nothing has changed.
if (!nextChildren && !prevChildren) {
- return null;
+ return;
}
var name;
+ var prevChild;
for (name in nextChildren) {
if (!nextChildren.hasOwnProperty(name)) {
continue;
}
- var prevChild = prevChildren && prevChildren[name];
+ prevChild = prevChildren && prevChildren[name];
var prevElement = prevChild && prevChild._currentElement;
var nextElement = nextChildren[name];
if (prevChild != null && shouldUpdateReactComponent(prevElement, nextElement)) {
ReactReconciler.receiveComponent(prevChild, nextElement, transaction, context);
nextChildren[name] = prevChild;
} else {
if (prevChild) {
- ReactReconciler.unmountComponent(prevChild, name);
+ removedNodes[name] = ReactReconciler.getHostNode(prevChild);
+ ReactReconciler.unmountComponent(prevChild, false);
}
// The child must be instantiated before it's mounted.
- var nextChildInstance = instantiateReactComponent(nextElement, null);
+ var nextChildInstance = instantiateReactComponent(nextElement, true);
nextChildren[name] = nextChildInstance;
+ // Creating mount image now ensures refs are resolved in right order
+ // (see https://github.com/facebook/react/pull/7101 for explanation).
+ var nextChildMountImage = ReactReconciler.mountComponent(nextChildInstance, transaction, hostParent, hostContainerInfo, context, selfDebugID);
+ mountImages.push(nextChildMountImage);
}
}
// Unmount children that are no longer present.
for (name in prevChildren) {
if (prevChildren.hasOwnProperty(name) && !(nextChildren && nextChildren.hasOwnProperty(name))) {
- ReactReconciler.unmountComponent(prevChildren[name]);
- }
- }
- return nextChildren;
+ prevChild = prevChildren[name];
+ removedNodes[name] = ReactReconciler.getHostNode(prevChild);
+ ReactReconciler.unmountComponent(prevChild, false);
+ }
+ }
},
/**
* Unmounts all rendered children. This should be used to clean up children
* when this component is unmounted.
*
* @param {?object} renderedChildren Previously initialized set of children.
* @internal
*/
- unmountChildren: function (renderedChildren) {
+ unmountChildren: function (renderedChildren, safely) {
for (var name in renderedChildren) {
if (renderedChildren.hasOwnProperty(name)) {
var renderedChild = renderedChildren[name];
- ReactReconciler.unmountComponent(renderedChild);
+ ReactReconciler.unmountComponent(renderedChild, safely);
}
}
}
};
module.exports = ReactChildReconciler;
-},{"132":132,"141":141,"142":142,"173":173,"84":84}],32:[function(_dereq_,module,exports){
-/**
- * Copyright 2013-2015, Facebook, Inc.
+}).call(this,undefined)
+},{"148":148,"158":158,"159":159,"187":187,"23":23,"38":38,"95":95}],32:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactChildren
*/
'use strict';
-var PooledClass = _dereq_(25);
-var ReactElement = _dereq_(57);
-
-var emptyFunction = _dereq_(153);
-var traverseAllChildren = _dereq_(142);
+var PooledClass = _dereq_(26);
+var ReactElement = _dereq_(65);
+
+var emptyFunction = _dereq_(170);
+var traverseAllChildren = _dereq_(159);
var twoArgumentPooler = PooledClass.twoArgumentPooler;
var fourArgumentPooler = PooledClass.fourArgumentPooler;
-var userProvidedKeyEscapeRegex = /\/(?!\/)/g;
+var userProvidedKeyEscapeRegex = /\/+/g;
function escapeUserProvidedKey(text) {
- return ('' + text).replace(userProvidedKeyEscapeRegex, '//');
+ return ('' + text).replace(userProvidedKeyEscapeRegex, '$&/');
}
/**
* PooledClass representing the bookkeeping associated with performing a child
* traversal. Allows avoiding binding callbacks.
*
* @constructor ForEachBookKeeping
* @param {!function} forEachFunction Function to perform traversal with.
@@ -4581,16 +4721,18 @@ function forEachSingleChild(bookKeeping,
var context = bookKeeping.context;
func.call(context, child, bookKeeping.count++);
}
/**
* Iterates through children that are typically specified as `props.children`.
*
+ * See https://facebook.github.io/react/docs/top-level-api.html#react.children.foreach
+ *
* The provided forEachFunc(child, index) will be called for each
* leaf child.
*
* @param {?*} children Children tree container.
* @param {function(*, int)} forEachFunc
* @param {*} forEachContext Context for forEachContext.
*/
function forEachChildren(children, forEachFunc, forEachContext) {
@@ -4628,25 +4770,26 @@ MapBookKeeping.prototype.destructor = fu
PooledClass.addPoolingTo(MapBookKeeping, fourArgumentPooler);
function mapSingleChildIntoContext(bookKeeping, child, childKey) {
var result = bookKeeping.result;
var keyPrefix = bookKeeping.keyPrefix;
var func = bookKeeping.func;
var context = bookKeeping.context;
+
var mappedChild = func.call(context, child, bookKeeping.count++);
if (Array.isArray(mappedChild)) {
mapIntoWithKeyPrefixInternal(mappedChild, result, childKey, emptyFunction.thatReturnsArgument);
} else if (mappedChild != null) {
if (ReactElement.isValidElement(mappedChild)) {
mappedChild = ReactElement.cloneAndReplaceKey(mappedChild,
// Keep both the (mapped) and old keys if they differ, just as
// traverseAllChildren used to do for objects as children
- keyPrefix + (mappedChild !== child ? escapeUserProvidedKey(mappedChild.key || '') + '/' : '') + childKey);
+ keyPrefix + (mappedChild.key && (!child || child.key !== mappedChild.key) ? escapeUserProvidedKey(mappedChild.key) + '/' : '') + childKey);
}
result.push(mappedChild);
}
}
function mapIntoWithKeyPrefixInternal(children, array, prefix, func, context) {
var escapedPrefix = '';
if (prefix != null) {
@@ -4655,16 +4798,18 @@ function mapIntoWithKeyPrefixInternal(ch
var traverseContext = MapBookKeeping.getPooled(array, escapedPrefix, func, context);
traverseAllChildren(children, mapSingleChildIntoContext, traverseContext);
MapBookKeeping.release(traverseContext);
}
/**
* Maps children that are typically specified as `props.children`.
*
+ * See https://facebook.github.io/react/docs/top-level-api.html#react.children.map
+ *
* The provided mapFunction(child, key, index) will be called for each
* leaf child.
*
* @param {?*} children Children tree container.
* @param {function(*, int)} func The map function.
* @param {*} context Context for mapFunction.
* @return {object} Object containing the ordered map of results.
*/
@@ -4680,68 +4825,129 @@ function mapChildren(children, func, con
function forEachSingleChildDummy(traverseContext, child, name) {
return null;
}
/**
* Count the number of children that are typically specified as
* `props.children`.
*
+ * See https://facebook.github.io/react/docs/top-level-api.html#react.children.count
+ *
* @param {?*} children Children tree container.
* @return {number} The number of children.
*/
function countChildren(children, context) {
return traverseAllChildren(children, forEachSingleChildDummy, null);
}
/**
* Flatten a children object (typically specified as `props.children`) and
* return an array with appropriately re-keyed children.
+ *
+ * See https://facebook.github.io/react/docs/top-level-api.html#react.children.toarray
*/
function toArray(children) {
var result = [];
mapIntoWithKeyPrefixInternal(children, result, null, emptyFunction.thatReturnsArgument);
return result;
}
var ReactChildren = {
forEach: forEachChildren,
map: mapChildren,
mapIntoWithKeyPrefixInternal: mapIntoWithKeyPrefixInternal,
count: countChildren,
toArray: toArray
};
module.exports = ReactChildren;
-},{"142":142,"153":153,"25":25,"57":57}],33:[function(_dereq_,module,exports){
-/**
- * Copyright 2013-2015, Facebook, Inc.
+},{"159":159,"170":170,"26":26,"65":65}],33:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-present, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
+ * @providesModule ReactChildrenMutationWarningHook
+ */
+
+'use strict';
+
+var ReactComponentTreeHook = _dereq_(38);
+
+var warning = _dereq_(187);
+
+function handleElement(debugID, element) {
+ if (element == null) {
+ return;
+ }
+ if (element._shadowChildren === undefined) {
+ return;
+ }
+ if (element._shadowChildren === element.props.children) {
+ return;
+ }
+ var isMutated = false;
+ if (Array.isArray(element._shadowChildren)) {
+ if (element._shadowChildren.length === element.props.children.length) {
+ for (var i = 0; i < element._shadowChildren.length; i++) {
+ if (element._shadowChildren[i] !== element.props.children[i]) {
+ isMutated = true;
+ }
+ }
+ } else {
+ isMutated = true;
+ }
+ }
+ if (!Array.isArray(element._shadowChildren) || isMutated) {
+ "development" !== 'production' ? warning(false, 'Component\'s children should not be mutated.%s', ReactComponentTreeHook.getStackAddendumByID(debugID)) : void 0;
+ }
+}
+
+var ReactChildrenMutationWarningHook = {
+ onMountComponent: function (debugID) {
+ handleElement(debugID, ReactComponentTreeHook.getElement(debugID));
+ },
+ onUpdateComponent: function (debugID) {
+ handleElement(debugID, ReactComponentTreeHook.getElement(debugID));
+ }
+};
+
+module.exports = ReactChildrenMutationWarningHook;
+},{"187":187,"38":38}],34:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactClass
*/
'use strict';
-var ReactComponent = _dereq_(34);
-var ReactElement = _dereq_(57);
-var ReactPropTypeLocations = _dereq_(81);
-var ReactPropTypeLocationNames = _dereq_(80);
-var ReactNoopUpdateQueue = _dereq_(76);
-
-var assign = _dereq_(24);
-var emptyObject = _dereq_(154);
-var invariant = _dereq_(161);
-var keyMirror = _dereq_(165);
-var keyOf = _dereq_(166);
-var warning = _dereq_(173);
+var _prodInvariant = _dereq_(153),
+ _assign = _dereq_(188);
+
+var ReactComponent = _dereq_(35);
+var ReactElement = _dereq_(65);
+var ReactPropTypeLocations = _dereq_(90);
+var ReactPropTypeLocationNames = _dereq_(89);
+var ReactNoopUpdateQueue = _dereq_(86);
+
+var emptyObject = _dereq_(171);
+var invariant = _dereq_(178);
+var keyMirror = _dereq_(181);
+var keyOf = _dereq_(182);
+var warning = _dereq_(187);
var MIXINS_KEY = keyOf({ mixins: null });
/**
* Policies that describe methods in `ReactClassInterface`.
*/
var SpecPolicy = keyMirror({
/**
@@ -4762,27 +4968,19 @@ var SpecPolicy = keyMirror({
* objects. We try to merge the keys of the return values of all the mixed in
* functions. If there is a key conflict we throw.
*/
DEFINE_MANY_MERGED: null
});
var injectedMixins = [];
-var warnedSetProps = false;
-function warnSetProps() {
- if (!warnedSetProps) {
- warnedSetProps = true;
- "development" !== 'production' ? warning(false, 'setProps(...) and replaceProps(...) are deprecated. ' + 'Instead, call render again at the top level.') : undefined;
- }
-}
-
/**
* Composite components are higher-level components that compose other composite
- * or native components.
+ * or host components.
*
* To create a new type of `ReactClass`, pass a specification of
* your new class to `React.createClass`. The only requirement of your class
* specification is that you implement a `render` method.
*
* var MyComponent = React.createClass({
* render: function() {
* return <div>Hello World</div>;
@@ -5039,84 +5237,91 @@ var RESERVED_SPEC_KEYS = {
mixSpecIntoComponent(Constructor, mixins[i]);
}
}
},
childContextTypes: function (Constructor, childContextTypes) {
if ("development" !== 'production') {
validateTypeDef(Constructor, childContextTypes, ReactPropTypeLocations.childContext);
}
- Constructor.childContextTypes = assign({}, Constructor.childContextTypes, childContextTypes);
+ Constructor.childContextTypes = _assign({}, Constructor.childContextTypes, childContextTypes);
},
contextTypes: function (Constructor, contextTypes) {
if ("development" !== 'production') {
validateTypeDef(Constructor, contextTypes, ReactPropTypeLocations.context);
}
- Constructor.contextTypes = assign({}, Constructor.contextTypes, contextTypes);
+ Constructor.contextTypes = _assign({}, Constructor.contextTypes, contextTypes);
},
/**
* Special case getDefaultProps which should move into statics but requires
* automatic merging.
*/
getDefaultProps: function (Constructor, getDefaultProps) {
if (Constructor.getDefaultProps) {
Constructor.getDefaultProps = createMergedResultFunction(Constructor.getDefaultProps, getDefaultProps);
} else {
Constructor.getDefaultProps = getDefaultProps;
}
},
propTypes: function (Constructor, propTypes) {
if ("development" !== 'production') {
validateTypeDef(Constructor, propTypes, ReactPropTypeLocations.prop);
}
- Constructor.propTypes = assign({}, Constructor.propTypes, propTypes);
+ Constructor.propTypes = _assign({}, Constructor.propTypes, propTypes);
},
statics: function (Constructor, statics) {
mixStaticSpecIntoComponent(Constructor, statics);
},
autobind: function () {} };
-// noop
function validateTypeDef(Constructor, typeDef, location) {
for (var propName in typeDef) {
if (typeDef.hasOwnProperty(propName)) {
// use a warning instead of an invariant so components
- // don't show up in prod but not in __DEV__
- "development" !== 'production' ? warning(typeof typeDef[propName] === 'function', '%s: %s type `%s` is invalid; it must be a function, usually from ' + 'React.PropTypes.', Constructor.displayName || 'ReactClass', ReactPropTypeLocationNames[location], propName) : undefined;
- }
- }
-}
-
-function validateMethodOverride(proto, name) {
+ // don't show up in prod but only in __DEV__
+ "development" !== 'production' ? warning(typeof typeDef[propName] === 'function', '%s: %s type `%s` is invalid; it must be a function, usually from ' + 'React.PropTypes.', Constructor.displayName || 'ReactClass', ReactPropTypeLocationNames[location], propName) : void 0;
+ }
+ }
+}
+
+function validateMethodOverride(isAlreadyDefined, name) {
var specPolicy = ReactClassInterface.hasOwnProperty(name) ? ReactClassInterface[name] : null;
// Disallow overriding of base class methods unless explicitly allowed.
if (ReactClassMixin.hasOwnProperty(name)) {
- !(specPolicy === SpecPolicy.OVERRIDE_BASE) ? "development" !== 'production' ? invariant(false, 'ReactClassInterface: You are attempting to override ' + '`%s` from your class specification. Ensure that your method names ' + 'do not overlap with React methods.', name) : invariant(false) : undefined;
+ !(specPolicy === SpecPolicy.OVERRIDE_BASE) ? "development" !== 'production' ? invariant(false, 'ReactClassInterface: You are attempting to override `%s` from your class specification. Ensure that your method names do not overlap with React methods.', name) : _prodInvariant('73', name) : void 0;
}
// Disallow defining methods more than once unless explicitly allowed.
- if (proto.hasOwnProperty(name)) {
- !(specPolicy === SpecPolicy.DEFINE_MANY || specPolicy === SpecPolicy.DEFINE_MANY_MERGED) ? "development" !== 'production' ? invariant(false, 'ReactClassInterface: You are attempting to define ' + '`%s` on your component more than once. This conflict may be due ' + 'to a mixin.', name) : invariant(false) : undefined;
+ if (isAlreadyDefined) {
+ !(specPolicy === SpecPolicy.DEFINE_MANY || specPolicy === SpecPolicy.DEFINE_MANY_MERGED) ? "development" !== 'production' ? invariant(false, 'ReactClassInterface: You are attempting to define `%s` on your component more than once. This conflict may be due to a mixin.', name) : _prodInvariant('74', name) : void 0;
}
}
/**
* Mixin helper which handles policy validation and reserved
- * specification keys when building React classses.
+ * specification keys when building React classes.
*/
function mixSpecIntoComponent(Constructor, spec) {
if (!spec) {
+ if ("development" !== 'production') {
+ var typeofSpec = typeof spec;
+ var isMixinValid = typeofSpec === 'object' && spec !== null;
+
+ "development" !== 'production' ? warning(isMixinValid, '%s: You\'re attempting to include a mixin that is either null ' + 'or not an object. Check the mixins included by the component, ' + 'as well as any mixins they include themselves. ' + 'Expected object but got %s.', Constructor.displayName || 'ReactClass', spec === null ? null : typeofSpec) : void 0;
+ }
+
return;
}
- !(typeof spec !== 'function') ? "development" !== 'production' ? invariant(false, 'ReactClass: You\'re attempting to ' + 'use a component class as a mixin. Instead, just use a regular object.') : invariant(false) : undefined;
- !!ReactElement.isValidElement(spec) ? "development" !== 'production' ? invariant(false, 'ReactClass: You\'re attempting to ' + 'use a component as a mixin. Instead, just use a regular object.') : invariant(false) : undefined;
+ !(typeof spec !== 'function') ? "development" !== 'production' ? invariant(false, 'ReactClass: You\'re attempting to use a component class or function as a mixin. Instead, just use a regular object.') : _prodInvariant('75') : void 0;
+ !!ReactElement.isValidElement(spec) ? "development" !== 'production' ? invariant(false, 'ReactClass: You\'re attempting to use a component as a mixin. Instead, just use a regular object.') : _prodInvariant('76') : void 0;
var proto = Constructor.prototype;
+ var autoBindPairs = proto.__reactAutoBindPairs;
// By handling mixins before any other properties, we ensure the same
// chaining order is applied to methods with DEFINE_MANY policy, whether
// mixins are listed before or after these methods in the spec.
if (spec.hasOwnProperty(MIXINS_KEY)) {
RESERVED_SPEC_KEYS.mixins(Constructor, spec.mixins);
}
@@ -5126,42 +5331,39 @@ function mixSpecIntoComponent(Constructo
}
if (name === MIXINS_KEY) {
// We have already handled mixins in a special case above.
continue;
}
var property = spec[name];
- validateMethodOverride(proto, name);
+ var isAlreadyDefined = proto.hasOwnProperty(name);
+ validateMethodOverride(isAlreadyDefined, name);
if (RESERVED_SPEC_KEYS.hasOwnProperty(name)) {
RESERVED_SPEC_KEYS[name](Constructor, property);
} else {
// Setup methods on prototype:
// The following member methods should not be automatically bound:
// 1. Expected ReactClass methods (in the "interface").
// 2. Overridden methods (that were mixed in).
var isReactClassMethod = ReactClassInterface.hasOwnProperty(name);
- var isAlreadyDefined = proto.hasOwnProperty(name);
var isFunction = typeof property === 'function';
var shouldAutoBind = isFunction && !isReactClassMethod && !isAlreadyDefined && spec.autobind !== false;
if (shouldAutoBind) {
- if (!proto.__reactAutoBindMap) {
- proto.__reactAutoBindMap = {};
- }
- proto.__reactAutoBindMap[name] = property;
+ autoBindPairs.push(name, property);
proto[name] = property;
} else {
if (isAlreadyDefined) {
var specPolicy = ReactClassInterface[name];
// These cases should already be caught by validateMethodOverride.
- !(isReactClassMethod && (specPolicy === SpecPolicy.DEFINE_MANY_MERGED || specPolicy === SpecPolicy.DEFINE_MANY)) ? "development" !== 'production' ? invariant(false, 'ReactClass: Unexpected spec policy %s for key %s ' + 'when mixing in component specs.', specPolicy, name) : invariant(false) : undefined;
+ !(isReactClassMethod && (specPolicy === SpecPolicy.DEFINE_MANY_MERGED || specPolicy === SpecPolicy.DEFINE_MANY)) ? "development" !== 'production' ? invariant(false, 'ReactClass: Unexpected spec policy %s for key %s when mixing in component specs.', specPolicy, name) : _prodInvariant('77', specPolicy, name) : void 0;
// For methods which are defined more than once, call the existing
// methods before calling the new property, merging if appropriate.
if (specPolicy === SpecPolicy.DEFINE_MANY_MERGED) {
proto[name] = createMergedResultFunction(proto[name], property);
} else if (specPolicy === SpecPolicy.DEFINE_MANY) {
proto[name] = createChainedFunction(proto[name], property);
}
@@ -5185,38 +5387,38 @@ function mixStaticSpecIntoComponent(Cons
return;
}
for (var name in statics) {
var property = statics[name];
if (!statics.hasOwnProperty(name)) {
continue;
}
- var isReserved = (name in RESERVED_SPEC_KEYS);
- !!isReserved ? "development" !== 'production' ? invariant(false, 'ReactClass: You are attempting to define a reserved ' + 'property, `%s`, that shouldn\'t be on the "statics" key. Define it ' + 'as an instance property instead; it will still be accessible on the ' + 'constructor.', name) : invariant(false) : undefined;
-
- var isInherited = (name in Constructor);
- !!isInherited ? "development" !== 'production' ? invariant(false, 'ReactClass: You are attempting to define ' + '`%s` on your component more than once. This conflict may be ' + 'due to a mixin.', name) : invariant(false) : undefined;
+ var isReserved = name in RESERVED_SPEC_KEYS;
+ !!isReserved ? "development" !== 'production' ? invariant(false, 'ReactClass: You are attempting to define a reserved property, `%s`, that shouldn\'t be on the "statics" key. Define it as an instance property instead; it will still be accessible on the constructor.', name) : _prodInvariant('78', name) : void 0;
+
+ var isInherited = name in Constructor;
+ !!isInherited ? "development" !== 'production' ? invariant(false, 'ReactClass: You are attempting to define `%s` on your component more than once. This conflict may be due to a mixin.', name) : _prodInvariant('79', name) : void 0;
Constructor[name] = property;
}
}
/**
* Merge two objects, but throw if both contain the same key.
*
* @param {object} one The first object, which is mutated.
* @param {object} two The second object
* @return {object} one after it has been mutated to contain everything in two.
*/
function mergeIntoWithNoDuplicateKeys(one, two) {
- !(one && two && typeof one === 'object' && typeof two === 'object') ? "development" !== 'production' ? invariant(false, 'mergeIntoWithNoDuplicateKeys(): Cannot merge non-objects.') : invariant(false) : undefined;
+ !(one && two && typeof one === 'object' && typeof two === 'object') ? "development" !== 'production' ? invariant(false, 'mergeIntoWithNoDuplicateKeys(): Cannot merge non-objects.') : _prodInvariant('80') : void 0;
for (var key in two) {
if (two.hasOwnProperty(key)) {
- !(one[key] === undefined) ? "development" !== 'production' ? invariant(false, 'mergeIntoWithNoDuplicateKeys(): ' + 'Tried to merge two objects with the same key: `%s`. This conflict ' + 'may be due to a mixin; in particular, this may be caused by two ' + 'getInitialState() or getDefaultProps() methods returning objects ' + 'with clashing keys.', key) : invariant(false) : undefined;
+ !(one[key] === undefined) ? "development" !== 'production' ? invariant(false, 'mergeIntoWithNoDuplicateKeys(): Tried to merge two objects with the same key: `%s`. This conflict may be due to a mixin; in particular, this may be caused by two getInitialState() or getDefaultProps() methods returning objects with clashing keys.', key) : _prodInvariant('81', key) : void 0;
one[key] = two[key];
}
}
return one;
}
/**
* Creates a function that invokes two functions and merges their return values.
@@ -5267,178 +5469,140 @@ function createChainedFunction(one, two)
function bindAutoBindMethod(component, method) {
var boundMethod = method.bind(component);
if ("development" !== 'production') {
boundMethod.__reactBoundContext = component;
boundMethod.__reactBoundMethod = method;
boundMethod.__reactBoundArguments = null;
var componentName = component.constructor.displayName;
var _bind = boundMethod.bind;
- /* eslint-disable block-scoped-var, no-undef */
boundMethod.bind = function (newThis) {
for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
args[_key - 1] = arguments[_key];
}
// User is trying to bind() an autobound method; we effectively will
// ignore the value of "this" that the user is trying to use, so
// let's warn.
if (newThis !== component && newThis !== null) {
- "development" !== 'production' ? warning(false, 'bind(): React component methods may only be bound to the ' + 'component instance. See %s', componentName) : undefined;
+ "development" !== 'production' ? warning(false, 'bind(): React component methods may only be bound to the ' + 'component instance. See %s', componentName) : void 0;
} else if (!args.length) {
- "development" !== 'production' ? warning(false, 'bind(): You are binding a component method to the component. ' + 'React does this for you automatically in a high-performance ' + 'way, so you can safely remove this call. See %s', componentName) : undefined;
+ "development" !== 'production' ? warning(false, 'bind(): You are binding a component method to the component. ' + 'React does this for you automatically in a high-performance ' + 'way, so you can safely remove this call. See %s', componentName) : void 0;
return boundMethod;
}
var reboundMethod = _bind.apply(boundMethod, arguments);
reboundMethod.__reactBoundContext = component;
reboundMethod.__reactBoundMethod = method;
reboundMethod.__reactBoundArguments = args;
return reboundMethod;
- /* eslint-enable */
};
}
return boundMethod;
}
/**
* Binds all auto-bound methods in a component.
*
* @param {object} component Component whose method is going to be bound.
*/
function bindAutoBindMethods(component) {
- for (var autoBindKey in component.__reactAutoBindMap) {
- if (component.__reactAutoBindMap.hasOwnProperty(autoBindKey)) {
- var method = component.__reactAutoBindMap[autoBindKey];
- component[autoBindKey] = bindAutoBindMethod(component, method);
- }
+ var pairs = component.__reactAutoBindPairs;
+ for (var i = 0; i < pairs.length; i += 2) {
+ var autoBindKey = pairs[i];
+ var method = pairs[i + 1];
+ component[autoBindKey] = bindAutoBindMethod(component, method);
}
}
/**
* Add more to the ReactClass base class. These are all legacy features and
* therefore not already part of the modern ReactComponent.
*/
var ReactClassMixin = {
/**
* TODO: This will be deprecated because state should always keep a consistent
* type signature and the only use case for this, is to avoid that.
*/
replaceState: function (newState, callback) {
this.updater.enqueueReplaceState(this, newState);
if (callback) {
- this.updater.enqueueCallback(this, callback);
+ this.updater.enqueueCallback(this, callback, 'replaceState');
}
},
/**
* Checks whether or not this composite component is mounted.
* @return {boolean} True if mounted, false otherwise.
* @protected
* @final
*/
isMounted: function () {
return this.updater.isMounted(this);
- },
-
- /**
- * Sets a subset of the props.
- *
- * @param {object} partialProps Subset of the next props.
- * @param {?function} callback Called after props are updated.
- * @final
- * @public
- * @deprecated
- */
- setProps: function (partialProps, callback) {
- if ("development" !== 'production') {
- warnSetProps();
- }
- this.updater.enqueueSetProps(this, partialProps);
- if (callback) {
- this.updater.enqueueCallback(this, callback);
- }
- },
-
- /**
- * Replace all the props.
- *
- * @param {object} newProps Subset of the next props.
- * @param {?function} callback Called after props are updated.
- * @final
- * @public
- * @deprecated
- */
- replaceProps: function (newProps, callback) {
- if ("development" !== 'production') {
- warnSetProps();
- }
- this.updater.enqueueReplaceProps(this, newProps);
- if (callback) {
- this.updater.enqueueCallback(this, callback);
- }
}
};
var ReactClassComponent = function () {};
-assign(ReactClassComponent.prototype, ReactComponent.prototype, ReactClassMixin);
+_assign(ReactClassComponent.prototype, ReactComponent.prototype, ReactClassMixin);
/**
* Module for creating composite components.
*
* @class ReactClass
*/
var ReactClass = {
/**
* Creates a composite component class given a class specification.
+ * See https://facebook.github.io/react/docs/top-level-api.html#react.createclass
*
* @param {object} spec Class specification (which must define `render`).
* @return {function} Component constructor function.
* @public
*/
createClass: function (spec) {
var Constructor = function (props, context, updater) {
- // This constructor is overridden by mocks. The argument is used
+ // This constructor gets overridden by mocks. The argument is used
// by mocks to assert on what gets mounted.
if ("development" !== 'production') {
- "development" !== 'production' ? warning(this instanceof Constructor, 'Something is calling a React component directly. Use a factory or ' + 'JSX instead. See: https://fb.me/react-legacyfactory') : undefined;
+ "development" !== 'production' ? warning(this instanceof Constructor, 'Something is calling a React component directly. Use a factory or ' + 'JSX instead. See: https://fb.me/react-legacyfactory') : void 0;
}
// Wire up auto-binding
- if (this.__reactAutoBindMap) {
+ if (this.__reactAutoBindPairs.length) {
bindAutoBindMethods(this);
}
this.props = props;
this.context = context;
this.refs = emptyObject;
this.updater = updater || ReactNoopUpdateQueue;
this.state = null;
// ReactClasses doesn't have constructors. Instead, they use the
// getInitialState and componentWillMount methods for initialization.
var initialState = this.getInitialState ? this.getInitialState() : null;
if ("development" !== 'production') {
// We allow auto-mocks to proceed as if they're returning null.
- if (typeof initialState === 'undefined' && this.getInitialState._isMockFunction) {
+ if (initialState === undefined && this.getInitialState._isMockFunction) {
// This is probably bad practice. Consider warning here and
// deprecating this convenience.
initialState = null;
}
}
- !(typeof initialState === 'object' && !Array.isArray(initialState)) ? "development" !== 'production' ? invariant(false, '%s.getInitialState(): must return an object or null', Constructor.displayName || 'ReactCompositeComponent') : invariant(false) : undefined;
+ !(typeof initialState === 'object' && !Array.isArray(initialState)) ? "development" !== 'production' ? invariant(false, '%s.getInitialState(): must return an object or null', Constructor.displayName || 'ReactCompositeComponent') : _prodInvariant('82', Constructor.displayName || 'ReactCompositeComponent') : void 0;
this.state = initialState;
};
Constructor.prototype = new ReactClassComponent();
Constructor.prototype.constructor = Constructor;
+ Constructor.prototype.__reactAutoBindPairs = [];
injectedMixins.forEach(mixSpecIntoComponent.bind(null, Constructor));
mixSpecIntoComponent(Constructor, spec);
// Initialize the defaultProps property after all mixins have been merged.
if (Constructor.getDefaultProps) {
Constructor.defaultProps = Constructor.getDefaultProps();
@@ -5452,21 +5616,21 @@ var ReactClass = {
if (Constructor.getDefaultProps) {
Constructor.getDefaultProps.isReactClassApproved = {};
}
if (Constructor.prototype.getInitialState) {
Constructor.prototype.getInitialState.isReactClassApproved = {};
}
}
- !Constructor.prototype.render ? "development" !== 'production' ? invariant(false, 'createClass(...): Class specification must implement a `render` method.') : invariant(false) : undefined;
-
- if ("development" !== 'production') {
- "development" !== 'production' ? warning(!Constructor.prototype.componentShouldUpdate, '%s has a method called ' + 'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' + 'The name is phrased as a question because the function is ' + 'expected to return a value.', spec.displayName || 'A component') : undefined;
- "development" !== 'production' ? warning(!Constructor.prototype.componentWillRecieveProps, '%s has a method called ' + 'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?', spec.displayName || 'A component') : undefined;
+ !Constructor.prototype.render ? "development" !== 'production' ? invariant(false, 'createClass(...): Class specification must implement a `render` method.') : _prodInvariant('83') : void 0;
+
+ if ("development" !== 'production') {
+ "development" !== 'production' ? warning(!Constructor.prototype.componentShouldUpdate, '%s has a method called ' + 'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' + 'The name is phrased as a question because the function is ' + 'expected to return a value.', spec.displayName || 'A component') : void 0;
+ "development" !== 'production' ? warning(!Constructor.prototype.componentWillRecieveProps, '%s has a method called ' + 'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?', spec.displayName || 'A component') : void 0;
}
// Reduce time spent doing lookups by setting these on the prototype.
for (var methodName in ReactClassInterface) {
if (!Constructor.prototype[methodName]) {
Constructor.prototype[methodName] = null;
}
}
@@ -5478,36 +5642,38 @@ var ReactClass = {
injectMixin: function (mixin) {
injectedMixins.push(mixin);
}
}
};
module.exports = ReactClass;
-},{"154":154,"161":161,"165":165,"166":166,"173":173,"24":24,"34":34,"57":57,"76":76,"80":80,"81":81}],34:[function(_dereq_,module,exports){
-/**
- * Copyright 2013-2015, Facebook, Inc.
+},{"153":153,"171":171,"178":178,"181":181,"182":182,"187":187,"188":188,"35":35,"65":65,"86":86,"89":89,"90":90}],35:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactComponent
*/
'use strict';
-var ReactNoopUpdateQueue = _dereq_(76);
-
-var canDefineProperty = _dereq_(117);
-var emptyObject = _dereq_(154);
-var invariant = _dereq_(161);
-var warning = _dereq_(173);
+var _prodInvariant = _dereq_(153);
+
+var ReactNoopUpdateQueue = _dereq_(86);
+
+var canDefineProperty = _dereq_(131);
+var emptyObject = _dereq_(171);
+var invariant = _dereq_(178);
+var warning = _dereq_(187);
/**
* Base class helpers for the updating state of a component.
*/
function ReactComponent(props, context, updater) {
this.props = props;
this.context = context;
this.refs = emptyObject;
@@ -5539,23 +5705,20 @@ ReactComponent.prototype.isReactComponen
*
* @param {object|function} partialState Next partial state or function to
* produce next partial state to be merged with current state.
* @param {?function} callback Called after state is updated.
* @final
* @protected
*/
ReactComponent.prototype.setState = function (partialState, callback) {
- !(typeof partialState === 'object' || typeof partialState === 'function' || partialState == null) ? "development" !== 'production' ? invariant(false, 'setState(...): takes an object of state variables to update or a ' + 'function which returns an object of state variables.') : invariant(false) : undefined;
- if ("development" !== 'production') {
- "development" !== 'production' ? warning(partialState != null, 'setState(...): You passed an undefined or null state object; ' + 'instead, use forceUpdate().') : undefined;
- }
+ !(typeof partialState === 'object' || typeof partialState === 'function' || partialState == null) ? "development" !== 'production' ? invariant(false, 'setState(...): takes an object of state variables to update or a function which returns an object of state variables.') : _prodInvariant('85') : void 0;
this.updater.enqueueSetState(this, partialState);
if (callback) {
- this.updater.enqueueCallback(this, callback);
+ this.updater.enqueueCallback(this, callback, 'setState');
}
};
/**
* Forces an update. This should only be invoked when it is known with
* certainty that we are **not** in a DOM transaction.
*
* You may want to call this when you know that some deeper aspect of the
@@ -5566,164 +5729,487 @@ ReactComponent.prototype.setState = func
*
* @param {?function} callback Called after update is complete.
* @final
* @protected
*/
ReactComponent.prototype.forceUpdate = function (callback) {
this.updater.enqueueForceUpdate(this);
if (callback) {
- this.updater.enqueueCallback(this, callback);
+ this.updater.enqueueCallback(this, callback, 'forceUpdate');
}
};
/**
* Deprecated APIs. These APIs used to exist on classic React classes but since
* we would like to deprecate them, we're not going to move them over to this
* modern base class. Instead, we define a getter that warns if it's accessed.
*/
if ("development" !== 'production') {
var deprecatedAPIs = {
- getDOMNode: ['getDOMNode', 'Use ReactDOM.findDOMNode(component) instead.'],
isMounted: ['isMounted', 'Instead, make sure to clean up subscriptions and pending requests in ' + 'componentWillUnmount to prevent memory leaks.'],
- replaceProps: ['replaceProps', 'Instead, call render again at the top level.'],
- replaceState: ['replaceState', 'Refactor your code to use setState instead (see ' + 'https://github.com/facebook/react/issues/3236).'],
- setProps: ['setProps', 'Instead, call render again at the top level.']
+ replaceState: ['replaceState', 'Refactor your code to use setState instead (see ' + 'https://github.com/facebook/react/issues/3236).']
};
var defineDeprecationWarning = function (methodName, info) {
if (canDefineProperty) {
Object.defineProperty(ReactComponent.prototype, methodName, {
get: function () {
- "development" !== 'production' ? warning(false, '%s(...) is deprecated in plain JavaScript React classes. %s', info[0], info[1]) : undefined;
+ "development" !== 'production' ? warning(false, '%s(...) is deprecated in plain JavaScript React classes. %s', info[0], info[1]) : void 0;
return undefined;
}
});
}
};
for (var fnName in deprecatedAPIs) {
if (deprecatedAPIs.hasOwnProperty(fnName)) {
defineDeprecationWarning(fnName, deprecatedAPIs[fnName]);
}
}
}
module.exports = ReactComponent;
-},{"117":117,"154":154,"161":161,"173":173,"76":76}],35:[function(_dereq_,module,exports){
-/**
- * Copyright 2013-2015, Facebook, Inc.
+},{"131":131,"153":153,"171":171,"178":178,"187":187,"86":86}],36:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactComponentBrowserEnvironment
*/
'use strict';
-var ReactDOMIDOperations = _dereq_(45);
-var ReactMount = _dereq_(72);
+var DOMChildrenOperations = _dereq_(7);
+var ReactDOMIDOperations = _dereq_(51);
/**
* Abstracts away all functionality of the reconciler that requires knowledge of
* the browser context. TODO: These callers should be refactored to avoid the
* need for this injection.
*/
var ReactComponentBrowserEnvironment = {
processChildrenUpdates: ReactDOMIDOperations.dangerouslyProcessChildrenUpdates,
- replaceNodeWithMarkupByID: ReactDOMIDOperations.dangerouslyReplaceNodeWithMarkupByID,
-
- /**
- * If a particular environment requires that some resources be cleaned up,
- * specify this in the injected Mixin. In the DOM, we would likely want to
- * purge any cached node ID lookups.
- *
- * @private
- */
- unmountIDFromEnvironment: function (rootNodeID) {
- ReactMount.purgeID(rootNodeID);
- }
+ replaceNodeWithMarkup: DOMChildrenOperations.dangerouslyReplaceNodeWithMarkup
};
module.exports = ReactComponentBrowserEnvironment;
-},{"45":45,"72":72}],36:[function(_dereq_,module,exports){
-/**
- * Copyright 2014-2015, Facebook, Inc.
+},{"51":51,"7":7}],37:[function(_dereq_,module,exports){
+/**
+ * Copyright 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactComponentEnvironment
*/
'use strict';
-var invariant = _dereq_(161);
+var _prodInvariant = _dereq_(153);
+
+var invariant = _dereq_(178);
var injected = false;
var ReactComponentEnvironment = {
/**
- * Optionally injectable environment dependent cleanup hook. (server vs.
- * browser etc). Example: A browser system caches DOM nodes based on component
- * ID and must remove that cache entry when this instance is unmounted.
- */
- unmountIDFromEnvironment: null,
-
- /**
* Optionally injectable hook for swapping out mount images in the middle of
* the tree.
*/
- replaceNodeWithMarkupByID: null,
+ replaceNodeWithMarkup: null,
/**
* Optionally injectable hook for processing a queue of child updates. Will
* later move into MultiChildComponents.
*/
processChildrenUpdates: null,
injection: {
injectEnvironment: function (environment) {
- !!injected ? "development" !== 'production' ? invariant(false, 'ReactCompositeComponent: injectEnvironment() can only be called once.') : invariant(false) : undefined;
- ReactComponentEnvironment.unmountIDFromEnvironment = environment.unmountIDFromEnvironment;
- ReactComponentEnvironment.replaceNodeWithMarkupByID = environment.replaceNodeWithMarkupByID;
+ !!injected ? "development" !== 'production' ? invariant(false, 'ReactCompositeComponent: injectEnvironment() can only be called once.') : _prodInvariant('104') : void 0;
+ ReactComponentEnvironment.replaceNodeWithMarkup = environment.replaceNodeWithMarkup;
ReactComponentEnvironment.processChildrenUpdates = environment.processChildrenUpdates;
injected = true;
}
}
};
module.exports = ReactComponentEnvironment;
-},{"161":161}],37:[function(_dereq_,module,exports){
-/**
- * Copyright 2013-2015, Facebook, Inc.
+},{"153":153,"178":178}],38:[function(_dereq_,module,exports){
+/**
+ * Copyright 2016-present, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
+ * @providesModule ReactComponentTreeHook
+ */
+
+'use strict';
+
+var _prodInvariant = _dereq_(153);
+
+var ReactCurrentOwner = _dereq_(41);
+
+var invariant = _dereq_(178);
+var warning = _dereq_(187);
+
+function isNative(fn) {
+ // Based on isNative() from Lodash
+ var funcToString = Function.prototype.toString;
+ var hasOwnProperty = Object.prototype.hasOwnProperty;
+ var reIsNative = RegExp('^' + funcToString
+ // Take an example native function source for comparison
+ .call(hasOwnProperty)
+ // Strip regex characters so we can use it for regex
+ .replace(/[\\^$.*+?()[\]{}|]/g, '\\$&')
+ // Remove hasOwnProperty from the template to make it generic
+ .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$');
+ try {
+ var source = funcToString.call(fn);
+ return reIsNative.test(source);
+ } catch (err) {
+ return false;
+ }
+}
+
+var canUseCollections =
+// Array.from
+typeof Array.from === 'function' &&
+// Map
+typeof Map === 'function' && isNative(Map) &&
+// Map.prototype.keys
+Map.prototype != null && typeof Map.prototype.keys === 'function' && isNative(Map.prototype.keys) &&
+// Set
+typeof Set === 'function' && isNative(Set) &&
+// Set.prototype.keys
+Set.prototype != null && typeof Set.prototype.keys === 'function' && isNative(Set.prototype.keys);
+
+var itemMap;
+var rootIDSet;
+
+var itemByKey;
+var rootByKey;
+
+if (canUseCollections) {
+ itemMap = new Map();
+ rootIDSet = new Set();
+} else {
+ itemByKey = {};
+ rootByKey = {};
+}
+
+var unmountedIDs = [];
+
+// Use non-numeric keys to prevent V8 performance issues:
+// https://github.com/facebook/react/pull/7232
+function getKeyFromID(id) {
+ return '.' + id;
+}
+function getIDFromKey(key) {
+ return parseInt(key.substr(1), 10);
+}
+
+function get(id) {
+ if (canUseCollections) {
+ return itemMap.get(id);
+ } else {
+ var key = getKeyFromID(id);
+ return itemByKey[key];
+ }
+}
+
+function remove(id) {
+ if (canUseCollections) {
+ itemMap['delete'](id);
+ } else {
+ var key = getKeyFromID(id);
+ delete itemByKey[key];
+ }
+}
+
+function create(id, element, parentID) {
+ var item = {
+ element: element,
+ parentID: parentID,
+ text: null,
+ childIDs: [],
+ isMounted: false,
+ updateCount: 0
+ };
+
+ if (canUseCollections) {
+ itemMap.set(id, item);
+ } else {
+ var key = getKeyFromID(id);
+ itemByKey[key] = item;
+ }
+}
+
+function addRoot(id) {
+ if (canUseCollections) {
+ rootIDSet.add(id);
+ } else {
+ var key = getKeyFromID(id);
+ rootByKey[key] = true;
+ }
+}
+
+function removeRoot(id) {
+ if (canUseCollections) {
+ rootIDSet['delete'](id);
+ } else {
+ var key = getKeyFromID(id);
+ delete rootByKey[key];
+ }
+}
+
+function getRegisteredIDs() {
+ if (canUseCollections) {
+ return Array.from(itemMap.keys());
+ } else {
+ return Object.keys(itemByKey).map(getIDFromKey);
+ }
+}
+
+function getRootIDs() {
+ if (canUseCollections) {
+ return Array.from(rootIDSet.keys());
+ } else {
+ return Object.keys(rootByKey).map(getIDFromKey);
+ }
+}
+
+function purgeDeep(id) {
+ var item = get(id);
+ if (item) {
+ var childIDs = item.childIDs;
+
+ remove(id);
+ childIDs.forEach(purgeDeep);
+ }
+}
+
+function describeComponentFrame(name, source, ownerName) {
+ return '\n in ' + name + (source ? ' (at ' + source.fileName.replace(/^.*[\\\/]/, '') + ':' + source.lineNumber + ')' : ownerName ? ' (created by ' + ownerName + ')' : '');
+}
+
+function getDisplayName(element) {
+ if (element == null) {
+ return '#empty';
+ } else if (typeof element === 'string' || typeof element === 'number') {
+ return '#text';
+ } else if (typeof element.type === 'string') {
+ return element.type;
+ } else {
+ return element.type.displayName || element.type.name || 'Unknown';
+ }
+}
+
+function describeID(id) {
+ var name = ReactComponentTreeHook.getDisplayName(id);
+ var element = ReactComponentTreeHook.getElement(id);
+ var ownerID = ReactComponentTreeHook.getOwnerID(id);
+ var ownerName;
+ if (ownerID) {
+ ownerName = ReactComponentTreeHook.getDisplayName(ownerID);
+ }
+ "development" !== 'production' ? warning(element, 'ReactComponentTreeHook: Missing React element for debugID %s when ' + 'building stack', id) : void 0;
+ return describeComponentFrame(name, element && element._source, ownerName);
+}
+
+var ReactComponentTreeHook = {
+ onSetChildren: function (id, nextChildIDs) {
+ var item = get(id);
+ item.childIDs = nextChildIDs;
+
+ for (var i = 0; i < nextChildIDs.length; i++) {
+ var nextChildID = nextChildIDs[i];
+ var nextChild = get(nextChildID);
+ !nextChild ? "development" !== 'production' ? invariant(false, 'Expected hook events to fire for the child before its parent includes it in onSetChildren().') : _prodInvariant('140') : void 0;
+ !(nextChild.childIDs != null || typeof nextChild.element !== 'object' || nextChild.element == null) ? "development" !== 'production' ? invariant(false, 'Expected onSetChildren() to fire for a container child before its parent includes it in onSetChildren().') : _prodInvariant('141') : void 0;
+ !nextChild.isMounted ? "development" !== 'production' ? invariant(false, 'Expected onMountComponent() to fire for the child before its parent includes it in onSetChildren().') : _prodInvariant('71') : void 0;
+ if (nextChild.parentID == null) {
+ nextChild.parentID = id;
+ // TODO: This shouldn't be necessary but mounting a new root during in
+ // componentWillMount currently causes not-yet-mounted components to
+ // be purged from our tree data so their parent ID is missing.
+ }
+ !(nextChild.parentID === id) ? "development" !== 'production' ? invariant(false, 'Expected onBeforeMountComponent() parent and onSetChildren() to be consistent (%s has parents %s and %s).', nextChildID, nextChild.parentID, id) : _prodInvariant('142', nextChildID, nextChild.parentID, id) : void 0;
+ }
+ },
+ onBeforeMountComponent: function (id, element, parentID) {
+ create(id, element, parentID);
+ },
+ onBeforeUpdateComponent: function (id, element) {
+ var item = get(id);
+ if (!item || !item.isMounted) {
+ // We may end up here as a result of setState() in componentWillUnmount().
+ // In this case, ignore the element.
+ return;
+ }
+ item.element = element;
+ },
+ onMountComponent: function (id) {
+ var item = get(id);
+ item.isMounted = true;
+ var isRoot = item.parentID === 0;
+ if (isRoot) {
+ addRoot(id);
+ }
+ },
+ onUpdateComponent: function (id) {
+ var item = get(id);
+ if (!item || !item.isMounted) {
+ // We may end up here as a result of setState() in componentWillUnmount().
+ // In this case, ignore the element.
+ return;
+ }
+ item.updateCount++;
+ },
+ onUnmountComponent: function (id) {
+ var item = get(id);
+ if (item) {
+ // We need to check if it exists.
+ // `item` might not exist if it is inside an error boundary, and a sibling
+ // error boundary child threw while mounting. Then this instance never
+ // got a chance to mount, but it still gets an unmounting event during
+ // the error boundary cleanup.
+ item.isMounted = false;
+ var isRoot = item.parentID === 0;
+ if (isRoot) {
+ removeRoot(id);
+ }
+ }
+ unmountedIDs.push(id);
+ },
+ purgeUnmountedComponents: function () {
+ if (ReactComponentTreeHook._preventPurging) {
+ // Should only be used for testing.
+ return;
+ }
+
+ for (var i = 0; i < unmountedIDs.length; i++) {
+ var id = unmountedIDs[i];
+ purgeDeep(id);
+ }
+ unmountedIDs.length = 0;
+ },
+ isMounted: function (id) {
+ var item = get(id);
+ return item ? item.isMounted : false;
+ },
+ getCurrentStackAddendum: function (topElement) {
+ var info = '';
+ if (topElement) {
+ var type = topElement.type;
+ var name = typeof type === 'function' ? type.displayName || type.name : type;
+ var owner = topElement._owner;
+ info += describeComponentFrame(name || 'Unknown', topElement._source, owner && owner.getName());
+ }
+
+ var currentOwner = ReactCurrentOwner.current;
+ var id = currentOwner && currentOwner._debugID;
+
+ info += ReactComponentTreeHook.getStackAddendumByID(id);
+ return info;
+ },
+ getStackAddendumByID: function (id) {
+ var info = '';
+ while (id) {
+ info += describeID(id);
+ id = ReactComponentTreeHook.getParentID(id);
+ }
+ return info;
+ },
+ getChildIDs: function (id) {
+ var item = get(id);
+ return item ? item.childIDs : [];
+ },
+ getDisplayName: function (id) {
+ var element = ReactComponentTreeHook.getElement(id);
+ if (!element) {
+ return null;
+ }
+ return getDisplayName(element);
+ },
+ getElement: function (id) {
+ var item = get(id);
+ return item ? item.element : null;
+ },
+ getOwnerID: function (id) {
+ var element = ReactComponentTreeHook.getElement(id);
+ if (!element || !element._owner) {
+ return null;
+ }
+ return element._owner._debugID;
+ },
+ getParentID: function (id) {
+ var item = get(id);
+ return item ? item.parentID : null;
+ },
+ getSource: function (id) {
+ var item = get(id);
+ var element = item ? item.element : null;
+ var source = element != null ? element._source : null;
+ return source;
+ },
+ getText: function (id) {
+ var element = ReactComponentTreeHook.getElement(id);
+ if (typeof element === 'string') {
+ return element;
+ } else if (typeof element === 'number') {
+ return '' + element;
+ } else {
+ return null;
+ }
+ },
+ getUpdateCount: function (id) {
+ var item = get(id);
+ return item ? item.updateCount : 0;
+ },
+
+
+ getRegisteredIDs: getRegisteredIDs,
+
+ getRootIDs: getRootIDs
+};
+
+module.exports = ReactComponentTreeHook;
+},{"153":153,"178":178,"187":187,"41":41}],39:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactComponentWithPureRenderMixin
*/
'use strict';
-var shallowCompare = _dereq_(140);
+var shallowCompare = _dereq_(157);
/**
* If your React component's render function is "pure", e.g. it will render the
- * same result given the same props and state, provide this Mixin for a
+ * same result given the same props and state, provide this mixin for a
* considerable performance boost.
*
* Most React components have pure render functions.
*
* Example:
*
* var ReactComponentWithPureRenderMixin =
* require('ReactComponentWithPureRenderMixin');
@@ -5734,70 +6220,105 @@ var shallowCompare = _dereq_(140);
* return <div className={this.props.className}>foo</div>;
* }
* });
*
* Note: This only checks shallow equality for props and state. If these contain
* complex data structures this mixin may have false-negatives for deeper
* differences. Only mixin to components which have simple props and state, or
* use `forceUpdate()` when you know deep data structures have changed.
+ *
+ * See https://facebook.github.io/react/docs/pure-render-mixin.html
*/
var ReactComponentWithPureRenderMixin = {
shouldComponentUpdate: function (nextProps, nextState) {
return shallowCompare(this, nextProps, nextState);
}
};
module.exports = ReactComponentWithPureRenderMixin;
-},{"140":140}],38:[function(_dereq_,module,exports){
-/**
- * Copyright 2013-2015, Facebook, Inc.
+},{"157":157}],40:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactCompositeComponent
*/
'use strict';
-var ReactComponentEnvironment = _dereq_(36);
-var ReactCurrentOwner = _dereq_(39);
-var ReactElement = _dereq_(57);
-var ReactInstanceMap = _dereq_(68);
-var ReactPerf = _dereq_(78);
-var ReactPropTypeLocations = _dereq_(81);
-var ReactPropTypeLocationNames = _dereq_(80);
-var ReactReconciler = _dereq_(84);
-var ReactUpdateQueue = _dereq_(95);
-
-var assign = _dereq_(24);
-var emptyObject = _dereq_(154);
-var invariant = _dereq_(161);
-var shouldUpdateReactComponent = _dereq_(141);
-var warning = _dereq_(173);
-
-function getDeclarationErrorAddendum(component) {
- var owner = component._currentElement._owner || null;
- if (owner) {
- var name = owner.getName();
- if (name) {
- return ' Check the render method of `' + name + '`.';
- }
- }
- return '';
-}
+var _prodInvariant = _dereq_(153),
+ _assign = _dereq_(188);
+
+var ReactComponentEnvironment = _dereq_(37);
+var ReactCurrentOwner = _dereq_(41);
+var ReactElement = _dereq_(65);
+var ReactErrorUtils = _dereq_(68);
+var ReactInstanceMap = _dereq_(77);
+var ReactInstrumentation = _dereq_(78);
+var ReactNodeTypes = _dereq_(85);
+var ReactPropTypeLocations = _dereq_(90);
+var ReactReconciler = _dereq_(95);
+
+var checkReactTypeSpec = _dereq_(132);
+var emptyObject = _dereq_(171);
+var invariant = _dereq_(178);
+var shallowEqual = _dereq_(186);
+var shouldUpdateReactComponent = _dereq_(158);
+var warning = _dereq_(187);
+
+var CompositeTypes = {
+ ImpureClass: 0,
+ PureClass: 1,
+ StatelessFunctional: 2
+};
function StatelessComponent(Component) {}
StatelessComponent.prototype.render = function () {
var Component = ReactInstanceMap.get(this)._currentElement.type;
- return Component(this.props, this.context, this.updater);
-};
+ var element = Component(this.props, this.context, this.updater);
+ warnIfInvalidElement(Component, element);
+ return element;
+};
+
+function warnIfInvalidElement(Component, element) {
+ if ("development" !== 'production') {
+ "development" !== 'production' ? warning(element === null || element === false || ReactElement.isValidElement(element), '%s(...): A valid React element (or null) must be returned. You may have ' + 'returned undefined, an array or some other invalid object.', Component.displayName || Component.name || 'Component') : void 0;
+ "development" !== 'production' ? warning(!Component.childContextTypes, '%s(...): childContextTypes cannot be defined on a functional component.', Component.displayName || Component.name || 'Component') : void 0;
+ }
+}
+
+function shouldConstruct(Component) {
+ return !!(Component.prototype && Component.prototype.isReactComponent);
+}
+
+function isPureComponent(Component) {
+ return !!(Component.prototype && Component.prototype.isPureReactComponent);
+}
+
+// Separated into a function to contain deoptimizations caused by try/finally.
+function measureLifeCyclePerf(fn, debugID, timerType) {
+ if (debugID === 0) {
+ // Top-level wrappers (see ReactMount) and empty components (see
+ // ReactDOMEmptyComponent) are invisible to hooks and devtools.
+ // Both are implementation details that should go away in the future.
+ return fn();
+ }
+
+ ReactInstrumentation.debugTool.onBeginLifeCycleTimer(debugID, timerType);
+ try {
+ return fn();
+ } finally {
+ ReactInstrumentation.debugTool.onEndLifeCycleTimer(debugID, timerType);
+ }
+}
/**
* ------------------ The Life-Cycle of a Composite Component ------------------
*
* - constructor: Initialization of state. The instance is now retained.
* - componentWillMount
* - render
* - [children's constructors]
@@ -5838,183 +6359,323 @@ var ReactCompositeComponentMixin = {
* Base constructor for all composite component.
*
* @param {ReactElement} element
* @final
* @internal
*/
construct: function (element) {
this._currentElement = element;
- this._rootNodeID = null;
+ this._rootNodeID = 0;
+ this._compositeType = null;
this._instance = null;
+ this._hostParent = null;
+ this._hostContainerInfo = null;
// See ReactUpdateQueue
+ this._updateBatchNumber = null;
this._pendingElement = null;
this._pendingStateQueue = null;
this._pendingReplaceState = false;
this._pendingForceUpdate = false;
+ this._renderedNodeType = null;
this._renderedComponent = null;
-
this._context = null;
this._mountOrder = 0;
this._topLevelWrapper = null;
// See ReactUpdates and ReactUpdateQueue.
this._pendingCallbacks = null;
+
+ // ComponentWillUnmount shall only be called once
+ this._calledComponentWillUnmount = false;
+
+ if ("development" !== 'production') {
+ this._warnedAboutRefsInRender = false;
+ }
},
/**
* Initializes the component, renders markup, and registers event listeners.
*
- * @param {string} rootID DOM ID of the root node.
* @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
+ * @param {?object} hostParent
+ * @param {?object} hostContainerInfo
+ * @param {?object} context
* @return {?string} Rendered markup to be inserted into the DOM.
* @final
* @internal
*/
- mountComponent: function (rootID, transaction, context) {
+ mountComponent: function (transaction, hostParent, hostContainerInfo, context) {
+ var _this = this;
+
this._context = context;
this._mountOrder = nextMountID++;
- this._rootNodeID = rootID;
-
- var publicProps = this._processProps(this._currentElement.props);
+ this._hostParent = hostParent;
+ this._hostContainerInfo = hostContainerInfo;
+
+ var publicProps = this._currentElement.props;
var publicContext = this._processContext(context);
var Component = this._currentElement.type;
+ var updateQueue = transaction.getUpdateQueue();
+
// Initialize the public class
- var inst;
+ var doConstruct = shouldConstruct(Component);
+ var inst = this._constructComponent(doConstruct, publicProps, publicContext, updateQueue);
var renderedElement;
- // This is a way to detect if Component is a stateless arrow function
- // component, which is not newable. It might not be 100% reliable but is
- // something we can do until we start detecting that Component extends
- // React.Component. We already assume that typeof Component === 'function'.
- var canInstantiate = ('prototype' in Component);
-
- if (canInstantiate) {
- if ("development" !== 'production') {
- ReactCurrentOwner.current = this;
- try {
- inst = new Component(publicProps, publicContext, ReactUpdateQueue);
- } finally {
- ReactCurrentOwner.current = null;
- }
+ // Support functional components
+ if (!doConstruct && (inst == null || inst.render == null)) {
+ renderedElement = inst;
+ warnIfInvalidElement(Component, renderedElement);
+ !(inst === null || inst === false || ReactElement.isValidElement(inst)) ? "development" !== 'production' ? invariant(false, '%s(...): A valid React element (or null) must be returned. You may have returned undefined, an array or some other invalid object.', Component.displayName || Component.name || 'Component') : _prodInvariant('105', Component.displayName || Component.name || 'Component') : void 0;
+ inst = new StatelessComponent(Component);
+ this._compositeType = CompositeTypes.StatelessFunctional;
+ } else {
+ if (isPureComponent(Component)) {
+ this._compositeType = CompositeTypes.PureClass;
} else {
- inst = new Component(publicProps, publicContext, ReactUpdateQueue);
- }
- }
-
- if (!canInstantiate || inst === null || inst === false || ReactElement.isValidElement(inst)) {
- renderedElement = inst;
- inst = new StatelessComponent(Component);
+ this._compositeType = CompositeTypes.ImpureClass;
+ }
}
if ("development" !== 'production') {
// This will throw later in _renderValidatedComponent, but add an early
// warning now to help debugging
if (inst.render == null) {
- "development" !== 'production' ? warning(false, '%s(...): No `render` method found on the returned component ' + 'instance: you may have forgotten to define `render`, returned ' + 'null/false from a stateless component, or tried to render an ' + 'element whose type is a function that isn\'t a React component.', Component.displayName || Component.name || 'Component') : undefined;
- } else {
- // We support ES6 inheriting from React.Component, the module pattern,
- // and stateless components, but not ES6 classes that don't extend
- "development" !== 'production' ? warning(Component.prototype && Component.prototype.isReactComponent || !canInstantiate || !(inst instanceof Component), '%s(...): React component classes must extend React.Component.', Component.displayName || Component.name || 'Component') : undefined;
- }
+ "development" !== 'production' ? warning(false, '%s(...): No `render` method found on the returned component ' + 'instance: you may have forgotten to define `render`.', Component.displayName || Component.name || 'Component') : void 0;
+ }
+
+ var propsMutated = inst.props !== publicProps;
+ var componentName = Component.displayName || Component.name || 'Component';
+
+ "development" !== 'production' ? warning(inst.props === undefined || !propsMutated, '%s(...): When calling super() in `%s`, make sure to pass ' + 'up the same props that your component\'s constructor was passed.', componentName, componentName) : void 0;
}
// These should be set up in the constructor, but as a convenience for
// simpler class abstractions, we set them up after the fact.
inst.props = publicProps;
inst.context = publicContext;
inst.refs = emptyObject;
- inst.updater = ReactUpdateQueue;
+ inst.updater = updateQueue;
this._instance = inst;
// Store a reference from the instance back to the internal representation
ReactInstanceMap.set(inst, this);
if ("development" !== 'production') {
// Since plain JS classes are defined without any special initialization
// logic, we can not catch common errors early. Therefore, we have to
// catch them here, at initialization time, instead.
- "development" !== 'production' ? warning(!inst.getInitialState || inst.getInitialState.isReactClassApproved, 'getInitialState was defined on %s, a plain JavaScript class. ' + 'This is only supported for classes created using React.createClass. ' + 'Did you mean to define a state property instead?', this.getName() || 'a component') : undefined;
- "development" !== 'production' ? warning(!inst.getDefaultProps || inst.getDefaultProps.isReactClassApproved, 'getDefaultProps was defined on %s, a plain JavaScript class. ' + 'This is only supported for classes created using React.createClass. ' + 'Use a static property to define defaultProps instead.', this.getName() || 'a component') : undefined;
- "development" !== 'production' ? warning(!inst.propTypes, 'propTypes was defined as an instance property on %s. Use a static ' + 'property to define propTypes instead.', this.getName() || 'a component') : undefined;
- "development" !== 'production' ? warning(!inst.contextTypes, 'contextTypes was defined as an instance property on %s. Use a ' + 'static property to define contextTypes instead.', this.getName() || 'a component') : undefined;
- "development" !== 'production' ? warning(typeof inst.componentShouldUpdate !== 'function', '%s has a method called ' + 'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' + 'The name is phrased as a question because the function is ' + 'expected to return a value.', this.getName() || 'A component') : undefined;
- "development" !== 'production' ? warning(typeof inst.componentDidUnmount !== 'function', '%s has a method called ' + 'componentDidUnmount(). But there is no such lifecycle method. ' + 'Did you mean componentWillUnmount()?', this.getName() || 'A component') : undefined;
- "development" !== 'production' ? warning(typeof inst.componentWillRecieveProps !== 'function', '%s has a method called ' + 'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?', this.getName() || 'A component') : undefined;
+ "development" !== 'production' ? warning(!inst.getInitialState || inst.getInitialState.isReactClassApproved, 'getInitialState was defined on %s, a plain JavaScript class. ' + 'This is only supported for classes created using React.createClass. ' + 'Did you mean to define a state property instead?', this.getName() || 'a component') : void 0;
+ "development" !== 'production' ? warning(!inst.getDefaultProps || inst.getDefaultProps.isReactClassApproved, 'getDefaultProps was defined on %s, a plain JavaScript class. ' + 'This is only supported for classes created using React.createClass. ' + 'Use a static property to define defaultProps instead.', this.getName() || 'a component') : void 0;
+ "development" !== 'production' ? warning(!inst.propTypes, 'propTypes was defined as an instance property on %s. Use a static ' + 'property to define propTypes instead.', this.getName() || 'a component') : void 0;
+ "development" !== 'production' ? warning(!inst.contextTypes, 'contextTypes was defined as an instance property on %s. Use a ' + 'static property to define contextTypes instead.', this.getName() || 'a component') : void 0;
+ "development" !== 'production' ? warning(typeof inst.componentShouldUpdate !== 'function', '%s has a method called ' + 'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' + 'The name is phrased as a question because the function is ' + 'expected to return a value.', this.getName() || 'A component') : void 0;
+ "development" !== 'production' ? warning(typeof inst.componentDidUnmount !== 'function', '%s has a method called ' + 'componentDidUnmount(). But there is no such lifecycle method. ' + 'Did you mean componentWillUnmount()?', this.getName() || 'A component') : void 0;
+ "development" !== 'production' ? warning(typeof inst.componentWillRecieveProps !== 'function', '%s has a method called ' + 'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?', this.getName() || 'A component') : void 0;
}
var initialState = inst.state;
if (initialState === undefined) {
inst.state = initialState = null;
}
- !(typeof initialState === 'object' && !Array.isArray(initialState)) ? "development" !== 'production' ? invariant(false, '%s.state: must be set to an object or null', this.getName() || 'ReactCompositeComponent') : invariant(false) : undefined;
+ !(typeof initialState === 'object' && !Array.isArray(initialState)) ? "development" !== 'production' ? invariant(false, '%s.state: must be set to an object or null', this.getName() || 'ReactCompositeComponent') : _prodInvariant('106', this.getName() || 'ReactCompositeComponent') : void 0;
this._pendingStateQueue = null;
this._pendingReplaceState = false;
this._pendingForceUpdate = false;
+ var markup;
+ if (inst.unstable_handleError) {
+ markup = this.performInitialMountWithErrorHandling(renderedElement, hostParent, hostContainerInfo, transaction, context);
+ } else {
+ markup = this.performInitialMount(renderedElement, hostParent, hostContainerInfo, transaction, context);
+ }
+
+ if (inst.componentDidMount) {
+ if ("development" !== 'production') {
+ transaction.getReactMountReady().enqueue(function () {
+ measureLifeCyclePerf(function () {
+ return inst.componentDidMount();
+ }, _this._debugID, 'componentDidMount');
+ });
+ } else {
+ transaction.getReactMountReady().enqueue(inst.componentDidMount, inst);
+ }
+ }
+
+ return markup;
+ },
+
+ _constructComponent: function (doConstruct, publicProps, publicContext, updateQueue) {
+ if ("development" !== 'production') {
+ ReactCurrentOwner.current = this;
+ try {
+ return this._constructComponentWithoutOwner(doConstruct, publicProps, publicContext, updateQueue);
+ } finally {
+ ReactCurrentOwner.current = null;
+ }
+ } else {
+ return this._constructComponentWithoutOwner(doConstruct, publicProps, publicContext, updateQueue);
+ }
+ },
+
+ _constructComponentWithoutOwner: function (doConstruct, publicProps, publicContext, updateQueue) {
+ var Component = this._currentElement.type;
+
+ if (doConstruct) {
+ if ("development" !== 'production') {
+ return measureLifeCyclePerf(function () {
+ return new Component(publicProps, publicContext, updateQueue);
+ }, this._debugID, 'ctor');
+ } else {
+ return new Component(publicProps, publicContext, updateQueue);
+ }
+ }
+
+ // This can still be an instance in case of factory components
+ // but we'll count this as time spent rendering as the more common case.
+ if ("development" !== 'production') {
+ return measureLifeCyclePerf(function () {
+ return Component(publicProps, publicContext, updateQueue);
+ }, this._debugID, 'render');
+ } else {
+ return Component(publicProps, publicContext, updateQueue);
+ }
+ },
+
+ performInitialMountWithErrorHandling: function (renderedElement, hostParent, hostContainerInfo, transaction, context) {
+ var markup;
+ var checkpoint = transaction.checkpoint();
+ try {
+ markup = this.performInitialMount(renderedElement, hostParent, hostContainerInfo, transaction, context);
+ } catch (e) {
+ // Roll back to checkpoint, handle error (which may add items to the transaction), and take a new checkpoint
+ transaction.rollback(checkpoint);
+ this._instance.unstable_handleError(e);
+ if (this._pendingStateQueue) {
+ this._instance.state = this._processPendingState(this._instance.props, this._instance.context);
+ }
+ checkpoint = transaction.checkpoint();
+
+ this._renderedComponent.unmountComponent(true);
+ transaction.rollback(checkpoint);
+
+ // Try again - we've informed the component about the error, so they can render an error message this time.
+ // If this throws again, the error will bubble up (and can be caught by a higher error boundary).
+ markup = this.performInitialMount(renderedElement, hostParent, hostContainerInfo, transaction, context);
+ }
+ return markup;
+ },
+
+ performInitialMount: function (renderedElement, hostParent, hostContainerInfo, transaction, context) {
+ var inst = this._instance;
+
+ var debugID = 0;
+ if ("development" !== 'production') {
+ debugID = this._debugID;
+ }
+
if (inst.componentWillMount) {
- inst.componentWillMount();
+ if ("development" !== 'production') {
+ measureLifeCyclePerf(function () {
+ return inst.componentWillMount();
+ }, debugID, 'componentWillMount');
+ } else {
+ inst.componentWillMount();
+ }
// When mounting, calls to `setState` by `componentWillMount` will set
// `this._pendingStateQueue` without triggering a re-render.
if (this._pendingStateQueue) {
inst.state = this._processPendingState(inst.props, inst.context);
}
}
// If not a stateless component, we now render
if (renderedElement === undefined) {
renderedElement = this._renderValidatedComponent();
}
- this._renderedComponent = this._instantiateReactComponent(renderedElement);
-
- var markup = ReactReconciler.mountComponent(this._renderedComponent, rootID, transaction, this._processChildContext(context));
- if (inst.componentDidMount) {
- transaction.getReactMountReady().enqueue(inst.componentDidMount, inst);
+ var nodeType = ReactNodeTypes.getType(renderedElement);
+ this._renderedNodeType = nodeType;
+ var child = this._instantiateReactComponent(renderedElement, nodeType !== ReactNodeTypes.EMPTY /* shouldHaveDebugID */
+ );
+ this._renderedComponent = child;
+
+ var markup = ReactReconciler.mountComponent(child, transaction, hostParent, hostContainerInfo, this._processChildContext(context), debugID);
+
+ if ("development" !== 'production') {
+ if (debugID !== 0) {
+ var childDebugIDs = child._debugID !== 0 ? [child._debugID] : [];
+ ReactInstrumentation.debugTool.onSetChildren(debugID, childDebugIDs);
+ }
}
return markup;
},
+ getHostNode: function () {
+ return ReactReconciler.getHostNode(this._renderedComponent);
+ },
+
/**
* Releases any resources allocated by `mountComponent`.
*
* @final
* @internal
*/
- unmountComponent: function () {
+ unmountComponent: function (safely) {
+ if (!this._renderedComponent) {
+ return;
+ }
+
var inst = this._instance;
- if (inst.componentWillUnmount) {
- inst.componentWillUnmount();
- }
-
- ReactReconciler.unmountComponent(this._renderedComponent);
- this._renderedComponent = null;
- this._instance = null;
+ if (inst.componentWillUnmount && !inst._calledComponentWillUnmount) {
+ inst._calledComponentWillUnmount = true;
+
+ if (safely) {
+ var name = this.getName() + '.componentWillUnmount()';
+ ReactErrorUtils.invokeGuardedCallback(name, inst.componentWillUnmount.bind(inst));
+ } else {
+ if ("development" !== 'production') {
+ measureLifeCyclePerf(function () {
+ return inst.componentWillUnmount();
+ }, this._debugID, 'componentWillUnmount');
+ } else {
+ inst.componentWillUnmount();
+ }
+ }
+ }
+
+ if (this._renderedComponent) {
+ ReactReconciler.unmountComponent(this._renderedComponent, safely);
+ this._renderedNodeType = null;
+ this._renderedComponent = null;
+ this._instance = null;
+ }
// Reset pending fields
// Even if this component is scheduled for another update in ReactUpdates,
// it would still be ignored because these fields are reset.
this._pendingStateQueue = null;
this._pendingReplaceState = false;
this._pendingForceUpdate = false;
this._pendingCallbacks = null;
this._pendingElement = null;
// These fields do not really need to be reset since this object is no
// longer accessible.
this._context = null;
- this._rootNodeID = null;
+ this._rootNodeID = 0;
this._topLevelWrapper = null;
// Delete the reference from the instance to this internal representation
// which allow the internals to be properly cleaned up even if the user
// leaks a reference to the public instance.
ReactInstanceMap.remove(inst);
// Some existing components rely on inst.props even after they've been
@@ -6028,23 +6689,22 @@ var ReactCompositeComponentMixin = {
* Filters the context object to only contain keys specified in
* `contextTypes`
*
* @param {object} context
* @return {?object}
* @private
*/
_maskContext: function (context) {
- var maskedContext = null;
var Component = this._currentElement.type;
var contextTypes = Component.contextTypes;
if (!contextTypes) {
return emptyObject;
}
- maskedContext = {};
+ var maskedContext = {};
for (var contextName in contextTypes) {
maskedContext[contextName] = context[contextName];
}
return maskedContext;
},
/**
* Filters the context object to only contain keys specified in
@@ -6054,101 +6714,68 @@ var ReactCompositeComponentMixin = {
* @return {?object}
* @private
*/
_processContext: function (context) {
var maskedContext = this._maskContext(context);
if ("development" !== 'production') {
var Component = this._currentElement.type;
if (Component.contextTypes) {
- this._checkPropTypes(Component.contextTypes, maskedContext, ReactPropTypeLocations.context);
+ this._checkContextTypes(Component.contextTypes, maskedContext, ReactPropTypeLocations.context);
}
}
return maskedContext;
},
/**
* @param {object} currentContext
* @return {object}
* @private
*/
_processChildContext: function (currentContext) {
var Component = this._currentElement.type;
var inst = this._instance;
- var childContext = inst.getChildContext && inst.getChildContext();
+ var childContext;
+
+ if (inst.getChildContext) {
+ if ("development" !== 'production') {
+ ReactInstrumentation.debugTool.onBeginProcessingChildContext();
+ try {
+ childContext = inst.getChildContext();
+ } finally {
+ ReactInstrumentation.debugTool.onEndProcessingChildContext();
+ }
+ } else {
+ childContext = inst.getChildContext();
+ }
+ }
+
if (childContext) {
- !(typeof Component.childContextTypes === 'object') ? "development" !== 'production' ? invariant(false, '%s.getChildContext(): childContextTypes must be defined in order to ' + 'use getChildContext().', this.getName() || 'ReactCompositeComponent') : invariant(false) : undefined;
+ !(typeof Component.childContextTypes === 'object') ? "development" !== 'production' ? invariant(false, '%s.getChildContext(): childContextTypes must be defined in order to use getChildContext().', this.getName() || 'ReactCompositeComponent') : _prodInvariant('107', this.getName() || 'ReactCompositeComponent') : void 0;
if ("development" !== 'production') {
- this._checkPropTypes(Component.childContextTypes, childContext, ReactPropTypeLocations.childContext);
+ this._checkContextTypes(Component.childContextTypes, childContext, ReactPropTypeLocations.childContext);
}
for (var name in childContext) {
- !(name in Component.childContextTypes) ? "development" !== 'production' ? invariant(false, '%s.getChildContext(): key "%s" is not defined in childContextTypes.', this.getName() || 'ReactCompositeComponent', name) : invariant(false) : undefined;
- }
- return assign({}, currentContext, childContext);
+ !(name in Component.childContextTypes) ? "development" !== 'production' ? invariant(false, '%s.getChildContext(): key "%s" is not defined in childContextTypes.', this.getName() || 'ReactCompositeComponent', name) : _prodInvariant('108', this.getName() || 'ReactCompositeComponent', name) : void 0;
+ }
+ return _assign({}, currentContext, childContext);
}
return currentContext;
},
/**
- * Processes props by setting default values for unspecified props and
- * asserting that the props are valid. Does not mutate its argument; returns
- * a new props object with defaults merged in.
- *
- * @param {object} newProps
- * @return {object}
- * @private
- */
- _processProps: function (newProps) {
- if ("development" !== 'production') {
- var Component = this._currentElement.type;
- if (Component.propTypes) {
- this._checkPropTypes(Component.propTypes, newProps, ReactPropTypeLocations.prop);
- }
- }
- return newProps;
- },
-
- /**
- * Assert that the props are valid
- *
- * @param {object} propTypes Map of prop name to a ReactPropType
- * @param {object} props
+ * Assert that the context types are valid
+ *
+ * @param {object} typeSpecs Map of context field to a ReactPropType
+ * @param {object} values Runtime values that need to be type-checked
* @param {string} location e.g. "prop", "context", "child context"
* @private
*/
- _checkPropTypes: function (propTypes, props, location) {
- // TODO: Stop validating prop types here and only use the element
- // validation.
- var componentName = this.getName();
- for (var propName in propTypes) {
- if (propTypes.hasOwnProperty(propName)) {
- var error;
- try {
- // This is intentionally an invariant that gets caught. It's the same
- // behavior as without this statement except with a better message.
- !(typeof propTypes[propName] === 'function') ? "development" !== 'production' ? invariant(false, '%s: %s type `%s` is invalid; it must be a function, usually ' + 'from React.PropTypes.', componentName || 'React class', ReactPropTypeLocationNames[location], propName) : invariant(false) : undefined;
- error = propTypes[propName](props, propName, componentName, location);
- } catch (ex) {
- error = ex;
- }
- if (error instanceof Error) {
- // We may want to extend this logic for similar errors in
- // top-level render calls, so I'm abstracting it away into
- // a function to minimize refactoring in the future
- var addendum = getDeclarationErrorAddendum(this);
-
- if (location === ReactPropTypeLocations.prop) {
- // Preface gives us something to blacklist in warning module
- "development" !== 'production' ? warning(false, 'Failed Composite propType: %s%s', error.message, addendum) : undefined;
- } else {
- "development" !== 'production' ? warning(false, 'Failed Context Types: %s%s', error.message, addendum) : undefined;
- }
- }
- }
- }
+ _checkContextTypes: function (typeSpecs, values, location) {
+ checkReactTypeSpec(typeSpecs, values, location, this.getName(), null, this._debugID);
},
receiveComponent: function (nextElement, transaction, nextContext) {
var prevElement = this._currentElement;
var prevContext = this._context;
this._pendingElement = null;
@@ -6159,21 +6786,21 @@ var ReactCompositeComponentMixin = {
* If any of `_pendingElement`, `_pendingStateQueue`, or `_pendingForceUpdate`
* is set, update the component.
*
* @param {ReactReconcileTransaction} transaction
* @internal
*/
performUpdateIfNecessary: function (transaction) {
if (this._pendingElement != null) {
- ReactReconciler.receiveComponent(this, this._pendingElement || this._currentElement, transaction, this._context);
- }
-
- if (this._pendingStateQueue !== null || this._pendingForceUpdate) {
+ ReactReconciler.receiveComponent(this, this._pendingElement, transaction, this._context);
+ } else if (this._pendingStateQueue !== null || this._pendingForceUpdate) {
this.updateComponent(transaction, this._currentElement, this._currentElement, this._context, this._context);
+ } else {
+ this._updateBatchNumber = null;
}
},
/**
* Perform an update to a mounted component. The componentWillReceiveProps and
* shouldComponentUpdate methods are called, then (assuming the update isn't
* skipped) the remaining update lifecycle methods are called and the DOM
* representation is updated.
@@ -6184,44 +6811,74 @@ var ReactCompositeComponentMixin = {
* @param {ReactReconcileTransaction} transaction
* @param {ReactElement} prevParentElement
* @param {ReactElement} nextParentElement
* @internal
* @overridable
*/
updateComponent: function (transaction, prevParentElement, nextParentElement, prevUnmaskedContext, nextUnmaskedContext) {
var inst = this._instance;
-
- var nextContext = this._context === nextUnmaskedContext ? inst.context : this._processContext(nextUnmaskedContext);
- var nextProps;
-
- // Distinguish between a props update versus a simple state update
- if (prevParentElement === nextParentElement) {
- // Skip checking prop types again -- we don't read inst.props to avoid
- // warning for DOM component props in this upgrade
- nextProps = nextParentElement.props;
- } else {
- nextProps = this._processProps(nextParentElement.props);
- // An update here will schedule an update but immediately set
- // _pendingStateQueue which will ensure that any state updates gets
- // immediately reconciled instead of waiting for the next batch.
-
- if (inst.componentWillReceiveProps) {
+ !(inst != null) ? "development" !== 'production' ? invariant(false, 'Attempted to update component `%s` that has already been unmounted (or failed to mount).', this.getName() || 'ReactCompositeComponent') : _prodInvariant('136', this.getName() || 'ReactCompositeComponent') : void 0;
+
+ var willReceive = false;
+ var nextContext;
+
+ // Determine if the context has changed or not
+ if (this._context === nextUnmaskedContext) {
+ nextContext = inst.context;
+ } else {
+ nextContext = this._processContext(nextUnmaskedContext);
+ willReceive = true;
+ }
+
+ var prevProps = prevParentElement.props;
+ var nextProps = nextParentElement.props;
+
+ // Not a simple state update but a props update
+ if (prevParentElement !== nextParentElement) {
+ willReceive = true;
+ }
+
+ // An update here will schedule an update but immediately set
+ // _pendingStateQueue which will ensure that any state updates gets
+ // immediately reconciled instead of waiting for the next batch.
+ if (willReceive && inst.componentWillReceiveProps) {
+ if ("development" !== 'production') {
+ measureLifeCyclePerf(function () {
+ return inst.componentWillReceiveProps(nextProps, nextContext);
+ }, this._debugID, 'componentWillReceiveProps');
+ } else {
inst.componentWillReceiveProps(nextProps, nextContext);
}
}
var nextState = this._processPendingState(nextProps, nextContext);
-
- var shouldUpdate = this._pendingForceUpdate || !inst.shouldComponentUpdate || inst.shouldComponentUpdate(nextProps, nextState, nextContext);
-
- if ("development" !== 'production') {
- "development" !== 'production' ? warning(typeof shouldUpdate !== 'undefined', '%s.shouldComponentUpdate(): Returned undefined instead of a ' + 'boolean value. Make sure to return true or false.', this.getName() || 'ReactCompositeComponent') : undefined;
- }
-
+ var shouldUpdate = true;
+
+ if (!this._pendingForceUpdate) {
+ if (inst.shouldComponentUpdate) {
+ if ("development" !== 'production') {
+ shouldUpdate = measureLifeCyclePerf(function () {
+ return inst.shouldComponentUpdate(nextProps, nextState, nextContext);
+ }, this._debugID, 'shouldComponentUpdate');
+ } else {
+ shouldUpdate = inst.shouldComponentUpdate(nextProps, nextState, nextContext);
+ }
+ } else {
+ if (this._compositeType === CompositeTypes.PureClass) {
+ shouldUpdate = !shallowEqual(prevProps, nextProps) || !shallowEqual(inst.state, nextState);
+ }
+ }
+ }
+
+ if ("development" !== 'production') {
+ "development" !== 'production' ? warning(shouldUpdate !== undefined, '%s.shouldComponentUpdate(): Returned undefined instead of a ' + 'boolean value. Make sure to return true or false.', this.getName() || 'ReactCompositeComponent') : void 0;
+ }
+
+ this._updateBatchNumber = null;
if (shouldUpdate) {
this._pendingForceUpdate = false;
// Will set `this.props`, `this.state` and `this.context`.
this._performComponentUpdate(nextParentElement, nextProps, nextState, nextContext, transaction, nextUnmaskedContext);
} else {
// If it's determined that a component should not update, we still want
// to set props and state but we shortcut the rest of the update.
this._currentElement = nextParentElement;
@@ -6242,20 +6899,20 @@ var ReactCompositeComponentMixin = {
if (!queue) {
return inst.state;
}
if (replace && queue.length === 1) {
return queue[0];
}
- var nextState = assign({}, replace ? queue[0] : inst.state);
+ var nextState = _assign({}, replace ? queue[0] : inst.state);
for (var i = replace ? 1 : 0; i < queue.length; i++) {
var partial = queue[i];
- assign(nextState, typeof partial === 'function' ? partial.call(inst, nextState, props, context) : partial);
+ _assign(nextState, typeof partial === 'function' ? partial.call(inst, nextState, props, context) : partial);
}
return nextState;
},
/**
* Merges new props and state, notifies delegate methods of update and
* performs update.
@@ -6264,126 +6921,173 @@ var ReactCompositeComponentMixin = {
* @param {object} nextProps Next public object to set as properties.
* @param {?object} nextState Next object to set as state.
* @param {?object} nextContext Next public object to set as context.
* @param {ReactReconcileTransaction} transaction
* @param {?object} unmaskedContext
* @private
*/
_performComponentUpdate: function (nextElement, nextProps, nextState, nextContext, transaction, unmaskedContext) {
+ var _this2 = this;
+
var inst = this._instance;
var hasComponentDidUpdate = Boolean(inst.componentDidUpdate);
var prevProps;
var prevState;
var prevContext;
if (hasComponentDidUpdate) {
prevProps = inst.props;
prevState = inst.state;
prevContext = inst.context;
}
if (inst.componentWillUpdate) {
- inst.componentWillUpdate(nextProps, nextState, nextContext);
+ if ("development" !== 'production') {
+ measureLifeCyclePerf(function () {
+ return inst.componentWillUpdate(nextProps, nextState, nextContext);
+ }, this._debugID, 'componentWillUpdate');
+ } else {
+ inst.componentWillUpdate(nextProps, nextState, nextContext);
+ }
}
this._currentElement = nextElement;
this._context = unmaskedContext;
inst.props = nextProps;
inst.state = nextState;
inst.context = nextContext;
this._updateRenderedComponent(transaction, unmaskedContext);
if (hasComponentDidUpdate) {
- transaction.getReactMountReady().enqueue(inst.componentDidUpdate.bind(inst, prevProps, prevState, prevContext), inst);
+ if ("development" !== 'production') {
+ transaction.getReactMountReady().enqueue(function () {
+ measureLifeCyclePerf(inst.componentDidUpdate.bind(inst, prevProps, prevState, prevContext), _this2._debugID, 'componentDidUpdate');
+ });
+ } else {
+ transaction.getReactMountReady().enqueue(inst.componentDidUpdate.bind(inst, prevProps, prevState, prevContext), inst);
+ }
}
},
/**
* Call the component's `render` method and update the DOM accordingly.
*
* @param {ReactReconcileTransaction} transaction
* @internal
*/
_updateRenderedComponent: function (transaction, context) {
var prevComponentInstance = this._renderedComponent;
var prevRenderedElement = prevComponentInstance._currentElement;
var nextRenderedElement = this._renderValidatedComponent();
+
+ var debugID = 0;
+ if ("development" !== 'production') {
+ debugID = this._debugID;
+ }
+
if (shouldUpdateReactComponent(prevRenderedElement, nextRenderedElement)) {
ReactReconciler.receiveComponent(prevComponentInstance, nextRenderedElement, transaction, this._processChildContext(context));
} else {
- // These two IDs are actually the same! But nothing should rely on that.
- var thisID = this._rootNodeID;
- var prevComponentID = prevComponentInstance._rootNodeID;
- ReactReconciler.unmountComponent(prevComponentInstance);
-
- this._renderedComponent = this._instantiateReactComponent(nextRenderedElement);
- var nextMarkup = ReactReconciler.mountComponent(this._renderedComponent, thisID, transaction, this._processChildContext(context));
- this._replaceNodeWithMarkupByID(prevComponentID, nextMarkup);
- }
- },
-
- /**
+ var oldHostNode = ReactReconciler.getHostNode(prevComponentInstance);
+ ReactReconciler.unmountComponent(prevComponentInstance, false);
+
+ var nodeType = ReactNodeTypes.getType(nextRenderedElement);
+ this._renderedNodeType = nodeType;
+ var child = this._instantiateReactComponent(nextRenderedElement, nodeType !== ReactNodeTypes.EMPTY /* shouldHaveDebugID */
+ );
+ this._renderedComponent = child;
+
+ var nextMarkup = ReactReconciler.mountComponent(child, transaction, this._hostParent, this._hostContainerInfo, this._processChildContext(context), debugID);
+
+ if ("development" !== 'production') {
+ if (debugID !== 0) {
+ var childDebugIDs = child._debugID !== 0 ? [child._debugID] : [];
+ ReactInstrumentation.debugTool.onSetChildren(debugID, childDebugIDs);
+ }
+ }
+
+ this._replaceNodeWithMarkup(oldHostNode, nextMarkup, prevComponentInstance);
+ }
+ },
+
+ /**
+ * Overridden in shallow rendering.
+ *
* @protected
*/
- _replaceNodeWithMarkupByID: function (prevComponentID, nextMarkup) {
- ReactComponentEnvironment.replaceNodeWithMarkupByID(prevComponentID, nextMarkup);
+ _replaceNodeWithMarkup: function (oldHostNode, nextMarkup, prevInstance) {
+ ReactComponentEnvironment.replaceNodeWithMarkup(oldHostNode, nextMarkup, prevInstance);
},
/**
* @protected
*/
_renderValidatedComponentWithoutOwnerOrContext: function () {
var inst = this._instance;
- var renderedComponent = inst.render();
+ var renderedComponent;
+
+ if ("development" !== 'production') {
+ renderedComponent = measureLifeCyclePerf(function () {
+ return inst.render();
+ }, this._debugID, 'render');
+ } else {
+ renderedComponent = inst.render();
+ }
+
if ("development" !== 'production') {
// We allow auto-mocks to proceed as if they're returning null.
- if (typeof renderedComponent === 'undefined' && inst.render._isMockFunction) {
+ if (renderedComponent === undefined && inst.render._isMockFunction) {
// This is probably bad practice. Consider warning here and
// deprecating this convenience.
renderedComponent = null;
}
}
return renderedComponent;
},
/**
* @private
*/
_renderValidatedComponent: function () {
var renderedComponent;
- ReactCurrentOwner.current = this;
- try {
+ if ("development" !== 'production' || this._compositeType !== CompositeTypes.StatelessFunctional) {
+ ReactCurrentOwner.current = this;
+ try {
+ renderedComponent = this._renderValidatedComponentWithoutOwnerOrContext();
+ } finally {
+ ReactCurrentOwner.current = null;
+ }
+ } else {
renderedComponent = this._renderValidatedComponentWithoutOwnerOrContext();
- } finally {
- ReactCurrentOwner.current = null;
}
!(
// TODO: An `isValidNode` function would probably be more appropriate
- renderedComponent === null || renderedComponent === false || ReactElement.isValidElement(renderedComponent)) ? "development" !== 'production' ? invariant(false, '%s.render(): A valid ReactComponent must be returned. You may have ' + 'returned undefined, an array or some other invalid object.', this.getName() || 'ReactCompositeComponent') : invariant(false) : undefined;
+ renderedComponent === null || renderedComponent === false || ReactElement.isValidElement(renderedComponent)) ? "development" !== 'production' ? invariant(false, '%s.render(): A valid React element (or null) must be returned. You may have returned undefined, an array or some other invalid object.', this.getName() || 'ReactCompositeComponent') : _prodInvariant('109', this.getName() || 'ReactCompositeComponent') : void 0;
+
return renderedComponent;
},
/**
* Lazily allocates the refs object and stores `component` as `ref`.
*
* @param {string} ref Reference name.
* @param {component} component Component to store as `ref`.
* @final
* @private
*/
attachRef: function (ref, component) {
var inst = this.getPublicInstance();
- !(inst != null) ? "development" !== 'production' ? invariant(false, 'Stateless function components cannot have refs.') : invariant(false) : undefined;
+ !(inst != null) ? "development" !== 'production' ? invariant(false, 'Stateless function components cannot have refs.') : _prodInvariant('110') : void 0;
var publicComponentInstance = component.getPublicInstance();
if ("development" !== 'production') {
var componentName = component && component.getName ? component.getName() : 'a component';
- "development" !== 'production' ? warning(publicComponentInstance != null, 'Stateless function components cannot be given refs ' + '(See ref "%s" in %s created by %s). ' + 'Attempts to access this ref will fail.', ref, componentName, this.getName()) : undefined;
+ "development" !== 'production' ? warning(publicComponentInstance != null || component._compositeType !== CompositeTypes.StatelessFunctional, 'Stateless function components cannot be given refs ' + '(See ref "%s" in %s created by %s). ' + 'Attempts to access this ref will fail.', ref, componentName, this.getName()) : void 0;
}
var refs = inst.refs === emptyObject ? inst.refs = {} : inst.refs;
refs[ref] = publicComponentInstance;
},
/**
* Detaches a reference name.
*
@@ -6413,43 +7117,37 @@ var ReactCompositeComponentMixin = {
* is exposed by refs and returned by render. Can be null for stateless
* components.
*
* @return {ReactComponent} the public component instance.
* @internal
*/
getPublicInstance: function () {
var inst = this._instance;
- if (inst instanceof StatelessComponent) {
+ if (this._compositeType === CompositeTypes.StatelessFunctional) {
return null;
}
return inst;
},
// Stub
_instantiateReactComponent: null
};
-ReactPerf.measureMethods(ReactCompositeComponentMixin, 'ReactCompositeComponent', {
- mountComponent: 'mountComponent',
- updateComponent: 'updateComponent',
- _renderValidatedComponent: '_renderValidatedComponent'
-});
-
var ReactCompositeComponent = {
Mixin: ReactCompositeComponentMixin
};
module.exports = ReactCompositeComponent;
-},{"141":141,"154":154,"161":161,"173":173,"24":24,"36":36,"39":39,"57":57,"68":68,"78":78,"80":80,"81":81,"84":84,"95":95}],39:[function(_dereq_,module,exports){
-/**
- * Copyright 2013-2015, Facebook, Inc.
+},{"132":132,"153":153,"158":158,"171":171,"178":178,"186":186,"187":187,"188":188,"37":37,"41":41,"65":65,"68":68,"77":77,"78":78,"85":85,"90":90,"95":95}],41:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactCurrentOwner
*/
@@ -6457,308 +7155,245 @@ module.exports = ReactCompositeComponent
'use strict';
/**
* Keeps track of the current owner.
*
* The current owner is the component who should own any components that are
* currently being constructed.
*/
+
var ReactCurrentOwner = {
/**
* @internal
* @type {ReactComponent}
*/
current: null
};
module.exports = ReactCurrentOwner;
-},{}],40:[function(_dereq_,module,exports){
-/**
- * Copyright 2013-2015, Facebook, Inc.
+},{}],42:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactDOM
*/
/* globals __REACT_DEVTOOLS_GLOBAL_HOOK__*/
'use strict';
-var ReactCurrentOwner = _dereq_(39);
-var ReactDOMTextComponent = _dereq_(51);
-var ReactDefaultInjection = _dereq_(54);
-var ReactInstanceHandles = _dereq_(67);
-var ReactMount = _dereq_(72);
-var ReactPerf = _dereq_(78);
-var ReactReconciler = _dereq_(84);
-var ReactUpdates = _dereq_(96);
-var ReactVersion = _dereq_(97);
-
-var findDOMNode = _dereq_(122);
-var renderSubtreeIntoContainer = _dereq_(137);
-var warning = _dereq_(173);
+var ReactDOMComponentTree = _dereq_(46);
+var ReactDefaultInjection = _dereq_(64);
+var ReactMount = _dereq_(82);
+var ReactReconciler = _dereq_(95);
+var ReactUpdates = _dereq_(107);
+var ReactVersion = _dereq_(108);
+
+var findDOMNode = _dereq_(136);
+var getHostComponentFromComposite = _dereq_(143);
+var renderSubtreeIntoContainer = _dereq_(154);
+var warning = _dereq_(187);
ReactDefaultInjection.inject();
-var render = ReactPerf.measure('React', 'render', ReactMount.render);
-
-var React = {
+var ReactDOM = {
findDOMNode: findDOMNode,
- render: render,
+ render: ReactMount.render,
unmountComponentAtNode: ReactMount.unmountComponentAtNode,
version: ReactVersion,
/* eslint-disable camelcase */
unstable_batchedUpdates: ReactUpdates.batchedUpdates,
unstable_renderSubtreeIntoContainer: renderSubtreeIntoContainer
};
// Inject the runtime into a devtools global hook regardless of browser.
// Allows for debugging when the hook is injected on the page.
-/* eslint-enable camelcase */
if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' && typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.inject === 'function') {
__REACT_DEVTOOLS_GLOBAL_HOOK__.inject({
- CurrentOwner: ReactCurrentOwner,
- InstanceHandles: ReactInstanceHandles,
+ ComponentTree: {
+ getClosestInstanceFromNode: ReactDOMComponentTree.getClosestInstanceFromNode,
+ getNodeFromInstance: function (inst) {
+ // inst is an internal instance (but could be a composite)
+ if (inst._renderedComponent) {
+ inst = getHostComponentFromComposite(inst);
+ }
+ if (inst) {
+ return ReactDOMComponentTree.getNodeFromInstance(inst);
+ } else {
+ return null;
+ }
+ }
+ },
Mount: ReactMount,
- Reconciler: ReactReconciler,
- TextComponent: ReactDOMTextComponent
+ Reconciler: ReactReconciler
});
}
if ("development" !== 'production') {
- var ExecutionEnvironment = _dereq_(147);
+ var ExecutionEnvironment = _dereq_(164);
if (ExecutionEnvironment.canUseDOM && window.top === window.self) {
// First check if devtools is not installed
if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined') {
// If we're in Chrome or Firefox, provide a download link if not installed.
if (navigator.userAgent.indexOf('Chrome') > -1 && navigator.userAgent.indexOf('Edge') === -1 || navigator.userAgent.indexOf('Firefox') > -1) {
- console.debug('Download the React DevTools for a better development experience: ' + 'https://fb.me/react-devtools');
- }
- }
+ // Firefox does not have the issue with devtools loaded over file://
+ var showFileUrlMessage = window.location.protocol.indexOf('http') === -1 && navigator.userAgent.indexOf('Firefox') === -1;
+ console.debug('Download the React DevTools ' + (showFileUrlMessage ? 'and use an HTTP server (instead of a file: URL) ' : '') + 'for a better development experience: ' + 'https://fb.me/react-devtools');
+ }
+ }
+
+ var testFunc = function testFn() {};
+ "development" !== 'production' ? warning((testFunc.name || testFunc.toString()).indexOf('testFn') !== -1, 'It looks like you\'re using a minified copy of the development build ' + 'of React. When deploying React apps to production, make sure to use ' + 'the production build which skips development warnings and is faster. ' + 'See https://fb.me/react-minification for more details.') : void 0;
// If we're in IE8, check to see if we are in compatibility mode and provide
// information on preventing compatibility mode
var ieCompatibilityMode = document.documentMode && document.documentMode < 8;
- "development" !== 'production' ? warning(!ieCompatibilityMode, 'Internet Explorer is running in compatibility mode; please add the ' + 'following tag to your HTML to prevent this from happening: ' + '<meta http-equiv="X-UA-Compatible" content="IE=edge" />') : undefined;
+ "development" !== 'production' ? warning(!ieCompatibilityMode, 'Internet Explorer is running in compatibility mode; please add the ' + 'following tag to your HTML to prevent this from happening: ' + '<meta http-equiv="X-UA-Compatible" content="IE=edge" />') : void 0;
var expectedFeatures = [
// shims
- Array.isArray, Array.prototype.every, Array.prototype.forEach, Array.prototype.indexOf, Array.prototype.map, Date.now, Function.prototype.bind, Object.keys, String.prototype.split, String.prototype.trim,
-
- // shams
- Object.create, Object.freeze];
+ Array.isArray, Array.prototype.every, Array.prototype.forEach, Array.prototype.indexOf, Array.prototype.map, Date.now, Function.prototype.bind, Object.keys, String.prototype.split, String.prototype.trim];
for (var i = 0; i < expectedFeatures.length; i++) {
if (!expectedFeatures[i]) {
- console.error('One or more ES5 shim/shams expected by React are not available: ' + 'https://fb.me/react-warning-polyfills');
- break;
- }
- }
- }
-}
-
-module.exports = React;
-},{"122":122,"137":137,"147":147,"173":173,"39":39,"51":51,"54":54,"67":67,"72":72,"78":78,"84":84,"96":96,"97":97}],41:[function(_dereq_,module,exports){
-/**
- * Copyright 2013-2015, Facebook, Inc.
+ "development" !== 'production' ? warning(false, 'One or more ES5 shims expected by React are not available: ' + 'https://fb.me/react-warning-polyfills') : void 0;
+ break;
+ }
+ }
+ }
+}
+
+if ("development" !== 'production') {
+ var ReactInstrumentation = _dereq_(78);
+ var ReactDOMUnknownPropertyHook = _dereq_(61);
+ var ReactDOMNullInputValuePropHook = _dereq_(53);
+
+ ReactInstrumentation.debugTool.addHook(ReactDOMUnknownPropertyHook);
+ ReactInstrumentation.debugTool.addHook(ReactDOMNullInputValuePropHook);
+}
+
+module.exports = ReactDOM;
+},{"107":107,"108":108,"136":136,"143":143,"154":154,"164":164,"187":187,"46":46,"53":53,"61":61,"64":64,"78":78,"82":82,"95":95}],43:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactDOMButton
*/
'use strict';
-var mouseListenerNames = {
- onClick: true,
- onDoubleClick: true,
- onMouseDown: true,
- onMouseMove: true,
- onMouseUp: true,
-
- onClickCapture: true,
- onDoubleClickCapture: true,
- onMouseDownCapture: true,
- onMouseMoveCapture: true,
- onMouseUpCapture: true
-};
-
-/**
- * Implements a <button> native component that does not receive mouse events
+var DisabledInputUtils = _dereq_(14);
+
+/**
+ * Implements a <button> host component that does not receive mouse events
* when `disabled` is set.
*/
var ReactDOMButton = {
- getNativeProps: function (inst, props, context) {
- if (!props.disabled) {
- return props;
- }
-
- // Copy the props, except the mouse listeners
- var nativeProps = {};
- for (var key in props) {
- if (props.hasOwnProperty(key) && !mouseListenerNames[key]) {
- nativeProps[key] = props[key];
- }
- }
-
- return nativeProps;
- }
+ getHostProps: DisabledInputUtils.getHostProps
};
module.exports = ReactDOMButton;
-},{}],42:[function(_dereq_,module,exports){
-/**
- * Copyright 2013-2015, Facebook, Inc.
+},{"14":14}],44:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactDOMComponent
- * @typechecks static-only
*/
/* global hasOwnProperty:true */
'use strict';
-var AutoFocusUtils = _dereq_(2);
-var CSSPropertyOperations = _dereq_(5);
+var _prodInvariant = _dereq_(153),
+ _assign = _dereq_(188);
+
+var AutoFocusUtils = _dereq_(1);
+var CSSPropertyOperations = _dereq_(4);
+var DOMLazyTree = _dereq_(8);
+var DOMNamespaces = _dereq_(9);
var DOMProperty = _dereq_(10);
var DOMPropertyOperations = _dereq_(11);
-var EventConstants = _dereq_(15);
+var EventConstants = _dereq_(16);
+var EventPluginHub = _dereq_(17);
+var EventPluginRegistry = _dereq_(18);
var ReactBrowserEventEmitter = _dereq_(28);
-var ReactComponentBrowserEnvironment = _dereq_(35);
-var ReactDOMButton = _dereq_(41);
-var ReactDOMInput = _dereq_(46);
-var ReactDOMOption = _dereq_(47);
-var ReactDOMSelect = _dereq_(48);
-var ReactDOMTextarea = _dereq_(52);
-var ReactMount = _dereq_(72);
-var ReactMultiChild = _dereq_(73);
-var ReactPerf = _dereq_(78);
-var ReactUpdateQueue = _dereq_(95);
-
-var assign = _dereq_(24);
-var canDefineProperty = _dereq_(117);
-var escapeTextContentForBrowser = _dereq_(121);
-var invariant = _dereq_(161);
-var isEventSupported = _dereq_(133);
-var keyOf = _dereq_(166);
-var setInnerHTML = _dereq_(138);
-var setTextContent = _dereq_(139);
-var shallowEqual = _dereq_(171);
-var validateDOMNesting = _dereq_(144);
-var warning = _dereq_(173);
-
-var deleteListener = ReactBrowserEventEmitter.deleteListener;
+var ReactDOMButton = _dereq_(43);
+var ReactDOMComponentFlags = _dereq_(45);
+var ReactDOMComponentTree = _dereq_(46);
+var ReactDOMInput = _dereq_(52);
+var ReactDOMOption = _dereq_(54);
+var ReactDOMSelect = _dereq_(55);
+var ReactDOMTextarea = _dereq_(59);
+var ReactInstrumentation = _dereq_(78);
+var ReactMultiChild = _dereq_(83);
+var ReactServerRenderingTransaction = _dereq_(99);
+
+var emptyFunction = _dereq_(170);
+var escapeTextContentForBrowser = _dereq_(135);
+var invariant = _dereq_(178);
+var isEventSupported = _dereq_(149);
+var keyOf = _dereq_(182);
+var shallowEqual = _dereq_(186);
+var validateDOMNesting = _dereq_(161);
+var warning = _dereq_(187);
+
+var Flags = ReactDOMComponentFlags;
+var deleteListener = EventPluginHub.deleteListener;
+var getNode = ReactDOMComponentTree.getNodeFromInstance;
var listenTo = ReactBrowserEventEmitter.listenTo;
-var registrationNameModules = ReactBrowserEventEmitter.registrationNameModules;
+var registrationNameModules = EventPluginRegistry.registrationNameModules;
// For quickly matching children type, to test if can be treated as content.
var CONTENT_TYPES = { 'string': true, 'number': true };
-var CHILDREN = keyOf({ children: null });
var STYLE = keyOf({ style: null });
var HTML = keyOf({ __html: null });
-
-var ELEMENT_NODE_TYPE = 1;
+var RESERVED_PROPS = {
+ children: null,
+ dangerouslySetInnerHTML: null,
+ suppressContentEditableWarning: null
+};
+
+// Node type for document fragments (Node.DOCUMENT_FRAGMENT_NODE).
+var DOC_FRAGMENT_TYPE = 11;
function getDeclarationErrorAddendum(internalInstance) {
if (internalInstance) {
var owner = internalInstance._currentElement._owner || null;
if (owner) {
var name = owner.getName();
if (name) {
return ' This DOM node was rendered by `' + name + '`.';
}
}
}
return '';
}
-var legacyPropsDescriptor;
-if ("development" !== 'production') {
- legacyPropsDescriptor = {
- props: {
- enumerable: false,
- get: function () {
- var component = this._reactInternalComponent;
- "development" !== 'production' ? warning(false, 'ReactDOMComponent: Do not access .props of a DOM node; instead, ' + 'recreate the props as `render` did originally or read the DOM ' + 'properties/attributes directly from this node (e.g., ' + 'this.refs.box.className).%s', getDeclarationErrorAddendum(component)) : undefined;
- return component._currentElement.props;
- }
- }
- };
-}
-
-function legacyGetDOMNode() {
- if ("development" !== 'production') {
- var component = this._reactInternalComponent;
- "development" !== 'production' ? warning(false, 'ReactDOMComponent: Do not access .getDOMNode() of a DOM node; ' + 'instead, use the node directly.%s', getDeclarationErrorAddendum(component)) : undefined;
- }
- return this;
-}
-
-function legacyIsMounted() {
- var component = this._reactInternalComponent;
- if ("development" !== 'production') {
- "development" !== 'production' ? warning(false, 'ReactDOMComponent: Do not access .isMounted() of a DOM node.%s', getDeclarationErrorAddendum(component)) : undefined;
- }
- return !!component;
-}
-
-function legacySetStateEtc() {
- if ("development" !== 'production') {
- var component = this._reactInternalComponent;
- "development" !== 'production' ? warning(false, 'ReactDOMComponent: Do not access .setState(), .replaceState(), or ' + '.forceUpdate() of a DOM node. This is a no-op.%s', getDeclarationErrorAddendum(component)) : undefined;
- }
-}
-
-function legacySetProps(partialProps, callback) {
- var component = this._reactInternalComponent;
- if ("development" !== 'production') {
- "development" !== 'production' ? warning(false, 'ReactDOMComponent: Do not access .setProps() of a DOM node. ' + 'Instead, call ReactDOM.render again at the top level.%s', getDeclarationErrorAddendum(component)) : undefined;
- }
- if (!component) {
- return;
- }
- ReactUpdateQueue.enqueueSetPropsInternal(component, partialProps);
- if (callback) {
- ReactUpdateQueue.enqueueCallbackInternal(component, callback);
- }
-}
-
-function legacyReplaceProps(partialProps, callback) {
- var component = this._reactInternalComponent;
- if ("development" !== 'production') {
- "development" !== 'production' ? warning(false, 'ReactDOMComponent: Do not access .replaceProps() of a DOM node. ' + 'Instead, call ReactDOM.render again at the top level.%s', getDeclarationErrorAddendum(component)) : undefined;
- }
- if (!component) {
- return;
- }
- ReactUpdateQueue.enqueueReplacePropsInternal(component, partialProps);
- if (callback) {
- ReactUpdateQueue.enqueueCallbackInternal(component, callback);
- }
-}
-
function friendlyStringify(obj) {
if (typeof obj === 'object') {
if (Array.isArray(obj)) {
return '[' + obj.map(friendlyStringify).join(', ') + ']';
} else {
var pairs = [];
for (var key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
@@ -6768,17 +7403,17 @@ function friendlyStringify(obj) {
}
return '{' + pairs.join(', ') + '}';
}
} else if (typeof obj === 'string') {
return JSON.stringify(obj);
} else if (typeof obj === 'function') {
return '[function object]';
}
- // Differs from JSON.stringify in that undefined becauses undefined and that
+ // Differs from JSON.stringify in that undefined because undefined and that
// inf and nan don't become null
return String(obj);
}
var styleMutationWarning = {};
function checkAndWarnForMutatedStyle(style1, style2, component) {
if (style1 == null || style2 == null) {
@@ -6798,65 +7433,110 @@ function checkAndWarnForMutatedStyle(sty
var hash = ownerName + '|' + componentName;
if (styleMutationWarning.hasOwnProperty(hash)) {
return;
}
styleMutationWarning[hash] = true;
- "development" !== 'production' ? warning(false, '`%s` was passed a style object that has previously been mutated. ' + 'Mutating `style` is deprecated. Consider cloning it beforehand. Check ' + 'the `render` %s. Previous style: %s. Mutated style: %s.', componentName, owner ? 'of `' + ownerName + '`' : 'using <' + componentName + '>', friendlyStringify(style1), friendlyStringify(style2)) : undefined;
+ "development" !== 'production' ? warning(false, '`%s` was passed a style object that has previously been mutated. ' + 'Mutating `style` is deprecated. Consider cloning it beforehand. Check ' + 'the `render` %s. Previous style: %s. Mutated style: %s.', componentName, owner ? 'of `' + ownerName + '`' : 'using <' + componentName + '>', friendlyStringify(style1), friendlyStringify(style2)) : void 0;
}
/**
* @param {object} component
* @param {?object} props
*/
function assertValidProps(component, props) {
if (!props) {
return;
}
// Note the use of `==` which checks for null or undefined.
- if ("development" !== 'production') {
- if (voidElementTags[component._tag]) {
- "development" !== 'production' ? warning(props.children == null && props.dangerouslySetInnerHTML == null, '%s is a void element tag and must not have `children` or ' + 'use `props.dangerouslySetInnerHTML`.%s', component._tag, component._currentElement._owner ? ' Check the render method of ' + component._currentElement._owner.getName() + '.' : '') : undefined;
- }
+ if (voidElementTags[component._tag]) {
+ !(props.children == null && props.dangerouslySetInnerHTML == null) ? "development" !== 'production' ? invariant(false, '%s is a void element tag and must neither have `children` nor use `dangerouslySetInnerHTML`.%s', component._tag, component._currentElement._owner ? ' Check the render method of ' + component._currentElement._owner.getName() + '.' : '') : _prodInvariant('137', component._tag, component._currentElement._owner ? ' Check the render method of ' + component._currentElement._owner.getName() + '.' : '') : void 0;
}
if (props.dangerouslySetInnerHTML != null) {
- !(props.children == null) ? "development" !== 'production' ? invariant(false, 'Can only set one of `children` or `props.dangerouslySetInnerHTML`.') : invariant(false) : undefined;
- !(typeof props.dangerouslySetInnerHTML === 'object' && HTML in props.dangerouslySetInnerHTML) ? "development" !== 'production' ? invariant(false, '`props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`. ' + 'Please visit https://fb.me/react-invariant-dangerously-set-inner-html ' + 'for more information.') : invariant(false) : undefined;
+ !(props.children == null) ? "development" !== 'production' ? invariant(false, 'Can only set one of `children` or `props.dangerouslySetInnerHTML`.') : _prodInvariant('60') : void 0;
+ !(typeof props.dangerouslySetInnerHTML === 'object' && HTML in props.dangerouslySetInnerHTML) ? "development" !== 'production' ? invariant(false, '`props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`. Please visit https://fb.me/react-invariant-dangerously-set-inner-html for more information.') : _prodInvariant('61') : void 0;
}
if ("development" !== 'production') {
- "development" !== 'production' ? warning(props.innerHTML == null, 'Directly setting property `innerHTML` is not permitted. ' + 'For more information, lookup documentation on `dangerouslySetInnerHTML`.') : undefined;
- "development" !== 'production' ? warning(!props.contentEditable || props.children == null, 'A component is `contentEditable` and contains `children` managed by ' + 'React. It is now your responsibility to guarantee that none of ' + 'those nodes are unexpectedly modified or duplicated. This is ' + 'probably not intentional.') : undefined;
- }
- !(props.style == null || typeof props.style === 'object') ? "development" !== 'production' ? invariant(false, 'The `style` prop expects a mapping from style properties to values, ' + 'not a string. For example, style={{marginRight: spacing + \'em\'}} when ' + 'using JSX.%s', getDeclarationErrorAddendum(component)) : invariant(false) : undefined;
-}
-
-function enqueuePutListener(id, registrationName, listener, transaction) {
+ "development" !== 'production' ? warning(props.innerHTML == null, 'Directly setting property `innerHTML` is not permitted. ' + 'For more information, lookup documentation on `dangerouslySetInnerHTML`.') : void 0;
+ "development" !== 'production' ? warning(props.suppressContentEditableWarning || !props.contentEditable || props.children == null, 'A component is `contentEditable` and contains `children` managed by ' + 'React. It is now your responsibility to guarantee that none of ' + 'those nodes are unexpectedly modified or duplicated. This is ' + 'probably not intentional.') : void 0;
+ "development" !== 'production' ? warning(props.onFocusIn == null && props.onFocusOut == null, 'React uses onFocus and onBlur instead of onFocusIn and onFocusOut. ' + 'All React events are normalized to bubble, so onFocusIn and onFocusOut ' + 'are not needed/supported by React.') : void 0;
+ }
+ !(props.style == null || typeof props.style === 'object') ? "development" !== 'production' ? invariant(false, 'The `style` prop expects a mapping from style properties to values, not a string. For example, style={{marginRight: spacing + \'em\'}} when using JSX.%s', getDeclarationErrorAddendum(component)) : _prodInvariant('62', getDeclarationErrorAddendum(component)) : void 0;
+}
+
+function enqueuePutListener(inst, registrationName, listener, transaction) {
+ if (transaction instanceof ReactServerRenderingTransaction) {
+ return;
+ }
if ("development" !== 'production') {
// IE8 has no API for event capturing and the `onScroll` event doesn't
// bubble.
- "development" !== 'production' ? warning(registrationName !== 'onScroll' || isEventSupported('scroll', true), 'This browser doesn\'t support the `onScroll` event') : undefined;
- }
- var container = ReactMount.findReactContainerForID(id);
- if (container) {
- var doc = container.nodeType === ELEMENT_NODE_TYPE ? container.ownerDocument : container;
- listenTo(registrationName, doc);
- }
+ "development" !== 'production' ? warning(registrationName !== 'onScroll' || isEventSupported('scroll', true), 'This browser doesn\'t support the `onScroll` event') : void 0;
+ }
+ var containerInfo = inst._hostContainerInfo;
+ var isDocumentFragment = containerInfo._node && containerInfo._node.nodeType === DOC_FRAGMENT_TYPE;
+ var doc = isDocumentFragment ? containerInfo._node : containerInfo._ownerDocument;
+ listenTo(registrationName, doc);
transaction.getReactMountReady().enqueue(putListener, {
- id: id,
+ inst: inst,
registrationName: registrationName,
listener: listener
});
}
function putListener() {
var listenerToPut = this;
- ReactBrowserEventEmitter.putListener(listenerToPut.id, listenerToPut.registrationName, listenerToPut.listener);
+ EventPluginHub.putListener(listenerToPut.inst, listenerToPut.registrationName, listenerToPut.listener);
+}
+
+function inputPostMount() {
+ var inst = this;
+ ReactDOMInput.postMountWrapper(inst);
+}
+
+function textareaPostMount() {
+ var inst = this;
+ ReactDOMTextarea.postMountWrapper(inst);
+}
+
+function optionPostMount() {
+ var inst = this;
+ ReactDOMOption.postMountWrapper(inst);
+}
+
+var setAndValidateContentChildDev = emptyFunction;
+if ("development" !== 'production') {
+ setAndValidateContentChildDev = function (content) {
+ var hasExistingContent = this._contentDebugID != null;
+ var debugID = this._debugID;
+ // This ID represents the inlined child that has no backing instance:
+ var contentDebugID = -debugID;
+
+ if (content == null) {
+ if (hasExistingContent) {
+ ReactInstrumentation.debugTool.onUnmountComponent(this._contentDebugID);
+ }
+ this._contentDebugID = null;
+ return;
+ }
+
+ validateDOMNesting(null, String(content), this, this._ancestorInfo);
+ this._contentDebugID = contentDebugID;
+ if (hasExistingContent) {
+ ReactInstrumentation.debugTool.onBeforeUpdateComponent(contentDebugID, content);
+ ReactInstrumentation.debugTool.onUpdateComponent(contentDebugID);
+ } else {
+ ReactInstrumentation.debugTool.onBeforeMountComponent(contentDebugID, content, debugID);
+ ReactInstrumentation.debugTool.onMountComponent(contentDebugID);
+ ReactInstrumentation.debugTool.onSetChildren(debugID, [contentDebugID]);
+ }
+ };
}
// There are so many media events, it makes sense to just
// maintain a list rather than create a `trapBubbledEvent` for each
var mediaEvents = {
topAbort: 'abort',
topCanPlay: 'canplay',
topCanPlayThrough: 'canplaythrough',
@@ -6881,55 +7561,59 @@ var mediaEvents = {
topVolumeChange: 'volumechange',
topWaiting: 'waiting'
};
function trapBubbledEventsLocal() {
var inst = this;
// If a component renders to null or if another component fatals and causes
// the state of the tree to be corrupted, `node` here can be null.
- !inst._rootNodeID ? "development" !== 'production' ? invariant(false, 'Must be mounted to trap events') : invariant(false) : undefined;
- var node = ReactMount.getNode(inst._rootNodeID);
- !node ? "development" !== 'production' ? invariant(false, 'trapBubbledEvent(...): Requires node to be rendered.') : invariant(false) : undefined;
+ !inst._rootNodeID ? "development" !== 'production' ? invariant(false, 'Must be mounted to trap events') : _prodInvariant('63') : void 0;
+ var node = getNode(inst);
+ !node ? "development" !== 'production' ? invariant(false, 'trapBubbledEvent(...): Requires node to be rendered.') : _prodInvariant('64') : void 0;
switch (inst._tag) {
case 'iframe':
+ case 'object':
inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topLoad, 'load', node)];
break;
case 'video':
case 'audio':
inst._wrapperState.listeners = [];
- // create listener for each media event
+ // Create listener for each media event
for (var event in mediaEvents) {
if (mediaEvents.hasOwnProperty(event)) {
inst._wrapperState.listeners.push(ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes[event], mediaEvents[event], node));
}
}
-
+ break;
+ case 'source':
+ inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topError, 'error', node)];
break;
case 'img':
inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topError, 'error', node), ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topLoad, 'load', node)];
break;
case 'form':
inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topReset, 'reset', node), ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topSubmit, 'submit', node)];
break;
- }
-}
-
-function mountReadyInputWrapper() {
- ReactDOMInput.mountReadyWrapper(this);
+ case 'input':
+ case 'select':
+ case 'textarea':
+ inst._wrapperState.listeners = [ReactBrowserEventEmitter.trapBubbledEvent(EventConstants.topLevelTypes.topInvalid, 'invalid', node)];
+ break;
+ }
}
function postUpdateSelectWrapper() {
ReactDOMSelect.postUpdateWrapper(this);
}
// For HTML, certain tags should omit their close tag. We keep a whitelist for
-// those special cased tags.
+// those special-case tags.
var omittedCloseTags = {
'area': true,
'base': true,
'br': true,
'col': true,
'embed': true,
'hr': true,
@@ -6939,187 +7623,256 @@ var omittedCloseTags = {
'link': true,
'meta': true,
'param': true,
'source': true,
'track': true,
'wbr': true
};
-// NOTE: menuitem's close tag should be omitted, but that causes problems.
var newlineEatingTags = {
'listing': true,
'pre': true,
'textarea': true
};
// For HTML, certain tags cannot have children. This has the same purpose as
// `omittedCloseTags` except that `menuitem` should still have its closing tag.
-var voidElementTags = assign({
+var voidElementTags = _assign({
'menuitem': true
}, omittedCloseTags);
// We accept any tag to be rendered but since this gets injected into arbitrary
// HTML, we want to make sure that it's a safe tag.
// http://www.w3.org/TR/REC-xml/#NT-Name
var VALID_TAG_REGEX = /^[a-zA-Z][a-zA-Z:_\.\-\d]*$/; // Simplified subset
var validatedTagCache = {};
-var hasOwnProperty = ({}).hasOwnProperty;
+var hasOwnProperty = {}.hasOwnProperty;
function validateDangerousTag(tag) {
if (!hasOwnProperty.call(validatedTagCache, tag)) {
- !VALID_TAG_REGEX.test(tag) ? "development" !== 'production' ? invariant(false, 'Invalid tag: %s', tag) : invariant(false) : undefined;
+ !VALID_TAG_REGEX.test(tag) ? "development" !== 'production' ? invariant(false, 'Invalid tag: %s', tag) : _prodInvariant('65', tag) : void 0;
validatedTagCache[tag] = true;
}
}
-function processChildContextDev(context, inst) {
- // Pass down our tag name to child components for validation purposes
- context = assign({}, context);
- var info = context[validateDOMNesting.ancestorInfoContextKey];
- context[validateDOMNesting.ancestorInfoContextKey] = validateDOMNesting.updatedAncestorInfo(info, inst._tag, inst);
- return context;
-}
-
function isCustomComponent(tagName, props) {
return tagName.indexOf('-') >= 0 || props.is != null;
}
+var globalIdCounter = 1;
+
/**
* Creates a new React class that is idempotent and capable of containing other
* React components. It accepts event listeners and DOM properties that are
* valid according to `DOMProperty`.
*
* - Event listeners: `onClick`, `onMouseDown`, etc.
* - DOM properties: `className`, `name`, `title`, etc.
*
* The `style` property functions differently from the DOM API. It accepts an
* object mapping of style properties to values.
*
* @constructor ReactDOMComponent
* @extends ReactMultiChild
*/
-function ReactDOMComponent(tag) {
+function ReactDOMComponent(element) {
+ var tag = element.type;
validateDangerousTag(tag);
+ this._currentElement = element;
this._tag = tag.toLowerCase();
+ this._namespaceURI = null;
this._renderedChildren = null;
this._previousStyle = null;
this._previousStyleCopy = null;
- this._rootNodeID = null;
+ this._hostNode = null;
+ this._hostParent = null;
+ this._rootNodeID = 0;
+ this._domID = 0;
+ this._hostContainerInfo = null;
this._wrapperState = null;
this._topLevelWrapper = null;
- this._nodeWithLegacyProperties = null;
+ this._flags = 0;
if ("development" !== 'production') {
- this._unprocessedContextDev = null;
- this._processedContextDev = null;
+ this._ancestorInfo = null;
+ setAndValidateContentChildDev.call(this, null);
}
}
ReactDOMComponent.displayName = 'ReactDOMComponent';
ReactDOMComponent.Mixin = {
- construct: function (element) {
- this._currentElement = element;
- },
-
/**
* Generates root tag markup then recurses. This method has side effects and
* is not idempotent.
*
* @internal
- * @param {string} rootID The root DOM ID for this node.
* @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
+ * @param {?ReactDOMComponent} the parent component instance
+ * @param {?object} info about the host container
* @param {object} context
* @return {string} The computed markup.
*/
- mountComponent: function (rootID, transaction, context) {
- this._rootNodeID = rootID;
+ mountComponent: function (transaction, hostParent, hostContainerInfo, context) {
+ this._rootNodeID = globalIdCounter++;
+ this._domID = hostContainerInfo._idCounter++;
+ this._hostParent = hostParent;
+ this._hostContainerInfo = hostContainerInfo;
var props = this._currentElement.props;
switch (this._tag) {
+ case 'audio':
+ case 'form':
case 'iframe':
case 'img':
- case 'form':
+ case 'link':
+ case 'object':
+ case 'source':
case 'video':
- case 'audio':
this._wrapperState = {
listeners: null
};
transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this);
break;
case 'button':
- props = ReactDOMButton.getNativeProps(this, props, context);
+ props = ReactDOMButton.getHostProps(this, props, hostParent);
break;
case 'input':
- ReactDOMInput.mountWrapper(this, props, context);
- props = ReactDOMInput.getNativeProps(this, props, context);
+ ReactDOMInput.mountWrapper(this, props, hostParent);
+ props = ReactDOMInput.getHostProps(this, props);
+ transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this);
break;
case 'option':
- ReactDOMOption.mountWrapper(this, props, context);
- props = ReactDOMOption.getNativeProps(this, props, context);
+ ReactDOMOption.mountWrapper(this, props, hostParent);
+ props = ReactDOMOption.getHostProps(this, props);
break;
case 'select':
- ReactDOMSelect.mountWrapper(this, props, context);
- props = ReactDOMSelect.getNativeProps(this, props, context);
- context = ReactDOMSelect.processChildContext(this, props, context);
+ ReactDOMSelect.mountWrapper(this, props, hostParent);
+ props = ReactDOMSelect.getHostProps(this, props);
+ transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this);
break;
case 'textarea':
- ReactDOMTextarea.mountWrapper(this, props, context);
- props = ReactDOMTextarea.getNativeProps(this, props, context);
+ ReactDOMTextarea.mountWrapper(this, props, hostParent);
+ props = ReactDOMTextarea.getHostProps(this, props);
+ transaction.getReactMountReady().enqueue(trapBubbledEventsLocal, this);
break;
}
assertValidProps(this, props);
- if ("development" !== 'production') {
- if (context[validateDOMNesting.ancestorInfoContextKey]) {
- validateDOMNesting(this._tag, this, context[validateDOMNesting.ancestorInfoContextKey]);
- }
- }
-
- if ("development" !== 'production') {
- this._unprocessedContextDev = context;
- this._processedContextDev = processChildContextDev(context, this);
- context = this._processedContextDev;
+
+ // We create tags in the namespace of their parent container, except HTML
+ // tags get no namespace.
+ var namespaceURI;
+ var parentTag;
+ if (hostParent != null) {
+ namespaceURI = hostParent._namespaceURI;
+ parentTag = hostParent._tag;
+ } else if (hostContainerInfo._tag) {
+ namespaceURI = hostContainerInfo._namespaceURI;
+ parentTag = hostContainerInfo._tag;
+ }
+ if (namespaceURI == null || namespaceURI === DOMNamespaces.svg && parentTag === 'foreignobject') {
+ namespaceURI = DOMNamespaces.html;
+ }
+ if (namespaceURI === DOMNamespaces.html) {
+ if (this._tag === 'svg') {
+ namespaceURI = DOMNamespaces.svg;
+ } else if (this._tag === 'math') {
+ namespaceURI = DOMNamespaces.mathml;
+ }
+ }
+ this._namespaceURI = namespaceURI;
+
+ if ("development" !== 'production') {
+ var parentInfo;
+ if (hostParent != null) {
+ parentInfo = hostParent._ancestorInfo;
+ } else if (hostContainerInfo._tag) {
+ parentInfo = hostContainerInfo._ancestorInfo;
+ }
+ if (parentInfo) {
+ // parentInfo should always be present except for the top-level
+ // component when server rendering
+ validateDOMNesting(this._tag, null, this, parentInfo);
+ }
+ this._ancestorInfo = validateDOMNesting.updatedAncestorInfo(parentInfo, this._tag, this);
}
var mountImage;
if (transaction.useCreateElement) {
- var ownerDocument = context[ReactMount.ownerDocumentContextKey];
- var el = ownerDocument.createElementNS('http://www.w3.org/1999/xhtml', this._currentElement.type);
- DOMPropertyOperations.setAttributeForID(el, this._rootNodeID);
- // Populate node cache
- ReactMount.getID(el);
- this._updateDOMProperties({}, props, transaction, el);
- this._createInitialChildren(transaction, props, context, el);
- mountImage = el;
+ var ownerDocument = hostContainerInfo._ownerDocument;
+ var el;
+ if (namespaceURI === DOMNamespaces.html) {
+ if (this._tag === 'script') {
+ // Create the script via .innerHTML so its "parser-inserted" flag is
+ // set to true and it does not execute
+ var div = ownerDocument.createElementNS('http://www.w3.org/1999/xhtml','div');
+ var type = this._currentElement.type;
+ div.innerHTML = '<' + type + '></' + type + '>';
+ el = div.removeChild(div.firstChild);
+ } else if (props.is) {
+ el = ownerDocument.createElementNS('http://www.w3.org/1999/xhtml',this._currentElement.type, props.is);
+ } else {
+ // Separate else branch instead of using `props.is || undefined` above becuase of a Firefox bug.
+ // See discussion in https://github.com/facebook/react/pull/6896
+ // and discussion in https://bugzilla.mozilla.org/show_bug.cgi?id=1276240
+ el = ownerDocument.createElementNS('http://www.w3.org/1999/xhtml',this._currentElement.type);
+ }
+ } else {
+ el = ownerDocument.createElementNS(namespaceURI, this._currentElement.type);
+ }
+ ReactDOMComponentTree.precacheNode(this, el);
+ this._flags |= Flags.hasCachedChildNodes;
+ if (!this._hostParent) {
+ DOMPropertyOperations.setAttributeForRoot(el);
+ }
+ this._updateDOMProperties(null, props, transaction);
+ var lazyTree = DOMLazyTree(el);
+ this._createInitialChildren(transaction, props, context, lazyTree);
+ mountImage = lazyTree;
} else {
var tagOpen = this._createOpenTagMarkupAndPutListeners(transaction, props);
var tagContent = this._createContentMarkup(transaction, props, context);
if (!tagContent && omittedCloseTags[this._tag]) {
mountImage = tagOpen + '/>';
} else {
mountImage = tagOpen + '>' + tagContent + '</' + this._currentElement.type + '>';
}
}
switch (this._tag) {
case 'input':
- transaction.getReactMountReady().enqueue(mountReadyInputWrapper, this);
- // falls through
- case 'button':
- case 'select':
+ transaction.getReactMountReady().enqueue(inputPostMount, this);
+ if (props.autoFocus) {
+ transaction.getReactMountReady().enqueue(AutoFocusUtils.focusDOMComponent, this);
+ }
+ break;
case 'textarea':
+ transaction.getReactMountReady().enqueue(textareaPostMount, this);
if (props.autoFocus) {
transaction.getReactMountReady().enqueue(AutoFocusUtils.focusDOMComponent, this);
}
break;
+ case 'select':
+ if (props.autoFocus) {
+ transaction.getReactMountReady().enqueue(AutoFocusUtils.focusDOMComponent, this);
+ }
+ break;
+ case 'button':
+ if (props.autoFocus) {
+ transaction.getReactMountReady().enqueue(AutoFocusUtils.focusDOMComponent, this);
+ }
+ break;
+ case 'option':
+ transaction.getReactMountReady().enqueue(optionPostMount, this);
+ break;
}
return mountImage;
},
/**
* Creates markup for the open tag and all attributes.
*
@@ -7141,32 +7894,32 @@ ReactDOMComponent.Mixin = {
continue;
}
var propValue = props[propKey];
if (propValue == null) {
continue;
}
if (registrationNameModules.hasOwnProperty(propKey)) {
if (propValue) {
- enqueuePutListener(this._rootNodeID, propKey, propValue, transaction);
+ enqueuePutListener(this, propKey, propValue, transaction);
}
} else {
if (propKey === STYLE) {
if (propValue) {
if ("development" !== 'production') {
// See `_updateDOMProperties`. style block
this._previousStyle = propValue;
}
- propValue = this._previousStyleCopy = assign({}, props.style);
+ propValue = this._previousStyleCopy = _assign({}, props.style);
}
- propValue = CSSPropertyOperations.createMarkupForStyles(propValue);
+ propValue = CSSPropertyOperations.createMarkupForStyles(propValue, this);
}
var markup = null;
if (this._tag != null && isCustomComponent(this._tag, props)) {
- if (propKey !== CHILDREN) {
+ if (!RESERVED_PROPS.hasOwnProperty(propKey)) {
markup = DOMPropertyOperations.createMarkupForCustomAttribute(propKey, propValue);
}
} else {
markup = DOMPropertyOperations.createMarkupForProperty(propKey, propValue);
}
if (markup) {
ret += ' ' + markup;
}
@@ -7174,18 +7927,21 @@ ReactDOMComponent.Mixin = {
}
// For static pages, no need to put React ID and checksum. Saves lots of
// bytes.
if (transaction.renderToStaticMarkup) {
return ret;
}
- var markupForID = DOMPropertyOperations.createMarkupForID(this._rootNodeID);
- return ret + ' ' + markupForID;
+ if (!this._hostParent) {
+ ret += ' ' + DOMPropertyOperations.createMarkupForRoot();
+ }
+ ret += ' ' + DOMPropertyOperations.createMarkupForID(this._domID);
+ return ret;
},
/**
* Creates markup for the content between the tags.
*
* @private
* @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
* @param {object} props
@@ -7202,16 +7958,19 @@ ReactDOMComponent.Mixin = {
ret = innerHTML.__html;
}
} else {
var contentToUse = CONTENT_TYPES[typeof props.children] ? props.children : null;
var childrenToUse = contentToUse != null ? null : props.children;
if (contentToUse != null) {
// TODO: Validate that text is allowed as a child of this node
ret = escapeTextContentForBrowser(contentToUse);
+ if ("development" !== 'production') {
+ setAndValidateContentChildDev.call(this, contentToUse);
+ }
} else if (childrenToUse != null) {
var mountImages = this.mountChildren(childrenToUse, transaction, context);
ret = mountImages.join('');
}
}
if (newlineEatingTags[this._tag] && ret.charAt(0) === '\n') {
// text/html ignores the first character in these tags if it's a newline
// Prefer to break application/xml over text/html (for now) by adding
@@ -7224,33 +7983,36 @@ ReactDOMComponent.Mixin = {
// See: Parsing of "textarea" "listing" and "pre" elements
// from <http://www.w3.org/TR/html5/syntax.html#parsing-main-inbody>
return '\n' + ret;
} else {
return ret;
}
},
- _createInitialChildren: function (transaction, props, context, el) {
+ _createInitialChildren: function (transaction, props, context, lazyTree) {
// Intentional use of != to avoid catching zero/false.
var innerHTML = props.dangerouslySetInnerHTML;
if (innerHTML != null) {
if (innerHTML.__html != null) {
- setInnerHTML(el, innerHTML.__html);
+ DOMLazyTree.queueHTML(lazyTree, innerHTML.__html);
}
} else {
var contentToUse = CONTENT_TYPES[typeof props.children] ? props.children : null;
var childrenToUse = contentToUse != null ? null : props.children;
if (contentToUse != null) {
// TODO: Validate that text is allowed as a child of this node
- setTextContent(el, contentToUse);
+ if ("development" !== 'production') {
+ setAndValidateContentChildDev.call(this, contentToUse);
+ }
+ DOMLazyTree.queueText(lazyTree, contentToUse);
} else if (childrenToUse != null) {
var mountImages = this.mountChildren(childrenToUse, transaction, context);
for (var i = 0; i < mountImages.length; i++) {
- el.appendChild(mountImages[i]);
+ DOMLazyTree.queueChild(lazyTree, mountImages[i]);
}
}
}
},
/**
* Receives a next element and updates the component.
*
@@ -7261,77 +8023,71 @@ ReactDOMComponent.Mixin = {
*/
receiveComponent: function (nextElement, transaction, context) {
var prevElement = this._currentElement;
this._currentElement = nextElement;
this.updateComponent(transaction, prevElement, nextElement, context);
},
/**
- * Updates a native DOM component after it has already been allocated and
+ * Updates a DOM component after it has already been allocated and
* attached to the DOM. Reconciles the root DOM node, then recurses.
*
* @param {ReactReconcileTransaction} transaction
* @param {ReactElement} prevElement
* @param {ReactElement} nextElement
* @internal
* @overridable
*/
updateComponent: function (transaction, prevElement, nextElement, context) {
var lastProps = prevElement.props;
var nextProps = this._currentElement.props;
switch (this._tag) {
case 'button':
- lastProps = ReactDOMButton.getNativeProps(this, lastProps);
- nextProps = ReactDOMButton.getNativeProps(this, nextProps);
+ lastProps = ReactDOMButton.getHostProps(this, lastProps);
+ nextProps = ReactDOMButton.getHostProps(this, nextProps);
break;
case 'input':
- ReactDOMInput.updateWrapper(this);
- lastProps = ReactDOMInput.getNativeProps(this, lastProps);
- nextProps = ReactDOMInput.getNativeProps(this, nextProps);
+ lastProps = ReactDOMInput.getHostProps(this, lastProps);
+ nextProps = ReactDOMInput.getHostProps(this, nextProps);
break;
case 'option':
- lastProps = ReactDOMOption.getNativeProps(this, lastProps);
- nextProps = ReactDOMOption.getNativeProps(this, nextProps);
+ lastProps = ReactDOMOption.getHostProps(this, lastProps);
+ nextProps = ReactDOMOption.getHostProps(this, nextProps);
break;
case 'select':
- lastProps = ReactDOMSelect.getNativeProps(this, lastProps);
- nextProps = ReactDOMSelect.getNativeProps(this, nextProps);
+ lastProps = ReactDOMSelect.getHostProps(this, lastProps);
+ nextProps = ReactDOMSelect.getHostProps(this, nextProps);
+ break;
+ case 'textarea':
+ lastProps = ReactDOMTextarea.getHostProps(this, lastProps);
+ nextProps = ReactDOMTextarea.getHostProps(this, nextProps);
+ break;
+ }
+
+ assertValidProps(this, nextProps);
+ this._updateDOMProperties(lastProps, nextProps, transaction);
+ this._updateDOMChildren(lastProps, nextProps, transaction, context);
+
+ switch (this._tag) {
+ case 'input':
+ // Update the wrapper around inputs *after* updating props. This has to
+ // happen after `_updateDOMProperties`. Otherwise HTML5 input validations
+ // raise warnings and prevent the new value from being assigned.
+ ReactDOMInput.updateWrapper(this);
break;
case 'textarea':
ReactDOMTextarea.updateWrapper(this);
- lastProps = ReactDOMTextarea.getNativeProps(this, lastProps);
- nextProps = ReactDOMTextarea.getNativeProps(this, nextProps);
- break;
- }
-
- if ("development" !== 'production') {
- // If the context is reference-equal to the old one, pass down the same
- // processed object so the update bailout in ReactReconciler behaves
- // correctly (and identically in dev and prod). See #5005.
- if (this._unprocessedContextDev !== context) {
- this._unprocessedContextDev = context;
- this._processedContextDev = processChildContextDev(context, this);
- }
- context = this._processedContextDev;
- }
-
- assertValidProps(this, nextProps);
- this._updateDOMProperties(lastProps, nextProps, transaction, null);
- this._updateDOMChildren(lastProps, nextProps, transaction, context);
-
- if (!canDefineProperty && this._nodeWithLegacyProperties) {
- this._nodeWithLegacyProperties.props = nextProps;
- }
-
- if (this._tag === 'select') {
- // <select> value update needs to occur after <option> children
- // reconciliation
- transaction.getReactMountReady().enqueue(postUpdateSelectWrapper, this);
+ break;
+ case 'select':
+ // <select> value update needs to occur after <option> children
+ // reconciliation
+ transaction.getReactMountReady().enqueue(postUpdateSelectWrapper, this);
+ break;
}
},
/**
* Reconciles the properties by detecting differences in property values and
* updating the DOM as necessary. This function is probably the single most
* critical path for performance optimization.
*
@@ -7339,63 +8095,63 @@ ReactDOMComponent.Mixin = {
* improves performance (especially statically positioned elements).
* TODO: Benchmark the effects of putting this at the top since 99% of props
* do not change for a given reconciliation.
* TODO: Benchmark areas that can be improved with caching.
*
* @private
* @param {object} lastProps
* @param {object} nextProps
- * @param {ReactReconcileTransaction} transaction
* @param {?DOMElement} node
*/
- _updateDOMProperties: function (lastProps, nextProps, transaction, node) {
+ _updateDOMProperties: function (lastProps, nextProps, transaction) {
var propKey;
var styleName;
var styleUpdates;
for (propKey in lastProps) {
- if (nextProps.hasOwnProperty(propKey) || !lastProps.hasOwnProperty(propKey)) {
+ if (nextProps.hasOwnProperty(propKey) || !lastProps.hasOwnProperty(propKey) || lastProps[propKey] == null) {
continue;
}
if (propKey === STYLE) {
var lastStyle = this._previousStyleCopy;
for (styleName in lastStyle) {
if (lastStyle.hasOwnProperty(styleName)) {
styleUpdates = styleUpdates || {};
styleUpdates[styleName] = '';
}
}
this._previousStyleCopy = null;
} else if (registrationNameModules.hasOwnProperty(propKey)) {
if (lastProps[propKey]) {
// Only call deleteListener if there was a listener previously or
// else willDeleteListener gets called when there wasn't actually a
// listener (e.g., onClick={null})
- deleteListener(this._rootNodeID, propKey);
+ deleteListener(this, propKey);
+ }
+ } else if (isCustomComponent(this._tag, lastProps)) {
+ if (!RESERVED_PROPS.hasOwnProperty(propKey)) {
+ DOMPropertyOperations.deleteValueForAttribute(getNode(this), propKey);
}
} else if (DOMProperty.properties[propKey] || DOMProperty.isCustomAttribute(propKey)) {
- if (!node) {
- node = ReactMount.getNode(this._rootNodeID);
- }
- DOMPropertyOperations.deleteValueForProperty(node, propKey);
+ DOMPropertyOperations.deleteValueForProperty(getNode(this), propKey);
}
}
for (propKey in nextProps) {
var nextProp = nextProps[propKey];
- var lastProp = propKey === STYLE ? this._previousStyleCopy : lastProps[propKey];
- if (!nextProps.hasOwnProperty(propKey) || nextProp === lastProp) {
+ var lastProp = propKey === STYLE ? this._previousStyleCopy : lastProps != null ? lastProps[propKey] : undefined;
+ if (!nextProps.hasOwnProperty(propKey) || nextProp === lastProp || nextProp == null && lastProp == null) {
continue;
}
if (propKey === STYLE) {
if (nextProp) {
if ("development" !== 'production') {
checkAndWarnForMutatedStyle(this._previousStyleCopy, this._previousStyle, this);
this._previousStyle = nextProp;
}
- nextProp = this._previousStyleCopy = assign({}, nextProp);
+ nextProp = this._previousStyleCopy = _assign({}, nextProp);
} else {
this._previousStyleCopy = null;
}
if (lastProp) {
// Unset styles on `lastProp` but not on `nextProp`.
for (styleName in lastProp) {
if (lastProp.hasOwnProperty(styleName) && (!nextProp || !nextProp.hasOwnProperty(styleName))) {
styleUpdates = styleUpdates || {};
@@ -7410,47 +8166,38 @@ ReactDOMComponent.Mixin = {
}
}
} else {
// Relies on `updateStylesByID` not mutating `styleUpdates`.
styleUpdates = nextProp;
}
} else if (registrationNameModules.hasOwnProperty(propKey)) {
if (nextProp) {
- enqueuePutListener(this._rootNodeID, propKey, nextProp, transaction);
+ enqueuePutListener(this, propKey, nextProp, transaction);
} else if (lastProp) {
- deleteListener(this._rootNodeID, propKey);
+ deleteListener(this, propKey);
}
} else if (isCustomComponent(this._tag, nextProps)) {
- if (!node) {
- node = ReactMount.getNode(this._rootNodeID);
- }
- if (propKey === CHILDREN) {
- nextProp = null;
- }
- DOMPropertyOperations.setValueForAttribute(node, propKey, nextProp);
+ if (!RESERVED_PROPS.hasOwnProperty(propKey)) {
+ DOMPropertyOperations.setValueForAttribute(getNode(this), propKey, nextProp);
+ }
} else if (DOMProperty.properties[propKey] || DOMProperty.isCustomAttribute(propKey)) {
- if (!node) {
- node = ReactMount.getNode(this._rootNodeID);
- }
+ var node = getNode(this);
// If we're updating to null or undefined, we should remove the property
- // from the DOM node instead of inadvertantly setting to a string. This
+ // from the DOM node instead of inadvertently setting to a string. This
// brings us in line with the same behavior we have on initial render.
if (nextProp != null) {
DOMPropertyOperations.setValueForProperty(node, propKey, nextProp);
} else {
DOMPropertyOperations.deleteValueForProperty(node, propKey);
}
}
}
if (styleUpdates) {
- if (!node) {
- node = ReactMount.getNode(this._rootNodeID);
- }
- CSSPropertyOperations.setValueForStyles(node, styleUpdates);
+ CSSPropertyOperations.setValueForStyles(getNode(this), styleUpdates, this);
}
},
/**
* Reconciles the children with the various properties that affect the
* children content.
*
* @param {object} lastProps
@@ -7472,527 +8219,867 @@ ReactDOMComponent.Mixin = {
// If we're switching from children to content/html or vice versa, remove
// the old content
var lastHasContentOrHtml = lastContent != null || lastHtml != null;
var nextHasContentOrHtml = nextContent != null || nextHtml != null;
if (lastChildren != null && nextChildren == null) {
this.updateChildren(null, transaction, context);
} else if (lastHasContentOrHtml && !nextHasContentOrHtml) {
this.updateTextContent('');
+ if ("development" !== 'production') {
+ ReactInstrumentation.debugTool.onSetChildren(this._debugID, []);
+ }
}
if (nextContent != null) {
if (lastContent !== nextContent) {
this.updateTextContent('' + nextContent);
+ if ("development" !== 'production') {
+ setAndValidateContentChildDev.call(this, nextContent);
+ }
}
} else if (nextHtml != null) {
if (lastHtml !== nextHtml) {
this.updateMarkup('' + nextHtml);
}
+ if ("development" !== 'production') {
+ ReactInstrumentation.debugTool.onSetChildren(this._debugID, []);
+ }
} else if (nextChildren != null) {
+ if ("development" !== 'production') {
+ setAndValidateContentChildDev.call(this, null);
+ }
+
this.updateChildren(nextChildren, transaction, context);
}
},
+ getHostNode: function () {
+ return getNode(this);
+ },
+
/**
* Destroys all event registrations for this instance. Does not remove from
* the DOM. That must be done by the parent.
*
* @internal
*/
- unmountComponent: function () {
+ unmountComponent: function (safely) {
switch (this._tag) {
+ case 'audio':
+ case 'form':
case 'iframe':
case 'img':
- case 'form':
+ case 'link':
+ case 'object':
+ case 'source':
case 'video':
- case 'audio':
var listeners = this._wrapperState.listeners;
if (listeners) {
for (var i = 0; i < listeners.length; i++) {
listeners[i].remove();
}
}
break;
- case 'input':
- ReactDOMInput.unmountWrapper(this);
- break;
case 'html':
case 'head':
case 'body':
/**
* Components like <html> <head> and <body> can't be removed or added
* easily in a cross-browser way, however it's valuable to be able to
* take advantage of React's reconciliation for styling and <title>
* management. So we just document it and throw in dangerous cases.
*/
- !false ? "development" !== 'production' ? invariant(false, '<%s> tried to unmount. Because of cross-browser quirks it is ' + 'impossible to unmount some top-level components (eg <html>, ' + '<head>, and <body>) reliably and efficiently. To fix this, have a ' + 'single top-level component that never unmounts render these ' + 'elements.', this._tag) : invariant(false) : undefined;
- break;
- }
-
- this.unmountChildren();
- ReactBrowserEventEmitter.deleteAllListeners(this._rootNodeID);
- ReactComponentBrowserEnvironment.unmountIDFromEnvironment(this._rootNodeID);
- this._rootNodeID = null;
+ !false ? "development" !== 'production' ? invariant(false, '<%s> tried to unmount. Because of cross-browser quirks it is impossible to unmount some top-level components (eg <html>, <head>, and <body>) reliably and efficiently. To fix this, have a single top-level component that never unmounts render these elements.', this._tag) : _prodInvariant('66', this._tag) : void 0;
+ break;
+ }
+
+ this.unmountChildren(safely);
+ ReactDOMComponentTree.uncacheNode(this);
+ EventPluginHub.deleteAllListeners(this);
+ this._rootNodeID = 0;
+ this._domID = 0;
this._wrapperState = null;
- if (this._nodeWithLegacyProperties) {
- var node = this._nodeWithLegacyProperties;
- node._reactInternalComponent = null;
- this._nodeWithLegacyProperties = null;
+
+ if ("development" !== 'production') {
+ setAndValidateContentChildDev.call(this, null);
}
},
getPublicInstance: function () {
- if (!this._nodeWithLegacyProperties) {
- var node = ReactMount.getNode(this._rootNodeID);
-
- node._reactInternalComponent = this;
- node.getDOMNode = legacyGetDOMNode;
- node.isMounted = legacyIsMounted;
- node.setState = legacySetStateEtc;
- node.replaceState = legacySetStateEtc;
- node.forceUpdate = legacySetStateEtc;
- node.setProps = legacySetProps;
- node.replaceProps = legacyReplaceProps;
-
- if ("development" !== 'production') {
- if (canDefineProperty) {
- Object.defineProperties(node, legacyPropsDescriptor);
- } else {
- // updateComponent will update this property on subsequent renders
- node.props = this._currentElement.props;
- }
- } else {
- // updateComponent will update this property on subsequent renders
- node.props = this._currentElement.props;
- }
-
- this._nodeWithLegacyProperties = node;
- }
- return this._nodeWithLegacyProperties;
- }
-
-};
-
-ReactPerf.measureMethods(ReactDOMComponent, 'ReactDOMComponent', {
- mountComponent: 'mountComponent',
- updateComponent: 'updateComponent'
-});
-
-assign(ReactDOMComponent.prototype, ReactDOMComponent.Mixin, ReactMultiChild.Mixin);
+ return getNode(this);
+ }
+
+};
+
+_assign(ReactDOMComponent.prototype, ReactDOMComponent.Mixin, ReactMultiChild.Mixin);
module.exports = ReactDOMComponent;
-},{"10":10,"11":11,"117":117,"121":121,"133":133,"138":138,"139":139,"144":144,"15":15,"161":161,"166":166,"171":171,"173":173,"2":2,"24":24,"28":28,"35":35,"41":41,"46":46,"47":47,"48":48,"5":5,"52":52,"72":72,"73":73,"78":78,"95":95}],43:[function(_dereq_,module,exports){
-/**
- * Copyright 2013-2015, Facebook, Inc.
+},{"1":1,"10":10,"11":11,"135":135,"149":149,"153":153,"16":16,"161":161,"17":17,"170":170,"178":178,"18":18,"182":182,"186":186,"187":187,"188":188,"28":28,"4":4,"43":43,"45":45,"46":46,"52":52,"54":54,"55":55,"59":59,"78":78,"8":8,"83":83,"9":9,"99":99}],45:[function(_dereq_,module,exports){
+/**
+ * Copyright 2015-present, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
+ * @providesModule ReactDOMComponentFlags
+ */
+
+'use strict';
+
+var ReactDOMComponentFlags = {
+ hasCachedChildNodes: 1 << 0
+};
+
+module.exports = ReactDOMComponentFlags;
+},{}],46:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-present, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
+ * @providesModule ReactDOMComponentTree
+ */
+
+'use strict';
+
+var _prodInvariant = _dereq_(153);
+
+var DOMProperty = _dereq_(10);
+var ReactDOMComponentFlags = _dereq_(45);
+
+var invariant = _dereq_(178);
+
+var ATTR_NAME = DOMProperty.ID_ATTRIBUTE_NAME;
+var Flags = ReactDOMComponentFlags;
+
+var internalInstanceKey = '__reactInternalInstance$' + Math.random().toString(36).slice(2);
+
+/**
+ * Drill down (through composites and empty components) until we get a host or
+ * host text component.
+ *
+ * This is pretty polymorphic but unavoidable with the current structure we have
+ * for `_renderedChildren`.
+ */
+function getRenderedHostOrTextFromComponent(component) {
+ var rendered;
+ while (rendered = component._renderedComponent) {
+ component = rendered;
+ }
+ return component;
+}
+
+/**
+ * Populate `_hostNode` on the rendered host/text component with the given
+ * DOM node. The passed `inst` can be a composite.
+ */
+function precacheNode(inst, node) {
+ var hostInst = getRenderedHostOrTextFromComponent(inst);
+ hostInst._hostNode = node;
+ node[internalInstanceKey] = hostInst;
+}
+
+function uncacheNode(inst) {
+ var node = inst._hostNode;
+ if (node) {
+ delete node[internalInstanceKey];
+ inst._hostNode = null;
+ }
+}
+
+/**
+ * Populate `_hostNode` on each child of `inst`, assuming that the children
+ * match up with the DOM (element) children of `node`.
+ *
+ * We cache entire levels at once to avoid an n^2 problem where we access the
+ * children of a node sequentially and have to walk from the start to our target
+ * node every time.
+ *
+ * Since we update `_renderedChildren` and the actual DOM at (slightly)
+ * different times, we could race here and see a newer `_renderedChildren` than
+ * the DOM nodes we see. To avoid this, ReactMultiChild calls
+ * `prepareToManageChildren` before we change `_renderedChildren`, at which
+ * time the container's child nodes are always cached (until it unmounts).
+ */
+function precacheChildNodes(inst, node) {
+ if (inst._flags & Flags.hasCachedChildNodes) {
+ return;
+ }
+ var children = inst._renderedChildren;
+ var childNode = node.firstChild;
+ outer: for (var name in children) {
+ if (!children.hasOwnProperty(name)) {
+ continue;
+ }
+ var childInst = children[name];
+ var childID = getRenderedHostOrTextFromComponent(childInst)._domID;
+ if (childID === 0) {
+ // We're currently unmounting this child in ReactMultiChild; skip it.
+ continue;
+ }
+ // We assume the child nodes are in the same order as the child instances.
+ for (; childNode !== null; childNode = childNode.nextSibling) {
+ if (childNode.nodeType === 1 && childNode.getAttribute(ATTR_NAME) === String(childID) || childNode.nodeType === 8 && childNode.nodeValue === ' react-text: ' + childID + ' ' || childNode.nodeType === 8 && childNode.nodeValue === ' react-empty: ' + childID + ' ') {
+ precacheNode(childInst, childNode);
+ continue outer;
+ }
+ }
+ // We reached the end of the DOM children without finding an ID match.
+ !false ? "development" !== 'production' ? invariant(false, 'Unable to find element with ID %s.', childID) : _prodInvariant('32', childID) : void 0;
+ }
+ inst._flags |= Flags.hasCachedChildNodes;
+}
+
+/**
+ * Given a DOM node, return the closest ReactDOMComponent or
+ * ReactDOMTextComponent instance ancestor.
+ */
+function getClosestInstanceFromNode(node) {
+ if (node[internalInstanceKey]) {
+ return node[internalInstanceKey];
+ }
+
+ // Walk up the tree until we find an ancestor whose instance we have cached.
+ var parents = [];
+ while (!node[internalInstanceKey]) {
+ parents.push(node);
+ 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).
+ return null;
+ }
+ }
+
+ var closest;
+ var inst;
+ for (; node && (inst = node[internalInstanceKey]); node = parents.pop()) {
+ closest = inst;
+ if (parents.length) {
+ precacheChildNodes(inst, node);
+ }
+ }
+
+ return closest;
+}
+
+/**
+ * Given a DOM node, return the ReactDOMComponent or ReactDOMTextComponent
+ * instance, or null if the node was not rendered by this React.
+ */
+function getInstanceFromNode(node) {
+ var inst = getClosestInstanceFromNode(node);
+ if (inst != null && inst._hostNode === node) {
+ return inst;
+ } else {
+ return null;
+ }
+}
+
+/**
+ * Given a ReactDOMComponent or ReactDOMTextComponent, return the corresponding
+ * DOM node.
+ */
+function getNodeFromInstance(inst) {
+ // Without this first invariant, passing a non-DOM-component triggers the next
+ // invariant for a missing parent, which is super confusing.
+ !(inst._hostNode !== undefined) ? "development" !== 'production' ? invariant(false, 'getNodeFromInstance: Invalid argument.') : _prodInvariant('33') : void 0;
+
+ if (inst._hostNode) {
+ return inst._hostNode;
+ }
+
+ // Walk up the tree until we find an ancestor whose DOM node we have cached.
+ var parents = [];
+ while (!inst._hostNode) {
+ parents.push(inst);
+ !inst._hostParent ? "development" !== 'production' ? invariant(false, 'React DOM tree root should always have a node reference.') : _prodInvariant('34') : void 0;
+ inst = inst._hostParent;
+ }
+
+ // Now parents contains each ancestor that does *not* have a cached native
+ // node, and `inst` is the deepest ancestor that does.
+ for (; parents.length; inst = parents.pop()) {
+ precacheChildNodes(inst, inst._hostNode);
+ }
+
+ return inst._hostNode;
+}
+
+var ReactDOMComponentTree = {
+ getClosestInstanceFromNode: getClosestInstanceFromNode,
+ getInstanceFromNode: getInstanceFromNode,
+ getNodeFromInstance: getNodeFromInstance,
+ precacheChildNodes: precacheChildNodes,
+ precacheNode: precacheNode,
+ uncacheNode: uncacheNode
+};
+
+module.exports = ReactDOMComponentTree;
+},{"10":10,"153":153,"178":178,"45":45}],47:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-present, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
+ * @providesModule ReactDOMContainerInfo
+ */
+
+'use strict';
+
+var validateDOMNesting = _dereq_(161);
+
+var DOC_NODE_TYPE = 9;
+
+function ReactDOMContainerInfo(topLevelWrapper, node) {
+ var info = {
+ _topLevelWrapper: topLevelWrapper,
+ _idCounter: 1,
+ _ownerDocument: node ? node.nodeType === DOC_NODE_TYPE ? node : node.ownerDocument : null,
+ _node: node,
+ _tag: node ? node.nodeName.toLowerCase() : null,
+ _namespaceURI: node ? node.namespaceURI : null
+ };
+ if ("development" !== 'production') {
+ info._ancestorInfo = node ? validateDOMNesting.updatedAncestorInfo(null, info._tag, null) : null;
+ }
+ return info;
+}
+
+module.exports = ReactDOMContainerInfo;
+},{"161":161}],48:[function(_dereq_,module,exports){
+/**
+ * Copyright 2014-present, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
+ * @providesModule ReactDOMEmptyComponent
+ */
+
+'use strict';
+
+var _assign = _dereq_(188);
+
+var DOMLazyTree = _dereq_(8);
+var ReactDOMComponentTree = _dereq_(46);
+
+var ReactDOMEmptyComponent = function (instantiate) {
+ // ReactCompositeComponent uses this:
+ this._currentElement = null;
+ // ReactDOMComponentTree uses these:
+ this._hostNode = null;
+ this._hostParent = null;
+ this._hostContainerInfo = null;
+ this._domID = 0;
+};
+_assign(ReactDOMEmptyComponent.prototype, {
+ mountComponent: function (transaction, hostParent, hostContainerInfo, context) {
+ var domID = hostContainerInfo._idCounter++;
+ this._domID = domID;
+ this._hostParent = hostParent;
+ this._hostContainerInfo = hostContainerInfo;
+
+ var nodeValue = ' react-empty: ' + this._domID + ' ';
+ if (transaction.useCreateElement) {
+ var ownerDocument = hostContainerInfo._ownerDocument;
+ var node = ownerDocument.createComment(nodeValue);
+ ReactDOMComponentTree.precacheNode(this, node);
+ return DOMLazyTree(node);
+ } else {
+ if (transaction.renderToStaticMarkup) {
+ // Normally we'd insert a comment node, but since this is a situation
+ // where React won't take over (static pages), we can simply return
+ // nothing.
+ return '';
+ }
+ return '<!--' + nodeValue + '-->';
+ }
+ },
+ receiveComponent: function () {},
+ getHostNode: function () {
+ return ReactDOMComponentTree.getNodeFromInstance(this);
+ },
+ unmountComponent: function () {
+ ReactDOMComponentTree.uncacheNode(this);
+ }
+});
+
+module.exports = ReactDOMEmptyComponent;
+},{"188":188,"46":46,"8":8}],49:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactDOMFactories
- * @typechecks static-only
- */
-
-'use strict';
-
-var ReactElement = _dereq_(57);
-var ReactElementValidator = _dereq_(58);
-
-var mapObject = _dereq_(167);
+ */
+
+'use strict';
+
+var ReactElement = _dereq_(65);
/**
* Create a factory that creates HTML tag elements.
*
- * @param {string} tag Tag name (e.g. `div`).
* @private
*/
-function createDOMFactory(tag) {
- if ("development" !== 'production') {
- return ReactElementValidator.createFactory(tag);
- }
- return ReactElement.createFactory(tag);
+var createDOMFactory = ReactElement.createFactory;
+if ("development" !== 'production') {
+ var ReactElementValidator = _dereq_(66);
+ createDOMFactory = ReactElementValidator.createFactory;
}
/**
* Creates a mapping from supported HTML tags to `ReactDOMComponent` classes.
* This is also accessible via `React.DOM`.
*
* @public
*/
-var ReactDOMFactories = mapObject({
- a: 'a',
- abbr: 'abbr',
- address: 'address',
- area: 'area',
- article: 'article',
- aside: 'aside',
- audio: 'audio',
- b: 'b',
- base: 'base',
- bdi: 'bdi',
- bdo: 'bdo',
- big: 'big',
- blockquote: 'blockquote',
- body: 'body',
- br: 'br',
- button: 'button',
- canvas: 'canvas',
- caption: 'caption',
- cite: 'cite',
- code: 'code',
- col: 'col',
- colgroup: 'colgroup',
- data: 'data',
- datalist: 'datalist',
- dd: 'dd',
- del: 'del',
- details: 'details',
- dfn: 'dfn',
- dialog: 'dialog',
- div: 'div',
- dl: 'dl',
- dt: 'dt',
- em: 'em',
- embed: 'embed',
- fieldset: 'fieldset',
- figcaption: 'figcaption',
- figure: 'figure',
- footer: 'footer',
- form: 'form',
- h1: 'h1',
- h2: 'h2',
- h3: 'h3',
- h4: 'h4',
- h5: 'h5',
- h6: 'h6',
- head: 'head',
- header: 'header',
- hgroup: 'hgroup',
- hr: 'hr',
- html: 'html',
- i: 'i',
- iframe: 'iframe',
- img: 'img',
- input: 'input',
- ins: 'ins',
- kbd: 'kbd',
- keygen: 'keygen',
- label: 'label',
- legend: 'legend',
- li: 'li',
- link: 'link',
- main: 'main',
- map: 'map',
- mark: 'mark',
- menu: 'menu',
- menuitem: 'menuitem',
- meta: 'meta',
- meter: 'meter',
- nav: 'nav',
- noscript: 'noscript',
- object: 'object',
- ol: 'ol',
- optgroup: 'optgroup',
- option: 'option',
- output: 'output',
- p: 'p',
- param: 'param',
- picture: 'picture',
- pre: 'pre',
- progress: 'progress',
- q: 'q',
- rp: 'rp',
- rt: 'rt',
- ruby: 'ruby',
- s: 's',
- samp: 'samp',
- script: 'script',
- section: 'section',
- select: 'select',
- small: 'small',
- source: 'source',
- span: 'span',
- strong: 'strong',
- style: 'style',
- sub: 'sub',
- summary: 'summary',
- sup: 'sup',
- table: 'table',
- tbody: 'tbody',
- td: 'td',
- textarea: 'textarea',
- tfoot: 'tfoot',
- th: 'th',
- thead: 'thead',
- time: 'time',
- title: 'title',
- tr: 'tr',
- track: 'track',
- u: 'u',
- ul: 'ul',
- 'var': 'var',
- video: 'video',
- wbr: 'wbr',
+var ReactDOMFactories = {
+ a: createDOMFactory('a'),
+ abbr: createDOMFactory('abbr'),
+ address: createDOMFactory('address'),
+ area: createDOMFactory('area'),
+ article: createDOMFactory('article'),
+ aside: createDOMFactory('aside'),
+ audio: createDOMFactory('audio'),
+ b: createDOMFactory('b'),
+ base: createDOMFactory('base'),
+ bdi: createDOMFactory('bdi'),
+ bdo: createDOMFactory('bdo'),
+ big: createDOMFactory('big'),
+ blockquote: createDOMFactory('blockquote'),
+ body: createDOMFactory('body'),
+ br: createDOMFactory('br'),
+ button: createDOMFactory('button'),
+ canvas: createDOMFactory('canvas'),
+ caption: createDOMFactory('caption'),
+ cite: createDOMFactory('cite'),
+ code: createDOMFactory('code'),
+ col: createDOMFactory('col'),
+ colgroup: createDOMFactory('colgroup'),
+ data: createDOMFactory('data'),
+ datalist: createDOMFactory('datalist'),
+ dd: createDOMFactory('dd'),
+ del: createDOMFactory('del'),
+ details: createDOMFactory('details'),
+ dfn: createDOMFactory('dfn'),
+ dialog: createDOMFactory('dialog'),
+ div: createDOMFactory('div'),
+ dl: createDOMFactory('dl'),
+ dt: createDOMFactory('dt'),
+ em: createDOMFactory('em'),
+ embed: createDOMFactory('embed'),
+ fieldset: createDOMFactory('fieldset'),
+ figcaption: createDOMFactory('figcaption'),
+ figure: createDOMFactory('figure'),
+ footer: createDOMFactory('footer'),
+ form: createDOMFactory('form'),
+ h1: createDOMFactory('h1'),
+ h2: createDOMFactory('h2'),
+ h3: createDOMFactory('h3'),
+ h4: createDOMFactory('h4'),
+ h5: createDOMFactory('h5'),
+ h6: createDOMFactory('h6'),
+ head: createDOMFactory('head'),
+ header: createDOMFactory('header'),
+ hgroup: createDOMFactory('hgroup'),
+ hr: createDOMFactory('hr'),
+ html: createDOMFactory('html'),
+ i: createDOMFactory('i'),
+ iframe: createDOMFactory('iframe'),
+ img: createDOMFactory('img'),
+ input: createDOMFactory('input'),
+ ins: createDOMFactory('ins'),
+ kbd: createDOMFactory('kbd'),
+ keygen: createDOMFactory('keygen'),
+ label: createDOMFactory('label'),
+ legend: createDOMFactory('legend'),
+ li: createDOMFactory('li'),
+ link: createDOMFactory('link'),
+ main: createDOMFactory('main'),
+ map: createDOMFactory('map'),
+ mark: createDOMFactory('mark'),
+ menu: createDOMFactory('menu'),
+ menuitem: createDOMFactory('menuitem'),
+ meta: createDOMFactory('meta'),
+ meter: createDOMFactory('meter'),
+ nav: createDOMFactory('nav'),
+ noscript: createDOMFactory('noscript'),
+ object: createDOMFactory('object'),
+ ol: createDOMFactory('ol'),
+ optgroup: createDOMFactory('optgroup'),
+ option: createDOMFactory('option'),
+ output: createDOMFactory('output'),
+ p: createDOMFactory('p'),
+ param: createDOMFactory('param'),
+ picture: createDOMFactory('picture'),
+ pre: createDOMFactory('pre'),
+ progress: createDOMFactory('progress'),
+ q: createDOMFactory('q'),
+ rp: createDOMFactory('rp'),
+ rt: createDOMFactory('rt'),
+ ruby: createDOMFactory('ruby'),
+ s: createDOMFactory('s'),
+ samp: createDOMFactory('samp'),
+ script: createDOMFactory('script'),
+ section: createDOMFactory('section'),
+ select: createDOMFactory('select'),
+ small: createDOMFactory('small'),
+ source: createDOMFactory('source'),
+ span: createDOMFactory('span'),
+ strong: createDOMFactory('strong'),
+ style: createDOMFactory('style'),
+ sub: createDOMFactory('sub'),
+ summary: createDOMFactory('summary'),
+ sup: createDOMFactory('sup'),
+ table: createDOMFactory('table'),
+ tbody: createDOMFactory('tbody'),
+ td: createDOMFactory('td'),
+ textarea: createDOMFactory('textarea'),
+ tfoot: createDOMFactory('tfoot'),
+ th: createDOMFactory('th'),
+ thead: createDOMFactory('thead'),
+ time: createDOMFactory('time'),
+ title: createDOMFactory('title'),
+ tr: createDOMFactory('tr'),
+ track: createDOMFactory('track'),
+ u: createDOMFactory('u'),
+ ul: createDOMFactory('ul'),
+ 'var': createDOMFactory('var'),
+ video: createDOMFactory('video'),
+ wbr: createDOMFactory('wbr'),
// SVG
- circle: 'circle',
- clipPath: 'clipPath',
- defs: 'defs',
- ellipse: 'ellipse',
- g: 'g',
- image: 'image',
- line: 'line',
- linearGradient: 'linearGradient',
- mask: 'mask',
- path: 'path',
- pattern: 'pattern',
- polygon: 'polygon',
- polyline: 'polyline',
- radialGradient: 'radialGradient',
- rect: 'rect',
- stop: 'stop',
- svg: 'svg',
- text: 'text',
- tspan: 'tspan'
-
-}, createDOMFactory);
+ circle: createDOMFactory('circle'),
+ clipPath: createDOMFactory('clipPath'),
+ defs: createDOMFactory('defs'),
+ ellipse: createDOMFactory('ellipse'),
+ g: createDOMFactory('g'),
+ image: createDOMFactory('image'),
+ line: createDOMFactory('line'),
+ linearGradient: createDOMFactory('linearGradient'),
+ mask: createDOMFactory('mask'),
+ path: createDOMFactory('path'),
+ pattern: createDOMFactory('pattern'),
+ polygon: createDOMFactory('polygon'),
+ polyline: createDOMFactory('polyline'),
+ radialGradient: createDOMFactory('radialGradient'),
+ rect: createDOMFactory('rect'),
+ stop: createDOMFactory('stop'),
+ svg: createDOMFactory('svg'),
+ text: createDOMFactory('text'),
+ tspan: createDOMFactory('tspan')
+};
module.exports = ReactDOMFactories;
-},{"167":167,"57":57,"58":58}],44:[function(_dereq_,module,exports){
-/**
- * Copyright 2013-2015, Facebook, Inc.
+},{"65":65,"66":66}],50:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactDOMFeatureFlags
*/
'use strict';
var ReactDOMFeatureFlags = {
- useCreateElement: false
+ useCreateElement: true
};
module.exports = ReactDOMFeatureFlags;
-},{}],45:[function(_dereq_,module,exports){
-/**
- * Copyright 2013-2015, Facebook, Inc.
+},{}],51:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactDOMIDOperations
- * @typechecks static-only
- */
-
-'use strict';
-
-var DOMChildrenOperations = _dereq_(9);
-var DOMPropertyOperations = _dereq_(11);
-var ReactMount = _dereq_(72);
-var ReactPerf = _dereq_(78);
-
-var invariant = _dereq_(161);
-
-/**
- * Errors for properties that should not be updated with `updatePropertyByID()`.
- *
- * @type {object}
- * @private
- */
-var INVALID_PROPERTY_ERRORS = {
- dangerouslySetInnerHTML: '`dangerouslySetInnerHTML` must be set using `updateInnerHTMLByID()`.',
- style: '`style` must be set using `updateStylesByID()`.'
-};
+ */
+
+'use strict';
+
+var DOMChildrenOperations = _dereq_(7);
+var ReactDOMComponentTree = _dereq_(46);
/**
* Operations used to process updates to DOM nodes.
*/
var ReactDOMIDOperations = {
/**
- * Updates a DOM node with new property values. This should only be used to
- * update DOM properties in `DOMProperty`.
- *
- * @param {string} id ID of the node to update.
- * @param {string} name A valid property name, see `DOMProperty`.
- * @param {*} value New value of the property.
- * @internal
- */
- updatePropertyByID: function (id, name, value) {
- var node = ReactMount.getNode(id);
- !!INVALID_PROPERTY_ERRORS.hasOwnProperty(name) ? "development" !== 'production' ? invariant(false, 'updatePropertyByID(...): %s', INVALID_PROPERTY_ERRORS[name]) : invariant(false) : undefined;
-
- // If we're updating to null or undefined, we should remove the property
- // from the DOM node instead of inadvertantly setting to a string. This
- // brings us in line with the same behavior we have on initial render.
- if (value != null) {
- DOMPropertyOperations.setValueForProperty(node, name, value);
- } else {
- DOMPropertyOperations.deleteValueForProperty(node, name);
- }
- },
-
- /**
- * Replaces a DOM node that exists in the document with markup.
- *
- * @param {string} id ID of child to be replaced.
- * @param {string} markup Dangerous markup to inject in place of child.
- * @internal
- * @see {Danger.dangerouslyReplaceNodeWithMarkup}
- */
- dangerouslyReplaceNodeWithMarkupByID: function (id, markup) {
- var node = ReactMount.getNode(id);
- DOMChildrenOperations.dangerouslyReplaceNodeWithMarkup(node, markup);
- },
-
- /**
* Updates a component's children by processing a series of updates.
*
* @param {array<object>} updates List of update configurations.
- * @param {array<string>} markup List of markup strings.
- * @internal
- */
- dangerouslyProcessChildrenUpdates: function (updates, markup) {
- for (var i = 0; i < updates.length; i++) {
- updates[i].parentNode = ReactMount.getNode(updates[i].parentID);
- }
- DOMChildrenOperations.processUpdates(updates, markup);
- }
-};
-
-ReactPerf.measureMethods(ReactDOMIDOperations, 'ReactDOMIDOperations', {
- dangerouslyReplaceNodeWithMarkupByID: 'dangerouslyReplaceNodeWithMarkupByID',
- dangerouslyProcessChildrenUpdates: 'dangerouslyProcessChildrenUpdates'
-});
+ * @internal
+ */
+ dangerouslyProcessChildrenUpdates: function (parentInst, updates) {
+ var node = ReactDOMComponentTree.getNodeFromInstance(parentInst);
+ DOMChildrenOperations.processUpdates(node, updates);
+ }
+};
module.exports = ReactDOMIDOperations;
-},{"11":11,"161":161,"72":72,"78":78,"9":9}],46:[function(_dereq_,module,exports){
-/**
- * Copyright 2013-2015, Facebook, Inc.
+},{"46":46,"7":7}],52:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactDOMInput
*/
'use strict';
-var ReactDOMIDOperations = _dereq_(45);
-var LinkedValueUtils = _dereq_(23);
-var ReactMount = _dereq_(72);
-var ReactUpdates = _dereq_(96);
-
-var assign = _dereq_(24);
-var invariant = _dereq_(161);
-
-var instancesByReactID = {};
+var _prodInvariant = _dereq_(153),
+ _assign = _dereq_(188);
+
+var DisabledInputUtils = _dereq_(14);
+var DOMPropertyOperations = _dereq_(11);
+var LinkedValueUtils = _dereq_(25);
+var ReactDOMComponentTree = _dereq_(46);
+var ReactUpdates = _dereq_(107);
+
+var invariant = _dereq_(178);
+var warning = _dereq_(187);
+
+var didWarnValueLink = false;
+var didWarnCheckedLink = false;
+var didWarnValueDefaultValue = false;
+var didWarnCheckedDefaultChecked = false;
+var didWarnControlledToUncontrolled = false;
+var didWarnUncontrolledToControlled = false;
function forceUpdateIfMounted() {
if (this._rootNodeID) {
// DOM component is still mounted; update
ReactDOMInput.updateWrapper(this);
}
}
-/**
- * Implements an <input> native component that allows setting these optional
+function isControlled(props) {
+ var usesChecked = props.type === 'checkbox' || props.type === 'radio';
+ return usesChecked ? props.checked != null : props.value != null;
+}
+
+/**
+ * Implements an <input> host component that allows setting these optional
* props: `checked`, `value`, `defaultChecked`, and `defaultValue`.
*
* If `checked` or `value` are not supplied (or null/undefined), user actions
* that affect the checked state or value will trigger updates to the element.
*
* If they are supplied (and not null/undefined), the rendered element will not
* trigger updates to the element. Instead, the props must change in order for
* the rendered element to be updated.
*
* The rendered element will be initialized as unchecked (or `defaultChecked`)
* with an empty value (or `defaultValue`).
*
* @see http://www.w3.org/TR/2012/WD-html5-20121025/the-input-element.html
*/
var ReactDOMInput = {
- getNativeProps: function (inst, props, context) {
+ getHostProps: function (inst, props) {
var value = LinkedValueUtils.getValue(props);
var checked = LinkedValueUtils.getChecked(props);
- var nativeProps = assign({}, props, {
+ var hostProps = _assign({
+ // Make sure we set .type before any other properties (setting .value
+ // before .type means .value is lost in IE11 and below)
+ type: undefined,
+ // Make sure we set .step before .value (setting .value before .step
+ // means .value is rounded on mount, based upon step precision)
+ step: undefined,
+ // Make sure we set .min & .max before .value (to ensure proper order
+ // in corner cases such as min or max deriving from value, e.g. Issue #7170)
+ min: undefined,
+ max: undefined
+ }, DisabledInputUtils.getHostProps(inst, props), {
defaultChecked: undefined,
defaultValue: undefined,
value: value != null ? value : inst._wrapperState.initialValue,
checked: checked != null ? checked : inst._wrapperState.initialChecked,
onChange: inst._wrapperState.onChange
});
- return nativeProps;
+ return hostProps;
},
mountWrapper: function (inst, props) {
if ("development" !== 'production') {
LinkedValueUtils.checkPropTypes('input', props, inst._currentElement._owner);
+
+ var owner = inst._currentElement._owner;
+
+ if (props.valueLink !== undefined && !didWarnValueLink) {
+ "development" !== 'production' ? warning(false, '`valueLink` prop on `input` is deprecated; set `value` and `onChange` instead.') : void 0;
+ didWarnValueLink = true;
+ }
+ if (props.checkedLink !== undefined && !didWarnCheckedLink) {
+ "development" !== 'production' ? warning(false, '`checkedLink` prop on `input` is deprecated; set `value` and `onChange` instead.') : void 0;
+ didWarnCheckedLink = true;
+ }
+ if (props.checked !== undefined && props.defaultChecked !== undefined && !didWarnCheckedDefaultChecked) {
+ "development" !== 'production' ? warning(false, '%s contains an input of type %s with both checked and defaultChecked props. ' + 'Input elements must be either controlled or uncontrolled ' + '(specify either the checked prop, or the defaultChecked prop, but not ' + 'both). Decide between using a controlled or uncontrolled input ' + 'element and remove one of these props. More info: ' + 'https://fb.me/react-controlled-components', owner && owner.getName() || 'A component', props.type) : void 0;
+ didWarnCheckedDefaultChecked = true;
+ }
+ if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValueDefaultValue) {
+ "development" !== 'production' ? warning(false, '%s contains an input of type %s with both value and defaultValue props. ' + 'Input elements must be either controlled or uncontrolled ' + '(specify either the value prop, or the defaultValue prop, but not ' + 'both). Decide between using a controlled or uncontrolled input ' + 'element and remove one of these props. More info: ' + 'https://fb.me/react-controlled-components', owner && owner.getName() || 'A component', props.type) : void 0;
+ didWarnValueDefaultValue = true;
+ }
}
var defaultValue = props.defaultValue;
inst._wrapperState = {
- initialChecked: props.defaultChecked || false,
- initialValue: defaultValue != null ? defaultValue : null,
+ initialChecked: props.checked != null ? props.checked : props.defaultChecked,
+ initialValue: props.value != null ? props.value : defaultValue,
+ listeners: null,
onChange: _handleChange.bind(inst)
};
- },
-
- mountReadyWrapper: function (inst) {
- // Can't be in mountWrapper or else server rendering leaks.
- instancesByReactID[inst._rootNodeID] = inst;
- },
-
- unmountWrapper: function (inst) {
- delete instancesByReactID[inst._rootNodeID];
+
+ if ("development" !== 'production') {
+ inst._wrapperState.controlled = isControlled(props);
+ }
},
updateWrapper: function (inst) {
var props = inst._currentElement.props;
+ if ("development" !== 'production') {
+ var controlled = isControlled(props);
+ var owner = inst._currentElement._owner;
+
+ if (!inst._wrapperState.controlled && controlled && !didWarnUncontrolledToControlled) {
+ "development" !== 'production' ? warning(false, '%s is changing an uncontrolled input of type %s to be controlled. ' + 'Input elements should not switch from uncontrolled to controlled (or vice versa). ' + 'Decide between using a controlled or uncontrolled input ' + 'element for the lifetime of the component. More info: https://fb.me/react-controlled-components', owner && owner.getName() || 'A component', props.type) : void 0;
+ didWarnUncontrolledToControlled = true;
+ }
+ if (inst._wrapperState.controlled && !controlled && !didWarnControlledToUncontrolled) {
+ "development" !== 'production' ? warning(false, '%s is changing a controlled input of type %s to be uncontrolled. ' + 'Input elements should not switch from controlled to uncontrolled (or vice versa). ' + 'Decide between using a controlled or uncontrolled input ' + 'element for the lifetime of the component. More info: https://fb.me/react-controlled-components', owner && owner.getName() || 'A component', props.type) : void 0;
+ didWarnControlledToUncontrolled = true;
+ }
+ }
+
// TODO: Shouldn't this be getChecked(props)?
var checked = props.checked;
if (checked != null) {
- ReactDOMIDOperations.updatePropertyByID(inst._rootNodeID, 'checked', checked || false);
- }
-
+ DOMPropertyOperations.setValueForProperty(ReactDOMComponentTree.getNodeFromInstance(inst), 'checked', checked || false);
+ }
+
+ var node = ReactDOMComponentTree.getNodeFromInstance(inst);
var value = LinkedValueUtils.getValue(props);
if (value != null) {
+
// Cast `value` to a string to ensure the value is set correctly. While
// browsers typically do this as necessary, jsdom doesn't.
- ReactDOMIDOperations.updatePropertyByID(inst._rootNodeID, 'value', '' + value);
+ var newValue = '' + value;
+
+ // To avoid side effects (such as losing text selection), only set value if changed
+ if (newValue !== node.value) {
+ node.value = newValue;
+ }
+ } else {
+ if (props.value == null && props.defaultValue != null) {
+ node.defaultValue = '' + props.defaultValue;
+ }
+ if (props.checked == null && props.defaultChecked != null) {
+ node.defaultChecked = !!props.defaultChecked;
+ }
+ }
+ },
+
+ postMountWrapper: function (inst) {
+ var props = inst._currentElement.props;
+
+ // This is in postMount because we need access to the DOM node, which is not
+ // available until after the component has mounted.
+ var node = ReactDOMComponentTree.getNodeFromInstance(inst);
+
+ // Detach value from defaultValue. We won't do anything if we're working on
+ // submit or reset inputs as those values & defaultValues are linked. They
+ // are not resetable nodes so this operation doesn't matter and actually
+ // removes browser-default values (eg "Submit Query") when no value is
+ // provided.
+
+ switch (props.type) {
+ case 'submit':
+ case 'reset':
+ break;
+ case 'color':
+ case 'date':
+ case 'datetime':
+ case 'datetime-local':
+ case 'month':
+ case 'time':
+ case 'week':
+ // This fixes the no-show issue on iOS Safari and Android Chrome:
+ // https://github.com/facebook/react/issues/7233
+ node.value = '';
+ node.value = node.defaultValue;
+ break;
+ default:
+ node.value = node.value;
+ break;
+ }
+
+ // Normally, we'd just do `node.checked = node.checked` upon initial mount, less this bug
+ // this is needed to work around a chrome bug where setting defaultChecked
+ // will sometimes influence the value of checked (even after detachment).
+ // Reference: https://bugs.chromium.org/p/chromium/issues/detail?id=608416
+ // We need to temporarily unset name to avoid disrupting radio button groups.
+ var name = node.name;
+ if (name !== '') {
+ node.name = '';
+ }
+ node.defaultChecked = !node.defaultChecked;
+ node.defaultChecked = !node.defaultChecked;
+ if (name !== '') {
+ node.name = name;
}
}
};
function _handleChange(event) {
var props = this._currentElement.props;
var returnValue = LinkedValueUtils.executeOnChange(props, event);
// Here we use asap to wait until all updates have propagated, which
// is important when using controlled components within layers:
// https://github.com/facebook/react/issues/1698
ReactUpdates.asap(forceUpdateIfMounted, this);
var name = props.name;
if (props.type === 'radio' && name != null) {
- var rootNode = ReactMount.getNode(this._rootNodeID);
+ var rootNode = ReactDOMComponentTree.getNodeFromInstance(this);
var queryRoot = rootNode;
while (queryRoot.parentNode) {
queryRoot = queryRoot.parentNode;
}
// If `rootNode.form` was non-null, then we could try `form.elements`,
// but that sometimes behaves strangely in IE8. We could also try using
@@ -8005,141 +9092,223 @@ function _handleChange(event) {
for (var i = 0; i < group.length; i++) {
var otherNode = group[i];
if (otherNode === rootNode || otherNode.form !== rootNode.form) {
continue;
}
// This will throw if radio buttons rendered by different copies of React
// 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 with non-React.
- var otherID = ReactMount.getID(otherNode);
- !otherID ? "development" !== 'production' ? invariant(false, 'ReactDOMInput: Mixing React and non-React radio inputs with the ' + 'same `name` is not supported.') : invariant(false) : undefined;
- var otherInstance = instancesByReactID[otherID];
- !otherInstance ? "development" !== 'production' ? invariant(false, 'ReactDOMInput: Unknown radio button ID %s.', otherID) : invariant(false) : undefined;
+ // mixing React radio buttons with non-React ones.
+ var otherInstance = ReactDOMComponentTree.getInstanceFromNode(otherNode);
+ !otherInstance ? "development" !== 'production' ? invariant(false, 'ReactDOMInput: Mixing React and non-React radio inputs with the same `name` is not supported.') : _prodInvariant('90') : void 0;
// If this is a controlled radio button group, forcing the input that
// was previously checked to update will cause it to be come re-checked
// as appropriate.
ReactUpdates.asap(forceUpdateIfMounted, otherInstance);
}
}
return returnValue;
}
module.exports = ReactDOMInput;
-},{"161":161,"23":23,"24":24,"45":45,"72":72,"96":96}],47:[function(_dereq_,module,exports){
-/**
- * Copyright 2013-2015, Facebook, Inc.
+},{"107":107,"11":11,"14":14,"153":153,"178":178,"187":187,"188":188,"25":25,"46":46}],53:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-present, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
+ * @providesModule ReactDOMNullInputValuePropHook
+ */
+
+'use strict';
+
+var ReactComponentTreeHook = _dereq_(38);
+
+var warning = _dereq_(187);
+
+var didWarnValueNull = false;
+
+function handleElement(debugID, element) {
+ if (element == null) {
+ return;
+ }
+ if (element.type !== 'input' && element.type !== 'textarea' && element.type !== 'select') {
+ return;
+ }
+ if (element.props != null && element.props.value === null && !didWarnValueNull) {
+ "development" !== 'production' ? warning(false, '`value` prop on `%s` should not be null. ' + 'Consider using the empty string to clear the component or `undefined` ' + 'for uncontrolled components.%s', element.type, ReactComponentTreeHook.getStackAddendumByID(debugID)) : void 0;
+
+ didWarnValueNull = true;
+ }
+}
+
+var ReactDOMNullInputValuePropHook = {
+ onBeforeMountComponent: function (debugID, element) {
+ handleElement(debugID, element);
+ },
+ onBeforeUpdateComponent: function (debugID, element) {
+ handleElement(debugID, element);
+ }
+};
+
+module.exports = ReactDOMNullInputValuePropHook;
+},{"187":187,"38":38}],54:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactDOMOption
*/
'use strict';
+var _assign = _dereq_(188);
+
var ReactChildren = _dereq_(32);
-var ReactDOMSelect = _dereq_(48);
-
-var assign = _dereq_(24);
-var warning = _dereq_(173);
-
-var valueContextKey = ReactDOMSelect.valueContextKey;
-
-/**
- * Implements an <option> native component that warns when `selected` is set.
+var ReactDOMComponentTree = _dereq_(46);
+var ReactDOMSelect = _dereq_(55);
+
+var warning = _dereq_(187);
+var didWarnInvalidOptionChildren = false;
+
+function flattenChildren(children) {
+ var content = '';
+
+ // Flatten children and warn if they aren't strings or numbers;
+ // invalid types are ignored.
+ ReactChildren.forEach(children, function (child) {
+ if (child == null) {
+ return;
+ }
+ if (typeof child === 'string' || typeof child === 'number') {
+ content += child;
+ } else if (!didWarnInvalidOptionChildren) {
+ didWarnInvalidOptionChildren = true;
+ "development" !== 'production' ? warning(false, 'Only strings and numbers are supported as <option> children.') : void 0;
+ }
+ });
+
+ return content;
+}
+
+/**
+ * Implements an <option> host component that warns when `selected` is set.
*/
var ReactDOMOption = {
- mountWrapper: function (inst, props, context) {
+ mountWrapper: function (inst, props, hostParent) {
// TODO (yungsters): Remove support for `selected` in <option>.
if ("development" !== 'production') {
- "development" !== 'production' ? warning(props.selected == null, 'Use the `defaultValue` or `value` props on <select> instead of ' + 'setting `selected` on <option>.') : undefined;
- }
-
- // Look up whether this option is 'selected' via context
- var selectValue = context[valueContextKey];
-
- // If context key is null (e.g., no specified value or after initial mount)
+ "development" !== 'production' ? warning(props.selected == null, 'Use the `defaultValue` or `value` props on <select> instead of ' + 'setting `selected` on <option>.') : void 0;
+ }
+
+ // Look up whether this option is 'selected'
+ var selectValue = null;
+ if (hostParent != null) {
+ var selectParent = hostParent;
+
+ if (selectParent._tag === 'optgroup') {
+ selectParent = selectParent._hostParent;
+ }
+
+ if (selectParent != null && selectParent._tag === 'select') {
+ selectValue = ReactDOMSelect.getSelectValueContext(selectParent);
+ }
+ }
+
+ // If the value is null (e.g., no specified value or after initial mount)
// or missing (e.g., for <datalist>), we don't change props.selected
var selected = null;
if (selectValue != null) {
+ var value;
+ if (props.value != null) {
+ value = props.value + '';
+ } else {
+ value = flattenChildren(props.children);
+ }
selected = false;
if (Array.isArray(selectValue)) {
// multiple
for (var i = 0; i < selectValue.length; i++) {
- if ('' + selectValue[i] === '' + props.value) {
+ if ('' + selectValue[i] === value) {
selected = true;
break;
}
}
} else {
- selected = '' + selectValue === '' + props.value;
+ selected = '' + selectValue === value;
}
}
inst._wrapperState = { selected: selected };
},
- getNativeProps: function (inst, props, context) {
- var nativeProps = assign({ selected: undefined, children: undefined }, props);
+ postMountWrapper: function (inst) {
+ // value="" should make a value attribute (#6219)
+ var props = inst._currentElement.props;
+ if (props.value != null) {
+ var node = ReactDOMComponentTree.getNodeFromInstance(inst);
+ node.setAttribute('value', props.value);
+ }
+ },
+
+ getHostProps: function (inst, props) {
+ var hostProps = _assign({ selected: undefined, children: undefined }, props);
// Read state only from initial mount because <select> updates value
// manually; we need the initial state only for server rendering
if (inst._wrapperState.selected != null) {
- nativeProps.selected = inst._wrapperState.selected;
- }
-
- var content = '';
-
- // Flatten children and warn if they aren't strings or numbers;
- // invalid types are ignored.
- ReactChildren.forEach(props.children, function (child) {
- if (child == null) {
- return;
- }
- if (typeof child === 'string' || typeof child === 'number') {
- content += child;
- } else {
- "development" !== 'production' ? warning(false, 'Only strings and numbers are supported as <option> children.') : undefined;
- }
- });
-
- nativeProps.children = content;
- return nativeProps;
+ hostProps.selected = inst._wrapperState.selected;
+ }
+
+ var content = flattenChildren(props.children);
+
+ if (content) {
+ hostProps.children = content;
+ }
+
+ return hostProps;
}
};
module.exports = ReactDOMOption;
-},{"173":173,"24":24,"32":32,"48":48}],48:[function(_dereq_,module,exports){
-/**
- * Copyright 2013-2015, Facebook, Inc.
+},{"187":187,"188":188,"32":32,"46":46,"55":55}],55:[function(_dereq_,module,exports){
+/**
+ * Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactDOMSelect
*/
'use strict';
-var LinkedValueUtils = _dereq_(23);
-var ReactMount = _dereq_(72);
-var ReactUpdates = _dereq_(96);
-
-var assign = _dereq_(24);
-var warning = _dereq_(173);
-
-var valueContextKey = '__ReactDOMSelect_value$' + Math.random().toString(36).slice(2);
+var _assign = _dereq_(188);
+
+var DisabledInputUtils = _dereq_(14);
+var LinkedValueUtils = _dereq_(25);
+var ReactDOMComponentTree = _dereq_(46);
+var ReactUpdates = _dereq_(107);
+
+var warning = _dereq_(187);
+
+var didWarnValueLink = false;
+var didWarnValueDefaultValue = false;
function updateOptionsIfPendingUpdateAndMounted() {
if (this._rootNodeID && this._wrapperState.pendingUpdate) {
this._wrapperState.pendingUpdate = false;
var props = this._currentElement.props;
var value = LinkedValueUtils.getValue(props);
@@ -8164,38 +9333,44 @@ var valuePropNames = ['value', 'defaultV
/**
* Validation function for `value` and `defaultValue`.
* @private
*/
function checkSelectPropTypes(inst, props) {
var owner = inst._currentElement._owner;
LinkedValueUtils.checkPropTypes('select', props, owner);
+ if (props.valueLink !== undefined && !didWarnValueLink) {
+ "development" !== 'production' ? warning(false, '`valueLink` prop on `select` is deprecated; set `value` and `onChange` instead.') : void 0;
+ didWarnValueLink = true;
+ }
+
for (var i = 0; i < valuePropNames.length; i++) {
var propName = valuePropNames[i];
if (props[propName] == null) {
continue;
}
- if (props.multiple) {
- "development" !== 'production' ? warning(Array.isArray(props[propName]), 'The `%s` prop supplied to <select> must be an array if ' + '`multiple` is true.%s', propName, getDeclarationErrorAddendum(owner)) : undefined;
- } else {
- "development" !== 'production' ? warning(!Array.isArray(props[propName]), 'The `%s` prop supplied to <select> must be a scalar ' + 'value if `multiple` is false.%s', propName, getDeclarationErrorAddendum(owner)) : undefined;
+ var isArray = Array.isArray(props[propName]);
+ if (props.multiple && !isArray) {
+ "development" !== 'production' ? warning(false, 'The `%s` prop supplied to <select> must be an array if ' + '`multiple` is true.%s', propName, getDeclarationErrorAddendum(owner)) : void 0;
+ } else if (!props.multiple && isArray) {
+ "development" !== 'production' ? warning(false, 'The `%s` prop supplied to <select> must be a scalar ' + 'value if `multiple` is false.%s', propName, getDeclarationErrorAddendum(owner)) : void 0;
}
}
}
/**
* @param {ReactDOMComponent} inst
* @param {boolean} multiple
* @param {*} propValue A stringable (with `multiple`, a list of stringables).
* @private
*/
function updateOptions(inst, multiple, propValue) {
var selectedValue, i;
- var options = ReactMount.getNode(inst._rootNodeID).options;
+ var options = ReactDOMComponentTree.getNodeFromInstance(inst).options;
if (multiple) {
selectedValue = {};
for (i = 0; i < propValue.length; i++) {
selectedValue['' + propValue[i]] = true;
}
for (i = 0; i < options.length; i++) {
var selected = selectedValue.hasOwnProperty(options[i].value);
@@ -8215,67 +9390,69 @@ function updateOptions(inst, multiple, p
}
if (options.length) {
options[0].selected = true;
}
}
}
/**
- * Implements a <select> native component that allows optionally setting the
+ * Implements a <select> host component that allows optionally setting the
* props `value` and `defaultValue`. If `multiple` is false, the prop must be a
* stringable. If `multiple` is true, the prop must be an array of stringables.
*
* If `value` is not supplied (or null/undefined), user actions that change the
* selected option will trigger updates to the rendered options.
*
* If it is supplied (and not null/undefined), the rendered options will not
* update in response to user actions. Instead, the `value` prop must change in
* order for the rendered options to update.
*
* If `defaultValue` is provided, any options with the supplied values will be
* selected.
*/
var ReactDOMSelect = {
- valueContextKey: valueContextKey,
-
- getNativeProps: function (inst, props, context) {
- return assign({}, props, {
+ getHostProps: function (inst, props) {
+ return _assign({}, DisabledInputUtils.getHostProps(inst, props), {
onChange: inst._wrapperState.onChange,
value: undefined
});
},
mountWrapper: function (inst, props) {
if ("development" !== 'production') {
checkSelectPropTypes(inst, props);
}
var value = LinkedValueUtils.getValue(props);
inst._wrapperState = {
pendingUpdate: false,
initialValue: value != null ? value : props.defaultValue,
+ listeners: null,
onChange: _handleChange.bind(inst),
wasMultiple: Boolean(props.multiple)
};
- },
-
- processChildContext: function (inst, props, context) {
- // Pass down initial value so initial generated markup has correct
- // `selected` attributes
- var childContext = assign({}, context);
- childContext[valueContextKey] = inst._wrapperState.initialValue;
- return childContext;
+
+ if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValueDefaultValue) {
+ "development" !== 'production' ? warning(false, 'Select elements must be either controlled or uncontrolled ' +