8
8
* @format
9
9
*/
10
10
11
- import type { AttributeConfiguration } from '../../Renderer/shims/ReactNativeTypes' ;
11
+ import type { PartialAttributeConfiguration as AttributeConfiguration } from '../../Renderer/shims/ReactNativeTypes' ;
12
12
13
13
import flattenStyle from '../../StyleSheet/flattenStyle' ;
14
14
import deepDiffer from '../../Utilities/differ/deepDiffer' ;
@@ -61,7 +61,7 @@ function restoreDeletedValuesInNestedArray(
61
61
} else if ( node && removedKeyCount > 0 ) {
62
62
const obj = node ;
63
63
for ( const propKey in removedKeys ) {
64
- // $FlowFixMe[incompatible-use] found when upgrading Flow
64
+ // $FlowFixMe[incompatible-use] removedKeys is always non-null
65
65
if ( ! removedKeys [ propKey ] ) {
66
66
continue ;
67
67
}
@@ -133,12 +133,12 @@ function diffNestedArrayProperty(
133
133
) ;
134
134
}
135
135
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 ) ;
142
142
}
143
143
return updatePayload ;
144
144
}
@@ -183,9 +183,7 @@ function diffNestedProperty(
183
183
if ( Array . isArray ( prevProp ) ) {
184
184
return diffProperties (
185
185
updatePayload ,
186
- // $FlowFixMe - We know that this is always an object when the input is.
187
186
flattenStyle ( prevProp ) ,
188
- // $FlowFixMe - We know that this isn't an array because of above flow.
189
187
nextProp ,
190
188
validAttributes ,
191
189
) ;
@@ -194,43 +192,11 @@ function diffNestedProperty(
194
192
return diffProperties (
195
193
updatePayload ,
196
194
prevProp ,
197
- // $FlowFixMe - We know that this is always an object when the input is.
198
195
flattenStyle ( nextProp ) ,
199
196
validAttributes ,
200
197
) ;
201
198
}
202
199
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
-
234
200
/**
235
201
* clearNestedProperty takes a single set of props and valid attributes. It
236
202
* adds a null sentinel to the updatePayload, for each prop key.
@@ -285,14 +251,19 @@ function diffProperties(
285
251
prevProp = prevProps [ propKey ] ;
286
252
nextProp = nextProps [ propKey ] ;
287
253
288
- // functions are converted to booleans as markers that the associated
289
- // events should be sent from native.
290
254
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
+ }
296
267
}
297
268
}
298
269
@@ -442,16 +413,69 @@ function diffProperties(
442
413
return updatePayload ;
443
414
}
444
415
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 ,
450
418
props : Object ,
451
419
validAttributes : AttributeConfiguration ,
452
420
) : 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 ;
455
479
}
456
480
457
481
/**
@@ -463,19 +487,14 @@ function clearProperties(
463
487
prevProps : Object ,
464
488
validAttributes : AttributeConfiguration ,
465
489
) : null | Object {
466
- // TODO: Fast path
467
490
return diffProperties ( updatePayload , prevProps , emptyObject , validAttributes ) ;
468
491
}
469
492
470
493
export function create (
471
494
props : Object ,
472
495
validAttributes : AttributeConfiguration ,
473
496
) : null | Object {
474
- return addProperties (
475
- null , // updatePayload
476
- props ,
477
- validAttributes ,
478
- ) ;
497
+ return addNestedProperty ( null , props , validAttributes ) ;
479
498
}
480
499
481
500
export function diff (
0 commit comments