From 60ba723bf78b9a28f60dce854e88e206fab52301 Mon Sep 17 00:00:00 2001 From: Ben Pernick <57197898+bpernick@users.noreply.github.com> Date: Wed, 26 Aug 2020 12:04:43 -0500 Subject: [PATCH] Add SuspenseList to devTools (#19684) * ensure getDisplayName is only called on functions * add SuspenseList to Dev tools element names * Add SuspenseList and pass tests * Import SuspenseList directly * run prettier * Refactor tests to use real components * run linter --- .../src/__tests__/utils-test.js | 44 ++++++++++++++++++- packages/react-devtools-shared/src/utils.js | 8 +++- packages/react-is/src/ReactIs.js | 2 + 3 files changed, 51 insertions(+), 3 deletions(-) diff --git a/packages/react-devtools-shared/src/__tests__/utils-test.js b/packages/react-devtools-shared/src/__tests__/utils-test.js index 37e445974a28c..f2d559485b2cf 100644 --- a/packages/react-devtools-shared/src/__tests__/utils-test.js +++ b/packages/react-devtools-shared/src/__tests__/utils-test.js @@ -7,7 +7,15 @@ * @flow */ -import {getDisplayName} from 'react-devtools-shared/src/utils'; +import { + getDisplayName, + getDisplayNameForReactElement, +} from 'react-devtools-shared/src/utils'; +import { + REACT_SUSPENSE_LIST_TYPE as SuspenseList, + REACT_STRICT_MODE_TYPE as StrictMode, +} from 'shared/ReactSymbols'; +import {createElement} from 'react/src/ReactElement'; describe('utils', () => { describe('getDisplayName', () => { @@ -37,4 +45,38 @@ describe('utils', () => { expect(getDisplayName(FauxComponent, 'Fallback')).toEqual('Fallback'); }); }); + describe('getDisplayNameForReactElement', () => { + it('should return correct display name for an element with function type', () => { + function FauxComponent() {} + FauxComponent.displayName = 'OverrideDisplayName'; + const element = createElement(FauxComponent); + expect(getDisplayNameForReactElement(element)).toEqual( + 'OverrideDisplayName', + ); + }); + it('should return correct display name for an element with a type of StrictMode', () => { + const element = createElement(StrictMode); + expect(getDisplayNameForReactElement(element)).toEqual('StrictMode'); + }); + it('should return correct display name for an element with a type of SuspenseList', () => { + const element = createElement(SuspenseList); + expect(getDisplayNameForReactElement(element)).toEqual('SuspenseList'); + }); + it('should return NotImplementedInDevtools for an element with invalid symbol type', () => { + const element = createElement(Symbol('foo')); + expect(getDisplayNameForReactElement(element)).toEqual( + 'NotImplementedInDevtools', + ); + }); + it('should return NotImplementedInDevtools for an element with invalid type', () => { + const element = createElement(true); + expect(getDisplayNameForReactElement(element)).toEqual( + 'NotImplementedInDevtools', + ); + }); + it('should return Element for null type', () => { + const element = createElement(); + expect(getDisplayNameForReactElement(element)).toEqual('Element'); + }); + }); }); diff --git a/packages/react-devtools-shared/src/utils.js b/packages/react-devtools-shared/src/utils.js index 87f845105b528..b0b873cca163d 100644 --- a/packages/react-devtools-shared/src/utils.js +++ b/packages/react-devtools-shared/src/utils.js @@ -22,6 +22,7 @@ import { StrictMode, Suspense, } from 'react-is'; +import {REACT_SUSPENSE_LIST_TYPE as SuspenseList} from 'shared/ReactSymbols'; import { TREE_OPERATION_ADD, TREE_OPERATION_REMOVE, @@ -43,7 +44,6 @@ import { } from 'react-devtools-shared/src/types'; import {localStorageGetItem, localStorageSetItem} from './storage'; import {meta} from './hydration'; - import type {ComponentFilter, ElementType} from './types'; const cachedDisplayNames: WeakMap = new WeakMap(); @@ -489,12 +489,16 @@ export function getDisplayNameForReactElement( return 'StrictMode'; case Suspense: return 'Suspense'; + case SuspenseList: + return 'SuspenseList'; default: const {type} = element; if (typeof type === 'string') { return type; - } else if (type != null) { + } else if (typeof type === 'function') { return getDisplayName(type, 'Anonymous'); + } else if (type != null) { + return 'NotImplementedInDevtools'; } else { return 'Element'; } diff --git a/packages/react-is/src/ReactIs.js b/packages/react-is/src/ReactIs.js index bac0db1a880ff..2f132ba5de9a0 100644 --- a/packages/react-is/src/ReactIs.js +++ b/packages/react-is/src/ReactIs.js @@ -21,6 +21,7 @@ import { REACT_PROVIDER_TYPE, REACT_STRICT_MODE_TYPE, REACT_SUSPENSE_TYPE, + REACT_SUSPENSE_LIST_TYPE, } from 'shared/ReactSymbols'; import isValidElementType from 'shared/isValidElementType'; @@ -36,6 +37,7 @@ export function typeOf(object: any) { case REACT_PROFILER_TYPE: case REACT_STRICT_MODE_TYPE: case REACT_SUSPENSE_TYPE: + case REACT_SUSPENSE_LIST_TYPE: return type; default: const $$typeofType = type && type.$$typeof;