diff --git a/packages/app/src/components/debugger/SourceViewer.vue b/packages/app/src/components/debugger/SourceViewer.vue index de67dcaf77..42bff9735f 100644 --- a/packages/app/src/components/debugger/SourceViewer.vue +++ b/packages/app/src/components/debugger/SourceViewer.vue @@ -15,7 +15,13 @@ :data-testid="item.expandable ? 'instruction-list-item-expandable' : 'instruction-list-item'" > - + {{ item.error }} @@ -69,6 +75,14 @@ const props = defineProps({ type: String, default: "", }, + traceCountPercentage: { + type: Object as PropType<{ [key: string]: number }>, + required: true, + }, + pcLineMapping: { + type: Object as PropType<{ [key: number]: number }>, + required: true, + }, }); type InstructionNode = { @@ -79,7 +93,10 @@ type InstructionNode = { expandable: boolean; }; -type VirtualInstructionNode = InstructionNode & { index: number }; +type VirtualInstructionNode = InstructionNode & { + index: number; + traceCountPercentage: number; +}; const expanded = ref([]); const isReady = ref(false); @@ -134,7 +151,17 @@ watchEffect(() => { } return val; }) - .map((item, index) => ({ ...item, index, line: item.line })); + .map((item, index) => ({ + ...item, + index, + line: item.line, + traceCountPercentage: + props.traceCountPercentage[ + `${props.address}_${Object.keys(props.pcLineMapping).find( + (key) => props.pcLineMapping[parseInt(key)] === index + )}` + ], + })); if (isReady.value) { rebuild(); } diff --git a/packages/app/src/composables/useTrace.ts b/packages/app/src/composables/useTrace.ts index 50ae382bb5..5880f131b0 100644 --- a/packages/app/src/composables/useTrace.ts +++ b/packages/app/src/composables/useTrace.ts @@ -200,6 +200,28 @@ export function useTraceNavigation(trace: ComputedRef, initial } }; + const traceCountPercentage = computed<{ [key: string]: number }>(() => { + if (!trace.value || !trace.value.steps || !trace.value.sources || index.value === null) { + return {}; + } + + let maxCount = 0; + const countDictionary = trace.value.steps.reduce((acc: { [key: string]: number }, step) => { + const key = `${step.contract_address}_${step.pc}`; + acc[key] = (acc[key] || 0) + 1; + maxCount = Math.max(maxCount, acc[key]); + return acc; + }, {}); + + const countPercentageDictionary: { [key: string]: number } = {}; + + for (const [key, value] of Object.entries(countDictionary)) { + countPercentageDictionary[key] = value / maxCount; + } + + return countPercentageDictionary; + }); + watch(trace, () => { index.value = null; }); @@ -208,6 +230,7 @@ export function useTraceNavigation(trace: ComputedRef, initial index, total: computed(() => trace.value?.steps.length), + traceCountPercentage, activeStep, activeLines, diff --git a/packages/app/src/views/DebuggerView.vue b/packages/app/src/views/DebuggerView.vue index 7a9b5d3f6f..9127b9164c 100644 --- a/packages/app/src/views/DebuggerView.vue +++ b/packages/app/src/views/DebuggerView.vue @@ -60,6 +60,8 @@ SourceNode :activeStep="activeStep" :searchText="searchText" :active-lines="activeLines[item.address]" + :traceCountPercentage="traceCountPercentage" + :pcLineMapping="item.pcLineMapping" @nav:navigateToLine="navigateToLine" /> ; expanded: boolean; + pcLineMapping: { + [key: number]: number; + }; }; const collection = ref(); const opened = ref(false); @@ -353,6 +359,7 @@ watchEffect(() => { source, errors, expanded: false, + pcLineMapping: item.pc_line_mapping, }; }); } else { diff --git a/packages/app/tests/components/debugger/SourceViewer.spec.ts b/packages/app/tests/components/debugger/SourceViewer.spec.ts index 257c627d3f..7ef1cef2bf 100644 --- a/packages/app/tests/components/debugger/SourceViewer.spec.ts +++ b/packages/app/tests/components/debugger/SourceViewer.spec.ts @@ -31,6 +31,8 @@ describe("SourceViewer:", () => { address: "0x00", source: ["Hello World"], container, + traceCountPercentage: {}, + pcLineMapping: {}, }, global: { plugins: [i18n], @@ -49,6 +51,8 @@ describe("SourceViewer:", () => { source: ["Hello World"], errors: ["Error text"], container, + traceCountPercentage: {}, + pcLineMapping: {}, }, global: { plugins: [i18n], @@ -68,6 +72,8 @@ describe("SourceViewer:", () => { address: "0x00", source: ["Hello", "", "World"], container, + traceCountPercentage: {}, + pcLineMapping: {}, }, global: { plugins: [i18n], @@ -85,6 +91,8 @@ describe("SourceViewer:", () => { address: "0x00", source: ["foo", ".func_begin", "Hello", "World", "!", ".func_end"], container, + traceCountPercentage: {}, + pcLineMapping: {}, }, global: { plugins: [i18n], @@ -107,6 +115,8 @@ describe("SourceViewer:", () => { address: "0x00", source: ["foo", ".func_begin", "Hello", "World", "!", ".func_end"], container, + traceCountPercentage: {}, + pcLineMapping: {}, }, global: { plugins: [i18n], @@ -133,6 +143,8 @@ describe("SourceViewer:", () => { address: "0x00", source: ["foo", ".func_begin", "Hello", "World", "!", ".func_end"], container, + traceCountPercentage: {}, + pcLineMapping: {}, }, global: { plugins: [i18n], @@ -159,6 +171,8 @@ describe("SourceViewer:", () => { address: "0x00", source, container, + traceCountPercentage: {}, + pcLineMapping: {}, }, global: { plugins: [i18n], @@ -184,6 +198,8 @@ describe("SourceViewer:", () => { address: "0x00", source, container, + traceCountPercentage: {}, + pcLineMapping: {}, }, global: { plugins: [i18n], @@ -218,6 +234,8 @@ describe("SourceViewer:", () => { line: 2, step: {}, }, + traceCountPercentage: {}, + pcLineMapping: {}, }, global: { plugins: [i18n], @@ -242,6 +260,8 @@ describe("SourceViewer:", () => { source, container: container as unknown as HTMLElement, activeStep: { address: "0x00", line: 2, step: {} } as ActiveStep, + traceCountPercentage: {}, + pcLineMapping: {}, }, global: { plugins: [i18n], @@ -268,6 +288,8 @@ describe("SourceViewer:", () => { }, container, searchText: "Wo", + traceCountPercentage: {}, + pcLineMapping: {}, }, global: { plugins: [i18n], @@ -294,6 +316,8 @@ describe("SourceViewer:", () => { }, container, searchText: "o", + traceCountPercentage: {}, + pcLineMapping: {}, }, global: { plugins: [i18n], @@ -315,6 +339,8 @@ describe("SourceViewer:", () => { container: container as unknown as HTMLElement, activeStep: { address: "0x00", line: 2, step: {} } as ActiveStep, activeLines: [1, 3], + traceCountPercentage: {}, + pcLineMapping: {}, }, global: { plugins: [i18n], @@ -342,6 +368,8 @@ describe("SourceViewer:", () => { container: container as unknown as HTMLElement, activeStep: { address: "0x00", line: 2, step: {} } as ActiveStep, activeLines: [1], + traceCountPercentage: {}, + pcLineMapping: {}, }, global: { plugins: [i18n], diff --git a/packages/app/tests/views/DebuggerView.spec.ts b/packages/app/tests/views/DebuggerView.spec.ts index 16e61882b7..de0815ebf6 100644 --- a/packages/app/tests/views/DebuggerView.spec.ts +++ b/packages/app/tests/views/DebuggerView.spec.ts @@ -441,6 +441,7 @@ describe("DebuggerView:", () => { }), index: ref(0), total: computed(() => 2), + traceCountPercentage: computed(() => ({})), }); const { unmount, container } = render(DebuggerView, { global: { @@ -486,6 +487,7 @@ describe("DebuggerView:", () => { }), index: ref(1), total: computed(() => 2), + traceCountPercentage: computed(() => ({})), }); const { unmount, container } = render(DebuggerView, { global: {