@samitouri / QOS-React-2 / commits / 6cd6ba703d

Land enableNewBooleanProps everywhere (#28676)

Rolled out internally. Removing flag.

Jack Pope committed Mar 29, 2024 at 16:02 UTC 6cd6ba703de77e332ab201518b6e30e47cd49aaf
14 files changed +74 -140
packages/react-dom-bindings/src/client/ReactDOMComponent.js
+34 -41
@@ -70,7 +70,6 @@ import {
70 disableIEWorkarounds,
71 enableTrustedTypesIntegration,
72 enableFilterEmptyStringAttributesDOM,
73 - enableNewBooleanProps,
73 } from 'shared/ReactFeatureFlags';
74 import {
75 mediaEventTypes,
@@ -668,24 +667,20 @@ function setProp(
667 break;
668 }
669 // Boolean
671 - case 'inert':
672 - if (!enableNewBooleanProps) {
673 - setValueForAttribute(domElement, key, value);
674 - break;
675 - } else {
676 - if (__DEV__) {
677 - if (value === '' && !didWarnForNewBooleanPropsWithEmptyValue[key]) {
678 - didWarnForNewBooleanPropsWithEmptyValue[key] = true;
679 - console.error(
680 - 'Received an empty string for a boolean attribute `%s`. ' +
681 - 'This will treat the attribute as if it were false. ' +
682 - 'Either pass `false` to silence this warning, or ' +
683 - 'pass `true` if you used an empty string in earlier versions of React to indicate this attribute is true.',
684 - key,
685 - );
686 - }
670 + case 'inert': {
671 + if (__DEV__) {
672 + if (value === '' && !didWarnForNewBooleanPropsWithEmptyValue[key]) {
673 + didWarnForNewBooleanPropsWithEmptyValue[key] = true;
674 + console.error(
675 + 'Received an empty string for a boolean attribute `%s`. ' +
676 + 'This will treat the attribute as if it were false. ' +
677 + 'Either pass `false` to silence this warning, or ' +
678 + 'pass `true` if you used an empty string in earlier versions of React to indicate this attribute is true.',
679 + key,
680 + );
681 }
682 }
683 + }
684 // fallthrough for new boolean props without the flag on
685 case 'allowFullScreen':
686 case 'async':
@@ -2764,32 +2759,30 @@ function diffHydratedGenericElement(
2759 );
2760 continue;
2761 case 'inert':
2767 - if (enableNewBooleanProps) {
2768 - if (__DEV__) {
2769 - if (
2770 - value === '' &&
2771 - !didWarnForNewBooleanPropsWithEmptyValue[propKey]
2772 - ) {
2773 - didWarnForNewBooleanPropsWithEmptyValue[propKey] = true;
2774 - console.error(
2775 - 'Received an empty string for a boolean attribute `%s`. ' +
2776 - 'This will treat the attribute as if it were false. ' +
2777 - 'Either pass `false` to silence this warning, or ' +
2778 - 'pass `true` if you used an empty string in earlier versions of React to indicate this attribute is true.',
2779 - propKey,
2780 - );
2781 - }
2762 + if (__DEV__) {
2763 + if (
2764 + value === '' &&
2765 + !didWarnForNewBooleanPropsWithEmptyValue[propKey]
2766 + ) {
2767 + didWarnForNewBooleanPropsWithEmptyValue[propKey] = true;
2768 + console.error(
2769 + 'Received an empty string for a boolean attribute `%s`. ' +
2770 + 'This will treat the attribute as if it were false. ' +
2771 + 'Either pass `false` to silence this warning, or ' +
2772 + 'pass `true` if you used an empty string in earlier versions of React to indicate this attribute is true.',
2773 + propKey,
2774 + );
2775 }
2783 - hydrateBooleanAttribute(
2784 - domElement,
2785 - propKey,
2786 - propKey,
2787 - value,
2788 - extraAttributes,
2789 - serverDifferences,
2790 - );
2791 - continue;
2776 }
2777 + hydrateBooleanAttribute(
2778 + domElement,
2779 + propKey,
2780 + propKey,
2781 + value,
2782 + extraAttributes,
2783 + serverDifferences,
2784 + );
2785 + continue;
2786 // fallthrough for new boolean props without the flag on
2787 default: {
2788 if (
packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js
+18 -21
@@ -31,7 +31,6 @@ import {
31 enableBigIntSupport,
32 enableFilterEmptyStringAttributesDOM,
33 enableFizzExternalRuntime,
34 - enableNewBooleanProps,
34 } from 'shared/ReactFeatureFlags';
35
36 import type {
@@ -1423,29 +1422,27 @@ function pushAttribute(
1422 pushStringAttribute(target, 'xml:space', value);
1423 return;
1424 case 'inert': {
1426 - if (enableNewBooleanProps) {
1427 - if (__DEV__) {
1428 - if (value === '' && !didWarnForNewBooleanPropsWithEmptyValue[name]) {
1429 - didWarnForNewBooleanPropsWithEmptyValue[name] = true;
1430 - console.error(
1431 - 'Received an empty string for a boolean attribute `%s`. ' +
1432 - 'This will treat the attribute as if it were false. ' +
1433 - 'Either pass `false` to silence this warning, or ' +
1434 - 'pass `true` if you used an empty string in earlier versions of React to indicate this attribute is true.',
1435 - name,
1436 - );
1437 - }
1438 - }
1439 - // Boolean
1440 - if (value && typeof value !== 'function' && typeof value !== 'symbol') {
1441 - target.push(
1442 - attributeSeparator,
1443 - stringToChunk(name),
1444 - attributeEmptyString,
1425 + if (__DEV__) {
1426 + if (value === '' && !didWarnForNewBooleanPropsWithEmptyValue[name]) {
1427 + didWarnForNewBooleanPropsWithEmptyValue[name] = true;
1428 + console.error(
1429 + 'Received an empty string for a boolean attribute `%s`. ' +
1430 + 'This will treat the attribute as if it were false. ' +
1431 + 'Either pass `false` to silence this warning, or ' +
1432 + 'pass `true` if you used an empty string in earlier versions of React to indicate this attribute is true.',
1433 + name,
1434 );
1435 }
1447 - return;
1436 }
1437 + // Boolean
1438 + if (value && typeof value !== 'function' && typeof value !== 'symbol') {
1439 + target.push(
1440 + attributeSeparator,
1441 + stringToChunk(name),
1442 + attributeEmptyString,
1443 + );
1444 + }
1445 + return;
1446 }
1447 // fallthrough for new boolean props without the flag on
1448 default:
packages/react-dom-bindings/src/shared/ReactDOMUnknownPropertyHook.js
+4 -16
@@ -9,7 +9,6 @@ import {ATTRIBUTE_NAME_CHAR} from './isAttributeNameSafe';
9 import isCustomElement from './isCustomElement';
10 import possibleStandardNames from './possibleStandardNames';
11 import hasOwnProperty from 'shared/hasOwnProperty';
12 -import {enableNewBooleanProps} from 'shared/ReactFeatureFlags';
12
13 const warnedProperties = {};
14 const EVENT_NAME_REGEX = /^on./;
@@ -228,18 +227,12 @@ function validateProperty(tagName, name, value, eventRegistry) {
227 case 'seamless':
228 case 'itemScope':
229 case 'capture':
231 - case 'download': {
230 + case 'download':
231 + case 'inert': {
232 // Boolean properties can accept boolean values
233 return true;
234 }
235 // fallthrough
236 - case 'inert': {
237 - if (enableNewBooleanProps) {
238 - // Boolean properties can accept boolean values
239 - return true;
240 - }
241 - }
242 - // fallthrough for new boolean props without the flag on
236 default: {
237 const prefix = name.toLowerCase().slice(0, 5);
238 if (prefix === 'data-' || prefix === 'aria-') {
@@ -311,15 +304,10 @@ function validateProperty(tagName, name, value, eventRegistry) {
304 case 'reversed':
305 case 'scoped':
306 case 'seamless':
314 - case 'itemScope': {
315 - break;
316 - }
307 + case 'itemScope':
308 case 'inert': {
318 - if (enableNewBooleanProps) {
319 - break;
320 - }
309 + break;
310 }
322 - // fallthrough for new boolean props without the flag on
311 default: {
312 return true;
313 }
packages/react-dom-bindings/src/shared/possibleStandardNames.js
+1 -5
@@ -4,7 +4,6 @@
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7 -import {enableNewBooleanProps} from 'shared/ReactFeatureFlags';
7
8 // When adding attributes to the HTML or SVG allowed attribute list, be sure to
9 // also add them to this module to ensure casing and incorrect name
@@ -83,6 +82,7 @@ const possibleStandardNames = {
82 id: 'id',
83 imagesizes: 'imageSizes',
84 imagesrcset: 'imageSrcSet',
85 + inert: 'inert',
86 innerhtml: 'innerHTML',
87 inputmode: 'inputMode',
88 integrity: 'integrity',
@@ -503,8 +503,4 @@ const possibleStandardNames = {
503 zoomandpan: 'zoomAndPan',
504 };
505
506 -if (enableNewBooleanProps) {
507 - possibleStandardNames.inert = 'inert';
508 -}
509 -
506 export default possibleStandardNames;
packages/react-dom/src/__tests__/ReactDOMAttribute-test.js
+10 -24
@@ -12,14 +12,12 @@
12 describe('ReactDOM unknown attribute', () => {
13 let React;
14 let ReactDOMClient;
15 - let ReactFeatureFlags;
15 let act;
16
17 beforeEach(() => {
18 jest.resetModules();
19 React = require('react');
20 ReactDOMClient = require('react-dom/client');
22 - ReactFeatureFlags = require('shared/ReactFeatureFlags');
21 act = require('internal-test-utils').act;
22 });
23
@@ -98,15 +96,9 @@ describe('ReactDOM unknown attribute', () => {
96 await act(() => {
97 root.render(<div inert={true} />);
98 });
101 - }).toErrorDev(
102 - ReactFeatureFlags.enableNewBooleanProps
103 - ? []
104 - : ['Warning: Received `true` for a non-boolean attribute `inert`.'],
105 - );
99 + }).toErrorDev([]);
100
107 - expect(el.firstChild.getAttribute('inert')).toBe(
108 - ReactFeatureFlags.enableNewBooleanProps ? '' : null,
109 - );
101 + expect(el.firstChild.getAttribute('inert')).toBe(true ? '' : null);
102 });
103
104 it('warns once for empty strings in new boolean props', async () => {
@@ -117,20 +109,14 @@ describe('ReactDOM unknown attribute', () => {
109 await act(() => {
110 root.render(<div inert="" />);
111 });
120 - }).toErrorDev(
121 - ReactFeatureFlags.enableNewBooleanProps
122 - ? [
123 - 'Warning: Received an empty string for a boolean attribute `inert`. ' +
124 - 'This will treat the attribute as if it were false. ' +
125 - 'Either pass `false` to silence this warning, or ' +
126 - 'pass `true` if you used an empty string in earlier versions of React to indicate this attribute is true.',
127 - ]
128 - : [],
129 - );
130 -
131 - expect(el.firstChild.getAttribute('inert')).toBe(
132 - ReactFeatureFlags.enableNewBooleanProps ? null : '',
133 - );
112 + }).toErrorDev([
113 + 'Warning: Received an empty string for a boolean attribute `inert`. ' +
114 + 'This will treat the attribute as if it were false. ' +
115 + 'Either pass `false` to silence this warning, or ' +
116 + 'pass `true` if you used an empty string in earlier versions of React to indicate this attribute is true.',
117 + ]);
118 +
119 + expect(el.firstChild.getAttribute('inert')).toBe(true ? null : '');
120
121 // The warning is only printed once.
122 await act(() => {
packages/react-dom/src/__tests__/ReactDOMServerIntegrationAttributes-test.js
+7 -19
@@ -742,36 +742,24 @@ describe('ReactDOMServerIntegration', () => {
742 });
743
744 itRenders('new boolean `true` attributes', async render => {
745 - const element = await render(
746 - <div inert={true} />,
747 - ReactFeatureFlags.enableNewBooleanProps ? 0 : 1,
748 - );
745 + const element = await render(<div inert={true} />, 0);
746
750 - expect(element.getAttribute('inert')).toBe(
751 - ReactFeatureFlags.enableNewBooleanProps ? '' : null,
752 - );
747 + expect(element.getAttribute('inert')).toBe('');
748 });
749
750 itRenders('new boolean `""` attributes', async render => {
751 const element = await render(
752 <div inert="" />,
758 - ReactFeatureFlags.enableNewBooleanProps
759 - ? // Warns since this used to render `inert=""` like `inert={true}`
760 - // but now renders it like `inert={false}`.
761 - 1
762 - : 0,
753 + // Warns since this used to render `inert=""` like `inert={true}`
754 + // but now renders it like `inert={false}`.
755 + 1,
756 );
757
765 - expect(element.getAttribute('inert')).toBe(
766 - ReactFeatureFlags.enableNewBooleanProps ? null : '',
767 - );
758 + expect(element.getAttribute('inert')).toBe(null);
759 });
760
761 itRenders('new boolean `false` attributes', async render => {
771 - const element = await render(
772 - <div inert={false} />,
773 - ReactFeatureFlags.enableNewBooleanProps ? 0 : 1,
774 - );
762 + const element = await render(<div inert={false} />, 0);
763
764 expect(element.getAttribute('inert')).toBe(null);
765 });
packages/shared/ReactFeatureFlags.js
-7
@@ -183,13 +183,6 @@ export const disableLegacyMode = __NEXT_MAJOR__;
183
184 export const disableDOMTestUtils = __NEXT_MAJOR__;
185
186 -// HTML boolean attributes need a special PropertyInfoRecord.
187 -// Between support of these attributes in browsers and React supporting them as
188 -// boolean props library users can use them as `<div someBooleanAttribute="" />`.
189 -// However, once React considers them as boolean props an empty string will
190 -// result in false property i.e. break existing usage.
191 -export const enableNewBooleanProps = __NEXT_MAJOR__;
192 -
186 // Make <Context> equivalent to <Context.Provider> instead of <Context.Consumer>
187 export const enableRenderableContext = __NEXT_MAJOR__;
188
packages/shared/forks/ReactFeatureFlags.native-fb.js
-1
@@ -78,7 +78,6 @@ export const enableLazyContextPropagation = false;
78 export const enableLegacyHidden = false;
79 export const forceConcurrentByDefaultForTesting = false;
80 export const allowConcurrentByDefault = false;
81 -export const enableNewBooleanProps = true;
81
82 export const enableTransitionTracing = false;
83
packages/shared/forks/ReactFeatureFlags.native-oss.js
-1
@@ -99,7 +99,6 @@ export const enableLazyContextPropagation = false;
99 export const enableLegacyHidden = false;
100 export const forceConcurrentByDefaultForTesting = false;
101 export const allowConcurrentByDefault = false;
102 -export const enableNewBooleanProps = true;
102 export const enableTransitionTracing = false;
103 export const enableDO_NOT_USE_disableStrictPassiveEffect = false;
104 export const passChildrenWhenCloningPersistedNodes = false;
packages/shared/forks/ReactFeatureFlags.test-renderer.js
-1
@@ -92,7 +92,6 @@ export const enableBigIntSupport = __NEXT_MAJOR__;
92 export const disableLegacyMode = __NEXT_MAJOR__;
93 export const disableLegacyContext = __NEXT_MAJOR__;
94 export const disableDOMTestUtils = __NEXT_MAJOR__;
95 -export const enableNewBooleanProps = __NEXT_MAJOR__;
95 export const enableRenderableContext = __NEXT_MAJOR__;
96 export const enableReactTestRendererWarning = __NEXT_MAJOR__;
97
packages/shared/forks/ReactFeatureFlags.test-renderer.native.js
-1
@@ -59,7 +59,6 @@ export const enableLegacyHidden = false;
59 export const forceConcurrentByDefaultForTesting = false;
60 export const enableUnifiedSyncLane = true;
61 export const allowConcurrentByDefault = true;
62 -export const enableNewBooleanProps = true;
62
63 export const consoleManagedByDevToolsDuringStrictMode = false;
64
packages/shared/forks/ReactFeatureFlags.test-renderer.www.js
-1
@@ -59,7 +59,6 @@ export const enableLegacyHidden = false;
59 export const forceConcurrentByDefaultForTesting = false;
60 export const enableUnifiedSyncLane = true;
61 export const allowConcurrentByDefault = true;
62 -export const enableNewBooleanProps = false;
62
63 export const consoleManagedByDevToolsDuringStrictMode = false;
64
packages/shared/forks/ReactFeatureFlags.www-dynamic.js
-1
@@ -30,7 +30,6 @@ export const enableUseDeferredValueInitialArg = __VARIANT__;
30 export const enableRenderableContext = __VARIANT__;
31 export const useModernStrictMode = __VARIANT__;
32 export const enableRefAsProp = __VARIANT__;
33 -export const enableNewBooleanProps = __VARIANT__;
33 export const enableRetryLaneExpiration = __VARIANT__;
34 export const favorSafetyOverHydrationPerf = __VARIANT__;
35 export const retryLaneExpirationMs = 5000;
packages/shared/forks/ReactFeatureFlags.www.js
-1
@@ -38,7 +38,6 @@ export const {
38 enableRenderableContext,
39 useModernStrictMode,
40 enableRefAsProp,
41 - enableNewBooleanProps,
41 favorSafetyOverHydrationPerf,
42 } = dynamicFeatureFlags;
43