Skip to content

Commit 94954ff

Browse files
committed
Pass SuspendedState as an argument instead of global state
This is safer since some calls need this to be closed over anyway. This will let us persist it longer like into the commit phase.
1 parent ae59661 commit 94954ff

File tree

10 files changed

+149
-88
lines changed

10 files changed

+149
-88
lines changed

packages/react-art/src/ReactFiberConfigART.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -609,11 +609,13 @@ export function preloadInstance(type, props) {
609609
return true;
610610
}
611611

612-
export function startSuspendingCommit() {}
612+
export function startSuspendingCommit() {
613+
return null;
614+
}
613615

614-
export function suspendInstance(instance, type, props) {}
616+
export function suspendInstance(state, instance, type, props) {}
615617

616-
export function suspendOnActiveViewTransition(container) {}
618+
export function suspendOnActiveViewTransition(state, container) {}
617619

618620
export function waitForCommitToBeReady(timeoutOffset) {
619621
return null;

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

Lines changed: 10 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5904,18 +5904,17 @@ export function preloadResource(resource: Resource): boolean {
59045904
return true;
59055905
}
59065906

5907-
type SuspendedState = {
5907+
export opaque type SuspendedState = {
59085908
stylesheets: null | Map<StylesheetResource, HoistableRoot>,
59095909
count: number, // suspensey css and active view transitions
59105910
imgCount: number, // suspensey images
59115911
imgBytes: number, // number of bytes we estimate needing to download
59125912
waitingForImages: boolean, // false when we're no longer blocking on images
59135913
unsuspend: null | (() => void),
59145914
};
5915-
let suspendedState: null | SuspendedState = null;
59165915

5917-
export function startSuspendingCommit(): void {
5918-
suspendedState = {
5916+
export function startSuspendingCommit(): SuspendedState {
5917+
return {
59195918
stylesheets: null,
59205919
count: 0,
59215920
imgCount: 0,
@@ -5930,19 +5929,14 @@ export function startSuspendingCommit(): void {
59305929
}
59315930

59325931
export function suspendInstance(
5932+
state: SuspendedState,
59335933
instance: Instance,
59345934
type: Type,
59355935
props: Props,
59365936
): void {
59375937
if (!enableSuspenseyImages && !enableViewTransition) {
59385938
return;
59395939
}
5940-
if (suspendedState === null) {
5941-
throw new Error(
5942-
'Internal React Error: suspendedState null when it was expected to exists. Please report this as a React bug.',
5943-
);
5944-
}
5945-
const state = suspendedState;
59465940
if (
59475941
// $FlowFixMe[prop-missing]
59485942
typeof instance.decode === 'function' &&
@@ -5971,16 +5965,11 @@ export function suspendInstance(
59715965
}
59725966

59735967
export function suspendResource(
5968+
state: SuspendedState,
59745969
hoistableRoot: HoistableRoot,
59755970
resource: Resource,
59765971
props: any,
59775972
): void {
5978-
if (suspendedState === null) {
5979-
throw new Error(
5980-
'Internal React Error: suspendedState null when it was expected to exists. Please report this as a React bug.',
5981-
);
5982-
}
5983-
const state = suspendedState;
59845973
if (resource.type === 'stylesheet') {
59855974
if (typeof props.media === 'string') {
59865975
// If we don't currently match media we avoid suspending on this resource
@@ -6060,13 +6049,10 @@ export function suspendResource(
60606049
}
60616050
}
60626051

6063-
export function suspendOnActiveViewTransition(rootContainer: Container): void {
6064-
if (suspendedState === null) {
6065-
throw new Error(
6066-
'Internal React Error: suspendedState null when it was expected to exists. Please report this as a React bug.',
6067-
);
6068-
}
6069-
const state = suspendedState;
6052+
export function suspendOnActiveViewTransition(
6053+
state: SuspendedState,
6054+
rootContainer: Container,
6055+
): void {
60706056
const ownerDocument =
60716057
rootContainer.nodeType === DOCUMENT_NODE
60726058
? rootContainer
@@ -6090,16 +6076,9 @@ const SUSPENSEY_IMAGE_TIME_ESTIMATE = 500;
60906076
let estimatedBytesWithinLimit: number = 0;
60916077

60926078
export function waitForCommitToBeReady(
6079+
state: SuspendedState,
60936080
timeoutOffset: number,
60946081
): null | ((() => void) => () => void) {
6095-
if (suspendedState === null) {
6096-
throw new Error(
6097-
'Internal React Error: suspendedState null when it was expected to exists. Please report this as a React bug.',
6098-
);
6099-
}
6100-
6101-
const state = suspendedState;
6102-
61036082
if (state.stylesheets && state.count === 0) {
61046083
// We are not currently blocked but we have not inserted all stylesheets.
61056084
// If this insertion happens and loads or errors synchronously then we can

packages/react-native-renderer/src/ReactFiberConfigFabric.js

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -602,17 +602,28 @@ export function preloadInstance(
602602
return true;
603603
}
604604

605-
export function startSuspendingCommit(): void {}
605+
export opaque type SuspendedState = null;
606+
607+
export function startSuspendingCommit(): SuspendedState {
608+
return null;
609+
}
606610

607611
export function suspendInstance(
612+
state: SuspendedState,
608613
instance: Instance,
609614
type: Type,
610615
props: Props,
611616
): void {}
612617

613-
export function suspendOnActiveViewTransition(container: Container): void {}
618+
export function suspendOnActiveViewTransition(
619+
state: SuspendedState,
620+
container: Container,
621+
): void {}
614622

615-
export function waitForCommitToBeReady(timeoutOffset: number): null {
623+
export function waitForCommitToBeReady(
624+
state: SuspendedState,
625+
timeoutOffset: number,
626+
): null {
616627
return null;
617628
}
618629

packages/react-native-renderer/src/ReactFiberConfigNative.js

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -778,17 +778,28 @@ export function preloadInstance(
778778
return true;
779779
}
780780

781-
export function startSuspendingCommit(): void {}
781+
export opaque type SuspendedState = null;
782+
783+
export function startSuspendingCommit(): SuspendedState {
784+
return null;
785+
}
782786

783787
export function suspendInstance(
788+
state: SuspendedState,
784789
instance: Instance,
785790
type: Type,
786791
props: Props,
787792
): void {}
788793

789-
export function suspendOnActiveViewTransition(container: Container): void {}
794+
export function suspendOnActiveViewTransition(
795+
state: SuspendedState,
796+
container: Container,
797+
): void {}
790798

791-
export function waitForCommitToBeReady(timeoutOffset: number): null {
799+
export function waitForCommitToBeReady(
800+
state: SuspendedState,
801+
timeoutOffset: number,
802+
): null {
792803
return null;
793804
}
794805

packages/react-noop-renderer/src/createReactNoop.js

Lines changed: 21 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ type SuspenseyCommitSubscription = {
9090
commit: null | (() => void),
9191
};
9292

93+
export opaque type SuspendedState = SuspenseyCommitSubscription;
94+
9395
export type TransitionStatus = mixed;
9496

9597
export type FormInstance = Instance;
@@ -311,17 +313,17 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
311313
'pending' | 'fulfilled',
312314
> | null = null;
313315

314-
// Represents a subscription for all the suspensey things that block a
315-
// particular commit. Once they've all loaded, the commit phase can proceed.
316-
let suspenseyCommitSubscription: SuspenseyCommitSubscription | null = null;
317-
318-
function startSuspendingCommit(): void {
319-
// This is where we might suspend on things that aren't associated with a
320-
// particular node, like document.fonts.ready.
321-
suspenseyCommitSubscription = null;
316+
function startSuspendingCommit(): SuspendedState {
317+
// Represents a subscription for all the suspensey things that block a
318+
// particular commit. Once they've all loaded, the commit phase can proceed.
319+
return {
320+
pendingCount: 0,
321+
commit: null,
322+
};
322323
}
323324

324325
function suspendInstance(
326+
state: SuspendedState,
325327
instance: Instance,
326328
type: string,
327329
props: Props,
@@ -338,20 +340,13 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
338340
if (record.status === 'fulfilled') {
339341
// Already loaded.
340342
} else if (record.status === 'pending') {
341-
if (suspenseyCommitSubscription === null) {
342-
suspenseyCommitSubscription = {
343-
pendingCount: 1,
344-
commit: null,
345-
};
346-
} else {
347-
suspenseyCommitSubscription.pendingCount++;
348-
}
343+
state.pendingCount++;
349344
// Stash the subscription on the record. In `resolveSuspenseyThing`,
350345
// we'll use this fire the commit once all the things have loaded.
351346
if (record.subscriptions === null) {
352347
record.subscriptions = [];
353348
}
354-
record.subscriptions.push(suspenseyCommitSubscription);
349+
record.subscriptions.push(state);
355350
}
356351
} else {
357352
throw new Error(
@@ -362,15 +357,14 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
362357
}
363358

364359
function waitForCommitToBeReady(
360+
state: SuspendedState,
365361
timeoutOffset: number,
366362
): ((commit: () => mixed) => () => void) | null {
367-
const subscription = suspenseyCommitSubscription;
368-
if (subscription !== null) {
369-
suspenseyCommitSubscription = null;
363+
if (state.pendingCount > 0) {
370364
return (commit: () => void) => {
371-
subscription.commit = commit;
365+
state.commit = commit;
372366
const cancelCommit = () => {
373-
subscription.commit = null;
367+
state.commit = null;
374368
};
375369
return cancelCommit;
376370
};
@@ -693,13 +687,16 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
693687
startSuspendingCommit,
694688
suspendInstance,
695689

696-
suspendResource(resource: mixed): void {
690+
suspendResource(state: SuspendedState, resource: mixed): void {
697691
throw new Error(
698692
'Resources are not implemented for React Noop yet. This method should not be called',
699693
);
700694
},
701695

702-
suspendOnActiveViewTransition(container: Container): void {
696+
suspendOnActiveViewTransition(
697+
state: SuspendedState,
698+
container: Container,
699+
): void {
703700
// Not implemented
704701
},
705702

0 commit comments

Comments
 (0)