main
js 104 lines 2.84 KB
Raw
1 /**
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
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 */
9
10 import type {ReactComponentInfo, ReactDebugInfo} from 'shared/ReactTypes';
11 import type {Fiber} from 'react-reconciler/src/ReactInternalTypes';
12 import type {WorkTagMap} from '../../types';
13 import type {Rect} from '../../types';
14
15 // $FlowFixMe[method-unbinding]
16 const toString = Object.prototype.toString;
17
18 export function isError(object: mixed): boolean {
19 return toString.call(object) === '[object Error]';
20 }
21
22 export function getFiberFlags(fiber: Fiber): number {
23 // The name of this field changed from "effectTag" to "flags"
24 return fiber.flags !== undefined ? fiber.flags : (fiber as any).effectTag;
25 }
26
27 export function rootSupportsProfiling(root: any): boolean {
28 if (root.memoizedInteractions != null) {
29 // v16 builds include this field for the scheduler/tracing API.
30 return true;
31 } else if (
32 root.current != null &&
33 root.current.hasOwnProperty('treeBaseDuration')
34 ) {
35 // The scheduler/tracing API was removed in v17 though
36 // so we need to check a non-root Fiber.
37 return true;
38 } else {
39 return false;
40 }
41 }
42
43 export function isErrorBoundary(workTagMap: WorkTagMap, fiber: Fiber): boolean {
44 const {tag, type} = fiber;
45
46 switch (tag) {
47 case workTagMap.ClassComponent:
48 case workTagMap.IncompleteClassComponent:
49 const instance = fiber.stateNode;
50 return (
51 typeof type.getDerivedStateFromError === 'function' ||
52 (instance !== null && typeof instance.componentDidCatch === 'function')
53 );
54 default:
55 return false;
56 }
57 }
58
59 export function getSecondaryEnvironmentName(
60 debugInfo: ?ReactDebugInfo,
61 index: number,
62 ): null | string {
63 if (debugInfo != null) {
64 const componentInfo: ReactComponentInfo = debugInfo[index] as any;
65 for (let i = index + 1; i < debugInfo.length; i++) {
66 const debugEntry = debugInfo[i];
67 if (typeof debugEntry.env === 'string') {
68 // If the next environment is different then this component was the boundary
69 // and it changed before entering the next component. So we assign this
70 // component a secondary environment.
71 return componentInfo.env !== debugEntry.env ? debugEntry.env : null;
72 }
73 }
74 }
75 return null;
76 }
77
78 export function areEqualRects(
79 a: null | Array<Rect>,
80 b: null | Array<Rect>,
81 ): boolean {
82 if (a === null) {
83 return b === null;
84 }
85 if (b === null) {
86 return false;
87 }
88 if (a.length !== b.length) {
89 return false;
90 }
91 for (let i = 0; i < a.length; i++) {
92 const aRect = a[i];
93 const bRect = b[i];
94 if (
95 aRect.x !== bRect.x ||
96 aRect.y !== bRect.y ||
97 aRect.width !== bRect.width ||
98 aRect.height !== bRect.height
99 ) {
100 return false;
101 }
102 }
103 return true;
104 }