From 47d2562f47d711f6f9f3b35c4ab313d56ec129b7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Felix=20B=C3=BCnemann?= {{ count }} Your counter is {{ $store.getters.isPositive ? 'positive' : 'negative' }} foo: {{ foo }} twoFoos: {{ twoFoos }} {{ count }} Your counter is {{ $store.getters.isPositive ? 'positive' : 'negative' }} foo: {{ foo }} twoFoos: {{ twoFoos }} Date: {{ date.toString() }} - Hours: {{ hours }} - Prototype: {{ date | prototypeString }}
-
+
-
+
-
+
{{ $store.state.dynamic }}
+ {{ $store.getters }}
+
+
+
+
{{localMsg}}
+ {{localMsg}} {{ msg }}
Regex: {{regex.toString()}}
(Press enter to set)
diff --git a/shells/dev/target/dynamic-module.js b/shells/dev/target/dynamic-module.js
new file mode 100644
index 000000000..6d1fb250f
--- /dev/null
+++ b/shells/dev/target/dynamic-module.js
@@ -0,0 +1,19 @@
+export default {
+ namespaced: true,
+ state () {
+ return {
+ dynamic: true
+ }
+ },
+ getters: {
+ notDynamic: state => {
+ console.log('notDynamic', JSON.stringify(state, null, 2))
+ if (state) return !state.dynamic
+ }
+ },
+ mutations: {
+ TOGGLE: state => {
+ state.dynamic = !state.dynamic
+ }
+ }
+}
diff --git a/src/backend/vuex.js b/src/backend/vuex.js
index f3fa4687a..17f47281f 100644
--- a/src/backend/vuex.js
+++ b/src/backend/vuex.js
@@ -1,31 +1,36 @@
import { stringify, parse } from 'src/util'
import SharedData from 'src/shared-data'
-import { set } from '../util'
+import { set, get } from '../util'
import Vue from 'vue'
export function initVuexBackend (hook, bridge, isLegacy) {
const store = hook.store
- let originalVm = store._vm
- const snapshotsVm = new Vue({
- data: {
- $$state: {}
- },
- computed: originalVm.$options.computed
- })
+ let snapshotsVm = null
+ const updateSnapshotsVm = (state) => {
+ snapshotsVm = new Vue({
+ data: {
+ $$state: state || {}
+ },
+ computed: store._vm.$options.computed
+ })
+ }
+
+ updateSnapshotsVm()
const getStateSnapshot = (_store = store) => stringify(_store.state)
let baseStateSnapshot, stateSnapshots, mutations, lastState
+ let registeredModules = {}
+ let allTimeModules = {}
function reset () {
baseStateSnapshot = getStateSnapshot(hook.initialStore)
- hook.initialStore = undefined
mutations = []
resetSnapshotCache()
}
- function resetSnapshotCache () {
+ function resetSnapshotCache (force = true) {
stateSnapshots = [
{ index: -1, state: baseStateSnapshot }
]
@@ -33,6 +38,45 @@ export function initVuexBackend (hook, bridge, isLegacy) {
reset()
+ const origRegisterModule = store.registerModule.bind(store)
+ store.registerModule = (path, module, options) => {
+ if (typeof path === 'string') path = [path]
+ if (SharedData.recordVuex) {
+ addMutation(`Register module: ${path.join('/')}`, {
+ path,
+ module,
+ options
+ }, {
+ registerModule: true
+ })
+ }
+
+ const key = path.join('/')
+ registeredModules[key] = allTimeModules[key] = {
+ path,
+ module,
+ options
+ }
+
+ origRegisterModule(path, module, options)
+ }
+
+ const origUnregisterModule = store.unregisterModule.bind(store)
+ store.unregisterModule = (path) => {
+ if (typeof path === 'string') path = [path]
+ if (SharedData.recordVuex) {
+ addMutation(`Unregister module: ${path.join('/')}`, {
+ path
+ }, {
+ unregisterModule: true
+ })
+ }
+
+ delete registeredModules[path.join('/')]
+
+ origUnregisterModule(path)
+ }
+
bridge.send('vuex:init')
// deal with multiple backend injections
@@ -42,13 +86,19 @@ export function initVuexBackend (hook, bridge, isLegacy) {
hook.on('vuex:mutation', ({ type, payload }) => {
if (!SharedData.recordVuex) return
+ addMutation(type, payload)
+ })
+
+ function addMutation (type, payload, options = {}) {
const index = mutations.length
mutations.push({
type,
payload,
index,
- handlers: store._mutations[type]
+ handlers: store._mutations[type],
+ registeredModules: Object.keys(registeredModules),
+ ...options
})
bridge.send('vuex:mutation', {
@@ -59,17 +109,18 @@ export function initVuexBackend (hook, bridge, isLegacy) {
},
timestamp: Date.now()
})
- })
+ }
// devtool -> application
bridge.on('vuex:travel-to-state', ({ index, apply }) => {
- const stateSnapshot = replayMutations(index)
- const state = parse(stateSnapshot, true)
+ const snapshot = replayMutations(index)
+ const { state } = parse(snapshot, true)
bridge.send('vuex:inspected-state', {
index,
- snapshot: getSnapshot(stateSnapshot)
+ snapshot
})
if (apply) {
+ ensureRegisteredModules(mutations[index])
hook.emit('vuex:travel-to-state', state)
}
})
@@ -93,6 +144,7 @@ export function initVuexBackend (hook, bridge, isLegacy) {
bridge.on('vuex:revert', index => {
resetSnapshotCache()
+ ensureRegisteredModules(mutations[index - 1])
mutations = mutations.slice(0, index)
})
@@ -108,17 +160,21 @@ export function initVuexBackend (hook, bridge, isLegacy) {
snapshot: getSnapshot(baseStateSnapshot)
})
} else {
- const stateSnapshot = replayMutations(index)
+ const snapshot = replayMutations(index)
bridge.send('vuex:inspected-state', {
index,
- snapshot: getSnapshot(stateSnapshot)
+ snapshot
})
}
})
function replayMutations (index) {
+ const originalVm = store._vm
store._vm = snapshotsVm
+ let tempRemovedModules = []
+ let tempAddedModules = []
+
// Get most recent snapshot for target index
// for faster replay
let stateSnapshot
@@ -137,7 +193,18 @@ export function initVuexBackend (hook, bridge, isLegacy) {
if (stateSnapshot.index === index) {
resultState = stateSnapshot.state
} else {
+ const startMutation = mutations[stateSnapshot.index]
+ if (startMutation) {
+ tempRemovedModules = Object.keys(registeredModules).filter(m => !startMutation.registeredModules.includes(m))
+ } else {
+ tempRemovedModules = Object.keys(registeredModules)
+ }
+ tempRemovedModules.forEach(m => {
+ origUnregisterModule(m.split('/'))
+ })
+
const state = parse(stateSnapshot.state, true)
+ updateSnapshotsVm(state)
store.replaceState(state)
SharedData.snapshotLoading = true
@@ -145,7 +212,19 @@ export function initVuexBackend (hook, bridge, isLegacy) {
// Replay mutations
for (let i = stateSnapshot.index + 1; i <= index; i++) {
const mutation = mutations[i]
- if (mutation.handlers) {
+ if (mutation.registerModule) {
+ const { path, module, options } = mutation.payload
+ tempAddedModules.push(path.join('/'))
+ origRegisterModule(path, module, options)
+ updateSnapshotsVm(store.state)
+ } else if (mutation.unregisterModule && get(store.state, mutation.payload.path.join('.')) != null) {
+ const path = mutation.payload.path
+ const index = tempAddedModules.indexOf(path.join('/'))
+ if (index !== -1) tempAddedModules.splice(index, 1)
+ origUnregisterModule(path)
+ updateSnapshotsVm(store.state)
+ } else if (mutation.handlers) {
+ store._committing = true
if (Array.isArray(mutation.handlers)) {
mutation.handlers.forEach(handler => handler(mutation.payload))
} else {
@@ -156,10 +235,11 @@ export function initVuexBackend (hook, bridge, isLegacy) {
mutation.handlers(mutation.payload)
}
}
+ store._committing = false
}
if (i !== index && i % SharedData.cacheVuexSnapshotsEvery === 0) {
- takeStateSnapshot(i, state)
+ takeStateSnapshot(i)
}
}
@@ -169,10 +249,22 @@ export function initVuexBackend (hook, bridge, isLegacy) {
lastState = resultState
+ const result = stringify({
+ state: store.state,
+ getters: store.getters || {}
+ })
+
// Restore user state
+ tempAddedModules.forEach(m => {
+ origUnregisterModule(m.split('/'))
+ })
+ tempRemovedModules.forEach(m => {
+ const { path, module, options } = registeredModules[m]
+ origRegisterModule(path, module, options)
+ })
store._vm = originalVm
- return resultState
+ return result
}
bridge.on('vuex:edit-state', ({ index, value, path }) => {
@@ -201,7 +293,9 @@ export function initVuexBackend (hook, bridge, isLegacy) {
}
function getSnapshot (stateSnapshot = null) {
+ let originalVm
if (stateSnapshot) {
+ originalVm = store._vm
store._vm = snapshotsVm
store.replaceState(parse(stateSnapshot, true))
}
@@ -218,6 +312,28 @@ export function initVuexBackend (hook, bridge, isLegacy) {
return result
}
+
+ function ensureRegisteredModules (mutation) {
+ if (mutation) {
+ mutation.registeredModules.forEach(m => {
+ if (!Object.keys(registeredModules).includes(m)) {
+ const data = allTimeModules[m]
+ if (data) {
+ const { path, module, options } = data
+ origRegisterModule(path, module, options)
+ registeredModules[path.join('/')] = data
+ }
+ }
+ })
+ Object.keys(registeredModules).forEach(m => {
+ if (!mutation.registeredModules.includes(m)) {
+ origUnregisterModule(m.split('/'))
+ delete registeredModules[m]
+ }
+ })
+ updateSnapshotsVm(store.state)
+ }
+ }
}
export function getCustomStoreDetails (store) {
diff --git a/src/devtools/views/vuex/VuexStateInspector.vue b/src/devtools/views/vuex/VuexStateInspector.vue
index 79e01482f..22bd893cc 100644
--- a/src/devtools/views/vuex/VuexStateInspector.vue
+++ b/src/devtools/views/vuex/VuexStateInspector.vue
@@ -171,7 +171,8 @@ export default {
},
isOnlyMutationPayload () {
- return Object.keys(this.inspectedState).length === 1 && this.inspectedState.mutation
+ return (Object.keys(this.inspectedState).length === 1 && this.inspectedState.mutation) ||
+ Object.keys(this.inspectedState).length < 1
},
isActive () {
From 6c23944546f90b99854beb58008a199d826828ae Mon Sep 17 00:00:00 2001
From: Guillaume Chau {{ $store.state.instant }}
-
+
{{ $store.state.dynamic }}
{{ $store.getters }}
-
-
-
+
+
+
{{ $store.state.instant }}
+
+
@@ -11,7 +13,9 @@
+ Large array size: {{ largeArray.length }} +
+{{ setDisplay() }}From 0f88dfab42f9ab1b7b354147733412140fe199ac Mon Sep 17 00:00:00 2001 From: Guillaume Chau
%EUjB*RigCabHJO!PS$y5MZI@$gDZ6jblw_4W)Pz^`&QidlPyv`o7MmFdqXx09
zpNDx^@STn$br~xYa+&e>#Du^ey4c*K?4hFfxS*JZi--IXEH1u~K`^oqaXlf}3axAC
zOzbc=Lm}`umxBf?E((8gP5h$PsDjkdPutleK)#R^XWzl
zs{A>g37cerb%pa*cLJjGbhoB>QX<|XsWD8^_2kzzDQUZ;XQwI|cFvmJoDj#^V|c$H
zYVzb}8>~2Af`082&65}IwN$&lVRN>MxE3VxibT%QxF)uMAWoQ7C`V9&?N8?(rq?=P
z&N4O652DtW=y2_Irr2bi8PECToZN-y%#L@Y&MW!&g(r)!D^EYqGm1PgNt1<&2BbtU
zTARqbWOiPdO`XKV#FFvwdLuQ3g?Sj0yUv}MO_wKCCa%ZC<%c-Ta~-HqfJtLJ(h11d
zMnZ#^^CJYHu;Bai*^jl&BI7(hrwZQfa#|$35lbZ;R;#_a6z<665lg&~H=-J#ZSR*^
z8_*&9j;+6>8Z5_w5)mn4!%=)zx%CTv$tXrj;WN&!`6+{$9#AkahZtY`q&xFLS_lPy
zD#@xtdvw1JG1JWuyQ&jcv7!>6*EO7N^DVd>f@94ii7$$e`?s&EX1o+_8{REs)muY+
z?zLM|sjaQ`Zbde^<>BR{q9T66)iM`>0mz?&wnzNAcPb_#iG!>bxyqwGs%8(KP)ju+
zAH<<(ok)J(gz|80nF=KoAme!vm(+rOf?OakW>PV!gR{gCorP>peiD8J(0o1yxO!27
zzPi1mZcVDHwABueNSMESk4$Avry4r|1?Y8VN)6y2p4@2}mbYD_32xO^pHEQUCi=2?x5GrVI!|9d7GB`?3&<{K
zPzZMRPkW{&cwAaueu8~keYAB_=X<{&HU1lo@Z!BbiF{D-N{H`HZhHN;!$22!b5&ZC
zXIc611bIDIz|^N=&9pD)PESk`XKOr%$J-%60GIyx;jqkeUT@q{II{O!I8G;&^M{UF
z;0B|2X8`wbkV%Nd)6-`BCqlfIt0Jy4?G0W7j$ft2uwD9awWnGyZdtG`uFkPd56aIj
zSk_Lmz{9OBt_Pmcwat$IEaGKfZ3EdOP%5>7rLxyo4@Y!aJ!QtspuW>$g3pZ23S`d|
z|EM=?Wz}wO1>L3nR_hF@z~UMnqUM7BQ)M>3<>P_HVondf-pZ1~*eJth{8aR@ReS^)
zXz4jW(KeaRnE6G3AX^
+L-j0ZT}-RK&w@l()Lu-
Apn@RO$aIg{1m=i1R%
zQ106Vv_k*4ma+KXT`@J4?FxtL&Wf%Hbe0XZ#
z2Pl5o(RCdqXPV(aTJX&b&_;`)ywF;p{#yRx%NNE#gg4ljhr0d_dsY9))S?bc=>G0J
zQ0t#`ve2EXO#Hd)24v`z>8xyQHbY*c*oh7Ljt#1kT^*N{*tavW#ZkXp%NlGmoL};^
zfl`u4#I6#UJg(I*%3P5+R3%H(OGClFFdFq+HO>08;&kSCP_>-iSjkGjVzz0fTv1S0
z12{Bw_w;
<_x`m4U_7UMW+p!KwMT-