Fix for long press state transition error in Touchable.js
Summary: public This diff fixes an occasional JS exception thrown by Touchable.js when it attempts to transitions to the RESPONDER_ACTIVE_LONG_PRESS_IN state from the RESPONDER_INACTIVE_PRESS_IN state. Although I wasn't able to reproduce the error while testing, I was able to identify the likely cause: the LONG_PRESS_DETECTED state transition is triggered by a timer that is started on touch-down. This timer should be cancelled if the gesture is interrupted, however I identified a code path where the state can be changed to RESPONDER_INACTIVE_PRESS_IN without the longPressDelayTimeout being cancelled. To fix this, I've added some logic to cancel the timer in that case. I've also added a test for the error scenario that will display a redbox in __DEV__ mode, but will fail gracefully in production mode. Reviewed By: jingc Differential Revision: D2709750 fb-gh-sync-id: aeea1a31de5e92eb394c2ea177f556b131d50790
This commit is contained in:
parent
7424af6078
commit
7ab17e5ef3
|
@ -456,6 +456,11 @@ var TouchableMixin = {
|
|||
pressExpandBottom;
|
||||
if (isTouchWithinActive) {
|
||||
this._receiveSignal(Signals.ENTER_PRESS_RECT, e);
|
||||
var curState = this.state.touchable.touchState;
|
||||
if (curState === States.RESPONDER_INACTIVE_PRESS_IN) {
|
||||
// fix for t7967420
|
||||
this._cancelLongPressDelayTimeout();
|
||||
}
|
||||
} else {
|
||||
this._cancelLongPressDelayTimeout();
|
||||
this._receiveSignal(Signals.LEAVE_PRESS_RECT, e);
|
||||
|
@ -564,7 +569,20 @@ var TouchableMixin = {
|
|||
|
||||
_handleLongDelay: function(e) {
|
||||
this.longPressDelayTimeout = null;
|
||||
this._receiveSignal(Signals.LONG_PRESS_DETECTED, e);
|
||||
var curState = this.state.touchable.touchState;
|
||||
if (curState !== States.RESPONDER_ACTIVE_PRESS_IN &&
|
||||
curState !== States.RESPONDER_ACTIVE_LONG_PRESS_IN) {
|
||||
if (__DEV__) {
|
||||
throw new Error(
|
||||
'Attempted to transition from state `' + curState + '` to `' +
|
||||
States.RESPONDER_ACTIVE_LONG_PRESS_IN + '`, which is not supported. ' +
|
||||
'This is most likely due to `Touchable.longPressDelayTimeout` not ' +
|
||||
'being cancelled.'
|
||||
);
|
||||
}
|
||||
} else {
|
||||
this._receiveSignal(Signals.LONG_PRESS_DETECTED, e);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -577,13 +595,13 @@ var TouchableMixin = {
|
|||
*/
|
||||
_receiveSignal: function(signal, e) {
|
||||
var curState = this.state.touchable.touchState;
|
||||
if (!(Transitions[curState] && Transitions[curState][signal])) {
|
||||
var nextState = Transitions[curState] && Transitions[curState][signal];
|
||||
if (!nextState) {
|
||||
throw new Error(
|
||||
'Unrecognized signal `' + signal + '` or state `' + curState +
|
||||
'` for Touchable responder `' + this.state.touchable.responderID + '`'
|
||||
);
|
||||
}
|
||||
var nextState = Transitions[curState][signal];
|
||||
if (nextState === States.ERROR) {
|
||||
throw new Error(
|
||||
'Touchable cannot transition from `' + curState + '` to `' + signal +
|
||||
|
|
Loading…
Reference in New Issue