mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Warn for inline style mismatches (#10084)
I use the technique of generating a style string and comparing that against the attribute.
This commit is contained in:
committed by
GitHub
parent
79868a978d
commit
e6f1d29f07
@@ -1531,6 +1531,13 @@ src/renderers/dom/shared/__tests__/ReactDOMServerIntegration-test.js
|
||||
* should error reconnecting missing attributes
|
||||
* should error reconnecting added attributes
|
||||
* should error reconnecting different attribute values
|
||||
* should error reconnecting missing style attribute
|
||||
* should error reconnecting added style attribute
|
||||
* should error reconnecting empty style attribute
|
||||
* should error reconnecting added style values
|
||||
* should error reconnecting different style values
|
||||
* should reconnect number and string versions of a number
|
||||
* should error reconnecting reordered style values
|
||||
* should error reconnecting different text
|
||||
* should reconnect a div with a number and string version of number
|
||||
* should error reconnecting different numbers
|
||||
|
||||
@@ -915,7 +915,13 @@ var ReactDOMFiberComponent = {
|
||||
} else if (propKey === STYLE) {
|
||||
// $FlowFixMe - Should be inferred as not undefined.
|
||||
extraAttributeNames.delete(propKey);
|
||||
// TOOD: Validate style sheets.
|
||||
const expectedStyle = CSSPropertyOperations.createDangerousStringForStyles(
|
||||
nextProp,
|
||||
);
|
||||
serverValue = domElement.getAttribute('style');
|
||||
if (expectedStyle !== serverValue) {
|
||||
warnForPropDifference(propKey, serverValue, expectedStyle);
|
||||
}
|
||||
} else if (
|
||||
isCustomComponentTag ||
|
||||
DOMProperty.isCustomAttribute(propKey)
|
||||
|
||||
@@ -207,7 +207,6 @@ var CSSPropertyOperations = {
|
||||
serialized += dangerousStyleValue(
|
||||
styleName,
|
||||
styleValue,
|
||||
component,
|
||||
isCustomProperty,
|
||||
);
|
||||
|
||||
@@ -217,6 +216,40 @@ var CSSPropertyOperations = {
|
||||
return serialized || null;
|
||||
},
|
||||
|
||||
/**
|
||||
* This creates a string that is expected to be equivalent to the style
|
||||
* attribute generated by server-side rendering. It by-passes warnings and
|
||||
* security checks so it's not safe to use this value for anything other than
|
||||
* comparison. It is only used in DEV for SSR validation. This is duplicated
|
||||
* from createMarkupForStyles because createMarkupForStyles is expected to
|
||||
* move out of the client-side renderer and it would be nice to make a clean
|
||||
* break.
|
||||
*/
|
||||
createDangerousStringForStyles: function(styles) {
|
||||
if (__DEV__) {
|
||||
var serialized = '';
|
||||
var delimiter = '';
|
||||
for (var styleName in styles) {
|
||||
if (!styles.hasOwnProperty(styleName)) {
|
||||
continue;
|
||||
}
|
||||
var styleValue = styles[styleName];
|
||||
if (styleValue != null) {
|
||||
var isCustomProperty = styleName.indexOf('--') === 0;
|
||||
serialized += delimiter + hyphenateStyleName(styleName) + ':';
|
||||
serialized += dangerousStyleValue(
|
||||
styleName,
|
||||
styleValue,
|
||||
isCustomProperty,
|
||||
);
|
||||
|
||||
delimiter = ';';
|
||||
}
|
||||
}
|
||||
return serialized || null;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the value for multiple styles on a node. If a value is specified as
|
||||
* '' (empty string), the corresponding style property will be unset.
|
||||
@@ -240,7 +273,6 @@ var CSSPropertyOperations = {
|
||||
var styleValue = dangerousStyleValue(
|
||||
styleName,
|
||||
styles[styleName],
|
||||
component,
|
||||
isCustomProperty,
|
||||
);
|
||||
if (styleName === 'float') {
|
||||
|
||||
@@ -2075,6 +2075,44 @@ describe('ReactDOMServerIntegration', () => {
|
||||
expectMarkupMismatch(<div id="foo" />, <div id="bar" />));
|
||||
});
|
||||
|
||||
describe('inline styles', function() {
|
||||
it('should error reconnecting missing style attribute', () =>
|
||||
expectMarkupMismatch(<div style={{width: '1px'}} />, <div />));
|
||||
|
||||
it('should error reconnecting added style attribute', () =>
|
||||
expectMarkupMismatch(<div />, <div style={{width: '1px'}} />));
|
||||
|
||||
it('should error reconnecting empty style attribute', () =>
|
||||
expectMarkupMismatch(
|
||||
<div style={{width: '1px'}} />,
|
||||
<div style={{}} />,
|
||||
));
|
||||
|
||||
it('should error reconnecting added style values', () =>
|
||||
expectMarkupMismatch(
|
||||
<div style={{}} />,
|
||||
<div style={{width: '1px'}} />,
|
||||
));
|
||||
|
||||
it('should error reconnecting different style values', () =>
|
||||
expectMarkupMismatch(
|
||||
<div style={{width: '1px'}} />,
|
||||
<div style={{width: '2px'}} />,
|
||||
));
|
||||
|
||||
it('should reconnect number and string versions of a number', () =>
|
||||
expectMarkupMatch(
|
||||
<div style={{width: '1px', height: 2}} />,
|
||||
<div style={{width: 1, height: '2px'}} />,
|
||||
));
|
||||
|
||||
it('should error reconnecting reordered style values', () =>
|
||||
expectMarkupMismatch(
|
||||
<div style={{width: '1px', fontSize: '2px'}} />,
|
||||
<div style={{fontSize: '2px', width: '1px'}} />,
|
||||
));
|
||||
});
|
||||
|
||||
describe('text nodes', function() {
|
||||
it('should error reconnecting different text', () =>
|
||||
expectMarkupMismatch(<div>Text</div>, <div>Other Text</div>));
|
||||
|
||||
@@ -22,10 +22,9 @@ var isUnitlessNumber = CSSProperty.isUnitlessNumber;
|
||||
*
|
||||
* @param {string} name CSS property name such as `topMargin`.
|
||||
* @param {*} value CSS property value such as `10px`.
|
||||
* @param {ReactDOMComponent} component
|
||||
* @return {string} Normalized style value with dimensions applied.
|
||||
*/
|
||||
function dangerousStyleValue(name, value, component, isCustomProperty) {
|
||||
function dangerousStyleValue(name, value, isCustomProperty) {
|
||||
// Note that we've removed escapeTextForBrowser() calls here since the
|
||||
// whole string will be escaped when the attribute is injected into
|
||||
// the markup. If you provide unsafe user data here they can inject
|
||||
|
||||
Reference in New Issue
Block a user