Skip to content

Commit

Permalink
fix circular structure object
Browse files Browse the repository at this point in the history
  • Loading branch information
Maizify committed Jun 5, 2016
1 parent 9643ed8 commit b79d09c
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 45 deletions.
4 changes: 2 additions & 2 deletions dist/vconsole.min.js

Large diffs are not rendered by default.

45 changes: 25 additions & 20 deletions src/lib/tool.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,7 @@ export function isSymbol(value) {
return Object.prototype.toString.call(value) == '[object Symbol]';
}
export function isObject(value) {
let is = (
Object.prototype.toString.call(value) == '[object Object]'
||
(value !== null && typeof value == 'object')
);
return is;
return Object.prototype.toString.call(value) == '[object Object]';
}
export function isFunction(value) {
return Object.prototype.toString.call(value) == '[object Function]';
Expand All @@ -85,28 +80,27 @@ export function JSONStringify(obj) {
let json = '',
lv = 0;

// use a map to track whether a value has been iterated in previous level
// use a map to track parent relationship
let objMap = [];
function _isIteratedInPreLevel(val, curLV) {
let is = false;
for (let item of objMap) {
if (item.obj == val && item.lv < curLV) {
is = true;
break;
function _hasSameParentAsChild(child) {
// find upper item which child is equal to this child
for (let i = objMap.length - 1; i >= 0; i--) {
if (objMap[i].child == child) {
return true;
}
}
return is;
return false;
}

function _iterateObj(val) {
if (isObject(val)) {
// object
if (_isIteratedInPreLevel(val, lv)) {
if (_hasSameParentAsChild(val)) {
// this object is circular, skip it
json += "{Circular Object}";
json += "CircularObject";
return;
}
objMap.push({obj: val, lv: lv});
objMap.push({parent: parent, child: val});

let keys = Object.keys(val);
json += "{";
Expand All @@ -115,25 +109,36 @@ export function JSONStringify(obj) {
let k = keys[i];
if (!val.hasOwnProperty(k)) { continue; }
json += k + ': ';
_iterateObj(val[k]);
_iterateObj(val[k], val);
if (i < keys.length - 1) {
json += ', ';
}
}
lv--;
json += '}';

objMap.pop();
} else if (isArray(val)) {
// array
if (_hasSameParentAsChild(val)) {
// this array is circular, skip it
json += "CircularArray";
return;
}
objMap.push({parent: parent, child: val});

json += '[';
lv++;
for (let i=0; i<val.length; i++) {
_iterateObj(val[i]);
_iterateObj(val[i], val);
if (i < val.length - 1) {
json += ', ';
}
}
lv--;
json += ']';

objMap.pop();
} else if (isString(val)) {
json += '"'+val+'"';
} else if (isNumber(val)) {
Expand All @@ -152,7 +157,7 @@ export function JSONStringify(obj) {
json += 'unknown';
}
}
_iterateObj(obj);
_iterateObj(obj, null);

return json;
}
Expand Down
39 changes: 25 additions & 14 deletions src/log/log.js
Original file line number Diff line number Diff line change
Expand Up @@ -247,28 +247,28 @@ class VConsoleLogTab extends VConsolePlugin {
outer = Object.prototype.toString.call(obj).replace('[object ', '').replace(']', '');
outer += ' ' + preview;

// use a map to track whether a value has been iterated in previous level
// use a map to track parent relationship
let objMap = [];
function _isIteratedInPreLevel(val, curLV) {
let is = false;
for (let item of objMap) {
if (item.obj == val && item.lv < curLV) {
is = true;
break;
function _hasSameParentAsChild(child) {
// find upper item which child is equal to this child
for (let i = objMap.length - 1; i >= 0; i--) {
if (objMap[i].child == child) {
return true;
}
}
return is;
return false;
}

function _iterateObj(val) {
function _iterateObj(val, parent) {

if (tool.isObject(val)) {
// object
if (_isIteratedInPreLevel(val, lv)) {
if (_hasSameParentAsChild(val)) {
// this object is circular, skip it
inner += "{Circular Object}";
return;
}
objMap.push({obj: val, lv: lv});
objMap.push({parent: parent, child: val});

let keys = Object.keys(val);
inner += "{\n";
Expand All @@ -277,26 +277,37 @@ class VConsoleLogTab extends VConsolePlugin {
let k = keys[i];
if (!val.hasOwnProperty(k)) { continue; }
inner += Array(lv + 1).join(p) + $.render(tplFoldCode, {type:'key', code:k}, true) + ': ';
_iterateObj(val[k]);
_iterateObj(val[k], val);
if (i < keys.length - 1) {
inner += ",\n";
}
}
lv--;
inner += "\n" + Array(lv + 1).join(p) + "}";

objMap.pop();
} else if (tool.isArray(val)) {
// array
if (_hasSameParentAsChild(val)) {
// this array is circular, skip it
inner += "[Circular Array]";
return;
}
objMap.push({parent: parent, child: val});

inner += "[\n";
lv++;
for (let i=0; i<val.length; i++) {
inner += Array(lv + 1).join(p) + $.render(tplFoldCode, {type:'key', code:i}, true) + ': ';
_iterateObj(val[i]);
_iterateObj(val[i], val);
if (i < val.length - 1) {
inner += ",\n";
}
}
lv--;
inner += "\n" + Array(lv + 1).join(p) + "]";

objMap.pop();
} else if (tool.isString(val)) {
inner += $.render(tplFoldCode, {type:'string', code:'"'+tool.htmlEncode(val)+'"'}, true);
} else if (tool.isNumber(val)) {
Expand All @@ -313,7 +324,7 @@ class VConsoleLogTab extends VConsolePlugin {
inner += JSON.stringify(val);
}
}
_iterateObj(obj);
_iterateObj(obj, null);

let line = $.render(tplFold, {outer: outer, inner: inner}, true);
return line;
Expand Down
25 changes: 16 additions & 9 deletions test/log.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
<a onclick="formattedLog()" href="javascript:;" class="weui_btn weui_btn_default">formattedLog</a>
<a onclick="normalObject()" href="javascript:;" class="weui_btn weui_btn_default">normalObject</a>
<a onclick="circularObject()" href="javascript:;" class="weui_btn weui_btn_default">circularObject</a>
<a onclick="circularArray()" href="javascript:;" class="weui_btn weui_btn_default">circularArray</a>
<a onclick="largeObject()" href="javascript:;" class="weui_btn weui_btn_default">largeObject</a>
</div>
</body>
Expand Down Expand Up @@ -45,19 +46,25 @@
console.info('normalObject() End');
}

function circularArray() {
console.info('circularArray() Start');
var arr = [];
arr[0] = 'foo';
arr[1] = arr;
console.log('A circular structure array:', arr);
console.info('circularArray() End');
}

function circularObject() {
console.info('circularObject() Start');
console.info('An child object printed in upper level will not be shown again in lower level.');
console.info('circularArray() Start');
var obj = {
foo: 'bar'
};
console.log('A circular structure JSON:', {
'level_1.1': obj,
'level_1.2': {
'level_2.1': obj
},
'level_1.3': obj
});
obj.self = obj;
obj.next = {};
obj.next.next = obj.next;
obj.next.self = obj;
console.log('A circular structure JSON:', obj);
console.info('circularObject() End');
}

Expand Down

0 comments on commit b79d09c

Please sign in to comment.