|
|
@@ -15,18 +15,23 @@ type EventValue = Function | Function[]
|
|
|
// Async edge case fix requires storing an event listener's attach timestamp.
|
|
|
let _getNow: () => number = Date.now
|
|
|
|
|
|
-// Determine what event timestamp the browser is using. Annoyingly, the
|
|
|
-// timestamp can either be hi-res (relative to page load) or low-res
|
|
|
-// (relative to UNIX epoch), so in order to compare time we have to use the
|
|
|
-// same timestamp type when saving the flush timestamp.
|
|
|
-if (
|
|
|
- typeof document !== 'undefined' &&
|
|
|
- _getNow() > document.createEvent('Event').timeStamp
|
|
|
-) {
|
|
|
- // if the low-res timestamp which is bigger than the event timestamp
|
|
|
- // (which is evaluated AFTER) it means the event is using a hi-res timestamp,
|
|
|
- // and we need to use the hi-res version for event listeners as well.
|
|
|
- _getNow = () => performance.now()
|
|
|
+let skipTimestampCheck = false
|
|
|
+
|
|
|
+if (typeof window !== 'undefined') {
|
|
|
+ // Determine what event timestamp the browser is using. Annoyingly, the
|
|
|
+ // timestamp can either be hi-res (relative to page load) or low-res
|
|
|
+ // (relative to UNIX epoch), so in order to compare time we have to use the
|
|
|
+ // same timestamp type when saving the flush timestamp.
|
|
|
+ if (_getNow() > document.createEvent('Event').timeStamp) {
|
|
|
+ // if the low-res timestamp which is bigger than the event timestamp
|
|
|
+ // (which is evaluated AFTER) it means the event is using a hi-res timestamp,
|
|
|
+ // and we need to use the hi-res version for event listeners as well.
|
|
|
+ _getNow = () => performance.now()
|
|
|
+ }
|
|
|
+ // #3485: Firefox <= 53 has incorrect Event.timeStamp implementation
|
|
|
+ // and does not fire microtasks in between event propagation, so safe to exclude.
|
|
|
+ const ffMatch = navigator.userAgent.match(/firefox\/(\d+)/i)
|
|
|
+ skipTimestampCheck = !!(ffMatch && Number(ffMatch[1]) <= 53)
|
|
|
}
|
|
|
|
|
|
// To avoid the overhead of repeatedly calling performance.now(), we cache
|
|
|
@@ -111,7 +116,8 @@ function createInvoker(
|
|
|
// and the handler would only fire if the event passed to it was fired
|
|
|
// AFTER it was attached.
|
|
|
const timeStamp = e.timeStamp || _getNow()
|
|
|
- if (timeStamp >= invoker.attached - 1) {
|
|
|
+
|
|
|
+ if (skipTimestampCheck || timeStamp >= invoker.attached - 1) {
|
|
|
callWithAsyncErrorHandling(
|
|
|
patchStopImmediatePropagation(e, invoker.value),
|
|
|
instance,
|