Skip to content

Commit

Permalink
Warn for invalid type in renderer with the correct RSC stack (faceboo…
Browse files Browse the repository at this point in the history
…k#30102)

This is all behind the `enableOwnerStacks` flag.

This is a follow up to facebook#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 commit facebook@e02baf6.
  • Loading branch information
sebmarkbage committed Jun 27, 2024
1 parent 54bd813 commit 0ee0a32
Show file tree
Hide file tree
Showing 14 changed files with 155 additions and 137 deletions.
2 changes: 1 addition & 1 deletion compiled-rn/VERSION_NATIVE_FB
Original file line number Diff line number Diff line change
@@ -1 +1 @@
19.0.0-native-fb-ffec9ec5b5-20240627
19.0.0-native-fb-e02baf6c92-20240627
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @noflow
* @nolint
* @preventMunge
* @generated SignedSource<<44d1ab19516f0dc7115b3084b1b6983a>>
* @generated SignedSource<<42baca610fefec93b87cf45e12c0249d>>
*/

"use strict";
Expand Down Expand Up @@ -2442,6 +2442,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 @@ -12527,34 +12528,32 @@ __DEV__ &&
break;
case REACT_PROFILER_TYPE:
return (
(type = pendingProps),
(owner = mode),
"string" !== typeof pendingProps.id &&
"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
),
(owner = createFiber(12, pendingProps, key, owner | 2)),
(owner.elementType = REACT_PROFILER_TYPE),
(owner.lanes = lanes),
(owner.stateNode = {
effectDuration: 0,
passiveEffectDuration: 0
}),
owner
(key = createFiber(12, type, key, owner | 2)),
(key.elementType = REACT_PROFILER_TYPE),
(key.lanes = lanes),
(key.stateNode = { effectDuration: 0, passiveEffectDuration: 0 }),
key
);
case REACT_SUSPENSE_TYPE:
return (
(owner = createFiber(13, pendingProps, key, mode)),
(owner.elementType = REACT_SUSPENSE_TYPE),
(owner.lanes = lanes),
owner
(key = createFiber(13, pendingProps, key, mode)),
(key.elementType = REACT_SUSPENSE_TYPE),
(key.lanes = lanes),
key
);
case REACT_SUSPENSE_LIST_TYPE:
return (
(owner = createFiber(19, pendingProps, key, mode)),
(owner.elementType = REACT_SUSPENSE_LIST_TYPE),
(owner.lanes = lanes),
owner
(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);
Expand All @@ -12580,40 +12579,43 @@ __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;
}
key = createFiber(fiberTag, pendingProps, key, mode);
key.elementType = type;
Expand Down Expand Up @@ -15070,14 +15072,14 @@ __DEV__ &&
scheduleRoot: scheduleRoot,
setRefreshHandler: setRefreshHandler,
getCurrentFiber: getCurrentFiberForDevTools,
reconcilerVersion: "19.0.0-native-fb-ffec9ec5b5-20240627"
reconcilerVersion: "19.0.0-native-fb-e02baf6c92-20240627"
});
})({
findFiberByHostInstance: function () {
throw Error("TestRenderer does not support findFiberByHostInstance()");
},
bundleType: 1,
version: "19.0.0-native-fb-ffec9ec5b5-20240627",
version: "19.0.0-native-fb-e02baf6c92-20240627",
rendererPackageName: "react-test-renderer"
});
exports._Scheduler = Scheduler;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @noflow
* @nolint
* @preventMunge
* @generated SignedSource<<718ff5e34ce4342f80f8cd32c0855485>>
* @generated SignedSource<<f5de4052aa29bedfe407f3611b05a317>>
*/

