]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(runtime-dom): fix event listeners call in firefox <= 53 (#3501)
authorHcySunYang <HcySunYang@outlook.com>
Mon, 29 Mar 2021 23:15:12 +0000 (07:15 +0800)
committerGitHub <noreply@github.com>
Mon, 29 Mar 2021 23:15:12 +0000 (19:15 -0400)
fix #3485

packages/runtime-dom/src/modules/events.ts

index a81b6fdf3f099754a46ac715006c2f0033501750..7172e3efdd24d2026fec8f30b277146333c33400 100644 (file)
@@ -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,