diff --git a/doc/TOOL_API.md b/doc/TOOL_API.md
index ae390a0..165d792 100644
--- a/doc/TOOL_API.md
+++ b/doc/TOOL_API.md
@@ -127,7 +127,7 @@ LocalStorage, sessionStorage, cookies, scripts, styleSheets and images.
## Sources
-View json, html, js, and css.
+View object, html, js, and css.
### Config
diff --git a/src/Console/Log.js b/src/Console/Log.js
index a81efc8..b82c965 100644
--- a/src/Console/Log.js
+++ b/src/Console/Log.js
@@ -555,10 +555,10 @@ function formatEl(val) {
)}`
}
-const regUrl = /(^|[\s\n]|<[A-Za-z]*\/?>)((?:https?|ftp):\/\/[-A-Z0-9+\u0026\u2019@#/%?=()~_|!:,.;]*[-A-Z0-9+\u0026@#/%=~()_|])/gi
+const regUrl = /((?:https?|ftp):\/\/[-A-Z0-9+\u0026\u2019@#/%?=()~_|!:,.;]*[-A-Z0-9+\u0026@#/%=~()_|])/gi
const recognizeUrl = str =>
- str.replace(regUrl, '$2')
+ str.replace(regUrl, '$1')
function getFrom() {
const e = new Error()
diff --git a/src/Elements/Elements.js b/src/Elements/Elements.js
index e3cf973..8ade06d 100644
--- a/src/Elements/Elements.js
+++ b/src/Elements/Elements.js
@@ -21,7 +21,6 @@ import {
pxToNum,
isNaN,
isNum,
- stringifyAll,
nextTick,
Emitter
} from '../lib/util'
@@ -180,23 +179,10 @@ export default class Elements extends Tool {
}
})
.on('click', '.eruda-breadcrumb', () => {
- let data = this._elData
-
- if (!data) {
- data = stringifyAll(this._curEl, {
- unenumerable: true,
- symbol: true,
- accessGetter: true,
- timeout: 1000
- })
- data = JSON.parse(data)
- }
const sources = container.get('sources')
- this._elData = data
-
if (sources) {
- sources.set('json', data)
+ sources.set('object', this._curEl)
container.showTool('sources')
}
})
@@ -262,7 +248,6 @@ export default class Elements extends Tool {
}
_setEl(el) {
this._curEl = el
- this._elData = null
this._curCssStore = new CssStore(el)
this._highlight.setEl(el)
this._rmDefComputedStyle = true
diff --git a/src/Network/Network.js b/src/Network/Network.js
index 32a54dc..0a23d1f 100644
--- a/src/Network/Network.js
+++ b/src/Network/Network.js
@@ -187,7 +187,7 @@ export default class Network extends Tool {
case 'javascript':
return showSources('js', resTxt)
case 'json':
- return showSources('json', resTxt)
+ return showSources('object', resTxt)
}
switch (data.type) {
case 'image':
diff --git a/src/Resources/Resources.js b/src/Resources/Resources.js
index a6263c8..171098a 100644
--- a/src/Resources/Resources.js
+++ b/src/Resources/Resources.js
@@ -279,7 +279,7 @@ export default class Resources extends Tool {
: sessionStorage.getItem(key)
try {
- showSources('json', JSON.parse(val))
+ showSources('object', JSON.parse(val))
} catch (e) {
showSources('raw', val)
}
diff --git a/src/Sources/Sources.js b/src/Sources/Sources.js
index 6252023..abb4696 100644
--- a/src/Sources/Sources.js
+++ b/src/Sources/Sources.js
@@ -1,6 +1,6 @@
import Tool from '../DevTools/Tool'
import beautify from 'js-beautify'
-import JsonViewer from '../lib/JsonViewer'
+import ObjViewer from '../lib/ObjViewer'
import Settings from '../Settings/Settings'
import { ajax, escape, trim, isStr, highlight } from '../lib/util'
import evalCss from '../lib/evalCss'
@@ -109,7 +109,7 @@ export default class Sources extends Tool {
_loadTpl() {
this._codeTpl = require('./code.hbs')
this._imgTpl = require('./image.hbs')
- this._jsonTpl = require('./json.hbs')
+ this._objTpl = require('./object.hbs')
this._rawTpl = require('./raw.hbs')
this._iframeTpl = require('./iframe.hbs')
}
@@ -164,8 +164,8 @@ export default class Sources extends Tool {
return this._renderCode()
case 'img':
return this._renderImg()
- case 'json':
- return this._renderJson()
+ case 'object':
+ return this._renderObj()
case 'raw':
return this._renderRaw()
case 'iframe':
@@ -225,9 +225,9 @@ export default class Sources extends Tool {
})
)
}
- _renderJson() {
- // Using cache will keep binding json events to the same elements.
- this._renderHtml(this._jsonTpl(), false)
+ _renderObj() {
+ // Using cache will keep binding events to the same elements.
+ this._renderHtml(this._objTpl(), false)
let val = this._data.val
@@ -238,7 +238,10 @@ export default class Sources extends Tool {
/* eslint-disable no-empty */
} catch (e) {}
- new JsonViewer(val, this._$el.find('.eruda-json'))
+ new ObjViewer(val, this._$el.find('.eruda-json'), {
+ showUnenumerable: true,
+ showGetterVal: true
+ })
}
_renderRaw() {
this._renderHtml(this._rawTpl({ val: this._data.val }))
diff --git a/src/Sources/json.hbs b/src/Sources/object.hbs
similarity index 100%
rename from src/Sources/json.hbs
rename to src/Sources/object.hbs
diff --git a/src/lib/JsonViewer.js b/src/lib/JsonViewer.js
index e4d26cb..a75e31e 100644
--- a/src/lib/JsonViewer.js
+++ b/src/lib/JsonViewer.js
@@ -5,8 +5,8 @@ import {
uniqId,
upperFirst,
toNum,
- escape,
toStr,
+ escape,
chunk,
each,
isNaN,
@@ -275,6 +275,8 @@ export const encode = str => {
// $, upperCase, lowerCase, _
export function sortObjName(a, b) {
+ a = toStr(a)
+ b = toStr(b)
const numA = toNum(a)
const numB = toNum(b)
if (!isNaN(numA) && !isNaN(numB)) {
diff --git a/src/lib/ObjViewer.js b/src/lib/ObjViewer.js
index a273480..8d7a573 100644
--- a/src/lib/ObjViewer.js
+++ b/src/lib/ObjViewer.js
@@ -1,4 +1,5 @@
import {
+ extend,
Emitter,
getProto,
isNum,
@@ -45,6 +46,12 @@ export default class ObjViewer extends Emitter {
this._bindEvent()
}
_objToHtml(data, firstLevel) {
+ let self = data
+ const visitedObj = this._visitor.get(data)
+ if (visitedObj && visitedObj.self) {
+ self = visitedObj.self
+ }
+
let ret = ''
const types = ['enumerable']
@@ -86,15 +93,40 @@ export default class ObjViewer extends Emitter {
for (let i = 0, len = typeKeys.length; i < len; i++) {
const key = typeKeys[i]
let val = ''
- try {
- val = data[key]
- if (isPromise(val)) {
- val.catch(() => {})
+ const descriptor = Object.getOwnPropertyDescriptor(data, key)
+ const hasGetter = descriptor && descriptor.get
+ const hasSetter = descriptor && descriptor.set
+ if (hasGetter && !this._showGetterVal) {
+ val = '(...)'
+ } else {
+ try {
+ val = self[key]
+ if (isPromise(val)) {
+ val.catch(() => {})
+ }
+ } catch (e) {
+ val = e.message
}
- } catch (e) {
- val = e.message
}
- ret += this._createEl(key, val, type, firstLevel)
+ ret += this._createEl(key, data, val, type, firstLevel)
+ if (hasGetter) {
+ ret += this._createEl(
+ `get ${key}`,
+ data,
+ descriptor.get,
+ type,
+ firstLevel
+ )
+ }
+ if (hasSetter) {
+ ret += this._createEl(
+ `set ${key}`,
+ data,
+ descriptor.set,
+ type,
+ firstLevel
+ )
+ }
}
})
@@ -103,13 +135,13 @@ export default class ObjViewer extends Emitter {
if (ret === '') {
ret = this._objToHtml(proto)
} else {
- ret += this._createEl('__proto__', proto, 'proto')
+ ret += this._createEl('__proto__', self || data, proto, 'proto')
}
}
return ret
}
- _createEl(key, val, keyType, firstLevel = false) {
+ _createEl(key, self, val, keyType, firstLevel = false) {
const visitor = this._visitor
let t = typeof val
const valType = type(val, false)
@@ -141,7 +173,11 @@ export default class ObjViewer extends Emitter {
if (visitedObj) {
id = visitedObj.id
} else {
- id = visitor.set(val)
+ const extra = {}
+ if (keyType === 'proto') {
+ extra.self = self
+ }
+ id = visitor.set(val, extra)
this._map[id] = val
}
const objAbstract = getObjAbstract(val, valType) || upperFirst(t)
@@ -242,12 +278,13 @@ class Visitor {
this.id = 0
this.visited = []
}
- set(val) {
+ set(val, extra) {
const { visited, id } = this
const obj = {
id,
val
}
+ extend(obj, extra)
visited.push(obj)
this.id++