[Flight] Delete Server Context (#28225)
Server Context was never documented, and has been deprecated in https://github.com/facebook/react/pull/27424. This PR removes it completely, including the implementation code. Notably, `useContext` is removed from the shared subset, so importing it from a React Server environment would now should be a build error in environments that are able to enforce that.
dan committed
Feb 5, 2024 at 22:39 UTC
472854820bfd0058dfc85524051171c7b7c998c1
47 files changed
+89
-1365
packages/react-client/src/ReactFlightClient.js
-6
@@ -48,8 +48,6 @@ import {
48
REACT_POSTPONE_TYPE,
49
} from 'shared/ReactSymbols';
50
51
-import {getOrCreateServerContext} from 'shared/ReactServerContextRegistry';
52
-
51
export type {CallServerCallback};
52
53
type UninitializedModel = string;
@@ -634,10 +632,6 @@ function parseModelString(
632
// Symbol
633
return Symbol.for(value.slice(2));
634
}
637
- case 'P': {
638
- // Server Context Provider
639
- return getOrCreateServerContext(value.slice(2)).Provider;
640
- }
635
case 'F': {
636
// Server Reference
637
const id = parseInt(value.slice(2), 16);
packages/react-client/src/__tests__/ReactFlight-test.js
+39
-387
@@ -122,32 +122,6 @@ describe('ReactFlight', () => {
122
jest.restoreAllMocks();
123
});
124
125
- function createServerContext(globalName, defaultValue, withStack) {
126
- let ctx;
127
- expect(() => {
128
- ctx = React.createServerContext(globalName, defaultValue);
129
- }).toErrorDev(
130
- 'Server Context is deprecated and will soon be removed. ' +
131
- 'It was never documented and we have found it not to be useful ' +
132
- 'enough to warrant the downside it imposes on all apps.',
133
- {withoutStack: !withStack},
134
- );
135
- return ctx;
136
- }
137
-
138
- function createServerServerContext(globalName, defaultValue, withStack) {
139
- let ctx;
140
- expect(() => {
141
- ctx = ReactServer.createServerContext(globalName, defaultValue);
142
- }).toErrorDev(
143
- 'Server Context is deprecated and will soon be removed. ' +
144
- 'It was never documented and we have found it not to be useful ' +
145
- 'enough to warrant the downside it imposes on all apps.',
146
- {withoutStack: !withStack},
147
- );
148
- return ctx;
149
- }
150
-
125
function clientReference(value) {
126
return Object.defineProperties(
127
function () {
@@ -1042,18 +1016,50 @@ describe('ReactFlight', () => {
1016
]);
1017
});
1018
1045
- it('should warn in DEV if a a client reference is passed to useContext()', () => {
1019
+ it('should error if useContext is called()', () => {
1020
+ function ServerComponent() {
1021
+ return ReactServer.useContext();
1022
+ }
1023
+ const errors = [];
1024
+ ReactNoopFlightServer.render(<ServerComponent />, {
1025
+ onError(x) {
1026
+ errors.push(x.message);
1027
+ },
1028
+ });
1029
+ expect(errors).toEqual(['ReactServer.useContext is not a function']);
1030
+ });
1031
+
1032
+ it('should error if a context without a client reference is passed to use()', () => {
1033
+ const Context = React.createContext();
1034
+ function ServerComponent() {
1035
+ return ReactServer.use(Context);
1036
+ }
1037
+ const errors = [];
1038
+ ReactNoopFlightServer.render(<ServerComponent />, {
1039
+ onError(x) {
1040
+ errors.push(x.message);
1041
+ },
1042
+ });
1043
+ expect(errors).toEqual([
1044
+ 'Cannot read a Client Context from a Server Component.',
1045
+ ]);
1046
+ });
1047
+
1048
+ it('should error if a client reference is passed to use()', () => {
1049
const Context = React.createContext();
1050
const ClientContext = clientReference(Context);
1051
function ServerComponent() {
1049
- return ReactServer.useContext(ClientContext);
1052
+ return ReactServer.use(ClientContext);
1053
}
1051
- expect(() => {
1052
- const transport = ReactNoopFlightServer.render(<ServerComponent />);
1053
- ReactNoopFlightClient.read(transport);
1054
- }).toErrorDev('Cannot read a Client Context from a Server Component.', {
1055
- withoutStack: true,
1054
+ const errors = [];
1055
+ ReactNoopFlightServer.render(<ServerComponent />, {
1056
+ onError(x) {
1057
+ errors.push(x.message);
1058
+ },
1059
});
1060
+ expect(errors).toEqual([
1061
+ 'Cannot read a Client Context from a Server Component.',
1062
+ ]);
1063
});
1064
1065
describe('Hooks', () => {
@@ -1149,360 +1155,6 @@ describe('ReactFlight', () => {
1155
});
1156
});
1157
1152
- describe('ServerContext', () => {
1153
- // @gate enableServerContext
1154
- it('supports basic createServerContext usage', async () => {
1155
- const ServerContext = createServerServerContext(
1156
- 'ServerContext',
1157
- 'hello from server',
1158
- );
1159
- function Foo() {
1160
- const context = ReactServer.useContext(ServerContext);
1161
- return <div>{context}</div>;
1162
- }
1163
-
1164
- const transport = ReactNoopFlightServer.render(<Foo />);
1165
- await act(async () => {
1166
- ReactNoop.render(await ReactNoopFlightClient.read(transport));
1167
- });
1168
-
1169
- expect(ReactNoop).toMatchRenderedOutput(<div>hello from server</div>);
1170
- });
1171
-
1172
- // @gate enableServerContext
1173
- it('propagates ServerContext providers in flight', async () => {
1174
- const ServerContext = createServerServerContext(
1175
- 'ServerContext',
1176
- 'default',
1177
- );
1178
-
1179
- function Foo() {
1180
- return (
1181
- <div>
1182
- <ServerContext.Provider value="hi this is server">
1183
- <Bar />
1184
- </ServerContext.Provider>
1185
- </div>
1186
- );
1187
- }
1188
- function Bar() {
1189
- const context = ReactServer.useContext(ServerContext);
1190
- return context;
1191
- }
1192
-
1193
- const transport = ReactNoopFlightServer.render(<Foo />);
1194
- await act(async () => {
1195
- ReactNoop.render(await ReactNoopFlightClient.read(transport));
1196
- });
1197
-
1198
- expect(ReactNoop).toMatchRenderedOutput(<div>hi this is server</div>);
1199
- });
1200
-
1201
- // @gate enableServerContext
1202
- it('errors if you try passing JSX through ServerContext value', () => {
1203
- const ServerContext = createServerServerContext('ServerContext', {
1204
- foo: {
1205
- bar: <span>hi this is default</span>,
1206
- },
1207
- });
1208
-
1209
- function Foo() {
1210
- return (
1211
- <div>
1212
- <ServerContext.Provider
1213
- value={{
1214
- foo: {
1215
- bar: <span>hi this is server</span>,
1216
- },
1217
- }}>
1218
- <Bar />
1219
- </ServerContext.Provider>
1220
- </div>
1221
- );
1222
- }
1223
- function Bar() {
1224
- const context = ReactServer.useContext(ServerContext);
1225
- return context.foo.bar;
1226
- }
1227
-
1228
- expect(() => {
1229
- ReactNoopFlightServer.render(<Foo />);
1230
- }).toErrorDev('React elements are not allowed in ServerContext', {
1231
- withoutStack: true,
1232
- });
1233
- });
1234
-
1235
- // @gate enableServerContext
1236
- it('propagates ServerContext and cleans up the providers in flight', async () => {
1237
- const ServerContext = createServerServerContext(
1238
- 'ServerContext',
1239
- 'default',
1240
- );
1241
-
1242
- function Foo() {
1243
- return (
1244
- <>
1245
- <ServerContext.Provider value="hi this is server outer">
1246
- <ServerContext.Provider value="hi this is server">
1247
- <Bar />
1248
- </ServerContext.Provider>
1249
- <ServerContext.Provider value="hi this is server2">
1250
- <Bar />
1251
- </ServerContext.Provider>
1252
- <Bar />
1253
- </ServerContext.Provider>
1254
- <ServerContext.Provider value="hi this is server outer2">
1255
- <Bar />
1256
- </ServerContext.Provider>
1257
- <Bar />
1258
- </>
1259
- );
1260
- }
1261
- function Bar() {
1262
- const context = ReactServer.useContext(ServerContext);
1263
- return <span>{context}</span>;
1264
- }
1265
-
1266
- const transport = ReactNoopFlightServer.render(<Foo />);
1267
- await act(async () => {
1268
- ReactNoop.render(await ReactNoopFlightClient.read(transport));
1269
- });
1270
-
1271
- expect(ReactNoop).toMatchRenderedOutput(
1272
- <>
1273
- <span>hi this is server</span>
1274
- <span>hi this is server2</span>
1275
- <span>hi this is server outer</span>
1276
- <span>hi this is server outer2</span>
1277
- <span>default</span>
1278
- </>,
1279
- );
1280
- });
1281
-
1282
- // @gate enableServerContext
1283
- it('propagates ServerContext providers in flight after suspending', async () => {
1284
- const ServerContext = createServerServerContext(
1285
- 'ServerContext',
1286
- 'default',
1287
- );
1288
-
1289
- function Foo() {
1290
- return (
1291
- <div>
1292
- <ServerContext.Provider value="hi this is server">
1293
- <React.Suspense fallback={'Loading'}>
1294
- <Bar />
1295
- </React.Suspense>
1296
- </ServerContext.Provider>
1297
- </div>
1298
- );
1299
- }
1300
-
1301
- let resolve;
1302
- const promise = new Promise(res => {
1303
- resolve = () => {
1304
- promise.unsuspend = true;
1305
- res();
1306
- };
1307
- });
1308
-
1309
- function Bar() {
1310
- if (!promise.unsuspend) {
1311
- Scheduler.log('suspended');
1312
- throw promise;
1313
- }
1314
- Scheduler.log('rendered');
1315
- const context = ReactServer.useContext(ServerContext);
1316
- return context;
1317
- }
1318
-
1319
- const transport = ReactNoopFlightServer.render(<Foo />);
1320
-
1321
- assertLog(['suspended']);
1322
-
1323
- await act(async () => {
1324
- resolve();
1325
- await promise;
1326
- jest.runAllImmediates();
1327
- });
1328
-
1329
- assertLog(['rendered']);
1330
-
1331
- await act(async () => {
1332
- ReactNoop.render(await ReactNoopFlightClient.read(transport));
1333
- });
1334
-
1335
- expect(ReactNoop).toMatchRenderedOutput(<div>hi this is server</div>);
1336
- });
1337
-
1338
- // @gate enableServerContext
1339
- it('serializes ServerContext to client', async () => {
1340
- const ServerContext = createServerServerContext(
1341
- 'ServerContext',
1342
- 'default',
1343
- );
1344
- const ClientContext = createServerContext('ServerContext', 'default');
1345
-
1346
- function ClientBar() {
1347
- Scheduler.log('ClientBar');
1348
- const context = React.useContext(ClientContext);
1349
- return <span>{context}</span>;
1350
- }
1351
-
1352
- const Bar = clientReference(ClientBar);
1353
-
1354
- function Foo() {
1355
- return (
1356
- <ServerContext.Provider value="hi this is server">
1357
- <Bar />
1358
- </ServerContext.Provider>
1359
- );
1360
- }
1361
-
1362
- const model = {
1363
- foo: <Foo />,
1364
- };
1365
-
1366
- const transport = ReactNoopFlightServer.render(model);
1367
-
1368
- assertLog([]);
1369
-
1370
- await act(async () => {
1371
- const flightModel = await ReactNoopFlightClient.read(transport);
1372
- ReactNoop.render(flightModel.foo);
1373
- });
1374
-
1375
- assertLog(['ClientBar']);
1376
- expect(ReactNoop).toMatchRenderedOutput(<span>hi this is server</span>);
1377
-
1378
- expect(() => {
1379
- createServerContext('ServerContext', 'default');
1380
- }).toThrow('ServerContext: ServerContext already defined');
1381
- });
1382
-
1383
- // @gate enableServerContext
1384
- it('takes ServerContext from the client for refetching use cases', async () => {
1385
- const ServerContext = createServerServerContext(
1386
- 'ServerContext',
1387
- 'default',
1388
- );
1389
- function Bar() {
1390
- return <span>{ReactServer.useContext(ServerContext)}</span>;
1391
- }
1392
- const transport = ReactNoopFlightServer.render(<Bar />, {
1393
- context: [['ServerContext', 'Override']],
1394
- });
1395
-
1396
- await act(async () => {
1397
- const flightModel = await ReactNoopFlightClient.read(transport);
1398
- ReactNoop.render(flightModel);
1399
- });
1400
- expect(ReactNoop).toMatchRenderedOutput(<span>Override</span>);
1401
- });
1402
-
1403
- // @gate enableServerContext
1404
- it('sets default initial value when defined lazily on server or client', async () => {
1405
- let ServerContext;
1406
- function inlineLazyServerContextInitialization() {
1407
- if (!ServerContext) {
1408
- ServerContext = createServerServerContext('ServerContext', 'default');
1409
- }
1410
- return ServerContext;
1411
- }
1412
-
1413
- let ClientContext;
1414
- function inlineContextInitialization() {
1415
- if (!ClientContext) {
1416
- ClientContext = createServerContext('ServerContext', 'default', true);
1417
- }
1418
- return ClientContext;
1419
- }
1420
-
1421
- function ClientBaz() {
1422
- const context = inlineContextInitialization();
1423
- const value = React.useContext(context);
1424
- return <div>{value}</div>;
1425
- }
1426
-
1427
- const Baz = clientReference(ClientBaz);
1428
-
1429
- function Bar() {
1430
- return (
1431
- <article>
1432
- <div>
1433
- {ReactServer.useContext(inlineLazyServerContextInitialization())}
1434
- </div>
1435
- <Baz />
1436
- </article>
1437
- );
1438
- }
1439
-
1440
- function ServerApp() {
1441
- const Context = inlineLazyServerContextInitialization();
1442
- return (
1443
- <>
1444
- <Context.Provider value="test">
1445
- <Bar />
1446
- </Context.Provider>
1447
- <Bar />
1448
- </>
1449
- );
1450
- }
1451
-
1452
- function ClientApp({serverModel}) {
1453
- return (
1454
- <>
1455
- {serverModel}
1456
- <ClientBaz />
1457
- </>
1458
- );
1459
- }
1460
-
1461
- const transport = ReactNoopFlightServer.render(<ServerApp />);
1462
-
1463
- expect(ClientContext).toBe(undefined);
1464
-
1465
- // Reset all modules, except flight-modules which keeps the registry of Client Components
1466
- const flightModules = require('react-noop-renderer/flight-modules');
1467
- jest.resetModules();
1468
- jest.mock('react', () => require('react/react.react-server'));
1469
- jest.mock('react-noop-renderer/flight-modules', () => flightModules);
1470
-
1471
- ReactServer = require('react');
1472
- ReactNoopFlightServer = require('react-noop-renderer/flight-server');
1473
-
1474
- __unmockReact();
1475
- jest.resetModules();
1476
- jest.mock('react-noop-renderer/flight-modules', () => flightModules);
1477
- React = require('react');
1478
- ReactNoop = require('react-noop-renderer');
1479
- ReactNoopFlightClient = require('react-noop-renderer/flight-client');
1480
- act = require('internal-test-utils').act;
1481
- Scheduler = require('scheduler');
1482
-
1483
- await act(async () => {
1484
- const serverModel = await ReactNoopFlightClient.read(transport);
1485
- ReactNoop.render(<ClientApp serverModel={serverModel} />);
1486
- });
1487
-
1488
- expect(ClientContext).not.toBe(ServerContext);
1489
-
1490
- expect(ReactNoop).toMatchRenderedOutput(
1491
- <>
1492
- <article>
1493
- <div>test</div>
1494
- <div>test</div>
1495
- </article>
1496
- <article>
1497
- <div>default</div>
1498
- <div>default</div>
1499
- </article>
1500
- <div>default</div>
1501
- </>,
1502
- );
1503
- });
1504
- });
1505
-
1158
// @gate enableTaint
1159
it('errors when a tainted object is serialized', async () => {
1160
function UserClient({user}) {
packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js
+2
-80
@@ -3353,62 +3353,6 @@ describe('ReactDOMFizzServer', () => {
3353
]);
3354
});
3355
3356
- // @gate enableServerContext
3357
- it('supports ServerContext', async () => {
3358
- let ServerContext;
3359
- function inlineLazyServerContextInitialization() {
3360
- if (!ServerContext) {
3361
- expect(() => {
3362
- ServerContext = React.createServerContext('ServerContext', 'default');
3363
- }).toErrorDev(
3364
- 'Server Context is deprecated and will soon be removed. ' +
3365
- 'It was never documented and we have found it not to be useful ' +
3366
- 'enough to warrant the downside it imposes on all apps.',
3367
- );
3368
- }
3369
- return ServerContext;
3370
- }
3371
-
3372
- function Foo() {
3373
- React.useState(); // component stack generation shouldn't reinit
3374
- inlineLazyServerContextInitialization();
3375
- return (
3376
- <>
3377
- <ServerContext.Provider value="hi this is server outer">
3378
- <ServerContext.Provider value="hi this is server">
3379
- <Bar />
3380
- </ServerContext.Provider>
3381
- <ServerContext.Provider value="hi this is server2">
3382
- <Bar />
3383
- </ServerContext.Provider>
3384
- <Bar />
3385
- </ServerContext.Provider>
3386
- <ServerContext.Provider value="hi this is server outer2">
3387
- <Bar />
3388
- </ServerContext.Provider>
3389
- <Bar />
3390
- </>
3391
- );
3392
- }
3393
- function Bar() {
3394
- const context = React.useContext(inlineLazyServerContextInitialization());
3395
- return <span>{context}</span>;
3396
- }
3397
-
3398
- await act(() => {
3399
- const {pipe} = renderToPipeableStream(<Foo />);
3400
- pipe(writable);
3401
- });
3402
-
3403
- expect(getVisibleChildren(container)).toEqual([
3404
- <span>hi this is server</span>,
3405
- <span>hi this is server2</span>,
3406
- <span>hi this is server outer</span>,
3407
- <span>hi this is server outer2</span>,
3408
- <span>default</span>,
3409
- ]);
3410
- });
3411
-
3356
it('Supports iterable', async () => {
3357
const Immutable = require('immutable');
3358
@@ -5886,39 +5830,18 @@ describe('ReactDOMFizzServer', () => {
5830
expect(getVisibleChildren(container)).toEqual('ABC');
5831
});
5832
5889
- // @gate enableServerContext
5833
it('basic use(context)', async () => {
5834
const ContextA = React.createContext('default');
5835
const ContextB = React.createContext('B');
5893
- let ServerContext;
5894
- expect(() => {
5895
- ServerContext = React.createServerContext('ServerContext', 'default');
5896
- }).toErrorDev(
5897
- 'Server Context is deprecated and will soon be removed. ' +
5898
- 'It was never documented and we have found it not to be useful ' +
5899
- 'enough to warrant the downside it imposes on all apps.',
5900
- {withoutStack: true},
5901
- );
5836
function Client() {
5837
return use(ContextA) + use(ContextB);
5838
}
5905
- function ServerComponent() {
5906
- return use(ServerContext);
5907
- }
5908
- function Server() {
5909
- return (
5910
- <ServerContext.Provider value="C">
5911
- <ServerComponent />
5912
- </ServerContext.Provider>
5913
- );
5914
- }
5839
function App() {
5840
return (
5841
<>
5842
<ContextA.Provider value="A">
5843
<Client />
5844
</ContextA.Provider>
5921
- <Server />
5845
</>
5846
);
5847
}
@@ -5927,16 +5850,15 @@ describe('ReactDOMFizzServer', () => {
5850
const {pipe} = renderToPipeableStream(<App />);
5851
pipe(writable);
5852
});
5930
- expect(getVisibleChildren(container)).toEqual(['AB', 'C']);
5853
+ expect(getVisibleChildren(container)).toEqual('AB');
5854
5855
// Hydration uses a different renderer runtime (Fiber instead of Fizz).
5856
// We reset _currentRenderer here to not trigger a warning about multiple
5857
// renderers concurrently using these contexts
5858
ContextA._currentRenderer = null;
5936
- ServerContext._currentRenderer = null;
5859
ReactDOMClient.hydrateRoot(container, <App />);
5860
await waitForAll([]);
5939
- expect(getVisibleChildren(container)).toEqual(['AB', 'C']);
5861
+ expect(getVisibleChildren(container)).toEqual('AB');
5862
});
5863
5864
it('use(promise) in multiple components', async () => {
packages/react-is/src/ReactIs.js
-2
@@ -11,7 +11,6 @@
11
12
import {
13
REACT_CONTEXT_TYPE,
14
- REACT_SERVER_CONTEXT_TYPE,
14
REACT_ELEMENT_TYPE,
15
REACT_FORWARD_REF_TYPE,
16
REACT_FRAGMENT_TYPE,
@@ -44,7 +43,6 @@ export function typeOf(object: any): mixed {
43
const $$typeofType = type && type.$$typeof;
44
45
switch ($$typeofType) {
47
- case REACT_SERVER_CONTEXT_TYPE:
46
case REACT_CONTEXT_TYPE:
47
case REACT_FORWARD_REF_TYPE:
48
case REACT_LAZY_TYPE:
packages/react-noop-renderer/src/ReactNoopFlightServer.js
-3
@@ -15,7 +15,6 @@
15
*/
16
17
import type {ReactClientValue} from 'react-server/src/ReactFlightServer';
18
-import type {ServerContextJSONValue} from 'shared/ReactTypes';
18
19
import {saveModule} from 'react-noop-renderer/flight-modules';
20
@@ -70,7 +69,6 @@ const ReactNoopFlightServer = ReactFlightServer({
69
70
type Options = {
71
onError?: (error: mixed) => void,
73
- context?: Array<[string, ServerContextJSONValue]>,
72
identifierPrefix?: string,
73
};
74
@@ -81,7 +79,6 @@ function render(model: ReactClientValue, options?: Options): Destination {
79
model,
80
bundlerConfig,
81
options ? options.onError : undefined,
84
- options ? options.context : undefined,
82
options ? options.identifierPrefix : undefined,
83
);
84
ReactNoopFlightServer.startWork(request);
packages/react-reconciler/src/ReactChildFiber.js
+4
-17
@@ -27,7 +27,6 @@ import {
27
REACT_PORTAL_TYPE,
28
REACT_LAZY_TYPE,
29
REACT_CONTEXT_TYPE,
30
- REACT_SERVER_CONTEXT_TYPE,
30
} from 'shared/ReactSymbols';
31
import {ClassComponent, HostText, HostPortal, Fragment} from './ReactWorkTags';
32
import isArray from 'shared/isArray';
@@ -577,10 +576,7 @@ function createChildReconciler(
576
return createChild(returnFiber, unwrapThenable(thenable), lanes);
577
}
578
580
- if (
581
- newChild.$$typeof === REACT_CONTEXT_TYPE ||
582
- newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE
583
- ) {
579
+ if (newChild.$$typeof === REACT_CONTEXT_TYPE) {
580
const context: ReactContext<mixed> = (newChild: any);
581
return createChild(
582
returnFiber,
@@ -667,10 +663,7 @@ function createChildReconciler(
663
);
664
}
665
670
- if (
671
- newChild.$$typeof === REACT_CONTEXT_TYPE ||
672
- newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE
673
- ) {
666
+ if (newChild.$$typeof === REACT_CONTEXT_TYPE) {
667
const context: ReactContext<mixed> = (newChild: any);
668
return updateSlot(
669
returnFiber,
@@ -756,10 +749,7 @@ function createChildReconciler(
749
);
750
}
751
759
- if (
760
- newChild.$$typeof === REACT_CONTEXT_TYPE ||
761
- newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE
762
- ) {
752
+ if (newChild.$$typeof === REACT_CONTEXT_TYPE) {
753
const context: ReactContext<mixed> = (newChild: any);
754
return updateFromMap(
755
existingChildren,
@@ -1442,10 +1432,7 @@ function createChildReconciler(
1432
);
1433
}
1434
1445
- if (
1446
- newChild.$$typeof === REACT_CONTEXT_TYPE ||
1447
- newChild.$$typeof === REACT_SERVER_CONTEXT_TYPE
1448
- ) {
1435
+ if (newChild.$$typeof === REACT_CONTEXT_TYPE) {
1436
const context: ReactContext<mixed> = (newChild: any);
1437
return reconcileChildFibersImpl(
1438
returnFiber,
packages/react-reconciler/src/ReactFiberCacheComponent.js
-2
@@ -73,8 +73,6 @@ export const CacheContext: ReactContext<Cache> = enableCache
73
_currentValue: (null: any),
74
_currentValue2: (null: any),
75
_threadCount: 0,
76
- _defaultValue: (null: any),
77
- _globalName: (null: any),
76
}
77
: (null: any);
78
packages/react-reconciler/src/ReactFiberHooks.js
+1
-5
@@ -46,7 +46,6 @@ import {
46
} from 'shared/ReactFeatureFlags';
47
import {
48
REACT_CONTEXT_TYPE,
49
- REACT_SERVER_CONTEXT_TYPE,
49
REACT_MEMO_CACHE_SENTINEL,
50
} from 'shared/ReactSymbols';
51
@@ -1072,10 +1071,7 @@ function use<T>(usable: Usable<T>): T {
1071
// This is a thenable.
1072
const thenable: Thenable<T> = (usable: any);
1073
return useThenable(thenable);
1075
- } else if (
1076
- usable.$$typeof === REACT_CONTEXT_TYPE ||
1077
- usable.$$typeof === REACT_SERVER_CONTEXT_TYPE
1078
- ) {
1074
+ } else if (usable.$$typeof === REACT_CONTEXT_TYPE) {
1075
const context: ReactContext<T> = (usable: any);
1076
return readContext(context);
1077
}
packages/react-reconciler/src/ReactFiberHostContext.js
-2
@@ -51,8 +51,6 @@ export const HostTransitionContext: ReactContext<TransitionStatus | null> = {
51
_threadCount: 0,
52
Provider: (null: any),
53
Consumer: (null: any),
54
- _defaultValue: (null: any),
55
- _globalName: (null: any),
54
};
55
56
function requiredContext<Value>(c: Value | null): Value {
packages/react-reconciler/src/ReactFiberNewContext.js
+2
-18
@@ -44,11 +44,9 @@ import {createUpdate, ForceUpdate} from './ReactFiberClassUpdateQueue';
44
import {markWorkInProgressReceivedUpdate} from './ReactFiberBeginWork';
45
import {
46
enableLazyContextPropagation,
47
- enableServerContext,
47
enableFormActions,
48
enableAsyncActions,
49
} from 'shared/ReactFeatureFlags';
51
-import {REACT_SERVER_CONTEXT_DEFAULT_VALUE_NOT_LOADED} from 'shared/ReactSymbols';
50
import {
51
getHostTransitionProvider,
52
HostTransitionContext,
@@ -153,28 +151,14 @@ export function popProvider(
151
const currentValue = valueCursor.current;
152
153
if (isPrimaryRenderer) {
156
- if (
157
- enableServerContext &&
158
- currentValue === REACT_SERVER_CONTEXT_DEFAULT_VALUE_NOT_LOADED
159
- ) {
160
- context._currentValue = context._defaultValue;
161
- } else {
162
- context._currentValue = currentValue;
163
- }
154
+ context._currentValue = currentValue;
155
if (__DEV__) {
156
const currentRenderer = rendererCursorDEV.current;
157
pop(rendererCursorDEV, providerFiber);
158
context._currentRenderer = currentRenderer;
159
}
160
} else {
170
- if (
171
- enableServerContext &&
172
- currentValue === REACT_SERVER_CONTEXT_DEFAULT_VALUE_NOT_LOADED
173
- ) {
174
- context._currentValue2 = context._defaultValue;
175
- } else {
176
- context._currentValue2 = currentValue;
177
- }
161
+ context._currentValue2 = currentValue;
162
if (__DEV__) {
163
const currentRenderer2 = renderer2CursorDEV.current;
164
pop(renderer2CursorDEV, providerFiber);
packages/react-server-dom-esm/src/ReactFlightDOMServerNode.js
+1
-3
@@ -16,7 +16,7 @@ import type {ClientManifest} from './ReactFlightServerConfigESMBundler';
16
import type {ServerManifest} from 'react-client/src/ReactFlightClientConfig';
17
import type {Busboy} from 'busboy';
18
import type {Writable} from 'stream';
19
-import type {ServerContextJSONValue, Thenable} from 'shared/ReactTypes';
19
+import type {Thenable} from 'shared/ReactTypes';
20
21
import {
22
createRequest,
@@ -54,7 +54,6 @@ function createDrainHandler(destination: Destination, request: Request) {
54
type Options = {
55
onError?: (error: mixed) => void,
56
onPostpone?: (reason: string) => void,
57
- context?: Array<[string, ServerContextJSONValue]>,
57
identifierPrefix?: string,
58
};
59
@@ -72,7 +71,6 @@ function renderToPipeableStream(
71
model,
72
moduleBasePath,
73
options ? options.onError : undefined,
75
- options ? options.context : undefined,
74
options ? options.identifierPrefix : undefined,
75
options ? options.onPostpone : undefined,
76
);
packages/react-server-dom-turbopack/src/ReactFlightDOMServerBrowser.js
+1
-3
@@ -8,7 +8,7 @@
8
*/
9
10
import type {ReactClientValue} from 'react-server/src/ReactFlightServer';
11
-import type {ServerContextJSONValue, Thenable} from 'shared/ReactTypes';
11
+import type {Thenable} from 'shared/ReactTypes';
12
import type {ClientManifest} from './ReactFlightServerConfigTurbopackBundler';
13
import type {ServerManifest} from 'react-client/src/ReactFlightClientConfig';
14
@@ -36,7 +36,6 @@ export {
36
type Options = {
37
identifierPrefix?: string,
38
signal?: AbortSignal,
39
- context?: Array<[string, ServerContextJSONValue]>,
39
onError?: (error: mixed) => void,
40
onPostpone?: (reason: string) => void,
41
};
@@ -50,7 +49,6 @@ function renderToReadableStream(
49
model,
50
turbopackMap,
51
options ? options.onError : undefined,
53
- options ? options.context : undefined,
52
options ? options.identifierPrefix : undefined,
53
options ? options.onPostpone : undefined,
54
);
packages/react-server-dom-turbopack/src/ReactFlightDOMServerEdge.js
+1
-3
@@ -8,7 +8,7 @@
8
*/
9
10
import type {ReactClientValue} from 'react-server/src/ReactFlightServer';
11
-import type {ServerContextJSONValue, Thenable} from 'shared/ReactTypes';
11
+import type {Thenable} from 'shared/ReactTypes';
12
import type {ClientManifest} from './ReactFlightServerConfigTurbopackBundler';
13
import type {ServerManifest} from 'react-client/src/ReactFlightClientConfig';
14
@@ -36,7 +36,6 @@ export {
36
type Options = {
37
identifierPrefix?: string,
38
signal?: AbortSignal,
39
- context?: Array<[string, ServerContextJSONValue]>,
39
onError?: (error: mixed) => void,
40
onPostpone?: (reason: string) => void,
41
};
@@ -50,7 +49,6 @@ function renderToReadableStream(
49
model,
50
turbopackMap,
51
options ? options.onError : undefined,
53
- options ? options.context : undefined,
52
options ? options.identifierPrefix : undefined,
53
options ? options.onPostpone : undefined,
54
);
packages/react-server-dom-turbopack/src/ReactFlightDOMServerNode.js
+1
-3
@@ -16,7 +16,7 @@ import type {ClientManifest} from './ReactFlightServerConfigTurbopackBundler';
16
import type {ServerManifest} from 'react-client/src/ReactFlightClientConfig';
17
import type {Busboy} from 'busboy';
18
import type {Writable} from 'stream';
19
-import type {ServerContextJSONValue, Thenable} from 'shared/ReactTypes';
19
+import type {Thenable} from 'shared/ReactTypes';
20
21
import {
22
createRequest,
@@ -51,7 +51,6 @@ function createDrainHandler(destination: Destination, request: Request) {
51
type Options = {
52
onError?: (error: mixed) => void,
53
onPostpone?: (reason: string) => void,
54
- context?: Array<[string, ServerContextJSONValue]>,
54
identifierPrefix?: string,
55
};
56
@@ -69,7 +68,6 @@ function renderToPipeableStream(
68
model,
69
turbopackMap,
70
options ? options.onError : undefined,
72
- options ? options.context : undefined,
71
options ? options.identifierPrefix : undefined,
72
options ? options.onPostpone : undefined,
73
);
packages/react-server-dom-webpack/src/ReactFlightDOMServerBrowser.js
+1
-3
@@ -8,7 +8,7 @@
8
*/
9
10
import type {ReactClientValue} from 'react-server/src/ReactFlightServer';
11
-import type {ServerContextJSONValue, Thenable} from 'shared/ReactTypes';
11
+import type {Thenable} from 'shared/ReactTypes';
12
import type {ClientManifest} from './ReactFlightServerConfigWebpackBundler';
13
import type {ServerManifest} from 'react-client/src/ReactFlightClientConfig';
14
@@ -40,7 +40,6 @@ export {
40
type Options = {
41
identifierPrefix?: string,
42
signal?: AbortSignal,
43
- context?: Array<[string, ServerContextJSONValue]>,
43
onError?: (error: mixed) => void,
44
onPostpone?: (reason: string) => void,
45
};
@@ -54,7 +53,6 @@ function renderToReadableStream(
53
model,
54
webpackMap,
55
options ? options.onError : undefined,
57
- options ? options.context : undefined,
56
options ? options.identifierPrefix : undefined,
57
options ? options.onPostpone : undefined,
58
);
packages/react-server-dom-webpack/src/ReactFlightDOMServerEdge.js
+1
-3
@@ -8,7 +8,7 @@
8
*/
9
10
import type {ReactClientValue} from 'react-server/src/ReactFlightServer';
11
-import type {ServerContextJSONValue, Thenable} from 'shared/ReactTypes';
11
+import type {Thenable} from 'shared/ReactTypes';
12
import type {ClientManifest} from './ReactFlightServerConfigWebpackBundler';
13
import type {ServerManifest} from 'react-client/src/ReactFlightClientConfig';
14
@@ -40,7 +40,6 @@ export {
40
type Options = {
41
identifierPrefix?: string,
42
signal?: AbortSignal,
43
- context?: Array<[string, ServerContextJSONValue]>,
43
onError?: (error: mixed) => void,
44
onPostpone?: (reason: string) => void,
45
};
@@ -54,7 +53,6 @@ function renderToReadableStream(
53
model,
54
webpackMap,
55
options ? options.onError : undefined,
57
- options ? options.context : undefined,
56
options ? options.identifierPrefix : undefined,
57
options ? options.onPostpone : undefined,
58
);
packages/react-server-dom-webpack/src/ReactFlightDOMServerNode.js
+1
-3
@@ -16,7 +16,7 @@ import type {ClientManifest} from './ReactFlightServerConfigWebpackBundler';
16
import type {ServerManifest} from 'react-client/src/ReactFlightClientConfig';
17
import type {Busboy} from 'busboy';
18
import type {Writable} from 'stream';
19
-import type {ServerContextJSONValue, Thenable} from 'shared/ReactTypes';
19
+import type {Thenable} from 'shared/ReactTypes';
20
21
import {
22
createRequest,
@@ -63,7 +63,6 @@ function createCancelHandler(request: Request, reason: string) {
63
type Options = {
64
onError?: (error: mixed) => void,
65
onPostpone?: (reason: string) => void,
66
- context?: Array<[string, ServerContextJSONValue]>,
66
identifierPrefix?: string,
67
};
68
@@ -81,7 +80,6 @@ function renderToPipeableStream(
80
model,
81
webpackMap,
82
options ? options.onError : undefined,
84
- options ? options.context : undefined,
83
options ? options.identifierPrefix : undefined,
84
options ? options.onPostpone : undefined,
85
);
packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMBrowser-test.js
-48
@@ -641,54 +641,6 @@ describe('ReactFlightDOMBrowser', () => {
641
expect(container.innerHTML).toBe('ABC');
642
});
643
644
- // @gate enableServerContext
645
- it('basic use(context)', async () => {
646
- let ContextA;
647
- let ContextB;
648
- expect(() => {
649
- ContextA = React.createServerContext('ContextA', '');
650
- ContextB = React.createServerContext('ContextB', 'B');
651
- }).toErrorDev(
652
- [
653
- 'Server Context is deprecated and will soon be removed. ' +
654
- 'It was never documented and we have found it not to be useful ' +
655
- 'enough to warrant the downside it imposes on all apps.',
656
- 'Server Context is deprecated and will soon be removed. ' +
657
- 'It was never documented and we have found it not to be useful ' +
658
- 'enough to warrant the downside it imposes on all apps.',
659
- ],
660
- {withoutStack: true},
661
- );
662
-
663
- function ServerComponent() {
664
- return ReactServer.use(ContextA) + ReactServer.use(ContextB);
665
- }
666
- function Server() {
667
- return (
668
- <ContextA.Provider value="A">
669
- <ServerComponent />
670
- </ContextA.Provider>
671
- );
672
- }
673
- const stream = ReactServerDOMServer.renderToReadableStream(<Server />);
674
- const response = ReactServerDOMClient.createFromReadableStream(stream);
675
-
676
- function Client() {
677
- return use(response);
678
- }
679
-
680
- const container = document.createElement('div');
681
- const root = ReactDOMClient.createRoot(container);
682
- await act(() => {
683
- // Client uses a different renderer.
684
- // We reset _currentRenderer here to not trigger a warning about multiple
685
- // renderers concurrently using this context
686
- ContextA._currentRenderer = null;
687
- root.render(<Client />);
688
- });
689
- expect(container.innerHTML).toBe('AB');
690
- });
691
-
644
it('use(promise) in multiple components', async () => {
645
function Child({prefix}) {
646
return (
packages/react-server/src/ReactFizzHooks.js
+1
-5
@@ -40,7 +40,6 @@ import {
40
} from 'shared/ReactFeatureFlags';
41
import is from 'shared/objectIs';
42
import {
43
- REACT_SERVER_CONTEXT_TYPE,
43
REACT_CONTEXT_TYPE,
44
REACT_MEMO_CACHE_SENTINEL,
45
} from 'shared/ReactSymbols';
@@ -745,10 +744,7 @@ function use<T>(usable: Usable<T>): T {
744
// This is a thenable.
745
const thenable: Thenable<T> = (usable: any);
746
return unwrapThenable(thenable);
748
- } else if (
749
- usable.$$typeof === REACT_CONTEXT_TYPE ||
750
- usable.$$typeof === REACT_SERVER_CONTEXT_TYPE
751
- ) {
747
+ } else if (usable.$$typeof === REACT_CONTEXT_TYPE) {
748
const context: ReactContext<T> = (usable: any);
749
return readContext(context);
750
}
packages/react-server/src/ReactFizzNewContext.js
+2
-11
@@ -9,7 +9,6 @@
9
10
import type {ReactContext} from 'shared/ReactTypes';
11
12
-import {REACT_SERVER_CONTEXT_DEFAULT_VALUE_NOT_LOADED} from 'shared/ReactSymbols';
12
import {isPrimaryRenderer} from './ReactFizzConfig';
13
14
let rendererSigil;
@@ -246,11 +245,7 @@ export function popProvider<T>(context: ReactContext<T>): ContextSnapshot {
245
}
246
if (isPrimaryRenderer) {
247
const value = prevSnapshot.parentValue;
249
- if (value === REACT_SERVER_CONTEXT_DEFAULT_VALUE_NOT_LOADED) {
250
- prevSnapshot.context._currentValue = prevSnapshot.context._defaultValue;
251
- } else {
252
- prevSnapshot.context._currentValue = value;
253
- }
248
+ prevSnapshot.context._currentValue = value;
249
if (__DEV__) {
250
if (
251
context._currentRenderer !== undefined &&
@@ -266,11 +261,7 @@ export function popProvider<T>(context: ReactContext<T>): ContextSnapshot {
261
}
262
} else {
263
const value = prevSnapshot.parentValue;
269
- if (value === REACT_SERVER_CONTEXT_DEFAULT_VALUE_NOT_LOADED) {
270
- prevSnapshot.context._currentValue2 = prevSnapshot.context._defaultValue;
271
- } else {
272
- prevSnapshot.context._currentValue2 = value;
273
- }
264
+ prevSnapshot.context._currentValue2 = value;
265
if (__DEV__) {
266
if (
267
context._currentRenderer2 !== undefined &&
packages/react-server/src/ReactFizzServer.js
+1
-5
@@ -129,7 +129,6 @@ import {
129
REACT_MEMO_TYPE,
130
REACT_PROVIDER_TYPE,
131
REACT_CONTEXT_TYPE,
132
- REACT_SERVER_CONTEXT_TYPE,
132
REACT_SCOPE_TYPE,
133
REACT_OFFSCREEN_TYPE,
134
REACT_POSTPONE_TYPE,
@@ -2270,10 +2269,7 @@ function renderNodeDestructive(
2269
);
2270
}
2271
2273
- if (
2274
- maybeUsable.$$typeof === REACT_CONTEXT_TYPE ||
2275
- maybeUsable.$$typeof === REACT_SERVER_CONTEXT_TYPE
2276
- ) {
2272
+ if (maybeUsable.$$typeof === REACT_CONTEXT_TYPE) {
2273
const context: ReactContext<ReactNodeList> = (maybeUsable: any);
2274
return renderNodeDestructive(
2275
request,
packages/react-server/src/ReactFlightHooks.js
+21
-37
@@ -9,13 +9,12 @@
9
10
import type {Dispatcher} from 'react-reconciler/src/ReactInternalTypes';
11
import type {Request} from './ReactFlightServer';
12
-import type {ReactServerContext, Thenable, Usable} from 'shared/ReactTypes';
12
+import type {Thenable, Usable} from 'shared/ReactTypes';
13
import type {ThenableState} from './ReactFlightThenable';
14
import {
15
- REACT_SERVER_CONTEXT_TYPE,
15
REACT_MEMO_CACHE_SENTINEL,
16
+ REACT_CONTEXT_TYPE,
17
} from 'shared/ReactSymbols';
18
-import {readContext as readContextImpl} from './ReactFlightNewContext';
18
import {createThenableState, trackUsedThenable} from './ReactFlightThenable';
19
import {isClientReference} from './ReactFlightServerConfig';
20
@@ -44,29 +43,6 @@ export function getThenableStateAfterSuspending(): null | ThenableState {
43
return state;
44
}
45
47
-function readContext<T>(context: ReactServerContext<T>): T {
48
- if (__DEV__) {
49
- if (context.$$typeof !== REACT_SERVER_CONTEXT_TYPE) {
50
- if (isClientReference(context)) {
51
- console.error('Cannot read a Client Context from a Server Component.');
52
- } else {
53
- console.error(
54
- 'Only createServerContext is supported in Server Components.',
55
- );
56
- }
57
- }
58
- if (currentRequest === null) {
59
- console.error(
60
- 'Context can only be read while React is rendering. ' +
61
- 'In classes, you can read it in the render method or getDerivedStateFromProps. ' +
62
- 'In function components, you can read it directly in the function body, but not ' +
63
- 'inside Hooks like useReducer() or useMemo().',
64
- );
65
- }
66
- }
67
- return readContextImpl(context);
68
-}
69
-
46
export const HooksDispatcher: Dispatcher = {
47
useMemo<T>(nextCreate: () => T): T {
48
return nextCreate();
@@ -77,8 +53,8 @@ export const HooksDispatcher: Dispatcher = {
53
useDebugValue(): void {},
54
useDeferredValue: (unsupportedHook: any),
55
useTransition: (unsupportedHook: any),
80
- readContext,
81
- useContext: readContext,
56
+ readContext: (unsupportedContext: any),
57
+ useContext: (unsupportedContext: any),
58
useReducer: (unsupportedHook: any),
59
useRef: (unsupportedHook: any),
60
useState: (unsupportedHook: any),
@@ -111,6 +87,10 @@ function unsupportedRefresh(): void {
87
);
88
}
89
90
+function unsupportedContext(): void {
91
+ throw new Error('Cannot read a Client Context from a Server Component.');
92
+}
93
+
94
function useId(): string {
95
if (currentRequest === null) {
96
throw new Error('useId can only be used while React is rendering');
@@ -138,18 +118,22 @@ function use<T>(usable: Usable<T>): T {
118
thenableState = createThenableState();
119
}
120
return trackUsedThenable(thenableState, thenable, index);
141
- } else if (usable.$$typeof === REACT_SERVER_CONTEXT_TYPE) {
142
- const context: ReactServerContext<T> = (usable: any);
143
- return readContext(context);
121
+ } else if (usable.$$typeof === REACT_CONTEXT_TYPE) {
122
+ unsupportedContext();
123
}
124
}
125
147
- if (__DEV__) {
148
- if (isClientReference(usable)) {
149
- console.error('Cannot use() an already resolved Client Reference.');
126
+ if (isClientReference(usable)) {
127
+ if (usable.value != null && usable.value.$$typeof === REACT_CONTEXT_TYPE) {
128
+ // Show a more specific message since it's a common mistake.
129
+ throw new Error('Cannot read a Client Context from a Server Component.');
130
+ } else {
131
+ throw new Error('Cannot use() an already resolved Client Reference.');
132
}
133
+ } else {
134
+ throw new Error(
135
+ // eslint-disable-next-line react-internal/safe-string-coercion
136
+ 'An unsupported type was passed to use(): ' + String(usable),
137
+ );
138
}
152
-
153
- // eslint-disable-next-line react-internal/safe-string-coercion
154
- throw new Error('An unsupported type was passed to use(): ' + String(usable));
139
}
packages/react-server/src/ReactFlightNewContext.js
deleted
-269
@@ -1,269 +0,0 @@
1
-/**
2
- * Copyright (c) Meta Platforms, Inc. and affiliates.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- *
7
- * @flow
8
- */
9
-
10
-import type {
11
- ReactServerContext,
12
- ServerContextJSONValue,
13
-} from 'shared/ReactTypes';
14
-
15
-import {REACT_SERVER_CONTEXT_DEFAULT_VALUE_NOT_LOADED} from 'shared/ReactSymbols';
16
-import {isPrimaryRenderer} from './ReactFlightServerConfig';
17
-
18
-let rendererSigil;
19
-if (__DEV__) {
20
- // Use this to detect multiple renderers using the same context
21
- rendererSigil = {};
22
-}
23
-
24
-// Used to store the parent path of all context overrides in a shared linked list.
25
-// Forming a reverse tree.
26
-type ContextNode<T: ServerContextJSONValue> = {
27
- parent: null | ContextNode<any>,
28
- depth: number, // Short hand to compute the depth of the tree at this node.
29
- context: ReactServerContext<T>,
30
- parentValue: T,
31
- value: T,
32
-};
33
-
34
-// The structure of a context snapshot is an implementation of this file.
35
-// Currently, it's implemented as tracking the current active node.
36
-export opaque type ContextSnapshot = null | ContextNode<any>;
37
-
38
-export const rootContextSnapshot: ContextSnapshot = null;
39
-
40
-// We assume that this runtime owns the "current" field on all ReactContext instances.
41
-// This global (actually thread local) state represents what state all those "current",
42
-// fields are currently in.
43
-let currentActiveSnapshot: ContextSnapshot = null;
44
-
45
-function popNode(prev: ContextNode<any>): void {
46
- if (isPrimaryRenderer) {
47
- prev.context._currentValue = prev.parentValue;
48
- } else {
49
- prev.context._currentValue2 = prev.parentValue;
50
- }
51
-}
52
-
53
-function pushNode(next: ContextNode<any>): void {
54
- if (isPrimaryRenderer) {
55
- next.context._currentValue = next.value;
56
- } else {
57
- next.context._currentValue2 = next.value;
58
- }
59
-}
60
-
61
-function popToNearestCommonAncestor(
62
- prev: ContextNode<any>,
63
- next: ContextNode<any>,
64
-): void {
65
- if (prev === next) {
66
- // We've found a shared ancestor. We don't need to pop nor reapply this one or anything above.
67
- } else {
68
- popNode(prev);
69
- const parentPrev = prev.parent;
70
- const parentNext = next.parent;
71
- if (parentPrev === null) {
72
- if (parentNext !== null) {
73
- throw new Error(
74
- 'The stacks must reach the root at the same time. This is a bug in React.',
75
- );
76
- }
77
- } else {
78
- if (parentNext === null) {
79
- throw new Error(
80
- 'The stacks must reach the root at the same time. This is a bug in React.',
81
- );
82
- }
83
-
84
- popToNearestCommonAncestor(parentPrev, parentNext);
85
- // On the way back, we push the new ones that weren't common.
86
- pushNode(next);
87
- }
88
- }
89
-}
90
-
91
-function popAllPrevious(prev: ContextNode<any>): void {
92
- popNode(prev);
93
- const parentPrev = prev.parent;
94
- if (parentPrev !== null) {
95
- popAllPrevious(parentPrev);
96
- }
97
-}
98
-
99
-function pushAllNext(next: ContextNode<any>): void {
100
- const parentNext = next.parent;
101
- if (parentNext !== null) {
102
- pushAllNext(parentNext);
103
- }
104
- pushNode(next);
105
-}
106
-
107
-function popPreviousToCommonLevel(
108
- prev: ContextNode<any>,
109
- next: ContextNode<any>,
110
-): void {
111
- popNode(prev);
112
- const parentPrev = prev.parent;
113
-
114
- if (parentPrev === null) {
115
- throw new Error(
116
- 'The depth must equal at least at zero before reaching the root. This is a bug in React.',
117
- );
118
- }
119
-
120
- if (parentPrev.depth === next.depth) {
121
- // We found the same level. Now we just need to find a shared ancestor.
122
- popToNearestCommonAncestor(parentPrev, next);
123
- } else {
124
- // We must still be deeper.
125
- popPreviousToCommonLevel(parentPrev, next);
126
- }
127
-}
128
-
129
-function popNextToCommonLevel(
130
- prev: ContextNode<any>,
131
- next: ContextNode<any>,
132
-): void {
133
- const parentNext = next.parent;
134
-
135
- if (parentNext === null) {
136
- throw new Error(
137
- 'The depth must equal at least at zero before reaching the root. This is a bug in React.',
138
- );
139
- }
140
-
141
- if (prev.depth === parentNext.depth) {
142
- // We found the same level. Now we just need to find a shared ancestor.
143
- popToNearestCommonAncestor(prev, parentNext);
144
- } else {
145
- // We must still be deeper.
146
- popNextToCommonLevel(prev, parentNext);
147
- }
148
- pushNode(next);
149
-}
150
-
151
-// Perform context switching to the new snapshot.
152
-// To make it cheap to read many contexts, while not suspending, we make the switch eagerly by
153
-// updating all the context's current values. That way reads, always just read the current value.
154
-// At the cost of updating contexts even if they're never read by this subtree.
155
-export function switchContext(newSnapshot: ContextSnapshot): void {
156
- // The basic algorithm we need to do is to pop back any contexts that are no longer on the stack.
157
- // We also need to update any new contexts that are now on the stack with the deepest value.
158
- // The easiest way to update new contexts is to just reapply them in reverse order from the
159
- // perspective of the backpointers. To avoid allocating a lot when switching, we use the stack
160
- // for that. Therefore this algorithm is recursive.
161
- // 1) First we pop which ever snapshot tree was deepest. Popping old contexts as we go.
162
- // 2) Then we find the nearest common ancestor from there. Popping old contexts as we go.
163
- // 3) Then we reapply new contexts on the way back up the stack.
164
- const prev = currentActiveSnapshot;
165
- const next = newSnapshot;
166
- if (prev !== next) {
167
- if (prev === null) {
168
- // $FlowFixMe[incompatible-call]: This has to be non-null since it's not equal to prev.
169
- pushAllNext(next);
170
- } else if (next === null) {
171
- popAllPrevious(prev);
172
- } else if (prev.depth === next.depth) {
173
- popToNearestCommonAncestor(prev, next);
174
- } else if (prev.depth > next.depth) {
175
- popPreviousToCommonLevel(prev, next);
176
- } else {
177
- popNextToCommonLevel(prev, next);
178
- }
179
- currentActiveSnapshot = next;
180
- }
181
-}
182
-
183
-export function pushProvider<T: ServerContextJSONValue>(
184
- context: ReactServerContext<T>,
185
- nextValue: T,
186
-): ContextSnapshot {
187
- let prevValue;
188
- if (isPrimaryRenderer) {
189
- prevValue = context._currentValue;
190
- context._currentValue = nextValue;
191
- if (__DEV__) {
192
- if (
193
- context._currentRenderer !== undefined &&
194
- context._currentRenderer !== null &&
195
- context._currentRenderer !== rendererSigil
196
- ) {
197
- console.error(
198
- 'Detected multiple renderers concurrently rendering the ' +
199
- 'same context provider. This is currently unsupported.',
200
- );
201
- }
202
- context._currentRenderer = rendererSigil;
203
- }
204
- } else {
205
- prevValue = context._currentValue2;
206
- context._currentValue2 = nextValue;
207
- if (__DEV__) {
208
- if (
209
- context._currentRenderer2 !== undefined &&
210
- context._currentRenderer2 !== null &&
211
- context._currentRenderer2 !== rendererSigil
212
- ) {
213
- console.error(
214
- 'Detected multiple renderers concurrently rendering the ' +
215
- 'same context provider. This is currently unsupported.',
216
- );
217
- }
218
- context._currentRenderer2 = rendererSigil;
219
- }
220
- }
221
- const prevNode = currentActiveSnapshot;
222
- const newNode: ContextNode<T> = {
223
- parent: prevNode,
224
- depth: prevNode === null ? 0 : prevNode.depth + 1,
225
- context: context,
226
- parentValue: prevValue,
227
- value: nextValue,
228
- };
229
- currentActiveSnapshot = newNode;
230
- return newNode;
231
-}
232
-
233
-export function popProvider(): ContextSnapshot {
234
- const prevSnapshot = currentActiveSnapshot;
235
-
236
- if (prevSnapshot === null) {
237
- throw new Error(
238
- 'Tried to pop a Context at the root of the app. This is a bug in React.',
239
- );
240
- }
241
-
242
- if (isPrimaryRenderer) {
243
- const value = prevSnapshot.parentValue;
244
- if (value === REACT_SERVER_CONTEXT_DEFAULT_VALUE_NOT_LOADED) {
245
- prevSnapshot.context._currentValue = prevSnapshot.context._defaultValue;
246
- } else {
247
- prevSnapshot.context._currentValue = value;
248
- }
249
- } else {
250
- const value = prevSnapshot.parentValue;
251
- if (value === REACT_SERVER_CONTEXT_DEFAULT_VALUE_NOT_LOADED) {
252
- prevSnapshot.context._currentValue2 = prevSnapshot.context._defaultValue;
253
- } else {
254
- prevSnapshot.context._currentValue2 = value;
255
- }
256
- }
257
- return (currentActiveSnapshot = prevSnapshot.parent);
258
-}
259
-
260
-export function getActiveContext(): ContextSnapshot {
261
- return currentActiveSnapshot;
262
-}
263
-
264
-export function readContext<T>(context: ReactServerContext<T>): T {
265
- const value = isPrimaryRenderer
266
- ? context._currentValue
267
- : context._currentValue2;
268
- return value;
269
-}
packages/react-server/src/ReactFlightServer.js
+4
-166
@@ -15,7 +15,6 @@ import {
15
enableBinaryFlight,
16
enablePostpone,
17
enableTaint,
18
- enableServerContext,
18
enableServerComponentKeys,
19
} from 'shared/ReactFeatureFlags';
20
@@ -46,17 +45,13 @@ import type {
45
HintCode,
46
HintModel,
47
} from './ReactFlightServerConfig';
49
-import type {ContextSnapshot} from './ReactFlightNewContext';
48
import type {ThenableState} from './ReactFlightThenable';
49
import type {
52
- ReactProviderType,
53
- ServerContextJSONValue,
50
Wakeable,
51
Thenable,
52
PendingThenable,
53
FulfilledThenable,
54
RejectedThenable,
59
- ReactServerContext,
55
} from 'shared/ReactTypes';
56
import type {LazyComponent} from 'react/src/ReactLazy';
57
@@ -82,13 +77,6 @@ import {
77
resetHooksForRequest,
78
} from './ReactFlightHooks';
79
import {DefaultCacheDispatcher} from './flight/ReactFlightServerCache';
85
-import {
86
- pushProvider,
87
- popProvider,
88
- switchContext,
89
- getActiveContext,
90
- rootContextSnapshot,
91
-} from './ReactFlightNewContext';
80
81
import {
82
getIteratorFn,
@@ -98,7 +86,6 @@ import {
86
REACT_LAZY_TYPE,
87
REACT_MEMO_TYPE,
88
REACT_POSTPONE_TYPE,
101
- REACT_PROVIDER_TYPE,
89
} from 'shared/ReactSymbols';
90
91
import {
@@ -110,7 +97,6 @@ import {
97
objectName,
98
} from 'shared/ReactSerializationErrors';
99
113
-import {getOrCreateServerContext} from 'shared/ReactServerContextRegistry';
100
import ReactSharedInternals from 'shared/ReactSharedInternals';
101
import ReactServerSharedInternals from './ReactServerSharedInternals';
102
import isArray from 'shared/isArray';
@@ -153,7 +139,6 @@ export type ReactClientValue =
139
// subtype, so the receiver can only accept once of these.
140
| React$Element<string>
141
| React$Element<ClientReference<any> & any>
156
- | ReactServerContext<any>
142
| string
143
| boolean
144
| number
@@ -184,7 +169,6 @@ type Task = {
169
toJSON: (key: string, value: ReactClientValue) => ReactJSONValue,
170
keyPath: null | string, // parent server component keys
171
implicitSlot: boolean, // true if the root server component of this sequence had a null key
187
- context: ContextSnapshot,
172
thenableState: ThenableState | null,
173
};
174
@@ -209,7 +193,6 @@ export type Request = {
193
writtenSymbols: Map<symbol, number>,
194
writtenClientReferences: Map<ClientReferenceKey, number>,
195
writtenServerReferences: Map<ServerReference<any>, number>,
212
- writtenProviders: Map<string, number>,
196
writtenObjects: WeakMap<Reference, number>, // -1 means "seen" but not outlined.
197
identifierPrefix: string,
198
identifierCount: number,
@@ -266,7 +249,6 @@ export function createRequest(
249
model: ReactClientValue,
250
bundlerConfig: ClientManifest,
251
onError: void | ((error: mixed) => ?string),
269
- context?: Array<[string, ServerContextJSONValue]>,
252
identifierPrefix?: string,
253
onPostpone: void | ((reason: string) => void),
254
): Request {
@@ -307,7 +289,6 @@ export function createRequest(
289
writtenSymbols: new Map(),
290
writtenClientReferences: new Map(),
291
writtenServerReferences: new Map(),
310
- writtenProviders: new Map(),
292
writtenObjects: new WeakMap(),
293
identifierPrefix: identifierPrefix || '',
294
identifierCount: 1,
@@ -316,15 +297,7 @@ export function createRequest(
297
onPostpone: onPostpone === undefined ? defaultPostponeHandler : onPostpone,
298
};
299
request.pendingChunks++;
319
- const rootContext = createRootContext(context);
320
- const rootTask = createTask(
321
- request,
322
- model,
323
- null,
324
- false,
325
- rootContext,
326
- abortSet,
327
- );
300
+ const rootTask = createTask(request, model, null, false, abortSet);
301
pingedTasks.push(rootTask);
302
return request;
303
}
@@ -340,14 +313,6 @@ export function resolveRequest(): null | Request {
313
return null;
314
}
315
343
-function createRootContext(
344
- reqContext?: Array<[string, ServerContextJSONValue]>,
345
-) {
346
- return importServerContexts(reqContext);
347
-}
348
-
349
-const POP = {};
350
-
316
function serializeThenable(
317
request: Request,
318
task: Task,
@@ -359,7 +324,6 @@ function serializeThenable(
324
null,
325
task.keyPath, // the server component sequence continues through Promise-as-a-child.
326
task.implicitSlot,
362
- task.context,
327
request.abortableTasks,
328
);
329
@@ -735,33 +699,6 @@ function renderElement(
699
case REACT_MEMO_TYPE: {
700
return renderElement(request, task, type.type, key, ref, props);
701
}
738
- case REACT_PROVIDER_TYPE: {
739
- if (enableServerContext) {
740
- task.context = pushProvider(type._context, props.value);
741
- if (__DEV__) {
742
- const extraKeys = Object.keys(props).filter(value => {
743
- if (value === 'children' || value === 'value') {
744
- return false;
745
- }
746
- return true;
747
- });
748
- if (extraKeys.length !== 0) {
749
- console.error(
750
- 'ServerContext can only have a value prop and children. Found: %s',
751
- JSON.stringify(extraKeys),
752
- );
753
- }
754
- }
755
- return renderClientElement(
756
- task,
757
- type,
758
- key,
759
- // Rely on __popProvider being serialized last to pop the provider.
760
- {value: props.value, children: props.children, __pop: POP},
761
- );
762
- }
763
- // Fallthrough
764
- }
702
}
703
}
704
throw new Error(
@@ -783,17 +720,13 @@ function createTask(
720
model: ReactClientValue,
721
keyPath: null | string,
722
implicitSlot: boolean,
786
- context: ContextSnapshot,
723
abortSet: Set<Task>,
724
): Task {
725
const id = request.nextChunkId++;
726
if (typeof model === 'object' && model !== null) {
727
// If we're about to write this into a new task we can assign it an ID early so that
728
// any other references can refer to the value we're about to write.
793
- if (
794
- enableServerComponentKeys &&
795
- (keyPath !== null || implicitSlot || context !== rootContextSnapshot)
796
- ) {
729
+ if (enableServerComponentKeys && (keyPath !== null || implicitSlot)) {
730
// If we're in some kind of context we can't necessarily reuse this object depending
731
// what parent components are used.
732
} else {
@@ -806,7 +739,6 @@ function createTask(
739
model,
740
keyPath,
741
implicitSlot,
809
- context,
742
ping: () => pingTask(request, task),
743
toJSON: function (
744
this:
@@ -850,26 +782,6 @@ function createTask(
782
);
783
}
784
}
853
-
854
- if (
855
- enableServerContext &&
856
- parent[0] === REACT_ELEMENT_TYPE &&
857
- parent[1] &&
858
- (parent[1]: any).$$typeof === REACT_PROVIDER_TYPE &&
859
- parentPropertyName === '3'
860
- ) {
861
- insideContextProps = value;
862
- } else if (
863
- insideContextProps === parent &&
864
- parentPropertyName === 'value'
865
- ) {
866
- isInsideContextValue = true;
867
- } else if (
868
- insideContextProps === parent &&
869
- parentPropertyName === 'children'
870
- ) {
871
- isInsideContextValue = false;
872
- }
785
}
786
return renderModel(request, task, parent, parentPropertyName, value);
787
},
@@ -899,10 +811,6 @@ function serializeSymbolReference(name: string): string {
811
return '$S' + name;
812
}
813
902
-function serializeProviderReference(name: string): string {
903
- return '$P' + name;
904
-}
905
-
814
function serializeNumber(number: number): string | number {
815
if (Number.isFinite(number)) {
816
if (number === 0 && 1 / number === -Infinity) {
@@ -1004,7 +912,6 @@ function outlineModel(request: Request, value: ReactClientValue): number {
912
value,
913
null, // The way we use outlining is for reusing an object.
914
false, // It makes no sense for that use case to be contextual.
1007
- rootContextSnapshot, // Therefore we don't pass any contextual information along.
915
request.abortableTasks,
916
);
917
retryTask(request, newTask);
@@ -1124,8 +1031,6 @@ function escapeStringValue(value: string): string {
1031
}
1032
}
1033
1127
-let insideContextProps = null;
1128
-let isInsideContextValue = false;
1034
let modelRoot: null | ReactClientValue = false;
1035
1036
function renderModel(
@@ -1169,7 +1074,6 @@ function renderModel(
1074
task.model,
1075
task.keyPath,
1076
task.implicitSlot,
1172
- task.context,
1077
request.abortableTasks,
1078
);
1079
const ping = newTask.ping;
@@ -1252,19 +1156,12 @@ function renderModelDestructive(
1156
if (typeof value === 'object') {
1157
switch ((value: any).$$typeof) {
1158
case REACT_ELEMENT_TYPE: {
1255
- if (__DEV__) {
1256
- if (enableServerContext && isInsideContextValue) {
1257
- console.error('React elements are not allowed in ServerContext');
1258
- }
1259
- }
1159
const writtenObjects = request.writtenObjects;
1160
const existingId = writtenObjects.get(value);
1161
if (existingId !== undefined) {
1162
if (
1163
enableServerComponentKeys &&
1265
- (task.keyPath !== null ||
1266
- task.implicitSlot ||
1267
- task.context !== rootContextSnapshot)
1164
+ (task.keyPath !== null || task.implicitSlot)
1165
) {
1166
// If we're in some kind of context we can't reuse the result of this render or
1167
// previous renders of this element. We only reuse elements if they're not wrapped
@@ -1341,9 +1238,7 @@ function renderModelDestructive(
1238
if (existingId !== undefined) {
1239
if (
1240
enableServerComponentKeys &&
1344
- (task.keyPath !== null ||
1345
- task.implicitSlot ||
1346
- task.context !== rootContextSnapshot)
1241
+ (task.keyPath !== null || task.implicitSlot)
1242
) {
1243
// If we're in some kind of context we can't reuse the result of this render or
1244
// previous renders of this element. We only reuse Promises if they're not wrapped
@@ -1366,29 +1261,6 @@ function renderModelDestructive(
1261
return serializePromiseID(promiseId);
1262
}
1263
1369
- if (enableServerContext) {
1370
- if ((value: any).$$typeof === REACT_PROVIDER_TYPE) {
1371
- const providerKey = ((value: any): ReactProviderType<any>)._context
1372
- ._globalName;
1373
- const writtenProviders = request.writtenProviders;
1374
- let providerId = writtenProviders.get(providerKey);
1375
- if (providerId === undefined) {
1376
- request.pendingChunks++;
1377
- providerId = request.nextChunkId++;
1378
- writtenProviders.set(providerKey, providerId);
1379
- emitProviderChunk(request, providerId, providerKey);
1380
- }
1381
- return serializeByValueID(providerId);
1382
- } else if (value === POP) {
1383
- task.context = popProvider();
1384
- if (__DEV__) {
1385
- insideContextProps = null;
1386
- isInsideContextValue = false;
1387
- }
1388
- return (undefined: any);
1389
- }
1390
- }
1391
-
1264
if (existingId !== undefined) {
1265
if (modelRoot === value) {
1266
// This is the ID we're currently emitting so we need to write it
@@ -1752,16 +1624,6 @@ function emitSymbolChunk(request: Request, id: number, name: string): void {
1624
request.completedImportChunks.push(processedChunk);
1625
}
1626
1755
-function emitProviderChunk(
1756
- request: Request,
1757
- id: number,
1758
- contextName: string,
1759
-): void {
1760
- const contextReference = serializeProviderReference(contextName);
1761
- const processedChunk = encodeReferenceChunk(request, id, contextReference);
1762
- request.completedRegularChunks.push(processedChunk);
1763
-}
1764
-
1627
function emitModelChunk(request: Request, id: number, json: string): void {
1628
const row = id.toString(16) + ':' + json + '\n';
1629
const processedChunk = stringToChunk(row);
@@ -1776,8 +1638,6 @@ function retryTask(request: Request, task: Task): void {
1638
return;
1639
}
1640
1779
- const prevContext = getActiveContext();
1780
- switchContext(task.context);
1641
try {
1642
// Track the root so we know that we have to emit this object even though it
1643
// already has an ID. This is needed because we might see this object twice
@@ -1848,10 +1708,6 @@ function retryTask(request: Request, task: Task): void {
1708
task.status = ERRORED;
1709
const digest = logRecoverableError(request, x);
1710
emitErrorChunk(request, task.id, digest, x);
1851
- } finally {
1852
- if (enableServerContext) {
1853
- switchContext(prevContext);
1854
- }
1711
}
1712
}
1713
@@ -2061,21 +1917,3 @@ export function abort(request: Request, reason: mixed): void {
1917
fatalError(request, error);
1918
}
1919
}
2064
-
2065
-function importServerContexts(
2066
- contexts?: Array<[string, ServerContextJSONValue]>,
2067
-) {
2068
- if (enableServerContext && contexts) {
2069
- const prevContext = getActiveContext();
2070
- switchContext(rootContextSnapshot);
2071
- for (let i = 0; i < contexts.length; i++) {
2072
- const [name, value] = contexts[i];
2073
- const context = getOrCreateServerContext(name);
2074
- pushProvider(context, value);
2075
- }
2076
- const importedContext = getActiveContext();
2077
- switchContext(prevContext);
2078
- return importedContext;
2079
- }
2080
- return rootContextSnapshot;
2081
-}
packages/react/index.experimental.js
-1
@@ -22,7 +22,6 @@ export {
22
createElement,
23
createFactory,
24
createRef,
25
- createServerContext,
25
use,
26
forwardRef,
27
isValidElement,
packages/react/index.js
-1
@@ -43,7 +43,6 @@ export {
43
createElement,
44
createFactory,
45
createRef,
46
- createServerContext,
46
use,
47
forwardRef,
48
isValidElement,
packages/react/src/ReactClient.js
-2
@@ -62,7 +62,6 @@ import {
62
useOptimistic,
63
} from './ReactHooks';
64
65
-import {createServerContext} from './ReactServerContext';
65
import ReactSharedInternals from './ReactSharedInternalsClient';
66
import {startTransition} from './ReactStartTransition';
67
import {act} from './ReactAct';
@@ -81,7 +80,6 @@ export {
80
Component,
81
PureComponent,
82
createContext,
84
- createServerContext,
83
forwardRef,
84
lazy,
85
memo,
packages/react/src/ReactContext.js
-4
@@ -31,10 +31,6 @@ export function createContext<T>(defaultValue: T): ReactContext<T> {
31
// These are circular
32
Provider: (null: any),
33
Consumer: (null: any),
34
-
35
- // Add these to use same hidden class in VM as ServerContext
36
- _defaultValue: (null: any),
37
- _globalName: (null: any),
34
};
35
36
context.Provider = {
packages/react/src/ReactServer.experimental.js
-4
@@ -24,12 +24,10 @@ import {
24
} from 'shared/ReactSymbols';
25
import {cloneElement, createElement, isValidElement} from './ReactElement';
26
import {createRef} from './ReactCreateRef';
27
-import {createServerContext} from './ReactServerContext';
27
import {
28
use,
29
useId,
30
useCallback,
32
- useContext,
31
useDebugValue,
32
useMemo,
33
getCacheSignal,
@@ -66,7 +64,6 @@ export {
64
cloneElement,
65
createElement,
66
createRef,
69
- createServerContext,
67
use,
68
forwardRef,
69
isValidElement,
@@ -81,7 +78,6 @@ export {
78
postpone as unstable_postpone,
79
useId,
80
useCallback,
84
- useContext,
81
useDebugValue,
82
useMemo,
83
version,
packages/react/src/ReactServer.js
+1
-11
@@ -23,15 +23,7 @@ import {
23
} from 'shared/ReactSymbols';
24
import {cloneElement, createElement, isValidElement} from './ReactElement';
25
import {createRef} from './ReactCreateRef';
26
-import {createServerContext} from './ReactServerContext';
27
-import {
28
- use,
29
- useId,
30
- useCallback,
31
- useContext,
32
- useDebugValue,
33
- useMemo,
34
-} from './ReactHooks';
26
+import {use, useId, useCallback, useDebugValue, useMemo} from './ReactHooks';
27
import {forwardRef} from './ReactForwardRef';
28
import {lazy} from './ReactLazy';
29
import {memo} from './ReactMemo';
@@ -56,7 +48,6 @@ export {
48
cloneElement,
49
createElement,
50
createRef,
59
- createServerContext,
51
use,
52
forwardRef,
53
isValidElement,
@@ -66,7 +57,6 @@ export {
57
startTransition,
58
useId,
59
useCallback,
69
- useContext,
60
useDebugValue,
61
useMemo,
62
version,
packages/react/src/ReactServerContext.js
deleted
-109
@@ -1,109 +0,0 @@
1
-/**
2
- * Copyright (c) Meta Platforms, Inc. and affiliates.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- *
7
- * @flow
8
- */
9
-
10
-import {
11
- REACT_PROVIDER_TYPE,
12
- REACT_SERVER_CONTEXT_TYPE,
13
- REACT_SERVER_CONTEXT_DEFAULT_VALUE_NOT_LOADED,
14
-} from 'shared/ReactSymbols';
15
-
16
-import type {
17
- ReactServerContext,
18
- ServerContextJSONValue,
19
-} from 'shared/ReactTypes';
20
-
21
-import {enableServerContext} from 'shared/ReactFeatureFlags';
22
-import {ContextRegistry} from './ReactServerContextRegistry';
23
-
24
-export function createServerContext<T: ServerContextJSONValue>(
25
- globalName: string,
26
- defaultValue: T,
27
-): ReactServerContext<T> {
28
- if (!enableServerContext) {
29
- throw new Error('Not implemented.');
30
- }
31
- if (__DEV__) {
32
- console.error(
33
- 'Server Context is deprecated and will soon be removed. ' +
34
- 'It was never documented and we have found it not to be useful ' +
35
- 'enough to warrant the downside it imposes on all apps.',
36
- );
37
- }
38
- let wasDefined = true;
39
- if (!ContextRegistry[globalName]) {
40
- wasDefined = false;
41
- const context: ReactServerContext<T> = {
42
- $$typeof: REACT_SERVER_CONTEXT_TYPE,
43
-
44
- // As a workaround to support multiple concurrent renderers, we categorize
45
- // some renderers as primary and others as secondary. We only expect
46
- // there to be two concurrent renderers at most: React Native (primary) and
47
- // Fabric (secondary); React DOM (primary) and React ART (secondary).
48
- // Secondary renderers store their context values on separate fields.
49
- _currentValue: defaultValue,
50
- _currentValue2: defaultValue,
51
-
52
- _defaultValue: defaultValue,
53
-
54
- // Used to track how many concurrent renderers this context currently
55
- // supports within in a single renderer. Such as parallel server rendering.
56
- _threadCount: 0,
57
- // These are circular
58
- Provider: (null: any),
59
- Consumer: (null: any),
60
- _globalName: globalName,
61
- };
62
-
63
- context.Provider = {
64
- $$typeof: REACT_PROVIDER_TYPE,
65
- _context: context,
66
- };
67
-
68
- if (__DEV__) {
69
- let hasWarnedAboutUsingConsumer;
70
- context._currentRenderer = null;
71
- context._currentRenderer2 = null;
72
- Object.defineProperties(
73
- context,
74
- ({
75
- Consumer: {
76
- get() {
77
- if (!hasWarnedAboutUsingConsumer) {
78
- console.error(
79
- 'Consumer pattern is not supported by ReactServerContext',
80
- );
81
- hasWarnedAboutUsingConsumer = true;
82
- }
83
- return null;
84
- },
85
- },
86
- }: any),
87
- );
88
- }
89
- ContextRegistry[globalName] = context;
90
- }
91
-
92
- const context = ContextRegistry[globalName];
93
- if (context._defaultValue === REACT_SERVER_CONTEXT_DEFAULT_VALUE_NOT_LOADED) {
94
- context._defaultValue = defaultValue;
95
- if (
96
- context._currentValue === REACT_SERVER_CONTEXT_DEFAULT_VALUE_NOT_LOADED
97
- ) {
98
- context._currentValue = defaultValue;
99
- }
100
- if (
101
- context._currentValue2 === REACT_SERVER_CONTEXT_DEFAULT_VALUE_NOT_LOADED
102
- ) {
103
- context._currentValue2 = defaultValue;
104
- }
105
- } else if (wasDefined) {
106
- throw new Error(`ServerContext: ${globalName} already defined`);
107
- }
108
- return context;
109
-}
packages/react/src/ReactServerContextRegistry.js
deleted
-14
@@ -1,14 +0,0 @@
1
-/**
2
- * Copyright (c) Meta Platforms, Inc. and affiliates.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- *
7
- * @flow
8
- */
9
-
10
-import type {ReactServerContext} from 'shared/ReactTypes';
11
-
12
-export const ContextRegistry: {
13
- [globalName: string]: ReactServerContext<any>,
14
-} = {};
packages/react/src/ReactSharedInternalsClient.js
-6
@@ -11,8 +11,6 @@ import ReactCurrentBatchConfig from './ReactCurrentBatchConfig';
11
import ReactCurrentActQueue from './ReactCurrentActQueue';
12
import ReactCurrentOwner from './ReactCurrentOwner';
13
import ReactDebugCurrentFrame from './ReactDebugCurrentFrame';
14
-import {enableServerContext} from 'shared/ReactFeatureFlags';
15
-import {ContextRegistry} from './ReactServerContextRegistry';
14
15
const ReactSharedInternals = {
16
ReactCurrentDispatcher,
@@ -26,8 +24,4 @@ if (__DEV__) {
24
ReactSharedInternals.ReactCurrentActQueue = ReactCurrentActQueue;
25
}
26
29
-if (enableServerContext) {
30
- ReactSharedInternals.ContextRegistry = ContextRegistry;
31
-}
32
-
27
export default ReactSharedInternals;
packages/react/src/ReactSharedInternalsServer.js
-6
@@ -8,8 +8,6 @@
8
import ReactCurrentDispatcher from './ReactCurrentDispatcher';
9
import ReactCurrentOwner from './ReactCurrentOwner';
10
import ReactDebugCurrentFrame from './ReactDebugCurrentFrame';
11
-import {enableServerContext} from 'shared/ReactFeatureFlags';
12
-import {ContextRegistry} from './ReactServerContextRegistry';
11
12
const ReactSharedInternals = {
13
ReactCurrentDispatcher,
@@ -20,8 +18,4 @@ if (__DEV__) {
18
ReactSharedInternals.ReactDebugCurrentFrame = ReactDebugCurrentFrame;
19
}
20
23
-if (enableServerContext) {
24
- ReactSharedInternals.ContextRegistry = ContextRegistry;
25
-}
26
-
21
export default ReactSharedInternals;
packages/react/src/forks/ReactSharedInternalsClient.umd.js
-6
@@ -12,8 +12,6 @@ import ReactCurrentActQueue from '../ReactCurrentActQueue';
12
import ReactCurrentOwner from '../ReactCurrentOwner';
13
import ReactDebugCurrentFrame from '../ReactDebugCurrentFrame';
14
import ReactCurrentBatchConfig from '../ReactCurrentBatchConfig';
15
-import {enableServerContext} from 'shared/ReactFeatureFlags';
16
-import {ContextRegistry} from '../ReactServerContextRegistry';
15
16
const ReactSharedInternalsClient = {
17
ReactCurrentDispatcher,
@@ -34,8 +32,4 @@ if (__DEV__) {
32
ReactSharedInternalsClient.ReactDebugCurrentFrame = ReactDebugCurrentFrame;
33
}
34
37
-if (enableServerContext) {
38
- ReactSharedInternalsClient.ContextRegistry = ContextRegistry;
39
-}
40
-
35
export default ReactSharedInternalsClient;
packages/shared/ReactFeatureFlags.js
-2
@@ -240,8 +240,6 @@ export const enableAsyncDebugInfo = __EXPERIMENTAL__;
240
// Track which Fiber(s) schedule render work.
241
export const enableUpdaterTracking = __PROFILE__;
242
243
-export const enableServerContext = __EXPERIMENTAL__;
244
-
243
// Internal only.
244
export const enableGetInspectorDataForInstanceInProduction = false;
245
packages/shared/ReactServerContextRegistry.js
deleted
-77
@@ -1,77 +0,0 @@
1
-/**
2
- * Copyright (c) Meta Platforms, Inc. and affiliates.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- *
7
- * @flow
8
- */
9
-
10
-import type {ReactServerContext} from 'shared/ReactTypes';
11
-
12
-import {
13
- REACT_PROVIDER_TYPE,
14
- REACT_SERVER_CONTEXT_TYPE,
15
- REACT_SERVER_CONTEXT_DEFAULT_VALUE_NOT_LOADED,
16
-} from 'shared/ReactSymbols';
17
-
18
-import ReactSharedInternals from 'shared/ReactSharedInternals';
19
-
20
-const ContextRegistry = ReactSharedInternals.ContextRegistry;
21
-
22
-export function getOrCreateServerContext(
23
- globalName: string,
24
-): ReactServerContext<any> {
25
- if (!ContextRegistry[globalName]) {
26
- const context: ReactServerContext<any> = {
27
- $$typeof: REACT_SERVER_CONTEXT_TYPE,
28
-
29
- // As a workaround to support multiple concurrent renderers, we categorize
30
- // some renderers as primary and others as secondary. We only expect
31
- // there to be two concurrent renderers at most: React Native (primary) and
32
- // Fabric (secondary); React DOM (primary) and React ART (secondary).
33
- // Secondary renderers store their context values on separate fields.
34
- _currentValue: REACT_SERVER_CONTEXT_DEFAULT_VALUE_NOT_LOADED,
35
- _currentValue2: REACT_SERVER_CONTEXT_DEFAULT_VALUE_NOT_LOADED,
36
-
37
- _defaultValue: REACT_SERVER_CONTEXT_DEFAULT_VALUE_NOT_LOADED,
38
-
39
- // Used to track how many concurrent renderers this context currently
40
- // supports within in a single renderer. Such as parallel server rendering.
41
- _threadCount: 0,
42
- // These are circular
43
- Provider: (null: any),
44
- Consumer: (null: any),
45
- _globalName: globalName,
46
- };
47
-
48
- context.Provider = {
49
- $$typeof: REACT_PROVIDER_TYPE,
50
- _context: context,
51
- };
52
-
53
- if (__DEV__) {
54
- let hasWarnedAboutUsingConsumer;
55
- context._currentRenderer = null;
56
- context._currentRenderer2 = null;
57
- Object.defineProperties(
58
- context,
59
- ({
60
- Consumer: {
61
- get() {
62
- if (!hasWarnedAboutUsingConsumer) {
63
- console.error(
64
- 'Consumer pattern is not supported by ReactServerContext',
65
- );
66
- hasWarnedAboutUsingConsumer = true;
67
- }
68
- return null;
69
- },
70
- },
71
- }: any),
72
- );
73
- }
74
- ContextRegistry[globalName] = context;
75
- }
76
- return ContextRegistry[globalName];
77
-}
packages/shared/ReactSymbols.js
-6
@@ -19,9 +19,6 @@ export const REACT_STRICT_MODE_TYPE: symbol = Symbol.for('react.strict_mode');
19
export const REACT_PROFILER_TYPE: symbol = Symbol.for('react.profiler');
20
export const REACT_PROVIDER_TYPE: symbol = Symbol.for('react.provider');
21
export const REACT_CONTEXT_TYPE: symbol = Symbol.for('react.context');
22
-export const REACT_SERVER_CONTEXT_TYPE: symbol = Symbol.for(
23
- 'react.server_context',
24
-);
22
export const REACT_FORWARD_REF_TYPE: symbol = Symbol.for('react.forward_ref');
23
export const REACT_SUSPENSE_TYPE: symbol = Symbol.for('react.suspense');
24
export const REACT_SUSPENSE_LIST_TYPE: symbol = Symbol.for(
@@ -41,9 +38,6 @@ export const REACT_CACHE_TYPE: symbol = Symbol.for('react.cache');
38
export const REACT_TRACING_MARKER_TYPE: symbol = Symbol.for(
39
'react.tracing_marker',
40
);
44
-export const REACT_SERVER_CONTEXT_DEFAULT_VALUE_NOT_LOADED: symbol = Symbol.for(
45
- 'react.default_value',
46
-);
41
42
export const REACT_MEMO_CACHE_SENTINEL: symbol = Symbol.for(
43
'react.memo_cache_sentinel',
packages/shared/ReactTypes.js
-14
@@ -62,22 +62,8 @@ export type ReactContext<T> = {
62
// This value may be added by application code
63
// to improve DEV tooling display names
64
displayName?: string,
65
-
66
- // only used by ServerContext
67
- _defaultValue: T,
68
- _globalName: string,
65
};
66
71
-export type ServerContextJSONValue =
72
- | string
73
- | boolean
74
- | number
75
- | null
76
- | $ReadOnlyArray<ServerContextJSONValue>
77
- | {+[key: string]: ServerContextJSONValue};
78
-
79
-export type ReactServerContext<T: any> = ReactContext<T>;
80
-
67
export type ReactPortal = {
68
$$typeof: symbol | number,
69
key: null | string,
packages/shared/forks/ReactFeatureFlags.native-fb.js
-1
@@ -80,7 +80,6 @@ export const allowConcurrentByDefault = true;
80
export const enableCustomElementPropertySupport = false;
81
82
export const consoleManagedByDevToolsDuringStrictMode = false;
83
-export const enableServerContext = false;
83
84
export const enableTransitionTracing = false;
85
packages/shared/forks/ReactFeatureFlags.native-oss.js
-1
@@ -66,7 +66,6 @@ export const allowConcurrentByDefault = false;
66
export const enableCustomElementPropertySupport = false;
67
68
export const consoleManagedByDevToolsDuringStrictMode = false;
69
-export const enableServerContext = false;
69
70
export const enableTransitionTracing = false;
71
packages/shared/forks/ReactFeatureFlags.test-renderer.js
-1
@@ -66,7 +66,6 @@ export const allowConcurrentByDefault = false;
66
export const enableCustomElementPropertySupport = false;
67
68
export const consoleManagedByDevToolsDuringStrictMode = false;
69
-export const enableServerContext = false;
69
70
export const enableTransitionTracing = false;
71
packages/shared/forks/ReactFeatureFlags.test-renderer.native.js
-1
@@ -64,7 +64,6 @@ export const enableUnifiedSyncLane = true;
64
export const allowConcurrentByDefault = true;
65
66
export const consoleManagedByDevToolsDuringStrictMode = false;
67
-export const enableServerContext = false;
67
68
export const enableTransitionTracing = false;
69
packages/shared/forks/ReactFeatureFlags.test-renderer.www.js
-1
@@ -66,7 +66,6 @@ export const allowConcurrentByDefault = true;
66
export const enableCustomElementPropertySupport = false;
67
68
export const consoleManagedByDevToolsDuringStrictMode = false;
69
-export const enableServerContext = false;
69
70
export const enableTransitionTracing = false;
71
packages/shared/forks/ReactFeatureFlags.www.js
-1
@@ -100,7 +100,6 @@ export const disableTextareaChildren = __EXPERIMENTAL__;
100
export const allowConcurrentByDefault = true;
101
102
export const consoleManagedByDevToolsDuringStrictMode = true;
103
-export const enableServerContext = false;
103
104
export const useModernStrictMode = false;
105
export const enableFizzExternalRuntime = true;
packages/shared/getComponentNameFromType.js
+1
-11
@@ -24,14 +24,9 @@ import {
24
REACT_LAZY_TYPE,
25
REACT_CACHE_TYPE,
26
REACT_TRACING_MARKER_TYPE,
27
- REACT_SERVER_CONTEXT_TYPE,
27
} from 'shared/ReactSymbols';
28
30
-import {
31
- enableServerContext,
32
- enableTransitionTracing,
33
- enableCache,
34
-} from './ReactFeatureFlags';
29
+import {enableTransitionTracing, enableCache} from './ReactFeatureFlags';
30
31
// Keep in sync with react-reconciler/getComponentNameFromFiber
32
function getWrappedName(
@@ -127,11 +122,6 @@ export default function getComponentNameFromType(type: mixed): string | null {
122
return null;
123
}
124
}
130
- case REACT_SERVER_CONTEXT_TYPE:
131
- if (enableServerContext) {
132
- const context2 = ((type: any): ReactContext<any>);
133
- return (context2.displayName || context2._globalName) + '.Provider';
134
- }
125
}
126
}
127
return null;
scripts/error-codes/codes.json
+3
-1
@@ -486,5 +486,7 @@
486
"498": "Only plain objects, and a few built-ins, can be passed to Client Components from Server Components. Classes or null prototypes are not supported.",
487
"499": "Only plain objects, and a few built-ins, can be passed to Server Actions. Classes or null prototypes are not supported.",
488
"500": "React expected a headers state to exist when emitEarlyPreloads was called but did not find it. This suggests emitEarlyPreloads was called more than once per request. This is a bug in React.",
489
- "501": "The render was aborted with postpone when the shell is incomplete. Reason: %s"
489
+ "501": "The render was aborted with postpone when the shell is incomplete. Reason: %s",
490
+ "502": "Cannot read a Client Context from a Server Component.",
491
+ "503": "Cannot use() an already resolved Client Reference."
492
}