d2-ui
Version:
144 lines (124 loc) • 5.43 kB
JavaScript
/**
* 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 instantiateReactComponent
*/
;
var _assign = require('object-assign');
var ReactCompositeComponent = require('./ReactCompositeComponent');
var ReactEmptyComponent = require('./ReactEmptyComponent');
var ReactNativeComponent = require('./ReactNativeComponent');
var ReactInstrumentation = require('./ReactInstrumentation');
var invariant = require('fbjs/lib/invariant');
var warning = require('fbjs/lib/warning');
// To avoid a cyclic dependency, we create the final class in this module
var ReactCompositeComponentWrapper = function (element) {
this.construct(element);
};
_assign(ReactCompositeComponentWrapper.prototype, ReactCompositeComponent.Mixin, {
_instantiateReactComponent: instantiateReactComponent
});
function getDeclarationErrorAddendum(owner) {
if (owner) {
var name = owner.getName();
if (name) {
return ' Check the render method of `' + name + '`.';
}
}
return '';
}
function getDisplayName(instance) {
var element = instance._currentElement;
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 if (instance.getName) {
return instance.getName() || 'Unknown';
} else {
return element.type.displayName || element.type.name || 'Unknown';
}
}
/**
* Check if the type reference is a known internal type. I.e. not a user
* provided composite type.
*
* @param {function} type
* @return {boolean} Returns true if this is a valid internal type.
*/
function isInternalComponentType(type) {
return typeof type === 'function' && typeof type.prototype !== 'undefined' && typeof type.prototype.mountComponent === 'function' && typeof type.prototype.receiveComponent === 'function';
}
var nextDebugID = 1;
/**
* Given a ReactNode, create an instance that will actually be mounted.
*
* @param {ReactNode} node
* @return {object} A new instance of the element's constructor.
* @protected
*/
function instantiateReactComponent(node) {
var instance;
var isEmpty = node === null || node === false;
if (isEmpty) {
instance = ReactEmptyComponent.create(instantiateReactComponent);
} else if (typeof node === 'object') {
var element = node;
!(element && (typeof element.type === 'function' || typeof element.type === 'string')) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Element type is invalid: expected a string (for built-in components) ' + 'or a class/function (for composite components) but got: %s.%s', element.type == null ? element.type : typeof element.type, getDeclarationErrorAddendum(element._owner)) : invariant(false) : void 0;
// Special case string values
if (typeof element.type === 'string') {
instance = ReactNativeComponent.createInternalComponent(element);
} else if (isInternalComponentType(element.type)) {
// This is temporarily available for custom components that are not string
// representations. I.e. ART. Once those are updated to use the string
// representation, we can drop this code path.
instance = new element.type(element);
} else {
instance = new ReactCompositeComponentWrapper(element);
}
} else if (typeof node === 'string' || typeof node === 'number') {
instance = ReactNativeComponent.createInstanceForText(node);
} else {
!false ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Encountered invalid React node of type %s', typeof node) : invariant(false) : void 0;
}
if (process.env.NODE_ENV !== 'production') {
process.env.NODE_ENV !== 'production' ? warning(typeof instance.mountComponent === 'function' && typeof instance.receiveComponent === 'function' && typeof instance.getNativeNode === 'function' && typeof instance.unmountComponent === 'function', 'Only React Components can be mounted.') : void 0;
}
// These two fields are used by the DOM and ART diffing algorithms
// respectively. Instead of using expandos on components, we should be
// storing the state needed by the diffing algorithms elsewhere.
instance._mountIndex = 0;
instance._mountImage = null;
if (process.env.NODE_ENV !== 'production') {
instance._isOwnerNecessary = false;
instance._warnedAboutRefsInRender = false;
}
if (process.env.NODE_ENV !== 'production') {
var debugID = isEmpty ? 0 : nextDebugID++;
instance._debugID = debugID;
if (debugID !== 0) {
var displayName = getDisplayName(instance);
ReactInstrumentation.debugTool.onSetDisplayName(debugID, displayName);
var owner = node && node._owner;
if (owner) {
ReactInstrumentation.debugTool.onSetOwner(debugID, owner._debugID);
}
}
}
// Internal instances should fully constructed at this point, so they should
// not get any new fields added to them at this point.
if (process.env.NODE_ENV !== 'production') {
if (Object.preventExtensions) {
Object.preventExtensions(instance);
}
}
return instance;
}
module.exports = instantiateReactComponent;