Statically enable enableFilterEmptyStringAttributesDOM (#19502)
Dan Abramov committed
Jul 31, 2020 at 14:57 UTC
815ee89bf55078f2447fe49a1c68336e70c1ce44
12 files changed
+111
-131
packages/react-dom/src/__tests__/ReactDOMComponent-test.js
+90
-92
@@ -441,110 +441,108 @@ describe('ReactDOMComponent', () => {
441
expect(node.hasAttribute('data-foo')).toBe(false);
442
});
443
444
- if (ReactFeatureFlags.enableFilterEmptyStringAttributesDOM) {
445
- it('should not add an empty src attribute', () => {
446
- const container = document.createElement('div');
447
- expect(() => ReactDOM.render(<img src="" />, container)).toErrorDev(
448
- 'An empty string ("") was passed to the src attribute. ' +
449
- 'This may cause the browser to download the whole page again over the network. ' +
450
- 'To fix this, either do not render the element at all ' +
451
- 'or pass null to src instead of an empty string.',
452
- );
453
- const node = container.firstChild;
454
- expect(node.hasAttribute('src')).toBe(false);
444
+ it('should not add an empty src attribute', () => {
445
+ const container = document.createElement('div');
446
+ expect(() => ReactDOM.render(<img src="" />, container)).toErrorDev(
447
+ 'An empty string ("") was passed to the src attribute. ' +
448
+ 'This may cause the browser to download the whole page again over the network. ' +
449
+ 'To fix this, either do not render the element at all ' +
450
+ 'or pass null to src instead of an empty string.',
451
+ );
452
+ const node = container.firstChild;
453
+ expect(node.hasAttribute('src')).toBe(false);
454
456
- ReactDOM.render(<img src="abc" />, container);
457
- expect(node.hasAttribute('src')).toBe(true);
455
+ ReactDOM.render(<img src="abc" />, container);
456
+ expect(node.hasAttribute('src')).toBe(true);
457
459
- expect(() => ReactDOM.render(<img src="" />, container)).toErrorDev(
460
- 'An empty string ("") was passed to the src attribute. ' +
461
- 'This may cause the browser to download the whole page again over the network. ' +
462
- 'To fix this, either do not render the element at all ' +
463
- 'or pass null to src instead of an empty string.',
464
- );
465
- expect(node.hasAttribute('src')).toBe(false);
466
- });
458
+ expect(() => ReactDOM.render(<img src="" />, container)).toErrorDev(
459
+ 'An empty string ("") was passed to the src attribute. ' +
460
+ 'This may cause the browser to download the whole page again over the network. ' +
461
+ 'To fix this, either do not render the element at all ' +
462
+ 'or pass null to src instead of an empty string.',
463
+ );
464
+ expect(node.hasAttribute('src')).toBe(false);
465
+ });
466
468
- it('should not add an empty href attribute', () => {
469
- const container = document.createElement('div');
470
- expect(() => ReactDOM.render(<link href="" />, container)).toErrorDev(
471
- 'An empty string ("") was passed to the href attribute. ' +
472
- 'To fix this, either do not render the element at all ' +
473
- 'or pass null to href instead of an empty string.',
474
- );
475
- const node = container.firstChild;
476
- expect(node.hasAttribute('href')).toBe(false);
467
+ it('should not add an empty href attribute', () => {
468
+ const container = document.createElement('div');
469
+ expect(() => ReactDOM.render(<link href="" />, container)).toErrorDev(
470
+ 'An empty string ("") was passed to the href attribute. ' +
471
+ 'To fix this, either do not render the element at all ' +
472
+ 'or pass null to href instead of an empty string.',
473
+ );
474
+ const node = container.firstChild;
475
+ expect(node.hasAttribute('href')).toBe(false);
476
478
- ReactDOM.render(<link href="abc" />, container);
479
- expect(node.hasAttribute('href')).toBe(true);
477
+ ReactDOM.render(<link href="abc" />, container);
478
+ expect(node.hasAttribute('href')).toBe(true);
479
481
- expect(() => ReactDOM.render(<link href="" />, container)).toErrorDev(
482
- 'An empty string ("") was passed to the href attribute. ' +
483
- 'To fix this, either do not render the element at all ' +
484
- 'or pass null to href instead of an empty string.',
485
- );
486
- expect(node.hasAttribute('href')).toBe(false);
487
- });
480
+ expect(() => ReactDOM.render(<link href="" />, container)).toErrorDev(
481
+ 'An empty string ("") was passed to the href attribute. ' +
482
+ 'To fix this, either do not render the element at all ' +
483
+ 'or pass null to href instead of an empty string.',
484
+ );
485
+ expect(node.hasAttribute('href')).toBe(false);
486
+ });
487
489
- it('should not add an empty action attribute', () => {
490
- const container = document.createElement('div');
491
- expect(() => ReactDOM.render(<form action="" />, container)).toErrorDev(
492
- 'An empty string ("") was passed to the action attribute. ' +
493
- 'To fix this, either do not render the element at all ' +
494
- 'or pass null to action instead of an empty string.',
495
- );
496
- const node = container.firstChild;
497
- expect(node.hasAttribute('action')).toBe(false);
488
+ it('should not add an empty action attribute', () => {
489
+ const container = document.createElement('div');
490
+ expect(() => ReactDOM.render(<form action="" />, container)).toErrorDev(
491
+ 'An empty string ("") was passed to the action attribute. ' +
492
+ 'To fix this, either do not render the element at all ' +
493
+ 'or pass null to action instead of an empty string.',
494
+ );
495
+ const node = container.firstChild;
496
+ expect(node.hasAttribute('action')).toBe(false);
497
499
- ReactDOM.render(<form action="abc" />, container);
500
- expect(node.hasAttribute('action')).toBe(true);
498
+ ReactDOM.render(<form action="abc" />, container);
499
+ expect(node.hasAttribute('action')).toBe(true);
500
502
- expect(() => ReactDOM.render(<form action="" />, container)).toErrorDev(
503
- 'An empty string ("") was passed to the action attribute. ' +
504
- 'To fix this, either do not render the element at all ' +
505
- 'or pass null to action instead of an empty string.',
506
- );
507
- expect(node.hasAttribute('action')).toBe(false);
508
- });
501
+ expect(() => ReactDOM.render(<form action="" />, container)).toErrorDev(
502
+ 'An empty string ("") was passed to the action attribute. ' +
503
+ 'To fix this, either do not render the element at all ' +
504
+ 'or pass null to action instead of an empty string.',
505
+ );
506
+ expect(node.hasAttribute('action')).toBe(false);
507
+ });
508
510
- it('should not add an empty formAction attribute', () => {
511
- const container = document.createElement('div');
512
- expect(() =>
513
- ReactDOM.render(<button formAction="" />, container),
514
- ).toErrorDev(
515
- 'An empty string ("") was passed to the formAction attribute. ' +
516
- 'To fix this, either do not render the element at all ' +
517
- 'or pass null to formAction instead of an empty string.',
518
- );
519
- const node = container.firstChild;
520
- expect(node.hasAttribute('formAction')).toBe(false);
509
+ it('should not add an empty formAction attribute', () => {
510
+ const container = document.createElement('div');
511
+ expect(() =>
512
+ ReactDOM.render(<button formAction="" />, container),
513
+ ).toErrorDev(
514
+ 'An empty string ("") was passed to the formAction attribute. ' +
515
+ 'To fix this, either do not render the element at all ' +
516
+ 'or pass null to formAction instead of an empty string.',
517
+ );
518
+ const node = container.firstChild;
519
+ expect(node.hasAttribute('formAction')).toBe(false);
520
522
- ReactDOM.render(<button formAction="abc" />, container);
523
- expect(node.hasAttribute('formAction')).toBe(true);
521
+ ReactDOM.render(<button formAction="abc" />, container);
522
+ expect(node.hasAttribute('formAction')).toBe(true);
523
525
- expect(() =>
526
- ReactDOM.render(<button formAction="" />, container),
527
- ).toErrorDev(
528
- 'An empty string ("") was passed to the formAction attribute. ' +
529
- 'To fix this, either do not render the element at all ' +
530
- 'or pass null to formAction instead of an empty string.',
531
- );
532
- expect(node.hasAttribute('formAction')).toBe(false);
533
- });
524
+ expect(() =>
525
+ ReactDOM.render(<button formAction="" />, container),
526
+ ).toErrorDev(
527
+ 'An empty string ("") was passed to the formAction attribute. ' +
528
+ 'To fix this, either do not render the element at all ' +
529
+ 'or pass null to formAction instead of an empty string.',
530
+ );
531
+ expect(node.hasAttribute('formAction')).toBe(false);
532
+ });
533
535
- it('should not filter attributes for custom elements', () => {
536
- const container = document.createElement('div');
537
- ReactDOM.render(
538
- <some-custom-element action="" formAction="" href="" src="" />,
539
- container,
540
- );
541
- const node = container.firstChild;
542
- expect(node.hasAttribute('action')).toBe(true);
543
- expect(node.hasAttribute('formAction')).toBe(true);
544
- expect(node.hasAttribute('href')).toBe(true);
545
- expect(node.hasAttribute('src')).toBe(true);
546
- });
547
- }
534
+ it('should not filter attributes for custom elements', () => {
535
+ const container = document.createElement('div');
536
+ ReactDOM.render(
537
+ <some-custom-element action="" formAction="" href="" src="" />,
538
+ container,
539
+ );
540
+ const node = container.firstChild;
541
+ expect(node.hasAttribute('action')).toBe(true);
542
+ expect(node.hasAttribute('formAction')).toBe(true);
543
+ expect(node.hasAttribute('href')).toBe(true);
544
+ expect(node.hasAttribute('src')).toBe(true);
545
+ });
546
547
it('should apply React-specific aliases to HTML elements', () => {
548
const container = document.createElement('div');
packages/react-dom/src/shared/DOMProperty.js
+21
-26
@@ -7,10 +7,7 @@
7
* @flow
8
*/
9
10
-import {
11
- enableDeprecatedFlareAPI,
12
- enableFilterEmptyStringAttributesDOM,
13
-} from 'shared/ReactFeatureFlags';
10
+import {enableDeprecatedFlareAPI} from 'shared/ReactFeatureFlags';
11
12
type PropertyType = 0 | 1 | 2 | 3 | 4 | 5 | 6;
13
@@ -167,30 +164,28 @@ export function shouldRemoveAttribute(
164
return false;
165
}
166
if (propertyInfo !== null) {
170
- if (enableFilterEmptyStringAttributesDOM) {
171
- if (propertyInfo.removeEmptyString && value === '') {
172
- if (__DEV__) {
173
- if (name === 'src') {
174
- console.error(
175
- 'An empty string ("") was passed to the %s attribute. ' +
176
- 'This may cause the browser to download the whole page again over the network. ' +
177
- 'To fix this, either do not render the element at all ' +
178
- 'or pass null to %s instead of an empty string.',
179
- name,
180
- name,
181
- );
182
- } else {
183
- console.error(
184
- 'An empty string ("") was passed to the %s attribute. ' +
185
- 'To fix this, either do not render the element at all ' +
186
- 'or pass null to %s instead of an empty string.',
187
- name,
188
- name,
189
- );
190
- }
167
+ if (propertyInfo.removeEmptyString && value === '') {
168
+ if (__DEV__) {
169
+ if (name === 'src') {
170
+ console.error(
171
+ 'An empty string ("") was passed to the %s attribute. ' +
172
+ 'This may cause the browser to download the whole page again over the network. ' +
173
+ 'To fix this, either do not render the element at all ' +
174
+ 'or pass null to %s instead of an empty string.',
175
+ name,
176
+ name,
177
+ );
178
+ } else {
179
+ console.error(
180
+ 'An empty string ("") was passed to the %s attribute. ' +
181
+ 'To fix this, either do not render the element at all ' +
182
+ 'or pass null to %s instead of an empty string.',
183
+ name,
184
+ name,
185
+ );
186
}
192
- return true;
187
}
188
+ return true;
189
}
190
191
switch (propertyInfo.type) {
packages/shared/ReactFeatureFlags.js
-4
@@ -7,10 +7,6 @@
7
* @flow strict
8
*/
9
10
-// Filter certain DOM attributes (e.g. src, href) if their values are empty strings.
11
-// This prevents e.g. <img src=""> from making an unnecessary HTTP request for certain browsers.
12
-export const enableFilterEmptyStringAttributesDOM = false;
13
-
10
// Adds verbose console logging for e.g. state updates, suspense, and work loop stuff.
11
// Intended to enable React core members to more easily debug scheduling issues in DEV builds.
12
export const enableDebugTracing = false;
packages/shared/forks/ReactFeatureFlags.native-fb.js
-1
@@ -44,7 +44,6 @@ export const warnUnstableRenderSubtreeIntoContainer = false;
44
export const warnAboutSpreadingKeyToJSX = false;
45
export const enableComponentStackLocations = false;
46
export const enableLegacyFBSupport = false;
47
-export const enableFilterEmptyStringAttributesDOM = false;
47
export const disableOnScrollBubbling = false;
48
49
export const enableNewReconciler = false;
packages/shared/forks/ReactFeatureFlags.native-oss.js
-1
@@ -43,7 +43,6 @@ export const warnUnstableRenderSubtreeIntoContainer = false;
43
export const warnAboutSpreadingKeyToJSX = false;
44
export const enableComponentStackLocations = false;
45
export const enableLegacyFBSupport = false;
46
-export const enableFilterEmptyStringAttributesDOM = false;
46
export const disableOnScrollBubbling = false;
47
48
export const enableNewReconciler = false;
packages/shared/forks/ReactFeatureFlags.test-renderer.js
-1
@@ -43,7 +43,6 @@ export const warnUnstableRenderSubtreeIntoContainer = false;
43
export const warnAboutSpreadingKeyToJSX = false;
44
export const enableComponentStackLocations = true;
45
export const enableLegacyFBSupport = false;
46
-export const enableFilterEmptyStringAttributesDOM = false;
46
export const disableOnScrollBubbling = false;
47
48
export const enableNewReconciler = false;
packages/shared/forks/ReactFeatureFlags.test-renderer.native.js
-1
@@ -43,7 +43,6 @@ export const warnUnstableRenderSubtreeIntoContainer = false;
43
export const warnAboutSpreadingKeyToJSX = false;
44
export const enableComponentStackLocations = false;
45
export const enableLegacyFBSupport = false;
46
-export const enableFilterEmptyStringAttributesDOM = false;
46
47
export const enableNewReconciler = false;
48
export const deferRenderPhaseUpdateToNextBatch = true;
packages/shared/forks/ReactFeatureFlags.test-renderer.www.js
-1
@@ -43,7 +43,6 @@ export const warnUnstableRenderSubtreeIntoContainer = false;
43
export const warnAboutSpreadingKeyToJSX = false;
44
export const enableComponentStackLocations = true;
45
export const enableLegacyFBSupport = false;
46
-export const enableFilterEmptyStringAttributesDOM = false;
46
export const disableOnScrollBubbling = false;
47
48
export const enableNewReconciler = false;
packages/shared/forks/ReactFeatureFlags.testing.js
-1
@@ -43,7 +43,6 @@ export const warnUnstableRenderSubtreeIntoContainer = false;
43
export const warnAboutSpreadingKeyToJSX = false;
44
export const enableComponentStackLocations = true;
45
export const enableLegacyFBSupport = false;
46
-export const enableFilterEmptyStringAttributesDOM = false;
46
export const disableOnScrollBubbling = false;
47
48
export const enableNewReconciler = false;
packages/shared/forks/ReactFeatureFlags.testing.www.js
-1
@@ -43,7 +43,6 @@ export const warnUnstableRenderSubtreeIntoContainer = false;
43
export const warnAboutSpreadingKeyToJSX = false;
44
export const enableComponentStackLocations = true;
45
export const enableLegacyFBSupport = !__EXPERIMENTAL__;
46
-export const enableFilterEmptyStringAttributesDOM = false;
46
export const disableOnScrollBubbling = false;
47
48
export const enableNewReconciler = false;
packages/shared/forks/ReactFeatureFlags.www-dynamic.js
-1
@@ -15,7 +15,6 @@
15
16
export const warnAboutSpreadingKeyToJSX = __VARIANT__;
17
export const disableInputAttributeSyncing = __VARIANT__;
18
-export const enableFilterEmptyStringAttributesDOM = __VARIANT__;
18
export const enableLegacyFBSupport = __VARIANT__;
19
export const decoupleUpdatePriorityFromScheduler = __VARIANT__;
20
export const disableOnScrollBubbling = __VARIANT__;
packages/shared/forks/ReactFeatureFlags.www.js
-1
@@ -21,7 +21,6 @@ export const {
21
disableSchedulerTimeoutBasedOnReactExpirationTime,
22
warnAboutSpreadingKeyToJSX,
23
replayFailedUnitOfWorkWithInvokeGuardedCallback,
24
- enableFilterEmptyStringAttributesDOM,
24
enableLegacyFBSupport,
25
deferRenderPhaseUpdateToNextBatch,
26
decoupleUpdatePriorityFromScheduler,