globalThis.stats = {
__primitiveInstanceId: 0,
__data: globalThis.stats?.__data || {},
resetMetricCounts() {
globalThis.stats.__data = {};
},
getMetricCounts() {
return structuredClone(globalThis.stats.__data);
},
summary() {
let stats = globalThis.stats.getMetricCounts();
for (let [k, v] of Object.entries(stats).sort((a, b) => a[0].localeCompare(b[0]))) {
if (k.includes(' ')) continue;
console.log(`${k}: ${v}`);
}
}
}
function interceptAndLog(klassName, methodName) {
const klass = globalThis[klassName];
if (methodName === 'constructor') {
const instantiationLabel = `new ${klassName}()`;
globalThis[klassName] = class extends klass {
constructor(...args) {
super(...args);
const instanceId = globalThis.stats.__primitiveInstanceId++;
globalThis.stats.__data[instantiationLabel] =
(globalThis.stats.__data[instantiationLabel] || 0) + 1;
this.instanceName = `${klassName}:${instanceId} - ${new Error().stack?.split('\n')[2]}`;
}
};
} else {
const original = klass.prototype[methodName];
const logName = `${klassName}.${methodName}`;
klass.prototype[methodName] = function (...args) {
globalThis.stats.__data[logName] = (globalThis.stats.__data[logName] || 0) + 1;
const { instanceName } = this;
if (!instanceName) {
const instanceId = globalThis.stats.__primitiveInstanceId++;
this.instanceName = `${klassName}.${methodName}:${instanceId} - ${new Error().stack?.split('\n')[2]}`;
}
const instanceLogName = `${logName} (${instanceName})`;
globalThis.stats.__data[instanceLogName] =
(globalThis.stats.__data[instanceLogName] || 0) + 1;
return original.apply(this, args);
};
}
}
interceptAndLog('Set', 'constructor');
interceptAndLog('Set', 'add');
interceptAndLog('Set', 'delete');
interceptAndLog('Set', 'has');
interceptAndLog('Set', 'set');
interceptAndLog('Set', 'get');
interceptAndLog('Map', 'constructor');
interceptAndLog('Map', 'set');
interceptAndLog('Map', 'delete');
interceptAndLog('Map', 'has');
interceptAndLog('Map', 'add');
interceptAndLog('Map', 'get');
interceptAndLog('WeakSet', 'constructor');
interceptAndLog('WeakSet', 'add');
interceptAndLog('WeakSet', 'delete');
interceptAndLog('WeakSet', 'has');
interceptAndLog('WeakSet', 'set');
interceptAndLog('WeakSet', 'get');
interceptAndLog('WeakMap', 'constructor');
interceptAndLog('WeakMap', 'set');
interceptAndLog('WeakMap', 'delete');
interceptAndLog('WeakMap', 'has');
interceptAndLog('WeakMap', 'add');
interceptAndLog('WeakMap', 'get');
code I stole and adapted from warp-drive
Results from: embroider-build/embroider#2339
Repro:
<script>tag in the<head>of your HTML/stats.summary()stats.getMetricCounts()to see some specific paths