Skip to content

Commit

Permalink
fix(drag-drop): error during browser emulation on firefox
Browse files Browse the repository at this point in the history
The events that Firefox emits when it emulates a mobile device in the dev tools are incomplete which causes an error to be thrown at the end of a drag seequence. These changes add a bit of extra logic so everything doesn't break down.

Fixes angular#19385.
  • Loading branch information
crisbeto committed May 19, 2020
1 parent e72e9ae commit 9dfd5bb
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 2 deletions.
21 changes: 21 additions & 0 deletions src/cdk/drag-drop/directives/drag.spec.ts
Expand Up @@ -1187,6 +1187,27 @@ describe('CdkDrag', () => {
expect(drag.rootElementSelector).toBe('.root');
}));

it('should not throw if touches and changedTouches are empty', fakeAsync(() => {
const fixture = createComponent(StandaloneDraggable);
fixture.detectChanges();
const dragElement = fixture.componentInstance.dragElement.nativeElement;

startDraggingViaTouch(fixture, dragElement);
continueDraggingViaTouch(fixture, 50, 100);

const event = createTouchEvent('touchend', 50, 100);
Object.defineProperties(event, {
touches: {get: () => []},
changedTouches: {get: () => []}
});

expect(() => {
dispatchEvent(document, event);
fixture.detectChanges();
tick();
}).not.toThrow();
}));

});

describe('draggable with a handle', () => {
Expand Down
11 changes: 9 additions & 2 deletions src/cdk/drag-drop/drag-ref.ts
Expand Up @@ -1034,9 +1034,16 @@ export class DragRef<T = any> {

/** Determines the point of the page that was touched by the user. */
private _getPointerPositionOnPage(event: MouseEvent | TouchEvent): Point {
// `touches` will be empty for start/end events so we have to fall back to `changedTouches`.
const point = isTouchEvent(event) ? (event.touches[0] || event.changedTouches[0]) : event;
const scrollPosition = this._getViewportScrollPosition();
const point = isTouchEvent(event) ?
// `touches` will be empty for start/end events so we have to fall back to `changedTouches`.
// Also note that on real devices we're guaranteed for either `touches` or `changedTouches`
// to have a value, but Firefox in device emulation mode has a bug where both can be empty
// for `touchstart` and `touchend` so we fall back to a dummy object in order to avoid
// throwing an error. The value returned here will be incorrect, but since this only
// breaks inside a developer tool and the value is only used for secondary information,
// we can get away with it. See https://bugzilla.mozilla.org/show_bug.cgi?id=1615824.
(event.touches[0] || event.changedTouches[0] || {pageX: 0, pageY: 0}) : event;

return {
x: point.pageX - scrollPosition.left,
Expand Down

0 comments on commit 9dfd5bb

Please sign in to comment.