Skip to content

Commit 9dfd5bb

Browse files
committed
fix(drag-drop): error during browser emulation on firefox
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 #19385.
1 parent e72e9ae commit 9dfd5bb

File tree

2 files changed

+30
-2
lines changed

2 files changed

+30
-2
lines changed

src/cdk/drag-drop/directives/drag.spec.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1187,6 +1187,27 @@ describe('CdkDrag', () => {
11871187
expect(drag.rootElementSelector).toBe('.root');
11881188
}));
11891189

1190+
it('should not throw if touches and changedTouches are empty', fakeAsync(() => {
1191+
const fixture = createComponent(StandaloneDraggable);
1192+
fixture.detectChanges();
1193+
const dragElement = fixture.componentInstance.dragElement.nativeElement;
1194+
1195+
startDraggingViaTouch(fixture, dragElement);
1196+
continueDraggingViaTouch(fixture, 50, 100);
1197+
1198+
const event = createTouchEvent('touchend', 50, 100);
1199+
Object.defineProperties(event, {
1200+
touches: {get: () => []},
1201+
changedTouches: {get: () => []}
1202+
});
1203+
1204+
expect(() => {
1205+
dispatchEvent(document, event);
1206+
fixture.detectChanges();
1207+
tick();
1208+
}).not.toThrow();
1209+
}));
1210+
11901211
});
11911212

11921213
describe('draggable with a handle', () => {

src/cdk/drag-drop/drag-ref.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1034,9 +1034,16 @@ export class DragRef<T = any> {
10341034

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

10411048
return {
10421049
x: point.pageX - scrollPosition.left,

0 commit comments

Comments
 (0)