react/packages/react-server/src/ReactFlightServer.js

1332 lines
39 KiB
JavaScript
Raw Normal View History

/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/
import type {
Destination,
Chunk,
BundlerConfig,
ModuleMetaData,
ModuleReference,
2020-11-11 11:58:58 +08:00
ModuleKey,
} from './ReactFlightServerConfig';
[ServerContext] Flight support for ServerContext (#23244) * Flight side of server context * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * reinline * rebase * add back changes lost due to rebase being hard * emit chunk for provider * remove case for React provider type * update type for SomeChunk * enable flag with experimental * add missing types * fix flow type * missing type * t: any * revert extraneous type change * better type * better type * feedback * change import to type import * test? * test? * remove react-dom * remove react-native-renderer from react-server-native-relay/package.json * gate change in FiberNewContext, getComponentNameFromType, use switch statement in FlightServer * getComponentNameFromTpe: server context type gated and use displayName if available * fallthrough * lint.... * POP * lint
2022-03-08 20:55:32 +08:00
import type {ContextSnapshot} from './ReactFlightNewContext';
import type {ThenableState} from './ReactFlightThenable';
[ServerContext] Flight support for ServerContext (#23244) * Flight side of server context * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * reinline * rebase * add back changes lost due to rebase being hard * emit chunk for provider * remove case for React provider type * update type for SomeChunk * enable flag with experimental * add missing types * fix flow type * missing type * t: any * revert extraneous type change * better type * better type * feedback * change import to type import * test? * test? * remove react-dom * remove react-native-renderer from react-server-native-relay/package.json * gate change in FiberNewContext, getComponentNameFromType, use switch statement in FlightServer * getComponentNameFromTpe: server context type gated and use displayName if available * fallthrough * lint.... * POP * lint
2022-03-08 20:55:32 +08:00
import type {
ReactProviderType,
ServerContextJSONValue,
Wakeable,
Thenable,
[ServerContext] Flight support for ServerContext (#23244) * Flight side of server context * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * reinline * rebase * add back changes lost due to rebase being hard * emit chunk for provider * remove case for React provider type * update type for SomeChunk * enable flag with experimental * add missing types * fix flow type * missing type * t: any * revert extraneous type change * better type * better type * feedback * change import to type import * test? * test? * remove react-dom * remove react-native-renderer from react-server-native-relay/package.json * gate change in FiberNewContext, getComponentNameFromType, use switch statement in FlightServer * getComponentNameFromTpe: server context type gated and use displayName if available * fallthrough * lint.... * POP * lint
2022-03-08 20:55:32 +08:00
} from 'shared/ReactTypes';
import type {LazyComponent} from 'react/src/ReactLazy';
import {
scheduleWork,
beginWriting,
writeChunkAndReturn,
completeWriting,
flushBuffered,
close,
closeWithError,
processModelChunk,
[Flight] Add support for Module References in transport protocol (#20121) * Refactor Flight to require a module reference to be brand checked This exposes a host environment (bundler) specific hook to check if an object is a module reference. This will be used so that they can be passed directly into Flight without needing additional wrapper objects. * Emit module references as a special type of value We already have JSON and errors as special types of "rows". This encodes module references as a special type of row value. This was always the intention because it allows those values to be emitted first in the stream so that as a large models stream down, we can start preloading as early as possible. We preload the module when they resolve but we lazily require them as they are referenced. * Emit module references where ever they occur This emits module references where ever they occur. In blocks or even directly in elements. * Don't special case the root row I originally did this so that a simple stream is also just plain JSON. However, since we might want to emit things like modules before the root module in the stream, this gets unnecessarily complicated. We could add this back as a special case if it's the first byte written but meh. * Update the protocol * Add test for using a module reference as a client component * Relax element type check Since Flight now accepts a module reference as returned by any bundler system, depending on the renderer running. We need to drastically relax the check to include all of them. We can add more as we discover them. * Move flow annotation Seems like our compiler is not happy with stripping this. * Some bookkeeping bug * Can't use the private field to check
2020-10-30 08:57:31 +08:00
processModuleChunk,
[ServerContext] Flight support for ServerContext (#23244) * Flight side of server context * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * reinline * rebase * add back changes lost due to rebase being hard * emit chunk for provider * remove case for React provider type * update type for SomeChunk * enable flag with experimental * add missing types * fix flow type * missing type * t: any * revert extraneous type change * better type * better type * feedback * change import to type import * test? * test? * remove react-dom * remove react-native-renderer from react-server-native-relay/package.json * gate change in FiberNewContext, getComponentNameFromType, use switch statement in FlightServer * getComponentNameFromTpe: server context type gated and use displayName if available * fallthrough * lint.... * POP * lint
2022-03-08 20:55:32 +08:00
processProviderChunk,
processSymbolChunk,
processErrorChunkProd,
processErrorChunkDev,
processReferenceChunk,
resolveModuleMetaData,
2020-11-11 11:58:58 +08:00
getModuleKey,
[Flight] Add support for Module References in transport protocol (#20121) * Refactor Flight to require a module reference to be brand checked This exposes a host environment (bundler) specific hook to check if an object is a module reference. This will be used so that they can be passed directly into Flight without needing additional wrapper objects. * Emit module references as a special type of value We already have JSON and errors as special types of "rows". This encodes module references as a special type of row value. This was always the intention because it allows those values to be emitted first in the stream so that as a large models stream down, we can start preloading as early as possible. We preload the module when they resolve but we lazily require them as they are referenced. * Emit module references where ever they occur This emits module references where ever they occur. In blocks or even directly in elements. * Don't special case the root row I originally did this so that a simple stream is also just plain JSON. However, since we might want to emit things like modules before the root module in the stream, this gets unnecessarily complicated. We could add this back as a special case if it's the first byte written but meh. * Update the protocol * Add test for using a module reference as a client component * Relax element type check Since Flight now accepts a module reference as returned by any bundler system, depending on the renderer running. We need to drastically relax the check to include all of them. We can add more as we discover them. * Move flow annotation Seems like our compiler is not happy with stripping this. * Some bookkeeping bug * Can't use the private field to check
2020-10-30 08:57:31 +08:00
isModuleReference,
} from './ReactFlightServerConfig';
import {
HooksDispatcher,
prepareToUseHooksForRequest,
prepareToUseHooksForComponent,
getThenableStateAfterSuspending,
resetHooksForRequest,
} from './ReactFlightHooks';
import {
DefaultCacheDispatcher,
getCurrentCache,
setCurrentCache,
} from './ReactFlightCache';
[ServerContext] Flight support for ServerContext (#23244) * Flight side of server context * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * reinline * rebase * add back changes lost due to rebase being hard * emit chunk for provider * remove case for React provider type * update type for SomeChunk * enable flag with experimental * add missing types * fix flow type * missing type * t: any * revert extraneous type change * better type * better type * feedback * change import to type import * test? * test? * remove react-dom * remove react-native-renderer from react-server-native-relay/package.json * gate change in FiberNewContext, getComponentNameFromType, use switch statement in FlightServer * getComponentNameFromTpe: server context type gated and use displayName if available * fallthrough * lint.... * POP * lint
2022-03-08 20:55:32 +08:00
import {
pushProvider,
popProvider,
switchContext,
getActiveContext,
rootContextSnapshot,
} from './ReactFlightNewContext';
import {trackSuspendedWakeable} from './ReactFlightThenable';
[ServerContext] Flight support for ServerContext (#23244) * Flight side of server context * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * reinline * rebase * add back changes lost due to rebase being hard * emit chunk for provider * remove case for React provider type * update type for SomeChunk * enable flag with experimental * add missing types * fix flow type * missing type * t: any * revert extraneous type change * better type * better type * feedback * change import to type import * test? * test? * remove react-dom * remove react-native-renderer from react-server-native-relay/package.json * gate change in FiberNewContext, getComponentNameFromType, use switch statement in FlightServer * getComponentNameFromTpe: server context type gated and use displayName if available * fallthrough * lint.... * POP * lint
2022-03-08 20:55:32 +08:00
import {
REACT_ELEMENT_TYPE,
REACT_FORWARD_REF_TYPE,
REACT_FRAGMENT_TYPE,
REACT_LAZY_TYPE,
REACT_MEMO_TYPE,
[ServerContext] Flight support for ServerContext (#23244) * Flight side of server context * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * reinline * rebase * add back changes lost due to rebase being hard * emit chunk for provider * remove case for React provider type * update type for SomeChunk * enable flag with experimental * add missing types * fix flow type * missing type * t: any * revert extraneous type change * better type * better type * feedback * change import to type import * test? * test? * remove react-dom * remove react-native-renderer from react-server-native-relay/package.json * gate change in FiberNewContext, getComponentNameFromType, use switch statement in FlightServer * getComponentNameFromTpe: server context type gated and use displayName if available * fallthrough * lint.... * POP * lint
2022-03-08 20:55:32 +08:00
REACT_PROVIDER_TYPE,
REACT_SUSPENSE_TYPE,
REACT_SUSPENSE_LIST_TYPE,
} from 'shared/ReactSymbols';
[ServerContext] Flight support for ServerContext (#23244) * Flight side of server context * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * reinline * rebase * add back changes lost due to rebase being hard * emit chunk for provider * remove case for React provider type * update type for SomeChunk * enable flag with experimental * add missing types * fix flow type * missing type * t: any * revert extraneous type change * better type * better type * feedback * change import to type import * test? * test? * remove react-dom * remove react-native-renderer from react-server-native-relay/package.json * gate change in FiberNewContext, getComponentNameFromType, use switch statement in FlightServer * getComponentNameFromTpe: server context type gated and use displayName if available * fallthrough * lint.... * POP * lint
2022-03-08 20:55:32 +08:00
import {getOrCreateServerContext} from 'shared/ReactServerContextRegistry';
import ReactSharedInternals from 'shared/ReactSharedInternals';
import isArray from 'shared/isArray';
type ReactJSONValue =
| string
| boolean
| number
| null
| $ReadOnlyArray<ReactJSONValue>
| ReactModelObject;
export type ReactModel =
| React$Element<any>
| LazyComponent<any, any>
| string
| boolean
| number
| symbol
| null
| Iterable<ReactModel>
| ReactModelObject;
type ReactModelObject = {+[key: string]: ReactModel};
const PENDING = 0;
const COMPLETED = 1;
const ABORTED = 3;
const ERRORED = 4;
type Task = {
id: number,
status: 0 | 1 | 3 | 4,
model: ReactModel,
ping: () => void,
[ServerContext] Flight support for ServerContext (#23244) * Flight side of server context * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * reinline * rebase * add back changes lost due to rebase being hard * emit chunk for provider * remove case for React provider type * update type for SomeChunk * enable flag with experimental * add missing types * fix flow type * missing type * t: any * revert extraneous type change * better type * better type * feedback * change import to type import * test? * test? * remove react-dom * remove react-native-renderer from react-server-native-relay/package.json * gate change in FiberNewContext, getComponentNameFromType, use switch statement in FlightServer * getComponentNameFromTpe: server context type gated and use displayName if available * fallthrough * lint.... * POP * lint
2022-03-08 20:55:32 +08:00
context: ContextSnapshot,
thenableState: ThenableState | null,
};
export type Request = {
status: 0 | 1 | 2,
fatalError: mixed,
destination: null | Destination,
bundlerConfig: BundlerConfig,
cache: Map<Function, mixed>,
nextChunkId: number,
pendingChunks: number,
abortableTasks: Set<Task>,
pingedTasks: Array<Task>,
[Flight] Add support for Module References in transport protocol (#20121) * Refactor Flight to require a module reference to be brand checked This exposes a host environment (bundler) specific hook to check if an object is a module reference. This will be used so that they can be passed directly into Flight without needing additional wrapper objects. * Emit module references as a special type of value We already have JSON and errors as special types of "rows". This encodes module references as a special type of row value. This was always the intention because it allows those values to be emitted first in the stream so that as a large models stream down, we can start preloading as early as possible. We preload the module when they resolve but we lazily require them as they are referenced. * Emit module references where ever they occur This emits module references where ever they occur. In blocks or even directly in elements. * Don't special case the root row I originally did this so that a simple stream is also just plain JSON. However, since we might want to emit things like modules before the root module in the stream, this gets unnecessarily complicated. We could add this back as a special case if it's the first byte written but meh. * Update the protocol * Add test for using a module reference as a client component * Relax element type check Since Flight now accepts a module reference as returned by any bundler system, depending on the renderer running. We need to drastically relax the check to include all of them. We can add more as we discover them. * Move flow annotation Seems like our compiler is not happy with stripping this. * Some bookkeeping bug * Can't use the private field to check
2020-10-30 08:57:31 +08:00
completedModuleChunks: Array<Chunk>,
completedJSONChunks: Array<Chunk>,
completedErrorChunks: Array<Chunk>,
writtenSymbols: Map<symbol, number>,
2020-11-11 11:58:58 +08:00
writtenModules: Map<ModuleKey, number>,
[ServerContext] Flight support for ServerContext (#23244) * Flight side of server context * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * reinline * rebase * add back changes lost due to rebase being hard * emit chunk for provider * remove case for React provider type * update type for SomeChunk * enable flag with experimental * add missing types * fix flow type * missing type * t: any * revert extraneous type change * better type * better type * feedback * change import to type import * test? * test? * remove react-dom * remove react-native-renderer from react-server-native-relay/package.json * gate change in FiberNewContext, getComponentNameFromType, use switch statement in FlightServer * getComponentNameFromTpe: server context type gated and use displayName if available * fallthrough * lint.... * POP * lint
2022-03-08 20:55:32 +08:00
writtenProviders: Map<string, number>,
identifierPrefix: string,
identifierCount: number,
onError: (error: mixed) => ?string,
toJSON: (key: string, value: ReactModel) => ReactJSONValue,
};
const ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher;
const ReactCurrentCache = ReactSharedInternals.ReactCurrentCache;
function defaultErrorHandler(error: mixed) {
console['error'](error);
// Don't transform to our wrapper
}
const OPEN = 0;
const CLOSING = 1;
const CLOSED = 2;
export function createRequest(
model: ReactModel,
bundlerConfig: BundlerConfig,
onError: void | ((error: mixed) => ?string),
[ServerContext] Flight support for ServerContext (#23244) * Flight side of server context * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * reinline * rebase * add back changes lost due to rebase being hard * emit chunk for provider * remove case for React provider type * update type for SomeChunk * enable flag with experimental * add missing types * fix flow type * missing type * t: any * revert extraneous type change * better type * better type * feedback * change import to type import * test? * test? * remove react-dom * remove react-native-renderer from react-server-native-relay/package.json * gate change in FiberNewContext, getComponentNameFromType, use switch statement in FlightServer * getComponentNameFromTpe: server context type gated and use displayName if available * fallthrough * lint.... * POP * lint
2022-03-08 20:55:32 +08:00
context?: Array<[string, ServerContextJSONValue]>,
identifierPrefix?: string,
): Request {
const abortSet: Set<Task> = new Set();
const pingedTasks = [];
const request = {
status: OPEN,
fatalError: null,
destination: null,
bundlerConfig,
cache: new Map(),
nextChunkId: 0,
pendingChunks: 0,
abortableTasks: abortSet,
pingedTasks: pingedTasks,
[Flight] Add support for Module References in transport protocol (#20121) * Refactor Flight to require a module reference to be brand checked This exposes a host environment (bundler) specific hook to check if an object is a module reference. This will be used so that they can be passed directly into Flight without needing additional wrapper objects. * Emit module references as a special type of value We already have JSON and errors as special types of "rows". This encodes module references as a special type of row value. This was always the intention because it allows those values to be emitted first in the stream so that as a large models stream down, we can start preloading as early as possible. We preload the module when they resolve but we lazily require them as they are referenced. * Emit module references where ever they occur This emits module references where ever they occur. In blocks or even directly in elements. * Don't special case the root row I originally did this so that a simple stream is also just plain JSON. However, since we might want to emit things like modules before the root module in the stream, this gets unnecessarily complicated. We could add this back as a special case if it's the first byte written but meh. * Update the protocol * Add test for using a module reference as a client component * Relax element type check Since Flight now accepts a module reference as returned by any bundler system, depending on the renderer running. We need to drastically relax the check to include all of them. We can add more as we discover them. * Move flow annotation Seems like our compiler is not happy with stripping this. * Some bookkeeping bug * Can't use the private field to check
2020-10-30 08:57:31 +08:00
completedModuleChunks: [],
completedJSONChunks: [],
completedErrorChunks: [],
writtenSymbols: new Map(),
2020-11-11 11:58:58 +08:00
writtenModules: new Map(),
[ServerContext] Flight support for ServerContext (#23244) * Flight side of server context * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * reinline * rebase * add back changes lost due to rebase being hard * emit chunk for provider * remove case for React provider type * update type for SomeChunk * enable flag with experimental * add missing types * fix flow type * missing type * t: any * revert extraneous type change * better type * better type * feedback * change import to type import * test? * test? * remove react-dom * remove react-native-renderer from react-server-native-relay/package.json * gate change in FiberNewContext, getComponentNameFromType, use switch statement in FlightServer * getComponentNameFromTpe: server context type gated and use displayName if available * fallthrough * lint.... * POP * lint
2022-03-08 20:55:32 +08:00
writtenProviders: new Map(),
identifierPrefix: identifierPrefix || '',
identifierCount: 1,
onError: onError === undefined ? defaultErrorHandler : onError,
toJSON: function(key: string, value: ReactModel): ReactJSONValue {
return resolveModelToJSON(request, this, key, value);
},
};
request.pendingChunks++;
[ServerContext] Flight support for ServerContext (#23244) * Flight side of server context * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * reinline * rebase * add back changes lost due to rebase being hard * emit chunk for provider * remove case for React provider type * update type for SomeChunk * enable flag with experimental * add missing types * fix flow type * missing type * t: any * revert extraneous type change * better type * better type * feedback * change import to type import * test? * test? * remove react-dom * remove react-native-renderer from react-server-native-relay/package.json * gate change in FiberNewContext, getComponentNameFromType, use switch statement in FlightServer * getComponentNameFromTpe: server context type gated and use displayName if available * fallthrough * lint.... * POP * lint
2022-03-08 20:55:32 +08:00
const rootContext = createRootContext(context);
const rootTask = createTask(request, model, rootContext, abortSet);
pingedTasks.push(rootTask);
return request;
}
[ServerContext] Flight support for ServerContext (#23244) * Flight side of server context * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * reinline * rebase * add back changes lost due to rebase being hard * emit chunk for provider * remove case for React provider type * update type for SomeChunk * enable flag with experimental * add missing types * fix flow type * missing type * t: any * revert extraneous type change * better type * better type * feedback * change import to type import * test? * test? * remove react-dom * remove react-native-renderer from react-server-native-relay/package.json * gate change in FiberNewContext, getComponentNameFromType, use switch statement in FlightServer * getComponentNameFromTpe: server context type gated and use displayName if available * fallthrough * lint.... * POP * lint
2022-03-08 20:55:32 +08:00
function createRootContext(
reqContext?: Array<[string, ServerContextJSONValue]>,
) {
return importServerContexts(reqContext);
}
const POP = {};
// Used for DEV messages to keep track of which parent rendered some props,
// in case they error.
const jsxPropsParents: WeakMap<any, any> = new WeakMap();
const jsxChildrenParents: WeakMap<any, any> = new WeakMap();
function readThenable<T>(thenable: Thenable<T>): T {
if (thenable.status === 'fulfilled') {
return thenable.value;
} else if (thenable.status === 'rejected') {
throw thenable.reason;
}
throw thenable;
}
function createLazyWrapperAroundWakeable(wakeable: Wakeable) {
trackSuspendedWakeable(wakeable);
const lazyType: LazyComponent<any, Thenable<any>> = {
$$typeof: REACT_LAZY_TYPE,
_payload: (wakeable: any),
_init: readThenable,
};
return lazyType;
}
function attemptResolveElement(
type: any,
key: null | React$Key,
ref: mixed,
props: any,
prevThenableState: ThenableState | null,
): ReactModel {
if (ref !== null && ref !== undefined) {
// When the ref moves to the regular props object this will implicitly
// throw for functions. We could probably relax it to a DEV warning for other
// cases.
[RFC] Codemod invariant -> throw new Error (#22435) * Hoist error codes import to module scope When this code was written, the error codes map (`codes.json`) was created on-the-fly, so we had to lazily require from inside the visitor. Because `codes.json` is now checked into source, we can import it a single time in module scope. * Minify error constructors in production We use a script to minify our error messages in production. Each message is assigned an error code, defined in `scripts/error-codes/codes.json`. Then our build script replaces the messages with a link to our error decoder page, e.g. https://reactjs.org/docs/error-decoder.html/?invariant=92 This enables us to write helpful error messages without increasing the bundle size. Right now, the script only works for `invariant` calls. It does not work if you throw an Error object. This is an old Facebookism that we don't really need, other than the fact that our error minification script relies on it. So, I've updated the script to minify error constructors, too: Input: Error(`A ${adj} message that contains ${noun}`); Output: Error(formatProdErrorMessage(ERR_CODE, adj, noun)); It only works for constructors that are literally named Error, though we could add support for other names, too. As a next step, I will add a lint rule to enforce that errors written this way must have a corresponding error code. * Minify "no fallback UI specified" error in prod This error message wasn't being minified because it doesn't use invariant. The reason it didn't use invariant is because this particular error is created without begin thrown — it doesn't need to be thrown because it's located inside the error handling part of the runtime. Now that the error minification script supports Error constructors, we can minify it by assigning it a production error code in `scripts/error-codes/codes.json`. To support the use of Error constructors more generally, I will add a lint rule that enforces each message has a corresponding error code. * Lint rule to detect unminified errors Adds a lint rule that detects when an Error constructor is used without a corresponding production error code. We already have this for `invariant`, but not for regular errors, i.e. `throw new Error(msg)`. There's also nothing that enforces the use of `invariant` besides convention. There are some packages where we don't care to minify errors. These are packages that run in environments where bundle size is not a concern, like react-pg. I added an override in the ESLint config to ignore these. * Temporarily add invariant codemod script I'm adding this codemod to the repo temporarily, but I'll revert it in the same PR. That way we don't have to check it in but it's still accessible (via the PR) if we need it later. * [Automated] Codemod invariant -> Error This commit contains only automated changes: npx jscodeshift -t scripts/codemod-invariant.js packages --ignore-pattern="node_modules/**/*" yarn linc --fix yarn prettier I will do any manual touch ups in separate commits so they're easier to review. * Remove temporary codemod script This reverts the codemod script and ESLint config I added temporarily in order to perform the invariant codemod. * Manual touch ups A few manual changes I made after the codemod ran. * Enable error code transform per package Currently we're not consistent about which packages should have their errors minified in production and which ones should. This adds a field to the bundle configuration to control whether to apply the transform. We should decide what the criteria is going forward. I think it's probably a good idea to minify any package that gets sent over the network. So yes to modules that run in the browser, and no to modules that run on the server and during development only.
2021-10-01 03:01:28 +08:00
throw new Error(
'Refs cannot be used in Server Components, nor passed to Client Components.',
);
}
if (__DEV__) {
jsxPropsParents.set(props, type);
if (typeof props.children === 'object') {
jsxChildrenParents.set(props.children, type);
}
}
if (typeof type === 'function') {
if (isModuleReference(type)) {
// This is a reference to a Client Component.
return [REACT_ELEMENT_TYPE, type, key, props];
}
// This is a server-side component.
prepareToUseHooksForComponent(prevThenableState);
const result = type(props);
if (
typeof result === 'object' &&
result !== null &&
typeof result.then === 'function'
) {
return createLazyWrapperAroundWakeable(result);
}
return result;
} else if (typeof type === 'string') {
// This is a host element. E.g. HTML.
return [REACT_ELEMENT_TYPE, type, key, props];
} else if (typeof type === 'symbol') {
if (type === REACT_FRAGMENT_TYPE) {
// For key-less fragments, we add a small optimization to avoid serializing
// it as a wrapper.
// TODO: If a key is specified, we should propagate its key to any children.
// Same as if a Server Component has a key.
return props.children;
}
// This might be a built-in React component. We'll let the client decide.
// Any built-in works as long as its props are serializable.
return [REACT_ELEMENT_TYPE, type, key, props];
} else if (type != null && typeof type === 'object') {
[Flight] Add support for Module References in transport protocol (#20121) * Refactor Flight to require a module reference to be brand checked This exposes a host environment (bundler) specific hook to check if an object is a module reference. This will be used so that they can be passed directly into Flight without needing additional wrapper objects. * Emit module references as a special type of value We already have JSON and errors as special types of "rows". This encodes module references as a special type of row value. This was always the intention because it allows those values to be emitted first in the stream so that as a large models stream down, we can start preloading as early as possible. We preload the module when they resolve but we lazily require them as they are referenced. * Emit module references where ever they occur This emits module references where ever they occur. In blocks or even directly in elements. * Don't special case the root row I originally did this so that a simple stream is also just plain JSON. However, since we might want to emit things like modules before the root module in the stream, this gets unnecessarily complicated. We could add this back as a special case if it's the first byte written but meh. * Update the protocol * Add test for using a module reference as a client component * Relax element type check Since Flight now accepts a module reference as returned by any bundler system, depending on the renderer running. We need to drastically relax the check to include all of them. We can add more as we discover them. * Move flow annotation Seems like our compiler is not happy with stripping this. * Some bookkeeping bug * Can't use the private field to check
2020-10-30 08:57:31 +08:00
if (isModuleReference(type)) {
// This is a reference to a Client Component.
return [REACT_ELEMENT_TYPE, type, key, props];
[Flight] Add support for Module References in transport protocol (#20121) * Refactor Flight to require a module reference to be brand checked This exposes a host environment (bundler) specific hook to check if an object is a module reference. This will be used so that they can be passed directly into Flight without needing additional wrapper objects. * Emit module references as a special type of value We already have JSON and errors as special types of "rows". This encodes module references as a special type of row value. This was always the intention because it allows those values to be emitted first in the stream so that as a large models stream down, we can start preloading as early as possible. We preload the module when they resolve but we lazily require them as they are referenced. * Emit module references where ever they occur This emits module references where ever they occur. In blocks or even directly in elements. * Don't special case the root row I originally did this so that a simple stream is also just plain JSON. However, since we might want to emit things like modules before the root module in the stream, this gets unnecessarily complicated. We could add this back as a special case if it's the first byte written but meh. * Update the protocol * Add test for using a module reference as a client component * Relax element type check Since Flight now accepts a module reference as returned by any bundler system, depending on the renderer running. We need to drastically relax the check to include all of them. We can add more as we discover them. * Move flow annotation Seems like our compiler is not happy with stripping this. * Some bookkeeping bug * Can't use the private field to check
2020-10-30 08:57:31 +08:00
}
switch (type.$$typeof) {
case REACT_LAZY_TYPE: {
const payload = type._payload;
const init = type._init;
const wrappedType = init(payload);
return attemptResolveElement(
wrappedType,
key,
ref,
props,
prevThenableState,
);
}
case REACT_FORWARD_REF_TYPE: {
const render = type.render;
prepareToUseHooksForComponent(prevThenableState);
return render(props, undefined);
}
case REACT_MEMO_TYPE: {
return attemptResolveElement(
type.type,
key,
ref,
props,
prevThenableState,
);
}
[ServerContext] Flight support for ServerContext (#23244) * Flight side of server context * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * reinline * rebase * add back changes lost due to rebase being hard * emit chunk for provider * remove case for React provider type * update type for SomeChunk * enable flag with experimental * add missing types * fix flow type * missing type * t: any * revert extraneous type change * better type * better type * feedback * change import to type import * test? * test? * remove react-dom * remove react-native-renderer from react-server-native-relay/package.json * gate change in FiberNewContext, getComponentNameFromType, use switch statement in FlightServer * getComponentNameFromTpe: server context type gated and use displayName if available * fallthrough * lint.... * POP * lint
2022-03-08 20:55:32 +08:00
case REACT_PROVIDER_TYPE: {
pushProvider(type._context, props.value);
if (__DEV__) {
const extraKeys = Object.keys(props).filter(value => {
if (value === 'children' || value === 'value') {
return false;
}
return true;
});
if (extraKeys.length !== 0) {
console.error(
'ServerContext can only have a value prop and children. Found: %s',
JSON.stringify(extraKeys),
);
}
}
return [
REACT_ELEMENT_TYPE,
type,
key,
// Rely on __popProvider being serialized last to pop the provider.
{value: props.value, children: props.children, __pop: POP},
];
}
}
}
[RFC] Codemod invariant -> throw new Error (#22435) * Hoist error codes import to module scope When this code was written, the error codes map (`codes.json`) was created on-the-fly, so we had to lazily require from inside the visitor. Because `codes.json` is now checked into source, we can import it a single time in module scope. * Minify error constructors in production We use a script to minify our error messages in production. Each message is assigned an error code, defined in `scripts/error-codes/codes.json`. Then our build script replaces the messages with a link to our error decoder page, e.g. https://reactjs.org/docs/error-decoder.html/?invariant=92 This enables us to write helpful error messages without increasing the bundle size. Right now, the script only works for `invariant` calls. It does not work if you throw an Error object. This is an old Facebookism that we don't really need, other than the fact that our error minification script relies on it. So, I've updated the script to minify error constructors, too: Input: Error(`A ${adj} message that contains ${noun}`); Output: Error(formatProdErrorMessage(ERR_CODE, adj, noun)); It only works for constructors that are literally named Error, though we could add support for other names, too. As a next step, I will add a lint rule to enforce that errors written this way must have a corresponding error code. * Minify "no fallback UI specified" error in prod This error message wasn't being minified because it doesn't use invariant. The reason it didn't use invariant is because this particular error is created without begin thrown — it doesn't need to be thrown because it's located inside the error handling part of the runtime. Now that the error minification script supports Error constructors, we can minify it by assigning it a production error code in `scripts/error-codes/codes.json`. To support the use of Error constructors more generally, I will add a lint rule that enforces each message has a corresponding error code. * Lint rule to detect unminified errors Adds a lint rule that detects when an Error constructor is used without a corresponding production error code. We already have this for `invariant`, but not for regular errors, i.e. `throw new Error(msg)`. There's also nothing that enforces the use of `invariant` besides convention. There are some packages where we don't care to minify errors. These are packages that run in environments where bundle size is not a concern, like react-pg. I added an override in the ESLint config to ignore these. * Temporarily add invariant codemod script I'm adding this codemod to the repo temporarily, but I'll revert it in the same PR. That way we don't have to check it in but it's still accessible (via the PR) if we need it later. * [Automated] Codemod invariant -> Error This commit contains only automated changes: npx jscodeshift -t scripts/codemod-invariant.js packages --ignore-pattern="node_modules/**/*" yarn linc --fix yarn prettier I will do any manual touch ups in separate commits so they're easier to review. * Remove temporary codemod script This reverts the codemod script and ESLint config I added temporarily in order to perform the invariant codemod. * Manual touch ups A few manual changes I made after the codemod ran. * Enable error code transform per package Currently we're not consistent about which packages should have their errors minified in production and which ones should. This adds a field to the bundle configuration to control whether to apply the transform. We should decide what the criteria is going forward. I think it's probably a good idea to minify any package that gets sent over the network. So yes to modules that run in the browser, and no to modules that run on the server and during development only.
2021-10-01 03:01:28 +08:00
throw new Error(
`Unsupported Server Component type: ${describeValueForErrorMessage(type)}`,
);
}
function pingTask(request: Request, task: Task): void {
const pingedTasks = request.pingedTasks;
pingedTasks.push(task);
if (pingedTasks.length === 1) {
scheduleWork(() => performWork(request));
}
}
function createTask(
[ServerContext] Flight support for ServerContext (#23244) * Flight side of server context * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * reinline * rebase * add back changes lost due to rebase being hard * emit chunk for provider * remove case for React provider type * update type for SomeChunk * enable flag with experimental * add missing types * fix flow type * missing type * t: any * revert extraneous type change * better type * better type * feedback * change import to type import * test? * test? * remove react-dom * remove react-native-renderer from react-server-native-relay/package.json * gate change in FiberNewContext, getComponentNameFromType, use switch statement in FlightServer * getComponentNameFromTpe: server context type gated and use displayName if available * fallthrough * lint.... * POP * lint
2022-03-08 20:55:32 +08:00
request: Request,
model: ReactModel,
context: ContextSnapshot,
abortSet: Set<Task>,
): Task {
const id = request.nextChunkId++;
const task = {
id,
status: PENDING,
model,
[ServerContext] Flight support for ServerContext (#23244) * Flight side of server context * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * reinline * rebase * add back changes lost due to rebase being hard * emit chunk for provider * remove case for React provider type * update type for SomeChunk * enable flag with experimental * add missing types * fix flow type * missing type * t: any * revert extraneous type change * better type * better type * feedback * change import to type import * test? * test? * remove react-dom * remove react-native-renderer from react-server-native-relay/package.json * gate change in FiberNewContext, getComponentNameFromType, use switch statement in FlightServer * getComponentNameFromTpe: server context type gated and use displayName if available * fallthrough * lint.... * POP * lint
2022-03-08 20:55:32 +08:00
context,
ping: () => pingTask(request, task),
thenableState: null,
};
abortSet.add(task);
return task;
}
function serializeByValueID(id: number): string {
return '$' + id.toString(16);
}
function serializeByRefID(id: number): string {
return '@' + id.toString(16);
}
function serializeModuleReference(
request: Request,
parent: {+[key: string | number]: ReactModel} | $ReadOnlyArray<ReactModel>,
key: string,
moduleReference: ModuleReference<any>,
): string {
const moduleKey: ModuleKey = getModuleKey(moduleReference);
const writtenModules = request.writtenModules;
const existingId = writtenModules.get(moduleKey);
if (existingId !== undefined) {
if (parent[0] === REACT_ELEMENT_TYPE && key === '1') {
// If we're encoding the "type" of an element, we can refer
// to that by a lazy reference instead of directly since React
// knows how to deal with lazy values. This lets us suspend
// on this component rather than its parent until the code has
// loaded.
return serializeByRefID(existingId);
}
return serializeByValueID(existingId);
}
try {
const moduleMetaData: ModuleMetaData = resolveModuleMetaData(
request.bundlerConfig,
moduleReference,
);
request.pendingChunks++;
const moduleId = request.nextChunkId++;
emitModuleChunk(request, moduleId, moduleMetaData);
writtenModules.set(moduleKey, moduleId);
if (parent[0] === REACT_ELEMENT_TYPE && key === '1') {
// If we're encoding the "type" of an element, we can refer
// to that by a lazy reference instead of directly since React
// knows how to deal with lazy values. This lets us suspend
// on this component rather than its parent until the code has
// loaded.
return serializeByRefID(moduleId);
}
return serializeByValueID(moduleId);
} catch (x) {
request.pendingChunks++;
const errorId = request.nextChunkId++;
const digest = logRecoverableError(request, x);
if (__DEV__) {
const {message, stack} = getErrorMessageAndStackDev(x);
emitErrorChunkDev(request, errorId, digest, message, stack);
} else {
emitErrorChunkProd(request, errorId, digest);
}
return serializeByValueID(errorId);
}
}
function escapeStringValue(value: string): string {
if (value[0] === '$' || value[0] === '@') {
// We need to escape $ or @ prefixed strings since we use those to encode
// references to IDs and as special symbol values.
return '$' + value;
} else {
return value;
}
}
function isObjectPrototype(object): boolean {
if (!object) {
return false;
}
const ObjectPrototype = Object.prototype;
if (object === ObjectPrototype) {
return true;
}
// It might be an object from a different Realm which is
// still just a plain simple object.
if (Object.getPrototypeOf(object)) {
return false;
}
const names = Object.getOwnPropertyNames(object);
for (let i = 0; i < names.length; i++) {
if (!(names[i] in ObjectPrototype)) {
return false;
}
}
return true;
}
function isSimpleObject(object): boolean {
if (!isObjectPrototype(Object.getPrototypeOf(object))) {
return false;
}
const names = Object.getOwnPropertyNames(object);
for (let i = 0; i < names.length; i++) {
const descriptor = Object.getOwnPropertyDescriptor(object, names[i]);
if (!descriptor) {
return false;
}
if (!descriptor.enumerable) {
if (
(names[i] === 'key' || names[i] === 'ref') &&
typeof descriptor.get === 'function'
) {
// React adds key and ref getters to props objects to issue warnings.
// Those getters will not be transferred to the client, but that's ok,
// so we'll special case them.
continue;
}
return false;
}
}
return true;
}
function objectName(object): string {
// $FlowFixMe[method-unbinding]
const name = Object.prototype.toString.call(object);
return name.replace(/^\[object (.*)\]$/, function(m, p0) {
return p0;
});
}
function describeKeyForErrorMessage(key: string): string {
const encodedKey = JSON.stringify(key);
return '"' + key + '"' === encodedKey ? key : encodedKey;
}
function describeValueForErrorMessage(value: ReactModel): string {
switch (typeof value) {
case 'string': {
return JSON.stringify(
value.length <= 10 ? value : value.substr(0, 10) + '...',
);
}
case 'object': {
if (isArray(value)) {
return '[...]';
}
const name = objectName(value);
if (name === 'Object') {
return '{...}';
}
return name;
}
case 'function':
return 'function';
default:
Improve DEV errors if string coercion throws (Temporal.*, Symbol, etc.) (#22064) * Revise ESLint rules for string coercion Currently, react uses `'' + value` to coerce mixed values to strings. This code will throw for Temporal objects or symbols. To make string-coercion safer and to improve user-facing error messages, This commit adds a new ESLint rule called `safe-string-coercion`. This rule has two modes: a production mode and a non-production mode. * If the `isProductionUserAppCode` option is true, then `'' + value` coercions are allowed (because they're faster, although they may throw) and `String(value)` coercions are disallowed. Exception: when building error messages or running DEV-only code in prod files, `String()` should be used because it won't throw. * If the `isProductionUserAppCode` option is false, then `'' + value` coercions are disallowed (because they may throw, and in non-prod code it's not worth the risk) and `String(value)` are allowed. Production mode is used for all files which will be bundled with developers' userland apps. Non-prod mode is used for all other React code: tests, DEV blocks, devtools extension, etc. In production mode, in addiiton to flagging `String(value)` calls, the rule will also flag `'' + value` or `value + ''` coercions that may throw. The rule is smart enough to silence itself in the following "will never throw" cases: * When the coercion is wrapped in a `typeof` test that restricts to safe (non-symbol, non-object) types. Example: if (typeof value === 'string' || typeof value === 'number') { thisWontReport('' + value); } * When what's being coerced is a unary function result, because unary functions never return an object or a symbol. * When the coerced value is a commonly-used numeric identifier: `i`, `idx`, or `lineNumber`. * When the statement immeidately before the coercion is a DEV-only call to a function from shared/CheckStringCoercion.js. This call is a no-op in production, but in DEV it will show a console error explaining the problem, then will throw right after a long explanatory code comment so that debugger users will have an idea what's going on. The check function call must be in the following format: if (__DEV__) { checkXxxxxStringCoercion(value); }; Manually disabling the rule is usually not necessary because almost all prod use of the `'' + value` pattern falls into one of the categories above. But in the rare cases where the rule isn't smart enough to detect safe usage (e.g. when a coercion is inside a nested ternary operator), manually disabling the rule will be needed. The rule should also be manually disabled in prod error handling code where `String(value)` should be used for coercions, because it'd be bad to throw while building an error message or stack trace! The prod and non-prod modes have differentiated error messages to explain how to do a proper coercion in that mode. If a production check call is needed but is missing or incorrect (e.g. not in a DEV block or not immediately before the coercion), then a context-sensitive error message will be reported so that developers can figure out what's wrong and how to fix the problem. Because string coercions are now handled by the `safe-string-coercion` rule, the `no-primitive-constructor` rule no longer flags `String()` usage. It still flags `new String(value)` because that usage is almost always a bug. * Add DEV-only string coercion check functions This commit adds DEV-only functions to check whether coercing values to strings using the `'' + value` pattern will throw. If it will throw, these functions will: 1. Display a console error with a friendly error message describing the problem and the developer can fix it. 2. Perform the coercion, which will throw. Right before the line where the throwing happens, there's a long code comment that will help debugger users (or others looking at the exception call stack) figure out what happened and how to fix the problem. One of these check functions should be called before all string coercion of user-provided values, except when the the coercion is guaranteed not to throw, e.g. * if inside a typeof check like `if (typeof value === 'string')` * if coercing the result of a unary function like `+value` or `value++` * if coercing a variable named in a whitelist of numeric identifiers: `i`, `idx`, or `lineNumber`. The new `safe-string-coercion` internal ESLint rule enforces that these check functions are called when they are required. Only use these check functions in production code that will be bundled with user apps. For non-prod code (and for production error-handling code), use `String(value)` instead which may be a little slower but will never throw. * Add failing tests for string coercion Added failing tests to verify: * That input, select, and textarea elements with value and defaultValue set to Temporal-like objects which will throw when coerced to string using the `'' + value` pattern. * That text elements will throw for Temporal-like objects * That dangerouslySetInnerHTML will *not* throw for Temporal-like objects because this value is not cast to a string before passing to the DOM. * That keys that are Temporal-like objects will throw All tests above validate the friendly error messages thrown. * Use `String(value)` for coercion in non-prod files This commit switches non-production code from `'' + value` (which throws for Temporal objects and symbols) to instead use `String(value)` which won't throw for these or other future plus-phobic types. "Non-produciton code" includes anything not bundled into user apps: * Tests and test utilities. Note that I didn't change legacy React test fixtures because I assumed it was good for those files to act just like old React, including coercion behavior. * Build scripts * Dev tools package - In addition to switching to `String`, I also removed special-case code for coercing symbols which is now unnecessary. * Add DEV-only string coercion checks to prod files This commit adds DEV-only function calls to to check if string coercion using `'' + value` will throw, which it will if the value is a Temporal object or a symbol because those types can't be added with `+`. If it will throw, then in DEV these checks will show a console error to help the user undertsand what went wrong and how to fix the problem. After emitting the console error, the check functions will retry the coercion which will throw with a call stack that's easy (or at least easier!) to troubleshoot because the exception happens right after a long comment explaining the issue. So whether the user is in a debugger, looking at the browser console, or viewing the in-browser DEV call stack, it should be easy to understand and fix the problem. In most cases, the safe-string-coercion ESLint rule is smart enough to detect when a coercion is safe. But in rare cases (e.g. when a coercion is inside a ternary) this rule will have to be manually disabled. This commit also switches error-handling code to use `String(value)` for coercion, because it's bad to crash when you're trying to build an error message or a call stack! Because `String()` is usually disallowed by the `safe-string-coercion` ESLint rule in production code, the rule must be disabled when `String()` is used.
2021-09-28 01:05:07 +08:00
// eslint-disable-next-line react-internal/safe-string-coercion
return String(value);
}
}
function describeElementType(type: any): string {
if (typeof type === 'string') {
return type;
}
switch (type) {
case REACT_SUSPENSE_TYPE:
return 'Suspense';
case REACT_SUSPENSE_LIST_TYPE:
return 'SuspenseList';
}
if (typeof type === 'object') {
switch (type.$$typeof) {
case REACT_FORWARD_REF_TYPE:
return describeElementType(type.render);
case REACT_MEMO_TYPE:
return describeElementType(type.type);
case REACT_LAZY_TYPE: {
const lazyComponent: LazyComponent<any, any> = (type: any);
const payload = lazyComponent._payload;
const init = lazyComponent._init;
try {
// Lazy may contain any component type so we recursively resolve it.
return describeElementType(init(payload));
} catch (x) {}
}
}
}
return '';
}
function describeObjectForErrorMessage(
objectOrArray:
| {+[key: string | number]: ReactModel, ...}
| $ReadOnlyArray<ReactModel>,
expandedName?: string,
): string {
const objKind = objectName(objectOrArray);
if (objKind !== 'Object' && objKind !== 'Array') {
return objKind;
}
let str = '';
let start = -1;
let length = 0;
if (isArray(objectOrArray)) {
if (__DEV__ && jsxChildrenParents.has(objectOrArray)) {
// Print JSX Children
const type = jsxChildrenParents.get(objectOrArray);
str = '<' + describeElementType(type) + '>';
const array: $ReadOnlyArray<ReactModel> = objectOrArray;
for (let i = 0; i < array.length; i++) {
const value = array[i];
let substr;
if (typeof value === 'string') {
substr = value;
} else if (typeof value === 'object' && value !== null) {
// $FlowFixMe[incompatible-call] found when upgrading Flow
substr = '{' + describeObjectForErrorMessage(value) + '}';
} else {
substr = '{' + describeValueForErrorMessage(value) + '}';
}
if ('' + i === expandedName) {
start = str.length;
length = substr.length;
str += substr;
} else if (substr.length < 15 && str.length + substr.length < 40) {
str += substr;
} else {
str += '{...}';
}
}
str += '</' + describeElementType(type) + '>';
} else {
// Print Array
str = '[';
const array: $ReadOnlyArray<ReactModel> = objectOrArray;
for (let i = 0; i < array.length; i++) {
if (i > 0) {
str += ', ';
}
const value = array[i];
let substr;
if (typeof value === 'object' && value !== null) {
// $FlowFixMe[incompatible-call] found when upgrading Flow
substr = describeObjectForErrorMessage(value);
} else {
substr = describeValueForErrorMessage(value);
}
if ('' + i === expandedName) {
start = str.length;
length = substr.length;
str += substr;
} else if (substr.length < 10 && str.length + substr.length < 40) {
str += substr;
} else {
str += '...';
}
}
str += ']';
}
} else {
if (objectOrArray.$$typeof === REACT_ELEMENT_TYPE) {
str = '<' + describeElementType(objectOrArray.type) + '/>';
} else if (__DEV__ && jsxPropsParents.has(objectOrArray)) {
// Print JSX
const type = jsxPropsParents.get(objectOrArray);
str = '<' + (describeElementType(type) || '...');
const object: {+[key: string | number]: ReactModel, ...} = objectOrArray;
const names = Object.keys(object);
for (let i = 0; i < names.length; i++) {
str += ' ';
const name = names[i];
str += describeKeyForErrorMessage(name) + '=';
const value = object[name];
let substr;
if (
name === expandedName &&
typeof value === 'object' &&
value !== null
) {
// $FlowFixMe[incompatible-call] found when upgrading Flow
substr = describeObjectForErrorMessage(value);
} else {
substr = describeValueForErrorMessage(value);
}
if (typeof value !== 'string') {
substr = '{' + substr + '}';
}
if (name === expandedName) {
start = str.length;
length = substr.length;
str += substr;
} else if (substr.length < 10 && str.length + substr.length < 40) {
str += substr;
} else {
str += '...';
}
}
str += '>';
} else {
// Print Object
str = '{';
const object: {+[key: string | number]: ReactModel, ...} = objectOrArray;
const names = Object.keys(object);
for (let i = 0; i < names.length; i++) {
if (i > 0) {
str += ', ';
}
const name = names[i];
str += describeKeyForErrorMessage(name) + ': ';
const value = object[name];
let substr;
if (typeof value === 'object' && value !== null) {
// $FlowFixMe[incompatible-call] found when upgrading Flow
substr = describeObjectForErrorMessage(value);
} else {
substr = describeValueForErrorMessage(value);
}
if (name === expandedName) {
start = str.length;
length = substr.length;
str += substr;
} else if (substr.length < 10 && str.length + substr.length < 40) {
str += substr;
} else {
str += '...';
}
}
str += '}';
}
}
if (expandedName === undefined) {
return str;
}
if (start > -1 && length > 0) {
const highlight = ' '.repeat(start) + '^'.repeat(length);
return '\n ' + str + '\n ' + highlight;
}
return '\n ' + str;
}
[ServerContext] Flight support for ServerContext (#23244) * Flight side of server context * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * reinline * rebase * add back changes lost due to rebase being hard * emit chunk for provider * remove case for React provider type * update type for SomeChunk * enable flag with experimental * add missing types * fix flow type * missing type * t: any * revert extraneous type change * better type * better type * feedback * change import to type import * test? * test? * remove react-dom * remove react-native-renderer from react-server-native-relay/package.json * gate change in FiberNewContext, getComponentNameFromType, use switch statement in FlightServer * getComponentNameFromTpe: server context type gated and use displayName if available * fallthrough * lint.... * POP * lint
2022-03-08 20:55:32 +08:00
let insideContextProps = null;
let isInsideContextValue = false;
export function resolveModelToJSON(
request: Request,
parent: {+[key: string | number]: ReactModel} | $ReadOnlyArray<ReactModel>,
key: string,
value: ReactModel,
): ReactJSONValue {
if (__DEV__) {
// $FlowFixMe
const originalValue = parent[key];
if (typeof originalValue === 'object' && originalValue !== value) {
if (objectName(originalValue) !== 'Object') {
const jsxParentType = jsxChildrenParents.get(parent);
if (typeof jsxParentType === 'string') {
console.error(
'%s objects cannot be rendered as text children. Try formatting it using toString().%s',
objectName(originalValue),
describeObjectForErrorMessage(parent, key),
);
} else {
console.error(
'Only plain objects can be passed to Client Components from Server Components. ' +
'%s objects are not supported.%s',
objectName(originalValue),
describeObjectForErrorMessage(parent, key),
);
}
} else {
console.error(
'Only plain objects can be passed to Client Components from Server Components. ' +
'Objects with toJSON methods are not supported. Convert it manually ' +
'to a simple value before passing it to props.%s',
describeObjectForErrorMessage(parent, key),
);
}
}
}
// Special Symbols
switch (value) {
case REACT_ELEMENT_TYPE:
return '$';
}
[ServerContext] Flight support for ServerContext (#23244) * Flight side of server context * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * reinline * rebase * add back changes lost due to rebase being hard * emit chunk for provider * remove case for React provider type * update type for SomeChunk * enable flag with experimental * add missing types * fix flow type * missing type * t: any * revert extraneous type change * better type * better type * feedback * change import to type import * test? * test? * remove react-dom * remove react-native-renderer from react-server-native-relay/package.json * gate change in FiberNewContext, getComponentNameFromType, use switch statement in FlightServer * getComponentNameFromTpe: server context type gated and use displayName if available * fallthrough * lint.... * POP * lint
2022-03-08 20:55:32 +08:00
if (__DEV__) {
if (
parent[0] === REACT_ELEMENT_TYPE &&
parent[1] &&
parent[1].$$typeof === REACT_PROVIDER_TYPE &&
key === '3'
) {
insideContextProps = value;
} else if (insideContextProps === parent && key === 'value') {
isInsideContextValue = true;
} else if (insideContextProps === parent && key === 'children') {
isInsideContextValue = false;
}
}
// Resolve Server Components.
while (
typeof value === 'object' &&
value !== null &&
((value: any).$$typeof === REACT_ELEMENT_TYPE ||
(value: any).$$typeof === REACT_LAZY_TYPE)
) {
[ServerContext] Flight support for ServerContext (#23244) * Flight side of server context * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * reinline * rebase * add back changes lost due to rebase being hard * emit chunk for provider * remove case for React provider type * update type for SomeChunk * enable flag with experimental * add missing types * fix flow type * missing type * t: any * revert extraneous type change * better type * better type * feedback * change import to type import * test? * test? * remove react-dom * remove react-native-renderer from react-server-native-relay/package.json * gate change in FiberNewContext, getComponentNameFromType, use switch statement in FlightServer * getComponentNameFromTpe: server context type gated and use displayName if available * fallthrough * lint.... * POP * lint
2022-03-08 20:55:32 +08:00
if (__DEV__) {
if (isInsideContextValue) {
console.error('React elements are not allowed in ServerContext');
}
}
try {
switch ((value: any).$$typeof) {
case REACT_ELEMENT_TYPE: {
// TODO: Concatenate keys of parents onto children.
const element: React$Element<any> = (value: any);
// Attempt to render the Server Component.
value = attemptResolveElement(
element.type,
element.key,
element.ref,
element.props,
null,
);
break;
}
case REACT_LAZY_TYPE: {
const payload = (value: any)._payload;
const init = (value: any)._init;
value = init(payload);
break;
}
}
} catch (x) {
if (typeof x === 'object' && x !== null && typeof x.then === 'function') {
// Something suspended, we'll need to create a new task and resolve it later.
request.pendingChunks++;
const newTask = createTask(
request,
value,
getActiveContext(),
request.abortableTasks,
);
const ping = newTask.ping;
x.then(ping, ping);
const wakeable: Wakeable = x;
trackSuspendedWakeable(wakeable);
newTask.thenableState = getThenableStateAfterSuspending();
return serializeByRefID(newTask.id);
} else {
// Something errored. We'll still send everything we have up until this point.
// We'll replace this element with a lazy reference that throws on the client
// once it gets rendered.
request.pendingChunks++;
const errorId = request.nextChunkId++;
const digest = logRecoverableError(request, x);
if (__DEV__) {
const {message, stack} = getErrorMessageAndStackDev(x);
emitErrorChunkDev(request, errorId, digest, message, stack);
} else {
emitErrorChunkProd(request, errorId, digest);
}
return serializeByRefID(errorId);
}
}
}
[Flight] Add support for Module References in transport protocol (#20121) * Refactor Flight to require a module reference to be brand checked This exposes a host environment (bundler) specific hook to check if an object is a module reference. This will be used so that they can be passed directly into Flight without needing additional wrapper objects. * Emit module references as a special type of value We already have JSON and errors as special types of "rows". This encodes module references as a special type of row value. This was always the intention because it allows those values to be emitted first in the stream so that as a large models stream down, we can start preloading as early as possible. We preload the module when they resolve but we lazily require them as they are referenced. * Emit module references where ever they occur This emits module references where ever they occur. In blocks or even directly in elements. * Don't special case the root row I originally did this so that a simple stream is also just plain JSON. However, since we might want to emit things like modules before the root module in the stream, this gets unnecessarily complicated. We could add this back as a special case if it's the first byte written but meh. * Update the protocol * Add test for using a module reference as a client component * Relax element type check Since Flight now accepts a module reference as returned by any bundler system, depending on the renderer running. We need to drastically relax the check to include all of them. We can add more as we discover them. * Move flow annotation Seems like our compiler is not happy with stripping this. * Some bookkeeping bug * Can't use the private field to check
2020-10-30 08:57:31 +08:00
if (value === null) {
return null;
}
if (typeof value === 'object') {
[Flight] Add support for Module References in transport protocol (#20121) * Refactor Flight to require a module reference to be brand checked This exposes a host environment (bundler) specific hook to check if an object is a module reference. This will be used so that they can be passed directly into Flight without needing additional wrapper objects. * Emit module references as a special type of value We already have JSON and errors as special types of "rows". This encodes module references as a special type of row value. This was always the intention because it allows those values to be emitted first in the stream so that as a large models stream down, we can start preloading as early as possible. We preload the module when they resolve but we lazily require them as they are referenced. * Emit module references where ever they occur This emits module references where ever they occur. In blocks or even directly in elements. * Don't special case the root row I originally did this so that a simple stream is also just plain JSON. However, since we might want to emit things like modules before the root module in the stream, this gets unnecessarily complicated. We could add this back as a special case if it's the first byte written but meh. * Update the protocol * Add test for using a module reference as a client component * Relax element type check Since Flight now accepts a module reference as returned by any bundler system, depending on the renderer running. We need to drastically relax the check to include all of them. We can add more as we discover them. * Move flow annotation Seems like our compiler is not happy with stripping this. * Some bookkeeping bug * Can't use the private field to check
2020-10-30 08:57:31 +08:00
if (isModuleReference(value)) {
return serializeModuleReference(request, parent, key, (value: any));
[ServerContext] Flight support for ServerContext (#23244) * Flight side of server context * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * reinline * rebase * add back changes lost due to rebase being hard * emit chunk for provider * remove case for React provider type * update type for SomeChunk * enable flag with experimental * add missing types * fix flow type * missing type * t: any * revert extraneous type change * better type * better type * feedback * change import to type import * test? * test? * remove react-dom * remove react-native-renderer from react-server-native-relay/package.json * gate change in FiberNewContext, getComponentNameFromType, use switch statement in FlightServer * getComponentNameFromTpe: server context type gated and use displayName if available * fallthrough * lint.... * POP * lint
2022-03-08 20:55:32 +08:00
} else if ((value: any).$$typeof === REACT_PROVIDER_TYPE) {
const providerKey = ((value: any): ReactProviderType<any>)._context
._globalName;
const writtenProviders = request.writtenProviders;
let providerId = writtenProviders.get(key);
if (providerId === undefined) {
request.pendingChunks++;
providerId = request.nextChunkId++;
writtenProviders.set(providerKey, providerId);
emitProviderChunk(request, providerId, providerKey);
}
return serializeByValueID(providerId);
} else if (value === POP) {
popProvider();
if (__DEV__) {
insideContextProps = null;
isInsideContextValue = false;
}
return (undefined: any);
[Flight] Add support for Module References in transport protocol (#20121) * Refactor Flight to require a module reference to be brand checked This exposes a host environment (bundler) specific hook to check if an object is a module reference. This will be used so that they can be passed directly into Flight without needing additional wrapper objects. * Emit module references as a special type of value We already have JSON and errors as special types of "rows". This encodes module references as a special type of row value. This was always the intention because it allows those values to be emitted first in the stream so that as a large models stream down, we can start preloading as early as possible. We preload the module when they resolve but we lazily require them as they are referenced. * Emit module references where ever they occur This emits module references where ever they occur. In blocks or even directly in elements. * Don't special case the root row I originally did this so that a simple stream is also just plain JSON. However, since we might want to emit things like modules before the root module in the stream, this gets unnecessarily complicated. We could add this back as a special case if it's the first byte written but meh. * Update the protocol * Add test for using a module reference as a client component * Relax element type check Since Flight now accepts a module reference as returned by any bundler system, depending on the renderer running. We need to drastically relax the check to include all of them. We can add more as we discover them. * Move flow annotation Seems like our compiler is not happy with stripping this. * Some bookkeeping bug * Can't use the private field to check
2020-10-30 08:57:31 +08:00
}
if (__DEV__) {
if (value !== null && !isArray(value)) {
// Verify that this is a simple plain object.
if (objectName(value) !== 'Object') {
console.error(
'Only plain objects can be passed to Client Components from Server Components. ' +
'%s objects are not supported.%s',
objectName(value),
describeObjectForErrorMessage(parent, key),
);
} else if (!isSimpleObject(value)) {
console.error(
'Only plain objects can be passed to Client Components from Server Components. ' +
'Classes or other objects with methods are not supported.%s',
describeObjectForErrorMessage(parent, key),
);
} else if (Object.getOwnPropertySymbols) {
const symbols = Object.getOwnPropertySymbols(value);
if (symbols.length > 0) {
console.error(
'Only plain objects can be passed to Client Components from Server Components. ' +
'Objects with symbol properties like %s are not supported.%s',
symbols[0].description,
describeObjectForErrorMessage(parent, key),
);
}
}
}
}
[ServerContext] Flight support for ServerContext (#23244) * Flight side of server context * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * reinline * rebase * add back changes lost due to rebase being hard * emit chunk for provider * remove case for React provider type * update type for SomeChunk * enable flag with experimental * add missing types * fix flow type * missing type * t: any * revert extraneous type change * better type * better type * feedback * change import to type import * test? * test? * remove react-dom * remove react-native-renderer from react-server-native-relay/package.json * gate change in FiberNewContext, getComponentNameFromType, use switch statement in FlightServer * getComponentNameFromTpe: server context type gated and use displayName if available * fallthrough * lint.... * POP * lint
2022-03-08 20:55:32 +08:00
// $FlowFixMe
return value;
}
if (typeof value === 'string') {
return escapeStringValue(value);
}
if (
typeof value === 'boolean' ||
typeof value === 'number' ||
typeof value === 'undefined'
) {
return value;
}
if (typeof value === 'function') {
if (isModuleReference(value)) {
return serializeModuleReference(request, parent, key, (value: any));
}
if (/^on[A-Z]/.test(key)) {
[RFC] Codemod invariant -> throw new Error (#22435) * Hoist error codes import to module scope When this code was written, the error codes map (`codes.json`) was created on-the-fly, so we had to lazily require from inside the visitor. Because `codes.json` is now checked into source, we can import it a single time in module scope. * Minify error constructors in production We use a script to minify our error messages in production. Each message is assigned an error code, defined in `scripts/error-codes/codes.json`. Then our build script replaces the messages with a link to our error decoder page, e.g. https://reactjs.org/docs/error-decoder.html/?invariant=92 This enables us to write helpful error messages without increasing the bundle size. Right now, the script only works for `invariant` calls. It does not work if you throw an Error object. This is an old Facebookism that we don't really need, other than the fact that our error minification script relies on it. So, I've updated the script to minify error constructors, too: Input: Error(`A ${adj} message that contains ${noun}`); Output: Error(formatProdErrorMessage(ERR_CODE, adj, noun)); It only works for constructors that are literally named Error, though we could add support for other names, too. As a next step, I will add a lint rule to enforce that errors written this way must have a corresponding error code. * Minify "no fallback UI specified" error in prod This error message wasn't being minified because it doesn't use invariant. The reason it didn't use invariant is because this particular error is created without begin thrown — it doesn't need to be thrown because it's located inside the error handling part of the runtime. Now that the error minification script supports Error constructors, we can minify it by assigning it a production error code in `scripts/error-codes/codes.json`. To support the use of Error constructors more generally, I will add a lint rule that enforces each message has a corresponding error code. * Lint rule to detect unminified errors Adds a lint rule that detects when an Error constructor is used without a corresponding production error code. We already have this for `invariant`, but not for regular errors, i.e. `throw new Error(msg)`. There's also nothing that enforces the use of `invariant` besides convention. There are some packages where we don't care to minify errors. These are packages that run in environments where bundle size is not a concern, like react-pg. I added an override in the ESLint config to ignore these. * Temporarily add invariant codemod script I'm adding this codemod to the repo temporarily, but I'll revert it in the same PR. That way we don't have to check it in but it's still accessible (via the PR) if we need it later. * [Automated] Codemod invariant -> Error This commit contains only automated changes: npx jscodeshift -t scripts/codemod-invariant.js packages --ignore-pattern="node_modules/**/*" yarn linc --fix yarn prettier I will do any manual touch ups in separate commits so they're easier to review. * Remove temporary codemod script This reverts the codemod script and ESLint config I added temporarily in order to perform the invariant codemod. * Manual touch ups A few manual changes I made after the codemod ran. * Enable error code transform per package Currently we're not consistent about which packages should have their errors minified in production and which ones should. This adds a field to the bundle configuration to control whether to apply the transform. We should decide what the criteria is going forward. I think it's probably a good idea to minify any package that gets sent over the network. So yes to modules that run in the browser, and no to modules that run on the server and during development only.
2021-10-01 03:01:28 +08:00
throw new Error(
'Event handlers cannot be passed to Client Component props.' +
describeObjectForErrorMessage(parent, key) +
'\nIf you need interactivity, consider converting part of this to a Client Component.',
);
} else {
[RFC] Codemod invariant -> throw new Error (#22435) * Hoist error codes import to module scope When this code was written, the error codes map (`codes.json`) was created on-the-fly, so we had to lazily require from inside the visitor. Because `codes.json` is now checked into source, we can import it a single time in module scope. * Minify error constructors in production We use a script to minify our error messages in production. Each message is assigned an error code, defined in `scripts/error-codes/codes.json`. Then our build script replaces the messages with a link to our error decoder page, e.g. https://reactjs.org/docs/error-decoder.html/?invariant=92 This enables us to write helpful error messages without increasing the bundle size. Right now, the script only works for `invariant` calls. It does not work if you throw an Error object. This is an old Facebookism that we don't really need, other than the fact that our error minification script relies on it. So, I've updated the script to minify error constructors, too: Input: Error(`A ${adj} message that contains ${noun}`); Output: Error(formatProdErrorMessage(ERR_CODE, adj, noun)); It only works for constructors that are literally named Error, though we could add support for other names, too. As a next step, I will add a lint rule to enforce that errors written this way must have a corresponding error code. * Minify "no fallback UI specified" error in prod This error message wasn't being minified because it doesn't use invariant. The reason it didn't use invariant is because this particular error is created without begin thrown — it doesn't need to be thrown because it's located inside the error handling part of the runtime. Now that the error minification script supports Error constructors, we can minify it by assigning it a production error code in `scripts/error-codes/codes.json`. To support the use of Error constructors more generally, I will add a lint rule that enforces each message has a corresponding error code. * Lint rule to detect unminified errors Adds a lint rule that detects when an Error constructor is used without a corresponding production error code. We already have this for `invariant`, but not for regular errors, i.e. `throw new Error(msg)`. There's also nothing that enforces the use of `invariant` besides convention. There are some packages where we don't care to minify errors. These are packages that run in environments where bundle size is not a concern, like react-pg. I added an override in the ESLint config to ignore these. * Temporarily add invariant codemod script I'm adding this codemod to the repo temporarily, but I'll revert it in the same PR. That way we don't have to check it in but it's still accessible (via the PR) if we need it later. * [Automated] Codemod invariant -> Error This commit contains only automated changes: npx jscodeshift -t scripts/codemod-invariant.js packages --ignore-pattern="node_modules/**/*" yarn linc --fix yarn prettier I will do any manual touch ups in separate commits so they're easier to review. * Remove temporary codemod script This reverts the codemod script and ESLint config I added temporarily in order to perform the invariant codemod. * Manual touch ups A few manual changes I made after the codemod ran. * Enable error code transform per package Currently we're not consistent about which packages should have their errors minified in production and which ones should. This adds a field to the bundle configuration to control whether to apply the transform. We should decide what the criteria is going forward. I think it's probably a good idea to minify any package that gets sent over the network. So yes to modules that run in the browser, and no to modules that run on the server and during development only.
2021-10-01 03:01:28 +08:00
throw new Error(
'Functions cannot be passed directly to Client Components ' +
"because they're not serializable." +
describeObjectForErrorMessage(parent, key),
);
}
}
if (typeof value === 'symbol') {
const writtenSymbols = request.writtenSymbols;
const existingId = writtenSymbols.get(value);
if (existingId !== undefined) {
return serializeByValueID(existingId);
}
// $FlowFixMe `description` might be undefined
const name: string = value.description;
[RFC] Codemod invariant -> throw new Error (#22435) * Hoist error codes import to module scope When this code was written, the error codes map (`codes.json`) was created on-the-fly, so we had to lazily require from inside the visitor. Because `codes.json` is now checked into source, we can import it a single time in module scope. * Minify error constructors in production We use a script to minify our error messages in production. Each message is assigned an error code, defined in `scripts/error-codes/codes.json`. Then our build script replaces the messages with a link to our error decoder page, e.g. https://reactjs.org/docs/error-decoder.html/?invariant=92 This enables us to write helpful error messages without increasing the bundle size. Right now, the script only works for `invariant` calls. It does not work if you throw an Error object. This is an old Facebookism that we don't really need, other than the fact that our error minification script relies on it. So, I've updated the script to minify error constructors, too: Input: Error(`A ${adj} message that contains ${noun}`); Output: Error(formatProdErrorMessage(ERR_CODE, adj, noun)); It only works for constructors that are literally named Error, though we could add support for other names, too. As a next step, I will add a lint rule to enforce that errors written this way must have a corresponding error code. * Minify "no fallback UI specified" error in prod This error message wasn't being minified because it doesn't use invariant. The reason it didn't use invariant is because this particular error is created without begin thrown — it doesn't need to be thrown because it's located inside the error handling part of the runtime. Now that the error minification script supports Error constructors, we can minify it by assigning it a production error code in `scripts/error-codes/codes.json`. To support the use of Error constructors more generally, I will add a lint rule that enforces each message has a corresponding error code. * Lint rule to detect unminified errors Adds a lint rule that detects when an Error constructor is used without a corresponding production error code. We already have this for `invariant`, but not for regular errors, i.e. `throw new Error(msg)`. There's also nothing that enforces the use of `invariant` besides convention. There are some packages where we don't care to minify errors. These are packages that run in environments where bundle size is not a concern, like react-pg. I added an override in the ESLint config to ignore these. * Temporarily add invariant codemod script I'm adding this codemod to the repo temporarily, but I'll revert it in the same PR. That way we don't have to check it in but it's still accessible (via the PR) if we need it later. * [Automated] Codemod invariant -> Error This commit contains only automated changes: npx jscodeshift -t scripts/codemod-invariant.js packages --ignore-pattern="node_modules/**/*" yarn linc --fix yarn prettier I will do any manual touch ups in separate commits so they're easier to review. * Remove temporary codemod script This reverts the codemod script and ESLint config I added temporarily in order to perform the invariant codemod. * Manual touch ups A few manual changes I made after the codemod ran. * Enable error code transform per package Currently we're not consistent about which packages should have their errors minified in production and which ones should. This adds a field to the bundle configuration to control whether to apply the transform. We should decide what the criteria is going forward. I think it's probably a good idea to minify any package that gets sent over the network. So yes to modules that run in the browser, and no to modules that run on the server and during development only.
2021-10-01 03:01:28 +08:00
if (Symbol.for(name) !== value) {
throw new Error(
'Only global symbols received from Symbol.for(...) can be passed to Client Components. ' +
`The symbol Symbol.for(${
// $FlowFixMe `description` might be undefined
value.description
}) cannot be found among global symbols.` +
describeObjectForErrorMessage(parent, key),
[RFC] Codemod invariant -> throw new Error (#22435) * Hoist error codes import to module scope When this code was written, the error codes map (`codes.json`) was created on-the-fly, so we had to lazily require from inside the visitor. Because `codes.json` is now checked into source, we can import it a single time in module scope. * Minify error constructors in production We use a script to minify our error messages in production. Each message is assigned an error code, defined in `scripts/error-codes/codes.json`. Then our build script replaces the messages with a link to our error decoder page, e.g. https://reactjs.org/docs/error-decoder.html/?invariant=92 This enables us to write helpful error messages without increasing the bundle size. Right now, the script only works for `invariant` calls. It does not work if you throw an Error object. This is an old Facebookism that we don't really need, other than the fact that our error minification script relies on it. So, I've updated the script to minify error constructors, too: Input: Error(`A ${adj} message that contains ${noun}`); Output: Error(formatProdErrorMessage(ERR_CODE, adj, noun)); It only works for constructors that are literally named Error, though we could add support for other names, too. As a next step, I will add a lint rule to enforce that errors written this way must have a corresponding error code. * Minify "no fallback UI specified" error in prod This error message wasn't being minified because it doesn't use invariant. The reason it didn't use invariant is because this particular error is created without begin thrown — it doesn't need to be thrown because it's located inside the error handling part of the runtime. Now that the error minification script supports Error constructors, we can minify it by assigning it a production error code in `scripts/error-codes/codes.json`. To support the use of Error constructors more generally, I will add a lint rule that enforces each message has a corresponding error code. * Lint rule to detect unminified errors Adds a lint rule that detects when an Error constructor is used without a corresponding production error code. We already have this for `invariant`, but not for regular errors, i.e. `throw new Error(msg)`. There's also nothing that enforces the use of `invariant` besides convention. There are some packages where we don't care to minify errors. These are packages that run in environments where bundle size is not a concern, like react-pg. I added an override in the ESLint config to ignore these. * Temporarily add invariant codemod script I'm adding this codemod to the repo temporarily, but I'll revert it in the same PR. That way we don't have to check it in but it's still accessible (via the PR) if we need it later. * [Automated] Codemod invariant -> Error This commit contains only automated changes: npx jscodeshift -t scripts/codemod-invariant.js packages --ignore-pattern="node_modules/**/*" yarn linc --fix yarn prettier I will do any manual touch ups in separate commits so they're easier to review. * Remove temporary codemod script This reverts the codemod script and ESLint config I added temporarily in order to perform the invariant codemod. * Manual touch ups A few manual changes I made after the codemod ran. * Enable error code transform per package Currently we're not consistent about which packages should have their errors minified in production and which ones should. This adds a field to the bundle configuration to control whether to apply the transform. We should decide what the criteria is going forward. I think it's probably a good idea to minify any package that gets sent over the network. So yes to modules that run in the browser, and no to modules that run on the server and during development only.
2021-10-01 03:01:28 +08:00
);
}
request.pendingChunks++;
const symbolId = request.nextChunkId++;
emitSymbolChunk(request, symbolId, name);
writtenSymbols.set(value, symbolId);
return serializeByValueID(symbolId);
}
// $FlowFixMe: bigint isn't added to Flow yet.
if (typeof value === 'bigint') {
[RFC] Codemod invariant -> throw new Error (#22435) * Hoist error codes import to module scope When this code was written, the error codes map (`codes.json`) was created on-the-fly, so we had to lazily require from inside the visitor. Because `codes.json` is now checked into source, we can import it a single time in module scope. * Minify error constructors in production We use a script to minify our error messages in production. Each message is assigned an error code, defined in `scripts/error-codes/codes.json`. Then our build script replaces the messages with a link to our error decoder page, e.g. https://reactjs.org/docs/error-decoder.html/?invariant=92 This enables us to write helpful error messages without increasing the bundle size. Right now, the script only works for `invariant` calls. It does not work if you throw an Error object. This is an old Facebookism that we don't really need, other than the fact that our error minification script relies on it. So, I've updated the script to minify error constructors, too: Input: Error(`A ${adj} message that contains ${noun}`); Output: Error(formatProdErrorMessage(ERR_CODE, adj, noun)); It only works for constructors that are literally named Error, though we could add support for other names, too. As a next step, I will add a lint rule to enforce that errors written this way must have a corresponding error code. * Minify "no fallback UI specified" error in prod This error message wasn't being minified because it doesn't use invariant. The reason it didn't use invariant is because this particular error is created without begin thrown — it doesn't need to be thrown because it's located inside the error handling part of the runtime. Now that the error minification script supports Error constructors, we can minify it by assigning it a production error code in `scripts/error-codes/codes.json`. To support the use of Error constructors more generally, I will add a lint rule that enforces each message has a corresponding error code. * Lint rule to detect unminified errors Adds a lint rule that detects when an Error constructor is used without a corresponding production error code. We already have this for `invariant`, but not for regular errors, i.e. `throw new Error(msg)`. There's also nothing that enforces the use of `invariant` besides convention. There are some packages where we don't care to minify errors. These are packages that run in environments where bundle size is not a concern, like react-pg. I added an override in the ESLint config to ignore these. * Temporarily add invariant codemod script I'm adding this codemod to the repo temporarily, but I'll revert it in the same PR. That way we don't have to check it in but it's still accessible (via the PR) if we need it later. * [Automated] Codemod invariant -> Error This commit contains only automated changes: npx jscodeshift -t scripts/codemod-invariant.js packages --ignore-pattern="node_modules/**/*" yarn linc --fix yarn prettier I will do any manual touch ups in separate commits so they're easier to review. * Remove temporary codemod script This reverts the codemod script and ESLint config I added temporarily in order to perform the invariant codemod. * Manual touch ups A few manual changes I made after the codemod ran. * Enable error code transform per package Currently we're not consistent about which packages should have their errors minified in production and which ones should. This adds a field to the bundle configuration to control whether to apply the transform. We should decide what the criteria is going forward. I think it's probably a good idea to minify any package that gets sent over the network. So yes to modules that run in the browser, and no to modules that run on the server and during development only.
2021-10-01 03:01:28 +08:00
throw new Error(
`BigInt (${value}) is not yet supported in Client Component props.` +
describeObjectForErrorMessage(parent, key),
);
}
[RFC] Codemod invariant -> throw new Error (#22435) * Hoist error codes import to module scope When this code was written, the error codes map (`codes.json`) was created on-the-fly, so we had to lazily require from inside the visitor. Because `codes.json` is now checked into source, we can import it a single time in module scope. * Minify error constructors in production We use a script to minify our error messages in production. Each message is assigned an error code, defined in `scripts/error-codes/codes.json`. Then our build script replaces the messages with a link to our error decoder page, e.g. https://reactjs.org/docs/error-decoder.html/?invariant=92 This enables us to write helpful error messages without increasing the bundle size. Right now, the script only works for `invariant` calls. It does not work if you throw an Error object. This is an old Facebookism that we don't really need, other than the fact that our error minification script relies on it. So, I've updated the script to minify error constructors, too: Input: Error(`A ${adj} message that contains ${noun}`); Output: Error(formatProdErrorMessage(ERR_CODE, adj, noun)); It only works for constructors that are literally named Error, though we could add support for other names, too. As a next step, I will add a lint rule to enforce that errors written this way must have a corresponding error code. * Minify "no fallback UI specified" error in prod This error message wasn't being minified because it doesn't use invariant. The reason it didn't use invariant is because this particular error is created without begin thrown — it doesn't need to be thrown because it's located inside the error handling part of the runtime. Now that the error minification script supports Error constructors, we can minify it by assigning it a production error code in `scripts/error-codes/codes.json`. To support the use of Error constructors more generally, I will add a lint rule that enforces each message has a corresponding error code. * Lint rule to detect unminified errors Adds a lint rule that detects when an Error constructor is used without a corresponding production error code. We already have this for `invariant`, but not for regular errors, i.e. `throw new Error(msg)`. There's also nothing that enforces the use of `invariant` besides convention. There are some packages where we don't care to minify errors. These are packages that run in environments where bundle size is not a concern, like react-pg. I added an override in the ESLint config to ignore these. * Temporarily add invariant codemod script I'm adding this codemod to the repo temporarily, but I'll revert it in the same PR. That way we don't have to check it in but it's still accessible (via the PR) if we need it later. * [Automated] Codemod invariant -> Error This commit contains only automated changes: npx jscodeshift -t scripts/codemod-invariant.js packages --ignore-pattern="node_modules/**/*" yarn linc --fix yarn prettier I will do any manual touch ups in separate commits so they're easier to review. * Remove temporary codemod script This reverts the codemod script and ESLint config I added temporarily in order to perform the invariant codemod. * Manual touch ups A few manual changes I made after the codemod ran. * Enable error code transform per package Currently we're not consistent about which packages should have their errors minified in production and which ones should. This adds a field to the bundle configuration to control whether to apply the transform. We should decide what the criteria is going forward. I think it's probably a good idea to minify any package that gets sent over the network. So yes to modules that run in the browser, and no to modules that run on the server and during development only.
2021-10-01 03:01:28 +08:00
throw new Error(
`Type ${typeof value} is not supported in Client Component props.` +
describeObjectForErrorMessage(parent, key),
);
}
function logRecoverableError(request: Request, error: mixed): string {
const onError = request.onError;
const errorDigest = onError(error);
if (errorDigest != null && typeof errorDigest !== 'string') {
// eslint-disable-next-line react-internal/prod-error-codes
throw new Error(
`onError returned something with a type other than "string". onError should return a string and may return null or undefined but must not return anything else. It received something of type "${typeof errorDigest}" instead`,
);
}
return errorDigest || '';
}
function getErrorMessageAndStackDev(
error: mixed,
): {message: string, stack: string} {
if (__DEV__) {
let message;
let stack = '';
try {
if (error instanceof Error) {
// eslint-disable-next-line react-internal/safe-string-coercion
message = String(error.message);
// eslint-disable-next-line react-internal/safe-string-coercion
stack = String(error.stack);
} else {
message = 'Error: ' + (error: any);
}
} catch (x) {
message = 'An error occurred but serializing the error message failed.';
}
return {
message,
stack,
};
} else {
// These errors should never make it into a build so we don't need to encode them in codes.json
// eslint-disable-next-line react-internal/prod-error-codes
throw new Error(
'getErrorMessageAndStackDev should never be called from production mode. This is a bug in React.',
);
}
}
function fatalError(request: Request, error: mixed): void {
// This is called outside error handling code such as if an error happens in React internals.
if (request.destination !== null) {
request.status = CLOSED;
closeWithError(request.destination, error);
} else {
request.status = CLOSING;
request.fatalError = error;
}
}
function emitErrorChunkProd(
request: Request,
id: number,
digest: string,
): void {
const processedChunk = processErrorChunkProd(request, id, digest);
request.completedErrorChunks.push(processedChunk);
}
function emitErrorChunkDev(
request: Request,
id: number,
digest: string,
message: string,
stack: string,
): void {
const processedChunk = processErrorChunkDev(
request,
id,
digest,
message,
stack,
);
request.completedErrorChunks.push(processedChunk);
}
[Flight] Add support for Module References in transport protocol (#20121) * Refactor Flight to require a module reference to be brand checked This exposes a host environment (bundler) specific hook to check if an object is a module reference. This will be used so that they can be passed directly into Flight without needing additional wrapper objects. * Emit module references as a special type of value We already have JSON and errors as special types of "rows". This encodes module references as a special type of row value. This was always the intention because it allows those values to be emitted first in the stream so that as a large models stream down, we can start preloading as early as possible. We preload the module when they resolve but we lazily require them as they are referenced. * Emit module references where ever they occur This emits module references where ever they occur. In blocks or even directly in elements. * Don't special case the root row I originally did this so that a simple stream is also just plain JSON. However, since we might want to emit things like modules before the root module in the stream, this gets unnecessarily complicated. We could add this back as a special case if it's the first byte written but meh. * Update the protocol * Add test for using a module reference as a client component * Relax element type check Since Flight now accepts a module reference as returned by any bundler system, depending on the renderer running. We need to drastically relax the check to include all of them. We can add more as we discover them. * Move flow annotation Seems like our compiler is not happy with stripping this. * Some bookkeeping bug * Can't use the private field to check
2020-10-30 08:57:31 +08:00
function emitModuleChunk(
request: Request,
id: number,
moduleMetaData: ModuleMetaData,
): void {
const processedChunk = processModuleChunk(request, id, moduleMetaData);
request.completedModuleChunks.push(processedChunk);
}
function emitSymbolChunk(request: Request, id: number, name: string): void {
const processedChunk = processSymbolChunk(request, id, name);
request.completedModuleChunks.push(processedChunk);
}
[ServerContext] Flight support for ServerContext (#23244) * Flight side of server context * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * reinline * rebase * add back changes lost due to rebase being hard * emit chunk for provider * remove case for React provider type * update type for SomeChunk * enable flag with experimental * add missing types * fix flow type * missing type * t: any * revert extraneous type change * better type * better type * feedback * change import to type import * test? * test? * remove react-dom * remove react-native-renderer from react-server-native-relay/package.json * gate change in FiberNewContext, getComponentNameFromType, use switch statement in FlightServer * getComponentNameFromTpe: server context type gated and use displayName if available * fallthrough * lint.... * POP * lint
2022-03-08 20:55:32 +08:00
function emitProviderChunk(
request: Request,
id: number,
contextName: string,
): void {
const processedChunk = processProviderChunk(request, id, contextName);
request.completedJSONChunks.push(processedChunk);
}
function retryTask(request: Request, task: Task): void {
if (task.status !== PENDING) {
// We completed this by other means before we had a chance to retry it.
return;
}
switchContext(task.context);
try {
let value = task.model;
if (
typeof value === 'object' &&
value !== null &&
[ServerContext] Flight support for ServerContext (#23244) * Flight side of server context * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * reinline * rebase * add back changes lost due to rebase being hard * emit chunk for provider * remove case for React provider type * update type for SomeChunk * enable flag with experimental * add missing types * fix flow type * missing type * t: any * revert extraneous type change * better type * better type * feedback * change import to type import * test? * test? * remove react-dom * remove react-native-renderer from react-server-native-relay/package.json * gate change in FiberNewContext, getComponentNameFromType, use switch statement in FlightServer * getComponentNameFromTpe: server context type gated and use displayName if available * fallthrough * lint.... * POP * lint
2022-03-08 20:55:32 +08:00
(value: any).$$typeof === REACT_ELEMENT_TYPE
) {
// TODO: Concatenate keys of parents onto children.
const element: React$Element<any> = (value: any);
// When retrying a component, reuse the thenableState from the
// previous attempt.
const prevThenableState = task.thenableState;
// Attempt to render the Server Component.
// Doing this here lets us reuse this same task if the next component
// also suspends.
task.model = value;
value = attemptResolveElement(
element.type,
element.key,
element.ref,
element.props,
prevThenableState,
);
// Successfully finished this component. We're going to keep rendering
// using the same task, but we reset its thenable state before continuing.
task.thenableState = null;
// Keep rendering and reuse the same task. This inner loop is separate
// from the render above because we don't need to reset the thenable state
// until the next time something suspends and retries.
while (
typeof value === 'object' &&
value !== null &&
(value: any).$$typeof === REACT_ELEMENT_TYPE
) {
// TODO: Concatenate keys of parents onto children.
const nextElement: React$Element<any> = (value: any);
task.model = value;
value = attemptResolveElement(
nextElement.type,
nextElement.key,
nextElement.ref,
nextElement.props,
null,
);
}
}
const processedChunk = processModelChunk(request, task.id, value);
request.completedJSONChunks.push(processedChunk);
request.abortableTasks.delete(task);
task.status = COMPLETED;
} catch (x) {
if (typeof x === 'object' && x !== null && typeof x.then === 'function') {
// Something suspended again, let's pick it back up later.
const ping = task.ping;
x.then(ping, ping);
const wakeable: Wakeable = x;
trackSuspendedWakeable(wakeable);
task.thenableState = getThenableStateAfterSuspending();
return;
} else {
request.abortableTasks.delete(task);
task.status = ERRORED;
const digest = logRecoverableError(request, x);
if (__DEV__) {
const {message, stack} = getErrorMessageAndStackDev(x);
emitErrorChunkDev(request, task.id, digest, message, stack);
} else {
emitErrorChunkProd(request, task.id, digest);
}
}
}
}
function performWork(request: Request): void {
const prevDispatcher = ReactCurrentDispatcher.current;
const prevCacheDispatcher = ReactCurrentCache.current;
[ServerContext] Flight support for ServerContext (#23244) * Flight side of server context * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * reinline * rebase * add back changes lost due to rebase being hard * emit chunk for provider * remove case for React provider type * update type for SomeChunk * enable flag with experimental * add missing types * fix flow type * missing type * t: any * revert extraneous type change * better type * better type * feedback * change import to type import * test? * test? * remove react-dom * remove react-native-renderer from react-server-native-relay/package.json * gate change in FiberNewContext, getComponentNameFromType, use switch statement in FlightServer * getComponentNameFromTpe: server context type gated and use displayName if available * fallthrough * lint.... * POP * lint
2022-03-08 20:55:32 +08:00
const prevCache = getCurrentCache();
ReactCurrentDispatcher.current = HooksDispatcher;
ReactCurrentCache.current = DefaultCacheDispatcher;
[ServerContext] Flight support for ServerContext (#23244) * Flight side of server context * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * reinline * rebase * add back changes lost due to rebase being hard * emit chunk for provider * remove case for React provider type * update type for SomeChunk * enable flag with experimental * add missing types * fix flow type * missing type * t: any * revert extraneous type change * better type * better type * feedback * change import to type import * test? * test? * remove react-dom * remove react-native-renderer from react-server-native-relay/package.json * gate change in FiberNewContext, getComponentNameFromType, use switch statement in FlightServer * getComponentNameFromTpe: server context type gated and use displayName if available * fallthrough * lint.... * POP * lint
2022-03-08 20:55:32 +08:00
setCurrentCache(request.cache);
prepareToUseHooksForRequest(request);
try {
const pingedTasks = request.pingedTasks;
request.pingedTasks = [];
for (let i = 0; i < pingedTasks.length; i++) {
const task = pingedTasks[i];
retryTask(request, task);
}
if (request.destination !== null) {
flushCompletedChunks(request, request.destination);
}
} catch (error) {
Add onRecoverableError option to hydrateRoot, createRoot (#23207) * [RFC] Add onHydrationError option to hydrateRoot This is not the final API but I'm pushing it for discussion purposes. When an error is thrown during hydration, we fallback to client rendering, without triggering an error boundary. This is good because, in many cases, the UI will recover and the user won't even notice that something has gone wrong behind the scenes. However, we shouldn't recover from these errors silently, because the underlying cause might be pretty serious. Server-client mismatches are not supposed to happen, even if UI doesn't break from the users perspective. Ignoring them could lead to worse problems later. De-opting from server to client rendering could also be a significant performance regression, depending on the scope of the UI it affects. So we need a way to log when hydration errors occur. This adds a new option for `hydrateRoot` called `onHydrationError`. It's symmetrical to the server renderer's `onError` option, and serves the same purpose. When no option is provided, the default behavior is to schedule a browser task and rethrow the error. This will trigger the normal browser behavior for errors, including dispatching an error event. If the app already has error monitoring, this likely will just work as expected without additional configuration. However, we can also expose additional metadata about these errors, like which Suspense boundaries were affected by the de-opt to client rendering. (I have not exposed any metadata in this commit; API needs more design work.) There are other situations besides hydration where we recover from an error without surfacing it to the user, or notifying an error boundary. For example, if an error occurs during a concurrent render, it could be due to a data race, so we try again synchronously in case that fixes it. We should probably expose a way to log these types of errors, too. (Also not implemented in this commit.) * Log all recoverable errors This expands the scope of onHydrationError to include all errors that are not surfaced to the UI (an error boundary). In addition to errors that occur during hydration, this also includes errors that recoverable by de-opting to synchronous rendering. Typically (or really, by definition) these errors are the result of a concurrent data race; blocking the main thread fixes them by prevents subsequent races. The logic for de-opting to synchronous rendering already existed. The only thing that has changed is that we now log the errors instead of silently proceeding. The logging API has been renamed from onHydrationError to onRecoverableError. * Don't log recoverable errors until commit phase If the render is interrupted and restarts, we don't want to log the errors multiple times. This change only affects errors that are recovered by de-opting to synchronous rendering; we'll have to do something else for errors during hydration, since they use a different recovery path. * Only log hydration error if client render succeeds Similar to previous step. When an error occurs during hydration, we only want to log it if falling back to client rendering _succeeds_. If client rendering fails, the error will get reported to the nearest error boundary, so there's no need for a duplicate log. To implement this, I added a list of errors to the hydration context. If the Suspense boundary successfully completes, they are added to the main recoverable errors queue (the one I added in the previous step.) * Log error with queueMicrotask instead of Scheduler If onRecoverableError is not provided, we default to rethrowing the error in a separate task. Originally, I scheduled the task with idle priority, but @sebmarkbage made the good point that if there are multiple errors logs, we want to preserve the original order. So I've switched it to a microtask. The priority can be lowered in userspace by scheduling an additional task inside onRecoverableError. * Only use host config method for default behavior Redefines the contract of the host config's logRecoverableError method to be a default implementation for onRecoverableError if a user-provided one is not provided when the root is created. * Log with reportError instead of rethrowing In modern browsers, reportError will dispatch an error event, emulating an uncaught JavaScript error. We can do this instead of rethrowing recoverable errors in a microtask, which is nice because it avoids any subtle ordering issues. In older browsers and test environments, we'll fall back to console.error. * Naming nits queueRecoverableHydrationErrors -> upgradeHydrationErrorsToRecoverable
2022-02-04 23:57:33 +08:00
logRecoverableError(request, error);
fatalError(request, error);
} finally {
ReactCurrentDispatcher.current = prevDispatcher;
ReactCurrentCache.current = prevCacheDispatcher;
[ServerContext] Flight support for ServerContext (#23244) * Flight side of server context * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * reinline * rebase * add back changes lost due to rebase being hard * emit chunk for provider * remove case for React provider type * update type for SomeChunk * enable flag with experimental * add missing types * fix flow type * missing type * t: any * revert extraneous type change * better type * better type * feedback * change import to type import * test? * test? * remove react-dom * remove react-native-renderer from react-server-native-relay/package.json * gate change in FiberNewContext, getComponentNameFromType, use switch statement in FlightServer * getComponentNameFromTpe: server context type gated and use displayName if available * fallthrough * lint.... * POP * lint
2022-03-08 20:55:32 +08:00
setCurrentCache(prevCache);
resetHooksForRequest();
}
}
function abortTask(task: Task, request: Request, errorId: number): void {
task.status = ABORTED;
// Instead of emitting an error per task.id, we emit a model that only
// has a single value referencing the error.
const ref = serializeByValueID(errorId);
const processedChunk = processReferenceChunk(request, task.id, ref);
request.completedErrorChunks.push(processedChunk);
}
function flushCompletedChunks(
request: Request,
destination: Destination,
): void {
beginWriting(destination);
try {
[Flight] Add support for Module References in transport protocol (#20121) * Refactor Flight to require a module reference to be brand checked This exposes a host environment (bundler) specific hook to check if an object is a module reference. This will be used so that they can be passed directly into Flight without needing additional wrapper objects. * Emit module references as a special type of value We already have JSON and errors as special types of "rows". This encodes module references as a special type of row value. This was always the intention because it allows those values to be emitted first in the stream so that as a large models stream down, we can start preloading as early as possible. We preload the module when they resolve but we lazily require them as they are referenced. * Emit module references where ever they occur This emits module references where ever they occur. In blocks or even directly in elements. * Don't special case the root row I originally did this so that a simple stream is also just plain JSON. However, since we might want to emit things like modules before the root module in the stream, this gets unnecessarily complicated. We could add this back as a special case if it's the first byte written but meh. * Update the protocol * Add test for using a module reference as a client component * Relax element type check Since Flight now accepts a module reference as returned by any bundler system, depending on the renderer running. We need to drastically relax the check to include all of them. We can add more as we discover them. * Move flow annotation Seems like our compiler is not happy with stripping this. * Some bookkeeping bug * Can't use the private field to check
2020-10-30 08:57:31 +08:00
// We emit module chunks first in the stream so that
// they can be preloaded as early as possible.
const moduleChunks = request.completedModuleChunks;
let i = 0;
[Flight] Add support for Module References in transport protocol (#20121) * Refactor Flight to require a module reference to be brand checked This exposes a host environment (bundler) specific hook to check if an object is a module reference. This will be used so that they can be passed directly into Flight without needing additional wrapper objects. * Emit module references as a special type of value We already have JSON and errors as special types of "rows". This encodes module references as a special type of row value. This was always the intention because it allows those values to be emitted first in the stream so that as a large models stream down, we can start preloading as early as possible. We preload the module when they resolve but we lazily require them as they are referenced. * Emit module references where ever they occur This emits module references where ever they occur. In blocks or even directly in elements. * Don't special case the root row I originally did this so that a simple stream is also just plain JSON. However, since we might want to emit things like modules before the root module in the stream, this gets unnecessarily complicated. We could add this back as a special case if it's the first byte written but meh. * Update the protocol * Add test for using a module reference as a client component * Relax element type check Since Flight now accepts a module reference as returned by any bundler system, depending on the renderer running. We need to drastically relax the check to include all of them. We can add more as we discover them. * Move flow annotation Seems like our compiler is not happy with stripping this. * Some bookkeeping bug * Can't use the private field to check
2020-10-30 08:57:31 +08:00
for (; i < moduleChunks.length; i++) {
request.pendingChunks--;
const chunk = moduleChunks[i];
const keepWriting: boolean = writeChunkAndReturn(destination, chunk);
if (!keepWriting) {
request.destination = null;
[Flight] Add support for Module References in transport protocol (#20121) * Refactor Flight to require a module reference to be brand checked This exposes a host environment (bundler) specific hook to check if an object is a module reference. This will be used so that they can be passed directly into Flight without needing additional wrapper objects. * Emit module references as a special type of value We already have JSON and errors as special types of "rows". This encodes module references as a special type of row value. This was always the intention because it allows those values to be emitted first in the stream so that as a large models stream down, we can start preloading as early as possible. We preload the module when they resolve but we lazily require them as they are referenced. * Emit module references where ever they occur This emits module references where ever they occur. In blocks or even directly in elements. * Don't special case the root row I originally did this so that a simple stream is also just plain JSON. However, since we might want to emit things like modules before the root module in the stream, this gets unnecessarily complicated. We could add this back as a special case if it's the first byte written but meh. * Update the protocol * Add test for using a module reference as a client component * Relax element type check Since Flight now accepts a module reference as returned by any bundler system, depending on the renderer running. We need to drastically relax the check to include all of them. We can add more as we discover them. * Move flow annotation Seems like our compiler is not happy with stripping this. * Some bookkeeping bug * Can't use the private field to check
2020-10-30 08:57:31 +08:00
i++;
break;
}
}
moduleChunks.splice(0, i);
[Flight] Add support for Module References in transport protocol (#20121) * Refactor Flight to require a module reference to be brand checked This exposes a host environment (bundler) specific hook to check if an object is a module reference. This will be used so that they can be passed directly into Flight without needing additional wrapper objects. * Emit module references as a special type of value We already have JSON and errors as special types of "rows". This encodes module references as a special type of row value. This was always the intention because it allows those values to be emitted first in the stream so that as a large models stream down, we can start preloading as early as possible. We preload the module when they resolve but we lazily require them as they are referenced. * Emit module references where ever they occur This emits module references where ever they occur. In blocks or even directly in elements. * Don't special case the root row I originally did this so that a simple stream is also just plain JSON. However, since we might want to emit things like modules before the root module in the stream, this gets unnecessarily complicated. We could add this back as a special case if it's the first byte written but meh. * Update the protocol * Add test for using a module reference as a client component * Relax element type check Since Flight now accepts a module reference as returned by any bundler system, depending on the renderer running. We need to drastically relax the check to include all of them. We can add more as we discover them. * Move flow annotation Seems like our compiler is not happy with stripping this. * Some bookkeeping bug * Can't use the private field to check
2020-10-30 08:57:31 +08:00
// Next comes model data.
const jsonChunks = request.completedJSONChunks;
i = 0;
for (; i < jsonChunks.length; i++) {
request.pendingChunks--;
const chunk = jsonChunks[i];
const keepWriting: boolean = writeChunkAndReturn(destination, chunk);
if (!keepWriting) {
request.destination = null;
i++;
break;
}
}
jsonChunks.splice(0, i);
[Flight] Add support for Module References in transport protocol (#20121) * Refactor Flight to require a module reference to be brand checked This exposes a host environment (bundler) specific hook to check if an object is a module reference. This will be used so that they can be passed directly into Flight without needing additional wrapper objects. * Emit module references as a special type of value We already have JSON and errors as special types of "rows". This encodes module references as a special type of row value. This was always the intention because it allows those values to be emitted first in the stream so that as a large models stream down, we can start preloading as early as possible. We preload the module when they resolve but we lazily require them as they are referenced. * Emit module references where ever they occur This emits module references where ever they occur. In blocks or even directly in elements. * Don't special case the root row I originally did this so that a simple stream is also just plain JSON. However, since we might want to emit things like modules before the root module in the stream, this gets unnecessarily complicated. We could add this back as a special case if it's the first byte written but meh. * Update the protocol * Add test for using a module reference as a client component * Relax element type check Since Flight now accepts a module reference as returned by any bundler system, depending on the renderer running. We need to drastically relax the check to include all of them. We can add more as we discover them. * Move flow annotation Seems like our compiler is not happy with stripping this. * Some bookkeeping bug * Can't use the private field to check
2020-10-30 08:57:31 +08:00
// Finally, errors are sent. The idea is that it's ok to delay
// any error messages and prioritize display of other parts of
// the page.
const errorChunks = request.completedErrorChunks;
i = 0;
for (; i < errorChunks.length; i++) {
request.pendingChunks--;
const chunk = errorChunks[i];
const keepWriting: boolean = writeChunkAndReturn(destination, chunk);
if (!keepWriting) {
request.destination = null;
i++;
break;
}
}
errorChunks.splice(0, i);
} finally {
completeWriting(destination);
}
flushBuffered(destination);
if (request.pendingChunks === 0) {
// We're done.
close(destination);
}
}
export function startWork(request: Request): void {
scheduleWork(() => performWork(request));
}
export function startFlowing(request: Request, destination: Destination): void {
if (request.status === CLOSING) {
request.status = CLOSED;
closeWithError(destination, request.fatalError);
return;
}
if (request.status === CLOSED) {
return;
}
if (request.destination !== null) {
// We're already flowing.
return;
}
request.destination = destination;
try {
flushCompletedChunks(request, destination);
} catch (error) {
Add onRecoverableError option to hydrateRoot, createRoot (#23207) * [RFC] Add onHydrationError option to hydrateRoot This is not the final API but I'm pushing it for discussion purposes. When an error is thrown during hydration, we fallback to client rendering, without triggering an error boundary. This is good because, in many cases, the UI will recover and the user won't even notice that something has gone wrong behind the scenes. However, we shouldn't recover from these errors silently, because the underlying cause might be pretty serious. Server-client mismatches are not supposed to happen, even if UI doesn't break from the users perspective. Ignoring them could lead to worse problems later. De-opting from server to client rendering could also be a significant performance regression, depending on the scope of the UI it affects. So we need a way to log when hydration errors occur. This adds a new option for `hydrateRoot` called `onHydrationError`. It's symmetrical to the server renderer's `onError` option, and serves the same purpose. When no option is provided, the default behavior is to schedule a browser task and rethrow the error. This will trigger the normal browser behavior for errors, including dispatching an error event. If the app already has error monitoring, this likely will just work as expected without additional configuration. However, we can also expose additional metadata about these errors, like which Suspense boundaries were affected by the de-opt to client rendering. (I have not exposed any metadata in this commit; API needs more design work.) There are other situations besides hydration where we recover from an error without surfacing it to the user, or notifying an error boundary. For example, if an error occurs during a concurrent render, it could be due to a data race, so we try again synchronously in case that fixes it. We should probably expose a way to log these types of errors, too. (Also not implemented in this commit.) * Log all recoverable errors This expands the scope of onHydrationError to include all errors that are not surfaced to the UI (an error boundary). In addition to errors that occur during hydration, this also includes errors that recoverable by de-opting to synchronous rendering. Typically (or really, by definition) these errors are the result of a concurrent data race; blocking the main thread fixes them by prevents subsequent races. The logic for de-opting to synchronous rendering already existed. The only thing that has changed is that we now log the errors instead of silently proceeding. The logging API has been renamed from onHydrationError to onRecoverableError. * Don't log recoverable errors until commit phase If the render is interrupted and restarts, we don't want to log the errors multiple times. This change only affects errors that are recovered by de-opting to synchronous rendering; we'll have to do something else for errors during hydration, since they use a different recovery path. * Only log hydration error if client render succeeds Similar to previous step. When an error occurs during hydration, we only want to log it if falling back to client rendering _succeeds_. If client rendering fails, the error will get reported to the nearest error boundary, so there's no need for a duplicate log. To implement this, I added a list of errors to the hydration context. If the Suspense boundary successfully completes, they are added to the main recoverable errors queue (the one I added in the previous step.) * Log error with queueMicrotask instead of Scheduler If onRecoverableError is not provided, we default to rethrowing the error in a separate task. Originally, I scheduled the task with idle priority, but @sebmarkbage made the good point that if there are multiple errors logs, we want to preserve the original order. So I've switched it to a microtask. The priority can be lowered in userspace by scheduling an additional task inside onRecoverableError. * Only use host config method for default behavior Redefines the contract of the host config's logRecoverableError method to be a default implementation for onRecoverableError if a user-provided one is not provided when the root is created. * Log with reportError instead of rethrowing In modern browsers, reportError will dispatch an error event, emulating an uncaught JavaScript error. We can do this instead of rethrowing recoverable errors in a microtask, which is nice because it avoids any subtle ordering issues. In older browsers and test environments, we'll fall back to console.error. * Naming nits queueRecoverableHydrationErrors -> upgradeHydrationErrorsToRecoverable
2022-02-04 23:57:33 +08:00
logRecoverableError(request, error);
fatalError(request, error);
}
}
// This is called to early terminate a request. It creates an error at all pending tasks.
export function abort(request: Request, reason: mixed): void {
try {
const abortableTasks = request.abortableTasks;
if (abortableTasks.size > 0) {
// We have tasks to abort. We'll emit one error row and then emit a reference
// to that row from every row that's still remaining.
const error =
reason === undefined
? new Error('The render was aborted by the server without a reason.')
: reason;
const digest = logRecoverableError(request, error);
request.pendingChunks++;
const errorId = request.nextChunkId++;
if (__DEV__) {
const {message, stack} = getErrorMessageAndStackDev(error);
emitErrorChunkDev(request, errorId, digest, message, stack);
} else {
emitErrorChunkProd(request, errorId, digest);
}
abortableTasks.forEach(task => abortTask(task, request, errorId));
abortableTasks.clear();
}
if (request.destination !== null) {
flushCompletedChunks(request, request.destination);
}
} catch (error) {
logRecoverableError(request, error);
fatalError(request, error);
}
}
[ServerContext] Flight support for ServerContext (#23244) * Flight side of server context * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * reinline * rebase * add back changes lost due to rebase being hard * emit chunk for provider * remove case for React provider type * update type for SomeChunk * enable flag with experimental * add missing types * fix flow type * missing type * t: any * revert extraneous type change * better type * better type * feedback * change import to type import * test? * test? * remove react-dom * remove react-native-renderer from react-server-native-relay/package.json * gate change in FiberNewContext, getComponentNameFromType, use switch statement in FlightServer * getComponentNameFromTpe: server context type gated and use displayName if available * fallthrough * lint.... * POP * lint
2022-03-08 20:55:32 +08:00
function importServerContexts(
contexts?: Array<[string, ServerContextJSONValue]>,
) {
if (contexts) {
const prevContext = getActiveContext();
switchContext(rootContextSnapshot);
for (let i = 0; i < contexts.length; i++) {
const [name, value] = contexts[i];
const context = getOrCreateServerContext(name);
pushProvider(context, value);
}
const importedContext = getActiveContext();
switchContext(prevContext);
return importedContext;
[RFC] Codemod invariant -> throw new Error (#22435) * Hoist error codes import to module scope When this code was written, the error codes map (`codes.json`) was created on-the-fly, so we had to lazily require from inside the visitor. Because `codes.json` is now checked into source, we can import it a single time in module scope. * Minify error constructors in production We use a script to minify our error messages in production. Each message is assigned an error code, defined in `scripts/error-codes/codes.json`. Then our build script replaces the messages with a link to our error decoder page, e.g. https://reactjs.org/docs/error-decoder.html/?invariant=92 This enables us to write helpful error messages without increasing the bundle size. Right now, the script only works for `invariant` calls. It does not work if you throw an Error object. This is an old Facebookism that we don't really need, other than the fact that our error minification script relies on it. So, I've updated the script to minify error constructors, too: Input: Error(`A ${adj} message that contains ${noun}`); Output: Error(formatProdErrorMessage(ERR_CODE, adj, noun)); It only works for constructors that are literally named Error, though we could add support for other names, too. As a next step, I will add a lint rule to enforce that errors written this way must have a corresponding error code. * Minify "no fallback UI specified" error in prod This error message wasn't being minified because it doesn't use invariant. The reason it didn't use invariant is because this particular error is created without begin thrown — it doesn't need to be thrown because it's located inside the error handling part of the runtime. Now that the error minification script supports Error constructors, we can minify it by assigning it a production error code in `scripts/error-codes/codes.json`. To support the use of Error constructors more generally, I will add a lint rule that enforces each message has a corresponding error code. * Lint rule to detect unminified errors Adds a lint rule that detects when an Error constructor is used without a corresponding production error code. We already have this for `invariant`, but not for regular errors, i.e. `throw new Error(msg)`. There's also nothing that enforces the use of `invariant` besides convention. There are some packages where we don't care to minify errors. These are packages that run in environments where bundle size is not a concern, like react-pg. I added an override in the ESLint config to ignore these. * Temporarily add invariant codemod script I'm adding this codemod to the repo temporarily, but I'll revert it in the same PR. That way we don't have to check it in but it's still accessible (via the PR) if we need it later. * [Automated] Codemod invariant -> Error This commit contains only automated changes: npx jscodeshift -t scripts/codemod-invariant.js packages --ignore-pattern="node_modules/**/*" yarn linc --fix yarn prettier I will do any manual touch ups in separate commits so they're easier to review. * Remove temporary codemod script This reverts the codemod script and ESLint config I added temporarily in order to perform the invariant codemod. * Manual touch ups A few manual changes I made after the codemod ran. * Enable error code transform per package Currently we're not consistent about which packages should have their errors minified in production and which ones should. This adds a field to the bundle configuration to control whether to apply the transform. We should decide what the criteria is going forward. I think it's probably a good idea to minify any package that gets sent over the network. So yes to modules that run in the browser, and no to modules that run on the server and during development only.
2021-10-01 03:01:28 +08:00
}
[ServerContext] Flight support for ServerContext (#23244) * Flight side of server context * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * 1 more test * rm unused function * flow+prettier * flow again =) * duplicate ReactServerContext across packages * store default value when lazily initializing server context * . * better comment * derp... missing import * rm optional chaining * missed feature flag * React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ?? * add warning if non ServerContext passed into useServerContext * pass context in as array of arrays * make importServerContext nott pollute the global context state * merge main * remove useServerContext * dont rely on object getters in ReactServerContext and disallow JSX * add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry * gate test case as experimental * feedback * remove unions * Lint * fix oopsies (tests/lint/mismatching arguments/signatures * lint again * replace-fork * remove extraneous change * rebase * reinline * rebase * add back changes lost due to rebase being hard * emit chunk for provider * remove case for React provider type * update type for SomeChunk * enable flag with experimental * add missing types * fix flow type * missing type * t: any * revert extraneous type change * better type * better type * feedback * change import to type import * test? * test? * remove react-dom * remove react-native-renderer from react-server-native-relay/package.json * gate change in FiberNewContext, getComponentNameFromType, use switch statement in FlightServer * getComponentNameFromTpe: server context type gated and use displayName if available * fallthrough * lint.... * POP * lint
2022-03-08 20:55:32 +08:00
return rootContextSnapshot;
}