UNPKG

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