' + func(text) + '
'; - * }); - * - * p('Fred, Wilma, & Pebbles'); - * // => 'Fred, Wilma, & Pebbles
' - */ - function wrap(value, wrapper) { - return createWrapper(wrapper, 16, [value]); - } + var SEPARATOR = ReactInstanceHandles.SEPARATOR; - /*--------------------------------------------------------------------------*/ + var ATTR_NAME = DOMProperty.ID_ATTRIBUTE_NAME; + var nodeCache = {}; - /** - * Creates a function that returns `value`. - * - * @static - * @memberOf _ - * @category Utilities - * @param {*} value The value to return from the new function. - * @returns {Function} Returns the new function. - * @example - * - * var object = { 'name': 'fred' }; - * var getter = _.constant(object); - * getter() === object; - * // => true - */ - function constant(value) { - return function() { - return value; - }; - } + var ELEMENT_NODE_TYPE = 1; + var DOC_NODE_TYPE = 9; - /** - * Produces a callback bound to an optional `thisArg`. If `func` is a property - * name the created callback will return the property value for a given element. - * If `func` is an object the created callback will return `true` for elements - * that contain the equivalent object properties, otherwise it will return `false`. - * - * @static - * @memberOf _ - * @category Utilities - * @param {*} [func=identity] The value to convert to a callback. - * @param {*} [thisArg] The `this` binding of the created callback. - * @param {number} [argCount] The number of arguments the callback accepts. - * @returns {Function} Returns a callback function. - * @example - * - * var characters = [ - * { 'name': 'barney', 'age': 36 }, - * { 'name': 'fred', 'age': 40 } - * ]; - * - * // wrap to create custom callback shorthands - * _.createCallback = _.wrap(_.createCallback, function(func, callback, thisArg) { - * var match = /^(.+?)__([gl]t)(.+)$/.exec(callback); - * return !match ? func(callback, thisArg) : function(object) { - * return match[2] == 'gt' ? object[match[1]] > match[3] : object[match[1]] < match[3]; - * }; - * }); - * - * _.filter(characters, 'age__gt38'); - * // => [{ 'name': 'fred', 'age': 40 }] - */ - function createCallback(func, thisArg, argCount) { - var type = typeof func; - if (func == null || type == 'function') { - return baseCreateCallback(func, thisArg, argCount); - } - // handle "_.pluck" style callback shorthands - if (type != 'object') { - return property(func); - } - var props = keys(func), - key = props[0], - a = func[key]; + /** Mapping from reactRootID to React component instance. */ + var instancesByReactRootID = {}; - // handle "_.where" style callback shorthands - if (props.length == 1 && a === a && !isObject(a)) { - // fast path the common case of providing an object with a single - // property containing a primitive value - return function(object) { - var b = object[key]; - return a === b && (a !== 0 || (1 / a == 1 / b)); - }; - } - return function(object) { - var length = props.length, - result = false; + /** Mapping from reactRootID to `container` nodes. */ + var containersByReactRootID = {}; - while (length--) { - if (!(result = baseIsEqual(object[props[length]], func[props[length]], null, true))) { - break; - } - } - return result; - }; - } + if ("production" !== process.env.NODE_ENV) { + /** __DEV__-only mapping from reactRootID to root elements. */ + var rootElementsByReactRootID = {}; + } - /** - * Converts the characters `&`, `<`, `>`, `"`, and `'` in `string` to their - * corresponding HTML entities. - * - * @static - * @memberOf _ - * @category Utilities - * @param {string} string The string to escape. - * @returns {string} Returns the escaped string. - * @example - * - * _.escape('Fred, Wilma, & Pebbles'); - * // => 'Fred, Wilma, & Pebbles' - */ - function escape(string) { - return string == null ? '' : String(string).replace(reUnescapedHtml, escapeHtmlChar); - } + // Used to store breadth-first search state in findComponentRoot. + var findComponentRootReusableArray = []; - /** - * This method returns the first argument provided to it. - * - * @static - * @memberOf _ - * @category Utilities - * @param {*} value Any value. - * @returns {*} Returns `value`. - * @example - * - * var object = { 'name': 'fred' }; - * _.identity(object) === object; - * // => true - */ - function identity(value) { - return value; + /** + * @param {DOMElement} container DOM element that may contain a React component. + * @return {?string} A "reactRoot" ID, if a React component is rendered. + */ + function getReactRootID(container) { + var rootElement = getReactRootElementInContainer(container); + return rootElement && ReactMount.getID(rootElement); + } + + /** + * Accessing node[ATTR_NAME] or calling getAttribute(ATTR_NAME) on a form + * element can return its control whose name or ID equals ATTR_NAME. All + * DOM nodes support `getAttributeNode` but this can also get called on + * other objects so just return '' if we're given something other than a + * DOM node (such as window). + * + * @param {?DOMElement|DOMWindow|DOMDocument|DOMTextNode} node DOM node. + * @return {string} ID of the supplied `domNode`. + */ + function getID(node) { + var id = internalGetID(node); + if (id) { + if (nodeCache.hasOwnProperty(id)) { + var cached = nodeCache[id]; + if (cached !== node) { + ("production" !== process.env.NODE_ENV ? invariant( + !isValid(cached, id), + 'ReactMount: Two valid but unequal nodes with the same `%s`: %s', + ATTR_NAME, id + ) : invariant(!isValid(cached, id))); + + nodeCache[id] = node; + } + } else { + nodeCache[id] = node; } + } - /** - * Adds function properties of a source object to the destination object. - * If `object` is a function methods will be added to its prototype as well. - * - * @static - * @memberOf _ - * @category Utilities - * @param {Function|Object} [object=lodash] object The destination object. - * @param {Object} source The object of functions to add. - * @param {Object} [options] The options object. - * @param {boolean} [options.chain=true] Specify whether the functions added are chainable. - * @example - * - * function capitalize(string) { - * return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase(); - * } - * - * _.mixin({ 'capitalize': capitalize }); - * _.capitalize('fred'); - * // => 'Fred' - * - * _('fred').capitalize().value(); - * // => 'Fred' - * - * _.mixin({ 'capitalize': capitalize }, { 'chain': false }); - * _('fred').capitalize(); - * // => 'Fred' - */ - function mixin(object, source, options) { - var chain = true, - methodNames = source && functions(source); + return id; + } - if (!source || (!options && !methodNames.length)) { - if (options == null) { - options = source; - } - ctor = lodashWrapper; - source = object; - object = lodash; - methodNames = functions(source); - } - if (options === false) { - chain = false; - } else if (isObject(options) && 'chain' in options) { - chain = options.chain; - } - var ctor = object, - isFunc = isFunction(ctor); + function internalGetID(node) { + // If node is something like a window, document, or text node, none of + // which support attributes or a .getAttribute method, gracefully return + // the empty string, as if the attribute were missing. + return node && node.getAttribute && node.getAttribute(ATTR_NAME) || ''; + } - forEach(methodNames, function(methodName) { - var func = object[methodName] = source[methodName]; - if (isFunc) { - ctor.prototype[methodName] = function() { - var chainAll = this.__chain__, - value = this.__wrapped__, - args = [value]; + /** + * Sets the React-specific ID of the given node. + * + * @param {DOMElement} node The DOM node whose ID will be set. + * @param {string} id The value of the ID attribute. + */ + function setID(node, id) { + var oldID = internalGetID(node); + if (oldID !== id) { + delete nodeCache[oldID]; + } + node.setAttribute(ATTR_NAME, id); + nodeCache[id] = node; + } - push.apply(args, arguments); - var result = func.apply(object, args); - if (chain || chainAll) { - if (value === result && isObject(result)) { - return this; - } - result = new ctor(result); - result.__chain__ = chainAll; - } - return result; - }; - } - }); - } + /** + * Finds the node with the supplied React-generated DOM ID. + * + * @param {string} id A React-generated DOM ID. + * @return {DOMElement} DOM node with the suppled `id`. + * @internal + */ + function getNode(id) { + if (!nodeCache.hasOwnProperty(id) || !isValid(nodeCache[id], id)) { + nodeCache[id] = ReactMount.findReactNodeByID(id); + } + return nodeCache[id]; + } - /** - * Reverts the '_' variable to its previous value and returns a reference to - * the `lodash` function. - * - * @static - * @memberOf _ - * @category Utilities - * @returns {Function} Returns the `lodash` function. - * @example - * - * var lodash = _.noConflict(); - */ - function noConflict() { - context._ = oldDash; - return this; - } + /** + * A node is "valid" if it is contained by a currently mounted container. + * + * This means that the node does not have to be contained by a document in + * order to be considered valid. + * + * @param {?DOMElement} node The candidate DOM node. + * @param {string} id The expected ID of the node. + * @return {boolean} Whether the node is contained by a mounted container. + */ + function isValid(node, id) { + if (node) { + ("production" !== process.env.NODE_ENV ? invariant( + internalGetID(node) === id, + 'ReactMount: Unexpected modification of `%s`', + ATTR_NAME + ) : invariant(internalGetID(node) === id)); - /** - * A no-operation function. - * - * @static - * @memberOf _ - * @category Utilities - * @example - * - * var object = { 'name': 'fred' }; - * _.noop(object) === undefined; - * // => true - */ - function noop() { - // no operation performed + var container = ReactMount.findReactContainerForID(id); + if (container && containsNode(container, node)) { + return true; } + } - /** - * Gets the number of milliseconds that have elapsed since the Unix epoch - * (1 January 1970 00:00:00 UTC). - * - * @static - * @memberOf _ - * @category Utilities - * @example - * - * var stamp = _.now(); - * _.defer(function() { console.log(_.now() - stamp); }); - * // => logs the number of milliseconds it took for the deferred function to be called - */ - var now = isNative(now = Date.now) && now || function() { - return new Date().getTime(); - }; + return false; + } - /** - * Converts the given value into an integer of the specified radix. - * If `radix` is `undefined` or `0` a `radix` of `10` is used unless the - * `value` is a hexadecimal, in which case a `radix` of `16` is used. - * - * Note: This method avoids differences in native ES3 and ES5 `parseInt` - * implementations. See http://es5.github.io/#E. - * - * @static - * @memberOf _ - * @category Utilities - * @param {string} value The value to parse. - * @param {number} [radix] The radix used to interpret the value to parse. - * @returns {number} Returns the new integer value. - * @example - * - * _.parseInt('08'); - * // => 8 - */ - var parseInt = nativeParseInt(whitespace + '08') == 8 ? nativeParseInt : function(value, radix) { - // Firefox < 21 and Opera < 15 follow the ES3 specified implementation of `parseInt` - return nativeParseInt(isString(value) ? value.replace(reLeadingSpacesAndZeros, '') : value, radix || 0); - }; + /** + * Causes the cache to forget about one React-specific ID. + * + * @param {string} id The ID to forget. + */ + function purgeID(id) { + delete nodeCache[id]; + } + + var deepestNodeSoFar = null; + function findDeepestCachedAncestorImpl(ancestorID) { + var ancestor = nodeCache[ancestorID]; + if (ancestor && isValid(ancestor, ancestorID)) { + deepestNodeSoFar = ancestor; + } else { + // This node isn't populated in the cache, so presumably none of its + // descendants are. Break out of the loop. + return false; + } + } + + /** + * Return the deepest cached node whose ID is a prefix of `targetID`. + */ + function findDeepestCachedAncestor(targetID) { + deepestNodeSoFar = null; + ReactInstanceHandles.traverseAncestors( + targetID, + findDeepestCachedAncestorImpl + ); + + var foundNode = deepestNodeSoFar; + deepestNodeSoFar = null; + return foundNode; + } + + /** + * Mounting is the process of initializing a React component by creatings its + * representative DOM elements and inserting them into a supplied `container`. + * Any prior content inside `container` is destroyed in the process. + * + * ReactMount.renderComponent( + * component, + * document.getElementById('container') + * ); + * + *