From c0520990caad90fe0162b6cb889157cfddfe3bbb Mon Sep 17 00:00:00 2001 From: Parth Date: Thu, 14 Feb 2019 11:29:30 +0530 Subject: [PATCH 1/3] Fixed issue#1507 : Memory leak happening while using registerModule/unregisterModule. --- src/store.js | 4 ++-- src/util.js | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/store.js b/src/store.js index dfcc755f8..f5dcbf067 100644 --- a/src/store.js +++ b/src/store.js @@ -1,7 +1,7 @@ import applyMixin from './mixin' import devtoolPlugin from './plugins/devtool' import ModuleCollection from './module/module-collection' -import { forEachValue, isObject, isPromise, assert } from './util' +import { forEachValue, isObject, isPromise, assert, partial } from './util' let Vue // bind on install @@ -256,7 +256,7 @@ function resetStoreVM (store, state, hot) { const computed = {} forEachValue(wrappedGetters, (fn, key) => { // use computed to leverage its lazy-caching mechanism - computed[key] = () => fn(store) + computed[key] = partial(fn, store) Object.defineProperty(store.getters, key, { get: () => store._vm[key], enumerable: true // for local getters diff --git a/src/util.js b/src/util.js index fb1203251..667983a42 100644 --- a/src/util.js +++ b/src/util.js @@ -64,3 +64,9 @@ export function isPromise (val) { export function assert (condition, msg) { if (!condition) throw new Error(`[vuex] ${msg}`) } + +export function partial (fn, ...bindargs) { + return function (...callargs) { + return fn(...bindargs, ...callargs) + } +} From 913a36736699524ef720667a08a67031009d3f45 Mon Sep 17 00:00:00 2001 From: Parth Date: Mon, 18 Mar 2019 17:56:47 +0530 Subject: [PATCH 2/3] Adding comment for leak description. Simplyfy partial function to take only one argument. --- src/store.js | 4 +++- src/util.js | 6 +++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/store.js b/src/store.js index f5dcbf067..deb6d5932 100644 --- a/src/store.js +++ b/src/store.js @@ -256,6 +256,8 @@ function resetStoreVM (store, state, hot) { const computed = {} forEachValue(wrappedGetters, (fn, key) => { // use computed to leverage its lazy-caching mechanism + // direct inline function use will lead to closure preserving oldVm. + // using partial to return function with only arguments preserved in closure enviroment. computed[key] = partial(fn, store) Object.defineProperty(store.getters, key, { get: () => store._vm[key], @@ -289,7 +291,7 @@ function resetStoreVM (store, state, hot) { oldVm._data.$$state = null }) } - Vue.nextTick(() => oldVm.$destroy()) + Vue.nextTick(() => { oldVm.$destroy(); oldVm.computed = null }) } } diff --git a/src/util.js b/src/util.js index 667983a42..2df74bb16 100644 --- a/src/util.js +++ b/src/util.js @@ -65,8 +65,8 @@ export function assert (condition, msg) { if (!condition) throw new Error(`[vuex] ${msg}`) } -export function partial (fn, ...bindargs) { - return function (...callargs) { - return fn(...bindargs, ...callargs) +export function partial (fn, arg) { + return function () { + return fn(arg) } } From 9fdaea94e18ff11adadfcb5c09f75f98a989e6dc Mon Sep 17 00:00:00 2001 From: Parth Date: Wed, 20 Mar 2019 21:22:53 +0530 Subject: [PATCH 3/3] Removed oldVm.computed = null. This statement is not required --- src/store.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/store.js b/src/store.js index deb6d5932..a79252b50 100644 --- a/src/store.js +++ b/src/store.js @@ -291,7 +291,7 @@ function resetStoreVM (store, state, hot) { oldVm._data.$$state = null }) } - Vue.nextTick(() => { oldVm.$destroy(); oldVm.computed = null }) + Vue.nextTick(() => oldVm.$destroy()) } }