88 * @format
99 */
1010
11- import type { AttributeConfiguration } from '../../Renderer/shims/ReactNativeTypes' ;
11+ import type { PartialAttributeConfiguration as AttributeConfiguration } from '../../Renderer/shims/ReactNativeTypes' ;
1212
1313import flattenStyle from '../../StyleSheet/flattenStyle' ;
1414import 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
470493export 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
481500export function diff (
0 commit comments