@samitouri / QOS-React / commits / 3089db94ce

Throw on invalid object type children

Same behavior as Stack

Andrew Clark committed Jan 30, 2017 at 11:29 UTC 3089db94ceacc5792d811d24423349fbbbaf78a1
1 file changed +45 -1
src/renderers/shared/fiber/ReactChildFiber.js
+45 -1
@@ -36,9 +36,11 @@ var emptyObject = require('emptyObject');
36 var getIteratorFn = require('getIteratorFn');
37 var invariant = require('invariant');
38 var ReactFeatureFlags = require('ReactFeatureFlags');
39 +var ReactCurrentOwner = require('ReactCurrentOwner');
40
41 if (__DEV__) {
42 var { getCurrentFiberStackAddendum } = require('ReactDebugCurrentFiber');
43 + var { getComponentName } = require('ReactFiberTreeReflection');
44 var warning = require('warning');
45 }
46
@@ -107,6 +109,37 @@ function coerceRef(current: ?Fiber, element: ReactElement) {
109 return mixedRef;
110 }
111
112 +function throwOnInvalidObjectType(newChild : Object) {
113 + const childrenString = String(newChild);
114 + let addendum = '';
115 + if (__DEV__) {
116 + addendum =
117 + ' If you meant to render a collection of children, use an array ' +
118 + 'instead or wrap the object using createFragment(object) from the ' +
119 + 'React add-ons.';
120 + if (newChild._isReactElement) {
121 + addendum =
122 + ' It looks like you\'re using an element created by a different ' +
123 + 'version of React. Make sure to use only one copy of React.';
124 + }
125 + if (ReactCurrentOwner.current) {
126 + const owner : Fiber = (ReactCurrentOwner.current : any);
127 + let name = getComponentName(owner);
128 + if (name) {
129 + addendum += ' Check the render method of `' + name + '`.';
130 + }
131 + }
132 + }
133 + invariant(
134 + false,
135 + 'Objects are not valid as a React child (found: %s).%s',
136 + childrenString === '[object Object]' ?
137 + 'object with keys {' + Object.keys(newChild).join(', ') + '}' :
138 + childrenString,
139 + addendum
140 + );
141 +}
142 +
143 // This wrapper function exists because I expect to clone the code in each path
144 // to be able to optimize each path individually by branching early. This needs
145 // a compiler or we can do it manually. Helpers that don't need this branching
@@ -418,6 +451,8 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
451 created.return = returnFiber;
452 return created;
453 }
454 +
455 + throwOnInvalidObjectType(newChild);
456 }
457
458 return null;
@@ -481,6 +516,8 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
516 }
517 return updateFragment(returnFiber, oldFiber, newChild, priority);
518 }
519 +
520 + throwOnInvalidObjectType(newChild);
521 }
522
523 return null;
@@ -536,6 +573,8 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
573 const matchedFiber = existingChildren.get(newIdx) || null;
574 return updateFragment(returnFiber, matchedFiber, newChild, priority);
575 }
576 +
577 + throwOnInvalidObjectType(newChild);
578 }
579
580 return null;
@@ -1083,7 +1122,8 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
1122 const disableNewFiberFeatures = ReactFeatureFlags.disableNewFiberFeatures;
1123
1124 // Handle object types
1086 - if (typeof newChild === 'object' && newChild !== null) {
1125 + const isObject = typeof newChild === 'object' && newChild !== null;
1126 + if (isObject) {
1127 // Support only the subset of return types that Stack supports. Treat
1128 // everything else as empty, but log a warning.
1129 if (disableNewFiberFeatures) {
@@ -1199,6 +1239,10 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) {
1239 );
1240 }
1241
1242 + if (isObject) {
1243 + throwOnInvalidObjectType(newChild);
1244 + }
1245 +
1246 if (!disableNewFiberFeatures && typeof newChild === 'undefined') {
1247 // If the new child is undefined, and the return fiber is a composite
1248 // component, throw an error. If Fiber return types are disabled,