8000 [2.0] Support circular structure for logger (#328) · poorprogrammer/vuejs.org@cdd09b5 · GitHub
[go: up one dir, main page]

Skip to content

Commit cdd09b5

Browse files
ktsnyyx990803
authored andcommitted
[2.0] Support circular structure for logger (vuejs#328)
* support circular structure for logger * move utility functions in index.js to utils.js
1 parent 32212d9 commit cdd09b5

File tree

5 files changed

+107
-15
lines changed

5 files changed

+107
-15
lines changed

src/index.js

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import devtoolPlugin from './plugins/devtool'
22
import applyMixin from './mixin'
33
import { mapState, mapMutations, mapGetters, mapActions } from './helpers'
4+
import { isObject, isPromise, assert } from './util'
45

56
let Vue // bind on install
67

@@ -157,10 +158,6 @@ class Store {
157158
}
158159
}
159160

160-
function assert (condition, msg) {
161-
if (!condition) throw new Error(`[vuex] ${msg}`)
162-
}
163-
164161
function updateModule (targetModule, newModule) {
165162
if (newModule.actions) {
166163
targetModule.actions = newModule.actions
@@ -339,14 +336,6 @@ function enableStrictMode (store) {
339336
}, { deep: true, sync: true })
340337
}
341338

342-
function isObject (obj) {
343-
return obj !== null && typeof obj === 'object'
344-
}
345-
346-
function isPromise (val) {
347-
return val && typeof val.then === 'function'
348-
}
349-
350339
function getNestedState (state, path) {
351340
return path.length
352341
? path.reduce((state, key) => state[key], state)

src/plugins/logger.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
11
// Credits: borrowed code from fcomb/redux-logger
22

3+
import { deepCopy } from '../util'
4+
35
export default function createLogger ({
46
collapsed = true,
57
transformer = state => state,
68
mutationTransformer = mut => mut
79
} = {}) {
810
return store => {
9-
let prevState = JSON.parse(JSON.stringify(store.state))
11+
let prevState = deepCopy(store.state)
1012

1113
store.subscribe((mutation, state) => {
1214
if (typeof console === 'undefined') {
1315
return
1416
}
15-
const nextState = JSON.parse(JSON.stringify(state))
17+
const nextState = deepCopy(state)
1618
const time = new Date()
1719
const formattedTime = ` @ ${pad(time.getHours(), 2)}:${pad(time.getMinutes(), 2)}:${pad(time.getSeconds(), 2)}.${pad(time.getMilliseconds(), 3)}`
1820
const formattedMutation = mutationTransformer(mutation)

src/util.js

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/**
2+
* Get the first item that pass the test
3+
* by second argument function
4+
*
5+
* @param {Array} list
6+
* @param {Function} f
7+
* @return {*}
8+
*/
9+
function find (list, f) {
10+
return list.filter(f)[0]
11+
}
12+
13+
/**
14+
* Deep copy the given object considering circular structure.
15+
* This function caches all nested objects and its copies.
16+
* If it detects circular structure, use cached copy to avoid infinite loop.
17+
*
18+
* @param {*} obj
19+
* @param {Array<Object>} cache
20+
* @return {*}
21+
*/
22+
export function deepCopy (obj, cache = []) {
23+
// just return if obj is immutable value
24+
if (obj === null || typeof obj !== 'object') {
25+
return obj
26+
}
27+
28+
// if obj is hit, it is in circular structure
29+
const hit = find(cache, c => c.original === obj)
30+
if (hit) {
31+
return hit.copy
32+
}
33+
34+
const copy = Array.isArray(obj) ? [] : {}
35+
// put the copy into cache at first
36+
// because we want to refer it in recursive deepCopy
37+
cache.push({
38+
original: obj,
39+
copy
40+
})
41+
42+
Object.keys(obj).forEach(key => {
43+
copy[key] = deepCopy(obj[key], cache)
44+
})
45+
46+
return copy
47+
}
48+
49+
export function isObject (obj) {
50+
return obj !== null && typeof obj === 'object'
51+
}
52+
53+
export function isPromise (val) {
54+
return val && typeof val.then === 'function'
55+
}
56+
57+
export function assert (condition, msg) {
58+
if (!condition) throw new Error(`[vuex] ${msg}`)
59+
}

test/unit/jasmine.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
{
22
"spec_dir": "test/unit",
33
"spec_files": [
4-
"test.js"
4+
"test.js",
5+
"util.js"
56
],
67
"helpers": [
78
"../../node_modules/babel-register/lib/node.js"

test/unit/util.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { deepCopy } from '../../src/util'
2+
3+
describe('util', () => {
4+
it('deepCopy: nornal structure', () => {
5+
const original = {
6+
a: 1,
7+
b: 'string',
8+
c: true,
9+
d: null,
10+
e: undefined
11+
}
12+
const copy = deepCopy(original)
13+
14+
expect(copy).toEqual(original)
15+
})
16+
17+
it('deepCopy: nested structure', () => {
18+
const original = {
19+
a: {
20+
b: 1,
21+
c: [2, 3, {
22+
d: 4
23+
}]
24+
}
25+
}
26+
const copy = deepCopy(original)
27+
28+
expect(copy).toEqual(original)
29+
})
30+
31+
it('deepCopy: circular structure', () => {
32+
const original = {
33+
a: 1
34+
}
35+
original.circular = original
36+
37+
const copy = deepCopy(original)
38+
39+
expect(copy).toEqual(original)
40+
})
41+
})

0 commit comments

Comments
 (0)
0