Cleanup enableFloat flag (#28613)

Cleanup enableFloat flag
This commit is contained in:
Jan Kassens
2024-03-22 12:22:30 -04:00
committed by GitHub
parent 6708115937
commit 208ceeb46c
31 changed files with 626 additions and 1074 deletions
@@ -34,7 +34,7 @@ import {
import {getParentSuspenseInstance} from './ReactFiberConfigDOM';
import {enableScopeAPI, enableFloat} from 'shared/ReactFeatureFlags';
import {enableScopeAPI} from 'shared/ReactFeatureFlags';
const randomKey = Math.random().toString(36).slice(2);
const internalInstanceKey = '__reactFiber$' + randomKey;
@@ -175,7 +175,7 @@ export function getInstanceFromNode(node: Node): Fiber | null {
tag === HostComponent ||
tag === HostText ||
tag === SuspenseComponent ||
(enableFloat ? tag === HostHoistable : false) ||
tag === HostHoistable ||
tag === HostSingleton ||
tag === HostRoot
) {
@@ -195,7 +195,7 @@ export function getNodeFromInstance(inst: Fiber): Instance | TextInstance {
const tag = inst.tag;
if (
tag === HostComponent ||
(enableFloat ? tag === HostHoistable : false) ||
tag === HostHoistable ||
tag === HostSingleton ||
tag === HostText
) {
@@ -91,7 +91,6 @@ import {
enableBigIntSupport,
enableCreateEventHandleAPI,
enableScopeAPI,
enableFloat,
enableTrustedTypesIntegration,
enableFormActions,
enableAsyncActions,
@@ -2161,25 +2160,16 @@ function preconnectAs(
}
function prefetchDNS(href: string) {
if (!enableFloat) {
return;
}
previousDispatcher.prefetchDNS(href);
preconnectAs('dns-prefetch', href, null);
}
function preconnect(href: string, crossOrigin?: ?CrossOriginEnum) {
if (!enableFloat) {
return;
}
previousDispatcher.preconnect(href, crossOrigin);
preconnectAs('preconnect', href, crossOrigin);
}
function preload(href: string, as: string, options?: ?PreloadImplOptions) {
if (!enableFloat) {
return;
}
previousDispatcher.preload(href, as, options);
const ownerDocument = getGlobalDocument();
if (ownerDocument && href && as) {
@@ -2258,9 +2248,6 @@ function preload(href: string, as: string, options?: ?PreloadImplOptions) {
}
function preloadModule(href: string, options?: ?PreloadModuleImplOptions) {
if (!enableFloat) {
return;
}
previousDispatcher.preloadModule(href, options);
const ownerDocument = getGlobalDocument();
if (ownerDocument && href) {
@@ -2322,9 +2309,6 @@ function preinitStyle(
precedence: ?string,
options?: ?PreinitStyleOptions,
) {
if (!enableFloat) {
return;
}
previousDispatcher.preinitStyle(href, precedence, options);
const ownerDocument = getGlobalDocument();
@@ -2399,9 +2383,6 @@ function preinitStyle(
}
function preinitScript(src: string, options?: ?PreinitScriptOptions) {
if (!enableFloat) {
return;
}
previousDispatcher.preinitScript(src, options);
const ownerDocument = getGlobalDocument();
@@ -2458,9 +2439,6 @@ function preinitModuleScript(
src: string,
options?: ?PreinitModuleScriptOptions,
) {
if (!enableFloat) {
return;
}
previousDispatcher.preinitModuleScript(src, options);
const ownerDocument = getGlobalDocument();
@@ -52,7 +52,6 @@ import {
enableLegacyFBSupport,
enableCreateEventHandleAPI,
enableScopeAPI,
enableFloat,
enableFormActions,
} from 'shared/ReactFeatureFlags';
import {createEventListenerWrapperWithPriority} from './ReactDOMEventListener';
@@ -647,7 +646,7 @@ export function dispatchEventForPluginEventSystem(
if (
parentTag === HostComponent ||
parentTag === HostText ||
(enableFloat ? parentTag === HostHoistable : false) ||
parentTag === HostHoistable ||
parentTag === HostSingleton
) {
node = ancestorInst = parentNode;
@@ -705,7 +704,7 @@ export function accumulateSinglePhaseListeners(
// Handle listeners that are on HostComponents (i.e. <div>)
if (
(tag === HostComponent ||
(enableFloat ? tag === HostHoistable : false) ||
tag === HostHoistable ||
tag === HostSingleton) &&
stateNode !== null
) {
@@ -819,7 +818,7 @@ export function accumulateTwoPhaseListeners(
// Handle listeners that are on HostComponents (i.e. <div>)
if (
(tag === HostComponent ||
(enableFloat ? tag === HostHoistable : false) ||
tag === HostHoistable ||
tag === HostSingleton) &&
stateNode !== null
) {
@@ -922,7 +921,7 @@ function accumulateEnterLeaveListenersForEvent(
}
if (
(tag === HostComponent ||
(enableFloat ? tag === HostHoistable : false) ||
tag === HostHoistable ||
tag === HostSingleton) &&
stateNode !== null
) {
@@ -16,8 +16,6 @@ import type {
PreinitModuleScriptOptions,
} from 'react-dom/src/shared/ReactDOMTypes';
import {enableFloat} from 'shared/ReactFeatureFlags';
import {
emitHint,
getHints,
@@ -40,107 +38,99 @@ ReactDOMCurrentDispatcher.current = {
};
function prefetchDNS(href: string) {
if (enableFloat) {
if (typeof href === 'string' && href) {
const request = resolveRequest();
if (request) {
const hints = getHints(request);
const key = 'D|' + href;
if (hints.has(key)) {
// duplicate hint
return;
}
hints.add(key);
emitHint(request, 'D', href);
} else {
previousDispatcher.prefetchDNS(href);
if (typeof href === 'string' && href) {
const request = resolveRequest();
if (request) {
const hints = getHints(request);
const key = 'D|' + href;
if (hints.has(key)) {
// duplicate hint
return;
}
hints.add(key);
emitHint(request, 'D', href);
} else {
previousDispatcher.prefetchDNS(href);
}
}
}
function preconnect(href: string, crossOrigin?: ?CrossOriginEnum) {
if (enableFloat) {
if (typeof href === 'string') {
const request = resolveRequest();
if (request) {
const hints = getHints(request);
if (typeof href === 'string') {
const request = resolveRequest();
if (request) {
const hints = getHints(request);
const key = `C|${crossOrigin == null ? 'null' : crossOrigin}|${href}`;
if (hints.has(key)) {
// duplicate hint
return;
}
hints.add(key);
if (typeof crossOrigin === 'string') {
emitHint(request, 'C', [href, crossOrigin]);
} else {
emitHint(request, 'C', href);
}
} else {
previousDispatcher.preconnect(href, crossOrigin);
const key = `C|${crossOrigin == null ? 'null' : crossOrigin}|${href}`;
if (hints.has(key)) {
// duplicate hint
return;
}
hints.add(key);
if (typeof crossOrigin === 'string') {
emitHint(request, 'C', [href, crossOrigin]);
} else {
emitHint(request, 'C', href);
}
} else {
previousDispatcher.preconnect(href, crossOrigin);
}
}
}
function preload(href: string, as: string, options?: ?PreloadImplOptions) {
if (enableFloat) {
if (typeof href === 'string') {
const request = resolveRequest();
if (request) {
const hints = getHints(request);
let key = 'L';
if (as === 'image' && options) {
key += getImagePreloadKey(
href,
options.imageSrcSet,
options.imageSizes,
);
} else {
key += `[${as}]${href}`;
}
if (hints.has(key)) {
// duplicate hint
return;
}
hints.add(key);
const trimmed = trimOptions(options);
if (trimmed) {
emitHint(request, 'L', [href, as, trimmed]);
} else {
emitHint(request, 'L', [href, as]);
}
if (typeof href === 'string') {
const request = resolveRequest();
if (request) {
const hints = getHints(request);
let key = 'L';
if (as === 'image' && options) {
key += getImagePreloadKey(
href,
options.imageSrcSet,
options.imageSizes,
);
} else {
previousDispatcher.preload(href, as, options);
key += `[${as}]${href}`;
}
if (hints.has(key)) {
// duplicate hint
return;
}
hints.add(key);
const trimmed = trimOptions(options);
if (trimmed) {
emitHint(request, 'L', [href, as, trimmed]);
} else {
emitHint(request, 'L', [href, as]);
}
} else {
previousDispatcher.preload(href, as, options);
}
}
}
function preloadModule(href: string, options?: ?PreloadModuleImplOptions) {
if (enableFloat) {
if (typeof href === 'string') {
const request = resolveRequest();
if (request) {
const hints = getHints(request);
const key = 'm|' + href;
if (hints.has(key)) {
// duplicate hint
return;
}
hints.add(key);
const trimmed = trimOptions(options);
if (trimmed) {
return emitHint(request, 'm', [href, trimmed]);
} else {
return emitHint(request, 'm', href);
}
} else {
previousDispatcher.preloadModule(href, options);
if (typeof href === 'string') {
const request = resolveRequest();
if (request) {
const hints = getHints(request);
const key = 'm|' + href;
if (hints.has(key)) {
// duplicate hint
return;
}
hints.add(key);
const trimmed = trimOptions(options);
if (trimmed) {
return emitHint(request, 'm', [href, trimmed]);
} else {
return emitHint(request, 'm', href);
}
} else {
previousDispatcher.preloadModule(href, options);
}
}
}
@@ -150,59 +140,55 @@ function preinitStyle(
precedence: ?string,
options?: ?PreinitStyleOptions,
) {
if (enableFloat) {
if (typeof href === 'string') {
const request = resolveRequest();
if (request) {
const hints = getHints(request);
const key = 'S|' + href;
if (hints.has(key)) {
// duplicate hint
return;
}
hints.add(key);
const trimmed = trimOptions(options);
if (trimmed) {
return emitHint(request, 'S', [
href,
typeof precedence === 'string' ? precedence : 0,
trimmed,
]);
} else if (typeof precedence === 'string') {
return emitHint(request, 'S', [href, precedence]);
} else {
return emitHint(request, 'S', href);
}
} else {
previousDispatcher.preinitStyle(href, precedence, options);
if (typeof href === 'string') {
const request = resolveRequest();
if (request) {
const hints = getHints(request);
const key = 'S|' + href;
if (hints.has(key)) {
// duplicate hint
return;
}
hints.add(key);
const trimmed = trimOptions(options);
if (trimmed) {
return emitHint(request, 'S', [
href,
typeof precedence === 'string' ? precedence : 0,
trimmed,
]);
} else if (typeof precedence === 'string') {
return emitHint(request, 'S', [href, precedence]);
} else {
return emitHint(request, 'S', href);
}
} else {
previousDispatcher.preinitStyle(href, precedence, options);
}
}
}
function preinitScript(src: string, options?: ?PreinitScriptOptions) {
if (enableFloat) {
if (typeof src === 'string') {
const request = resolveRequest();
if (request) {
const hints = getHints(request);
const key = 'X|' + src;
if (hints.has(key)) {
// duplicate hint
return;
}
hints.add(key);
const trimmed = trimOptions(options);
if (trimmed) {
return emitHint(request, 'X', [src, trimmed]);
} else {
return emitHint(request, 'X', src);
}
} else {
previousDispatcher.preinitScript(src, options);
if (typeof src === 'string') {
const request = resolveRequest();
if (request) {
const hints = getHints(request);
const key = 'X|' + src;
if (hints.has(key)) {
// duplicate hint
return;
}
hints.add(key);
const trimmed = trimOptions(options);
if (trimmed) {
return emitHint(request, 'X', [src, trimmed]);
} else {
return emitHint(request, 'X', src);
}
} else {
previousDispatcher.preinitScript(src, options);
}
}
}
@@ -211,27 +197,25 @@ function preinitModuleScript(
src: string,
options?: ?PreinitModuleScriptOptions,
) {
if (enableFloat) {
if (typeof src === 'string') {
const request = resolveRequest();
if (request) {
const hints = getHints(request);
const key = 'M|' + src;
if (hints.has(key)) {
// duplicate hint
return;
}
hints.add(key);
const trimmed = trimOptions(options);
if (trimmed) {
return emitHint(request, 'M', [src, trimmed]);
} else {
return emitHint(request, 'M', src);
}
} else {
previousDispatcher.preinitModuleScript(src, options);
if (typeof src === 'string') {
const request = resolveRequest();
if (request) {
const hints = getHints(request);
const key = 'M|' + src;
if (hints.has(key)) {
// duplicate hint
return;
}
hints.add(key);
const trimmed = trimOptions(options);
if (trimmed) {
return emitHint(request, 'M', [src, trimmed]);
} else {
return emitHint(request, 'M', src);
}
} else {
previousDispatcher.preinitModuleScript(src, options);
}
}
}
File diff suppressed because it is too large Load Diff
+40 -107
View File
@@ -5080,7 +5080,6 @@ describe('ReactDOMFizzServer', () => {
);
});
// @gate enableFloat
it('can emit the preamble even if the head renders asynchronously', async () => {
function AsyncNoOutput() {
readText('nooutput');
@@ -5133,7 +5132,6 @@ describe('ReactDOMFizzServer', () => {
);
});
// @gate enableFloat
it('holds back body and html closing tags (the postamble) until all pending tasks are completed', async () => {
const chunks = [];
writable.on('data', chunk => {
@@ -5734,14 +5732,7 @@ describe('ReactDOMFizzServer', () => {
', or object with a novel `toString` method but found an Array with length 2 instead. Browsers treat all child Nodes of <title> tags as Text content and React expects to be able to convert `children` of <title> tags to a single string value which is why Arrays of length greater than 1 are not supported. When using JSX it can be commong to combine text nodes and value nodes. For example: <title>hello {nameOfUser}</title>. While not immediately apparent, `children` in this case is an Array with length 2. If your `children` prop is using this form try rewriting it using a template string: <title>{`hello ${nameOfUser}`}</title>.',
]);
if (gate(flags => flags.enableFloat)) {
expect(getVisibleChildren(document.head)).toEqual(<title />);
} else {
expect(getVisibleChildren(document.head)).toEqual(
<title>{'hello1<!-- -->hello2'}</title>,
);
}
expect(getVisibleChildren(document.head)).toEqual(<title />);
const errors = [];
ReactDOMClient.hydrateRoot(document.head, <App />, {
onRecoverableError(error) {
@@ -5749,24 +5740,9 @@ describe('ReactDOMFizzServer', () => {
},
});
await waitForAll([]);
if (gate(flags => flags.enableFloat)) {
expect(errors).toEqual([]);
// with float, the title doesn't render on the client or on the server
expect(getVisibleChildren(document.head)).toEqual(<title />);
} else {
expect(errors).toEqual(
[
gate(flags => flags.enableClientRenderFallbackOnTextMismatch)
? 'Text content does not match server-rendered HTML.'
: null,
'Hydration failed because the initial UI does not match what was rendered on the server.',
'There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.',
].filter(Boolean),
);
expect(getVisibleChildren(document.head)).toEqual(
<title>{['hello1', 'hello2']}</title>,
);
}
expect(errors).toEqual([]);
// with float, the title doesn't render on the client or on the server
expect(getVisibleChildren(document.head)).toEqual(<title />);
});
it('should warn in dev if you pass a React Component as a child to <title>', async () => {
@@ -5784,37 +5760,20 @@ describe('ReactDOMFizzServer', () => {
);
}
if (gate(flags => flags.enableFloat)) {
await expect(async () => {
await act(() => {
const {pipe} = renderToPipeableStream(<App />);
pipe(writable);
});
}).toErrorDev([
'React expects the `children` prop of <title> tags to be a string, number' +
gate(flags => (flags.enableBigIntSupport ? ', bigint' : '')) +
', or object with a novel `toString` method but found an object that appears to be a React element which never implements a suitable `toString` method. Browsers treat all child Nodes of <title> tags as Text content and React expects to be able to convert children of <title> tags to a single string value which is why rendering React elements is not supported. If the `children` of <title> is a React Component try moving the <title> tag into that component. If the `children` of <title> is some HTML markup change it to be Text only to be valid HTML.',
]);
} else {
await expect(async () => {
await act(() => {
const {pipe} = renderToPipeableStream(<App />);
pipe(writable);
});
}).toErrorDev([
'A title element received a React element for children. In the browser title Elements can only have Text Nodes as children. If the children being rendered output more than a single text node in aggregate the browser will display markup and comments as text in the title and hydration will likely fail and fall back to client rendering',
]);
}
if (gate(flags => flags.enableFloat)) {
// object titles are toStringed when float is on
expect(getVisibleChildren(document.head)).toEqual(
<title>{'[object Object]'}</title>,
);
} else {
expect(getVisibleChildren(document.head)).toEqual(<title>hello</title>);
}
await expect(async () => {
await act(() => {
const {pipe} = renderToPipeableStream(<App />);
pipe(writable);
});
}).toErrorDev([
'React expects the `children` prop of <title> tags to be a string, number' +
gate(flags => (flags.enableBigIntSupport ? ', bigint' : '')) +
', or object with a novel `toString` method but found an object that appears to be a React element which never implements a suitable `toString` method. Browsers treat all child Nodes of <title> tags as Text content and React expects to be able to convert children of <title> tags to a single string value which is why rendering React elements is not supported. If the `children` of <title> is a React Component try moving the <title> tag into that component. If the `children` of <title> is some HTML markup change it to be Text only to be valid HTML.',
]);
// object titles are toStringed when float is on
expect(getVisibleChildren(document.head)).toEqual(
<title>{'[object Object]'}</title>,
);
const errors = [];
ReactDOMClient.hydrateRoot(document.head, <App />, {
onRecoverableError(error) {
@@ -5823,14 +5782,10 @@ describe('ReactDOMFizzServer', () => {
});
await waitForAll([]);
expect(errors).toEqual([]);
if (gate(flags => flags.enableFloat)) {
// object titles are toStringed when float is on
expect(getVisibleChildren(document.head)).toEqual(
<title>{'[object Object]'}</title>,
);
} else {
expect(getVisibleChildren(document.head)).toEqual(<title>hello</title>);
}
// object titles are toStringed when float is on
expect(getVisibleChildren(document.head)).toEqual(
<title>{'[object Object]'}</title>,
);
});
it('should warn in dev if you pass an object that does not implement toString as a child to <title>', async () => {
@@ -5842,37 +5797,20 @@ describe('ReactDOMFizzServer', () => {
);
}
if (gate(flags => flags.enableFloat)) {
await expect(async () => {
await act(() => {
const {pipe} = renderToPipeableStream(<App />);
pipe(writable);
});
}).toErrorDev([
'React expects the `children` prop of <title> tags to be a string, number' +
gate(flags => (flags.enableBigIntSupport ? ', bigint' : '')) +
', or object with a novel `toString` method but found an object that does not implement a suitable `toString` method. Browsers treat all child Nodes of <title> tags as Text content and React expects to be able to convert children of <title> tags to a single string value. Using the default `toString` method available on every object is almost certainly an error. Consider whether the `children` of this <title> is an object in error and change it to a string or number value if so. Otherwise implement a `toString` method that React can use to produce a valid <title>.',
]);
} else {
await expect(async () => {
await act(() => {
const {pipe} = renderToPipeableStream(<App />);
pipe(writable);
});
}).toErrorDev([
'A title element received a React element for children. In the browser title Elements can only have Text Nodes as children. If the children being rendered output more than a single text node in aggregate the browser will display markup and comments as text in the title and hydration will likely fail and fall back to client rendering',
]);
}
if (gate(flags => flags.enableFloat)) {
// object titles are toStringed when float is on
expect(getVisibleChildren(document.head)).toEqual(
<title>{'[object Object]'}</title>,
);
} else {
expect(getVisibleChildren(document.head)).toEqual(<title>hello</title>);
}
await expect(async () => {
await act(() => {
const {pipe} = renderToPipeableStream(<App />);
pipe(writable);
});
}).toErrorDev([
'React expects the `children` prop of <title> tags to be a string, number' +
gate(flags => (flags.enableBigIntSupport ? ', bigint' : '')) +
', or object with a novel `toString` method but found an object that does not implement a suitable `toString` method. Browsers treat all child Nodes of <title> tags as Text content and React expects to be able to convert children of <title> tags to a single string value. Using the default `toString` method available on every object is almost certainly an error. Consider whether the `children` of this <title> is an object in error and change it to a string or number value if so. Otherwise implement a `toString` method that React can use to produce a valid <title>.',
]);
// object titles are toStringed when float is on
expect(getVisibleChildren(document.head)).toEqual(
<title>{'[object Object]'}</title>,
);
const errors = [];
ReactDOMClient.hydrateRoot(document.head, <App />, {
onRecoverableError(error) {
@@ -5881,14 +5819,10 @@ describe('ReactDOMFizzServer', () => {
});
await waitForAll([]);
expect(errors).toEqual([]);
if (gate(flags => flags.enableFloat)) {
// object titles are toStringed when float is on
expect(getVisibleChildren(document.head)).toEqual(
<title>{'[object Object]'}</title>,
);
} else {
expect(getVisibleChildren(document.head)).toEqual(<title>hello</title>);
}
// object titles are toStringed when float is on
expect(getVisibleChildren(document.head)).toEqual(
<title>{'[object Object]'}</title>,
);
});
});
@@ -6436,7 +6370,6 @@ describe('ReactDOMFizzServer', () => {
);
});
// @gate enableFloat
it('warns if script has complex children', async () => {
function MyScript() {
return 'bar();';
@@ -62,15 +62,9 @@ describe('ReactDOMFizzServerBrowser', () => {
</html>,
);
const result = await readResult(stream);
if (gate(flags => flags.enableFloat)) {
expect(result).toMatchInlineSnapshot(
`"<!DOCTYPE html><html><head></head><body>hello world</body></html>"`,
);
} else {
expect(result).toMatchInlineSnapshot(
`"<!DOCTYPE html><html><body>hello world</body></html>"`,
);
}
expect(result).toMatchInlineSnapshot(
`"<!DOCTYPE html><html><head></head><body>hello world</body></html>"`,
);
});
it('should emit bootstrap script src at the end', async () => {
@@ -73,16 +73,10 @@ describe('ReactDOMFizzServerNode', () => {
);
pipe(writable);
jest.runAllTimers();
if (gate(flags => flags.enableFloat)) {
// with Float, we emit empty heads if they are elided when rendering <html>
expect(output.result).toMatchInlineSnapshot(
`"<!DOCTYPE html><html><head></head><body>hello world</body></html>"`,
);
} else {
expect(output.result).toMatchInlineSnapshot(
`"<!DOCTYPE html><html><body>hello world</body></html>"`,
);
}
// with Float, we emit empty heads if they are elided when rendering <html>
expect(output.result).toMatchInlineSnapshot(
`"<!DOCTYPE html><html><head></head><body>hello world</body></html>"`,
);
});
it('should emit bootstrap script src at the end', () => {
@@ -126,15 +126,9 @@ describe('ReactDOMFizzStaticBrowser', () => {
</html>,
);
const prelude = await readContent(result.prelude);
if (gate(flags => flags.enableFloat)) {
expect(prelude).toMatchInlineSnapshot(
`"<!DOCTYPE html><html><head></head><body>hello world</body></html>"`,
);
} else {
expect(prelude).toMatchInlineSnapshot(
`"<!DOCTYPE html><html><body>hello world</body></html>"`,
);
}
expect(prelude).toMatchInlineSnapshot(
`"<!DOCTYPE html><html><head></head><body>hello world</body></html>"`,
);
});
// @gate experimental
@@ -63,15 +63,9 @@ describe('ReactDOMFizzStaticNode', () => {
</html>,
);
const prelude = await readContent(result.prelude);
if (gate(flags => flags.enableFloat)) {
expect(prelude).toMatchInlineSnapshot(
`"<!DOCTYPE html><html><head></head><body>hello world</body></html>"`,
);
} else {
expect(prelude).toMatchInlineSnapshot(
`"<!DOCTYPE html><html><body>hello world</body></html>"`,
);
}
expect(prelude).toMatchInlineSnapshot(
`"<!DOCTYPE html><html><head></head><body>hello world</body></html>"`,
);
});
// @gate experimental
+2 -64
View File
@@ -400,7 +400,6 @@ describe('ReactDOMFloat', () => {
}
}
// @gate enableFloat
it('can render resources before singletons', async () => {
const root = ReactDOMClient.createRoot(document);
root.render(
@@ -433,7 +432,6 @@ describe('ReactDOMFloat', () => {
);
});
// @gate enableFloat
it('can hydrate non Resources in head when Resources are also inserted there', async () => {
await act(() => {
const {pipe} = renderToPipeableStream(
@@ -499,7 +497,6 @@ describe('ReactDOMFloat', () => {
);
});
// @gate enableFloat || !__DEV__
it('warns if you render resource-like elements above <head> or <body>', async () => {
const root = ReactDOMClient.createRoot(document);
@@ -631,7 +628,6 @@ describe('ReactDOMFloat', () => {
);
});
// @gate enableFloat
it('can acquire a resource after releasing it in the same commit', async () => {
const root = ReactDOMClient.createRoot(container);
root.render(
@@ -671,7 +667,6 @@ describe('ReactDOMFloat', () => {
);
});
// @gate enableFloat
it('emits an implicit <head> element to hold resources when none is rendered but an <html> is rendered', async () => {
const chunks = [];
@@ -697,7 +692,6 @@ describe('ReactDOMFloat', () => {
]);
});
// @gate enableFloat
it('dedupes if the external runtime is explicitly loaded using preinit', async () => {
const unstable_externalRuntimeSrc = 'src-of-external-runtime';
function App() {
@@ -731,7 +725,6 @@ describe('ReactDOMFloat', () => {
).toEqual(['<script src="src-of-external-runtime" async=""></script>']);
});
// @gate enableFloat
it('can send style insertion implementation independent of boundary commpletion instruction implementation', async () => {
await act(() => {
renderToPipeableStream(
@@ -790,7 +783,6 @@ describe('ReactDOMFloat', () => {
);
});
// @gate enableFloat
it('can avoid inserting a late stylesheet if it already rendered on the client', async () => {
await act(() => {
renderToPipeableStream(
@@ -911,7 +903,6 @@ describe('ReactDOMFloat', () => {
);
});
// @gate enableFloat
it('can hoist <link rel="stylesheet" .../> and <style /> tags together, respecting order of discovery', async () => {
const css = `
body {
@@ -1196,7 +1187,6 @@ body {
);
});
// @gate enableFloat
it('client renders a boundary if a style Resource dependency fails to load', async () => {
function App() {
return (
@@ -1298,7 +1288,6 @@ body {
]);
});
// @gate enableFloat
it('treats stylesheet links with a precedence as a resource', async () => {
await act(() => {
const {pipe} = renderToPipeableStream(
@@ -1339,7 +1328,6 @@ body {
);
});
// @gate enableFloat
it('inserts text separators following text when followed by an element that is converted to a resource and thus removed from the html inline', async () => {
// If you render many of these as siblings the values get emitted as a single text with no separator sometimes
// because the link gets elided as a resource
@@ -1386,7 +1374,6 @@ body {
);
});
// @gate enableFloat
it('hoists late stylesheets the correct precedence', async () => {
function PresetPrecedence() {
ReactDOM.preinit('preset', {as: 'style', precedence: 'preset'});
@@ -1671,7 +1658,6 @@ body {
);
});
// @gate enableFloat
it('normalizes stylesheet resource precedence for all boundaries inlined as part of the shell flush', async () => {
await act(() => {
const {pipe} = renderToPipeableStream(
@@ -1755,7 +1741,6 @@ body {
);
});
// @gate enableFloat
it('stylesheet resources are inserted according to precedence order on the client', async () => {
await act(() => {
const {pipe} = renderToPipeableStream(
@@ -1836,7 +1821,6 @@ body {
);
});
// @gate enableFloat
it('inserts preloads in render phase eagerly', async () => {
function Throw() {
throw new Error('Uh oh!');
@@ -1878,7 +1862,6 @@ body {
);
});
// @gate enableFloat
it('will include child boundary stylesheet resources in the boundary reveal instruction', async () => {
await act(() => {
const {pipe} = renderToPipeableStream(
@@ -1997,7 +1980,6 @@ body {
);
});
// @gate enableFloat
it('will hoist resources of child boundaries emitted as part of a partial boundary to the parent boundary', async () => {
await act(() => {
const {pipe} = renderToPipeableStream(
@@ -2161,7 +2143,6 @@ body {
);
});
// @gate enableFloat
it('encodes attributes consistently whether resources are flushed in shell or in late boundaries', async () => {
function App() {
return (
@@ -2305,7 +2286,6 @@ body {
);
});
// @gate enableFloat
it('boundary stylesheet resource dependencies hoist to a parent boundary when flushed inline', async () => {
await act(() => {
const {pipe} = renderToPipeableStream(
@@ -2428,7 +2408,6 @@ body {
);
});
// @gate enableFloat
it('always enforces crossOrigin "anonymous" for font preloads', async () => {
function App() {
ReactDOM.preload('foo', {as: 'font', type: 'font/woff2'});
@@ -2619,7 +2598,6 @@ body {
]);
});
// @gate enableFloat
it('can hydrate resources and components in the head and body even if a browser or 3rd party script injects extra html nodes', async () => {
// This is a stress test case for hydrating a complex combination of hoistable elements, hoistable resources and host components
// in an environment that has been manipulated by 3rd party scripts/extensions to modify the <head> and <body>
@@ -5195,7 +5173,6 @@ body {
});
describe('ReactDOM.preload(href, { as: ... })', () => {
// @gate enableFloat
it('creates a preload resource when called', async () => {
function App() {
ReactDOM.preload('foo', {as: 'style'});
@@ -5284,7 +5261,6 @@ body {
);
});
// @gate enableFloat
it('can seed connection props for stylesheet and script resources', async () => {
function App() {
ReactDOM.preload('foo', {
@@ -5326,7 +5302,6 @@ body {
);
});
// @gate enableFloat
it('warns if you do not pass in a valid href argument or options argument', async () => {
function App() {
ReactDOM.preload();
@@ -5629,7 +5604,6 @@ body {
});
describe('ReactDOM.preinit(href, { as: ... })', () => {
// @gate enableFloat
it('creates a stylesheet resource when ReactDOM.preinit(..., {as: "style" }) is called', async () => {
function App() {
ReactDOM.preinit('foo', {as: 'style'});
@@ -5713,7 +5687,6 @@ body {
);
});
// @gate enableFloat
it('creates a stylesheet resource in the ownerDocument when ReactDOM.preinit(..., {as: "style" }) is called outside of render on the client', async () => {
function App() {
React.useEffect(() => {
@@ -5739,7 +5712,6 @@ body {
);
});
// @gate enableFloat
it('creates a stylesheet resource in the ownerDocument when ReactDOM.preinit(..., {as: "style" }) is called outside of render on the client', async () => {
// This is testing behavior, but it shows that it is not a good idea to preinit inside a shadowRoot. The point is we are asserting a behavior
// you would want to avoid in a real app.
@@ -5783,7 +5755,6 @@ body {
expect(getMeaningfulChildren(shadow)).toEqual(<div>shadow</div>);
});
// @gate enableFloat
it('creates a script resource when ReactDOM.preinit(..., {as: "script" }) is called', async () => {
function App() {
ReactDOM.preinit('foo', {as: 'script'});
@@ -5861,7 +5832,6 @@ body {
);
});
// @gate enableFloat
it('creates a script resource when ReactDOM.preinit(..., {as: "script" }) is called outside of render on the client', async () => {
function App() {
React.useEffect(() => {
@@ -5887,7 +5857,6 @@ body {
);
});
// @gate enableFloat
it('warns if you do not pass in a valid href argument or options argument', async () => {
function App() {
ReactDOM.preinit();
@@ -6296,7 +6265,6 @@ body {
});
describe('Stylesheet Resources', () => {
// @gate enableFloat
it('treats link rel stylesheet elements as a stylesheet resource when it includes a precedence when server rendering', async () => {
await act(() => {
const {pipe} = renderToPipeableStream(
@@ -6323,7 +6291,6 @@ body {
);
});
// @gate enableFloat
it('treats link rel stylesheet elements as a stylesheet resource when it includes a precedence when client rendering', async () => {
const root = ReactDOMClient.createRoot(document);
root.render(
@@ -6349,7 +6316,6 @@ body {
);
});
// @gate enableFloat
it('treats link rel stylesheet elements as a stylesheet resource when it includes a precedence when hydrating', async () => {
await act(() => {
const {pipe} = renderToPipeableStream(
@@ -6387,7 +6353,6 @@ body {
);
});
// @gate enableFloat
it('hoists stylesheet resources to the correct precedence', async () => {
await act(() => {
const {pipe} = renderToPipeableStream(
@@ -6449,7 +6414,6 @@ body {
);
});
// @gate enableFloat
it('retains styles even after the last referring Resource unmounts', async () => {
// This test is true until a future update where there is some form of garbage collection.
const root = ReactDOMClient.createRoot(document);
@@ -6482,7 +6446,7 @@ body {
);
});
// @gate enableFloat && enableClientRenderFallbackOnTextMismatch
// @gate enableClientRenderFallbackOnTextMismatch
it('retains styles even when a new html, head, and/body mount', async () => {
await act(() => {
const {pipe} = renderToPipeableStream(
@@ -6534,7 +6498,6 @@ body {
);
});
// @gate enableFloat
it('retains styles in head through head remounts', async () => {
const root = ReactDOMClient.createRoot(document);
root.render(
@@ -6585,7 +6548,6 @@ body {
</html>,
);
});
// @gate enableFloat
it('can support styles inside portals to a shadowRoot', async () => {
const shadow = document.body.attachShadow({mode: 'open'});
const root = ReactDOMClient.createRoot(container);
@@ -6629,7 +6591,6 @@ body {
<div>shadow</div>,
]);
});
// @gate enableFloat
it('can support styles inside portals to an element in shadowRoots', async () => {
const template = document.createElement('template');
template.innerHTML =
@@ -6699,7 +6660,6 @@ body {
]);
});
// @gate enableFloat
it('escapes hrefs when selecting matching elements in the document when rendering Resources', async () => {
function App() {
ReactDOM.preload('preload', {as: 'style'});
@@ -6767,7 +6727,6 @@ body {
);
});
// @gate enableFloat
it('escapes hrefs when selecting matching elements in the document when using preload and preinit', async () => {
await act(() => {
const {pipe} = renderToPipeableStream(
@@ -6830,7 +6789,6 @@ body {
);
});
// @gate enableFloat
it('does not create stylesheet resources when inside an <svg> context', async () => {
await act(() => {
const {pipe} = renderToPipeableStream(
@@ -6891,7 +6849,6 @@ body {
);
});
// @gate enableFloat
it('does not create stylesheet resources when inside a <noscript> context', async () => {
await act(() => {
const {pipe} = renderToPipeableStream(
@@ -6933,7 +6890,6 @@ body {
);
});
// @gate enableFloat
it('warns if you provide a `precedence` prop with other props that invalidate the creation of a stylesheet resource', async () => {
await expect(async () => {
await act(() => {
@@ -7006,7 +6962,6 @@ body {
]);
});
// @gate enableFloat
it('will not block displaying a Suspense boundary on a stylesheet with media that does not match', async () => {
await act(() => {
renderToPipeableStream(
@@ -7123,7 +7078,6 @@ body {
});
describe('Style Resource', () => {
// @gate enableFloat
it('treats <style href="..." precedence="..."> elements as a style resource when server rendering', async () => {
const css = `
body {
@@ -7153,7 +7107,6 @@ body {
);
});
// @gate enableFloat
it('can insert style resources as part of a boundary reveal', async () => {
const cssRed = `
body {
@@ -7269,7 +7222,6 @@ background-color: green;
);
});
// @gate enableFloat
it('can emit styles early when a partial boundary flushes', async () => {
const css = 'body { background-color: red; }';
await act(() => {
@@ -7601,7 +7553,6 @@ background-color: green;
});
describe('Script Resources', () => {
// @gate enableFloat
it('treats async scripts without onLoad or onError as Resources', async () => {
await act(() => {
const {pipe} = renderToPipeableStream(
@@ -7681,7 +7632,6 @@ background-color: green;
);
});
// @gate enableFloat
it('does not create script resources when inside an <svg> context', async () => {
await act(() => {
const {pipe} = renderToPipeableStream(
@@ -7742,7 +7692,6 @@ background-color: green;
);
});
// @gate enableFloat
it('does not create script resources when inside a <noscript> context', async () => {
await act(() => {
const {pipe} = renderToPipeableStream(
@@ -7786,7 +7735,6 @@ background-color: green;
});
describe('Hoistables', () => {
// @gate enableFloat
it('can hoist meta tags on the server and hydrate them on the client', async () => {
await act(() => {
const {pipe} = renderToPipeableStream(
@@ -7840,7 +7788,6 @@ background-color: green;
);
});
// @gate enableFloat
it('can hoist meta tags on the client', async () => {
const root = ReactDOMClient.createRoot(container);
await act(() => {
@@ -7862,7 +7809,6 @@ background-color: green;
expect(getMeaningfulChildren(document.head)).toEqual(undefined);
});
// @gate enableFloat
it('can hoist link (non-stylesheet) tags on the server and hydrate them on the client', async () => {
await act(() => {
const {pipe} = renderToPipeableStream(
@@ -7916,7 +7862,6 @@ background-color: green;
);
});
// @gate enableFloat
it('can hoist link (non-stylesheet) tags on the client', async () => {
const root = ReactDOMClient.createRoot(container);
await act(() => {
@@ -7938,7 +7883,6 @@ background-color: green;
expect(getMeaningfulChildren(document.head)).toEqual(undefined);
});
// @gate enableFloat
it('can hoist title tags on the server and hydrate them on the client', async () => {
await act(() => {
const {pipe} = renderToPipeableStream(
@@ -7992,7 +7936,6 @@ background-color: green;
);
});
// @gate enableFloat
it('can hoist title tags on the client', async () => {
const root = ReactDOMClient.createRoot(container);
await act(() => {
@@ -8014,7 +7957,6 @@ background-color: green;
expect(getMeaningfulChildren(document.head)).toEqual(undefined);
});
// @gate enableFloat
it('prioritizes ordering for certain hoistables over others when rendering on the server', async () => {
await act(() => {
const {pipe} = renderToPipeableStream(
@@ -8054,7 +7996,6 @@ background-color: green;
);
});
// @gate enableFloat
it('supports rendering hoistables outside of <html> scope', async () => {
await act(() => {
const {pipe} = renderToPipeableStream(
@@ -8232,7 +8173,6 @@ background-color: green;
);
});
// @gate enableFloat
it('does not hoist inside an <svg> context', async () => {
await act(() => {
const {pipe} = renderToPipeableStream(
@@ -8266,7 +8206,6 @@ background-color: green;
]);
});
// @gate enableFloat
it('does not hoist inside noscript context', async () => {
await act(() => {
const {pipe} = renderToPipeableStream(
@@ -8293,7 +8232,7 @@ background-color: green;
]);
});
// @gate enableFloat && (enableClientRenderFallbackOnTextMismatch || !__DEV__)
// @gate enableClientRenderFallbackOnTextMismatch || !__DEV__
it('can render a title before a singleton even if that singleton clears its contents', async () => {
await act(() => {
const {pipe} = renderToPipeableStream(
@@ -8350,7 +8289,6 @@ background-color: green;
);
});
// @gate enableFloat
it('can update title tags', async () => {
const root = ReactDOMClient.createRoot(container);
await act(() => {
@@ -22,7 +22,6 @@ describe('ReactDOMFloat', () => {
});
// fixes #27177
// @gate enableFloat
it('does not hoist above the <html> tag', async () => {
const result = ReactDOMFizzServer.renderToString(
<html>
+5 -30
View File
@@ -222,21 +222,8 @@ describe('ReactDOMRoot', () => {
});
it('warns if creating a root on the document.body', async () => {
if (gate(flags => flags.enableFloat)) {
// we no longer expect an error for this if float is enabled
ReactDOMClient.createRoot(document.body);
} else {
expect(() => {
ReactDOMClient.createRoot(document.body);
}).toErrorDev(
'createRoot(): Creating roots directly with document.body is ' +
'discouraged, since its children are often manipulated by third-party ' +
'scripts and browser extensions. This may lead to subtle ' +
'reconciliation issues. Try using a container element created ' +
'for your app.',
{withoutStack: true},
);
}
// we no longer expect an error for this if float is enabled
ReactDOMClient.createRoot(document.body);
});
it('warns if updating a root that has had its contents removed', async () => {
@@ -245,21 +232,9 @@ describe('ReactDOMRoot', () => {
await waitForAll([]);
container.innerHTML = '';
if (gate(flags => flags.enableFloat)) {
// When either of these flags are on this validation is turned off so we
// expect there to be no warnings
root.render(<div>Hi</div>);
} else {
expect(() => {
root.render(<div>Hi</div>);
}).toErrorDev(
'It looks like the React-rendered content of the ' +
'root container was removed without using React. This is not ' +
'supported and will cause errors. Instead, call ' +
"root.unmount() to empty a root's container.",
{withoutStack: true},
);
}
// When either of these flags are on this validation is turned off so we
// expect there to be no warnings
root.render(<div>Hi</div>);
});
it('should render different components in same root', async () => {
@@ -123,7 +123,6 @@ describe('ReactDOM HostSingleton', () => {
: children;
}
// @gate enableFloat
it('warns if you render the same singleton twice at the same time', async () => {
const root = ReactDOMClient.createRoot(document);
root.render(
@@ -208,7 +207,6 @@ describe('ReactDOM HostSingleton', () => {
);
});
// @gate enableFloat
it('renders into html, head, and body persistently so the node identities never change and extraneous styles are retained', async () => {
// Server render some html that will get replaced with a client render
await actIntoEmptyDocument(() => {
@@ -806,7 +804,6 @@ describe('ReactDOM HostSingleton', () => {
);
});
// @gate enableFloat
it('clears persistent body when it is the container', async () => {
await actIntoEmptyDocument(() => {
const {pipe} = ReactDOMFizzServer.renderToPipeableStream(
+23 -50
View File
@@ -319,57 +319,30 @@ describe('rendering React components at document', () => {
}
}
if (gate(flags => flags.enableFloat)) {
// with float the title no longer is a hydration mismatch so we get an error on the body mismatch
expect(() => {
ReactDOM.flushSync(() => {
ReactDOMClient.hydrateRoot(
testDocument,
<Component text="Hello world" />,
{
onRecoverableError: error => {
Scheduler.log('Log recoverable error: ' + error.message);
},
// with float the title no longer is a hydration mismatch so we get an error on the body mismatch
expect(() => {
ReactDOM.flushSync(() => {
ReactDOMClient.hydrateRoot(
testDocument,
<Component text="Hello world" />,
{
onRecoverableError: error => {
Scheduler.log('Log recoverable error: ' + error.message);
},
);
});
}).toErrorDev(
[
'Warning: An error occurred during hydration. The server HTML was replaced with client content in <#document>.',
'Expected server HTML to contain a matching text node for "Hello world" in <body>',
],
{withoutStack: 1},
);
assertLog([
'Log recoverable error: Hydration failed because the initial UI does not match what was rendered on the server.',
'Log recoverable error: There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.',
]);
} else {
// getTestDocument() has an extra <meta> that we didn't render.
expect(() => {
ReactDOM.flushSync(() => {
ReactDOMClient.hydrateRoot(
testDocument,
<Component text="Hello world" />,
{
onRecoverableError: error => {
Scheduler.log('Log recoverable error: ' + error.message);
},
},
);
});
}).toErrorDev(
[
'Warning: An error occurred during hydration. The server HTML was replaced with client content in <#document>.',
'Warning: Text content did not match. Server: "test doc" Client: "Hello World"',
],
{withoutStack: 1},
);
assertLog([
'Log recoverable error: Text content does not match server-rendered HTML.',
'Log recoverable error: There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.',
]);
}
},
);
});
}).toErrorDev(
[
'Warning: An error occurred during hydration. The server HTML was replaced with client content in <#document>.',
'Expected server HTML to contain a matching text node for "Hello world" in <body>',
],
{withoutStack: 1},
);
assertLog([
'Log recoverable error: Hydration failed because the initial UI does not match what was rendered on the server.',
'Log recoverable error: There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.',
]);
expect(testDocument.body.innerHTML).toBe('Hello world');
});
@@ -38,7 +38,6 @@ describe('react-dom-server-rendering-stub', () => {
expect(ReactDOM.unstable_runWithPriority).toBe(undefined);
});
// @gate enableFloat
it('provides preload, preloadModule, preinit, and preinitModule exports', async () => {
function App() {
ReactDOM.preload('foo', {as: 'style'});
+1 -2
View File
@@ -21,7 +21,6 @@ import {
} from 'react-reconciler/src/ReactWorkTags';
import {SyntheticEvent} from 'react-dom-bindings/src/events/SyntheticEvent';
import {ELEMENT_NODE} from 'react-dom-bindings/src/client/HTMLNodeType';
import {enableFloat} from 'shared/ReactFeatureFlags';
import assign from 'shared/assign';
import isArray from 'shared/isArray';
@@ -63,7 +62,7 @@ function findAllInRenderedFiberTreeInternal(fiber, test) {
node.tag === HostText ||
node.tag === ClassComponent ||
node.tag === FunctionComponent ||
(enableFloat ? node.tag === HostHoistable : false) ||
node.tag === HostHoistable ||
node.tag === HostSingleton
) {
const publicInst = node.stateNode;
+2 -3
View File
@@ -36,7 +36,6 @@ import {
allowConcurrentByDefault,
enableTransitionTracing,
enableDebugTracing,
enableFloat,
enableDO_NOT_USE_disableStrictPassiveEffect,
enableRenderableContext,
} from 'shared/ReactFeatureFlags';
@@ -508,14 +507,14 @@ export function createFiberFromTypeAndProps(
}
}
} else if (typeof type === 'string') {
if (enableFloat && supportsResources && supportsSingletons) {
if (supportsResources && supportsSingletons) {
const hostContext = getHostContext();
fiberTag = isHostHoistableType(type, pendingProps, hostContext)
? HostHoistable
: isHostSingletonType(type)
? HostSingleton
: HostComponent;
} else if (enableFloat && supportsResources) {
} else if (supportsResources) {
const hostContext = getHostContext();
fiberTag = isHostHoistableType(type, pendingProps, hostContext)
? HostHoistable
+1 -2
View File
@@ -105,7 +105,6 @@ import {
enableTransitionTracing,
enableLegacyHidden,
enableCPUSuspense,
enableFloat,
enableFormActions,
enableAsyncActions,
enablePostpone,
@@ -4089,7 +4088,7 @@ function beginWork(
case HostRoot:
return updateHostRoot(current, workInProgress, renderLanes);
case HostHoistable:
if (enableFloat && supportsResources) {
if (supportsResources) {
return updateHostHoistable(current, workInProgress, renderLanes);
}
// Fall through
+8 -11
View File
@@ -52,7 +52,6 @@ import {
enableCache,
enableTransitionTracing,
enableUseEffectEventHook,
enableFloat,
enableLegacyHidden,
disableStringRefs,
} from 'shared/ReactFeatureFlags';
@@ -1105,7 +1104,7 @@ function commitLayoutEffectOnFiber(
break;
}
case HostHoistable: {
if (enableFloat && supportsResources) {
if (supportsResources) {
recursivelyTraverseLayoutEffects(
finishedRoot,
finishedWork,
@@ -1509,9 +1508,7 @@ function hideOrUnhideAllChildren(finishedWork: Fiber, isHidden: boolean) {
while (true) {
if (
node.tag === HostComponent ||
(enableFloat && supportsResources
? node.tag === HostHoistable
: false) ||
(supportsResources ? node.tag === HostHoistable : false) ||
(supportsSingletons ? node.tag === HostSingleton : false)
) {
if (hostSubtreeRoot === null) {
@@ -1733,7 +1730,7 @@ function isHostParent(fiber: Fiber): boolean {
return (
fiber.tag === HostComponent ||
fiber.tag === HostRoot ||
(enableFloat && supportsResources ? fiber.tag === HostHoistable : false) ||
(supportsResources ? fiber.tag === HostHoistable : false) ||
(supportsSingletons ? fiber.tag === HostSingleton : false) ||
fiber.tag === HostPortal
);
@@ -2011,7 +2008,7 @@ function commitDeletionEffectsOnFiber(
// that don't modify the stack.
switch (deletedFiber.tag) {
case HostHoistable: {
if (enableFloat && supportsResources) {
if (supportsResources) {
if (!offscreenSubtreeWasHidden) {
safelyDetachRef(deletedFiber, nearestMountedAncestor);
}
@@ -2604,7 +2601,7 @@ function commitMutationEffectsOnFiber(
return;
}
case HostHoistable: {
if (enableFloat && supportsResources) {
if (supportsResources) {
// We cast because we always set the root at the React root and so it cannot be
// null while we are processing mutation effects
const hoistableRoot: HoistableRoot = (currentHoistableRoot: any);
@@ -2800,7 +2797,7 @@ function commitMutationEffectsOnFiber(
return;
}
case HostRoot: {
if (enableFloat && supportsResources) {
if (supportsResources) {
prepareToCommitHoistables();
const previousHoistableRoot = currentHoistableRoot;
@@ -2845,7 +2842,7 @@ function commitMutationEffectsOnFiber(
return;
}
case HostPortal: {
if (enableFloat && supportsResources) {
if (supportsResources) {
const previousHoistableRoot = currentHoistableRoot;
currentHoistableRoot = getHoistableRoot(
finishedWork.stateNode.containerInfo,
@@ -4114,7 +4111,7 @@ function accumulateSuspenseyCommitOnFiber(fiber: Fiber) {
}
case HostRoot:
case HostPortal: {
if (enableFloat && supportsResources) {
if (supportsResources) {
const previousHoistableRoot = currentHoistableRoot;
const container: Container = fiber.stateNode.containerInfo;
currentHoistableRoot = getHoistableRoot(container);
+1 -2
View File
@@ -38,7 +38,6 @@ import {
enableProfilerTimer,
enableCache,
enableTransitionTracing,
enableFloat,
enableRenderableContext,
passChildrenWhenCloningPersistedNodes,
} from 'shared/ReactFeatureFlags';
@@ -1051,7 +1050,7 @@ function completeWork(
return null;
}
case HostHoistable: {
if (enableFloat && supportsResources) {
if (supportsResources) {
// The branching here is more complicated than you might expect because
// a HostHoistable sometimes corresponds to a Resource and sometimes
// corresponds to an Instance. It can also switch during an update.
+1 -2
View File
@@ -14,7 +14,6 @@ import type {Fiber, FiberRoot} from './ReactInternalTypes';
import type {Instance} from './ReactFiberConfig';
import type {ReactNodeList} from 'shared/ReactTypes';
import {enableFloat} from 'shared/ReactFeatureFlags';
import {
flushSync,
scheduleUpdateOnFiber,
@@ -468,7 +467,7 @@ function findChildHostInstancesForFiberShallowly(
while (true) {
if (
node.tag === HostComponent ||
(enableFloat ? node.tag === HostHoistable : false) ||
node.tag === HostHoistable ||
(supportsSingletons ? node.tag === HostSingleton : false)
) {
// We got a match.
+2 -3
View File
@@ -25,7 +25,6 @@ import {
SuspenseComponent,
} from './ReactWorkTags';
import {NoFlags, Placement, Hydrating} from './ReactFiberFlags';
import {enableFloat} from 'shared/ReactFeatureFlags';
const ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner;
@@ -280,7 +279,7 @@ function findCurrentHostFiberImpl(node: Fiber): Fiber | null {
const tag = node.tag;
if (
tag === HostComponent ||
(enableFloat ? tag === HostHoistable : false) ||
tag === HostHoistable ||
tag === HostSingleton ||
tag === HostText
) {
@@ -311,7 +310,7 @@ function findCurrentHostFiberWithNoPortalsImpl(node: Fiber): Fiber | null {
const tag = node.tag;
if (
tag === HostComponent ||
(enableFloat ? tag === HostHoistable : false) ||
tag === HostHoistable ||
tag === HostSingleton ||
tag === HostText
) {
+20 -42
View File
@@ -141,7 +141,6 @@ import {
enableBigIntSupport,
enableScopeAPI,
enableSuspenseAvoidThisFallbackFizz,
enableFloat,
enableCache,
enablePostpone,
enableRenderableContext,
@@ -3820,12 +3819,8 @@ function flushSegment(
const id = boundary.rootSegmentID;
writeStartPendingSuspenseBoundary(destination, request.renderState, id);
// We are going to flush the fallback so we need to hoist the fallback
// state to the parent boundary
if (enableFloat) {
if (hoistableState) {
hoistHoistables(hoistableState, boundary.fallbackState);
}
if (hoistableState) {
hoistHoistables(hoistableState, boundary.fallbackState);
}
// Flush the fallback.
flushSubtree(request, destination, segment, hoistableState);
@@ -3859,10 +3854,8 @@ function flushSegment(
return writeEndPendingSuspenseBoundary(destination, request.renderState);
} else {
if (enableFloat) {
if (hoistableState) {
hoistHoistables(hoistableState, boundary.contentState);
}
if (hoistableState) {
hoistHoistables(hoistableState, boundary.contentState);
}
// We can inline this boundary's content as a complete boundary.
writeStartCompletedSuspenseBoundary(destination, request.renderState);
@@ -3927,14 +3920,11 @@ function flushCompletedBoundary(
}
completedSegments.length = 0;
if (enableFloat) {
writeHoistablesForBoundary(
destination,
boundary.contentState,
request.renderState,
);
}
writeHoistablesForBoundary(
destination,
boundary.contentState,
request.renderState,
);
return writeCompletedBoundaryInstruction(
destination,
request.resumableState,
@@ -3965,15 +3955,11 @@ function flushPartialBoundary(
}
completedSegments.splice(0, i);
if (enableFloat) {
return writeHoistablesForBoundary(
destination,
boundary.contentState,
request.renderState,
);
} else {
return true;
}
return writeHoistablesForBoundary(
destination,
boundary.contentState,
request.renderState,
);
}
function flushPartiallyCompletedSegment(
@@ -4035,10 +4021,7 @@ function flushCompletedQueues(
// We postponed the root, so we write nothing.
return;
} else if (request.pendingRootTasks === 0) {
if (enableFloat) {
flushPreamble(request, destination, completedRootSegment);
}
flushPreamble(request, destination, completedRootSegment);
flushSegment(request, destination, completedRootSegment, null);
request.completedRootSegment = null;
writeCompletedRoot(destination, request.renderState);
@@ -4047,10 +4030,7 @@ function flushCompletedQueues(
return;
}
}
if (enableFloat) {
writeHoistables(destination, request.resumableState, request.renderState);
}
writeHoistables(destination, request.resumableState, request.renderState);
// We emit client rendering instructions for already emitted boundaries first.
// This is so that we can signal to the client to start client rendering them as
// soon as possible.
@@ -4126,12 +4106,10 @@ function flushCompletedQueues(
// either they have pending task or they're complete.
) {
request.flushScheduled = false;
if (enableFloat) {
// We write the trailing tags but only if don't have any data to resume.
// If we need to resume we'll write the postamble in the resume instead.
if (!enablePostpone || request.trackedPostpones === null) {
writePostamble(destination, request.resumableState);
}
// We write the trailing tags but only if don't have any data to resume.
// If we need to resume we'll write the postamble in the resume instead.
if (!enablePostpone || request.trackedPostpones === null) {
writePostamble(destination, request.resumableState);
}
completeWriting(destination);
flushBuffered(destination);
-2
View File
@@ -100,8 +100,6 @@ export const enableSuspenseAvoidThisFallbackFizz = false;
export const enableCPUSuspense = __EXPERIMENTAL__;
export const enableFloat = true;
// Enables unstable_useMemoCache hook, intended as a compilation target for
// auto-memoization.
export const enableUseMemoCacheHook = __EXPERIMENTAL__;
@@ -85,8 +85,6 @@ export const enableNewBooleanProps = true;
export const enableTransitionTracing = false;
export const enableFloat = true;
export const enableDO_NOT_USE_disableStrictPassiveEffect = false;
export const enableFizzExternalRuntime = true;
@@ -76,8 +76,6 @@ export const consoleManagedByDevToolsDuringStrictMode = false;
export const enableTransitionTracing = false;
export const enableFloat = true;
export const useModernStrictMode = false;
export const enableDO_NOT_USE_disableStrictPassiveEffect = false;
export const enableFizzExternalRuntime = true;
@@ -66,8 +66,6 @@ export const consoleManagedByDevToolsDuringStrictMode = false;
export const enableTransitionTracing = false;
export const enableFloat = true;
export const useModernStrictMode = false;
export const enableDO_NOT_USE_disableStrictPassiveEffect = false;
export const enableFizzExternalRuntime = true;
@@ -69,8 +69,6 @@ export const consoleManagedByDevToolsDuringStrictMode = false;
export const enableTransitionTracing = false;
export const enableFloat = true;
export const useModernStrictMode = false;
export const enableDO_NOT_USE_disableStrictPassiveEffect = false;
export const enableDeferRootSchedulingToMicrotask = false;
@@ -69,8 +69,6 @@ export const consoleManagedByDevToolsDuringStrictMode = false;
export const enableTransitionTracing = false;
export const enableFloat = true;
export const useModernStrictMode = false;
export const enableDO_NOT_USE_disableStrictPassiveEffect = false;
export const enableFizzExternalRuntime = false;
@@ -56,7 +56,6 @@ export const enableSuspenseAvoidThisFallbackFizz = false;
export const enableCustomElementPropertySupport = true;
export const enableCPUSuspense = true;
export const enableFloat = true;
export const enableUseMemoCacheHook = true;
export const enableUseEffectEventHook = true;
export const enableFilterEmptyStringAttributesDOM = true;