mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
@@ -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
|
||||
) {
|
||||
|
||||
+132
-148
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+368
-523
File diff suppressed because it is too large
Load Diff
+40
-107
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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.
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user