Skip to content

Commit 17fce59

Browse files
committed
Add WebChannel API for JS source code fetching
Implement browser communication to fetch JS source code using GlobalJSSourceId. This enables the profiler to retrieve original source content directly from the browser's JavaScript engine. Backend bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1916785
1 parent 18c3a38 commit 17fce59

File tree

3 files changed

+50
-1
lines changed

3 files changed

+50
-1
lines changed

src/app-logic/browser-connection.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
querySymbolicationApiViaWebChannel,
1313
getPageFaviconsViaWebChannel,
1414
showFunctionInDevtoolsViaWebChannel,
15+
getJSSourcesViaWebChannel,
1516
} from './web-channel';
1617
import type {
1718
Milliseconds,
@@ -83,6 +84,8 @@ export interface BrowserConnection {
8384
line: number | null,
8485
column: number | null
8586
): Promise<void>;
87+
88+
getJSSource(sourceUuid: string): Promise<string | null>;
8689
}
8790

8891
/**
@@ -98,6 +101,7 @@ class BrowserConnectionImpl implements BrowserConnection {
98101
_webChannelSupportsGetExternalMarkers: boolean;
99102
_webChannelSupportsGetPageFavicons: boolean;
100103
_webChannelSupportsOpenDebuggerInTab: boolean;
104+
_webChannelSupportsGetJSSource: boolean;
101105
_geckoProfiler: $GeckoProfiler | undefined;
102106

103107
constructor(webChannelVersion: number) {
@@ -106,6 +110,7 @@ class BrowserConnectionImpl implements BrowserConnection {
106110
this._webChannelSupportsGetExternalMarkers = webChannelVersion >= 3;
107111
this._webChannelSupportsGetPageFavicons = webChannelVersion >= 4;
108112
this._webChannelSupportsOpenDebuggerInTab = webChannelVersion >= 5;
113+
this._webChannelSupportsGetJSSource = webChannelVersion >= 6;
109114
}
110115

111116
// Only called when we must obtain the profile from the browser, i.e. if we
@@ -226,6 +231,26 @@ class BrowserConnectionImpl implements BrowserConnection {
226231

227232
return [];
228233
}
234+
235+
/**
236+
* Fetches JavaScript source code from the browser using the source UUID.
237+
* This method requires WebChannel version 6 or higher (Firefox 145+).
238+
*/
239+
async getJSSource(sourceUuid: string): Promise<string | null> {
240+
if (!this._webChannelSupportsGetJSSource) {
241+
throw new Error(
242+
"Can't use getJSSource in Firefox versions with the old WebChannel."
243+
);
244+
}
245+
246+
// Even though the WebChannel request for fetching JS sources supports
247+
// fetching multiple sources, we only fetch one at a time currently.
248+
// TODO: Change this to fetch multiple JS sources at the load time or while
249+
// we share the profile.
250+
return getJSSourcesViaWebChannel([sourceUuid]).then(
251+
(sources) => sources[0]
252+
);
253+
}
229254
}
230255

231256
// Should work with:

src/app-logic/web-channel.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ export type Request =
2828
| GetSymbolTableRequest
2929
| QuerySymbolicationApiRequest
3030
| GetPageFaviconsRequest
31-
| OpenScriptInTabDebuggerRequest;
31+
| OpenScriptInTabDebuggerRequest
32+
| GetJSSourcesRequest;
3233

3334
type StatusQueryRequest = { type: 'STATUS_QUERY' };
3435
type EnableMenuButtonRequest = { type: 'ENABLE_MENU_BUTTON' };
@@ -64,6 +65,10 @@ type OpenScriptInTabDebuggerRequest = {
6465
line: number | null;
6566
column: number | null;
6667
};
68+
type GetJSSourcesRequest = {
69+
type: 'GET_JS_SOURCES';
70+
sourceUuids: Array<string>;
71+
};
6772

6873
export type MessageFromBrowser<R extends ResponseFromBrowser> =
6974
| OutOfBandErrorMessageFromBrowser
@@ -128,6 +133,10 @@ type StatusQueryResponse = {
128133
// Shipped in Firefox 136.
129134
// Adds support for showing the JS script in DevTools debugger.
130135
// - OPEN_SCRIPT_IN_DEBUGGER
136+
// Version 6:
137+
// Shipped in Firefox 145.
138+
// Adds support for fetching JS sources.
139+
// - GET_JS_SOURCES
131140
version?: number;
132141
};
133142
type EnableMenuButtonResponse = void;
@@ -138,6 +147,7 @@ type GetSymbolTableResponse = SymbolTableAsTuple;
138147
type QuerySymbolicationApiResponse = string;
139148
type GetPageFaviconsResponse = Array<FaviconData | null>;
140149
type OpenScriptInTabDebuggerResponse = void;
150+
type GetJSSourcesResponse = Array<string | null>;
141151

142152
// TypeScript function overloads for request/response pairs.
143153
function _sendMessageWithResponse(
@@ -167,6 +177,10 @@ function _sendMessageWithResponse(
167177
function _sendMessageWithResponse(
168178
request: OpenScriptInTabDebuggerRequest
169179
): Promise<OpenScriptInTabDebuggerResponse>;
180+
function _sendMessageWithResponse(
181+
request: GetJSSourcesRequest
182+
): Promise<GetJSSourcesResponse>;
183+
170184
function _sendMessageWithResponse(request: Request): Promise<any> {
171185
const requestId = _requestId++;
172186
const type = request.type;
@@ -371,6 +385,15 @@ export async function showFunctionInDevtoolsViaWebChannel(
371385
});
372386
}
373387

388+
export async function getJSSourcesViaWebChannel(
389+
sourceUuids: Array<string>
390+
): Promise<Array<string | null>> {
391+
return _sendMessageWithResponse({
392+
type: 'GET_JS_SOURCES',
393+
sourceUuids,
394+
});
395+
}
396+
374397
/**
375398
* -----------------------------------------------------------------------------
376399
*

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,7 @@ describe('RegularExternalCommunicationDelegate', function () {
271271
getSymbolTable: jest.fn(bcOverrides.getSymbolTable),
272272
getPageFavicons: jest.fn(bcOverrides.getPageFavicons),
273273
showFunctionInDevtools: jest.fn(bcOverrides.showFunctionInDevtools),
274+
getJSSource: jest.fn(bcOverrides.getJSSource),
274275
}
275276
: null;
276277

0 commit comments

Comments
 (0)