browser_dbg-sourcemaps.js (6645B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */ 4 5 // Tests loading sourcemapped sources, setting breakpoints, and 6 // stepping in them. 7 8 "use strict"; 9 10 requestLongerTimeout(2); 11 12 add_task(async function () { 13 // NOTE: the CORS call makes the test run times inconsistent 14 const dbg = await initDebugger( 15 "doc-sourcemaps.html", 16 "entry.js", 17 "output.js", 18 "times2.js", 19 "opts.js" 20 ); 21 const { 22 selectors: { getBreakpointCount }, 23 } = dbg; 24 25 // Check that the original sources appear in the source tree 26 info("Before opening the page directory, no source are displayed"); 27 await waitForSourcesInSourceTree(dbg, [], { noExpand: true }); 28 await clickElement(dbg, "sourceDirectoryLabel", 4); 29 info( 30 "After opening the page directory, only all original sources (entry, output, time2, opts). (bundle is still hidden)" 31 ); 32 await waitForSourcesInSourceTree( 33 dbg, 34 ["entry.js", "output.js", "times2.js", "opts.js"], 35 { noExpand: true } 36 ); 37 info("Expand the page folder and assert that the bundle appears"); 38 await clickElement(dbg, "sourceDirectoryLabel", 3); 39 await clickElement(dbg, "sourceDirectoryLabel", 4); 40 await waitForSourcesInSourceTree( 41 dbg, 42 ["entry.js", "output.js", "times2.js", "opts.js", "bundle.js"], 43 { noExpand: true } 44 ); 45 46 const bundleSrc = findSource(dbg, "bundle.js"); 47 await selectSource(dbg, bundleSrc); 48 49 await clickGutter(dbg, 70); 50 await waitForBreakpointCount(dbg, 1); 51 await assertBreakpoint(dbg, 70); 52 53 await clickGutter(dbg, 70); 54 await waitForBreakpointCount(dbg, 0); 55 56 const entrySrc = findSource(dbg, "entry.js"); 57 58 await selectSource(dbg, entrySrc); 59 ok( 60 getEditorContent(dbg).includes("window.keepMeAlive"), 61 "Original source text loaded correctly" 62 ); 63 64 // Bug 1824375 - pending location shouldn't be location and include only url, line and column attributes 65 let pendingSelectedLocation = Services.prefs.getStringPref( 66 "devtools.debugger.pending-selected-location" 67 ); 68 is( 69 pendingSelectedLocation, 70 JSON.stringify({ url: entrySrc.url, line: 0, column: undefined }), 71 "Pending selected location is the expected one" 72 ); 73 74 // Test breaking on a breakpoint 75 await addBreakpoint(dbg, "entry.js", 15); 76 is(getBreakpointCount(), 1, "One breakpoint exists"); 77 assertBreakpointExists(dbg, entrySrc, 15); 78 79 invokeInTab("keepMeAlive"); 80 await waitForPausedInOriginalFileAndToggleMapScopes(dbg); 81 await assertPausedAtSourceAndLine(dbg, entrySrc.id, 15); 82 83 await stepIn(dbg); 84 await assertPausedAtSourceAndLine(dbg, findSource(dbg, "times2.js").id, 2); 85 86 await stepOver(dbg); 87 await assertPausedAtSourceAndLine(dbg, findSource(dbg, "times2.js").id, 3); 88 89 await stepOut(dbg); 90 await assertPausedAtSourceAndLine(dbg, entrySrc.id, 16); 91 92 pendingSelectedLocation = Services.prefs.getStringPref( 93 "devtools.debugger.pending-selected-location" 94 ); 95 is( 96 pendingSelectedLocation, 97 JSON.stringify({ url: entrySrc.url, line: 16, column: 0 }), 98 "Pending selected location is the expected one" 99 ); 100 101 const footerButton = findElement(dbg, "sourceMapFooterButton"); 102 is( 103 footerButton.textContent, 104 "original file", 105 "The source map button's label mention an original file" 106 ); 107 ok( 108 footerButton.classList.contains("original"), 109 "The source map icon is original" 110 ); 111 ok( 112 !footerButton.classList.contains("not-mapped"), 113 "The source map button isn't gray out" 114 ); 115 ok( 116 !footerButton.classList.contains("loading"), 117 "The source map button isn't reporting in-process loading" 118 ); 119 120 info("Click on jump to generated source link from editor's footer"); 121 let mappedSourceLink = findElement(dbg, "mappedSourceLink"); 122 is( 123 mappedSourceLink.textContent, 124 "To bundle.js", 125 "The link to mapped source mentions the bundle" 126 ); 127 128 is( 129 mappedSourceLink.title, 130 "Open related bundle (https://example.com/browser/devtools/client/debugger/test/mochitest/examples/sourcemaps/bundle.js)", 131 "The tooltip to mapped source shows the correct message to open the bundle" 132 ); 133 mappedSourceLink.click(); 134 135 await waitForSelectedSource(dbg, bundleSrc); 136 await assertPausedAtSourceAndLine(dbg, bundleSrc.id, 62); 137 // The mapped source link is computed asynchronously when we are on the bundle 138 mappedSourceLink = await waitFor(() => findElement(dbg, "mappedSourceLink")); 139 mappedSourceLink = findElement(dbg, "mappedSourceLink"); 140 is( 141 mappedSourceLink.textContent, 142 "From entry.js", 143 "The link to mapped source mentions the original source" 144 ); 145 is( 146 footerButton.textContent, 147 "bundle file", 148 "When moved to the bundle, the source map button's label mention a bundle file" 149 ); 150 ok( 151 !footerButton.classList.contains("original"), 152 "The source map icon isn't original" 153 ); 154 ok( 155 !footerButton.classList.contains("not-mapped"), 156 "The source map button isn't gray out" 157 ); 158 ok( 159 !footerButton.classList.contains("loading"), 160 "The source map button isn't reporting in-process loading" 161 ); 162 163 info("Move the cursor within the bundle to another original source"); 164 await setEditorCursorAt(dbg, 71, 0); 165 mappedSourceLink = await waitFor(() => findElement(dbg, "mappedSourceLink")); 166 is( 167 mappedSourceLink.textContent, 168 "From times2.js", 169 "The link to mapped source updates to the newly selected original source within the bundle" 170 ); 171 172 info("Move to the new original file via the source map button/menu"); 173 await clickOnSourceMapMenuItem(dbg, ".debugger-jump-mapped-source"); 174 is( 175 dbg.panel.panelWin.parent.document.querySelector( 176 ".debugger-jump-mapped-source" 177 ).textContent, 178 DEBUGGER_L10N.getStr("sourceFooter.sourceMapButton.jumpToOriginalSource"), 179 "assert jump to original menu label" 180 ); 181 await waitForSelectedSource(dbg, "times2.js"); 182 183 info("Open the related source map file and wait for a new tab to be opened"); 184 const onTabLoaded = BrowserTestUtils.waitForNewTab( 185 gBrowser, 186 `view-source:${EXAMPLE_URL}sourcemaps/bundle.js.map` 187 ); 188 await clickOnSourceMapMenuItem(dbg, ".debugger-source-map-link"); 189 await onTabLoaded; 190 }); 191 192 function assertBreakpointExists(dbg, source, line) { 193 const { 194 selectors: { getBreakpoint }, 195 } = dbg; 196 197 ok( 198 getBreakpoint(createLocation({ source, line })), 199 "Breakpoint has correct line" 200 ); 201 } 202 203 async function waitForBreakpointCount(dbg, count) { 204 const { 205 selectors: { getBreakpointCount }, 206 } = dbg; 207 await waitForState(dbg, () => getBreakpointCount() == count); 208 }