From b772228aef68c10b928cdcb2724d49987235a841 Mon Sep 17 00:00:00 2001 From: Sebastian Markbage Date: Thu, 30 May 2024 12:24:56 -0400 Subject: [PATCH] Don't use Component name in console.createTask Chrome requires us to have a Task name. Currently the component name appears twice. Once in the Task name and then once in the next callsite that appears within that Component. This removes the component name from the Task name and just replaces it with `<>` to indicate that it's a React task spawned from a JSX callsite. Yet still keeps it light weight. I keep the name for built-ins because they don't have another stack frame associated with them and they're always the last stack frame since they don't create other elements they're never the owner. --- .../react-client/src/ReactFlightClient.js | 56 ++++++------------- packages/react/src/jsx/ReactJSXElement.js | 37 +++++------- 2 files changed, 32 insertions(+), 61 deletions(-) diff --git a/packages/react-client/src/ReactFlightClient.js b/packages/react-client/src/ReactFlightClient.js index 7795b3025215..99ec610b7ece 100644 --- a/packages/react-client/src/ReactFlightClient.js +++ b/packages/react-client/src/ReactFlightClient.js @@ -67,7 +67,6 @@ import { REACT_ELEMENT_TYPE, REACT_POSTPONE_TYPE, ASYNC_ITERATOR, - REACT_FRAGMENT_TYPE, } from 'shared/ReactSymbols'; import getComponentNameFromType from 'shared/getComponentNameFromType'; @@ -576,41 +575,23 @@ function nullRefGetter() { } } -function getServerComponentTaskName(componentInfo: ReactComponentInfo): string { - return '<' + (componentInfo.name || '...') + '>'; -} - -function getTaskName(type: mixed): string { - if (type === REACT_FRAGMENT_TYPE) { - return '<>'; - } - if (typeof type === 'function') { - // This is a function so it must have been a Client Reference that resolved to - // a function. We use "use client" to indicate that this is the boundary into - // the client. There should only be one for any given owner chain. - return '"use client"'; - } - if ( - typeof type === 'object' && - type !== null && - type.$$typeof === REACT_LAZY_TYPE - ) { - if (type._init === readChunk) { - // This is a lazy node created by Flight. It is probably a client reference. - // We use the "use client" string to indicate that this is the boundary into - // the client. There will only be one for any given owner chain. - return '"use client"'; - } - // We don't want to eagerly initialize the initializer in DEV mode so we can't - // call it to extract the type so we don't know the type of this component. - return '<...>'; - } - try { +function getClientTaskName(type: mixed): string { + if (typeof type === 'symbol' || typeof type === 'string') { + // If we have a built-in or host component, we add its name to the task. + // That's because there won't be any user space stack frames that has that + // name in it. These only appear at the top of the stack because a built-in + // and host component will never be the owner of any other components. + // This name only appears when the error/warning is coming from the built-in + // itself. Such as if you pass an invalid DOM attribute. const name = getComponentNameFromType(type); - return name ? '<' + name + '>' : '<...>'; - } catch (x) { - return '<...>'; + if (name) { + return '<' + name + '>'; + } } + // For anything else that was rendered as a Client Element, it must have come + // from a client reference. We use "use client" to indicate that this Task is + // the boundary into the client. There should only be one for any given owner chain. + return '"use client"'; } function createElement( @@ -692,7 +673,7 @@ function createElement( if (supportsCreateTask && stack !== null) { const createTaskFn = (console: any).createTask.bind( console, - getTaskName(type), + getClientTaskName(type), ); const callStack = buildFakeCallStack(stack, createTaskFn); // This owner should ideally have already been initialized to avoid getting @@ -1738,10 +1719,7 @@ function initializeFakeTask( : initializeFakeTask(componentInfo.owner); // eslint-disable-next-line react-internal/no-production-logging - const createTaskFn = (console: any).createTask.bind( - console, - getServerComponentTaskName(componentInfo), - ); + const createTaskFn = (console: any).createTask.bind(console, '<>'); const callStack = buildFakeCallStack(stack, createTaskFn); if (ownerTask === null) { diff --git a/packages/react/src/jsx/ReactJSXElement.js b/packages/react/src/jsx/ReactJSXElement.js index 0f8b9f397df5..20452bbbfcf0 100644 --- a/packages/react/src/jsx/ReactJSXElement.js +++ b/packages/react/src/jsx/ReactJSXElement.js @@ -9,12 +9,7 @@ import getComponentNameFromType from 'shared/getComponentNameFromType'; import ReactSharedInternals from 'shared/ReactSharedInternals'; import hasOwnProperty from 'shared/hasOwnProperty'; import assign from 'shared/assign'; -import { - getIteratorFn, - REACT_ELEMENT_TYPE, - REACT_FRAGMENT_TYPE, - REACT_LAZY_TYPE, -} from 'shared/ReactSymbols'; +import {getIteratorFn, REACT_ELEMENT_TYPE} from 'shared/ReactSymbols'; import {checkKeyStringCoercion} from 'shared/CheckStringCoercion'; import isValidElementType from 'shared/isValidElementType'; import isArray from 'shared/isArray'; @@ -40,24 +35,22 @@ const createTask = : () => null; function getTaskName(type) { - if (type === REACT_FRAGMENT_TYPE) { - return '<>'; - } - if ( - typeof type === 'object' && - type !== null && - type.$$typeof === REACT_LAZY_TYPE - ) { - // We don't want to eagerly initialize the initializer in DEV mode so we can't - // call it to extract the type so we don't know the type of this component. - return '<...>'; - } - try { + if (typeof type === 'symbol' || typeof type === 'string') { + // If we have a built-in or host component, we add its name to the task. + // That's because there won't be any user space stack frames that has that + // name in it. These only appear at the top of the stack because a built-in + // and host component will never be the owner of any other components. + // This name only appears when the error/warning is coming from the built-in + // itself. Such as if you pass an invalid DOM attribute. const name = getComponentNameFromType(type); - return name ? '<' + name + '>' : '<...>'; - } catch (x) { - return '<...>'; + if (name) { + return '<' + name + '>'; + } } + // For anything else, we just make a blank JSX-like indicator that this is + // a React Task. It symbolizes JSX but the actual name of the component will + // be on the next stack frame. We leave it blank to avoid duplicating the name. + return '<>'; } function getOwner() {