[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;