"use strict";
Expand Down Expand Up @@ -8869,10 +8869,12 @@ function createFiberFromTypeAndProps(
owner = null;
break a;
}
throw Error(
fiberTag = 29;
pendingProps = Error(
"Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: " +
((null === type ? "null" : typeof type) + ".")
);
owner = null;
}
key = createFiber(fiberTag, pendingProps, key, mode);
key.elementType = type;
Expand Down Expand Up @@ -9397,7 +9399,7 @@ var devToolsConfig$jscomp$inline_1034 = {
throw Error("TestRenderer does not support findFiberByHostInstance()");
},
bundleType: 0,
version: "19.0.0-native-fb-ffec9ec5b5-20240627",
version: "19.0.0-native-fb-e02baf6c92-20240627",
rendererPackageName: "react-test-renderer"
};
var internals$jscomp$inline_1223 = {
Expand Down Expand Up @@ -9428,7 +9430,7 @@ var internals$jscomp$inline_1223 = {
scheduleRoot: null,
setRefreshHandler: null,
getCurrentFiber: null,
reconcilerVersion: "19.0.0-native-fb-ffec9ec5b5-20240627"
reconcilerVersion: "19.0.0-native-fb-e02baf6c92-20240627"
};
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
var hook$jscomp$inline_1224 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @noflow
* @nolint
* @preventMunge
* @generated SignedSource<<c46fe24487d3b639d3f58189945d6b49>>
* @generated SignedSource<<af4ea00784664da9aaa9bc4db9dca3f0>>
*/

"use strict";
Expand Down Expand Up @@ -9484,10 +9484,12 @@ function createFiberFromTypeAndProps(
owner = null;
break a;
}
throw Error(
fiberTag = 29;
pendingProps = Error(
"Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: " +
((null === type ? "null" : typeof type) + ".")
);
owner = null;
}
key = createFiber(fiberTag, pendingProps, key, mode);
key.elementType = type;
Expand Down Expand Up @@ -10017,7 +10019,7 @@ var devToolsConfig$jscomp$inline_1117 = {
throw Error("TestRenderer does not support findFiberByHostInstance()");
},
bundleType: 0,
version: "19.0.0-native-fb-ffec9ec5b5-20240627",
version: "19.0.0-native-fb-e02baf6c92-20240627",
rendererPackageName: "react-test-renderer"
};
(function (internals) {
Expand Down Expand Up @@ -10061,7 +10063,7 @@ var devToolsConfig$jscomp$inline_1117 = {
scheduleRoot: null,
setRefreshHandler: null,
getCurrentFiber: null,
reconcilerVersion: "19.0.0-native-fb-ffec9ec5b5-20240627"
reconcilerVersion: "19.0.0-native-fb-e02baf6c92-20240627"
});
exports._Scheduler = Scheduler;
exports.act = act;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @noflow
* @nolint
* @preventMunge
* @generated SignedSource<<fe33295fc61cdcf79ee85f36a7be4698>>
* @generated SignedSource<<547bd318a581226337229e507fdff7e4>>
*/

"use strict";
Expand Down Expand Up @@ -1741,7 +1741,7 @@ __DEV__ &&
exports.useTransition = function () {
return resolveDispatcher().useTransition();
};
exports.version = "19.0.0-native-fb-ffec9ec5b5-20240627";
exports.version = "19.0.0-native-fb-e02baf6c92-20240627";
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
"function" ===
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @noflow
* @nolint
* @preventMunge
* @generated SignedSource<<4f2a029ed6d83dece5be6850f80680a9>>
* @generated SignedSource<<f500c5a68996ef417fddaed92745aa08>>
*/

"use strict";
Expand Down Expand Up @@ -604,4 +604,4 @@ exports.useSyncExternalStore = function (
exports.useTransition = function () {
return ReactSharedInternals.H.useTransition();
};
exports.version = "19.0.0-native-fb-ffec9ec5b5-20240627";
exports.version = "19.0.0-native-fb-e02baf6c92-20240627";
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @noflow
* @nolint
* @preventMunge
* @generated SignedSource<<f990feb6dde9284b1bec4cd8dcdf2e3b>>
* @generated SignedSource<<8fed01692ebeb6102c3169cea0452442>>
*/

"use strict";
Expand Down Expand Up @@ -608,7 +608,7 @@ exports.useSyncExternalStore = function (
exports.useTransition = function () {
return ReactSharedInternals.H.useTransition();
};
exports.version = "19.0.0-native-fb-ffec9ec5b5-20240627";
exports.version = "19.0.0-native-fb-e02baf6c92-20240627";
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
"function" ===
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
ffec9ec5b5c846f61d7b40e92f138e2a7b34f273
e02baf6c92833a0d45a77fb2e741676f393c24f7
Loading

0 comments on commit 0ee0a32

Please sign in to comment.