@samitouri / QOS-React-1 / commits / 472854820b

[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 }