Skip to content

Commit

Permalink
Track Owner for Server Components in DEV (#28753)
Browse files Browse the repository at this point in the history
This implements the concept of a DEV-only "owner" for Server Components.
The owner concept isn't really super useful. We barely use it anymore,
but we do have it as a concept in DevTools in a couple of cases so this
adds it for parity. However, this is mainly interesting because it could
be used to wire up future owner-based stacks.

I do this by outlining the DebugInfo for a Server Component
(ReactComponentInfo). Then I just rely on Flight deduping to refer to
that. I refer to the same thing by referential equality so that we can
associate a Server Component parent in DebugInfo with an owner.

If you suspend and replay a Server Component, we have to restore the
same owner. To do that, I did a little ugly hack and stashed it on the
thenable state object. Felt unnecessarily complicated to add a stateful
wrapper for this one dev-only case.

The owner could really be anything since it could be coming from a
different implementation. Because this is the first time we have an
owner other than Fiber, I have to fix up a bunch of places that assumes
Fiber. I mainly did the `typeof owner.tag === 'number'` to assume it's a
Fiber for now.

This also doesn't actually add it to DevTools / RN Inspector yet. I just
ignore them there for now.

Because Server Components can be async the owner isn't tracked after an
await. We need per-component AsyncLocalStorage for that. This can be
done in a follow up.

DiffTrain build for [e0455fe](e0455fe)
  • Loading branch information
kassens committed Apr 11, 2024
1 parent 60928e3 commit 2b619ee
Show file tree
Hide file tree
Showing 30 changed files with 640 additions and 475 deletions.
35 changes: 16 additions & 19 deletions compiled/facebook-www/JSXDEVRuntime-dev.classic.js
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,7 @@ if (__DEV__) {

var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher;
var prefix;
function describeBuiltInComponentFrame(name, ownerFn) {
function describeBuiltInComponentFrame(name) {
{
if (prefix === undefined) {
// Extract the VM specific prefix used by each line.
Expand Down Expand Up @@ -740,7 +740,7 @@ if (__DEV__) {

return syntheticFrame;
}
function describeFunctionComponentFrame(fn, ownerFn) {
function describeFunctionComponentFrame(fn) {
{
return describeNativeComponentFrame(fn, false);
}
Expand All @@ -751,7 +751,7 @@ if (__DEV__) {
return !!(prototype && prototype.isReactComponent);
}

function describeUnknownElementTypeFrameInDEV(type, ownerFn) {
function describeUnknownElementTypeFrameInDEV(type) {
if (type == null) {
return "";
}
Expand Down Expand Up @@ -781,7 +781,7 @@ if (__DEV__) {

case REACT_MEMO_TYPE:
// Memo may contain any component type so we recursively resolve it.
return describeUnknownElementTypeFrameInDEV(type.type, ownerFn);
return describeUnknownElementTypeFrameInDEV(type.type);

case REACT_LAZY_TYPE: {
var lazyComponent = type;
Expand All @@ -790,10 +790,7 @@ if (__DEV__) {

try {
// Lazy may contain any component type so we recursively resolve it.
return describeUnknownElementTypeFrameInDEV(
init(payload),
ownerFn
);
return describeUnknownElementTypeFrameInDEV(init(payload));
} catch (x) {}
}
}
Expand Down Expand Up @@ -1397,14 +1394,18 @@ if (__DEV__) {

if (
element &&
element._owner &&
element._owner != null &&
element._owner !== ReactCurrentOwner.current
) {
// Give the component that originally created this child.
childOwner =
" It was passed a child from " +
getComponentNameFromType(element._owner.type) +
".";
var ownerName = null;

if (typeof element._owner.tag === "number") {
ownerName = getComponentNameFromType(element._owner.type);
} else if (typeof element._owner.name === "string") {
ownerName = element._owner.name;
} // Give the component that originally created this child.

childOwner = " It was passed a child from " + ownerName + ".";
}

setCurrentlyValidatingElement(element);
Expand All @@ -1423,11 +1424,7 @@ if (__DEV__) {
function setCurrentlyValidatingElement(element) {
{
if (element) {
var owner = element._owner;
var stack = describeUnknownElementTypeFrameInDEV(
element.type,
owner ? owner.type : null
);
var stack = describeUnknownElementTypeFrameInDEV(element.type);
ReactDebugCurrentFrame.setExtraStackFrame(stack);
} else {
ReactDebugCurrentFrame.setExtraStackFrame(null);
Expand Down
35 changes: 16 additions & 19 deletions compiled/facebook-www/JSXDEVRuntime-dev.modern.js
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,7 @@ if (__DEV__) {

var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher;
var prefix;
function describeBuiltInComponentFrame(name, ownerFn) {
function describeBuiltInComponentFrame(name) {
{
if (prefix === undefined) {
// Extract the VM specific prefix used by each line.
Expand Down Expand Up @@ -740,7 +740,7 @@ if (__DEV__) {

return syntheticFrame;
}
function describeFunctionComponentFrame(fn, ownerFn) {
function describeFunctionComponentFrame(fn) {
{
return describeNativeComponentFrame(fn, false);
}
Expand All @@ -751,7 +751,7 @@ if (__DEV__) {
return !!(prototype && prototype.isReactComponent);
}

function describeUnknownElementTypeFrameInDEV(type, ownerFn) {
function describeUnknownElementTypeFrameInDEV(type) {
if (type == null) {
return "";
}
Expand Down Expand Up @@ -781,7 +781,7 @@ if (__DEV__) {

case REACT_MEMO_TYPE:
// Memo may contain any component type so we recursively resolve it.
return describeUnknownElementTypeFrameInDEV(type.type, ownerFn);
return describeUnknownElementTypeFrameInDEV(type.type);

case REACT_LAZY_TYPE: {
var lazyComponent = type;
Expand All @@ -790,10 +790,7 @@ if (__DEV__) {

try {
// Lazy may contain any component type so we recursively resolve it.
return describeUnknownElementTypeFrameInDEV(
init(payload),
ownerFn
);
return describeUnknownElementTypeFrameInDEV(init(payload));
} catch (x) {}
}
}
Expand Down Expand Up @@ -1397,14 +1394,18 @@ if (__DEV__) {

if (
element &&
element._owner &&
element._owner != null &&
element._owner !== ReactCurrentOwner.current
) {
// Give the component that originally created this child.
childOwner =
" It was passed a child from " +
getComponentNameFromType(element._owner.type) +
".";
var ownerName = null;

if (typeof element._owner.tag === "number") {
ownerName = getComponentNameFromType(element._owner.type);
} else if (typeof element._owner.name === "string") {
ownerName = element._owner.name;
} // Give the component that originally created this child.

childOwner = " It was passed a child from " + ownerName + ".";
}

setCurrentlyValidatingElement(element);
Expand All @@ -1423,11 +1424,7 @@ if (__DEV__) {
function setCurrentlyValidatingElement(element) {
{
if (element) {
var owner = element._owner;
var stack = describeUnknownElementTypeFrameInDEV(
element.type,
owner ? owner.type : null
);
var stack = describeUnknownElementTypeFrameInDEV(element.type);
ReactDebugCurrentFrame.setExtraStackFrame(stack);
} else {
ReactDebugCurrentFrame.setExtraStackFrame(null);
Expand Down
2 changes: 1 addition & 1 deletion compiled/facebook-www/REVISION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
48b4ecc9012638ed51b275aad24b2086b8215e32
e0455fe62a648f541d2e029017465ae4b5f000a8
37 changes: 17 additions & 20 deletions compiled/facebook-www/React-dev.classic.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ if (__DEV__) {
) {
__REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(new Error());
}
var ReactVersion = "19.0.0-www-classic-b9e0eea7";
var ReactVersion = "19.0.0-www-classic-8aa01ae9";

// ATTENTION
// When adding new symbols to this file,
Expand Down Expand Up @@ -843,7 +843,7 @@ if (__DEV__) {

var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher;
var prefix;
function describeBuiltInComponentFrame(name, ownerFn) {
function describeBuiltInComponentFrame(name) {
{
if (prefix === undefined) {
// Extract the VM specific prefix used by each line.
Expand Down Expand Up @@ -1112,7 +1112,7 @@ if (__DEV__) {

return syntheticFrame;
}
function describeFunctionComponentFrame(fn, ownerFn) {
function describeFunctionComponentFrame(fn) {
{
return describeNativeComponentFrame(fn, false);
}
Expand All @@ -1123,7 +1123,7 @@ if (__DEV__) {
return !!(prototype && prototype.isReactComponent);
}

function describeUnknownElementTypeFrameInDEV(type, ownerFn) {
function describeUnknownElementTypeFrameInDEV(type) {
if (type == null) {
return "";
}
Expand Down Expand Up @@ -1153,7 +1153,7 @@ if (__DEV__) {

case REACT_MEMO_TYPE:
// Memo may contain any component type so we recursively resolve it.
return describeUnknownElementTypeFrameInDEV(type.type, ownerFn);
return describeUnknownElementTypeFrameInDEV(type.type);

case REACT_LAZY_TYPE: {
var lazyComponent = type;
Expand All @@ -1162,10 +1162,7 @@ if (__DEV__) {

try {
// Lazy may contain any component type so we recursively resolve it.
return describeUnknownElementTypeFrameInDEV(
init(payload),
ownerFn
);
return describeUnknownElementTypeFrameInDEV(init(payload));
} catch (x) {}
}
}
Expand Down Expand Up @@ -2097,14 +2094,18 @@ if (__DEV__) {

if (
element &&
element._owner &&
element._owner != null &&
element._owner !== ReactCurrentOwner.current
) {
// Give the component that originally created this child.
childOwner =
" It was passed a child from " +
getComponentNameFromType(element._owner.type) +
".";
var ownerName = null;

if (typeof element._owner.tag === "number") {
ownerName = getComponentNameFromType(element._owner.type);
} else if (typeof element._owner.name === "string") {
ownerName = element._owner.name;
} // Give the component that originally created this child.

childOwner = " It was passed a child from " + ownerName + ".";
}

setCurrentlyValidatingElement(element);
Expand All @@ -2123,11 +2124,7 @@ if (__DEV__) {
function setCurrentlyValidatingElement(element) {
{
if (element) {
var owner = element._owner;
var stack = describeUnknownElementTypeFrameInDEV(
element.type,
owner ? owner.type : null
);
var stack = describeUnknownElementTypeFrameInDEV(element.type);
ReactDebugCurrentFrame.setExtraStackFrame(stack);
} else {
ReactDebugCurrentFrame.setExtraStackFrame(null);
Expand Down
37 changes: 17 additions & 20 deletions compiled/facebook-www/React-dev.modern.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ if (__DEV__) {
) {
__REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(new Error());
}
var ReactVersion = "19.0.0-www-modern-3a8173ed";
var ReactVersion = "19.0.0-www-modern-ab03ab4b";

// ATTENTION
// When adding new symbols to this file,
Expand Down Expand Up @@ -843,7 +843,7 @@ if (__DEV__) {

var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher;
var prefix;
function describeBuiltInComponentFrame(name, ownerFn) {
function describeBuiltInComponentFrame(name) {
{
if (prefix === undefined) {
// Extract the VM specific prefix used by each line.
Expand Down Expand Up @@ -1112,7 +1112,7 @@ if (__DEV__) {

return syntheticFrame;
}
function describeFunctionComponentFrame(fn, ownerFn) {
function describeFunctionComponentFrame(fn) {
{
return describeNativeComponentFrame(fn, false);
}
Expand All @@ -1123,7 +1123,7 @@ if (__DEV__) {
return !!(prototype && prototype.isReactComponent);
}

function describeUnknownElementTypeFrameInDEV(type, ownerFn) {
function describeUnknownElementTypeFrameInDEV(type) {
if (type == null) {
return "";
}
Expand Down Expand Up @@ -1153,7 +1153,7 @@ if (__DEV__) {

case REACT_MEMO_TYPE:
// Memo may contain any component type so we recursively resolve it.
return describeUnknownElementTypeFrameInDEV(type.type, ownerFn);
return describeUnknownElementTypeFrameInDEV(type.type);

case REACT_LAZY_TYPE: {
var lazyComponent = type;
Expand All @@ -1162,10 +1162,7 @@ if (__DEV__) {

try {
// Lazy may contain any component type so we recursively resolve it.
return describeUnknownElementTypeFrameInDEV(
init(payload),
ownerFn
);
return describeUnknownElementTypeFrameInDEV(init(payload));
} catch (x) {}
}
}
Expand Down Expand Up @@ -2097,14 +2094,18 @@ if (__DEV__) {

if (
element &&
element._owner &&
element._owner != null &&
element._owner !== ReactCurrentOwner.current
) {
// Give the component that originally created this child.
childOwner =
" It was passed a child from " +
getComponentNameFromType(element._owner.type) +
".";
var ownerName = null;

if (typeof element._owner.tag === "number") {
ownerName = getComponentNameFromType(element._owner.type);
} else if (typeof element._owner.name === "string") {
ownerName = element._owner.name;
} // Give the component that originally created this child.

childOwner = " It was passed a child from " + ownerName + ".";
}

setCurrentlyValidatingElement(element);
Expand All @@ -2123,11 +2124,7 @@ if (__DEV__) {
function setCurrentlyValidatingElement(element) {
{
if (element) {
var owner = element._owner;
var stack = describeUnknownElementTypeFrameInDEV(
element.type,
owner ? owner.type : null
);
var stack = describeUnknownElementTypeFrameInDEV(element.type);
ReactDebugCurrentFrame.setExtraStackFrame(stack);
} else {
ReactDebugCurrentFrame.setExtraStackFrame(null);
Expand Down
Loading

0 comments on commit 2b619ee

Please sign in to comment.