Skip to content

Commit

Permalink
Warn for invalid type in renderer with the correct RSC stack (#30102)
Browse files Browse the repository at this point in the history
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)
  • Loading branch information
sebmarkbage committed Jun 27, 2024
1 parent 4365cb3 commit 0f2a59e
Show file tree
Hide file tree
Showing 34 changed files with 728 additions and 672 deletions.
2 changes: 1 addition & 1 deletion compiled/facebook-www/REVISION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
349a99a7a347f280ce40e9297cac5a3bd796901e
e02baf6c92833a0d45a77fb2e741676f393c24f7
2 changes: 1 addition & 1 deletion compiled/facebook-www/REVISION_TRANSFORMS
Original file line number Diff line number Diff line change
@@ -1 +1 @@
349a99a7a347f280ce40e9297cac5a3bd796901e
e02baf6c92833a0d45a77fb2e741676f393c24f7
2 changes: 1 addition & 1 deletion compiled/facebook-www/React-dev.classic.js
Original file line number Diff line number Diff line change
Expand Up @@ -1991,7 +1991,7 @@ __DEV__ &&
exports.useTransition = function () {
return resolveDispatcher().useTransition();
};
exports.version = "19.0.0-www-classic-349a99a7a3-20240626";
exports.version = "19.0.0-www-classic-e02baf6c92-20240627";
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
"function" ===
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&
Expand Down
2 changes: 1 addition & 1 deletion compiled/facebook-www/React-dev.modern.js
Original file line number Diff line number Diff line change
Expand Up @@ -1971,7 +1971,7 @@ __DEV__ &&
exports.useTransition = function () {
return resolveDispatcher().useTransition();
};
exports.version = "19.0.0-www-modern-349a99a7a3-20240626";
exports.version = "19.0.0-www-modern-e02baf6c92-20240627";
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
"function" ===
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&
Expand Down
2 changes: 1 addition & 1 deletion compiled/facebook-www/React-prod.classic.js
Original file line number Diff line number Diff line change
Expand Up @@ -669,4 +669,4 @@ exports.useSyncExternalStore = function (
exports.useTransition = function () {
return ReactSharedInternals.H.useTransition();
};
exports.version = "19.0.0-www-classic-349a99a7a3-20240626";
exports.version = "19.0.0-www-classic-e02baf6c92-20240627";
2 changes: 1 addition & 1 deletion compiled/facebook-www/React-prod.modern.js
Original file line number Diff line number Diff line change
Expand Up @@ -669,4 +669,4 @@ exports.useSyncExternalStore = function (
exports.useTransition = function () {
return ReactSharedInternals.H.useTransition();
};
exports.version = "19.0.0-www-modern-349a99a7a3-20240626";
exports.version = "19.0.0-www-modern-e02baf6c92-20240627";
2 changes: 1 addition & 1 deletion compiled/facebook-www/React-profiling.classic.js
Original file line number Diff line number Diff line change
Expand Up @@ -673,7 +673,7 @@ exports.useSyncExternalStore = function (
exports.useTransition = function () {
return ReactSharedInternals.H.useTransition();
};
exports.version = "19.0.0-www-classic-349a99a7a3-20240626";
exports.version = "19.0.0-www-classic-e02baf6c92-20240627";
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
"function" ===
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&
Expand Down
2 changes: 1 addition & 1 deletion compiled/facebook-www/React-profiling.modern.js
Original file line number Diff line number Diff line change
Expand Up @@ -673,7 +673,7 @@ exports.useSyncExternalStore = function (
exports.useTransition = function () {
return ReactSharedInternals.H.useTransition();
};
exports.version = "19.0.0-www-modern-349a99a7a3-20240626";
exports.version = "19.0.0-www-modern-e02baf6c92-20240627";
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
"function" ===
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&
Expand Down
102 changes: 52 additions & 50 deletions compiled/facebook-www/ReactART-dev.classic.js
Original file line number Diff line number Diff line change
Expand Up @@ -2836,6 +2836,7 @@ __DEV__ &&
if ("children" !== key && "key" !== key) {
null === fiber &&
((fiber = createFiberFromElement(element, returnFiber.mode, 0)),
(fiber._debugInfo = currentDebugInfo),
(fiber.return = returnFiber));
runWithFiberInDEV(
fiber,
Expand Down Expand Up @@ -14444,61 +14445,59 @@ __DEV__ &&
break;
case REACT_PROFILER_TYPE:
return (
(type = mode),
"string" !== typeof pendingProps.id &&
(type = pendingProps),
"string" !== typeof type.id &&
error$jscomp$0(
'Profiler must specify an "id" of type `string` as a prop. Received the type `%s` instead.',
typeof pendingProps.id
typeof type.id
),
(type = createFiber(12, pendingProps, key, type | 2)),
(type.elementType = REACT_PROFILER_TYPE),
(type.lanes = lanes),
(type.stateNode = {
effectDuration: 0,
passiveEffectDuration: 0
}),
type
(key = createFiber(12, type, key, mode | 2)),
(key.elementType = REACT_PROFILER_TYPE),
(key.lanes = lanes),
(key.stateNode = { effectDuration: 0, passiveEffectDuration: 0 }),
key
);
case REACT_SUSPENSE_TYPE:
return (
(type = createFiber(13, pendingProps, key, mode)),
(type.elementType = REACT_SUSPENSE_TYPE),
(type.lanes = lanes),
type
(key = createFiber(13, pendingProps, key, mode)),
(key.elementType = REACT_SUSPENSE_TYPE),
(key.lanes = lanes),
key
);
case REACT_SUSPENSE_LIST_TYPE:
return (
(type = createFiber(19, pendingProps, key, mode)),
(type.elementType = REACT_SUSPENSE_LIST_TYPE),
(type.lanes = lanes),
type
(key = createFiber(19, pendingProps, key, mode)),
(key.elementType = REACT_SUSPENSE_LIST_TYPE),
(key.lanes = lanes),
key
);
case REACT_OFFSCREEN_TYPE:
return createFiberFromOffscreen(pendingProps, mode, lanes, key);
case REACT_LEGACY_HIDDEN_TYPE:
return createFiberFromLegacyHidden(pendingProps, mode, lanes, key);
case REACT_SCOPE_TYPE:
return (
(owner = createFiber(21, pendingProps, key, mode)),
(owner.type = type),
(owner.elementType = type),
(owner.lanes = lanes),
owner
(key = createFiber(21, pendingProps, key, mode)),
(key.type = type),
(key.elementType = type),
(key.lanes = lanes),
key
);
case REACT_TRACING_MARKER_TYPE:
if (enableTransitionTracing)
return (
(type = createFiber(25, pendingProps, key, mode)),
(type.elementType = REACT_TRACING_MARKER_TYPE),
(type.lanes = lanes),
(type.stateNode = {
(type = pendingProps),
(key = createFiber(25, type, key, mode)),
(key.elementType = REACT_TRACING_MARKER_TYPE),
(key.lanes = lanes),
(key.stateNode = {
tag: TransitionTracingMarker,
transitions: null,
pendingBoundaries: null,
aborts: null,
name: pendingProps.name
name: type.name
}),
type
key
);
case REACT_DEBUG_TRACING_MODE_TYPE:
if (enableDebugTracing) {
Expand Down Expand Up @@ -14534,47 +14533,50 @@ __DEV__ &&
resolvedType = null;
break a;
}
lanes = "";
resolvedType = "";
if (
void 0 === type ||
("object" === typeof type &&
null !== type &&
0 === Object.keys(type).length)
)
lanes +=
resolvedType +=
" You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.";
null === type
? (type = "null")
? (pendingProps = "null")
: isArrayImpl(type)
? (type = "array")
? (pendingProps = "array")
: void 0 !== type && type.$$typeof === REACT_ELEMENT_TYPE
? ((type =
? ((pendingProps =
"<" +
(getComponentNameFromType(type.type) || "Unknown") +
" />"),
(lanes =
(resolvedType =
" Did you accidentally export a JSX literal instead of a component?"))
: (type = typeof type);
owner = owner
: (pendingProps = typeof type);
fiberTag = owner
? "number" === typeof owner.tag
? getComponentNameFromFiber(owner)
: "string" === typeof owner.name
? owner.name
: null
: null;
owner &&
(lanes += "\n\nCheck the render method of `" + owner + "`.");
throw Error(
fiberTag &&
(resolvedType +=
"\n\nCheck the render method of `" + fiberTag + "`.");
fiberTag = 29;
pendingProps = Error(
"Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: " +
(type + "." + lanes)
(pendingProps + "." + resolvedType)
);
resolvedType = null;
}
pendingProps = createFiber(fiberTag, pendingProps, key, mode);
pendingProps.elementType = type;
pendingProps.type = resolvedType;
pendingProps.lanes = lanes;
pendingProps._debugOwner = owner;
return pendingProps;
key = createFiber(fiberTag, pendingProps, key, mode);
key.elementType = type;
key.type = resolvedType;
key.lanes = lanes;
key._debugOwner = owner;
return key;
}
function createFiberFromElement(element, mode, lanes) {
mode = createFiberFromTypeAndProps(
Expand Down Expand Up @@ -16932,14 +16934,14 @@ __DEV__ &&
scheduleRoot: scheduleRoot,
setRefreshHandler: setRefreshHandler,
getCurrentFiber: getCurrentFiberForDevTools,
reconcilerVersion: "19.0.0-www-classic-349a99a7a3-20240626"
reconcilerVersion: "19.0.0-www-classic-e02baf6c92-20240627"
});
})({
findFiberByHostInstance: function () {
return null;
},
bundleType: 1,
version: "19.0.0-www-classic-349a99a7a3-20240626",
version: "19.0.0-www-classic-e02baf6c92-20240627",
rendererPackageName: "react-art"
});
var ClippingRectangle = TYPES.CLIPPING_RECTANGLE,
Expand Down
Loading

0 comments on commit 0f2a59e

Please sign in to comment.