From 201dcc76c84893af3b5e980c6e9edadba8e132d4 Mon Sep 17 00:00:00 2001 From: HcySunYang Date: Mon, 29 Mar 2021 12:39:07 +0800 Subject: [PATCH 1/2] fix(runtime-dom): fix the event listeners call in firefox <= 53 --- packages/runtime-dom/src/modules/events.ts | 10 ++++++++-- packages/shared/src/index.ts | 4 ++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/packages/runtime-dom/src/modules/events.ts b/packages/runtime-dom/src/modules/events.ts index a81b6fdf3f0..69ff2776bf4 100644 --- a/packages/runtime-dom/src/modules/events.ts +++ b/packages/runtime-dom/src/modules/events.ts @@ -1,4 +1,4 @@ -import { hyphenate, isArray } from '@vue/shared' +import { hyphenate, isArray, isFF } from '@vue/shared' import { ComponentInternalInstance, callWithAsyncErrorHandling @@ -111,7 +111,13 @@ 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 ( + timeStamp >= invoker.attached - 1 || + // #3485: Firefox <= 53 has incorrect Event.timeStamp implementation + // and does not fire microtasks in between event propagation, so safe to exclude. + (isFF && Number(isFF[1]) <= 53) + ) { callWithAsyncErrorHandling( patchStopImmediatePropagation(e, invoker.value), instance, diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts index 84b324beda3..8a7acab03f0 100644 --- a/packages/shared/src/index.ts +++ b/packages/shared/src/index.ts @@ -180,3 +180,7 @@ export const getGlobalThis = (): any => { : {}) ) } + +const UA = + typeof window !== 'undefined' && window.navigator.userAgent.toLowerCase() +export const isFF = UA && UA.match(/firefox\/(\d+)/) From e075777c0d26718763f0ad28eda6cf379379dfad Mon Sep 17 00:00:00 2001 From: Evan You Date: Mon, 29 Mar 2021 19:09:48 -0400 Subject: [PATCH 2/2] refactor: move utils in --- packages/runtime-dom/src/modules/events.ts | 38 +++++++++++----------- packages/shared/src/index.ts | 4 --- 2 files changed, 19 insertions(+), 23 deletions(-) diff --git a/packages/runtime-dom/src/modules/events.ts b/packages/runtime-dom/src/modules/events.ts index 69ff2776bf4..7172e3efdd2 100644 --- a/packages/runtime-dom/src/modules/events.ts +++ b/packages/runtime-dom/src/modules/events.ts @@ -1,4 +1,4 @@ -import { hyphenate, isArray, isFF } from '@vue/shared' +import { hyphenate, isArray } from '@vue/shared' import { ComponentInternalInstance, callWithAsyncErrorHandling @@ -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 @@ -112,12 +117,7 @@ function createInvoker( // AFTER it was attached. const timeStamp = e.timeStamp || _getNow() - if ( - timeStamp >= invoker.attached - 1 || - // #3485: Firefox <= 53 has incorrect Event.timeStamp implementation - // and does not fire microtasks in between event propagation, so safe to exclude. - (isFF && Number(isFF[1]) <= 53) - ) { + if (skipTimestampCheck || timeStamp >= invoker.attached - 1) { callWithAsyncErrorHandling( patchStopImmediatePropagation(e, invoker.value), instance, diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts index 8a7acab03f0..84b324beda3 100644 --- a/packages/shared/src/index.ts +++ b/packages/shared/src/index.ts @@ -180,7 +180,3 @@ export const getGlobalThis = (): any => { : {}) ) } - -const UA = - typeof window !== 'undefined' && window.navigator.userAgent.toLowerCase() -export const isFF = UA && UA.match(/firefox\/(\d+)/)