// 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
// 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,