UNPKG

@observablehq/inspector

Version:

[![Node CI](https://github.com/observablehq/inspector/workflows/Node%20CI/badge.svg)](https://github.com/observablehq/inspector/actions?workflow=Node+CI)

223 lines (200 loc) 6.47 kB
import dispatch from "./dispatch.js"; import inspectName from "./inspectName.js"; import {isarray, isindex} from "./array.js"; import inspectCollapsed from "./collapsed.js"; import formatSymbol from "./formatSymbol.js"; import {inspect, replace} from "./inspect.js"; import {isown, symbolsof, tagof, valueof} from "./object.js"; import {immutableName} from "./immutable.js"; const {getPrototypeOf, getOwnPropertyDescriptors} = Object; const objectPrototype = getPrototypeOf({}); export default function inspectExpanded(object, _, name, proto) { let arrayish = isarray(object); let tag, fields, next, n; if (object instanceof Map) { if (object instanceof object.constructor) { tag = `Map(${object.size})`; fields = iterateMap; } else { // avoid incompatible receiver error for prototype tag = "Map()"; fields = iterateObject; } } else if (object instanceof Set) { if (object instanceof object.constructor) { tag = `Set(${object.size})`; fields = iterateSet; } else { // avoid incompatible receiver error for prototype tag = "Set()"; fields = iterateObject; } } else if (arrayish) { tag = `${object.constructor.name}(${object.length})`; fields = iterateArray; } else if ((n = immutableName(object))) { tag = `Immutable.${n.name}${n.name === "Record" ? "" : `(${object.size})`}`; arrayish = n.arrayish; fields = n.arrayish ? iterateImArray : n.setish ? iterateImSet : iterateImObject; } else if (proto) { tag = tagof(object); fields = iterateProto; } else { tag = tagof(object); fields = iterateObject; } const span = document.createElement("span"); span.className = "observablehq--expanded"; if (name) { span.appendChild(inspectName(name)); } const a = span.appendChild(document.createElement("a")); a.innerHTML = `<svg width=8 height=8 class='observablehq--caret'> <path d='M4 7L0 1h8z' fill='currentColor' /> </svg>`; a.appendChild(document.createTextNode(`${tag}${arrayish ? " [" : " {"}`)); a.addEventListener("mouseup", function(event) { event.stopPropagation(); replace(span, inspectCollapsed(object, null, name, proto)); }); fields = fields(object); for (let i = 0; !(next = fields.next()).done && i < 20; ++i) { span.appendChild(next.value); } if (!next.done) { const a = span.appendChild(document.createElement("a")); a.className = "observablehq--field"; a.style.display = "block"; a.appendChild(document.createTextNode(` … more`)); a.addEventListener("mouseup", function(event) { event.stopPropagation(); span.insertBefore(next.value, span.lastChild.previousSibling); for (let i = 0; !(next = fields.next()).done && i < 19; ++i) { span.insertBefore(next.value, span.lastChild.previousSibling); } if (next.done) span.removeChild(span.lastChild.previousSibling); dispatch(span, "load"); }); } span.appendChild(document.createTextNode(arrayish ? "]" : "}")); return span; } function* iterateMap(map) { for (const [key, value] of map) { yield formatMapField(key, value); } yield* iterateObject(map); } function* iterateSet(set) { for (const value of set) { yield formatSetField(value); } yield* iterateObject(set); } function* iterateImSet(set) { for (const value of set) { yield formatSetField(value); } } function* iterateArray(array) { for (let i = 0, n = array.length; i < n; ++i) { if (i in array) { yield formatField(i, valueof(array, i), "observablehq--index"); } } for (const key in array) { if (!isindex(key) && isown(array, key)) { yield formatField(key, valueof(array, key), "observablehq--key"); } } for (const symbol of symbolsof(array)) { yield formatField( formatSymbol(symbol), valueof(array, symbol), "observablehq--symbol" ); } } function* iterateImArray(array) { let i1 = 0; for (const n = array.size; i1 < n; ++i1) { yield formatField(i1, array.get(i1), true); } } function* iterateProto(object) { for (const key in getOwnPropertyDescriptors(object)) { yield formatField(key, valueof(object, key), "observablehq--key"); } for (const symbol of symbolsof(object)) { yield formatField( formatSymbol(symbol), valueof(object, symbol), "observablehq--symbol" ); } const proto = getPrototypeOf(object); if (proto && proto !== objectPrototype) { yield formatPrototype(proto); } } function* iterateObject(object) { for (const key in object) { if (isown(object, key)) { yield formatField(key, valueof(object, key), "observablehq--key"); } } for (const symbol of symbolsof(object)) { yield formatField( formatSymbol(symbol), valueof(object, symbol), "observablehq--symbol" ); } const proto = getPrototypeOf(object); if (proto && proto !== objectPrototype) { yield formatPrototype(proto); } } function* iterateImObject(object) { for (const [key, value] of object) { yield formatField(key, value, "observablehq--key"); } } function formatPrototype(value) { const item = document.createElement("div"); const span = item.appendChild(document.createElement("span")); item.className = "observablehq--field"; span.className = "observablehq--prototype-key"; span.textContent = ` <prototype>`; item.appendChild(document.createTextNode(": ")); item.appendChild(inspect(value, undefined, undefined, undefined, true)); return item; } function formatField(key, value, className) { const item = document.createElement("div"); const span = item.appendChild(document.createElement("span")); item.className = "observablehq--field"; span.className = className; span.textContent = ` ${key}`; item.appendChild(document.createTextNode(": ")); item.appendChild(inspect(value)); return item; } function formatMapField(key, value) { const item = document.createElement("div"); item.className = "observablehq--field"; item.appendChild(document.createTextNode(" ")); item.appendChild(inspect(key)); item.appendChild(document.createTextNode(" => ")); item.appendChild(inspect(value)); return item; } function formatSetField(value) { const item = document.createElement("div"); item.className = "observablehq--field"; item.appendChild(document.createTextNode(" ")); item.appendChild(inspect(value)); return item; }