UNPKG

5.06 kBJavaScriptView Raw
1/**
2 * Copyright 2013-present, Facebook, Inc.
3 * All rights reserved.
4 *
5 * This source code is licensed under the BSD-style license found in the
6 * LICENSE file in the root directory of this source tree. An additional grant
7 * of patent rights can be found in the PATENTS file in the same directory.
8 *
9 */
10
11'use strict';
12
13var _prodInvariant = require('./reactProdInvariant'),
14 _assign = require('object-assign');
15
16var ReactCompositeComponent = require('./ReactCompositeComponent');
17var ReactEmptyComponent = require('./ReactEmptyComponent');
18var ReactHostComponent = require('./ReactHostComponent');
19
20var getNextDebugID = require('react/lib/getNextDebugID');
21var invariant = require('fbjs/lib/invariant');
22var warning = require('fbjs/lib/warning');
23
24// To avoid a cyclic dependency, we create the final class in this module
25var ReactCompositeComponentWrapper = function (element) {
26 this.construct(element);
27};
28
29function getDeclarationErrorAddendum(owner) {
30 if (owner) {
31 var name = owner.getName();
32 if (name) {
33 return ' Check the render method of `' + name + '`.';
34 }
35 }
36 return '';
37}
38
39/**
40 * Check if the type reference is a known internal type. I.e. not a user
41 * provided composite type.
42 *
43 * @param {function} type
44 * @return {boolean} Returns true if this is a valid internal type.
45 */
46function isInternalComponentType(type) {
47 return typeof type === 'function' && typeof type.prototype !== 'undefined' && typeof type.prototype.mountComponent === 'function' && typeof type.prototype.receiveComponent === 'function';
48}
49
50/**
51 * Given a ReactNode, create an instance that will actually be mounted.
52 *
53 * @param {ReactNode} node
54 * @param {boolean} shouldHaveDebugID
55 * @return {object} A new instance of the element's constructor.
56 * @protected
57 */
58function instantiateReactComponent(node, shouldHaveDebugID) {
59 var instance;
60
61 if (node === null || node === false) {
62 instance = ReactEmptyComponent.create(instantiateReactComponent);
63 } else if (typeof node === 'object') {
64 var element = node;
65 var type = element.type;
66 if (typeof type !== 'function' && typeof type !== 'string') {
67 var info = '';
68 if (process.env.NODE_ENV !== 'production') {
69 if (type === undefined || typeof type === 'object' && type !== null && Object.keys(type).length === 0) {
70 info += ' You likely forgot to export your component from the file ' + "it's defined in.";
71 }
72 }
73 info += getDeclarationErrorAddendum(element._owner);
74 !false ? 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', type == null ? type : typeof type, info) : _prodInvariant('130', type == null ? type : typeof type, info) : void 0;
75 }
76
77 // Special case string values
78 if (typeof element.type === 'string') {
79 instance = ReactHostComponent.createInternalComponent(element);
80 } else if (isInternalComponentType(element.type)) {
81 // This is temporarily available for custom components that are not string
82 // representations. I.e. ART. Once those are updated to use the string
83 // representation, we can drop this code path.
84 instance = new element.type(element);
85
86 // We renamed this. Allow the old name for compat. :(
87 if (!instance.getHostNode) {
88 instance.getHostNode = instance.getNativeNode;
89 }
90 } else {
91 instance = new ReactCompositeComponentWrapper(element);
92 }
93 } else if (typeof node === 'string' || typeof node === 'number') {
94 instance = ReactHostComponent.createInstanceForText(node);
95 } else {
96 !false ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Encountered invalid React node of type %s', typeof node) : _prodInvariant('131', typeof node) : void 0;
97 }
98
99 if (process.env.NODE_ENV !== 'production') {
100 process.env.NODE_ENV !== 'production' ? warning(typeof instance.mountComponent === 'function' && typeof instance.receiveComponent === 'function' && typeof instance.getHostNode === 'function' && typeof instance.unmountComponent === 'function', 'Only React Components can be mounted.') : void 0;
101 }
102
103 // These two fields are used by the DOM and ART diffing algorithms
104 // respectively. Instead of using expandos on components, we should be
105 // storing the state needed by the diffing algorithms elsewhere.
106 instance._mountIndex = 0;
107 instance._mountImage = null;
108
109 if (process.env.NODE_ENV !== 'production') {
110 instance._debugID = shouldHaveDebugID ? getNextDebugID() : 0;
111 }
112
113 // Internal instances should fully constructed at this point, so they should
114 // not get any new fields added to them at this point.
115 if (process.env.NODE_ENV !== 'production') {
116 if (Object.preventExtensions) {
117 Object.preventExtensions(instance);
118 }
119 }
120
121 return instance;
122}
123
124_assign(ReactCompositeComponentWrapper.prototype, ReactCompositeComponent, {
125 _instantiateReactComponent: instantiateReactComponent
126});
127
128module.exports = instantiateReactComponent;
\No newline at end of file