export function initStrace() { instrumentAll(Element.prototype); instrumentAll(Document.prototype); instrumentAll(Node.prototype); instrumentAll(EventTarget.prototype); } const counts = new Map; counts.total = 0; let timer = null; function log(ctorName, kind, key) { counts.total += 1; const entry = `${kind} ${ctorName}#${key}` const count = counts.get(entry); if (count === undefined) { counts.set(entry, 1); } else { counts.set(entry, count + 1); } if (timer !== null) { clearTimeout(timer); } timer = setTimeout(dumpAndReset, 100); } function dumpAndReset() { const data = [...counts] .sort((a, b) => b[1] - a[1]) .map(a => ({ "DOM Method": a[0], "Count": a[1] })); data.push({ "DOM Method": "", "Count": counts.total }); console.table(data, ["DOM Method", "Count"]); counts.clear(); counts.total = 0; } function instrument(proto, key, desc) { const ctorName = proto.constructor.name; if (typeof desc.value == "function") { const f = desc.value; desc.value = function (...args) { log(ctorName, "call", key); return f.apply(this, args); }; } if (typeof desc.get == "function") { const get = desc.get; desc.get = function (...args) { log(ctorName, "get", key); return get.apply(this, args); }; } if (typeof desc.set == "function") { const set = desc.set; desc.set = function (...args) { log(ctorName, "set", key); return set.apply(this, args); }; } Object.defineProperty(proto, key, desc); } function instrumentAll(proto) { for (const key of Object.keys(proto)) { const desc = Object.getOwnPropertyDescriptor(proto, key); if (desc.configurable) { instrument(proto, key, desc); } } }