Clean up fastAddProperties and make it more correct (#29015)
## Summary This PR makes some fixes to the `fastAddProperties` function: - Use `if (!attributeConfig)` instead of `if (attributeConfig === undefined)` to account for `null`. - If a prop has an Object `attributeConfig` with a `diff` function defined on it, treat it as an atomic value to keep the semantics of `diffProperties`. ## How did you test this change? Build and run RNTester app.
Dmytro Rykun committed
May 8, 2024 at 13:10 UTC
b37e4b4e616d6d66c1cde9c0a4c2cbd866b0b582
1 file changed
+34
-34
packages/react-native-renderer/src/ReactNativeAttributePayloadFabric.js
+34
-34
@@ -446,65 +446,65 @@ function diffProperties(
446
}
447
448
function fastAddProperties(
449
- updatePayload: null | Object,
450
- nextProps: Object,
449
+ payload: null | Object,
450
+ props: Object,
451
validAttributes: AttributeConfiguration,
452
): null | Object {
453
let attributeConfig;
454
- let nextProp;
454
+ let prop;
455
456
- for (const propKey in nextProps) {
457
- nextProp = nextProps[propKey];
456
+ for (const propKey in props) {
457
+ prop = props[propKey];
458
459
- if (nextProp === undefined) {
459
+ if (prop === undefined) {
460
continue;
461
}
462
463
- attributeConfig = validAttributes[propKey];
463
+ attributeConfig = ((validAttributes[propKey]: any): AttributeConfiguration);
464
465
- if (attributeConfig === undefined) {
465
+ if (attributeConfig == null) {
466
continue;
467
}
468
469
- if (typeof nextProp === 'function') {
470
- nextProp = (true: any);
469
+ let newValue;
470
+
471
+ if (typeof prop === 'function') {
472
+ // A function prop. It represents an event handler. Pass it to native as 'true'.
473
+ newValue = true;
474
+ } else if (typeof attributeConfig !== 'object') {
475
+ // An atomic prop. Doesn't need to be flattened.
476
+ newValue = prop;
477
+ } else if (typeof attributeConfig.process === 'function') {
478
+ // An atomic prop with custom processing.
479
+ newValue = attributeConfig.process(prop);
480
+ } else if (typeof attributeConfig.diff === 'function') {
481
+ // An atomic prop with custom diffing. We don't do diffing here.
482
+ newValue = prop;
483
}
484
473
- if (typeof attributeConfig !== 'object') {
474
- if (!updatePayload) {
475
- updatePayload = ({}: {[string]: $FlowFixMe});
485
+ if (newValue !== undefined) {
486
+ if (!payload) {
487
+ payload = ({}: {[string]: $FlowFixMe});
488
}
477
- updatePayload[propKey] = nextProp;
489
+ payload[propKey] = newValue;
490
continue;
491
}
492
481
- if (typeof attributeConfig.process === 'function') {
482
- if (!updatePayload) {
483
- updatePayload = ({}: {[string]: $FlowFixMe});
484
- }
485
- updatePayload[propKey] = attributeConfig.process(nextProp);
486
- continue;
487
- }
493
+ // Not-atomic prop that needs to be flattened. Likely it's the 'style' prop.
494
489
- if (isArray(nextProp)) {
490
- for (let i = 0; i < nextProp.length; i++) {
491
- updatePayload = fastAddProperties(
492
- updatePayload,
493
- nextProp[i],
494
- ((attributeConfig: any): AttributeConfiguration),
495
- );
495
+ // It can be an array.
496
+ if (isArray(prop)) {
497
+ for (let i = 0; i < prop.length; i++) {
498
+ payload = fastAddProperties(payload, prop[i], attributeConfig);
499
}
500
continue;
501
}
502
500
- updatePayload = fastAddProperties(
501
- updatePayload,
502
- nextProp,
503
- ((attributeConfig: any): AttributeConfiguration),
504
- );
503
+ // Or it can be an object.
504
+ payload = fastAddProperties(payload, prop, attributeConfig);
505
}
506
507
- return updatePayload;
507
+ return payload;
508
}
509
510
/**