text: /**
   * 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 ReactCompositeComponent
   */
  
  'use strict';
  
  var ReactComponentEnvironment = require("./ReactComponentEnvironment");
  var ReactContext = require("./ReactContext");
  var ReactCurrentOwner = require("./ReactCurrentOwner");
  var ReactElement = require("./ReactElement");
  var ReactElementValidator = require("./ReactElementValidator");
  var ReactInstanceMap = require("./ReactInstanceMap");
  var ReactLifeCycle = require("./ReactLifeCycle");
  var ReactNativeComponent = require("./ReactNativeComponent");
  var ReactPerf = require("./ReactPerf");
  var ReactPropTypeLocations = require("./ReactPropTypeLocations");
  var ReactPropTypeLocationNames = require("./ReactPropTypeLocationNames");
  var ReactReconciler = require("./ReactReconciler");
  var ReactUpdates = require("./ReactUpdates");
  
  var assign = require("./Object.assign");
  var emptyObject = require("./emptyObject");
  var invariant = require("./invariant");
  var shouldUpdateReactComponent = require("./shouldUpdateReactComponent");
  var warning = require("./warning");
  
  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 '';
  }
  
  /**
   * ------------------ The Life-Cycle of a Composite Component ------------------
   *
   * - constructor: Initialization of state. The instance is now retained.
   *   - componentWillMount
   *   - render
   *   - [children's constructors]
   *     - [children's componentWillMount and render]
   *     - [children's componentDidMount]
   *     - componentDidMount
   *
   *       Update Phases:
   *       - componentWillReceiveProps (only called if parent updated)
   *       - shouldComponentUpdate
   *         - componentWillUpdate
   *           - render
   *           - [children's constructors or receive props phases]
   *         - componentDidUpdate
   *
   *     - componentWillUnmount
   *     - [children's componentWillUnmount]
   *   - [children destroyed]
   * - (destroyed): The instance is now blank, released by React and ready for GC.
   *
   * -----------------------------------------------------------------------------
   */
  
  /**
   * An incrementing ID assigned to each component when it is mounted. This is
   * used to enforce the order in which `ReactUpdates` updates dirty components.
   *
   * @private
   */
  var nextMountID = 1;
  
  /**
   * @lends {ReactCompositeComponent.prototype}
   */
  var ReactCompositeComponentMixin = {
  
    /**
     * Base constructor for all composite component.
     *
     * @param {ReactElement} element
     * @final
     * @internal
     */
    construct: function(element) {
      this._currentElement = element;
      this._rootNodeID = null;
      this._instance = null;
  
      // See ReactUpdateQueue
      this._pendingElement = null;
      this._pendingStateQueue = null;
      this._pendingReplaceState = false;
      this._pendingForceUpdate = false;
  
      this._renderedComponent = null;
  
      this._context = null;
      this._mountOrder = 0;
      this._isTopLevel = false;
  
      // See ReactUpdates and ReactUpdateQueue.
      this._pendingCallbacks = null;
    },
  
    /**
     * Initializes the component, renders markup, and registers event listeners.
     *
     * @param {string} rootID DOM ID of the root node.
     * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
     * @return {?string} Rendered markup to be inserted into the DOM.
     * @final
     * @internal
     */
    mountComponent: function(rootID, transaction, context) {
      this._context = context;
      this._mountOrder = nextMountID++;
      this._rootNodeID = rootID;
  
      var publicProps = this._processProps(this._currentElement.props);
      var publicContext = this._processContext(this._currentElement._context);
  
      var Component = ReactNativeComponent.getComponentClassForElement(
        this._currentElement
      );
  
      // Initialize the public class
      var inst = new Component(publicProps, publicContext);
  
      if ("production" !== process.env.NODE_ENV) {
        // This will throw later in _renderValidatedComponent, but add an early
        // warning now to help debugging
        ("production" !== process.env.NODE_ENV ? warning(
          inst.render != null,
          '%s(...): No `render` method found on the returned component ' +
          'instance: you may have forgotten to define `render` in your ' +
          'component or you may have accidentally tried to render an element ' +
          'whose type is a function that isn\'t a React component.',
          Component.displayName || Component.name || 'Component'
        ) : null);
      }
  
      // 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;
  
      this._instance = inst;
  
      // Store a reference from the instance back to the internal representation
      ReactInstanceMap.set(inst, this);
  
      if ("production" !== process.env.NODE_ENV) {
        this._warnIfContextsDiffer(this._currentElement._context, context);
      }
  
      if ("production" !== process.env.NODE_ENV) {
        // 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.
        ("production" !== process.env.NODE_ENV ? 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'
        ) : null);
        ("production" !== process.env.NODE_ENV ? 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'
        ) : null);
        ("production" !== process.env.NODE_ENV ? warning(
          !inst.propTypes,
          'propTypes was defined as an instance property on %s. Use a static ' +
          'property to define propTypes instead.',
          this.getName() || 'a component'
        ) : null);
        ("production" !== process.env.NODE_ENV ? warning(
          !inst.contextTypes,
          'contextTypes was defined as an instance property on %s. Use a ' +
          'static property to define contextTypes instead.',
          this.getName() || 'a component'
        ) : null);
        ("production" !== process.env.NODE_ENV ? 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')
        ) : null);
      }
  
      var initialState = inst.state;
      if (initialState === undefined) {
        inst.state = initialState = null;
      }
      ("production" !== process.env.NODE_ENV ? invariant(
        typeof initialState === 'object' && !Array.isArray(initialState),
        '%s.state: must be set to an object or null',
        this.getName() || 'ReactCompositeComponent'
      ) : invariant(typeof initialState === 'object' && !Array.isArray(initialState)));
  
      this._pendingStateQueue = null;
      this._pendingReplaceState = false;
      this._pendingForceUpdate = false;
  
      var renderedElement;
  
      var previouslyMounting = ReactLifeCycle.currentlyMountingInstance;
      ReactLifeCycle.currentlyMountingInstance = this;
      try {
        if (inst.componentWillMount) {
          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);
          }
        }
  
        renderedElement = this._renderValidatedComponent();
      } finally {
        ReactLifeCycle.currentlyMountingInstance = previouslyMounting;
      }
  
      this._renderedComponent = this._instantiateReactComponent(
        renderedElement,
        this._currentElement.type // The wrapping type
      );
  
      var markup = ReactReconciler.mountComponent(
        this._renderedComponent,
        rootID,
        transaction,
        this._processChildContext(context)
      );
      if (inst.componentDidMount) {
        transaction.getReactMountReady().enqueue(inst.componentDidMount, inst);
      }
  
      return markup;
    },
  
    /**
     * Releases any resources allocated by `mountComponent`.
     *
     * @final
     * @internal
     */
    unmountComponent: function() {
      var inst = this._instance;
  
      if (inst.componentWillUnmount) {
        var previouslyUnmounting = ReactLifeCycle.currentlyUnmountingInstance;
        ReactLifeCycle.currentlyUnmountingInstance = this;
        try {
          inst.componentWillUnmount();
        } finally {
          ReactLifeCycle.currentlyUnmountingInstance = previouslyUnmounting;
        }
      }
  
      ReactReconciler.unmountComponent(this._renderedComponent);
      this._renderedComponent = null;
  
      // Reset pending fields
      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;
  
      // 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
      // destroyed (in event handlers).
      // TODO: inst.props = null;
      // TODO: inst.state = null;
      // TODO: inst.context = null;
    },
  
    /**
     * Schedule a partial update to the props. Only used for internal testing.
     *
     * @param {object} partialProps Subset of the next props.
     * @param {?function} callback Called after props are updated.
     * @final
     * @internal
     */
    _setPropsInternal: function(partialProps, callback) {
      // This is a deoptimized path. We optimize for always having an element.
      // This creates an extra internal element.
      var element = this._pendingElement || this._currentElement;
      this._pendingElement = ReactElement.cloneAndReplaceProps(
        element,
        assign({}, element.props, partialProps)
      );
      ReactUpdates.enqueueUpdate(this, callback);
    },
  
    /**
     * Filters the context object to only contain keys specified in
     * `contextTypes`
     *
     * @param {object} context
     * @return {?object}
     * @private
     */
    _maskContext: function(context) {
      var maskedContext = null;
      // This really should be getting the component class for the element,
      // but we know that we're not going to need it for built-ins.
      if (typeof this._currentElement.type === 'string') {
        return emptyObject;
      }
      var contextTypes = this._currentElement.type.contextTypes;
      if (!contextTypes) {
        return emptyObject;
      }
      maskedContext = {};
      for (var contextName in contextTypes) {
        maskedContext[contextName] = context[contextName];
      }
      return maskedContext;
    },
  
    /**
     * Filters the context object to only contain keys specified in
     * `contextTypes`, and asserts that they are valid.
     *
     * @param {object} context
     * @return {?object}
     * @private
     */
    _processContext: function(context) {
      var maskedContext = this._maskContext(context);
      if ("production" !== process.env.NODE_ENV) {
        var Component = ReactNativeComponent.getComponentClassForElement(
          this._currentElement
        );
        if (Component.contextTypes) {
          this._checkPropTypes(
            Component.contextTypes,
            maskedContext,
            ReactPropTypeLocations.context
          );
        }
      }
      return maskedContext;
    },
  
    /**
     * @param {object} currentContext
     * @return {object}
     * @private
     */
    _processChildContext: function(currentContext) {
      var inst = this._instance;
      var childContext = inst.getChildContext && inst.getChildContext();
      if (childContext) {
        ("production" !== process.env.NODE_ENV ? invariant(
          typeof inst.constructor.childContextTypes === 'object',
          '%s.getChildContext(): childContextTypes must be defined in order to ' +
          'use getChildContext().',
          this.getName() || 'ReactCompositeComponent'
        ) : invariant(typeof inst.constructor.childContextTypes === 'object'));
        if ("production" !== process.env.NODE_ENV) {
          this._checkPropTypes(
            inst.constructor.childContextTypes,
            childContext,
            ReactPropTypeLocations.childContext
          );
        }
        for (var name in childContext) {
          ("production" !== process.env.NODE_ENV ? invariant(
            name in inst.constructor.childContextTypes,
            '%s.getChildContext(): key "%s" is not defined in childContextTypes.',
            this.getName() || 'ReactCompositeComponent',
            name
          ) : invariant(name in inst.constructor.childContextTypes));
        }
        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 ("production" !== process.env.NODE_ENV) {
        var Component = ReactNativeComponent.getComponentClassForElement(
          this._currentElement
        );
        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
     * @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.
            ("production" !== process.env.NODE_ENV ? invariant(
              typeof propTypes[propName] === 'function',
              '%s: %s type `%s` is invalid; it must be a function, usually ' +
              'from React.PropTypes.',
              componentName || 'React class',
              ReactPropTypeLocationNames[location],
              propName
            ) : invariant(typeof propTypes[propName] === 'function'));
            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
            // React.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
              ("production" !== process.env.NODE_ENV ? warning(
                false,
                'Failed Composite propType: %s%s',
                error.message,
                addendum
              ) : null);
            } else {
              ("production" !== process.env.NODE_ENV ? warning(
                false,
                'Failed Context Types: %s%s',
                error.message,
                addendum
              ) : null);
            }
          }
        }
      }
    },
  
    receiveComponent: function(nextElement, transaction, nextContext) {
      var prevElement = this._currentElement;
      var prevContext = this._context;
  
      this._pendingElement = null;
  
      this.updateComponent(
        transaction,
        prevElement,
        nextElement,
        prevContext,
        nextContext
      );
    },
  
    /**
     * 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) {
        if ("production" !== process.env.NODE_ENV) {
          ReactElementValidator.checkAndWarnForMutatedProps(
            this._currentElement
          );
        }
  
        this.updateComponent(
          transaction,
          this._currentElement,
          this._currentElement,
          this._context,
          this._context
        );
      }
    },
  
    /**
     * Compare two contexts, warning if they are different
     * TODO: Remove this check when owner-context is removed
     */
     _warnIfContextsDiffer: function(ownerBasedContext, parentBasedContext) {
      ownerBasedContext = this._maskContext(ownerBasedContext);
      parentBasedContext = this._maskContext(parentBasedContext);
      var parentKeys = Object.keys(parentBasedContext).sort();
      var displayName = this.getName() || 'ReactCompositeComponent';
      for (var i = 0; i < parentKeys.length; i++) {
        var key = parentKeys[i];
        ("production" !== process.env.NODE_ENV ? warning(
          ownerBasedContext[key] === parentBasedContext[key],
          'owner-based and parent-based contexts differ '  +
          '(values: `%s` vs `%s`) for key (%s) while mounting %s ' +
          '(see: http://fb.me/react-context-by-parent)',
          ownerBasedContext[key],
          parentBasedContext[key],
          key,
          displayName
        ) : 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.
     *
     * By default, this implements React's rendering and reconciliation algorithm.
     * Sophisticated clients may wish to override this.
     *
     * @param {ReactReconcileTransaction} transaction
     * @param {ReactElement} prevParentElement
     * @param {ReactElement} nextParentElement
     * @internal
     * @overridable
     */
    updateComponent: function(
      transaction,
      prevParentElement,
      nextParentElement,
      prevUnmaskedContext,
      nextUnmaskedContext
    ) {
      var inst = this._instance;
  
      var nextContext = inst.context;
      var nextProps = inst.props;
  
      // Distinguish between a props update versus a simple state update
      if (prevParentElement !== nextParentElement) {
        nextContext = this._processContext(nextParentElement._context);
        nextProps = this._processProps(nextParentElement.props);
  
        if ("production" !== process.env.NODE_ENV) {
          if (nextUnmaskedContext != null) {
            this._warnIfContextsDiffer(
              nextParentElement._context,
              nextUnmaskedContext
            );
          }
        }
  
        // 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.componentWillReceiveProps(nextProps, nextContext);
        }
      }
  
      var nextState = this._processPendingState(nextProps, nextContext);
  
      var shouldUpdate =
        this._pendingForceUpdate ||
        !inst.shouldComponentUpdate ||
        inst.shouldComponentUpdate(nextProps, nextState, nextContext);
  
      if ("production" !== process.env.NODE_ENV) {
        ("production" !== process.env.NODE_ENV ? warning(
          typeof shouldUpdate !== 'undefined',
          '%s.shouldComponentUpdate(): Returned undefined instead of a ' +
          'boolean value. Make sure to return true or false.',
          this.getName() || 'ReactCompositeComponent'
        ) : 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;
        this._context = nextUnmaskedContext;
        inst.props = nextProps;
        inst.state = nextState;
        inst.context = nextContext;
      }
    },
  
    _processPendingState: function(props, context) {
      var inst = this._instance;
      var queue = this._pendingStateQueue;
      var replace = this._pendingReplaceState;
      this._pendingReplaceState = false;
      this._pendingStateQueue = null;
  
      if (!queue) {
        return 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
        );
      }
  
      return nextState;
    },
  
    /**
     * Merges new props and state, notifies delegate methods of update and
     * performs update.
     *
     * @param {ReactElement} nextElement Next element
     * @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 inst = this._instance;
  
      var prevProps = inst.props;
      var prevState = inst.state;
      var prevContext = inst.context;
  
      if (inst.componentWillUpdate) {
        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 (inst.componentDidUpdate) {
        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();
      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,
          this._currentElement.type
        );
        var nextMarkup = ReactReconciler.mountComponent(
          this._renderedComponent,
          thisID,
          transaction,
          this._processChildContext(context)
        );
        this._replaceNodeWithMarkupByID(prevComponentID, nextMarkup);
      }
    },
  
    /**
     * @protected
     */
    _replaceNodeWithMarkupByID: function(prevComponentID, nextMarkup) {
      ReactComponentEnvironment.replaceNodeWithMarkupByID(
        prevComponentID,
        nextMarkup
      );
    },
  
    /**
     * @protected
     */
    _renderValidatedComponentWithoutOwnerOrContext: function() {
      var inst = this._instance;
      var renderedComponent = inst.render();
      if ("production" !== process.env.NODE_ENV) {
        // We allow auto-mocks to proceed as if they're returning null.
        if (typeof 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;
      var previousContext = ReactContext.current;
      ReactContext.current = this._processChildContext(
        this._currentElement._context
      );
      ReactCurrentOwner.current = this;
      try {
        renderedComponent =
          this._renderValidatedComponentWithoutOwnerOrContext();
      } finally {
        ReactContext.current = previousContext;
        ReactCurrentOwner.current = null;
      }
      ("production" !== process.env.NODE_ENV ? invariant(
        // TODO: An `isValidNode` function would probably be more appropriate
        renderedComponent === null || renderedComponent === false ||
        ReactElement.isValidElement(renderedComponent),
        '%s.render(): A valid ReactComponent must be returned. You may have ' +
          'returned undefined, an array or some other invalid object.',
        this.getName() || 'ReactCompositeComponent'
      ) : invariant(// TODO: An `isValidNode` function would probably be more appropriate
      renderedComponent === null || renderedComponent === false ||
      ReactElement.isValidElement(renderedComponent)));
      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();
      var refs = inst.refs === emptyObject ? (inst.refs = {}) : inst.refs;
      refs[ref] = component.getPublicInstance();
    },
  
    /**
     * Detaches a reference name.
     *
     * @param {string} ref Name to dereference.
     * @final
     * @private
     */
    detachRef: function(ref) {
      var refs = this.getPublicInstance().refs;
      delete refs[ref];
    },
  
    /**
     * Get a text description of the component that can be used to identify it
     * in error messages.
     * @return {string} The name or null.
     * @internal
     */
    getName: function() {
      var type = this._currentElement.type;
      var constructor = this._instance && this._instance.constructor;
      return (
        type.displayName || (constructor && constructor.displayName) ||
        type.name || (constructor && constructor.name) ||
        null
      );
    },
  
    /**
     * Get the publicly accessible representation of this component - i.e. what
     * is exposed by refs and returned by React.render. Can be null for stateless
     * components.
     *
     * @return {ReactComponent} the public component instance.
     * @internal
     */
    getPublicInstance: function() {
      return this._instance;
    },
  
    // Stub
    _instantiateReactComponent: null
  
  };
  
  ReactPerf.measureMethods(
    ReactCompositeComponentMixin,
    'ReactCompositeComponent',
    {
      mountComponent: 'mountComponent',
      updateComponent: 'updateComponent',
      _renderValidatedComponent: '_renderValidatedComponent'
    }
  );
  
  var ReactCompositeComponent = {
  
    Mixin: ReactCompositeComponentMixin
  
  };
  
  module.exports = ReactCompositeComponent;
  