Skip to content

Commit aa1fce0

Browse files
committed
Fetch the JS source from the browser
1 parent 17fce59 commit aa1fce0

File tree

8 files changed

+130
-4
lines changed

8 files changed

+130
-4
lines changed

locales/en-US/app.ftl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1243,6 +1243,14 @@ SourceView--not-in-archive-error-when-obtaining-source =
12431243
SourceView--archive-parsing-error-when-obtaining-source =
12441244
The archive at { $url } could not be parsed: { $parsingErrorMessage }
12451245
1246+
# Displayed below SourceView--cannot-obtain-source, if a JS file could not be found in
1247+
# the browser.
1248+
# Variables:
1249+
# $url (String) - The URL of the JS source file.
1250+
# $sourceUuid (number) - The UUID of the JS source file.
1251+
SourceView--not-in-browser-error-when-obtaining-js-source =
1252+
The JS file { $url } with sourceUuid { $sourceId } was not found in the browser.
1253+
12461254
## Toggle buttons in the top right corner of the bottom box
12471255

12481256
# The toggle button for the assembly view, while the assembly view is hidden.

src/components/app/CodeErrorOverlay.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,17 @@ export function CodeErrorOverlay({ errors }: CodeErrorOverlayProps) {
112112
</Localized>
113113
);
114114
}
115+
case 'NOT_PRESENT_IN_BROWSER': {
116+
const { sourceUuid, url } = error;
117+
return (
118+
<Localized
119+
id="SourceView--not-in-browser-error-when-obtaining-js-source"
120+
vars={{ url, sourceUuid }}
121+
>
122+
<li>{`The JS file ${url} with sourceUuid ${sourceUuid} was not found in the browser.`}</li>
123+
</Localized>
124+
);
125+
}
115126
default:
116127
throw assertExhaustiveCheck(error);
117128
}

src/test/unit/fetch-assembly.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ describe('fetchAssembly', function () {
7474
) => {
7575
throw new Error('No browser connection');
7676
},
77+
fetchJSSourceFromBrowser: async (_sourceUuid: string) => {
78+
throw new Error('No browser connection');
79+
},
7780
})
7881
).toEqual({
7982
type: 'SUCCESS',
@@ -145,6 +148,9 @@ describe('fetchAssembly', function () {
145148
) => {
146149
throw new Error('No browser connection');
147150
},
151+
fetchJSSourceFromBrowser: async (_sourceUuid: string) => {
152+
throw new Error('No browser connection');
153+
},
148154
}
149155
)
150156
).type
@@ -175,6 +181,9 @@ describe('fetchAssembly', function () {
175181
}
176182
return exampleResponse;
177183
},
184+
fetchJSSourceFromBrowser: async (_sourceUuid: string) => {
185+
throw new Error('No browser connection');
186+
},
178187
}
179188
)
180189
).type
@@ -193,6 +202,9 @@ describe('fetchAssembly', function () {
193202
) => {
194203
throw new Error('No browser connection');
195204
},
205+
fetchJSSourceFromBrowser: async (_sourceUuid: string) => {
206+
throw new Error('No browser connection');
207+
},
196208
})
197209
).toEqual({
198210
type: 'ERROR',
@@ -231,6 +243,9 @@ describe('fetchAssembly', function () {
231243
) => {
232244
return exampleResponse;
233245
},
246+
fetchJSSourceFromBrowser: async (_sourceUuid: string) => {
247+
throw new Error('No browser connection');
248+
},
234249
}
235250
)
236251
).type

