From 0e8255f732648ea3f6ecfd5ec6bc4b19a96bcec9 Mon Sep 17 00:00:00 2001
From: Josh Story
Date: Tue, 7 Feb 2023 13:44:15 -0800
Subject: [PATCH] cleanup
---
.prettierrc.js | 2 +-
.../src/client/ReactDOMFloatClient.js | 27 +--
.../src/client/ReactDOMHostConfig.js | 50 +++--
.../src/server/ReactDOMServerFormatConfig.js | 156 +++++++------
.../ReactDOMServerLegacyFormatConfig.js | 1 +
...actDOMFizzInstructionSetExternalRuntime.js | 2 +-
.../ReactDOMFizzInstructionSetInlineSource.js | 2 +-
.../src/__tests__/ReactDOMComponent-test.js | 1 +
.../src/__tests__/ReactDOMFizzServer-test.js | 206 ++++++++----------
.../ReactDOMFizzServerBrowser-test.js | 12 +-
.../__tests__/ReactDOMFizzServerNode-test.js | 13 +-
.../ReactDOMFizzStaticBrowser-test.js | 12 +-
.../__tests__/ReactDOMFizzStaticNode-test.js | 12 +-
.../src/__tests__/ReactDOMFloat-test.js | 130 ++++++++++-
.../src/__tests__/ReactDOMRoot-test.js | 23 +-
.../ReactDOMSingletonComponents-test.js | 10 +-
.../react-dom-server-rendering-stub-test.js | 2 +-
.../server/ReactNativeServerFormatConfig.js | 12 +-
.../src/ReactNoopServer.js | 2 -
.../src/ReactFiberBeginWork.js | 67 +++---
.../src/ReactFiberCommitWork.js | 39 ++--
.../src/ReactFiberCompleteWork.js | 58 +++--
.../ReactFiberHostConfigWithNoResources.js | 7 +
.../src/ReactFiberWorkLoop.js | 16 +-
.../src/forks/ReactFiberHostConfig.custom.js | 6 +
.../forks/ReactServerFormatConfig.custom.js | 2 +
packages/shared/ReactFeatureFlags.js | 3 +-
scripts/error-codes/codes.json | 2 +-
28 files changed, 520 insertions(+), 355 deletions(-)
diff --git a/.prettierrc.js b/.prettierrc.js
index 7109a6fe8c57b..4f7ef193130c9 100644
--- a/.prettierrc.js
+++ b/.prettierrc.js
@@ -8,7 +8,7 @@ module.exports = {
jsxBracketSameLine: true,
trailingComma: 'es5',
printWidth: 80,
- parser: 'babel',
+ parser: 'flow',
arrowParens: 'avoid',
overrides: [
{
diff --git a/packages/react-dom-bindings/src/client/ReactDOMFloatClient.js b/packages/react-dom-bindings/src/client/ReactDOMFloatClient.js
index 73b18a3aff76c..10c44364c5b60 100644
--- a/packages/react-dom-bindings/src/client/ReactDOMFloatClient.js
+++ b/packages/react-dom-bindings/src/client/ReactDOMFloatClient.js
@@ -16,13 +16,6 @@ import ReactDOMSharedInternals from 'shared/ReactDOMSharedInternals.js';
const {Dispatcher} = ReactDOMSharedInternals;
import {DOCUMENT_NODE} from '../shared/HTMLNodeType';
import {
- warnOnMissingHrefAndRel,
- validatePreloadResourceDifference,
- validateURLKeyedUpdatedProps,
- validateStyleResourceDifference,
- validateScriptResourceDifference,
- validateLinkPropsForStyleResource,
- validateLinkPropsForPreloadResource,
validatePreloadArguments,
validatePreinitArguments,
} from '../shared/ReactDOMResourceValidation';
@@ -178,9 +171,8 @@ function preload(href: string, options: PreloadOptions) {
ownerDocument
) {
const as = options.as;
- const limitedEscapedHref = escapeSelectorAttributeValueInsideDoubleQuotes(
- href,
- );
+ const limitedEscapedHref =
+ escapeSelectorAttributeValueInsideDoubleQuotes(href);
const preloadKey = `link[rel="preload"][as="${as}"][href="${limitedEscapedHref}"]`;
let key = preloadKey;
switch (as) {
@@ -256,9 +248,8 @@ function preinit(href: string, options: PreinitOptions) {
// matching preload with this href
const preloadDocument = getDocumentForPreloads();
if (preloadDocument) {
- const limitedEscapedHref = escapeSelectorAttributeValueInsideDoubleQuotes(
- href,
- );
+ const limitedEscapedHref =
+ escapeSelectorAttributeValueInsideDoubleQuotes(href);
const preloadKey = `link[rel="preload"][as="${as}"][href="${limitedEscapedHref}"]`;
let key = preloadKey;
switch (as) {
@@ -476,8 +467,6 @@ export function getResource(
const styles = getResourcesFromRoot(resourceRoot).hoistableStyles;
let resource = styles.get(key);
if (!resource) {
- // We asserted this above but Flow can't figure out that the type satisfies
- const ownerDocument = getDocumentFromRoot(resourceRoot);
resource = {
type: 'style',
instance: null,
@@ -570,9 +559,8 @@ function styleTagPropsFromRawProps(
}
function getStyleKey(href: string) {
- const limitedEscapedHref = escapeSelectorAttributeValueInsideDoubleQuotes(
- href,
- );
+ const limitedEscapedHref =
+ escapeSelectorAttributeValueInsideDoubleQuotes(href);
return `href="${limitedEscapedHref}"`;
}
@@ -609,9 +597,6 @@ function preloadStylesheet(
// There is no matching stylesheet instance in the Document.
// We will insert a preload now to kick off loading because
// we expect this stylesheet to commit
- const limitedEscapedHref = escapeSelectorAttributeValueInsideDoubleQuotes(
- preloadProps.href,
- );
if (
null ===
ownerDocument.querySelector(getPreloadStylesheetSelectorFromKey(key))
diff --git a/packages/react-dom-bindings/src/client/ReactDOMHostConfig.js b/packages/react-dom-bindings/src/client/ReactDOMHostConfig.js
index dfcd38e561fba..281cc2a118ec0 100644
--- a/packages/react-dom-bindings/src/client/ReactDOMHostConfig.js
+++ b/packages/react-dom-bindings/src/client/ReactDOMHostConfig.js
@@ -463,10 +463,7 @@ export const scheduleMicrotask: any =
? queueMicrotask
: typeof localPromise !== 'undefined'
? callback =>
- localPromise
- .resolve(null)
- .then(callback)
- .catch(handleErrorInNextTick)
+ localPromise.resolve(null).then(callback).catch(handleErrorInNextTick)
: scheduleTimeout; // TODO: Determine the best fallback here.
function handleErrorInNextTick(error: any) {
@@ -1591,8 +1588,8 @@ export function isHostHoistableType(
if (__DEV__) {
const hostContextDev: HostContextDev = (hostContext: any);
// We can only render resources when we are not within the host container context
- outsideHostContainerContext = !hostContextDev.ancestorInfo
- .containerTagInScope;
+ outsideHostContainerContext =
+ !hostContextDev.ancestorInfo.containerTagInScope;
namespace = hostContextDev.namespace;
} else {
const hostContextProd: HostContextProd = (hostContext: any);
@@ -1623,22 +1620,40 @@ export function isHostHoistableType(
);
}
case 'link': {
- const {onLoad, onError} = props;
- if (onLoad || onError) {
+ const {onLoad, onError, rel, href} = props;
+ if (
+ namespace === SVG_NAMESPACE ||
+ typeof rel !== 'string' ||
+ typeof href !== 'string' ||
+ href === '' ||
+ onLoad ||
+ onError
+ ) {
if (__DEV__) {
if (outsideHostContainerContext) {
- console.error(
- 'Cannot render a with onLoad or onError listeners outside the main document.' +
- ' Try removing onLoad={...} and onError={...} or moving it into the root tag or' +
- ' somewhere in the .',
- );
+ if (
+ typeof rel !== 'string' ||
+ typeof href !== 'string' ||
+ href === ''
+ ) {
+ console.error(
+ 'Cannot render a outside the main document without a `rel` and `href` prop.' +
+ ' Try adding a `rel` and/or `href` prop to this or moving the link into the tag',
+ );
+ } else if (onError || onLoad) {
+ console.error(
+ 'Cannot render a with onLoad or onError listeners outside the main document.' +
+ ' Try removing onLoad={...} and onError={...} or moving it into the root tag or' +
+ ' somewhere in the .',
+ );
+ }
}
}
return false;
}
switch (props.rel) {
case 'stylesheet': {
- const {href, precedence, disabled} = props;
+ const {precedence, disabled} = props;
if (__DEV__) {
validateLinkPropsForStyleResource(props);
if (typeof precedence !== 'string') {
@@ -1650,12 +1665,7 @@ export function isHostHoistableType(
}
}
}
- return (
- namespace !== SVG_NAMESPACE &&
- typeof href === 'string' &&
- typeof precedence === 'string' &&
- disabled == null
- );
+ return typeof precedence === 'string' && disabled == null;
}
default: {
return true;
diff --git a/packages/react-dom-bindings/src/server/ReactDOMServerFormatConfig.js b/packages/react-dom-bindings/src/server/ReactDOMServerFormatConfig.js
index 1152782e83d9a..cc1029c92d811 100644
--- a/packages/react-dom-bindings/src/server/ReactDOMServerFormatConfig.js
+++ b/packages/react-dom-bindings/src/server/ReactDOMServerFormatConfig.js
@@ -892,7 +892,7 @@ function flattenOptionChildren(children: mixed): string {
let content = '';
// Flatten children and warn if they aren't strings or numbers;
// invalid types are ignored.
- Children.forEach((children: any), function(child) {
+ Children.forEach((children: any), function (child) {
if (child == null) {
return;
}
@@ -1355,8 +1355,8 @@ function pushLink(
// This stylesheet refers to a Resource and we create a new one if necessary
let resource = resources.stylesMap.get(key);
if (__DEV__) {
- if (resource) {
- const devResource: ResourceDEV = (resource: any);
+ const devResource = getAsResourceDEV(resource);
+ if (devResource) {
switch (devResource.__provenance) {
case 'rendered': {
const differentProps = compareResourcePropsForWarning(
@@ -1365,9 +1365,8 @@ function pushLink(
devResource.__originalProps,
);
if (differentProps) {
- const differenceDescription = describeDifferencesForStylesheets(
- differentProps,
- );
+ const differenceDescription =
+ describeDifferencesForStylesheets(differentProps);
if (differenceDescription) {
console.error(
'React encountered a with a `precedence` prop that has props that conflict' +
@@ -1388,9 +1387,10 @@ function pushLink(
devResource.__propsEquivalent,
);
if (differentProps) {
- const differenceDescription = describeDifferencesForStylesheetOverPreinit(
- differentProps,
- );
+ const differenceDescription =
+ describeDifferencesForStylesheetOverPreinit(
+ differentProps,
+ );
if (differenceDescription) {
console.error(
'React encountered a with props that conflict' +
@@ -1725,22 +1725,40 @@ function pushTitle(
: null
: children;
- if (
- typeof child === 'function' ||
- typeof child === 'symbol' ||
- Array.isArray(child)
- ) {
+ if (Array.isArray(children) && children.length > 1) {
+ console.error(
+ 'React expects the `children` prop of tags to be a string, number, or object with a novel `toString` method but found an Array with length %s instead.' +
+ ' Browsers treat all child Nodes of tags as Text content and React expects to be able to convert `children` of 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: hello {nameOfUser}. 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: {`hello ${nameOfUser}`}.',
+ children.length,
+ );
+ } else if (typeof child === 'function' || typeof child === 'symbol') {
const childType =
- typeof child === 'function'
- ? 'a Function'
- : typeof child === 'symbol'
- ? 'a Sybmol'
- : 'an Array';
+ typeof child === 'function' ? 'a Function' : 'a Sybmol';
console.error(
- 'React expect children of tags to be a string, number, or object with a `toString` method but found %s instead. ' +
- 'In browsers title Elements can only have `Text` Nodes as children.',
+ 'React expect children of tags to be a string, number, or object with a novel `toString` method but found %s instead.' +
+ ' Browsers treat all child Nodes of tags as Text content and React expects to be able to convert children of ' +
+ ' tags to a single string value.',
childType,
);
+ } else if (child && child.toString === {}.toString) {
+ if (child.$$typeof != null) {
+ console.error(
+ 'React expects the `children` prop of tags to be a string, number, 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 tags as Text content and React expects to' +
+ ' be able to convert children of tags to a single string value which is why rendering React elements is not supported. If the `children` of is' +
+ ' a React Component try moving the tag into that component. If the `children` of is some HTML markup change it to be Text only to be valid HTML.',
+ );
+ } else {
+ console.error(
+ 'React expects the `children` prop of tags to be a string, number, 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 tags as Text content and React expects to be able to convert children of 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 ' +
+ ' 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 .',
+ );
+ }
}
}
}
@@ -2535,29 +2553,22 @@ const startPendingSuspenseBoundary1 = stringToPrecomputedChunk(
'');
-const startClientRenderedSuspenseBoundary = stringToPrecomputedChunk(
- '',
-);
+const startClientRenderedSuspenseBoundary =
+ stringToPrecomputedChunk('');
const endSuspenseBoundary = stringToPrecomputedChunk('');
-const clientRenderedSuspenseBoundaryError1 = stringToPrecomputedChunk(
- '');
+// Tracks whether we wrote any late style tags. We use this to determine
+// whether we need to emit a closing template tag after flushing late style tags
+let didWrite = false;
+
function flushStyleTagsLateForBoundary(
this: Destination,
resource: StyleResource,
) {
if (resource.type === 'style' && (resource.state & Flushed) === NoState) {
+ if (didWrite === false) {
+ // we are going to write so we need to emit the open tag
+ didWrite = true;
+ writeChunk(this, styleTagTemplateOpen);
+ }
// This
+
+