mirror of
https://github.com/liriliri/eruda.git
synced 2026-04-01 10:18:35 +08:00
Add: Elements dom object access
This commit is contained in:
167
src/lib/stringify.es6
Normal file
167
src/lib/stringify.es6
Normal file
@@ -0,0 +1,167 @@
|
||||
import util from './util'
|
||||
|
||||
// Modified from: https://jsconsole.com/
|
||||
export default function stringify(obj, visited, topObj, simple)
|
||||
{
|
||||
let json = '',
|
||||
type = '',
|
||||
parts = [],
|
||||
names = [],
|
||||
proto,
|
||||
circular = false;
|
||||
|
||||
visited = visited || [];
|
||||
topObj = topObj || obj;
|
||||
|
||||
try {
|
||||
type = ({}).toString.call(obj);
|
||||
} catch (e)
|
||||
{
|
||||
type = '[object Object]';
|
||||
}
|
||||
|
||||
var isFn = (type == '[object Function]'),
|
||||
isStr = (type == '[object String]'),
|
||||
isArr = (type == '[object Array]'),
|
||||
isObj = (type == '[object Object]'),
|
||||
isNum = (type == '[object Number]'),
|
||||
isSymbol = (type == '[object Symbol]'),
|
||||
isBool = (type == '[object Boolean]');
|
||||
|
||||
for (let i = 0, len = visited.length; i < len; i++)
|
||||
{
|
||||
if (obj === visited[i])
|
||||
{
|
||||
circular = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (circular)
|
||||
{
|
||||
json = '"[circular]"';
|
||||
} else if (isStr)
|
||||
{
|
||||
json = `"${escapeJsonStr(obj)}"`;
|
||||
} else if (isArr)
|
||||
{
|
||||
visited.push(obj);
|
||||
|
||||
json = '[';
|
||||
util.each(obj, val => parts.push(`${stringify(val, visited, null, simple)}`));
|
||||
json += parts.join(', ') + ']';
|
||||
} else if (isObj || isFn)
|
||||
{
|
||||
visited.push(obj);
|
||||
|
||||
names = Object.getOwnPropertyNames(obj);
|
||||
proto = Object.getPrototypeOf(obj);
|
||||
if (proto === Object.prototype || isFn || simple) proto = null;
|
||||
if (proto) proto = `"erudaProto": ${stringify(proto, visited, topObj)}`;
|
||||
names.sort(sortObjName);
|
||||
if (isFn)
|
||||
{
|
||||
// We don't these properties to be display for functions.
|
||||
names = names.filter(val => ['arguments', 'caller', 'name', 'length', 'prototype'].indexOf(val) < 0);
|
||||
}
|
||||
if (names.length === 0 && isFn)
|
||||
{
|
||||
json = `"${escapeJsonStr(obj.toString())}"`;
|
||||
} else
|
||||
{
|
||||
json = '{';
|
||||
if (isFn)
|
||||
{
|
||||
// Function length is restricted to 500 for performance reason.
|
||||
var fnStr = obj.toString();
|
||||
if (fnStr.length > 500) fnStr = fnStr.slice(0, 500) + '...';
|
||||
parts.push(`"erudaObjAbstract": "${escapeJsonStr(fnStr)}"`);
|
||||
}
|
||||
util.each(names, name =>
|
||||
{
|
||||
parts.push(`"${escapeJsonStr(name)}": ${stringify(obj[name], visited, null, simple)}`);
|
||||
});
|
||||
if (proto) parts.push(proto);
|
||||
json += parts.join(', ') + '}';
|
||||
}
|
||||
} else if (isNum)
|
||||
{
|
||||
json = obj + '';
|
||||
if (util.endWith(json, 'Infinity') || json === 'NaN') json = `"${json}"`;
|
||||
} else if (isBool)
|
||||
{
|
||||
json = obj ? 'true' : 'false';
|
||||
} else if (obj === null)
|
||||
{
|
||||
json = 'null';
|
||||
} else if (isSymbol)
|
||||
{
|
||||
json = '"Symbol"';
|
||||
} else if (obj === undefined)
|
||||
{
|
||||
json = '"undefined"';
|
||||
} else if (type === '[object HTMLAllCollection]')
|
||||
{
|
||||
// https://docs.webplatform.org/wiki/dom/HTMLAllCollection
|
||||
// Might cause a performance issue when stringify a dom element.
|
||||
json = '"[object HTMLAllCollection]"';
|
||||
} else
|
||||
{
|
||||
try
|
||||
{
|
||||
visited.push(obj);
|
||||
|
||||
json = '{\n';
|
||||
if (!simple) parts.push(`"erudaObjAbstract": "${type.replace(/(\[object )|]/g, '')}"`);
|
||||
names = Object.getOwnPropertyNames(obj);
|
||||
proto = Object.getPrototypeOf(obj);
|
||||
if (proto === Object.prototype || simple) proto = null;
|
||||
if (proto)
|
||||
{
|
||||
try
|
||||
{
|
||||
proto = `"erudaProto": ${stringify(proto, visited, topObj)}`;
|
||||
} catch(e)
|
||||
{
|
||||
proto = `"erudaProto": "${escapeJsonStr(e.message)}"`;
|
||||
}
|
||||
}
|
||||
names.sort(sortObjName);
|
||||
util.each(names, name =>
|
||||
{
|
||||
let val = topObj[name];
|
||||
|
||||
try
|
||||
{
|
||||
parts.push(`"${escapeJsonStr(name)}": ${stringify(val, visited, null, simple)}`);
|
||||
} catch (e)
|
||||
{
|
||||
parts.push(`"${escapeJsonStr(name)}": "${escapeJsonStr(e.message)}"`);
|
||||
}
|
||||
});
|
||||
if (proto) parts.push(proto);
|
||||
json += parts.join(',\n') + '\n}';
|
||||
} catch (e) {
|
||||
json = `"${obj}"`;
|
||||
}
|
||||
}
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
var escapeJsonStr = str => str.replace(/\\/g, '\\\\')
|
||||
.replace(/"/g, '\\"')
|
||||
.replace(/\f|\n|\r|\t/g, '');
|
||||
|
||||
var sortObjName = (a, b) =>
|
||||
{
|
||||
let codeA = a.charCodeAt(0),
|
||||
codeB = b.charCodeAt(0);
|
||||
|
||||
if (isLetter(codeA) && !isLetter(codeB)) return -1;
|
||||
if (!isLetter(codeA) && isLetter(codeB)) return 1;
|
||||
|
||||
return a > b ? 1 : -1;
|
||||
};
|
||||
|
||||
var isLetter = code => (code > 64 && code < 90) || (code > 96 && code < 123);
|
||||
Reference in New Issue
Block a user