Skip to content

Commit

Permalink
Enforce that the "react-server" build of "react" is used (#27436)
Browse files Browse the repository at this point in the history
I do this by simply renaming the secret export name in the "subset"
bundle and this renamed version is what the FlightServer uses.

This requires us to be more diligent about always using the correct
instance of "react" in our tests so there's a bunch of clean up for
that.
  • Loading branch information
sebmarkbage committed Sep 29, 2023
1 parent d900fad commit c7ba8c0
Show file tree
Hide file tree
Showing 30 changed files with 245 additions and 1,258 deletions.
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,7 @@ module.exports = {
__TEST__: 'readonly',
__UMD__: 'readonly',
__VARIANT__: 'readonly',
__unmockReact: 'readonly',
gate: 'readonly',
trustedTypes: 'readonly',
IS_REACT_ACT_ENVIRONMENT: 'readonly',
Expand Down
94 changes: 64 additions & 30 deletions packages/react-client/src/__tests__/ReactFlight-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ let act;
let use;
let startTransition;
let React;
let ReactServer;
let ReactNoop;
let ReactNoopFlightServer;
let ReactNoopFlightClient;
Expand All @@ -25,12 +26,18 @@ let assertLog;
describe('ReactFlight', () => {
beforeEach(() => {
jest.resetModules();

jest.mock('react', () => require('react/react.shared-subset'));
ReactServer = require('react');
ReactNoopFlightServer = require('react-noop-renderer/flight-server');
// This stores the state so we need to preserve it
const flightModules = require('react-noop-renderer/flight-modules');
__unmockReact();
jest.resetModules();
jest.mock('react-noop-renderer/flight-modules', () => flightModules);
React = require('react');
startTransition = React.startTransition;
use = React.use;
ReactNoop = require('react-noop-renderer');
ReactNoopFlightServer = require('react-noop-renderer/flight-server');
ReactNoopFlightClient = require('react-noop-renderer/flight-client');
act = require('internal-test-utils').act;
Scheduler = require('scheduler');
Expand Down Expand Up @@ -111,6 +118,19 @@ describe('ReactFlight', () => {
return ctx;
}

function createServerServerContext(globalName, defaultValue, withStack) {
let ctx;
expect(() => {
ctx = ReactServer.createServerContext(globalName, defaultValue);
}).toErrorDev(
'Server Context is deprecated and will soon be removed. ' +
'It was never documented and we have found it not to be useful ' +
'enough to warrant the downside it imposes on all apps.',
{withoutStack: !withStack},
);
return ctx;
}

function clientReference(value) {
return Object.defineProperties(
function () {
Expand Down Expand Up @@ -970,7 +990,7 @@ describe('ReactFlight', () => {
const Context = React.createContext();
const ClientContext = clientReference(Context);
function ServerComponent() {
return React.useContext(ClientContext);
return ReactServer.useContext(ClientContext);
}
expect(() => {
const transport = ReactNoopFlightServer.render(<ServerComponent />);
Expand All @@ -982,7 +1002,7 @@ describe('ReactFlight', () => {

describe('Hooks', () => {
function DivWithId({children}) {
const id = React.useId();
const id = ReactServer.useId();
return <div prop={id}>{children}</div>;
}

Expand Down Expand Up @@ -1039,7 +1059,7 @@ describe('ReactFlight', () => {
// so the output passed to the Client has no knowledge of the useId use. In the future we would like to add a DEV warning when this happens. For now
// we just accept that it is a nuance of useId in Flight
function App() {
const id = React.useId();
const id = ReactServer.useId();
const div = <div prop={id}>{id}</div>;
return <ClientDoublerModuleRef el={div} />;
}
Expand Down Expand Up @@ -1076,19 +1096,17 @@ describe('ReactFlight', () => {
describe('ServerContext', () => {
// @gate enableServerContext
it('supports basic createServerContext usage', async () => {
const ServerContext = createServerContext(
const ServerContext = createServerServerContext(
'ServerContext',
'hello from server',
);
function Foo() {
const context = React.useContext(ServerContext);
const context = ReactServer.useContext(ServerContext);
return <div>{context}</div>;
}

const transport = ReactNoopFlightServer.render(<Foo />);
await act(async () => {
ServerContext._currentRenderer = null;
ServerContext._currentRenderer2 = null;
ReactNoop.render(await ReactNoopFlightClient.read(transport));
});

Expand All @@ -1097,7 +1115,10 @@ describe('ReactFlight', () => {

// @gate enableServerContext
it('propagates ServerContext providers in flight', async () => {
const ServerContext = createServerContext('ServerContext', 'default');
const ServerContext = createServerServerContext(
'ServerContext',
'default',
);

function Foo() {
return (
Expand All @@ -1109,14 +1130,12 @@ describe('ReactFlight', () => {
);
}
function Bar() {
const context = React.useContext(ServerContext);
const context = ReactServer.useContext(ServerContext);
return context;
}

const transport = ReactNoopFlightServer.render(<Foo />);
await act(async () => {
ServerContext._currentRenderer = null;
ServerContext._currentRenderer2 = null;
ReactNoop.render(await ReactNoopFlightClient.read(transport));
});

Expand All @@ -1125,7 +1144,7 @@ describe('ReactFlight', () => {

// @gate enableServerContext
it('errors if you try passing JSX through ServerContext value', () => {
const ServerContext = createServerContext('ServerContext', {
const ServerContext = createServerServerContext('ServerContext', {
foo: {
bar: <span>hi this is default</span>,
},
Expand All @@ -1146,7 +1165,7 @@ describe('ReactFlight', () => {
);
}
function Bar() {
const context = React.useContext(ServerContext);
const context = ReactServer.useContext(ServerContext);
return context.foo.bar;
}

Expand All @@ -1159,7 +1178,10 @@ describe('ReactFlight', () => {

// @gate enableServerContext
it('propagates ServerContext and cleans up the providers in flight', async () => {
const ServerContext = createServerContext('ServerContext', 'default');
const ServerContext = createServerServerContext(
'ServerContext',
'default',
);

function Foo() {
return (
Expand All @@ -1181,7 +1203,7 @@ describe('ReactFlight', () => {
);
}
function Bar() {
const context = React.useContext(ServerContext);
const context = ReactServer.useContext(ServerContext);
return <span>{context}</span>;
}

Expand All @@ -1203,7 +1225,10 @@ describe('ReactFlight', () => {

// @gate enableServerContext
it('propagates ServerContext providers in flight after suspending', async () => {
const ServerContext = createServerContext('ServerContext', 'default');
const ServerContext = createServerServerContext(
'ServerContext',
'default',
);

function Foo() {
return (
Expand Down Expand Up @@ -1231,7 +1256,7 @@ describe('ReactFlight', () => {
throw promise;
}
Scheduler.log('rendered');
const context = React.useContext(ServerContext);
const context = ReactServer.useContext(ServerContext);
return context;
}

Expand All @@ -1248,8 +1273,6 @@ describe('ReactFlight', () => {
assertLog(['rendered']);

await act(async () => {
ServerContext._currentRenderer = null;
ServerContext._currentRenderer2 = null;
ReactNoop.render(await ReactNoopFlightClient.read(transport));
});

Expand All @@ -1258,11 +1281,15 @@ describe('ReactFlight', () => {

// @gate enableServerContext
it('serializes ServerContext to client', async () => {
const ServerContext = createServerContext('ServerContext', 'default');
const ServerContext = createServerServerContext(
'ServerContext',
'default',
);
const ClientContext = createServerContext('ServerContext', 'default');

function ClientBar() {
Scheduler.log('ClientBar');
const context = React.useContext(ServerContext);
const context = React.useContext(ClientContext);
return <span>{context}</span>;
}

Expand All @@ -1285,8 +1312,6 @@ describe('ReactFlight', () => {
assertLog([]);

await act(async () => {
ServerContext._currentRenderer = null;
ServerContext._currentRenderer2 = null;
const flightModel = await ReactNoopFlightClient.read(transport);
ReactNoop.render(flightModel.foo);
});
Expand All @@ -1301,9 +1326,12 @@ describe('ReactFlight', () => {

// @gate enableServerContext
it('takes ServerContext from the client for refetching use cases', async () => {
const ServerContext = createServerContext('ServerContext', 'default');
const ServerContext = createServerServerContext(
'ServerContext',
'default',
);
function Bar() {
return <span>{React.useContext(ServerContext)}</span>;
return <span>{ReactServer.useContext(ServerContext)}</span>;
}
const transport = ReactNoopFlightServer.render(<Bar />, {
context: [['ServerContext', 'Override']],
Expand All @@ -1321,7 +1349,7 @@ describe('ReactFlight', () => {
let ServerContext;
function inlineLazyServerContextInitialization() {
if (!ServerContext) {
ServerContext = createServerContext('ServerContext', 'default');
ServerContext = createServerServerContext('ServerContext', 'default');
}
return ServerContext;
}
Expand All @@ -1346,7 +1374,7 @@ describe('ReactFlight', () => {
return (
<article>
<div>
{React.useContext(inlineLazyServerContextInitialization())}
{ReactServer.useContext(inlineLazyServerContextInitialization())}
</div>
<Baz />
</article>
Expand Down Expand Up @@ -1381,11 +1409,17 @@ describe('ReactFlight', () => {
// Reset all modules, except flight-modules which keeps the registry of Client Components
const flightModules = require('react-noop-renderer/flight-modules');
jest.resetModules();
jest.mock('react', () => require('react/react.shared-subset'));
jest.mock('react-noop-renderer/flight-modules', () => flightModules);

ReactServer = require('react');
ReactNoopFlightServer = require('react-noop-renderer/flight-server');

__unmockReact();
jest.resetModules();
jest.mock('react-noop-renderer/flight-modules', () => flightModules);
React = require('react');
ReactNoop = require('react-noop-renderer');
ReactNoopFlightServer = require('react-noop-renderer/flight-server');
ReactNoopFlightClient = require('react-noop-renderer/flight-client');
act = require('internal-test-utils').act;
Scheduler = require('scheduler');
Expand Down
1 change: 1 addition & 0 deletions packages/react-dom/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"test-utils.js",
"unstable_testing.js",
"unstable_server-external-runtime.js",
"react-dom.shared-subset.js",
"cjs/",
"umd/"
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ describe('ReactFlightDOM', () => {

// This reset is to load modules for the SSR/Browser scope.
jest.resetModules();
jest.unmock('react');
__unmockReact();
act = require('internal-test-utils').act;
Stream = require('stream');
React = require('react');
Expand Down
Loading

0 comments on commit c7ba8c0

Please sign in to comment.