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
This commit is contained in:
Josh Story
2023-04-03 09:34:53 -07:00
committed by GitHub
parent b14f8da155
commit 4a1cc2ddd0
@@ -3926,48 +3926,51 @@ function writeStyleResourceAttributeInJS(
return;
// Attribute renames
case 'className':
case 'className': {
attributeName = 'class';
if (__DEV__) {
checkAttributeStringCoercion(value, attributeName);
}
attributeValue = '' + (value: any);
break;
}
// Booleans
case 'hidden':
case 'hidden': {
if (value === false) {
return;
}
attributeValue = '';
break;
}
// Santized URLs
case 'src':
case 'href': {
value = sanitizeURL(value);
if (__DEV__) {
checkAttributeStringCoercion(value, attributeName);
}
value = sanitizeURL(value);
attributeValue = '' + (value: any);
break;
}
default: {
if (
// unrecognized event handlers are not SSR'd and we (apparently)
// use on* as hueristic for these handler props
name.length > 2 &&
(name[0] === 'o' || name[0] === 'O') &&
(name[1] === 'n' || name[1] === 'N')
) {
return;
}
if (!isAttributeNameSafe(name)) {
return;
}
if (__DEV__) {
checkAttributeStringCoercion(value, attributeName);
}
attributeValue = '' + (value: any);
}
}
if (
// shouldIgnoreAttribute
// We have already filtered out null/undefined and reserved words.
name.length > 2 &&
(name[0] === 'o' || name[0] === 'O') &&
(name[1] === 'n' || name[1] === 'N')
) {
return;
}
if (__DEV__) {
checkAttributeStringCoercion(value, attributeName);
}
attributeValue = '' + (value: any);
writeChunk(destination, arrayInterstitial);
writeChunk(
destination,
@@ -4119,48 +4122,53 @@ function writeStyleResourceAttributeInAttr(
return;
// Attribute renames
case 'className':
case 'className': {
attributeName = 'class';
if (__DEV__) {
checkAttributeStringCoercion(value, attributeName);
}
attributeValue = '' + (value: any);
break;
}
// Booleans
case 'hidden':
case 'hidden': {
if (value === false) {
return;
}
attributeValue = '';
break;
}
// Santized URLs
case 'src':
case 'href': {
value = sanitizeURL(value);
if (__DEV__) {
checkAttributeStringCoercion(value, attributeName);
}
value = sanitizeURL(value);
attributeValue = '' + (value: any);
break;
}
default: {
if (
// unrecognized event handlers are not SSR'd and we (apparently)
// use on* as hueristic for these handler props
name.length > 2 &&
(name[0] === 'o' || name[0] === 'O') &&
(name[1] === 'n' || name[1] === 'N')
) {
return;
}
if (!isAttributeNameSafe(name)) {
return;
}
if (__DEV__) {
checkAttributeStringCoercion(value, attributeName);
}
attributeValue = '' + (value: any);
}
}
if (
// shouldIgnoreAttribute
// We have already filtered out null/undefined and reserved words.
name.length > 2 &&
(name[0] === 'o' || name[0] === 'O') &&
(name[1] === 'n' || name[1] === 'N')
) {
return;
}
if (__DEV__) {
checkAttributeStringCoercion(value, attributeName);
}
attributeValue = '' + (value: any);
writeChunk(destination, arrayInterstitial);
writeChunk(
destination,