src/test/unit/fetch-source.test.ts

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ describe('fetchSource', function () {
2626
) => {
2727
throw new Error('No browser connection');
2828
},
29+
fetchJSSourceFromBrowser: async (_sourceUuid: string) => {
30+
throw new Error('No browser connection');
31+
},
2932
}
3033
)
3134
).toEqual({
@@ -67,6 +70,9 @@ describe('fetchSource', function () {
6770
) => {
6871
throw new Error('No browser connection');
6972
};
73+
const fetchJSSourceFromBrowser = async (_sourceUuid: string) => {
74+
throw new Error('No browser connection');
75+
};
7076

7177
const archiveCache = new Map<string, Promise<Uint8Array>>();
7278

@@ -77,7 +83,11 @@ describe('fetchSource', function () {
7783
'https://symbolication.services.mozilla.com',
7884
null,
7985
archiveCache,
80-
{ fetchUrlResponse, queryBrowserSymbolicationApi }
86+
{
87+
fetchUrlResponse,
88+
queryBrowserSymbolicationApi,
89+
fetchJSSourceFromBrowser,
90+
}
8191
)
8292
).toEqual({
8393
type: 'SUCCESS',
@@ -96,7 +106,11 @@ describe('fetchSource', function () {
96106
'https://symbolication.services.mozilla.com',
97107
null,
98108
archiveCache,
99-
{ fetchUrlResponse, queryBrowserSymbolicationApi }
109+
{
110+
fetchUrlResponse,
111+
queryBrowserSymbolicationApi,
112+
fetchJSSourceFromBrowser,
113+
}
100114
)
101115
).toEqual({
102116
type: 'SUCCESS',
@@ -113,7 +127,11 @@ describe('fetchSource', function () {
113127
'https://symbolication.services.mozilla.com',
114128
null,
115129
archiveCache,
116-
{ fetchUrlResponse, queryBrowserSymbolicationApi }
130+
{
131+
fetchUrlResponse,
132+
queryBrowserSymbolicationApi,
133+
fetchJSSourceFromBrowser,
134+
}
117135
)
118136
).toEqual({
119137
type: 'ERROR',
@@ -148,6 +166,9 @@ describe('fetchSource', function () {
148166
// Shouldn't be called anyway because we're not providing an AddressProof.
149167
throw new Error('No browser connection');
150168
},
169+
fetchJSSourceFromBrowser: async (_sourceUuid: string) => {
170+
throw new Error('No browser connection');
171+
},
151172
}
152173
)
153174
).toEqual({
@@ -192,6 +213,9 @@ describe('fetchSource', function () {
192213
source: `Fake source from browser symbolication API, for request JSON ${requestJson}`,
193214
});
194215
},
216+
fetchJSSourceFromBrowser: async (_sourceUuid: string) => {
217+
throw new Error('No browser connection');
218+
},
195219
}
196220
)
197221
).toEqual({
@@ -243,6 +267,9 @@ describe('fetchSource', function () {
243267
) => {
244268
throw new Error('No browser connection');
245269
},
270+
fetchJSSourceFromBrowser: async (_sourceUuid: string) => {
271+
throw new Error('No browser connection');
272+
},
246273
}
247274
)
248275
).toEqual({
@@ -294,6 +321,9 @@ describe('fetchSource', function () {
294321
) => {
295322
throw new Error('No browser connection');
296323
},
324+
fetchJSSourceFromBrowser: async (_sourceUuid: string) => {
325+
throw new Error('No browser connection');
326+
},
297327
}
298328
)
299329
).toEqual({
@@ -343,6 +373,9 @@ describe('fetchSource', function () {
343373
) => {
344374
throw new Error('No browser connection');
345375
},
376+
fetchJSSourceFromBrowser: async (_sourceUuid: string) => {
377+
throw new Error('No browser connection');
378+
},
346379
}
347380
)
348381
).toEqual({
@@ -374,6 +407,9 @@ describe('fetchSource', function () {
374407
) => {
375408
throw new Error('No browser connection');
376409
},
410+
fetchJSSourceFromBrowser: async (_sourceUuid: string) => {
411+
throw new Error('No browser connection');
412+
},
377413
}
378414
)
379415
).toEqual({
@@ -415,6 +451,9 @@ describe('fetchSource', function () {
415451
) => {
416452
throw new Error('No browser connection');
417453
},
454+
fetchJSSourceFromBrowser: async (_sourceUuid: string) => {
455+
throw new Error('No browser connection');
456+
},
418457
}
419458
)
420459
).toEqual({
@@ -448,6 +487,9 @@ describe('fetchSource', function () {
448487
}
449488
return '[Invalid \\ JSON}';
450489
},
490+
fetchJSSourceFromBrowser: async (_sourceUuid: string) => {
491+
throw new Error('No browser connection');
492+
},
451493
}
452494
)
453495
).toEqual({
@@ -494,6 +536,9 @@ describe('fetchSource', function () {
494536
hahaYouThoughtThereWouldBeSourceHereButNo: 42,
495537
});
496538
},
539+
fetchJSSourceFromBrowser: async (_sourceUuid: string) => {
540+
throw new Error('No browser connection');
541+
},
497542
}
498543
)
499544
).toEqual({

src/test/unit/query-api.test.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ describe('queryApiWithFallback', function () {
2929
throw new Error('Not implemented');
3030
})
3131
),
32+
fetchJSSourceFromBrowser: jest.fn(
33+
overrides.fetchJSSourceFromBrowser ??
34+
(async () => {
35+
throw new Error('Not implemented');
36+
})
37+
),
3238
};
3339
}
3440

src/types/state.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,11 @@ export type SourceCodeLoadingError =
330330
type: 'ARCHIVE_PARSING_ERROR';
331331
url: string;
332332
parsingErrorMessage: string;
333+
}
334+
| {
335+
type: 'NOT_PRESENT_IN_BROWSER';
336+
sourceUuid: string;
337+
url: string;
333338
};
334339

