Skip to content

Commit 0e42d33

Browse files
javachefacebook-github-bot
authored andcommitted
Sync ReactNativeAttributePayload with upstream (#51998)
Summary: Pull Request resolved: #51998 Sync with https://github.com/facebook/react/blob/main/packages/react-native-renderer/src/ReactNativeAttributePayloadFabric.js Next step is to remove the copy in React upstream and consume it from ReactNativePrivateInterface, so I've copied over the tests as well. Changelog: [Internal] Reviewed By: mdvacca Differential Revision: D75943237 fbshipit-source-id: c89c8711b55882f7069c54f6c1ce389f46760089
1 parent abc8fe1 commit 0e42d33

File tree

2 files changed

+576
-62
lines changed

2 files changed

+576
-62
lines changed

packages/react-native/Libraries/ReactNative/ReactFabricPublicInstance/ReactNativeAttributePayload.js

Lines changed: 81 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* @format
99
*/
1010

11-
import type {AttributeConfiguration} from '../../Renderer/shims/ReactNativeTypes';
11+
import type {PartialAttributeConfiguration as AttributeConfiguration} from '../../Renderer/shims/ReactNativeTypes';
1212

1313
import flattenStyle from '../../StyleSheet/flattenStyle';
1414
import deepDiffer from '../../Utilities/differ/deepDiffer';
@@ -61,7 +61,7 @@ function restoreDeletedValuesInNestedArray(
6161
} else if (node && removedKeyCount > 0) {
6262
const obj = node;
6363
for (const propKey in removedKeys) {
64-
// $FlowFixMe[incompatible-use] found when upgrading Flow
64+
// $FlowFixMe[incompatible-use] removedKeys is always non-null
6565
if (!removedKeys[propKey]) {
6666
continue;
6767
}
@@ -133,12 +133,12 @@ function diffNestedArrayProperty(
133133
);
134134
}
135135
for (; i < nextArray.length; i++) {
136-
// Add all remaining properties.
137-
updatePayload = addNestedProperty(
138-
updatePayload,
139-
nextArray[i],
140-
validAttributes,
141-
);
136+
// Add all remaining properties
137+
const nextProp = nextArray[i];
138+
if (!nextProp) {
139+
continue;
140+
}
141+
updatePayload = addNestedProperty(updatePayload, nextProp, validAttributes);
142142
}
143143
return updatePayload;
144144
}
@@ -183,9 +183,7 @@ function diffNestedProperty(
183183
if (Array.isArray(prevProp)) {
184184
return diffProperties(
185185
updatePayload,
186-
// $FlowFixMe - We know that this is always an object when the input is.
187186
flattenStyle(prevProp),
188-
// $FlowFixMe - We know that this isn't an array because of above flow.
189187
nextProp,
190188
validAttributes,
191189
);
@@ -194,43 +192,11 @@ function diffNestedProperty(
194192
return diffProperties(
195193
updatePayload,
196194
prevProp,
197-
// $FlowFixMe - We know that this is always an object when the input is.
198195
flattenStyle(nextProp),
199196
validAttributes,
200197
);
201198
}
202199

203-
/**
204-
* addNestedProperty takes a single set of props and valid attribute
205-
* attribute configurations. It processes each prop and adds it to the
206-
* updatePayload.
207-
*/
208-
function addNestedProperty(
209-
updatePayload: null | Object,
210-
nextProp: NestedNode,
211-
validAttributes: AttributeConfiguration,
212-
): $FlowFixMe {
213-
if (!nextProp) {
214-
return updatePayload;
215-
}
216-
217-
if (!Array.isArray(nextProp)) {
218-
// Add each property of the leaf.
219-
return addProperties(updatePayload, nextProp, validAttributes);
220-
}
221-
222-
for (let i = 0; i < nextProp.length; i++) {
223-
// Add all the properties of the array.
224-
updatePayload = addNestedProperty(
225-
updatePayload,
226-
nextProp[i],
227-
validAttributes,
228-
);
229-
}
230-
231-
return updatePayload;
232-
}
233-
234200
/**
235201
* clearNestedProperty takes a single set of props and valid attributes. It
236202
* adds a null sentinel to the updatePayload, for each prop key.
@@ -285,14 +251,19 @@ function diffProperties(
285251
prevProp = prevProps[propKey];
286252
nextProp = nextProps[propKey];
287253

288-
// functions are converted to booleans as markers that the associated
289-
// events should be sent from native.
290254
if (typeof nextProp === 'function') {
291-
nextProp = (true: any);
292-
// If nextProp is not a function, then don't bother changing prevProp
293-
// since nextProp will win and go into the updatePayload regardless.
294-
if (typeof prevProp === 'function') {
295-
prevProp = (true: any);
255+
const attributeConfigHasProcess =
256+
typeof attributeConfig === 'object' &&
257+
typeof attributeConfig.process === 'function';
258+
if (!attributeConfigHasProcess) {
259+
// functions are converted to booleans as markers that the associated
260+
// events should be sent from native.
261+
nextProp = (true: any);
262+
// If nextProp is not a function, then don't bother changing prevProp
263+
// since nextProp will win and go into the updatePayload regardless.
264+
if (typeof prevProp === 'function') {
265+
prevProp = (true: any);
266+
}
296267
}
297268
}
298269

@@ -442,16 +413,69 @@ function diffProperties(
442413
return updatePayload;
443414
}
444415

445-
/**
446-
* addProperties adds all the valid props to the payload after being processed.
447-
*/
448-
function addProperties(
449-
updatePayload: null | Object,
416+
function addNestedProperty(
417+
payload: null | Object,
450418
props: Object,
451419
validAttributes: AttributeConfiguration,
452420
): null | Object {
453-
// TODO: Fast path
454-
return diffProperties(updatePayload, emptyObject, props, validAttributes);
421+
// Flatten nested style props.
422+
if (Array.isArray(props)) {
423+
for (let i = 0; i < props.length; i++) {
424+
payload = addNestedProperty(payload, props[i], validAttributes);
425+
}
426+
return payload;
427+
}
428+
429+
for (const propKey in props) {
430+
const prop = props[propKey];
431+
432+
const attributeConfig = ((validAttributes[
433+
propKey
434+
]: any): AttributeConfiguration);
435+
436+
if (attributeConfig == null) {
437+
continue;
438+
}
439+
440+
let newValue;
441+
442+
if (prop === undefined) {
443+
// Discard the prop if it was previously defined.
444+
if (payload && payload[propKey] !== undefined) {
445+
newValue = null;
446+
} else {
447+
continue;
448+
}
449+
} else if (typeof attributeConfig === 'object') {
450+
if (typeof attributeConfig.process === 'function') {
451+
// An atomic prop with custom processing.
452+
newValue = attributeConfig.process(prop);
453+
} else if (typeof attributeConfig.diff === 'function') {
454+
// An atomic prop with custom diffing. We don't need to do diffing when adding props.
455+
newValue = prop;
456+
}
457+
} else {
458+
if (typeof prop === 'function') {
459+
// A function prop. It represents an event handler. Pass it to native as 'true'.
460+
newValue = true;
461+
} else {
462+
// An atomic prop. Doesn't need to be flattened.
463+
newValue = prop;
464+
}
465+
}
466+
467+
if (newValue !== undefined) {
468+
if (!payload) {
469+
payload = ({}: {[string]: $FlowFixMe});
470+
}
471+
payload[propKey] = newValue;
472+
continue;
473+
}
474+
475+
payload = addNestedProperty(payload, prop, attributeConfig);
476+
}
477+
478+
return payload;
455479
}
456480

457481
/**
@@ -463,19 +487,14 @@ function clearProperties(
463487
prevProps: Object,
464488
validAttributes: AttributeConfiguration,
465489
): null | Object {
466-
// TODO: Fast path
467490
return diffProperties(updatePayload, prevProps, emptyObject, validAttributes);
468491
}
469492

470493
export function create(
471494
props: Object,
472495
validAttributes: AttributeConfiguration,
473496
): null | Object {
474-
return addProperties(
475-
null, // updatePayload
476-
props,
477-
validAttributes,
478-
);
497+
return addNestedProperty(null, props, validAttributes);
479498
}
480499

481500
export function diff(

0 commit comments

Comments
 (0)