@samitouri / QOS-React / commits / 5c6a496d98

Inline some internals, reduce shared/ utilities between isomorphic and renderers (#9903)

* Make ReactControlledValuePropTypes DEV-only * Remove canDefineProperty This breaks IE8. We don't support it. * Remove getNextDebugID It was added temporarily to avoid Stack shared state issues across renderers. Not a problem anymore. * Make KeyEscapeUtils.unescape() DEV-only * Remove unused deprecated() module It's unlikely we'll deprecate anything else on React.* object soon. * Inline getIteratorFn at the call sites * Inline ReactElementSymbol * Inline KeyEscapeUtils into Children and move the file into Stack It's only used in one place in isomorphic. It's used more broadly in Stack so we move it there to die. * Update artifacts * Reorder declarations for consistency * Fix Flow

Dan Abramov committed Jun 9, 2017 at 12:41 UTC 5c6a496d98b80d19d851c2ec3a56d760b7118a50
22 files changed +328 -465
scripts/fiber/tests-passing.txt
+1 -4
@@ -66,6 +66,7 @@ src/isomorphic/children/__tests__/ReactChildren-test.js
66 * should count the number of children in flat structure
67 * should count the number of children in nested structure
68 * should flatten children to an array
69 +* should escape keys
70 * should throw on object
71 * should throw on regex
72 * warns for keys for arrays of elements in a fragment
@@ -1992,10 +1993,6 @@ src/renderers/testing/__tests__/ReactTestRenderer-test.js
1993 * can update text nodes when rendered as root
1994 * can render and update root fragments
1995
1995 -src/shared/utils/__tests__/KeyEscapeUtils-test.js
1996 -* should properly escape and wrap user defined keys
1997 -* should properly unescape and unwrap user defined keys
1998 -
1996 src/shared/utils/__tests__/PooledClass-test.js
1997 * should initialize a pool correctly
1998 * should return a new instance when the pool is empty
scripts/rollup/results.json
+65 -65
@@ -1,52 +1,52 @@
1 {
2 "bundleSizes": {
3 "react.development.js (UMD_DEV)": {
4 - "size": 73848,
5 - "gzip": 18852
4 + "size": 71599,
5 + "gzip": 18504
6 },
7 "react.production.min.js (UMD_PROD)": {
8 - "size": 7756,
9 - "gzip": 3089
8 + "size": 7585,
9 + "gzip": 2999
10 },
11 "react.development.js (NODE_DEV)": {
12 - "size": 64064,
13 - "gzip": 16441
12 + "size": 61813,
13 + "gzip": 16090
14 },
15 "react.production.min.js (NODE_PROD)": {
16 - "size": 6650,
17 - "gzip": 2671
16 + "size": 6483,
17 + "gzip": 2580
18 },
19 "React-dev.js (FB_DEV)": {
20 - "size": 63268,
21 - "gzip": 16164
20 + "size": 61047,
21 + "gzip": 15810
22 },
23 "React-prod.js (FB_PROD)": {
24 - "size": 30387,
25 - "gzip": 7986
24 + "size": 29022,
25 + "gzip": 7688
26 },
27 "react-dom.development.js (UMD_DEV)": {
28 - "size": 610969,
29 - "gzip": 139956
28 + "size": 609601,
29 + "gzip": 139786
30 },
31 "react-dom.production.min.js (UMD_PROD)": {
32 - "size": 126083,
33 - "gzip": 39657
32 + "size": 126103,
33 + "gzip": 39656
34 },
35 "react-dom.development.js (NODE_DEV)": {
36 - "size": 569585,
37 - "gzip": 130099
36 + "size": 568219,
37 + "gzip": 130074
38 },
39 "react-dom.production.min.js (NODE_PROD)": {
40 - "size": 122448,
41 - "gzip": 38377
40 + "size": 122468,
41 + "gzip": 38382
42 },
43 "ReactDOMFiber-dev.js (FB_DEV)": {
44 - "size": 570829,
45 - "gzip": 130755
44 + "size": 569463,
45 + "gzip": 130731
46 },
47 "ReactDOMFiber-prod.js (FB_PROD)": {
48 - "size": 429650,
49 - "gzip": 97470
48 + "size": 428904,
49 + "gzip": 97327
50 },
51 "react-dom-test-utils.development.js (NODE_DEV)": {
52 "size": 52921,
@@ -57,84 +57,84 @@
57 "gzip": 13637
58 },
59 "ReactDOMServerStack-dev.js (FB_DEV)": {
60 - "size": 463011,
61 - "gzip": 112037
60 + "size": 460708,
61 + "gzip": 111956
62 },
63 "ReactDOMServerStack-prod.js (FB_PROD)": {
64 - "size": 339859,
65 - "gzip": 82131
64 + "size": 338131,
65 + "gzip": 81938
66 },
67 "react-dom-server.development.js (UMD_DEV)": {
68 - "size": 307624,
69 - "gzip": 77081
68 + "size": 305758,
69 + "gzip": 76969
70 },
71 "react-dom-server.production.min.js (UMD_PROD)": {
72 - "size": 66076,
73 - "gzip": 22578
72 + "size": 65877,
73 + "gzip": 22507
74 },
75 "react-dom-server.development.js (NODE_DEV)": {
76 - "size": 266407,
77 - "gzip": 67681
76 + "size": 264541,
77 + "gzip": 67429
78 },
79 "react-dom-server.production.min.js (NODE_PROD)": {
80 - "size": 62426,
81 - "gzip": 21275
80 + "size": 62227,
81 + "gzip": 21216
82 },
83 "ReactDOMServerStream-dev.js (FB_DEV)": {
84 - "size": 265929,
85 - "gzip": 67653
84 + "size": 264063,
85 + "gzip": 67395
86 },
87 "ReactDOMServerStream-prod.js (FB_PROD)": {
88 - "size": 199167,
89 - "gzip": 51447
88 + "size": 197791,
89 + "gzip": 51010
90 },
91 "react-art.development.js (UMD_DEV)": {
92 - "size": 360814,
93 - "gzip": 80077
92 + "size": 359726,
93 + "gzip": 79927
94 },
95 "react-art.production.min.js (UMD_PROD)": {
96 - "size": 98709,
96 + "size": 98725,
97 "gzip": 29979
98 },
99 "react-art.development.js (NODE_DEV)": {
100 - "size": 282155,
101 - "gzip": 59988
100 + "size": 281067,
101 + "gzip": 59839
102 },
103 "react-art.production.min.js (NODE_PROD)": {
104 - "size": 60094,
105 - "gzip": 18032
104 + "size": 60110,
105 + "gzip": 18041
106 },
107 "ReactARTFiber-dev.js (FB_DEV)": {
108 - "size": 281653,
109 - "gzip": 59957
108 + "size": 280565,
109 + "gzip": 59808
110 },
111 "ReactARTFiber-prod.js (FB_PROD)": {
112 - "size": 218977,
113 - "gzip": 45607
112 + "size": 218583,
113 + "gzip": 45494
114 },
115 "ReactNativeStack-dev.js (RN_DEV)": {
116 - "size": 185386,
117 - "gzip": 35756
116 + "size": 185110,
117 + "gzip": 35690
118 },
119 "ReactNativeStack-prod.js (RN_PROD)": {
120 - "size": 137169,
121 - "gzip": 26154
120 + "size": 136665,
121 + "gzip": 26014
122 },
123 "ReactNativeFiber-dev.js (RN_DEV)": {
124 - "size": 282783,
125 - "gzip": 50688
124 + "size": 282752,
125 + "gzip": 50683
126 },
127 "ReactNativeFiber-prod.js (RN_PROD)": {
128 - "size": 220885,
129 - "gzip": 37833
128 + "size": 220854,
129 + "gzip": 37832
130 },
131 "react-test-renderer.development.js (NODE_DEV)": {
132 - "size": 279649,
133 - "gzip": 58862
132 + "size": 278561,
133 + "gzip": 58711
134 },
135 "ReactTestRendererFiber-dev.js (FB_DEV)": {
136 - "size": 279138,
137 - "gzip": 58819
136 + "size": 278050,
137 + "gzip": 58674
138 },
139 "react-test-renderer-shallow.development.js (NODE_DEV)": {
140 "size": 8108,
@@ -145,8 +145,8 @@
145 "gzip": 2234
146 },
147 "react-noop-renderer.development.js (NODE_DEV)": {
148 - "size": 270811,
149 - "gzip": 56635
148 + "size": 269723,
149 + "gzip": 56481
150 }
151 }
152 }
\ No newline at end of file
src/isomorphic/children/__tests__/ReactChildren-test.js
+19
@@ -841,6 +841,25 @@ describe('ReactChildren', () => {
841 ]);
842 });
843
844 + it('should escape keys', () => {
845 + var zero = <div key="1" />;
846 + var one = <div key="1=::=2" />;
847 + var instance = (
848 + <div>
849 + {zero}
850 + {one}
851 + </div>
852 + );
853 + var mappedChildren = React.Children.map(
854 + instance.props.children,
855 + kid => kid,
856 + );
857 + expect(mappedChildren).toEqual([
858 + <div key=".$1" />,
859 + <div key=".$1=0=2=2=02" />,
860 + ]);
861 + });
862 +
863 it('should throw on object', () => {
864 expect(function() {
865 React.Children.forEach({a: 1, b: 2}, function() {}, null);
src/isomorphic/children/flattenChildren.js
+4 -3
@@ -12,7 +12,6 @@
12
13 'use strict';
14
15 -var KeyEscapeUtils = require('KeyEscapeUtils');
15 var traverseAllChildren = require('traverseAllChildren');
16 var warning = require('fbjs/lib/warning');
17 var ReactComponentTreeHook = require('ReactComponentTreeHook');
@@ -28,6 +27,7 @@ function flattenSingleChildIntoContext(
27 child: ReactElement<any>,
28 name: string,
29 selfDebugID?: number,
30 + unescapeInDev: (name: string) => string,
31 ): void {
32 // We found a component instance.
33 if (traverseContext && typeof traverseContext === 'object') {
@@ -40,7 +40,7 @@ function flattenSingleChildIntoContext(
40 'flattenChildren(...): Encountered two children with the same key, ' +
41 '`%s`. Child keys must be unique; when two children share a key, only ' +
42 'the first child will be used.%s',
43 - KeyEscapeUtils.unescape(name),
43 + unescapeInDev(name),
44 ReactComponentTreeHook.getStackAddendumByID(selfDebugID),
45 );
46 }
@@ -68,12 +68,13 @@ function flattenChildren(
68 if (__DEV__) {
69 traverseAllChildren(
70 children,
71 - (traverseContext, child, name) =>
71 + (traverseContext, child, name, unescapeInDev) =>
72 flattenSingleChildIntoContext(
73 traverseContext,
74 child,
75 name,
76 selfDebugID,
77 + unescapeInDev,
78 ),
79 result,
80 );
src/isomorphic/children/traverseAllChildren.js
+54 -9
@@ -11,13 +11,18 @@
11
12 'use strict';
13
14 -var REACT_ELEMENT_TYPE = require('ReactElementSymbol');
15 -
16 -var getIteratorFn = require('getIteratorFn');
14 +var emptyFunction = require('fbjs/lib/emptyFunction');
15 var invariant = require('fbjs/lib/invariant');
18 -var KeyEscapeUtils = require('KeyEscapeUtils');
16 var warning = require('fbjs/lib/warning');
17
18 +var ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;
19 +var FAUX_ITERATOR_SYMBOL = '@@iterator'; // Before Symbol spec.
20 +// The Symbol used to tag the ReactElement type. If there is no native Symbol
21 +// nor polyfill, then a plain number is used for performance.
22 +var REACT_ELEMENT_TYPE =
23 + (typeof Symbol === 'function' && Symbol.for && Symbol.for('react.element')) ||
24 + 0xeac7;
25 +
26 if (__DEV__) {
27 var {getCurrentStackAddendum} = require('ReactComponentTreeHook');
28 }
@@ -26,10 +31,47 @@ var SEPARATOR = '.';
31 var SUBSEPARATOR = ':';
32
33 /**
29 - * This is inlined from ReactElement since this file is shared between
30 - * isomorphic and renderers. We could extract this to a
34 + * Escape and wrap key so it is safe to use as a reactid
35 *
36 + * @param {string} key to be escaped.
37 + * @return {string} the escaped key.
38 */
39 +function escape(key: string): string {
40 + var escapeRegex = /[=:]/g;
41 + var escaperLookup = {
42 + '=': '=0',
43 + ':': '=2',
44 + };
45 + var escapedString = ('' + key).replace(escapeRegex, function(match) {
46 + return escaperLookup[match];
47 + });
48 +
49 + return '$' + escapedString;
50 +}
51 +
52 +var unescapeInDev = emptyFunction;
53 +if (__DEV__) {
54 + /**
55 + * Unescape and unwrap key for human-readable display
56 + *
57 + * @param {string} key to unescape.
58 + * @return {string} the unescaped key.
59 + */
60 + unescapeInDev = function(key: string): string {
61 + var unescapeRegex = /(=0|=2)/g;
62 + var unescaperLookup = {
63 + '=0': '=',
64 + '=2': ':',
65 + };
66 + var keySubstring = key[0] === '.' && key[1] === '$'
67 + ? key.substring(2)
68 + : key.substring(1);
69 +
70 + return ('' + keySubstring).replace(unescapeRegex, function(match) {
71 + return unescaperLookup[match];
72 + });
73 + };
74 +}
75
76 /**
77 * TODO: Test that a single child and an array with one item have the same key
@@ -54,7 +96,7 @@ function getComponentKey(component, index) {
96 component.key != null
97 ) {
98 // Explicit key
57 - return KeyEscapeUtils.escape(component.key);
99 + return escape(component.key);
100 }
101 // Implicit key determined by the index in the set
102 return index.toString(36);
@@ -95,6 +137,7 @@ function traverseAllChildrenImpl(
137 // If it's the only child, treat the name as if it was wrapped in an array
138 // so that it's consistent if the number of children grows.
139 nameSoFar === '' ? SEPARATOR + getComponentKey(children, 0) : nameSoFar,
140 + unescapeInDev,
141 );
142 return 1;
143 }
@@ -116,8 +159,10 @@ function traverseAllChildrenImpl(
159 );
160 }
161 } else {
119 - var iteratorFn = getIteratorFn(children);
120 - if (iteratorFn) {
162 + var iteratorFn =
163 + (ITERATOR_SYMBOL && children[ITERATOR_SYMBOL]) ||
164 + children[FAUX_ITERATOR_SYMBOL];
165 + if (typeof iteratorFn === 'function') {
166 if (__DEV__) {
167 // Warn about using Maps as children
168 if (iteratorFn === children.entries) {
src/isomorphic/classic/element/ReactElement.js
+26 -29
@@ -14,10 +14,13 @@
14 var ReactCurrentOwner = require('ReactCurrentOwner');
15
16 var warning = require('fbjs/lib/warning');
17 -var canDefineProperty = require('canDefineProperty');
17 var hasOwnProperty = Object.prototype.hasOwnProperty;
18
20 -var REACT_ELEMENT_TYPE = require('ReactElementSymbol');
19 +// The Symbol used to tag the ReactElement type. If there is no native Symbol
20 +// nor polyfill, then a plain number is used for performance.
21 +var REACT_ELEMENT_TYPE =
22 + (typeof Symbol === 'function' && Symbol.for && Symbol.for('react.element')) ||
23 + 0xeac7;
24
25 var RESERVED_PROPS = {
26 key: true,
@@ -140,33 +143,27 @@ var ReactElement = function(type, key, ref, self, source, owner, props) {
143 // the validation flag non-enumerable (where possible, which should
144 // include every environment we run tests in), so the test framework
145 // ignores it.
143 - if (canDefineProperty) {
144 - Object.defineProperty(element._store, 'validated', {
145 - configurable: false,
146 - enumerable: false,
147 - writable: true,
148 - value: false,
149 - });
150 - // self and source are DEV only properties.
151 - Object.defineProperty(element, '_self', {
152 - configurable: false,
153 - enumerable: false,
154 - writable: false,
155 - value: self,
156 - });
157 - // Two elements created in two different places should be considered
158 - // equal for testing purposes and therefore we hide it from enumeration.
159 - Object.defineProperty(element, '_source', {
160 - configurable: false,
161 - enumerable: false,
162 - writable: false,
163 - value: source,
164 - });
165 - } else {
166 - element._store.validated = false;
167 - element._self = self;
168 - element._source = source;
169 - }
146 + Object.defineProperty(element._store, 'validated', {
147 + configurable: false,
148 + enumerable: false,
149 + writable: true,
150 + value: false,
151 + });
152 + // self and source are DEV only properties.
153 + Object.defineProperty(element, '_self', {
154 + configurable: false,
155 + enumerable: false,
156 + writable: false,
157 + value: self,
158 + });
159 + // Two elements created in two different places should be considered
160 + // equal for testing purposes and therefore we hide it from enumeration.
161 + Object.defineProperty(element, '_source', {
162 + configurable: false,
163 + enumerable: false,
164 + writable: false,
165 + value: source,
166 + });
167 if (Object.freeze) {
168 Object.freeze(element.props);
169 Object.freeze(element);
src/isomorphic/classic/element/ReactElementValidator.js
+22 -21
@@ -21,9 +21,7 @@
21 var ReactCurrentOwner = require('ReactCurrentOwner');
22 var ReactElement = require('ReactElement');
23
24 -var canDefineProperty = require('canDefineProperty');
24 var getComponentName = require('getComponentName');
26 -var getIteratorFn = require('getIteratorFn');
25
26 if (__DEV__) {
27 var checkPropTypes = require('prop-types/checkPropTypes');
@@ -33,6 +31,9 @@ if (__DEV__) {
31 var {getCurrentStackAddendum} = require('ReactComponentTreeHook');
32 }
33
34 +var ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;
35 +var FAUX_ITERATOR_SYMBOL = '@@iterator'; // Before Symbol spec.
36 +
37 function getDeclarationErrorAddendum() {
38 if (ReactCurrentOwner.current) {
39 var name = getComponentName(ReactCurrentOwner.current);
@@ -150,9 +151,11 @@ function validateChildKeys(node, parentType) {
151 node._store.validated = true;
152 }
153 } else if (node) {
153 - var iteratorFn = getIteratorFn(node);
154 - // Entry iterators provide implicit keys.
155 - if (iteratorFn) {
154 + var iteratorFn =
155 + (ITERATOR_SYMBOL && node[ITERATOR_SYMBOL]) || node[FAUX_ITERATOR_SYMBOL];
156 + if (typeof iteratorFn === 'function') {
157 + // Entry iterators used to provide implicit keys,
158 + // but now we print a separate warning for them later.
159 if (iteratorFn !== node.entries) {
160 var iterator = iteratorFn.call(node);
161 var step;
@@ -282,22 +285,20 @@ var ReactElementValidator = {
285 validatedFactory.type = type;
286
287 if (__DEV__) {
285 - if (canDefineProperty) {
286 - Object.defineProperty(validatedFactory, 'type', {
287 - enumerable: false,
288 - get: function() {
289 - lowPriorityWarning(
290 - false,
291 - 'Factory.type is deprecated. Access the class directly ' +
292 - 'before passing it to createFactory.',
293 - );
294 - Object.defineProperty(this, 'type', {
295 - value: type,
296 - });
297 - return type;
298 - },
299 - });
300 - }
288 + Object.defineProperty(validatedFactory, 'type', {
289 + enumerable: false,
290 + get: function() {
291 + lowPriorityWarning(
292 + false,
293 + 'Factory.type is deprecated. Access the class directly ' +
294 + 'before passing it to createFactory.',
295 + );
296 + Object.defineProperty(this, 'type', {
297 + value: type,
298 + });
299 + return type;
300 + },
301 + });
302 }
303
304 return validatedFactory;
src/isomorphic/modern/class/ReactBaseClasses.js
+11 -14
@@ -13,7 +13,6 @@
13
14 var ReactNoopUpdateQueue = require('ReactNoopUpdateQueue');
15
16 -var canDefineProperty = require('canDefineProperty');
16 var emptyObject = require('fbjs/lib/emptyObject');
17 var invariant = require('fbjs/lib/invariant');
18 var lowPriorityWarning = require('lowPriorityWarning');
@@ -105,19 +104,17 @@ if (__DEV__) {
104 ],
105 };
106 var defineDeprecationWarning = function(methodName, info) {
108 - if (canDefineProperty) {
109 - Object.defineProperty(ReactComponent.prototype, methodName, {
110 - get: function() {
111 - lowPriorityWarning(
112 - false,
113 - '%s(...) is deprecated in plain JavaScript React classes. %s',
114 - info[0],
115 - info[1],
116 - );
117 - return undefined;
118 - },
119 - });
120 - }
107 + Object.defineProperty(ReactComponent.prototype, methodName, {
108 + get: function() {
109 + lowPriorityWarning(
110 + false,
111 + '%s(...) is deprecated in plain JavaScript React classes. %s',
112 + info[0],
113 + info[1],
114 + );
115 + return undefined;
116 + },
117 + });
118 };
119 for (var fnName in deprecatedAPIs) {
120 if (deprecatedAPIs.hasOwnProperty(fnName)) {
src/renderers/dom/shared/utils/ReactControlledValuePropTypes.js
+64 -55
@@ -12,65 +12,74 @@
12 'use strict';
13
14 var PropTypes = require('prop-types');
15 -var ReactPropTypesSecret = require('ReactPropTypesSecret');
16 -
15 +var emptyFunction = require('fbjs/lib/emptyFunction');
16 var warning = require('fbjs/lib/warning');
17
19 -var hasReadOnlyValue = {
20 - button: true,
21 - checkbox: true,
22 - image: true,
23 - hidden: true,
24 - radio: true,
25 - reset: true,
26 - submit: true,
18 +var ReactControlledValuePropTypes = {
19 + checkPropTypes: emptyFunction,
20 };
21
29 -var propTypes = {
30 - value: function(props, propName, componentName) {
31 - if (
32 - !props[propName] ||
33 - hasReadOnlyValue[props.type] ||
34 - props.onChange ||
35 - props.readOnly ||
36 - props.disabled
37 - ) {
38 - return null;
39 - }
40 - return new Error(
41 - 'You provided a `value` prop to a form field without an ' +
42 - '`onChange` handler. This will render a read-only field. If ' +
43 - 'the field should be mutable use `defaultValue`. Otherwise, ' +
44 - 'set either `onChange` or `readOnly`.',
45 - );
46 - },
47 - checked: function(props, propName, componentName) {
48 - if (
49 - !props[propName] ||
50 - props.onChange ||
51 - props.readOnly ||
52 - props.disabled
53 - ) {
54 - return null;
55 - }
56 - return new Error(
57 - 'You provided a `checked` prop to a form field without an ' +
58 - '`onChange` handler. This will render a read-only field. If ' +
59 - 'the field should be mutable use `defaultChecked`. Otherwise, ' +
60 - 'set either `onChange` or `readOnly`.',
61 - );
62 - },
63 - onChange: PropTypes.func,
64 -};
22 +if (__DEV__) {
23 + var ReactPropTypesSecret = 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED';
24
66 -var loggedTypeFailures = {};
25 + var hasReadOnlyValue = {
26 + button: true,
27 + checkbox: true,
28 + image: true,
29 + hidden: true,
30 + radio: true,
31 + reset: true,
32 + submit: true,
33 + };
34
68 -/**
69 - * Provide a linked `value` attribute for controlled forms. You should not use
70 - * this outside of the ReactDOM controlled form components.
71 - */
72 -var ReactControlledValuePropTypes = {
73 - checkPropTypes: function(tagName, props, getStack) {
35 + var propTypes = {
36 + value: function(props, propName, componentName) {
37 + if (
38 + !props[propName] ||
39 + hasReadOnlyValue[props.type] ||
40 + props.onChange ||
41 + props.readOnly ||
42 + props.disabled
43 + ) {
44 + return null;
45 + }
46 + return new Error(
47 + 'You provided a `value` prop to a form field without an ' +
48 + '`onChange` handler. This will render a read-only field. If ' +
49 + 'the field should be mutable use `defaultValue`. Otherwise, ' +
50 + 'set either `onChange` or `readOnly`.',
51 + );
52 + },
53 + checked: function(props, propName, componentName) {
54 + if (
55 + !props[propName] ||
56 + props.onChange ||
57 + props.readOnly ||
58 + props.disabled
59 + ) {
60 + return null;
61 + }
62 + return new Error(
63 + 'You provided a `checked` prop to a form field without an ' +
64 + '`onChange` handler. This will render a read-only field. If ' +
65 + 'the field should be mutable use `defaultChecked`. Otherwise, ' +
66 + 'set either `onChange` or `readOnly`.',
67 + );
68 + },
69 + onChange: PropTypes.func,
70 + };
71 +
72 + var loggedTypeFailures = {};
73 +
74 + /**
75 + * Provide a linked `value` attribute for controlled forms. You should not use
76 + * this outside of the ReactDOM controlled form components.
77 + */
78 + ReactControlledValuePropTypes.checkPropTypes = function(
79 + tagName,
80 + props,
81 + getStack,
82 + ) {
83 for (var propName in propTypes) {
84 if (propTypes.hasOwnProperty(propName)) {
85 var error = propTypes[propName](
@@ -90,7 +99,7 @@ var ReactControlledValuePropTypes = {
99 warning(false, 'Failed form propType: %s%s', error.message, getStack());
100 }
101 }
93 - },
94 -};
102 + };
103 +}
104
105 module.exports = ReactControlledValuePropTypes;
src/renderers/shared/fiber/ReactChildFiber.js
+21 -2
@@ -18,7 +18,6 @@ import type {Fiber} from 'ReactFiber';
18 import type {ReactInstance} from 'ReactInstanceType';
19 import type {PriorityLevel} from 'ReactPriorityLevel';
20
21 -var REACT_ELEMENT_TYPE = require('ReactElementSymbol');
21 var {REACT_COROUTINE_TYPE, REACT_YIELD_TYPE} = require('ReactCoroutine');
22 var {REACT_PORTAL_TYPE} = require('ReactPortal');
23
@@ -27,7 +26,6 @@ var ReactTypeOfSideEffect = require('ReactTypeOfSideEffect');
26 var ReactTypeOfWork = require('ReactTypeOfWork');
27
28 var emptyObject = require('fbjs/lib/emptyObject');
30 -var getIteratorFn = require('getIteratorFn');
29 var invariant = require('fbjs/lib/invariant');
30 var ReactFeatureFlags = require('ReactFeatureFlags');
31
@@ -99,6 +97,27 @@ const {
97
98 const {NoEffect, Placement, Deletion} = ReactTypeOfSideEffect;
99
100 +const ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;
101 +const FAUX_ITERATOR_SYMBOL = '@@iterator'; // Before Symbol spec.
102 +// The Symbol used to tag the ReactElement type. If there is no native Symbol
103 +// nor polyfill, then a plain number is used for performance.
104 +const REACT_ELEMENT_TYPE =
105 + (typeof Symbol === 'function' && Symbol.for && Symbol.for('react.element')) ||
106 + 0xeac7;
107 +
108 +function getIteratorFn(maybeIterable: ?any): ?() => ?Iterator<*> {
109 + if (maybeIterable === null || typeof maybeIterable === 'undefined') {
110 + return null;
111 + }
112 + const iteratorFn =
113 + (ITERATOR_SYMBOL && maybeIterable[ITERATOR_SYMBOL]) ||
114 + maybeIterable[FAUX_ITERATOR_SYMBOL];
115 + if (typeof iteratorFn === 'function') {
116 + return iteratorFn;
117 + }
118 + return null;
119 +}
120 +
121 function coerceRef(current: Fiber | null, element: ReactElement) {
122 let mixedRef = element.ref;
123 if (mixedRef !== null && typeof mixedRef !== 'function') {
src/renderers/shared/stack/reconciler/KeyEscapeUtils.js renamed
+24 -19
@@ -12,6 +12,8 @@
12
13 'use strict';
14
15 +var emptyFunction = require('fbjs/lib/emptyFunction');
16 +
17 /**
18 * Escape and wrap key so it is safe to use as a reactid
19 *
@@ -31,30 +33,33 @@ function escape(key: string): string {
33 return '$' + escapedString;
34 }
35
34 -/**
35 - * Unescape and unwrap key for human-readable display
36 - *
37 - * @param {string} key to unescape.
38 - * @return {string} the unescaped key.
39 - */
40 -function unescape(key: string): string {
41 - var unescapeRegex = /(=0|=2)/g;
42 - var unescaperLookup = {
43 - '=0': '=',
44 - '=2': ':',
45 - };
46 - var keySubstring = key[0] === '.' && key[1] === '$'
47 - ? key.substring(2)
48 - : key.substring(1);
36 +var unescapeInDev = emptyFunction;
37 +if (__DEV__) {
38 + /**
39 + * Unescape and unwrap key for human-readable display
40 + *
41 + * @param {string} key to unescape.
42 + * @return {string} the unescaped key.
43 + */
44 + unescapeInDev = function(key: string): string {
45 + var unescapeRegex = /(=0|=2)/g;
46 + var unescaperLookup = {
47 + '=0': '=',
48 + '=2': ':',
49 + };
50 + var keySubstring = key[0] === '.' && key[1] === '$'
51 + ? key.substring(2)
52 + : key.substring(1);
53
50 - return ('' + keySubstring).replace(unescapeRegex, function(match) {
51 - return unescaperLookup[match];
52 - });
54 + return ('' + keySubstring).replace(unescapeRegex, function(match) {
55 + return unescaperLookup[match];
56 + });
57 + };
58 }
59
60 var KeyEscapeUtils = {
61 escape: escape,
57 - unescape: unescape,
62 + unescapeInDev: unescapeInDev,
63 };
64
65 module.exports = KeyEscapeUtils;
src/renderers/shared/stack/reconciler/ReactChildReconciler.js
+1 -1
@@ -49,7 +49,7 @@ function instantiateChild(childInstances, child, name, selfDebugID) {
49 'flattenChildren(...): Encountered two children with the same key, ' +
50 '`%s`. Child keys must be unique; when two children share a key, only ' +
51 'the first child will be used.%s',
52 - KeyEscapeUtils.unescape(name),
52 + KeyEscapeUtils.unescapeInDev(name),
53 ReactComponentTreeHook.getStackAddendumByID(selfDebugID),
54 );
55 }
src/renderers/shared/stack/reconciler/flattenStackChildren.js
+1 -1
@@ -59,7 +59,7 @@ function flattenSingleChildIntoContext(
59 'flattenChildren(...): Encountered two children with the same key, ' +
60 '`%s`. Child keys must be unique; when two children share a key, only ' +
61 'the first child will be used.%s',
62 - KeyEscapeUtils.unescape(name),
62 + KeyEscapeUtils.unescapeInDev(name),
63 ReactComponentTreeHook.getStackAddendumByID(selfDebugID),
64 );
65 }
src/renderers/shared/stack/reconciler/instantiateReactComponent.js
+3 -2
@@ -15,10 +15,11 @@ var ReactCompositeComponent = require('ReactCompositeComponent');
15 var ReactEmptyComponent = require('ReactEmptyComponent');
16 var ReactHostComponent = require('ReactHostComponent');
17
18 -var getNextDebugID = require('getNextDebugID');
18 var invariant = require('fbjs/lib/invariant');
19 var warning = require('fbjs/lib/warning');
20
21 +var nextDebugID = 1;
22 +
23 // To avoid a cyclic dependency, we create the final class in this module
24 var ReactCompositeComponentWrapper = function(element) {
25 this.construct(element);
@@ -129,7 +130,7 @@ function instantiateReactComponent(node, shouldHaveDebugID) {
130 instance._mountImage = null;
131
132 if (__DEV__) {
132 - instance._debugID = shouldHaveDebugID ? getNextDebugID() : 0;
133 + instance._debugID = shouldHaveDebugID ? nextDebugID++ : 0;
134 }
135
136 // Internal instances should fully constructed at this point, so they should
src/renderers/shared/stack/reconciler/traverseStackChildren.js
+12 -5
@@ -11,13 +11,18 @@
11
12 'use strict';
13
14 -var REACT_ELEMENT_TYPE = require('ReactElementSymbol');
15 -
16 -var getIteratorFn = require('getIteratorFn');
14 var invariant = require('fbjs/lib/invariant');
15 var KeyEscapeUtils = require('KeyEscapeUtils');
16 var warning = require('fbjs/lib/warning');
17
18 +var ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;
19 +var FAUX_ITERATOR_SYMBOL = '@@iterator'; // Before Symbol spec.
20 +// The Symbol used to tag the ReactElement type. If there is no native Symbol
21 +// nor polyfill, then a plain number is used for performance.
22 +var REACT_ELEMENT_TYPE =
23 + (typeof Symbol === 'function' && Symbol.for && Symbol.for('react.element')) ||
24 + 0xeac7;
25 +
26 if (__DEV__) {
27 var {
28 getCurrentStackAddendum,
@@ -114,8 +119,10 @@ function traverseStackChildrenImpl(
119 );
120 }
121 } else {
117 - var iteratorFn = getIteratorFn(children);
118 - if (iteratorFn) {
122 + var iteratorFn =
123 + (ITERATOR_SYMBOL && children[ITERATOR_SYMBOL]) ||
124 + children[FAUX_ITERATOR_SYMBOL];
125 + if (typeof iteratorFn === 'function') {
126 if (__DEV__) {
127 // Warn about using Maps as children
128 if (iteratorFn === children.entries) {
src/shared/types/ReactPropTypesSecret.js deleted
-17
@@ -1,17 +0,0 @@
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 - * @flow
10 - * @providesModule ReactPropTypesSecret
11 - */
12 -
13 -'use strict';
14 -
15 -const ReactPropTypesSecret = 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED';
16 -
17 -module.exports = ReactPropTypesSecret;
src/shared/utils/ReactElementSymbol.js deleted
-21
@@ -1,21 +0,0 @@
1 -/**
2 - * Copyright 2014-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 - * @providesModule ReactElementSymbol
10 - * @flow
11 - */
12 -
13 -'use strict';
14 -
15 -// The Symbol used to tag the ReactElement type. If there is no native Symbol
16 -// nor polyfill, then a plain number is used for performance.
17 -var REACT_ELEMENT_TYPE =
18 - (typeof Symbol === 'function' && Symbol.for && Symbol.for('react.element')) ||
19 - 0xeac7;
20 -
21 -module.exports = REACT_ELEMENT_TYPE;
src/shared/utils/__tests__/KeyEscapeUtils-test.js deleted
-38
@@ -1,38 +0,0 @@
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 - * @emails react-core
10 - */
11 -
12 -'use strict';
13 -
14 -var KeyEscapeUtils;
15 -
16 -describe('KeyEscapeUtils', () => {
17 - beforeEach(() => {
18 - jest.resetModules();
19 -
20 - KeyEscapeUtils = require('KeyEscapeUtils');
21 - });
22 -
23 - describe('escape', () => {
24 - it('should properly escape and wrap user defined keys', () => {
25 - expect(KeyEscapeUtils.escape('1')).toBe('$1');
26 - expect(KeyEscapeUtils.escape('1=::=2')).toBe('$1=0=2=2=02');
27 - });
28 - });
29 -
30 - describe('unescape', () => {
31 - it('should properly unescape and unwrap user defined keys', () => {
32 - expect(KeyEscapeUtils.unescape('.1')).toBe('1');
33 - expect(KeyEscapeUtils.unescape('$1')).toBe('1');
34 - expect(KeyEscapeUtils.unescape('.$1')).toBe('1');
35 - expect(KeyEscapeUtils.unescape('$1=0=2=2=02')).toBe('1=::=2');
36 - });
37 - });
38 -});
src/shared/utils/canDefineProperty.js deleted
-26
@@ -1,26 +0,0 @@
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 - * @flow
10 - * @providesModule canDefineProperty
11 - */
12 -
13 -'use strict';
14 -
15 -var canDefineProperty = false;
16 -if (__DEV__) {
17 - try {
18 - // $FlowFixMe https://github.com/facebook/flow/issues/285
19 - Object.defineProperty({}, 'x', {get: function() {}});
20 - canDefineProperty = true;
21 - } catch (x) {
22 - // IE will fail on defineProperty
23 - }
24 -}
25 -
26 -module.exports = canDefineProperty;
src/shared/utils/deprecated.js deleted
-69
@@ -1,69 +0,0 @@
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 - * @providesModule deprecated
10 - * @flow
11 - */
12 -
13 -'use strict';
14 -
15 -var lowPriorityWarning = require('lowPriorityWarning');
16 -
17 -/**
18 - * This will log a single deprecation notice per function and forward the call
19 - * on to the new API.
20 - *
21 - * @param {string} fnName The name of the function
22 - * @param {string} newModule The module that fn will exist in
23 - * @param {string} newPackage The module that fn will exist in
24 - * @param {*} ctx The context this forwarded call should run in
25 - * @param {function} fn The function to forward on to
26 - * @return {function} The function that will warn once and then call fn
27 - */
28 -function deprecated<T: Function>(
29 - fnName: string,
30 - newModule: string,
31 - newPackage: string,
32 - ctx: mixed,
33 - fn: T,
34 -): T {
35 - var warned = false;
36 - if (__DEV__) {
37 - var newFn = function() {
38 - lowPriorityWarning(
39 - warned,
40 - /* eslint-disable no-useless-concat */
41 - // Require examples in this string must be split to prevent React's
42 - // build tools from mistaking them for real requires.
43 - // Otherwise the build tools will attempt to build a '%s' module.
44 - 'React.%s is deprecated. Please use %s.%s from require' +
45 - "('%s') " +
46 - 'instead.',
47 - fnName,
48 - newModule,
49 - fnName,
50 - newPackage,
51 - );
52 - /* eslint-enable no-useless-concat */
53 - warned = true;
54 - return fn.apply(ctx, arguments);
55 - };
56 - // We need to make sure all properties of the original fn are copied over.
57 - // In particular, this is needed to support PropTypes
58 - Object.assign(newFn, (fn: Object));
59 -
60 - // Flow is not smart enough to figure out that newFn is of the same type as
61 - // fn. Since we don't want to lose out the type of the function, casting
62 - // to any and force flow to use T.
63 - return ((newFn: any): T);
64 - }
65 -
66 - return fn;
67 -}
68 -
69 -module.exports = deprecated;
src/shared/utils/getIteratorFn.js deleted
-43
@@ -1,43 +0,0 @@
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 - * @providesModule getIteratorFn
10 - * @flow
11 - */
12 -
13 -'use strict';
14 -
15 -/* global Symbol */
16 -var ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;
17 -var FAUX_ITERATOR_SYMBOL = '@@iterator'; // Before Symbol spec.
18 -
19 -/**
20 - * Returns the iterator method function contained on the iterable object.
21 - *
22 - * Be sure to invoke the function with the iterable as context:
23 - *
24 - * var iteratorFn = getIteratorFn(myIterable);
25 - * if (iteratorFn) {
26 - * var iterator = iteratorFn.call(myIterable);
27 - * ...
28 - * }
29 - *
30 - * @param {?object} maybeIterable
31 - * @return {?function}
32 - */
33 -function getIteratorFn(maybeIterable: ?any): ?() => ?Iterator<*> {
34 - var iteratorFn =
35 - maybeIterable &&
36 - ((ITERATOR_SYMBOL && maybeIterable[ITERATOR_SYMBOL]) ||
37 - maybeIterable[FAUX_ITERATOR_SYMBOL]);
38 - if (typeof iteratorFn === 'function') {
39 - return iteratorFn;
40 - }
41 -}
42 -
43 -module.exports = getIteratorFn;
src/shared/utils/getNextDebugID.js deleted
-21
@@ -1,21 +0,0 @@
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 - * @providesModule getNextDebugID
10 - * @flow
11 - */
12 -
13 -'use strict';
14 -
15 -var nextDebugID = 1;
16 -
17 -function getNextDebugID(): number {
18 - return nextDebugID++;
19 -}
20 -
21 -module.exports = getNextDebugID;