Skip to content

Commit

Permalink
Fix validation of AnimatedEvent with AnimatedValueXY
Browse files Browse the repository at this point in the history
Summary: Changelog: [General][Fixed] Support Animated.ValueXY when validating Animated.event

Reviewed By: yungsters

Differential Revision: D30779011

fbshipit-source-id: 56f4d9eb6a20200584e5429a1693d0703f8c1a37
  • Loading branch information
javache authored and facebook-github-bot committed Sep 9, 2021
1 parent b7c023a commit 27dd2ec
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 4 deletions.
27 changes: 23 additions & 4 deletions Libraries/Animated/AnimatedEvent.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,18 @@
'use strict';

const AnimatedValue = require('./nodes/AnimatedValue');
const AnimatedValueXY = require('./nodes/AnimatedValueXY');
const NativeAnimatedHelper = require('./NativeAnimatedHelper');
const ReactNative = require('../Renderer/shims/ReactNative');

const invariant = require('invariant');

const {shouldUseNativeDriver} = require('./NativeAnimatedHelper');

export type Mapping = {[key: string]: Mapping, ...} | AnimatedValue;
export type Mapping =
| {[key: string]: Mapping, ...}
| AnimatedValue
| AnimatedValueXY;
export type EventConfig = {
listener?: ?Function,
useNativeDriver: boolean,
Expand All @@ -41,6 +45,9 @@ function attachNativeEvent(
nativeEventPath: path,
animatedValueTag: value.__getNativeTag(),
});
} else if (value instanceof AnimatedValueXY) {
traverse(value.x, path.concat('x'));
traverse(value.y, path.concat('y'));
} else if (typeof value === 'object') {
for (const key in value) {
traverse(value[key], path.concat(key));
Expand Down Expand Up @@ -95,6 +102,13 @@ function validateMapping(argMapping, args) {
);
return;
}
if (recMapping instanceof AnimatedValueXY) {
invariant(
typeof recEvt.x === 'number' && typeof recEvt.y === 'number',
'Bad mapping of event key ' + key + ', should be XY but got ' + recEvt,
);
return;
}
if (typeof recEvt === 'number') {
invariant(
recMapping instanceof AnimatedValue,
Expand Down Expand Up @@ -204,22 +218,27 @@ class AnimatedEvent {
validatedMapping = true;
}

const traverse = (recMapping, recEvt, key) => {
const traverse = (recMapping, recEvt) => {
if (recMapping instanceof AnimatedValue) {
if (typeof recEvt === 'number') {
recMapping.setValue(recEvt);
}
} else if (recMapping instanceof AnimatedValueXY) {
if (typeof recEvt === 'object') {
traverse(recMapping.x, recEvt.x);
traverse(recMapping.y, recEvt.y);
}
} else if (typeof recMapping === 'object') {
for (const mappingKey in recMapping) {
/* $FlowFixMe[prop-missing] (>=0.120.0) This comment suppresses an
* error found when Flow v0.120 was deployed. To see the error,
* delete this comment and run Flow. */
traverse(recMapping[mappingKey], recEvt[mappingKey], mappingKey);
traverse(recMapping[mappingKey], recEvt[mappingKey]);
}
}
};
this._argMapping.forEach((mapping, idx) => {
traverse(mapping, args[idx], 'arg' + idx);
traverse(mapping, args[idx]);
});

this._callListeners(...args);
Expand Down
13 changes: 13 additions & 0 deletions Libraries/Animated/__tests__/Animated-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -638,6 +638,16 @@ describe('Animated tests', () => {
handler({bar: 'ignoreBar'}, {state: {baz: 'ignoreBaz', foo: 42}});
expect(value.__getValue()).toBe(42);
});

it('should validate AnimatedValueXY mappings', () => {
const value = new Animated.ValueXY({x: 0, y: 0});
const handler = Animated.event([{state: value}], {
useNativeDriver: false,
});
handler({state: {x: 1, y: 2}});
expect(value.__getValue()).toMatchObject({x: 1, y: 2});
});

it('should call listeners', () => {
const value = new Animated.Value(0);
const listener = jest.fn();
Expand All @@ -650,6 +660,7 @@ describe('Animated tests', () => {
expect(listener.mock.calls.length).toBe(1);
expect(listener).toBeCalledWith({foo: 42});
});

it('should call forked event listeners, with Animated.event() listener', () => {
const value = new Animated.Value(0);
const listener = jest.fn();
Expand All @@ -666,6 +677,7 @@ describe('Animated tests', () => {
expect(listener2.mock.calls.length).toBe(1);
expect(listener2).toBeCalledWith({foo: 42});
});

it('should call forked event listeners, with js listener', () => {
const listener = jest.fn();
const listener2 = jest.fn();
Expand All @@ -676,6 +688,7 @@ describe('Animated tests', () => {
expect(listener2.mock.calls.length).toBe(1);
expect(listener2).toBeCalledWith({foo: 42});
});

it('should call forked event listeners, with undefined listener', () => {
const listener = undefined;
const listener2 = jest.fn();
Expand Down
18 changes: 18 additions & 0 deletions Libraries/Animated/__tests__/AnimatedNative-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,24 @@ describe('Native Animated', () => {
);
});

it('shoud map AnimatedValueXY', () => {
const value = new Animated.ValueXY({x: 0, y: 0});
value.__makeNative();
const event = Animated.event([{nativeEvent: {state: value}}], {
useNativeDriver: true,
});

TestRenderer.create(<Animated.View onTouchMove={event} />);
['x', 'y'].forEach((key, idx) =>
expect(
NativeAnimatedModule.addAnimatedEventToView,
).toHaveBeenNthCalledWith(idx + 1, expect.any(Number), 'onTouchMove', {
nativeEventPath: ['state', key],
animatedValueTag: value[key].__getNativeTag(),
}),
);
});

it('should throw on invalid event path', () => {
const value = new Animated.Value(0);
value.__makeNative();
Expand Down

0 comments on commit 27dd2ec

Please sign in to comment.