diff --git a/packages/react-dom/src/__tests__/ReactDOMComponent-test.js b/packages/react-dom/src/__tests__/ReactDOMComponent-test.js index c1f66a33a034..e695a845ff50 100644 --- a/packages/react-dom/src/__tests__/ReactDOMComponent-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMComponent-test.js @@ -146,141 +146,6 @@ describe('ReactDOMComponent', () => { } }); - it('should warn for conflicting CSS shorthand updates', () => { - const container = document.createElement('div'); - ReactDOM.render( -
, - container, - ); - expect(() => - ReactDOM.render(
, container), - ).toWarnDev( - 'Warning: Removing a style property during rerender (fontStyle) ' + - 'when a conflicting property is set (font) can lead to styling ' + - "bugs. To avoid this, don't mix shorthand and non-shorthand " + - 'properties for the same value; instead, replace the shorthand ' + - 'with separate values.' + - '\n in div (at **)', - ); - - // These updates are OK and don't warn: - ReactDOM.render( -
, - container, - ); - ReactDOM.render( -
, - container, - ); - - expect(() => - ReactDOM.render( -
, - container, - ), - ).toWarnDev( - 'Warning: Updating a style property during rerender (font) when ' + - 'a conflicting property is set (fontStyle) can lead to styling ' + - "bugs. To avoid this, don't mix shorthand and non-shorthand " + - 'properties for the same value; instead, replace the shorthand ' + - 'with separate values.' + - '\n in div (at **)', - ); - expect(() => - ReactDOM.render(
, container), - ).toWarnDev( - 'Warning: Removing a style property during rerender (font) when ' + - 'a conflicting property is set (fontStyle) can lead to styling ' + - "bugs. To avoid this, don't mix shorthand and non-shorthand " + - 'properties for the same value; instead, replace the shorthand ' + - 'with separate values.' + - '\n in div (at **)', - ); - - // A bit of a special case: backgroundPosition isn't technically longhand - // (it expands to backgroundPosition{X,Y} but so does background) - ReactDOM.render( -
, - container, - ); - expect(() => - ReactDOM.render(
, container), - ).toWarnDev( - 'Warning: Removing a style property during rerender ' + - '(backgroundPosition) when a conflicting property is set ' + - "(background) can lead to styling bugs. To avoid this, don't mix " + - 'shorthand and non-shorthand properties for the same value; ' + - 'instead, replace the shorthand with separate values.' + - '\n in div (at **)', - ); - ReactDOM.render( -
, - container, - ); - // But setting them at the same time is OK: - ReactDOM.render( -
, - container, - ); - expect(() => - ReactDOM.render(
, container), - ).toWarnDev( - 'Warning: Removing a style property during rerender (background) ' + - 'when a conflicting property is set (backgroundPosition) can lead ' + - "to styling bugs. To avoid this, don't mix shorthand and " + - 'non-shorthand properties for the same value; instead, replace the ' + - 'shorthand with separate values.' + - '\n in div (at **)', - ); - - // A bit of an even more special case: borderLeft and borderStyle overlap. - ReactDOM.render( -
, - container, - ); - expect(() => - ReactDOM.render( -
, - container, - ), - ).toWarnDev( - 'Warning: Removing a style property during rerender (borderStyle) ' + - 'when a conflicting property is set (borderLeft) can lead to ' + - "styling bugs. To avoid this, don't mix shorthand and " + - 'non-shorthand properties for the same value; instead, replace the ' + - 'shorthand with separate values.' + - '\n in div (at **)', - ); - expect(() => - ReactDOM.render( -
, - container, - ), - ).toWarnDev( - 'Warning: Updating a style property during rerender (borderStyle) ' + - 'when a conflicting property is set (borderLeft) can lead to ' + - "styling bugs. To avoid this, don't mix shorthand and " + - 'non-shorthand properties for the same value; instead, replace the ' + - 'shorthand with separate values.' + - '\n in div (at **)', - ); - // But setting them at the same time is OK: - ReactDOM.render( -
, - container, - ); - expect(() => - ReactDOM.render(
, container), - ).toWarnDev( - 'Warning: Removing a style property during rerender (borderLeft) ' + - 'when a conflicting property is set (borderStyle) can lead to ' + - "styling bugs. To avoid this, don't mix shorthand and " + - 'non-shorthand properties for the same value; instead, replace the ' + - 'shorthand with separate values.' + - '\n in div (at **)', - ); - }); - it('should warn for unknown prop', () => { const container = document.createElement('div'); expect(() => diff --git a/packages/react-dom/src/__tests__/ReactDOMShorthandCSSPropertyCollision-test.internal.js b/packages/react-dom/src/__tests__/ReactDOMShorthandCSSPropertyCollision-test.internal.js new file mode 100644 index 000000000000..aa7742cf1e04 --- /dev/null +++ b/packages/react-dom/src/__tests__/ReactDOMShorthandCSSPropertyCollision-test.internal.js @@ -0,0 +1,147 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @emails react-core + */ + +'use strict'; + +describe('ReactDOMShorthandCSSPropertyCollision', () => { + let ReactFeatureFlags; + let React; + let ReactDOM; + + beforeEach(() => { + jest.resetModules(); + ReactFeatureFlags = require('shared/ReactFeatureFlags'); + ReactFeatureFlags.warnAboutShorthandPropertyCollision = true; + React = require('react'); + ReactDOM = require('react-dom'); + }); + + it('should warn for conflicting CSS shorthand updates', () => { + const container = document.createElement('div'); + ReactDOM.render(
, container); + expect(() => + ReactDOM.render(
, container), + ).toWarnDev( + 'Warning: Removing a style property during rerender (fontStyle) ' + + 'when a conflicting property is set (font) can lead to styling ' + + "bugs. To avoid this, don't mix shorthand and non-shorthand " + + 'properties for the same value; instead, replace the shorthand ' + + 'with separate values.' + + '\n in div (at **)', + ); + + // These updates are OK and don't warn: + ReactDOM.render(
, container); + ReactDOM.render(
, container); + + expect(() => + ReactDOM.render( +
, + container, + ), + ).toWarnDev( + 'Warning: Updating a style property during rerender (font) when ' + + 'a conflicting property is set (fontStyle) can lead to styling ' + + "bugs. To avoid this, don't mix shorthand and non-shorthand " + + 'properties for the same value; instead, replace the shorthand ' + + 'with separate values.' + + '\n in div (at **)', + ); + expect(() => + ReactDOM.render(
, container), + ).toWarnDev( + 'Warning: Removing a style property during rerender (font) when ' + + 'a conflicting property is set (fontStyle) can lead to styling ' + + "bugs. To avoid this, don't mix shorthand and non-shorthand " + + 'properties for the same value; instead, replace the shorthand ' + + 'with separate values.' + + '\n in div (at **)', + ); + + // A bit of a special case: backgroundPosition isn't technically longhand + // (it expands to backgroundPosition{X,Y} but so does background) + ReactDOM.render( +
, + container, + ); + expect(() => + ReactDOM.render(
, container), + ).toWarnDev( + 'Warning: Removing a style property during rerender ' + + '(backgroundPosition) when a conflicting property is set ' + + "(background) can lead to styling bugs. To avoid this, don't mix " + + 'shorthand and non-shorthand properties for the same value; ' + + 'instead, replace the shorthand with separate values.' + + '\n in div (at **)', + ); + ReactDOM.render( +
, + container, + ); + // But setting them at the same time is OK: + ReactDOM.render( +
, + container, + ); + expect(() => + ReactDOM.render(
, container), + ).toWarnDev( + 'Warning: Removing a style property during rerender (background) ' + + 'when a conflicting property is set (backgroundPosition) can lead ' + + "to styling bugs. To avoid this, don't mix shorthand and " + + 'non-shorthand properties for the same value; instead, replace the ' + + 'shorthand with separate values.' + + '\n in div (at **)', + ); + + // A bit of an even more special case: borderLeft and borderStyle overlap. + ReactDOM.render( +
, + container, + ); + expect(() => + ReactDOM.render(
, container), + ).toWarnDev( + 'Warning: Removing a style property during rerender (borderStyle) ' + + 'when a conflicting property is set (borderLeft) can lead to ' + + "styling bugs. To avoid this, don't mix shorthand and " + + 'non-shorthand properties for the same value; instead, replace the ' + + 'shorthand with separate values.' + + '\n in div (at **)', + ); + expect(() => + ReactDOM.render( +
, + container, + ), + ).toWarnDev( + 'Warning: Updating a style property during rerender (borderStyle) ' + + 'when a conflicting property is set (borderLeft) can lead to ' + + "styling bugs. To avoid this, don't mix shorthand and " + + 'non-shorthand properties for the same value; instead, replace the ' + + 'shorthand with separate values.' + + '\n in div (at **)', + ); + // But setting them at the same time is OK: + ReactDOM.render( +
, + container, + ); + expect(() => + ReactDOM.render(
, container), + ).toWarnDev( + 'Warning: Removing a style property during rerender (borderLeft) ' + + 'when a conflicting property is set (borderStyle) can lead to ' + + "styling bugs. To avoid this, don't mix shorthand and " + + 'non-shorthand properties for the same value; instead, replace the ' + + 'shorthand with separate values.' + + '\n in div (at **)', + ); + }); +}); diff --git a/packages/react-dom/src/shared/CSSPropertyOperations.js b/packages/react-dom/src/shared/CSSPropertyOperations.js index ad09c633e5cd..c7f6786e8c76 100644 --- a/packages/react-dom/src/shared/CSSPropertyOperations.js +++ b/packages/react-dom/src/shared/CSSPropertyOperations.js @@ -12,6 +12,8 @@ import hyphenateStyleName from './hyphenateStyleName'; import warnValidStyle from './warnValidStyle'; import warning from 'shared/warning'; +import {warnAboutShorthandPropertyCollision} from 'shared/ReactFeatureFlags'; + /** * Operations for dealing with CSS properties. */ @@ -123,6 +125,10 @@ export function validateShorthandPropertyCollisionInDev( styleUpdates, nextStyles, ) { + if (!warnAboutShorthandPropertyCollision) { + return; + } + if (!nextStyles) { return; } diff --git a/packages/shared/ReactFeatureFlags.js b/packages/shared/ReactFeatureFlags.js index 028b5a8e32d9..9b7b557ac65f 100644 --- a/packages/shared/ReactFeatureFlags.js +++ b/packages/shared/ReactFeatureFlags.js @@ -47,3 +47,5 @@ export const disableInputAttributeSyncing = false; // These APIs will no longer be "unstable" in the upcoming 16.7 release, // Control this behavior with a flag to support 16.6 minor releases in the meanwhile. export const enableStableConcurrentModeAPIs = false; + +export const warnAboutShorthandPropertyCollision = false; diff --git a/packages/shared/forks/ReactFeatureFlags.native-fabric-fb.js b/packages/shared/forks/ReactFeatureFlags.native-fabric-fb.js index 971f6bcbd3f9..a8f8df08ee1e 100644 --- a/packages/shared/forks/ReactFeatureFlags.native-fabric-fb.js +++ b/packages/shared/forks/ReactFeatureFlags.native-fabric-fb.js @@ -23,6 +23,7 @@ export const enableSchedulerTracing = __PROFILE__; export const enableSuspenseServerRenderer = false; export const disableInputAttributeSyncing = false; export const enableStableConcurrentModeAPIs = false; +export const warnAboutShorthandPropertyCollision = false; // Only used in www builds. export function addUserTimingListener() { diff --git a/packages/shared/forks/ReactFeatureFlags.native-fabric-oss.js b/packages/shared/forks/ReactFeatureFlags.native-fabric-oss.js index 3f647674e34d..f5a8fe9192ac 100644 --- a/packages/shared/forks/ReactFeatureFlags.native-fabric-oss.js +++ b/packages/shared/forks/ReactFeatureFlags.native-fabric-oss.js @@ -23,6 +23,7 @@ export const enableSchedulerTracing = __PROFILE__; export const enableSuspenseServerRenderer = false; export const disableInputAttributeSyncing = false; export const enableStableConcurrentModeAPIs = false; +export const warnAboutShorthandPropertyCollision = false; // Only used in www builds. export function addUserTimingListener() { diff --git a/packages/shared/forks/ReactFeatureFlags.native-fb.js b/packages/shared/forks/ReactFeatureFlags.native-fb.js index 6e9d290359c6..7d3694107560 100644 --- a/packages/shared/forks/ReactFeatureFlags.native-fb.js +++ b/packages/shared/forks/ReactFeatureFlags.native-fb.js @@ -28,6 +28,7 @@ export const enableProfilerTimer = __PROFILE__; export const enableSchedulerTracing = __PROFILE__; export const enableSuspenseServerRenderer = false; export const enableStableConcurrentModeAPIs = false; +export const warnAboutShorthandPropertyCollision = false; // Only used in www builds. export function addUserTimingListener() { diff --git a/packages/shared/forks/ReactFeatureFlags.native-oss.js b/packages/shared/forks/ReactFeatureFlags.native-oss.js index 96f7607431a1..01153dfc927d 100644 --- a/packages/shared/forks/ReactFeatureFlags.native-oss.js +++ b/packages/shared/forks/ReactFeatureFlags.native-oss.js @@ -23,6 +23,7 @@ export const enableSchedulerTracing = __PROFILE__; export const enableSuspenseServerRenderer = false; export const disableInputAttributeSyncing = false; export const enableStableConcurrentModeAPIs = false; +export const warnAboutShorthandPropertyCollision = false; // Only used in www builds. export function addUserTimingListener() { diff --git a/packages/shared/forks/ReactFeatureFlags.persistent.js b/packages/shared/forks/ReactFeatureFlags.persistent.js index bcb561d62b21..dc43add41035 100644 --- a/packages/shared/forks/ReactFeatureFlags.persistent.js +++ b/packages/shared/forks/ReactFeatureFlags.persistent.js @@ -23,6 +23,7 @@ export const enableSchedulerTracing = __PROFILE__; export const enableSuspenseServerRenderer = false; export const disableInputAttributeSyncing = false; export const enableStableConcurrentModeAPIs = false; +export const warnAboutShorthandPropertyCollision = false; // Only used in www builds. export function addUserTimingListener() { diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.js index 9431ff5623d7..3979848d6a18 100644 --- a/packages/shared/forks/ReactFeatureFlags.test-renderer.js +++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.js @@ -23,6 +23,7 @@ export const enableSchedulerTracing = false; export const enableSuspenseServerRenderer = false; export const disableInputAttributeSyncing = false; export const enableStableConcurrentModeAPIs = false; +export const warnAboutShorthandPropertyCollision = false; // Only used in www builds. export function addUserTimingListener() { diff --git a/packages/shared/forks/ReactFeatureFlags.www.js b/packages/shared/forks/ReactFeatureFlags.www.js index ab5157a7306f..c52f380f9bbc 100644 --- a/packages/shared/forks/ReactFeatureFlags.www.js +++ b/packages/shared/forks/ReactFeatureFlags.www.js @@ -18,6 +18,7 @@ export const { replayFailedUnitOfWorkWithInvokeGuardedCallback, warnAboutDeprecatedLifecycles, disableInputAttributeSyncing, + warnAboutShorthandPropertyCollision, } = require('ReactFeatureFlags'); // The rest of the flags are static for better dead code elimination.