Skip to content

Commit

Permalink
Deploy Sept 5, 2024 (#5119)
Browse files Browse the repository at this point in the history
[Tatsuyuki Ish] Fix type error in getPagesMap (#5063)
[Nazım Can Altınova] [Tab selector 1] Add a redux state for the tab
filter (#5072)
[Markus Stange] Remove a test for the inverted stack chart. (#5075)
[Markus Stange] Add an inverted tree test for getSamplesSelectedStates
and getTreeOrderComparator (#5076)
[Nazım Can Altınova] [Tab selector 2] Extract the page data in the full
view (#5073)
[Nazım Can Altınova] Do not crash on timeline hover/selection when a
profile doesn't have any samples or markers (#5086)
[Nazım Can Altınova] [Tab selector 3] Generate page information for all
tabs (#5082)
[Nazım Can Altınova] [Tab selector 4] Add a getTabToThreadIndexesMap
selector to get relevant threads per tab (#5087)
[joshuaobrien] Use the word 'archive' instead of 'zip file' in copy
(#5081)
[Markus Stange] Send a UserAgent header to the symbolication server
again (#5103)
[Julien Wajsberg] Add some console utilities to retrieve the current
profile and save it to disk (#5105)
[Nazım Can Altınova]  Add `selectedMarker` to the console APIs (#5107)
And various dependency updates.
  • Loading branch information
canova authored Sep 5, 2024
2 parents 2c84592 + 662dc4a commit 7b8ce3b
Show file tree
Hide file tree
Showing 37 changed files with 2,146 additions and 1,194 deletions.
58 changes: 29 additions & 29 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,20 +58,20 @@
"@codemirror/lang-rust": "^6.0.1",
"@codemirror/language": "^6.10.2",
"@codemirror/state": "^6.4.1",
"@codemirror/view": "^6.28.0",
"@codemirror/view": "^6.30.0",
"@firefox-devtools/react-contextmenu": "^5.1.1",
"@fluent/bundle": "^0.18.0",
"@fluent/langneg": "^0.7.0",
"@fluent/react": "^0.15.2",
"@lezer/highlight": "^1.2.0",
"@tgwf/co2": "^0.15.0",
"@lezer/highlight": "^1.2.1",
"@tgwf/co2": "^0.16.0",
"array-move": "^3.0.1",
"array-range": "^1.0.1",
"clamp": "^1.0.1",
"classnames": "^2.5.1",
"common-tags": "^1.8.2",
"copy-to-clipboard": "^3.3.3",
"core-js": "^3.37.1",
"core-js": "^3.38.0",
"escape-string-regexp": "^4.0.0",
"gecko-profiler-demangle": "^0.3.3",
"idb": "^8.0.0",
Expand All @@ -81,87 +81,87 @@
"mixedtuplemap": "^1.0.0",
"namedtuplemap": "^1.0.0",
"photon-colors": "^3.3.2",
"query-string": "^9.0.0",
"query-string": "^9.1.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-intersection-observer": "^9.10.3",
"react-intersection-observer": "^9.13.0",
"react-redux": "^9.1.2",
"react-splitter-layout": "^4.0.0",
"react-transition-group": "^4.4.5",
"redux": "^5.0.1",
"redux-logger": "^3.0.6",
"redux-thunk": "^3.1.0",
"reselect": "^4.1.8",
"url": "^0.11.3",
"url": "^0.11.4",
"weaktuplemap": "^1.0.0",
"workbox-window": "^7.1.0"
},
"devDependencies": {
"@babel/cli": "^7.24.7",
"@babel/core": "^7.24.7",
"@babel/eslint-parser": "^7.24.7",
"@babel/eslint-plugin": "^7.24.7",
"@babel/cli": "^7.24.8",
"@babel/core": "^7.25.2",
"@babel/eslint-parser": "^7.25.1",
"@babel/eslint-plugin": "^7.25.1",
"@babel/plugin-proposal-class-properties": "^7.18.6",
"@babel/preset-env": "^7.24.7",
"@babel/preset-env": "^7.25.3",
"@babel/preset-flow": "^7.24.7",
"@babel/preset-react": "^7.24.7",
"@testing-library/dom": "^10.1.0",
"@testing-library/jest-dom": "^6.4.6",
"@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^6.4.8",
"@testing-library/react": "^16.0.0",
"alex": "^11.0.1",
"autoprefixer": "^10.4.19",
"autoprefixer": "^10.4.20",
"babel-jest": "^29.7.0",
"babel-loader": "^9.1.3",
"babel-plugin-module-resolver": "^5.0.2",
"browserslist": "^4.23.1",
"caniuse-lite": "^1.0.30001632",
"browserslist": "^4.23.3",
"caniuse-lite": "^1.0.30001640",
"circular-dependency-plugin": "^5.2.1",
"codecov": "^3.8.3",
"copy-webpack-plugin": "^12.0.2",
"cross-env": "^7.0.3",
"css-loader": "^7.1.2",
"cssnano": "^7.0.2",
"cssnano": "^7.0.5",
"devtools-license-check": "^0.9.0",
"eslint": "^8.57.0",
"eslint-config-prettier": "^9.1.0",
"eslint-import-resolver-alias": "^1.1.2",
"eslint-plugin-flowtype": "^8.0.3",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-jest": "^28.6.0",
"eslint-plugin-jest": "^28.8.0",
"eslint-plugin-jest-dom": "^5.4.0",
"eslint-plugin-jest-formatting": "^3.1.0",
"eslint-plugin-react": "^7.34.3",
"eslint-plugin-testing-library": "^6.2.2",
"eslint-plugin-react": "^7.35.0",
"eslint-plugin-testing-library": "^6.3.0",
"espree": "^10.1.0",
"fake-indexeddb": "^6.0.0",
"fetch-mock-jest": "^1.5.1",
"file-loader": "^6.2.0",
"flow-bin": "^0.96.0",
"flow-coverage-report": "^0.8.0",
"flow-typed": "^4.0.0",
"glob": "^10.4.1",
"glob": "^10.4.5",
"html-webpack-plugin": "^5.6.0",
"husky": "^4.3.8",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"jest-extended": "^4.0.2",
"json-loader": "^0.5.7",
"local-web-server": "^5.3.3",
"local-web-server": "^5.4.0",
"lockfile-lint": "^4.14.0",
"mkdirp": "^3.0.1",
"node-fetch": "^2.6.11",
"npm-run-all": "^4.1.5",
"open": "^10.1.0",
"postcss": "^8.4.38",
"postcss": "^8.4.41",
"postcss-loader": "^8.1.1",
"prettier": "^3.3.1",
"prettier": "^3.3.3",
"raw-loader": "^4.0.2",
"rimraf": "^5.0.7",
"rimraf": "^5.0.10",
"style-loader": "^4.0.0",
"stylelint": "^16.6.1",
"stylelint": "^16.8.2",
"stylelint-config-idiomatic-order": "^10.0.0",
"stylelint-config-standard": "^36.0.0",
"webpack": "^5.92.0",
"stylelint-config-standard": "^36.0.1",
"webpack": "^5.94.0",
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^5.0.4",
"workbox-webpack-plugin": "^7.1.0",
Expand Down
14 changes: 14 additions & 0 deletions src/actions/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import type {
UrlState,
UploadedProfileInformation,
IndexIntoCategoryList,
TabID,
} from 'firefox-profiler/types';
import type { TabSlug } from 'firefox-profiler/app-logic/tabs-handling';
import type {
Expand Down Expand Up @@ -428,3 +429,16 @@ export function toggleOpenCategoryInSidebar(
category,
};
}

/**
* Change the selected browser tab filter for the profile.
* TabID here means the unique ID for a give browser tab and corresponds to
* multiple pages in the `profile.pages` array.
* If it's null it will undo the filter and will show the full profile.
*/
export function changeTabFilter(tabID: TabID | null): Action {
return {
type: 'CHANGE_TAB_FILTER',
tabID,
};
}
2 changes: 1 addition & 1 deletion src/actions/profile-view.js
Original file line number Diff line number Diff line change
Expand Up @@ -1362,7 +1362,7 @@ function _findOtherVisibleThread(
const localTrackOrder = getLocalTrackOrder(getState(), globalTrack.pid);
const hiddenLocalTracks = getHiddenLocalTracks(getState(), globalTrack.pid);
const localTrackIndexesToIgnore = localTrackIndexesToIgnoreByPid
? localTrackIndexesToIgnoreByPid.get(globalTrack.pid) ?? new Set()
? (localTrackIndexesToIgnoreByPid.get(globalTrack.pid) ?? new Set())
: new Set();

for (const trackIndex of localTrackOrder) {
Expand Down
71 changes: 42 additions & 29 deletions src/actions/receive-profile.js
Original file line number Diff line number Diff line change
Expand Up @@ -914,6 +914,11 @@ function getSymbolStore(
body: json,
method: 'POST',
mode: 'cors',
// Use a profiler-specific user agent, so that the symbolication server knows
// what's making this request.
headers: new Headers({
'User-Agent': `FirefoxProfiler/1.0 (+${location.origin})`,
}),
});
return response.json();
}
Expand Down Expand Up @@ -995,39 +1000,47 @@ export async function doSymbolicateProfile(
dispatch(doneSymbolicating());
}

// From a BrowserConnectionStatus, this unwraps the included browserConnection
// when possible.
export function unwrapBrowserConnection(
browserConnectionStatus: BrowserConnectionStatus
): BrowserConnection {
switch (browserConnectionStatus.status) {
case 'ESTABLISHED':
// Good. This is the normal case.
break;
// The other cases are error cases.
case 'NOT_FIREFOX':
throw new Error('/from-browser only works in Firefox browsers');
case 'NO_ATTEMPT':
throw new Error(
'retrieveProfileFromBrowser should never be called while browserConnectionStatus is NO_ATTEMPT'
);
case 'WAITING':
throw new Error(
'retrieveProfileFromBrowser should never be called while browserConnectionStatus is WAITING'
);
case 'DENIED':
throw browserConnectionStatus.error;
case 'TIMED_OUT':
throw new Error('Timed out when waiting for reply to WebChannel message');
default:
throw assertExhaustiveCheck(browserConnectionStatus.status);
}

// Now we know that browserConnectionStatus.status === 'ESTABLISHED'.
return browserConnectionStatus.browserConnection;
}

export function retrieveProfileFromBrowser(
browserConnectionStatus: BrowserConnectionStatus,
initialLoad: boolean = false
): ThunkAction<Promise<void>> {
return async (dispatch) => {
try {
switch (browserConnectionStatus.status) {
case 'ESTABLISHED':
// Good. This is the normal case.
break;
// The other cases are error cases.
case 'NOT_FIREFOX':
throw new Error('/from-browser only works in Firefox browsers');
case 'NO_ATTEMPT':
throw new Error(
'retrieveProfileFromBrowser should never be called while browserConnectionStatus is NO_ATTEMPT'
);
case 'WAITING':
throw new Error(
'retrieveProfileFromBrowser should never be called while browserConnectionStatus is WAITING'
);
case 'DENIED':
throw browserConnectionStatus.error;
case 'TIMED_OUT':
throw new Error(
'Timed out when waiting for reply to WebChannel message'
);
default:
throw assertExhaustiveCheck(browserConnectionStatus.status);
}

// Now we know that browserConnectionStatus.status === 'ESTABLISHED'.
const browserConnection = browserConnectionStatus.browserConnection;
const browserConnection = unwrapBrowserConnection(
browserConnectionStatus
);

// XXX update state to show that we're connected to the browser

Expand Down Expand Up @@ -1283,7 +1296,7 @@ async function _extractZipFromResponse(
// Catch the error if unable to load the zip.
return zip;
} catch (error) {
const message = 'Unable to unzip the zip file.';
const message = 'Unable to open the archive file.';
reportError(message);
reportError('Error:', error);
reportError('Fetch response:', response);
Expand Down Expand Up @@ -1409,7 +1422,7 @@ export function retrieveProfileOrZipFromUrl(
default:
throw assertExhaustiveCheck(
response.responseType,
'Expected to receive a zip file or profile from _fetchProfile.'
'Expected to receive an archive or profile from _fetchProfile.'
);
}
} catch (error) {
Expand Down
4 changes: 2 additions & 2 deletions src/actions/zipped-profiles.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export function viewProfileFromZip(
const file = zipFileTable.file[zipFileIndex];
if (!file) {
throw new Error(
'Attempted to load a zip file that did not exist or was a directory.'
'Attempted to load an archive that did not exist or was a directory.'
);
}

Expand All @@ -74,7 +74,7 @@ export function viewProfileFromZip(
}
} catch (error) {
console.error(
'Failed to process the profile in the zip file with the following error:'
'Failed to process the profile in the archive with the following error:'
);
console.error(error);
dispatch({ type: 'FAILED_TO_PROCESS_PROFILE_FROM_ZIP_FILE', error });
Expand Down
21 changes: 16 additions & 5 deletions src/app-logic/url-handling.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ type FullProfileSpecificBaseQuery = {|
hiddenGlobalTracks: string, // "01"
hiddenLocalTracksByPid: string, // "1549-0w8~1593-23~1598-01~1602-02~1607-1"
localTrackOrderByPid: string, // "1549-780w6~1560-01"
tabID: TabID,
// The following values are legacy, and will be converted to track-based values. These
// value can't be upgraded using the typical URL upgrading process, as the full profile
// must be fetched to compute the tracks.
Expand Down Expand Up @@ -328,6 +329,7 @@ export function getQueryStringFromUrlState(urlState: UrlState): string {
urlState.profileSpecific.full.localTrackOrderByPid,
urlState.profileSpecific.full.localTrackOrderChangedPids
);
baseQuery.tabID = urlState.profileSpecific.full.tabFilter ?? undefined;

break;
}
Expand Down Expand Up @@ -581,9 +583,17 @@ export function stateFromLocation(
transforms[selectedThreadsKey] = parseTransforms(query.transforms);
}

let tabID = null;
// oldTabID is used for the old active tab view that we had. We will remove
// it in the end, but have to keep this while we have the view.
let oldTabID = null;
if (query.ctxId && Number.isInteger(Number(query.ctxId))) {
tabID = Number(query.ctxId);
oldTabID = Number(query.ctxId);
}

// tabID is used for the tab selector that we have in our full view.
let tabID = null;
if (query.tabID && Number.isInteger(Number(query.tabID))) {
tabID = Number(query.tabID);
}

const selectedTab =
Expand Down Expand Up @@ -631,7 +641,7 @@ export function stateFromLocation(
symbolServerUrl: query.symbolServer || null,
timelineTrackOrganization: validateTimelineTrackOrganization(
query.view,
tabID
oldTabID
),
profileSpecific: {
implementation,
Expand Down Expand Up @@ -663,6 +673,7 @@ export function stateFromLocation(
),
localTrackOrderByPid,
localTrackOrderChangedPids,
tabFilter: tabID,
legacyThreadOrder: query.threadOrder
? query.threadOrder.split('-').map((index) => Number(index))
: null,
Expand Down Expand Up @@ -1347,8 +1358,8 @@ function validateTimelineTrackOrganization(
* provided or something else is provided for some reason.
*/
function validateTimelineType(type: ?string): TimelineType {
// Pretend this is a TimelineTrackOrganization so that we can exhaustively
// go through each option.
// Pretend this is a TimelineType so that we can exhaustively go through
// each option.
const timelineType: TimelineType = (type: any);
switch (timelineType) {
case 'stack':
Expand Down
5 changes: 5 additions & 0 deletions src/components/app/ListOfPublishedProfiles.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ import './ListOfPublishedProfiles.css';
// them by clicking on them, or delete them.

function _formatRange(range: StartEndRange): string {
if (!Number.isFinite(range.start) || !Number.isFinite(range.end)) {
// Do not attempt to show if the range is NaN or Infinity, which happens
// if a profile doesn't have any samples or markers.
return '';
}
return formatSeconds(range.end - range.start, 3, 1);
}

Expand Down
2 changes: 1 addition & 1 deletion src/components/app/ProfileViewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ class ProfileViewerImpl extends PureComponent<Props> {
<button
type="button"
className="profileViewerZipButton"
title="View all files in the zip file"
title="View all files in the archive"
onClick={returnToZipFileList}
/>
) : null}
Expand Down
2 changes: 1 addition & 1 deletion src/components/app/UrlManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ class UrlManagerImpl extends React.PureComponent<Props> {
)
) {
updateBrowserConnectionStatus({ status: 'WAITING' });
browserConnectionStatus = await createBrowserConnection('Firefox/123.0');
browserConnectionStatus = await createBrowserConnection();
updateBrowserConnectionStatus(browserConnectionStatus);
}

Expand Down
2 changes: 1 addition & 1 deletion src/components/app/WindowTitle.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ class WindowTitleImpl extends PureComponent<Props> {
document.title = title;
} else if (listingZipFile) {
/* We're looking at the zip file contents. */
document.title = 'Zip File Contents' + SEPARATOR + PRODUCT;
document.title = 'Archive Contents' + SEPARATOR + PRODUCT;
} else {
/* There's no profile yet, but we're not looking at a zip file.
* Let's use a sensible default, but do not throw because we forgot a
Expand Down
Loading

0 comments on commit 7b8ce3b

Please sign in to comment.