Skip to content

Commit

Permalink
Update deepDiffer usage in React Native renderer (#17282)
Browse files Browse the repository at this point in the history
* Add RN prop diffing test with function values

* Update RN deepDiffer mock

* Explicitly ignore functions in RN prop differ
  • Loading branch information
motiz88 authored Nov 7, 2019
1 parent e701632 commit 61d3dd0
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ function defaultDiffer(prevProp: mixed, nextProp: mixed): boolean {
return true;
} else {
// For objects and arrays, the default diffing algorithm is a deep compare
return deepDiffer(prevProp, nextProp);
return deepDiffer(prevProp, nextProp, {unsafelyIgnoreFunctions: true});
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,43 @@
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
* @flow
*/

'use strict';

// TODO: Move deepDiffer into react
type Options = {|+unsafelyIgnoreFunctions?: boolean|};

const deepDiffer = function(one: any, two: any): boolean {
/*
* @returns {bool} true if different, false if equal
*/
const deepDiffer = function(
one: any,
two: any,
maxDepthOrOptions: Options | number = -1,
maybeOptions?: Options,
): boolean {
const options =
typeof maxDepthOrOptions === 'number' ? maybeOptions : maxDepthOrOptions;
const maxDepth =
typeof maxDepthOrOptions === 'number' ? maxDepthOrOptions : -1;
if (maxDepth === 0) {
return true;
}
if (one === two) {
// Short circuit on identical object references instead of traversing them.
return false;
}
if (typeof one === 'function' && typeof two === 'function') {
// We consider all functions equal
return false;
// We consider all functions equal unless explicitly configured otherwise
let unsafelyIgnoreFunctions =
options == null ? null : options.unsafelyIgnoreFunctions;
if (unsafelyIgnoreFunctions == null) {
unsafelyIgnoreFunctions = true;
}
return !unsafelyIgnoreFunctions;
}
if (typeof one !== 'object' || one === null) {
// Primitives can be directly compared
Expand All @@ -37,13 +60,13 @@ const deepDiffer = function(one: any, two: any): boolean {
return true;
}
for (let ii = 0; ii < len; ii++) {
if (deepDiffer(one[ii], two[ii])) {
if (deepDiffer(one[ii], two[ii], maxDepth - 1, options)) {
return true;
}
}
} else {
for (const key in one) {
if (deepDiffer(one[key], two[key])) {
if (deepDiffer(one[key], two[key], maxDepth - 1, options)) {
return true;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,4 +231,44 @@ describe('ReactNativeAttributePayload', () => {
),
).toEqual({a: null, c: true});
});

it('should skip changed functions', () => {
expect(
diff(
{
a: function() {
return 1;
},
},
{
a: function() {
return 9;
},
},
{a: true},
),
).toEqual(null);
});

it('should skip deeply-nested changed functions', () => {
expect(
diff(
{
wrapper: {
a: function() {
return 1;
},
},
},
{
wrapper: {
a: function() {
return 9;
},
},
},
{wrapper: true},
),
).toEqual(null);
});
});
14 changes: 13 additions & 1 deletion scripts/flow/react-native-host-hooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,20 @@ import type {
import type {RNTopLevelEventType} from 'legacy-events/TopLevelEventTypes';
import type {CapturedError} from 'react-reconciler/src/ReactCapturedValue';

type DeepDifferOptions = {|+unsafelyIgnoreFunctions?: boolean|};

declare module 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface' {
declare export function deepDiffer(one: any, two: any): boolean;
declare export function deepDiffer(
one: any,
two: any,
maxDepth?: number,
options?: DeepDifferOptions,
): boolean;
declare export function deepDiffer(
one: any,
two: any,
options: DeepDifferOptions,
): boolean;
declare export function deepFreezeAndThrowOnMutationInDev<T>(obj: T): T;
declare export function flattenStyle(style: any): any;
declare export var RCTEventEmitter: {
Expand Down

0 comments on commit 61d3dd0

Please sign in to comment.