Skip to content

Commit 4a1cc2d

Browse files
authored
Fix logic around attribute seralization (#26526)
There was a bug in the attribute seralization for stylesheet resources injected by the Fizz runtime. For boolean properties the attribute value was set to an empty string but later immediately set to a string coerced value. This PR fixes that bug and refactors the code paths to be clearer
1 parent b14f8da commit 4a1cc2d

File tree

1 file changed

+46
-38
lines changed

1 file changed

+46
-38
lines changed

packages/react-dom-bindings/src/server/ReactDOMServerFormatConfig.js

+46-38
Original file line numberDiff line numberDiff line change
@@ -3926,48 +3926,51 @@ function writeStyleResourceAttributeInJS(
39263926
return;
39273927

39283928
// Attribute renames
3929-
case 'className':
3929+
case 'className': {
39303930
attributeName = 'class';
3931+
if (__DEV__) {
3932+
checkAttributeStringCoercion(value, attributeName);
3933+
}
3934+
attributeValue = '' + (value: any);
39313935
break;
3932-
3936+
}
39333937
// Booleans
3934-
case 'hidden':
3938+
case 'hidden': {
39353939
if (value === false) {
39363940
return;
39373941
}
39383942
attributeValue = '';
39393943
break;
3940-
3944+
}
39413945
// Santized URLs
39423946
case 'src':
39433947
case 'href': {
3948+
value = sanitizeURL(value);
39443949
if (__DEV__) {
39453950
checkAttributeStringCoercion(value, attributeName);
39463951
}
3947-
value = sanitizeURL(value);
3952+
attributeValue = '' + (value: any);
39483953
break;
39493954
}
39503955
default: {
3956+
if (
3957+
// unrecognized event handlers are not SSR'd and we (apparently)
3958+
// use on* as hueristic for these handler props
3959+
name.length > 2 &&
3960+
(name[0] === 'o' || name[0] === 'O') &&
3961+
(name[1] === 'n' || name[1] === 'N')
3962+
) {
3963+
return;
3964+
}
39513965
if (!isAttributeNameSafe(name)) {
39523966
return;
39533967
}
3968+
if (__DEV__) {
3969+
checkAttributeStringCoercion(value, attributeName);
3970+
}
3971+
attributeValue = '' + (value: any);
39543972
}
39553973
}
3956-
3957-
if (
3958-
// shouldIgnoreAttribute
3959-
// We have already filtered out null/undefined and reserved words.
3960-
name.length > 2 &&
3961-
(name[0] === 'o' || name[0] === 'O') &&
3962-
(name[1] === 'n' || name[1] === 'N')
3963-
) {
3964-
return;
3965-
}
3966-
3967-
if (__DEV__) {
3968-
checkAttributeStringCoercion(value, attributeName);
3969-
}
3970-
attributeValue = '' + (value: any);
39713974
writeChunk(destination, arrayInterstitial);
39723975
writeChunk(
39733976
destination,
@@ -4119,48 +4122,53 @@ function writeStyleResourceAttributeInAttr(
41194122
return;
41204123

41214124
// Attribute renames
4122-
case 'className':
4125+
case 'className': {
41234126
attributeName = 'class';
4127+
if (__DEV__) {
4128+
checkAttributeStringCoercion(value, attributeName);
4129+
}
4130+
attributeValue = '' + (value: any);
41244131
break;
4132+
}
41254133

41264134
// Booleans
4127-
case 'hidden':
4135+
case 'hidden': {
41284136
if (value === false) {
41294137
return;
41304138
}
41314139
attributeValue = '';
41324140
break;
4141+
}
41334142

41344143
// Santized URLs
41354144
case 'src':
41364145
case 'href': {
4146+
value = sanitizeURL(value);
41374147
if (__DEV__) {
41384148
checkAttributeStringCoercion(value, attributeName);
41394149
}
4140-
value = sanitizeURL(value);
4150+
attributeValue = '' + (value: any);
41414151
break;
41424152
}
41434153
default: {
4154+
if (
4155+
// unrecognized event handlers are not SSR'd and we (apparently)
4156+
// use on* as hueristic for these handler props
4157+
name.length > 2 &&
4158+
(name[0] === 'o' || name[0] === 'O') &&
4159+
(name[1] === 'n' || name[1] === 'N')
4160+
) {
4161+
return;
4162+
}
41444163
if (!isAttributeNameSafe(name)) {
41454164
return;
41464165
}
4166+
if (__DEV__) {
4167+
checkAttributeStringCoercion(value, attributeName);
4168+
}
4169+
attributeValue = '' + (value: any);
41474170
}
41484171
}
4149-
4150-
if (
4151-
// shouldIgnoreAttribute
4152-
// We have already filtered out null/undefined and reserved words.
4153-
name.length > 2 &&
4154-
(name[0] === 'o' || name[0] === 'O') &&
4155-
(name[1] === 'n' || name[1] === 'N')
4156-
) {
4157-
return;
4158-
}
4159-
4160-
if (__DEV__) {
4161-
checkAttributeStringCoercion(value, attributeName);
4162-
}
4163-
attributeValue = '' + (value: any);
41644172
writeChunk(destination, arrayInterstitial);
41654173
writeChunk(
41664174
destination,

0 commit comments

Comments
 (0)