From a4b9ce263f11d89826e796d933bec6ad33107e75 Mon Sep 17 00:00:00 2001 From: hezedu Date: Mon, 8 Mar 2021 22:43:42 +0800 Subject: [PATCH] fix(state-key): PositionStore memory leak(fix #3445) --- src/util/push-state.js | 3 ++- src/util/scroll.js | 11 ++++++++++- src/util/state-key.js | 20 +++++++++++--------- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/util/push-state.js b/src/util/push-state.js index dcbab672b..b058f7574 100644 --- a/src/util/push-state.js +++ b/src/util/push-state.js @@ -1,7 +1,7 @@ /* @flow */ import { inBrowser } from './dom' -import { saveScrollPosition } from './scroll' +import { saveScrollPosition, clearPositionStore } from './scroll' import { genStateKey, setStateKey, getStateKey } from './state-key' import { extend } from './misc' @@ -28,6 +28,7 @@ export function pushState (url?: string, replace?: boolean) { // DOM Exception 18 where it limits to 100 pushState calls const history = window.history try { + clearPositionStore() if (replace) { // preserve existing history state as it could be overriden by the user const stateCopy = extend({}, history.state) diff --git a/src/util/scroll.js b/src/util/scroll.js index d1adeb310..5848c00d2 100644 --- a/src/util/scroll.js +++ b/src/util/scroll.js @@ -2,7 +2,7 @@ import type Router from '../index' import { assert } from './warn' -import { getStateKey, setStateKey } from './state-key' +import { getStateKey, setStateKey, getCurrentStateKey } from './state-key' import { extend } from './misc' const positionStore = Object.create(null) @@ -173,3 +173,12 @@ function scrollToPosition (shouldScroll, position) { } } } + +export function clearPositionStore () { + const key = getCurrentStateKey() + for (var i in positionStore) { + if (Number(i) > key) { + delete (positionStore[i]) + } + } +} diff --git a/src/util/state-key.js b/src/util/state-key.js index be9144d74..24e018df9 100644 --- a/src/util/state-key.js +++ b/src/util/state-key.js @@ -1,22 +1,24 @@ /* @flow */ import { inBrowser } from './dom' -// use User Timing api (if present) for more accurate key precision -const Time = - inBrowser && window.performance && window.performance.now - ? window.performance - : Date +export function getCurrentStateKey (): number { + const state = window.history.state + if (state && typeof state.key === 'number') { + return state.key + } + return 1 +} -export function genStateKey (): string { - return Time.now().toFixed(3) +export function genStateKey (): number { + return getCurrentStateKey() + 1 } -let _key: string = genStateKey() +let _key: number = inBrowser ? getCurrentStateKey() : -1 export function getStateKey () { return _key } -export function setStateKey (key: string) { +export function setStateKey (key: number) { return (_key = key) }