From 8d9b49242a7eb6a417266046348180b37ed53fba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=95=B7?= <3756473+zendive@users.noreply.github.com> Date: Sat, 6 Jul 2024 03:32:53 +0300 Subject: [PATCH 01/53] create trace and traceId in one call --- manifest.json | 2 +- src/api/const.ts | 2 +- src/api/wrappers.ts | 203 ++++++++++-------- src/view/components/ActiveTimers.svelte | 4 +- src/view/components/Callstack.svelte | 11 - src/view/components/EvalMetrics.svelte | 4 +- src/view/components/TimersHistory.svelte | 4 +- src/view/components/Trace.svelte | 11 + ...{CallstackLink.svelte => TraceLink.svelte} | 0 9 files changed, 130 insertions(+), 111 deletions(-) delete mode 100644 src/view/components/Callstack.svelte create mode 100644 src/view/components/Trace.svelte rename src/view/components/{CallstackLink.svelte => TraceLink.svelte} (100%) diff --git a/manifest.json b/manifest.json index c745e3d..b12b877 100644 --- a/manifest.json +++ b/manifest.json @@ -1,5 +1,5 @@ { - "version": "1.0.4", + "version": "1.0.5", "name": "API Monitor", "manifest_version": 3, "description": "Reveal active or passed timeouts, intervals, and eval invocation call stacks. Observe events and properties of video/audio elements", diff --git a/src/api/const.ts b/src/api/const.ts index 0be0240..0fce402 100644 --- a/src/api/const.ts +++ b/src/api/const.ts @@ -111,7 +111,7 @@ export const READY_STATE = [ ]; export const TRACE_ERROR_MESSAGE = 'browser-api-monitor'; -export const REGEX_STACKTRACE_PREFIX = /^.*at /; +export const REGEX_STACKTRACE_PREFIX = /^\s*at /; export const REGEX_STACKTRACE_NAME = /^(.+)\(.*/; export const REGEX_STACKTRACE_LINK = /.*\((.*)\).*/; export const REGEX_STACKTRACE_CLEAN_URL = /(.*):\d+:\d+$/; diff --git a/src/api/wrappers.ts b/src/api/wrappers.ts index 504ce92..9dadbe2 100644 --- a/src/api/wrappers.ts +++ b/src/api/wrappers.ts @@ -15,34 +15,39 @@ import { TAG_EXCEPTION, cloneObjectSafely } from '@/api/clone.ts'; import type { TPanelVisibilityMap } from '@/api/settings.ts'; import { sha256 } from 'js-sha256'; -export type TCallstack = { +export type TTrace = { name: string | 0; link: string; -}[]; +}; +type TCallstack = { + traceId: string; + trace: TTrace[]; +}; export enum ETimeType { TIMEOUT, INTERVAL, } export type TOnlineTimerMetrics = { + traceId: string; + trace: TTrace[]; type: ETimeType; delay: number | undefined; handler: number; - trace: TCallstack; isEval: boolean; rawTrace?: string; // for debugging }; export type TTimerHistory = { traceId: string; + trace: TTrace[]; individualInvocations: number; recentHandler: number | string; handlerDelay: number | undefined | string; - trace: TCallstack; isEval: boolean | undefined; hasError: boolean; }; export type TEvalHistory = { traceId: string; - trace: TCallstack; + trace: TTrace[]; individualInvocations: number; returnedValue: any; code: any; @@ -61,64 +66,6 @@ export type TWrapperMetrics = { type TOnlineTimers = Map; -let selfCallLink = ''; -function createCallstack(e: Error): TCallstack { - const rv: TCallstack = []; - const arr = e.stack?.split('\n') || []; - - if (!selfCallLink) { - const link = arr[1] - .replace(REGEX_STACKTRACE_LINK, '$1') - .replace(REGEX_STACKTRACE_CLEAN_URL, '$1'); - if (link) { - selfCallLink = link; - } - } - - // loop from the end, excluding error name and self trace - for (let n = arr.length - 1; n > 1; n--) { - let v = arr[n]; - - if (v.indexOf(selfCallLink) >= 0) { - continue; - } - - v = v.replace(REGEX_STACKTRACE_PREFIX, ''); - const link = v.replace(REGEX_STACKTRACE_LINK, '$1').trim(); - - if (link.startsWith('')) { - continue; - } - - let name: string | 0 = v.replace(REGEX_STACKTRACE_NAME, '$1').trim(); - - if (name === link) { - name = 0; - } - - rv.push({ name, link }); - } - - if (!rv.length) { - rv.push({ - name: TAG_INVALID_CALLSTACK, - link: `(id: ${crypto.randomUUID()})`, - }); - } - - return rv; -} - -function createTraceId(trace: TCallstack) { - const joinedLinks = trace.map((v) => v.link).join(''); - - if (joinedLinks.length > 64) { - return sha256(joinedLinks); - } - - return joinedLinks; -} - export class Wrapper { onlineTimers: TOnlineTimers = new Map(); setTimeoutHistory: TTimerHistory[] = []; @@ -140,6 +87,7 @@ export class Wrapper { clearInterval: clearInterval, eval: lessEval, }; + static selfCallLink = ''; constructor() {} @@ -147,15 +95,16 @@ export class Wrapper { type: ETimeType, handler: number, delay: number | undefined, - trace: TCallstack, + callstack: TCallstack, isEval: boolean ) { this.onlineTimers.set(handler, { type, handler, delay, - trace, isEval, + traceId: callstack.traceId, + trace: callstack.trace, //rawTrace }); } @@ -182,11 +131,10 @@ export class Wrapper { history: TTimerHistory[], handler: number, delay: number | undefined, - trace: TCallstack, + callstack: TCallstack, isEval: boolean ) { - const traceId = createTraceId(trace); - const existing = history.findLast((v) => v.traceId === traceId); + const existing = history.findLast((v) => v.traceId === callstack.traceId); const hasError = this.#badTimerDelay(delay); let handlerDelay: string | number | undefined = delay; @@ -202,13 +150,13 @@ export class Wrapper { existing.hasError = hasError; } else { history.push({ - traceId, recentHandler: handler, individualInvocations: 1, handlerDelay, - trace, isEval, hasError, + traceId: callstack.traceId, + trace: callstack.trace, }); history.sort((a, b) => (b.handlerDelay || 0) > (a.handlerDelay || 0) ? 1 : -1 @@ -219,10 +167,9 @@ export class Wrapper { updateClearTimersHistory( history: TTimerHistory[], handler: unknown, - trace: TCallstack + callstack: TCallstack ) { - const traceId = createTraceId(trace); - const existing = history.findLast((v) => v.traceId === traceId); + const existing = history.findLast((v) => v.traceId === callstack.traceId); const hasError = this.#badTimerHandler(handler); const onlineTimer = !hasError ? this.onlineTimers.get(handler) @@ -250,13 +197,13 @@ export class Wrapper { existing.hasError = hasError; } else { history.push({ - traceId, recentHandler: handler, individualInvocations: 1, handlerDelay, - trace, isEval: handlerIsEval, hasError, + traceId: callstack.traceId, + trace: callstack.trace, }); history.sort((a, b) => (b.handlerDelay || 0) > (a.handlerDelay || 0) ? 1 : -1 @@ -267,11 +214,12 @@ export class Wrapper { updateEvalHistory( code: string, returnedValue: any, - trace: TCallstack, + callstack: TCallstack, usesLocalScope: boolean ) { - const traceId = createTraceId(trace); - const existing = this.evalHistory.find((v) => v.traceId === traceId); + const existing = this.evalHistory.find( + (v) => v.traceId === callstack.traceId + ); if (existing) { existing.code = cloneObjectSafely(code); @@ -283,9 +231,9 @@ export class Wrapper { individualInvocations: 1, code: cloneObjectSafely(code), returnedValue: cloneObjectSafely(returnedValue), - trace, - traceId, usesLocalScope, + traceId: callstack.traceId, + trace: callstack.trace, }); } } @@ -372,8 +320,12 @@ export class Wrapper { } } - const trace = createCallstack(new Error(TRACE_ERROR_MESSAGE)); - this.updateEvalHistory(code, rv, trace, usesLocalScope); + this.updateEvalHistory( + code, + rv, + Wrapper.createCallstack(new Error(TRACE_ERROR_MESSAGE)), + usesLocalScope + ); if (throwError) { throw throwError; @@ -404,20 +356,25 @@ export class Wrapper { delay, ...args ); - const trace = createCallstack(new Error(TRACE_ERROR_MESSAGE)); + const callstack = Wrapper.createCallstack(new Error(TRACE_ERROR_MESSAGE)); this.callCounter.setTimeout++; - this.timerOnline(ETimeType.TIMEOUT, handler, delay, trace, isEval); + this.timerOnline(ETimeType.TIMEOUT, handler, delay, callstack, isEval); this.updateSetTimersHistory( this.setTimeoutHistory, handler, delay, - trace, + callstack, isEval ); if (isEval) { this.callCounter.eval++; - this.updateEvalHistory(code, '(N/A - via setTimeout)', trace, false); + this.updateEvalHistory( + code, + '(N/A - via setTimeout)', + callstack, + false + ); } return handler; @@ -430,7 +387,7 @@ export class Wrapper { this.updateClearTimersHistory( this.clearTimeoutHistory, handler, - createCallstack(new Error(TRACE_ERROR_MESSAGE)) + Wrapper.createCallstack(new Error(TRACE_ERROR_MESSAGE)) ); if (handler !== undefined) { this.timerOffline(handler); @@ -459,20 +416,25 @@ export class Wrapper { delay, ...args ); - const trace = createCallstack(new Error(TRACE_ERROR_MESSAGE)); + const callstack = Wrapper.createCallstack(new Error(TRACE_ERROR_MESSAGE)); this.callCounter.setInterval++; - this.timerOnline(ETimeType.INTERVAL, handler, delay, trace, isEval); + this.timerOnline(ETimeType.INTERVAL, handler, delay, callstack, isEval); this.updateSetTimersHistory( this.setIntervalHistory, handler, delay, - trace, + callstack, isEval ); if (isEval) { this.callCounter.eval++; - this.updateEvalHistory(code, '(N/A - via setInterval)', trace, false); + this.updateEvalHistory( + code, + '(N/A - via setInterval)', + callstack, + false + ); } return handler; @@ -485,7 +447,7 @@ export class Wrapper { this.updateClearTimersHistory( this.clearIntervalHistory, handler, - createCallstack(new Error(TRACE_ERROR_MESSAGE)) + Wrapper.createCallstack(new Error(TRACE_ERROR_MESSAGE)) ); if (handler !== undefined) { this.timerOffline(handler); @@ -495,4 +457,61 @@ export class Wrapper { this.native.clearInterval(handler); }.bind(this); } + + static createCallstack(e: Error): TCallstack { + const trace: TTrace[] = []; + const stack = e.stack?.split('\n') || []; + let links = ''; + + if (!Wrapper.selfCallLink) { + const link = stack[1] + .replace(REGEX_STACKTRACE_LINK, '$1') + .replace(REGEX_STACKTRACE_CLEAN_URL, '$1'); + if (link) { + Wrapper.selfCallLink = link; + } + } + + // loop from the end, excluding error name and self trace + for (let n = stack.length - 1; n > 1; n--) { + let v = stack[n]; + + if (v.indexOf(Wrapper.selfCallLink) >= 0) { + continue; + } + + v = v.replace(REGEX_STACKTRACE_PREFIX, ''); + const link = v.replace(REGEX_STACKTRACE_LINK, '$1').trim(); + + if (link.startsWith('')) { + continue; + } + + let name: string | 0 = v.replace(REGEX_STACKTRACE_NAME, '$1').trim(); + + if (name === link) { + name = 0; + } + + trace.push({ name, link }); + links += link; + } + + if (!trace.length) { + const link = `(id: ${crypto.randomUUID()})`; + trace.push({ + name: TAG_INVALID_CALLSTACK, + link, + }); + links += link; + } + + let traceId = links; + + if (traceId.length > 64) { + traceId = sha256(traceId); + } + + return { traceId, trace }; + } } diff --git a/src/view/components/ActiveTimers.svelte b/src/view/components/ActiveTimers.svelte index fda6510..7ae63dd 100644 --- a/src/view/components/ActiveTimers.svelte +++ b/src/view/components/ActiveTimers.svelte @@ -1,7 +1,7 @@ - -{#each trace as stack, index (index)} - {#if index > 0} •{/if} - -{/each} diff --git a/src/view/components/EvalMetrics.svelte b/src/view/components/EvalMetrics.svelte index dc0b9c6..5d4b4b3 100644 --- a/src/view/components/EvalMetrics.svelte +++ b/src/view/components/EvalMetrics.svelte @@ -1,6 +1,6 @@ + +{#each trace as stack, index (index)} + {#if index > 0} •{/if} + +{/each} diff --git a/src/view/components/CallstackLink.svelte b/src/view/components/TraceLink.svelte similarity index 100% rename from src/view/components/CallstackLink.svelte rename to src/view/components/TraceLink.svelte From 4df9e8dc42ed8e7c5e8356b024a8b81bb9117cf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=95=B7?= <3756473+zendive@users.noreply.github.com> Date: Sat, 6 Jul 2024 03:40:36 +0300 Subject: [PATCH 02/53] fix: Eval Usages -> Eval History to show history length --- src/view/App.svelte | 5 +---- src/view/components/EvalMetrics.svelte | 5 ++--- src/view/components/InfoBar.svelte | 2 +- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/view/App.svelte b/src/view/App.svelte index 8cadb41..4e0c77e 100644 --- a/src/view/App.svelte +++ b/src/view/App.svelte @@ -102,10 +102,7 @@ {#if msg}
- + diff --git a/src/view/components/EvalMetrics.svelte b/src/view/components/EvalMetrics.svelte index 5d4b4b3..c9c0dc6 100644 --- a/src/view/components/EvalMetrics.svelte +++ b/src/view/components/EvalMetrics.svelte @@ -3,7 +3,6 @@ import Trace from '@/view/components/Trace.svelte'; import type { TEvalHistory } from '@/api/wrappers.ts'; - export let callCount: number = 0; export let metrics: TEvalHistory[] = []; function dynamicValue(value: unknown): string { @@ -20,9 +19,9 @@ {#if metrics.length} - +
Eval History {/each} From d0d5fde6845fdb3f848b5c0bb501f7843aa30a55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=95=B7?= <3756473+zendive@users.noreply.github.com> Date: Mon, 8 Jul 2024 13:41:49 +0300 Subject: [PATCH 04/53] fix test --- jest/tests/wrappers.test.ts | 42 ++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/jest/tests/wrappers.test.ts b/jest/tests/wrappers.test.ts index c60df2c..0d16638 100644 --- a/jest/tests/wrappers.test.ts +++ b/jest/tests/wrappers.test.ts @@ -32,22 +32,22 @@ describe('wrappers', () => { }); test('setTimeoutHistory & clearTimeoutHistory - recorded', () => { - expect(wrapper.setTimeoutHistory.length).toBe(0); - expect(wrapper.clearTimeoutHistory.length).toBe(0); + expect(wrapper.setTimeoutHistory.size).toBe(0); + expect(wrapper.clearTimeoutHistory.size).toBe(0); const handler = setTimeout(() => {}, 123); expect(wrapper.onlineTimers.size).toBe(1); clearTimeout(handler); expect(wrapper.onlineTimers.size).toBe(0); - expect(wrapper.clearTimeoutHistory.length).toBe(1); - expect(wrapper.setTimeoutHistory.length).toBe(1); + expect(wrapper.clearTimeoutHistory.size).toBe(1); + expect(wrapper.setTimeoutHistory.size).toBe(1); }); test('setTimeoutHistory - valid delay', () => { const DELAY = 123; const handler = setTimeout(() => {}, DELAY); - const rec = wrapper.setTimeoutHistory[0]; + const rec = [...wrapper.setTimeoutHistory.values()][0]; expect(rec.individualInvocations).toBe(1); expect(rec.handlerDelay).toBe(DELAY); @@ -61,7 +61,7 @@ describe('wrappers', () => { test('setTimeoutHistory - invalid delay', () => { setTimeout(() => {}, -1); - const rec = wrapper.setTimeoutHistory[0]; + const rec = [...wrapper.setTimeoutHistory.values()][0]; expect(rec.individualInvocations).toBe(1); expect(rec.handlerDelay).toBe(TAG_EXCEPTION('-1')); @@ -72,13 +72,13 @@ describe('wrappers', () => { test('clearTimeoutHistory - valid handler', () => { const handler = setTimeout(() => {}, 1e3); clearTimeout(handler); - const rec = wrapper.clearTimeoutHistory[0]; + const rec = [...wrapper.clearTimeoutHistory.values()][0]; expect(rec.handlerDelay).toBe(1e3); }); test('clearTimeoutHistory - non existent handler', () => { clearTimeout(1000); - const rec = wrapper.clearTimeoutHistory[0]; + const rec = [...wrapper.clearTimeoutHistory.values()][0]; expect(rec.handlerDelay).toBe('N/A'); expect(rec.hasError).toBe(false); @@ -87,29 +87,29 @@ describe('wrappers', () => { test('clearTimeoutHistory - invalid handler', () => { clearTimeout(0); - const rec = wrapper.clearTimeoutHistory[0]; + const rec = [...wrapper.clearTimeoutHistory.values()][0]; expect(rec.handlerDelay).toBe('N/A'); expect(rec.hasError).toBe(true); }); test('setIntervalHistory & clearIntervalHistory - recorded', () => { - expect(wrapper.setIntervalHistory.length).toBe(0); - expect(wrapper.clearIntervalHistory.length).toBe(0); + expect(wrapper.setIntervalHistory.size).toBe(0); + expect(wrapper.clearIntervalHistory.size).toBe(0); const handler = setInterval(() => {}, 123); expect(wrapper.onlineTimers.size).toBe(1); clearInterval(handler); expect(wrapper.onlineTimers.size).toBe(0); - expect(wrapper.clearIntervalHistory.length).toBe(1); - expect(wrapper.setIntervalHistory.length).toBe(1); + expect(wrapper.clearIntervalHistory.size).toBe(1); + expect(wrapper.setIntervalHistory.size).toBe(1); }); test('setIntervalHistory - valid delay', () => { const DELAY = 123; const handler = setInterval(() => {}, DELAY); - const rec = wrapper.setIntervalHistory[0]; + const rec = [...wrapper.setIntervalHistory.values()][0]; expect(rec.individualInvocations).toBe(1); expect(rec.handlerDelay).toBe(DELAY); @@ -123,7 +123,7 @@ describe('wrappers', () => { test('setIntervalHistory - invalid delay', () => { const handler = setInterval(() => {}, -1); - const rec = wrapper.setIntervalHistory[0]; + const rec = [...wrapper.setIntervalHistory.values()][0]; expect(rec.individualInvocations).toBe(1); expect(rec.handlerDelay).toBe(TAG_EXCEPTION('-1')); @@ -136,7 +136,7 @@ describe('wrappers', () => { test('clearIntervalHistory - valid handler', () => { const handler = setInterval(() => {}, 1e3); clearInterval(handler); - const rec = wrapper.clearIntervalHistory[0]; + const rec = [...wrapper.clearIntervalHistory.values()][0]; expect(rec.handlerDelay).toBe(1e3); }); @@ -144,7 +144,7 @@ describe('wrappers', () => { test('clearIntervalHistory - non existent handler', () => { clearInterval(1000); - const rec = wrapper.clearIntervalHistory[0]; + const rec = [...wrapper.clearIntervalHistory.values()][0]; expect(rec.handlerDelay).toBe('N/A'); expect(rec.hasError).toBe(false); }); @@ -152,7 +152,7 @@ describe('wrappers', () => { test('clearIntervalHistory - invalid handler', () => { clearInterval(0); - const rec = wrapper.clearIntervalHistory[0]; + const rec = [...wrapper.clearIntervalHistory.values()][0]; expect(rec.handlerDelay).toBe('N/A'); expect(rec.hasError).toBe(true); }); @@ -165,9 +165,9 @@ describe('wrappers', () => { for (let i = 0, I = NUMBER_OF_INVOCATIONS; i < I; i++) { window.eval(CODE); } - expect(wrapper.evalHistory.length).toBe(1); + expect(wrapper.evalHistory.size).toBe(1); - const rec = wrapper.evalHistory[0]; + const rec = [...wrapper.evalHistory.values()][0]; expect(rec.individualInvocations).toBe(NUMBER_OF_INVOCATIONS); expect(rec.usesLocalScope).toBe(false); expect(rec.code).toBe(CODE); @@ -180,7 +180,7 @@ describe('wrappers', () => { const local_variable = 0; window.eval('(local_variable++)'); - const rec = wrapper.evalHistory[0]; + const rec = [...wrapper.evalHistory.values()][0]; expect(rec.individualInvocations).toBe(1); expect(local_variable).toBe(0); expect(rec.usesLocalScope).toBe(true); From 16b16381bdf53c8339f679d47ec9ac3734d85ca3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=95=B7?= <3756473+zendive@users.noreply.github.com> Date: Thu, 11 Jul 2024 07:47:23 +0300 Subject: [PATCH 05/53] play catch noop --- src/api/mediaMonitor.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/mediaMonitor.ts b/src/api/mediaMonitor.ts index 2b00930..e1e187a 100644 --- a/src/api/mediaMonitor.ts +++ b/src/api/mediaMonitor.ts @@ -110,7 +110,7 @@ export function doMediaCommand( } else if (cmd === 'pause') { mediaModel.el.pause(); } else if (cmd === 'play') { - mediaModel.el.play(); + mediaModel.el.play().catch(() => {}); } else if (cmd === 'frame-backward') { mediaModel.el.currentTime -= FRAME_1of60; } else if (cmd === 'frame-forward') { From 9dc25d81250436509d4f7b7dd5831eac8dc403e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=95=B7?= <3756473+zendive@users.noreply.github.com> Date: Thu, 11 Jul 2024 07:47:48 +0300 Subject: [PATCH 06/53] extract method `#initSelfTrace` --- src/api/const.ts | 1 + src/api/wrappers.ts | 64 ++++++++++++++++++++++----------------------- 2 files changed, 32 insertions(+), 33 deletions(-) diff --git a/src/api/const.ts b/src/api/const.ts index 711262c..57e012d 100644 --- a/src/api/const.ts +++ b/src/api/const.ts @@ -118,3 +118,4 @@ export const REGEX_STACKTRACE_CLEAN_URL = new RegExp(/(.*):\d+:\d+$/); export const REGEX_STACKTRACE_LINE_NUMBER = new RegExp(/.*:(\d+):\d+$/); export const REGEX_STACKTRACE_COLUMN_NUMBER = new RegExp(/.*:\d+:(\d+)$/); export const FRAME_1of60 = 1 / 60; +export const SHA256_HEX_STRING_LENGTH = 64; diff --git a/src/api/wrappers.ts b/src/api/wrappers.ts index 0784e71..06868cb 100644 --- a/src/api/wrappers.ts +++ b/src/api/wrappers.ts @@ -10,6 +10,7 @@ import { REGEX_STACKTRACE_SPLIT, REGEX_STACKTRACE_CLEAN_URL, TAG_INVALID_CALLSTACK, + SHA256_HEX_STRING_LENGTH, } from '@/api/const.ts'; import { TAG_EXCEPTION, cloneObjectSafely } from '@/api/clone.ts'; import type { TPanelVisibilityMap } from '@/api/settings.ts'; @@ -86,6 +87,29 @@ export class Wrapper { }; selfTraceLink = ''; + constructor() { + this.#initSelfTrace(); + } + + #initSelfTrace() { + const error = new Error(TRACE_ERROR_MESSAGE); + this.selfTraceLink = (error?.stack || '') + .split(REGEX_STACKTRACE_SPLIT)[1] + .replace(REGEX_STACKTRACE_LINK, '$1') + .replace(REGEX_STACKTRACE_CLEAN_URL, '$1'); + } + + #badTimerHandler(handler: unknown) { + return !Number.isFinite(handler) || handler < 1; + } + + #badTimerDelay(delay: unknown) { + return ( + (delay !== undefined && !Number.isFinite(delay)) || + (Number.isFinite(delay) && delay < 0) + ); + } + timerOnline( type: ETimeType, handler: number, @@ -110,17 +134,6 @@ export class Wrapper { this.onlineTimers.delete(handler); } - #badTimerHandler(handler: unknown) { - return !Number.isFinite(handler) || handler < 1; - } - - #badTimerDelay(delay: unknown) { - return ( - (delay !== undefined && !Number.isFinite(delay)) || - (Number.isFinite(delay) && delay < 0) - ); - } - updateSetTimersHistory( history: Map, handler: number, @@ -444,19 +457,10 @@ export class Wrapper { }.bind(this); } - createCallstack(e: Error): TCallstack { + createCallstack(e: Error, fn: () => void): TCallstack { const trace: TTrace[] = []; const stack = e.stack?.split(REGEX_STACKTRACE_SPLIT) || []; - let links = ''; - - if (!this.selfTraceLink) { - const link = stack[1] - .replace(REGEX_STACKTRACE_LINK, '$1') - .replace(REGEX_STACKTRACE_CLEAN_URL, '$1'); - if (link) { - this.selfTraceLink = link; - } - } + let traceId = ''; // loop from the end, excluding error name and self trace for (let n = stack.length - 1; n > 1; n--) { @@ -472,14 +476,10 @@ export class Wrapper { continue; } - let name: string | 0 = v.replace(REGEX_STACKTRACE_NAME, '$1').trim(); + let name = v.replace(REGEX_STACKTRACE_NAME, '$1').trim(); - if (name === link) { - name = 0; - } - - trace.push({ name, link }); - links += link; + trace.push({ name: name === link ? 0 : name, link }); + traceId += link; } if (!trace.length) { @@ -488,12 +488,10 @@ export class Wrapper { name: TAG_INVALID_CALLSTACK, link, }); - links += link; + traceId = link; } - let traceId = links; - - if (traceId.length > 64) { + if (traceId.length > SHA256_HEX_STRING_LENGTH) { traceId = sha256(traceId); } From 5ce719129262052a525463aa300e4ebc35cb652a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=95=B7?= <3756473+zendive@users.noreply.github.com> Date: Thu, 11 Jul 2024 17:38:20 +0300 Subject: [PATCH 07/53] trace function name if no callstack - example: (function testThis(){ function timedEvent() {const e = new Error('trace'); console.log(e.stack.split('\n'))}; window.addEventListener('click', setTimeout.bind(window, timedEvent, 0)) })(); --- src/api/const.ts | 2 +- src/api/wrappers.ts | 34 +++++++++++++++++++++------- src/view/components/Trace.svelte | 2 +- src/view/components/TraceLink.svelte | 27 +++++++++++----------- 4 files changed, 42 insertions(+), 23 deletions(-) diff --git a/src/api/const.ts b/src/api/const.ts index 57e012d..a0d0cd8 100644 --- a/src/api/const.ts +++ b/src/api/const.ts @@ -11,7 +11,7 @@ export const setInterval = window.setInterval.bind(window); export const clearInterval = window.clearInterval.bind(window); // https://rollupjs.org/troubleshooting/#avoiding-eval export const lessEval = window.eval.bind(window); -export const TAG_INVALID_CALLSTACK = 'N/A'; +export const TAG_INVALID_CALLSTACK_LINK = '⟪N/A⟫'; export const MEDIA_ELEMENT_EVENTS = [ 'abort', diff --git a/src/api/wrappers.ts b/src/api/wrappers.ts index 06868cb..636711c 100644 --- a/src/api/wrappers.ts +++ b/src/api/wrappers.ts @@ -9,7 +9,7 @@ import { TRACE_ERROR_MESSAGE, REGEX_STACKTRACE_SPLIT, REGEX_STACKTRACE_CLEAN_URL, - TAG_INVALID_CALLSTACK, + TAG_INVALID_CALLSTACK_LINK, SHA256_HEX_STRING_LENGTH, } from '@/api/const.ts'; import { TAG_EXCEPTION, cloneObjectSafely } from '@/api/clone.ts'; @@ -355,7 +355,10 @@ export class Wrapper { delay, ...args ); - const callstack = this.createCallstack(new Error(TRACE_ERROR_MESSAGE)); + const callstack = this.createCallstack( + new Error(TRACE_ERROR_MESSAGE), + code + ); this.callCounter.setTimeout++; this.timerOnline(ETimeType.TIMEOUT, handler, delay, callstack, isEval); @@ -415,7 +418,10 @@ export class Wrapper { delay, ...args ); - const callstack = this.createCallstack(new Error(TRACE_ERROR_MESSAGE)); + const callstack = this.createCallstack( + new Error(TRACE_ERROR_MESSAGE), + code + ); this.callCounter.setInterval++; this.timerOnline(ETimeType.INTERVAL, handler, delay, callstack, isEval); @@ -457,7 +463,7 @@ export class Wrapper { }.bind(this); } - createCallstack(e: Error, fn: () => void): TCallstack { + createCallstack(e: Error, fn?: unknown): TCallstack { const trace: TTrace[] = []; const stack = e.stack?.split(REGEX_STACKTRACE_SPLIT) || []; let traceId = ''; @@ -483,12 +489,24 @@ export class Wrapper { } if (!trace.length) { - const link = `(id: ${crypto.randomUUID()})`; + let name: TTrace['name']; + if (typeof fn === 'function' && fn.name) { + name = fn.name; + traceId = name; + } else { + name = 0; + + if (typeof crypto.randomUUID === 'function') { + traceId = crypto.randomUUID(); + } else { + traceId = Math.random().toString(36); + } + } + trace.push({ - name: TAG_INVALID_CALLSTACK, - link, + name, + link: TAG_INVALID_CALLSTACK_LINK, }); - traceId = link; } if (traceId.length > SHA256_HEX_STRING_LENGTH) { diff --git a/src/view/components/Trace.svelte b/src/view/components/Trace.svelte index 4cb3514..003ade8 100644 --- a/src/view/components/Trace.svelte +++ b/src/view/components/Trace.svelte @@ -7,5 +7,5 @@ {#each trace as stack, index (index)} {#if index > 0} •{/if} - + {/each} diff --git a/src/view/components/TraceLink.svelte b/src/view/components/TraceLink.svelte index 8548949..dd4e941 100644 --- a/src/view/components/TraceLink.svelte +++ b/src/view/components/TraceLink.svelte @@ -3,27 +3,26 @@ REGEX_STACKTRACE_CLEAN_URL, REGEX_STACKTRACE_COLUMN_NUMBER, REGEX_STACKTRACE_LINE_NUMBER, - TAG_INVALID_CALLSTACK, + TAG_INVALID_CALLSTACK_LINK, } from '@/api/const.ts'; - export let href: string = ''; - export let name: string | 0 = 0; + export let link: string = ''; + export let name; let isSeen = false; $: lineNumber = parseInt( - href?.replace(REGEX_STACKTRACE_LINE_NUMBER, '$1'), + link?.replace(REGEX_STACKTRACE_LINE_NUMBER, '$1'), 10 ); $: columnNumber = parseInt( - href.replace(REGEX_STACKTRACE_COLUMN_NUMBER, '$1'), + link.replace(REGEX_STACKTRACE_COLUMN_NUMBER, '$1'), 10 ); - $: isSourceLess = !isFinite(lineNumber) || TAG_INVALID_CALLSTACK === href; + $: isSourceLess = + !isFinite(lineNumber) || TAG_INVALID_CALLSTACK_LINK === link; - function showStackTraceResource(e: MouseEvent) { - e.preventDefault(); - - const cleanUrl = href.replace(REGEX_STACKTRACE_CLEAN_URL, '$1'); + function showStackTraceResource() { + const cleanUrl = link.replace(REGEX_STACKTRACE_CLEAN_URL, '$1'); chrome.devtools.panels.openResource( cleanUrl, @@ -36,13 +35,15 @@ {#if isSourceLess} - {`${name ? name : ''} ${href}`} + + {name ? `${name} ${link}` : link} + {:else} {name || href}{name || link} {/if} From 872b0248a69716e7203f8dfd043d4752026e39c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=95=B7?= <3756473+zendive@users.noreply.github.com> Date: Fri, 12 Jul 2024 19:26:16 +0300 Subject: [PATCH 08/53] add `traceDomain` to highlight trace origin --- src/api/const.ts | 1 + src/api/wrappers.ts | 27 ++++++++++++++++++++++-- src/view/components/ActiveTimers.svelte | 5 ++++- src/view/components/EvalMetrics.svelte | 7 +++++- src/view/components/TimersHistory.svelte | 5 ++++- src/view/components/Trace.svelte | 11 +++++++++- 6 files changed, 50 insertions(+), 6 deletions(-) diff --git a/src/api/const.ts b/src/api/const.ts index a0d0cd8..8079183 100644 --- a/src/api/const.ts +++ b/src/api/const.ts @@ -117,5 +117,6 @@ export const REGEX_STACKTRACE_LINK = new RegExp(/.*\((.*)\)$/); export const REGEX_STACKTRACE_CLEAN_URL = new RegExp(/(.*):\d+:\d+$/); export const REGEX_STACKTRACE_LINE_NUMBER = new RegExp(/.*:(\d+):\d+$/); export const REGEX_STACKTRACE_COLUMN_NUMBER = new RegExp(/.*:\d+:(\d+)$/); +export const REGEX_STACKTRACE_LINK_PROTOCOL = new RegExp(/^http[s]?\:\/\//); export const FRAME_1of60 = 1 / 60; export const SHA256_HEX_STRING_LENGTH = 64; diff --git a/src/api/wrappers.ts b/src/api/wrappers.ts index 636711c..6c5ba20 100644 --- a/src/api/wrappers.ts +++ b/src/api/wrappers.ts @@ -9,6 +9,7 @@ import { TRACE_ERROR_MESSAGE, REGEX_STACKTRACE_SPLIT, REGEX_STACKTRACE_CLEAN_URL, + REGEX_STACKTRACE_LINK_PROTOCOL, TAG_INVALID_CALLSTACK_LINK, SHA256_HEX_STRING_LENGTH, } from '@/api/const.ts'; @@ -25,12 +26,18 @@ type TCallstack = { trace: TTrace[]; }; export enum ETimeType { - TIMEOUT, - INTERVAL, + TIMEOUT = 0, + INTERVAL = 1, +} +export enum ETraceDomain { + LOCAL = 0, + EXTERNAL = 1, + UNKNOWN = 2, } export type TOnlineTimerMetrics = { traceId: string; trace: TTrace[]; + traceDomain: ETraceDomain; type: ETimeType; delay: number | undefined | string; handler: number; @@ -39,6 +46,7 @@ export type TOnlineTimerMetrics = { export type TTimerHistory = { traceId: string; trace: TTrace[]; + traceDomain: ETraceDomain; individualInvocations: number; recentHandler: number | string; handlerDelay: number | undefined | string; @@ -48,6 +56,7 @@ export type TTimerHistory = { export type TEvalHistory = { traceId: string; trace: TTrace[]; + traceDomain: ETraceDomain; individualInvocations: number; returnedValue: any; code: any; @@ -110,6 +119,16 @@ export class Wrapper { ); } + #getTraceDomain(trace: TTrace) { + if (trace.link.startsWith(location.origin)) { + return ETraceDomain.LOCAL; + } else if (REGEX_STACKTRACE_LINK_PROTOCOL.test(trace.link)) { + return ETraceDomain.EXTERNAL; + } + + return ETraceDomain.UNKNOWN; + } + timerOnline( type: ETimeType, handler: number, @@ -127,6 +146,7 @@ export class Wrapper { isEval, traceId: callstack.traceId, trace: callstack.trace, + traceDomain: this.#getTraceDomain(callstack.trace[0]), }); } @@ -164,6 +184,7 @@ export class Wrapper { hasError, traceId: callstack.traceId, trace: callstack.trace, + traceDomain: this.#getTraceDomain(callstack.trace[0]), }); } } @@ -208,6 +229,7 @@ export class Wrapper { hasError, traceId: callstack.traceId, trace: callstack.trace, + traceDomain: this.#getTraceDomain(callstack.trace[0]), }); } } @@ -233,6 +255,7 @@ export class Wrapper { usesLocalScope, traceId: callstack.traceId, trace: callstack.trace, + traceDomain: this.#getTraceDomain(callstack.trace[0]), }); } } diff --git a/src/view/components/ActiveTimers.svelte b/src/view/components/ActiveTimers.svelte index 5af6a19..9ddb2b7 100644 --- a/src/view/components/ActiveTimers.svelte +++ b/src/view/components/ActiveTimers.svelte @@ -44,7 +44,10 @@ /> {/each} diff --git a/src/view/components/EvalMetrics.svelte b/src/view/components/EvalMetrics.svelte index c9c0dc6..8556468 100644 --- a/src/view/components/EvalMetrics.svelte +++ b/src/view/components/EvalMetrics.svelte @@ -30,7 +30,12 @@ > {#each metrics as metric (metric.traceId)} - + - + - + + {/each}
Eval Usages
CallstackScopeCalled void scrollTo('Eval Usages')} + on:click|preventDefault={() => void scrollTo('Eval History')} > eval: From 18b5374d2337da53808037e25909a1a62884499d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=95=B7?= <3756473+zendive@users.noreply.github.com> Date: Mon, 8 Jul 2024 13:00:48 +0300 Subject: [PATCH 03/53] digress array over Map for history keeping + observed more discrete-flat memory footprint over saw like --- src/api/const.ts | 12 +-- src/api/wrappers.ts | 131 +++++++++++------------- src/view/components/ActiveTimers.svelte | 3 - 3 files changed, 64 insertions(+), 82 deletions(-) diff --git a/src/api/const.ts b/src/api/const.ts index 0fce402..711262c 100644 --- a/src/api/const.ts +++ b/src/api/const.ts @@ -111,10 +111,10 @@ export const READY_STATE = [ ]; export const TRACE_ERROR_MESSAGE = 'browser-api-monitor'; -export const REGEX_STACKTRACE_PREFIX = /^\s*at /; -export const REGEX_STACKTRACE_NAME = /^(.+)\(.*/; -export const REGEX_STACKTRACE_LINK = /.*\((.*)\).*/; -export const REGEX_STACKTRACE_CLEAN_URL = /(.*):\d+:\d+$/; -export const REGEX_STACKTRACE_LINE_NUMBER = /.*:(\d+):\d+$/; -export const REGEX_STACKTRACE_COLUMN_NUMBER = /.*:\d+:(\d+)$/; +export const REGEX_STACKTRACE_SPLIT = new RegExp(/\n\s+at\s/); +export const REGEX_STACKTRACE_NAME = new RegExp(/^(.+)\(.*/); +export const REGEX_STACKTRACE_LINK = new RegExp(/.*\((.*)\)$/); +export const REGEX_STACKTRACE_CLEAN_URL = new RegExp(/(.*):\d+:\d+$/); +export const REGEX_STACKTRACE_LINE_NUMBER = new RegExp(/.*:(\d+):\d+$/); +export const REGEX_STACKTRACE_COLUMN_NUMBER = new RegExp(/.*:\d+:(\d+)$/); export const FRAME_1of60 = 1 / 60; diff --git a/src/api/wrappers.ts b/src/api/wrappers.ts index 9dadbe2..0784e71 100644 --- a/src/api/wrappers.ts +++ b/src/api/wrappers.ts @@ -7,7 +7,7 @@ import { REGEX_STACKTRACE_NAME, REGEX_STACKTRACE_LINK, TRACE_ERROR_MESSAGE, - REGEX_STACKTRACE_PREFIX, + REGEX_STACKTRACE_SPLIT, REGEX_STACKTRACE_CLEAN_URL, TAG_INVALID_CALLSTACK, } from '@/api/const.ts'; @@ -31,10 +31,9 @@ export type TOnlineTimerMetrics = { traceId: string; trace: TTrace[]; type: ETimeType; - delay: number | undefined; + delay: number | undefined | string; handler: number; isEval: boolean; - rawTrace?: string; // for debugging }; export type TTimerHistory = { traceId: string; @@ -64,15 +63,13 @@ export type TWrapperMetrics = { evalHistory: TEvalHistory[]; }; -type TOnlineTimers = Map; - export class Wrapper { - onlineTimers: TOnlineTimers = new Map(); - setTimeoutHistory: TTimerHistory[] = []; - clearTimeoutHistory: TTimerHistory[] = []; - setIntervalHistory: TTimerHistory[] = []; - clearIntervalHistory: TTimerHistory[] = []; - evalHistory: TEvalHistory[] = []; + onlineTimers: Map = new Map(); + setTimeoutHistory: Map = new Map(); + clearTimeoutHistory: Map = new Map(); + setIntervalHistory: Map = new Map(); + clearIntervalHistory: Map = new Map(); + evalHistory: Map = new Map(); callCounter = { setTimeout: 0, clearTimeout: 0, @@ -87,17 +84,18 @@ export class Wrapper { clearInterval: clearInterval, eval: lessEval, }; - static selfCallLink = ''; - - constructor() {} + selfTraceLink = ''; timerOnline( type: ETimeType, handler: number, - delay: number | undefined, + delay: number | undefined | string, callstack: TCallstack, isEval: boolean ) { + if (this.#badTimerDelay(delay)) { + delay = TAG_EXCEPTION(`${delay}`); + } this.onlineTimers.set(handler, { type, handler, @@ -105,7 +103,6 @@ export class Wrapper { isEval, traceId: callstack.traceId, trace: callstack.trace, - //rawTrace }); } @@ -114,27 +111,24 @@ export class Wrapper { } #badTimerHandler(handler: unknown) { - const rv = !Number.isFinite(handler) || handler < 1; - - return rv; + return !Number.isFinite(handler) || handler < 1; } #badTimerDelay(delay: unknown) { - const rv = + return ( (delay !== undefined && !Number.isFinite(delay)) || - (Number.isFinite(delay) && delay < 0); - - return rv; + (Number.isFinite(delay) && delay < 0) + ); } updateSetTimersHistory( - history: TTimerHistory[], + history: Map, handler: number, delay: number | undefined, callstack: TCallstack, isEval: boolean ) { - const existing = history.findLast((v) => v.traceId === callstack.traceId); + const existing = history.get(callstack.traceId); const hasError = this.#badTimerDelay(delay); let handlerDelay: string | number | undefined = delay; @@ -149,7 +143,7 @@ export class Wrapper { existing.isEval = isEval; existing.hasError = hasError; } else { - history.push({ + history.set(callstack.traceId, { recentHandler: handler, individualInvocations: 1, handlerDelay, @@ -158,22 +152,19 @@ export class Wrapper { traceId: callstack.traceId, trace: callstack.trace, }); - history.sort((a, b) => - (b.handlerDelay || 0) > (a.handlerDelay || 0) ? 1 : -1 - ); } } updateClearTimersHistory( - history: TTimerHistory[], + history: Map, handler: unknown, callstack: TCallstack ) { - const existing = history.findLast((v) => v.traceId === callstack.traceId); + const existing = history.get(callstack.traceId); const hasError = this.#badTimerHandler(handler); - const onlineTimer = !hasError - ? this.onlineTimers.get(handler) - : null; + const onlineTimer = hasError + ? null + : this.onlineTimers.get(handler); let handlerDelay: string | number | undefined = 'N/A'; let handlerIsEval = undefined; @@ -196,7 +187,7 @@ export class Wrapper { existing.isEval = handlerIsEval; existing.hasError = hasError; } else { - history.push({ + history.set(callstack.traceId, { recentHandler: handler, individualInvocations: 1, handlerDelay, @@ -205,9 +196,6 @@ export class Wrapper { traceId: callstack.traceId, trace: callstack.trace, }); - history.sort((a, b) => - (b.handlerDelay || 0) > (a.handlerDelay || 0) ? 1 : -1 - ); } } @@ -217,9 +205,7 @@ export class Wrapper { callstack: TCallstack, usesLocalScope: boolean ) { - const existing = this.evalHistory.find( - (v) => v.traceId === callstack.traceId - ); + const existing = this.evalHistory.get(callstack.traceId); if (existing) { existing.code = cloneObjectSafely(code); @@ -227,7 +213,7 @@ export class Wrapper { existing.individualInvocations++; existing.usesLocalScope = usesLocalScope; } else { - this.evalHistory.push({ + this.evalHistory.set(callstack.traceId, { individualInvocations: 1, code: cloneObjectSafely(code), returnedValue: cloneObjectSafely(returnedValue), @@ -238,20 +224,18 @@ export class Wrapper { } } - cleanHistory(what?: string[]) { - if (!what || !what.length) { - this.setTimeoutHistory.splice(0); - this.clearTimeoutHistory.splice(0); - this.setIntervalHistory.splice(0); - this.clearIntervalHistory.splice(0); - this.evalHistory.splice(0); - this.callCounter.setTimeout = - this.callCounter.clearTimeout = - this.callCounter.setInterval = - this.callCounter.clearInterval = - this.callCounter.eval = - 0; - } + cleanHistory() { + this.setTimeoutHistory.clear(); + this.clearTimeoutHistory.clear(); + this.setIntervalHistory.clear(); + this.clearIntervalHistory.clear(); + this.evalHistory.clear(); + this.callCounter.setTimeout = + this.callCounter.clearTimeout = + this.callCounter.setInterval = + this.callCounter.clearInterval = + this.callCounter.eval = + 0; } collectWrapperMetrics(panels: TPanelVisibilityMap): TWrapperMetrics { @@ -261,21 +245,23 @@ export class Wrapper { onlineTimers: this.onlineTimers.size, onlineTimeouts: timeouts, onlineIntervals: intervals, - setTimeoutHistory: panels.setTimeoutHistory ? this.setTimeoutHistory : [], + setTimeoutHistory: panels.setTimeoutHistory + ? [...this.setTimeoutHistory.values()] + : [], clearTimeoutHistory: panels.clearTimeoutHistory - ? this.clearTimeoutHistory + ? [...this.clearTimeoutHistory.values()] : [], setIntervalHistory: panels.setIntervalHistory - ? this.setIntervalHistory + ? [...this.setIntervalHistory.values()] : [], clearIntervalHistory: panels.clearIntervalHistory - ? this.clearIntervalHistory + ? [...this.clearIntervalHistory.values()] : [], - evalHistory: panels.eval ? this.evalHistory : [], + evalHistory: panels.eval ? [...this.evalHistory.values()] : [], }; if (panels.activeTimers) { - for (const [, timer] of this.onlineTimers) { + for (const timer of this.onlineTimers.values()) { if (timer.type === ETimeType.INTERVAL) { intervals.push(timer); } else { @@ -323,7 +309,7 @@ export class Wrapper { this.updateEvalHistory( code, rv, - Wrapper.createCallstack(new Error(TRACE_ERROR_MESSAGE)), + this.createCallstack(new Error(TRACE_ERROR_MESSAGE)), usesLocalScope ); @@ -356,7 +342,7 @@ export class Wrapper { delay, ...args ); - const callstack = Wrapper.createCallstack(new Error(TRACE_ERROR_MESSAGE)); + const callstack = this.createCallstack(new Error(TRACE_ERROR_MESSAGE)); this.callCounter.setTimeout++; this.timerOnline(ETimeType.TIMEOUT, handler, delay, callstack, isEval); @@ -387,7 +373,7 @@ export class Wrapper { this.updateClearTimersHistory( this.clearTimeoutHistory, handler, - Wrapper.createCallstack(new Error(TRACE_ERROR_MESSAGE)) + this.createCallstack(new Error(TRACE_ERROR_MESSAGE)) ); if (handler !== undefined) { this.timerOffline(handler); @@ -416,7 +402,7 @@ export class Wrapper { delay, ...args ); - const callstack = Wrapper.createCallstack(new Error(TRACE_ERROR_MESSAGE)); + const callstack = this.createCallstack(new Error(TRACE_ERROR_MESSAGE)); this.callCounter.setInterval++; this.timerOnline(ETimeType.INTERVAL, handler, delay, callstack, isEval); @@ -447,7 +433,7 @@ export class Wrapper { this.updateClearTimersHistory( this.clearIntervalHistory, handler, - Wrapper.createCallstack(new Error(TRACE_ERROR_MESSAGE)) + this.createCallstack(new Error(TRACE_ERROR_MESSAGE)) ); if (handler !== undefined) { this.timerOffline(handler); @@ -458,17 +444,17 @@ export class Wrapper { }.bind(this); } - static createCallstack(e: Error): TCallstack { + createCallstack(e: Error): TCallstack { const trace: TTrace[] = []; - const stack = e.stack?.split('\n') || []; + const stack = e.stack?.split(REGEX_STACKTRACE_SPLIT) || []; let links = ''; - if (!Wrapper.selfCallLink) { + if (!this.selfTraceLink) { const link = stack[1] .replace(REGEX_STACKTRACE_LINK, '$1') .replace(REGEX_STACKTRACE_CLEAN_URL, '$1'); if (link) { - Wrapper.selfCallLink = link; + this.selfTraceLink = link; } } @@ -476,11 +462,10 @@ export class Wrapper { for (let n = stack.length - 1; n > 1; n--) { let v = stack[n]; - if (v.indexOf(Wrapper.selfCallLink) >= 0) { + if (v.indexOf(this.selfTraceLink) >= 0) { continue; } - v = v.replace(REGEX_STACKTRACE_PREFIX, ''); const link = v.replace(REGEX_STACKTRACE_LINK, '$1').trim(); if (link.startsWith('')) { diff --git a/src/view/components/ActiveTimers.svelte b/src/view/components/ActiveTimers.svelte index 7ae63dd..5af6a19 100644 --- a/src/view/components/ActiveTimers.svelte +++ b/src/view/components/ActiveTimers.svelte @@ -45,9 +45,6 @@ - {#if IS_DEV && metric.rawTrace} -
{metric.rawTrace}
- {/if}
- +
+ + {#if metric.usesLocalScope} - + diff --git a/src/view/components/Trace.svelte b/src/view/components/Trace.svelte index 003ade8..1fe0350 100644 --- a/src/view/components/Trace.svelte +++ b/src/view/components/Trace.svelte @@ -1,10 +1,19 @@ +{#if traceDomain === ETraceDomain.LOCAL} + 🏡 +{:else if traceDomain === ETraceDomain.EXTERNAL} + 🌍 +{:else if traceDomain === ETraceDomain.UNKNOWN} + +{/if} + {#each trace as stack, index (index)} {#if index > 0} •{/if} From b273af0558e2f8950d28dc7e7e33491184fe6f09 Mon Sep 17 00:00:00 2001 From: zendive <3756473+zendive@users.noreply.github.com> Date: Fri, 12 Jul 2024 19:54:06 +0300 Subject: [PATCH 09/53] Add dependency review action --- .github/workflows/dependency-review.yml | 39 +++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 .github/workflows/dependency-review.yml diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml new file mode 100644 index 0000000..444f0d0 --- /dev/null +++ b/.github/workflows/dependency-review.yml @@ -0,0 +1,39 @@ +# Dependency Review Action +# +# This Action will scan dependency manifest files that change as part of a Pull Request, +# surfacing known-vulnerable versions of the packages declared or updated in the PR. +# Once installed, if the workflow run is marked as required, PRs introducing known-vulnerable +# packages will be blocked from merging. +# +# Source repository: https://github.com/actions/dependency-review-action +# Public documentation: https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-dependency-review#dependency-review-enforcement +name: 'Dependency review' +on: + pull_request: + branches: [ "master", "next" ] + +# If using a dependency submission action in this workflow this permission will need to be set to: +# +# permissions: +# contents: write +# +# https://docs.github.com/en/enterprise-cloud@latest/code-security/supply-chain-security/understanding-your-software-supply-chain/using-the-dependency-submission-api +permissions: + contents: read + # Write permissions for pull-requests are required for using the `comment-summary-in-pr` option, comment out if you aren't using this option + pull-requests: write + +jobs: + dependency-review: + runs-on: ubuntu-latest + steps: + - name: 'Checkout repository' + uses: actions/checkout@v4 + - name: 'Dependency Review' + uses: actions/dependency-review-action@v4 + # Commonly enabled options, see https://github.com/actions/dependency-review-action#configuration-options for all available options. + with: + comment-summary-in-pr: always + # fail-on-severity: moderate + # deny-licenses: GPL-1.0-or-later, LGPL-2.0-or-later + # retry-on-snapshot-warnings: true From 2e3050a81ebd204e1419818eaa7c8773cb28a00a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=95=B7?= <3756473+zendive@users.noreply.github.com> Date: Sun, 14 Jul 2024 07:23:35 +0300 Subject: [PATCH 10/53] deprecate TimerHistory sort by `traceId` --- src/api/settings.ts | 3 +-- src/view/components/TimersHistory.svelte | 9 +-------- src/view/components/TimersHistoryCellSort.svelte | 6 +++--- 3 files changed, 5 insertions(+), 13 deletions(-) diff --git a/src/api/settings.ts b/src/api/settings.ts index c5aea5a..0b8e3ed 100644 --- a/src/api/settings.ts +++ b/src/api/settings.ts @@ -10,7 +10,6 @@ type TPanelKey = | 'clearIntervalHistory'; export enum ETimerHistoryField { - traceId = 'traceId', individualInvocations = 'individualInvocations', recentHandler = 'recentHandler', handlerDelay = 'handlerDelay', @@ -34,7 +33,7 @@ export type TSettingsPanel = { export type TSettings = typeof DEFAULT_SETTINGS; export type TSettingsProperty = Partial; -const SETTINGS_VERSION = '1.0.3'; +const SETTINGS_VERSION = '1.0.5'; const DEFAULT_PANELS: TSettingsPanel[] = [ { key: 'eval', label: 'eval', visible: true }, { key: 'media', label: 'Media', visible: true }, diff --git a/src/view/components/TimersHistory.svelte b/src/view/components/TimersHistory.svelte index ac76c10..0cefe22 100644 --- a/src/view/components/TimersHistory.svelte +++ b/src/view/components/TimersHistory.svelte @@ -73,14 +73,7 @@
- Callstack - Callstack {#if field === currentField} {/if} diff --git a/src/view/components/TogglePanels.svelte b/src/view/components/TogglePanels.svelte index 74b7127..f1482e8 100644 --- a/src/view/components/TogglePanels.svelte +++ b/src/view/components/TogglePanels.svelte @@ -49,7 +49,6 @@ padding: 0px 6px; margin: 0; z-index: 1; - user-select: none; .menu-item { cursor: pointer; From 6b6e5efe3af7d975c5927b0eab7470bf997f012c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=95=B7?= <3756473+zendive@users.noreply.github.com> Date: Thu, 18 Jul 2024 13:49:16 +0300 Subject: [PATCH 14/53] rename fields --- jest/tests/wrappers.test.ts | 44 +++++++------- src/api/settings.ts | 8 +-- src/api/wrappers.ts | 66 ++++++++++----------- src/view/components/AnimationHistory.svelte | 8 +-- src/view/components/EvalMetrics.svelte | 2 +- src/view/components/TimersHistory.svelte | 13 ++-- 6 files changed, 69 insertions(+), 72 deletions(-) diff --git a/jest/tests/wrappers.test.ts b/jest/tests/wrappers.test.ts index fc67c71..d1e6b15 100644 --- a/jest/tests/wrappers.test.ts +++ b/jest/tests/wrappers.test.ts @@ -49,8 +49,8 @@ describe('wrappers', () => { const handler = setTimeout(() => {}, DELAY); const rec = Array.from(wrapper.setTimeoutHistory.values())[0]; - expect(rec.individualInvocations).toBe(1); - expect(rec.handlerDelay).toBe(DELAY); + expect(rec.calls).toBe(1); + expect(rec.delay).toBe(DELAY); expect(rec.hasError).toBe(false); expect(rec.isEval).toBe(false); expect(rec.trace.length).toBeGreaterThan(1); @@ -64,8 +64,8 @@ describe('wrappers', () => { const rec = Array.from(wrapper.setTimeoutHistory.values())[0]; - expect(rec.individualInvocations).toBe(1); - expect(rec.handlerDelay).toBe(TAG_EXCEPTION('-1')); + expect(rec.calls).toBe(1); + expect(rec.delay).toBe(TAG_EXCEPTION('-1')); expect(rec.hasError).toBe(true); expect(rec.isEval).toBe(false); }); @@ -76,7 +76,7 @@ describe('wrappers', () => { const rec = Array.from(wrapper.clearTimeoutHistory.values())[0]; - expect(rec.handlerDelay).toBe(1e3); + expect(rec.delay).toBe(1e3); }); test('clearTimeoutHistory - non existent handler', () => { @@ -84,7 +84,7 @@ describe('wrappers', () => { const rec = Array.from(wrapper.clearTimeoutHistory.values())[0]; - expect(rec.handlerDelay).toBe('N/A'); + expect(rec.delay).toBe('N/A'); expect(rec.hasError).toBe(false); }); @@ -93,8 +93,8 @@ describe('wrappers', () => { const rec = Array.from(wrapper.clearTimeoutHistory.values())[0]; - expect(rec.handlerDelay).toBe('N/A'); - expect(rec.recentHandler).toBe(TAG_EXCEPTION(0)); + expect(rec.delay).toBe('N/A'); + expect(rec.handler).toBe(TAG_EXCEPTION(0)); expect(rec.hasError).toBe(true); }); @@ -116,8 +116,8 @@ describe('wrappers', () => { const handler = setInterval(() => {}, DELAY); const rec = Array.from(wrapper.setIntervalHistory.values())[0]; - expect(rec.individualInvocations).toBe(1); - expect(rec.handlerDelay).toBe(DELAY); + expect(rec.calls).toBe(1); + expect(rec.delay).toBe(DELAY); expect(rec.hasError).toBe(false); expect(rec.isEval).toBe(false); expect(rec.trace.length).toBeGreaterThan(1); @@ -130,8 +130,8 @@ describe('wrappers', () => { const handler = setInterval(() => {}, -1); const rec = Array.from(wrapper.setIntervalHistory.values())[0]; - expect(rec.individualInvocations).toBe(1); - expect(rec.handlerDelay).toBe(TAG_EXCEPTION('-1')); + expect(rec.calls).toBe(1); + expect(rec.delay).toBe(TAG_EXCEPTION('-1')); expect(rec.hasError).toBe(true); expect(rec.isEval).toBe(false); @@ -144,7 +144,7 @@ describe('wrappers', () => { const rec = Array.from(wrapper.clearIntervalHistory.values())[0]; - expect(rec.handlerDelay).toBe(1e3); + expect(rec.delay).toBe(1e3); }); test('clearIntervalHistory - non existent handler', () => { @@ -152,7 +152,7 @@ describe('wrappers', () => { const rec = Array.from(wrapper.clearIntervalHistory.values())[0]; - expect(rec.handlerDelay).toBe('N/A'); + expect(rec.delay).toBe('N/A'); expect(rec.hasError).toBe(false); }); @@ -161,7 +161,7 @@ describe('wrappers', () => { const rec = Array.from(wrapper.clearIntervalHistory.values())[0]; - expect(rec.handlerDelay).toBe('N/A'); + expect(rec.delay).toBe('N/A'); expect(rec.hasError).toBe(true); }); @@ -177,7 +177,7 @@ describe('wrappers', () => { const rec = Array.from(wrapper.evalHistory.values())[0]; - expect(rec.individualInvocations).toBe(NUMBER_OF_INVOCATIONS); + expect(rec.calls).toBe(NUMBER_OF_INVOCATIONS); expect(rec.usesLocalScope).toBe(false); expect(rec.code).toBe(CODE); expect(rec.returnedValue).toBe(RESULT); @@ -191,7 +191,7 @@ describe('wrappers', () => { const rec = Array.from(wrapper.evalHistory.values())[0]; - expect(rec.individualInvocations).toBe(1); + expect(rec.calls).toBe(1); expect(local_variable).toBe(0); expect(rec.usesLocalScope).toBe(true); expect(rec.returnedValue).toBe(TAG_UNDEFINED); @@ -209,8 +209,8 @@ describe('wrappers', () => { expect(typeOfArgument).toBe('number'); expect(wrapper.rafHistory.size).toBe(1); - expect(rec.recentHandler).toBe(handler); - expect(rec.individualInvocations).toBe(1); + expect(rec.handler).toBe(handler); + expect(rec.calls).toBe(1); expect(rec.trace.length).toBeGreaterThan(1); expect(rec.traceId.length).toBeGreaterThan(1); expect(wrapper.callCounter.requestAnimationFrame).toBe(1); @@ -230,8 +230,8 @@ describe('wrappers', () => { expect(changeable).toBe(unchanged); expect(wrapper.rafHistory.size).toBe(1); expect(wrapper.cafHistory.size).toBe(1); - expect(rec.recentHandler).toBe(handler); - expect(rec.individualInvocations).toBe(1); + expect(rec.handler).toBe(handler); + expect(rec.calls).toBe(1); expect(rec.trace.length).toBeGreaterThan(1); expect(rec.traceId.length).toBeGreaterThan(1); expect(wrapper.callCounter.cancelAnimationFrame).toBe(1); @@ -242,6 +242,6 @@ describe('wrappers', () => { const rec = Array.from(wrapper.cafHistory?.values())[0]; - expect(rec.recentHandler).toBe(TAG_EXCEPTION(0)); + expect(rec.handler).toBe(TAG_EXCEPTION(0)); }); }); diff --git a/src/api/settings.ts b/src/api/settings.ts index a15e3f1..6202249 100644 --- a/src/api/settings.ts +++ b/src/api/settings.ts @@ -12,9 +12,9 @@ type TPanelKey = | 'cancelAnimationFrame'; export enum ETimerHistoryField { - individualInvocations = 'individualInvocations', - recentHandler = 'recentHandler', - handlerDelay = 'handlerDelay', + calls = 'calls', + handler = 'handler', + delay = 'delay', } export enum ESortOrder { @@ -53,7 +53,7 @@ const DEFAULT_PANELS: TSettingsPanel[] = [ ]; export const DEFAULT_SORT = { - timersHistoryField: ETimerHistoryField.handlerDelay, + timersHistoryField: ETimerHistoryField.delay, timersHistoryOrder: ESortOrder.DESCENDING, }; diff --git a/src/api/wrappers.ts b/src/api/wrappers.ts index c45afcf..1de5166 100644 --- a/src/api/wrappers.ts +++ b/src/api/wrappers.ts @@ -50,9 +50,9 @@ export type TTimerHistory = { traceId: string; trace: TTrace[]; traceDomain: ETraceDomain; - individualInvocations: number; - recentHandler: number | string; - handlerDelay: number | undefined | string; + calls: number; + handler: number | string; + delay: number | undefined | string; isEval: boolean | undefined; hasError: boolean; }; @@ -60,7 +60,7 @@ export type TEvalHistory = { traceId: string; trace: TTrace[]; traceDomain: ETraceDomain; - individualInvocations: number; + calls: number; returnedValue: any; code: any; usesLocalScope: boolean; @@ -69,8 +69,8 @@ export type TAnimationHistory = { traceId: string; trace: TTrace[]; traceDomain: ETraceDomain; - individualInvocations: number; - recentHandler: number | undefined | string; + calls: number; + handler: number | undefined | string; hasError?: boolean; }; export type TWrapperMetrics = { @@ -187,16 +187,16 @@ export class Wrapper { } if (existing) { - existing.recentHandler = handler; - existing.handlerDelay = handlerDelay; - existing.individualInvocations++; + existing.handler = handler; + existing.delay = handlerDelay; + existing.calls++; existing.isEval = isEval; existing.hasError = hasError; } else { history.set(callstack.traceId, { - recentHandler: handler, - individualInvocations: 1, - handlerDelay, + handler, + calls: 1, + delay: handlerDelay, isEval, hasError, traceId: callstack.traceId, @@ -223,7 +223,7 @@ export class Wrapper { handlerDelay = onlineTimer.delay; handlerIsEval = onlineTimer.isEval; } else if (existing) { - handlerDelay = existing.handlerDelay; + handlerDelay = existing.delay; handlerIsEval = existing.isEval; } @@ -232,16 +232,16 @@ export class Wrapper { } if (existing) { - existing.recentHandler = handler; - existing.handlerDelay = handlerDelay; - existing.individualInvocations++; + existing.handler = handler; + existing.delay = handlerDelay; + existing.calls++; existing.isEval = handlerIsEval; existing.hasError = hasError; } else { history.set(callstack.traceId, { - recentHandler: handler, - individualInvocations: 1, - handlerDelay, + handler: handler, + calls: 1, + delay: handlerDelay, isEval: handlerIsEval, hasError, traceId: callstack.traceId, @@ -262,11 +262,11 @@ export class Wrapper { if (existing) { existing.code = cloneObjectSafely(code); existing.returnedValue = cloneObjectSafely(returnedValue); - existing.individualInvocations++; + existing.calls++; existing.usesLocalScope = usesLocalScope; } else { this.evalHistory.set(callstack.traceId, { - individualInvocations: 1, + calls: 1, code: cloneObjectSafely(code), returnedValue: cloneObjectSafely(returnedValue), usesLocalScope, @@ -281,15 +281,15 @@ export class Wrapper { const existing = this.rafHistory.get(callstack.traceId); if (existing) { - existing.individualInvocations++; - existing.recentHandler = handler; + existing.calls++; + existing.handler = handler; } else { this.rafHistory.set(callstack.traceId, { traceId: callstack.traceId, trace: callstack.trace, traceDomain: this.#getTraceDomain(callstack.trace[0]), - individualInvocations: 1, - recentHandler: handler, + calls: 1, + handler, }); } } @@ -303,16 +303,16 @@ export class Wrapper { } if (existing) { - existing.individualInvocations++; - existing.recentHandler = handler; + existing.calls++; + existing.handler = handler; existing.hasError = hasError; } else { this.cafHistory.set(callstack.traceId, { traceId: callstack.traceId, trace: callstack.trace, traceDomain: this.#getTraceDomain(callstack.trace[0]), - individualInvocations: 1, - recentHandler: handler, + calls: 1, + handler, hasError, }); } @@ -383,11 +383,7 @@ export class Wrapper { fn: FrameRequestCallback ) { this.callCounter.requestAnimationFrame++; - const handler = this.native.requestAnimationFrame( - (time: DOMHighResTimeStamp) => { - fn(time); - } - ); + const handler = this.native.requestAnimationFrame(fn); this.updateRafHistory( handler, this.createCallstack(new Error(TRACE_ERROR_MESSAGE), fn) @@ -602,7 +598,7 @@ export class Wrapper { let name: TTrace['name'] = 0; if (typeof uniqueTrait === 'function') { - name = uniqueTrait.name ?? 0; + name = uniqueTrait.name || 0; traceId = sha256(String(uniqueTrait)); } else { traceId = String(uniqueTrait); diff --git a/src/view/components/AnimationHistory.svelte b/src/view/components/AnimationHistory.svelte index 34123ba..8004e5b 100644 --- a/src/view/components/AnimationHistory.svelte +++ b/src/view/components/AnimationHistory.svelte @@ -50,7 +50,7 @@ Callstack Called Handler - {metric.individualInvocations}{metric.recentHandler}{metric.calls}{metric.handler}
diff --git a/src/view/components/EvalMetrics.svelte b/src/view/components/EvalMetrics.svelte index 8bf4747..d24075f 100644 --- a/src/view/components/EvalMetrics.svelte +++ b/src/view/components/EvalMetrics.svelte @@ -48,7 +48,7 @@ {/if} - +
{dynamicValue(metric.code)}
diff --git a/src/view/components/TimersHistory.svelte b/src/view/components/TimersHistory.svelte index 692b5d2..a541799 100644 --- a/src/view/components/TimersHistory.svelte +++ b/src/view/components/TimersHistory.svelte @@ -48,7 +48,7 @@ Callstack Called Handler Delay - + - {metric.recentHandler} - {metric.handlerDelay} + {metric.handler} + {metric.delay} {/each} +callscalls From 6899b2645557d665f17ba69c028e7e5e623566e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=95=B7?= <3756473+zendive@users.noreply.github.com> Date: Thu, 18 Jul 2024 15:06:43 +0300 Subject: [PATCH 15/53] add isOnline indication to setTimeout/setInterval histories --- jest/tests/wrappers.test.ts | 34 +++++++++++++++++++++++- src/api/wrappers.ts | 19 +++++++++++++ src/view/components/TimersHistory.svelte | 5 +++- 3 files changed, 56 insertions(+), 2 deletions(-) diff --git a/jest/tests/wrappers.test.ts b/jest/tests/wrappers.test.ts index d1e6b15..f857e97 100644 --- a/jest/tests/wrappers.test.ts +++ b/jest/tests/wrappers.test.ts @@ -22,8 +22,8 @@ describe('wrappers', () => { const DELAY = 5; const handler = setTimeout(() => {}, DELAY); - // typecasting handler to number since here its having NodeJS.Timeout type expect(wrapper.onlineTimers.size).toBe(1); + // typecasting handler to number since here its having NodeJS.Timeout type expect(wrapper.onlineTimers.has(Number(handler))).toBe(true); await new Promise((resolve) => setTimeout(resolve, 2 * DELAY)); @@ -44,6 +44,28 @@ describe('wrappers', () => { expect(wrapper.setTimeoutHistory.size).toBe(1); }); + test('setTimeoutHistory - isOnline becomes false after timer fired', async () => { + const DELAY = 5; + setTimeout(() => {}, DELAY); + + const rec = Array.from(wrapper.setTimeoutHistory.values())[0]; + expect(rec.isOnline).toBe(true); + + await new Promise((resolve) => setTimeout(resolve, 2 * DELAY)); + + expect(rec.isOnline).toBe(false); + }); + + test('setTimeoutHistory - isOnline becomes false after timer canceled', () => { + const DELAY = 123; + const handler = setTimeout(() => {}, DELAY); + const rec = Array.from(wrapper.setTimeoutHistory.values())[0]; + + expect(rec.isOnline).toBe(true); + clearTimeout(handler); + expect(rec.isOnline).toBe(false); + }); + test('setTimeoutHistory - valid delay', () => { const DELAY = 123; const handler = setTimeout(() => {}, DELAY); @@ -111,6 +133,16 @@ describe('wrappers', () => { expect(wrapper.setIntervalHistory.size).toBe(1); }); + test('setIntervalHistory - isOnline becomes false after interval canceled', () => { + const DELAY = 123; + const handler = setInterval(() => {}, DELAY); + const rec = Array.from(wrapper.setIntervalHistory.values())[0]; + + expect(rec.isOnline).toBe(true); + clearInterval(handler); + expect(rec.isOnline).toBe(false); + }); + test('setIntervalHistory - valid delay', () => { const DELAY = 123; const handler = setInterval(() => {}, DELAY); diff --git a/src/api/wrappers.ts b/src/api/wrappers.ts index 1de5166..d265196 100644 --- a/src/api/wrappers.ts +++ b/src/api/wrappers.ts @@ -55,6 +55,7 @@ export type TTimerHistory = { delay: number | undefined | string; isEval: boolean | undefined; hasError: boolean; + isOnline: boolean; }; export type TEvalHistory = { traceId: string; @@ -168,6 +169,20 @@ export class Wrapper { } timerOffline(handler: number) { + const timer = this.onlineTimers.get(handler); + if (!timer) { + return; + } + + const record = + timer.type === ETimerType.TIMEOUT + ? this.setTimeoutHistory.get(timer.traceId) + : this.setIntervalHistory.get(timer.traceId); + + if (record) { + record.isOnline = false; + } + this.onlineTimers.delete(handler); } @@ -192,6 +207,7 @@ export class Wrapper { existing.calls++; existing.isEval = isEval; existing.hasError = hasError; + existing.isOnline = true; } else { history.set(callstack.traceId, { handler, @@ -199,6 +215,7 @@ export class Wrapper { delay: handlerDelay, isEval, hasError, + isOnline: true, traceId: callstack.traceId, trace: callstack.trace, traceDomain: this.#getTraceDomain(callstack.trace[0]), @@ -237,6 +254,7 @@ export class Wrapper { existing.calls++; existing.isEval = handlerIsEval; existing.hasError = hasError; + existing.isOnline = false; } else { history.set(callstack.traceId, { handler: handler, @@ -244,6 +262,7 @@ export class Wrapper { delay: handlerDelay, isEval: handlerIsEval, hasError, + isOnline: false, traceId: callstack.traceId, trace: callstack.trace, traceDomain: this.#getTraceDomain(callstack.trace[0]), diff --git a/src/view/components/TimersHistory.svelte b/src/view/components/TimersHistory.svelte index a541799..a3ee115 100644 --- a/src/view/components/TimersHistory.svelte +++ b/src/view/components/TimersHistory.svelte @@ -70,6 +70,7 @@ on:changeSort={onChangeSort}>Delay + {#each metrics as metric (metric.traceId)} @@ -85,7 +86,9 @@ {metric.handler} {metric.delay} + {#if metric.isOnline}⏰{/if} {/each} -callscalls From 6729954a4c1200e19d455d99a69c9ff6f04b719f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=95=B7?= <3756473+zendive@users.noreply.github.com> Date: Thu, 18 Jul 2024 15:10:01 +0300 Subject: [PATCH 16/53] add eval timers tests --- jest/tests/wrappers.test.ts | 30 +++++++++++++++++++++++++++--- src/api/const.ts | 2 ++ src/api/wrappers.ts | 6 ++++-- 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/jest/tests/wrappers.test.ts b/jest/tests/wrappers.test.ts index f857e97..d3a8bd5 100644 --- a/jest/tests/wrappers.test.ts +++ b/jest/tests/wrappers.test.ts @@ -2,9 +2,9 @@ import { describe, expect, test, beforeEach, afterEach } from '@jest/globals'; import { Wrapper } from '../../src/api/wrappers.ts'; import { TAG_EXCEPTION, TAG_UNDEFINED } from '../../src/api/clone.ts'; import { - DEFAULT_SETTINGS, - panelsArrayToVisibilityMap, -} from '../../src/api/settings.ts'; + TAG_EVAL_RETURN_SET_TIMEOUT, + TAG_EVAL_RETURN_SET_INTERVAL, +} from '../../src/api/const.ts'; describe('wrappers', () => { let wrapper: Wrapper; @@ -229,6 +229,30 @@ describe('wrappers', () => { expect(rec.returnedValue).toBe(TAG_UNDEFINED); }); + test('setTimeoutHistory - isEval recorded', () => { + const CODE = '(1+2)'; + const handler = setTimeout(CODE); + const timerRec = Array.from(wrapper.setTimeoutHistory.values())[0]; + const evalRec = Array.from(wrapper.evalHistory.values())[0]; + + expect(timerRec.isEval).toBe(true); + expect(evalRec.code).toBe(CODE); + expect(evalRec.returnedValue).toBe(TAG_EVAL_RETURN_SET_TIMEOUT); + }); + + test('setIntervalHistory - isEval recorded', () => { + const CODE = '(1+2)'; + const handler = setInterval(CODE, 123); + const timerRec = Array.from(wrapper.setIntervalHistory.values())[0]; + const evalRec = Array.from(wrapper.evalHistory.values())[0]; + + expect(timerRec.isEval).toBe(true); + expect(evalRec.code).toBe(CODE); + expect(evalRec.returnedValue).toBe(TAG_EVAL_RETURN_SET_INTERVAL); + + clearInterval(handler); + }); + test('rafHistory - recorded', async () => { let typeOfArgument = ''; const handler = await new Promise((resolve) => { diff --git a/src/api/const.ts b/src/api/const.ts index b81b409..795e1b1 100644 --- a/src/api/const.ts +++ b/src/api/const.ts @@ -14,6 +14,8 @@ export const lessEval = window.eval.bind(window); export const requestAnimationFrame = window.requestAnimationFrame.bind(window); export const cancelAnimationFrame = window.cancelAnimationFrame.bind(window); export const TAG_INVALID_CALLSTACK_LINK = '⟪N/A⟫'; +export const TAG_EVAL_RETURN_SET_TIMEOUT = '(N/A - via setTimeout)'; +export const TAG_EVAL_RETURN_SET_INTERVAL = '(N/A - via setInterval)'; export const MEDIA_ELEMENT_EVENTS = [ 'abort', diff --git a/src/api/wrappers.ts b/src/api/wrappers.ts index d265196..8eeb134 100644 --- a/src/api/wrappers.ts +++ b/src/api/wrappers.ts @@ -14,6 +14,8 @@ import { REGEX_STACKTRACE_LINK_PROTOCOL, TAG_INVALID_CALLSTACK_LINK, SHA256_HEX_STRING_LENGTH, + TAG_EVAL_RETURN_SET_TIMEOUT, + TAG_EVAL_RETURN_SET_INTERVAL, } from '@/api/const.ts'; import { TAG_EXCEPTION, cloneObjectSafely } from '@/api/clone.ts'; import type { TPanelVisibilityMap } from '@/api/settings.ts'; @@ -498,7 +500,7 @@ export class Wrapper { this.callCounter.eval++; this.updateEvalHistory( code, - '(N/A - via setTimeout)', + TAG_EVAL_RETURN_SET_TIMEOUT, callstack, false ); @@ -561,7 +563,7 @@ export class Wrapper { this.callCounter.eval++; this.updateEvalHistory( code, - '(N/A - via setInterval)', + TAG_EVAL_RETURN_SET_INTERVAL, callstack, false ); From 9892e12d9d81debb1f2cef166462228dc12075a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=95=B7?= <3756473+zendive@users.noreply.github.com> Date: Thu, 18 Jul 2024 17:35:58 +0300 Subject: [PATCH 17/53] webpack/optimization.minimizer EsbuildPlugin doesnt remove imports marked as unused --- src/api/wrappers.ts | 1 - webpack.config.ts | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/api/wrappers.ts b/src/api/wrappers.ts index 8eeb134..fca2b8a 100644 --- a/src/api/wrappers.ts +++ b/src/api/wrappers.ts @@ -20,7 +20,6 @@ import { import { TAG_EXCEPTION, cloneObjectSafely } from '@/api/clone.ts'; import type { TPanelVisibilityMap } from '@/api/settings.ts'; import { sha256 } from 'js-sha256'; -import type { TMediaMetrics } from './mediaMonitor'; export type TTrace = { name: string | 0; diff --git a/webpack.config.ts b/webpack.config.ts index 6b1e8d7..881469d 100644 --- a/webpack.config.ts +++ b/webpack.config.ts @@ -92,7 +92,7 @@ export default function ( splitChunks: false, usedExports: true, minimize: isProd, - minimizer: [new EsbuildPlugin()], + // minimizer: [new EsbuildPlugin()], }, devtool: false, From 62360c8d1808f65b58f2362600584a5381bd8f2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=95=B7?= <3756473+zendive@users.noreply.github.com> Date: Thu, 18 Jul 2024 19:33:38 +0300 Subject: [PATCH 18/53] typescript noUnusedLocals --- jest/tests/wrappers.test.ts | 2 +- tsconfig.json | 1 + webpack.config.ts | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/jest/tests/wrappers.test.ts b/jest/tests/wrappers.test.ts index d3a8bd5..d5f3a45 100644 --- a/jest/tests/wrappers.test.ts +++ b/jest/tests/wrappers.test.ts @@ -231,7 +231,7 @@ describe('wrappers', () => { test('setTimeoutHistory - isEval recorded', () => { const CODE = '(1+2)'; - const handler = setTimeout(CODE); + setTimeout(CODE); const timerRec = Array.from(wrapper.setTimeoutHistory.values())[0]; const evalRec = Array.from(wrapper.evalHistory.values())[0]; diff --git a/tsconfig.json b/tsconfig.json index 4053ee2..24a767f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,6 +4,7 @@ "strict": true, "strictNullChecks": true, "verbatimModuleSyntax": true, + "noUnusedLocals": true, "types": ["chrome"], "baseUrl": ".", "paths": { diff --git a/webpack.config.ts b/webpack.config.ts index 881469d..b081782 100644 --- a/webpack.config.ts +++ b/webpack.config.ts @@ -1,5 +1,5 @@ import webpack from 'webpack'; -import { EsbuildPlugin } from 'esbuild-loader'; +// import { EsbuildPlugin } from 'esbuild-loader'; import { sveltePreprocess } from 'svelte-preprocess'; import MiniCssExtractPlugin from 'mini-css-extract-plugin'; import manifest from './manifest.json' with { type: 'json' }; From 744d6f6b54331999bff023526639b7568e7a2a4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=95=B7?= <3756473+zendive@users.noreply.github.com> Date: Thu, 18 Jul 2024 20:34:28 +0300 Subject: [PATCH 19/53] add TSetTimerHistory.canceledByTraceId --- src/api/wrappers.ts | 67 +++++++++++++++--------- src/view/components/TimersHistory.svelte | 6 +-- src/view/components/Trace.svelte | 4 +- 3 files changed, 46 insertions(+), 31 deletions(-) diff --git a/src/api/wrappers.ts b/src/api/wrappers.ts index fca2b8a..413ace3 100644 --- a/src/api/wrappers.ts +++ b/src/api/wrappers.ts @@ -34,7 +34,7 @@ export enum ETimerType { INTERVAL = 1, } export enum ETraceDomain { - LOCAL = 0, + SAME = 0, EXTERNAL = 1, UNKNOWN = 2, } @@ -47,7 +47,7 @@ export type TOnlineTimerMetrics = { handler: number; isEval: boolean; }; -export type TTimerHistory = { +export type TSetTimerHistory = { traceId: string; trace: TTrace[]; traceDomain: ETraceDomain; @@ -57,7 +57,18 @@ export type TTimerHistory = { isEval: boolean | undefined; hasError: boolean; isOnline: boolean; + canceledByTraceId: string | null; }; +export type TClearTimerHistory = { + traceId: string; + trace: TTrace[]; + traceDomain: ETraceDomain; + calls: number; + handler: number | string; + delay: number | undefined | string; + hasError: boolean; +}; + export type TEvalHistory = { traceId: string; trace: TTrace[]; @@ -77,10 +88,10 @@ export type TAnimationHistory = { }; export type TWrapperMetrics = { onlineTimers: TOnlineTimerMetrics[] | null; - setTimeoutHistory: TTimerHistory[] | null; - clearTimeoutHistory: TTimerHistory[] | null; - setIntervalHistory: TTimerHistory[] | null; - clearIntervalHistory: TTimerHistory[] | null; + setTimeoutHistory: TSetTimerHistory[] | null; + clearTimeoutHistory: TClearTimerHistory[] | null; + setIntervalHistory: TSetTimerHistory[] | null; + clearIntervalHistory: TClearTimerHistory[] | null; evalHistory: TEvalHistory[] | null; rafHistory: TAnimationHistory[] | null; cafHistory: TAnimationHistory[] | null; @@ -88,10 +99,10 @@ export type TWrapperMetrics = { export class Wrapper { onlineTimers: Map = new Map(); - setTimeoutHistory: Map = new Map(); - clearTimeoutHistory: Map = new Map(); - setIntervalHistory: Map = new Map(); - clearIntervalHistory: Map = new Map(); + setTimeoutHistory: Map = new Map(); + clearTimeoutHistory: Map = new Map(); + setIntervalHistory: Map = new Map(); + clearIntervalHistory: Map = new Map(); evalHistory: Map = new Map(); rafHistory: Map = new Map(); cafHistory: Map = new Map(); @@ -140,7 +151,7 @@ export class Wrapper { #getTraceDomain(trace: TTrace) { if (trace.link.startsWith(location.origin)) { - return ETraceDomain.LOCAL; + return ETraceDomain.SAME; } else if (REGEX_STACKTRACE_LINK_PROTOCOL.test(trace.link)) { return ETraceDomain.EXTERNAL; } @@ -169,9 +180,10 @@ export class Wrapper { }); } - timerOffline(handler: number) { + timerOffline(handler: number, canceledByTraceId: string | null) { const timer = this.onlineTimers.get(handler); if (!timer) { + // already offline return; } @@ -182,13 +194,14 @@ export class Wrapper { if (record) { record.isOnline = false; + record.canceledByTraceId = canceledByTraceId; } this.onlineTimers.delete(handler); } updateSetTimersHistory( - history: Map, + history: Map, handler: number, delay: number | undefined, callstack: TCallstack, @@ -220,12 +233,13 @@ export class Wrapper { traceId: callstack.traceId, trace: callstack.trace, traceDomain: this.#getTraceDomain(callstack.trace[0]), + canceledByTraceId: null, }); } } updateClearTimersHistory( - history: Map, + history: Map, handler: unknown, callstack: TCallstack ) { @@ -235,14 +249,11 @@ export class Wrapper { ? null : this.onlineTimers.get(handler); let handlerDelay: string | number | undefined = 'N/A'; - let handlerIsEval = undefined; if (onlineTimer) { handlerDelay = onlineTimer.delay; - handlerIsEval = onlineTimer.isEval; } else if (existing) { handlerDelay = existing.delay; - handlerIsEval = existing.isEval; } if (hasError) { @@ -253,17 +264,13 @@ export class Wrapper { existing.handler = handler; existing.delay = handlerDelay; existing.calls++; - existing.isEval = handlerIsEval; existing.hasError = hasError; - existing.isOnline = false; } else { history.set(callstack.traceId, { handler: handler, calls: 1, delay: handlerDelay, - isEval: handlerIsEval, hasError, - isOnline: false, traceId: callstack.traceId, trace: callstack.trace, traceDomain: this.#getTraceDomain(callstack.trace[0]), @@ -470,7 +477,7 @@ export class Wrapper { const isEval = typeof code === 'string'; const handler = this.native.setTimeout( (...params: any[]) => { - this.timerOffline(handler); + this.timerOffline(handler, null); if (isEval) { // see https://developer.mozilla.org/docs/Web/API/setTimeout#code this.native.eval(code); @@ -512,13 +519,17 @@ export class Wrapper { this: Wrapper, handler: number | undefined ) { + const callstack = this.createCallstack( + new Error(TRACE_ERROR_MESSAGE), + false + ); this.updateClearTimersHistory( this.clearTimeoutHistory, handler, - this.createCallstack(new Error(TRACE_ERROR_MESSAGE), false) + callstack ); if (handler !== undefined) { - this.timerOffline(handler); + this.timerOffline(handler, callstack.traceId); } this.callCounter.clearTimeout++; @@ -575,13 +586,17 @@ export class Wrapper { this: Wrapper, handler: number | undefined ) { + const callstack = this.createCallstack( + new Error(TRACE_ERROR_MESSAGE), + false + ); this.updateClearTimersHistory( this.clearIntervalHistory, handler, - this.createCallstack(new Error(TRACE_ERROR_MESSAGE), false) + callstack ); if (handler !== undefined) { - this.timerOffline(handler); + this.timerOffline(handler, callstack.traceId); } this.callCounter.clearInterval++; diff --git a/src/view/components/TimersHistory.svelte b/src/view/components/TimersHistory.svelte index a3ee115..f6902fa 100644 --- a/src/view/components/TimersHistory.svelte +++ b/src/view/components/TimersHistory.svelte @@ -1,5 +1,5 @@ -{#if traceDomain === ETraceDomain.LOCAL} - +{#if traceDomain === ETraceDomain.SAME} + {:else if traceDomain === ETraceDomain.EXTERNAL} {:else if traceDomain === ETraceDomain.UNKNOWN} From 1c6b85d372656797501943add4024ee399a73afb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=95=B7?= <3756473+zendive@users.noreply.github.com> Date: Fri, 19 Jul 2024 09:40:14 +0300 Subject: [PATCH 20/53] add test `canceledByTraceId` --- jest/tests/wrappers.test.ts | 8 ++++++-- src/api/wrappers.ts | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/jest/tests/wrappers.test.ts b/jest/tests/wrappers.test.ts index d5f3a45..1ca4780 100644 --- a/jest/tests/wrappers.test.ts +++ b/jest/tests/wrappers.test.ts @@ -44,26 +44,30 @@ describe('wrappers', () => { expect(wrapper.setTimeoutHistory.size).toBe(1); }); - test('setTimeoutHistory - isOnline becomes false after timer fired', async () => { + test('setTimeoutHistory - isOnline/canceledByTraceId handled after timer fired', async () => { const DELAY = 5; setTimeout(() => {}, DELAY); const rec = Array.from(wrapper.setTimeoutHistory.values())[0]; expect(rec.isOnline).toBe(true); + expect(rec.canceledByTraceId).toBe(null); await new Promise((resolve) => setTimeout(resolve, 2 * DELAY)); expect(rec.isOnline).toBe(false); + expect(rec.canceledByTraceId).toBe(null); }); - test('setTimeoutHistory - isOnline becomes false after timer canceled', () => { + test('setTimeoutHistory - isOnline/canceledByTraceId handled after timer canceled', () => { const DELAY = 123; const handler = setTimeout(() => {}, DELAY); const rec = Array.from(wrapper.setTimeoutHistory.values())[0]; expect(rec.isOnline).toBe(true); + expect(rec.canceledByTraceId).toBe(null); clearTimeout(handler); expect(rec.isOnline).toBe(false); + expect(rec.canceledByTraceId?.length).toBeGreaterThan(1); }); test('setTimeoutHistory - valid delay', () => { diff --git a/src/api/wrappers.ts b/src/api/wrappers.ts index 413ace3..3218e0f 100644 --- a/src/api/wrappers.ts +++ b/src/api/wrappers.ts @@ -222,6 +222,7 @@ export class Wrapper { existing.isEval = isEval; existing.hasError = hasError; existing.isOnline = true; + existing.canceledByTraceId = null; } else { history.set(callstack.traceId, { handler, From 44226470fbded45ec5468ddd0f11e0611caf528e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=95=B7?= <3756473+zendive@users.noreply.github.com> Date: Fri, 19 Jul 2024 14:14:39 +0300 Subject: [PATCH 21/53] show regressor for prematurely canceled timer --- public/global.css | 3 +- src/api/mediaMonitor.ts | 2 +- src/view/components/ActiveTimers.svelte | 2 +- src/view/components/AnimationHistory.svelte | 2 +- src/view/components/Timers.svelte | 19 +- ...story.svelte => TimersClearHistory.svelte} | 24 +-- .../TimersClearHistoryMetric.svelte | 18 ++ src/view/components/TimersSetHistory.svelte | 175 ++++++++++++++++++ src/view/components/Trace.svelte | 2 +- 9 files changed, 215 insertions(+), 32 deletions(-) rename src/view/components/{TimersHistory.svelte => TimersClearHistory.svelte} (73%) create mode 100644 src/view/components/TimersClearHistoryMetric.svelte create mode 100644 src/view/components/TimersSetHistory.svelte diff --git a/public/global.css b/public/global.css index 54f42d1..f325a01 100644 --- a/public/global.css +++ b/public/global.css @@ -1,4 +1,5 @@ -:root { +:root, +.light { --header-height: 20px; --bg: rgb(255 255 255); diff --git a/src/api/mediaMonitor.ts b/src/api/mediaMonitor.ts index e1e187a..de2f2dc 100644 --- a/src/api/mediaMonitor.ts +++ b/src/api/mediaMonitor.ts @@ -28,7 +28,7 @@ export type TMediaTelemetry = { collection: TMediaMetrics[]; }; -let mediaCollection: TMediaModel[] = []; +let mediaCollection: TMediaModel[]; export function meetMedia(els: NodeListOf) { // farewell old diff --git a/src/view/components/ActiveTimers.svelte b/src/view/components/ActiveTimers.svelte index 77d8655..f70410d 100644 --- a/src/view/components/ActiveTimers.svelte +++ b/src/view/components/ActiveTimers.svelte @@ -5,7 +5,7 @@ import { portPost } from '@/api/communication.ts'; export let caption: string = ''; - export let metrics: TOnlineTimerMetrics[] = []; + export let metrics: TOnlineTimerMetrics[]; function onRemoveHandler(metric: TOnlineTimerMetrics) { portPost({ diff --git a/src/view/components/AnimationHistory.svelte b/src/view/components/AnimationHistory.svelte index 8004e5b..46d1fd9 100644 --- a/src/view/components/AnimationHistory.svelte +++ b/src/view/components/AnimationHistory.svelte @@ -13,7 +13,7 @@ import { compareByFieldOrder } from '@/api/comparator.ts'; export let caption: string = ''; - export let metrics: TAnimationHistory[] = []; + export let metrics: TAnimationHistory[]; let field = DEFAULT_SORT.timersHistoryField; let order = DEFAULT_SORT.timersHistoryOrder; diff --git a/src/view/components/Timers.svelte b/src/view/components/Timers.svelte index 2a8b19c..17c01f2 100644 --- a/src/view/components/Timers.svelte +++ b/src/view/components/Timers.svelte @@ -2,13 +2,14 @@ import type { TMetrics } from '@/api-monitor-cs-main.ts'; import { ETimerType, type TOnlineTimerMetrics } from '@/api/wrappers.ts'; import ActiveTimers from '@/view/components/ActiveTimers.svelte'; - import TimersHistory from '@/view/components/TimersHistory.svelte'; + import TimersSetHistory from '@/view/components/TimersSetHistory.svelte'; + import TimersClearHistory from '@/view/components/TimersClearHistory.svelte'; import { compareByDelayHandlerDescending } from '@/api/comparator.ts'; export let metrics: TMetrics['wrapperMetrics']; - let timeouts: TOnlineTimerMetrics[] = []; - let intervals: TOnlineTimerMetrics[] = []; + let timeouts: TOnlineTimerMetrics[]; + let intervals: TOnlineTimerMetrics[]; $: { intervals = []; @@ -37,28 +38,32 @@ {/if} {#if metrics.setTimeoutHistory?.length} - {/if} {#if metrics.clearTimeoutHistory?.length} - {/if} {#if metrics.setIntervalHistory?.length} - {/if} {#if metrics.clearIntervalHistory?.length} - diff --git a/src/view/components/TimersHistory.svelte b/src/view/components/TimersClearHistory.svelte similarity index 73% rename from src/view/components/TimersHistory.svelte rename to src/view/components/TimersClearHistory.svelte index f6902fa..31b04b3 100644 --- a/src/view/components/TimersHistory.svelte +++ b/src/view/components/TimersClearHistory.svelte @@ -1,7 +1,6 @@ + + + + + + + + + {metric.handler} + {metric.delay} + diff --git a/src/view/components/TimersSetHistory.svelte b/src/view/components/TimersSetHistory.svelte new file mode 100644 index 0000000..e768d3c --- /dev/null +++ b/src/view/components/TimersSetHistory.svelte @@ -0,0 +1,175 @@ + + + + {#if timersClearHistoryMetric} +
+ ✖️ +
+ + {/if} +
+ + + + + + + + + + + + {#each metrics as metric (metric.traceId)} + + + + + + + + {/each} +
+ {caption} + +
Callstack + Called + + Handler + + Delay +
+ + + + {metric.handler}{metric.delay} + {#if metric.isOnline} + + {:else if metric.canceledByTraceId} + + void onShowRegressor(metric.canceledByTraceId)}>☠️ + {/if} +
+ + diff --git a/src/view/components/Trace.svelte b/src/view/components/Trace.svelte index c310b06..1ea1a6e 100644 --- a/src/view/components/Trace.svelte +++ b/src/view/components/Trace.svelte @@ -2,7 +2,7 @@ import { type TTrace, ETraceDomain } from '@/api/wrappers.ts'; import TraceLink from '@/view/components/TraceLink.svelte'; - export let trace: TTrace[] = []; + export let trace: TTrace[]; export let traceDomain: ETraceDomain; From 5c3c80859dd73ac207c0f4c844debeb709aee2f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=95=B7?= <3756473+zendive@users.noreply.github.com> Date: Fri, 19 Jul 2024 14:35:57 +0300 Subject: [PATCH 22/53] revert erroneous change --- src/api/mediaMonitor.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/mediaMonitor.ts b/src/api/mediaMonitor.ts index de2f2dc..e1e187a 100644 --- a/src/api/mediaMonitor.ts +++ b/src/api/mediaMonitor.ts @@ -28,7 +28,7 @@ export type TMediaTelemetry = { collection: TMediaMetrics[]; }; -let mediaCollection: TMediaModel[]; +let mediaCollection: TMediaModel[] = []; export function meetMedia(els: NodeListOf) { // farewell old From 45069912febb63b1ef7b7a1347b5b11a568a60e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=95=B7?= <3756473+zendive@users.noreply.github.com> Date: Sun, 21 Jul 2024 15:54:58 +0300 Subject: [PATCH 23/53] fix/improve sorting --- src/api/comparator.ts | 51 +++++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/src/api/comparator.ts b/src/api/comparator.ts index e251a32..0e91b59 100644 --- a/src/api/comparator.ts +++ b/src/api/comparator.ts @@ -1,45 +1,48 @@ import type { TOnlineTimerMetrics } from '@/api/wrappers.ts'; import { ESortOrder } from '@/api/settings.ts'; +// descending sort by `handler` field +function compareIfEqual( + field: Key, + first: T, + second: T +) { + if (field === 'calls' || field === 'delay') { + // @ts-ignore + return second['handler'] > first['handler'] ? 1 : -1; + } else { + return 0; + } +} + export function compareByFieldOrder( field: Key, order: ESortOrder ) { return function (first: T, second: T) { - const a = first[field]; - const b = second[field]; - - if (a === undefined) { - return ESortOrder.DESCENDING ? -1 : 1; - } else if (b === undefined) { - return ESortOrder.DESCENDING ? 1 : -1; - } + let a = first[field] || 0; + let b = second[field] || 0; if ( (typeof a === 'number' && typeof b === 'number') || (typeof a === 'string' && typeof b === 'string') ) { - return order === ESortOrder.DESCENDING - ? b > a - ? 1 - : b < a - ? -1 - : 0 - : a > b - ? 1 - : a < b - ? -1 - : 0; + if (order === ESortOrder.DESCENDING) { + return b > a ? 1 : b < a ? -1 : compareIfEqual(field, first, second); + } else { + return a > b ? 1 : a < b ? -1 : compareIfEqual(field, first, second); + } } else { - return typeof (ESortOrder.DESCENDING ? b : a) === 'number' ? -1 : 1; + return typeof (order === ESortOrder.DESCENDING ? b : a) === 'number' + ? -1 + : 1; } }; } -export function compareByDelayHandlerDescending( - a: T, - b: T -) { +export function compareByDelayThenHandlerDescending< + T extends TOnlineTimerMetrics, +>(a: T, b: T) { const aDelay = a.delay ?? 0; const bDelay = b.delay ?? 0; return bDelay > aDelay From ca362312706e54caf7aefb49316710b883b64e02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=95=B7?= <3756473+zendive@users.noreply.github.com> Date: Sun, 21 Jul 2024 16:33:35 +0300 Subject: [PATCH 24/53] improve traceDomain and isOnline metric indicators --- public/global.css | 4 +++ public/img/scheduled.svg | 4 +++ src/api-monitor-cs-main.ts | 34 +++++++++++-------- src/api/const.ts | 5 +-- src/view/components/ActiveTimers.svelte | 18 +++++++--- src/view/components/AnimationHistory.svelte | 14 +++++--- src/view/components/EvalMetrics.svelte | 24 ++++++++----- src/view/components/Timers.svelte | 4 +-- src/view/components/TimersClearHistory.svelte | 7 ++++ .../TimersClearHistoryMetric.svelte | 4 ++- src/view/components/TimersSetHistory.svelte | 27 ++++++++++----- src/view/components/Trace.svelte | 11 +----- src/view/components/TraceDomain.svelte | 13 +++++++ 13 files changed, 113 insertions(+), 56 deletions(-) create mode 100644 public/img/scheduled.svg create mode 100644 src/view/components/TraceDomain.svelte diff --git a/public/global.css b/public/global.css index f325a01..02ee1ec 100644 --- a/public/global.css +++ b/public/global.css @@ -207,3 +207,7 @@ th, -webkit-mask-image: url(img/trace-local.svg); mask-image: url(img/trace-local.svg); } +.icon.-scheduled { + -webkit-mask-image: url(img/scheduled.svg); + mask-image: url(img/scheduled.svg); +} diff --git a/public/img/scheduled.svg b/public/img/scheduled.svg new file mode 100644 index 0000000..bd37c8d --- /dev/null +++ b/public/img/scheduled.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/api-monitor-cs-main.ts b/src/api-monitor-cs-main.ts index 9c2d8b4..61f3334 100644 --- a/src/api-monitor-cs-main.ts +++ b/src/api-monitor-cs-main.ts @@ -1,8 +1,9 @@ import { windowListen, windowPost } from '@/api/communication.ts'; import { IS_DEV } from './api/env.ts'; import { - UI_UPDATE_FREQUENCY_LOW, - UI_UPDATE_FREQUENCY_VERYLOW, + TELEMETRY_FREQUENCY_5PS, + TELEMETRY_FREQUENCY_1PS, + TELEMETRY_FREQUENCY_60PS, } from '@/api/const.ts'; import { MeanAggregator, Stopper, Timer } from '@/api/time.ts'; import { @@ -50,16 +51,21 @@ const eachSecond = new Timer( ); const tick = new Timer( function apiMonitorPostMetric() { - meanExecutionTime.add(tick.executionTime); - // adaptive update-frequency - if (0 < tick.executionTime && tick.executionTime < 3) { - tick.options.animation = true; - } else { - tick.options.animation = false; - tick.delay = - tick.executionTime < 6 - ? UI_UPDATE_FREQUENCY_LOW - : UI_UPDATE_FREQUENCY_VERYLOW; + if (0 < tick.executionTime) { + meanExecutionTime.add(tick.executionTime); + + // adaptive update-frequency + if ( + meanExecutionTime.mean < 3 && + meanExecutionTime.standardDeviation < 1 + ) { + tick.delay = TELEMETRY_FREQUENCY_60PS; + } else { + tick.delay = + meanExecutionTime.mean < 8 + ? TELEMETRY_FREQUENCY_5PS + : TELEMETRY_FREQUENCY_1PS; + } } const metrics: TMetrics = { @@ -71,8 +77,8 @@ const tick = new Timer( windowPost({ msg: 'telemetry', metrics }); }, - UI_UPDATE_FREQUENCY_LOW, - { interval: true, animation: true, measurable: true } + TELEMETRY_FREQUENCY_5PS, + { interval: true, animation: false, measurable: true } ); function startObserve() { diff --git a/src/api/const.ts b/src/api/const.ts index 795e1b1..7f19b65 100644 --- a/src/api/const.ts +++ b/src/api/const.ts @@ -2,8 +2,9 @@ export const ERRORS_IGNORED = [ 'Could not establish connection. Receiving end does not exist.', 'The message port closed before a response was received.', ]; -export const UI_UPDATE_FREQUENCY_LOW = 200; // ms -export const UI_UPDATE_FREQUENCY_VERYLOW = 1000; // ms +export const TELEMETRY_FREQUENCY_60PS = 100 / 6; //MS +export const TELEMETRY_FREQUENCY_5PS = 200; // ms +export const TELEMETRY_FREQUENCY_1PS = 1000; // ms // store native functions export const setTimeout = window.setTimeout.bind(window); export const clearTimeout = window.clearTimeout.bind(window); diff --git a/src/view/components/ActiveTimers.svelte b/src/view/components/ActiveTimers.svelte index f70410d..932860f 100644 --- a/src/view/components/ActiveTimers.svelte +++ b/src/view/components/ActiveTimers.svelte @@ -2,6 +2,7 @@ import type { TOnlineTimerMetrics } from '@/api/wrappers.ts'; import Variable from '@/view/components/Variable.svelte'; import Trace from '@/view/components/Trace.svelte'; + import TraceDomain from '@/view/components/TraceDomain.svelte'; import { portPost } from '@/api/communication.ts'; export let caption: string = ''; @@ -20,9 +21,16 @@ {caption} - DelayHandlerCallstack + + + Delay + Handler + Callstack + + {#each metrics as metric (metric.handler)} + {metric.delay} {metric.handler} @@ -36,16 +44,16 @@ /> - + {/each} diff --git a/src/view/components/EvalMetrics.svelte b/src/view/components/EvalMetrics.svelte index d24075f..6b559a2 100644 --- a/src/view/components/EvalMetrics.svelte +++ b/src/view/components/EvalMetrics.svelte @@ -1,9 +1,10 @@ + - + diff --git a/src/view/components/TimersSetHistory.svelte b/src/view/components/TimersSetHistory.svelte index e768d3c..920b9ce 100644 --- a/src/view/components/TimersSetHistory.svelte +++ b/src/view/components/TimersSetHistory.svelte @@ -2,6 +2,7 @@ import type { TClearTimerHistory, TSetTimerHistory } from '@/api/wrappers.ts'; import Variable from '@/view/components/Variable.svelte'; import Trace from '@/view/components/Trace.svelte'; + import TraceDomain from '@/view/components/TraceDomain.svelte'; import { DEFAULT_SORT, getSettings, @@ -81,10 +82,13 @@ {#if timersClearHistoryMetric}
✖️ + +
+ Callstack Delay - + {#each metrics as metric (metric.traceId)} + - + @@ -142,14 +145,17 @@ {metric.delay} {#if metric.isOnline} - + {:else if metric.canceledByTraceId} - void onShowRegressor(metric.canceledByTraceId)}>☠️ + + {/if} @@ -157,6 +163,9 @@ diff --git a/src/view/components/EvalMetrics.svelte b/src/view/components/EvalMetrics.svelte index 6b559a2..dd24c1d 100644 --- a/src/view/components/EvalMetrics.svelte +++ b/src/view/components/EvalMetrics.svelte @@ -65,7 +65,7 @@ diff --git a/src/view/components/TimersSetHistory.svelte b/src/view/components/TimersSetHistory.svelte index 920b9ce..90b6372 100644 --- a/src/view/components/TimersSetHistory.svelte +++ b/src/view/components/TimersSetHistory.svelte @@ -164,7 +164,7 @@ diff --git a/src/view/components/TimersSetHistory.svelte b/src/view/components/TimersSetHistory.svelte index 3a39487..44b3e09 100644 --- a/src/view/components/TimersSetHistory.svelte +++ b/src/view/components/TimersSetHistory.svelte @@ -91,6 +91,16 @@ {#if timersClearHistoryMetric}
+
+
+ Places from which timer with current callstack was prematurely + canceled: +
+
+ The information is actual only on time of demand. For full coverage - + requires both clearTimeout and clearInterval panels enabled. +
+
Date: Wed, 31 Jul 2024 15:36:27 +0300 Subject: [PATCH 39/53] on `content-script-loaded` event - don't post `start-observe` if panel is hidden --- src/api-monitor-devtools.ts | 4 +++- src/api/settings.ts | 1 + src/view/App.svelte | 19 +++++++++---------- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/api-monitor-devtools.ts b/src/api-monitor-devtools.ts index dab0839..eda898a 100644 --- a/src/api-monitor-devtools.ts +++ b/src/api-monitor-devtools.ts @@ -1,5 +1,5 @@ import { portPost } from '@/api/communication.ts'; -import { getSettings } from '@/api/settings.ts'; +import { getSettings, setSettings } from '@/api/settings.ts'; // tabId may be null if user opened the devtools of the devtools if (chrome.devtools.inspectedWindow.tabId !== null) { @@ -13,9 +13,11 @@ if (chrome.devtools.inspectedWindow.tabId !== null) { if (!settings.paused) { portPost({ msg: 'start-observe' }); } + setSettings({ devtoolsPanelShown: true }); }); panel.onHidden.addListener(() => { portPost({ msg: 'stop-observe' }); + setSettings({ devtoolsPanelShown: false }); }); } ); diff --git a/src/api/settings.ts b/src/api/settings.ts index 97cb800..209d2f1 100644 --- a/src/api/settings.ts +++ b/src/api/settings.ts @@ -63,6 +63,7 @@ export const DEFAULT_SETTINGS = { panels: DEFAULT_PANELS, sort: DEFAULT_SORT, paused: false, + devtoolsPanelShown: false, }; export function panelsArrayToVisibilityMap(panels: TSettingsPanel[]) { diff --git a/src/view/App.svelte b/src/view/App.svelte index 92e2db4..c82a6c4 100644 --- a/src/view/App.svelte +++ b/src/view/App.svelte @@ -18,10 +18,13 @@ let paused = false; let msg: TMetrics; - runtimeListen((o) => { - if (o.msg === 'content-script-loaded' && !paused) { - // TODO: ... - portPost({ msg: 'start-observe' }); + runtimeListen(async (o) => { + if (o.msg === 'content-script-loaded') { + const settings = await getSettings(); + + if (settings.devtoolsPanelShown && !settings.paused) { + portPost({ msg: 'start-observe' }); + } } else if (o.msg === 'telemetry') { msg = o.metrics; @@ -43,12 +46,8 @@ }); onMount(() => { - getSettings().then((state) => { - paused = state.paused; - - if (!paused) { - portPost({ msg: 'start-observe' }); - } + getSettings().then((settings) => { + paused = settings.paused; }); window.addEventListener('beforeunload', () => { From 3922a0898747708d4962f8b0b3ed50107eae13aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=95=B7?= <3756473+zendive@users.noreply.github.com> Date: Wed, 31 Jul 2024 17:02:18 +0300 Subject: [PATCH 40/53] package replace js-sha256 with @noble/hashes --- jest/tests/wrappers.test.ts | 3 +++ package.json | 2 +- pnpm-lock.yaml | 17 +++++++++-------- src/api/const.ts | 1 - src/api/hash.ts | 8 ++++++++ src/api/wrappers.ts | 9 ++++----- 6 files changed, 25 insertions(+), 15 deletions(-) create mode 100644 src/api/hash.ts diff --git a/jest/tests/wrappers.test.ts b/jest/tests/wrappers.test.ts index 3bf1b4d..2638f3f 100644 --- a/jest/tests/wrappers.test.ts +++ b/jest/tests/wrappers.test.ts @@ -6,6 +6,9 @@ import { TAG_EVAL_RETURN_SET_INTERVAL, TRACE_ERROR_MESSAGE, } from '../../src/api/const.ts'; +import { TextEncoder } from 'node:util'; + +global.TextEncoder = TextEncoder; describe('wrappers', () => { let wrapper: Wrapper; diff --git a/package.json b/package.json index a5e4d1a..9f63f92 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,6 @@ "webpack-cli": "5.1.4" }, "dependencies": { - "js-sha256": "^0.11.0" + "@noble/hashes": "^1.4.0" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3438778..527d32e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,9 +8,9 @@ importers: .: dependencies: - js-sha256: - specifier: ^0.11.0 - version: 0.11.0 + '@noble/hashes': + specifier: ^1.4.0 + version: 1.4.0 devDependencies: '@jest/globals': specifier: ^29.7.0 @@ -651,6 +651,10 @@ packages: '@jridgewell/trace-mapping@0.3.9': resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + '@noble/hashes@1.4.0': + resolution: {integrity: sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==} + engines: {node: '>= 16'} + '@sinclair/typebox@0.27.8': resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} @@ -1652,9 +1656,6 @@ packages: node-notifier: optional: true - js-sha256@0.11.0: - resolution: {integrity: sha512-6xNlKayMZvds9h1Y1VWc0fQHQ82BxTXizWPEtEeGvmOUYpBRy4gbWroHLpzowe6xiQhHpelCQiE7HEdznyBL9Q==} - js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -3063,6 +3064,8 @@ snapshots: '@jridgewell/resolve-uri': 3.1.1 '@jridgewell/sourcemap-codec': 1.4.15 + '@noble/hashes@1.4.0': {} + '@sinclair/typebox@0.27.8': {} '@sinonjs/commons@3.0.1': @@ -4307,8 +4310,6 @@ snapshots: - supports-color - ts-node - js-sha256@0.11.0: {} - js-tokens@4.0.0: {} js-yaml@3.14.1: diff --git a/src/api/const.ts b/src/api/const.ts index 1ae289c..65c949a 100644 --- a/src/api/const.ts +++ b/src/api/const.ts @@ -124,4 +124,3 @@ export const REGEX_STACKTRACE_LINE_NUMBER = new RegExp(/.*:(\d+):\d+$/); export const REGEX_STACKTRACE_COLUMN_NUMBER = new RegExp(/.*:\d+:(\d+)$/); export const REGEX_STACKTRACE_LINK_PROTOCOL = new RegExp(/http[s]?\:\/\//); export const FRAME_1of60 = 1 / 60; -export const SHA256_HEX_STRING_LENGTH = 64; diff --git a/src/api/hash.ts b/src/api/hash.ts new file mode 100644 index 0000000..4fe63c6 --- /dev/null +++ b/src/api/hash.ts @@ -0,0 +1,8 @@ +import { sha256 } from '@noble/hashes/sha256'; +import { bytesToHex } from '@noble/hashes/utils'; + +export const HASH_STRING_LENGTH = 64; + +export function hashString(str: string): string { + return bytesToHex(sha256(str)); +} diff --git a/src/api/wrappers.ts b/src/api/wrappers.ts index 4aeeb98..5111f6d 100644 --- a/src/api/wrappers.ts +++ b/src/api/wrappers.ts @@ -13,13 +13,12 @@ import { REGEX_STACKTRACE_CLEAN_URL, REGEX_STACKTRACE_LINK_PROTOCOL, TAG_INVALID_CALLSTACK_LINK, - SHA256_HEX_STRING_LENGTH, TAG_EVAL_RETURN_SET_TIMEOUT, TAG_EVAL_RETURN_SET_INTERVAL, } from '@/api/const.ts'; import { TAG_EXCEPTION, cloneObjectSafely } from '@/api/clone.ts'; import type { TPanelVisibilityMap } from '@/api/settings.ts'; -import { sha256 } from 'js-sha256'; +import { HASH_STRING_LENGTH, hashString } from '@/api//hash.ts'; export type TTrace = { name: string | 0; @@ -647,7 +646,7 @@ export class Wrapper { if (typeof uniqueTrait === 'function') { name = uniqueTrait.name || 0; - traceId = sha256(String(uniqueTrait)); + traceId = hashString(String(uniqueTrait)); } else { traceId = String(uniqueTrait); } @@ -658,8 +657,8 @@ export class Wrapper { }); } - if (traceId.length > SHA256_HEX_STRING_LENGTH) { - traceId = sha256(traceId); + if (traceId.length > HASH_STRING_LENGTH) { + traceId = hashString(traceId); } return { traceId, trace }; From 98d422c7423e7f0ab8c4a1f813b408bf7f7ac1bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=95=B7?= <3756473+zendive@users.noreply.github.com> Date: Wed, 31 Jul 2024 17:14:37 +0300 Subject: [PATCH 41/53] update deps --- README.md | 2 +- package.json | 6 +- pnpm-lock.yaml | 1090 +++++++++++------------- src/view/components/EvalMetrics.svelte | 1 + 4 files changed, 520 insertions(+), 579 deletions(-) diff --git a/README.md b/README.md index 8e48a8f..369da04 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ To explore the internals of a complex systems. ### Build requirements - OS: Linux -- Node: 20.15.0 (LTS) +- Node: 20.16.0 (LTS) ### Build instructions diff --git a/package.json b/package.json index 9f63f92..248d935 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "@jest/globals": "^29.7.0", "@types/chrome": "^0.0.269", "@types/jest": "^29.5.12", - "@types/node": "^20.14.12", + "@types/node": "^22.0.0", "css-loader": "^7.1.2", "esbuild": "0.23.0", "esbuild-loader": "4.2.2", @@ -14,12 +14,12 @@ "prettier": "3.3.3", "sass": "^1.77.8", "svelte": "^4.2.18", - "svelte-check": "^3.8.4", + "svelte-check": "^3.8.5", "svelte-loader": "^3.2.3", "svelte-preprocess": "^6.0.2", "ts-jest": "^29.2.3", "ts-node": "^10.9.2", - "tsx": "^4.16.2", + "tsx": "^4.16.3", "typescript": "^5.5.4", "webpack": "5.93.0", "webpack-cli": "5.1.4" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 527d32e..4a2f991 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -22,8 +22,8 @@ importers: specifier: ^29.5.12 version: 29.5.12 '@types/node': - specifier: ^20.14.12 - version: 20.14.12 + specifier: ^22.0.0 + version: 22.0.0 css-loader: specifier: ^7.1.2 version: 7.1.2(webpack@5.93.0(esbuild@0.23.0)(webpack-cli@5.1.4)) @@ -35,7 +35,7 @@ importers: version: 4.2.2(webpack@5.93.0(esbuild@0.23.0)(webpack-cli@5.1.4)) jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@20.14.12)(ts-node@10.9.2(@types/node@20.14.12)(typescript@5.5.4)) + version: 29.7.0(@types/node@22.0.0)(ts-node@10.9.2(@types/node@22.0.0)(typescript@5.5.4)) jest-environment-jsdom: specifier: ^29.7.0 version: 29.7.0 @@ -52,23 +52,23 @@ importers: specifier: ^4.2.18 version: 4.2.18 svelte-check: - specifier: ^3.8.4 - version: 3.8.4(@babel/core@7.24.5)(postcss@8.4.35)(sass@1.77.8)(svelte@4.2.18) + specifier: ^3.8.5 + version: 3.8.5(@babel/core@7.25.2)(postcss@8.4.40)(sass@1.77.8)(svelte@4.2.18) svelte-loader: specifier: ^3.2.3 version: 3.2.3(svelte@4.2.18) svelte-preprocess: specifier: ^6.0.2 - version: 6.0.2(@babel/core@7.24.5)(postcss@8.4.35)(sass@1.77.8)(svelte@4.2.18)(typescript@5.5.4) + version: 6.0.2(@babel/core@7.25.2)(postcss@8.4.40)(sass@1.77.8)(svelte@4.2.18)(typescript@5.5.4) ts-jest: specifier: ^29.2.3 - version: 29.2.3(@babel/core@7.24.5)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.5))(esbuild@0.23.0)(jest@29.7.0(@types/node@20.14.12)(ts-node@10.9.2(@types/node@20.14.12)(typescript@5.5.4)))(typescript@5.5.4) + version: 29.2.3(@babel/core@7.25.2)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.2))(esbuild@0.23.0)(jest@29.7.0(@types/node@22.0.0)(ts-node@10.9.2(@types/node@22.0.0)(typescript@5.5.4)))(typescript@5.5.4) ts-node: specifier: ^10.9.2 - version: 10.9.2(@types/node@20.14.12)(typescript@5.5.4) + version: 10.9.2(@types/node@22.0.0)(typescript@5.5.4) tsx: - specifier: ^4.16.2 - version: 4.16.2 + specifier: ^4.16.3 + version: 4.16.3 typescript: specifier: ^5.5.4 version: 5.5.4 @@ -81,86 +81,70 @@ importers: packages: - '@ampproject/remapping@2.2.1': - resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==} + '@ampproject/remapping@2.3.0': + resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} - '@babel/code-frame@7.24.2': - resolution: {integrity: sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==} + '@babel/code-frame@7.24.7': + resolution: {integrity: sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==} engines: {node: '>=6.9.0'} - '@babel/compat-data@7.24.4': - resolution: {integrity: sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==} + '@babel/compat-data@7.25.2': + resolution: {integrity: sha512-bYcppcpKBvX4znYaPEeFau03bp89ShqNMLs+rmdptMw+heSZh9+z84d2YG+K7cYLbWwzdjtDoW/uqZmPjulClQ==} engines: {node: '>=6.9.0'} - '@babel/core@7.24.5': - resolution: {integrity: sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA==} + '@babel/core@7.25.2': + resolution: {integrity: sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==} engines: {node: '>=6.9.0'} - '@babel/generator@7.24.5': - resolution: {integrity: sha512-x32i4hEXvr+iI0NEoEfDKzlemF8AmtOP8CcrRaEcpzysWuoEb1KknpcvMsHKPONoKZiDuItklgWhB18xEhr9PA==} + '@babel/generator@7.25.0': + resolution: {integrity: sha512-3LEEcj3PVW8pW2R1SR1M89g/qrYk/m/mB/tLqn7dn4sbBUQyTqnlod+II2U4dqiGtUmkcnAmkMDralTFZttRiw==} engines: {node: '>=6.9.0'} - '@babel/helper-compilation-targets@7.23.6': - resolution: {integrity: sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==} + '@babel/helper-compilation-targets@7.25.2': + resolution: {integrity: sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==} engines: {node: '>=6.9.0'} - '@babel/helper-environment-visitor@7.22.20': - resolution: {integrity: sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==} + '@babel/helper-module-imports@7.24.7': + resolution: {integrity: sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==} engines: {node: '>=6.9.0'} - '@babel/helper-function-name@7.23.0': - resolution: {integrity: sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==} - engines: {node: '>=6.9.0'} - - '@babel/helper-hoist-variables@7.22.5': - resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==} - engines: {node: '>=6.9.0'} - - '@babel/helper-module-imports@7.24.3': - resolution: {integrity: sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==} - engines: {node: '>=6.9.0'} - - '@babel/helper-module-transforms@7.24.5': - resolution: {integrity: sha512-9GxeY8c2d2mdQUP1Dye0ks3VDyIMS98kt/llQ2nUId8IsWqTF0l1LkSX0/uP7l7MCDrzXS009Hyhe2gzTiGW8A==} + '@babel/helper-module-transforms@7.25.2': + resolution: {integrity: sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-plugin-utils@7.24.5': - resolution: {integrity: sha512-xjNLDopRzW2o6ba0gKbkZq5YWEBaK3PCyTOY1K2P/O07LGMhMqlMXPxwN4S5/RhWuCobT8z0jrlKGlYmeR1OhQ==} + '@babel/helper-plugin-utils@7.24.8': + resolution: {integrity: sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==} engines: {node: '>=6.9.0'} - '@babel/helper-simple-access@7.24.5': - resolution: {integrity: sha512-uH3Hmf5q5n7n8mz7arjUlDOCbttY/DW4DYhE6FUsjKJ/oYC1kQQUvwEQWxRwUpX9qQKRXeqLwWxrqilMrf32sQ==} + '@babel/helper-simple-access@7.24.7': + resolution: {integrity: sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==} engines: {node: '>=6.9.0'} - '@babel/helper-split-export-declaration@7.24.5': - resolution: {integrity: sha512-5CHncttXohrHk8GWOFCcCl4oRD9fKosWlIRgWm4ql9VYioKm52Mk2xsmoohvm7f3JoiLSM5ZgJuRaf5QZZYd3Q==} + '@babel/helper-string-parser@7.24.8': + resolution: {integrity: sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==} engines: {node: '>=6.9.0'} - '@babel/helper-string-parser@7.24.1': - resolution: {integrity: sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==} + '@babel/helper-validator-identifier@7.24.7': + resolution: {integrity: sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@7.24.5': - resolution: {integrity: sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA==} + '@babel/helper-validator-option@7.24.8': + resolution: {integrity: sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-option@7.23.5': - resolution: {integrity: sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==} + '@babel/helpers@7.25.0': + resolution: {integrity: sha512-MjgLZ42aCm0oGjJj8CtSM3DB8NOOf8h2l7DCTePJs29u+v7yO/RBX9nShlKMgFnRks/Q4tBAe7Hxnov9VkGwLw==} engines: {node: '>=6.9.0'} - '@babel/helpers@7.24.5': - resolution: {integrity: sha512-CiQmBMMpMQHwM5m01YnrM6imUG1ebgYJ+fAIW4FZe6m4qHTPaRHti+R8cggAwkdz4oXhtO4/K9JWlh+8hIfR2Q==} + '@babel/highlight@7.24.7': + resolution: {integrity: sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==} engines: {node: '>=6.9.0'} - '@babel/highlight@7.24.5': - resolution: {integrity: sha512-8lLmua6AVh/8SLJRRVD6V8p73Hir9w5mJrhE+IPpILG31KKlI9iz5zmBYKcWPS59qSfgP9RaSBQSHHE81WKuEw==} - engines: {node: '>=6.9.0'} - - '@babel/parser@7.24.5': - resolution: {integrity: sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg==} + '@babel/parser@7.25.3': + resolution: {integrity: sha512-iLTJKDbJ4hMvFPgQwwsVoxtHyWpKKPBrxkANrSYewDPaPpT5py5yeVkgPIJ7XYXhndxJpaA3PyALSXQ7u8e/Dw==} engines: {node: '>=6.0.0'} hasBin: true @@ -189,8 +173,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-jsx@7.24.1': - resolution: {integrity: sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA==} + '@babel/plugin-syntax-jsx@7.24.7': + resolution: {integrity: sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -231,22 +215,22 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-typescript@7.24.1': - resolution: {integrity: sha512-Yhnmvy5HZEnHUty6i++gcfH1/l68AHnItFHnaCv6hn9dNh0hQvvQJsxpi4BMBFN5DLeHBuucT/0DgzXif/OyRw==} + '@babel/plugin-syntax-typescript@7.24.7': + resolution: {integrity: sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/template@7.24.0': - resolution: {integrity: sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==} + '@babel/template@7.25.0': + resolution: {integrity: sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==} engines: {node: '>=6.9.0'} - '@babel/traverse@7.24.5': - resolution: {integrity: sha512-7aaBLeDQ4zYcUFDUD41lJc1fG8+5IU9DaNSJAgal866FGvmD5EbWQgnEC6kO1gGLsX0esNkfnJSndbTXA3r7UA==} + '@babel/traverse@7.25.3': + resolution: {integrity: sha512-HefgyP1x754oGCsKmV5reSmtV7IXj/kpaE1XYY+D9G5PvKKoFfSbiS4M77MdjuwlZKDIKFCffq9rPU+H/s3ZdQ==} engines: {node: '>=6.9.0'} - '@babel/types@7.24.5': - resolution: {integrity: sha512-6mQNsaLeXTw0nxYUYu+NSa4Hx4BlF1x1x8/PMFbiR+GBSr+2DkECc69b8hgy2frEodNcvPffeH8YfWd3LI6jhQ==} + '@babel/types@7.25.2': + resolution: {integrity: sha512-YTnYtra7W9e6/oAZEHj0bJehPRUlLH9/fbpT5LfB0NhQXyALCRkRs3zH9v07IYhkgpqX6Z78FnuccZr/l4Fs4Q==} engines: {node: '>=6.9.0'} '@bcoe/v8-coverage@0.2.3': @@ -616,34 +600,23 @@ packages: resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - '@jridgewell/gen-mapping@0.3.3': - resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==} - engines: {node: '>=6.0.0'} - '@jridgewell/gen-mapping@0.3.5': resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} engines: {node: '>=6.0.0'} - '@jridgewell/resolve-uri@3.1.1': - resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==} - engines: {node: '>=6.0.0'} - - '@jridgewell/set-array@1.1.2': - resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} '@jridgewell/set-array@1.2.1': resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} engines: {node: '>=6.0.0'} - '@jridgewell/source-map@0.3.5': - resolution: {integrity: sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==} - - '@jridgewell/sourcemap-codec@1.4.15': - resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + '@jridgewell/source-map@0.3.6': + resolution: {integrity: sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==} - '@jridgewell/trace-mapping@0.3.22': - resolution: {integrity: sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==} + '@jridgewell/sourcemap-codec@1.5.0': + resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} '@jridgewell/trace-mapping@0.3.25': resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} @@ -689,8 +662,8 @@ packages: '@types/babel__template@7.4.4': resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} - '@types/babel__traverse@7.20.5': - resolution: {integrity: sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==} + '@types/babel__traverse@7.20.6': + resolution: {integrity: sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==} '@types/chrome@0.0.269': resolution: {integrity: sha512-vF7x8YywnhXX2F06njQ/OE7a3Qeful43C5GUOsUksXWk89WoSFUU3iLeZW8lDpVO9atm8iZIEiLQTRC3H7NOXQ==} @@ -698,14 +671,14 @@ packages: '@types/eslint-scope@3.7.7': resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==} - '@types/eslint@8.56.5': - resolution: {integrity: sha512-u5/YPJHo1tvkSF2CE0USEkxon82Z5DBy2xR+qfyYNszpX9qcs4sT6uq2kBbj4BXY1+DBGDPnrhMZV3pKWGNukw==} + '@types/eslint@9.6.0': + resolution: {integrity: sha512-gi6WQJ7cHRgZxtkQEoyHMppPjq9Kxo5Tjn2prSKDSmZrCz8TZ3jSRCeTJm+WoM+oB0WG37bRqLzaaU3q7JypGg==} '@types/estree@1.0.5': resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} - '@types/filesystem@0.0.35': - resolution: {integrity: sha512-1eKvCaIBdrD2mmMgy5dwh564rVvfEhZTWVQQGRNn0Nt4ZEnJ0C8oSUCzvMKRA4lGde5oEVo+q2MrTTbV/GHDCQ==} + '@types/filesystem@0.0.36': + resolution: {integrity: sha512-vPDXOZuannb9FZdxgHnqSwAG/jvdGM8Wq+6N4D/d80z+D4HWH+bItqsZaVRQykAn6WEVeEkLm2oQigyHtgb0RA==} '@types/filewriter@0.0.33': resolution: {integrity: sha512-xFU8ZXTw4gd358lb2jw25nxY9QAgqn2+bKKjKOYfNCzN4DKCFetK7sPtrlpg66Ywe3vWY9FNxprZawAh9wfJ3g==} @@ -734,8 +707,8 @@ packages: '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - '@types/node@20.14.12': - resolution: {integrity: sha512-r7wNXakLeSsGT0H1AU863vS2wa5wBOK4bWMjZz2wj+8nBx+m5PeIn0k8AloSLpRuiwdRQZwarZqHE4FNArPuJQ==} + '@types/node@22.0.0': + resolution: {integrity: sha512-VT7KSYudcPOzP5Q0wfbowyNLaVR8QWUdw+088uFWwfvpY6uCWaXpqV6ieLAu9WBcnTa7H4Z5RLK8I5t2FuOcqw==} '@types/pug@2.0.10': resolution: {integrity: sha512-Sk/uYFOBAB7mb74XcpizmH0KOR2Pv3D2Hmrh1Dmy5BmK3MpdSa5kqZcg6EKBdklU0bFXX9gCfzvpnyUehrPIuA==} @@ -840,12 +813,12 @@ packages: peerDependencies: acorn: ^8 - acorn-walk@8.3.2: - resolution: {integrity: sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==} + acorn-walk@8.3.3: + resolution: {integrity: sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==} engines: {node: '>=0.4.0'} - acorn@8.11.3: - resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} + acorn@8.12.1: + resolution: {integrity: sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==} engines: {node: '>=0.4.0'} hasBin: true @@ -874,8 +847,8 @@ packages: ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - ajv@8.12.0: - resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} + ajv@8.17.1: + resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} ansi-escapes@4.3.2: resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} @@ -916,8 +889,9 @@ packages: asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - axobject-query@4.0.0: - resolution: {integrity: sha512-+60uv1hiVFhHZeO+Lz0RYzsVHy5Wr1ayX0mwda9KPDVLNJgZ1T9Ny7VmFbLDzxsH0D87I86vgj3gFrjTJUYznw==} + axobject-query@4.1.0: + resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} + engines: {node: '>= 0.4'} babel-jest@29.7.0: resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==} @@ -950,8 +924,8 @@ packages: big.js@5.2.2: resolution: {integrity: sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==} - binary-extensions@2.2.0: - resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} + binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} brace-expansion@1.1.11: @@ -960,12 +934,12 @@ packages: brace-expansion@2.0.1: resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} - braces@3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} - browserslist@4.23.0: - resolution: {integrity: sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==} + browserslist@4.23.2: + resolution: {integrity: sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true @@ -976,8 +950,9 @@ packages: bser@2.1.1: resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} - buffer-crc32@0.2.13: - resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} + buffer-crc32@1.0.0: + resolution: {integrity: sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==} + engines: {node: '>=8.0.0'} buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} @@ -994,8 +969,8 @@ packages: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} - caniuse-lite@1.0.30001597: - resolution: {integrity: sha512-7LjJvmQU6Sj7bL0j5b5WY/3n7utXUJvAe1lxhsHDbLmwX9mdL86Yjtr+5SRCyf8qME4M7pU2hswj0FpyBVCv9w==} + caniuse-lite@1.0.30001645: + resolution: {integrity: sha512-GFtY2+qt91kzyMk6j48dJcwJVq5uTkk71XxE3RtScx7XWRLsO7bU44LOFkOZYR8w9YMS0UhPSYpN/6rAMImmLw==} chalk@2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} @@ -1013,8 +988,8 @@ packages: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} - chrome-trace-event@1.0.3: - resolution: {integrity: sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==} + chrome-trace-event@1.0.4: + resolution: {integrity: sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==} engines: {node: '>=6.0'} ci-info@3.9.0: @@ -1122,8 +1097,8 @@ packages: resolution: {integrity: sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==} engines: {node: '>=12'} - debug@4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + debug@4.3.6: + resolution: {integrity: sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==} engines: {node: '>=6.0'} peerDependencies: supports-color: '*' @@ -1180,8 +1155,8 @@ packages: engines: {node: '>=0.10.0'} hasBin: true - electron-to-chromium@1.4.701: - resolution: {integrity: sha512-K3WPQ36bUOtXg/1+69bFlFOvdSm0/0bGqmsfPDLRXLanoKXdA+pIWuf/VbA9b+2CwBFuONgl4NEz4OEm+OJOKA==} + electron-to-chromium@1.5.4: + resolution: {integrity: sha512-orzA81VqLyIGUEA77YkVA1D+N+nNfl2isJVjjmOyrlxuooZ19ynb+dOlaDTqd/idKRS9lDCSBmtzM+kyCsMnkA==} emittery@0.13.1: resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} @@ -1194,24 +1169,24 @@ packages: resolution: {integrity: sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==} engines: {node: '>= 4'} - enhanced-resolve@5.17.0: - resolution: {integrity: sha512-dwDPwZL0dmye8Txp2gzFmA6sxALaSvdRDjPH0viLcKrtlOL3tw62nWWweVD1SdILDTJrbrL6tdWVN58Wo6U3eA==} + enhanced-resolve@5.17.1: + resolution: {integrity: sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==} engines: {node: '>=10.13.0'} entities@4.5.0: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} - envinfo@7.11.1: - resolution: {integrity: sha512-8PiZgZNIB4q/Lw4AhOvAfB/ityHAd2bli3lESSWmWSzSsl5dKpy5N1d1Rfkd2teq/g9xN90lc6o98DOjMeYHpg==} + envinfo@7.13.0: + resolution: {integrity: sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q==} engines: {node: '>=4'} hasBin: true error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} - es-module-lexer@1.4.1: - resolution: {integrity: sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==} + es-module-lexer@1.5.4: + resolution: {integrity: sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==} es6-promise@3.3.1: resolution: {integrity: sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==} @@ -1298,6 +1273,9 @@ packages: fast-json-stable-stringify@2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + fast-uri@3.0.1: + resolution: {integrity: sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw==} + fastest-levenshtein@1.0.16: resolution: {integrity: sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==} engines: {node: '>= 4.9.1'} @@ -1308,8 +1286,8 @@ packages: filelist@1.0.4: resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} - fill-range@7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} find-up@4.1.0: @@ -1351,8 +1329,8 @@ packages: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} engines: {node: '>=10'} - get-tsconfig@4.7.5: - resolution: {integrity: sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw==} + get-tsconfig@4.7.6: + resolution: {integrity: sha512-ZAqrLlu18NbDdRaHq+AKXzAmqIUPswPWKUchfytdAjiRFnCe5ojG2bstg6mRiZabkKfCoL/e98pbBELIV/YCeA==} glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} @@ -1363,6 +1341,7 @@ packages: glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Glob versions prior to v9 are no longer supported globals@11.12.0: resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} @@ -1379,8 +1358,8 @@ packages: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} - hasown@2.0.0: - resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==} + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} html-encoding-sniffer@3.0.0: @@ -1412,11 +1391,11 @@ packages: peerDependencies: postcss: ^8.1.0 - immutable@4.3.5: - resolution: {integrity: sha512-8eabxkth9gZatlwl5TBuJnCsoTADlL6ftEr7A4qgdaTsPyreilDSnUk57SO+jfKcNtxPa22U5KK6DSeAYhpBJw==} + immutable@4.3.7: + resolution: {integrity: sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==} - import-local@3.1.0: - resolution: {integrity: sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==} + import-local@3.2.0: + resolution: {integrity: sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==} engines: {node: '>=8'} hasBin: true @@ -1426,6 +1405,7 @@ packages: inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} @@ -1441,8 +1421,9 @@ packages: resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} engines: {node: '>=8'} - is-core-module@2.13.1: - resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} + is-core-module@2.15.0: + resolution: {integrity: sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA==} + engines: {node: '>= 0.4'} is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} @@ -1493,8 +1474,8 @@ packages: resolution: {integrity: sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==} engines: {node: '>=8'} - istanbul-lib-instrument@6.0.2: - resolution: {integrity: sha512-1WUsZ9R1lA0HtBSohTkm39WTPlNKSJ5iFk7UwqXkBLoHQT+hfqPsfsTDVuZdKGaBwn7din9bS7SsnoAr943hvw==} + istanbul-lib-instrument@6.0.3: + resolution: {integrity: sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==} engines: {node: '>=10'} istanbul-lib-report@3.0.1: @@ -1727,13 +1708,8 @@ packages: lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} - lru-cache@6.0.0: - resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} - engines: {node: '>=10'} - - magic-string@0.30.7: - resolution: {integrity: sha512-8vBuFF/I/+OSLRmdf2wwFCJCz+nSn0m6DPvGH1fS/KiQoSaR+sETbov0eIk9KhEKy8CYqIkIAnbohxT/4H0kuA==} - engines: {node: '>=12'} + magic-string@0.30.11: + resolution: {integrity: sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==} make-dir@4.0.0: resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} @@ -1751,8 +1727,8 @@ packages: merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - micromatch@4.0.5: - resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + micromatch@4.0.7: + resolution: {integrity: sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==} engines: {node: '>=8.6'} mime-db@1.52.0: @@ -1812,8 +1788,8 @@ packages: node-int64@0.4.0: resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} - node-releases@2.0.14: - resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} + node-releases@2.0.18: + resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==} normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} @@ -1823,8 +1799,8 @@ packages: resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} engines: {node: '>=8'} - nwsapi@2.2.9: - resolution: {integrity: sha512-2f3F0SEEer8bBu0dsNCFF50N0cTThV1nWFYcEYFZttdW0lDAoybv9cQoK7X7/68Z89S7FoRrVjP1LPX4XRf9vg==} + nwsapi@2.2.12: + resolution: {integrity: sha512-qXDmcVlZV4XRtKFzddidpfVP4oMSGhga+xdMc25mv8kaLUHtgzCDhUxkrN8exkGdTlLNaXj7CV3GtON7zuGZ+w==} once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} @@ -1874,8 +1850,8 @@ packages: periscopic@3.1.0: resolution: {integrity: sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==} - picocolors@1.0.0: - resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + picocolors@1.0.1: + resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} @@ -1913,15 +1889,15 @@ packages: peerDependencies: postcss: ^8.1.0 - postcss-selector-parser@6.0.15: - resolution: {integrity: sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw==} + postcss-selector-parser@6.1.1: + resolution: {integrity: sha512-b4dlw/9V8A71rLIDsSwVmak9z2DuBUB7CA1/wSdelNEzqsjoSPeADTWNO09lpH49Diy3/JIZ2bSPB1dI3LJCHg==} engines: {node: '>=4'} postcss-value-parser@4.2.0: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - postcss@8.4.35: - resolution: {integrity: sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==} + postcss@8.4.40: + resolution: {integrity: sha512-YF2kKIUzAofPMpfH6hOi2cGnv/HrUlfucspc7pDyvv7kGdqXrfj8SCl/t8owkEgKEuu8ZcRjSOxFxVLqwChZ2Q==} engines: {node: ^10 || ^12 || >=14} prettier@3.3.3: @@ -2033,8 +2009,8 @@ packages: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true - semver@7.6.0: - resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==} + semver@7.6.3: + resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} engines: {node: '>=10'} hasBin: true @@ -2063,15 +2039,15 @@ packages: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} - sorcery@0.11.0: - resolution: {integrity: sha512-J69LQ22xrQB1cIFJhPfgtLuI6BpWRiWu1Y3vSsIwK/eAScqJxd/+CJlUuHQRdX2C9NGFamq+KqNywGgaThwfHw==} + sorcery@0.11.1: + resolution: {integrity: sha512-o7npfeJE6wi6J9l0/5LKshFzZ2rMatRiCDwYeDQaOzqdzRJwALhX7mk/A/ecg6wjMu7wdZbmXfD2S/vpOg0bdQ==} hasBin: true source-list-map@2.0.1: resolution: {integrity: sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==} - source-map-js@1.0.2: - resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} + source-map-js@1.2.0: + resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} engines: {node: '>=0.10.0'} source-map-support@0.5.13: @@ -2135,8 +2111,8 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} - svelte-check@3.8.4: - resolution: {integrity: sha512-61aHMkdinWyH8BkkTX9jPLYxYzaAAz/FK/VQqdr2FiCQQ/q04WCwDlpGbHff1GdrMYTmW8chlTFvRWL9k0A8vg==} + svelte-check@3.8.5: + resolution: {integrity: sha512-3OGGgr9+bJ/+1nbPgsvulkLC48xBsqsgtc8Wam281H4G9F5v3mYGa2bHRsPuwHC5brKl4AxJH95QF73kmfihGQ==} hasBin: true peerDependencies: svelte: ^3.55.0 || ^4.0.0-next.0 || ^4.0.0 || ^5.0.0-next.0 @@ -2256,8 +2232,8 @@ packages: uglify-js: optional: true - terser@5.27.0: - resolution: {integrity: sha512-bi1HRwVRskAjheeYl291n3JC4GgO/Ty4z1nVs5AAsmonJulGxpSektecnNedrwK9C7vpvVtcX3cw00VSLt7U2A==} + terser@5.31.3: + resolution: {integrity: sha512-pAfYn3NIZLyZpa83ZKigvj6Rn9c/vd5KfYGX7cN1mnzqgDcxWvrU5ZtAfIKhEXz9nRecw4z3LXkjaq96/qZqAA==} engines: {node: '>=10'} hasBin: true @@ -2322,8 +2298,8 @@ packages: '@swc/wasm': optional: true - tsx@4.16.2: - resolution: {integrity: sha512-C1uWweJDgdtX2x600HjaFaucXTilT7tgUZHbOE4+ypskZ1OP8CRCSDkCxG6Vya9EwaFIVagWwpaVAn5wzypaqQ==} + tsx@4.16.3: + resolution: {integrity: sha512-MP8AEUxVnboD2rCC6kDLxnpDBNWN9k3BSVU/0/nNxgm70bPBnfn+yCKcnOsIVPQwdkbKYoFOlKjjWZWJ2XCXUg==} engines: {node: '>=18.0.0'} hasBin: true @@ -2340,15 +2316,15 @@ packages: engines: {node: '>=14.17'} hasBin: true - undici-types@5.26.5: - resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + undici-types@6.11.1: + resolution: {integrity: sha512-mIDEX2ek50x0OlRgxryxsenE5XaQD4on5U2inY7RApK3SOJpofyw7uW2AyfMKkhAxXIceo2DeWGVGwyvng1GNQ==} universalify@0.2.0: resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} engines: {node: '>= 4.0.0'} - update-browserslist-db@1.0.13: - resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==} + update-browserslist-db@1.1.0: + resolution: {integrity: sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==} hasBin: true peerDependencies: browserslist: '>= 4.21.0' @@ -2365,8 +2341,8 @@ packages: v8-compile-cache-lib@3.0.1: resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} - v8-to-istanbul@9.2.0: - resolution: {integrity: sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==} + v8-to-istanbul@9.3.0: + resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==} engines: {node: '>=10.12.0'} w3c-xmlserializer@4.0.0: @@ -2453,8 +2429,8 @@ packages: resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - ws@8.17.0: - resolution: {integrity: sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==} + ws@8.18.0: + resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==} engines: {node: '>=10.0.0'} peerDependencies: bufferutil: ^4.0.1 @@ -2479,9 +2455,6 @@ packages: yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - yallist@4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - yargs-parser@21.1.1: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} engines: {node: '>=12'} @@ -2500,207 +2473,193 @@ packages: snapshots: - '@ampproject/remapping@2.2.1': + '@ampproject/remapping@2.3.0': dependencies: - '@jridgewell/gen-mapping': 0.3.3 - '@jridgewell/trace-mapping': 0.3.22 + '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/trace-mapping': 0.3.25 - '@babel/code-frame@7.24.2': + '@babel/code-frame@7.24.7': dependencies: - '@babel/highlight': 7.24.5 - picocolors: 1.0.0 + '@babel/highlight': 7.24.7 + picocolors: 1.0.1 - '@babel/compat-data@7.24.4': {} + '@babel/compat-data@7.25.2': {} - '@babel/core@7.24.5': + '@babel/core@7.25.2': dependencies: - '@ampproject/remapping': 2.2.1 - '@babel/code-frame': 7.24.2 - '@babel/generator': 7.24.5 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-module-transforms': 7.24.5(@babel/core@7.24.5) - '@babel/helpers': 7.24.5 - '@babel/parser': 7.24.5 - '@babel/template': 7.24.0 - '@babel/traverse': 7.24.5 - '@babel/types': 7.24.5 + '@ampproject/remapping': 2.3.0 + '@babel/code-frame': 7.24.7 + '@babel/generator': 7.25.0 + '@babel/helper-compilation-targets': 7.25.2 + '@babel/helper-module-transforms': 7.25.2(@babel/core@7.25.2) + '@babel/helpers': 7.25.0 + '@babel/parser': 7.25.3 + '@babel/template': 7.25.0 + '@babel/traverse': 7.25.3 + '@babel/types': 7.25.2 convert-source-map: 2.0.0 - debug: 4.3.4 + debug: 4.3.6 gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 transitivePeerDependencies: - supports-color - '@babel/generator@7.24.5': + '@babel/generator@7.25.0': dependencies: - '@babel/types': 7.24.5 + '@babel/types': 7.25.2 '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 jsesc: 2.5.2 - '@babel/helper-compilation-targets@7.23.6': + '@babel/helper-compilation-targets@7.25.2': dependencies: - '@babel/compat-data': 7.24.4 - '@babel/helper-validator-option': 7.23.5 - browserslist: 4.23.0 + '@babel/compat-data': 7.25.2 + '@babel/helper-validator-option': 7.24.8 + browserslist: 4.23.2 lru-cache: 5.1.1 semver: 6.3.1 - '@babel/helper-environment-visitor@7.22.20': {} - - '@babel/helper-function-name@7.23.0': - dependencies: - '@babel/template': 7.24.0 - '@babel/types': 7.24.5 - - '@babel/helper-hoist-variables@7.22.5': + '@babel/helper-module-imports@7.24.7': dependencies: - '@babel/types': 7.24.5 - - '@babel/helper-module-imports@7.24.3': - dependencies: - '@babel/types': 7.24.5 + '@babel/traverse': 7.25.3 + '@babel/types': 7.25.2 + transitivePeerDependencies: + - supports-color - '@babel/helper-module-transforms@7.24.5(@babel/core@7.24.5)': + '@babel/helper-module-transforms@7.25.2(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-module-imports': 7.24.3 - '@babel/helper-simple-access': 7.24.5 - '@babel/helper-split-export-declaration': 7.24.5 - '@babel/helper-validator-identifier': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-module-imports': 7.24.7 + '@babel/helper-simple-access': 7.24.7 + '@babel/helper-validator-identifier': 7.24.7 + '@babel/traverse': 7.25.3 + transitivePeerDependencies: + - supports-color - '@babel/helper-plugin-utils@7.24.5': {} + '@babel/helper-plugin-utils@7.24.8': {} - '@babel/helper-simple-access@7.24.5': + '@babel/helper-simple-access@7.24.7': dependencies: - '@babel/types': 7.24.5 - - '@babel/helper-split-export-declaration@7.24.5': - dependencies: - '@babel/types': 7.24.5 + '@babel/traverse': 7.25.3 + '@babel/types': 7.25.2 + transitivePeerDependencies: + - supports-color - '@babel/helper-string-parser@7.24.1': {} + '@babel/helper-string-parser@7.24.8': {} - '@babel/helper-validator-identifier@7.24.5': {} + '@babel/helper-validator-identifier@7.24.7': {} - '@babel/helper-validator-option@7.23.5': {} + '@babel/helper-validator-option@7.24.8': {} - '@babel/helpers@7.24.5': + '@babel/helpers@7.25.0': dependencies: - '@babel/template': 7.24.0 - '@babel/traverse': 7.24.5 - '@babel/types': 7.24.5 - transitivePeerDependencies: - - supports-color + '@babel/template': 7.25.0 + '@babel/types': 7.25.2 - '@babel/highlight@7.24.5': + '@babel/highlight@7.24.7': dependencies: - '@babel/helper-validator-identifier': 7.24.5 + '@babel/helper-validator-identifier': 7.24.7 chalk: 2.4.2 js-tokens: 4.0.0 - picocolors: 1.0.0 + picocolors: 1.0.1 - '@babel/parser@7.24.5': + '@babel/parser@7.25.3': dependencies: - '@babel/types': 7.24.5 + '@babel/types': 7.25.2 - '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.24.5)': + '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.24.5)': + '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.24.5)': + '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.24.5)': + '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.24.5)': + '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-jsx@7.24.1(@babel/core@7.24.5)': + '@babel/plugin-syntax-jsx@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.24.5)': + '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.24.5)': + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.24.5)': + '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.24.5)': + '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.24.5)': + '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.24.5)': + '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.24.5)': + '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-typescript@7.24.1(@babel/core@7.24.5)': + '@babel/plugin-syntax-typescript@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.5 - '@babel/helper-plugin-utils': 7.24.5 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 - '@babel/template@7.24.0': + '@babel/template@7.25.0': dependencies: - '@babel/code-frame': 7.24.2 - '@babel/parser': 7.24.5 - '@babel/types': 7.24.5 + '@babel/code-frame': 7.24.7 + '@babel/parser': 7.25.3 + '@babel/types': 7.25.2 - '@babel/traverse@7.24.5': + '@babel/traverse@7.25.3': dependencies: - '@babel/code-frame': 7.24.2 - '@babel/generator': 7.24.5 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-function-name': 7.23.0 - '@babel/helper-hoist-variables': 7.22.5 - '@babel/helper-split-export-declaration': 7.24.5 - '@babel/parser': 7.24.5 - '@babel/types': 7.24.5 - debug: 4.3.4 + '@babel/code-frame': 7.24.7 + '@babel/generator': 7.25.0 + '@babel/parser': 7.25.3 + '@babel/template': 7.25.0 + '@babel/types': 7.25.2 + debug: 4.3.6 globals: 11.12.0 transitivePeerDependencies: - supports-color - '@babel/types@7.24.5': + '@babel/types@7.25.2': dependencies: - '@babel/helper-string-parser': 7.24.1 - '@babel/helper-validator-identifier': 7.24.5 + '@babel/helper-string-parser': 7.24.8 + '@babel/helper-validator-identifier': 7.24.7 to-fast-properties: 2.0.0 '@bcoe/v8-coverage@0.2.3': {} @@ -2865,27 +2824,27 @@ snapshots: '@jest/console@29.7.0': dependencies: '@jest/types': 29.6.3 - '@types/node': 20.14.12 + '@types/node': 22.0.0 chalk: 4.1.2 jest-message-util: 29.7.0 jest-util: 29.7.0 slash: 3.0.0 - '@jest/core@29.7.0(ts-node@10.9.2(@types/node@20.14.12)(typescript@5.5.4))': + '@jest/core@29.7.0(ts-node@10.9.2(@types/node@22.0.0)(typescript@5.5.4))': dependencies: '@jest/console': 29.7.0 '@jest/reporters': 29.7.0 '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.12 + '@types/node': 22.0.0 ansi-escapes: 4.3.2 chalk: 4.1.2 ci-info: 3.9.0 exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@20.14.12)(ts-node@10.9.2(@types/node@20.14.12)(typescript@5.5.4)) + jest-config: 29.7.0(@types/node@22.0.0)(ts-node@10.9.2(@types/node@22.0.0)(typescript@5.5.4)) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -2897,7 +2856,7 @@ snapshots: jest-util: 29.7.0 jest-validate: 29.7.0 jest-watcher: 29.7.0 - micromatch: 4.0.5 + micromatch: 4.0.7 pretty-format: 29.7.0 slash: 3.0.0 strip-ansi: 6.0.1 @@ -2910,7 +2869,7 @@ snapshots: dependencies: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.12 + '@types/node': 22.0.0 jest-mock: 29.7.0 '@jest/expect-utils@29.7.0': @@ -2928,7 +2887,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@sinonjs/fake-timers': 10.3.0 - '@types/node': 20.14.12 + '@types/node': 22.0.0 jest-message-util: 29.7.0 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -2950,14 +2909,14 @@ snapshots: '@jest/transform': 29.7.0 '@jest/types': 29.6.3 '@jridgewell/trace-mapping': 0.3.25 - '@types/node': 20.14.12 + '@types/node': 22.0.0 chalk: 4.1.2 collect-v8-coverage: 1.0.2 exit: 0.1.2 glob: 7.2.3 graceful-fs: 4.2.11 istanbul-lib-coverage: 3.2.2 - istanbul-lib-instrument: 6.0.2 + istanbul-lib-instrument: 6.0.3 istanbul-lib-report: 3.0.1 istanbul-lib-source-maps: 4.0.1 istanbul-reports: 3.1.7 @@ -2967,7 +2926,7 @@ snapshots: slash: 3.0.0 string-length: 4.0.2 strip-ansi: 6.0.1 - v8-to-istanbul: 9.2.0 + v8-to-istanbul: 9.3.0 transitivePeerDependencies: - supports-color @@ -2997,7 +2956,7 @@ snapshots: '@jest/transform@29.7.0': dependencies: - '@babel/core': 7.24.5 + '@babel/core': 7.25.2 '@jest/types': 29.6.3 '@jridgewell/trace-mapping': 0.3.25 babel-plugin-istanbul: 6.1.1 @@ -3008,7 +2967,7 @@ snapshots: jest-haste-map: 29.7.0 jest-regex-util: 29.6.3 jest-util: 29.7.0 - micromatch: 4.0.5 + micromatch: 4.0.7 pirates: 4.0.6 slash: 3.0.0 write-file-atomic: 4.0.2 @@ -3020,49 +2979,36 @@ snapshots: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 20.14.12 + '@types/node': 22.0.0 '@types/yargs': 17.0.32 chalk: 4.1.2 - '@jridgewell/gen-mapping@0.3.3': - dependencies: - '@jridgewell/set-array': 1.1.2 - '@jridgewell/sourcemap-codec': 1.4.15 - '@jridgewell/trace-mapping': 0.3.22 - '@jridgewell/gen-mapping@0.3.5': dependencies: '@jridgewell/set-array': 1.2.1 - '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/sourcemap-codec': 1.5.0 '@jridgewell/trace-mapping': 0.3.25 - '@jridgewell/resolve-uri@3.1.1': {} - - '@jridgewell/set-array@1.1.2': {} + '@jridgewell/resolve-uri@3.1.2': {} '@jridgewell/set-array@1.2.1': {} - '@jridgewell/source-map@0.3.5': + '@jridgewell/source-map@0.3.6': dependencies: '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 - '@jridgewell/sourcemap-codec@1.4.15': {} - - '@jridgewell/trace-mapping@0.3.22': - dependencies: - '@jridgewell/resolve-uri': 3.1.1 - '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/sourcemap-codec@1.5.0': {} '@jridgewell/trace-mapping@0.3.25': dependencies: - '@jridgewell/resolve-uri': 3.1.1 - '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.0 '@jridgewell/trace-mapping@0.3.9': dependencies: - '@jridgewell/resolve-uri': 3.1.1 - '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.0 '@noble/hashes@1.4.0': {} @@ -3088,43 +3034,43 @@ snapshots: '@types/babel__core@7.20.5': dependencies: - '@babel/parser': 7.24.5 - '@babel/types': 7.24.5 + '@babel/parser': 7.25.3 + '@babel/types': 7.25.2 '@types/babel__generator': 7.6.8 '@types/babel__template': 7.4.4 - '@types/babel__traverse': 7.20.5 + '@types/babel__traverse': 7.20.6 '@types/babel__generator@7.6.8': dependencies: - '@babel/types': 7.24.5 + '@babel/types': 7.25.2 '@types/babel__template@7.4.4': dependencies: - '@babel/parser': 7.24.5 - '@babel/types': 7.24.5 + '@babel/parser': 7.25.3 + '@babel/types': 7.25.2 - '@types/babel__traverse@7.20.5': + '@types/babel__traverse@7.20.6': dependencies: - '@babel/types': 7.24.5 + '@babel/types': 7.25.2 '@types/chrome@0.0.269': dependencies: - '@types/filesystem': 0.0.35 + '@types/filesystem': 0.0.36 '@types/har-format': 1.2.15 '@types/eslint-scope@3.7.7': dependencies: - '@types/eslint': 8.56.5 + '@types/eslint': 9.6.0 '@types/estree': 1.0.5 - '@types/eslint@8.56.5': + '@types/eslint@9.6.0': dependencies: '@types/estree': 1.0.5 '@types/json-schema': 7.0.15 '@types/estree@1.0.5': {} - '@types/filesystem@0.0.35': + '@types/filesystem@0.0.36': dependencies: '@types/filewriter': 0.0.33 @@ -3132,7 +3078,7 @@ snapshots: '@types/graceful-fs@4.1.9': dependencies: - '@types/node': 20.14.12 + '@types/node': 22.0.0 '@types/har-format@1.2.15': {} @@ -3153,15 +3099,15 @@ snapshots: '@types/jsdom@20.0.1': dependencies: - '@types/node': 20.14.12 + '@types/node': 22.0.0 '@types/tough-cookie': 4.0.5 parse5: 7.1.2 '@types/json-schema@7.0.15': {} - '@types/node@20.14.12': + '@types/node@22.0.0': dependencies: - undici-types: 5.26.5 + undici-types: 6.11.1 '@types/pug@2.0.10': {} @@ -3274,34 +3220,36 @@ snapshots: acorn-globals@7.0.1: dependencies: - acorn: 8.11.3 - acorn-walk: 8.3.2 + acorn: 8.12.1 + acorn-walk: 8.3.3 - acorn-import-attributes@1.9.5(acorn@8.11.3): + acorn-import-attributes@1.9.5(acorn@8.12.1): dependencies: - acorn: 8.11.3 + acorn: 8.12.1 - acorn-walk@8.3.2: {} + acorn-walk@8.3.3: + dependencies: + acorn: 8.12.1 - acorn@8.11.3: {} + acorn@8.12.1: {} agent-base@6.0.2: dependencies: - debug: 4.3.4 + debug: 4.3.6 transitivePeerDependencies: - supports-color - ajv-formats@2.1.1(ajv@8.12.0): + ajv-formats@2.1.1(ajv@8.17.1): optionalDependencies: - ajv: 8.12.0 + ajv: 8.17.1 ajv-keywords@3.5.2(ajv@6.12.6): dependencies: ajv: 6.12.6 - ajv-keywords@5.1.0(ajv@8.12.0): + ajv-keywords@5.1.0(ajv@8.17.1): dependencies: - ajv: 8.12.0 + ajv: 8.17.1 fast-deep-equal: 3.1.3 ajv@6.12.6: @@ -3311,12 +3259,12 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 - ajv@8.12.0: + ajv@8.17.1: dependencies: fast-deep-equal: 3.1.3 + fast-uri: 3.0.1 json-schema-traverse: 1.0.0 require-from-string: 2.0.2 - uri-js: 4.4.1 ansi-escapes@4.3.2: dependencies: @@ -3353,17 +3301,15 @@ snapshots: asynckit@0.4.0: {} - axobject-query@4.0.0: - dependencies: - dequal: 2.0.3 + axobject-query@4.1.0: {} - babel-jest@29.7.0(@babel/core@7.24.5): + babel-jest@29.7.0(@babel/core@7.25.2): dependencies: - '@babel/core': 7.24.5 + '@babel/core': 7.25.2 '@jest/transform': 29.7.0 '@types/babel__core': 7.20.5 babel-plugin-istanbul: 6.1.1 - babel-preset-jest: 29.6.3(@babel/core@7.24.5) + babel-preset-jest: 29.6.3(@babel/core@7.25.2) chalk: 4.1.2 graceful-fs: 4.2.11 slash: 3.0.0 @@ -3372,7 +3318,7 @@ snapshots: babel-plugin-istanbul@6.1.1: dependencies: - '@babel/helper-plugin-utils': 7.24.5 + '@babel/helper-plugin-utils': 7.24.8 '@istanbuljs/load-nyc-config': 1.1.0 '@istanbuljs/schema': 0.1.3 istanbul-lib-instrument: 5.2.1 @@ -3382,38 +3328,38 @@ snapshots: babel-plugin-jest-hoist@29.6.3: dependencies: - '@babel/template': 7.24.0 - '@babel/types': 7.24.5 + '@babel/template': 7.25.0 + '@babel/types': 7.25.2 '@types/babel__core': 7.20.5 - '@types/babel__traverse': 7.20.5 - - babel-preset-current-node-syntax@1.0.1(@babel/core@7.24.5): - dependencies: - '@babel/core': 7.24.5 - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.24.5) - '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.24.5) - '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.24.5) - '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.24.5) - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.24.5) - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.24.5) - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.24.5) - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.24.5) - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.24.5) - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.24.5) - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.24.5) - '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.24.5) - - babel-preset-jest@29.6.3(@babel/core@7.24.5): - dependencies: - '@babel/core': 7.24.5 + '@types/babel__traverse': 7.20.6 + + babel-preset-current-node-syntax@1.0.1(@babel/core@7.25.2): + dependencies: + '@babel/core': 7.25.2 + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.25.2) + '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.25.2) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.25.2) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.25.2) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.25.2) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.25.2) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.25.2) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.25.2) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.25.2) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.25.2) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.25.2) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.25.2) + + babel-preset-jest@29.6.3(@babel/core@7.25.2): + dependencies: + '@babel/core': 7.25.2 babel-plugin-jest-hoist: 29.6.3 - babel-preset-current-node-syntax: 1.0.1(@babel/core@7.24.5) + babel-preset-current-node-syntax: 1.0.1(@babel/core@7.25.2) balanced-match@1.0.2: {} big.js@5.2.2: {} - binary-extensions@2.2.0: {} + binary-extensions@2.3.0: {} brace-expansion@1.1.11: dependencies: @@ -3424,16 +3370,16 @@ snapshots: dependencies: balanced-match: 1.0.2 - braces@3.0.2: + braces@3.0.3: dependencies: - fill-range: 7.0.1 + fill-range: 7.1.1 - browserslist@4.23.0: + browserslist@4.23.2: dependencies: - caniuse-lite: 1.0.30001597 - electron-to-chromium: 1.4.701 - node-releases: 2.0.14 - update-browserslist-db: 1.0.13(browserslist@4.23.0) + caniuse-lite: 1.0.30001645 + electron-to-chromium: 1.5.4 + node-releases: 2.0.18 + update-browserslist-db: 1.1.0(browserslist@4.23.2) bs-logger@0.2.6: dependencies: @@ -3443,7 +3389,7 @@ snapshots: dependencies: node-int64: 0.4.0 - buffer-crc32@0.2.13: {} + buffer-crc32@1.0.0: {} buffer-from@1.1.2: {} @@ -3453,7 +3399,7 @@ snapshots: camelcase@6.3.0: {} - caniuse-lite@1.0.30001597: {} + caniuse-lite@1.0.30001645: {} chalk@2.4.2: dependencies: @@ -3471,7 +3417,7 @@ snapshots: chokidar@3.6.0: dependencies: anymatch: 3.1.3 - braces: 3.0.2 + braces: 3.0.3 glob-parent: 5.1.2 is-binary-path: 2.1.0 is-glob: 4.0.3 @@ -3480,7 +3426,7 @@ snapshots: optionalDependencies: fsevents: 2.3.3 - chrome-trace-event@1.0.3: {} + chrome-trace-event@1.0.4: {} ci-info@3.9.0: {} @@ -3502,9 +3448,9 @@ snapshots: code-red@1.0.4: dependencies: - '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/sourcemap-codec': 1.5.0 '@types/estree': 1.0.5 - acorn: 8.11.3 + acorn: 8.12.1 estree-walker: 3.0.3 periscopic: 3.1.0 @@ -3536,13 +3482,13 @@ snapshots: convert-source-map@2.0.0: {} - create-jest@29.7.0(@types/node@20.14.12)(ts-node@10.9.2(@types/node@20.14.12)(typescript@5.5.4)): + create-jest@29.7.0(@types/node@22.0.0)(ts-node@10.9.2(@types/node@22.0.0)(typescript@5.5.4)): dependencies: '@jest/types': 29.6.3 chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@20.14.12)(ts-node@10.9.2(@types/node@20.14.12)(typescript@5.5.4)) + jest-config: 29.7.0(@types/node@22.0.0)(ts-node@10.9.2(@types/node@22.0.0)(typescript@5.5.4)) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -3561,21 +3507,21 @@ snapshots: css-loader@7.1.2(webpack@5.93.0(esbuild@0.23.0)(webpack-cli@5.1.4)): dependencies: - icss-utils: 5.1.0(postcss@8.4.35) - postcss: 8.4.35 - postcss-modules-extract-imports: 3.1.0(postcss@8.4.35) - postcss-modules-local-by-default: 4.0.5(postcss@8.4.35) - postcss-modules-scope: 3.2.0(postcss@8.4.35) - postcss-modules-values: 4.0.0(postcss@8.4.35) + icss-utils: 5.1.0(postcss@8.4.40) + postcss: 8.4.40 + postcss-modules-extract-imports: 3.1.0(postcss@8.4.40) + postcss-modules-local-by-default: 4.0.5(postcss@8.4.40) + postcss-modules-scope: 3.2.0(postcss@8.4.40) + postcss-modules-values: 4.0.0(postcss@8.4.40) postcss-value-parser: 4.2.0 - semver: 7.6.0 + semver: 7.6.3 optionalDependencies: webpack: 5.93.0(esbuild@0.23.0)(webpack-cli@5.1.4) css-tree@2.3.1: dependencies: mdn-data: 2.0.30 - source-map-js: 1.0.2 + source-map-js: 1.2.0 cssesc@3.0.0: {} @@ -3593,7 +3539,7 @@ snapshots: whatwg-mimetype: 3.0.0 whatwg-url: 11.0.0 - debug@4.3.4: + debug@4.3.6: dependencies: ms: 2.1.2 @@ -3623,7 +3569,7 @@ snapshots: dependencies: jake: 10.9.2 - electron-to-chromium@1.4.701: {} + electron-to-chromium@1.5.4: {} emittery@0.13.1: {} @@ -3631,27 +3577,27 @@ snapshots: emojis-list@3.0.0: {} - enhanced-resolve@5.17.0: + enhanced-resolve@5.17.1: dependencies: graceful-fs: 4.2.11 tapable: 2.2.1 entities@4.5.0: {} - envinfo@7.11.1: {} + envinfo@7.13.0: {} error-ex@1.3.2: dependencies: is-arrayish: 0.2.1 - es-module-lexer@1.4.1: {} + es-module-lexer@1.5.4: {} es6-promise@3.3.1: {} esbuild-loader@4.2.2(webpack@5.93.0(esbuild@0.23.0)(webpack-cli@5.1.4)): dependencies: esbuild: 0.21.5 - get-tsconfig: 4.7.5 + get-tsconfig: 4.7.6 loader-utils: 2.0.4 webpack: 5.93.0(esbuild@0.23.0)(webpack-cli@5.1.4) webpack-sources: 1.4.3 @@ -3772,6 +3718,8 @@ snapshots: fast-json-stable-stringify@2.1.0: {} + fast-uri@3.0.1: {} + fastest-levenshtein@1.0.16: {} fb-watchman@2.0.2: @@ -3782,7 +3730,7 @@ snapshots: dependencies: minimatch: 5.1.6 - fill-range@7.0.1: + fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 @@ -3814,7 +3762,7 @@ snapshots: get-stream@6.0.1: {} - get-tsconfig@4.7.5: + get-tsconfig@4.7.6: dependencies: resolve-pkg-maps: 1.0.0 @@ -3841,7 +3789,7 @@ snapshots: has-flag@4.0.0: {} - hasown@2.0.0: + hasown@2.0.2: dependencies: function-bind: 1.1.2 @@ -3855,14 +3803,14 @@ snapshots: dependencies: '@tootallnate/once': 2.0.0 agent-base: 6.0.2 - debug: 4.3.4 + debug: 4.3.6 transitivePeerDependencies: - supports-color https-proxy-agent@5.0.1: dependencies: agent-base: 6.0.2 - debug: 4.3.4 + debug: 4.3.6 transitivePeerDependencies: - supports-color @@ -3872,13 +3820,13 @@ snapshots: dependencies: safer-buffer: 2.1.2 - icss-utils@5.1.0(postcss@8.4.35): + icss-utils@5.1.0(postcss@8.4.40): dependencies: - postcss: 8.4.35 + postcss: 8.4.40 - immutable@4.3.5: {} + immutable@4.3.7: {} - import-local@3.1.0: + import-local@3.2.0: dependencies: pkg-dir: 4.2.0 resolve-cwd: 3.0.0 @@ -3898,11 +3846,11 @@ snapshots: is-binary-path@2.1.0: dependencies: - binary-extensions: 2.2.0 + binary-extensions: 2.3.0 - is-core-module@2.13.1: + is-core-module@2.15.0: dependencies: - hasown: 2.0.0 + hasown: 2.0.2 is-extglob@2.1.1: {} @@ -3936,21 +3884,21 @@ snapshots: istanbul-lib-instrument@5.2.1: dependencies: - '@babel/core': 7.24.5 - '@babel/parser': 7.24.5 + '@babel/core': 7.25.2 + '@babel/parser': 7.25.3 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.2 semver: 6.3.1 transitivePeerDependencies: - supports-color - istanbul-lib-instrument@6.0.2: + istanbul-lib-instrument@6.0.3: dependencies: - '@babel/core': 7.24.5 - '@babel/parser': 7.24.5 + '@babel/core': 7.25.2 + '@babel/parser': 7.25.3 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.2 - semver: 7.6.0 + semver: 7.6.3 transitivePeerDependencies: - supports-color @@ -3962,7 +3910,7 @@ snapshots: istanbul-lib-source-maps@4.0.1: dependencies: - debug: 4.3.4 + debug: 4.3.6 istanbul-lib-coverage: 3.2.2 source-map: 0.6.1 transitivePeerDependencies: @@ -3992,7 +3940,7 @@ snapshots: '@jest/expect': 29.7.0 '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.12 + '@types/node': 22.0.0 chalk: 4.1.2 co: 4.6.0 dedent: 1.5.3 @@ -4012,16 +3960,16 @@ snapshots: - babel-plugin-macros - supports-color - jest-cli@29.7.0(@types/node@20.14.12)(ts-node@10.9.2(@types/node@20.14.12)(typescript@5.5.4)): + jest-cli@29.7.0(@types/node@22.0.0)(ts-node@10.9.2(@types/node@22.0.0)(typescript@5.5.4)): dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@20.14.12)(typescript@5.5.4)) + '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@22.0.0)(typescript@5.5.4)) '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@20.14.12)(ts-node@10.9.2(@types/node@20.14.12)(typescript@5.5.4)) + create-jest: 29.7.0(@types/node@22.0.0)(ts-node@10.9.2(@types/node@22.0.0)(typescript@5.5.4)) exit: 0.1.2 - import-local: 3.1.0 - jest-config: 29.7.0(@types/node@20.14.12)(ts-node@10.9.2(@types/node@20.14.12)(typescript@5.5.4)) + import-local: 3.2.0 + jest-config: 29.7.0(@types/node@22.0.0)(ts-node@10.9.2(@types/node@22.0.0)(typescript@5.5.4)) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -4031,12 +3979,12 @@ snapshots: - supports-color - ts-node - jest-config@29.7.0(@types/node@20.14.12)(ts-node@10.9.2(@types/node@20.14.12)(typescript@5.5.4)): + jest-config@29.7.0(@types/node@22.0.0)(ts-node@10.9.2(@types/node@22.0.0)(typescript@5.5.4)): dependencies: - '@babel/core': 7.24.5 + '@babel/core': 7.25.2 '@jest/test-sequencer': 29.7.0 '@jest/types': 29.6.3 - babel-jest: 29.7.0(@babel/core@7.24.5) + babel-jest: 29.7.0(@babel/core@7.25.2) chalk: 4.1.2 ci-info: 3.9.0 deepmerge: 4.3.1 @@ -4050,14 +3998,14 @@ snapshots: jest-runner: 29.7.0 jest-util: 29.7.0 jest-validate: 29.7.0 - micromatch: 4.0.5 + micromatch: 4.0.7 parse-json: 5.2.0 pretty-format: 29.7.0 slash: 3.0.0 strip-json-comments: 3.1.1 optionalDependencies: - '@types/node': 20.14.12 - ts-node: 10.9.2(@types/node@20.14.12)(typescript@5.5.4) + '@types/node': 22.0.0 + ts-node: 10.9.2(@types/node@22.0.0)(typescript@5.5.4) transitivePeerDependencies: - babel-plugin-macros - supports-color @@ -4087,7 +4035,7 @@ snapshots: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 '@types/jsdom': 20.0.1 - '@types/node': 20.14.12 + '@types/node': 22.0.0 jest-mock: 29.7.0 jest-util: 29.7.0 jsdom: 20.0.3 @@ -4101,7 +4049,7 @@ snapshots: '@jest/environment': 29.7.0 '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.12 + '@types/node': 22.0.0 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -4111,14 +4059,14 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@types/graceful-fs': 4.1.9 - '@types/node': 20.14.12 + '@types/node': 22.0.0 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 jest-regex-util: 29.6.3 jest-util: 29.7.0 jest-worker: 29.7.0 - micromatch: 4.0.5 + micromatch: 4.0.7 walker: 1.0.8 optionalDependencies: fsevents: 2.3.3 @@ -4137,12 +4085,12 @@ snapshots: jest-message-util@29.7.0: dependencies: - '@babel/code-frame': 7.24.2 + '@babel/code-frame': 7.24.7 '@jest/types': 29.6.3 '@types/stack-utils': 2.0.3 chalk: 4.1.2 graceful-fs: 4.2.11 - micromatch: 4.0.5 + micromatch: 4.0.7 pretty-format: 29.7.0 slash: 3.0.0 stack-utils: 2.0.6 @@ -4150,7 +4098,7 @@ snapshots: jest-mock@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 20.14.12 + '@types/node': 22.0.0 jest-util: 29.7.0 jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): @@ -4185,7 +4133,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.12 + '@types/node': 22.0.0 chalk: 4.1.2 emittery: 0.13.1 graceful-fs: 4.2.11 @@ -4213,7 +4161,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.12 + '@types/node': 22.0.0 chalk: 4.1.2 cjs-module-lexer: 1.3.1 collect-v8-coverage: 1.0.2 @@ -4233,15 +4181,15 @@ snapshots: jest-snapshot@29.7.0: dependencies: - '@babel/core': 7.24.5 - '@babel/generator': 7.24.5 - '@babel/plugin-syntax-jsx': 7.24.1(@babel/core@7.24.5) - '@babel/plugin-syntax-typescript': 7.24.1(@babel/core@7.24.5) - '@babel/types': 7.24.5 + '@babel/core': 7.25.2 + '@babel/generator': 7.25.0 + '@babel/plugin-syntax-jsx': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-syntax-typescript': 7.24.7(@babel/core@7.25.2) + '@babel/types': 7.25.2 '@jest/expect-utils': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - babel-preset-current-node-syntax: 1.0.1(@babel/core@7.24.5) + babel-preset-current-node-syntax: 1.0.1(@babel/core@7.25.2) chalk: 4.1.2 expect: 29.7.0 graceful-fs: 4.2.11 @@ -4252,14 +4200,14 @@ snapshots: jest-util: 29.7.0 natural-compare: 1.4.0 pretty-format: 29.7.0 - semver: 7.6.0 + semver: 7.6.3 transitivePeerDependencies: - supports-color jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 20.14.12 + '@types/node': 22.0.0 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -4278,7 +4226,7 @@ snapshots: dependencies: '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.12 + '@types/node': 22.0.0 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.13.1 @@ -4287,23 +4235,23 @@ snapshots: jest-worker@27.5.1: dependencies: - '@types/node': 20.14.12 + '@types/node': 22.0.0 merge-stream: 2.0.0 supports-color: 8.1.1 jest-worker@29.7.0: dependencies: - '@types/node': 20.14.12 + '@types/node': 22.0.0 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 - jest@29.7.0(@types/node@20.14.12)(ts-node@10.9.2(@types/node@20.14.12)(typescript@5.5.4)): + jest@29.7.0(@types/node@22.0.0)(ts-node@10.9.2(@types/node@22.0.0)(typescript@5.5.4)): dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@20.14.12)(typescript@5.5.4)) + '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@22.0.0)(typescript@5.5.4)) '@jest/types': 29.6.3 - import-local: 3.1.0 - jest-cli: 29.7.0(@types/node@20.14.12)(ts-node@10.9.2(@types/node@20.14.12)(typescript@5.5.4)) + import-local: 3.2.0 + jest-cli: 29.7.0(@types/node@22.0.0)(ts-node@10.9.2(@types/node@22.0.0)(typescript@5.5.4)) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -4320,7 +4268,7 @@ snapshots: jsdom@20.0.3: dependencies: abab: 2.0.6 - acorn: 8.11.3 + acorn: 8.12.1 acorn-globals: 7.0.1 cssom: 0.5.0 cssstyle: 2.3.0 @@ -4333,7 +4281,7 @@ snapshots: http-proxy-agent: 5.0.0 https-proxy-agent: 5.0.1 is-potential-custom-element-name: 1.0.1 - nwsapi: 2.2.9 + nwsapi: 2.2.12 parse5: 7.1.2 saxes: 6.0.0 symbol-tree: 3.2.4 @@ -4343,7 +4291,7 @@ snapshots: whatwg-encoding: 2.0.0 whatwg-mimetype: 3.0.0 whatwg-url: 11.0.0 - ws: 8.17.0 + ws: 8.18.0 xml-name-validator: 4.0.0 transitivePeerDependencies: - bufferutil @@ -4388,17 +4336,13 @@ snapshots: dependencies: yallist: 3.1.1 - lru-cache@6.0.0: - dependencies: - yallist: 4.0.0 - - magic-string@0.30.7: + magic-string@0.30.11: dependencies: - '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/sourcemap-codec': 1.5.0 make-dir@4.0.0: dependencies: - semver: 7.6.0 + semver: 7.6.3 make-error@1.3.6: {} @@ -4410,9 +4354,9 @@ snapshots: merge-stream@2.0.0: {} - micromatch@4.0.5: + micromatch@4.0.7: dependencies: - braces: 3.0.2 + braces: 3.0.3 picomatch: 2.3.1 mime-db@1.52.0: {} @@ -4457,7 +4401,7 @@ snapshots: node-int64@0.4.0: {} - node-releases@2.0.14: {} + node-releases@2.0.18: {} normalize-path@3.0.0: {} @@ -4465,7 +4409,7 @@ snapshots: dependencies: path-key: 3.1.1 - nwsapi@2.2.9: {} + nwsapi@2.2.12: {} once@1.4.0: dependencies: @@ -4491,7 +4435,7 @@ snapshots: parse-json@5.2.0: dependencies: - '@babel/code-frame': 7.24.2 + '@babel/code-frame': 7.24.7 error-ex: 1.3.2 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 @@ -4514,7 +4458,7 @@ snapshots: estree-walker: 3.0.3 is-reference: 3.0.2 - picocolors@1.0.0: {} + picocolors@1.0.1: {} picomatch@2.3.1: {} @@ -4524,39 +4468,39 @@ snapshots: dependencies: find-up: 4.1.0 - postcss-modules-extract-imports@3.1.0(postcss@8.4.35): + postcss-modules-extract-imports@3.1.0(postcss@8.4.40): dependencies: - postcss: 8.4.35 + postcss: 8.4.40 - postcss-modules-local-by-default@4.0.5(postcss@8.4.35): + postcss-modules-local-by-default@4.0.5(postcss@8.4.40): dependencies: - icss-utils: 5.1.0(postcss@8.4.35) - postcss: 8.4.35 - postcss-selector-parser: 6.0.15 + icss-utils: 5.1.0(postcss@8.4.40) + postcss: 8.4.40 + postcss-selector-parser: 6.1.1 postcss-value-parser: 4.2.0 - postcss-modules-scope@3.2.0(postcss@8.4.35): + postcss-modules-scope@3.2.0(postcss@8.4.40): dependencies: - postcss: 8.4.35 - postcss-selector-parser: 6.0.15 + postcss: 8.4.40 + postcss-selector-parser: 6.1.1 - postcss-modules-values@4.0.0(postcss@8.4.35): + postcss-modules-values@4.0.0(postcss@8.4.40): dependencies: - icss-utils: 5.1.0(postcss@8.4.35) - postcss: 8.4.35 + icss-utils: 5.1.0(postcss@8.4.40) + postcss: 8.4.40 - postcss-selector-parser@6.0.15: + postcss-selector-parser@6.1.1: dependencies: cssesc: 3.0.0 util-deprecate: 1.0.2 postcss-value-parser@4.2.0: {} - postcss@8.4.35: + postcss@8.4.40: dependencies: nanoid: 3.3.7 - picocolors: 1.0.0 - source-map-js: 1.0.2 + picocolors: 1.0.1 + source-map-js: 1.2.0 prettier@3.3.3: {} @@ -4611,7 +4555,7 @@ snapshots: resolve@1.22.8: dependencies: - is-core-module: 2.13.1 + is-core-module: 2.15.0 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 @@ -4637,8 +4581,8 @@ snapshots: sass@1.77.8: dependencies: chokidar: 3.6.0 - immutable: 4.3.5 - source-map-js: 1.0.2 + immutable: 4.3.7 + source-map-js: 1.2.0 saxes@6.0.0: dependencies: @@ -4653,15 +4597,13 @@ snapshots: schema-utils@4.2.0: dependencies: '@types/json-schema': 7.0.15 - ajv: 8.12.0 - ajv-formats: 2.1.1(ajv@8.12.0) - ajv-keywords: 5.1.0(ajv@8.12.0) + ajv: 8.17.1 + ajv-formats: 2.1.1(ajv@8.17.1) + ajv-keywords: 5.1.0(ajv@8.17.1) semver@6.3.1: {} - semver@7.6.0: - dependencies: - lru-cache: 6.0.0 + semver@7.6.3: {} serialize-javascript@6.0.2: dependencies: @@ -4683,16 +4625,16 @@ snapshots: slash@3.0.0: {} - sorcery@0.11.0: + sorcery@0.11.1: dependencies: - '@jridgewell/sourcemap-codec': 1.4.15 - buffer-crc32: 0.2.13 + '@jridgewell/sourcemap-codec': 1.5.0 + buffer-crc32: 1.0.0 minimist: 1.2.8 sander: 0.5.1 source-list-map@2.0.1: {} - source-map-js@1.0.2: {} + source-map-js@1.2.0: {} source-map-support@0.5.13: dependencies: @@ -4751,14 +4693,14 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - svelte-check@3.8.4(@babel/core@7.24.5)(postcss@8.4.35)(sass@1.77.8)(svelte@4.2.18): + svelte-check@3.8.5(@babel/core@7.25.2)(postcss@8.4.40)(sass@1.77.8)(svelte@4.2.18): dependencies: '@jridgewell/trace-mapping': 0.3.25 chokidar: 3.6.0 - picocolors: 1.0.0 + picocolors: 1.0.1 sade: 1.8.1 svelte: 4.2.18 - svelte-preprocess: 5.1.4(@babel/core@7.24.5)(postcss@8.4.35)(sass@1.77.8)(svelte@4.2.18)(typescript@5.5.4) + svelte-preprocess: 5.1.4(@babel/core@7.25.2)(postcss@8.4.40)(sass@1.77.8)(svelte@4.2.18)(typescript@5.5.4) typescript: 5.5.4 transitivePeerDependencies: - '@babel/core' @@ -4784,44 +4726,44 @@ snapshots: svelte-dev-helper: 1.1.9 svelte-hmr: 0.14.12(svelte@4.2.18) - svelte-preprocess@5.1.4(@babel/core@7.24.5)(postcss@8.4.35)(sass@1.77.8)(svelte@4.2.18)(typescript@5.5.4): + svelte-preprocess@5.1.4(@babel/core@7.25.2)(postcss@8.4.40)(sass@1.77.8)(svelte@4.2.18)(typescript@5.5.4): dependencies: '@types/pug': 2.0.10 detect-indent: 6.1.0 - magic-string: 0.30.7 - sorcery: 0.11.0 + magic-string: 0.30.11 + sorcery: 0.11.1 strip-indent: 3.0.0 svelte: 4.2.18 optionalDependencies: - '@babel/core': 7.24.5 - postcss: 8.4.35 + '@babel/core': 7.25.2 + postcss: 8.4.40 sass: 1.77.8 typescript: 5.5.4 - svelte-preprocess@6.0.2(@babel/core@7.24.5)(postcss@8.4.35)(sass@1.77.8)(svelte@4.2.18)(typescript@5.5.4): + svelte-preprocess@6.0.2(@babel/core@7.25.2)(postcss@8.4.40)(sass@1.77.8)(svelte@4.2.18)(typescript@5.5.4): dependencies: svelte: 4.2.18 optionalDependencies: - '@babel/core': 7.24.5 - postcss: 8.4.35 + '@babel/core': 7.25.2 + postcss: 8.4.40 sass: 1.77.8 typescript: 5.5.4 svelte@4.2.18: dependencies: - '@ampproject/remapping': 2.2.1 - '@jridgewell/sourcemap-codec': 1.4.15 + '@ampproject/remapping': 2.3.0 + '@jridgewell/sourcemap-codec': 1.5.0 '@jridgewell/trace-mapping': 0.3.25 '@types/estree': 1.0.5 - acorn: 8.11.3 + acorn: 8.12.1 aria-query: 5.3.0 - axobject-query: 4.0.0 + axobject-query: 4.1.0 code-red: 1.0.4 css-tree: 2.3.1 estree-walker: 3.0.3 is-reference: 3.0.2 locate-character: 3.0.0 - magic-string: 0.30.7 + magic-string: 0.30.11 periscopic: 3.1.0 symbol-tree@3.2.4: {} @@ -4834,15 +4776,15 @@ snapshots: jest-worker: 27.5.1 schema-utils: 3.3.0 serialize-javascript: 6.0.2 - terser: 5.27.0 + terser: 5.31.3 webpack: 5.93.0(esbuild@0.23.0)(webpack-cli@5.1.4) optionalDependencies: esbuild: 0.23.0 - terser@5.27.0: + terser@5.31.3: dependencies: - '@jridgewell/source-map': 0.3.5 - acorn: 8.11.3 + '@jridgewell/source-map': 0.3.6 + acorn: 8.12.1 commander: 2.20.3 source-map-support: 0.5.21 @@ -4871,36 +4813,36 @@ snapshots: dependencies: punycode: 2.3.1 - ts-jest@29.2.3(@babel/core@7.24.5)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.5))(esbuild@0.23.0)(jest@29.7.0(@types/node@20.14.12)(ts-node@10.9.2(@types/node@20.14.12)(typescript@5.5.4)))(typescript@5.5.4): + ts-jest@29.2.3(@babel/core@7.25.2)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.2))(esbuild@0.23.0)(jest@29.7.0(@types/node@22.0.0)(ts-node@10.9.2(@types/node@22.0.0)(typescript@5.5.4)))(typescript@5.5.4): dependencies: bs-logger: 0.2.6 ejs: 3.1.10 fast-json-stable-stringify: 2.1.0 - jest: 29.7.0(@types/node@20.14.12)(ts-node@10.9.2(@types/node@20.14.12)(typescript@5.5.4)) + jest: 29.7.0(@types/node@22.0.0)(ts-node@10.9.2(@types/node@22.0.0)(typescript@5.5.4)) jest-util: 29.7.0 json5: 2.2.3 lodash.memoize: 4.1.2 make-error: 1.3.6 - semver: 7.6.0 + semver: 7.6.3 typescript: 5.5.4 yargs-parser: 21.1.1 optionalDependencies: - '@babel/core': 7.24.5 + '@babel/core': 7.25.2 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - babel-jest: 29.7.0(@babel/core@7.24.5) + babel-jest: 29.7.0(@babel/core@7.25.2) esbuild: 0.23.0 - ts-node@10.9.2(@types/node@20.14.12)(typescript@5.5.4): + ts-node@10.9.2(@types/node@22.0.0)(typescript@5.5.4): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.11 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 - '@types/node': 20.14.12 - acorn: 8.11.3 - acorn-walk: 8.3.2 + '@types/node': 22.0.0 + acorn: 8.12.1 + acorn-walk: 8.3.3 arg: 4.1.3 create-require: 1.1.1 diff: 4.0.2 @@ -4909,10 +4851,10 @@ snapshots: v8-compile-cache-lib: 3.0.1 yn: 3.1.1 - tsx@4.16.2: + tsx@4.16.3: dependencies: esbuild: 0.21.5 - get-tsconfig: 4.7.5 + get-tsconfig: 4.7.6 optionalDependencies: fsevents: 2.3.3 @@ -4922,15 +4864,15 @@ snapshots: typescript@5.5.4: {} - undici-types@5.26.5: {} + undici-types@6.11.1: {} universalify@0.2.0: {} - update-browserslist-db@1.0.13(browserslist@4.23.0): + update-browserslist-db@1.1.0(browserslist@4.23.2): dependencies: - browserslist: 4.23.0 + browserslist: 4.23.2 escalade: 3.1.2 - picocolors: 1.0.0 + picocolors: 1.0.1 uri-js@4.4.1: dependencies: @@ -4945,7 +4887,7 @@ snapshots: v8-compile-cache-lib@3.0.1: {} - v8-to-istanbul@9.2.0: + v8-to-istanbul@9.3.0: dependencies: '@jridgewell/trace-mapping': 0.3.25 '@types/istanbul-lib-coverage': 2.0.6 @@ -4975,9 +4917,9 @@ snapshots: colorette: 2.0.20 commander: 10.0.1 cross-spawn: 7.0.3 - envinfo: 7.11.1 + envinfo: 7.13.0 fastest-levenshtein: 1.0.16 - import-local: 3.1.0 + import-local: 3.2.0 interpret: 3.1.1 rechoir: 0.8.0 webpack: 5.93.0(esbuild@0.23.0)(webpack-cli@5.1.4) @@ -5003,12 +4945,12 @@ snapshots: '@webassemblyjs/ast': 1.12.1 '@webassemblyjs/wasm-edit': 1.12.1 '@webassemblyjs/wasm-parser': 1.12.1 - acorn: 8.11.3 - acorn-import-attributes: 1.9.5(acorn@8.11.3) - browserslist: 4.23.0 - chrome-trace-event: 1.0.3 - enhanced-resolve: 5.17.0 - es-module-lexer: 1.4.1 + acorn: 8.12.1 + acorn-import-attributes: 1.9.5(acorn@8.12.1) + browserslist: 4.23.2 + chrome-trace-event: 1.0.4 + enhanced-resolve: 5.17.1 + es-module-lexer: 1.5.4 eslint-scope: 5.1.1 events: 3.3.0 glob-to-regexp: 0.4.1 @@ -5059,7 +5001,7 @@ snapshots: imurmurhash: 0.1.4 signal-exit: 3.0.7 - ws@8.17.0: {} + ws@8.18.0: {} xml-name-validator@4.0.0: {} @@ -5069,8 +5011,6 @@ snapshots: yallist@3.1.1: {} - yallist@4.0.0: {} - yargs-parser@21.1.1: {} yargs@17.7.2: diff --git a/src/view/components/EvalMetrics.svelte b/src/view/components/EvalMetrics.svelte index dd24c1d..16184a9 100644 --- a/src/view/components/EvalMetrics.svelte +++ b/src/view/components/EvalMetrics.svelte @@ -76,6 +76,7 @@ display: -webkit-box; max-width: 200px; -webkit-line-clamp: 3; + line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; } From 20ca8a9cc6dbc468e5f7dc7b17ac60d5866ef62f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=95=B7?= <3756473+zendive@users.noreply.github.com> Date: Thu, 1 Aug 2024 03:35:55 +0300 Subject: [PATCH 42/53] add requestIdleCallback/cancelIdleCallback --- jest/tests/time.test.ts | 8 + jest/tests/wrappers.test.ts | 11 +- manifest.json | 2 +- src/api-monitor-cs-main.ts | 10 - src/api/const.ts | 7 +- src/api/settings.ts | 34 +-- src/api/wrappers.ts | 206 ++++++++++++++++-- src/view/App.svelte | 2 + src/view/components/AnimationHistory.svelte | 10 +- .../IdleCallbackCancelHistory.svelte | 88 ++++++++ .../components/IdleCallbackMetrics.svelte | 22 ++ .../IdleCallbackRequestHistory.svelte | 196 +++++++++++++++++ src/view/components/InfoBar.svelte | 60 +++-- src/view/components/TimersClearHistory.svelte | 14 +- .../components/TimersHistoryCellSort.svelte | 6 +- src/view/components/TimersSetHistory.svelte | 28 +-- 16 files changed, 608 insertions(+), 96 deletions(-) create mode 100644 src/view/components/IdleCallbackCancelHistory.svelte create mode 100644 src/view/components/IdleCallbackMetrics.svelte create mode 100644 src/view/components/IdleCallbackRequestHistory.svelte diff --git a/jest/tests/time.test.ts b/jest/tests/time.test.ts index 2ee14e0..debc733 100644 --- a/jest/tests/time.test.ts +++ b/jest/tests/time.test.ts @@ -1,3 +1,11 @@ +// {{ jestis +import { TextEncoder } from 'node:util'; +global.TextEncoder = TextEncoder; +// @ts-ignore +global.requestIdleCallback = function noop() {}; +global.cancelIdleCallback = function noop() {}; +// }} + import { describe, expect, test, beforeEach } from '@jest/globals'; import { Stopper, Timer, Fps, MeanAggregator } from '../../src/api/time.ts'; diff --git a/jest/tests/wrappers.test.ts b/jest/tests/wrappers.test.ts index 2638f3f..1c90b5d 100644 --- a/jest/tests/wrappers.test.ts +++ b/jest/tests/wrappers.test.ts @@ -1,3 +1,11 @@ +// {{ jestis +import { TextEncoder } from 'node:util'; +global.TextEncoder = TextEncoder; +// @ts-ignore +global.requestIdleCallback = function noop() {}; +global.cancelIdleCallback = function noop() {}; +// }} + import { describe, expect, test, beforeEach, afterEach } from '@jest/globals'; import { Wrapper } from '../../src/api/wrappers.ts'; import { TAG_EXCEPTION, TAG_UNDEFINED } from '../../src/api/clone.ts'; @@ -6,9 +14,6 @@ import { TAG_EVAL_RETURN_SET_INTERVAL, TRACE_ERROR_MESSAGE, } from '../../src/api/const.ts'; -import { TextEncoder } from 'node:util'; - -global.TextEncoder = TextEncoder; describe('wrappers', () => { let wrapper: Wrapper; diff --git a/manifest.json b/manifest.json index b12b877..c28dd5b 100644 --- a/manifest.json +++ b/manifest.json @@ -2,7 +2,7 @@ "version": "1.0.5", "name": "API Monitor", "manifest_version": 3, - "description": "Reveal active or passed timeouts, intervals, and eval invocation call stacks. Observe events and properties of video/audio elements", + "description": "Reveal active or passed timeouts, intervals, and eval invocation call stacks. Observe events and properties of media elements", "minimum_chrome_version": "122.0", "homepage_url": "https://github.com/zendive/browser-api-monitor", "author": "calexblock@gmail.com", diff --git a/src/api-monitor-cs-main.ts b/src/api-monitor-cs-main.ts index 9f52f26..46e96dc 100644 --- a/src/api-monitor-cs-main.ts +++ b/src/api-monitor-cs-main.ts @@ -20,15 +20,6 @@ import { export interface TMetrics { mediaMetrics: TMediaTelemetry; wrapperMetrics: TWrapperMetrics; - callCounter: { - setTimeout: number; - clearTimeout: number; - setInterval: number; - clearInterval: number; - eval: number; - requestAnimationFrame: number; - cancelAnimationFrame: number; - }; collectingStartTime: number; } @@ -50,7 +41,6 @@ const tick = new Timer( const metrics: TMetrics = { mediaMetrics: collectMediaMetrics(panels.media), wrapperMetrics: wrapper.collectWrapperMetrics(panels), - callCounter: wrapper.callCounter, collectingStartTime: now, }; diff --git a/src/api/const.ts b/src/api/const.ts index 65c949a..4159a63 100644 --- a/src/api/const.ts +++ b/src/api/const.ts @@ -10,10 +10,13 @@ export const setTimeout = window.setTimeout.bind(window); export const clearTimeout = window.clearTimeout.bind(window); export const setInterval = window.setInterval.bind(window); export const clearInterval = window.clearInterval.bind(window); -// https://rollupjs.org/troubleshooting/#avoiding-eval -export const lessEval = window.eval.bind(window); export const requestAnimationFrame = window.requestAnimationFrame.bind(window); export const cancelAnimationFrame = window.cancelAnimationFrame.bind(window); +export const requestIdleCallback = window.requestIdleCallback.bind(window); +export const cancelIdleCallback = window.cancelIdleCallback.bind(window); +// https://rollupjs.org/troubleshooting/#avoiding-eval +export const lessEval = window.eval.bind(window); + export const TAG_INVALID_CALLSTACK_LINK = '⟪N/A⟫'; export const TAG_EVAL_RETURN_SET_TIMEOUT = '(N/A - via setTimeout)'; export const TAG_EVAL_RETURN_SET_INTERVAL = '(N/A - via setInterval)'; diff --git a/src/api/settings.ts b/src/api/settings.ts index 209d2f1..4677ee7 100644 --- a/src/api/settings.ts +++ b/src/api/settings.ts @@ -4,20 +4,22 @@ type TPanelKey = | 'eval' | 'media' | 'activeTimers' - | 'setTimeoutHistory' - | 'clearTimeoutHistory' - | 'setIntervalHistory' - | 'clearIntervalHistory' + | 'setTimeout' + | 'clearTimeout' + | 'setInterval' + | 'clearInterval' | 'requestAnimationFrame' - | 'cancelAnimationFrame'; + | 'cancelAnimationFrame' + | 'requestIdleCallback' + | 'cancelIdleCallback'; -export const ETimerHistoryField = { +export const EHistorySortField = { calls: 'calls', handler: 'handler', delay: 'delay', } as const; -export type ETimerHistoryFieldKeys = - (typeof ETimerHistoryField)[keyof typeof ETimerHistoryField]; +export type EHistorySortFieldKeys = + (typeof EHistorySortField)[keyof typeof EHistorySortField]; export const ESortOrder = { ASCENDING: 0, @@ -42,20 +44,22 @@ const DEFAULT_PANELS: TSettingsPanel[] = [ { key: 'eval', label: 'eval', visible: true }, { key: 'media', label: 'Media', visible: true }, { key: 'activeTimers', label: 'Active Timers', visible: true }, - { key: 'setTimeoutHistory', label: 'setTimeout History', visible: true }, - { key: 'clearTimeoutHistory', label: 'clearTimeout History', visible: true }, - { key: 'setIntervalHistory', label: 'setInterval History', visible: true }, + { key: 'setTimeout', label: 'setTimeout History', visible: true }, + { key: 'clearTimeout', label: 'clearTimeout History', visible: true }, + { key: 'setInterval', label: 'setInterval History', visible: true }, { - key: 'clearIntervalHistory', + key: 'clearInterval', label: 'clearInterval History', visible: true, }, - { key: 'requestAnimationFrame', label: 'RAF', visible: false }, - { key: 'cancelAnimationFrame', label: 'CAF', visible: false }, + { key: 'requestAnimationFrame', label: 'RAF History', visible: false }, + { key: 'cancelAnimationFrame', label: 'CAF History', visible: false }, + { key: 'requestIdleCallback', label: 'RIC History', visible: false }, + { key: 'cancelIdleCallback', label: 'CIC History', visible: false }, ]; export const DEFAULT_SORT = { - timersHistoryField: ETimerHistoryField.delay as ETimerHistoryFieldKeys, + timersHistoryField: EHistorySortField.delay as EHistorySortFieldKeys, timersHistoryOrder: ESortOrder.DESCENDING as ESortOrderKeys, }; diff --git a/src/api/wrappers.ts b/src/api/wrappers.ts index 5111f6d..2fd4c09 100644 --- a/src/api/wrappers.ts +++ b/src/api/wrappers.ts @@ -6,6 +6,8 @@ import { lessEval, requestAnimationFrame, cancelAnimationFrame, + requestIdleCallback, + cancelIdleCallback, REGEX_STACKTRACE_NAME, REGEX_STACKTRACE_LINK, TRACE_ERROR_MESSAGE, @@ -87,6 +89,26 @@ export type TAnimationHistory = { handler: number | undefined | string; hasError?: boolean; }; +export type TRequestIdleCallbackHistory = { + traceId: string; + trace: TTrace[]; + traceDomain: ETraceDomainKeys; + calls: number; + handler: number | undefined | string; + delay: number | undefined | string; + hasError: boolean; + didTimeout: undefined | boolean; + isOnline: boolean; + canceledByTraceIds: string[] | null; +}; +export type TCancelIdleCallbackHistory = { + traceId: string; + trace: TTrace[]; + traceDomain: ETraceDomainKeys; + calls: number; + handler: number | undefined | string; + hasError: boolean; +}; export type TWrapperMetrics = { onlineTimers: TOnlineTimerMetrics[] | null; setTimeoutHistory: TSetTimerHistory[] | null; @@ -96,6 +118,19 @@ export type TWrapperMetrics = { evalHistory: TEvalHistory[] | null; rafHistory: TAnimationHistory[] | null; cafHistory: TAnimationHistory[] | null; + ricHistory: TRequestIdleCallbackHistory[] | null; + cicHistory: TCancelIdleCallbackHistory[] | null; + callCounter: { + setTimeout: number; + clearTimeout: number; + setInterval: number; + clearInterval: number; + eval: number; + requestAnimationFrame: number; + cancelAnimationFrame: number; + requestIdleCallback: number; + cancelIdleCallback: number; + }; }; export class Wrapper { @@ -107,7 +142,9 @@ export class Wrapper { evalHistory: Map = new Map(); rafHistory: Map = new Map(); cafHistory: Map = new Map(); - callCounter = { + ricHistory: Map = new Map(); + cicHistory: Map = new Map(); + callCounter: TWrapperMetrics['callCounter'] = { setTimeout: 0, clearTimeout: 0, setInterval: 0, @@ -115,6 +152,8 @@ export class Wrapper { eval: 0, requestAnimationFrame: 0, cancelAnimationFrame: 0, + requestIdleCallback: 0, + cancelIdleCallback: 0, }; native = { setTimeout: setTimeout, @@ -124,6 +163,8 @@ export class Wrapper { eval: lessEval, requestAnimationFrame: requestAnimationFrame, cancelAnimationFrame: cancelAnimationFrame, + requestIdleCallback: requestIdleCallback, + cancelIdleCallback: cancelIdleCallback, }; selfTraceLink = ''; @@ -139,14 +180,13 @@ export class Wrapper { .replace(REGEX_STACKTRACE_CLEAN_URL, '$1'); } - #badTimerHandler(handler: unknown) { - return !Number.isFinite(handler) || handler < 1; + #validTimerHandler(handler: unknown): handler is number { + return Number.isFinite(handler) && handler > 0; } - #badTimerDelay(delay: unknown) { + #validTimerDelay(delay: unknown): delay is number { return ( - (delay !== undefined && !Number.isFinite(delay)) || - (Number.isFinite(delay) && delay < 0) + delay === undefined || (Number.isFinite(delay) && delay >= 0) ); } @@ -167,7 +207,7 @@ export class Wrapper { callstack: TCallstack, isEval: boolean ) { - if (this.#badTimerDelay(delay)) { + if (!this.#validTimerDelay(delay)) { delay = TAG_EXCEPTION(delay); } this.onlineTimers.set(handler, { @@ -220,7 +260,7 @@ export class Wrapper { isEval: boolean ) { const existing = history.get(callstack.traceId); - const hasError = this.#badTimerDelay(delay); + const hasError = !this.#validTimerDelay(delay); let handlerDelay: string | number | undefined = delay; if (hasError) { @@ -256,7 +296,7 @@ export class Wrapper { callstack: TCallstack ) { const existing = history.get(callstack.traceId); - const hasError = this.#badTimerHandler(handler); + const hasError = !this.#validTimerHandler(handler); const onlineTimer = hasError ? null : this.onlineTimers.get(handler); @@ -335,7 +375,7 @@ export class Wrapper { updateCafHistory(handler: number | string, callstack: TCallstack) { const existing = this.cafHistory.get(callstack.traceId); - const hasError = this.#badTimerHandler(handler); + const hasError = !this.#validTimerHandler(handler); if (hasError) { handler = TAG_EXCEPTION(handler); @@ -357,12 +397,94 @@ export class Wrapper { } } + markIdleRicRecord(deadline: IdleDeadline, callstack: TCallstack) { + const record = this.ricHistory.get(callstack.traceId); + + if (record) { + record.didTimeout = deadline.didTimeout; + record.isOnline = false; + } + } + + updateRicHistory( + handler: number, + delay: number | undefined | string, + callstack: TCallstack + ) { + const existing = this.ricHistory.get(callstack.traceId); + const hasError = !this.#validTimerDelay(delay); + + if (hasError) { + delay = 'N/A'; + } + + if (existing) { + existing.calls++; + existing.handler = handler; + existing.didTimeout = undefined; + existing.delay = delay; + existing.hasError = hasError; + existing.isOnline = true; + } else { + this.ricHistory.set(callstack.traceId, { + traceId: callstack.traceId, + trace: callstack.trace, + traceDomain: this.#getTraceDomain(callstack.trace[0]), + calls: 1, + handler, + didTimeout: undefined, + delay, + hasError, + isOnline: true, + canceledByTraceIds: null, + }); + } + } + + updateCicHistory(handler: number | string, callstack: TCallstack) { + const existing = this.cicHistory.get(callstack.traceId); + const hasError = !this.#validTimerHandler(handler); + + if (hasError) { + handler = TAG_EXCEPTION(handler); + } + + if (existing) { + existing.calls++; + existing.handler = handler; + existing.hasError = hasError; + } else { + this.cicHistory.set(callstack.traceId, { + traceId: callstack.traceId, + trace: callstack.trace, + traceDomain: this.#getTraceDomain(callstack.trace[0]), + calls: 1, + handler, + hasError, + }); + } + + const ricRecord = this.ricHistory.get(callstack.traceId); + if (ricRecord) { + ricRecord.isOnline = false; + if (ricRecord.canceledByTraceIds === null) { + ricRecord.canceledByTraceIds = [callstack.traceId]; + } else if (!ricRecord.canceledByTraceIds.includes(callstack.traceId)) { + ricRecord.canceledByTraceIds.push(callstack.traceId); + } + } + } + cleanHistory() { + this.evalHistory.clear(); this.setTimeoutHistory.clear(); this.clearTimeoutHistory.clear(); this.setIntervalHistory.clear(); this.clearIntervalHistory.clear(); - this.evalHistory.clear(); + this.rafHistory.clear(); + this.cafHistory.clear(); + this.ricHistory.clear(); + this.cicHistory.clear(); this.callCounter.setTimeout = this.callCounter.clearTimeout = this.callCounter.setInterval = @@ -370,50 +492,98 @@ export class Wrapper { this.callCounter.eval = this.callCounter.requestAnimationFrame = this.callCounter.cancelAnimationFrame = + this.callCounter.requestIdleCallback = + this.callCounter.cancelIdleCallback = 0; } collectWrapperMetrics(panels: TPanelVisibilityMap): TWrapperMetrics { return { + evalHistory: panels.eval ? Array.from(this.evalHistory.values()) : null, onlineTimers: panels.activeTimers ? Array.from(this.onlineTimers.values()) : null, - setTimeoutHistory: panels.setTimeoutHistory + setTimeoutHistory: panels.setTimeout ? Array.from(this.setTimeoutHistory.values()) : null, - clearTimeoutHistory: panels.clearTimeoutHistory + clearTimeoutHistory: panels.clearTimeout ? Array.from(this.clearTimeoutHistory.values()) : null, - setIntervalHistory: panels.setIntervalHistory + setIntervalHistory: panels.setInterval ? Array.from(this.setIntervalHistory.values()) : null, - clearIntervalHistory: panels.clearIntervalHistory + clearIntervalHistory: panels.clearInterval ? Array.from(this.clearIntervalHistory.values()) : null, - evalHistory: panels.eval ? Array.from(this.evalHistory.values()) : null, rafHistory: panels.requestAnimationFrame ? Array.from(this.rafHistory.values()) : null, cafHistory: panels.cancelAnimationFrame ? Array.from(this.cafHistory.values()) : null, + ricHistory: panels.requestIdleCallback + ? Array.from(this.ricHistory.values()) + : null, + cicHistory: panels.cancelIdleCallback + ? Array.from(this.cicHistory.values()) + : null, + callCounter: this.callCounter, }; } unwrapApis() { + window.eval = this.native.eval; window.setTimeout = this.native.setTimeout; window.clearTimeout = this.native.clearTimeout; window.setInterval = this.native.setInterval; window.clearInterval = this.native.clearInterval; - window.eval = this.native.eval; window.requestAnimationFrame = this.native.requestAnimationFrame; window.cancelAnimationFrame = this.native.cancelAnimationFrame; + window.requestIdleCallback = this.native.requestIdleCallback; + window.cancelIdleCallback = this.native.cancelIdleCallback; } wrapApis() { - this.wrapTimers(); this.wrapEval(); + this.wrapTimers(); this.wrapAnimation(); + this.wrapIdleCallback(); + } + + wrapIdleCallback() { + window.requestIdleCallback = function requestIdleCallback( + this: Wrapper, + fn: IdleRequestCallback, + options?: IdleRequestOptions | undefined + ) { + this.callCounter.requestIdleCallback++; + + const delay = options?.timeout; + const callstack = this.createCallstack( + new Error(TRACE_ERROR_MESSAGE), + fn + ); + const handler = this.native.requestIdleCallback((deadline) => { + this.markIdleRicRecord(deadline, callstack); + fn(deadline); + }, options); + + this.updateRicHistory(handler, delay, callstack); + + return handler; + }.bind(this); + + window.cancelIdleCallback = function cancelIdleCallback( + this: Wrapper, + handler: number + ) { + this.updateCicHistory( + handler, + this.createCallstack(new Error(TRACE_ERROR_MESSAGE), false) + ); + this.callCounter.cancelIdleCallback++; + this.native.cancelIdleCallback(handler); + }.bind(this); } wrapAnimation() { diff --git a/src/view/App.svelte b/src/view/App.svelte index c82a6c4..35c8717 100644 --- a/src/view/App.svelte +++ b/src/view/App.svelte @@ -13,6 +13,7 @@ import { getSettings, setSettings } from '@/api/settings.ts'; import TickSpinner from '@/view/components/TickSpinner.svelte'; import { MAX_TRAFFIC_DURATION_BEFORE_AUTOPAUSE } from '@/api/const.ts'; + import IdleCallbackMetrics from '@/view/components/IdleCallbackMetrics.svelte'; let spinner: TickSpinner | null = null; let paused = false; @@ -114,6 +115,7 @@ +
{/if} diff --git a/src/view/components/AnimationHistory.svelte b/src/view/components/AnimationHistory.svelte index 5a74551..b9dba6f 100644 --- a/src/view/components/AnimationHistory.svelte +++ b/src/view/components/AnimationHistory.svelte @@ -8,8 +8,8 @@ DEFAULT_SORT, getSettings, setSettings, - ETimerHistoryField, - type ETimerHistoryFieldKeys, + EHistorySortField, + type EHistorySortFieldKeys, type ESortOrderKeys, } from '@/api/settings.ts'; import { compareByFieldOrder } from '@/api/comparator.ts'; @@ -30,7 +30,7 @@ }); function onChangeSort( - e: CustomEvent<{ field: ETimerHistoryFieldKeys; order: ESortOrderKeys }> + e: CustomEvent<{ field: EHistorySortFieldKeys; order: ESortOrderKeys }> ) { field = e.detail.field; order = e.detail.order; @@ -53,7 +53,7 @@ Callstack Called Handler + import type { TCancelIdleCallbackHistory } from '@/api/wrappers.ts'; + import Variable from '@/view/components/Variable.svelte'; + import Trace from '@/view/components/Trace.svelte'; + import TraceDomain from '@/view/components/TraceDomain.svelte'; + import TimersHistoryCellSort from '@/view/components/TimersHistoryCellSort.svelte'; + import { + DEFAULT_SORT, + getSettings, + setSettings, + EHistorySortField, + type EHistorySortFieldKeys, + type ESortOrderKeys, + } from '@/api/settings.ts'; + import { compareByFieldOrder } from '@/api/comparator.ts'; + + export let caption: string = ''; + export let metrics: TCancelIdleCallbackHistory[]; + + let field = DEFAULT_SORT.timersHistoryField; + let order = DEFAULT_SORT.timersHistoryOrder; + + $: sortedMetrics = metrics.sort( + compareByFieldOrder(field, order) + ); + + getSettings().then((settings) => { + field = settings.sort.timersHistoryField; + order = settings.sort.timersHistoryOrder; + }); + + function onChangeSort( + e: CustomEvent<{ field: EHistorySortFieldKeys; order: ESortOrderKeys }> + ) { + field = e.detail.field; + order = e.detail.order; + setSettings({ + sort: { + timersHistoryField: field, + timersHistoryOrder: order, + }, + }); + } + + + + + + + + + + + + {#each sortedMetrics as metric (metric.traceId)} + + + + + + + {/each} +
+ {caption} + +
Callstack + Called + + Handler +
+ + {metric.calls}{metric.handler}
+ + diff --git a/src/view/components/IdleCallbackMetrics.svelte b/src/view/components/IdleCallbackMetrics.svelte new file mode 100644 index 0000000..1438228 --- /dev/null +++ b/src/view/components/IdleCallbackMetrics.svelte @@ -0,0 +1,22 @@ + + +{#if metrics.ricHistory?.length} + +{/if} + +{#if metrics.cicHistory?.length} + +{/if} diff --git a/src/view/components/IdleCallbackRequestHistory.svelte b/src/view/components/IdleCallbackRequestHistory.svelte new file mode 100644 index 0000000..2d1ed6e --- /dev/null +++ b/src/view/components/IdleCallbackRequestHistory.svelte @@ -0,0 +1,196 @@ + + + + {#if cicHistoryMetrics} +
+ + {/if} + + + + + + + + + + + + + + + {#each sortedMetrics as metric (metric.traceId)} + + + + + + + + + + {/each} +
+ {caption} + +
Callstack + Called + + Handler + didTimeout + Delay +
+ + {metric.calls}{metric.handler} + {#if metric.didTimeout !== undefined} + {metric.didTimeout} + {/if} + {metric.delay} + {#if metric.isOnline} + + {:else if metric.canceledByTraceIds?.length} + + void onShowRegressors(metric.canceledByTraceIds)} + > + + + {/if} +
+ + diff --git a/src/view/components/InfoBar.svelte b/src/view/components/InfoBar.svelte index 4e2bf89..5628a3b 100644 --- a/src/view/components/InfoBar.svelte +++ b/src/view/components/InfoBar.svelte @@ -48,10 +48,12 @@ {#if msg} void scrollTo('Eval History')} > - eval: + eval: void scrollTo('setTimeout History')} > setTimeout: void scrollTo('clearTimeout History')} > clearTimeout: void scrollTo('setInterval History')} > setInterval: void scrollTo('clearInterval History')} > clearInterval: void scrollTo('requestAnimationFrame History')} > RAF: - {msg.callCounter.requestAnimationFrame} + {msg.wrapperMetrics.callCounter.requestAnimationFrame} void scrollTo('cancelAnimationFrame History')} > CAF: - {msg.callCounter.cancelAnimationFrame} + {msg.wrapperMetrics.callCounter.cancelAnimationFrame} + + + + void scrollTo('requestIdleCallback History')} + > + RIC: + {msg.wrapperMetrics.callCounter.requestIdleCallback} + + + + void scrollTo('cancelIdleCallback History')} + > + CIC: + {msg.wrapperMetrics.callCounter.cancelIdleCallback} {/if} diff --git a/src/view/components/TimersClearHistory.svelte b/src/view/components/TimersClearHistory.svelte index ae487b3..bba2656 100644 --- a/src/view/components/TimersClearHistory.svelte +++ b/src/view/components/TimersClearHistory.svelte @@ -4,9 +4,9 @@ import { DEFAULT_SORT, getSettings, - ETimerHistoryField, + EHistorySortField, setSettings, - type ETimerHistoryFieldKeys, + type EHistorySortFieldKeys, type ESortOrderKeys, } from '@/api/settings.ts'; import TimersHistoryCellSort from '@/view/components/TimersHistoryCellSort.svelte'; @@ -16,7 +16,7 @@ export let caption: string = ''; export let metrics: TClearTimerHistory[]; - let field: ETimerHistoryFieldKeys = DEFAULT_SORT.timersHistoryField; + let field: EHistorySortFieldKeys = DEFAULT_SORT.timersHistoryField; let order: ESortOrderKeys = DEFAULT_SORT.timersHistoryOrder; $: metrics.sort(compareByFieldOrder(field, order)); @@ -27,7 +27,7 @@ }); function onChangeSort( - e: CustomEvent<{ field: ETimerHistoryFieldKeys; order: ESortOrderKeys }> + e: CustomEvent<{ field: EHistorySortFieldKeys; order: ESortOrderKeys }> ) { field = e.detail.field; order = e.detail.order; @@ -50,7 +50,7 @@ Callstack Called Handler Delay + e: CustomEvent<{ field: EHistorySortFieldKeys; order: ESortOrderKeys }> ) { field = e.detail.field; order = e.detail.order; @@ -52,16 +52,16 @@ } } + let clearTimerHistoryMetrics: TClearTimerHistory[] | null; + function onHideRegressor() { document.removeEventListener('keydown', onKeyboardEvent); dialog?.close(); - timersClearHistoryMetric = null; + clearTimerHistoryMetrics = null; } - let timersClearHistoryMetric: TClearTimerHistory[] | null; - function onShowRegressors(regressors: string[] | null) { - timersClearHistoryMetric = null; + clearTimerHistoryMetrics = null; if (!dialog || !regressors?.length) { return; } @@ -81,7 +81,7 @@ return; } - timersClearHistoryMetric = records; + clearTimerHistoryMetrics = records; dialog.showModal(); document.addEventListener('keydown', onKeyboardEvent); @@ -89,7 +89,7 @@ - {#if timersClearHistoryMetric} + {#if clearTimerHistoryMetrics}
@@ -112,7 +112,7 @@
{/if}
@@ -127,7 +127,7 @@ Callstack Called Handler Delay Date: Thu, 1 Aug 2024 04:40:07 +0300 Subject: [PATCH 43/53] fix active timers counter --- src/api/wrappers.ts | 4 ++++ src/view/components/InfoBar.svelte | 8 +++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/api/wrappers.ts b/src/api/wrappers.ts index 2fd4c09..3fffbaa 100644 --- a/src/api/wrappers.ts +++ b/src/api/wrappers.ts @@ -121,6 +121,7 @@ export type TWrapperMetrics = { ricHistory: TRequestIdleCallbackHistory[] | null; cicHistory: TCancelIdleCallbackHistory[] | null; callCounter: { + activeTimers: number; setTimeout: number; clearTimeout: number; setInterval: number; @@ -145,6 +146,7 @@ export class Wrapper { ricHistory: Map = new Map(); cicHistory: Map = new Map(); callCounter: TWrapperMetrics['callCounter'] = { + activeTimers: 0, setTimeout: 0, clearTimeout: 0, setInterval: 0, @@ -498,6 +500,8 @@ export class Wrapper { } collectWrapperMetrics(panels: TPanelVisibilityMap): TWrapperMetrics { + this.callCounter.activeTimers = this.onlineTimers.size; + return { evalHistory: panels.eval ? Array.from(this.evalHistory.values()) : null, onlineTimers: panels.activeTimers diff --git a/src/view/components/InfoBar.svelte b/src/view/components/InfoBar.svelte index 5628a3b..6e14093 100644 --- a/src/view/components/InfoBar.svelte +++ b/src/view/components/InfoBar.svelte @@ -11,7 +11,6 @@ export let msg: TMetrics; let panels: TPanelVisibilityMap; - $: onlineTimersSize = msg?.wrapperMetrics.onlineTimers?.length ?? 0; getSettings().then((settings) => { panels = panelsArrayToVisibilityMap(settings.panels); @@ -67,10 +66,13 @@ void scrollTo('Active')} > - Active Timers: + Active Timers: Date: Thu, 1 Aug 2024 21:44:04 +0300 Subject: [PATCH 44/53] add `onlineIdleCallbackLookup` for ric cancelation history to work --- src/api/hash.ts | 10 +++++++--- src/api/wrappers.ts | 37 ++++++++++++++++++++----------------- 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/src/api/hash.ts b/src/api/hash.ts index 4fe63c6..edf7b09 100644 --- a/src/api/hash.ts +++ b/src/api/hash.ts @@ -1,8 +1,12 @@ import { sha256 } from '@noble/hashes/sha256'; import { bytesToHex } from '@noble/hashes/utils'; -export const HASH_STRING_LENGTH = 64; +const HASH_STRING_LENGTH = 64; -export function hashString(str: string): string { - return bytesToHex(sha256(str)); +export function hashString(str: string) { + if (str.length > HASH_STRING_LENGTH) { + return bytesToHex(sha256(str)); + } + + return str; } diff --git a/src/api/wrappers.ts b/src/api/wrappers.ts index 3fffbaa..689ea76 100644 --- a/src/api/wrappers.ts +++ b/src/api/wrappers.ts @@ -20,7 +20,7 @@ import { } from '@/api/const.ts'; import { TAG_EXCEPTION, cloneObjectSafely } from '@/api/clone.ts'; import type { TPanelVisibilityMap } from '@/api/settings.ts'; -import { HASH_STRING_LENGTH, hashString } from '@/api//hash.ts'; +import { hashString } from '@/api/hash.ts'; export type TTrace = { name: string | 0; @@ -143,6 +143,8 @@ export class Wrapper { evalHistory: Map = new Map(); rafHistory: Map = new Map(); cafHistory: Map = new Map(); + /** mapping ric/cic handler to ric traceId */ + onlineIdleCallbackLookup: Map = new Map(); ricHistory: Map = new Map(); cicHistory: Map = new Map(); callCounter: TWrapperMetrics['callCounter'] = { @@ -399,10 +401,12 @@ export class Wrapper { } } - markIdleRicRecord(deadline: IdleDeadline, callstack: TCallstack) { + ricOffline(deadline: IdleDeadline, callstack: TCallstack) { const record = this.ricHistory.get(callstack.traceId); if (record) { + this.onlineIdleCallbackLookup.delete(Number(record.handler)); + record.didTimeout = deadline.didTimeout; record.isOnline = false; } @@ -417,7 +421,7 @@ export class Wrapper { const hasError = !this.#validTimerDelay(delay); if (hasError) { - delay = 'N/A'; + delay = TAG_EXCEPTION(delay); } if (existing) { @@ -441,6 +445,8 @@ export class Wrapper { canceledByTraceIds: null, }); } + + this.onlineIdleCallbackLookup.set(handler, callstack.traceId); } updateCicHistory(handler: number | string, callstack: TCallstack) { @@ -466,8 +472,11 @@ export class Wrapper { }); } - const ricRecord = this.ricHistory.get(callstack.traceId); + const ricTraceId = this.onlineIdleCallbackLookup.get(Number(handler)); + const ricRecord = ricTraceId && this.ricHistory.get(ricTraceId); if (ricRecord) { + this.onlineIdleCallbackLookup.delete(Number(handler)); + ricRecord.isOnline = false; if (ricRecord.canceledByTraceIds === null) { ricRecord.canceledByTraceIds = [callstack.traceId]; @@ -568,7 +577,7 @@ export class Wrapper { fn ); const handler = this.native.requestIdleCallback((deadline) => { - this.markIdleRicRecord(deadline, callstack); + this.ricOffline(deadline, callstack); fn(deadline); }, options); @@ -815,14 +824,12 @@ export class Wrapper { traceId += link; } - if (!trace.length) { - let name: TTrace['name'] = 0; + if (!traceId.length) { + traceId = String(uniqueTrait); - if (typeof uniqueTrait === 'function') { - name = uniqueTrait.name || 0; - traceId = hashString(String(uniqueTrait)); - } else { - traceId = String(uniqueTrait); + let name: TTrace['name'] = 0; + if (typeof uniqueTrait === 'function' && uniqueTrait.name) { + name = uniqueTrait.name; } trace.push({ @@ -831,10 +838,6 @@ export class Wrapper { }); } - if (traceId.length > HASH_STRING_LENGTH) { - traceId = hashString(traceId); - } - - return { traceId, trace }; + return { traceId: hashString(traceId), trace }; } } From 99cf0edf490bf3f80d347a47ed28f0c46aec62e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=95=B7?= <3756473+zendive@users.noreply.github.com> Date: Fri, 2 Aug 2024 19:06:36 +0300 Subject: [PATCH 45/53] extract Dialog component - add click-outside handler --- src/api-monitor-cs-main.ts | 2 +- src/api/wrappers.ts | 1 + src/view/components/Dialog.svelte | 90 +++++++++++++++ .../IdleCallbackRequestHistory.svelte | 82 ++++---------- src/view/components/MediaMetrics.svelte | 2 +- src/view/components/TimersClearHistory.svelte | 4 +- src/view/components/TimersSetHistory.svelte | 104 ++++-------------- 7 files changed, 143 insertions(+), 142 deletions(-) create mode 100644 src/view/components/Dialog.svelte diff --git a/src/api-monitor-cs-main.ts b/src/api-monitor-cs-main.ts index 46e96dc..9ce175d 100644 --- a/src/api-monitor-cs-main.ts +++ b/src/api-monitor-cs-main.ts @@ -1,5 +1,5 @@ import { windowListen, windowPost } from '@/api/communication.ts'; -import { IS_DEV } from './api/env.ts'; +import { IS_DEV } from '@/api/env.ts'; import { TELEMETRY_FREQUENCY_1PS, TELEMETRY_FREQUENCY_30PS, diff --git a/src/api/wrappers.ts b/src/api/wrappers.ts index 689ea76..1c88b28 100644 --- a/src/api/wrappers.ts +++ b/src/api/wrappers.ts @@ -478,6 +478,7 @@ export class Wrapper { this.onlineIdleCallbackLookup.delete(Number(handler)); ricRecord.isOnline = false; + ricRecord.didTimeout = undefined; if (ricRecord.canceledByTraceIds === null) { ricRecord.canceledByTraceIds = [callstack.traceId]; } else if (!ricRecord.canceledByTraceIds.includes(callstack.traceId)) { diff --git a/src/view/components/Dialog.svelte b/src/view/components/Dialog.svelte new file mode 100644 index 0000000..ff19052 --- /dev/null +++ b/src/view/components/Dialog.svelte @@ -0,0 +1,90 @@ + + + + {#if showContent} +
+
+ {#if title} + {title} + {/if} + {#if description} +
{description}
+ {/if} +
+ +
+ + +
+ + + {/if} + + + diff --git a/src/view/components/IdleCallbackRequestHistory.svelte b/src/view/components/IdleCallbackRequestHistory.svelte index 2d1ed6e..e1d64a5 100644 --- a/src/view/components/IdleCallbackRequestHistory.svelte +++ b/src/view/components/IdleCallbackRequestHistory.svelte @@ -16,15 +16,16 @@ type ESortOrderKeys, } from '@/api/settings.ts'; import { compareByFieldOrder } from '@/api/comparator.ts'; - import IdleCallbackCancelHistory from './IdleCallbackCancelHistory.svelte'; + import IdleCallbackCancelHistory from '@/view/components/IdleCallbackCancelHistory.svelte'; + import Dialog from '@/view/components/Dialog.svelte'; export let caption: string = ''; export let metrics: TRequestIdleCallbackHistory[]; + export let cicHistory: TCancelIdleCallbackHistory[] | null; let field = DEFAULT_SORT.timersHistoryField; let order = DEFAULT_SORT.timersHistoryOrder; - let dialog: HTMLDialogElement | null = null; - export let cicHistory: TCancelIdleCallbackHistory[] | null; + let dialog: Dialog | null = null; $: sortedMetrics = metrics.sort( compareByFieldOrder(field, order) @@ -48,77 +49,42 @@ }); } - function onKeyboardEvent(e: KeyboardEvent) { - if (e.key === 'Escape') { - e.preventDefault(); - e.stopImmediatePropagation(); - onHideRegressor(); - } - } - - let cicHistoryMetrics: TCancelIdleCallbackHistory[] | null; - - function onHideRegressor() { - document.removeEventListener('keydown', onKeyboardEvent); - dialog?.close(); - cicHistoryMetrics = null; - } + let cicHistoryMetrics: TCancelIdleCallbackHistory[] = []; - function onShowRegressors(regressors: string[] | null) { - cicHistoryMetrics = null; + function onFindRegressors(regressors: string[] | null) { if (!dialog || !regressors?.length) { return; } - const records = []; - for (let n = regressors.length - 1; n >= 0; n--) { const traceId = regressors[n]; let record = cicHistory?.find((r) => r.traceId === traceId); if (record) { - records.push(record); + cicHistoryMetrics.push(record); } } - if (!records.length) { - return; + if (cicHistoryMetrics.length) { + dialog.showModal(); } + } - cicHistoryMetrics = records; - - dialog.showModal(); - document.addEventListener('keydown', onKeyboardEvent); + function onCloseDialog() { + cicHistoryMetrics.splice(0); } - - {#if cicHistoryMetrics} -
-
-
- Places from which timer with current callstack was prematurely - canceled: -
-
- The information is actual only on time of demand. For full coverage - - requires both clearTimeout and clearInterval panels enabled. -
-
- - - -
- - {/if} -
+ + + {/each} @@ -55,7 +55,7 @@ min-width: var(--small-icon-size); } .handler-cell { - .icon.-remove { + .icon { display: none; cursor: pointer; } @@ -63,7 +63,7 @@ .handler-value { display: none; } - .icon.-remove { + .icon { display: inline-block; } } diff --git a/src/view/components/AnimationHistory.svelte b/src/view/components/AnimationHistory.svelte index b9dba6f..56ba078 100644 --- a/src/view/components/AnimationHistory.svelte +++ b/src/view/components/AnimationHistory.svelte @@ -73,7 +73,7 @@ diff --git a/src/view/components/EvalMetrics.svelte b/src/view/components/EvalMetrics.svelte index 16184a9..f44dde4 100644 --- a/src/view/components/EvalMetrics.svelte +++ b/src/view/components/EvalMetrics.svelte @@ -35,7 +35,7 @@ diff --git a/src/view/components/IdleCallbackRequestHistory.svelte b/src/view/components/IdleCallbackRequestHistory.svelte index e38640a..b4c4422 100644 --- a/src/view/components/IdleCallbackRequestHistory.svelte +++ b/src/view/components/IdleCallbackRequestHistory.svelte @@ -126,7 +126,7 @@ diff --git a/src/view/components/TimersClearHistoryMetric.svelte b/src/view/components/TimersClearHistoryMetric.svelte index c65b9d1..759c8af 100644 --- a/src/view/components/TimersClearHistoryMetric.svelte +++ b/src/view/components/TimersClearHistoryMetric.svelte @@ -10,7 +10,7 @@
@@ -179,7 +145,7 @@ title={`Canceled by ${metric.canceledByTraceIds?.length}`} href="void(0)" on:click|preventDefault={() => - void onShowRegressors(metric.canceledByTraceIds)} + void onFindRegressors(metric.canceledByTraceIds)} > diff --git a/src/view/components/MediaMetrics.svelte b/src/view/components/MediaMetrics.svelte index 2dcfb70..368d5da 100644 --- a/src/view/components/MediaMetrics.svelte +++ b/src/view/components/MediaMetrics.svelte @@ -1,7 +1,7 @@ - - {#if clearTimerHistoryMetrics} -
-
-
- Places from which timer with current callstack was prematurely - canceled: -
-
- The information is actual only on time of demand. For full coverage - - requires both clearTimeout and clearInterval panels enabled. -
-
- - - -
- - {/if} -
+ + + - {#each metrics as metric (metric.traceId)} + {#each sortedMetrics as metric (metric.traceId)} diff --git a/src/view/components/TimersSetHistory.svelte b/src/view/components/TimersSetHistory.svelte index 6faa934..df3859b 100644 --- a/src/view/components/TimersSetHistory.svelte +++ b/src/view/components/TimersSetHistory.svelte @@ -130,18 +130,22 @@ From b967a61487c568d3271d7074ef3e98e7d528e9bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=95=B7?= <3756473+zendive@users.noreply.github.com> Date: Wed, 7 Aug 2024 08:43:06 +0300 Subject: [PATCH 49/53] add wrap/unwrap functionality to the rest of the functions --- src/api-monitor-cs-main.ts | 35 ++++++++++++----- src/api/settings.ts | 6 +-- src/api/wrappers.ts | 27 ++++++++++--- src/view/components/InfoBarItem.svelte | 21 +++++------ src/view/components/TogglePanels.svelte | 50 ++++++++++++------------- 5 files changed, 83 insertions(+), 56 deletions(-) diff --git a/src/api-monitor-cs-main.ts b/src/api-monitor-cs-main.ts index 0382f92..484b7b8 100644 --- a/src/api-monitor-cs-main.ts +++ b/src/api-monitor-cs-main.ts @@ -24,12 +24,23 @@ export interface TMetrics { } const wrapper = new Wrapper(); -const wrapEvalOnce = callingOnce(wrapper.wrapEval.bind(wrapper)); -// @NOTE: wrqpper.wrapEvel() not called here -wrapper.wrapTimers(); -wrapper.wrapAnimationFrame(); -wrapper.wrapIdleCallback(); - +const wrapEvalOnce = callingOnce(() => wrapper.wrapEval()); +const wrapSetTimeoutOnce = callingOnce(() => wrapper.wrapSetTimeout()); +const wrapClearTimeoutOnce = callingOnce(() => wrapper.wrapClearTimeout()); +const wrapSetIntervalOnce = callingOnce(() => wrapper.wrapSetInterval()); +const wrapClearIntervalOnce = callingOnce(() => wrapper.wrapClearInterval()); +const wrapRequestAnimationFrameOnce = callingOnce(() => + wrapper.wrapRequestAnimationFrame() +); +const wrapCancelAnimationFrameOnce = callingOnce(() => + wrapper.wrapCancelAnimationFrame() +); +const wrapRequestIdleCallbackOnce = callingOnce(() => + wrapper.wrapRequestIdleCallback() +); +const wrapCancelIdleCallbackOnce = callingOnce(() => + wrapper.wrapCancelIdleCallback() +); let panels = panelsArrayToVisibilityMap(DEFAULT_SETTINGS.panels); const eachSecond = new Timer( () => { @@ -81,9 +92,15 @@ windowListen((o) => { typeof o.settings === 'object' ) { panels = panelsArrayToVisibilityMap(o.settings.panels); - if (panels.eval.wrap) { - wrapEvalOnce(); - } + panels.eval.wrap && wrapEvalOnce(); + panels.setTimeout.wrap && wrapSetTimeoutOnce(); + panels.clearTimeout.wrap && wrapClearTimeoutOnce(); + panels.setInterval.wrap && wrapSetIntervalOnce(); + panels.clearInterval.wrap && wrapClearIntervalOnce(); + panels.requestAnimationFrame && wrapRequestAnimationFrameOnce(); + panels.cancelAnimationFrame && wrapCancelAnimationFrameOnce(); + panels.requestIdleCallback && wrapRequestIdleCallbackOnce(); + panels.cancelIdleCallback && wrapCancelIdleCallbackOnce(); } else if (o.msg === 'reset-wrapper-history') { wrapper.cleanHistory(); tick.trigger(); diff --git a/src/api/settings.ts b/src/api/settings.ts index cb5416c..8de17d0 100644 --- a/src/api/settings.ts +++ b/src/api/settings.ts @@ -23,16 +23,16 @@ export type TSettingsPanel = { key: TPanelKey; label: string; visible: boolean; - wrap: boolean; + wrap: boolean | null; }; export type TSettings = typeof DEFAULT_SETTINGS; export type TSettingsProperty = Partial; const SETTINGS_VERSION = '1.0.5'; const DEFAULT_PANELS: TSettingsPanel[] = [ + { key: 'media', label: 'Media', visible: true, wrap: null }, + { key: 'activeTimers', label: 'Active Timers', visible: true, wrap: null }, { key: 'eval', label: 'eval', visible: true, wrap: false }, - { key: 'media', label: 'Media', visible: true, wrap: true }, - { key: 'activeTimers', label: 'Active Timers', visible: true, wrap: true }, { key: 'setTimeout', label: 'setTimeout History', visible: true, wrap: true }, { key: 'clearTimeout', diff --git a/src/api/wrappers.ts b/src/api/wrappers.ts index ae7b4e0..4bdb444 100644 --- a/src/api/wrappers.ts +++ b/src/api/wrappers.ts @@ -561,12 +561,17 @@ export class Wrapper { wrapApis() { this.wrapEval(); - this.wrapTimers(); - this.wrapAnimationFrame(); - this.wrapIdleCallback(); + this.wrapSetTimeout(); + this.wrapClearTimeout(); + this.wrapSetInterval(); + this.wrapClearInterval(); + this.wrapRequestAnimationFrame(); + this.wrapCancelAnimationFrame(); + this.wrapRequestIdleCallback(); + this.wrapCancelIdleCallback(); } - wrapIdleCallback() { + wrapRequestIdleCallback() { window.requestIdleCallback = function requestIdleCallback( this: Wrapper, fn: IdleRequestCallback, @@ -588,7 +593,9 @@ export class Wrapper { return handler; }.bind(this); + } + wrapCancelIdleCallback() { window.cancelIdleCallback = function cancelIdleCallback( this: Wrapper, handler: number @@ -602,7 +609,7 @@ export class Wrapper { }.bind(this); } - wrapAnimationFrame() { + wrapRequestAnimationFrame() { window.requestAnimationFrame = function requestAnimationFrame( this: Wrapper, fn: FrameRequestCallback @@ -616,7 +623,9 @@ export class Wrapper { return handler; }.bind(this); + } + wrapCancelAnimationFrame() { window.cancelAnimationFrame = function cancelAnimationFrame( this: Wrapper, handler: number @@ -665,7 +674,7 @@ export class Wrapper { }.bind(this); } - wrapTimers() { + wrapSetTimeout() { window.setTimeout = function setTimeout( this: Wrapper, code: TimerHandler, @@ -712,7 +721,9 @@ export class Wrapper { return handler; }.bind(this); + } + wrapClearTimeout() { window.clearTimeout = function clearTimeout( this: Wrapper, handler: number | undefined @@ -733,7 +744,9 @@ export class Wrapper { this.callCounter.clearTimeout++; this.native.clearTimeout(handler); }.bind(this); + } + wrapSetInterval() { window.setInterval = function setInterval( this: Wrapper, code: TimerHandler, @@ -779,7 +792,9 @@ export class Wrapper { return handler; }.bind(this); + } + wrapClearInterval() { window.clearInterval = function clearInterval( this: Wrapper, handler: number | undefined diff --git a/src/view/components/InfoBarItem.svelte b/src/view/components/InfoBarItem.svelte index 47a249c..d2888b8 100644 --- a/src/view/components/InfoBarItem.svelte +++ b/src/view/components/InfoBarItem.svelte @@ -42,14 +42,15 @@ } - - {label}: - +{#if panel.wrap !== false} + + {label}: + +{/if} diff --git a/src/view/components/TogglePanels.svelte b/src/view/components/TogglePanels.svelte index 6616fa4..fd8d18a 100644 --- a/src/view/components/TogglePanels.svelte +++ b/src/view/components/TogglePanels.svelte @@ -6,6 +6,7 @@ type TSettingsPanel, } from '@/api/settings.ts'; + const nonWrappable = ['media', 'activeTimers']; let panels: TSettingsPanel[] = []; let popoverEl: HTMLElement | null = null; @@ -33,27 +34,31 @@
@@ -152,7 +118,7 @@
@@ -172,7 +138,7 @@ title={`Canceled by ${metric.canceledByTraceIds?.length}`} href="void(0)" on:click|preventDefault={() => - void onShowRegressors(metric.canceledByTraceIds)} + void onFindRegressors(metric.canceledByTraceIds)} > @@ -186,26 +152,4 @@ .shaft { min-width: var(--small-icon-size); } - dialog { - background-color: var(--bg); - color: var(--text); - border: 1px solid var(--border); - - .header { - display: flex; - flex-wrap: nowrap; - margin-bottom: 0.5rem; - - .title { - flex-grow: 1; - font-size: large; - .requirement { - font-size: x-small; - } - } - .close-icon { - text-decoration: none; - } - } - } From 9438fddda8bc619250c641826f6fc40422c350d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=95=B7?= <3756473+zendive@users.noreply.github.com> Date: Mon, 5 Aug 2024 06:43:47 +0300 Subject: [PATCH 46/53] fix #9: wrap eval on demand --- src/api-monitor-cs-main.ts | 13 +- src/api/settings.ts | 79 +++++--- src/api/time.ts | 10 + src/api/wrappers.ts | 26 +-- src/view/components/InfoBar.svelte | 232 +++++++++--------------- src/view/components/InfoBarItem.svelte | 69 +++++++ src/view/components/TogglePanels.svelte | 98 +++++++--- 7 files changed, 314 insertions(+), 213 deletions(-) create mode 100644 src/view/components/InfoBarItem.svelte diff --git a/src/api-monitor-cs-main.ts b/src/api-monitor-cs-main.ts index 9ce175d..0382f92 100644 --- a/src/api-monitor-cs-main.ts +++ b/src/api-monitor-cs-main.ts @@ -4,7 +4,7 @@ import { TELEMETRY_FREQUENCY_1PS, TELEMETRY_FREQUENCY_30PS, } from '@/api/const.ts'; -import { Timer } from '@/api/time.ts'; +import { callingOnce, Timer } from '@/api/time.ts'; import { collectMediaMetrics, meetMedia, @@ -24,7 +24,11 @@ export interface TMetrics { } const wrapper = new Wrapper(); -wrapper.wrapApis(); +const wrapEvalOnce = callingOnce(wrapper.wrapEval.bind(wrapper)); +// @NOTE: wrqpper.wrapEvel() not called here +wrapper.wrapTimers(); +wrapper.wrapAnimationFrame(); +wrapper.wrapIdleCallback(); let panels = panelsArrayToVisibilityMap(DEFAULT_SETTINGS.panels); const eachSecond = new Timer( @@ -39,7 +43,7 @@ const tick = new Timer( const now = Date.now(); const metrics: TMetrics = { - mediaMetrics: collectMediaMetrics(panels.media), + mediaMetrics: collectMediaMetrics(panels.media.visible), wrapperMetrics: wrapper.collectWrapperMetrics(panels), collectingStartTime: now, }; @@ -77,6 +81,9 @@ windowListen((o) => { typeof o.settings === 'object' ) { panels = panelsArrayToVisibilityMap(o.settings.panels); + if (panels.eval.wrap) { + wrapEvalOnce(); + } } else if (o.msg === 'reset-wrapper-history') { wrapper.cleanHistory(); tick.trigger(); diff --git a/src/api/settings.ts b/src/api/settings.ts index 4677ee7..cb5416c 100644 --- a/src/api/settings.ts +++ b/src/api/settings.ts @@ -13,51 +13,82 @@ type TPanelKey = | 'requestIdleCallback' | 'cancelIdleCallback'; -export const EHistorySortField = { - calls: 'calls', - handler: 'handler', - delay: 'delay', -} as const; export type EHistorySortFieldKeys = (typeof EHistorySortField)[keyof typeof EHistorySortField]; - -export const ESortOrder = { - ASCENDING: 0, - DESCENDING: 1, -} as const; export type ESortOrderKeys = (typeof ESortOrder)[keyof typeof ESortOrder]; export type TPanelVisibilityMap = { - [K in TPanelKey]: boolean; + [K in TPanelKey]: TSettingsPanel; }; - export type TSettingsPanel = { key: TPanelKey; label: string; visible: boolean; + wrap: boolean; }; - export type TSettings = typeof DEFAULT_SETTINGS; export type TSettingsProperty = Partial; const SETTINGS_VERSION = '1.0.5'; const DEFAULT_PANELS: TSettingsPanel[] = [ - { key: 'eval', label: 'eval', visible: true }, - { key: 'media', label: 'Media', visible: true }, - { key: 'activeTimers', label: 'Active Timers', visible: true }, - { key: 'setTimeout', label: 'setTimeout History', visible: true }, - { key: 'clearTimeout', label: 'clearTimeout History', visible: true }, - { key: 'setInterval', label: 'setInterval History', visible: true }, + { key: 'eval', label: 'eval', visible: true, wrap: false }, + { key: 'media', label: 'Media', visible: true, wrap: true }, + { key: 'activeTimers', label: 'Active Timers', visible: true, wrap: true }, + { key: 'setTimeout', label: 'setTimeout History', visible: true, wrap: true }, + { + key: 'clearTimeout', + label: 'clearTimeout History', + visible: true, + wrap: true, + }, + { + key: 'setInterval', + label: 'setInterval History', + visible: true, + wrap: true, + }, { key: 'clearInterval', label: 'clearInterval History', visible: true, + wrap: true, + }, + { + key: 'requestAnimationFrame', + label: 'RAF History', + visible: false, + wrap: true, + }, + { + key: 'cancelAnimationFrame', + label: 'CAF History', + visible: false, + wrap: true, + }, + { + key: 'requestIdleCallback', + label: 'RIC History', + visible: false, + wrap: true, + }, + { + key: 'cancelIdleCallback', + label: 'CIC History', + visible: false, + wrap: true, }, - { key: 'requestAnimationFrame', label: 'RAF History', visible: false }, - { key: 'cancelAnimationFrame', label: 'CAF History', visible: false }, - { key: 'requestIdleCallback', label: 'RIC History', visible: false }, - { key: 'cancelIdleCallback', label: 'CIC History', visible: false }, ]; +export const EHistorySortField = { + calls: 'calls', + handler: 'handler', + delay: 'delay', +} as const; + +export const ESortOrder = { + ASCENDING: 0, + DESCENDING: 1, +} as const; + export const DEFAULT_SORT = { timersHistoryField: EHistorySortField.delay as EHistorySortFieldKeys, timersHistoryOrder: ESortOrder.DESCENDING as ESortOrderKeys, @@ -72,7 +103,7 @@ export const DEFAULT_SETTINGS = { export function panelsArrayToVisibilityMap(panels: TSettingsPanel[]) { return panels.reduce( - (acc, o) => Object.assign(acc, { [o.key]: o.visible }), + (acc, o) => Object.assign(acc, { [o.key]: o }), {} as TPanelVisibilityMap ); } diff --git a/src/api/time.ts b/src/api/time.ts index 68cf80d..2e3a86c 100644 --- a/src/api/time.ts +++ b/src/api/time.ts @@ -5,6 +5,16 @@ import { cancelAnimationFrame, } from '@/api/const.ts'; +export function callingOnce(fn: (...args: any[]) => any) { + let runOnce = false; + return () => { + if (!runOnce) { + fn(); + runOnce = true; + } + }; +} + /** * Measure time between start/stop calls * programmatic alternative to console.time/console.endTime diff --git a/src/api/wrappers.ts b/src/api/wrappers.ts index 1c88b28..ae7b4e0 100644 --- a/src/api/wrappers.ts +++ b/src/api/wrappers.ts @@ -513,32 +513,34 @@ export class Wrapper { this.callCounter.activeTimers = this.onlineTimers.size; return { - evalHistory: panels.eval ? Array.from(this.evalHistory.values()) : null, - onlineTimers: panels.activeTimers + evalHistory: panels.eval.visible + ? Array.from(this.evalHistory.values()) + : null, + onlineTimers: panels.activeTimers.visible ? Array.from(this.onlineTimers.values()) : null, - setTimeoutHistory: panels.setTimeout + setTimeoutHistory: panels.setTimeout.visible ? Array.from(this.setTimeoutHistory.values()) : null, - clearTimeoutHistory: panels.clearTimeout + clearTimeoutHistory: panels.clearTimeout.visible ? Array.from(this.clearTimeoutHistory.values()) : null, - setIntervalHistory: panels.setInterval + setIntervalHistory: panels.setInterval.visible ? Array.from(this.setIntervalHistory.values()) : null, - clearIntervalHistory: panels.clearInterval + clearIntervalHistory: panels.clearInterval.visible ? Array.from(this.clearIntervalHistory.values()) : null, - rafHistory: panels.requestAnimationFrame + rafHistory: panels.requestAnimationFrame.visible ? Array.from(this.rafHistory.values()) : null, - cafHistory: panels.cancelAnimationFrame + cafHistory: panels.cancelAnimationFrame.visible ? Array.from(this.cafHistory.values()) : null, - ricHistory: panels.requestIdleCallback + ricHistory: panels.requestIdleCallback.visible ? Array.from(this.ricHistory.values()) : null, - cicHistory: panels.cancelIdleCallback + cicHistory: panels.cancelIdleCallback.visible ? Array.from(this.cicHistory.values()) : null, callCounter: this.callCounter, @@ -560,7 +562,7 @@ export class Wrapper { wrapApis() { this.wrapEval(); this.wrapTimers(); - this.wrapAnimation(); + this.wrapAnimationFrame(); this.wrapIdleCallback(); } @@ -600,7 +602,7 @@ export class Wrapper { }.bind(this); } - wrapAnimation() { + wrapAnimationFrame() { window.requestAnimationFrame = function requestAnimationFrame( this: Wrapper, fn: FrameRequestCallback diff --git a/src/view/components/InfoBar.svelte b/src/view/components/InfoBar.svelte index 6e14093..52a9f62 100644 --- a/src/view/components/InfoBar.svelte +++ b/src/view/components/InfoBar.svelte @@ -1,12 +1,12 @@ @@ -172,15 +113,4 @@ flex-grow: 1; align-items: center; } - - a { - pointer-events: none; - padding: 0 0.4rem; - border-right: 1px solid var(--border); - - &.panel-enabled { - pointer-events: all; - color: var(--text); - } - } diff --git a/src/view/components/InfoBarItem.svelte b/src/view/components/InfoBarItem.svelte new file mode 100644 index 0000000..d542838 --- /dev/null +++ b/src/view/components/InfoBarItem.svelte @@ -0,0 +1,69 @@ + + + + {label}: + + + diff --git a/src/view/components/TogglePanels.svelte b/src/view/components/TogglePanels.svelte index f1482e8..6616fa4 100644 --- a/src/view/components/TogglePanels.svelte +++ b/src/view/components/TogglePanels.svelte @@ -1,4 +1,5 @@ + +
+ Tab reload required
From 12505625154b751dcff3df43178209b75e000f3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=95=B7?= <3756473+zendive@users.noreply.github.com> Date: Mon, 5 Aug 2024 11:30:39 +0300 Subject: [PATCH 47/53] tune infobar link hover text decoration --- src/view/components/InfoBarItem.svelte | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/view/components/InfoBarItem.svelte b/src/view/components/InfoBarItem.svelte index d542838..47a249c 100644 --- a/src/view/components/InfoBarItem.svelte +++ b/src/view/components/InfoBarItem.svelte @@ -57,9 +57,17 @@ padding: 0 0.4rem; border-right: 1px solid var(--border); + &:hover { + text-decoration: none; + } + &.panel-enabled { cursor: pointer; color: var(--text); + + &:hover { + text-decoration: underline; + } } &.panel-unwrapped { From 7fd939d38e3ad1793d1c0815bac06e06ff779f71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=95=B7?= <3756473+zendive@users.noreply.github.com> Date: Tue, 6 Aug 2024 07:01:21 +0300 Subject: [PATCH 48/53] show regressors also for metrics being currently online --- .../components/IdleCallbackRequestHistory.svelte | 14 +++++++++----- src/view/components/TimersSetHistory.svelte | 14 +++++++++----- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/view/components/IdleCallbackRequestHistory.svelte b/src/view/components/IdleCallbackRequestHistory.svelte index e1d64a5..e38640a 100644 --- a/src/view/components/IdleCallbackRequestHistory.svelte +++ b/src/view/components/IdleCallbackRequestHistory.svelte @@ -137,18 +137,22 @@
{metric.delay} - {#if metric.isOnline} - - {:else if metric.canceledByTraceIds?.length} + {#if metric.canceledByTraceIds?.length} void onFindRegressors(metric.canceledByTraceIds)} > - + {#if metric.isOnline} + + {:else} + + {/if} + {:else if metric.isOnline} + {/if}
{metric.handler} {metric.delay} - {#if metric.isOnline} - - {:else if metric.canceledByTraceIds?.length} + {#if metric.canceledByTraceIds?.length} void onFindRegressors(metric.canceledByTraceIds)} > - + {#if metric.isOnline} + + {:else} + + {/if} + {:else if metric.isOnline} + {/if}
{#each panels as panel, index (panel.key)} - - {#if panel.key === 'eval'} - {/if} - + {/each} - +
@@ -83,28 +88,21 @@ .dropdown-content { position: absolute; display: none; - min-width: 8rem; background-color: var(--bg); border-right: 1px solid var(--border); border-bottom: 1px solid var(--border); border-left: 1px solid var(--border); - list-style: none; - padding: 0px 6px; margin: 0; z-index: 1; .menu-item { - display: flex; - cursor: pointer; - line-height: 1.5rem; + line-height: 1.4rem; .toggle-visibility { - flex-grow: 1; color: var(--text); + text-wrap: nowrap; + margin-left: 0.375rem; - &:hover { - font-weight: bold; - } &.hidden { color: var(--text-passive); } @@ -114,7 +112,7 @@ color: var(--text); border-left: 1px solid var(--border); border-right: none; - margin-right: 0; + margin-left: 0.375rem; } } } From d7407e7112f6ce18bbffacded487e47240d7c9ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=95=B7?= <3756473+zendive@users.noreply.github.com> Date: Wed, 7 Aug 2024 10:59:08 +0300 Subject: [PATCH 50/53] fix `createCallstack` (translate.google.com requestIdleCallback) --- src/api-monitor-cs-isolated.ts | 10 +++--- src/api/wrappers.ts | 62 ++++++++++++---------------------- 2 files changed, 27 insertions(+), 45 deletions(-) diff --git a/src/api-monitor-cs-isolated.ts b/src/api-monitor-cs-isolated.ts index 8577ab9..35fdbb3 100644 --- a/src/api-monitor-cs-isolated.ts +++ b/src/api-monitor-cs-isolated.ts @@ -6,11 +6,6 @@ import { } from '@/api/communication.ts'; import { getSettings, onSettingsChange } from '@/api/settings.ts'; -portListen(windowPost); -windowListen(runtimePost); - -runtimePost({ msg: 'content-script-loaded' }); - getSettings().then((settings) => { windowPost({ msg: 'settings', settings: settings }); @@ -18,3 +13,8 @@ getSettings().then((settings) => { windowPost({ msg: 'settings', settings: newValue }); }); }); + +portListen(windowPost); +windowListen(runtimePost); + +runtimePost({ msg: 'content-script-loaded' }); diff --git a/src/api/wrappers.ts b/src/api/wrappers.ts index 4bdb444..ccaa0c9 100644 --- a/src/api/wrappers.ts +++ b/src/api/wrappers.ts @@ -580,10 +580,8 @@ export class Wrapper { this.callCounter.requestIdleCallback++; const delay = options?.timeout; - const callstack = this.createCallstack( - new Error(TRACE_ERROR_MESSAGE), - fn - ); + const err = new Error(TRACE_ERROR_MESSAGE); + const callstack = this.createCallstack(err, fn); const handler = this.native.requestIdleCallback((deadline) => { this.ricOffline(deadline, callstack); fn(deadline); @@ -600,10 +598,8 @@ export class Wrapper { this: Wrapper, handler: number ) { - this.updateCicHistory( - handler, - this.createCallstack(new Error(TRACE_ERROR_MESSAGE), false) - ); + const err = new Error(TRACE_ERROR_MESSAGE); + this.updateCicHistory(handler, this.createCallstack(err)); this.callCounter.cancelIdleCallback++; this.native.cancelIdleCallback(handler); }.bind(this); @@ -616,10 +612,8 @@ export class Wrapper { ) { this.callCounter.requestAnimationFrame++; const handler = this.native.requestAnimationFrame(fn); - this.updateRafHistory( - handler, - this.createCallstack(new Error(TRACE_ERROR_MESSAGE), fn) - ); + const err = new Error(TRACE_ERROR_MESSAGE); + this.updateRafHistory(handler, this.createCallstack(err, fn)); return handler; }.bind(this); @@ -630,10 +624,8 @@ export class Wrapper { this: Wrapper, handler: number ) { - this.updateCafHistory( - handler, - this.createCallstack(new Error(TRACE_ERROR_MESSAGE), false) - ); + const err = new Error(TRACE_ERROR_MESSAGE); + this.updateCafHistory(handler, this.createCallstack(err)); this.callCounter.cancelAnimationFrame++; this.native.cancelAnimationFrame(handler); }.bind(this); @@ -659,10 +651,11 @@ export class Wrapper { } } + const err = new Error(TRACE_ERROR_MESSAGE); this.updateEvalHistory( code, rv, - this.createCallstack(new Error(TRACE_ERROR_MESSAGE), code), + this.createCallstack(err, code), usesLocalScope ); @@ -695,10 +688,8 @@ export class Wrapper { delay, ...args ); - const callstack = this.createCallstack( - new Error(TRACE_ERROR_MESSAGE), - code - ); + const err = new Error(TRACE_ERROR_MESSAGE); + const callstack = this.createCallstack(err, code); this.callCounter.setTimeout++; this.timerOnline(ETimerType.TIMEOUT, handler, delay, callstack, isEval); @@ -728,10 +719,8 @@ export class Wrapper { this: Wrapper, handler: number | undefined ) { - const callstack = this.createCallstack( - new Error(TRACE_ERROR_MESSAGE), - false - ); + const err = new Error(TRACE_ERROR_MESSAGE); + const callstack = this.createCallstack(err); this.updateClearTimersHistory( this.clearTimeoutHistory, handler, @@ -766,10 +755,8 @@ export class Wrapper { delay, ...args ); - const callstack = this.createCallstack( - new Error(TRACE_ERROR_MESSAGE), - code - ); + const err = new Error(TRACE_ERROR_MESSAGE); + const callstack = this.createCallstack(err, code); this.callCounter.setInterval++; this.timerOnline(ETimerType.INTERVAL, handler, delay, callstack, isEval); @@ -799,10 +786,8 @@ export class Wrapper { this: Wrapper, handler: number | undefined ) { - const callstack = this.createCallstack( - new Error(TRACE_ERROR_MESSAGE), - false - ); + const err = new Error(TRACE_ERROR_MESSAGE); + const callstack = this.createCallstack(err); this.updateClearTimersHistory( this.clearIntervalHistory, handler, @@ -817,10 +802,10 @@ export class Wrapper { }.bind(this); } - createCallstack(e: Error, uniqueTrait: unknown): TCallstack { + createCallstack(e: Error, uniqueTrait?: unknown): TCallstack { const trace: TTrace[] = []; const stack = e.stack?.split(REGEX_STACKTRACE_SPLIT) || []; - let traceId = ''; + const traceId = e.stack || String(uniqueTrait); // loop from the end, excluding error name and self trace for (let n = stack.length - 1; n > 1; n--) { @@ -832,19 +817,16 @@ export class Wrapper { const link = v.replace(REGEX_STACKTRACE_LINK, '$2').trim(); - if (link.startsWith('')) { + if (link.indexOf('') >= 0) { continue; } let name = v.replace(REGEX_STACKTRACE_NAME, '$1').trim(); trace.push({ name: name === link ? 0 : name, link }); - traceId += link; } - if (!traceId.length) { - traceId = String(uniqueTrait); - + if (!trace.length) { let name: TTrace['name'] = 0; if (typeof uniqueTrait === 'function' && uniqueTrait.name) { name = uniqueTrait.name; From edcf8d22ba8b371c9a28c1f06fb413c5898480f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=95=B7?= <3756473+zendive@users.noreply.github.com> Date: Thu, 8 Aug 2024 05:06:38 +0300 Subject: [PATCH 51/53] add `traceForDebug` for illusive callstacks --- README.md | 2 +- src/api-monitor-cs-main.ts | 1 + src/api/settings.ts | 1 + src/api/wrappers.ts | 81 +++++++++++++------ src/view/components/ActiveTimers.svelte | 8 +- src/view/components/AnimationHistory.svelte | 2 +- src/view/components/EvalMetrics.svelte | 2 +- .../IdleCallbackCancelHistory.svelte | 2 +- .../IdleCallbackRequestHistory.svelte | 2 +- .../TimersClearHistoryMetric.svelte | 2 +- src/view/components/TimersSetHistory.svelte | 2 +- src/view/components/Trace.svelte | 37 +++++++++ 12 files changed, 107 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index 369da04..b2c1028 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ - Available in Chrome Web Store as [API Monitor](https://chromewebstore.google.com/detail/api-monitor/bghmfoakiidiedpheejcjhciekobjcjp) -Whether you're developing a Single Page Application (SPA) and want to assess implementation correctness or are curious about how something works, this tool adds additional functionality to the Chrome browser DevTools to reveal active or passed timeouts, intervals, and `eval` usages while mapping their invocation call stacks to a source code location. If the page has mounted `video` or `audio` media element's, their events and property state changes can be observed as they happen ([documentation](https://developer.mozilla.org/docs/Web/API/HTMLMediaElement), [example](https://www.w3.org/2010/05/video/mediaevents.html)). +Whether you're developing a Single Page Application (SPA) and want to assess implementation correctness or are curious about how something works, this tool adds additional functionality to the Chrome browser DevTools to reveal timeouts, intervals, idle callbacks, animation frames and `eval` usages while mapping their invocation call stacks to a source code location. If the page has mounted `video` or `audio` media element's, their events and property state changes can be observed as they happen ([documentation](https://developer.mozilla.org/docs/Web/API/HTMLMediaElement), [example](https://www.w3.org/2010/05/video/mediaevents.html)). ### Motivation diff --git a/src/api-monitor-cs-main.ts b/src/api-monitor-cs-main.ts index 484b7b8..b4f42db 100644 --- a/src/api-monitor-cs-main.ts +++ b/src/api-monitor-cs-main.ts @@ -101,6 +101,7 @@ windowListen((o) => { panels.cancelAnimationFrame && wrapCancelAnimationFrameOnce(); panels.requestIdleCallback && wrapRequestIdleCallbackOnce(); panels.cancelIdleCallback && wrapCancelIdleCallbackOnce(); + wrapper.setTraceForDebug(o.settings.traceForDebug); } else if (o.msg === 'reset-wrapper-history') { wrapper.cleanHistory(); tick.trigger(); diff --git a/src/api/settings.ts b/src/api/settings.ts index 8de17d0..061ea3b 100644 --- a/src/api/settings.ts +++ b/src/api/settings.ts @@ -99,6 +99,7 @@ export const DEFAULT_SETTINGS = { sort: DEFAULT_SORT, paused: false, devtoolsPanelShown: false, + traceForDebug: null, }; export function panelsArrayToVisibilityMap(panels: TSettingsPanel[]) { diff --git a/src/api/wrappers.ts b/src/api/wrappers.ts index ccaa0c9..6b33733 100644 --- a/src/api/wrappers.ts +++ b/src/api/wrappers.ts @@ -171,6 +171,7 @@ export class Wrapper { cancelIdleCallback: cancelIdleCallback, }; selfTraceLink = ''; + #traceForDebug: string | null = null; constructor() { this.#initSelfTrace(); @@ -204,6 +205,10 @@ export class Wrapper { return ETraceDomain.UNKNOWN; } + setTraceForDebug(traceId: string | null) { + this.#traceForDebug = traceId; + } + timerOnline( type: ETimerTypeKeys, handler: number, @@ -497,6 +502,7 @@ export class Wrapper { this.cafHistory.clear(); this.ricHistory.clear(); this.cicHistory.clear(); + this.onlineIdleCallbackLookup.clear(); this.callCounter.setTimeout = this.callCounter.clearTimeout = this.callCounter.setInterval = @@ -548,7 +554,7 @@ export class Wrapper { } unwrapApis() { - window.eval = this.native.eval; + window.eval = this.native.eval; // won't do revert effect, here for consistency window.setTimeout = this.native.setTimeout; window.clearTimeout = this.native.clearTimeout; window.setInterval = this.native.setInterval; @@ -577,16 +583,17 @@ export class Wrapper { fn: IdleRequestCallback, options?: IdleRequestOptions | undefined ) { - this.callCounter.requestIdleCallback++; - const delay = options?.timeout; const err = new Error(TRACE_ERROR_MESSAGE); const callstack = this.createCallstack(err, fn); + if (this.#traceForDebug === callstack.traceId) { + debugger; + } + this.callCounter.requestIdleCallback++; const handler = this.native.requestIdleCallback((deadline) => { this.ricOffline(deadline, callstack); fn(deadline); }, options); - this.updateRicHistory(handler, delay, callstack); return handler; @@ -599,7 +606,11 @@ export class Wrapper { handler: number ) { const err = new Error(TRACE_ERROR_MESSAGE); - this.updateCicHistory(handler, this.createCallstack(err)); + const callstack = this.createCallstack(err); + if (this.#traceForDebug === callstack.traceId) { + debugger; + } + this.updateCicHistory(handler, callstack); this.callCounter.cancelIdleCallback++; this.native.cancelIdleCallback(handler); }.bind(this); @@ -610,10 +621,14 @@ export class Wrapper { this: Wrapper, fn: FrameRequestCallback ) { + const err = new Error(TRACE_ERROR_MESSAGE); + const callstack = this.createCallstack(err, fn); + if (this.#traceForDebug === callstack.traceId) { + debugger; + } this.callCounter.requestAnimationFrame++; const handler = this.native.requestAnimationFrame(fn); - const err = new Error(TRACE_ERROR_MESSAGE); - this.updateRafHistory(handler, this.createCallstack(err, fn)); + this.updateRafHistory(handler, callstack); return handler; }.bind(this); @@ -625,7 +640,11 @@ export class Wrapper { handler: number ) { const err = new Error(TRACE_ERROR_MESSAGE); - this.updateCafHistory(handler, this.createCallstack(err)); + const callstack = this.createCallstack(err); + if (this.#traceForDebug === callstack.traceId) { + debugger; + } + this.updateCafHistory(handler, callstack); this.callCounter.cancelAnimationFrame++; this.native.cancelAnimationFrame(handler); }.bind(this); @@ -633,12 +652,17 @@ export class Wrapper { wrapEval() { window.eval = function WrappedLessEval(this: Wrapper, code: string) { - this.callCounter.eval++; let rv: unknown; let throwError = null; let usesLocalScope = false; + const err = new Error(TRACE_ERROR_MESSAGE); + const callstack = this.createCallstack(err, code); + if (this.#traceForDebug === callstack.traceId) { + debugger; + } try { + this.callCounter.eval++; rv = this.native.eval(code); } catch (error: unknown) { if (error instanceof Error && 'ReferenceError' === error.name) { @@ -651,13 +675,7 @@ export class Wrapper { } } - const err = new Error(TRACE_ERROR_MESSAGE); - this.updateEvalHistory( - code, - rv, - this.createCallstack(err, code), - usesLocalScope - ); + this.updateEvalHistory(code, rv, callstack, usesLocalScope); if (throwError) { throw throwError; @@ -674,11 +692,19 @@ export class Wrapper { delay: number | undefined, ...args: any[] ) { + const err = new Error(TRACE_ERROR_MESSAGE); + const callstack = this.createCallstack(err, code); + if (this.#traceForDebug === callstack.traceId) { + debugger; + } + const isEval = typeof code === 'string'; + this.callCounter.setTimeout++; const handler = this.native.setTimeout( (...params: any[]) => { this.timerOffline(handler, null); if (isEval) { + this.callCounter.eval++; // see https://developer.mozilla.org/docs/Web/API/setTimeout#code this.native.eval(code); } else { @@ -688,10 +714,7 @@ export class Wrapper { delay, ...args ); - const err = new Error(TRACE_ERROR_MESSAGE); - const callstack = this.createCallstack(err, code); - this.callCounter.setTimeout++; this.timerOnline(ETimerType.TIMEOUT, handler, delay, callstack, isEval); this.updateSetTimersHistory( this.setTimeoutHistory, @@ -701,7 +724,6 @@ export class Wrapper { isEval ); if (isEval) { - this.callCounter.eval++; this.updateEvalHistory( code, TAG_EVAL_RETURN_SET_TIMEOUT, @@ -721,6 +743,9 @@ export class Wrapper { ) { const err = new Error(TRACE_ERROR_MESSAGE); const callstack = this.createCallstack(err); + if (this.#traceForDebug === callstack.traceId) { + debugger; + } this.updateClearTimersHistory( this.clearTimeoutHistory, handler, @@ -742,10 +767,18 @@ export class Wrapper { delay: number | undefined, ...args: any[] ) { + const err = new Error(TRACE_ERROR_MESSAGE); + const callstack = this.createCallstack(err, code); + if (this.#traceForDebug === callstack.traceId) { + debugger; + } + const isEval = typeof code === 'string'; + this.callCounter.setInterval++; const handler = this.native.setInterval( (...params: any[]) => { if (isEval) { + this.callCounter.eval++; // see https://developer.mozilla.org/docs/Web/API/setInterval this.native.eval(code); } else { @@ -755,10 +788,7 @@ export class Wrapper { delay, ...args ); - const err = new Error(TRACE_ERROR_MESSAGE); - const callstack = this.createCallstack(err, code); - this.callCounter.setInterval++; this.timerOnline(ETimerType.INTERVAL, handler, delay, callstack, isEval); this.updateSetTimersHistory( this.setIntervalHistory, @@ -768,7 +798,6 @@ export class Wrapper { isEval ); if (isEval) { - this.callCounter.eval++; this.updateEvalHistory( code, TAG_EVAL_RETURN_SET_INTERVAL, @@ -788,6 +817,10 @@ export class Wrapper { ) { const err = new Error(TRACE_ERROR_MESSAGE); const callstack = this.createCallstack(err); + if (this.#traceForDebug === callstack.traceId) { + debugger; + } + this.updateClearTimersHistory( this.clearIntervalHistory, handler, diff --git a/src/view/components/ActiveTimers.svelte b/src/view/components/ActiveTimers.svelte index f91d3a9..2183f3c 100644 --- a/src/view/components/ActiveTimers.svelte +++ b/src/view/components/ActiveTimers.svelte @@ -35,7 +35,7 @@ {metric.handler}
- +
- + {metric.calls} {metric.handler}
- + {#if metric.usesLocalScope} diff --git a/src/view/components/IdleCallbackCancelHistory.svelte b/src/view/components/IdleCallbackCancelHistory.svelte index 3414499..c0224c2 100644 --- a/src/view/components/IdleCallbackCancelHistory.svelte +++ b/src/view/components/IdleCallbackCancelHistory.svelte @@ -73,7 +73,7 @@
- + {metric.calls} {metric.handler}
- + {metric.calls} {metric.handler}
- + diff --git a/src/view/components/TimersSetHistory.svelte b/src/view/components/TimersSetHistory.svelte index df3859b..5c83e37 100644 --- a/src/view/components/TimersSetHistory.svelte +++ b/src/view/components/TimersSetHistory.svelte @@ -122,7 +122,7 @@
- + diff --git a/src/view/components/Trace.svelte b/src/view/components/Trace.svelte index 5e7242c..988f5a1 100644 --- a/src/view/components/Trace.svelte +++ b/src/view/components/Trace.svelte @@ -1,11 +1,48 @@ {#each trace as stack, index (index)} {#if index !== 0} •{/if} {/each} + +{#if hardToGet} + +{/if} + + From c18385b037157a5318e44d3c622f12caa9a16238 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=95=B7?= <3756473+zendive@users.noreply.github.com> Date: Thu, 8 Aug 2024 05:35:18 +0300 Subject: [PATCH 52/53] update deps --- package.json | 6 +- pnpm-lock.yaml | 220 ++++++++++++++++++++++++------------------------- 2 files changed, 113 insertions(+), 113 deletions(-) diff --git a/package.json b/package.json index 248d935..360a690 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "@jest/globals": "^29.7.0", "@types/chrome": "^0.0.269", "@types/jest": "^29.5.12", - "@types/node": "^22.0.0", + "@types/node": "^22.1.0", "css-loader": "^7.1.2", "esbuild": "0.23.0", "esbuild-loader": "4.2.2", @@ -17,9 +17,9 @@ "svelte-check": "^3.8.5", "svelte-loader": "^3.2.3", "svelte-preprocess": "^6.0.2", - "ts-jest": "^29.2.3", + "ts-jest": "^29.2.4", "ts-node": "^10.9.2", - "tsx": "^4.16.3", + "tsx": "^4.16.5", "typescript": "^5.5.4", "webpack": "5.93.0", "webpack-cli": "5.1.4" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4a2f991..830c1dd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -22,8 +22,8 @@ importers: specifier: ^29.5.12 version: 29.5.12 '@types/node': - specifier: ^22.0.0 - version: 22.0.0 + specifier: ^22.1.0 + version: 22.1.0 css-loader: specifier: ^7.1.2 version: 7.1.2(webpack@5.93.0(esbuild@0.23.0)(webpack-cli@5.1.4)) @@ -35,7 +35,7 @@ importers: version: 4.2.2(webpack@5.93.0(esbuild@0.23.0)(webpack-cli@5.1.4)) jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@22.0.0)(ts-node@10.9.2(@types/node@22.0.0)(typescript@5.5.4)) + version: 29.7.0(@types/node@22.1.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.5.4)) jest-environment-jsdom: specifier: ^29.7.0 version: 29.7.0 @@ -53,22 +53,22 @@ importers: version: 4.2.18 svelte-check: specifier: ^3.8.5 - version: 3.8.5(@babel/core@7.25.2)(postcss@8.4.40)(sass@1.77.8)(svelte@4.2.18) + version: 3.8.5(@babel/core@7.25.2)(postcss@8.4.41)(sass@1.77.8)(svelte@4.2.18) svelte-loader: specifier: ^3.2.3 version: 3.2.3(svelte@4.2.18) svelte-preprocess: specifier: ^6.0.2 - version: 6.0.2(@babel/core@7.25.2)(postcss@8.4.40)(sass@1.77.8)(svelte@4.2.18)(typescript@5.5.4) + version: 6.0.2(@babel/core@7.25.2)(postcss@8.4.41)(sass@1.77.8)(svelte@4.2.18)(typescript@5.5.4) ts-jest: - specifier: ^29.2.3 - version: 29.2.3(@babel/core@7.25.2)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.2))(esbuild@0.23.0)(jest@29.7.0(@types/node@22.0.0)(ts-node@10.9.2(@types/node@22.0.0)(typescript@5.5.4)))(typescript@5.5.4) + specifier: ^29.2.4 + version: 29.2.4(@babel/core@7.25.2)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.2))(esbuild@0.23.0)(jest@29.7.0(@types/node@22.1.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.5.4)))(typescript@5.5.4) ts-node: specifier: ^10.9.2 - version: 10.9.2(@types/node@22.0.0)(typescript@5.5.4) + version: 10.9.2(@types/node@22.1.0)(typescript@5.5.4) tsx: - specifier: ^4.16.3 - version: 4.16.3 + specifier: ^4.16.5 + version: 4.16.5 typescript: specifier: ^5.5.4 version: 5.5.4 @@ -707,8 +707,8 @@ packages: '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - '@types/node@22.0.0': - resolution: {integrity: sha512-VT7KSYudcPOzP5Q0wfbowyNLaVR8QWUdw+088uFWwfvpY6uCWaXpqV6ieLAu9WBcnTa7H4Z5RLK8I5t2FuOcqw==} + '@types/node@22.1.0': + resolution: {integrity: sha512-AOmuRF0R2/5j1knA3c6G3HOk523Ga+l+ZXltX8SF1+5oqcXijjfTd8fY3XRZqSihEu9XhtQnKYLmkFaoxgsJHw==} '@types/pug@2.0.10': resolution: {integrity: sha512-Sk/uYFOBAB7mb74XcpizmH0KOR2Pv3D2Hmrh1Dmy5BmK3MpdSa5kqZcg6EKBdklU0bFXX9gCfzvpnyUehrPIuA==} @@ -722,8 +722,8 @@ packages: '@types/yargs-parser@21.0.3': resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} - '@types/yargs@17.0.32': - resolution: {integrity: sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==} + '@types/yargs@17.0.33': + resolution: {integrity: sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==} '@webassemblyjs/ast@1.12.1': resolution: {integrity: sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==} @@ -938,8 +938,8 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} - browserslist@4.23.2: - resolution: {integrity: sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA==} + browserslist@4.23.3: + resolution: {integrity: sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true @@ -969,8 +969,8 @@ packages: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} - caniuse-lite@1.0.30001645: - resolution: {integrity: sha512-GFtY2+qt91kzyMk6j48dJcwJVq5uTkk71XxE3RtScx7XWRLsO7bU44LOFkOZYR8w9YMS0UhPSYpN/6rAMImmLw==} + caniuse-lite@1.0.30001650: + resolution: {integrity: sha512-fgEc7hP/LB7iicdXHUI9VsBsMZmUmlVJeQP2qqQW+3lkqVhbmjEU8zp+h5stWeilX+G7uXuIUIIlWlDw9jdt8g==} chalk@2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} @@ -1155,8 +1155,8 @@ packages: engines: {node: '>=0.10.0'} hasBin: true - electron-to-chromium@1.5.4: - resolution: {integrity: sha512-orzA81VqLyIGUEA77YkVA1D+N+nNfl2isJVjjmOyrlxuooZ19ynb+dOlaDTqd/idKRS9lDCSBmtzM+kyCsMnkA==} + electron-to-chromium@1.5.5: + resolution: {integrity: sha512-QR7/A7ZkMS8tZuoftC/jfqNkZLQO779SSW3YuZHP4eXpj3EffGLFcB/Xu9AAZQzLccTiCV+EmUo3ha4mQ9wnlA==} emittery@0.13.1: resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} @@ -1896,8 +1896,8 @@ packages: postcss-value-parser@4.2.0: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - postcss@8.4.40: - resolution: {integrity: sha512-YF2kKIUzAofPMpfH6hOi2cGnv/HrUlfucspc7pDyvv7kGdqXrfj8SCl/t8owkEgKEuu8ZcRjSOxFxVLqwChZ2Q==} + postcss@8.4.41: + resolution: {integrity: sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==} engines: {node: ^10 || ^12 || >=14} prettier@3.3.3: @@ -2232,8 +2232,8 @@ packages: uglify-js: optional: true - terser@5.31.3: - resolution: {integrity: sha512-pAfYn3NIZLyZpa83ZKigvj6Rn9c/vd5KfYGX7cN1mnzqgDcxWvrU5ZtAfIKhEXz9nRecw4z3LXkjaq96/qZqAA==} + terser@5.31.4: + resolution: {integrity: sha512-3OU03GgblDgu0g+sdnsVzhBPxnjV+WJuMmocN1qBBZDQ3ia7jZQSAkePeKbPlYAejGXUTYe1CmSaUeV51mvaIw==} engines: {node: '>=10'} hasBin: true @@ -2260,8 +2260,8 @@ packages: resolution: {integrity: sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==} engines: {node: '>=12'} - ts-jest@29.2.3: - resolution: {integrity: sha512-yCcfVdiBFngVz9/keHin9EnsrQtQtEu3nRykNy9RVp+FiPFFbPJ3Sg6Qg4+TkmH0vMP5qsTKgXSsk80HRwvdgQ==} + ts-jest@29.2.4: + resolution: {integrity: sha512-3d6tgDyhCI29HlpwIq87sNuI+3Q6GLTTCeYRHCs7vDz+/3GCMwEtV9jezLyl4ZtnBgx00I7hm8PCP8cTksMGrw==} engines: {node: ^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: @@ -2298,8 +2298,8 @@ packages: '@swc/wasm': optional: true - tsx@4.16.3: - resolution: {integrity: sha512-MP8AEUxVnboD2rCC6kDLxnpDBNWN9k3BSVU/0/nNxgm70bPBnfn+yCKcnOsIVPQwdkbKYoFOlKjjWZWJ2XCXUg==} + tsx@4.16.5: + resolution: {integrity: sha512-ArsiAQHEW2iGaqZ8fTA1nX0a+lN5mNTyuGRRO6OW3H/Yno1y9/t1f9YOI1Cfoqz63VAthn++ZYcbDP7jPflc+A==} engines: {node: '>=18.0.0'} hasBin: true @@ -2316,8 +2316,8 @@ packages: engines: {node: '>=14.17'} hasBin: true - undici-types@6.11.1: - resolution: {integrity: sha512-mIDEX2ek50x0OlRgxryxsenE5XaQD4on5U2inY7RApK3SOJpofyw7uW2AyfMKkhAxXIceo2DeWGVGwyvng1GNQ==} + undici-types@6.13.0: + resolution: {integrity: sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg==} universalify@0.2.0: resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} @@ -2516,7 +2516,7 @@ snapshots: dependencies: '@babel/compat-data': 7.25.2 '@babel/helper-validator-option': 7.24.8 - browserslist: 4.23.2 + browserslist: 4.23.3 lru-cache: 5.1.1 semver: 6.3.1 @@ -2824,27 +2824,27 @@ snapshots: '@jest/console@29.7.0': dependencies: '@jest/types': 29.6.3 - '@types/node': 22.0.0 + '@types/node': 22.1.0 chalk: 4.1.2 jest-message-util: 29.7.0 jest-util: 29.7.0 slash: 3.0.0 - '@jest/core@29.7.0(ts-node@10.9.2(@types/node@22.0.0)(typescript@5.5.4))': + '@jest/core@29.7.0(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.5.4))': dependencies: '@jest/console': 29.7.0 '@jest/reporters': 29.7.0 '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.0.0 + '@types/node': 22.1.0 ansi-escapes: 4.3.2 chalk: 4.1.2 ci-info: 3.9.0 exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@22.0.0)(ts-node@10.9.2(@types/node@22.0.0)(typescript@5.5.4)) + jest-config: 29.7.0(@types/node@22.1.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.5.4)) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -2869,7 +2869,7 @@ snapshots: dependencies: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.0.0 + '@types/node': 22.1.0 jest-mock: 29.7.0 '@jest/expect-utils@29.7.0': @@ -2887,7 +2887,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@sinonjs/fake-timers': 10.3.0 - '@types/node': 22.0.0 + '@types/node': 22.1.0 jest-message-util: 29.7.0 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -2909,7 +2909,7 @@ snapshots: '@jest/transform': 29.7.0 '@jest/types': 29.6.3 '@jridgewell/trace-mapping': 0.3.25 - '@types/node': 22.0.0 + '@types/node': 22.1.0 chalk: 4.1.2 collect-v8-coverage: 1.0.2 exit: 0.1.2 @@ -2979,8 +2979,8 @@ snapshots: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 22.0.0 - '@types/yargs': 17.0.32 + '@types/node': 22.1.0 + '@types/yargs': 17.0.33 chalk: 4.1.2 '@jridgewell/gen-mapping@0.3.5': @@ -3078,7 +3078,7 @@ snapshots: '@types/graceful-fs@4.1.9': dependencies: - '@types/node': 22.0.0 + '@types/node': 22.1.0 '@types/har-format@1.2.15': {} @@ -3099,15 +3099,15 @@ snapshots: '@types/jsdom@20.0.1': dependencies: - '@types/node': 22.0.0 + '@types/node': 22.1.0 '@types/tough-cookie': 4.0.5 parse5: 7.1.2 '@types/json-schema@7.0.15': {} - '@types/node@22.0.0': + '@types/node@22.1.0': dependencies: - undici-types: 6.11.1 + undici-types: 6.13.0 '@types/pug@2.0.10': {} @@ -3117,7 +3117,7 @@ snapshots: '@types/yargs-parser@21.0.3': {} - '@types/yargs@17.0.32': + '@types/yargs@17.0.33': dependencies: '@types/yargs-parser': 21.0.3 @@ -3374,12 +3374,12 @@ snapshots: dependencies: fill-range: 7.1.1 - browserslist@4.23.2: + browserslist@4.23.3: dependencies: - caniuse-lite: 1.0.30001645 - electron-to-chromium: 1.5.4 + caniuse-lite: 1.0.30001650 + electron-to-chromium: 1.5.5 node-releases: 2.0.18 - update-browserslist-db: 1.1.0(browserslist@4.23.2) + update-browserslist-db: 1.1.0(browserslist@4.23.3) bs-logger@0.2.6: dependencies: @@ -3399,7 +3399,7 @@ snapshots: camelcase@6.3.0: {} - caniuse-lite@1.0.30001645: {} + caniuse-lite@1.0.30001650: {} chalk@2.4.2: dependencies: @@ -3482,13 +3482,13 @@ snapshots: convert-source-map@2.0.0: {} - create-jest@29.7.0(@types/node@22.0.0)(ts-node@10.9.2(@types/node@22.0.0)(typescript@5.5.4)): + create-jest@29.7.0(@types/node@22.1.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.5.4)): dependencies: '@jest/types': 29.6.3 chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@22.0.0)(ts-node@10.9.2(@types/node@22.0.0)(typescript@5.5.4)) + jest-config: 29.7.0(@types/node@22.1.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.5.4)) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -3507,12 +3507,12 @@ snapshots: css-loader@7.1.2(webpack@5.93.0(esbuild@0.23.0)(webpack-cli@5.1.4)): dependencies: - icss-utils: 5.1.0(postcss@8.4.40) - postcss: 8.4.40 - postcss-modules-extract-imports: 3.1.0(postcss@8.4.40) - postcss-modules-local-by-default: 4.0.5(postcss@8.4.40) - postcss-modules-scope: 3.2.0(postcss@8.4.40) - postcss-modules-values: 4.0.0(postcss@8.4.40) + icss-utils: 5.1.0(postcss@8.4.41) + postcss: 8.4.41 + postcss-modules-extract-imports: 3.1.0(postcss@8.4.41) + postcss-modules-local-by-default: 4.0.5(postcss@8.4.41) + postcss-modules-scope: 3.2.0(postcss@8.4.41) + postcss-modules-values: 4.0.0(postcss@8.4.41) postcss-value-parser: 4.2.0 semver: 7.6.3 optionalDependencies: @@ -3569,7 +3569,7 @@ snapshots: dependencies: jake: 10.9.2 - electron-to-chromium@1.5.4: {} + electron-to-chromium@1.5.5: {} emittery@0.13.1: {} @@ -3820,9 +3820,9 @@ snapshots: dependencies: safer-buffer: 2.1.2 - icss-utils@5.1.0(postcss@8.4.40): + icss-utils@5.1.0(postcss@8.4.41): dependencies: - postcss: 8.4.40 + postcss: 8.4.41 immutable@4.3.7: {} @@ -3940,7 +3940,7 @@ snapshots: '@jest/expect': 29.7.0 '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.0.0 + '@types/node': 22.1.0 chalk: 4.1.2 co: 4.6.0 dedent: 1.5.3 @@ -3960,16 +3960,16 @@ snapshots: - babel-plugin-macros - supports-color - jest-cli@29.7.0(@types/node@22.0.0)(ts-node@10.9.2(@types/node@22.0.0)(typescript@5.5.4)): + jest-cli@29.7.0(@types/node@22.1.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.5.4)): dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@22.0.0)(typescript@5.5.4)) + '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.5.4)) '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@22.0.0)(ts-node@10.9.2(@types/node@22.0.0)(typescript@5.5.4)) + create-jest: 29.7.0(@types/node@22.1.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.5.4)) exit: 0.1.2 import-local: 3.2.0 - jest-config: 29.7.0(@types/node@22.0.0)(ts-node@10.9.2(@types/node@22.0.0)(typescript@5.5.4)) + jest-config: 29.7.0(@types/node@22.1.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.5.4)) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -3979,7 +3979,7 @@ snapshots: - supports-color - ts-node - jest-config@29.7.0(@types/node@22.0.0)(ts-node@10.9.2(@types/node@22.0.0)(typescript@5.5.4)): + jest-config@29.7.0(@types/node@22.1.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.5.4)): dependencies: '@babel/core': 7.25.2 '@jest/test-sequencer': 29.7.0 @@ -4004,8 +4004,8 @@ snapshots: slash: 3.0.0 strip-json-comments: 3.1.1 optionalDependencies: - '@types/node': 22.0.0 - ts-node: 10.9.2(@types/node@22.0.0)(typescript@5.5.4) + '@types/node': 22.1.0 + ts-node: 10.9.2(@types/node@22.1.0)(typescript@5.5.4) transitivePeerDependencies: - babel-plugin-macros - supports-color @@ -4035,7 +4035,7 @@ snapshots: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 '@types/jsdom': 20.0.1 - '@types/node': 22.0.0 + '@types/node': 22.1.0 jest-mock: 29.7.0 jest-util: 29.7.0 jsdom: 20.0.3 @@ -4049,7 +4049,7 @@ snapshots: '@jest/environment': 29.7.0 '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.0.0 + '@types/node': 22.1.0 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -4059,7 +4059,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@types/graceful-fs': 4.1.9 - '@types/node': 22.0.0 + '@types/node': 22.1.0 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -4098,7 +4098,7 @@ snapshots: jest-mock@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 22.0.0 + '@types/node': 22.1.0 jest-util: 29.7.0 jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): @@ -4133,7 +4133,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.0.0 + '@types/node': 22.1.0 chalk: 4.1.2 emittery: 0.13.1 graceful-fs: 4.2.11 @@ -4161,7 +4161,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.0.0 + '@types/node': 22.1.0 chalk: 4.1.2 cjs-module-lexer: 1.3.1 collect-v8-coverage: 1.0.2 @@ -4207,7 +4207,7 @@ snapshots: jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 22.0.0 + '@types/node': 22.1.0 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -4226,7 +4226,7 @@ snapshots: dependencies: '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.0.0 + '@types/node': 22.1.0 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.13.1 @@ -4235,23 +4235,23 @@ snapshots: jest-worker@27.5.1: dependencies: - '@types/node': 22.0.0 + '@types/node': 22.1.0 merge-stream: 2.0.0 supports-color: 8.1.1 jest-worker@29.7.0: dependencies: - '@types/node': 22.0.0 + '@types/node': 22.1.0 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 - jest@29.7.0(@types/node@22.0.0)(ts-node@10.9.2(@types/node@22.0.0)(typescript@5.5.4)): + jest@29.7.0(@types/node@22.1.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.5.4)): dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@22.0.0)(typescript@5.5.4)) + '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.5.4)) '@jest/types': 29.6.3 import-local: 3.2.0 - jest-cli: 29.7.0(@types/node@22.0.0)(ts-node@10.9.2(@types/node@22.0.0)(typescript@5.5.4)) + jest-cli: 29.7.0(@types/node@22.1.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.5.4)) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -4468,26 +4468,26 @@ snapshots: dependencies: find-up: 4.1.0 - postcss-modules-extract-imports@3.1.0(postcss@8.4.40): + postcss-modules-extract-imports@3.1.0(postcss@8.4.41): dependencies: - postcss: 8.4.40 + postcss: 8.4.41 - postcss-modules-local-by-default@4.0.5(postcss@8.4.40): + postcss-modules-local-by-default@4.0.5(postcss@8.4.41): dependencies: - icss-utils: 5.1.0(postcss@8.4.40) - postcss: 8.4.40 + icss-utils: 5.1.0(postcss@8.4.41) + postcss: 8.4.41 postcss-selector-parser: 6.1.1 postcss-value-parser: 4.2.0 - postcss-modules-scope@3.2.0(postcss@8.4.40): + postcss-modules-scope@3.2.0(postcss@8.4.41): dependencies: - postcss: 8.4.40 + postcss: 8.4.41 postcss-selector-parser: 6.1.1 - postcss-modules-values@4.0.0(postcss@8.4.40): + postcss-modules-values@4.0.0(postcss@8.4.41): dependencies: - icss-utils: 5.1.0(postcss@8.4.40) - postcss: 8.4.40 + icss-utils: 5.1.0(postcss@8.4.41) + postcss: 8.4.41 postcss-selector-parser@6.1.1: dependencies: @@ -4496,7 +4496,7 @@ snapshots: postcss-value-parser@4.2.0: {} - postcss@8.4.40: + postcss@8.4.41: dependencies: nanoid: 3.3.7 picocolors: 1.0.1 @@ -4693,14 +4693,14 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - svelte-check@3.8.5(@babel/core@7.25.2)(postcss@8.4.40)(sass@1.77.8)(svelte@4.2.18): + svelte-check@3.8.5(@babel/core@7.25.2)(postcss@8.4.41)(sass@1.77.8)(svelte@4.2.18): dependencies: '@jridgewell/trace-mapping': 0.3.25 chokidar: 3.6.0 picocolors: 1.0.1 sade: 1.8.1 svelte: 4.2.18 - svelte-preprocess: 5.1.4(@babel/core@7.25.2)(postcss@8.4.40)(sass@1.77.8)(svelte@4.2.18)(typescript@5.5.4) + svelte-preprocess: 5.1.4(@babel/core@7.25.2)(postcss@8.4.41)(sass@1.77.8)(svelte@4.2.18)(typescript@5.5.4) typescript: 5.5.4 transitivePeerDependencies: - '@babel/core' @@ -4726,7 +4726,7 @@ snapshots: svelte-dev-helper: 1.1.9 svelte-hmr: 0.14.12(svelte@4.2.18) - svelte-preprocess@5.1.4(@babel/core@7.25.2)(postcss@8.4.40)(sass@1.77.8)(svelte@4.2.18)(typescript@5.5.4): + svelte-preprocess@5.1.4(@babel/core@7.25.2)(postcss@8.4.41)(sass@1.77.8)(svelte@4.2.18)(typescript@5.5.4): dependencies: '@types/pug': 2.0.10 detect-indent: 6.1.0 @@ -4736,16 +4736,16 @@ snapshots: svelte: 4.2.18 optionalDependencies: '@babel/core': 7.25.2 - postcss: 8.4.40 + postcss: 8.4.41 sass: 1.77.8 typescript: 5.5.4 - svelte-preprocess@6.0.2(@babel/core@7.25.2)(postcss@8.4.40)(sass@1.77.8)(svelte@4.2.18)(typescript@5.5.4): + svelte-preprocess@6.0.2(@babel/core@7.25.2)(postcss@8.4.41)(sass@1.77.8)(svelte@4.2.18)(typescript@5.5.4): dependencies: svelte: 4.2.18 optionalDependencies: '@babel/core': 7.25.2 - postcss: 8.4.40 + postcss: 8.4.41 sass: 1.77.8 typescript: 5.5.4 @@ -4776,12 +4776,12 @@ snapshots: jest-worker: 27.5.1 schema-utils: 3.3.0 serialize-javascript: 6.0.2 - terser: 5.31.3 + terser: 5.31.4 webpack: 5.93.0(esbuild@0.23.0)(webpack-cli@5.1.4) optionalDependencies: esbuild: 0.23.0 - terser@5.31.3: + terser@5.31.4: dependencies: '@jridgewell/source-map': 0.3.6 acorn: 8.12.1 @@ -4813,12 +4813,12 @@ snapshots: dependencies: punycode: 2.3.1 - ts-jest@29.2.3(@babel/core@7.25.2)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.2))(esbuild@0.23.0)(jest@29.7.0(@types/node@22.0.0)(ts-node@10.9.2(@types/node@22.0.0)(typescript@5.5.4)))(typescript@5.5.4): + ts-jest@29.2.4(@babel/core@7.25.2)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.2))(esbuild@0.23.0)(jest@29.7.0(@types/node@22.1.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.5.4)))(typescript@5.5.4): dependencies: bs-logger: 0.2.6 ejs: 3.1.10 fast-json-stable-stringify: 2.1.0 - jest: 29.7.0(@types/node@22.0.0)(ts-node@10.9.2(@types/node@22.0.0)(typescript@5.5.4)) + jest: 29.7.0(@types/node@22.1.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.5.4)) jest-util: 29.7.0 json5: 2.2.3 lodash.memoize: 4.1.2 @@ -4833,14 +4833,14 @@ snapshots: babel-jest: 29.7.0(@babel/core@7.25.2) esbuild: 0.23.0 - ts-node@10.9.2(@types/node@22.0.0)(typescript@5.5.4): + ts-node@10.9.2(@types/node@22.1.0)(typescript@5.5.4): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.11 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 - '@types/node': 22.0.0 + '@types/node': 22.1.0 acorn: 8.12.1 acorn-walk: 8.3.3 arg: 4.1.3 @@ -4851,7 +4851,7 @@ snapshots: v8-compile-cache-lib: 3.0.1 yn: 3.1.1 - tsx@4.16.3: + tsx@4.16.5: dependencies: esbuild: 0.21.5 get-tsconfig: 4.7.6 @@ -4864,13 +4864,13 @@ snapshots: typescript@5.5.4: {} - undici-types@6.11.1: {} + undici-types@6.13.0: {} universalify@0.2.0: {} - update-browserslist-db@1.1.0(browserslist@4.23.2): + update-browserslist-db@1.1.0(browserslist@4.23.3): dependencies: - browserslist: 4.23.2 + browserslist: 4.23.3 escalade: 3.1.2 picocolors: 1.0.1 @@ -4947,7 +4947,7 @@ snapshots: '@webassemblyjs/wasm-parser': 1.12.1 acorn: 8.12.1 acorn-import-attributes: 1.9.5(acorn@8.12.1) - browserslist: 4.23.2 + browserslist: 4.23.3 chrome-trace-event: 1.0.4 enhanced-resolve: 5.17.1 es-module-lexer: 1.5.4 From d19f26dea52e2d81fa7d030de1b516f40e42de4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=95=B7?= <3756473+zendive@users.noreply.github.com> Date: Thu, 8 Aug 2024 06:15:38 +0300 Subject: [PATCH 53/53] add Gimp promo to VCS --- doc/api-monitor-promo.xcf | Bin 0 -> 463058 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 doc/api-monitor-promo.xcf diff --git a/doc/api-monitor-promo.xcf b/doc/api-monitor-promo.xcf new file mode 100644 index 0000000000000000000000000000000000000000..0b558fb69c78d5c47a513bd5d05acc9bddcad38a GIT binary patch literal 463058 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
1(i}GTR1`UVPq4E6Y+@s(z>xv2j^`gYMdt{ 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 mI7KV!Yq(`PkRSh4UW%P%UT|=OC~I)W(AF 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லYsSAvl9!2`%2hlkZ!NTx1KamnQtrqD&M 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