Skip to content

Commit 565eb78

Browse files
authored
Unwrap a reference to a Lazy value (facebook#34535)
If we are referencing a lazy value that isn't explicitly lazy ($L...) it's because we added it around an element that was blocked to be able to defer things inside. However, once that is unblocked we can start unwrap it and just use the inner element instead for any future reference. The race condition is still there since it's a race condition whether we added the wrapper in the first place. This just makes it consistent with unwrapping of the rest of the path.
1 parent d415fd3 commit 565eb78

File tree

1 file changed

+69
-2
lines changed

1 file changed

+69
-2
lines changed

packages/react-client/src/ReactFlightClient.js

Lines changed: 69 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1337,7 +1337,11 @@ function fulfillReference(
13371337
const {response, handler, parentObject, key, map, path} = reference;
13381338

13391339
for (let i = 1; i < path.length; i++) {
1340-
while (value.$$typeof === REACT_LAZY_TYPE) {
1340+
while (
1341+
typeof value === 'object' &&
1342+
value !== null &&
1343+
value.$$typeof === REACT_LAZY_TYPE
1344+
) {
13411345
// We never expect to see a Lazy node on this path because we encode those as
13421346
// separate models. This must mean that we have inserted an extra lazy node
13431347
// e.g. to replace a blocked element. We must instead look for it inside.
@@ -1408,6 +1412,39 @@ function fulfillReference(
14081412
}
14091413
value = value[path[i]];
14101414
}
1415+
1416+
while (
1417+
typeof value === 'object' &&
1418+
value !== null &&
1419+
value.$$typeof === REACT_LAZY_TYPE
1420+
) {
1421+
// If what we're referencing is a Lazy it must be because we inserted one as a virtual node
1422+
// while it was blocked by other data. If it's no longer blocked, we can unwrap it.
1423+
const referencedChunk: SomeChunk<any> = value._payload;
1424+
if (referencedChunk === handler.chunk) {
1425+
// This is a reference to the thing we're currently blocking. We can peak
1426+
// inside of it to get the value.
1427+
value = handler.value;
1428+
continue;
1429+
} else {
1430+
switch (referencedChunk.status) {
1431+
case RESOLVED_MODEL:
1432+
initializeModelChunk(referencedChunk);
1433+
break;
1434+
case RESOLVED_MODULE:
1435+
initializeModuleChunk(referencedChunk);
1436+
break;
1437+
}
1438+
switch (referencedChunk.status) {
1439+
case INITIALIZED: {
1440+
value = referencedChunk.value;
1441+
continue;
1442+
}
1443+
}
1444+
}
1445+
break;
1446+
}
1447+
14111448
const mappedValue = map(response, value, parentObject, key);
14121449
parentObject[key] = mappedValue;
14131450

@@ -1855,7 +1892,11 @@ function getOutlinedModel<T>(
18551892
case INITIALIZED:
18561893
let value = chunk.value;
18571894
for (let i = 1; i < path.length; i++) {
1858-
while (value.$$typeof === REACT_LAZY_TYPE) {
1895+
while (
1896+
typeof value === 'object' &&
1897+
value !== null &&
1898+
value.$$typeof === REACT_LAZY_TYPE
1899+
) {
18591900
const referencedChunk: SomeChunk<any> = value._payload;
18601901
switch (referencedChunk.status) {
18611902
case RESOLVED_MODEL:
@@ -1924,6 +1965,32 @@ function getOutlinedModel<T>(
19241965
}
19251966
value = value[path[i]];
19261967
}
1968+
1969+
while (
1970+
typeof value === 'object' &&
1971+
value !== null &&
1972+
value.$$typeof === REACT_LAZY_TYPE
1973+
) {
1974+
// If what we're referencing is a Lazy it must be because we inserted one as a virtual node
1975+
// while it was blocked by other data. If it's no longer blocked, we can unwrap it.
1976+
const referencedChunk: SomeChunk<any> = value._payload;
1977+
switch (referencedChunk.status) {
1978+
case RESOLVED_MODEL:
1979+
initializeModelChunk(referencedChunk);
1980+
break;
1981+
case RESOLVED_MODULE:
1982+
initializeModuleChunk(referencedChunk);
1983+
break;
1984+
}
1985+
switch (referencedChunk.status) {
1986+
case INITIALIZED: {
1987+
value = referencedChunk.value;
1988+
continue;
1989+
}
1990+
}
1991+
break;
1992+
}
1993+
19271994
const chunkValue = map(response, value, parentObject, key);
19281995
if (
19291996
parentObject[0] === REACT_ELEMENT_TYPE &&

0 commit comments

Comments
 (0)