Skip to content

Commit 0f2a59e

Browse files
committed
Warn for invalid type in renderer with the correct RSC stack (#30102)
This is all behind the `enableOwnerStacks` flag. This is a follow up to #29088. In that I moved type validation into the renderer since that's the one that knows what types are allowed. However, I only removed it from `React.createElement` and not the JSX which was an oversight. However, I also noticed that for invalid types we don't have the right stack trace for throws because we're not yet inside the JSX element that itself is invalid. We should use its stack for the stack trace. That's the reason it's enough to just use the throw now because we can get a good stack trace from the owner stack. This is fixed by creating a fake Throw Fiber that gets assigned the right stack. Additionally, I noticed that for certain invalid types like the most common one `undefined` we error in Flight so a missing import in RSC leads to a generic error. Instead of erroring on the Flight side we should just let anything that's not a Server Component through to the client and then let the Client renderer determine whether it's a valid type or not. Since we now have owner stacks through the server too, this will still be able to provide a good stack trace on the client that points to the server in that case. <img width="571" alt="Screenshot 2024-06-25 at 6 46 35 PM" src="https://github.com/facebook/react/assets/63648/6812c24f-e274-4e09-b4de-21deda9ea1d4"> To get the best stack you have to expand the little icon and the regular stack is noisy [due to this Chrome bug](https://issues.chromium.org/issues/345248263) which makes it a little harder to find but once that's fixed it might be easier. DiffTrain build for [e02baf6](e02baf6)
1 parent 4365cb3 commit 0f2a59e

34 files changed

+728
-672
lines changed

compiled/facebook-www/REVISION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
349a99a7a347f280ce40e9297cac5a3bd796901e
1+
e02baf6c92833a0d45a77fb2e741676f393c24f7
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
349a99a7a347f280ce40e9297cac5a3bd796901e
1+
e02baf6c92833a0d45a77fb2e741676f393c24f7

compiled/facebook-www/React-dev.classic.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1991,7 +1991,7 @@ __DEV__ &&
19911991
exports.useTransition = function () {
19921992
return resolveDispatcher().useTransition();
19931993
};
1994-
exports.version = "19.0.0-www-classic-349a99a7a3-20240626";
1994+
exports.version = "19.0.0-www-classic-e02baf6c92-20240627";
19951995
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
19961996
"function" ===
19971997
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&

compiled/facebook-www/React-dev.modern.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1971,7 +1971,7 @@ __DEV__ &&
19711971
exports.useTransition = function () {
19721972
return resolveDispatcher().useTransition();
19731973
};
1974-
exports.version = "19.0.0-www-modern-349a99a7a3-20240626";
1974+
exports.version = "19.0.0-www-modern-e02baf6c92-20240627";
19751975
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
19761976
"function" ===
19771977
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&

compiled/facebook-www/React-prod.classic.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -669,4 +669,4 @@ exports.useSyncExternalStore = function (
669669
exports.useTransition = function () {
670670
return ReactSharedInternals.H.useTransition();
671671
};
672-
exports.version = "19.0.0-www-classic-349a99a7a3-20240626";
672+
exports.version = "19.0.0-www-classic-e02baf6c92-20240627";

compiled/facebook-www/React-prod.modern.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -669,4 +669,4 @@ exports.useSyncExternalStore = function (
669669
exports.useTransition = function () {
670670
return ReactSharedInternals.H.useTransition();
671671
};
672-
exports.version = "19.0.0-www-modern-349a99a7a3-20240626";
672+
exports.version = "19.0.0-www-modern-e02baf6c92-20240627";

compiled/facebook-www/React-profiling.classic.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -673,7 +673,7 @@ exports.useSyncExternalStore = function (
673673
exports.useTransition = function () {
674674
return ReactSharedInternals.H.useTransition();
675675
};
676-
exports.version = "19.0.0-www-classic-349a99a7a3-20240626";
676+
exports.version = "19.0.0-www-classic-e02baf6c92-20240627";
677677
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
678678
"function" ===
679679
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&

compiled/facebook-www/React-profiling.modern.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -673,7 +673,7 @@ exports.useSyncExternalStore = function (
673673
exports.useTransition = function () {
674674
return ReactSharedInternals.H.useTransition();
675675
};
676-
exports.version = "19.0.0-www-modern-349a99a7a3-20240626";
676+
exports.version = "19.0.0-www-modern-e02baf6c92-20240627";
677677
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
678678
"function" ===
679679
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&

compiled/facebook-www/ReactART-dev.classic.js

Lines changed: 52 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -2836,6 +2836,7 @@ __DEV__ &&
28362836
if ("children" !== key && "key" !== key) {
28372837
null === fiber &&
28382838
((fiber = createFiberFromElement(element, returnFiber.mode, 0)),
2839+
(fiber._debugInfo = currentDebugInfo),
28392840
(fiber.return = returnFiber));
28402841
runWithFiberInDEV(
28412842
fiber,
@@ -14444,61 +14445,59 @@ __DEV__ &&
1444414445
break;
1444514446
case REACT_PROFILER_TYPE:
1444614447
return (
14447-
(type = mode),
14448-
"string" !== typeof pendingProps.id &&
14448+
(type = pendingProps),
14449+
"string" !== typeof type.id &&
1444914450
error$jscomp$0(
1445014451
'Profiler must specify an "id" of type `string` as a prop. Received the type `%s` instead.',
14451-
typeof pendingProps.id
14452+
typeof type.id
1445214453
),
14453-
(type = createFiber(12, pendingProps, key, type | 2)),
14454-
(type.elementType = REACT_PROFILER_TYPE),
14455-
(type.lanes = lanes),
14456-
(type.stateNode = {
14457-
effectDuration: 0,
14458-
passiveEffectDuration: 0
14459-
}),
14460-
type
14454+
(key = createFiber(12, type, key, mode | 2)),
14455+
(key.elementType = REACT_PROFILER_TYPE),
14456+
(key.lanes = lanes),
14457+
(key.stateNode = { effectDuration: 0, passiveEffectDuration: 0 }),
14458+
key
1446114459
);
1446214460
case REACT_SUSPENSE_TYPE:
1446314461
return (
14464-
(type = createFiber(13, pendingProps, key, mode)),
14465-
(type.elementType = REACT_SUSPENSE_TYPE),
14466-
(type.lanes = lanes),
14467-
type
14462+
(key = createFiber(13, pendingProps, key, mode)),
14463+
(key.elementType = REACT_SUSPENSE_TYPE),
14464+
(key.lanes = lanes),
14465+
key
1446814466
);
1446914467
case REACT_SUSPENSE_LIST_TYPE:
1447014468
return (
14471-
(type = createFiber(19, pendingProps, key, mode)),
14472-
(type.elementType = REACT_SUSPENSE_LIST_TYPE),
14473-
(type.lanes = lanes),
14474-
type
14469+
(key = createFiber(19, pendingProps, key, mode)),
14470+
(key.elementType = REACT_SUSPENSE_LIST_TYPE),
14471+
(key.lanes = lanes),
14472+
key
1447514473
);
1447614474
case REACT_OFFSCREEN_TYPE:
1447714475
return createFiberFromOffscreen(pendingProps, mode, lanes, key);
1447814476
case REACT_LEGACY_HIDDEN_TYPE:
1447914477
return createFiberFromLegacyHidden(pendingProps, mode, lanes, key);
1448014478
case REACT_SCOPE_TYPE:
1448114479
return (
14482-
(owner = createFiber(21, pendingProps, key, mode)),
14483-
(owner.type = type),
14484-
(owner.elementType = type),
14485-
(owner.lanes = lanes),
14486-
owner
14480+
(key = createFiber(21, pendingProps, key, mode)),
14481+
(key.type = type),
14482+
(key.elementType = type),
14483+
(key.lanes = lanes),
14484+
key
1448714485
);
1448814486
case REACT_TRACING_MARKER_TYPE:
1448914487
if (enableTransitionTracing)
1449014488
return (
14491-
(type = createFiber(25, pendingProps, key, mode)),
14492-
(type.elementType = REACT_TRACING_MARKER_TYPE),
14493-
(type.lanes = lanes),
14494-
(type.stateNode = {
14489+
(type = pendingProps),
14490+
(key = createFiber(25, type, key, mode)),
14491+
(key.elementType = REACT_TRACING_MARKER_TYPE),
14492+
(key.lanes = lanes),
14493+
(key.stateNode = {
1449514494
tag: TransitionTracingMarker,
1449614495
transitions: null,
1449714496
pendingBoundaries: null,
1449814497
aborts: null,
14499-
name: pendingProps.name
14498+
name: type.name
1450014499
}),
14501-
type
14500+
key
1450214501
);
1450314502
case REACT_DEBUG_TRACING_MODE_TYPE:
1450414503
if (enableDebugTracing) {
@@ -14534,47 +14533,50 @@ __DEV__ &&
1453414533
resolvedType = null;
1453514534
break a;
1453614535
}
14537-
lanes = "";
14536+
resolvedType = "";
1453814537
if (
1453914538
void 0 === type ||
1454014539
("object" === typeof type &&
1454114540
null !== type &&
1454214541
0 === Object.keys(type).length)
1454314542
)
14544-
lanes +=
14543+
resolvedType +=
1454514544
" You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.";
1454614545
null === type
14547-
? (type = "null")
14546+
? (pendingProps = "null")
1454814547
: isArrayImpl(type)
14549-
? (type = "array")
14548+
? (pendingProps = "array")
1455014549
: void 0 !== type && type.$$typeof === REACT_ELEMENT_TYPE
14551-
? ((type =
14550+
? ((pendingProps =
1455214551
"<" +
1455314552
(getComponentNameFromType(type.type) || "Unknown") +
1455414553
" />"),
14555-
(lanes =
14554+
(resolvedType =
1455614555
" Did you accidentally export a JSX literal instead of a component?"))
14557-
: (type = typeof type);
14558-
owner = owner
14556+
: (pendingProps = typeof type);
14557+
fiberTag = owner
1455914558
? "number" === typeof owner.tag
1456014559
? getComponentNameFromFiber(owner)
1456114560
: "string" === typeof owner.name
1456214561
? owner.name
1456314562
: null
1456414563
: null;
14565-
owner &&
14566-
(lanes += "\n\nCheck the render method of `" + owner + "`.");
14567-
throw Error(
14564+
fiberTag &&
14565+
(resolvedType +=
14566+
"\n\nCheck the render method of `" + fiberTag + "`.");
14567+
fiberTag = 29;
14568+
pendingProps = Error(
1456814569
"Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: " +
14569-
(type + "." + lanes)
14570+
(pendingProps + "." + resolvedType)
1457014571
);
14572+
resolvedType = null;
1457114573
}
14572-
pendingProps = createFiber(fiberTag, pendingProps, key, mode);
14573-
pendingProps.elementType = type;
14574-
pendingProps.type = resolvedType;
14575-
pendingProps.lanes = lanes;
14576-
pendingProps._debugOwner = owner;
14577-
return pendingProps;
14574+
key = createFiber(fiberTag, pendingProps, key, mode);
14575+
key.elementType = type;
14576+
key.type = resolvedType;
14577+
key.lanes = lanes;
14578+
key._debugOwner = owner;
14579+
return key;
1457814580
}
1457914581
function createFiberFromElement(element, mode, lanes) {
1458014582
mode = createFiberFromTypeAndProps(
@@ -16932,14 +16934,14 @@ __DEV__ &&
1693216934
scheduleRoot: scheduleRoot,
1693316935
setRefreshHandler: setRefreshHandler,
1693416936
getCurrentFiber: getCurrentFiberForDevTools,
16935-
reconcilerVersion: "19.0.0-www-classic-349a99a7a3-20240626"
16937+
reconcilerVersion: "19.0.0-www-classic-e02baf6c92-20240627"
1693616938
});
1693716939
})({
1693816940
findFiberByHostInstance: function () {
1693916941
return null;
1694016942
},
1694116943
bundleType: 1,
16942-
version: "19.0.0-www-classic-349a99a7a3-20240626",
16944+
version: "19.0.0-www-classic-e02baf6c92-20240627",
1694316945
rendererPackageName: "react-art"
1694416946
});
1694516947
var ClippingRectangle = TYPES.CLIPPING_RECTANGLE,

0 commit comments

Comments
 (0)