Skip to content

Commit b50214b

Browse files
committed
[Flight] Update stale blocked values in createModelResolver (#28669)
Alternative to #28620. Instead of emitting lazy references to not-yet-emitted models in the Flight Server, this fixes the observed issue in unstubbable/ai-rsc-test#1 by adjusting the lazy model resolution in the Flight Client to update stale blocked root models, before assigning them as chunk values. In addition, the element props are not outlined anymore in the Flight Server to avoid having to also handle their staleness in blocked elements. fixes #28595 DiffTrain build for [93f9179](93f9179)
1 parent b1ac5c1 commit b50214b

File tree

5 files changed

+35
-21
lines changed

5 files changed

+35
-21
lines changed

compiled/facebook-www/REVISION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
df95577db0d1d7ca383f281bc1d9e6ba5579bef2
1+
93f91795a0c71bae4aadd7f082b91de0068a0f91

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -673,7 +673,13 @@ if (__DEV__) {
673673
}
674674

675675
return function (value) {
676-
parentObject[key] = value;
676+
parentObject[key] = value; // If this is the root object for a model reference, where `blocked.value`
677+
// is a stale `null`, the resolved value can be used directly.
678+
679+
if (key === "" && blocked.value === null) {
680+
blocked.value = value;
681+
}
682+
677683
blocked.deps--;
678684

679685
if (blocked.deps === 0) {

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ function createModelResolver(chunk, parentObject, key, cyclic) {
202202
};
203203
return function (value) {
204204
parentObject[key] = value;
205+
"" === key && null === blocked.value && (blocked.value = value);
205206
blocked.deps--;
206207
0 === blocked.deps &&
207208
"blocked" === chunk.status &&

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

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1194,10 +1194,14 @@ if (__DEV__) {
11941194
var ObjectPrototype = Object.prototype;
11951195
var stringify = JSON.stringify; // Serializable values
11961196
// Thenable<ReactClientValue>
1197+
// task status
11971198

11981199
var PENDING = 0;
11991200
var COMPLETED = 1;
1200-
var ERRORED = 4;
1201+
var ERRORED = 4; // object reference status
1202+
1203+
var SEEN_BUT_NOT_YET_OUTLINED = -1;
1204+
var NEVER_OUTLINED = -2;
12011205
var ReactCurrentCache = ReactSharedServerInternals.ReactCurrentCache;
12021206
var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher;
12031207

@@ -1968,8 +1972,7 @@ if (__DEV__) {
19681972
var existingId = writtenObjects.get(key);
19691973

19701974
if (existingId === undefined) {
1971-
// Mark all object keys as seen so that they're always outlined.
1972-
writtenObjects.set(key, -1);
1975+
writtenObjects.set(key, SEEN_BUT_NOT_YET_OUTLINED);
19731976
}
19741977
}
19751978
}
@@ -1989,8 +1992,7 @@ if (__DEV__) {
19891992
var existingId = writtenObjects.get(key);
19901993

19911994
if (existingId === undefined) {
1992-
// Mark all object keys as seen so that they're always outlined.
1993-
writtenObjects.set(key, -1);
1995+
writtenObjects.set(key, SEEN_BUT_NOT_YET_OUTLINED);
19941996
}
19951997
}
19961998
}
@@ -2114,8 +2116,7 @@ if (__DEV__) {
21142116
// This is the ID we're currently emitting so we need to write it
21152117
// once but if we discover it again, we refer to it by id.
21162118
modelRoot = null;
2117-
} else if (_existingId === -1) {
2118-
// Seen but not yet outlined.
2119+
} else if (_existingId === SEEN_BUT_NOT_YET_OUTLINED) {
21192120
// TODO: If we throw here we can treat this as suspending which causes an outline
21202121
// but that is able to reuse the same task if we're already in one but then that
21212122
// will be a lazy future value rather than guaranteed to exist but maybe that's good.
@@ -2134,7 +2135,10 @@ if (__DEV__) {
21342135
} else {
21352136
// This is the first time we've seen this object. We may never see it again
21362137
// so we'll inline it. Mark it as seen. If we see it again, we'll outline.
2137-
_writtenObjects.set(value, -1);
2138+
_writtenObjects.set(value, SEEN_BUT_NOT_YET_OUTLINED); // The element's props are marked as "never outlined" so that they are inlined into
2139+
// the same row as the element itself.
2140+
2141+
_writtenObjects.set(value.props, NEVER_OUTLINED);
21382142
}
21392143

21402144
var element = value;
@@ -2257,20 +2261,19 @@ if (__DEV__) {
22572261
// This is the ID we're currently emitting so we need to write it
22582262
// once but if we discover it again, we refer to it by id.
22592263
modelRoot = null;
2260-
} else if (existingId === -1) {
2261-
// Seen but not yet outlined.
2264+
} else if (existingId === SEEN_BUT_NOT_YET_OUTLINED) {
22622265
var _newId = outlineModel(request, value);
22632266

22642267
return serializeByValueID(_newId);
2265-
} else {
2268+
} else if (existingId !== NEVER_OUTLINED) {
22662269
// We've already emitted this as an outlined object, so we can
22672270
// just refer to that by its existing ID.
22682271
return serializeByValueID(existingId);
22692272
}
22702273
} else {
22712274
// This is the first time we've seen this object. We may never see it again
22722275
// so we'll inline it. Mark it as seen. If we see it again, we'll outline.
2273-
writtenObjects.set(value, -1);
2276+
writtenObjects.set(value, SEEN_BUT_NOT_YET_OUTLINED);
22742277
}
22752278

22762279
if (isArray(value)) {
@@ -2643,7 +2646,7 @@ if (__DEV__) {
26432646
return serializeInfinitePromise();
26442647
}
26452648

2646-
if (existingId !== undefined && existingId !== -1) {
2649+
if (existingId !== undefined && existingId >= 0) {
26472650
// We've already emitted this as a real object, so we can
26482651
// just refer to that by its existing ID.
26492652
return serializeByValueID(existingId);

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

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -793,7 +793,7 @@ function renderModelDestructive(
793793
? ((request = outlineModel(request, value)),
794794
serializeByValueID(request))
795795
: serializeByValueID(parentPropertyName);
796-
} else parent.set(value, -1);
796+
} else parent.set(value, -1), parent.set(value.props, -2);
797797
parent = value.props;
798798
enableRefAsProp
799799
? ((parentPropertyName = parent.ref),
@@ -838,11 +838,15 @@ function renderModelDestructive(
838838
}
839839
if (void 0 !== parentPropertyName)
840840
if (modelRoot === value) modelRoot = null;
841-
else
842-
return -1 === parentPropertyName
843-
? ((request = outlineModel(request, value)),
844-
serializeByValueID(request))
845-
: serializeByValueID(parentPropertyName);
841+
else {
842+
if (-1 === parentPropertyName)
843+
return (
844+
(request = outlineModel(request, value)),
845+
serializeByValueID(request)
846+
);
847+
if (-2 !== parentPropertyName)
848+
return serializeByValueID(parentPropertyName);
849+
}
846850
else parent.set(value, -1);
847851
if (isArrayImpl(value)) return renderFragment(request, task, value);
848852
if (value instanceof Map) {

0 commit comments

Comments
 (0)