[noop] Typecheck `react-noop-renderer` against host config and renderer API (#35944)
Sebastian "Sebbie" Silbermann committed
Mar 4, 2026 at 13:52 UTC
5e4279134dbc29116407a5ec515e74e2c0ae5018
21 files changed
+782
-65
packages/react-client/flight.js
+7
@@ -7,4 +7,11 @@
7
* @flow
8
*/
9
10
+import typeof * as FlightClientAPI from './src/ReactFlightClient';
11
+import typeof * as HostConfig from './src/ReactFlightClientConfig';
12
+
13
export * from './src/ReactFlightClient';
14
+
15
+// At build time, this module is wrapped as a factory function ($$$reconciler).
16
+// Consumers pass a host config object and get back the Flight client API.
17
+declare export default (hostConfig: HostConfig) => FlightClientAPI;
packages/react-client/src/forks/ReactFlightClientConfig.noop.js
new
+57
@@ -0,0 +1,57 @@
1
+/**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow
8
+ */
9
+
10
+// This is a host config that's used for the internal `react-noop-renderer` package.
11
+//
12
+// Its API lets you pass the host config as an argument.
13
+// However, inside the `react-server` we treat host config as a module.
14
+// This file is a shim between two worlds.
15
+//
16
+// It works because the `react-server` bundle is wrapped in something like:
17
+//
18
+// module.exports = function ($$$config) {
19
+// /* renderer code */
20
+// }
21
+//
22
+// So `$$$config` looks like a global variable, but it's
23
+// really an argument to a top-level wrapping function.
24
+
25
+declare const $$$config: $FlowFixMe;
26
+
27
+export opaque type ModuleLoading = mixed;
28
+export opaque type ServerConsumerModuleMap = mixed;
29
+export opaque type ServerManifest = mixed;
30
+export opaque type ServerReferenceId = string;
31
+export opaque type ClientReferenceMetadata = mixed;
32
+export opaque type ClientReference<T> = mixed; // eslint-disable-line no-unused-vars
33
+export const resolveClientReference = $$$config.resolveClientReference;
34
+export const resolveServerReference = $$$config.resolveServerReference;
35
+export const preloadModule = $$$config.preloadModule;
36
+export const requireModule = $$$config.requireModule;
37
+export const getModuleDebugInfo = $$$config.getModuleDebugInfo;
38
+export const dispatchHint = $$$config.dispatchHint;
39
+export const prepareDestinationForModule =
40
+ $$$config.prepareDestinationForModule;
41
+export const usedWithSSR = true;
42
+
43
+export opaque type Source = mixed;
44
+
45
+export opaque type StringDecoder = mixed;
46
+
47
+export const createStringDecoder = $$$config.createStringDecoder;
48
+export const readPartialStringChunk = $$$config.readPartialStringChunk;
49
+export const readFinalStringChunk = $$$config.readFinalStringChunk;
50
+
51
+export const bindToConsole = $$$config.bindToConsole;
52
+
53
+export const rendererVersion = $$$config.rendererVersion;
54
+export const rendererPackageName = $$$config.rendererPackageName;
55
+
56
+export const checkEvalAvailabilityOnceDev =
57
+ $$$config.checkEvalAvailabilityOnceDev;
packages/react-noop-renderer/src/ReactFiberConfigNoop.js
new
+33
@@ -0,0 +1,33 @@
1
+/**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow
8
+ */
9
+
10
+export type HostContext = Object;
11
+
12
+export type TextInstance = {
13
+ text: string,
14
+ id: number,
15
+ parent: number,
16
+ hidden: boolean,
17
+ context: HostContext,
18
+};
19
+
20
+export type Instance = {
21
+ type: string,
22
+ id: number,
23
+ parent: number,
24
+ children: Array<Instance | TextInstance>,
25
+ text: string | null,
26
+ prop: any,
27
+ hidden: boolean,
28
+ context: HostContext,
29
+};
30
+
31
+export type PublicInstance = Instance;
32
+
33
+export type TransitionStatus = mixed;
packages/react-noop-renderer/src/ReactNoop.js
+1
@@ -53,6 +53,7 @@ export const {
53
getRoot,
54
// TODO: Remove this after callers migrate to alternatives.
55
unstable_runWithPriority,
56
+ // $FlowFixMe[signature-verification-failure]
57
} = createReactNoop(
58
ReactFiberReconciler, // reconciler
59
true, // useMutation
packages/react-noop-renderer/src/ReactNoopFlightClient.js
+14
-2
@@ -14,6 +14,7 @@
14
* environment.
15
*/
16
17
+import type {Thenable} from 'shared/ReactTypes';
18
import type {FindSourceMapURLCallback} from 'react-client/flight';
19
20
import {readModule} from 'react-noop-renderer/flight-modules';
@@ -25,6 +26,7 @@ type Source = Array<Uint8Array>;
26
const decoderOptions = {stream: true};
27
28
const {createResponse, createStreamState, processBinaryChunk, getRoot, close} =
29
+ // $FlowFixMe[prop-missing]
30
ReactFlightClient({
31
createStringDecoder() {
32
return new TextDecoder();
@@ -44,6 +46,7 @@ const {createResponse, createStreamState, processBinaryChunk, getRoot, close} =
46
return readModule(idx);
47
},
48
bindToConsole(methodName, args, badgeName) {
49
+ // $FlowFixMe[incompatible-call]
50
return Function.prototype.bind.apply(
51
// eslint-disable-next-line react-internal/no-production-logging
52
console[methodName],
@@ -61,8 +64,10 @@ type ReadOptions = {|
64
65
function read<T>(source: Source, options: ReadOptions): Thenable<T> {
66
const response = createResponse(
67
+ // $FlowFixMe[incompatible-call]
68
source,
69
null,
70
+ // $FlowFixMe[incompatible-call]
71
null,
72
undefined,
73
undefined,
@@ -73,12 +78,19 @@ function read<T>(source: Source, options: ReadOptions): Thenable<T> {
78
true,
79
undefined,
80
__DEV__ && options !== undefined && options.debugChannel !== undefined
76
- ? options.debugChannel.onMessage
81
+ ? // $FlowFixMe[incompatible-call]
82
+ options.debugChannel.onMessage
83
: undefined,
84
);
85
const streamState = createStreamState(response, source);
86
for (let i = 0; i < source.length; i++) {
81
- processBinaryChunk(response, streamState, source[i], 0);
87
+ processBinaryChunk(
88
+ response,
89
+ streamState,
90
+ source[i],
91
+ // $FlowFixMe[extra-arg]
92
+ 0,
93
+ );
94
}
95
if (options !== undefined && options.close) {
96
close(response);
packages/react-noop-renderer/src/ReactNoopFlightServer.js
+9
-2
@@ -20,10 +20,11 @@ import {saveModule} from 'react-noop-renderer/flight-modules';
20
21
import ReactFlightServer from 'react-server/flight';
22
23
-type Destination = Array<Uint8Array>;
23
+type Destination = Array<Uint8Array | string>;
24
25
const textEncoder = new TextEncoder();
26
27
+// $FlowFixMe[prop-missing]
28
const ReactNoopFlightServer = ReactFlightServer({
29
scheduleMicrotask(callback: () => void) {
30
callback();
@@ -81,6 +82,7 @@ function render(model: ReactClientValue, options?: Options): Destination {
82
const bundlerConfig = undefined;
83
const request = ReactNoopFlightServer.createRequest(
84
model,
85
+ // $FlowFixMe[incompatible-call]
86
bundlerConfig,
87
options ? options.onError : undefined,
88
options ? options.identifierPrefix : undefined,
@@ -88,6 +90,7 @@ function render(model: ReactClientValue, options?: Options): Destination {
90
options ? options.startTime : undefined,
91
__DEV__ && options ? options.environmentName : undefined,
92
__DEV__ && options ? options.filterStackFrame : undefined,
93
+ // $FlowFixMe[incompatible-call]
94
__DEV__ && options && options.debugChannel !== undefined,
95
);
96
const signal = options ? options.signal : undefined;
@@ -108,7 +111,11 @@ function render(model: ReactClientValue, options?: Options): Destination {
111
};
112
}
113
ReactNoopFlightServer.startWork(request);
111
- ReactNoopFlightServer.startFlowing(request, destination);
114
+ ReactNoopFlightServer.startFlowing(
115
+ request,
116
+ // $FlowFixMe[incompatible-call]
117
+ destination,
118
+ );
119
return destination;
120
}
121
packages/react-noop-renderer/src/ReactNoopPersistent.js
+1
@@ -55,6 +55,7 @@ export const {
55
// TODO: Remove this once callers migrate to alternatives.
56
// This should only be used by React internals.
57
unstable_runWithPriority,
58
+ // $FlowFixMe[signature-verification-failure]
59
} = createReactNoop(
60
ReactFiberReconciler, // reconciler
61
false, // useMutation
packages/react-noop-renderer/src/ReactNoopServer.js
+11
-3
@@ -40,12 +40,12 @@ type SuspenseInstance = {
40
};
41
42
type Placeholder = {
43
- parent: Instance | SuspenseInstance,
43
+ parent: Instance | Segment | SuspenseInstance,
44
index: number,
45
};
46
47
type Segment = {
48
- children: null | Instance | TextInstance | SuspenseInstance,
48
+ children: Array<Instance | TextInstance | SuspenseInstance>,
49
};
50
51
type Destination = {
@@ -79,6 +79,7 @@ function write(destination: Destination, buffer: Uint8Array): void {
79
stack.push(instance);
80
}
81
82
+// $FlowFixMe[prop-missing]
83
const ReactNoopServer = ReactFizzServer({
84
scheduleMicrotask(callback: () => void) {
85
callback();
@@ -175,6 +176,7 @@ const ReactNoopServer = ReactFizzServer({
176
destination: Destination,
177
renderState: RenderState,
178
id: number,
179
+ // $FlowFixMe[incompatible-return]
180
): boolean {
181
const parent = destination.stack[destination.stack.length - 1];
182
destination.placeholders.set(id, {
@@ -258,7 +260,7 @@ const ReactNoopServer = ReactFizzServer({
260
formatContext: null,
261
id: number,
262
): boolean {
261
- const segment = {
263
+ const segment: Segment = {
264
children: [],
265
};
266
destination.segments.set(id, segment);
@@ -314,6 +316,7 @@ const ReactNoopServer = ReactFizzServer({
316
renderState: RenderState,
317
boundary: SuspenseInstance,
318
): boolean {
319
+ // $FlowFixMe[prop-missing]
320
boundary.status = 'client-render';
321
return true;
322
},
@@ -357,6 +360,7 @@ type Options = {
360
};
361
362
function render(children: React$Element<any>, options?: Options): Destination {
363
+ // $FlowFixMe[prop-missing]
364
const destination: Destination = {
365
root: null,
366
placeholders: new Map(),
@@ -368,8 +372,11 @@ function render(children: React$Element<any>, options?: Options): Destination {
372
};
373
const request = ReactNoopServer.createRequest(
374
children,
375
+ // $FlowFixMe[incompatible-call]
376
null,
377
+ // $FlowFixMe[incompatible-call]
378
null,
379
+ // $FlowFixMe[incompatible-call]
380
null,
381
options ? options.progressiveChunkSize : undefined,
382
options ? options.onError : undefined,
@@ -377,6 +384,7 @@ function render(children: React$Element<any>, options?: Options): Destination {
384
options ? options.onShellReady : undefined,
385
);
386
ReactNoopServer.startWork(request);
387
+ // $FlowFixMe[incompatible-call]
388
ReactNoopServer.startFlowing(request, destination);
389
return destination;
390
}
packages/react-noop-renderer/src/createReactNoop.js
+118
-47
@@ -23,6 +23,14 @@ import type {ReactNodeList} from 'shared/ReactTypes';
23
import type {RootTag} from 'react-reconciler/src/ReactRootTags';
24
import type {EventPriority} from 'react-reconciler/src/ReactEventPriorities';
25
import type {TransitionTypes} from 'react/src/ReactTransitionType';
26
+import typeof * as HostConfig from 'react-reconciler/src/ReactFiberConfig';
27
+import typeof * as ReconcilerAPI from 'react-reconciler/src/ReactFiberReconciler';
28
+import type {
29
+ HostContext,
30
+ Instance,
31
+ PublicInstance,
32
+ TextInstance,
33
+} from './ReactFiberConfigNoop';
34
35
import * as Scheduler from 'scheduler/unstable_mock';
36
import {REACT_FRAGMENT_TYPE, REACT_ELEMENT_TYPE} from 'shared/ReactSymbols';
@@ -58,28 +66,19 @@ type Props = {
66
src?: string,
67
...
68
};
61
-type Instance = {
62
- type: string,
63
- id: number,
64
- parent: number,
65
- children: Array<Instance | TextInstance>,
66
- text: string | null,
67
- prop: any,
68
- hidden: boolean,
69
- context: HostContext,
70
-};
71
-type TextInstance = {
72
- text: string,
73
- id: number,
74
- parent: number,
75
- hidden: boolean,
76
- context: HostContext,
77
-};
78
-type HostContext = Object;
69
type CreateRootOptions = {
70
unstable_transitionCallbacks?: TransitionTracingCallbacks,
81
- onUncaughtError?: (error: mixed, errorInfo: {componentStack: string}) => void,
82
- onCaughtError?: (error: mixed, errorInfo: {componentStack: string}) => void,
71
+ onUncaughtError?: (
72
+ error: mixed,
73
+ errorInfo: {+componentStack: ?string},
74
+ ) => void,
75
+ onCaughtError?: (
76
+ error: mixed,
77
+ errorInfo: {
78
+ +componentStack: ?string,
79
+ +errorBoundary?: ?component(...props: any),
80
+ },
81
+ ) => void,
82
onDefaultTransitionIndicator?: () => void | (() => void),
83
...
84
};
@@ -108,7 +107,11 @@ if (__DEV__) {
107
Object.freeze(NO_CONTEXT);
108
}
109
111
-function createReactNoop(reconciler: Function, useMutation: boolean) {
110
+// $FlowFixMe[signature-verification-failure]
111
+function createReactNoop(
112
+ reconciler: (hostConfig: HostConfig) => ReconcilerAPI,
113
+ useMutation: boolean,
114
+): any {
115
let instanceCounter = 0;
116
let hostUpdateCounter = 0;
117
let hostCloneCounter = 0;
@@ -118,9 +121,11 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
121
child: Instance | TextInstance,
122
): void {
123
const prevParent = child.parent;
124
+ // $FlowFixMe[prop-missing]
125
if (prevParent !== -1 && prevParent !== parentInstance.id) {
126
throw new Error('Reparenting is not allowed');
127
}
128
+ // $FlowFixMe[prop-missing]
129
child.parent = parentInstance.id;
130
const index = parentInstance.children.indexOf(child);
131
if (index !== -1) {
@@ -265,6 +270,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
270
};
271
272
if (type === 'suspensey-thing' && typeof newProps.src === 'string') {
273
+ // $FlowFixMe[prop-missing]
274
clone.src = newProps.src;
275
}
276
@@ -285,6 +291,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
291
enumerable: false,
292
});
293
hostCloneCounter++;
294
+ // $FlowFixMe[incompatible-return]
295
return clone;
296
}
297
@@ -299,7 +306,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
306
);
307
}
308
302
- function computeText(rawText, hostContext) {
309
+ function computeText(rawText: string, hostContext: HostContext) {
310
return hostContext === UPPERCASE_CONTEXT ? rawText.toUpperCase() : rawText;
311
}
312
@@ -333,6 +340,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
340
// Attach a listener to the suspensey thing and create a subscription
341
// object that uses reference counting to track when all the suspensey
342
// things have loaded.
343
+ // $FlowFixMe
344
const record = suspenseyThingCache.get(src);
345
if (record === undefined) {
346
throw new Error('Could not find record for key.');
@@ -344,8 +352,10 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
352
// Stash the subscription on the record. In `resolveSuspenseyThing`,
353
// we'll use this fire the commit once all the things have loaded.
354
if (record.subscriptions === null) {
355
+ // $FlowFixMe[incompatible-use]
356
record.subscriptions = [];
357
}
358
+ // $FlowFixMe[incompatible-use]
359
record.subscriptions.push(state);
360
}
361
} else {
@@ -361,7 +371,8 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
371
timeoutOffset: number,
372
): ((commit: () => mixed) => () => void) | null {
373
if (state.pendingCount > 0) {
364
- return (commit: () => void) => {
374
+ return (commit: () => mixed) => {
375
+ // $FlowFixMe[incompatible-type]
376
state.commit = commit;
377
const cancelCommit = () => {
378
state.commit = null;
@@ -392,8 +403,8 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
403
return NO_CONTEXT;
404
},
405
395
- getPublicInstance(instance) {
396
- return instance;
406
+ getPublicInstance(instance: Instance): PublicInstance {
407
+ return (instance: any);
408
},
409
410
createInstance(
@@ -413,7 +424,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
424
checkPropStringCoercion(props.children, 'children');
425
}
426
}
416
- const inst = {
427
+ const inst: Instance = {
428
id: instanceCounter++,
429
type: type,
430
children: [],
@@ -428,6 +439,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
439
};
440
441
if (type === 'suspensey-thing' && typeof props.src === 'string') {
442
+ // $FlowFixMe[prop-missing]
443
inst.src = props.src;
444
}
445
@@ -445,10 +457,12 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
457
value: inst.context,
458
enumerable: false,
459
});
460
+ // $FlowFixMe[prop-missing]
461
Object.defineProperty(inst, 'fiber', {
462
value: internalInstanceHandle,
463
enumerable: false,
464
});
465
+ // $FlowFixMe[incompatible-return]
466
return inst;
467
},
468
@@ -511,19 +525,19 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
525
throw new Error('Not yet implemented.');
526
},
527
514
- createFragmentInstance(fragmentFiber) {
528
+ createFragmentInstance(fragmentFiber: mixed) {
529
return null;
530
},
531
518
- updateFragmentInstanceFiber(fragmentFiber, fragmentInstance) {
532
+ updateFragmentInstanceFiber(fragmentFiber: mixed, fragmentInstance: mixed) {
533
// Noop
534
},
535
522
- commitNewChildToFragmentInstance(child, fragmentInstance) {
536
+ commitNewChildToFragmentInstance(child: mixed, fragmentInstance: mixed) {
537
// Noop
538
},
539
526
- deleteChildFromFragmentInstance(child, fragmentInstance) {
540
+ deleteChildFromFragmentInstance(child: mixed, fragmentInstance: mixed) {
541
// Noop
542
},
543
@@ -536,7 +550,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
550
typeof queueMicrotask === 'function'
551
? queueMicrotask
552
: typeof Promise !== 'undefined'
539
- ? callback =>
553
+ ? (callback: () => void) =>
554
Promise.resolve(null)
555
.then(callback)
556
.catch(error => {
@@ -610,7 +624,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
624
// no-op
625
},
626
613
- requestPostPaintCallback(callback) {
627
+ requestPostPaintCallback(callback: (time: number) => void) {
628
const endTime = Scheduler.unstable_now();
629
callback(endTime);
630
},
@@ -661,19 +675,23 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
675
if (suspenseyThingCache === null) {
676
suspenseyThingCache = new Map();
677
}
678
+ // $FlowFixMe
679
const record = suspenseyThingCache.get(props.src);
680
if (record === undefined) {
681
const newRecord: SuspenseyThingRecord = {
682
status: 'pending',
683
subscriptions: null,
684
};
685
+ // $FlowFixMe
686
suspenseyThingCache.set(props.src, newRecord);
687
+ // $FlowFixMe[prop-missing]
688
const onLoadStart = props.onLoadStart;
689
if (typeof onLoadStart === 'function') {
690
onLoadStart();
691
}
692
return false;
693
} else {
694
+ // $FlowFixMe[prop-missing]
695
return record.status === 'fulfilled';
696
}
697
},
@@ -713,7 +731,8 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
731
732
resetFormInstance(form: Instance) {},
733
716
- bindToConsole(methodName, args, badgeName) {
734
+ bindToConsole(methodName: $FlowFixMe, args: Array<any>, badgeName: string) {
735
+ // $FlowFixMe[incompatible-call]
736
return Function.prototype.bind.apply(
737
// eslint-disable-next-line react-internal/no-production-logging
738
console[methodName],
@@ -722,8 +741,9 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
741
},
742
};
743
725
- const hostConfig = useMutation
726
- ? {
744
+ const hostConfig: HostConfig = useMutation
745
+ ? // $FlowFixMe[prop-missing]
746
+ {
747
...sharedHostConfig,
748
749
supportsMutation: true,
@@ -747,6 +767,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
767
instance.hidden = !!newProps.hidden;
768
769
if (type === 'suspensey-thing' && typeof newProps.src === 'string') {
770
+ // $FlowFixMe[prop-missing]
771
instance.src = newProps.src;
772
}
773
@@ -907,7 +928,8 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
928
instance.text = null;
929
},
930
}
910
- : {
931
+ : // $FlowFixMe[prop-missing]
932
+ {
933
...sharedHostConfig,
934
supportsMutation: false,
935
supportsPersistence: true,
@@ -987,8 +1009,8 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
1009
1010
const NoopRenderer = reconciler(hostConfig);
1011
990
- const rootContainers = new Map();
991
- const roots = new Map();
1012
+ const rootContainers = new Map<string, Container>();
1013
+ const roots = new Map<string, Object>();
1014
const DEFAULT_ROOT_ID = '<default>';
1015
1016
let currentUpdatePriority = NoEventPriority;
@@ -1002,6 +1024,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
1024
1025
let currentEventPriority = DefaultEventPriority;
1026
1027
+ // $FlowFixMe[missing-local-annot]
1028
function createJSXElementForTestComparison(type, props) {
1029
if (__DEV__) {
1030
const element = {
@@ -1012,6 +1035,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
1035
_owner: null,
1036
_store: __DEV__ ? {} : undefined,
1037
};
1038
+ // $FlowFixMe[prop-missing]
1039
Object.defineProperty(element, 'ref', {
1040
enumerable: false,
1041
value: null,
@@ -1028,6 +1052,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
1052
}
1053
}
1054
1055
+ // $FlowFixMe
1056
function childToJSX(child, text) {
1057
if (text !== null) {
1058
return text;
@@ -1066,6 +1091,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
1091
if (instance.hidden) {
1092
props.hidden = true;
1093
}
1094
+ // $FlowFixMe[prop-missing]
1095
if (instance.src) {
1096
props.src = instance.src;
1097
}
@@ -1082,6 +1108,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
1108
return textInstance.text;
1109
}
1110
1111
+ // $FlowFixMe[missing-local-annot]
1112
function getChildren(root) {
1113
if (root) {
1114
return root.children;
@@ -1090,6 +1117,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
1117
}
1118
}
1119
1120
+ // $FlowFixMe[missing-local-annot]
1121
function getPendingChildren(root) {
1122
if (root) {
1123
return root.children;
@@ -1098,6 +1126,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
1126
}
1127
}
1128
1129
+ // $FlowFixMe[missing-local-annot]
1130
function getChildrenAsJSX(root) {
1131
const children = childToJSX(getChildren(root), null);
1132
if (children === null) {
@@ -1109,6 +1138,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
1138
return children;
1139
}
1140
1141
+ // $FlowFixMe[missing-local-annot]
1142
function getPendingChildrenAsJSX(root) {
1143
const children = childToJSX(getChildren(root), null);
1144
if (children === null) {
@@ -1139,6 +1169,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
1169
if (fn) {
1170
return fn();
1171
} else {
1172
+ // $FlowFixMe[incompatible-return]
1173
return undefined;
1174
}
1175
} finally {
@@ -1159,6 +1190,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
1190
1191
let idCounter = 0;
1192
1193
+ // $FlowFixMe
1194
const ReactNoop = {
1195
_Scheduler: Scheduler,
1196
@@ -1199,12 +1231,19 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
1231
getOrCreateRootContainer(rootID: string = DEFAULT_ROOT_ID, tag: RootTag) {
1232
let root = roots.get(rootID);
1233
if (!root) {
1202
- const container = {rootID: rootID, pendingChildren: [], children: []};
1234
+ const container: Container = {
1235
+ rootID: rootID,
1236
+ pendingChildren: [],
1237
+ children: [],
1238
+ };
1239
+ // $FlowFixMe[incompatible-call]
1240
rootContainers.set(rootID, container);
1241
root = NoopRenderer.createContainer(
1242
+ // $FlowFixMe[incompatible-call] -- Discovered when typechecking noop-renderer
1243
container,
1244
tag,
1245
null,
1246
+ // $FlowFixMe[incompatible-call] -- Discovered when typechecking noop-renderer
1247
null,
1248
false,
1249
'',
@@ -1221,15 +1260,17 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
1260
1261
// TODO: Replace ReactNoop.render with createRoot + root.render
1262
createRoot(options?: CreateRootOptions) {
1224
- const container = {
1263
+ const container: Container = {
1264
rootID: '' + idCounter++,
1265
pendingChildren: [],
1266
children: [],
1267
};
1268
const fiberRoot = NoopRenderer.createContainer(
1269
+ // $FlowFixMe[incompatible-call]
1270
container,
1271
ConcurrentRoot,
1272
null,
1273
+ // $FlowFixMe[incompatible-call]
1274
null,
1275
false,
1276
'',
@@ -1272,9 +1313,11 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
1313
children: [],
1314
};
1315
const fiberRoot = NoopRenderer.createContainer(
1316
+ // $FlowFixMe[incompatible-call] -- TODO: Discovered when typechecking noop-renderer
1317
container,
1318
LegacyRoot,
1319
null,
1320
+ // $FlowFixMe[incompatible-call] -- TODO: Discovered when typechecking noop-renderer
1321
null,
1322
false,
1323
'',
@@ -1309,11 +1352,13 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
1352
return getPendingChildrenAsJSX(container);
1353
},
1354
1355
+ // $FlowFixMe[missing-local-annot]
1356
getSuspenseyThingStatus(src): string | null {
1357
if (suspenseyThingCache === null) {
1358
return null;
1359
} else {
1360
const record = suspenseyThingCache.get(src);
1361
+ // $FlowFixMe[prop-missing]
1362
return record === undefined ? null : record.status;
1363
}
1364
},
@@ -1322,18 +1367,24 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
1367
if (suspenseyThingCache === null) {
1368
suspenseyThingCache = new Map();
1369
}
1370
+ // $FlowFixMe[incompatible-call]
1371
const record = suspenseyThingCache.get(key);
1372
if (record === undefined) {
1373
const newRecord: SuspenseyThingRecord = {
1374
status: 'fulfilled',
1375
subscriptions: null,
1376
};
1377
+ // $FlowFixMe
1378
suspenseyThingCache.set(key, newRecord);
1379
} else {
1380
+ // $FlowFixMe[prop-missing]
1381
if (record.status === 'pending') {
1382
+ // $FlowFixMe[incompatible-use]
1383
record.status = 'fulfilled';
1384
+ // $FlowFixMe[prop-missing]
1385
const subscriptions = record.subscriptions;
1386
if (subscriptions !== null) {
1387
+ // $FlowFixMe[incompatible-use]
1388
record.subscriptions = null;
1389
for (let i = 0; i < subscriptions.length; i++) {
1390
const subscription = subscriptions[i];
@@ -1411,11 +1462,13 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
1462
return component;
1463
}
1464
if (__DEV__) {
1465
+ // $FlowFixMe[incompatible-return]
1466
return NoopRenderer.findHostInstanceWithWarning(
1467
component,
1468
'findInstance',
1469
);
1470
}
1471
+ // $FlowFixMe[incompatible-return]
1472
return NoopRenderer.findHostInstance(component);
1473
},
1474
@@ -1474,6 +1527,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
1527
1528
discreteUpdates: NoopRenderer.discreteUpdates,
1529
1530
+ // $FlowFixMe[incompatible-return]
1531
idleUpdates<T>(fn: () => T): T {
1532
const prevEventPriority = currentEventPriority;
1533
currentEventPriority = IdleEventPriority;
@@ -1497,14 +1551,16 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
1551
return;
1552
}
1553
1500
- const bufferedLog = [];
1501
- function log(...args) {
1554
+ const bufferedLog: string[] = [];
1555
+ // $FlowFixMe[missing-local-annot]
1556
+ function log(...args: string[]) {
1557
+ // $FlowFixMe[incompatible-call]
1558
bufferedLog.push(...args, '\n');
1559
}
1560
1561
function logHostInstances(
1562
children: Array<Instance | TextInstance>,
1507
- depth,
1563
+ depth: number,
1564
) {
1565
for (let i = 0; i < children.length; i++) {
1566
const child = children[i];
@@ -1512,17 +1568,23 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
1568
if (typeof child.text === 'string') {
1569
log(indent + '- ' + child.text);
1570
} else {
1571
+ // $FlowFixMe[unsafe-addition]
1572
log(indent + '- ' + child.type + '#' + child.id);
1516
- logHostInstances(child.children, depth + 1);
1573
+
1574
+ logHostInstances(
1575
+ // $FlowFixMe[incompatible-call]
1576
+ child.children,
1577
+ depth + 1,
1578
+ );
1579
}
1580
}
1581
}
1520
- function logContainer(container: Container, depth) {
1582
+ function logContainer(container: Container, depth: number) {
1583
log(' '.repeat(depth) + '- [root#' + container.rootID + ']');
1584
logHostInstances(container.children, depth + 1);
1585
}
1586
1525
- function logUpdateQueue(updateQueue: UpdateQueue<mixed>, depth) {
1587
+ function logUpdateQueue(updateQueue: UpdateQueue<mixed>, depth: number) {
1588
log(' '.repeat(depth + 1) + 'QUEUED UPDATES');
1589
const first = updateQueue.firstBaseUpdate;
1590
const update = first;
@@ -1530,6 +1592,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
1592
do {
1593
log(
1594
' '.repeat(depth + 1) + '~',
1595
+ // $FlowFixMe
1596
'[' + update.expirationTime + ']',
1597
);
1598
} while (update !== null);
@@ -1543,6 +1606,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
1606
do {
1607
log(
1608
' '.repeat(depth + 1) + '~',
1609
+ // $FlowFixMe
1610
'[' + pendingUpdate.expirationTime + ']',
1611
);
1612
} while (pendingUpdate !== null && pendingUpdate !== firstPending);
@@ -1550,19 +1614,26 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
1614
}
1615
}
1616
1617
+ // $FlowFixMe[missing-local-annot]
1618
function logFiber(fiber: Fiber, depth) {
1619
log(
1620
' '.repeat(depth) +
1621
'- ' +
1622
// need to explicitly coerce Symbol to a string
1623
(fiber.type ? fiber.type.name || fiber.type.toString() : '[root]'),
1624
+ // $FlowFixMe[unsafe-addition]
1625
'[' +
1626
+ // $FlowFixMe[prop-missing]
1627
fiber.childExpirationTime +
1628
(fiber.pendingProps ? '*' : '') +
1629
']',
1630
);
1631
if (fiber.updateQueue) {
1565
- logUpdateQueue(fiber.updateQueue, depth);
1632
+ logUpdateQueue(
1633
+ // $FlowFixMe[incompatible-call]
1634
+ fiber.updateQueue,
1635
+ depth,
1636
+ );
1637
}
1638
// const childInProgress = fiber.progressedChild;
1639
// if (childInProgress && childInProgress !== fiber.child) {
packages/react-reconciler/index.js
+7
@@ -7,4 +7,11 @@
7
* @flow
8
*/
9
10
+import typeof * as ReconcilerAPI from './src/ReactFiberReconciler';
11
+import typeof * as HostConfig from './src/ReactFiberConfig';
12
+
13
export * from './src/ReactFiberReconciler';
14
+
15
+// At build time, this module is wrapped as a factory function ($$$reconciler).
16
+// Consumers pass a host config object and get back the reconciler API.
17
+declare export default (hostConfig: HostConfig) => ReconcilerAPI;
packages/react-reconciler/src/forks/ReactFiberConfig.noop.js
new
+282
@@ -0,0 +1,282 @@
1
+/**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow
8
+ */
9
+
10
+// This is a host config that's used for the internal `react-noop-renderer`.
11
+//
12
+// Its API lets you pass the host config as an argument.
13
+// However, inside the `react-reconciler` we treat host config as a module.
14
+// This file is a shim between two worlds.
15
+//
16
+// It works because the `react-reconciler` bundle is wrapped in something like:
17
+//
18
+// module.exports = function ($$$config) {
19
+// /* reconciler code */
20
+// }
21
+//
22
+// So `$$$config` looks like a global variable, but it's
23
+// really an argument to a top-level wrapping function.
24
+
25
+export * from 'react-noop-renderer/src/ReactFiberConfigNoop';
26
+
27
+declare const $$$config: $FlowFixMe;
28
+export opaque type Type = mixed;
29
+export opaque type Props = mixed;
30
+export opaque type Container = mixed;
31
+export opaque type ActivityInstance = mixed;
32
+export opaque type SuspenseInstance = mixed;
33
+export opaque type HydratableInstance = mixed;
34
+export opaque type UpdatePayload = mixed;
35
+export opaque type ChildSet = mixed;
36
+export opaque type TimeoutHandle = mixed;
37
+export opaque type NoTimeout = mixed;
38
+export opaque type RendererInspectionConfig = mixed;
39
+export opaque type FormInstance = mixed;
40
+export opaque type SuspendedState = mixed;
41
+export type RunningViewTransition = mixed;
42
+export type ViewTransitionInstance = null | {name: string, ...};
43
+export opaque type InstanceMeasurement = mixed;
44
+export type EventResponder = any;
45
+export type GestureTimeline = any;
46
+export type FragmentInstanceType = null;
47
+
48
+export const rendererVersion = $$$config.rendererVersion;
49
+export const rendererPackageName = $$$config.rendererPackageName;
50
+export const extraDevToolsConfig = $$$config.extraDevToolsConfig;
51
+
52
+export const getPublicInstance = $$$config.getPublicInstance;
53
+export const getRootHostContext = $$$config.getRootHostContext;
54
+export const getChildHostContext = $$$config.getChildHostContext;
55
+export const prepareForCommit = $$$config.prepareForCommit;
56
+export const resetAfterCommit = $$$config.resetAfterCommit;
57
+export const createInstance = $$$config.createInstance;
58
+export const cloneMutableInstance = $$$config.cloneMutableInstance;
59
+export const appendInitialChild = $$$config.appendInitialChild;
60
+export const finalizeInitialChildren = $$$config.finalizeInitialChildren;
61
+export const shouldSetTextContent = $$$config.shouldSetTextContent;
62
+export const createTextInstance = $$$config.createTextInstance;
63
+export const cloneMutableTextInstance = $$$config.cloneMutableTextInstance;
64
+export const scheduleTimeout = $$$config.scheduleTimeout;
65
+export const cancelTimeout = $$$config.cancelTimeout;
66
+export const noTimeout = $$$config.noTimeout;
67
+export const isPrimaryRenderer = $$$config.isPrimaryRenderer;
68
+export const warnsIfNotActing = $$$config.warnsIfNotActing;
69
+export const supportsMutation = $$$config.supportsMutation;
70
+export const supportsPersistence = $$$config.supportsPersistence;
71
+export const supportsHydration = $$$config.supportsHydration;
72
+export const getInstanceFromNode = $$$config.getInstanceFromNode;
73
+export const beforeActiveInstanceBlur = $$$config.beforeActiveInstanceBlur;
74
+export const afterActiveInstanceBlur = $$$config.afterActiveInstanceBlur;
75
+export const preparePortalMount = $$$config.preparePortalMount;
76
+export const prepareScopeUpdate = $$$config.prepareScopeUpdate;
77
+export const getInstanceFromScope = $$$config.getInstanceFromScope;
78
+export const setCurrentUpdatePriority = $$$config.setCurrentUpdatePriority;
79
+export const getCurrentUpdatePriority = $$$config.getCurrentUpdatePriority;
80
+export const resolveUpdatePriority = $$$config.resolveUpdatePriority;
81
+export const trackSchedulerEvent = $$$config.trackSchedulerEvent;
82
+export const resolveEventType = $$$config.resolveEventType;
83
+export const resolveEventTimeStamp = $$$config.resolveEventTimeStamp;
84
+export const shouldAttemptEagerTransition =
85
+ $$$config.shouldAttemptEagerTransition;
86
+export const detachDeletedInstance = $$$config.detachDeletedInstance;
87
+export const requestPostPaintCallback = $$$config.requestPostPaintCallback;
88
+export const maySuspendCommit = $$$config.maySuspendCommit;
89
+export const maySuspendCommitOnUpdate = $$$config.maySuspendCommitOnUpdate;
90
+export const maySuspendCommitInSyncRender =
91
+ $$$config.maySuspendCommitInSyncRender;
92
+export const preloadInstance = $$$config.preloadInstance;
93
+export const startSuspendingCommit = $$$config.startSuspendingCommit;
94
+export const suspendInstance = $$$config.suspendInstance;
95
+export const suspendOnActiveViewTransition =
96
+ $$$config.suspendOnActiveViewTransition;
97
+export const waitForCommitToBeReady = $$$config.waitForCommitToBeReady;
98
+export const getSuspendedCommitReason = $$$config.getSuspendedCommitReason;
99
+export const NotPendingTransition = $$$config.NotPendingTransition;
100
+export const HostTransitionContext = $$$config.HostTransitionContext;
101
+export const resetFormInstance = $$$config.resetFormInstance;
102
+export const bindToConsole = $$$config.bindToConsole;
103
+
104
+// -------------------
105
+// Microtasks
106
+// (optional)
107
+// -------------------
108
+export const supportsMicrotasks = $$$config.supportsMicrotasks;
109
+export const scheduleMicrotask = $$$config.scheduleMicrotask;
110
+
111
+// -------------------
112
+// Test selectors
113
+// (optional)
114
+// -------------------
115
+export const supportsTestSelectors = $$$config.supportsTestSelectors;
116
+export const findFiberRoot = $$$config.findFiberRoot;
117
+export const getBoundingRect = $$$config.getBoundingRect;
118
+export const getTextContent = $$$config.getTextContent;
119
+export const isHiddenSubtree = $$$config.isHiddenSubtree;
120
+export const matchAccessibilityRole = $$$config.matchAccessibilityRole;
121
+export const setFocusIfFocusable = $$$config.setFocusIfFocusable;
122
+export const setupIntersectionObserver = $$$config.setupIntersectionObserver;
123
+
124
+// -------------------
125
+// Mutation
126
+// (optional)
127
+// -------------------
128
+export const appendChild = $$$config.appendChild;
129
+export const appendChildToContainer = $$$config.appendChildToContainer;
130
+export const commitTextUpdate = $$$config.commitTextUpdate;
131
+export const commitMount = $$$config.commitMount;
132
+export const commitUpdate = $$$config.commitUpdate;
133
+export const insertBefore = $$$config.insertBefore;
134
+export const insertInContainerBefore = $$$config.insertInContainerBefore;
135
+export const removeChild = $$$config.removeChild;
136
+export const removeChildFromContainer = $$$config.removeChildFromContainer;
137
+export const resetTextContent = $$$config.resetTextContent;
138
+export const hideInstance = $$$config.hideInstance;
139
+export const hideTextInstance = $$$config.hideTextInstance;
140
+export const unhideInstance = $$$config.unhideInstance;
141
+export const unhideTextInstance = $$$config.unhideTextInstance;
142
+export const applyViewTransitionName = $$$config.applyViewTransitionName;
143
+export const restoreViewTransitionName = $$$config.restoreViewTransitionName;
144
+export const cancelViewTransitionName = $$$config.cancelViewTransitionName;
145
+export const cancelRootViewTransitionName =
146
+ $$$config.cancelRootViewTransitionName;
147
+export const restoreRootViewTransitionName =
148
+ $$$config.restoreRootViewTransitionName;
149
+export const cloneRootViewTransitionContainer =
150
+ $$$config.cloneRootViewTransitionContainer;
151
+export const removeRootViewTransitionClone =
152
+ $$$config.removeRootViewTransitionClone;
153
+export const measureInstance = $$$config.measureInstance;
154
+export const measureClonedInstance = $$$config.measureClonedInstance;
155
+export const wasInstanceInViewport = $$$config.wasInstanceInViewport;
156
+export const hasInstanceChanged = $$$config.hasInstanceChanged;
157
+export const hasInstanceAffectedParent = $$$config.hasInstanceAffectedParent;
158
+export const startViewTransition = $$$config.startViewTransition;
159
+export const startGestureTransition = $$$config.startGestureTransition;
160
+export const stopViewTransition = $$$config.stopViewTransition;
161
+export const addViewTransitionFinishedListener =
162
+ $$$config.addViewTransitionFinishedListener;
163
+export const getCurrentGestureOffset = $$$config.getCurrentGestureOffset;
164
+export const createViewTransitionInstance =
165
+ $$$config.createViewTransitionInstance;
166
+export const clearContainer = $$$config.clearContainer;
167
+export const createFragmentInstance = $$$config.createFragmentInstance;
168
+export const updateFragmentInstanceFiber =
169
+ $$$config.updateFragmentInstanceFiber;
170
+export const commitNewChildToFragmentInstance =
171
+ $$$config.commitNewChildToFragmentInstance;
172
+export const deleteChildFromFragmentInstance =
173
+ $$$config.deleteChildFromFragmentInstance;
174
+
175
+// -------------------
176
+// Persistence
177
+// (optional)
178
+// -------------------
179
+export const cloneInstance = $$$config.cloneInstance;
180
+export const createContainerChildSet = $$$config.createContainerChildSet;
181
+export const appendChildToContainerChildSet =
182
+ $$$config.appendChildToContainerChildSet;
183
+export const finalizeContainerChildren = $$$config.finalizeContainerChildren;
184
+export const replaceContainerChildren = $$$config.replaceContainerChildren;
185
+export const cloneHiddenInstance = $$$config.cloneHiddenInstance;
186
+export const cloneHiddenTextInstance = $$$config.cloneHiddenTextInstance;
187
+
188
+// -------------------
189
+// Hydration
190
+// (optional)
191
+// -------------------
192
+export const isSuspenseInstancePending = $$$config.isSuspenseInstancePending;
193
+export const isSuspenseInstanceFallback = $$$config.isSuspenseInstanceFallback;
194
+export const getSuspenseInstanceFallbackErrorDetails =
195
+ $$$config.getSuspenseInstanceFallbackErrorDetails;
196
+export const registerSuspenseInstanceRetry =
197
+ $$$config.registerSuspenseInstanceRetry;
198
+export const canHydrateFormStateMarker = $$$config.canHydrateFormStateMarker;
199
+export const isFormStateMarkerMatching = $$$config.isFormStateMarkerMatching;
200
+export const getNextHydratableSibling = $$$config.getNextHydratableSibling;
201
+export const getNextHydratableSiblingAfterSingleton =
202
+ $$$config.getNextHydratableSiblingAfterSingleton;
203
+export const getFirstHydratableChild = $$$config.getFirstHydratableChild;
204
+export const getFirstHydratableChildWithinContainer =
205
+ $$$config.getFirstHydratableChildWithinContainer;
206
+export const getFirstHydratableChildWithinActivityInstance =
207
+ $$$config.getFirstHydratableChildWithinActivityInstance;
208
+export const getFirstHydratableChildWithinSuspenseInstance =
209
+ $$$config.getFirstHydratableChildWithinSuspenseInstance;
210
+export const getFirstHydratableChildWithinSingleton =
211
+ $$$config.getFirstHydratableChildWithinSingleton;
212
+export const canHydrateInstance = $$$config.canHydrateInstance;
213
+export const canHydrateTextInstance = $$$config.canHydrateTextInstance;
214
+export const canHydrateActivityInstance = $$$config.canHydrateActivityInstance;
215
+export const canHydrateSuspenseInstance = $$$config.canHydrateSuspenseInstance;
216
+export const hydrateInstance = $$$config.hydrateInstance;
217
+export const hydrateTextInstance = $$$config.hydrateTextInstance;
218
+export const hydrateActivityInstance = $$$config.hydrateActivityInstance;
219
+export const hydrateSuspenseInstance = $$$config.hydrateSuspenseInstance;
220
+export const getNextHydratableInstanceAfterActivityInstance =
221
+ $$$config.getNextHydratableInstanceAfterActivityInstance;
222
+export const getNextHydratableInstanceAfterSuspenseInstance =
223
+ $$$config.getNextHydratableInstanceAfterSuspenseInstance;
224
+export const commitHydratedInstance = $$$config.commitHydratedInstance;
225
+export const commitHydratedContainer = $$$config.commitHydratedContainer;
226
+export const commitHydratedActivityInstance =
227
+ $$$config.commitHydratedActivityInstance;
228
+export const commitHydratedSuspenseInstance =
229
+ $$$config.commitHydratedSuspenseInstance;
230
+export const finalizeHydratedChildren = $$$config.finalizeHydratedChildren;
231
+export const flushHydrationEvents = $$$config.flushHydrationEvents;
232
+export const clearActivityBoundary = $$$config.clearActivityBoundary;
233
+export const clearSuspenseBoundary = $$$config.clearSuspenseBoundary;
234
+export const clearActivityBoundaryFromContainer =
235
+ $$$config.clearActivityBoundaryFromContainer;
236
+export const clearSuspenseBoundaryFromContainer =
237
+ $$$config.clearSuspenseBoundaryFromContainer;
238
+export const hideDehydratedBoundary = $$$config.hideDehydratedBoundary;
239
+export const unhideDehydratedBoundary = $$$config.unhideDehydratedBoundary;
240
+export const shouldDeleteUnhydratedTailInstances =
241
+ $$$config.shouldDeleteUnhydratedTailInstances;
242
+export const diffHydratedPropsForDevWarnings =
243
+ $$$config.diffHydratedPropsForDevWarnings;
244
+export const diffHydratedTextForDevWarnings =
245
+ $$$config.diffHydratedTextForDevWarnings;
246
+export const describeHydratableInstanceForDevWarnings =
247
+ $$$config.describeHydratableInstanceForDevWarnings;
248
+export const validateHydratableInstance = $$$config.validateHydratableInstance;
249
+export const validateHydratableTextInstance =
250
+ $$$config.validateHydratableTextInstance;
251
+
252
+// -------------------
253
+// Resources
254
+// (optional)
255
+// -------------------
256
+export type HoistableRoot = mixed;
257
+export type Resource = mixed;
258
+export const supportsResources = $$$config.supportsResources;
259
+export const isHostHoistableType = $$$config.isHostHoistableType;
260
+export const getHoistableRoot = $$$config.getHoistableRoot;
261
+export const getResource = $$$config.getResource;
262
+export const acquireResource = $$$config.acquireResource;
263
+export const releaseResource = $$$config.releaseResource;
264
+export const hydrateHoistable = $$$config.hydrateHoistable;
265
+export const mountHoistable = $$$config.mountHoistable;
266
+export const unmountHoistable = $$$config.unmountHoistable;
267
+export const createHoistableInstance = $$$config.createHoistableInstance;
268
+export const prepareToCommitHoistables = $$$config.prepareToCommitHoistables;
269
+export const mayResourceSuspendCommit = $$$config.mayResourceSuspendCommit;
270
+export const preloadResource = $$$config.preloadResource;
271
+export const suspendResource = $$$config.suspendResource;
272
+
273
+// -------------------
274
+// Singletons
275
+// (optional)
276
+// -------------------
277
+export const supportsSingletons = $$$config.supportsSingletons;
278
+export const resolveSingletonInstance = $$$config.resolveSingletonInstance;
279
+export const acquireSingletonInstance = $$$config.acquireSingletonInstance;
280
+export const releaseSingletonInstance = $$$config.releaseSingletonInstance;
281
+export const isHostSingletonType = $$$config.isHostSingletonType;
282
+export const isSingletonScope = $$$config.isSingletonScope;
packages/react-server/flight.js
+7
@@ -7,4 +7,11 @@
7
* @flow
8
*/
9
10
+import typeof * as FlightServerAPI from './src/ReactFlightServer';
11
+import typeof * as HostConfig from './src/ReactFlightServerConfig';
12
+
13
export * from './src/ReactFlightServer';
14
+
15
+// At build time, this module is wrapped as a factory function ($$$reconciler).
16
+// Consumers pass a host config object and get back the Flight server API.
17
+declare export default (hostConfig: HostConfig) => FlightServerAPI;
packages/react-server/index.js
+7
@@ -7,4 +7,11 @@
7
* @flow
8
*/
9
10
+import typeof * as FizzAPI from './src/ReactFizzServer';
11
+import typeof * as HostConfig from './src/ReactFizzConfig';
12
+
13
export * from './src/ReactFizzServer';
14
+
15
+// At build time, this module is wrapped as a factory function ($$$reconciler).
16
+// Consumers pass a host config object and get back the Fizz server API.
17
+declare export default (hostConfig: HostConfig) => FizzAPI;
packages/react-server/src/forks/ReactFizzConfig.noop.js
new
+108
@@ -0,0 +1,108 @@
1
+/**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow
8
+ */
9
+
10
+// This is a host config that's used for the `react-server` package on npm.
11
+// It is only used by third-party renderers.
12
+//
13
+// Its API lets you pass the host config as an argument.
14
+// However, inside the `react-server` we treat host config as a module.
15
+// This file is a shim between two worlds.
16
+//
17
+// It works because the `react-server` bundle is wrapped in something like:
18
+//
19
+// module.exports = function ($$$config) {
20
+// /* renderer code */
21
+// }
22
+//
23
+// So `$$$config` looks like a global variable, but it's
24
+// really an argument to a top-level wrapping function.
25
+
26
+import type {Request} from 'react-server/src/ReactFizzServer';
27
+import type {TransitionStatus} from 'react-reconciler/src/ReactFiberConfig';
28
+
29
+declare const $$$config: $FlowFixMe;
30
+export opaque type Destination = mixed;
31
+export opaque type RenderState = mixed;
32
+export opaque type HoistableState = mixed;
33
+export opaque type ResumableState = mixed;
34
+export opaque type PreambleState = mixed;
35
+export opaque type FormatContext = mixed;
36
+export opaque type HeadersDescriptor = mixed;
37
+export type {TransitionStatus};
38
+
39
+export const isPrimaryRenderer = false;
40
+
41
+export const supportsClientAPIs = true;
42
+
43
+export const supportsRequestStorage = false;
44
+export const requestStorage: AsyncLocalStorage<Request | void> = (null: any);
45
+
46
+export const bindToConsole = $$$config.bindToConsole;
47
+
48
+export const resetResumableState = $$$config.resetResumableState;
49
+export const completeResumableState = $$$config.completeResumableState;
50
+export const getChildFormatContext = $$$config.getChildFormatContext;
51
+export const getSuspenseFallbackFormatContext =
52
+ $$$config.getSuspenseFallbackFormatContext;
53
+export const getSuspenseContentFormatContext =
54
+ $$$config.getSuspenseContentFormatContext;
55
+export const getViewTransitionFormatContext =
56
+ $$$config.getViewTransitionFormatContext;
57
+export const makeId = $$$config.makeId;
58
+export const pushTextInstance = $$$config.pushTextInstance;
59
+export const pushStartInstance = $$$config.pushStartInstance;
60
+export const pushEndInstance = $$$config.pushEndInstance;
61
+export const pushSegmentFinale = $$$config.pushSegmentFinale;
62
+export const pushFormStateMarkerIsMatching =
63
+ $$$config.pushFormStateMarkerIsMatching;
64
+export const pushFormStateMarkerIsNotMatching =
65
+ $$$config.pushFormStateMarkerIsNotMatching;
66
+export const writeCompletedRoot = $$$config.writeCompletedRoot;
67
+export const writePlaceholder = $$$config.writePlaceholder;
68
+export const pushStartActivityBoundary = $$$config.pushStartActivityBoundary;
69
+export const pushEndActivityBoundary = $$$config.pushEndActivityBoundary;
70
+export const writeStartCompletedSuspenseBoundary =
71
+ $$$config.writeStartCompletedSuspenseBoundary;
72
+export const writeStartPendingSuspenseBoundary =
73
+ $$$config.writeStartPendingSuspenseBoundary;
74
+export const writeStartClientRenderedSuspenseBoundary =
75
+ $$$config.writeStartClientRenderedSuspenseBoundary;
76
+export const writeEndCompletedSuspenseBoundary =
77
+ $$$config.writeEndCompletedSuspenseBoundary;
78
+export const writeEndPendingSuspenseBoundary =
79
+ $$$config.writeEndPendingSuspenseBoundary;
80
+export const writeEndClientRenderedSuspenseBoundary =
81
+ $$$config.writeEndClientRenderedSuspenseBoundary;
82
+export const writeStartSegment = $$$config.writeStartSegment;
83
+export const writeEndSegment = $$$config.writeEndSegment;
84
+export const writeCompletedSegmentInstruction =
85
+ $$$config.writeCompletedSegmentInstruction;
86
+export const writeCompletedBoundaryInstruction =
87
+ $$$config.writeCompletedBoundaryInstruction;
88
+export const writeClientRenderBoundaryInstruction =
89
+ $$$config.writeClientRenderBoundaryInstruction;
90
+export const NotPendingTransition = $$$config.NotPendingTransition;
91
+export const createPreambleState = $$$config.createPreambleState;
92
+export const canHavePreamble = $$$config.canHavePreamble;
93
+export const isPreambleContext = $$$config.isPreambleContext;
94
+export const isPreambleReady = $$$config.isPreambleReady;
95
+export const hoistPreambleState = $$$config.hoistPreambleState;
96
+
97
+// -------------------------
98
+// Resources
99
+// -------------------------
100
+export const writePreambleStart = $$$config.writePreambleStart;
101
+export const writePreambleEnd = $$$config.writePreambleEnd;
102
+export const writeHoistables = $$$config.writeHoistables;
103
+export const writeHoistablesForBoundary = $$$config.writeHoistablesForBoundary;
104
+export const writePostamble = $$$config.writePostamble;
105
+export const hoistHoistables = $$$config.hoistHoistables;
106
+export const createHoistableState = $$$config.createHoistableState;
107
+export const hasSuspenseyContent = $$$config.hasSuspenseyContent;
108
+export const emitEarlyPreloads = $$$config.emitEarlyPreloads;
packages/react-server/src/forks/ReactFlightServerConfig.noop.js
new
+47
@@ -0,0 +1,47 @@
1
+/**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow
8
+ */
9
+
10
+import type {Request} from 'react-server/src/ReactFlightServer';
11
+import type {ReactComponentInfo} from 'shared/ReactTypes';
12
+
13
+export * from '../ReactFlightServerConfigBundlerCustom';
14
+
15
+export * from '../ReactFlightServerConfigDebugNoop';
16
+
17
+export * from '../ReactFlightStackConfigV8';
18
+export * from '../ReactServerConsoleConfigPlain';
19
+
20
+export type Hints = null;
21
+export type HintCode = string;
22
+export type HintModel<T: HintCode> = null; // eslint-disable-line no-unused-vars
23
+
24
+export const supportsRequestStorage = false;
25
+export const requestStorage: AsyncLocalStorage<Request | void> = (null: any);
26
+
27
+export const supportsComponentStorage = false;
28
+export const componentStorage: AsyncLocalStorage<ReactComponentInfo | void> =
29
+ (null: any);
30
+
31
+export function createHints(): Hints {
32
+ return null;
33
+}
34
+
35
+export type FormatContext = null;
36
+
37
+export function createRootFormatContext(): FormatContext {
38
+ return null;
39
+}
40
+
41
+export function getChildFormatContext(
42
+ parentContext: FormatContext,
43
+ type: string,
44
+ props: Object,
45
+): FormatContext {
46
+ return parentContext;
47
+}
packages/react-server/src/forks/ReactServerStreamConfig.noop.js
new
+48
@@ -0,0 +1,48 @@
1
+/**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow
8
+ */
9
+
10
+// This is a host config that's used for the `react-server` package on npm.
11
+// It is only used by third-party renderers.
12
+//
13
+// Its API lets you pass the host config as an argument.
14
+// However, inside the `react-server` we treat host config as a module.
15
+// This file is a shim between two worlds.
16
+//
17
+// It works because the `react-server` bundle is wrapped in something like:
18
+//
19
+// module.exports = function ($$$config) {
20
+// /* renderer code */
21
+// }
22
+//
23
+// So `$$$config` looks like a global variable, but it's
24
+// really an argument to a top-level wrapping function.
25
+
26
+declare const $$$config: $FlowFixMe;
27
+export opaque type Destination = mixed;
28
+
29
+export opaque type PrecomputedChunk = mixed;
30
+export opaque type Chunk = mixed;
31
+export opaque type BinaryChunk = mixed;
32
+
33
+export const scheduleWork = $$$config.scheduleWork;
34
+export const scheduleMicrotask = $$$config.scheduleMicrotask;
35
+export const beginWriting = $$$config.beginWriting;
36
+export const writeChunk = $$$config.writeChunk;
37
+export const writeChunkAndReturn = $$$config.writeChunkAndReturn;
38
+export const completeWriting = $$$config.completeWriting;
39
+export const flushBuffered = $$$config.flushBuffered;
40
+export const close = $$$config.close;
41
+export const closeWithError = $$$config.closeWithError;
42
+export const stringToChunk = $$$config.stringToChunk;
43
+export const stringToPrecomputedChunk = $$$config.stringToPrecomputedChunk;
44
+export const typedArrayToBinaryChunk = $$$config.typedArrayToBinaryChunk;
45
+export const byteLengthOfChunk = $$$config.byteLengthOfChunk;
46
+export const byteLengthOfBinaryChunk = $$$config.byteLengthOfBinaryChunk;
47
+export const createFastHash = $$$config.createFastHash;
48
+export const readAsDataURL = $$$config.readAsDataURL;
scripts/flow/config/flowconfig
-3
@@ -15,9 +15,6 @@
15
.*/__tests__/.*
16
17
18
-# TODO: noop should get its own inlinedHostConfig entry
19
-.*/packages/react-noop-renderer/.*
20
-
18
%REACT_RENDERER_FLOW_IGNORES%
19
20
[libs]
scripts/jest/setupHostConfigs.js
+6
@@ -248,3 +248,9 @@ jest.mock('shared/ReactDOMSharedInternals', () =>
248
);
249
250
jest.mock('scheduler', () => jest.requireActual('scheduler/unstable_mock'));
251
+
252
+if (global.__PERSISTENT__) {
253
+ jest.mock('react-noop-renderer', () =>
254
+ jest.requireActual('react-noop-renderer/persistent')
255
+ );
256
+}
scripts/jest/setupTests.persistent.js
-4
@@ -1,7 +1,3 @@
1
'use strict';
2
3
-jest.mock('react-noop-renderer', () =>
4
- jest.requireActual('react-noop-renderer/persistent')
5
-);
6
-
3
global.__PERSISTENT__ = true;
scripts/jest/setupTests.xplat.js
-4
@@ -28,9 +28,5 @@ jest.mock('shared/ReactFeatureFlags', () => {
28
return actual;
29
});
30
31
-jest.mock('react-noop-renderer', () =>
32
- jest.requireActual('react-noop-renderer/persistent')
33
-);
34
-
31
global.__PERSISTENT__ = true;
32
global.__XPLAT__ = true;
scripts/shared/inlinedHostConfigs.js
+19
@@ -661,6 +661,25 @@ module.exports = [
661
isFlowTyped: false, // TODO: type it.
662
isServerSupported: false,
663
},
664
+ {
665
+ shortName: 'noop',
666
+ entryPoints: [
667
+ 'react-noop-renderer',
668
+ 'react-noop-renderer/persistent',
669
+ 'react-noop-renderer/server',
670
+ 'react-noop-renderer/flight-server',
671
+ 'react-noop-renderer/flight-client',
672
+ ],
673
+ paths: [
674
+ 'react-noop-renderer',
675
+ 'react-client/flight',
676
+ 'react-server/flight',
677
+ 'react-server/src/ReactFlightServerConfigDebugNoop.js',
678
+ ],
679
+ isFlowTyped: true,
680
+ isServerSupported: true,
681
+ isFlightSupported: true,
682
+ },
683
{
684
shortName: 'custom',
685
entryPoints: [