Skip to content

Commit 26e3c42

Browse files
committed
Move the image timeout to a central place like the stylesheet timeout
1 parent d1afba9 commit 26e3c42

File tree

1 file changed

+46
-18
lines changed

1 file changed

+46
-18
lines changed

packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js

Lines changed: 46 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5905,7 +5905,9 @@ export function preloadResource(resource: Resource): boolean {
59055905

59065906
type SuspendedState = {
59075907
stylesheets: null | Map<StylesheetResource, HoistableRoot>,
5908-
count: number,
5908+
count: number, // suspensey css and active view transitions
5909+
imgCount: number, // suspensey images
5910+
waitingForImages: boolean, // false when we're no longer blocking on images
59095911
unsuspend: null | (() => void),
59105912
};
59115913
let suspendedState: null | SuspendedState = null;
@@ -5914,6 +5916,8 @@ export function startSuspendingCommit(): void {
59145916
suspendedState = {
59155917
stylesheets: null,
59165918
count: 0,
5919+
imgCount: 0,
5920+
waitingForImages: true,
59175921
// We use a noop function when we begin suspending because if possible we want the
59185922
// waitfor step to finish synchronously. If it doesn't we'll return a function to
59195923
// provide the actual unsuspend function and that will get completed when the count
@@ -5922,6 +5926,8 @@ export function startSuspendingCommit(): void {
59225926
};
59235927
}
59245928

5929+
const SUSPENSEY_STYLESHEET_TIMEOUT = 60000;
5930+
59255931
const SUSPENSEY_IMAGE_TIMEOUT = 500;
59265932

59275933
export function suspendInstance(
@@ -5946,13 +5952,10 @@ export function suspendInstance(
59465952
// If this browser supports decode() API, we use it to suspend waiting on the image.
59475953
// The loading should have already started at this point, so it should be enough to
59485954
// just call decode() which should also wait for the data to finish loading.
5949-
state.count++;
5950-
const ping = onUnsuspend.bind(state);
5951-
Promise.race([
5952-
// $FlowFixMe[prop-missing]
5953-
instance.decode(),
5954-
new Promise(resolve => setTimeout(resolve, SUSPENSEY_IMAGE_TIMEOUT)),
5955-
]).then(ping, ping);
5955+
state.imgCount++;
5956+
const ping = onUnsuspendImg.bind(state);
5957+
// $FlowFixMe[prop-missing]
5958+
instance.decode().then(ping, ping);
59565959
}
59575960
}
59585961

@@ -6087,7 +6090,7 @@ export function waitForCommitToBeReady(
60876090

60886091
// We need to check the count again because the inserted stylesheets may have led to new
60896092
// tasks to wait on.
6090-
if (state.count > 0) {
6093+
if (state.count > 0 || state.imgCount > 0) {
60916094
return commit => {
60926095
// We almost never want to show content before its styles have loaded. But
60936096
// eventually we will give up and allow unstyled content. So this number is
@@ -6104,37 +6107,62 @@ export function waitForCommitToBeReady(
61046107
state.unsuspend = null;
61056108
unsuspend();
61066109
}
6107-
}, 60000 + timeoutOffset); // one minute
6110+
}, SUSPENSEY_STYLESHEET_TIMEOUT + timeoutOffset);
6111+
6112+
const imgTimer = setTimeout(() => {
6113+
// We're no longer blocked on images. If CSS resolves after this we can commit.
6114+
state.waitingForImages = false;
6115+
if (state.count === 0) {
6116+
if (state.stylesheets) {
6117+
insertSuspendedStylesheets(state, state.stylesheets);
6118+
}
6119+
if (state.unsuspend) {
6120+
const unsuspend = state.unsuspend;
6121+
state.unsuspend = null;
6122+
unsuspend();
6123+
}
6124+
}
6125+
}, SUSPENSEY_IMAGE_TIMEOUT + timeoutOffset);
61086126

61096127
state.unsuspend = commit;
61106128

61116129
return () => {
61126130
state.unsuspend = null;
61136131
clearTimeout(stylesheetTimer);
6132+
clearTimeout(imgTimer);
61146133
};
61156134
};
61166135
}
61176136
return null;
61186137
}
61196138

6120-
function onUnsuspend(this: SuspendedState) {
6121-
this.count--;
6122-
if (this.count === 0) {
6123-
if (this.stylesheets) {
6139+
function checkIfFullyUnsuspended(state: SuspendedState) {
6140+
if (state.count === 0 && (state.imgCount === 0 || !state.waitingForImages)) {
6141+
if (state.stylesheets) {
61246142
// If we haven't actually inserted the stylesheets yet we need to do so now before starting the commit.
61256143
// The reason we do this after everything else has finished is because we want to have all the stylesheets
61266144
// load synchronously right before mutating. Ideally the new styles will cause a single recalc only on the
61276145
// new tree. When we filled up stylesheets we only inlcuded stylesheets with matching media attributes so we
61286146
// wait for them to load before actually continuing. We expect this to increase the count above zero
6129-
insertSuspendedStylesheets(this, this.stylesheets);
6130-
} else if (this.unsuspend) {
6131-
const unsuspend = this.unsuspend;
6132-
this.unsuspend = null;
6147+
insertSuspendedStylesheets(state, state.stylesheets);
6148+
} else if (state.unsuspend) {
6149+
const unsuspend = state.unsuspend;
6150+
state.unsuspend = null;
61336151
unsuspend();
61346152
}
61356153
}
61366154
}
61376155

6156+
function onUnsuspend(this: SuspendedState) {
6157+
this.count--;
6158+
checkIfFullyUnsuspended(this);
6159+
}
6160+
6161+
function onUnsuspendImg(this: SuspendedState) {
6162+
this.imgCount--;
6163+
checkIfFullyUnsuspended(this);
6164+
}
6165+
61386166
// We use a value that is type distinct from precedence to track which one is last.
61396167
// This ensures there is no collision with user defined precedences. Normally we would
61406168
// just track this in module scope but since the precedences are tracked per HoistableRoot

0 commit comments

Comments
 (0)