Remove Stack-only DEV code (#10797)
Dan Abramov committed
Oct 2, 2017 at 11:42 UTC
745c4ab0af92d9510a6373a0985acf04bf865384
16 files changed
+51
-5297
src/isomorphic/ReactEntry.js
-1
@@ -58,7 +58,6 @@ var React = {
58
if (__DEV__) {
59
Object.assign(React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED, {
60
// These should not be included in production.
61
- ReactComponentTreeHook: require('ReactComponentTreeHook'),
61
ReactDebugCurrentFrame: require('ReactDebugCurrentFrame'),
62
});
63
}
src/isomorphic/hooks/ReactComponentTreeHook.js
deleted
-396
@@ -1,396 +0,0 @@
1
-/**
2
- * Copyright (c) 2016-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
- * @flow
8
- * @providesModule ReactComponentTreeHook
9
- */
10
-
11
-'use strict';
12
-
13
-var ReactCurrentOwner = require('ReactCurrentOwner');
14
-var invariant = require('fbjs/lib/invariant');
15
-var describeComponentFrame = require('describeComponentFrame');
16
-
17
-if (__DEV__) {
18
- var warning = require('fbjs/lib/warning');
19
-}
20
-
21
-import type {ReactElement, Source} from 'ReactElementType';
22
-import type {DebugID} from 'ReactInstanceType';
23
-
24
-function isNative(fn) {
25
- // Based on isNative() from Lodash
26
- var funcToString = Function.prototype.toString;
27
- var reIsNative = RegExp(
28
- '^' +
29
- funcToString
30
- // Take an example native function source for comparison
31
- .call(Object.prototype.hasOwnProperty)
32
- // Strip regex characters so we can use it for regex
33
- .replace(/[\\^$.*+?()[\]{}|]/g, '\\$&')
34
- // Remove hasOwnProperty from the template to make it generic
35
- .replace(
36
- /hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,
37
- '$1.*?',
38
- ) +
39
- '$',
40
- );
41
- try {
42
- var source = funcToString.call(fn);
43
- return reIsNative.test(source);
44
- } catch (err) {
45
- return false;
46
- }
47
-}
48
-
49
-var canUseCollections =
50
- // Array.from
51
- typeof Array.from === 'function' &&
52
- // Map
53
- typeof Map === 'function' &&
54
- isNative(Map) &&
55
- // Map.prototype.keys
56
- Map.prototype != null &&
57
- typeof Map.prototype.keys === 'function' &&
58
- isNative(Map.prototype.keys) &&
59
- // Set
60
- typeof Set === 'function' &&
61
- isNative(Set) &&
62
- // Set.prototype.keys
63
- Set.prototype != null &&
64
- typeof Set.prototype.keys === 'function' &&
65
- isNative(Set.prototype.keys);
66
-
67
-var setItem;
68
-var getItem;
69
-var removeItem;
70
-var getItemIDs;
71
-var addRoot;
72
-var removeRoot;
73
-var getRootIDs;
74
-
75
-if (canUseCollections) {
76
- var itemMap = new Map();
77
- var rootIDSet = new Set();
78
-
79
- setItem = function(id, item) {
80
- itemMap.set(id, item);
81
- };
82
- getItem = function(id) {
83
- return itemMap.get(id);
84
- };
85
- removeItem = function(id) {
86
- itemMap.delete(id);
87
- };
88
- getItemIDs = function() {
89
- return Array.from(itemMap.keys());
90
- };
91
-
92
- addRoot = function(id) {
93
- rootIDSet.add(id);
94
- };
95
- removeRoot = function(id) {
96
- rootIDSet.delete(id);
97
- };
98
- getRootIDs = function() {
99
- return Array.from(rootIDSet.keys());
100
- };
101
-} else {
102
- var itemByKey = {};
103
- var rootByKey = {};
104
-
105
- // Use non-numeric keys to prevent V8 performance issues:
106
- // https://github.com/facebook/react/pull/7232
107
- var getKeyFromID = function(id: DebugID): string {
108
- return '.' + id;
109
- };
110
- var getIDFromKey = function(key: string): DebugID {
111
- return parseInt(key.substr(1), 10);
112
- };
113
-
114
- setItem = function(id, item) {
115
- var key = getKeyFromID(id);
116
- itemByKey[key] = item;
117
- };
118
- getItem = function(id) {
119
- var key = getKeyFromID(id);
120
- return itemByKey[key];
121
- };
122
- removeItem = function(id) {
123
- var key = getKeyFromID(id);
124
- delete itemByKey[key];
125
- };
126
- getItemIDs = function() {
127
- return Object.keys(itemByKey).map(getIDFromKey);
128
- };
129
-
130
- addRoot = function(id) {
131
- var key = getKeyFromID(id);
132
- rootByKey[key] = true;
133
- };
134
- removeRoot = function(id) {
135
- var key = getKeyFromID(id);
136
- delete rootByKey[key];
137
- };
138
- getRootIDs = function() {
139
- return Object.keys(rootByKey).map(getIDFromKey);
140
- };
141
-}
142
-
143
-var unmountedIDs: Array<DebugID> = [];
144
-
145
-function purgeDeep(id) {
146
- var item = getItem(id);
147
- if (item) {
148
- var {childIDs} = item;
149
- removeItem(id);
150
- childIDs.forEach(purgeDeep);
151
- }
152
-}
153
-
154
-function getDisplayName(element: ?ReactElement): string {
155
- if (element == null) {
156
- return '#empty';
157
- } else if (typeof element === 'string' || typeof element === 'number') {
158
- return '#text';
159
- } else if (typeof element.type === 'string') {
160
- return element.type;
161
- } else {
162
- return element.type.displayName || element.type.name || 'Unknown';
163
- }
164
-}
165
-
166
-function describeID(id: DebugID): string {
167
- const name = ReactComponentTreeHook.getDisplayName(id);
168
- const element = ReactComponentTreeHook.getElement(id);
169
- const ownerID = ReactComponentTreeHook.getOwnerID(id);
170
- let ownerName;
171
-
172
- if (ownerID) {
173
- ownerName = ReactComponentTreeHook.getDisplayName(ownerID);
174
- }
175
- warning(
176
- element,
177
- 'ReactComponentTreeHook: Missing React element for debugID %s when ' +
178
- 'building stack',
179
- id,
180
- );
181
- return describeComponentFrame(
182
- name || '',
183
- element && element._source,
184
- ownerName || '',
185
- );
186
-}
187
-
188
-var ReactComponentTreeHook = {
189
- onSetChildren(id: DebugID, nextChildIDs: Array<DebugID>): void {
190
- var item = getItem(id);
191
- invariant(item, 'Item must have been set');
192
- item.childIDs = nextChildIDs;
193
-
194
- for (var i = 0; i < nextChildIDs.length; i++) {
195
- var nextChildID = nextChildIDs[i];
196
- var nextChild = getItem(nextChildID);
197
- invariant(
198
- nextChild,
199
- 'Expected hook events to fire for the child ' +
200
- 'before its parent includes it in onSetChildren().',
201
- );
202
- invariant(
203
- nextChild.childIDs != null ||
204
- typeof nextChild.element !== 'object' ||
205
- nextChild.element == null,
206
- 'Expected onSetChildren() to fire for a container child ' +
207
- 'before its parent includes it in onSetChildren().',
208
- );
209
- invariant(
210
- nextChild.isMounted,
211
- 'Expected onMountComponent() to fire for the child ' +
212
- 'before its parent includes it in onSetChildren().',
213
- );
214
- if (nextChild.parentID == null) {
215
- nextChild.parentID = id;
216
- // TODO: This shouldn't be necessary but mounting a new root during in
217
- // componentWillMount currently causes not-yet-mounted components to
218
- // be purged from our tree data so their parent id is missing.
219
- }
220
- invariant(
221
- nextChild.parentID === id,
222
- 'Expected onBeforeMountComponent() parent and onSetChildren() to ' +
223
- 'be consistent (%s has parents %s and %s).',
224
- nextChildID,
225
- nextChild.parentID,
226
- id,
227
- );
228
- }
229
- },
230
-
231
- onBeforeMountComponent(
232
- id: DebugID,
233
- element: ReactElement,
234
- parentID: DebugID,
235
- ): void {
236
- var item = {
237
- element,
238
- parentID,
239
- text: null,
240
- childIDs: [],
241
- isMounted: false,
242
- updateCount: 0,
243
- };
244
- setItem(id, item);
245
- },
246
-
247
- onBeforeUpdateComponent(id: DebugID, element: ReactElement): void {
248
- var item = getItem(id);
249
- if (!item || !item.isMounted) {
250
- // We may end up here as a result of setState() in componentWillUnmount().
251
- // In this case, ignore the element.
252
- return;
253
- }
254
- item.element = element;
255
- },
256
-
257
- onMountComponent(id: DebugID): void {
258
- var item = getItem(id);
259
- invariant(item, 'Item must have been set');
260
- item.isMounted = true;
261
- var isRoot = item.parentID === 0;
262
- if (isRoot) {
263
- addRoot(id);
264
- }
265
- },
266
-
267
- onUpdateComponent(id: DebugID): void {
268
- var item = getItem(id);
269
- if (!item || !item.isMounted) {
270
- // We may end up here as a result of setState() in componentWillUnmount().
271
- // In this case, ignore the element.
272
- return;
273
- }
274
- item.updateCount++;
275
- },
276
-
277
- onUnmountComponent(id: DebugID): void {
278
- var item = getItem(id);
279
- if (item) {
280
- // We need to check if it exists.
281
- // `item` might not exist if it is inside an error boundary, and a sibling
282
- // error boundary child threw while mounting. Then this instance never
283
- // got a chance to mount, but it still gets an unmounting event during
284
- // the error boundary cleanup.
285
- item.isMounted = false;
286
- var isRoot = item.parentID === 0;
287
- if (isRoot) {
288
- removeRoot(id);
289
- }
290
- }
291
- unmountedIDs.push(id);
292
- },
293
-
294
- purgeUnmountedComponents(): void {
295
- if (ReactComponentTreeHook._preventPurging) {
296
- // Should only be used for testing.
297
- return;
298
- }
299
-
300
- for (var i = 0; i < unmountedIDs.length; i++) {
301
- var id = unmountedIDs[i];
302
- purgeDeep(id);
303
- }
304
- unmountedIDs.length = 0;
305
- },
306
-
307
- isMounted(id: DebugID): boolean {
308
- var item = getItem(id);
309
- return item ? item.isMounted : false;
310
- },
311
-
312
- getCurrentStackAddendum(): string {
313
- var info = '';
314
- var currentOwner = ReactCurrentOwner.current;
315
- if (currentOwner) {
316
- invariant(
317
- typeof currentOwner.tag !== 'number',
318
- 'Fiber owners should not show up in Stack stack traces.',
319
- );
320
- if (typeof currentOwner._debugID === 'number') {
321
- info += ReactComponentTreeHook.getStackAddendumByID(
322
- currentOwner._debugID,
323
- );
324
- }
325
- }
326
- return info;
327
- },
328
-
329
- getStackAddendumByID(id: ?DebugID): string {
330
- var info = '';
331
- while (id) {
332
- info += describeID(id);
333
- id = ReactComponentTreeHook.getParentID(id);
334
- }
335
- return info;
336
- },
337
-
338
- getChildIDs(id: DebugID): Array<DebugID> {
339
- var item = getItem(id);
340
- return item ? item.childIDs : [];
341
- },
342
-
343
- getDisplayName(id: DebugID): ?string {
344
- var element = ReactComponentTreeHook.getElement(id);
345
- if (!element) {
346
- return null;
347
- }
348
- return getDisplayName(element);
349
- },
350
-
351
- getElement(id: DebugID): ?ReactElement {
352
- var item = getItem(id);
353
- return item ? item.element : null;
354
- },
355
-
356
- getOwnerID(id: DebugID): ?DebugID {
357
- var element = ReactComponentTreeHook.getElement(id);
358
- if (!element || !element._owner) {
359
- return null;
360
- }
361
- return element._owner._debugID;
362
- },
363
-
364
- getParentID(id: DebugID): ?DebugID {
365
- var item = getItem(id);
366
- return item ? item.parentID : null;
367
- },
368
-
369
- getSource(id: DebugID): ?Source {
370
- var item = getItem(id);
371
- var element = item ? item.element : null;
372
- var source = element != null ? element._source : null;
373
- return source;
374
- },
375
-
376
- getText(id: DebugID): ?string {
377
- var element = ReactComponentTreeHook.getElement(id);
378
- if (typeof element === 'string') {
379
- return element;
380
- } else if (typeof element === 'number') {
381
- return '' + element;
382
- } else {
383
- return null;
384
- }
385
- },
386
-
387
- getUpdateCount(id: DebugID): number {
388
- var item = getItem(id);
389
- return item ? item.updateCount : 0;
390
- },
391
-
392
- getRootIDs,
393
- getRegisteredIDs: getItemIDs,
394
-};
395
-
396
-module.exports = ReactComponentTreeHook;
src/renderers/__tests__/ReactComponentTreeHook-test.js
deleted
-2146
@@ -1,2146 +0,0 @@
1
-/**
2
- * Copyright (c) 2016-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
- * @emails react-core
8
- */
9
-
10
-'use strict';
11
-
12
-describe.skip('ReactComponentTreeHook', () => {
13
- var React;
14
- var ReactDOM;
15
- var ReactInstanceMap;
16
- var ReactComponentTreeHook;
17
- var ReactDebugCurrentFiber;
18
- var ReactComponentTreeTestUtils;
19
-
20
- beforeEach(() => {
21
- jest.resetModules();
22
-
23
- React = require('react');
24
- ReactDOM = require('react-dom');
25
- ReactInstanceMap = require('ReactInstanceMap');
26
- ReactDebugCurrentFiber = require('ReactDebugCurrentFiber');
27
- ReactComponentTreeHook = require('ReactComponentTreeHook');
28
- ReactComponentTreeTestUtils = require('ReactComponentTreeTestUtils');
29
- });
30
-
31
- // This is the only part used both by Stack and Fiber.
32
- describe('stack addenda', () => {
33
- it('gets created', () => {
34
- function getAddendum(element) {
35
- var addendum =
36
- ReactDebugCurrentFiber.getCurrentFiberStackAddendum() || '';
37
- return addendum.replace(/\(at .+?:\d+\)/g, '(at **)');
38
- }
39
-
40
- function Anon() {
41
- return null;
42
- }
43
- Object.defineProperty(Anon, 'name', {
44
- value: null,
45
- });
46
- // function Orange() {
47
- // return null;
48
- // }
49
-
50
- expectDev(getAddendum()).toBe('');
51
- // expectDev(getAddendum(<div />)).toBe('\n in div (at **)');
52
- // expectDev(getAddendum(<Anon />)).toBe('\n in Unknown (at **)');
53
- // expectDev(getAddendum(<Orange />)).toBe('\n in Orange (at **)');
54
- // expectDev(getAddendum(React.createElement(Orange))).toBe(
55
- // '\n in Orange',
56
- // );
57
-
58
- var renders = 0;
59
- //var rOwnedByQ;
60
-
61
- function Q() {
62
- return /*rOwnedByQ =*/ React.createElement(R);
63
- }
64
- function R() {
65
- return <div><S /></div>;
66
- }
67
- class S extends React.Component {
68
- componentDidMount() {
69
- // Check that the parent path is still fetched when only S itself is on
70
- // the stack.
71
- this.forceUpdate();
72
- }
73
- render() {
74
- expectDev(getAddendum()).toBe(
75
- '\n in S (at **)' +
76
- '\n in div (at **)' +
77
- '\n in R (created by Q)' +
78
- '\n in Q (at **)',
79
- );
80
- expectDev(getAddendum(<span />)).toBe(
81
- // '\n in span (at **)' +
82
- '\n in S (at **)' +
83
- '\n in div (at **)' +
84
- '\n in R (created by Q)' +
85
- '\n in Q (at **)',
86
- );
87
- expectDev(getAddendum(React.createElement('span'))).toBe(
88
- // '\n in span (created by S)' +
89
- '\n in S (at **)' +
90
- '\n in div (at **)' +
91
- '\n in R (created by Q)' +
92
- '\n in Q (at **)',
93
- );
94
- renders++;
95
- return null;
96
- }
97
- }
98
- ReactDOM.render(<Q />, document.createElement('div'));
99
- expectDev(renders).toBe(2);
100
-
101
- // Make sure owner is fetched for the top element too.
102
- // expectDev(getAddendum(rOwnedByQ)).toBe('\n in R (created by Q)');
103
- });
104
- });
105
-
106
- // The rest of this file is not relevant for Fiber.
107
- // TODO: remove tests below when we delete Stack.
108
-
109
- function assertTreeMatches(pairs) {
110
- if (!Array.isArray(pairs[0])) {
111
- pairs = [pairs];
112
- }
113
-
114
- var node = document.createElement('div');
115
- var currentElement;
116
- var rootInstance;
117
-
118
- class Wrapper extends React.Component {
119
- render() {
120
- rootInstance = ReactInstanceMap.get(this);
121
- return currentElement;
122
- }
123
- }
124
-
125
- function expectWrapperTreeToEqual(expectedTree, andStayMounted) {
126
- ReactComponentTreeTestUtils.expectTree(rootInstance._debugID, {
127
- displayName: 'Wrapper',
128
- children: expectedTree ? [expectedTree] : [],
129
- });
130
- var rootDisplayNames = ReactComponentTreeTestUtils.getRootDisplayNames();
131
- var registeredDisplayNames = ReactComponentTreeTestUtils.getRegisteredDisplayNames();
132
- if (!expectedTree) {
133
- expectDev(rootDisplayNames).toEqual([]);
134
- expectDev(registeredDisplayNames).toEqual([]);
135
- } else if (andStayMounted) {
136
- expectDev(rootDisplayNames).toContain('Wrapper');
137
- expectDev(registeredDisplayNames).toContain('Wrapper');
138
- }
139
- }
140
-
141
- // Mount once, render updates, then unmount.
142
- // Ensure the tree is correct on every step.
143
- pairs.forEach(([element, expectedTree]) => {
144
- currentElement = element;
145
-
146
- // Mount a new tree or update the existing tree.
147
- ReactDOM.render(<Wrapper />, node);
148
- expectWrapperTreeToEqual(expectedTree, true);
149
-
150
- // Purging should have no effect
151
- // on the tree we expect to see.
152
- ReactComponentTreeHook.purgeUnmountedComponents();
153
- expectWrapperTreeToEqual(expectedTree, true);
154
- });
155
-
156
- // Unmounting the root node should purge
157
- // the whole subtree automatically.
158
- ReactDOM.unmountComponentAtNode(node);
159
- expectWrapperTreeToEqual(null);
160
- }
161
-
162
- describe('mount', () => {
163
- it('uses displayName or Unknown for classic components', () => {
164
- class Foo extends React.Component {
165
- render() {
166
- return null;
167
- }
168
- }
169
-
170
- Foo.displayName = 'Bar';
171
-
172
- class Baz extends React.Component {
173
- render() {
174
- return null;
175
- }
176
- }
177
-
178
- class Qux extends React.Component {
179
- render() {
180
- return null;
181
- }
182
- }
183
-
184
- delete Qux.displayName;
185
-
186
- var element = <div><Foo /><Baz /><Qux /></div>;
187
- var tree = {
188
- displayName: 'div',
189
- children: [
190
- {
191
- displayName: 'Bar',
192
- children: [],
193
- },
194
- {
195
- displayName: 'Baz',
196
- children: [],
197
- },
198
- {
199
- displayName: 'Unknown',
200
- children: [],
201
- },
202
- ],
203
- };
204
- assertTreeMatches([element, tree]);
205
- });
206
-
207
- it('uses displayName, name, or ReactComponent for modern components', () => {
208
- class Foo extends React.Component {
209
- render() {
210
- return null;
211
- }
212
- }
213
- Foo.displayName = 'Bar';
214
- class Baz extends React.Component {
215
- render() {
216
- return null;
217
- }
218
- }
219
- class Qux extends React.Component {
220
- render() {
221
- return null;
222
- }
223
- }
224
- delete Qux.name;
225
-
226
- var element = <div><Foo /><Baz /><Qux /></div>;
227
- var tree = {
228
- displayName: 'div',
229
- element,
230
- children: [
231
- {
232
- displayName: 'Bar',
233
- children: [],
234
- },
235
- {
236
- displayName: 'Baz',
237
- children: [],
238
- },
239
- {
240
- // Note: Ideally fallback name should be consistent (e.g. "Unknown")
241
- displayName: 'ReactComponent',
242
- children: [],
243
- },
244
- ],
245
- };
246
- assertTreeMatches([element, tree]);
247
- });
248
-
249
- it('uses displayName, name, or Object for factory components', () => {
250
- function Foo() {
251
- return {
252
- render() {
253
- return null;
254
- },
255
- };
256
- }
257
- Foo.displayName = 'Bar';
258
- function Baz() {
259
- return {
260
- render() {
261
- return null;
262
- },
263
- };
264
- }
265
- function Qux() {
266
- return {
267
- render() {
268
- return null;
269
- },
270
- };
271
- }
272
- delete Qux.name;
273
-
274
- var element = <div><Foo /><Baz /><Qux /></div>;
275
- var tree = {
276
- displayName: 'div',
277
- element,
278
- children: [
279
- {
280
- displayName: 'Bar',
281
- children: [],
282
- },
283
- {
284
- displayName: 'Baz',
285
- children: [],
286
- },
287
- {
288
- displayName: 'Unknown',
289
- children: [],
290
- },
291
- ],
292
- };
293
- assertTreeMatches([element, tree]);
294
- });
295
-
296
- it('uses displayName, name, or StatelessComponent for functional components', () => {
297
- function Foo() {
298
- return null;
299
- }
300
- Foo.displayName = 'Bar';
301
- function Baz() {
302
- return null;
303
- }
304
- function Qux() {
305
- return null;
306
- }
307
- delete Qux.name;
308
-
309
- var element = <div><Foo /><Baz /><Qux /></div>;
310
- var tree = {
311
- displayName: 'div',
312
- element,
313
- children: [
314
- {
315
- displayName: 'Bar',
316
- children: [],
317
- },
318
- {
319
- displayName: 'Baz',
320
- children: [],
321
- },
322
- {
323
- displayName: 'Unknown',
324
- children: [],
325
- },
326
- ],
327
- };
328
- assertTreeMatches([element, tree]);
329
- });
330
-
331
- it('reports a host tree correctly', () => {
332
- var element = (
333
- <div>
334
- <p>
335
- <span>
336
- Hi!
337
- </span>
338
- Wow.
339
- </p>
340
- <hr />
341
- </div>
342
- );
343
- var tree = {
344
- displayName: 'div',
345
- children: [
346
- {
347
- displayName: 'p',
348
- children: [
349
- {
350
- displayName: 'span',
351
- children: [
352
- {
353
- displayName: '#text',
354
- text: 'Hi!',
355
- },
356
- ],
357
- },
358
- {
359
- displayName: '#text',
360
- text: 'Wow.',
361
- },
362
- ],
363
- },
364
- {
365
- displayName: 'hr',
366
- element: <hr />,
367
- children: [],
368
- },
369
- ],
370
- };
371
- assertTreeMatches([element, tree]);
372
- });
373
-
374
- it('reports a simple tree with composites correctly', () => {
375
- class Foo extends React.Component {
376
- render() {
377
- return <div />;
378
- }
379
- }
380
-
381
- var element = <Foo />;
382
- var tree = {
383
- displayName: 'Foo',
384
- element,
385
- children: [
386
- {
387
- displayName: 'div',
388
- element: <div />,
389
- children: [],
390
- },
391
- ],
392
- };
393
- assertTreeMatches([element, tree]);
394
- });
395
-
396
- it('reports a tree with composites correctly', () => {
397
- class Qux extends React.Component {
398
- render() {
399
- return null;
400
- }
401
- }
402
-
403
- function Foo() {
404
- return {
405
- render() {
406
- return <Qux />;
407
- },
408
- };
409
- }
410
- function Bar({children}) {
411
- return <h1>{children}</h1>;
412
- }
413
- class Baz extends React.Component {
414
- render() {
415
- return (
416
- <div>
417
- <Foo />
418
- <Bar>
419
- <span>Hi,</span>
420
- Mom
421
- </Bar>
422
- <a href="#">Click me.</a>
423
- </div>
424
- );
425
- }
426
- }
427
-
428
- var element = <Baz />;
429
- var tree = {
430
- displayName: 'Baz',
431
- element,
432
- children: [
433
- {
434
- displayName: 'div',
435
- children: [
436
- {
437
- displayName: 'Foo',
438
- element: <Foo />,
439
- children: [
440
- {
441
- displayName: 'Qux',
442
- element: <Qux />,
443
- children: [],
444
- },
445
- ],
446
- },
447
- {
448
- displayName: 'Bar',
449
- children: [
450
- {
451
- displayName: 'h1',
452
- children: [
453
- {
454
- displayName: 'span',
455
- children: [
456
- {
457
- displayName: '#text',
458
- element: 'Hi,',
459
- text: 'Hi,',
460
- },
461
- ],
462
- },
463
- {
464
- displayName: '#text',
465
- text: 'Mom',
466
- element: 'Mom',
467
- },
468
- ],
469
- },
470
- ],
471
- },
472
- {
473
- displayName: 'a',
474
- children: [
475
- {
476
- displayName: '#text',
477
- text: 'Click me.',
478
- element: 'Click me.',
479
- },
480
- ],
481
- },
482
- ],
483
- },
484
- ],
485
- };
486
- assertTreeMatches([element, tree]);
487
- });
488
-
489
- it('ignores null children', () => {
490
- class Foo extends React.Component {
491
- render() {
492
- return null;
493
- }
494
- }
495
- var element = <Foo />;
496
- var tree = {
497
- displayName: 'Foo',
498
- children: [],
499
- };
500
- assertTreeMatches([element, tree]);
501
- });
502
-
503
- it('ignores false children', () => {
504
- class Foo extends React.Component {
505
- render() {
506
- return false;
507
- }
508
- }
509
- var element = <Foo />;
510
- var tree = {
511
- displayName: 'Foo',
512
- children: [],
513
- };
514
- assertTreeMatches([element, tree]);
515
- });
516
-
517
- it('reports text nodes as children', () => {
518
- var element = <div>{'1'}{2}</div>;
519
- var tree = {
520
- displayName: 'div',
521
- element,
522
- children: [
523
- {
524
- displayName: '#text',
525
- text: '1',
526
- },
527
- {
528
- displayName: '#text',
529
- text: '2',
530
- },
531
- ],
532
- };
533
- assertTreeMatches([element, tree]);
534
- });
535
-
536
- it('reports a single text node as a child', () => {
537
- var element = <div>{'1'}</div>;
538
- var tree = {
539
- displayName: 'div',
540
- element,
541
- children: [
542
- {
543
- displayName: '#text',
544
- text: '1',
545
- },
546
- ],
547
- };
548
- assertTreeMatches([element, tree]);
549
- });
550
-
551
- it('reports a single number node as a child', () => {
552
- var element = <div>{42}</div>;
553
- var tree = {
554
- displayName: 'div',
555
- element,
556
- children: [
557
- {
558
- displayName: '#text',
559
- text: '42',
560
- },
561
- ],
562
- };
563
- assertTreeMatches([element, tree]);
564
- });
565
-
566
- it('reports a zero as a child', () => {
567
- var element = <div>{0}</div>;
568
- var tree = {
569
- displayName: 'div',
570
- element,
571
- children: [
572
- {
573
- displayName: '#text',
574
- text: '0',
575
- },
576
- ],
577
- };
578
- assertTreeMatches([element, tree]);
579
- });
580
-
581
- it('skips empty nodes for multiple children', () => {
582
- function Foo() {
583
- return <div />;
584
- }
585
- var element = (
586
- <div>
587
- {'hi'}
588
- {false}
589
- {42}
590
- {null}
591
- <Foo />
592
- </div>
593
- );
594
- var tree = {
595
- displayName: 'div',
596
- element,
597
- children: [
598
- {
599
- displayName: '#text',
600
- text: 'hi',
601
- element: 'hi',
602
- },
603
- {
604
- displayName: '#text',
605
- text: '42',
606
- element: 42,
607
- },
608
- {
609
- displayName: 'Foo',
610
- element: <Foo />,
611
- children: [
612
- {
613
- displayName: 'div',
614
- element: <div />,
615
- children: [],
616
- },
617
- ],
618
- },
619
- ],
620
- };
621
- assertTreeMatches([element, tree]);
622
- });
623
-
624
- it('reports html content as no children', () => {
625
- var element = <div dangerouslySetInnerHTML={{__html: 'Bye.'}} />;
626
- var tree = {
627
- displayName: 'div',
628
- children: [],
629
- };
630
- assertTreeMatches([element, tree]);
631
- });
632
- });
633
-
634
- describe('update', () => {
635
- describe('host component', () => {
636
- it('updates text of a single text child', () => {
637
- var elementBefore = <div>Hi.</div>;
638
- var treeBefore = {
639
- displayName: 'div',
640
- children: [
641
- {
642
- displayName: '#text',
643
- text: 'Hi.',
644
- },
645
- ],
646
- };
647
-
648
- var elementAfter = <div>Bye.</div>;
649
- var treeAfter = {
650
- displayName: 'div',
651
- children: [
652
- {
653
- displayName: '#text',
654
- text: 'Bye.',
655
- },
656
- ],
657
- };
658
-
659
- assertTreeMatches([
660
- [elementBefore, treeBefore],
661
- [elementAfter, treeAfter],
662
- ]);
663
- });
664
-
665
- it('updates from no children to a single text child', () => {
666
- var elementBefore = <div />;
667
- var treeBefore = {
668
- displayName: 'div',
669
- children: [],
670
- };
671
-
672
- var elementAfter = <div>Hi.</div>;
673
- var treeAfter = {
674
- displayName: 'div',
675
- children: [
676
- {
677
- displayName: '#text',
678
- text: 'Hi.',
679
- },
680
- ],
681
- };
682
-
683
- assertTreeMatches([
684
- [elementBefore, treeBefore],
685
- [elementAfter, treeAfter],
686
- ]);
687
- });
688
-
689
- it('updates from a single text child to no children', () => {
690
- var elementBefore = <div>Hi.</div>;
691
- var treeBefore = {
692
- displayName: 'div',
693
- children: [
694
- {
695
- displayName: '#text',
696
- text: 'Hi.',
697
- },
698
- ],
699
- };
700
-
701
- var elementAfter = <div />;
702
- var treeAfter = {
703
- displayName: 'div',
704
- children: [],
705
- };
706
-
707
- assertTreeMatches([
708
- [elementBefore, treeBefore],
709
- [elementAfter, treeAfter],
710
- ]);
711
- });
712
-
713
- it('updates from html content to a single text child', () => {
714
- var elementBefore = <div dangerouslySetInnerHTML={{__html: 'Hi.'}} />;
715
- var treeBefore = {
716
- displayName: 'div',
717
- children: [],
718
- };
719
-
720
- var elementAfter = <div>Hi.</div>;
721
- var treeAfter = {
722
- displayName: 'div',
723
- children: [
724
- {
725
- displayName: '#text',
726
- text: 'Hi.',
727
- },
728
- ],
729
- };
730
-
731
- assertTreeMatches([
732
- [elementBefore, treeBefore],
733
- [elementAfter, treeAfter],
734
- ]);
735
- });
736
-
737
- it('updates from a single text child to html content', () => {
738
- var elementBefore = <div>Hi.</div>;
739
- var treeBefore = {
740
- displayName: 'div',
741
- children: [
742
- {
743
- displayName: '#text',
744
- text: 'Hi.',
745
- },
746
- ],
747
- };
748
-
749
- var elementAfter = <div dangerouslySetInnerHTML={{__html: 'Hi.'}} />;
750
- var treeAfter = {
751
- displayName: 'div',
752
- children: [],
753
- };
754
-
755
- assertTreeMatches([
756
- [elementBefore, treeBefore],
757
- [elementAfter, treeAfter],
758
- ]);
759
- });
760
-
761
- it('updates from no children to multiple text children', () => {
762
- var elementBefore = <div />;
763
- var treeBefore = {
764
- displayName: 'div',
765
- children: [],
766
- };
767
-
768
- var elementAfter = <div>{'Hi.'}{'Bye.'}</div>;
769
- var treeAfter = {
770
- displayName: 'div',
771
- children: [
772
- {
773
- displayName: '#text',
774
- text: 'Hi.',
775
- },
776
- {
777
- displayName: '#text',
778
- text: 'Bye.',
779
- },
780
- ],
781
- };
782
-
783
- assertTreeMatches([
784
- [elementBefore, treeBefore],
785
- [elementAfter, treeAfter],
786
- ]);
787
- });
788
-
789
- it('updates from multiple text children to no children', () => {
790
- var elementBefore = <div>{'Hi.'}{'Bye.'}</div>;
791
- var treeBefore = {
792
- displayName: 'div',
793
- children: [
794
- {
795
- displayName: '#text',
796
- text: 'Hi.',
797
- },
798
- {
799
- displayName: '#text',
800
- text: 'Bye.',
801
- },
802
- ],
803
- };
804
-
805
- var elementAfter = <div />;
806
- var treeAfter = {
807
- displayName: 'div',
808
- children: [],
809
- };
810
-
811
- assertTreeMatches([
812
- [elementBefore, treeBefore],
813
- [elementAfter, treeAfter],
814
- ]);
815
- });
816
-
817
- it('updates from html content to multiple text children', () => {
818
- var elementBefore = <div dangerouslySetInnerHTML={{__html: 'Hi.'}} />;
819
- var treeBefore = {
820
- displayName: 'div',
821
- children: [],
822
- };
823
-
824
- var elementAfter = <div>{'Hi.'}{'Bye.'}</div>;
825
- var treeAfter = {
826
- displayName: 'div',
827
- children: [
828
- {
829
- displayName: '#text',
830
- text: 'Hi.',
831
- },
832
- {
833
- displayName: '#text',
834
- text: 'Bye.',
835
- },
836
- ],
837
- };
838
-
839
- assertTreeMatches([
840
- [elementBefore, treeBefore],
841
- [elementAfter, treeAfter],
842
- ]);
843
- });
844
-
845
- it('updates from multiple text children to html content', () => {
846
- var elementBefore = <div>{'Hi.'}{'Bye.'}</div>;
847
- var treeBefore = {
848
- displayName: 'div',
849
- children: [
850
- {
851
- displayName: '#text',
852
- text: 'Hi.',
853
- },
854
- {
855
- displayName: '#text',
856
- text: 'Bye.',
857
- },
858
- ],
859
- };
860
-
861
- var elementAfter = <div dangerouslySetInnerHTML={{__html: 'Hi.'}} />;
862
- var treeAfter = {
863
- displayName: 'div',
864
- children: [],
865
- };
866
-
867
- assertTreeMatches([
868
- [elementBefore, treeBefore],
869
- [elementAfter, treeAfter],
870
- ]);
871
- });
872
-
873
- it('updates from html content to no children', () => {
874
- var elementBefore = <div dangerouslySetInnerHTML={{__html: 'Hi.'}} />;
875
- var treeBefore = {
876
- displayName: 'div',
877
- children: [],
878
- };
879
-
880
- var elementAfter = <div />;
881
- var treeAfter = {
882
- displayName: 'div',
883
- children: [],
884
- };
885
-
886
- assertTreeMatches([
887
- [elementBefore, treeBefore],
888
- [elementAfter, treeAfter],
889
- ]);
890
- });
891
-
892
- it('updates from no children to html content', () => {
893
- var elementBefore = <div />;
894
- var treeBefore = {
895
- displayName: 'div',
896
- children: [],
897
- };
898
-
899
- var elementAfter = <div dangerouslySetInnerHTML={{__html: 'Hi.'}} />;
900
- var treeAfter = {
901
- displayName: 'div',
902
- children: [],
903
- };
904
-
905
- assertTreeMatches([
906
- [elementBefore, treeBefore],
907
- [elementAfter, treeAfter],
908
- ]);
909
- });
910
-
911
- it('updates from one text child to multiple text children', () => {
912
- var elementBefore = <div>Hi.</div>;
913
- var treeBefore = {
914
- displayName: 'div',
915
- children: [
916
- {
917
- displayName: '#text',
918
- text: 'Hi.',
919
- },
920
- ],
921
- };
922
-
923
- var elementAfter = <div>{'Hi.'}{'Bye.'}</div>;
924
- var treeAfter = {
925
- displayName: 'div',
926
- children: [
927
- {
928
- displayName: '#text',
929
- text: 'Hi.',
930
- },
931
- {
932
- displayName: '#text',
933
- text: 'Bye.',
934
- },
935
- ],
936
- };
937
-
938
- assertTreeMatches([
939
- [elementBefore, treeBefore],
940
- [elementAfter, treeAfter],
941
- ]);
942
- });
943
-
944
- it('updates from multiple text children to one text child', () => {
945
- var elementBefore = <div>{'Hi.'}{'Bye.'}</div>;
946
- var treeBefore = {
947
- displayName: 'div',
948
- children: [
949
- {
950
- displayName: '#text',
951
- text: 'Hi.',
952
- },
953
- {
954
- displayName: '#text',
955
- text: 'Bye.',
956
- },
957
- ],
958
- };
959
-
960
- var elementAfter = <div>Hi.</div>;
961
- var treeAfter = {
962
- displayName: 'div',
963
- children: [
964
- {
965
- displayName: '#text',
966
- text: 'Hi.',
967
- },
968
- ],
969
- };
970
- assertTreeMatches([
971
- [elementBefore, treeBefore],
972
- [elementAfter, treeAfter],
973
- ]);
974
- });
975
-
976
- it('updates text nodes when reordering', () => {
977
- var elementBefore = <div>{'Hi.'}{'Bye.'}</div>;
978
- var treeBefore = {
979
- displayName: 'div',
980
- children: [
981
- {
982
- displayName: '#text',
983
- text: 'Hi.',
984
- },
985
- {
986
- displayName: '#text',
987
- text: 'Bye.',
988
- },
989
- ],
990
- };
991
-
992
- var elementAfter = <div>{'Bye.'}{'Hi.'}</div>;
993
- var treeAfter = {
994
- displayName: 'div',
995
- children: [
996
- {
997
- displayName: '#text',
998
- text: 'Bye.',
999
- },
1000
- {
1001
- displayName: '#text',
1002
- text: 'Hi.',
1003
- },
1004
- ],
1005
- };
1006
- assertTreeMatches([
1007
- [elementBefore, treeBefore],
1008
- [elementAfter, treeAfter],
1009
- ]);
1010
- });
1011
-
1012
- it('updates host nodes when reordering with keys', () => {
1013
- var elementBefore = (
1014
- <div>
1015
- <div key="a">Hi.</div>
1016
- <div key="b">Bye.</div>
1017
- </div>
1018
- );
1019
- var treeBefore = {
1020
- displayName: 'div',
1021
- children: [
1022
- {
1023
- displayName: 'div',
1024
- children: [
1025
- {
1026
- displayName: '#text',
1027
- text: 'Hi.',
1028
- },
1029
- ],
1030
- },
1031
- {
1032
- displayName: 'div',
1033
- children: [
1034
- {
1035
- displayName: '#text',
1036
- text: 'Bye.',
1037
- },
1038
- ],
1039
- },
1040
- ],
1041
- };
1042
-
1043
- var elementAfter = (
1044
- <div>
1045
- <div key="b">Bye.</div>
1046
- <div key="a">Hi.</div>
1047
- </div>
1048
- );
1049
- var treeAfter = {
1050
- displayName: 'div',
1051
- children: [
1052
- {
1053
- displayName: 'div',
1054
- children: [
1055
- {
1056
- displayName: '#text',
1057
- text: 'Bye.',
1058
- },
1059
- ],
1060
- },
1061
- {
1062
- displayName: 'div',
1063
- children: [
1064
- {
1065
- displayName: '#text',
1066
- text: 'Hi.',
1067
- },
1068
- ],
1069
- },
1070
- ],
1071
- };
1072
-
1073
- assertTreeMatches([
1074
- [elementBefore, treeBefore],
1075
- [elementAfter, treeAfter],
1076
- ]);
1077
- });
1078
-
1079
- it('updates host nodes when reordering without keys', () => {
1080
- var elementBefore = (
1081
- <div>
1082
- <div>Hi.</div>
1083
- <div>Bye.</div>
1084
- </div>
1085
- );
1086
- var treeBefore = {
1087
- displayName: 'div',
1088
- children: [
1089
- {
1090
- displayName: 'div',
1091
- children: [
1092
- {
1093
- displayName: '#text',
1094
- text: 'Hi.',
1095
- },
1096
- ],
1097
- },
1098
- {
1099
- displayName: 'div',
1100
- children: [
1101
- {
1102
- displayName: '#text',
1103
- text: 'Bye.',
1104
- },
1105
- ],
1106
- },
1107
- ],
1108
- };
1109
-
1110
- var elementAfter = (
1111
- <div>
1112
- <div>Bye.</div>
1113
- <div>Hi.</div>
1114
- </div>
1115
- );
1116
- var treeAfter = {
1117
- displayName: 'div',
1118
- children: [
1119
- {
1120
- displayName: 'div',
1121
- children: [
1122
- {
1123
- displayName: '#text',
1124
- text: 'Bye.',
1125
- },
1126
- ],
1127
- },
1128
- {
1129
- displayName: 'div',
1130
- children: [
1131
- {
1132
- displayName: '#text',
1133
- text: 'Hi.',
1134
- },
1135
- ],
1136
- },
1137
- ],
1138
- };
1139
-
1140
- assertTreeMatches([
1141
- [elementBefore, treeBefore],
1142
- [elementAfter, treeAfter],
1143
- ]);
1144
- });
1145
-
1146
- it('updates a single composite child of a different type', () => {
1147
- function Foo() {
1148
- return null;
1149
- }
1150
-
1151
- function Bar() {
1152
- return null;
1153
- }
1154
-
1155
- var elementBefore = <div><Foo /></div>;
1156
- var treeBefore = {
1157
- displayName: 'div',
1158
- children: [
1159
- {
1160
- displayName: 'Foo',
1161
- children: [],
1162
- },
1163
- ],
1164
- };
1165
-
1166
- var elementAfter = <div><Bar /></div>;
1167
- var treeAfter = {
1168
- displayName: 'div',
1169
- children: [
1170
- {
1171
- displayName: 'Bar',
1172
- children: [],
1173
- },
1174
- ],
1175
- };
1176
-
1177
- assertTreeMatches([
1178
- [elementBefore, treeBefore],
1179
- [elementAfter, treeAfter],
1180
- ]);
1181
- });
1182
-
1183
- it('updates a single composite child of the same type', () => {
1184
- function Foo({children}) {
1185
- return children;
1186
- }
1187
-
1188
- var elementBefore = <div><Foo><div /></Foo></div>;
1189
- var treeBefore = {
1190
- displayName: 'div',
1191
- children: [
1192
- {
1193
- displayName: 'Foo',
1194
- children: [
1195
- {
1196
- displayName: 'div',
1197
- children: [],
1198
- },
1199
- ],
1200
- },
1201
- ],
1202
- };
1203
-
1204
- var elementAfter = <div><Foo><span /></Foo></div>;
1205
- var treeAfter = {
1206
- displayName: 'div',
1207
- children: [
1208
- {
1209
- displayName: 'Foo',
1210
- children: [
1211
- {
1212
- displayName: 'span',
1213
- children: [],
1214
- },
1215
- ],
1216
- },
1217
- ],
1218
- };
1219
-
1220
- assertTreeMatches([
1221
- [elementBefore, treeBefore],
1222
- [elementAfter, treeAfter],
1223
- ]);
1224
- });
1225
-
1226
- it('updates from no children to a single composite child', () => {
1227
- function Foo() {
1228
- return null;
1229
- }
1230
-
1231
- var elementBefore = <div />;
1232
- var treeBefore = {
1233
- displayName: 'div',
1234
- children: [],
1235
- };
1236
-
1237
- var elementAfter = <div><Foo /></div>;
1238
- var treeAfter = {
1239
- displayName: 'div',
1240
- children: [
1241
- {
1242
- displayName: 'Foo',
1243
- children: [],
1244
- },
1245
- ],
1246
- };
1247
-
1248
- assertTreeMatches([
1249
- [elementBefore, treeBefore],
1250
- [elementAfter, treeAfter],
1251
- ]);
1252
- });
1253
-
1254
- it('updates from a single composite child to no children', () => {
1255
- function Foo() {
1256
- return null;
1257
- }
1258
-
1259
- var elementBefore = <div><Foo /></div>;
1260
- var treeBefore = {
1261
- displayName: 'div',
1262
- children: [
1263
- {
1264
- displayName: 'Foo',
1265
- children: [],
1266
- },
1267
- ],
1268
- };
1269
-
1270
- var elementAfter = <div />;
1271
- var treeAfter = {
1272
- displayName: 'div',
1273
- children: [],
1274
- };
1275
-
1276
- assertTreeMatches([
1277
- [elementBefore, treeBefore],
1278
- [elementAfter, treeAfter],
1279
- ]);
1280
- });
1281
-
1282
- it('updates mixed children', () => {
1283
- function Foo() {
1284
- return <div />;
1285
- }
1286
- var element1 = (
1287
- <div>
1288
- {'hi'}
1289
- {false}
1290
- {42}
1291
- {null}
1292
- <Foo />
1293
- </div>
1294
- );
1295
- var tree1 = {
1296
- displayName: 'div',
1297
- children: [
1298
- {
1299
- displayName: '#text',
1300
- text: 'hi',
1301
- },
1302
- {
1303
- displayName: '#text',
1304
- text: '42',
1305
- },
1306
- {
1307
- displayName: 'Foo',
1308
- children: [
1309
- {
1310
- displayName: 'div',
1311
- children: [],
1312
- },
1313
- ],
1314
- },
1315
- ],
1316
- };
1317
-
1318
- var element2 = (
1319
- <div>
1320
- <Foo />
1321
- {false}
1322
- {'hi'}
1323
- {null}
1324
- </div>
1325
- );
1326
- var tree2 = {
1327
- displayName: 'div',
1328
- children: [
1329
- {
1330
- displayName: 'Foo',
1331
- children: [
1332
- {
1333
- displayName: 'div',
1334
- children: [],
1335
- },
1336
- ],
1337
- },
1338
- {
1339
- displayName: '#text',
1340
- text: 'hi',
1341
- },
1342
- ],
1343
- };
1344
-
1345
- var element3 = (
1346
- <div>
1347
- <Foo />
1348
- </div>
1349
- );
1350
- var tree3 = {
1351
- displayName: 'div',
1352
- children: [
1353
- {
1354
- displayName: 'Foo',
1355
- children: [
1356
- {
1357
- displayName: 'div',
1358
- children: [],
1359
- },
1360
- ],
1361
- },
1362
- ],
1363
- };
1364
-
1365
- assertTreeMatches([
1366
- [element1, tree1],
1367
- [element2, tree2],
1368
- [element3, tree3],
1369
- ]);
1370
- });
1371
- });
1372
-
1373
- describe('functional component', () => {
1374
- it('updates with a host child', () => {
1375
- function Foo({children}) {
1376
- return children;
1377
- }
1378
-
1379
- var elementBefore = <Foo><div /></Foo>;
1380
- var treeBefore = {
1381
- displayName: 'Foo',
1382
- children: [
1383
- {
1384
- displayName: 'div',
1385
- children: [],
1386
- },
1387
- ],
1388
- };
1389
-
1390
- var elementAfter = <Foo><span /></Foo>;
1391
- var treeAfter = {
1392
- displayName: 'Foo',
1393
- children: [
1394
- {
1395
- displayName: 'span',
1396
- children: [],
1397
- },
1398
- ],
1399
- };
1400
-
1401
- assertTreeMatches([
1402
- [elementBefore, treeBefore],
1403
- [elementAfter, treeAfter],
1404
- ]);
1405
- });
1406
-
1407
- it('updates from null to a host child', () => {
1408
- function Foo({children}) {
1409
- return children;
1410
- }
1411
-
1412
- var elementBefore = <Foo>{null}</Foo>;
1413
- var treeBefore = {
1414
- displayName: 'Foo',
1415
- children: [],
1416
- };
1417
-
1418
- var elementAfter = <Foo><div /></Foo>;
1419
- var treeAfter = {
1420
- displayName: 'Foo',
1421
- children: [
1422
- {
1423
- displayName: 'div',
1424
- children: [],
1425
- },
1426
- ],
1427
- };
1428
-
1429
- assertTreeMatches([
1430
- [elementBefore, treeBefore],
1431
- [elementAfter, treeAfter],
1432
- ]);
1433
- });
1434
-
1435
- it('updates from a host child to null', () => {
1436
- function Foo({children}) {
1437
- return children;
1438
- }
1439
-
1440
- var elementBefore = <Foo><div /></Foo>;
1441
- var treeBefore = {
1442
- displayName: 'Foo',
1443
- children: [
1444
- {
1445
- displayName: 'div',
1446
- children: [],
1447
- },
1448
- ],
1449
- };
1450
-
1451
- var elementAfter = <Foo>{null}</Foo>;
1452
- var treeAfter = {
1453
- displayName: 'Foo',
1454
- children: [],
1455
- };
1456
-
1457
- assertTreeMatches([
1458
- [elementBefore, treeBefore],
1459
- [elementAfter, treeAfter],
1460
- ]);
1461
- });
1462
-
1463
- it('updates from a host child to a composite child', () => {
1464
- function Bar() {
1465
- return null;
1466
- }
1467
-
1468
- function Foo({children}) {
1469
- return children;
1470
- }
1471
-
1472
- var elementBefore = <Foo><div /></Foo>;
1473
- var treeBefore = {
1474
- displayName: 'Foo',
1475
- children: [
1476
- {
1477
- displayName: 'div',
1478
- children: [],
1479
- },
1480
- ],
1481
- };
1482
-
1483
- var elementAfter = <Foo><Bar /></Foo>;
1484
- var treeAfter = {
1485
- displayName: 'Foo',
1486
- children: [
1487
- {
1488
- displayName: 'Bar',
1489
- children: [],
1490
- },
1491
- ],
1492
- };
1493
-
1494
- assertTreeMatches([
1495
- [elementBefore, treeBefore],
1496
- [elementAfter, treeAfter],
1497
- ]);
1498
- });
1499
-
1500
- it('updates from a composite child to a host child', () => {
1501
- function Bar() {
1502
- return null;
1503
- }
1504
-
1505
- function Foo({children}) {
1506
- return children;
1507
- }
1508
-
1509
- var elementBefore = <Foo><Bar /></Foo>;
1510
- var treeBefore = {
1511
- displayName: 'Foo',
1512
- children: [
1513
- {
1514
- displayName: 'Bar',
1515
- children: [],
1516
- },
1517
- ],
1518
- };
1519
-
1520
- var elementAfter = <Foo><div /></Foo>;
1521
- var treeAfter = {
1522
- displayName: 'Foo',
1523
- children: [
1524
- {
1525
- displayName: 'div',
1526
- children: [],
1527
- },
1528
- ],
1529
- };
1530
-
1531
- assertTreeMatches([
1532
- [elementBefore, treeBefore],
1533
- [elementAfter, treeAfter],
1534
- ]);
1535
- });
1536
-
1537
- it('updates from null to a composite child', () => {
1538
- function Bar() {
1539
- return null;
1540
- }
1541
-
1542
- function Foo({children}) {
1543
- return children;
1544
- }
1545
-
1546
- var elementBefore = <Foo>{null}</Foo>;
1547
- var treeBefore = {
1548
- displayName: 'Foo',
1549
- children: [],
1550
- };
1551
-
1552
- var elementAfter = <Foo><Bar /></Foo>;
1553
- var treeAfter = {
1554
- displayName: 'Foo',
1555
- children: [
1556
- {
1557
- displayName: 'Bar',
1558
- children: [],
1559
- },
1560
- ],
1561
- };
1562
-
1563
- assertTreeMatches([
1564
- [elementBefore, treeBefore],
1565
- [elementAfter, treeAfter],
1566
- ]);
1567
- });
1568
-
1569
- it('updates from a composite child to null', () => {
1570
- function Bar() {
1571
- return null;
1572
- }
1573
-
1574
- function Foo({children}) {
1575
- return children;
1576
- }
1577
-
1578
- var elementBefore = <Foo><Bar /></Foo>;
1579
- var treeBefore = {
1580
- displayName: 'Foo',
1581
- children: [
1582
- {
1583
- displayName: 'Bar',
1584
- children: [],
1585
- },
1586
- ],
1587
- };
1588
-
1589
- var elementAfter = <Foo>{null}</Foo>;
1590
- var treeAfter = {
1591
- displayName: 'Foo',
1592
- children: [],
1593
- };
1594
-
1595
- assertTreeMatches([
1596
- [elementBefore, treeBefore],
1597
- [elementAfter, treeAfter],
1598
- ]);
1599
- });
1600
- });
1601
-
1602
- describe('class component', () => {
1603
- it('updates with a host child', () => {
1604
- class Foo extends React.Component {
1605
- render() {
1606
- return this.props.children;
1607
- }
1608
- }
1609
-
1610
- var elementBefore = <Foo><div /></Foo>;
1611
- var treeBefore = {
1612
- displayName: 'Foo',
1613
- children: [
1614
- {
1615
- displayName: 'div',
1616
- children: [],
1617
- },
1618
- ],
1619
- };
1620
-
1621
- var elementAfter = <Foo><span /></Foo>;
1622
- var treeAfter = {
1623
- displayName: 'Foo',
1624
- children: [
1625
- {
1626
- displayName: 'span',
1627
- children: [],
1628
- },
1629
- ],
1630
- };
1631
-
1632
- assertTreeMatches([
1633
- [elementBefore, treeBefore],
1634
- [elementAfter, treeAfter],
1635
- ]);
1636
- });
1637
-
1638
- it('updates from null to a host child', () => {
1639
- class Foo extends React.Component {
1640
- render() {
1641
- return this.props.children;
1642
- }
1643
- }
1644
-
1645
- var elementBefore = <Foo>{null}</Foo>;
1646
- var treeBefore = {
1647
- displayName: 'Foo',
1648
- children: [],
1649
- };
1650
-
1651
- var elementAfter = <Foo><div /></Foo>;
1652
- var treeAfter = {
1653
- displayName: 'Foo',
1654
- children: [
1655
- {
1656
- displayName: 'div',
1657
- children: [],
1658
- },
1659
- ],
1660
- };
1661
-
1662
- assertTreeMatches([
1663
- [elementBefore, treeBefore],
1664
- [elementAfter, treeAfter],
1665
- ]);
1666
- });
1667
-
1668
- it('updates from a host child to null', () => {
1669
- class Foo extends React.Component {
1670
- render() {
1671
- return this.props.children;
1672
- }
1673
- }
1674
-
1675
- var elementBefore = <Foo><div /></Foo>;
1676
- var treeBefore = {
1677
- displayName: 'Foo',
1678
- children: [
1679
- {
1680
- displayName: 'div',
1681
- children: [],
1682
- },
1683
- ],
1684
- };
1685
-
1686
- var elementAfter = <Foo>{null}</Foo>;
1687
- var treeAfter = {
1688
- displayName: 'Foo',
1689
- children: [],
1690
- };
1691
-
1692
- assertTreeMatches([
1693
- [elementBefore, treeBefore],
1694
- [elementAfter, treeAfter],
1695
- ]);
1696
- });
1697
-
1698
- it('updates from a host child to a composite child', () => {
1699
- class Bar extends React.Component {
1700
- render() {
1701
- return null;
1702
- }
1703
- }
1704
-
1705
- class Foo extends React.Component {
1706
- render() {
1707
- return this.props.children;
1708
- }
1709
- }
1710
-
1711
- var elementBefore = <Foo><div /></Foo>;
1712
- var treeBefore = {
1713
- displayName: 'Foo',
1714
- children: [
1715
- {
1716
- displayName: 'div',
1717
- children: [],
1718
- },
1719
- ],
1720
- };
1721
-
1722
- var elementAfter = <Foo><Bar /></Foo>;
1723
- var treeAfter = {
1724
- displayName: 'Foo',
1725
- children: [
1726
- {
1727
- displayName: 'Bar',
1728
- children: [],
1729
- },
1730
- ],
1731
- };
1732
-
1733
- assertTreeMatches([
1734
- [elementBefore, treeBefore],
1735
- [elementAfter, treeAfter],
1736
- ]);
1737
- });
1738
-
1739
- it('updates from a composite child to a host child', () => {
1740
- class Bar extends React.Component {
1741
- render() {
1742
- return null;
1743
- }
1744
- }
1745
-
1746
- class Foo extends React.Component {
1747
- render() {
1748
- return this.props.children;
1749
- }
1750
- }
1751
-
1752
- var elementBefore = <Foo><Bar /></Foo>;
1753
- var treeBefore = {
1754
- displayName: 'Foo',
1755
- children: [
1756
- {
1757
- displayName: 'Bar',
1758
- children: [],
1759
- },
1760
- ],
1761
- };
1762
-
1763
- var elementAfter = <Foo><div /></Foo>;
1764
- var treeAfter = {
1765
- displayName: 'Foo',
1766
- children: [
1767
- {
1768
- displayName: 'div',
1769
- children: [],
1770
- },
1771
- ],
1772
- };
1773
-
1774
- assertTreeMatches([
1775
- [elementBefore, treeBefore],
1776
- [elementAfter, treeAfter],
1777
- ]);
1778
- });
1779
-
1780
- it('updates from null to a composite child', () => {
1781
- class Bar extends React.Component {
1782
- render() {
1783
- return null;
1784
- }
1785
- }
1786
-
1787
- class Foo extends React.Component {
1788
- render() {
1789
- return this.props.children;
1790
- }
1791
- }
1792
-
1793
- var elementBefore = <Foo>{null}</Foo>;
1794
- var treeBefore = {
1795
- displayName: 'Foo',
1796
- children: [],
1797
- };
1798
-
1799
- var elementAfter = <Foo><Bar /></Foo>;
1800
- var treeAfter = {
1801
- displayName: 'Foo',
1802
- children: [
1803
- {
1804
- displayName: 'Bar',
1805
- children: [],
1806
- },
1807
- ],
1808
- };
1809
-
1810
- assertTreeMatches([
1811
- [elementBefore, treeBefore],
1812
- [elementAfter, treeAfter],
1813
- ]);
1814
- });
1815
-
1816
- it('updates from a composite child to null', () => {
1817
- class Bar extends React.Component {
1818
- render() {
1819
- return null;
1820
- }
1821
- }
1822
-
1823
- class Foo extends React.Component {
1824
- render() {
1825
- return this.props.children;
1826
- }
1827
- }
1828
-
1829
- var elementBefore = <Foo><Bar /></Foo>;
1830
- var treeBefore = {
1831
- displayName: 'Foo',
1832
- children: [
1833
- {
1834
- displayName: 'Bar',
1835
- children: [],
1836
- },
1837
- ],
1838
- };
1839
-
1840
- var elementAfter = <Foo>{null}</Foo>;
1841
- var treeAfter = {
1842
- displayName: 'Foo',
1843
- children: [],
1844
- };
1845
-
1846
- assertTreeMatches([
1847
- [elementBefore, treeBefore],
1848
- [elementAfter, treeAfter],
1849
- ]);
1850
- });
1851
- });
1852
- });
1853
-
1854
- describe('misc', () => {
1855
- it('tracks owner correctly', () => {
1856
- class Foo extends React.Component {
1857
- render() {
1858
- return <Bar><h1>Hi.</h1></Bar>;
1859
- }
1860
- }
1861
- function Bar({children}) {
1862
- return <div>{children} Mom</div>;
1863
- }
1864
-
1865
- // Note that owner is not calculated for text nodes
1866
- // because they are not created from real elements.
1867
- var element = <article><Foo /></article>;
1868
- var tree = {
1869
- displayName: 'article',
1870
- children: [
1871
- {
1872
- displayName: 'Foo',
1873
- children: [
1874
- {
1875
- displayName: 'Bar',
1876
- ownerDisplayName: 'Foo',
1877
- children: [
1878
- {
1879
- displayName: 'div',
1880
- ownerDisplayName: 'Bar',
1881
- children: [
1882
- {
1883
- displayName: 'h1',
1884
- ownerDisplayName: 'Foo',
1885
- children: [
1886
- {
1887
- displayName: '#text',
1888
- text: 'Hi.',
1889
- },
1890
- ],
1891
- },
1892
- {
1893
- displayName: '#text',
1894
- text: ' Mom',
1895
- },
1896
- ],
1897
- },
1898
- ],
1899
- },
1900
- ],
1901
- },
1902
- ],
1903
- };
1904
- assertTreeMatches([element, tree]);
1905
- });
1906
-
1907
- it('purges unmounted components automatically', () => {
1908
- var node = document.createElement('div');
1909
- var renderBar = true;
1910
- var fooInstance;
1911
- var barInstance;
1912
-
1913
- class Foo extends React.Component {
1914
- render() {
1915
- fooInstance = ReactInstanceMap.get(this);
1916
- return renderBar ? <Bar /> : null;
1917
- }
1918
- }
1919
-
1920
- class Bar extends React.Component {
1921
- render() {
1922
- barInstance = ReactInstanceMap.get(this);
1923
- return null;
1924
- }
1925
- }
1926
-
1927
- ReactDOM.render(<Foo />, node);
1928
- ReactComponentTreeTestUtils.expectTree(
1929
- barInstance._debugID,
1930
- {
1931
- displayName: 'Bar',
1932
- parentDisplayName: 'Foo',
1933
- parentID: fooInstance._debugID,
1934
- children: [],
1935
- },
1936
- 'Foo',
1937
- );
1938
-
1939
- renderBar = false;
1940
- ReactDOM.render(<Foo />, node);
1941
- ReactDOM.render(<Foo />, node);
1942
- ReactComponentTreeTestUtils.expectTree(
1943
- barInstance._debugID,
1944
- {
1945
- displayName: 'Unknown',
1946
- children: [],
1947
- parentID: null,
1948
- },
1949
- 'Foo',
1950
- );
1951
-
1952
- ReactDOM.unmountComponentAtNode(node);
1953
- ReactComponentTreeTestUtils.expectTree(
1954
- barInstance._debugID,
1955
- {
1956
- displayName: 'Unknown',
1957
- children: [],
1958
- parentID: null,
1959
- },
1960
- 'Foo',
1961
- );
1962
- });
1963
-
1964
- it('reports update counts', () => {
1965
- var node = document.createElement('div');
1966
-
1967
- ReactDOM.render(<div className="a" />, node);
1968
- var divID = ReactComponentTreeHook.getRootIDs()[0];
1969
- expectDev(ReactComponentTreeHook.getUpdateCount(divID)).toEqual(0);
1970
-
1971
- ReactDOM.render(<span className="a" />, node);
1972
- var spanID = ReactComponentTreeHook.getRootIDs()[0];
1973
- expectDev(ReactComponentTreeHook.getUpdateCount(divID)).toEqual(0);
1974
- expectDev(ReactComponentTreeHook.getUpdateCount(spanID)).toEqual(0);
1975
-
1976
- ReactDOM.render(<span className="b" />, node);
1977
- expectDev(ReactComponentTreeHook.getUpdateCount(divID)).toEqual(0);
1978
- expectDev(ReactComponentTreeHook.getUpdateCount(spanID)).toEqual(1);
1979
-
1980
- ReactDOM.render(<span className="c" />, node);
1981
- expectDev(ReactComponentTreeHook.getUpdateCount(divID)).toEqual(0);
1982
- expectDev(ReactComponentTreeHook.getUpdateCount(spanID)).toEqual(2);
1983
-
1984
- ReactDOM.unmountComponentAtNode(node);
1985
- expectDev(ReactComponentTreeHook.getUpdateCount(divID)).toEqual(0);
1986
- expectDev(ReactComponentTreeHook.getUpdateCount(spanID)).toEqual(0);
1987
- });
1988
-
1989
- it('does not report top-level wrapper as a root', () => {
1990
- var node = document.createElement('div');
1991
-
1992
- ReactDOM.render(<div className="a" />, node);
1993
- expectDev(ReactComponentTreeTestUtils.getRootDisplayNames()).toEqual([
1994
- 'div',
1995
- ]);
1996
-
1997
- ReactDOM.render(<div className="b" />, node);
1998
- expectDev(ReactComponentTreeTestUtils.getRootDisplayNames()).toEqual([
1999
- 'div',
2000
- ]);
2001
-
2002
- ReactDOM.unmountComponentAtNode(node);
2003
- expectDev(ReactComponentTreeTestUtils.getRootDisplayNames()).toEqual([]);
2004
- expectDev(
2005
- ReactComponentTreeTestUtils.getRegisteredDisplayNames(),
2006
- ).toEqual([]);
2007
- });
2008
-
2009
- it('registers inlined text nodes', () => {
2010
- var node = document.createElement('div');
2011
-
2012
- ReactDOM.render(<div>hi</div>, node);
2013
- expectDev(
2014
- ReactComponentTreeTestUtils.getRegisteredDisplayNames(),
2015
- ).toEqual(['div', '#text']);
2016
-
2017
- ReactDOM.unmountComponentAtNode(node);
2018
- expectDev(
2019
- ReactComponentTreeTestUtils.getRegisteredDisplayNames(),
2020
- ).toEqual([]);
2021
- });
2022
- });
2023
-
2024
- describe('in environment without Map, Set and Array.from', () => {
2025
- var realMap;
2026
- var realSet;
2027
- var realArrayFrom;
2028
-
2029
- beforeEach(() => {
2030
- realMap = global.Map;
2031
- realSet = global.Set;
2032
- realArrayFrom = Array.from;
2033
-
2034
- global.Map = undefined;
2035
- global.Set = undefined;
2036
- Array.from = undefined;
2037
-
2038
- jest.resetModules();
2039
-
2040
- React = require('react');
2041
- ReactDOM = require('react-dom');
2042
- ReactInstanceMap = require('ReactInstanceMap');
2043
- ReactComponentTreeHook = require('ReactComponentTreeHook');
2044
- ReactComponentTreeTestUtils = require('ReactComponentTreeTestUtils');
2045
- });
2046
-
2047
- afterEach(() => {
2048
- global.Map = realMap;
2049
- global.Set = realSet;
2050
- Array.from = realArrayFrom;
2051
- });
2052
-
2053
- it('works', () => {
2054
- class Qux extends React.Component {
2055
- render() {
2056
- return null;
2057
- }
2058
- }
2059
-
2060
- function Foo() {
2061
- return {
2062
- render() {
2063
- return <Qux />;
2064
- },
2065
- };
2066
- }
2067
- function Bar({children}) {
2068
- return <h1>{children}</h1>;
2069
- }
2070
- class Baz extends React.Component {
2071
- render() {
2072
- return (
2073
- <div>
2074
- <Foo />
2075
- <Bar>
2076
- <span>Hi,</span>
2077
- Mom
2078
- </Bar>
2079
- <a href="#">Click me.</a>
2080
- </div>
2081
- );
2082
- }
2083
- }
2084
-
2085
- var element = <Baz />;
2086
- var tree = {
2087
- displayName: 'Baz',
2088
- element,
2089
- children: [
2090
- {
2091
- displayName: 'div',
2092
- children: [
2093
- {
2094
- displayName: 'Foo',
2095
- element: <Foo />,
2096
- children: [
2097
- {
2098
- displayName: 'Qux',
2099
- element: <Qux />,
2100
- children: [],
2101
- },
2102
- ],
2103
- },
2104
- {
2105
- displayName: 'Bar',
2106
- children: [
2107
- {
2108
- displayName: 'h1',
2109
- children: [
2110
- {
2111
- displayName: 'span',
2112
- children: [
2113
- {
2114
- displayName: '#text',
2115
- element: 'Hi,',
2116
- text: 'Hi,',
2117
- },
2118
- ],
2119
- },
2120
- {
2121
- displayName: '#text',
2122
- text: 'Mom',
2123
- element: 'Mom',
2124
- },
2125
- ],
2126
- },
2127
- ],
2128
- },
2129
- {
2130
- displayName: 'a',
2131
- children: [
2132
- {
2133
- displayName: '#text',
2134
- text: 'Click me.',
2135
- element: 'Click me.',
2136
- },
2137
- ],
2138
- },
2139
- ],
2140
- },
2141
- ],
2142
- };
2143
- assertTreeMatches([element, tree]);
2144
- });
2145
- });
2146
-});
src/renderers/__tests__/ReactHostOperationHistoryHook-test.js
deleted
-776
@@ -1,776 +0,0 @@
1
-/**
2
- * Copyright (c) 2016-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
- * @emails react-core
8
- */
9
-
10
-'use strict';
11
-
12
-// This is only used by ReactPerf which is currently not supported on Fiber.
13
-// Use browser timeline integration instead.
14
-describe.skip('ReactHostOperationHistoryHook', () => {
15
- var React;
16
- var ReactPerf;
17
- var ReactDOM;
18
- var ReactDOMComponentTree;
19
- var ReactHostOperationHistoryHook;
20
-
21
- beforeEach(() => {
22
- jest.resetModules();
23
-
24
- React = require('react');
25
- ReactPerf = require('ReactPerf');
26
- ReactDOM = require('react-dom');
27
- ReactDOMComponentTree = require('ReactDOMComponentTree');
28
- ReactHostOperationHistoryHook = require('ReactHostOperationHistoryHook');
29
-
30
- ReactPerf.start();
31
- });
32
-
33
- afterEach(() => {
34
- ReactPerf.stop();
35
- });
36
-
37
- function assertHistoryMatches(expectedHistory) {
38
- var actualHistory = ReactHostOperationHistoryHook.getHistory();
39
- expectDev(actualHistory).toEqual(expectedHistory);
40
- }
41
-
42
- describe('mount', () => {
43
- it('gets recorded for host roots', () => {
44
- var node = document.createElement('div');
45
- ReactHostOperationHistoryHook._preventClearing = true;
46
- ReactDOM.render(<div><p>Hi.</p></div>, node);
47
-
48
- var inst = ReactDOMComponentTree.getInstanceFromNode(node.firstChild);
49
- assertHistoryMatches([
50
- {
51
- instanceID: inst._debugID,
52
- type: 'mount',
53
- payload: 'DIV',
54
- },
55
- ]);
56
- });
57
-
58
- it('gets recorded for composite roots', () => {
59
- function Foo() {
60
- return <div><p>Hi.</p></div>;
61
- }
62
- var node = document.createElement('div');
63
-
64
- ReactHostOperationHistoryHook._preventClearing = true;
65
- ReactDOM.render(<Foo />, node);
66
-
67
- var inst = ReactDOMComponentTree.getInstanceFromNode(node.firstChild);
68
- assertHistoryMatches([
69
- {
70
- instanceID: inst._debugID,
71
- type: 'mount',
72
- payload: 'DIV',
73
- },
74
- ]);
75
- });
76
-
77
- it('gets ignored for composite roots that return null', () => {
78
- function Foo() {
79
- return null;
80
- }
81
- var node = document.createElement('div');
82
-
83
- ReactHostOperationHistoryHook._preventClearing = true;
84
- ReactDOM.render(<Foo />, node);
85
-
86
- // Empty DOM components should be invisible to hooks.
87
- assertHistoryMatches([]);
88
- });
89
-
90
- it('gets recorded when a native is mounted deeply instead of null', () => {
91
- var element;
92
- function Foo() {
93
- return element;
94
- }
95
-
96
- ReactHostOperationHistoryHook._preventClearing = true;
97
-
98
- var node = document.createElement('div');
99
- element = null;
100
- ReactDOM.render(<Foo />, node);
101
-
102
- element = <span />;
103
- ReactDOM.render(<Foo />, node);
104
- var inst = ReactDOMComponentTree.getInstanceFromNode(node.firstChild);
105
-
106
- // Since empty components should be invisible to hooks,
107
- // we record a "mount" event rather than a "replace with".
108
- assertHistoryMatches([
109
- {
110
- instanceID: inst._debugID,
111
- type: 'mount',
112
- payload: 'SPAN',
113
- },
114
- ]);
115
- });
116
- });
117
-
118
- describe('update styles', () => {
119
- it('gets recorded during mount', () => {
120
- var node = document.createElement('div');
121
-
122
- ReactHostOperationHistoryHook._preventClearing = true;
123
- ReactDOM.render(
124
- <div
125
- style={{
126
- color: 'red',
127
- backgroundColor: 'yellow',
128
- }}
129
- />,
130
- node,
131
- );
132
-
133
- var inst = ReactDOMComponentTree.getInstanceFromNode(node.firstChild);
134
- assertHistoryMatches([
135
- {
136
- instanceID: inst._debugID,
137
- type: 'update styles',
138
- payload: {
139
- color: 'red',
140
- backgroundColor: 'yellow',
141
- },
142
- },
143
- {
144
- instanceID: inst._debugID,
145
- type: 'mount',
146
- payload: 'DIV',
147
- },
148
- ]);
149
- });
150
-
151
- it('gets recorded during an update', () => {
152
- var node = document.createElement('div');
153
- ReactDOM.render(<div />, node);
154
- var inst = ReactDOMComponentTree.getInstanceFromNode(node.firstChild);
155
-
156
- ReactHostOperationHistoryHook._preventClearing = true;
157
- ReactDOM.render(<div style={{color: 'red'}} />, node);
158
- ReactDOM.render(
159
- <div
160
- style={{
161
- color: 'blue',
162
- backgroundColor: 'yellow',
163
- }}
164
- />,
165
- node,
166
- );
167
- ReactDOM.render(<div style={{backgroundColor: 'green'}} />, node);
168
- ReactDOM.render(<div />, node);
169
-
170
- assertHistoryMatches([
171
- {
172
- instanceID: inst._debugID,
173
- type: 'update styles',
174
- payload: {color: 'red'},
175
- },
176
- {
177
- instanceID: inst._debugID,
178
- type: 'update styles',
179
- payload: {color: 'blue', backgroundColor: 'yellow'},
180
- },
181
- {
182
- instanceID: inst._debugID,
183
- type: 'update styles',
184
- payload: {color: '', backgroundColor: 'green'},
185
- },
186
- {
187
- instanceID: inst._debugID,
188
- type: 'update styles',
189
- payload: {backgroundColor: ''},
190
- },
191
- ]);
192
- });
193
-
194
- it('gets ignored if the styles are shallowly equal', () => {
195
- var node = document.createElement('div');
196
- ReactDOM.render(<div />, node);
197
- var inst = ReactDOMComponentTree.getInstanceFromNode(node.firstChild);
198
-
199
- ReactHostOperationHistoryHook._preventClearing = true;
200
- ReactDOM.render(
201
- <div
202
- style={{
203
- color: 'red',
204
- backgroundColor: 'yellow',
205
- }}
206
- />,
207
- node,
208
- );
209
- ReactDOM.render(
210
- <div
211
- style={{
212
- color: 'red',
213
- backgroundColor: 'yellow',
214
- }}
215
- />,
216
- node,
217
- );
218
-
219
- assertHistoryMatches([
220
- {
221
- instanceID: inst._debugID,
222
- type: 'update styles',
223
- payload: {
224
- color: 'red',
225
- backgroundColor: 'yellow',
226
- },
227
- },
228
- ]);
229
- });
230
- });
231
-
232
- describe('update attribute', () => {
233
- describe('simple attribute', () => {
234
- it('gets recorded during mount', () => {
235
- var node = document.createElement('div');
236
-
237
- ReactHostOperationHistoryHook._preventClearing = true;
238
- ReactDOM.render(<div className="rad" tabIndex={42} />, node);
239
-
240
- var inst = ReactDOMComponentTree.getInstanceFromNode(node.firstChild);
241
- assertHistoryMatches([
242
- {
243
- instanceID: inst._debugID,
244
- type: 'update attribute',
245
- payload: {className: 'rad'},
246
- },
247
- {
248
- instanceID: inst._debugID,
249
- type: 'update attribute',
250
- payload: {tabIndex: 42},
251
- },
252
- {
253
- instanceID: inst._debugID,
254
- type: 'mount',
255
- payload: 'DIV',
256
- },
257
- ]);
258
- });
259
-
260
- it('gets recorded during an update', () => {
261
- var node = document.createElement('div');
262
- ReactDOM.render(<div />, node);
263
- var inst = ReactDOMComponentTree.getInstanceFromNode(node.firstChild);
264
-
265
- ReactHostOperationHistoryHook._preventClearing = true;
266
- ReactDOM.render(<div className="rad" />, node);
267
- ReactDOM.render(<div className="mad" tabIndex={42} />, node);
268
- ReactDOM.render(<div tabIndex={43} />, node);
269
-
270
- assertHistoryMatches([
271
- {
272
- instanceID: inst._debugID,
273
- type: 'update attribute',
274
- payload: {className: 'rad'},
275
- },
276
- {
277
- instanceID: inst._debugID,
278
- type: 'update attribute',
279
- payload: {className: 'mad'},
280
- },
281
- {
282
- instanceID: inst._debugID,
283
- type: 'update attribute',
284
- payload: {tabIndex: 42},
285
- },
286
- {
287
- instanceID: inst._debugID,
288
- type: 'remove attribute',
289
- payload: 'className',
290
- },
291
- {
292
- instanceID: inst._debugID,
293
- type: 'update attribute',
294
- payload: {tabIndex: 43},
295
- },
296
- ]);
297
- });
298
- });
299
-
300
- describe('attribute that gets removed with certain values', () => {
301
- it('gets recorded as a removal during an update', () => {
302
- var node = document.createElement('div');
303
- ReactDOM.render(<div />, node);
304
- var inst = ReactDOMComponentTree.getInstanceFromNode(node.firstChild);
305
-
306
- ReactHostOperationHistoryHook._preventClearing = true;
307
- ReactDOM.render(<div disabled={true} />, node);
308
- ReactDOM.render(<div disabled={false} />, node);
309
-
310
- assertHistoryMatches([
311
- {
312
- instanceID: inst._debugID,
313
- type: 'update attribute',
314
- payload: {disabled: true},
315
- },
316
- {
317
- instanceID: inst._debugID,
318
- type: 'remove attribute',
319
- payload: 'disabled',
320
- },
321
- ]);
322
- });
323
- });
324
-
325
- describe('custom attribute', () => {
326
- it('gets recorded during mount', () => {
327
- var node = document.createElement('div');
328
-
329
- ReactHostOperationHistoryHook._preventClearing = true;
330
- ReactDOM.render(<div data-x="rad" data-y={42} />, node);
331
-
332
- var inst = ReactDOMComponentTree.getInstanceFromNode(node.firstChild);
333
- assertHistoryMatches([
334
- {
335
- instanceID: inst._debugID,
336
- type: 'update attribute',
337
- payload: {'data-x': 'rad'},
338
- },
339
- {
340
- instanceID: inst._debugID,
341
- type: 'update attribute',
342
- payload: {'data-y': 42},
343
- },
344
- {
345
- instanceID: inst._debugID,
346
- type: 'mount',
347
- payload: 'DIV',
348
- },
349
- ]);
350
- });
351
-
352
- it('gets recorded during an update', () => {
353
- var node = document.createElement('div');
354
- ReactDOM.render(<div />, node);
355
- var inst = ReactDOMComponentTree.getInstanceFromNode(node.firstChild);
356
-
357
- ReactHostOperationHistoryHook._preventClearing = true;
358
- ReactDOM.render(<div data-x="rad" />, node);
359
- ReactDOM.render(<div data-x="mad" data-y={42} />, node);
360
- ReactDOM.render(<div data-y={43} />, node);
361
-
362
- assertHistoryMatches([
363
- {
364
- instanceID: inst._debugID,
365
- type: 'update attribute',
366
- payload: {'data-x': 'rad'},
367
- },
368
- {
369
- instanceID: inst._debugID,
370
- type: 'update attribute',
371
- payload: {'data-x': 'mad'},
372
- },
373
- {
374
- instanceID: inst._debugID,
375
- type: 'update attribute',
376
- payload: {'data-y': 42},
377
- },
378
- {
379
- instanceID: inst._debugID,
380
- type: 'remove attribute',
381
- payload: 'data-x',
382
- },
383
- {
384
- instanceID: inst._debugID,
385
- type: 'update attribute',
386
- payload: {'data-y': 43},
387
- },
388
- ]);
389
- });
390
- });
391
-
392
- describe('attribute on a web component', () => {
393
- it('gets recorded during mount', () => {
394
- var node = document.createElement('div');
395
-
396
- ReactHostOperationHistoryHook._preventClearing = true;
397
- ReactDOM.render(<my-component className="rad" tabIndex={42} />, node);
398
-
399
- var inst = ReactDOMComponentTree.getInstanceFromNode(node.firstChild);
400
- assertHistoryMatches([
401
- {
402
- instanceID: inst._debugID,
403
- type: 'update attribute',
404
- payload: {className: 'rad'},
405
- },
406
- {
407
- instanceID: inst._debugID,
408
- type: 'update attribute',
409
- payload: {tabIndex: 42},
410
- },
411
- {
412
- instanceID: inst._debugID,
413
- type: 'mount',
414
- payload: 'MY-COMPONENT',
415
- },
416
- ]);
417
- });
418
-
419
- it('gets recorded during an update', () => {
420
- var node = document.createElement('div');
421
- ReactDOM.render(<my-component />, node);
422
- var inst = ReactDOMComponentTree.getInstanceFromNode(node.firstChild);
423
-
424
- ReactHostOperationHistoryHook._preventClearing = true;
425
- ReactDOM.render(<my-component className="rad" />, node);
426
- ReactDOM.render(<my-component className="mad" tabIndex={42} />, node);
427
- ReactDOM.render(<my-component tabIndex={43} />, node);
428
-
429
- assertHistoryMatches([
430
- {
431
- instanceID: inst._debugID,
432
- type: 'update attribute',
433
- payload: {className: 'rad'},
434
- },
435
- {
436
- instanceID: inst._debugID,
437
- type: 'update attribute',
438
- payload: {className: 'mad'},
439
- },
440
- {
441
- instanceID: inst._debugID,
442
- type: 'update attribute',
443
- payload: {tabIndex: 42},
444
- },
445
- {
446
- instanceID: inst._debugID,
447
- type: 'remove attribute',
448
- payload: 'className',
449
- },
450
- {
451
- instanceID: inst._debugID,
452
- type: 'update attribute',
453
- payload: {tabIndex: 43},
454
- },
455
- ]);
456
- });
457
- });
458
- });
459
-
460
- describe('replace text', () => {
461
- describe('text content', () => {
462
- it('gets recorded during an update from text content', () => {
463
- var node = document.createElement('div');
464
- ReactDOM.render(<div>Hi.</div>, node);
465
- var inst = ReactDOMComponentTree.getInstanceFromNode(node.firstChild);
466
-
467
- ReactHostOperationHistoryHook._preventClearing = true;
468
- ReactDOM.render(<div>Bye.</div>, node);
469
-
470
- assertHistoryMatches([
471
- {
472
- instanceID: inst._debugID,
473
- type: 'replace text',
474
- payload: 'Bye.',
475
- },
476
- ]);
477
- });
478
-
479
- it('gets recorded during an update from html', () => {
480
- var node = document.createElement('div');
481
- ReactDOM.render(
482
- <div dangerouslySetInnerHTML={{__html: 'Hi.'}} />,
483
- node,
484
- );
485
- var inst = ReactDOMComponentTree.getInstanceFromNode(node.firstChild);
486
-
487
- ReactHostOperationHistoryHook._preventClearing = true;
488
- ReactDOM.render(<div>Bye.</div>, node);
489
-
490
- assertHistoryMatches([
491
- {
492
- instanceID: inst._debugID,
493
- type: 'replace text',
494
- payload: 'Bye.',
495
- },
496
- ]);
497
- });
498
-
499
- it('gets recorded during an update from children', () => {
500
- var node = document.createElement('div');
501
- ReactDOM.render(<div><span /><p /></div>, node);
502
- var inst = ReactDOMComponentTree.getInstanceFromNode(node.firstChild);
503
-
504
- ReactHostOperationHistoryHook._preventClearing = true;
505
- ReactDOM.render(<div>Bye.</div>, node);
506
-
507
- assertHistoryMatches([
508
- {
509
- instanceID: inst._debugID,
510
- type: 'remove child',
511
- payload: {fromIndex: 0},
512
- },
513
- {
514
- instanceID: inst._debugID,
515
- type: 'remove child',
516
- payload: {fromIndex: 1},
517
- },
518
- {
519
- instanceID: inst._debugID,
520
- type: 'replace text',
521
- payload: 'Bye.',
522
- },
523
- ]);
524
- });
525
-
526
- it('gets ignored if new text is equal', () => {
527
- var node = document.createElement('div');
528
- ReactDOM.render(<div>Hi.</div>, node);
529
-
530
- ReactHostOperationHistoryHook._preventClearing = true;
531
- ReactDOM.render(<div>Hi.</div>, node);
532
-
533
- assertHistoryMatches([]);
534
- });
535
- });
536
-
537
- describe('text node', () => {
538
- it('gets recorded during an update', () => {
539
- var node = document.createElement('div');
540
- ReactDOM.render(<div>{'Hi.'}{42}</div>, node);
541
- var inst1 = ReactDOMComponentTree.getInstanceFromNode(
542
- node.firstChild.childNodes[0],
543
- );
544
- var inst2 = ReactDOMComponentTree.getInstanceFromNode(
545
- node.firstChild.childNodes[3],
546
- );
547
-
548
- ReactHostOperationHistoryHook._preventClearing = true;
549
- ReactDOM.render(<div>{'Bye.'}{43}</div>, node);
550
-
551
- assertHistoryMatches([
552
- {
553
- instanceID: inst1._debugID,
554
- type: 'replace text',
555
- payload: 'Bye.',
556
- },
557
- {
558
- instanceID: inst2._debugID,
559
- type: 'replace text',
560
- payload: '43',
561
- },
562
- ]);
563
- });
564
-
565
- it('gets ignored if new text is equal', () => {
566
- var node = document.createElement('div');
567
- ReactDOM.render(<div>{'Hi.'}{42}</div>, node);
568
-
569
- ReactHostOperationHistoryHook._preventClearing = true;
570
- ReactDOM.render(<div>{'Hi.'}{42}</div>, node);
571
-
572
- assertHistoryMatches([]);
573
- });
574
- });
575
- });
576
-
577
- describe('replace with', () => {
578
- it('gets recorded when composite renders to a different type', () => {
579
- var element;
580
- function Foo() {
581
- return element;
582
- }
583
-
584
- var node = document.createElement('div');
585
- element = <div />;
586
- ReactDOM.render(<Foo />, node);
587
- var inst = ReactDOMComponentTree.getInstanceFromNode(node.firstChild);
588
-
589
- element = <span />;
590
-
591
- ReactHostOperationHistoryHook._preventClearing = true;
592
- ReactDOM.render(<Foo />, node);
593
-
594
- assertHistoryMatches([
595
- {
596
- instanceID: inst._debugID,
597
- type: 'replace with',
598
- payload: 'SPAN',
599
- },
600
- ]);
601
- });
602
-
603
- it('gets recorded when composite renders to null after a native', () => {
604
- var element;
605
- function Foo() {
606
- return element;
607
- }
608
-
609
- var node = document.createElement('div');
610
- element = <span />;
611
- ReactDOM.render(<Foo />, node);
612
-
613
- var inst = ReactDOMComponentTree.getInstanceFromNode(node.firstChild);
614
- element = null;
615
-
616
- ReactHostOperationHistoryHook._preventClearing = true;
617
- ReactDOM.render(<Foo />, node);
618
-
619
- assertHistoryMatches([
620
- {
621
- instanceID: inst._debugID,
622
- type: 'replace with',
623
- payload: '#comment',
624
- },
625
- ]);
626
- });
627
-
628
- it('gets ignored if the type has not changed', () => {
629
- var element;
630
- function Foo() {
631
- return element;
632
- }
633
-
634
- var node = document.createElement('div');
635
- element = <div />;
636
- ReactDOM.render(<Foo />, node);
637
-
638
- element = <div />;
639
-
640
- ReactHostOperationHistoryHook._preventClearing = true;
641
- ReactDOM.render(<Foo />, node);
642
-
643
- assertHistoryMatches([]);
644
- });
645
- });
646
-
647
- describe('replace children', () => {
648
- it('gets recorded during an update from text content', () => {
649
- var node = document.createElement('div');
650
- ReactDOM.render(<div>Hi.</div>, node);
651
- var inst = ReactDOMComponentTree.getInstanceFromNode(node.firstChild);
652
-
653
- ReactHostOperationHistoryHook._preventClearing = true;
654
- ReactDOM.render(<div dangerouslySetInnerHTML={{__html: 'Bye.'}} />, node);
655
-
656
- assertHistoryMatches([
657
- {
658
- instanceID: inst._debugID,
659
- type: 'replace children',
660
- payload: 'Bye.',
661
- },
662
- ]);
663
- });
664
-
665
- it('gets recorded during an update from html', () => {
666
- var node = document.createElement('div');
667
- ReactDOM.render(<div dangerouslySetInnerHTML={{__html: 'Hi.'}} />, node);
668
- var inst = ReactDOMComponentTree.getInstanceFromNode(node.firstChild);
669
-
670
- ReactHostOperationHistoryHook._preventClearing = true;
671
- ReactDOM.render(<div dangerouslySetInnerHTML={{__html: 'Bye.'}} />, node);
672
-
673
- assertHistoryMatches([
674
- {
675
- instanceID: inst._debugID,
676
- type: 'replace children',
677
- payload: 'Bye.',
678
- },
679
- ]);
680
- });
681
-
682
- it('gets recorded during an update from children', () => {
683
- var node = document.createElement('div');
684
- ReactDOM.render(<div><span /><p /></div>, node);
685
- var inst = ReactDOMComponentTree.getInstanceFromNode(node.firstChild);
686
-
687
- ReactHostOperationHistoryHook._preventClearing = true;
688
- ReactDOM.render(<div dangerouslySetInnerHTML={{__html: 'Hi.'}} />, node);
689
-
690
- assertHistoryMatches([
691
- {
692
- instanceID: inst._debugID,
693
- type: 'remove child',
694
- payload: {fromIndex: 0},
695
- },
696
- {
697
- instanceID: inst._debugID,
698
- type: 'remove child',
699
- payload: {fromIndex: 1},
700
- },
701
- {
702
- instanceID: inst._debugID,
703
- type: 'replace children',
704
- payload: 'Hi.',
705
- },
706
- ]);
707
- });
708
-
709
- it('gets ignored if new html is equal', () => {
710
- var node = document.createElement('div');
711
- ReactDOM.render(<div dangerouslySetInnerHTML={{__html: 'Hi.'}} />, node);
712
-
713
- ReactHostOperationHistoryHook._preventClearing = true;
714
- ReactDOM.render(<div dangerouslySetInnerHTML={{__html: 'Hi.'}} />, node);
715
-
716
- assertHistoryMatches([]);
717
- });
718
- });
719
-
720
- describe('insert child', () => {
721
- it('gets reported when a child is inserted', () => {
722
- var node = document.createElement('div');
723
- ReactDOM.render(<div><span /></div>, node);
724
- var inst = ReactDOMComponentTree.getInstanceFromNode(node.firstChild);
725
-
726
- ReactHostOperationHistoryHook._preventClearing = true;
727
- ReactDOM.render(<div><span /><p /></div>, node);
728
-
729
- assertHistoryMatches([
730
- {
731
- instanceID: inst._debugID,
732
- type: 'insert child',
733
- payload: {toIndex: 1, content: 'P'},
734
- },
735
- ]);
736
- });
737
- });
738
-
739
- describe('move child', () => {
740
- it('gets reported when a child is inserted', () => {
741
- var node = document.createElement('div');
742
- ReactDOM.render(<div><span key="a" /><p key="b" /></div>, node);
743
- var inst = ReactDOMComponentTree.getInstanceFromNode(node.firstChild);
744
-
745
- ReactHostOperationHistoryHook._preventClearing = true;
746
- ReactDOM.render(<div><p key="b" /><span key="a" /></div>, node);
747
-
748
- assertHistoryMatches([
749
- {
750
- instanceID: inst._debugID,
751
- type: 'move child',
752
- payload: {fromIndex: 0, toIndex: 1},
753
- },
754
- ]);
755
- });
756
- });
757
-
758
- describe('remove child', () => {
759
- it('gets reported when a child is removed', () => {
760
- var node = document.createElement('div');
761
- ReactDOM.render(<div><span key="a" /><p key="b" /></div>, node);
762
- var inst = ReactDOMComponentTree.getInstanceFromNode(node.firstChild);
763
-
764
- ReactHostOperationHistoryHook._preventClearing = true;
765
- ReactDOM.render(<div><span key="a" /></div>, node);
766
-
767
- assertHistoryMatches([
768
- {
769
- instanceID: inst._debugID,
770
- type: 'remove child',
771
- payload: {fromIndex: 1},
772
- },
773
- ]);
774
- });
775
- });
776
-});
src/renderers/__tests__/ReactPerf-test.js
deleted
-741
@@ -1,741 +0,0 @@
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
- * @emails react-core
8
- */
9
-
10
-'use strict';
11
-
12
-// ReactPerf is currently not supported on Fiber.
13
-// Use browser timeline integration instead.
14
-describe.skip('ReactPerf', () => {
15
- var React;
16
- var ReactDOM;
17
- var ReactPerf;
18
- var ReactTestUtils;
19
- var emptyFunction;
20
-
21
- var App;
22
- var Box;
23
- var Div;
24
- var LifeCycle;
25
-
26
- beforeEach(() => {
27
- var now = 0;
28
- jest.setMock('fbjs/lib/performanceNow', function() {
29
- return now++;
30
- });
31
-
32
- if (typeof console.table !== 'function') {
33
- console.table = () => {};
34
- console.table.isFake = true;
35
- }
36
-
37
- React = require('react');
38
- ReactDOM = require('react-dom');
39
- ReactPerf = require('ReactPerf');
40
- ReactTestUtils = require('react-dom/test-utils');
41
- emptyFunction = require('fbjs/lib/emptyFunction');
42
-
43
- App = class extends React.Component {
44
- render() {
45
- return <div><Box /><Box flip={this.props.flipSecond} /></div>;
46
- }
47
- };
48
-
49
- Box = class extends React.Component {
50
- render() {
51
- return <div key={!!this.props.flip}><input /></div>;
52
- }
53
- };
54
-
55
- // ReactPerf only measures composites, so we put everything in one.
56
- Div = class extends React.Component {
57
- render() {
58
- return <div {...this.props} />;
59
- }
60
- };
61
-
62
- LifeCycle = class extends React.Component {
63
- shouldComponentUpdate = emptyFunction.thatReturnsTrue;
64
- componentWillMount = emptyFunction;
65
- componentDidMount = emptyFunction;
66
- componentWillReceiveProps = emptyFunction;
67
- componentWillUpdate = emptyFunction;
68
- componentDidUpdate = emptyFunction;
69
- componentWillUnmount = emptyFunction;
70
- render = emptyFunction.thatReturnsNull;
71
- };
72
- });
73
-
74
- afterEach(() => {
75
- if (console.table.isFake) {
76
- delete console.table;
77
- }
78
- });
79
-
80
- function measure(fn) {
81
- ReactPerf.start();
82
- fn();
83
- ReactPerf.stop();
84
-
85
- // Make sure none of the methods crash.
86
- ReactPerf.getWasted();
87
- ReactPerf.getInclusive();
88
- ReactPerf.getExclusive();
89
- ReactPerf.getOperations();
90
-
91
- return ReactPerf.getLastMeasurements();
92
- }
93
-
94
- it('should count no-op update as waste', () => {
95
- var container = document.createElement('div');
96
- ReactDOM.render(<App />, container);
97
- var measurements = measure(() => {
98
- ReactDOM.render(<App />, container);
99
- });
100
-
101
- var summary = ReactPerf.getWasted(measurements);
102
- expect(summary).toEqual([
103
- {
104
- key: 'App',
105
- instanceCount: 1,
106
- inclusiveRenderDuration: 3,
107
- renderCount: 1,
108
- },
109
- {
110
- key: 'App > Box',
111
- instanceCount: 2,
112
- inclusiveRenderDuration: 2,
113
- renderCount: 2,
114
- },
115
- ]);
116
- });
117
-
118
- it('should count no-op update in child as waste', () => {
119
- var container = document.createElement('div');
120
- ReactDOM.render(<App />, container);
121
-
122
- // Here, we add a Box -- two of the <Box /> updates are wasted time (but the
123
- // addition of the third is not)
124
- var measurements = measure(() => {
125
- ReactDOM.render(<App flipSecond={true} />, container);
126
- });
127
-
128
- var summary = ReactPerf.getWasted(measurements);
129
- expect(summary).toEqual([
130
- {
131
- key: 'App > Box',
132
- instanceCount: 1,
133
- inclusiveRenderDuration: 1,
134
- renderCount: 1,
135
- },
136
- ]);
137
- });
138
-
139
- function expectNoWaste(fn) {
140
- var measurements = measure(fn);
141
- var summary = ReactPerf.getWasted(measurements);
142
- expect(summary).toEqual([]);
143
- }
144
-
145
- it('should not count initial render as waste', () => {
146
- expectNoWaste(() => {
147
- ReactTestUtils.renderIntoDocument(<App />);
148
- });
149
- });
150
-
151
- it('should not count unmount as waste', () => {
152
- var container = document.createElement('div');
153
- ReactDOM.render(<Div>hello</Div>, container);
154
- expectNoWaste(() => {
155
- ReactDOM.unmountComponentAtNode(container);
156
- });
157
- });
158
-
159
- it('should not count content update as waste', () => {
160
- var container = document.createElement('div');
161
- ReactDOM.render(<Div>hello</Div>, container);
162
- expectNoWaste(() => {
163
- ReactDOM.render(<Div>hello world</Div>, container);
164
- });
165
- });
166
-
167
- it('should not count child addition as waste', () => {
168
- var container = document.createElement('div');
169
- ReactDOM.render(<Div><span /></Div>, container);
170
- expectNoWaste(() => {
171
- ReactDOM.render(<Div><span /><span /></Div>, container);
172
- });
173
- });
174
-
175
- it('should not count child removal as waste', () => {
176
- var container = document.createElement('div');
177
- ReactDOM.render(<Div><span /><span /></Div>, container);
178
- expectNoWaste(() => {
179
- ReactDOM.render(<Div><span /></Div>, container);
180
- });
181
- });
182
-
183
- it('should not count property update as waste', () => {
184
- var container = document.createElement('div');
185
- ReactDOM.render(<Div className="yellow">hey</Div>, container);
186
- expectNoWaste(() => {
187
- ReactDOM.render(<Div className="blue">hey</Div>, container);
188
- });
189
- });
190
-
191
- it('should not count style update as waste', () => {
192
- var container = document.createElement('div');
193
- ReactDOM.render(<Div style={{color: 'yellow'}}>hey</Div>, container);
194
- expectNoWaste(() => {
195
- ReactDOM.render(<Div style={{color: 'blue'}}>hey</Div>, container);
196
- });
197
- });
198
-
199
- it('should not count property removal as waste', () => {
200
- var container = document.createElement('div');
201
- ReactDOM.render(<Div className="yellow">hey</Div>, container);
202
- expectNoWaste(() => {
203
- ReactDOM.render(<Div>hey</Div>, container);
204
- });
205
- });
206
-
207
- it('should not count raw HTML update as waste', () => {
208
- var container = document.createElement('div');
209
- ReactDOM.render(
210
- <Div dangerouslySetInnerHTML={{__html: 'me'}} />,
211
- container,
212
- );
213
- expectNoWaste(() => {
214
- ReactDOM.render(
215
- <Div dangerouslySetInnerHTML={{__html: 'you'}} />,
216
- container,
217
- );
218
- });
219
- });
220
-
221
- it('should not count child reordering as waste', () => {
222
- var container = document.createElement('div');
223
- ReactDOM.render(<Div><div key="A" /><div key="B" /></Div>, container);
224
- expectNoWaste(() => {
225
- ReactDOM.render(<Div><div key="B" /><div key="A" /></Div>, container);
226
- });
227
- });
228
-
229
- it('should not count text update as waste', () => {
230
- var container = document.createElement('div');
231
- ReactDOM.render(<Div>{'hello'}{'world'}</Div>, container);
232
- expectNoWaste(() => {
233
- ReactDOM.render(<Div>{'hello'}{'friend'}</Div>, container);
234
- });
235
- });
236
-
237
- it('should not count replacing null with a host as waste', () => {
238
- var element = null;
239
- function Foo() {
240
- return element;
241
- }
242
- var container = document.createElement('div');
243
- ReactDOM.render(<Foo />, container);
244
- expectNoWaste(() => {
245
- element = <div />;
246
- ReactDOM.render(<Foo />, container);
247
- });
248
- });
249
-
250
- it('should not count replacing a host with null as waste', () => {
251
- var element = <div />;
252
- function Foo() {
253
- return element;
254
- }
255
- var container = document.createElement('div');
256
- ReactDOM.render(<Foo />, container);
257
- expectNoWaste(() => {
258
- element = null;
259
- ReactDOM.render(<Foo />, container);
260
- });
261
- });
262
-
263
- it('should include stats for components unmounted during measurement', () => {
264
- var container = document.createElement('div');
265
- var measurements = measure(() => {
266
- ReactDOM.render(<Div><Div key="a" /></Div>, container);
267
- ReactDOM.render(<Div><Div key="b" /></Div>, container);
268
- });
269
- expect(ReactPerf.getExclusive(measurements)).toEqual([
270
- {
271
- key: 'Div',
272
- instanceCount: 3,
273
- counts: {ctor: 3, render: 4},
274
- durations: {ctor: 3, render: 4},
275
- totalDuration: 7,
276
- },
277
- ]);
278
- });
279
-
280
- it('should include lifecycle methods in measurements', () => {
281
- var container = document.createElement('div');
282
- var measurements = measure(() => {
283
- var instance = ReactDOM.render(<LifeCycle />, container);
284
- ReactDOM.render(<LifeCycle />, container);
285
- instance.setState({});
286
- ReactDOM.unmountComponentAtNode(container);
287
- });
288
- expect(ReactPerf.getExclusive(measurements)).toEqual([
289
- {
290
- key: 'LifeCycle',
291
- instanceCount: 1,
292
- totalDuration: 14,
293
- counts: {
294
- ctor: 1,
295
- shouldComponentUpdate: 2,
296
- componentWillMount: 1,
297
- componentDidMount: 1,
298
- componentWillReceiveProps: 1,
299
- componentWillUpdate: 2,
300
- componentDidUpdate: 2,
301
- componentWillUnmount: 1,
302
- render: 3,
303
- },
304
- durations: {
305
- ctor: 1,
306
- shouldComponentUpdate: 2,
307
- componentWillMount: 1,
308
- componentDidMount: 1,
309
- componentWillReceiveProps: 1,
310
- componentWillUpdate: 2,
311
- componentDidUpdate: 2,
312
- componentWillUnmount: 1,
313
- render: 3,
314
- },
315
- },
316
- ]);
317
- });
318
-
319
- it('should include render time of functional components', () => {
320
- function Foo() {
321
- return null;
322
- }
323
-
324
- var container = document.createElement('div');
325
- var measurements = measure(() => {
326
- ReactDOM.render(<Foo />, container);
327
- });
328
- expect(ReactPerf.getExclusive(measurements)).toEqual([
329
- {
330
- key: 'Foo',
331
- instanceCount: 1,
332
- totalDuration: 1,
333
- counts: {
334
- render: 1,
335
- },
336
- durations: {
337
- render: 1,
338
- },
339
- },
340
- ]);
341
- });
342
-
343
- it('should not count time in a portal towards lifecycle method', () => {
344
- function Foo() {
345
- return null;
346
- }
347
-
348
- var portalContainer = document.createElement('div');
349
- class Portal extends React.Component {
350
- componentDidMount() {
351
- ReactDOM.render(<Foo />, portalContainer);
352
- }
353
- render() {
354
- return null;
355
- }
356
- }
357
-
358
- var container = document.createElement('div');
359
- var measurements = measure(() => {
360
- ReactDOM.render(<Portal />, container);
361
- });
362
-
363
- expect(ReactPerf.getExclusive(measurements)).toEqual([
364
- {
365
- key: 'Portal',
366
- instanceCount: 1,
367
- totalDuration: 6,
368
- counts: {
369
- ctor: 1,
370
- componentDidMount: 1,
371
- render: 1,
372
- },
373
- durations: {
374
- ctor: 1,
375
- // We want to exclude nested imperative ReactDOM.render() from lifecycle hook's own time.
376
- // Otherwise it would artificially float to the top even though its exclusive time is small.
377
- // This is how we get 4 as a number with the performanceNow() mock:
378
- // - we capture the time we enter componentDidMount (n = 0)
379
- // - we capture the time when we enter a nested flush (n = 1)
380
- // - in the nested flush, we call it twice: before and after <Foo /> rendering. (n = 3)
381
- // - we capture the time when we exit a nested flush (n = 4)
382
- // - we capture the time we exit componentDidMount (n = 5)
383
- // Time spent in componentDidMount = (5 - 0 - (4 - 3)) = 4.
384
- componentDidMount: 4,
385
- render: 1,
386
- },
387
- },
388
- {
389
- key: 'Foo',
390
- instanceCount: 1,
391
- totalDuration: 1,
392
- counts: {
393
- render: 1,
394
- },
395
- durations: {
396
- render: 1,
397
- },
398
- },
399
- ]);
400
- });
401
-
402
- it('warns once when using getMeasurementsSummaryMap', () => {
403
- var measurements = measure(() => {});
404
- spyOn(console, 'warn');
405
- ReactPerf.getMeasurementsSummaryMap(measurements);
406
- expectDev(console.warn.calls.count()).toBe(1);
407
- expectDev(console.warn.calls.argsFor(0)[0]).toContain(
408
- '`ReactPerf.getMeasurementsSummaryMap(...)` is deprecated. Use ' +
409
- '`ReactPerf.getWasted(...)` instead.',
410
- );
411
-
412
- ReactPerf.getMeasurementsSummaryMap(measurements);
413
- expectDev(console.warn.calls.count()).toBe(1);
414
- });
415
-
416
- it('warns once when using printDOM', () => {
417
- var measurements = measure(() => {});
418
- spyOn(console, 'warn');
419
- ReactPerf.printDOM(measurements);
420
- expectDev(console.warn.calls.count()).toBe(1);
421
- expectDev(console.warn.calls.argsFor(0)[0]).toContain(
422
- '`ReactPerf.printDOM(...)` is deprecated. Use ' +
423
- '`ReactPerf.printOperations(...)` instead.',
424
- );
425
-
426
- ReactPerf.printDOM(measurements);
427
- expectDev(console.warn.calls.count()).toBe(1);
428
- });
429
-
430
- it('returns isRunning state', () => {
431
- expect(ReactPerf.isRunning()).toBe(false);
432
-
433
- ReactPerf.start();
434
- expect(ReactPerf.isRunning()).toBe(true);
435
-
436
- ReactPerf.stop();
437
- expect(ReactPerf.isRunning()).toBe(false);
438
- });
439
-
440
- it('start has no effect when already running', () => {
441
- expect(ReactPerf.isRunning()).toBe(false);
442
-
443
- ReactPerf.start();
444
- expect(ReactPerf.isRunning()).toBe(true);
445
-
446
- ReactPerf.start();
447
- expect(ReactPerf.isRunning()).toBe(true);
448
-
449
- ReactPerf.stop();
450
- expect(ReactPerf.isRunning()).toBe(false);
451
- });
452
-
453
- it('stop has no effect when already stopped', () => {
454
- expect(ReactPerf.isRunning()).toBe(false);
455
-
456
- ReactPerf.stop();
457
- expect(ReactPerf.isRunning()).toBe(false);
458
-
459
- ReactPerf.stop();
460
- expect(ReactPerf.isRunning()).toBe(false);
461
- });
462
-
463
- it('should print console error only once', () => {
464
- __DEV__ = false;
465
-
466
- spyOn(console, 'error');
467
-
468
- expect(ReactPerf.getLastMeasurements()).toEqual([]);
469
- expect(ReactPerf.getExclusive()).toEqual([]);
470
- expect(ReactPerf.getInclusive()).toEqual([]);
471
- expect(ReactPerf.getWasted()).toEqual([]);
472
- expect(ReactPerf.getOperations()).toEqual([]);
473
- expect(ReactPerf.printExclusive()).toEqual(undefined);
474
- expect(ReactPerf.printInclusive()).toEqual(undefined);
475
- expect(ReactPerf.printWasted()).toEqual(undefined);
476
- expect(ReactPerf.printOperations()).toEqual(undefined);
477
- expect(ReactPerf.start()).toBe(undefined);
478
- expect(ReactPerf.stop()).toBe(undefined);
479
- expect(ReactPerf.isRunning()).toBe(false);
480
-
481
- expectDev(console.error.calls.count()).toBe(1);
482
-
483
- __DEV__ = true;
484
- });
485
-
486
- it('should work when measurement starts during reconciliation', () => {
487
- // https://github.com/facebook/react/issues/6949#issuecomment-230371009
488
- class Measurer extends React.Component {
489
- componentWillMount() {
490
- ReactPerf.start();
491
- }
492
-
493
- componentDidMount() {
494
- ReactPerf.stop();
495
- }
496
-
497
- componentWillUpdate() {
498
- ReactPerf.start();
499
- }
500
-
501
- componentDidUpdate() {
502
- ReactPerf.stop();
503
- }
504
-
505
- render() {
506
- // Force reconciliation despite constant element
507
- return React.cloneElement(this.props.children);
508
- }
509
- }
510
-
511
- var container = document.createElement('div');
512
- ReactDOM.render(<Measurer><App /></Measurer>, container);
513
- expect(ReactPerf.getWasted()).toEqual([]);
514
-
515
- ReactDOM.render(<Measurer><App /></Measurer>, container);
516
- expect(ReactPerf.getWasted()).toEqual([
517
- {
518
- key: 'Measurer',
519
- instanceCount: 1,
520
- inclusiveRenderDuration: 4,
521
- renderCount: 1,
522
- },
523
- {
524
- key: 'App',
525
- instanceCount: 1,
526
- inclusiveRenderDuration: 3,
527
- renderCount: 1,
528
- },
529
- {
530
- key: 'App > Box',
531
- instanceCount: 2,
532
- inclusiveRenderDuration: 2,
533
- renderCount: 2,
534
- },
535
- ]);
536
- });
537
-
538
- it('should not print errant warnings if render() throws', () => {
539
- var container = document.createElement('div');
540
- var thrownErr = new Error('Muhaha!');
541
-
542
- class Evil extends React.Component {
543
- render() {
544
- throw thrownErr;
545
- }
546
- }
547
-
548
- ReactPerf.start();
549
- try {
550
- ReactDOM.render(
551
- <div>
552
- <LifeCycle />
553
- <Evil />
554
- </div>,
555
- container,
556
- );
557
- } catch (err) {
558
- if (err !== thrownErr) {
559
- throw err;
560
- }
561
- }
562
- ReactPerf.stop();
563
- });
564
-
565
- it('should not print errant warnings if componentWillMount() throws', () => {
566
- var container = document.createElement('div');
567
- var thrownErr = new Error('Muhaha!');
568
-
569
- class Evil extends React.Component {
570
- componentWillMount() {
571
- throw thrownErr;
572
- }
573
- render() {
574
- return <div />;
575
- }
576
- }
577
-
578
- ReactPerf.start();
579
- try {
580
- ReactDOM.render(
581
- <div>
582
- <LifeCycle />
583
- <Evil />
584
- </div>,
585
- container,
586
- );
587
- } catch (err) {
588
- if (err !== thrownErr) {
589
- throw err;
590
- }
591
- }
592
- ReactPerf.stop();
593
- });
594
-
595
- it('should not print errant warnings if componentDidMount() throws', () => {
596
- var container = document.createElement('div');
597
- var thrownErr = new Error('Muhaha!');
598
-
599
- class Evil extends React.Component {
600
- componentDidMount() {
601
- throw thrownErr;
602
- }
603
- render() {
604
- return <div />;
605
- }
606
- }
607
-
608
- ReactPerf.start();
609
- try {
610
- ReactDOM.render(
611
- <div>
612
- <LifeCycle />
613
- <Evil />
614
- </div>,
615
- container,
616
- );
617
- } catch (err) {
618
- if (err !== thrownErr) {
619
- throw err;
620
- }
621
- }
622
- ReactPerf.stop();
623
- });
624
-
625
- it('should not print errant warnings if portal throws in render()', () => {
626
- var container = document.createElement('div');
627
- var thrownErr = new Error('Muhaha!');
628
-
629
- class Evil extends React.Component {
630
- render() {
631
- throw thrownErr;
632
- }
633
- }
634
- class EvilPortal extends React.Component {
635
- componentDidMount() {
636
- var portalContainer = document.createElement('div');
637
- ReactDOM.render(<Evil />, portalContainer);
638
- }
639
- render() {
640
- return <div />;
641
- }
642
- }
643
-
644
- ReactPerf.start();
645
- try {
646
- ReactDOM.render(
647
- <div>
648
- <LifeCycle />
649
- <EvilPortal />
650
- </div>,
651
- container,
652
- );
653
- } catch (err) {
654
- if (err !== thrownErr) {
655
- throw err;
656
- }
657
- }
658
- ReactDOM.unmountComponentAtNode(container);
659
- ReactPerf.stop();
660
- });
661
-
662
- it('should not print errant warnings if portal throws in componentWillMount()', () => {
663
- var container = document.createElement('div');
664
- var thrownErr = new Error('Muhaha!');
665
-
666
- class Evil extends React.Component {
667
- componentWillMount() {
668
- throw thrownErr;
669
- }
670
- render() {
671
- return <div />;
672
- }
673
- }
674
- class EvilPortal extends React.Component {
675
- componentWillMount() {
676
- var portalContainer = document.createElement('div');
677
- ReactDOM.render(<Evil />, portalContainer);
678
- }
679
- render() {
680
- return <div />;
681
- }
682
- }
683
-
684
- ReactPerf.start();
685
- try {
686
- ReactDOM.render(
687
- <div>
688
- <LifeCycle />
689
- <EvilPortal />
690
- </div>,
691
- container,
692
- );
693
- } catch (err) {
694
- if (err !== thrownErr) {
695
- throw err;
696
- }
697
- }
698
- ReactDOM.unmountComponentAtNode(container);
699
- ReactPerf.stop();
700
- });
701
-
702
- it('should not print errant warnings if portal throws in componentDidMount()', () => {
703
- var container = document.createElement('div');
704
- var thrownErr = new Error('Muhaha!');
705
-
706
- class Evil extends React.Component {
707
- componentDidMount() {
708
- throw thrownErr;
709
- }
710
- render() {
711
- return <div />;
712
- }
713
- }
714
- class EvilPortal extends React.Component {
715
- componentDidMount() {
716
- var portalContainer = document.createElement('div');
717
- ReactDOM.render(<Evil />, portalContainer);
718
- }
719
- render() {
720
- return <div />;
721
- }
722
- }
723
-
724
- ReactPerf.start();
725
- try {
726
- ReactDOM.render(
727
- <div>
728
- <LifeCycle />
729
- <EvilPortal />
730
- </div>,
731
- container,
732
- );
733
- } catch (err) {
734
- if (err !== thrownErr) {
735
- throw err;
736
- }
737
- }
738
- ReactDOM.unmountComponentAtNode(container);
739
- ReactPerf.stop();
740
- });
741
-});
src/renderers/dom/shared/DOMPropertyOperations.js
-27
@@ -10,8 +10,6 @@
10
'use strict';
11
12
var DOMProperty = require('DOMProperty');
13
-var ReactDOMComponentTree = require('ReactDOMComponentTree');
14
-var ReactInstrumentation = require('ReactInstrumentation');
13
14
if (__DEV__) {
15
var warning = require('fbjs/lib/warning');
@@ -201,11 +199,6 @@ var DOMPropertyOperations = {
199
if (__DEV__) {
200
var payload = {};
201
payload[name] = value;
204
- ReactInstrumentation.debugTool.onHostOperation({
205
- instanceID: ReactDOMComponentTree.getInstanceFromNode(node)._debugID,
206
- type: 'update attribute',
207
- payload: payload,
208
- });
202
}
203
},
204
@@ -222,11 +215,6 @@ var DOMPropertyOperations = {
215
if (__DEV__) {
216
var payload = {};
217
payload[name] = value;
225
- ReactInstrumentation.debugTool.onHostOperation({
226
- instanceID: ReactDOMComponentTree.getInstanceFromNode(node)._debugID,
227
- type: 'update attribute',
228
- payload: payload,
229
- });
218
}
219
},
220
@@ -238,13 +226,6 @@ var DOMPropertyOperations = {
226
*/
227
deleteValueForAttribute: function(node, name) {
228
node.removeAttribute(name);
241
- if (__DEV__) {
242
- ReactInstrumentation.debugTool.onHostOperation({
243
- instanceID: ReactDOMComponentTree.getInstanceFromNode(node)._debugID,
244
- type: 'remove attribute',
245
- payload: name,
246
- });
247
- }
229
},
230
231
/**
@@ -272,14 +253,6 @@ var DOMPropertyOperations = {
253
} else {
254
node.removeAttribute(name);
255
}
275
-
276
- if (__DEV__) {
277
- ReactInstrumentation.debugTool.onHostOperation({
278
- instanceID: ReactDOMComponentTree.getInstanceFromNode(node)._debugID,
279
- type: 'remove attribute',
280
- payload: name,
281
- });
282
- }
256
},
257
};
258
src/renderers/dom/shared/hooks/ReactDOMInvalidARIAHook.js
+14
-36
@@ -22,27 +22,17 @@ var hasOwnProperty = Object.prototype.hasOwnProperty;
22
23
if (__DEV__) {
24
var warning = require('fbjs/lib/warning');
25
- var {
26
- ReactComponentTreeHook,
27
- ReactDebugCurrentFrame,
28
- } = require('ReactGlobalSharedState');
29
- var {getStackAddendumByID} = ReactComponentTreeHook;
25
+ var {ReactDebugCurrentFrame} = require('ReactGlobalSharedState');
26
27
var validAriaProperties = require('./validAriaProperties');
28
}
29
34
-function getStackAddendum(debugID) {
35
- if (debugID != null) {
36
- // This can only happen on Stack
37
- return getStackAddendumByID(debugID);
38
- } else {
39
- // This can only happen on Fiber / Server
40
- var stack = ReactDebugCurrentFrame.getStackAddendum();
41
- return stack != null ? stack : '';
42
- }
30
+function getStackAddendum() {
31
+ var stack = ReactDebugCurrentFrame.getStackAddendum();
32
+ return stack != null ? stack : '';
33
}
34
45
-function validateProperty(tagName, name, debugID) {
35
+function validateProperty(tagName, name) {
36
if (hasOwnProperty.call(warnedProperties, name) && warnedProperties[name]) {
37
return true;
38
}
@@ -60,7 +50,7 @@ function validateProperty(tagName, name, debugID) {
50
false,
51
'Invalid ARIA attribute `%s`. ARIA attributes follow the pattern aria-* and must be lowercase.%s',
52
name,
63
- getStackAddendum(debugID),
53
+ getStackAddendum(),
54
);
55
warnedProperties[name] = true;
56
return true;
@@ -72,7 +62,7 @@ function validateProperty(tagName, name, debugID) {
62
'Invalid ARIA attribute `%s`. Did you mean `%s`?%s',
63
name,
64
correctName,
75
- getStackAddendum(debugID),
65
+ getStackAddendum(),
66
);
67
warnedProperties[name] = true;
68
return true;
@@ -98,7 +88,7 @@ function validateProperty(tagName, name, debugID) {
88
'Unknown ARIA attribute `%s`. Did you mean `%s`?%s',
89
name,
90
standardName,
101
- getStackAddendum(debugID),
91
+ getStackAddendum(),
92
);
93
warnedProperties[name] = true;
94
return true;
@@ -108,11 +98,11 @@ function validateProperty(tagName, name, debugID) {
98
return true;
99
}
100
111
-function warnInvalidARIAProps(type, props, debugID) {
101
+function warnInvalidARIAProps(type, props) {
102
const invalidProps = [];
103
104
for (var key in props) {
115
- var isValid = validateProperty(type, key, debugID);
105
+ var isValid = validateProperty(type, key);
106
if (!isValid) {
107
invalidProps.push(key);
108
}
@@ -129,7 +119,7 @@ function warnInvalidARIAProps(type, props, debugID) {
119
'For details, see https://fb.me/invalid-aria-prop%s',
120
unknownPropString,
121
type,
132
- getStackAddendum(debugID),
122
+ getStackAddendum(),
123
);
124
} else if (invalidProps.length > 1) {
125
warning(
@@ -138,32 +128,20 @@ function warnInvalidARIAProps(type, props, debugID) {
128
'For details, see https://fb.me/invalid-aria-prop%s',
129
unknownPropString,
130
type,
141
- getStackAddendum(debugID),
131
+ getStackAddendum(),
132
);
133
}
134
}
135
146
-function validateProperties(type, props, debugID /* Stack only */) {
136
+function validateProperties(type, props) {
137
if (isCustomComponent(type, props)) {
138
return;
139
}
150
- warnInvalidARIAProps(type, props, debugID);
140
+ warnInvalidARIAProps(type, props);
141
}
142
143
var ReactDOMInvalidARIAHook = {
154
- // Fiber
144
validateProperties,
156
- // Stack
157
- onBeforeMountComponent(debugID, element) {
158
- if (__DEV__ && element != null && typeof element.type === 'string') {
159
- validateProperties(element.type, element.props, debugID);
160
- }
161
- },
162
- onBeforeUpdateComponent(debugID, element) {
163
- if (__DEV__ && element != null && typeof element.type === 'string') {
164
- validateProperties(element.type, element.props, debugID);
165
- }
166
- },
145
};
146
147
module.exports = ReactDOMInvalidARIAHook;
src/renderers/dom/shared/hooks/ReactDOMNullInputValuePropHook.js
+6
-28
@@ -11,27 +11,17 @@
11
12
if (__DEV__) {
13
var warning = require('fbjs/lib/warning');
14
- var {
15
- ReactComponentTreeHook,
16
- ReactDebugCurrentFrame,
17
- } = require('ReactGlobalSharedState');
18
- var {getStackAddendumByID} = ReactComponentTreeHook;
14
+ var {ReactDebugCurrentFrame} = require('ReactGlobalSharedState');
15
}
16
17
var didWarnValueNull = false;
18
23
-function getStackAddendum(debugID) {
24
- if (debugID != null) {
25
- // This can only happen on Stack
26
- return getStackAddendumByID(debugID);
27
- } else {
28
- // This can only happen on Fiber / Server
29
- var stack = ReactDebugCurrentFrame.getStackAddendum();
30
- return stack != null ? stack : '';
31
- }
19
+function getStackAddendum() {
20
+ var stack = ReactDebugCurrentFrame.getStackAddendum();
21
+ return stack != null ? stack : '';
22
}
23
34
-function validateProperties(type, props, debugID /* Stack only */) {
24
+function validateProperties(type, props) {
25
if (type !== 'input' && type !== 'textarea' && type !== 'select') {
26
return;
27
}
@@ -42,7 +32,7 @@ function validateProperties(type, props, debugID /* Stack only */) {
32
'Consider using the empty string to clear the component or `undefined` ' +
33
'for uncontrolled components.%s',
34
type,
45
- getStackAddendum(debugID),
35
+ getStackAddendum(),
36
);
37
38
didWarnValueNull = true;
@@ -50,19 +40,7 @@ function validateProperties(type, props, debugID /* Stack only */) {
40
}
41
42
var ReactDOMNullInputValuePropHook = {
53
- // Fiber
43
validateProperties,
55
- // Stack
56
- onBeforeMountComponent(debugID, element) {
57
- if (__DEV__ && element != null && typeof element.type === 'string') {
58
- validateProperties(element.type, element.props, debugID);
59
- }
60
- },
61
- onBeforeUpdateComponent(debugID, element) {
62
- if (__DEV__ && element != null && typeof element.type === 'string') {
63
- validateProperties(element.type, element.props, debugID);
64
- }
65
- },
44
};
45
46
module.exports = ReactDOMNullInputValuePropHook;
src/renderers/dom/shared/hooks/ReactDOMUnknownPropertyHook.js
+18
-40
@@ -15,22 +15,12 @@ var isCustomComponent = require('isCustomComponent');
15
16
if (__DEV__) {
17
var warning = require('fbjs/lib/warning');
18
- var {
19
- ReactComponentTreeHook,
20
- ReactDebugCurrentFrame,
21
- } = require('ReactGlobalSharedState');
22
- var {getStackAddendumByID} = ReactComponentTreeHook;
18
+ var {ReactDebugCurrentFrame} = require('ReactGlobalSharedState');
19
}
20
25
-function getStackAddendum(debugID) {
26
- if (debugID != null) {
27
- // This can only happen on Stack
28
- return getStackAddendumByID(debugID);
29
- } else {
30
- // This can only happen on Fiber / Server
31
- var stack = ReactDebugCurrentFrame.getStackAddendum();
32
- return stack != null ? stack : '';
33
- }
21
+function getStackAddendum() {
22
+ var stack = ReactDebugCurrentFrame.getStackAddendum();
23
+ return stack != null ? stack : '';
24
}
25
26
if (__DEV__) {
@@ -43,7 +33,7 @@ if (__DEV__) {
33
);
34
var possibleStandardNames = require('possibleStandardNames');
35
46
- var validateProperty = function(tagName, name, value, debugID) {
36
+ var validateProperty = function(tagName, name, value) {
37
if (hasOwnProperty.call(warnedProperties, name) && warnedProperties[name]) {
38
return true;
39
}
@@ -74,7 +64,7 @@ if (__DEV__) {
64
'Invalid event handler property `%s`. Did you mean `%s`?%s',
65
name,
66
registrationName,
77
- getStackAddendum(debugID),
67
+ getStackAddendum(),
68
);
69
warnedProperties[name] = true;
70
return true;
@@ -85,7 +75,7 @@ if (__DEV__) {
75
false,
76
'Unknown event handler property `%s`. It will be ignored.%s',
77
name,
88
- getStackAddendum(debugID),
78
+ getStackAddendum(),
79
);
80
warnedProperties[name] = true;
81
return true;
@@ -138,7 +128,7 @@ if (__DEV__) {
128
'Received a `%s` for string attribute `is`. If this is expected, cast ' +
129
'the value to a string.%s',
130
typeof value,
141
- getStackAddendum(debugID),
131
+ getStackAddendum(),
132
);
133
warnedProperties[name] = true;
134
return true;
@@ -150,7 +140,7 @@ if (__DEV__) {
140
'Received NaN for numeric attribute `%s`. If this is expected, cast ' +
141
'the value to a string.%s',
142
name,
153
- getStackAddendum(debugID),
143
+ getStackAddendum(),
144
);
145
warnedProperties[name] = true;
146
return true;
@@ -167,7 +157,7 @@ if (__DEV__) {
157
'Invalid DOM property `%s`. Did you mean `%s`?%s',
158
name,
159
standardName,
170
- getStackAddendum(debugID),
160
+ getStackAddendum(),
161
);
162
warnedProperties[name] = true;
163
return true;
@@ -184,7 +174,7 @@ if (__DEV__) {
174
'it from the DOM element.%s',
175
name,
176
lowerCasedName,
187
- getStackAddendum(debugID),
177
+ getStackAddendum(),
178
);
179
warnedProperties[name] = true;
180
return true;
@@ -197,7 +187,7 @@ if (__DEV__) {
187
'the value to a string.%s',
188
value,
189
name,
200
- getStackAddendum(debugID),
190
+ getStackAddendum(),
191
);
192
warnedProperties[name] = true;
193
return true;
@@ -219,10 +209,10 @@ if (__DEV__) {
209
};
210
}
211
222
-var warnUnknownProperties = function(type, props, debugID) {
212
+var warnUnknownProperties = function(type, props) {
213
var unknownProps = [];
214
for (var key in props) {
225
- var isValid = validateProperty(type, key, props[key], debugID);
215
+ var isValid = validateProperty(type, key, props[key]);
216
if (!isValid) {
217
unknownProps.push(key);
218
}
@@ -237,7 +227,7 @@ var warnUnknownProperties = function(type, props, debugID) {
227
'For details, see https://fb.me/react-attribute-behavior%s',
228
unknownPropString,
229
type,
240
- getStackAddendum(debugID),
230
+ getStackAddendum(),
231
);
232
} else if (unknownProps.length > 1) {
233
warning(
@@ -247,32 +237,20 @@ var warnUnknownProperties = function(type, props, debugID) {
237
'For details, see https://fb.me/react-attribute-behavior%s',
238
unknownPropString,
239
type,
250
- getStackAddendum(debugID),
240
+ getStackAddendum(),
241
);
242
}
243
};
244
255
-function validateProperties(type, props, debugID /* Stack only */) {
245
+function validateProperties(type, props) {
246
if (isCustomComponent(type, props)) {
247
return;
248
}
259
- warnUnknownProperties(type, props, debugID);
249
+ warnUnknownProperties(type, props);
250
}
251
252
var ReactDOMUnknownPropertyHook = {
263
- // Fiber
253
validateProperties,
265
- // Stack
266
- onBeforeMountComponent(debugID, element) {
267
- if (__DEV__ && element != null && typeof element.type === 'string') {
268
- validateProperties(element.type, element.props, debugID);
269
- }
270
- },
271
- onBeforeUpdateComponent(debugID, element) {
272
- if (__DEV__ && element != null && typeof element.type === 'string') {
273
- validateProperties(element.type, element.props, debugID);
274
- }
275
- },
254
};
255
256
module.exports = ReactDOMUnknownPropertyHook;
src/renderers/native/ReactNativeFiberEntry.js
+13
-2
@@ -109,8 +109,19 @@ if (__DEV__) {
109
Object.assign(
110
ReactNativeFiber.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
111
{
112
- ReactDebugTool: require('ReactDebugTool'), // RCTRenderingPerf, Systrace
113
- ReactPerf: require('ReactPerf'), // ReactPerfStallHandler, RCTRenderingPerf
112
+ // TODO: none of these work since Fiber. Remove these dependencies.
113
+ // Used by RCTRenderingPerf, Systrace:
114
+ ReactDebugTool: {
115
+ addHook() {},
116
+ removeHook() {},
117
+ },
118
+ // Used by ReactPerfStallHandler, RCTRenderingPerf:
119
+ ReactPerf: {
120
+ start() {},
121
+ stop() {},
122
+ printInclusive() {},
123
+ printWasted() {},
124
+ },
125
},
126
);
127
}
src/renderers/shared/ReactDebugTool.js
deleted
-439
@@ -1,439 +0,0 @@
1
-/**
2
- * Copyright (c) 2016-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
- * @providesModule ReactDebugTool
8
- * @flow
9
- */
10
-
11
-'use strict';
12
-
13
-var ReactInvalidSetStateWarningHook = require('ReactInvalidSetStateWarningHook');
14
-var ReactHostOperationHistoryHook = require('ReactHostOperationHistoryHook');
15
-var ExecutionEnvironment = require('fbjs/lib/ExecutionEnvironment');
16
-var {ReactComponentTreeHook} = require('ReactGlobalSharedState');
17
-
18
-var performanceNow = require('fbjs/lib/performanceNow');
19
-
20
-if (__DEV__) {
21
- var warning = require('fbjs/lib/warning');
22
-}
23
-
24
-import type {ReactElement} from 'ReactElementType';
25
-import type {DebugID} from 'ReactInstanceType';
26
-import type {Operation} from 'ReactHostOperationHistoryHook';
27
-
28
-type Hook = any;
29
-
30
-type TimerType =
31
- | 'ctor'
32
- | 'render'
33
- | 'componentWillMount'
34
- | 'componentWillUnmount'
35
- | 'componentWillReceiveProps'
36
- | 'shouldComponentUpdate'
37
- | 'componentWillUpdate'
38
- | 'componentDidUpdate'
39
- | 'componentDidMount';
40
-
41
-type Measurement = {
42
- timerType: TimerType,
43
- instanceID: DebugID,
44
- duration: number,
45
-};
46
-
47
-type TreeSnapshot = {
48
- [key: DebugID]: {
49
- displayName: string,
50
- text: string,
51
- updateCount: number,
52
- childIDs: Array<DebugID>,
53
- ownerID: DebugID,
54
- parentID: DebugID,
55
- },
56
-};
57
-
58
-type HistoryItem = {
59
- duration: number,
60
- measurements: Array<Measurement>,
61
- operations: Array<Operation>,
62
- treeSnapshot: TreeSnapshot,
63
-};
64
-
65
-export type FlushHistory = Array<HistoryItem>;
66
-
67
-// Trust the developer to only use this with a __DEV__ check
68
-var ReactDebugTool = ((null: any): typeof ReactDebugTool);
69
-
70
-if (__DEV__) {
71
- var hooks = [];
72
- var didHookThrowForEvent = {};
73
-
74
- const callHook = function(event, fn, context, arg1, arg2, arg3, arg4, arg5) {
75
- try {
76
- fn.call(context, arg1, arg2, arg3, arg4, arg5);
77
- } catch (e) {
78
- warning(
79
- didHookThrowForEvent[event],
80
- 'Exception thrown by hook while handling %s: %s',
81
- event,
82
- e + '\n' + e.stack,
83
- );
84
- didHookThrowForEvent[event] = true;
85
- }
86
- };
87
-
88
- const emitEvent = function(event, arg1, arg2, arg3, arg4, arg5) {
89
- for (var i = 0; i < hooks.length; i++) {
90
- var hook = hooks[i];
91
- var fn = hook[event];
92
- if (fn) {
93
- callHook(event, fn, hook, arg1, arg2, arg3, arg4, arg5);
94
- }
95
- }
96
- };
97
-
98
- var isProfiling = false;
99
- var flushHistory = [];
100
- var lifeCycleTimerStack = [];
101
- var currentFlushNesting = 0;
102
- var currentFlushMeasurements = [];
103
- var currentFlushStartTime = 0;
104
- var currentTimerDebugID = null;
105
- var currentTimerStartTime = 0;
106
- var currentTimerNestedFlushDuration = 0;
107
- var currentTimerType = null;
108
-
109
- var lifeCycleTimerHasWarned = false;
110
-
111
- const clearHistory = function() {
112
- ReactComponentTreeHook.purgeUnmountedComponents();
113
- ReactHostOperationHistoryHook.clearHistory();
114
- };
115
-
116
- const getTreeSnapshot = function(registeredIDs) {
117
- return registeredIDs.reduce((tree, id) => {
118
- var ownerID = ReactComponentTreeHook.getOwnerID(id);
119
- var parentID = ReactComponentTreeHook.getParentID(id);
120
- tree[id] = {
121
- displayName: ReactComponentTreeHook.getDisplayName(id),
122
- text: ReactComponentTreeHook.getText(id),
123
- updateCount: ReactComponentTreeHook.getUpdateCount(id),
124
- childIDs: ReactComponentTreeHook.getChildIDs(id),
125
- // Text nodes don't have owners but this is close enough.
126
- ownerID: ownerID ||
127
- (parentID && ReactComponentTreeHook.getOwnerID(parentID)) ||
128
- 0,
129
- parentID,
130
- };
131
- return tree;
132
- }, {});
133
- };
134
-
135
- const resetMeasurements = function() {
136
- var previousStartTime = currentFlushStartTime;
137
- var previousMeasurements = currentFlushMeasurements;
138
- var previousOperations = ReactHostOperationHistoryHook.getHistory();
139
-
140
- if (currentFlushNesting === 0) {
141
- currentFlushStartTime = 0;
142
- currentFlushMeasurements = [];
143
- clearHistory();
144
- return;
145
- }
146
-
147
- if (previousMeasurements.length || previousOperations.length) {
148
- var registeredIDs = ReactComponentTreeHook.getRegisteredIDs();
149
- flushHistory.push({
150
- duration: performanceNow() - previousStartTime,
151
- measurements: previousMeasurements || [],
152
- operations: previousOperations || [],
153
- treeSnapshot: getTreeSnapshot(registeredIDs),
154
- });
155
- }
156
-
157
- clearHistory();
158
- currentFlushStartTime = performanceNow();
159
- currentFlushMeasurements = [];
160
- };
161
-
162
- const checkDebugID = function(debugID, allowRoot = false) {
163
- if (allowRoot && debugID === 0) {
164
- return;
165
- }
166
- if (!debugID) {
167
- warning(false, 'ReactDebugTool: debugID may not be empty.');
168
- }
169
- };
170
-
171
- const beginLifeCycleTimer = function(debugID, timerType) {
172
- if (currentFlushNesting === 0) {
173
- return;
174
- }
175
- if (currentTimerType && !lifeCycleTimerHasWarned) {
176
- warning(
177
- false,
178
- 'There is an internal error in the React performance measurement code.' +
179
- '\n\nDid not expect %s timer to start while %s timer is still in ' +
180
- 'progress for %s instance.',
181
- timerType,
182
- currentTimerType || 'no',
183
- debugID === currentTimerDebugID ? 'the same' : 'another',
184
- );
185
- lifeCycleTimerHasWarned = true;
186
- }
187
- currentTimerStartTime = performanceNow();
188
- currentTimerNestedFlushDuration = 0;
189
- currentTimerDebugID = debugID;
190
- currentTimerType = timerType;
191
- };
192
-
193
- const endLifeCycleTimer = function(debugID, timerType) {
194
- if (currentFlushNesting === 0) {
195
- return;
196
- }
197
- if (currentTimerType !== timerType && !lifeCycleTimerHasWarned) {
198
- warning(
199
- false,
200
- 'There is an internal error in the React performance measurement code. ' +
201
- 'We did not expect %s timer to stop while %s timer is still in ' +
202
- 'progress for %s instance. Please report this as a bug in React.',
203
- timerType,
204
- currentTimerType || 'no',
205
- debugID === currentTimerDebugID ? 'the same' : 'another',
206
- );
207
- lifeCycleTimerHasWarned = true;
208
- }
209
- if (isProfiling) {
210
- currentFlushMeasurements.push({
211
- timerType,
212
- instanceID: debugID,
213
- duration: performanceNow() -
214
- currentTimerStartTime -
215
- currentTimerNestedFlushDuration,
216
- });
217
- }
218
- currentTimerStartTime = 0;
219
- currentTimerNestedFlushDuration = 0;
220
- currentTimerDebugID = null;
221
- currentTimerType = null;
222
- };
223
-
224
- const pauseCurrentLifeCycleTimer = function() {
225
- var currentTimer = {
226
- startTime: currentTimerStartTime,
227
- nestedFlushStartTime: performanceNow(),
228
- debugID: currentTimerDebugID,
229
- timerType: currentTimerType,
230
- };
231
- lifeCycleTimerStack.push(currentTimer);
232
- currentTimerStartTime = 0;
233
- currentTimerNestedFlushDuration = 0;
234
- currentTimerDebugID = null;
235
- currentTimerType = null;
236
- };
237
-
238
- const resumeCurrentLifeCycleTimer = function() {
239
- var {
240
- startTime,
241
- nestedFlushStartTime,
242
- debugID,
243
- timerType,
244
- } = lifeCycleTimerStack.pop();
245
- var nestedFlushDuration = performanceNow() - nestedFlushStartTime;
246
- currentTimerStartTime = startTime;
247
- currentTimerNestedFlushDuration += nestedFlushDuration;
248
- currentTimerDebugID = debugID;
249
- currentTimerType = timerType;
250
- };
251
-
252
- var lastMarkTimeStamp = 0;
253
- var canUsePerformanceMeasure: boolean =
254
- typeof performance !== 'undefined' &&
255
- typeof performance.mark === 'function' &&
256
- typeof performance.clearMarks === 'function' &&
257
- typeof performance.measure === 'function' &&
258
- typeof performance.clearMeasures === 'function';
259
-
260
- const shouldMark = function(debugID) {
261
- if (!isProfiling || !canUsePerformanceMeasure) {
262
- return false;
263
- }
264
- var element = ReactComponentTreeHook.getElement(debugID);
265
- if (element == null || typeof element !== 'object') {
266
- return false;
267
- }
268
- var isHostElement = typeof element.type === 'string';
269
- if (isHostElement) {
270
- return false;
271
- }
272
- return true;
273
- };
274
-
275
- const markBegin = function(debugID, markType) {
276
- if (!shouldMark(debugID)) {
277
- return;
278
- }
279
-
280
- var markName = `${debugID}::${markType}`;
281
- lastMarkTimeStamp = performanceNow();
282
- performance.mark(markName);
283
- };
284
-
285
- const markEnd = function(debugID, markType) {
286
- if (!shouldMark(debugID)) {
287
- return;
288
- }
289
-
290
- var markName = `${debugID}::${markType}`;
291
- var displayName =
292
- ReactComponentTreeHook.getDisplayName(debugID) || 'Unknown';
293
-
294
- // Chrome has an issue of dropping markers recorded too fast:
295
- // https://bugs.chromium.org/p/chromium/issues/detail?id=640652
296
- // To work around this, we will not report very small measurements.
297
- // I determined the magic number by tweaking it back and forth.
298
- // 0.05ms was enough to prevent the issue, but I set it to 0.1ms to be safe.
299
- // When the bug is fixed, we can `measure()` unconditionally if we want to.
300
- var timeStamp = performanceNow();
301
- if (timeStamp - lastMarkTimeStamp > 0.1) {
302
- var measurementName = `${displayName} [${markType}]`;
303
- performance.measure(measurementName, markName);
304
- }
305
-
306
- performance.clearMarks(markName);
307
- if (measurementName) {
308
- performance.clearMeasures(measurementName);
309
- }
310
- };
311
-
312
- ReactDebugTool = {
313
- addHook(hook: Hook): void {
314
- hooks.push(hook);
315
- },
316
- removeHook(hook: Hook): void {
317
- for (var i = 0; i < hooks.length; i++) {
318
- if (hooks[i] === hook) {
319
- hooks.splice(i, 1);
320
- i--;
321
- }
322
- }
323
- },
324
- isProfiling(): boolean {
325
- return isProfiling;
326
- },
327
- beginProfiling(): void {
328
- if (isProfiling) {
329
- return;
330
- }
331
-
332
- isProfiling = true;
333
- flushHistory.length = 0;
334
- resetMeasurements();
335
- ReactDebugTool.addHook(ReactHostOperationHistoryHook);
336
- },
337
- endProfiling(): void {
338
- if (!isProfiling) {
339
- return;
340
- }
341
-
342
- isProfiling = false;
343
- resetMeasurements();
344
- ReactDebugTool.removeHook(ReactHostOperationHistoryHook);
345
- },
346
- getFlushHistory(): FlushHistory {
347
- return flushHistory;
348
- },
349
- onBeginFlush(): void {
350
- currentFlushNesting++;
351
- resetMeasurements();
352
- pauseCurrentLifeCycleTimer();
353
- emitEvent('onBeginFlush');
354
- },
355
- onEndFlush(): void {
356
- resetMeasurements();
357
- currentFlushNesting--;
358
- resumeCurrentLifeCycleTimer();
359
- emitEvent('onEndFlush');
360
- },
361
- onBeginLifeCycleTimer(debugID: DebugID, timerType: TimerType): void {
362
- checkDebugID(debugID);
363
- emitEvent('onBeginLifeCycleTimer', debugID, timerType);
364
- markBegin(debugID, timerType);
365
- beginLifeCycleTimer(debugID, timerType);
366
- },
367
- onEndLifeCycleTimer(debugID: DebugID, timerType: TimerType): void {
368
- checkDebugID(debugID);
369
- endLifeCycleTimer(debugID, timerType);
370
- markEnd(debugID, timerType);
371
- emitEvent('onEndLifeCycleTimer', debugID, timerType);
372
- },
373
- onBeginProcessingChildContext(): void {
374
- emitEvent('onBeginProcessingChildContext');
375
- },
376
- onEndProcessingChildContext(): void {
377
- emitEvent('onEndProcessingChildContext');
378
- },
379
- onHostOperation(operation: Operation) {
380
- checkDebugID(operation.instanceID);
381
- emitEvent('onHostOperation', operation);
382
- },
383
- onSetState(): void {
384
- emitEvent('onSetState');
385
- },
386
- onSetChildren(debugID: DebugID, childDebugIDs: Array<DebugID>) {
387
- checkDebugID(debugID);
388
- childDebugIDs.forEach(checkDebugID);
389
- emitEvent('onSetChildren', debugID, childDebugIDs);
390
- },
391
- onBeforeMountComponent(
392
- debugID: DebugID,
393
- element: ReactElement,
394
- parentDebugID: DebugID,
395
- ): void {
396
- checkDebugID(debugID);
397
- checkDebugID(parentDebugID, true);
398
- emitEvent('onBeforeMountComponent', debugID, element, parentDebugID);
399
- markBegin(debugID, 'mount');
400
- },
401
- onMountComponent(debugID: DebugID): void {
402
- checkDebugID(debugID);
403
- markEnd(debugID, 'mount');
404
- emitEvent('onMountComponent', debugID);
405
- },
406
- onBeforeUpdateComponent(debugID: DebugID, element: ReactElement): void {
407
- checkDebugID(debugID);
408
- emitEvent('onBeforeUpdateComponent', debugID, element);
409
- markBegin(debugID, 'update');
410
- },
411
- onUpdateComponent(debugID: DebugID): void {
412
- checkDebugID(debugID);
413
- markEnd(debugID, 'update');
414
- emitEvent('onUpdateComponent', debugID);
415
- },
416
- onBeforeUnmountComponent(debugID: DebugID): void {
417
- checkDebugID(debugID);
418
- emitEvent('onBeforeUnmountComponent', debugID);
419
- markBegin(debugID, 'unmount');
420
- },
421
- onUnmountComponent(debugID: DebugID): void {
422
- checkDebugID(debugID);
423
- markEnd(debugID, 'unmount');
424
- emitEvent('onUnmountComponent', debugID);
425
- },
426
- onTestEvent(): void {
427
- emitEvent('onTestEvent');
428
- },
429
- };
430
-
431
- ReactDebugTool.addHook(ReactInvalidSetStateWarningHook);
432
- ReactDebugTool.addHook(ReactComponentTreeHook);
433
- var url = (ExecutionEnvironment.canUseDOM && window.location.href) || '';
434
- if (/[?&]react_perf\b/.test(url)) {
435
- ReactDebugTool.beginProfiling();
436
- }
437
-}
438
-
439
-module.exports = ReactDebugTool;
src/renderers/shared/ReactGlobalSharedState.js
-1
@@ -18,7 +18,6 @@ var ReactGlobalSharedState = {
18
19
if (__DEV__) {
20
Object.assign(ReactGlobalSharedState, {
21
- ReactComponentTreeHook: ReactInternals.ReactComponentTreeHook,
21
ReactDebugCurrentFrame: ReactInternals.ReactDebugCurrentFrame,
22
});
23
}
src/renderers/shared/ReactInstrumentation.js
deleted
-21
@@ -1,21 +0,0 @@
1
-/**
2
- * Copyright (c) 2016-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
- * @providesModule ReactInstrumentation
8
- * @flow
9
- */
10
-
11
-'use strict';
12
-
13
-// Trust the developer to only use ReactInstrumentation with a __DEV__ check
14
-var debugTool = ((null: any): typeof ReactDebugTool);
15
-
16
-if (__DEV__) {
17
- var ReactDebugTool = require('ReactDebugTool');
18
- debugTool = ReactDebugTool;
19
-}
20
-
21
-module.exports = {debugTool};
src/renderers/shared/ReactPerf.js
deleted
-456
@@ -1,456 +0,0 @@
1
-/**
2
- * Copyright (c) 2016-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
- * @providesModule ReactPerf
8
- * @flow
9
- */
10
-
11
-'use strict';
12
-
13
-var ReactDebugTool = require('ReactDebugTool');
14
-var lowPriorityWarning = require('lowPriorityWarning');
15
-var alreadyWarned = false;
16
-
17
-import type {FlushHistory} from 'ReactDebugTool';
18
-
19
-function roundFloat(val, base = 2) {
20
- var n = Math.pow(10, base);
21
- return Math.floor(val * n) / n;
22
-}
23
-
24
-// Flow type definition of console.table is too strict right now, see
25
-// https://github.com/facebook/flow/pull/2353 for updates
26
-function consoleTable(table: Array<{[key: string]: any}>): void {
27
- console.table((table: any));
28
-}
29
-
30
-function warnInProduction() {
31
- if (alreadyWarned) {
32
- return;
33
- }
34
- alreadyWarned = true;
35
- if (typeof console !== 'undefined') {
36
- console.error(
37
- 'ReactPerf is not supported in the production builds of React. ' +
38
- 'To collect measurements, please use the development build of React instead.',
39
- );
40
- }
41
-}
42
-
43
-function getLastMeasurements() {
44
- if (!__DEV__) {
45
- warnInProduction();
46
- return [];
47
- }
48
-
49
- return ReactDebugTool.getFlushHistory();
50
-}
51
-
52
-function getExclusive(flushHistory = getLastMeasurements()) {
53
- if (!__DEV__) {
54
- warnInProduction();
55
- return [];
56
- }
57
-
58
- var aggregatedStats = {};
59
- var affectedIDs = {};
60
-
61
- function updateAggregatedStats(
62
- treeSnapshot,
63
- instanceID,
64
- timerType,
65
- applyUpdate,
66
- ) {
67
- var {displayName} = treeSnapshot[instanceID];
68
- var key = displayName;
69
- var stats = aggregatedStats[key];
70
- if (!stats) {
71
- affectedIDs[key] = {};
72
- stats = aggregatedStats[key] = {
73
- key,
74
- instanceCount: 0,
75
- counts: {},
76
- durations: {},
77
- totalDuration: 0,
78
- };
79
- }
80
- if (!stats.durations[timerType]) {
81
- stats.durations[timerType] = 0;
82
- }
83
- if (!stats.counts[timerType]) {
84
- stats.counts[timerType] = 0;
85
- }
86
- affectedIDs[key][instanceID] = true;
87
- applyUpdate(stats);
88
- }
89
-
90
- flushHistory.forEach(flush => {
91
- var {measurements, treeSnapshot} = flush;
92
- measurements.forEach(measurement => {
93
- var {duration, instanceID, timerType} = measurement;
94
- updateAggregatedStats(treeSnapshot, instanceID, timerType, stats => {
95
- stats.totalDuration += duration;
96
- stats.durations[timerType] += duration;
97
- stats.counts[timerType]++;
98
- });
99
- });
100
- });
101
-
102
- return Object.keys(aggregatedStats)
103
- .map(key => ({
104
- ...aggregatedStats[key],
105
- instanceCount: Object.keys(affectedIDs[key]).length,
106
- }))
107
- .sort((a, b) => b.totalDuration - a.totalDuration);
108
-}
109
-
110
-function getInclusive(flushHistory = getLastMeasurements()) {
111
- if (!__DEV__) {
112
- warnInProduction();
113
- return [];
114
- }
115
-
116
- var aggregatedStats = {};
117
- var affectedIDs = {};
118
-
119
- function updateAggregatedStats(treeSnapshot, instanceID, applyUpdate) {
120
- var {displayName, ownerID} = treeSnapshot[instanceID];
121
- var owner = treeSnapshot[ownerID];
122
- var key = (owner ? owner.displayName + ' > ' : '') + displayName;
123
- var stats = aggregatedStats[key];
124
- if (!stats) {
125
- affectedIDs[key] = {};
126
- stats = aggregatedStats[key] = {
127
- key,
128
- instanceCount: 0,
129
- inclusiveRenderDuration: 0,
130
- renderCount: 0,
131
- };
132
- }
133
- affectedIDs[key][instanceID] = true;
134
- applyUpdate(stats);
135
- }
136
-
137
- var isCompositeByID = {};
138
- flushHistory.forEach(flush => {
139
- var {measurements} = flush;
140
- measurements.forEach(measurement => {
141
- var {instanceID, timerType} = measurement;
142
- if (timerType !== 'render') {
143
- return;
144
- }
145
- isCompositeByID[instanceID] = true;
146
- });
147
- });
148
-
149
- flushHistory.forEach(flush => {
150
- var {measurements, treeSnapshot} = flush;
151
- measurements.forEach(measurement => {
152
- var {duration, instanceID, timerType} = measurement;
153
- if (timerType !== 'render') {
154
- return;
155
- }
156
- updateAggregatedStats(treeSnapshot, instanceID, stats => {
157
- stats.renderCount++;
158
- });
159
- var nextParentID = instanceID;
160
- while (nextParentID) {
161
- // As we traverse parents, only count inclusive time towards composites.
162
- // We know something is a composite if its render() was called.
163
- if (isCompositeByID[nextParentID]) {
164
- updateAggregatedStats(treeSnapshot, nextParentID, stats => {
165
- stats.inclusiveRenderDuration += duration;
166
- });
167
- }
168
- nextParentID = treeSnapshot[nextParentID].parentID;
169
- }
170
- });
171
- });
172
-
173
- return Object.keys(aggregatedStats)
174
- .map(key => ({
175
- ...aggregatedStats[key],
176
- instanceCount: Object.keys(affectedIDs[key]).length,
177
- }))
178
- .sort((a, b) => b.inclusiveRenderDuration - a.inclusiveRenderDuration);
179
-}
180
-
181
-function getWasted(flushHistory = getLastMeasurements()) {
182
- if (!__DEV__) {
183
- warnInProduction();
184
- return [];
185
- }
186
-
187
- var aggregatedStats = {};
188
- var affectedIDs = {};
189
-
190
- function updateAggregatedStats(treeSnapshot, instanceID, applyUpdate) {
191
- var {displayName, ownerID} = treeSnapshot[instanceID];
192
- var owner = treeSnapshot[ownerID];
193
- var key = (owner ? owner.displayName + ' > ' : '') + displayName;
194
- var stats = aggregatedStats[key];
195
- if (!stats) {
196
- affectedIDs[key] = {};
197
- stats = aggregatedStats[key] = {
198
- key,
199
- instanceCount: 0,
200
- inclusiveRenderDuration: 0,
201
- renderCount: 0,
202
- };
203
- }
204
- affectedIDs[key][instanceID] = true;
205
- applyUpdate(stats);
206
- }
207
-
208
- flushHistory.forEach(flush => {
209
- var {measurements, treeSnapshot, operations} = flush;
210
- var isDefinitelyNotWastedByID = {};
211
-
212
- // Find host components associated with an operation in this batch.
213
- // Mark all components in their parent tree as definitely not wasted.
214
- operations.forEach(operation => {
215
- var {instanceID} = operation;
216
- var nextParentID = instanceID;
217
- while (nextParentID) {
218
- isDefinitelyNotWastedByID[nextParentID] = true;
219
- nextParentID = treeSnapshot[nextParentID].parentID;
220
- }
221
- });
222
-
223
- // Find composite components that rendered in this batch.
224
- // These are potential candidates for being wasted renders.
225
- var renderedCompositeIDs = {};
226
- measurements.forEach(measurement => {
227
- var {instanceID, timerType} = measurement;
228
- if (timerType !== 'render') {
229
- return;
230
- }
231
- renderedCompositeIDs[instanceID] = true;
232
- });
233
-
234
- measurements.forEach(measurement => {
235
- var {duration, instanceID, timerType} = measurement;
236
- if (timerType !== 'render') {
237
- return;
238
- }
239
-
240
- // If there was a DOM update below this component, or it has just been
241
- // mounted, its render() is not considered wasted.
242
- var {updateCount} = treeSnapshot[instanceID];
243
- if (isDefinitelyNotWastedByID[instanceID] || updateCount === 0) {
244
- return;
245
- }
246
-
247
- // We consider this render() wasted.
248
- updateAggregatedStats(treeSnapshot, instanceID, stats => {
249
- stats.renderCount++;
250
- });
251
-
252
- var nextParentID = instanceID;
253
- while (nextParentID) {
254
- // Any parents rendered during this batch are considered wasted
255
- // unless we previously marked them as dirty.
256
- var isWasted =
257
- renderedCompositeIDs[nextParentID] &&
258
- !isDefinitelyNotWastedByID[nextParentID];
259
- if (isWasted) {
260
- updateAggregatedStats(treeSnapshot, nextParentID, stats => {
261
- stats.inclusiveRenderDuration += duration;
262
- });
263
- }
264
- nextParentID = treeSnapshot[nextParentID].parentID;
265
- }
266
- });
267
- });
268
-
269
- return Object.keys(aggregatedStats)
270
- .map(key => ({
271
- ...aggregatedStats[key],
272
- instanceCount: Object.keys(affectedIDs[key]).length,
273
- }))
274
- .sort((a, b) => b.inclusiveRenderDuration - a.inclusiveRenderDuration);
275
-}
276
-
277
-function getOperations(flushHistory = getLastMeasurements()) {
278
- if (!__DEV__) {
279
- warnInProduction();
280
- return [];
281
- }
282
-
283
- var stats = [];
284
- flushHistory.forEach((flush, flushIndex) => {
285
- var {operations, treeSnapshot} = flush;
286
- operations.forEach(operation => {
287
- var {instanceID, type, payload} = operation;
288
- var {displayName, ownerID} = treeSnapshot[instanceID];
289
- var owner = treeSnapshot[ownerID];
290
- var key = (owner ? owner.displayName + ' > ' : '') + displayName;
291
-
292
- stats.push({
293
- flushIndex,
294
- instanceID,
295
- key,
296
- type,
297
- ownerID,
298
- payload,
299
- });
300
- });
301
- });
302
- return stats;
303
-}
304
-
305
-function printExclusive(flushHistory?: FlushHistory) {
306
- if (!__DEV__) {
307
- warnInProduction();
308
- return;
309
- }
310
-
311
- var stats = getExclusive(flushHistory);
312
- var table = stats.map(item => {
313
- var {key, instanceCount, totalDuration} = item;
314
- var renderCount = item.counts.render || 0;
315
- var renderDuration = item.durations.render || 0;
316
- return {
317
- Component: key,
318
- 'Total time (ms)': roundFloat(totalDuration),
319
- 'Instance count': instanceCount,
320
- 'Total render time (ms)': roundFloat(renderDuration),
321
- 'Average render time (ms)': renderCount
322
- ? roundFloat(renderDuration / renderCount)
323
- : undefined,
324
- 'Render count': renderCount,
325
- 'Total lifecycle time (ms)': roundFloat(totalDuration - renderDuration),
326
- };
327
- });
328
- consoleTable(table);
329
-}
330
-
331
-function printInclusive(flushHistory?: FlushHistory) {
332
- if (!__DEV__) {
333
- warnInProduction();
334
- return;
335
- }
336
-
337
- var stats = getInclusive(flushHistory);
338
- var table = stats.map(item => {
339
- var {key, instanceCount, inclusiveRenderDuration, renderCount} = item;
340
- return {
341
- 'Owner > Component': key,
342
- 'Inclusive render time (ms)': roundFloat(inclusiveRenderDuration),
343
- 'Instance count': instanceCount,
344
- 'Render count': renderCount,
345
- };
346
- });
347
- consoleTable(table);
348
-}
349
-
350
-function printWasted(flushHistory?: FlushHistory) {
351
- if (!__DEV__) {
352
- warnInProduction();
353
- return;
354
- }
355
-
356
- var stats = getWasted(flushHistory);
357
- var table = stats.map(item => {
358
- var {key, instanceCount, inclusiveRenderDuration, renderCount} = item;
359
- return {
360
- 'Owner > Component': key,
361
- 'Inclusive wasted time (ms)': roundFloat(inclusiveRenderDuration),
362
- 'Instance count': instanceCount,
363
- 'Render count': renderCount,
364
- };
365
- });
366
- consoleTable(table);
367
-}
368
-
369
-function printOperations(flushHistory?: FlushHistory) {
370
- if (!__DEV__) {
371
- warnInProduction();
372
- return;
373
- }
374
-
375
- var stats = getOperations(flushHistory);
376
- var table = stats.map(stat => ({
377
- 'Owner > Node': stat.key,
378
- Operation: stat.type,
379
- Payload: typeof stat.payload === 'object'
380
- ? JSON.stringify(stat.payload)
381
- : stat.payload,
382
- 'Flush index': stat.flushIndex,
383
- 'Owner Component ID': stat.ownerID,
384
- 'DOM Component ID': stat.instanceID,
385
- }));
386
- consoleTable(table);
387
-}
388
-
389
-var warnedAboutPrintDOM = false;
390
-function printDOM(measurements: FlushHistory) {
391
- lowPriorityWarning(
392
- warnedAboutPrintDOM,
393
- '`ReactPerf.printDOM(...)` is deprecated. Use ' +
394
- '`ReactPerf.printOperations(...)` instead.',
395
- );
396
- warnedAboutPrintDOM = true;
397
- return printOperations(measurements);
398
-}
399
-
400
-var warnedAboutGetMeasurementsSummaryMap = false;
401
-function getMeasurementsSummaryMap(measurements: FlushHistory) {
402
- lowPriorityWarning(
403
- warnedAboutGetMeasurementsSummaryMap,
404
- '`ReactPerf.getMeasurementsSummaryMap(...)` is deprecated. Use ' +
405
- '`ReactPerf.getWasted(...)` instead.',
406
- );
407
- warnedAboutGetMeasurementsSummaryMap = true;
408
- return getWasted(measurements);
409
-}
410
-
411
-function start() {
412
- if (!__DEV__) {
413
- warnInProduction();
414
- return;
415
- }
416
-
417
- ReactDebugTool.beginProfiling();
418
-}
419
-
420
-function stop() {
421
- if (!__DEV__) {
422
- warnInProduction();
423
- return;
424
- }
425
-
426
- ReactDebugTool.endProfiling();
427
-}
428
-
429
-function isRunning() {
430
- if (!__DEV__) {
431
- warnInProduction();
432
- return false;
433
- }
434
-
435
- return ReactDebugTool.isProfiling();
436
-}
437
-
438
-var ReactPerfAnalysis = {
439
- getLastMeasurements,
440
- getExclusive,
441
- getInclusive,
442
- getWasted,
443
- getOperations,
444
- printExclusive,
445
- printInclusive,
446
- printWasted,
447
- printOperations,
448
- start,
449
- stop,
450
- isRunning,
451
- // Deprecated:
452
- printDOM,
453
- getMeasurementsSummaryMap,
454
-};
455
-
456
-module.exports = ReactPerfAnalysis;
src/renderers/shared/__tests__/ReactDebugTool-test.js
deleted
-82
@@ -1,82 +0,0 @@
1
-/**
2
- * Copyright (c) 2016-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
- * @emails react-core
8
- */
9
-
10
-'use strict';
11
-
12
-describe('ReactDebugTool', () => {
13
- var ReactDebugTool;
14
-
15
- beforeEach(() => {
16
- jest.resetModules();
17
- ReactDebugTool = require('ReactDebugTool');
18
- });
19
-
20
- it('should add and remove hooks', () => {
21
- var handler1 = jasmine.createSpy('spy');
22
- var handler2 = jasmine.createSpy('spy');
23
- var hook1 = {onTestEvent: handler1};
24
- var hook2 = {onTestEvent: handler2};
25
-
26
- ReactDebugTool.addHook(hook1);
27
- ReactDebugTool.onTestEvent();
28
- expect(handler1.calls.count()).toBe(1);
29
- expect(handler2.calls.count()).toBe(0);
30
-
31
- ReactDebugTool.onTestEvent();
32
- expect(handler1.calls.count()).toBe(2);
33
- expect(handler2.calls.count()).toBe(0);
34
-
35
- ReactDebugTool.addHook(hook2);
36
- ReactDebugTool.onTestEvent();
37
- expect(handler1.calls.count()).toBe(3);
38
- expect(handler2.calls.count()).toBe(1);
39
-
40
- ReactDebugTool.onTestEvent();
41
- expect(handler1.calls.count()).toBe(4);
42
- expect(handler2.calls.count()).toBe(2);
43
-
44
- ReactDebugTool.removeHook(hook1);
45
- ReactDebugTool.onTestEvent();
46
- expect(handler1.calls.count()).toBe(4);
47
- expect(handler2.calls.count()).toBe(3);
48
-
49
- ReactDebugTool.removeHook(hook2);
50
- ReactDebugTool.onTestEvent();
51
- expect(handler1.calls.count()).toBe(4);
52
- expect(handler2.calls.count()).toBe(3);
53
- });
54
-
55
- it('warns once when an error is thrown in hook', () => {
56
- spyOn(console, 'error');
57
- ReactDebugTool.addHook({
58
- onTestEvent() {
59
- throw new Error('Hi.');
60
- },
61
- });
62
-
63
- ReactDebugTool.onTestEvent();
64
- expectDev(console.error.calls.count()).toBe(1);
65
- expectDev(console.error.calls.argsFor(0)[0]).toContain(
66
- 'Exception thrown by hook while handling ' + 'onTestEvent: Error: Hi.',
67
- );
68
-
69
- ReactDebugTool.onTestEvent();
70
- expectDev(console.error.calls.count()).toBe(1);
71
- });
72
-
73
- it('returns isProfiling state', () => {
74
- expect(ReactDebugTool.isProfiling()).toBe(false);
75
-
76
- ReactDebugTool.beginProfiling();
77
- expect(ReactDebugTool.isProfiling()).toBe(true);
78
-
79
- ReactDebugTool.endProfiling();
80
- expect(ReactDebugTool.isProfiling()).toBe(false);
81
- });
82
-});
src/test/ReactComponentTreeTestUtils.js
deleted
-105
@@ -1,105 +0,0 @@
1
-/**
2
- * Copyright (c) 2016-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
- * @providesModule ReactComponentTreeTestUtils
8
- */
9
-
10
-'use strict';
11
-
12
-var ReactComponentTreeHook = require('ReactComponentTreeHook');
13
-
14
-function getRootDisplayNames() {
15
- return ReactComponentTreeHook.getRootIDs().map(
16
- ReactComponentTreeHook.getDisplayName,
17
- );
18
-}
19
-
20
-function getRegisteredDisplayNames() {
21
- return ReactComponentTreeHook.getRegisteredIDs().map(
22
- ReactComponentTreeHook.getDisplayName,
23
- );
24
-}
25
-
26
-function expectTree(rootID, expectedTree, parentPath) {
27
- var displayName = ReactComponentTreeHook.getDisplayName(rootID);
28
- var ownerID = ReactComponentTreeHook.getOwnerID(rootID);
29
- var parentID = ReactComponentTreeHook.getParentID(rootID);
30
- var childIDs = ReactComponentTreeHook.getChildIDs(rootID);
31
- var text = ReactComponentTreeHook.getText(rootID);
32
- var element = ReactComponentTreeHook.getElement(rootID);
33
- var path = parentPath ? `${parentPath} > ${displayName}` : displayName;
34
-
35
- function expectEqual(actual, expected, name) {
36
- // Get Jasmine to print descriptive error messages.
37
- // We pass path so that we know where the mismatch occurred.
38
- expectDev({
39
- path,
40
- [name]: actual,
41
- }).toEqual({
42
- path,
43
- [name]: expected,
44
- });
45
- }
46
-
47
- if (expectedTree.parentDisplayName !== undefined) {
48
- expectEqual(
49
- ReactComponentTreeHook.getDisplayName(parentID),
50
- expectedTree.parentDisplayName,
51
- 'parentDisplayName',
52
- );
53
- }
54
- if (expectedTree.ownerDisplayName !== undefined) {
55
- expectEqual(
56
- ReactComponentTreeHook.getDisplayName(ownerID),
57
- expectedTree.ownerDisplayName,
58
- 'ownerDisplayName',
59
- );
60
- }
61
- if (expectedTree.parentID !== undefined) {
62
- expectEqual(parentID, expectedTree.parentID, 'parentID');
63
- }
64
- if (expectedTree.text !== undefined) {
65
- expectEqual(text, expectedTree.text, 'text');
66
- expectEqual('' + element, expectedTree.text, 'element.toString()');
67
- } else {
68
- expectEqual(text, null, 'text');
69
- }
70
- if (expectedTree.element !== undefined) {
71
- // TODO: Comparing elements makes tests run out of memory on errors.
72
- // For now, compare just types.
73
- expectEqual(
74
- element && element.type,
75
- expectedTree.element && expectedTree.element.type,
76
- 'element.type',
77
- );
78
- } else if (text == null) {
79
- expectEqual(typeof element, 'object', 'typeof element');
80
- }
81
- if (expectedTree.children !== undefined) {
82
- expectEqual(
83
- childIDs.length,
84
- expectedTree.children.length,
85
- 'children.length',
86
- );
87
- for (var i = 0; i < childIDs.length; i++) {
88
- expectTree(
89
- childIDs[i],
90
- {parentID: rootID, ...expectedTree.children[i]},
91
- path,
92
- );
93
- }
94
- } else {
95
- expectEqual(childIDs, [], 'childIDs');
96
- }
97
-}
98
-
99
-var ReactComponentTreeTestUtils = {
100
- expectTree,
101
- getRootDisplayNames,
102
- getRegisteredDisplayNames,
103
-};
104
-
105
-module.exports = ReactComponentTreeTestUtils;