Skip to content

Commit b98adb6

Browse files
authored
Simplify CSS shorthand property warning (#14183)
I figured out a simpler way to do #14181. It does allocate some but I think that's OK. Time complexity might even be better since we avoid the nested loops the old one had.
1 parent f8bfd58 commit b98adb6

File tree

2 files changed

+217
-301
lines changed

2 files changed

+217
-301
lines changed

packages/react-dom/src/shared/CSSPropertyOperations.js

Lines changed: 34 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,7 @@
55
* LICENSE file in the root directory of this source tree.
66
*/
77

8-
import {
9-
overlappingShorthandsInDev,
10-
longhandToShorthandInDev,
11-
shorthandToLonghandInDev,
12-
} from './CSSShorthandProperty';
8+
import {shorthandToLonghand} from './CSSShorthandProperty';
139

1410
import dangerousStyleValue from './dangerousStyleValue';
1511
import hyphenateStyleName from './hyphenateStyleName';
@@ -90,6 +86,25 @@ function isValueEmpty(value) {
9086
return value == null || typeof value === 'boolean' || value === '';
9187
}
9288

89+
/**
90+
* Given {color: 'red', overflow: 'hidden'} returns {
91+
* color: 'color',
92+
* overflowX: 'overflow',
93+
* overflowY: 'overflow',
94+
* }. This can be read as "the overflowY property was set by the overflow
95+
* shorthand". That is, the values are the property that each was derived from.
96+
*/
97+
function expandShorthandMap(styles) {
98+
const expanded = {};
99+
for (const key in styles) {
100+
const longhands = shorthandToLonghand[key] || [key];
101+
for (let i = 0; i < longhands.length; i++) {
102+
expanded[longhands[i]] = key;
103+
}
104+
}
105+
return expanded;
106+
}
107+
93108
/**
94109
* When mixing shorthand and longhand property names, we warn during updates if
95110
* we expect an incorrect result to occur. In particular, we warn for:
@@ -112,64 +127,28 @@ export function validateShorthandPropertyCollisionInDev(
112127
return;
113128
}
114129

115-
for (const key in styleUpdates) {
116-
const isEmpty = isValueEmpty(styleUpdates[key]);
117-
if (isEmpty) {
118-
// Property removal; check if we're removing a longhand property
119-
const shorthands = longhandToShorthandInDev[key];
120-
if (shorthands) {
121-
const conflicting = shorthands.filter(
122-
s => !isValueEmpty(nextStyles[s]),
123-
);
124-
if (conflicting.length) {
125-
warning(
126-
false,
127-
'Removing a style property during rerender (%s) when a ' +
128-
'conflicting property is set (%s) can lead to styling bugs. To ' +
129-
"avoid this, don't mix shorthand and non-shorthand properties " +
130-
'for the same value; instead, replace the shorthand with ' +
131-
'separate values.',
132-
key,
133-
conflicting.join(', '),
134-
);
135-
}
130+
const expandedUpdates = expandShorthandMap(styleUpdates);
131+
const expandedStyles = expandShorthandMap(nextStyles);
132+
const warnedAbout = {};
133+
for (const key in expandedUpdates) {
134+
const originalKey = expandedUpdates[key];
135+
const correctOriginalKey = expandedStyles[key];
136+
if (correctOriginalKey && originalKey !== correctOriginalKey) {
137+
const warningKey = originalKey + ',' + correctOriginalKey;
138+
if (warnedAbout[warningKey]) {
139+
continue;
136140
}
137-
}
138-
139-
// Updating or removing a property; check if it's a shorthand property
140-
const longhands = shorthandToLonghandInDev[key];
141-
const overlapping = overlappingShorthandsInDev[key];
142-
// eslint-disable-next-line no-var
143-
var conflicting = new Set();
144-
if (longhands) {
145-
longhands.forEach(l => {
146-
if (isValueEmpty(styleUpdates[l]) && !isValueEmpty(nextStyles[l])) {
147-
// ex: key = 'font', l = 'fontStyle'
148-
conflicting.add(l);
149-
}
150-
});
151-
}
152-
if (overlapping) {
153-
overlapping.forEach(l => {
154-
if (isValueEmpty(styleUpdates[l]) && !isValueEmpty(nextStyles[l])) {
155-
// ex: key = 'borderLeft', l = 'borderStyle'
156-
conflicting.add(l);
157-
}
158-
});
159-
}
160-
if (conflicting.size) {
141+
warnedAbout[warningKey] = true;
161142
warning(
162143
false,
163144
'%s a style property during rerender (%s) when a ' +
164145
'conflicting property is set (%s) can lead to styling bugs. To ' +
165146
"avoid this, don't mix shorthand and non-shorthand properties " +
166147
'for the same value; instead, replace the shorthand with ' +
167148
'separate values.',
168-
isEmpty ? 'Removing' : 'Updating',
169-
key,
170-
Array.from(conflicting)
171-
.sort()
172-
.join(', '),
149+
isValueEmpty(styleUpdates[originalKey]) ? 'Removing' : 'Updating',
150+
originalKey,
151+
correctOriginalKey,
173152
);
174153
}
175154
}

0 commit comments

Comments
 (0)