@samitouri / QOS-React / commits / 9a5996a6c1

[flags] Cleanup `enableHalt` (#35708)

Sebastian "Sebbie" Silbermann committed Feb 6, 2026 at 10:33 UTC 9a5996a6c144b4d6950b840f2098eff0117b5ac2
20 files changed +61 -311
packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js
-1
@@ -6710,7 +6710,6 @@ describe('ReactDOMFizzServer', () => {
6710 },
6711 );
6712
6713 - // @gate enableHalt
6713 it('can resume a prerender that was aborted', async () => {
6714 const promise = new Promise(r => {});
6715
packages/react-dom/src/__tests__/ReactDOMFizzStatic-test.js
+1 -5
@@ -230,9 +230,7 @@ describe('ReactDOMFizzStatic', () => {
230
231 const result = await promise;
232
233 - expect(result.postponed).toBe(
234 - gate(flags => flags.enableHalt) ? null : undefined,
235 - );
233 + expect(result.postponed).toBe(null);
234
235 await act(async () => {
236 result.prelude.pipe(writable);
@@ -362,7 +360,6 @@ describe('ReactDOMFizzStatic', () => {
360 );
361 });
362
365 - // @gate enableHalt
363 it('will halt a prerender when aborting with an error during a render', async () => {
364 const controller = new AbortController();
365 function App() {
@@ -384,7 +381,6 @@ describe('ReactDOMFizzStatic', () => {
381 expect(getVisibleChildren(container)).toEqual(undefined);
382 });
383
387 - // @gate enableHalt
384 it('will halt a prerender when aborting with an error in a microtask', async () => {
385 const errors = [];
386
packages/react-dom/src/__tests__/ReactDOMFizzStaticBrowser-test.js
+7 -94
@@ -309,40 +309,6 @@ describe('ReactDOMFizzStaticBrowser', () => {
309 expect(errors).toEqual(['This operation was aborted']);
310 });
311
312 - // @gate !enableHalt
313 - it('should reject if aborting before the shell is complete and enableHalt is disabled', async () => {
314 - const errors = [];
315 - const controller = new AbortController();
316 - const promise = serverAct(() =>
317 - ReactDOMFizzStatic.prerender(
318 - <div>
319 - <InfiniteSuspend />
320 - </div>,
321 - {
322 - signal: controller.signal,
323 - onError(x) {
324 - errors.push(x.message);
325 - },
326 - },
327 - ),
328 - );
329 -
330 - await jest.runAllTimers();
331 -
332 - const theReason = new Error('aborted for reasons');
333 - controller.abort(theReason);
334 -
335 - let caughtError = null;
336 - try {
337 - await promise;
338 - } catch (error) {
339 - caughtError = error;
340 - }
341 - expect(caughtError).toBe(theReason);
342 - expect(errors).toEqual(['aborted for reasons']);
343 - });
344 -
345 - // @gate enableHalt
312 it('should resolve an empty prelude if aborting before the shell is complete', async () => {
313 const errors = [];
314 const controller = new AbortController();
@@ -403,59 +369,12 @@ describe('ReactDOMFizzStaticBrowser', () => {
369 ),
370 );
371
406 - if (gate(flags => flags.enableHalt)) {
407 - const {prelude} = await streamPromise;
408 - const content = await readContent(prelude);
409 - expect(errors).toEqual(['This operation was aborted']);
410 - expect(content).toBe('');
411 - } else {
412 - let caughtError = null;
413 - try {
414 - await streamPromise;
415 - } catch (error) {
416 - caughtError = error;
417 - }
418 - expect(caughtError.message).toBe('This operation was aborted');
419 - expect(errors).toEqual(['This operation was aborted']);
420 - }
421 - });
422 -
423 - // @gate !enableHalt
424 - it('should reject if passing an already aborted signal and enableHalt is disabled', async () => {
425 - const errors = [];
426 - const controller = new AbortController();
427 - const theReason = new Error('aborted for reasons');
428 - controller.abort(theReason);
429 -
430 - const promise = serverAct(() =>
431 - ReactDOMFizzStatic.prerender(
432 - <div>
433 - <Suspense fallback={<div>Loading</div>}>
434 - <InfiniteSuspend />
435 - </Suspense>
436 - </div>,
437 - {
438 - signal: controller.signal,
439 - onError(x) {
440 - errors.push(x.message);
441 - },
442 - },
443 - ),
444 - );
445 -
446 - // Technically we could still continue rendering the shell but currently the
447 - // semantics mean that we also abort any pending CPU work.
448 - let caughtError = null;
449 - try {
450 - await promise;
451 - } catch (error) {
452 - caughtError = error;
453 - }
454 - expect(caughtError).toBe(theReason);
455 - expect(errors).toEqual(['aborted for reasons']);
372 + const {prelude} = await streamPromise;
373 + const content = await readContent(prelude);
374 + expect(errors).toEqual(['This operation was aborted']);
375 + expect(content).toBe('');
376 });
377
458 - // @gate enableHalt
378 it('should resolve an empty prelude if passing an already aborted signal', async () => {
379 const errors = [];
380 const controller = new AbortController();
@@ -593,16 +512,13 @@ describe('ReactDOMFizzStaticBrowser', () => {
512 onError,
513 }),
514 );
596 - expect(prerendered.postponed).toBe(
597 - gate(flags => flags.enableHalt) ? null : undefined,
598 - );
515 + expect(prerendered.postponed).toBe(null);
516 expect(errors).toEqual(['bad onHeaders']);
517
518 await readIntoContainer(prerendered.prelude);
519 expect(getVisibleChildren(container)).toEqual(<div>hello</div>);
520 });
521
605 - // @gate enableHalt
522 it('can resume render of a prerender', async () => {
523 const errors = [];
524
@@ -689,7 +605,6 @@ describe('ReactDOMFizzStaticBrowser', () => {
605 expect(getVisibleChildren(container)).toEqual(<div>Hello</div>);
606 });
607
692 - // @gate enableHalt
608 it('can prerender a preamble', async () => {
609 const errors = [];
610
@@ -850,7 +765,6 @@ describe('ReactDOMFizzStaticBrowser', () => {
765 expect(errors).toEqual(['boom']);
766 });
767
853 - // @gate enableHalt
768 it('will render fallback Document when erroring a boundary above the body', async () => {
769 let isPrerendering = true;
770 const promise = new Promise(() => {});
@@ -927,7 +841,6 @@ describe('ReactDOMFizzStaticBrowser', () => {
841 );
842 });
843
930 - // @gate enableHalt
844 it('can omit a preamble with an empty shell if no preamble is ready when prerendering finishes', async () => {
845 const errors = [];
846
@@ -1027,7 +940,7 @@ describe('ReactDOMFizzStaticBrowser', () => {
940 );
941 });
942
1030 - // @gate enableHalt && enableSuspenseList
943 + // @gate enableSuspenseList
944 it('can resume a partially prerendered SuspenseList', async () => {
945 const errors = [];
946
@@ -1112,7 +1025,7 @@ describe('ReactDOMFizzStaticBrowser', () => {
1025 );
1026 });
1027
1115 - // @gate enableHalt && enableOptimisticKey
1028 + // @gate enableOptimisticKey
1029 it('can resume an optimistic keyed slot', async () => {
1030 const errors = [];
1031
packages/react-dom/src/__tests__/ReactDOMFizzStaticNode-test.js
+4 -95
@@ -56,7 +56,6 @@ describe('ReactDOMFizzStaticNode', () => {
56 }
57 }
58
59 - // @gate enableHalt
59 it('should call prerenderToNodeStream', async () => {
60 const result = await ReactDOMFizzStatic.prerenderToNodeStream(
61 <div>hello world</div>,
@@ -65,14 +64,12 @@ describe('ReactDOMFizzStaticNode', () => {
64 expect(prelude).toMatchInlineSnapshot(`"<div>hello world</div>"`);
65 });
66
68 - // @gate enableHalt
67 it('should suppport web streams', async () => {
68 const result = await ReactDOMFizzStatic.prerender(<div>hello world</div>);
69 const prelude = await readContentWeb(result.prelude);
70 expect(prelude).toMatchInlineSnapshot(`"<div>hello world</div>"`);
71 });
72
75 - // @gate enableHalt
73 it('should emit DOCTYPE at the root of the document', async () => {
74 const result = await ReactDOMFizzStatic.prerenderToNodeStream(
75 <html>
@@ -91,7 +88,6 @@ describe('ReactDOMFizzStaticNode', () => {
88 }
89 });
90
94 - // @gate enableHalt
91 it('should emit bootstrap script src at the end', async () => {
92 const result = await ReactDOMFizzStatic.prerenderToNodeStream(
93 <div>hello world</div>,
@@ -107,7 +103,6 @@ describe('ReactDOMFizzStaticNode', () => {
103 );
104 });
105
110 - // @gate enableHalt
106 it('emits all HTML as one unit', async () => {
107 let hasLoaded = false;
108 let resolve;
@@ -137,7 +132,6 @@ describe('ReactDOMFizzStaticNode', () => {
132 expect(prelude).toMatchInlineSnapshot(`"<div><!--$-->Done<!--/$--></div>"`);
133 });
134
140 - // @gate enableHalt
135 it('should reject the promise when an error is thrown at the root', async () => {
136 const reportedErrors = [];
137 let caughtError = null;
@@ -159,7 +153,6 @@ describe('ReactDOMFizzStaticNode', () => {
153 expect(reportedErrors).toEqual([theError]);
154 });
155
162 - // @gate enableHalt
156 it('should reject the promise when an error is thrown inside a fallback', async () => {
157 const reportedErrors = [];
158 let caughtError = null;
@@ -183,7 +176,6 @@ describe('ReactDOMFizzStaticNode', () => {
176 expect(reportedErrors).toEqual([theError]);
177 });
178
186 - // @gate enableHalt
179 it('should not error the stream when an error is thrown inside suspense boundary', async () => {
180 const reportedErrors = [];
181 const result = await ReactDOMFizzStatic.prerenderToNodeStream(
@@ -204,7 +196,6 @@ describe('ReactDOMFizzStaticNode', () => {
196 expect(reportedErrors).toEqual([theError]);
197 });
198
207 - // @gate enableHalt
199 it('should be able to complete by aborting even if the promise never resolves', async () => {
200 const errors = [];
201 const controller = new AbortController();
@@ -234,39 +225,6 @@ describe('ReactDOMFizzStaticNode', () => {
225 expect(errors).toEqual(['This operation was aborted']);
226 });
227
237 - // @gate enableHalt
238 - // @gate !enableHalt
239 - it('should reject if aborting before the shell is complete and enableHalt is disabled', async () => {
240 - const errors = [];
241 - const controller = new AbortController();
242 - const promise = ReactDOMFizzStatic.prerenderToNodeStream(
243 - <div>
244 - <InfiniteSuspend />
245 - </div>,
246 - {
247 - signal: controller.signal,
248 - onError(x) {
249 - errors.push(x.message);
250 - },
251 - },
252 - );
253 -
254 - await jest.runAllTimers();
255 -
256 - const theReason = new Error('aborted for reasons');
257 - controller.abort(theReason);
258 -
259 - let caughtError = null;
260 - try {
261 - await promise;
262 - } catch (error) {
263 - caughtError = error;
264 - }
265 - expect(caughtError).toBe(theReason);
266 - expect(errors).toEqual(['aborted for reasons']);
267 - });
268 -
269 - // @gate enableHalt
228 it('should resolve an empty shell if aborting before the shell is complete', async () => {
229 const errors = [];
230 const controller = new AbortController();
@@ -300,7 +258,6 @@ describe('ReactDOMFizzStaticNode', () => {
258 expect(content).toBe('');
259 });
260
303 - // @gate enableHalt
261 it('should be able to abort before something suspends', async () => {
262 const errors = [];
263 const controller = new AbortController();
@@ -324,58 +281,12 @@ describe('ReactDOMFizzStaticNode', () => {
281 },
282 );
283
327 - if (gate(flags => flags.enableHalt)) {
328 - const {prelude} = await streamPromise;
329 - const content = await readContent(prelude);
330 - expect(errors).toEqual(['This operation was aborted']);
331 - expect(content).toBe('');
332 - } else {
333 - let caughtError = null;
334 - try {
335 - await streamPromise;
336 - } catch (error) {
337 - caughtError = error;
338 - }
339 - expect(caughtError.message).toBe('This operation was aborted');
340 - expect(errors).toEqual(['This operation was aborted']);
341 - }
342 - });
343 -
344 - // @gate enableHalt
345 - // @gate !enableHalt
346 - it('should reject if passing an already aborted signal and enableHalt is disabled', async () => {
347 - const errors = [];
348 - const controller = new AbortController();
349 - const theReason = new Error('aborted for reasons');
350 - controller.abort(theReason);
351 -
352 - const promise = ReactDOMFizzStatic.prerenderToNodeStream(
353 - <div>
354 - <Suspense fallback={<div>Loading</div>}>
355 - <InfiniteSuspend />
356 - </Suspense>
357 - </div>,
358 - {
359 - signal: controller.signal,
360 - onError(x) {
361 - errors.push(x.message);
362 - },
363 - },
364 - );
365 -
366 - // Technically we could still continue rendering the shell but currently the
367 - // semantics mean that we also abort any pending CPU work.
368 - let caughtError = null;
369 - try {
370 - await promise;
371 - } catch (error) {
372 - caughtError = error;
373 - }
374 - expect(caughtError).toBe(theReason);
375 - expect(errors).toEqual(['aborted for reasons']);
284 + const {prelude} = await streamPromise;
285 + const content = await readContent(prelude);
286 + expect(errors).toEqual(['This operation was aborted']);
287 + expect(content).toBe('');
288 });
289
378 - // @gate enableHalt
290 it('should resolve with an empty prelude if passing an already aborted signal', async () => {
291 const errors = [];
292 const controller = new AbortController();
@@ -412,7 +323,6 @@ describe('ReactDOMFizzStaticNode', () => {
323 expect(content).toBe('');
324 });
325
415 - // @gate enableHalt
326 it('supports custom abort reasons with a string', async () => {
327 const promise = new Promise(r => {});
328 function Wait() {
@@ -454,7 +364,6 @@ describe('ReactDOMFizzStaticNode', () => {
364 expect(errors).toEqual(['foobar', 'foobar']);
365 });
366
457 - // @gate enableHalt
367 it('supports custom abort reasons with an Error', async () => {
368 const promise = new Promise(r => {});
369 function Wait() {
packages/react-dom/src/server/ReactDOMFizzStaticBrowser.js
+4 -10
@@ -34,8 +34,6 @@ import {
34 createRootFormatContext,
35 } from 'react-dom-bindings/src/server/ReactFizzConfigDOM';
36
37 -import {enableHalt} from 'shared/ReactFeatureFlags';
38 -
37 import {ensureCorrectIsomorphicReactVersion} from '../shared/ensureCorrectIsomorphicReactVersion';
38 ensureCorrectIsomorphicReactVersion();
39
@@ -89,14 +87,10 @@ function prerender(
87 {highWaterMark: 0},
88 );
89
92 - const result: StaticResult = enableHalt
93 - ? {
94 - postponed: getPostponedState(request),
95 - prelude: stream,
96 - }
97 - : ({
98 - prelude: stream,
99 - }: any);
90 + const result: StaticResult = {
91 + postponed: getPostponedState(request),
92 + prelude: stream,
93 + };
94 resolve(result);
95 }
96
packages/react-dom/src/server/ReactDOMFizzStaticEdge.js
+4 -10
@@ -34,8 +34,6 @@ import {
34 createRootFormatContext,
35 } from 'react-dom-bindings/src/server/ReactFizzConfigDOM';
36
37 -import {enableHalt} from 'shared/ReactFeatureFlags';
38 -
37 import {ensureCorrectIsomorphicReactVersion} from '../shared/ensureCorrectIsomorphicReactVersion';
38 ensureCorrectIsomorphicReactVersion();
39
@@ -89,14 +87,10 @@ function prerender(
87 {highWaterMark: 0},
88 );
89
92 - const result: StaticResult = enableHalt
93 - ? {
94 - postponed: getPostponedState(request),
95 - prelude: stream,
96 - }
97 - : ({
98 - prelude: stream,
99 - }: any);
90 + const result: StaticResult = {
91 + postponed: getPostponedState(request),
92 + prelude: stream,
93 + };
94 resolve(result);
95 }
96
packages/react-dom/src/server/ReactDOMFizzStaticNode.js
+8 -18
@@ -36,8 +36,6 @@ import {
36 createRootFormatContext,
37 } from 'react-dom-bindings/src/server/ReactFizzConfigDOM';
38
39 -import {enableHalt} from 'shared/ReactFeatureFlags';
40 -
39 import {textEncoder} from 'react-server/src/ReactServerStreamConfigNode';
40
41 import {ensureCorrectIsomorphicReactVersion} from '../shared/ensureCorrectIsomorphicReactVersion';
@@ -130,14 +128,10 @@ function prerenderToNodeStream(
128 });
129 const writable = createFakeWritableFromReadable(readable);
130
133 - const result: StaticResult = enableHalt
134 - ? {
135 - postponed: getPostponedState(request),
136 - prelude: readable,
137 - }
138 - : ({
139 - prelude: readable,
140 - }: any);
131 + const result: StaticResult = {
132 + postponed: getPostponedState(request),
133 + prelude: readable,
134 + };
135 resolve(result);
136 }
137 const resumableState = createResumableState(
@@ -215,14 +209,10 @@ function prerender(
209 {highWaterMark: 0},
210 );
211
218 - const result = enableHalt
219 - ? {
220 - postponed: getPostponedState(request),
221 - prelude: stream,
222 - }
223 - : ({
224 - prelude: stream,
225 - }: any);
212 + const result = {
213 + postponed: getPostponedState(request),
214 + prelude: stream,
215 + };
216 resolve(result);
217 }
218
packages/react-server-dom-webpack/src/__tests__/ReactFlightDOM-test.js
-5
@@ -2878,7 +2878,6 @@ describe('ReactFlightDOM', () => {
2878 );
2879 });
2880
2881 - // @gate enableHalt
2881 it('can prerender', async () => {
2882 let resolveGreeting;
2883 const greetingPromise = new Promise(resolve => {
@@ -2940,7 +2939,6 @@ describe('ReactFlightDOM', () => {
2939 expect(getMeaningfulChildren(container)).toEqual(<div>hello world</div>);
2940 });
2941
2943 - // @gate enableHalt
2942 it('does not propagate abort reasons errors when aborting a prerender', async () => {
2943 let resolveGreeting;
2944 const greetingPromise = new Promise(resolve => {
@@ -3023,8 +3021,6 @@ describe('ReactFlightDOM', () => {
3021 expect(getMeaningfulChildren(container)).toEqual(<div>loading...</div>);
3022 });
3023
3026 - // This could be a bug. Discovered while making enableAsyncDebugInfo dynamic for www.
3027 - // @gate enableHalt || (enableAsyncDebugInfo && __DEV__)
3024 it('will leave async iterables in an incomplete state when halting', async () => {
3025 let resolve;
3026 const wait = new Promise(r => (resolve = r));
@@ -3083,7 +3079,6 @@ describe('ReactFlightDOM', () => {
3079 expect(await race).toBe('timeout');
3080 });
3081
3086 - // @gate enableHalt
3082 it('will halt unfinished chunks inside Suspense when aborting a prerender', async () => {
3083 const controller = new AbortController();
3084 function ComponentThatAborts() {
packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMBrowser-test.js
+2 -4
@@ -2389,7 +2389,6 @@ describe('ReactFlightDOMBrowser', () => {
2389 expect(errors).toEqual([reason]);
2390 });
2391
2392 - // @gate enableHalt
2392 it('can prerender', async () => {
2393 let resolveGreeting;
2394 const greetingPromise = new Promise(resolve => {
@@ -2438,7 +2437,6 @@ describe('ReactFlightDOMBrowser', () => {
2437 expect(container.innerHTML).toBe('<div>hello world</div>');
2438 });
2439
2441 - // @gate enableHalt
2440 it('does not propagate abort reasons errors when aborting a prerender', async () => {
2441 let resolveGreeting;
2442 const greetingPromise = new Promise(resolve => {
@@ -2904,9 +2902,9 @@ describe('ReactFlightDOMBrowser', () => {
2902 [
2903 "Object.<anonymous>",
2904 "/packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMBrowser-test.js",
2907 - 2826,
2905 + 2824,
2906 19,
2909 - 2810,
2907 + 2808,
2908 89,
2909 ],
2910 ],
packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMEdge-test.js
-10
@@ -1527,7 +1527,6 @@ describe('ReactFlightDOMEdge', () => {
1527 ]);
1528 });
1529
1530 - // @gate enableHalt
1530 it('can prerender', async () => {
1531 let resolveGreeting;
1532 const greetingPromise = new Promise(resolve => {
@@ -1581,7 +1580,6 @@ describe('ReactFlightDOMEdge', () => {
1580 expect(result).toBe('<div>hello world</div>');
1581 });
1582
1584 - // @gate enableHalt
1583 it('does not propagate abort reasons errors when aborting a prerender', async () => {
1584 let resolveGreeting;
1585 const greetingPromise = new Promise(resolve => {
@@ -1661,7 +1659,6 @@ describe('ReactFlightDOMEdge', () => {
1659 expect(div.textContent).toBe('loading...');
1660 });
1661
1664 - // @gate enableHalt
1662 it('should abort parsing an incomplete prerender payload', async () => {
1663 const infinitePromise = new Promise(() => {});
1664 const controller = new AbortController();
@@ -1709,7 +1706,6 @@ describe('ReactFlightDOMEdge', () => {
1706 expect(error.message).toBe('Connection closed.');
1707 });
1708
1712 - // @gate enableHalt
1709 it('should be able to handle a rejected promise in prerender', async () => {
1710 const expectedError = new Error('Bam!');
1711 const errors = [];
@@ -1748,7 +1744,6 @@ describe('ReactFlightDOMEdge', () => {
1744 expect(error.message).toBe(expectedMessage);
1745 });
1746
1751 - // @gate enableHalt
1747 it('should be able to handle an erroring async iterable in prerender', async () => {
1748 const expectedError = new Error('Bam!');
1749 const errors = [];
@@ -1795,7 +1790,6 @@ describe('ReactFlightDOMEdge', () => {
1790 expect(error.message).toBe(expectedMessage);
1791 });
1792
1798 - // @gate enableHalt
1793 it('should be able to handle an erroring readable stream in prerender', async () => {
1794 const expectedError = new Error('Bam!');
1795 const errors = [];
@@ -1843,7 +1837,6 @@ describe('ReactFlightDOMEdge', () => {
1837 expect(error.message).toBe(expectedMessage);
1838 });
1839
1846 - // @gate enableHalt
1840 it('can prerender an async iterable', async () => {
1841 const errors = [];
1842
@@ -1887,7 +1880,6 @@ describe('ReactFlightDOMEdge', () => {
1880 expect(text).toBe('hello world');
1881 });
1882
1890 - // @gate enableHalt
1883 it('can prerender a readable stream', async () => {
1884 const errors = [];
1885
@@ -1921,7 +1913,6 @@ describe('ReactFlightDOMEdge', () => {
1913 expect(result).toBe('hello world');
1914 });
1915
1924 - // @gate enableHalt
1916 it('does not return a prerender prelude early when an error is emitted and there are still pending tasks', async () => {
1917 let rejectPromise;
1918 const rejectingPromise = new Promise(
@@ -1990,7 +1981,6 @@ describe('ReactFlightDOMEdge', () => {
1981 expect(error.message).toBe(expectedMessage);
1982 });
1983
1993 - // @gate enableHalt
1984 it('does not include source locations in component stacks for halted components', async () => {
1985 // We only support adding source locations for halted components in the Node.js builds.
1986
packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMNode-test.js
+10 -17
@@ -548,7 +548,6 @@ describe('ReactFlightDOMNode', () => {
548 expect(errors).toEqual([reason]);
549 });
550
551 - // @gate enableHalt
551 it('can prerender', async () => {
552 let resolveGreeting;
553 const greetingPromise = new Promise(resolve => {
@@ -602,7 +601,6 @@ describe('ReactFlightDOMNode', () => {
601 expect(result).toBe('<div>hello world</div>');
602 });
603
605 - // @gate enableHalt
604 it('does not propagate abort reasons errors when aborting a prerender', async () => {
605 let resolveGreeting;
606 const greetingPromise = new Promise(resolve => {
@@ -675,7 +673,6 @@ describe('ReactFlightDOMNode', () => {
673 expect(result).toContain('loading...');
674 });
675
678 - // @gate enableHalt
676 it('includes source locations in component and owner stacks for halted components', async () => {
677 async function Component() {
678 await new Promise(() => {});
@@ -810,7 +807,6 @@ describe('ReactFlightDOMNode', () => {
807 }
808 });
809
813 - // @gate enableHalt
810 it('includes source locations in component and owner stacks for halted Client components', async () => {
811 function SharedComponent({p1, p2, p3}) {
812 use(p1);
@@ -959,17 +955,16 @@ describe('ReactFlightDOMNode', () => {
955 // The concrete location may change as this test is updated.
956 // Just make sure they still point at React.use(p2)
957 (gate(flags => flags.enableAsyncDebugInfo)
962 - ? '\n at SharedComponent (./ReactFlightDOMNode-test.js:817:7)'
958 + ? '\n at SharedComponent (./ReactFlightDOMNode-test.js:813:7)'
959 : '') +
964 - '\n at ServerComponent (file://./ReactFlightDOMNode-test.js:839:26)' +
965 - '\n at App (file://./ReactFlightDOMNode-test.js:856:25)',
960 + '\n at ServerComponent (file://./ReactFlightDOMNode-test.js:835:26)' +
961 + '\n at App (file://./ReactFlightDOMNode-test.js:852:25)',
962 );
963 } else {
964 expect(ownerStack).toBeNull();
965 }
966 });
967
972 - // @gate enableHalt
968 it('includes deeper location for aborted stacks', async () => {
969 async function getData() {
970 const signal = ReactServer.cacheSignal();
@@ -1127,8 +1122,6 @@ describe('ReactFlightDOMNode', () => {
1122 }
1123 });
1124
1130 - // @gate enableHalt
1131 - // @gate enableHalt
1125 it('can handle an empty prelude when prerendering', async () => {
1126 function App() {
1127 return null;
@@ -1549,12 +1542,12 @@ describe('ReactFlightDOMNode', () => {
1542 '\n' +
1543 ' in Dynamic' +
1544 (gate(flags => flags.enableAsyncDebugInfo)
1552 - ? ' (file://ReactFlightDOMNode-test.js:1423:27)\n'
1545 + ? ' (file://ReactFlightDOMNode-test.js:1416:27)\n'
1546 : '\n') +
1547 ' in body\n' +
1548 ' in html\n' +
1556 - ' in App (file://ReactFlightDOMNode-test.js:1436:25)\n' +
1557 - ' in ClientRoot (ReactFlightDOMNode-test.js:1511:16)',
1549 + ' in App (file://ReactFlightDOMNode-test.js:1429:25)\n' +
1550 + ' in ClientRoot (ReactFlightDOMNode-test.js:1504:16)',
1551 );
1552 } else {
1553 expect(
@@ -1563,7 +1556,7 @@ describe('ReactFlightDOMNode', () => {
1556 '\n' +
1557 ' in body\n' +
1558 ' in html\n' +
1566 - ' in ClientRoot (ReactFlightDOMNode-test.js:1511:16)',
1559 + ' in ClientRoot (ReactFlightDOMNode-test.js:1504:16)',
1560 );
1561 }
1562
@@ -1573,8 +1566,8 @@ describe('ReactFlightDOMNode', () => {
1566 normalizeCodeLocInfo(ownerStack, {preserveLocation: true}),
1567 ).toBe(
1568 '\n' +
1576 - ' in Dynamic (file://ReactFlightDOMNode-test.js:1423:27)\n' +
1577 - ' in App (file://ReactFlightDOMNode-test.js:1436:25)',
1569 + ' in Dynamic (file://ReactFlightDOMNode-test.js:1416:27)\n' +
1570 + ' in App (file://ReactFlightDOMNode-test.js:1429:25)',
1571 );
1572 } else {
1573 expect(
@@ -1582,7 +1575,7 @@ describe('ReactFlightDOMNode', () => {
1575 ).toBe(
1576 '' +
1577 '\n' +
1585 - ' in App (file://ReactFlightDOMNode-test.js:1436:25)',
1578 + ' in App (file://ReactFlightDOMNode-test.js:1429:25)',
1579 );
1580 }
1581 } else {
packages/react-server/src/ReactFizzServer.js
+14 -25
@@ -178,7 +178,6 @@ import {
178 disableLegacyContext,
179 disableLegacyContextForFunctionComponents,
180 enableScopeAPI,
181 - enableHalt,
181 enableAsyncIterableChildren,
182 enableViewTransition,
183 enableFizzBlockingRender,
@@ -4643,11 +4642,7 @@ function abortTask(task: Task, request: Request, error: mixed): void {
4642 if (replay === null) {
4643 // We didn't complete the root so we have nothing to show. We can close
4644 // the request;
4646 - if (
4647 - enableHalt &&
4648 - request.trackedPostpones !== null &&
4649 - segment !== null
4650 - ) {
4645 + if (request.trackedPostpones !== null && segment !== null) {
4646 const trackedPostpones = request.trackedPostpones;
4647 // We are aborting a prerender and must treat the shell as halted
4648 // We log the error but we still resolve the prerender
@@ -4693,20 +4688,18 @@ function abortTask(task: Task, request: Request, error: mixed): void {
4688 // boundary the message is referring to
4689 const trackedPostpones = request.trackedPostpones;
4690 if (boundary.status !== CLIENT_RENDERED) {
4696 - if (enableHalt) {
4697 - if (trackedPostpones !== null && segment !== null) {
4698 - // We are aborting a prerender and must halt this boundary.
4699 - // We treat this like other postpones during prerendering
4700 - logRecoverableError(request, error, errorInfo, task.debugTask);
4701 - trackPostpone(request, trackedPostpones, task, segment);
4702 - // If this boundary was still pending then we haven't already cancelled its fallbacks.
4703 - // We'll need to abort the fallbacks, which will also error that parent boundary.
4704 - boundary.fallbackAbortableTasks.forEach(fallbackTask =>
4705 - abortTask(fallbackTask, request, error),
4706 - );
4707 - boundary.fallbackAbortableTasks.clear();
4708 - return finishedTask(request, boundary, task.row, segment);
4709 - }
4691 + if (trackedPostpones !== null && segment !== null) {
4692 + // We are aborting a prerender and must halt this boundary.
4693 + // We treat this like other postpones during prerendering
4694 + logRecoverableError(request, error, errorInfo, task.debugTask);
4695 + trackPostpone(request, trackedPostpones, task, segment);
4696 + // If this boundary was still pending then we haven't already cancelled its fallbacks.
4697 + // We'll need to abort the fallbacks, which will also error that parent boundary.
4698 + boundary.fallbackAbortableTasks.forEach(fallbackTask =>
4699 + abortTask(fallbackTask, request, error),
4700 + );
4701 + boundary.fallbackAbortableTasks.clear();
4702 + return finishedTask(request, boundary, task.row, segment);
4703 }
4704 boundary.status = CLIENT_RENDERED;
4705 // We are aborting a render or resume which should put boundaries
@@ -5110,11 +5103,7 @@ function retryRenderTask(
5103 ? request.fatalError
5104 : thrownValue;
5105
5113 - if (
5114 - enableHalt &&
5115 - request.status === ABORTING &&
5116 - request.trackedPostpones !== null
5117 - ) {
5106 + if (request.status === ABORTING && request.trackedPostpones !== null) {
5107 // We are aborting a prerender and need to halt this task.
5108 const trackedPostpones = request.trackedPostpones;
5109 const thrownInfo = getThrownInfo(task.componentStack);
packages/react-server/src/ReactFlightServer.js
+7 -8
@@ -12,7 +12,6 @@ import type {Chunk, BinaryChunk, Destination} from './ReactServerStreamConfig';
12 import type {TemporaryReferenceSet} from './ReactFlightServerTemporaryReferences';
13
14 import {
15 - enableHalt,
15 enableTaint,
16 enableProfilerTimer,
17 enableComponentPerformanceTrack,
@@ -1083,7 +1082,7 @@ function serializeThenable(
1082 if (request.status === ABORTING) {
1083 // We can no longer accept any resolved values
1084 request.abortableTasks.delete(newTask);
1086 - if (enableHalt && request.type === PRERENDER) {
1085 + if (request.type === PRERENDER) {
1086 haltTask(newTask, request);
1087 finishHaltedTask(newTask, request);
1088 } else {
@@ -1245,7 +1244,7 @@ function serializeReadableStream(
1244 const signal = request.cacheController.signal;
1245 signal.removeEventListener('abort', abortStream);
1246 const reason = signal.reason;
1248 - if (enableHalt && request.type === PRERENDER) {
1247 + if (request.type === PRERENDER) {
1248 request.abortableTasks.delete(streamTask);
1249 haltTask(streamTask, request);
1250 finishHaltedTask(streamTask, request);
@@ -1379,7 +1378,7 @@ function serializeAsyncIterable(
1378 const signal = request.cacheController.signal;
1379 signal.removeEventListener('abort', abortIterable);
1380 const reason = signal.reason;
1382 - if (enableHalt && request.type === PRERENDER) {
1381 + if (request.type === PRERENDER) {
1382 request.abortableTasks.delete(streamTask);
1383 haltTask(streamTask, request);
1384 finishHaltedTask(streamTask, request);
@@ -3322,7 +3321,7 @@ function serializeBlob(request: Request, blob: Blob): string {
3321 const signal = request.cacheController.signal;
3322 signal.removeEventListener('abort', abortBlob);
3323 const reason = signal.reason;
3325 - if (enableHalt && request.type === PRERENDER) {
3324 + if (request.type === PRERENDER) {
3325 request.abortableTasks.delete(newTask);
3326 haltTask(newTask, request);
3327 finishHaltedTask(newTask, request);
@@ -3383,7 +3382,7 @@ function renderModel(
3382
3383 if (request.status === ABORTING) {
3384 task.status = ABORTED;
3386 - if (enableHalt && request.type === PRERENDER) {
3385 + if (request.type === PRERENDER) {
3386 // This will create a new task and refer to it in this slot
3387 // the new task won't be retried because we are aborting
3388 return outlineHaltedTask(request, task, wasReactNode);
@@ -5814,7 +5813,7 @@ function retryTask(request: Request, task: Task): void {
5813 if (request.status === ABORTING) {
5814 request.abortableTasks.delete(task);
5815 task.status = PENDING;
5817 - if (enableHalt && request.type === PRERENDER) {
5816 + if (request.type === PRERENDER) {
5817 // When aborting a prerener with halt semantics we don't emit
5818 // anything into the slot for a task that aborts, it remains unresolved
5819 haltTask(task, request);
@@ -6251,7 +6250,7 @@ export function abort(request: Request, reason: mixed): void {
6250 request.cacheController.abort(reason);
6251 const abortableTasks = request.abortableTasks;
6252 if (abortableTasks.size > 0) {
6254 - if (enableHalt && request.type === PRERENDER) {
6253 + if (request.type === PRERENDER) {
6254 // When prerendering with halt semantics we simply halt the task
6255 // and leave the reference unfulfilled.
6256 abortableTasks.forEach(task => haltTask(task, request));
packages/shared/ReactFeatureFlags.js
-2
@@ -78,8 +78,6 @@ export const enableAsyncIterableChildren = __EXPERIMENTAL__;
78
79 export const enableTaint = __EXPERIMENTAL__;
80
81 -export const enableHalt: boolean = true;
82 -
81 export const enableViewTransition: boolean = true;
82
83 export const enableGestureTransition = __EXPERIMENTAL__;
packages/shared/forks/ReactFeatureFlags.native-fb.js
-1
@@ -46,7 +46,6 @@ export const enableCPUSuspense: boolean = true;
46 export const enableCreateEventHandleAPI: boolean = false;
47 export const enableMoveBefore: boolean = true;
48 export const enableFizzExternalRuntime: boolean = true;
49 -export const enableHalt: boolean = true;
49 export const enableInfiniteRenderLoopDetection: boolean = false;
50 export const enableLegacyCache: boolean = false;
51 export const enableLegacyFBSupport: boolean = false;
packages/shared/forks/ReactFeatureFlags.native-oss.js
-1
@@ -30,7 +30,6 @@ export const enableCPUSuspense: boolean = false;
30 export const enableCreateEventHandleAPI: boolean = false;
31 export const enableMoveBefore: boolean = true;
32 export const enableFizzExternalRuntime: boolean = true;
33 -export const enableHalt: boolean = true;
33 export const enableHiddenSubtreeInsertionEffectCleanup: boolean = false;
34 export const enableInfiniteRenderLoopDetection: boolean = false;
35 export const enableLegacyCache: boolean = false;
packages/shared/forks/ReactFeatureFlags.test-renderer.js
-1
@@ -21,7 +21,6 @@ export const enableUpdaterTracking: boolean = false;
21 export const enableLegacyCache: boolean = __EXPERIMENTAL__;
22 export const enableAsyncIterableChildren: boolean = false;
23 export const enableTaint: boolean = true;
24 -export const enableHalt: boolean = true;
24 export const disableCommentsAsDOMContainers: boolean = true;
25 export const disableInputAttributeSyncing: boolean = false;
26 export const enableScopeAPI: boolean = false;
packages/shared/forks/ReactFeatureFlags.test-renderer.native-fb.js
-1
@@ -25,7 +25,6 @@ export const enableCPUSuspense = true;
25 export const enableCreateEventHandleAPI = false;
26 export const enableMoveBefore = false;
27 export const enableFizzExternalRuntime = true;
28 -export const enableHalt = true;
28 export const enableInfiniteRenderLoopDetection = false;
29 export const enableHiddenSubtreeInsertionEffectCleanup = true;
30 export const enableLegacyCache = false;
packages/shared/forks/ReactFeatureFlags.test-renderer.www.js
-1
@@ -21,7 +21,6 @@ export const enableUpdaterTracking: boolean = false;
21 export const enableLegacyCache: boolean = true;
22 export const enableAsyncIterableChildren: boolean = false;
23 export const enableTaint: boolean = true;
24 -export const enableHalt: boolean = true;
24 export const disableCommentsAsDOMContainers: boolean = true;
25 export const disableInputAttributeSyncing: boolean = false;
26 export const enableScopeAPI: boolean = true;
packages/shared/forks/ReactFeatureFlags.www.js
-2
@@ -74,8 +74,6 @@ export const enableAsyncIterableChildren: boolean = false;
74
75 export const enableTaint: boolean = false;
76
77 -export const enableHalt: boolean = true;
78 -
77 // TODO: www currently relies on this feature. It's disabled in open source.
78 // Need to remove it.
79 export const disableCommentsAsDOMContainers: boolean = false;