diff --git a/locales/en-US/app.ftl b/locales/en-US/app.ftl index 3697baf81e..1e48d817b7 100644 --- a/locales/en-US/app.ftl +++ b/locales/en-US/app.ftl @@ -1284,6 +1284,13 @@ BottomBox--source-code-not-available-title = Source code not available SourceView--source-not-available-text = See issue #3741 for supported scenarios and planned improvements. +# Displayed in the source view when the source code for a JavaScript file could +# not be obtained. It hints that the "JavaScript Sources" feature needs to be +# enabled in the recording settings before capturing a profile. +# "JavaScript Sources" and "about:profiling" should not be translated. +SourceView--enable-js-sources-feature-hint = + To view the source of this JavaScript file, before recording the profile enable the “JavaScript Sources” feature in the recording settings in about:profiling. + # Displayed whenever the assembly view was not able to get the assembly code for # a file. # Assembly refers to the low-level programming language. diff --git a/src/components/app/BottomBox.tsx b/src/components/app/BottomBox.tsx index 669146ca48..f5645b4a0d 100644 --- a/src/components/app/BottomBox.tsx +++ b/src/components/app/BottomBox.tsx @@ -38,6 +38,7 @@ import { import { getSourceViewFile, getSourceViewStartLine, + getSourceViewSourceId, } from 'firefox-profiler/selectors/profile'; import explicitConnect from 'firefox-profiler/utils/connect'; @@ -60,6 +61,7 @@ import './BottomBox.css'; type StateProps = { readonly isFullscreen: boolean; readonly sourceViewFile: string | null; + readonly sourceViewHasValidId: boolean; readonly sourceViewCode: SourceCodeStatus | void; readonly sourceViewScrollGeneration: number; readonly sourceViewScrollToLineNumber?: number; @@ -82,13 +84,29 @@ type DispatchProps = { type Props = ConnectedProps<{}, StateProps, DispatchProps>; -export function SourceCodeErrorOverlay({ errors }: CodeErrorOverlayProps) { +type SourceCodeErrorOverlayProps = CodeErrorOverlayProps & { + readonly hasValidId: boolean; +}; + +export function SourceCodeErrorOverlay({ + errors, + hasValidId, +}: SourceCodeErrorOverlayProps) { return (

Source code not available

+ {hasValidId ? ( + +

+ To view the source of this JavaScript file, enable the “JavaScript + Sources” feature in the recording settings on about:profiling + before recording the profile. +

+
+ ) : null} { const { isFullscreen, sourceViewFile, + sourceViewHasValidId, sourceViewCode, globalLineTimings, sourceViewScrollGeneration, @@ -278,7 +297,10 @@ class BottomBoxImpl extends React.PureComponent { ) : null} {sourceViewCode !== undefined && sourceViewCode.type === 'ERROR' ? ( - + ) : null}
@@ -341,6 +363,7 @@ export const BottomBox = explicitConnect<{}, StateProps, DispatchProps>({ mapStateToProps: (state) => ({ isFullscreen: getIsBottomBoxFullscreen(state), sourceViewFile: getSourceViewFile(state), + sourceViewHasValidId: getSourceViewSourceId(state) !== null, sourceViewCode: getSourceViewCode(state), globalLineTimings: selectedThreadSelectors.getSourceViewLineTimings(state), sourceViewScrollGeneration: getSourceViewScrollGeneration(state), diff --git a/src/test/components/BottomBox.test.tsx b/src/test/components/BottomBox.test.tsx index e8b9728770..1d6cf4bc06 100644 --- a/src/test/components/BottomBox.test.tsx +++ b/src/test/components/BottomBox.test.tsx @@ -5,6 +5,7 @@ import { Provider } from 'react-redux'; import { stripIndent } from 'common-tags'; import { ProfileViewer } from 'firefox-profiler/components/app/ProfileViewer'; +import { SourceCodeErrorOverlay } from 'firefox-profiler/components/app/BottomBox'; import { updateUrlState } from 'firefox-profiler/actions/app'; import { viewProfile } from 'firefox-profiler/actions/receive-profile'; import { stateFromLocation } from 'firefox-profiler/app-logic/url-handling'; @@ -238,3 +239,17 @@ describe('BottomBox', () => { expect(nextButton).toBeEnabled(); }); }); + +describe('SourceCodeErrorOverlay', () => { + const errors = [{ type: 'NO_KNOWN_CORS_URL' } as const]; + + it('shows the JS sources hint when the source has a valid id', () => { + render(); + expect(screen.getByText(/JavaScript Sources/)).toBeInTheDocument(); + }); + + it('does not show the JS sources hint when the source has no id', () => { + render(); + expect(screen.queryByText(/JavaScript Sources/)).not.toBeInTheDocument(); + }); +});