@samitouri / QOS-React-1 / commits / 5ea1397b2b

Remove excess validation (#27223)

stacked on #27222 When I initially developed Float I was trying to be extremely clever in how to explain when there are mismatching Resource instances. I still think that we should do some kind of validation here but I want to implement something much simpler. In practice there are not many cases where you would accidentally create the same resource twice but with differing props. Since I am going to land `preloadModule` and `preinitModule` soon and I want to avoid adding to the overly complex dev validation there I am going to remove it now and add something later that is simplified.

Josh Story committed Aug 14, 2023 at 10:08 UTC 5ea1397b2b62875dfb521cf8de0efcc15d0df797
3 files changed -1058
packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js
-393
@@ -79,15 +79,6 @@ import {
79 import {
80 getValueDescriptorExpectingObjectForWarning,
81 getValueDescriptorExpectingEnumForWarning,
82 - describeDifferencesForStylesheets,
83 - describeDifferencesForStylesheetOverPreinit,
84 - describeDifferencesForScripts,
85 - describeDifferencesForScriptOverPreinit,
86 - describeDifferencesForPreinits,
87 - describeDifferencesForPreinitOverStylesheet,
88 - describeDifferencesForPreinitOverScript,
89 - describeDifferencesForPreloads,
90 - describeDifferencesForPreloadOverImplicitPreload,
82 } from '../shared/ReactDOMResourceValidation';
83
84 import {NotPending} from '../shared/ReactDOMFormActions';
@@ -2004,55 +1995,6 @@ function pushLink(
1995 } else {
1996 // This stylesheet refers to a Resource and we create a new one if necessary
1997 let resource = resources.stylesMap.get(key);
2007 - if (__DEV__) {
2008 - const devResource = getAsResourceDEV(resource);
2009 - if (devResource) {
2010 - switch (devResource.__provenance) {
2011 - case 'rendered': {
2012 - const differenceDescription = describeDifferencesForStylesheets(
2013 - // Diff the props from the JSX element, not the derived resource props
2014 - props,
2015 - devResource.__originalProps,
2016 - );
2017 - if (differenceDescription) {
2018 - console.error(
2019 - 'React encountered a <link rel="stylesheet" href="%s" .../> with a `precedence` prop that has props that conflict' +
2020 - ' with another hoistable stylesheet with the same `href`. When using `precedence` with <link rel="stylsheet" .../>' +
2021 - ' the props from the first encountered instance will be used and props from later instances will be ignored.' +
2022 - ' Update the props on either <link rel="stylesheet" .../> instance so they agree.%s',
2023 - href,
2024 - differenceDescription,
2025 - );
2026 - }
2027 - break;
2028 - }
2029 - case 'preinit': {
2030 - const differenceDescription =
2031 - describeDifferencesForStylesheetOverPreinit(
2032 - // Diff the props from the JSX element, not the derived resource props
2033 - props,
2034 - devResource.__propsEquivalent,
2035 - );
2036 - if (differenceDescription) {
2037 - console.error(
2038 - 'React encountered a <link rel="stylesheet" precedence="%s" href="%s" .../> with props that conflict' +
2039 - ' with the options provided to `ReactDOM.preinit("%s", { as: "style", ... })`. React will use the first props or preinitialization' +
2040 - ' options encountered when rendering a hoistable stylesheet with a particular `href` and will ignore any newer props or' +
2041 - ' options. The first instance of this stylesheet resource was created using the `ReactDOM.preinit()` function.' +
2042 - ' Please note, `ReactDOM.preinit()` is modeled off of module import assertions capabilities and does not support' +
2043 - ' arbitrary props. If you need to have props not included with the preinit options you will need to rely on rendering' +
2044 - ' <link> tags only.%s',
2045 - precedence,
2046 - href,
2047 - href,
2048 - differenceDescription,
2049 - );
2050 - }
2051 - break;
2052 - }
2053 - }
2054 - }
2055 - }
1998 if (!resource) {
1999 const resourceProps = stylesheetPropsFromRawProps(props);
2000 const preloadResource = resources.preloadsMap.get(key);
@@ -2076,9 +2018,6 @@ function pushLink(
2018 props: resourceProps,
2019 };
2020 resources.stylesMap.set(key, resource);
2079 - if (__DEV__) {
2080 - markAsRenderedResourceDEV(resource, props);
2081 - }
2021 let precedenceSet = resources.precedences.get(precedence);
2022 if (!precedenceSet) {
2023 precedenceSet = new Set();
@@ -2443,9 +2382,6 @@ function pushImg(
2382 },
2383 };
2384 resources.preloadsMap.set(key, resource);
2446 - if (__DEV__) {
2447 - markAsRenderedResourceDEV(resource, props);
2448 - }
2385 pushLinkImpl(resource.chunks, resource.props);
2386 }
2387 if (
@@ -2790,54 +2726,6 @@ function pushScript(
2726 const key = getResourceKey('script', src);
2727 // We can make this <script> into a ScriptResource
2728 let resource = resources.scriptsMap.get(key);
2793 - if (__DEV__) {
2794 - const devResource = getAsResourceDEV(resource);
2795 - if (devResource) {
2796 - switch (devResource.__provenance) {
2797 - case 'rendered': {
2798 - const differenceDescription = describeDifferencesForScripts(
2799 - // Diff the props from the JSX element, not the derived resource props
2800 - props,
2801 - devResource.__originalProps,
2802 - );
2803 - if (differenceDescription) {
2804 - console.error(
2805 - 'React encountered a <script async={true} src="%s" .../> that has props that conflict' +
2806 - ' with another hoistable script with the same `src`. When rendering hoistable scripts (async scripts without any loading handlers)' +
2807 - ' the props from the first encountered instance will be used and props from later instances will be ignored.' +
2808 - ' Update the props on both <script async={true} .../> instance so they agree.%s',
2809 - src,
2810 - differenceDescription,
2811 - );
2812 - }
2813 - break;
2814 - }
2815 - case 'preinit': {
2816 - const differenceDescription =
2817 - describeDifferencesForScriptOverPreinit(
2818 - // Diff the props from the JSX element, not the derived resource props
2819 - props,
2820 - devResource.__propsEquivalent,
2821 - );
2822 - if (differenceDescription) {
2823 - console.error(
2824 - 'React encountered a <script async={true} src="%s" .../> with props that conflict' +
2825 - ' with the options provided to `ReactDOM.preinit("%s", { as: "script", ... })`. React will use the first props or preinitialization' +
2826 - ' options encountered when rendering a hoistable script with a particular `src` and will ignore any newer props or' +
2827 - ' options. The first instance of this script resource was created using the `ReactDOM.preinit()` function.' +
2828 - ' Please note, `ReactDOM.preinit()` is modeled off of module import assertions capabilities and does not support' +
2829 - ' arbitrary props. If you need to have props not included with the preinit options you will need to rely on rendering' +
2830 - ' <script> tags only.%s',
2831 - src,
2832 - src,
2833 - differenceDescription,
2834 - );
2835 - }
2836 - break;
2837 - }
2838 - }
2839 - }
2840 - }
2729 if (!resource) {
2730 resource = {
2731 type: 'script',
@@ -2846,9 +2734,6 @@ function pushScript(
2734 props: null,
2735 };
2736 resources.scriptsMap.set(key, resource);
2849 - if (__DEV__) {
2850 - markAsRenderedResourceDEV(resource, props);
2851 - }
2737 // Add to the script flushing queue
2738 resources.scripts.add(resource);
2739
@@ -4874,30 +4759,6 @@ type TResource<
4759 state: ResourceStateTag,
4760 props: P,
4761 };
4877 -// Dev extensions.
4878 -// Stylesheets and Scripts rendered with jsx
4879 -type RenderedResourceDEV = {
4880 - __provenance: 'rendered',
4881 - __originalProps: any,
4882 -};
4883 -// Preloads, Stylesheets, and Scripts from ReactDOM.preload or ReactDOM.preinit
4884 -type ImperativeResourceDEV = {
4885 - __provenance: 'preload' | 'preinit',
4886 - __originalHref: string,
4887 - __originalOptions: any,
4888 - __propsEquivalent: any,
4889 -};
4890 -// Preloads created for normal components we rendered but know we can preload early such as
4891 -// sync Scripts and stylesheets without precedence or with onLoad/onError handlers
4892 -type ImplicitResourceDEV = {
4893 - __provenance: 'implicit',
4894 - __underlyingProps: any,
4895 - __impliedProps: any,
4896 -};
4897 -type ResourceDEV =
4898 - | RenderedResourceDEV
4899 - | ImperativeResourceDEV
4900 - | ImplicitResourceDEV;
4762
4763 type PreconnectProps = {
4764 rel: 'preconnect' | 'dns-prefetch',
@@ -5193,61 +5054,6 @@ function preload(href: string, options: PreloadOptions) {
5054 key = getResourceKey(as, href);
5055 }
5056 let resource = resources.preloadsMap.get(key);
5196 - if (__DEV__) {
5197 - const devResource = getAsResourceDEV(resource);
5198 - if (devResource) {
5199 - switch (devResource.__provenance) {
5200 - case 'preload': {
5201 - const differenceDescription = describeDifferencesForPreloads(
5202 - options,
5203 - devResource.__originalOptions,
5204 - );
5205 - if (differenceDescription) {
5206 - console.error(
5207 - 'ReactDOM.preload(): The options provided conflict with another call to `ReactDOM.preload("%s", { as: "%s", ...})`.' +
5208 - ' React will always use the options it first encounters when preloading a resource for a given `href` and `as` type, and any later options will be ignored if different.' +
5209 - ' Try updating all calls to `ReactDOM.preload()` with the same `href` and `as` type to use the same options, or eliminate one of the calls.%s',
5210 - href,
5211 - as,
5212 - differenceDescription,
5213 - );
5214 - }
5215 - break;
5216 - }
5217 - case 'implicit': {
5218 - const differenceDescription =
5219 - describeDifferencesForPreloadOverImplicitPreload(
5220 - options,
5221 - devResource.__impliedProps,
5222 - );
5223 - if (differenceDescription) {
5224 - const elementDescription =
5225 - as === 'style'
5226 - ? '<link rel="stylesheet" ... />'
5227 - : as === 'script'
5228 - ? '<script ... />'
5229 - : null;
5230 - if (elementDescription) {
5231 - console.error(
5232 - 'ReactDOM.preload(): For `href` "%s", The options provided conflict with props on a matching %s element. When the preload' +
5233 - ' options disagree with the underlying resource it usually means the browser will not be able to use the preload when the resource' +
5234 - ' is fetched, negating any benefit the preload would provide. React will preload the resource using props derived from the resource instead' +
5235 - ' and ignore the options provided to the `ReactDOM.preload()` call. In general, preloading is useful when you expect to' +
5236 - ' render a resource soon but have not yet done so. In this case since the underlying resource was already rendered the preload call' +
5237 - ' may be extraneous. Try removing the call, otherwise try adjusting both the props on the %s and the options' +
5238 - ' passed to `ReactDOM.preload()` to agree.%s',
5239 - href,
5240 - elementDescription,
5241 - elementDescription,
5242 - differenceDescription,
5243 - );
5244 - }
5245 - }
5246 - break;
5247 - }
5248 - }
5249 - }
5250 - }
5057 if (!resource) {
5058 resource = {
5059 type: 'preload',
@@ -5256,16 +5062,6 @@ function preload(href: string, options: PreloadOptions) {
5062 props: preloadPropsFromPreloadOptions(href, as, options),
5063 };
5064 resources.preloadsMap.set(key, resource);
5259 - if (__DEV__) {
5260 - markAsImperativeResourceDEV(
5261 - resource,
5262 - 'preload',
5263 - href,
5264 - options,
5265 - resource.props,
5266 - );
5267 - }
5268 -
5065 pushLinkImpl(resource.chunks, resource.props);
5066 }
5067 if (as === 'font') {
@@ -5323,64 +5119,6 @@ function preinit(href: string, options: PreinitOptions): void {
5119 const key = getResourceKey(as, href);
5120 let resource = resources.stylesMap.get(key);
5121 const precedence = options.precedence || 'default';
5326 - if (__DEV__) {
5327 - const devResource = getAsResourceDEV(resource);
5328 - if (devResource) {
5329 - const resourceProps = stylesheetPropsFromPreinitOptions(
5330 - href,
5331 - precedence,
5332 - options,
5333 - );
5334 - const propsEquivalent = {
5335 - ...resourceProps,
5336 - precedence: options.precedence,
5337 - ['data-precedence']: null,
5338 - };
5339 - switch (devResource.__provenance) {
5340 - case 'rendered': {
5341 - const differenceDescription =
5342 - describeDifferencesForPreinitOverStylesheet(
5343 - // Diff the props from the JSX element, not the derived resource props
5344 - propsEquivalent,
5345 - devResource.__originalProps,
5346 - );
5347 - if (differenceDescription) {
5348 - console.error(
5349 - 'ReactDOM.preinit(): For `href` "%s", the options provided conflict with props found on a <link rel="stylesheet" precedence="%s" href="%s" .../> that was already rendered.' +
5350 - ' React will always use the props or options it first encounters for a hoistable stylesheet for a given `href` and any later props or options will be ignored if different.' +
5351 - ' Generally, ReactDOM.preinit() is useful when you are not yet rendering a stylesheet but you anticipate it will be used soon.' +
5352 - ' In this case the stylesheet was already rendered so preinitializing it does not provide any additional benefit.' +
5353 - ' To resolve, try making the props and options agree between the <link rel="stylesheet" .../> and the `ReactDOM.preinit()` call or' +
5354 - ' remove the `ReactDOM.preinit()` call.%s',
5355 - href,
5356 - devResource.__originalProps.precedence,
5357 - href,
5358 - differenceDescription,
5359 - );
5360 - }
5361 - break;
5362 - }
5363 - case 'preinit': {
5364 - const differenceDescription = describeDifferencesForPreinits(
5365 - // Diff the props from the JSX element, not the derived resource props
5366 - propsEquivalent,
5367 - devResource.__propsEquivalent,
5368 - );
5369 - if (differenceDescription) {
5370 - console.error(
5371 - 'ReactDOM.preinit(): For `href` "%s", the options provided conflict with another call to `ReactDOM.preinit("%s", { as: "style", ... })`.' +
5372 - ' React will always use the options it first encounters when preinitializing a hoistable stylesheet for a given `href` and any later options will be ignored if different.' +
5373 - ' Try updating all calls to `ReactDOM.preinit()` for a given `href` to use the same options, or only call `ReactDOM.preinit()` once per `href`.%s',
5374 - href,
5375 - href,
5376 - differenceDescription,
5377 - );
5378 - }
5379 - break;
5380 - }
5381 - }
5382 - }
5383 - }
5122 if (!resource) {
5123 let state = NoState;
5124 const preloadResource = resources.preloadsMap.get(key);
@@ -5394,13 +5132,6 @@ function preinit(href: string, options: PreinitOptions): void {
5132 props: stylesheetPropsFromPreinitOptions(href, precedence, options),
5133 };
5134 resources.stylesMap.set(key, resource);
5397 - if (__DEV__) {
5398 - markAsImperativeResourceDEV(resource, 'preinit', href, options, {
5399 - ...resource.props,
5400 - precedence,
5401 - ['data-precedence']: undefined,
5402 - });
5403 - }
5135 let precedenceSet = resources.precedences.get(precedence);
5136 if (!precedenceSet) {
5137 precedenceSet = new Set();
@@ -5434,53 +5165,6 @@ function preinit(href: string, options: PreinitOptions): void {
5165 const src = href;
5166 const key = getResourceKey(as, src);
5167 let resource = resources.scriptsMap.get(key);
5437 - if (__DEV__) {
5438 - const devResource = getAsResourceDEV(resource);
5439 - if (devResource) {
5440 - const propsEquivalent = scriptPropsFromPreinitOptions(src, options);
5441 - switch (devResource.__provenance) {
5442 - case 'rendered': {
5443 - const differenceDescription =
5444 - describeDifferencesForPreinitOverScript(
5445 - // Diff the props from the JSX element, not the derived resource props
5446 - propsEquivalent,
5447 - devResource.__originalProps,
5448 - );
5449 - if (differenceDescription) {
5450 - console.error(
5451 - 'ReactDOM.preinit(): For `href` "%s", the options provided conflict with props found on a <script async={true} src="%s" .../> that was already rendered.' +
5452 - ' React will always use the props or options it first encounters for a hoistable script for a given `href` and any later props or options will be ignored if different.' +
5453 - ' Generally, ReactDOM.preinit() is useful when you are not yet rendering a script but you anticipate it will be used soon and want to go beyond preloading it and have it' +
5454 - ' execute early. In this case the script was already rendered so preinitializing it does not provide any additional benefit.' +
5455 - ' To resolve, try making the props and options agree between the <script .../> and the `ReactDOM.preinit()` call or remove the `ReactDOM.preinit()` call.%s',
5456 - href,
5457 - href,
5458 - differenceDescription,
5459 - );
5460 - }
5461 - break;
5462 - }
5463 - case 'preinit': {
5464 - const differenceDescription = describeDifferencesForPreinits(
5465 - // Diff the props from the JSX element, not the derived resource props
5466 - propsEquivalent,
5467 - devResource.__propsEquivalent,
5468 - );
5469 - if (differenceDescription) {
5470 - console.error(
5471 - 'ReactDOM.preinit(): For `href` "%s", the options provided conflict with another call to `ReactDOM.preinit("%s", { as: "script", ... })`.' +
5472 - ' React will always use the options it first encounters when preinitializing a hoistable script for a given `href` and any later options will be ignored if different.' +
5473 - ' Try updating all calls to `ReactDOM.preinit()` for a given `href` to use the same options, or only call `ReactDOM.preinit()` once per `href`.%s',
5474 - href,
5475 - href,
5476 - differenceDescription,
5477 - );
5478 - }
5479 - break;
5480 - }
5481 - }
5482 - }
5483 - }
5168 if (!resource) {
5169 resource = {
5170 type: 'script',
@@ -5490,15 +5174,6 @@ function preinit(href: string, options: PreinitOptions): void {
5174 };
5175 resources.scriptsMap.set(key, resource);
5176 const resourceProps = scriptPropsFromPreinitOptions(src, options);
5493 - if (__DEV__) {
5494 - markAsImperativeResourceDEV(
5495 - resource,
5496 - 'preinit',
5497 - href,
5498 - options,
5499 - resourceProps,
5500 - );
5501 - }
5177 resources.scripts.add(resource);
5178 pushScriptImpl(resource.chunks, resourceProps);
5179 flushResources(request);
@@ -5724,73 +5399,5 @@ export function hoistResources(
5399 }
5400 }
5401
5727 -function markAsRenderedResourceDEV(
5728 - resource: Resource,
5729 - originalProps: any,
5730 -): void {
5731 - if (__DEV__) {
5732 - const devResource: RenderedResourceDEV = (resource: any);
5733 - if (typeof devResource.__provenance === 'string') {
5734 - console.error(
5735 - 'Resource already marked for DEV type. This is a bug in React.',
5736 - );
5737 - }
5738 - devResource.__provenance = 'rendered';
5739 - devResource.__originalProps = originalProps;
5740 - } else {
5741 - // eslint-disable-next-line react-internal/prod-error-codes
5742 - throw new Error(
5743 - 'markAsRenderedResourceDEV was included in a production build. This is a bug in React.',
5744 - );
5745 - }
5746 -}
5747 -
5748 -function markAsImperativeResourceDEV(
5749 - resource: Resource,
5750 - provenance: 'preload' | 'preinit',
5751 - originalHref: string,
5752 - originalOptions: any,
5753 - propsEquivalent: any,
5754 -): void {
5755 - if (__DEV__) {
5756 - const devResource: ImperativeResourceDEV = (resource: any);
5757 - if (typeof devResource.__provenance === 'string') {
5758 - console.error(
5759 - 'Resource already marked for DEV type. This is a bug in React.',
5760 - );
5761 - }
5762 - devResource.__provenance = provenance;
5763 - devResource.__originalHref = originalHref;
5764 - devResource.__originalOptions = originalOptions;
5765 - devResource.__propsEquivalent = propsEquivalent;
5766 - } else {
5767 - // eslint-disable-next-line react-internal/prod-error-codes
5768 - throw new Error(
5769 - 'markAsImperativeResourceDEV was included in a production build. This is a bug in React.',
5770 - );
5771 - }
5772 -}
5773 -
5774 -function getAsResourceDEV(
5775 - resource: null | void | Resource,
5776 -): null | ResourceDEV {
5777 - if (__DEV__) {
5778 - if (resource) {
5779 - if (typeof (resource: any).__provenance === 'string') {
5780 - return (resource: any);
5781 - }
5782 - console.error(
5783 - 'Resource was not marked for DEV type. This is a bug in React.',
5784 - );
5785 - }
5786 - return null;
5787 - } else {
5788 - // eslint-disable-next-line react-internal/prod-error-codes
5789 - throw new Error(
5790 - 'getAsResourceDEV was included in a production build. This is a bug in React.',
5791 - );
5792 - }
5793 -}
5794 -
5402 export type TransitionStatus = FormStatus;
5403 export const NotPendingTransition: TransitionStatus = NotPending;
packages/react-dom-bindings/src/shared/ReactDOMResourceValidation.js
-403
@@ -125,406 +125,3 @@ export function getValueDescriptorExpectingEnumForWarning(thing: any): string {
125 ? JSON.stringify(thing)
126 : `something with type "${typeof thing}"`;
127 }
128 -
129 -type PropDifferences = {
130 - missing: {
131 - [string]: any,
132 - },
133 - extra: {
134 - [string]: any,
135 - },
136 - different: {
137 - [string]: {
138 - original: any,
139 - latest: any,
140 - },
141 - },
142 -};
143 -function compareResourcePropsForWarning(
144 - newProps: any,
145 - currentProps: any,
146 -): null | PropDifferences {
147 - if (__DEV__) {
148 - let propDiffs: null | PropDifferences = null;
149 -
150 - const allProps = Array.from(
151 - new Set(Object.keys(currentProps).concat(Object.keys(newProps))),
152 - );
153 -
154 - for (let i = 0; i < allProps.length; i++) {
155 - const propName = allProps[i];
156 - const newValue = newProps[propName];
157 - const currentValue = currentProps[propName];
158 - if (
159 - newValue !== currentValue &&
160 - !(newValue == null && currentValue == null)
161 - ) {
162 - if (newValue == null) {
163 - if (propDiffs === null) {
164 - propDiffs = ({
165 - missing: {},
166 - extra: {},
167 - different: {},
168 - }: PropDifferences);
169 - }
170 - propDiffs.missing[propName] = currentValue;
171 - } else if (currentValue == null) {
172 - if (propDiffs === null) {
173 - propDiffs = ({
174 - missing: {},
175 - extra: {},
176 - different: {},
177 - }: PropDifferences);
178 - }
179 - propDiffs.extra[propName] = newValue;
180 - } else {
181 - if (propDiffs === null) {
182 - propDiffs = ({
183 - missing: {},
184 - extra: {},
185 - different: {},
186 - }: PropDifferences);
187 - }
188 - propDiffs.different[propName] = {
189 - original: currentValue,
190 - latest: newValue,
191 - };
192 - }
193 - }
194 - }
195 -
196 - return propDiffs;
197 - }
198 - return null;
199 -}
200 -
201 -export function describeDifferencesForStylesheets(
202 - newProps: any,
203 - currentProps: any,
204 -): string {
205 - const diff = compareResourcePropsForWarning(newProps, currentProps);
206 - if (!diff) return '';
207 -
208 - let description = '';
209 -
210 - for (const propName in diff.missing) {
211 - const propValue = diff.missing[propName];
212 - if (propName === 'media') {
213 - description += `\n "${propName}" missing for props, original value: ${getValueDescriptorExpectingEnumForWarning(
214 - propValue,
215 - )}`;
216 - }
217 - }
218 - for (const propName in diff.extra) {
219 - const propValue = diff.extra[propName];
220 - description += `\n "${propName}" prop value: ${getValueDescriptorExpectingEnumForWarning(
221 - propValue,
222 - )}, missing from original props`;
223 - }
224 - for (const propName in diff.different) {
225 - const latestValue = diff.different[propName].latest;
226 - const originalValue = diff.different[propName].original;
227 - description += `\n "${propName}" prop value: ${getValueDescriptorExpectingEnumForWarning(
228 - latestValue,
229 - )}, original value: ${getValueDescriptorExpectingEnumForWarning(
230 - originalValue,
231 - )}`;
232 - }
233 - return description;
234 -}
235 -
236 -export function describeDifferencesForStylesheetOverPreinit(
237 - newProps: any,
238 - currentProps: any,
239 -): string {
240 - const diff = compareResourcePropsForWarning(newProps, currentProps);
241 - if (!diff) return '';
242 -
243 - let description = '';
244 -
245 - for (const propName in diff.extra) {
246 - const propValue = diff.extra[propName];
247 - if (
248 - propName === 'precedence' ||
249 - propName === 'crossOrigin' ||
250 - propName === 'integrity'
251 - ) {
252 - description += `\n "${propName}" prop value: ${getValueDescriptorExpectingEnumForWarning(
253 - propValue,
254 - )}, option missing`;
255 - } else {
256 - description += `\n "${propName}" prop value: ${getValueDescriptorExpectingEnumForWarning(
257 - propValue,
258 - )}, option not available with ReactDOM.preinit()`;
259 - }
260 - }
261 - for (const propName in diff.different) {
262 - const latestValue = diff.different[propName].latest;
263 - const originalValue = diff.different[propName].original;
264 - if (propName === 'precedence' && originalValue === 'default') {
265 - description += `\n "${propName}" prop value: ${getValueDescriptorExpectingEnumForWarning(
266 - latestValue,
267 - )}, missing from options`;
268 - } else {
269 - description += `\n "${propName}" prop value: ${getValueDescriptorExpectingEnumForWarning(
270 - latestValue,
271 - )}, option value: ${getValueDescriptorExpectingEnumForWarning(
272 - originalValue,
273 - )}`;
274 - }
275 - }
276 - return description;
277 -}
278 -
279 -export function describeDifferencesForPreinitOverStylesheet(
280 - newProps: any,
281 - currentProps: any,
282 -): string {
283 - const diff = compareResourcePropsForWarning(newProps, currentProps);
284 - if (!diff) return '';
285 -
286 - let description = '';
287 - for (const propName in diff.missing) {
288 - const propValue = diff.missing[propName];
289 - if (propName === 'precedence' && propValue !== 'default') {
290 - description += `\n "${propName}" missing from options, prop value: ${getValueDescriptorExpectingEnumForWarning(
291 - propValue,
292 - )}`;
293 - }
294 - }
295 - for (const propName in diff.extra) {
296 - const propValue = diff.extra[propName];
297 - if (
298 - propName === 'precedence' ||
299 - propName === 'crossOrigin' ||
300 - propName === 'integrity'
301 - ) {
302 - description += `\n "${propName}" option value: ${getValueDescriptorExpectingEnumForWarning(
303 - propValue,
304 - )}, missing from props`;
305 - }
306 - }
307 - for (const propName in diff.different) {
308 - const latestValue = diff.different[propName].latest;
309 - const originalValue = diff.different[propName].original;
310 - description += `\n "${propName}" option value: ${getValueDescriptorExpectingEnumForWarning(
311 - latestValue,
312 - )}, prop value: ${getValueDescriptorExpectingEnumForWarning(
313 - originalValue,
314 - )}`;
315 - }
316 - return description;
317 -}
318 -
319 -export function describeDifferencesForPreinits(
320 - newProps: any,
321 - currentProps: any,
322 -): string {
323 - const diff = compareResourcePropsForWarning(newProps, currentProps);
324 - if (!diff) return '';
325 -
326 - let description = '';
327 - for (const propName in diff.missing) {
328 - const propValue = diff.missing[propName];
329 - if (propName === 'precedence' && propValue !== 'default') {
330 - description += `\n "${propName}" missing from options, original option value: ${getValueDescriptorExpectingEnumForWarning(
331 - propValue,
332 - )}`;
333 - }
334 - }
335 - for (const propName in diff.extra) {
336 - const propValue = diff.extra[propName];
337 - if (
338 - (propName === 'precedence' && propValue !== 'default') ||
339 - propName === 'crossOrigin' ||
340 - propName === 'integrity'
341 - ) {
342 - description += `\n "${propName}" option value: ${getValueDescriptorExpectingEnumForWarning(
343 - propValue,
344 - )}, missing from original options`;
345 - }
346 - }
347 - for (const propName in diff.different) {
348 - const latestValue = diff.different[propName].latest;
349 - const originalValue = diff.different[propName].original;
350 - description += `\n "${propName}" option value: ${getValueDescriptorExpectingEnumForWarning(
351 - latestValue,
352 - )}, original option value: ${getValueDescriptorExpectingEnumForWarning(
353 - originalValue,
354 - )}`;
355 - }
356 - return description;
357 -}
358 -
359 -const preloadOptionsForComparison = ['as', 'crossOrigin', 'integrity', 'media'];
360 -
361 -export function describeDifferencesForPreloads(
362 - newProps: any,
363 - currentProps: any,
364 -): string {
365 - const diff = compareResourcePropsForWarning(newProps, currentProps);
366 - if (!diff) return '';
367 -
368 - let description = '';
369 - for (const propName in diff.missing) {
370 - const propValue = diff.missing[propName];
371 - if (preloadOptionsForComparison.includes(propName)) {
372 - description += `\n "${propName}" missing from options, original option value: ${getValueDescriptorExpectingEnumForWarning(
373 - propValue,
374 - )}`;
375 - }
376 - }
377 - for (const propName in diff.extra) {
378 - const propValue = diff.extra[propName];
379 - if (preloadOptionsForComparison.includes(propName)) {
380 - description += `\n "${propName}" option value: ${getValueDescriptorExpectingEnumForWarning(
381 - propValue,
382 - )}, missing from original options`;
383 - }
384 - }
385 - for (const propName in diff.different) {
386 - const latestValue = diff.different[propName].latest;
387 - const originalValue = diff.different[propName].original;
388 - if (preloadOptionsForComparison.includes(propName)) {
389 - description += `\n "${propName}" option value: ${getValueDescriptorExpectingEnumForWarning(
390 - latestValue,
391 - )}, original option value: ${getValueDescriptorExpectingEnumForWarning(
392 - originalValue,
393 - )}`;
394 - }
395 - }
396 - return description;
397 -}
398 -
399 -export function describeDifferencesForPreloadOverImplicitPreload(
400 - newProps: any,
401 - currentProps: any,
402 -): string {
403 - const diff = compareResourcePropsForWarning(newProps, currentProps);
404 - if (!diff) return '';
405 -
406 - let description = '';
407 - for (const propName in diff.missing) {
408 - const propValue = diff.missing[propName];
409 - if (preloadOptionsForComparison.includes(propName)) {
410 - description += `\n "${propName}" missing from options, underlying prop value: ${getValueDescriptorExpectingEnumForWarning(
411 - propValue,
412 - )}`;
413 - }
414 - }
415 - for (const propName in diff.extra) {
416 - const propValue = diff.extra[propName];
417 - if (preloadOptionsForComparison.includes(propName)) {
418 - description += `\n "${propName}" option value: ${getValueDescriptorExpectingEnumForWarning(
419 - propValue,
420 - )}, missing from underlying props`;
421 - }
422 - }
423 - for (const propName in diff.different) {
424 - const latestValue = diff.different[propName].latest;
425 - const originalValue = diff.different[propName].original;
426 - if (preloadOptionsForComparison.includes(propName)) {
427 - description += `\n "${propName}" option value: ${getValueDescriptorExpectingEnumForWarning(
428 - latestValue,
429 - )}, underlying prop value: ${getValueDescriptorExpectingEnumForWarning(
430 - originalValue,
431 - )}`;
432 - }
433 - }
434 - return description;
435 -}
436 -
437 -export function describeDifferencesForScripts(
438 - newProps: any,
439 - currentProps: any,
440 -): string {
441 - const diff = compareResourcePropsForWarning(newProps, currentProps);
442 - if (!diff) return '';
443 -
444 - let description = '';
445 -
446 - for (const propName in diff.missing) {
447 - const propValue = diff.missing[propName];
448 - description += `\n "${propName}" missing for props, original value: ${getValueDescriptorExpectingEnumForWarning(
449 - propValue,
450 - )}`;
451 - }
452 - for (const propName in diff.extra) {
453 - const propValue = diff.extra[propName];
454 - description += `\n "${propName}" prop value: ${getValueDescriptorExpectingEnumForWarning(
455 - propValue,
456 - )}, missing from original props`;
457 - }
458 - for (const propName in diff.different) {
459 - const latestValue = diff.different[propName].latest;
460 - const originalValue = diff.different[propName].original;
461 - description += `\n "${propName}" prop value: ${getValueDescriptorExpectingEnumForWarning(
462 - latestValue,
463 - )}, original value: ${getValueDescriptorExpectingEnumForWarning(
464 - originalValue,
465 - )}`;
466 - }
467 - return description;
468 -}
469 -
470 -export function describeDifferencesForScriptOverPreinit(
471 - newProps: any,
472 - currentProps: any,
473 -): string {
474 - const diff = compareResourcePropsForWarning(newProps, currentProps);
475 - if (!diff) return '';
476 -
477 - let description = '';
478 -
479 - for (const propName in diff.extra) {
480 - const propValue = diff.extra[propName];
481 - if (propName === 'crossOrigin' || propName === 'integrity') {
482 - description += `\n "${propName}" prop value: ${getValueDescriptorExpectingEnumForWarning(
483 - propValue,
484 - )}, option missing`;
485 - } else {
486 - description += `\n "${propName}" prop value: ${getValueDescriptorExpectingEnumForWarning(
487 - propValue,
488 - )}, option not available with ReactDOM.preinit()`;
489 - }
490 - }
491 - for (const propName in diff.different) {
492 - const latestValue = diff.different[propName].latest;
493 - const originalValue = diff.different[propName].original;
494 - description += `\n "${propName}" prop value: ${getValueDescriptorExpectingEnumForWarning(
495 - latestValue,
496 - )}, option value: ${getValueDescriptorExpectingEnumForWarning(
497 - originalValue,
498 - )}`;
499 - }
500 - return description;
501 -}
502 -
503 -export function describeDifferencesForPreinitOverScript(
504 - newProps: any,
505 - currentProps: any,
506 -): string {
507 - const diff = compareResourcePropsForWarning(newProps, currentProps);
508 - if (!diff) return '';
509 -
510 - let description = '';
511 -
512 - for (const propName in diff.extra) {
513 - const propValue = diff.extra[propName];
514 - if (propName === 'crossOrigin' || propName === 'integrity') {
515 - description += `\n "${propName}" option value: ${getValueDescriptorExpectingEnumForWarning(
516 - propValue,
517 - )}, missing from props`;
518 - }
519 - }
520 - for (const propName in diff.different) {
521 - const latestValue = diff.different[propName].latest;
522 - const originalValue = diff.different[propName].original;
523 - description += `\n "${propName}" option value: ${getValueDescriptorExpectingEnumForWarning(
524 - latestValue,
525 - )}, prop value: ${getValueDescriptorExpectingEnumForWarning(
526 - originalValue,
527 - )}`;
528 - }
529 - return description;
530 -}
packages/react-dom/src/__tests__/ReactDOMFloat-test.js
-262
@@ -4295,40 +4295,6 @@ body {
4295 ]);
4296 });
4297
4298 - // @gate enableFloat
4299 - it('warns if you pass incompatible options to two `ReactDOM.preload(...)` with the same href', async () => {
4300 - function Component() {
4301 - ReactDOM.preload('foo', {
4302 - as: 'font',
4303 - crossOrigin: 'use-credentials',
4304 - });
4305 - ReactDOM.preload('foo', {
4306 - as: 'font',
4307 - integrity: 'some hash',
4308 - crossOrigin: 'anonymous',
4309 - });
4310 - ReactDOM.preload('foo', {
4311 - as: 'font',
4312 - extra: 'ignored',
4313 - });
4314 - }
4315 -
4316 - await expect(async () => {
4317 - await act(() => {
4318 - renderToPipeableStream(
4319 - <html>
4320 - <body>
4321 - <Component />
4322 - </body>
4323 - </html>,
4324 - );
4325 - });
4326 - }).toErrorDev([
4327 - 'Warning: ReactDOM.preload(): The options provided conflict with another call to `ReactDOM.preload("foo", { as: "font", ...})`. React will always use the options it first encounters when preloading a resource for a given `href` and `as` type, and any later options will be ignored if different. Try updating all calls to `ReactDOM.preload()` with the same `href` and `as` type to use the same options, or eliminate one of the calls.\n "integrity" option value: "some hash", missing from original options\n "crossOrigin" option value: "anonymous", original option value: "use-credentials"',
4328 - 'Warning: ReactDOM.preload(): The options provided conflict with another call to `ReactDOM.preload("foo", { as: "font", ...})`. React will always use the options it first encounters when preloading a resource for a given `href` and `as` type, and any later options will be ignored if different. Try updating all calls to `ReactDOM.preload()` with the same `href` and `as` type to use the same options, or eliminate one of the calls.\n "crossOrigin" missing from options, original option value: "use-credentials"',
4329 - ]);
4330 - });
4331 -
4298 it('supports fetchPriority', async () => {
4299 function Component({isServer}) {
4300 ReactDOM.preload(isServer ? 'highserver' : 'highclient', {
@@ -4759,122 +4725,6 @@ body {
4725 ]);
4726 });
4727
4762 - // @gate enableFloat
4763 - it('warns if you pass options to `ReactDOM.preinit(..., { as: "style", ... })` incompatible with props from an existing <link rel="stylesheet" .../>', async () => {
4764 - function Component() {
4765 - ReactDOM.preinit('foo', {
4766 - as: 'style',
4767 - integrity: 'some hash',
4768 - crossOrigin: 'use-credentials',
4769 - });
4770 - }
4771 -
4772 - await expect(async () => {
4773 - await act(() => {
4774 - renderToPipeableStream(
4775 - <html>
4776 - <body>
4777 - <link
4778 - rel="stylesheet"
4779 - href="foo"
4780 - precedence="foo"
4781 - crossOrigin="anonymous"
4782 - />
4783 - <Component />
4784 - </body>
4785 - </html>,
4786 - );
4787 - });
4788 - }).toErrorDev([
4789 - 'ReactDOM.preinit(): For `href` "foo", the options provided conflict with props found on a <link rel="stylesheet" precedence="foo" href="foo" .../> that was already rendered. React will always use the props or options it first encounters for a hoistable stylesheet for a given `href` and any later props or options will be ignored if different. Generally, ReactDOM.preinit() is useful when you are not yet rendering a stylesheet but you anticipate it will be used soon. In this case the stylesheet was already rendered so preinitializing it does not provide any additional benefit. To resolve, try making the props and options agree between the <link rel="stylesheet" .../> and the `ReactDOM.preinit()` call or remove the `ReactDOM.preinit()` call.\n "precedence" missing from options, prop value: "foo"\n "integrity" option value: "some hash", missing from props\n "crossOrigin" option value: "use-credentials", prop value: "anonymous"',
4790 - ]);
4791 - });
4792 -
4793 - // @gate enableFloat
4794 - it('warns if you pass incompatible options to two `ReactDOM.preinit(..., { as: "style", ... })` with the same href', async () => {
4795 - function Component() {
4796 - ReactDOM.preinit('foo', {
4797 - as: 'style',
4798 - precedence: 'foo',
4799 - crossOrigin: 'use-credentials',
4800 - });
4801 - ReactDOM.preinit('foo', {
4802 - as: 'style',
4803 - integrity: 'some hash',
4804 - crossOrigin: 'anonymous',
4805 - });
4806 - }
4807 -
4808 - await expect(async () => {
4809 - await act(() => {
4810 - renderToPipeableStream(
4811 - <html>
4812 - <body>
4813 - <Component />
4814 - </body>
4815 - </html>,
4816 - );
4817 - });
4818 - }).toErrorDev([
4819 - 'ReactDOM.preinit(): For `href` "foo", the options provided conflict with another call to `ReactDOM.preinit("foo", { as: "style", ... })`. React will always use the options it first encounters when preinitializing a hoistable stylesheet for a given `href` and any later options will be ignored if different. Try updating all calls to `ReactDOM.preinit()` for a given `href` to use the same options, or only call `ReactDOM.preinit()` once per `href`.\n "precedence" missing from options, original option value: "foo"\n "integrity" option value: "some hash", missing from original options\n "crossOrigin" option value: "anonymous", original option value: "use-credentials"',
4820 - ]);
4821 - });
4822 -
4823 - // @gate enableFloat
4824 - it('warns if you pass options to `ReactDOM.preinit(..., { as: "script", ... })` incompatible with props from an existing <script async={true} .../>', async () => {
4825 - function Component() {
4826 - ReactDOM.preinit('foo', {
4827 - as: 'script',
4828 - integrity: 'some hash',
4829 - crossOrigin: 'use-credentials',
4830 - });
4831 - }
4832 -
4833 - await expect(async () => {
4834 - await act(() => {
4835 - renderToPipeableStream(
4836 - <html>
4837 - <body>
4838 - <script async={true} src="foo" crossOrigin="anonymous" />
4839 - <Component />
4840 - </body>
4841 - </html>,
4842 - );
4843 - });
4844 - }).toErrorDev([
4845 - 'ReactDOM.preinit(): For `href` "foo", the options provided conflict with props found on a <script async={true} src="foo" .../> that was already rendered. React will always use the props or options it first encounters for a hoistable script for a given `href` and any later props or options will be ignored if different. Generally, ReactDOM.preinit() is useful when you are not yet rendering a script but you anticipate it will be used soon and want to go beyond preloading it and have it execute early. In this case the script was already rendered so preinitializing it does not provide any additional benefit. To resolve, try making the props and options agree between the <script .../> and the `ReactDOM.preinit()` call or remove the `ReactDOM.preinit()` call.\n "integrity" option value: "some hash", missing from props\n "crossOrigin" option value: "use-credentials", prop value: "anonymous"',
4846 - ]);
4847 - });
4848 -
4849 - // @gate enableFloat
4850 - it('warns if you pass incompatible options to two `ReactDOM.preinit(..., { as: "script", ... })` with the same href', async () => {
4851 - function Component() {
4852 - ReactDOM.preinit('foo', {
4853 - as: 'script',
4854 - crossOrigin: 'use-credentials',
4855 - });
4856 - ReactDOM.preinit('foo', {
4857 - as: 'script',
4858 - integrity: 'some hash',
4859 - crossOrigin: 'anonymous',
4860 - });
4861 - }
4862 -
4863 - await expect(async () => {
4864 - await act(() => {
4865 - renderToPipeableStream(
4866 - <html>
4867 - <body>
4868 - <Component />
4869 - </body>
4870 - </html>,
4871 - );
4872 - });
4873 - }).toErrorDev([
4874 - 'ReactDOM.preinit(): For `href` "foo", the options provided conflict with another call to `ReactDOM.preinit("foo", { as: "script", ... })`. React will always use the options it first encounters when preinitializing a hoistable script for a given `href` and any later options will be ignored if different. Try updating all calls to `ReactDOM.preinit()` for a given `href` to use the same options, or only call `ReactDOM.preinit()` once per `href`.\n "integrity" option value: "some hash", missing from original options\n "crossOrigin" option value: "anonymous", original option value: "use-credentials"',
4875 - ]);
4876 - });
4877 -
4728 it('accepts a `nonce` option for `as: "script"`', async () => {
4729 function Component({src}) {
4730 ReactDOM.preinit(src, {as: 'script', nonce: 'R4nD0m'});
@@ -5892,57 +5742,6 @@ body {
5742 ]);
5743 });
5744
5895 - // @gate enableFloat
5896 - it('warns if you provide different props between <link re="stylesheet" .../> and ReactDOM.preinit(..., {as: "style"}) for the same `href`', async () => {
5897 - function App() {
5898 - ReactDOM.preinit('foo', {as: 'style'});
5899 - return (
5900 - <html>
5901 - <body>
5902 - <link rel="stylesheet" href="foo" precedence="foo" media="all" />
5903 - hello
5904 - </body>
5905 - </html>
5906 - );
5907 - }
5908 - await expect(async () => {
5909 - await act(() => {
5910 - const {pipe} = renderToPipeableStream(<App />);
5911 - pipe(writable);
5912 - });
5913 - }).toErrorDev([
5914 - 'Warning: React encountered a <link rel="stylesheet" precedence="foo" href="foo" .../> with props that conflict with the options provided to `ReactDOM.preinit("foo", { as: "style", ... })`. React will use the first props or preinitialization options encountered when rendering a hoistable stylesheet with a particular `href` and will ignore any newer props or options. The first instance of this stylesheet resource was created using the `ReactDOM.preinit()` function. Please note, `ReactDOM.preinit()` is modeled off of module import assertions capabilities and does not support arbitrary props. If you need to have props not included with the preinit options you will need to rely on rendering <link> tags only.\n "media" prop value: "all", option not available with ReactDOM.preinit()\n "precedence" prop value: "foo", missing from options',
5915 - ]);
5916 - });
5917 -
5918 - // @gate enableFloat
5919 - it('warns if you provide different props between two <link re="stylesheet" .../> that share the same `href`', async () => {
5920 - function App() {
5921 - return (
5922 - <html>
5923 - <body>
5924 - <link rel="stylesheet" href="foo" precedence="foo" media="all" />
5925 - <link
5926 - rel="stylesheet"
5927 - href="foo"
5928 - precedence="bar"
5929 - data-extra="foo"
5930 - />
5931 - hello
5932 - </body>
5933 - </html>
5934 - );
5935 - }
5936 - await expect(async () => {
5937 - await act(() => {
5938 - const {pipe} = renderToPipeableStream(<App />);
5939 - pipe(writable);
5940 - });
5941 - }).toErrorDev([
5942 - 'Warning: React encountered a <link rel="stylesheet" href="foo" .../> with a `precedence` prop that has props that conflict with another hoistable stylesheet with the same `href`. When using `precedence` with <link rel="stylsheet" .../> the props from the first encountered instance will be used and props from later instances will be ignored. Update the props on either <link rel="stylesheet" .../> instance so they agree.\n "media" missing for props, original value: "all"\n "data-extra" prop value: "foo", missing from original props\n "precedence" prop value: "bar", original value: "foo"',
5943 - ]);
5944 - });
5945 -
5745 // @gate enableFloat
5746 it('will not block displaying a Suspense boundary on a stylesheet with media that does not match', async () => {
5747 await act(() => {
@@ -6720,67 +6519,6 @@ background-color: green;
6519 </div>,
6520 );
6521 });
6723 -
6724 - // @gate enableFloat
6725 - it('warns if you provide different props between <script async={true} .../> and ReactDOM.preinit(..., {as: "script"}) for the same `href`', async () => {
6726 - function App() {
6727 - ReactDOM.preinit('foo', {as: 'script', integrity: 'some hash'});
6728 - return (
6729 - <html>
6730 - <body>
6731 - <script
6732 - async={true}
6733 - src="foo"
6734 - integrity="different hash"
6735 - data-foo=""
6736 - />
6737 - hello
6738 - </body>
6739 - </html>
6740 - );
6741 - }
6742 - await expect(async () => {
6743 - await act(() => {
6744 - const {pipe} = renderToPipeableStream(<App />);
6745 - pipe(writable);
6746 - });
6747 - }).toErrorDev([
6748 - 'Warning: React encountered a <script async={true} src="foo" .../> with props that conflict with the options provided to `ReactDOM.preinit("foo", { as: "script", ... })`. React will use the first props or preinitialization options encountered when rendering a hoistable script with a particular `src` and will ignore any newer props or options. The first instance of this script resource was created using the `ReactDOM.preinit()` function. Please note, `ReactDOM.preinit()` is modeled off of module import assertions capabilities and does not support arbitrary props. If you need to have props not included with the preinit options you will need to rely on rendering <script> tags only.\n "data-foo" prop value: an empty string, option not available with ReactDOM.preinit()\n "integrity" prop value: "different hash", option value: "some hash"',
6749 - ]);
6750 - });
6751 -
6752 - // @gate enableFloat
6753 - it('warns if you provide different props between two <script async={true} .../> that share the same `src`', async () => {
6754 - function App() {
6755 - return (
6756 - <html>
6757 - <body>
6758 - <script
6759 - async={true}
6760 - src="foo"
6761 - integrity="some hash"
6762 - data-foo=""
6763 - />
6764 - <script
6765 - async={true}
6766 - src="foo"
6767 - integrity="different hash"
6768 - data-bar=""
6769 - />
6770 - hello
6771 - </body>
6772 - </html>
6773 - );
6774 - }
6775 - await expect(async () => {
6776 - await act(() => {
6777 - const {pipe} = renderToPipeableStream(<App />);
6778 - pipe(writable);
6779 - });
6780 - }).toErrorDev([
6781 - 'React encountered a <script async={true} src="foo" .../> that has props that conflict with another hoistable script with the same `src`. When rendering hoistable scripts (async scripts without any loading handlers) the props from the first encountered instance will be used and props from later instances will be ignored. Update the props on both <script async={true} .../> instance so they agree.\n "data-foo" missing for props, original value: an empty string\n "data-bar" prop value: an empty string, missing from original props\n "integrity" prop value: "different hash", original value: "some hash"',
6782 - ]);
6783 - });
6522 });
6523
6524 describe('Hoistables', () => {