main
js 258 lines 6.52 KB
Raw
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 {ReactNodeList} from 'shared/ReactTypes';
11
12 import type {
13 RenderState,
14 ResumableState,
15 PreambleState,
16 HoistableState,
17 FormatContext,
18 } from 'react-dom-bindings/src/server/ReactFizzConfigDOM';
19
20 import {
21 pushStartInstance as pushStartInstanceImpl,
22 writePreambleStart as writePreambleStartImpl,
23 } from 'react-dom-bindings/src/server/ReactFizzConfigDOM';
24
25 import type {
26 Destination,
27 Chunk,
28 PrecomputedChunk,
29 } from 'react-server/src/ReactServerStreamConfig';
30
31 import type {FormStatus} from 'react-dom-bindings/src/shared/ReactDOMFormActions';
32
33 import {NotPending} from 'react-dom-bindings/src/shared/ReactDOMFormActions';
34
35 import hasOwnProperty from 'shared/hasOwnProperty';
36
37 // Allow embedding inside another Fizz render.
38 export const isPrimaryRenderer = false;
39
40 // Disable Client Hooks
41 export const supportsClientAPIs = false;
42
43 import {stringToChunk} from 'react-server/src/ReactServerStreamConfig';
44
45 export type {
46 RenderState,
47 ResumableState,
48 HoistableState,
49 PreambleState,
50 FormatContext,
51 } from 'react-dom-bindings/src/server/ReactFizzConfigDOM';
52
53 export {
54 getChildFormatContext,
55 getSuspenseFallbackFormatContext,
56 getSuspenseContentFormatContext,
57 makeId,
58 pushEndInstance,
59 pushFormStateMarkerIsMatching,
60 pushFormStateMarkerIsNotMatching,
61 writeStartSegment,
62 writeEndSegment,
63 writeCompletedSegmentInstruction,
64 writeCompletedBoundaryInstruction,
65 writeClientRenderBoundaryInstruction,
66 writeStartPendingSuspenseBoundary,
67 writeEndPendingSuspenseBoundary,
68 writeHoistablesForBoundary,
69 writePlaceholder,
70 createRootFormatContext,
71 createRenderState,
72 createResumableState,
73 createPreambleState,
74 createHoistableState,
75 writePreambleEnd,
76 writeHoistables,
77 writePostamble,
78 hoistHoistables,
79 resetResumableState,
80 completeResumableState,
81 emitEarlyPreloads,
82 doctypeChunk,
83 canHavePreamble,
84 hoistPreambleState,
85 isPreambleReady,
86 isPreambleContext,
87 } from 'react-dom-bindings/src/server/ReactFizzConfigDOM';
88
89 import escapeTextForBrowser from 'react-dom-bindings/src/server/escapeTextForBrowser';
90
91 export function getViewTransitionFormatContext(
92 resumableState: ResumableState,
93 parentContext: FormatContext,
94 update: void | null | 'none' | 'auto' | string,
95 enter: void | null | 'none' | 'auto' | string,
96 exit: void | null | 'none' | 'auto' | string,
97 share: void | null | 'none' | 'auto' | string,
98 parentEnter: void | null | 'none' | 'auto' | string,
99 parentExit: void | null | 'none' | 'auto' | string,
100 hasParentEnterHandler: boolean,
101 hasParentExitHandler: boolean,
102 name: void | null | 'auto' | string,
103 autoName: string, // name or an autogenerated unique name
104 ): FormatContext {
105 // ViewTransition reveals are not supported in markup renders.
106 return parentContext;
107 }
108
109 export function pushStartInstance(
110 target: Array<Chunk | PrecomputedChunk>,
111 type: string,
112 props: Object,
113 resumableState: ResumableState,
114 renderState: RenderState,
115 preambleState: null | PreambleState,
116 hoistableState: null | HoistableState,
117 formatContext: FormatContext,
118 textEmbedded: boolean,
119 ): ReactNodeList {
120 for (const propKey in props) {
121 if (hasOwnProperty.call(props, propKey)) {
122 const propValue = props[propKey];
123 if (propKey === 'ref' && propValue != null) {
124 throw new Error(
125 'Cannot pass ref in renderToHTML because they will never be hydrated.',
126 );
127 }
128 if (typeof propValue === 'function') {
129 throw new Error(
130 'Cannot pass event handlers (' +
131 propKey +
132 ') in renderToHTML because ' +
133 'the HTML will never be hydrated so they can never get called.',
134 );
135 }
136 }
137 }
138
139 return pushStartInstanceImpl(
140 target,
141 type,
142 props,
143 resumableState,
144 renderState,
145 preambleState,
146 hoistableState,
147 formatContext,
148 textEmbedded,
149 );
150 }
151
152 export function pushTextInstance(
153 target: Array<Chunk | PrecomputedChunk>,
154 text: string,
155 renderState: RenderState,
156 textEmbedded: boolean,
157 ): boolean {
158 // Markup doesn't need any termination.
159 target.push(stringToChunk(escapeTextForBrowser(text)));
160 return false;
161 }
162
163 export function pushSegmentFinale(
164 target: Array<Chunk | PrecomputedChunk>,
165 renderState: RenderState,
166 lastPushedText: boolean,
167 textEmbedded: boolean,
168 ): void {
169 // Markup doesn't need any termination.
170 return;
171 }
172
173 export function pushStartActivityBoundary(
174 target: Array<Chunk | PrecomputedChunk>,
175 renderState: RenderState,
176 ): void {
177 // Markup doesn't have any instructions.
178 return;
179 }
180
181 export function pushEndActivityBoundary(
182 target: Array<Chunk | PrecomputedChunk>,
183 renderState: RenderState,
184 ): void {
185 // Markup doesn't have any instructions.
186 return;
187 }
188
189 export function writeStartCompletedSuspenseBoundary(
190 destination: Destination,
191 renderState: RenderState,
192 ): boolean {
193 // Markup doesn't have any instructions.
194 return true;
195 }
196
197 export function writeStartClientRenderedSuspenseBoundary(
198 destination: Destination,
199 renderState: RenderState,
200 // flushing these error arguments are not currently supported in this legacy streaming format.
201 errorDigest: ?string,
202 errorMessage: ?string,
203 errorStack: ?string,
204 errorComponentStack: ?string,
205 ): boolean {
206 // Markup doesn't have any instructions.
207 return true;
208 }
209
210 export function writeEndCompletedSuspenseBoundary(
211 destination: Destination,
212 renderState: RenderState,
213 ): boolean {
214 // Markup doesn't have any instructions.
215 return true;
216 }
217 export function writeEndClientRenderedSuspenseBoundary(
218 destination: Destination,
219 renderState: RenderState,
220 ): boolean {
221 // Markup doesn't have any instructions.
222 return true;
223 }
224
225 export function writePreambleStart(
226 destination: Destination,
227 resumableState: ResumableState,
228 renderState: RenderState,
229 skipBlockingShell: boolean,
230 ): void {
231 return writePreambleStartImpl(
232 destination,
233 resumableState,
234 renderState,
235 true, // skipBlockingShell
236 );
237 }
238
239 export function writeCompletedRoot(
240 destination: Destination,
241 resumableState: ResumableState,
242 renderState: RenderState,
243 isComplete: boolean,
244 ): boolean {
245 // Markup doesn't have any bootstrap scripts nor shell completions.
246 return true;
247 }
248
249 export function hasSuspenseyContent(
250 hoistableState: HoistableState,
251 flushingInShell: boolean,
252 ): boolean {
253 // Never outline.
254 return false;
255 }
256
257 export type TransitionStatus = FormStatus;
258 export const NotPendingTransition: TransitionStatus = NotPending;