7
7
* @noflow
8
8
* @nolint
9
9
* @preventMunge
10
- * @generated SignedSource<<202c1c7cbff4135eff9604c4cb02a215 >>
10
+ * @generated SignedSource<<dcb3a30556188c6961c11e3ffe2a0c3a >>
11
11
*/
12
12
13
13
"use strict";
@@ -4770,7 +4770,14 @@ if (__DEV__) {
4770
4770
}
4771
4771
}
4772
4772
4773
- var ReactCurrentActQueue$2 = ReactSharedInternals.ReactCurrentActQueue; // An error that is thrown (e.g. by `use`) to trigger Suspense. If we
4773
+ var ReactCurrentActQueue$2 = ReactSharedInternals.ReactCurrentActQueue;
4774
+
4775
+ function getThenablesFromState(state) {
4776
+ {
4777
+ var devState = state;
4778
+ return devState.thenables;
4779
+ }
4780
+ } // An error that is thrown (e.g. by `use`) to trigger Suspense. If we
4774
4781
// detect this is caught by userspace, we'll log a warning in development.
4775
4782
4776
4783
var SuspenseException = new Error(
@@ -4803,7 +4810,12 @@ if (__DEV__) {
4803
4810
function createThenableState() {
4804
4811
// The ThenableState is created the first time a component suspends. If it
4805
4812
// suspends again, we'll reuse the same state.
4806
- return [];
4813
+ {
4814
+ return {
4815
+ didWarnAboutUncachedPromise: false,
4816
+ thenables: []
4817
+ };
4818
+ }
4807
4819
}
4808
4820
function isThenableResolved(thenable) {
4809
4821
var status = thenable.status;
@@ -4817,16 +4829,45 @@ if (__DEV__) {
4817
4829
ReactCurrentActQueue$2.didUsePromise = true;
4818
4830
}
4819
4831
4820
- var previous = thenableState[index];
4832
+ var trackedThenables = getThenablesFromState(thenableState);
4833
+ var previous = trackedThenables[index];
4821
4834
4822
4835
if (previous === undefined) {
4823
- thenableState .push(thenable);
4836
+ trackedThenables .push(thenable);
4824
4837
} else {
4825
4838
if (previous !== thenable) {
4826
4839
// Reuse the previous thenable, and drop the new one. We can assume
4827
4840
// they represent the same value, because components are idempotent.
4828
- // Avoid an unhandled rejection errors for the Promises that we'll
4841
+ {
4842
+ var thenableStateDev = thenableState;
4843
+
4844
+ if (!thenableStateDev.didWarnAboutUncachedPromise) {
4845
+ // We should only warn the first time an uncached thenable is
4846
+ // discovered per component, because if there are multiple, the
4847
+ // subsequent ones are likely derived from the first.
4848
+ //
4849
+ // We track this on the thenableState instead of deduping using the
4850
+ // component name like we usually do, because in the case of a
4851
+ // promise-as-React-node, the owner component is likely different from
4852
+ // the parent that's currently being reconciled. We'd have to track
4853
+ // the owner using state, which we're trying to move away from. Though
4854
+ // since this is dev-only, maybe that'd be OK.
4855
+ //
4856
+ // However, another benefit of doing it this way is we might
4857
+ // eventually have a thenableState per memo/Forget boundary instead
4858
+ // of per component, so this would allow us to have more
4859
+ // granular warnings.
4860
+ thenableStateDev.didWarnAboutUncachedPromise = true; // TODO: This warning should link to a corresponding docs page.
4861
+
4862
+ error(
4863
+ "A component was suspended by an uncached promise. Creating " +
4864
+ "promises inside a Client Component or hook is not yet " +
4865
+ "supported, except via a Suspense-compatible library or framework."
4866
+ );
4867
+ }
4868
+ } // Avoid an unhandled rejection errors for the Promises that we'll
4829
4869
// intentionally ignore.
4870
+
4830
4871
thenable.then(noop, noop);
4831
4872
thenable = previous;
4832
4873
}
@@ -6903,7 +6944,7 @@ if (__DEV__) {
6903
6944
}
6904
6945
}
6905
6946
6906
- function warnIfAsyncClientComponent(Component, componentDoesIncludeHooks ) {
6947
+ function warnIfAsyncClientComponent(Component) {
6907
6948
{
6908
6949
// This dev-only check only works for detecting native async functions,
6909
6950
// not transpiled ones. There's also a prod check that we use to prevent
@@ -6915,43 +6956,20 @@ if (__DEV__) {
6915
6956
"[object AsyncFunction]";
6916
6957
6917
6958
if (isAsyncFunction) {
6918
- // Encountered an async Client Component. This is not yet supported,
6919
- // except in certain constrained cases, like during a route navigation.
6959
+ // Encountered an async Client Component. This is not yet supported.
6920
6960
var componentName = getComponentNameFromFiber(
6921
6961
currentlyRenderingFiber$1
6922
6962
);
6923
6963
6924
6964
if (!didWarnAboutAsyncClientComponent.has(componentName)) {
6925
- didWarnAboutAsyncClientComponent.add(componentName); // Check if this is a sync update. We use the "root" render lanes here
6926
- // because the "subtree" render lanes may include additional entangled
6927
- // lanes related to revealing previously hidden content.
6965
+ didWarnAboutAsyncClientComponent.add(componentName);
6928
6966
6929
- var root = getWorkInProgressRoot();
6930
- var rootRenderLanes = getWorkInProgressRootRenderLanes();
6931
-
6932
- if (root !== null && includesBlockingLane(root, rootRenderLanes)) {
6933
- error(
6934
- "async/await is not yet supported in Client Components, only " +
6935
- "Server Components. This error is often caused by accidentally " +
6936
- "adding `'use client'` to a module that was originally written " +
6937
- "for the server."
6938
- );
6939
- } else {
6940
- // This is a concurrent (Transition, Retry, etc) render. We don't
6941
- // warn in these cases.
6942
- //
6943
- // However, Async Components are forbidden to include hooks, even
6944
- // during a transition, so let's check for that here.
6945
- //
6946
- // TODO: Add a corresponding warning to Server Components runtime.
6947
- if (componentDoesIncludeHooks) {
6948
- error(
6949
- "Hooks are not supported inside an async component. This " +
6950
- "error is often caused by accidentally adding `'use client'` " +
6951
- "to a module that was originally written for the server."
6952
- );
6953
- }
6954
- }
6967
+ error(
6968
+ "async/await is not yet supported in Client Components, only " +
6969
+ "Server Components. This error is often caused by accidentally " +
6970
+ "adding `'use client'` to a module that was originally written " +
6971
+ "for the server."
6972
+ );
6955
6973
}
6956
6974
}
6957
6975
}
@@ -7034,6 +7052,7 @@ if (__DEV__) {
7034
7052
7035
7053
ignorePreviousDependencies =
7036
7054
current !== null && current.type !== workInProgress.type;
7055
+ warnIfAsyncClientComponent(Component);
7037
7056
}
7038
7057
7039
7058
workInProgress.memoizedState = null;
@@ -7109,16 +7128,13 @@ if (__DEV__) {
7109
7128
);
7110
7129
}
7111
7130
7112
- finishRenderingHooks(current, workInProgress, Component );
7131
+ finishRenderingHooks(current, workInProgress);
7113
7132
return children;
7114
7133
}
7115
7134
7116
7135
function finishRenderingHooks(current, workInProgress, Component) {
7117
7136
{
7118
7137
workInProgress._debugHookTypes = hookTypesDev;
7119
- var componentDoesIncludeHooks =
7120
- workInProgressHook !== null || thenableIndexCounter !== 0;
7121
- warnIfAsyncClientComponent(Component, componentDoesIncludeHooks);
7122
7138
} // We can assume the previous dispatcher is always this one, since we set it
7123
7139
// at the beginning of the render phase and there's no re-entrance.
7124
7140
@@ -7220,7 +7236,7 @@ if (__DEV__) {
7220
7236
props,
7221
7237
secondArg
7222
7238
);
7223
- finishRenderingHooks(current, workInProgress, Component );
7239
+ finishRenderingHooks(current, workInProgress);
7224
7240
return children;
7225
7241
}
7226
7242
@@ -25607,7 +25623,7 @@ if (__DEV__) {
25607
25623
return root;
25608
25624
}
25609
25625
25610
- var ReactVersion = "18.3.0-canary-554fc49f4 -20240130";
25626
+ var ReactVersion = "18.3.0-canary-178f43519 -20240130";
25611
25627
25612
25628
// Might add PROFILE later.
25613
25629
0 commit comments