Dev: Support circular object
This commit is contained in:
@@ -6,6 +6,7 @@ draggabilly
|
||||
eruda
|
||||
focusin
|
||||
iframe
|
||||
iteratee
|
||||
onerror
|
||||
postcss
|
||||
scss
|
||||
|
||||
6
eustia/escapeJsonStr.js
Normal file
6
eustia/escapeJsonStr.js
Normal file
@@ -0,0 +1,6 @@
|
||||
function exports(str)
|
||||
{
|
||||
return str.replace(/\\/g, '\\\\')
|
||||
.replace(/"/g, '\\"')
|
||||
.replace(/\f|\n|\r|\t/g, '');
|
||||
}
|
||||
@@ -33,7 +33,7 @@
|
||||
}
|
||||
.json {
|
||||
background: #fff;
|
||||
padding: 0 25px 10px;
|
||||
padding: $padding;
|
||||
}
|
||||
.http {
|
||||
.breadcrumb {
|
||||
|
||||
@@ -8,22 +8,31 @@ export default class JsonViewer
|
||||
|
||||
this._data = [data];
|
||||
this._$el = $el;
|
||||
this._map = {};
|
||||
|
||||
this._appendTpl();
|
||||
this._bindEvent();
|
||||
}
|
||||
_appendTpl()
|
||||
{
|
||||
this._$el.html(jsonToHtml(this._data, true));
|
||||
this._$el.html(jsonToHtml(this._data, this._map, true));
|
||||
}
|
||||
_bindEvent()
|
||||
{
|
||||
var map = this._map;
|
||||
|
||||
this._$el.on('click', 'li', function (e)
|
||||
{
|
||||
var $this = util.$(this),
|
||||
circularId = $this.data('circular'),
|
||||
$firstSpan = util.$(this).find('span').eq(0);
|
||||
|
||||
if ($this.data('first-level') === 'true') return;
|
||||
if ($this.data('first-level')) return;
|
||||
if (circularId)
|
||||
{
|
||||
$this.find('ul').html(jsonToHtml(map[circularId], map, false));
|
||||
$this.rmAttr('data-circular');
|
||||
}
|
||||
|
||||
if (!$firstSpan.hasClass('eruda-expanded')) return;
|
||||
|
||||
@@ -43,33 +52,44 @@ export default class JsonViewer
|
||||
}
|
||||
}
|
||||
|
||||
function jsonToHtml(data, firstLevel)
|
||||
function jsonToHtml(data, map, firstLevel)
|
||||
{
|
||||
var ret = '';
|
||||
|
||||
for (let key in data)
|
||||
{
|
||||
if (key === 'erudaObjAbstract') continue;
|
||||
if (Object.hasOwnProperty.call(data, key)) ret += createEl(key, data[key], firstLevel);
|
||||
let val = data[key];
|
||||
|
||||
if (key === 'erudaObjAbstract' ||
|
||||
key === 'erudaCircular' ||
|
||||
key === 'erudaId' ||
|
||||
(util.isStr(val) && util.startWith(val, 'erudaJson'))) continue;
|
||||
|
||||
if (Object.hasOwnProperty.call(data, key)) ret += createEl(key, val, map, firstLevel);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
function createEl(key, val, firstLevel)
|
||||
function createEl(key, val, map, firstLevel = false)
|
||||
{
|
||||
let type = 'object',
|
||||
isUnenumerable = false;
|
||||
isUnenumerable = false,
|
||||
id;
|
||||
|
||||
if (key === 'erudaProto') key = '__proto__';
|
||||
if (key === 'erudaId') return `<li id="${val}" class="eruda-hidden"></li>`;
|
||||
if (util.startWith(key, 'erudaUnenumerable'))
|
||||
{
|
||||
key = util.trim(key.replace('erudaUnenumerable', ''));
|
||||
isUnenumerable = true;
|
||||
}
|
||||
|
||||
if (util.isArr(val)) type = 'array';
|
||||
if (util.isArr(val))
|
||||
{
|
||||
type = 'array';
|
||||
let lastVal = util.last(val);
|
||||
if (util.isStr(val) && util.startWith(lastVal, 'erudaJson')) id = lastVal;
|
||||
}
|
||||
|
||||
function wrapKey(key)
|
||||
{
|
||||
@@ -90,14 +110,17 @@ function createEl(key, val, firstLevel)
|
||||
}
|
||||
if (util.isObj(val))
|
||||
{
|
||||
if (val.erudaId) id = val.erudaId;
|
||||
let circularId = val.erudaCircular;
|
||||
if (id) map[id] = val;
|
||||
var objAbstract = val['erudaObjAbstract'] || util.upperFirst(type);
|
||||
|
||||
var obj = `<li data-first-level="${firstLevel}">
|
||||
<span class="eruda-expanded ${firstLevel ? '' : 'eruda-collapsed'}"></span>
|
||||
var obj = `<li ${firstLevel ? 'data-first-level="true"' : ''} ${circularId ? 'data-circular="' + circularId + '"' : ''}>
|
||||
<span class="${firstLevel ? '' : 'eruda-expanded eruda-collapsed'}"></span>
|
||||
${wrapKey(key)}
|
||||
<span class="eruda-open">${firstLevel ? '' : objAbstract}</span>
|
||||
<ul class="eruda-${type}" ${firstLevel ? '' : 'style="display:none"'}>`;
|
||||
obj += jsonToHtml(val);
|
||||
obj += jsonToHtml(val, map);
|
||||
|
||||
return obj + `</ul><span class="eruda-close"></span></li>`;
|
||||
}
|
||||
@@ -108,10 +131,6 @@ function createEl(key, val, firstLevel)
|
||||
<span class="eruda-${typeof val}">${encode(val)}</span>
|
||||
</li>`;
|
||||
}
|
||||
if (util.isStr(val) && util.startWith(val, 'erudaJson'))
|
||||
{
|
||||
return `<li id="${val}" class="eruda-hidden"></li>`;
|
||||
}
|
||||
if (util.isStr(val) && util.startWith(val, 'function'))
|
||||
{
|
||||
return `<li>
|
||||
@@ -127,12 +146,6 @@ function createEl(key, val, firstLevel)
|
||||
</li>`;
|
||||
}
|
||||
|
||||
/*if (util.isStr(val) && util.startWith(val, '[circular]'))
|
||||
{
|
||||
let id = util.last(val.split(' '));
|
||||
return `<li class="eruda-circular" class="eruda-hidden" data-id="${id}"></li>`;
|
||||
}*/
|
||||
|
||||
return `<li>
|
||||
${wrapKey(key)}
|
||||
<span class="eruda-${typeof val}">"${encode(val)}"</span>
|
||||
|
||||
@@ -3,7 +3,6 @@ import util from './util'
|
||||
|
||||
// Modified from: https://jsconsole.com/
|
||||
export default function getAbstract(obj, {
|
||||
visited = [],
|
||||
topObj,
|
||||
level = 0,
|
||||
getterVal = false,
|
||||
@@ -17,16 +16,12 @@ export default function getAbstract(obj, {
|
||||
names = [],
|
||||
objEllipsis = '',
|
||||
circular = false,
|
||||
i, len;
|
||||
i;
|
||||
|
||||
topObj = topObj || obj;
|
||||
|
||||
let passOpts = {
|
||||
visited, getterVal,
|
||||
unenumerable,
|
||||
level: level + 1
|
||||
};
|
||||
let doStringify = level === 0;
|
||||
let passOpts = {getterVal, unenumerable, level: level + 1},
|
||||
doStringify = level === 0;
|
||||
|
||||
let keyWrapper = '<span style="color: #a71d5d;">',
|
||||
fnWrapper = '<span style="color: #a71d5d;">',
|
||||
@@ -67,6 +62,31 @@ export default function getAbstract(obj, {
|
||||
|
||||
return strWrapper + strEscape(`"${str}"`) + wrapperEnd;
|
||||
}
|
||||
|
||||
function objIteratee(name)
|
||||
{
|
||||
if (i > keyNum)
|
||||
{
|
||||
objEllipsis = '...';
|
||||
return;
|
||||
}
|
||||
let key = wrapKey(util.escapeJsonStr(name));
|
||||
|
||||
if (!getterVal)
|
||||
{
|
||||
let descriptor = Object.getOwnPropertyDescriptor(obj, name);
|
||||
if (descriptor.get)
|
||||
{
|
||||
parts.push(`${key}: ${wrapStr('(...)')}`);
|
||||
i++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (typeof topObj[name] === 'function') return;
|
||||
parts.push(`${key}: ${getAbstract(topObj[name], passOpts)}`);
|
||||
i++;
|
||||
}
|
||||
|
||||
try {
|
||||
type = ({}).toString.call(obj);
|
||||
} catch (e)
|
||||
@@ -81,25 +101,14 @@ export default function getAbstract(obj, {
|
||||
isSymbol = (type == '[object Symbol]'),
|
||||
isBool = (type == '[object Boolean]');
|
||||
|
||||
for (i = 0, len = visited.length; i < len; i++)
|
||||
{
|
||||
if (obj === visited[i])
|
||||
{
|
||||
circular = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (circular)
|
||||
{
|
||||
json = wrapStr('[circular]');
|
||||
} else if (isStr)
|
||||
{
|
||||
json = wrapStr(escapeJsonStr(obj));
|
||||
json = wrapStr(util.escapeJsonStr(obj));
|
||||
} else if (isArr)
|
||||
{
|
||||
visited.push(obj);
|
||||
|
||||
if (doStringify)
|
||||
{
|
||||
json = '[';
|
||||
@@ -111,8 +120,6 @@ export default function getAbstract(obj, {
|
||||
}
|
||||
} else if (isObj)
|
||||
{
|
||||
visited.push(obj);
|
||||
|
||||
if (canBeProto(obj))
|
||||
{
|
||||
obj = Object.getPrototypeOf(obj);
|
||||
@@ -123,29 +130,7 @@ export default function getAbstract(obj, {
|
||||
{
|
||||
i = 1;
|
||||
json = '{ ';
|
||||
util.each(names, name =>
|
||||
{
|
||||
if (i > keyNum)
|
||||
{
|
||||
objEllipsis = '...';
|
||||
return;
|
||||
}
|
||||
let key = wrapKey(escapeJsonStr(name));
|
||||
|
||||
if (!getterVal)
|
||||
{
|
||||
let descriptor = Object.getOwnPropertyDescriptor(obj, name);
|
||||
if (descriptor.get)
|
||||
{
|
||||
parts.push(`${key}: ${wrapStr('(...)')}`);
|
||||
i++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (typeof topObj[name] === 'function') return;
|
||||
parts.push(`${key}: ${getAbstract(topObj[name], passOpts)}`);
|
||||
i++;
|
||||
});
|
||||
util.each(names, objIteratee);
|
||||
json += parts.join(', ') + objEllipsis + ' }';
|
||||
} else
|
||||
{
|
||||
@@ -185,7 +170,6 @@ export default function getAbstract(obj, {
|
||||
} else {
|
||||
try
|
||||
{
|
||||
visited.push(obj);
|
||||
if (canBeProto(obj))
|
||||
{
|
||||
obj = Object.getPrototypeOf(obj);
|
||||
@@ -196,29 +180,7 @@ export default function getAbstract(obj, {
|
||||
i = 1;
|
||||
json = '{ ';
|
||||
names = unenumerable ? Object.getOwnPropertyNames(obj) : Object.keys(obj);
|
||||
util.each(names, name =>
|
||||
{
|
||||
if (i > keyNum)
|
||||
{
|
||||
objEllipsis = '...';
|
||||
return;
|
||||
}
|
||||
let key = wrapKey(escapeJsonStr(name));
|
||||
|
||||
if (!getterVal)
|
||||
{
|
||||
let descriptor = Object.getOwnPropertyDescriptor(obj, name);
|
||||
if (descriptor.get)
|
||||
{
|
||||
parts.push(`${key}: ${wrapStr('(...)')}`);
|
||||
i++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (typeof topObj[name] === 'function') return;
|
||||
parts.push(`${key}: ${getAbstract(topObj[name], passOpts)}`);
|
||||
i++;
|
||||
});
|
||||
util.each(names, objIteratee);
|
||||
json += parts.join(', ') + objEllipsis + ' }';
|
||||
} else
|
||||
{
|
||||
@@ -235,10 +197,6 @@ export default function getAbstract(obj, {
|
||||
|
||||
const SPECIAL_VAL = ['(...)', 'undefined', 'Symbol', 'Object'];
|
||||
|
||||
var escapeJsonStr = str => str.replace(/\\/g, '\\\\')
|
||||
.replace(/"/g, '\\"')
|
||||
.replace(/\f|\n|\r|\t/g, '');
|
||||
|
||||
function canBeProto(obj)
|
||||
{
|
||||
let emptyObj = util.isEmpty(Object.getOwnPropertyNames(obj)),
|
||||
|
||||
@@ -2,11 +2,11 @@ import util from './util'
|
||||
|
||||
// Modified from: https://jsconsole.com/
|
||||
export default function stringify(obj, {
|
||||
visited = [],
|
||||
visitor = new Visitor(),
|
||||
topObj,
|
||||
level = 0,
|
||||
circularMarker = false,
|
||||
getterVal = false,
|
||||
specialVal = false,
|
||||
unenumerable = true
|
||||
} = {})
|
||||
{
|
||||
@@ -15,67 +15,19 @@ export default function stringify(obj, {
|
||||
parts = [],
|
||||
names = [],
|
||||
proto,
|
||||
circularId,
|
||||
objAbstract,
|
||||
circularObj,
|
||||
allKeys, keys,
|
||||
id = '',
|
||||
circular = false;
|
||||
id = '';
|
||||
|
||||
topObj = topObj || obj;
|
||||
|
||||
let passOpts = {
|
||||
visited, specialVal, getterVal,
|
||||
unenumerable,
|
||||
level: level + 1
|
||||
},
|
||||
passProtoOpts = {
|
||||
visited, specialVal, getterVal, topObj,
|
||||
unenumerable,
|
||||
level: level + 1
|
||||
};
|
||||
let passOpts = {visitor, getterVal, unenumerable, level: level + 1},
|
||||
passProtoOpts = {visitor, getterVal, topObj, unenumerable, level: level + 1};
|
||||
|
||||
let specialWrapper = '',
|
||||
fnWrapper = '',
|
||||
strEscape = str => str,
|
||||
wrapperEnd = '';
|
||||
let wrapKey = key => `"${key}"`,
|
||||
wrapStr = str => `"${util.toStr(str)}"`;
|
||||
|
||||
let wrapKey = key => '"' + strEscape(key) + '"';
|
||||
|
||||
function visit(value)
|
||||
{
|
||||
let id = util.uniqId('erudaJson');
|
||||
|
||||
visited.push({id, value});
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
function wrapStr(str)
|
||||
{
|
||||
str = util.toStr(str);
|
||||
|
||||
if (specialVal)
|
||||
{
|
||||
str = str.replace(/\\/g, '');
|
||||
if (util.startWith(str, 'function'))
|
||||
{
|
||||
return fnWrapper + 'function' + wrapperEnd + ' ( )';
|
||||
}
|
||||
if (util.contain(SPECIAL_VAL, str) || util.startWith(str, 'Array['))
|
||||
{
|
||||
return specialWrapper + strEscape(str) + wrapperEnd;
|
||||
}
|
||||
if (util.startWith(str, '[circular]'))
|
||||
{
|
||||
return specialWrapper + '[circular]' + wrapperEnd;
|
||||
}
|
||||
if (util.startWith(str, '[object '))
|
||||
{
|
||||
return specialWrapper + strEscape(str.replace(/(\[object )|]/g, '')) + wrapperEnd;
|
||||
}
|
||||
}
|
||||
|
||||
return strEscape(`"${str}"`);
|
||||
}
|
||||
try {
|
||||
type = ({}).toString.call(obj);
|
||||
} catch (e)
|
||||
@@ -91,25 +43,18 @@ export default function stringify(obj, {
|
||||
isSymbol = (type == '[object Symbol]'),
|
||||
isBool = (type == '[object Boolean]');
|
||||
|
||||
for (let i = 0, len = visited.length; i < len; i++)
|
||||
{
|
||||
if (obj === visited[i].value)
|
||||
{
|
||||
circular = true;
|
||||
circularId = visited[i].id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
circularObj = visitor.check(obj);
|
||||
|
||||
if (circular)
|
||||
if (circularObj)
|
||||
{
|
||||
json = wrapStr('[circular]' + ' ' + circularId);
|
||||
json = stringify(circularObj.abstract, {circularMarker: true});
|
||||
} else if (isStr)
|
||||
{
|
||||
json = wrapStr(escapeJsonStr(obj));
|
||||
json = wrapStr(util.escapeJsonStr(obj));
|
||||
} else if (isArr)
|
||||
{
|
||||
id = visit(obj);
|
||||
id = visitor.visit(obj);
|
||||
visitor.updateAbstract(id, [`erudaCircular ${id}`]);
|
||||
|
||||
json = '[';
|
||||
util.each(obj, val => parts.push(`${stringify(val, passOpts)}`));
|
||||
@@ -117,19 +62,23 @@ export default function stringify(obj, {
|
||||
json += parts.join(', ') + ']';
|
||||
} else if (isObj || isFn)
|
||||
{
|
||||
id = visit(obj);
|
||||
id = visitor.visit(obj);
|
||||
|
||||
if (canBeProto(obj))
|
||||
{
|
||||
obj = Object.getPrototypeOf(obj);
|
||||
id = visit(obj);
|
||||
id = visitor.visit(obj);
|
||||
}
|
||||
|
||||
allKeys = Object.getOwnPropertyNames(obj);
|
||||
keys = Object.keys(obj);
|
||||
names = unenumerable ? allKeys : keys;
|
||||
proto = Object.getPrototypeOf(obj);
|
||||
if (proto) proto = `${wrapKey('erudaProto')}: ${stringify(proto, passProtoOpts)}`;
|
||||
if (circularMarker && proto === Object.prototype) proto = null;
|
||||
if (proto)
|
||||
{
|
||||
proto = `${wrapKey('erudaProto')}: ${stringify(proto, passProtoOpts)}`;
|
||||
}
|
||||
names.sort(sortObjName);
|
||||
if (isFn)
|
||||
{
|
||||
@@ -137,29 +86,14 @@ export default function stringify(obj, {
|
||||
names = names.filter(val => ['arguments', 'caller', 'prototype'].indexOf(val) < 0);
|
||||
}
|
||||
json = '{ ';
|
||||
if (isFn) parts.push(`${wrapKey('erudaObjAbstract')}: ${wrapStr(getFnAbstract(obj))}`);
|
||||
parts.push(`"erudaId": "${id}"`);
|
||||
util.each(names, name =>
|
||||
{
|
||||
let unenumerable = !util.contain(keys, name) ? 'erudaUnenumerable' : '',
|
||||
key = wrapKey(unenumerable + ' ' + escapeJsonStr(name)),
|
||||
getKey = wrapKey(unenumerable + ' ' + escapeJsonStr('get ' + name)),
|
||||
setKey = wrapKey(unenumerable + ' ' + escapeJsonStr('set ' + name));
|
||||
|
||||
let descriptor = Object.getOwnPropertyDescriptor(obj, name),
|
||||
hasGetter = descriptor && descriptor.get,
|
||||
hasSetter = descriptor && descriptor.set;
|
||||
if (!getterVal && hasGetter)
|
||||
{
|
||||
parts.push(`${getKey}: ${wrapStr(escapeJsonStr(extractFnHead(descriptor.get)))}`);
|
||||
}
|
||||
if (hasSetter)
|
||||
{
|
||||
parts.push(`${setKey}: ${wrapStr(escapeJsonStr(extractFnHead(descriptor.set)))}`);
|
||||
}
|
||||
if (!getterVal && hasGetter) return;
|
||||
parts.push(`${key}: ${stringify(topObj[name], passOpts)}`);
|
||||
objAbstract = isFn ? getFnAbstract(obj) : type.replace(/(\[object )|]/g, '');
|
||||
visitor.updateAbstract(id, {
|
||||
erudaObjAbstract: objAbstract,
|
||||
erudaCircular: id
|
||||
});
|
||||
parts.push(`${wrapKey('erudaObjAbstract')}: ${wrapStr(objAbstract)}`);
|
||||
if (!circularMarker) parts.push(`"erudaId": "${id}"`);
|
||||
util.each(names, objIteratee);
|
||||
if (proto) parts.push(proto);
|
||||
json += parts.join(', ') + ' }';
|
||||
} else if (isNum)
|
||||
@@ -193,20 +127,26 @@ export default function stringify(obj, {
|
||||
} else {
|
||||
try
|
||||
{
|
||||
id = visit(obj);
|
||||
id = visitor.visit(obj);
|
||||
if (canBeProto(obj))
|
||||
{
|
||||
obj = Object.getPrototypeOf(obj);
|
||||
id = visit(obj);
|
||||
id = visitor.visit(obj);
|
||||
}
|
||||
|
||||
json = '{ ';
|
||||
parts.push(`${wrapKey('erudaObjAbstract')}: "${type.replace(/(\[object )|]/g, '')}"`);
|
||||
parts.push(`"erudaId": "${id}"`);
|
||||
objAbstract = type.replace(/(\[object )|]/g, '');
|
||||
visitor.updateAbstract(id, {
|
||||
erudaObjAbstract: objAbstract,
|
||||
erudaCircular: id
|
||||
});
|
||||
parts.push(`${wrapKey('erudaObjAbstract')}: ${wrapStr(objAbstract)}`);
|
||||
if (!circularMarker) parts.push(`"erudaId": "${id}"`);
|
||||
allKeys = Object.getOwnPropertyNames(obj);
|
||||
keys = Object.keys(obj);
|
||||
names = unenumerable ? allKeys : keys;
|
||||
proto = Object.getPrototypeOf(obj);
|
||||
if (circularMarker && proto === Object.prototype) proto = null;
|
||||
if (proto)
|
||||
{
|
||||
try
|
||||
@@ -214,49 +154,46 @@ export default function stringify(obj, {
|
||||
proto = `${wrapKey('erudaProto')}: ${stringify(proto, passProtoOpts)}`;
|
||||
} catch(e)
|
||||
{
|
||||
proto = `${wrapKey('erudaProto')}: ${wrapStr(escapeJsonStr(e.message))}`;
|
||||
proto = `${wrapKey('erudaProto')}: ${wrapStr(e.message)}`;
|
||||
}
|
||||
}
|
||||
names.sort(sortObjName);
|
||||
util.each(names, name =>
|
||||
{
|
||||
let unenumerable = !util.contain(keys, name) ? 'erudaUnenumerable' : '',
|
||||
key = wrapKey(unenumerable + ' ' + escapeJsonStr(name)),
|
||||
getKey = wrapKey(unenumerable + ' ' + escapeJsonStr('get ' + name)),
|
||||
setKey = wrapKey(unenumerable + ' ' + escapeJsonStr('set ' + name));
|
||||
|
||||
let descriptor = Object.getOwnPropertyDescriptor(obj, name),
|
||||
hasGetter = descriptor && descriptor.get,
|
||||
hasSetter = descriptor && descriptor.set;
|
||||
if (!getterVal && hasGetter)
|
||||
{
|
||||
parts.push(`${getKey}: ${wrapStr(escapeJsonStr(extractFnHead(descriptor.get)))}`);
|
||||
}
|
||||
if (hasSetter)
|
||||
{
|
||||
parts.push(`${setKey}: ${wrapStr(escapeJsonStr(extractFnHead(descriptor.set)))}`);
|
||||
}
|
||||
if (!getterVal && hasGetter) return;
|
||||
parts.push(`${key}: ${stringify(topObj[name], passOpts)}`);
|
||||
});
|
||||
util.each(names, objIteratee);
|
||||
if (proto) parts.push(proto);
|
||||
json += parts.join(', ') + ' }';
|
||||
} catch (e)
|
||||
{
|
||||
json = wrapStr(e.message);
|
||||
// json = wrapStr(obj);
|
||||
json = wrapStr(obj);
|
||||
}
|
||||
}
|
||||
|
||||
function objIteratee(name)
|
||||
{
|
||||
let unenumerable = !util.contain(keys, name) ? 'erudaUnenumerable ' : '',
|
||||
key = wrapKey(unenumerable + util.escapeJsonStr(name)),
|
||||
getKey = wrapKey(unenumerable + util.escapeJsonStr('get ' + name)),
|
||||
setKey = wrapKey(unenumerable + util.escapeJsonStr('set ' + name));
|
||||
|
||||
let descriptor = Object.getOwnPropertyDescriptor(obj, name),
|
||||
hasGetter = descriptor && descriptor.get,
|
||||
hasSetter = descriptor && descriptor.set;
|
||||
|
||||
if (!getterVal && hasGetter)
|
||||
{
|
||||
parts.push(`${getKey}: ${wrapStr(util.escapeJsonStr(extractFnHead(descriptor.get)))}`);
|
||||
} else
|
||||
{
|
||||
parts.push(`${key}: ${stringify(topObj[name], passOpts)}`);
|
||||
}
|
||||
if (hasSetter)
|
||||
{
|
||||
parts.push(`${setKey}: ${wrapStr(util.escapeJsonStr(extractFnHead(descriptor.set)))}`);
|
||||
}
|
||||
}
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
const SPECIAL_VAL = ['(...)', 'undefined', 'Symbol', 'Object'];
|
||||
|
||||
var escapeJsonStr = str => str.replace(/\\/g, '\\\\')
|
||||
.replace(/"/g, '\\"')
|
||||
.replace(/\f|\n|\r|\t/g, '');
|
||||
|
||||
// $, upperCase, lowerCase, _
|
||||
var sortObjName = (a, b) =>
|
||||
{
|
||||
@@ -311,7 +248,7 @@ function getFnAbstract(fn)
|
||||
let fnStr = fn.toString();
|
||||
if (fnStr.length > 500) fnStr = fnStr.slice(0, 500) + '...';
|
||||
|
||||
return escapeJsonStr(extractFnHead(fnStr).replace('function', ''));
|
||||
return util.escapeJsonStr(extractFnHead(fnStr).replace('function', ''));
|
||||
}
|
||||
|
||||
function canBeProto(obj)
|
||||
@@ -322,3 +259,39 @@ function canBeProto(obj)
|
||||
return emptyObj && proto && proto !== Object.prototype;
|
||||
}
|
||||
|
||||
class Visitor
|
||||
{
|
||||
constructor()
|
||||
{
|
||||
this._visited = [];
|
||||
this._map = {};
|
||||
}
|
||||
visit(val)
|
||||
{
|
||||
let id = util.uniqId('erudaJson');
|
||||
|
||||
this._visited.push({id, val, abstract: {}});
|
||||
this._map[id] = util.last(this._visited);
|
||||
|
||||
return id;
|
||||
}
|
||||
check(val)
|
||||
{
|
||||
let visited = this._visited;
|
||||
|
||||
for (let i = 0, len = visited.length; i < len; i++)
|
||||
{
|
||||
if (val === visited[i].val) return visited[i];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
update(id, data)
|
||||
{
|
||||
util.extend(this._map[id], data);
|
||||
}
|
||||
updateAbstract(id, abstract)
|
||||
{
|
||||
this.update(id, {abstract});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -506,6 +506,20 @@ module.exports = (function ()
|
||||
return exports;
|
||||
})();
|
||||
|
||||
/* ------------------------------ escapeJsonStr ------------------------------ */
|
||||
|
||||
var escapeJsonStr = _.escapeJsonStr = (function ()
|
||||
{
|
||||
function exports(str)
|
||||
{
|
||||
return str.replace(/\\/g, '\\\\')
|
||||
.replace(/"/g, '\\"')
|
||||
.replace(/\f|\n|\r|\t/g, '');
|
||||
}
|
||||
|
||||
return exports;
|
||||
})();
|
||||
|
||||
/* ------------------------------ escapeRegExp ------------------------------ */
|
||||
|
||||
var escapeRegExp = _.escapeRegExp = (function ()
|
||||
|
||||
Reference in New Issue
Block a user