diff --git a/lib/utils/gestures.html b/lib/utils/gestures.html
index e4599758c2..c81b51cd6f 100644
--- a/lib/utils/gestures.html
+++ b/lib/utils/gestures.html
@@ -150,6 +150,11 @@
// the bounding box of the target of the event
// Thanks IE 10 >:(
let t = Gestures._findOriginalTarget(ev);
+ // make sure the target of the event is an element so we can use getBoundingClientRect,
+ // if not, just assume it is a synthetic click
+ if (t.nodeType !== Node.ELEMENT_NODE) {
+ return true;
+ }
let bcr = t.getBoundingClientRect();
// use page x/y to account for scrolling
let x = ev.pageX, y = ev.pageY;
diff --git a/test/unit/gestures.html b/test/unit/gestures.html
index 868961910c..289de18e61 100644
--- a/test/unit/gestures.html
+++ b/test/unit/gestures.html
@@ -506,6 +506,16 @@
assert.equal(el[key], 'pan-y');
})
});
+
+ suite('Regression Testing', function() {
+ test('#4459', function() {
+ Polymer.Gestures.add(document, 'tap', null);
+ document.dispatchEvent(new MouseEvent('mousedown', { detail: 1, clientX: -100, bubbles: true, composed: true }));
+ document.dispatchEvent(new MouseEvent('mouseup', { detail: 1, clientX: 100, bubbles: true, composed: true }));
+ document.dispatchEvent(new MouseEvent('click', { detail: 1, clientX: 100, bubbles: true, composed: true }));
+ Polymer.Gestures.remove(document, 'tap', null);
+ });
+ })