335340
export type ProfileSpecificUrlState = {

src/utils/fetch-source.ts

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ export type FetchSourceResult =
3939
*/
4040
export async function fetchSource(
4141
file: string,
42-
_sourceUuid: string | null,
42+
sourceUuid: string | null,
4343
symbolServerUrl: string,
4444
addressProof: AddressProof | null,
4545
archiveCache: Map<string, Promise<Uint8Array>>,
@@ -88,6 +88,31 @@ export async function fetchSource(
8888
}
8989
}
9090

91+
// Try to obtain the source by downloading a file from the browser if it's a
92+
// JS source.
93+
if (sourceUuid !== null) {
94+
try {
95+
const response = await delegate.fetchJSSourceFromBrowser(sourceUuid);
96+
if (response) {
97+
return {
98+
type: 'SUCCESS',
99+
source: response,
100+
};
101+
}
102+
103+
errors.push({
104+
type: 'NOT_PRESENT_IN_BROWSER',
105+
sourceUuid,
106+
url: file,
107+
});
108+
} catch (e) {
109+
errors.push({
110+
type: 'BROWSER_API_ERROR',
111+
apiErrorMessage: e.message,
112+
});
113+
}
114+
}
115+
91116
// Try to obtain the source by downloading a file from the web.
92117

93118
const parsedName = parseFileNameFromSymbolication(file);

src/utils/query-api.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ export interface ExternalCommunicationDelegate {
2323
path: string,
2424
requestJson: string
2525
): Promise<string>;
26+
27+
fetchJSSourceFromBrowser(source: string): Promise<string | null>;
2628
}
2729

2830
export type ApiQueryResult<T> =
@@ -160,4 +162,13 @@ export class RegularExternalCommunicationDelegate
160162
this._callbacks.onBeginBrowserConnectionQuery();
161163
return browserConnection.querySymbolicationApi(path, requestJson);
162164
}
165+
166+
fetchJSSourceFromBrowser(source: string): Promise<string | null> {
167+
const browserConnection = this._browserConnection;
168+
if (browserConnection === null) {
169+
throw new Error('No connection to the browser.');
170+
}
171+
this._callbacks.onBeginBrowserConnectionQuery();
172+
return browserConnection.getJSSource(source);
173+
}
163174
}

0 commit comments

Comments
 (0)