Skip to content

Commit 17253c9

Browse files
committed
Show source-mapped source in profiler-cli function annotate
`fetchSourceAnnotation` was always reading from funcTable.source[funcIndex], which points at the compiled bundle. For JS-symbolicated functions the original file already lives behind funcTable.sourceMapInfo, and its text is typically embedded on the shared source table either by sourcesContent during symbolication or by the publish-with-sources path. Resolve the effective source through getOriginalPositionForFrame so the filename, line hit attribution, and content lookup all target the original source when sourceMapInfo is present. When sources.content is populated, use it directly and skip the network fetch entirely so the source view works offline for published-with-sources profiles.
1 parent 4f834e3 commit 17253c9

1 file changed

Lines changed: 40 additions & 16 deletions

File tree

src/profile-query/function-annotate.ts

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
getNativeSymbolInfo,
2121
getNativeSymbolsForFunc,
2222
findAddressProofForFile,
23+
getOriginalPositionForFrame,
2324
} from 'firefox-profiler/profile-logic/profile-data';
2425
import { fetchAssembly } from 'firefox-profiler/utils/fetch-assembly';
2526
import { fetchSource } from 'firefox-profiler/utils/fetch-source';
@@ -76,8 +77,8 @@ async function fetchSourceAnnotation(
7677
contextOption: string
7778
): Promise<SourceAnnotationResult> {
7879
const warnings: string[] = [];
79-
const sourceIndex = profile.shared.funcTable.source[funcIndex];
80-
if (sourceIndex === null) {
80+
const compiledSourceIndex = profile.shared.funcTable.source[funcIndex];
81+
if (compiledSourceIndex === null) {
8182
if (mode === 'src') {
8283
warnings.push(
8384
`Function ${functionHandle} has no source index. Use --mode asm for assembly view.`
@@ -93,10 +94,25 @@ async function fetchSourceAnnotation(
9394
samples,
9495
sourceLocationTable,
9596
} = thread;
97+
98+
// For JS-symbolicated funcs, prefer the original source from
99+
// sourceLocationTable so the source view shows the original file (filename,
100+
// content, line/column hits) rather than the compiled bundle. Falls back to
101+
// the compiled source when no source map info is present.
102+
const { source: resolvedSourceIndex } = getOriginalPositionForFrame(
103+
null,
104+
funcIndex,
105+
frameTable,
106+
threadFuncTable,
107+
sourceLocationTable
108+
);
109+
const sourceIndex = resolvedSourceIndex ?? compiledSourceIndex;
110+
96111
const filename = thread.stringTable.getString(
97112
thread.sources.filename[sourceIndex]
98113
);
99114
const sourceUuid = thread.sources.id[sourceIndex];
115+
const inlineContent = thread.sources.content[sourceIndex];
100116

101117
const stackLineInfo = getStackLineInfo(
102118
stackTable,
@@ -132,22 +148,30 @@ async function fetchSourceAnnotation(
132148

133149
let fileLines: string[] | null = null;
134150
let totalFileLines: number | null = null;
135-
const fetchResult = await fetchSource(
136-
filename,
137-
sourceUuid,
138-
symbolServerUrl,
139-
addressProof,
140-
archiveCache,
141-
nodeDelegate
142-
);
143-
if (fetchResult.type === 'SUCCESS') {
144-
fileLines = fetchResult.source.split('\n');
151+
if (inlineContent !== null) {
152+
// Source content was embedded in the profile (e.g. captured from a source
153+
// map's sourcesContent during JS symbolication). Use it directly so the
154+
// source view works offline.
155+
fileLines = inlineContent.split('\n');
145156
totalFileLines = fileLines.length;
146157
} else {
147-
const errorMessages = fetchResult.errors
148-
.map((e) => JSON.stringify(e))
149-
.join('; ');
150-
warnings.push(`Could not fetch source for ${filename}: ${errorMessages}`);
158+
const fetchResult = await fetchSource(
159+
filename,
160+
sourceUuid,
161+
symbolServerUrl,
162+
addressProof,
163+
archiveCache,
164+
nodeDelegate
165+
);
166+
if (fetchResult.type === 'SUCCESS') {
167+
fileLines = fetchResult.source.split('\n');
168+
totalFileLines = fileLines.length;
169+
} else {
170+
const errorMessages = fetchResult.errors
171+
.map((e) => JSON.stringify(e))
172+
.join('; ');
173+
warnings.push(`Could not fetch source for ${filename}: ${errorMessages}`);
174+
}
151175
}
152176

153177
const annotatedLineNums = new Set([

0 commit comments

Comments
 (0)