tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

browser_dbg-features-breakable-positions.js (10244B)


      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 "use strict";
      6 
      7 const testServer = createVersionizedHttpTestServer(
      8  "../examples/sourcemaps-reload-uncompressed"
      9 );
     10 const TEST_URL = testServer.urlFor("index.html");
     11 
     12 // getTokenFromPosition pauses 0.5s for each line,
     13 // so this test is quite slow to complete
     14 requestLongerTimeout(10);
     15 
     16 /**
     17 * Cover the breakpoints positions/columns:
     18 * - assert that the UI displayed markers in CodeMirror next to each breakable columns,
     19 * - assert the data in the reducers about the breakable columns.
     20 *
     21 * Note that it doesn't assert that the breakpoint can be hit.
     22 * It only verify data integrity and the UI.
     23 */
     24 add_task(async function testBreakableLinesOverReloads() {
     25  const dbg = await initDebuggerWithAbsoluteURL(
     26    TEST_URL,
     27    "index.html",
     28    "script.js",
     29    "original.js"
     30  );
     31 
     32  info("Assert breakable lines of the first html page load");
     33  await assertBreakablePositions(dbg, "index.html", 85, [
     34    { line: 16, columns: [6, 14] },
     35    { line: 17, columns: [] },
     36    { line: 21, columns: [12, 20, 48] },
     37    { line: 24, columns: [12, 20] },
     38    { line: 25, columns: [] },
     39    { line: 30, columns: [] },
     40    { line: 36, columns: [] },
     41    { line: 39, columns: [] },
     42    { line: 41, columns: [8, 18] },
     43    { line: 42, columns: [] },
     44    { line: 43, columns: [] },
     45  ]);
     46 
     47  info("Pretty print first html page load and assert breakable lines");
     48  await togglePrettyPrint(dbg);
     49  await assertBreakablePositions(dbg, "index.html:formatted", 96, [
     50    { line: 16, columns: [0, 8] },
     51    { line: 22, columns: [0, 8, 35] },
     52    { line: 27, columns: [0, 8] },
     53    { line: 28, columns: [] },
     54    { line: 36, columns: [] },
     55    { line: 48, columns: [] },
     56    { line: 50, columns: [2, 12] },
     57    { line: 53, columns: [] },
     58  ]);
     59  await closeTab(dbg, "index.html:formatted");
     60 
     61  info("Assert breakable lines of the first original source file, original.js");
     62  // The length of original.js is longer than the test file
     63  // because the sourcemap replaces the content of the original file
     64  // and appends a few lines with a "WEBPACK FOOTER" comment
     65  // All the appended lines are empty lines or comments, so none of them are breakable.
     66  await assertBreakablePositions(dbg, "original.js", 15, [
     67    { line: 1, columns: [] },
     68    { line: 2, columns: [2, 9, 32] },
     69    { line: 3, columns: [] },
     70    { line: 5, columns: [] },
     71    { line: 8, columns: [2, 8] },
     72    { line: 9, columns: [2, 10] },
     73    { line: 10, columns: [] },
     74  ]);
     75 
     76  info("Assert breakable lines of the simple first load of script.js");
     77  await assertBreakablePositions(dbg, "script.js", 9, [
     78    { line: 1, columns: [0, 8] },
     79    { line: 5, columns: [2, 10] },
     80    { line: 7, columns: [2, 9] },
     81    { line: 8, columns: [] },
     82    { line: 9, columns: [] },
     83  ]);
     84 
     85  info("Pretty print first load of script.js and assert breakable lines");
     86  await togglePrettyPrint(dbg);
     87  await assertBreakablePositions(dbg, "script.js:formatted", 8, [
     88    { line: 1, columns: [0, 8] },
     89    { line: 4, columns: [2, 10] },
     90    { line: 6, columns: [2, 9] },
     91    { line: 7, columns: [] },
     92  ]);
     93  await closeTab(dbg, "script.js:formatted");
     94 
     95  info(
     96    "Reload the page, wait for sources and assert that breakable lines get updated"
     97  );
     98  testServer.switchToNextVersion();
     99  await reload(dbg, "index.html", "script.js", "original.js");
    100 
    101  info("Assert breakable lines of the more complex second load of script.js");
    102  await assertBreakablePositions(dbg, "script.js", 23, [
    103    { line: 2, columns: [0, 8] },
    104    { line: 13, columns: [4, 12] },
    105    { line: 14, columns: [] },
    106    { line: 15, columns: [] },
    107    { line: 16, columns: [] },
    108    { line: 17, columns: [] },
    109    { line: 18, columns: [2, 10] },
    110    { line: 19, columns: [] },
    111    { line: 20, columns: [] },
    112    { line: 21, columns: [] },
    113    { line: 22, columns: [] },
    114    { line: 23, columns: [] },
    115  ]);
    116 
    117  info("Pretty print first load of script.js and assert breakable lines");
    118  await togglePrettyPrint(dbg);
    119  await assertBreakablePositions(dbg, "script.js:formatted", 23, [
    120    { line: 2, columns: [0, 8] },
    121    { line: 13, columns: [4, 12] },
    122    { line: 14, columns: [] },
    123    { line: 15, columns: [] },
    124    { line: 16, columns: [] },
    125    { line: 17, columns: [] },
    126    { line: 18, columns: [2, 10] },
    127    { line: 19, columns: [] },
    128    { line: 20, columns: [] },
    129    { line: 21, columns: [] },
    130    { line: 22, columns: [] },
    131  ]);
    132  await closeTab(dbg, "script.js:formatted");
    133 
    134  info("Assert breakable lines of the second html page load");
    135  await assertBreakablePositions(dbg, "index.html", 33, [
    136    { line: 25, columns: [6, 14] },
    137    { line: 27, columns: [] },
    138  ]);
    139 
    140  info("Pretty print second html page load and assert breakable lines");
    141  await togglePrettyPrint(dbg);
    142  await assertBreakablePositions(dbg, "index.html:formatted", 33, [
    143    { line: 25, columns: [0, 8] },
    144  ]);
    145  await closeTab(dbg, "index.html:formatted");
    146 
    147  info("Assert breakable lines of the second orignal file");
    148  // See first assertion about original.js,
    149  // the size of original.js doesn't match the size of the test file
    150  await assertBreakablePositions(dbg, "original.js", 18, [
    151    { line: 1, columns: [] },
    152    { line: 2, columns: [2, 9, 32] },
    153    { line: 3, columns: [] },
    154    { line: 8, columns: [] },
    155    { line: 9, columns: [2, 8] },
    156    { line: 10, columns: [2, 10] },
    157    { line: 11, columns: [] },
    158    { line: 13, columns: [0, 8] },
    159  ]);
    160 });
    161 
    162 async function assertBreakablePositions(
    163  dbg,
    164  file,
    165  numberOfLines,
    166  breakablePositions
    167 ) {
    168  await selectSource(dbg, file);
    169  is(
    170    getLineCount(dbg),
    171    numberOfLines,
    172    `We show the expected number of lines in CodeMirror for ${file}`
    173  );
    174  for (let line = 1; line <= numberOfLines; line++) {
    175    info(`Asserting line #${line}`);
    176    const positions = breakablePositions.find(
    177      position => position.line == line
    178    );
    179    // If we don't have any position, only assert that the line isn't breakable
    180    if (!positions) {
    181      await assertLineIsBreakable(dbg, file, line, false);
    182      continue;
    183    }
    184    const { columns } = positions;
    185    // Otherwise, set a breakpoint on the line to ensure we force fetching the breakable columns per line
    186    // (this is only fetch on-demand)
    187    await addBreakpointViaGutter(dbg, line);
    188    await assertBreakpoint(dbg, line);
    189    const source = findSource(dbg, file);
    190 
    191    // If there is no column breakpoint, skip all further assertions
    192    // Last lines of inline script are reported as breakable lines and selectors reports
    193    // one breakable column, but, we don't report any available column breakpoint for them.
    194    if (!columns.length) {
    195      // So, only ensure that there really is no marker on this line
    196      const lineElement = await getTokenFromPosition(dbg, { line });
    197      const columnMarkers = lineElement.querySelectorAll(".column-breakpoint");
    198      is(
    199        columnMarkers.length,
    200        0,
    201        `There is no breakable columns on line ${line}`
    202      );
    203      await removeBreakpoint(dbg, source.id, line);
    204      continue;
    205    }
    206 
    207    const selectorPositions = dbg.selectors.getBreakpointPositionsForSource(
    208      source.id
    209    );
    210    ok(selectorPositions, "Selector returned positions");
    211    const selectorPositionsForLine = selectorPositions[line];
    212    ok(selectorPositionsForLine, "Selector returned positions for the line");
    213    is(
    214      selectorPositionsForLine.length,
    215      columns.length,
    216      "Selector has the expected number of breakable columns"
    217    );
    218    for (const selPos of selectorPositionsForLine) {
    219      is(
    220        selPos.location.line,
    221        line,
    222        "Selector breakable column has the right line"
    223      );
    224      ok(
    225        columns.includes(selPos.location.column),
    226        `Selector breakable column has an expected column (${
    227          selPos.location.column
    228        } in ${JSON.stringify(columns)}) for line ${line}`
    229      );
    230      is(
    231        selPos.location.source.id,
    232        source.id,
    233        "Selector breakable column has the right source id"
    234      );
    235      is(
    236        selPos.location.source.url,
    237        source.url,
    238        "Selector breakable column has the right source url"
    239      );
    240    }
    241 
    242    const tokenElement = await getTokenFromPosition(dbg, { line });
    243    const lineElement = tokenElement.closest(".cm-line");
    244    // Those are the breakpoint chevron we click on to set a breakpoint on a given column
    245    const columnMarkers = [
    246      ...lineElement.querySelectorAll(".column-breakpoint"),
    247    ];
    248    is(
    249      columnMarkers.length,
    250      columns.length,
    251      "Got the expeced number of column markers"
    252    );
    253 
    254    // The first breakable column received the line breakpoint when calling addBreakpoint()
    255    const firstColumn = columns[0];
    256    ok(
    257      findColumnBreakpoint(dbg, file, line, firstColumn),
    258      `The first column ${firstColumn} has a breakpoint automatically`
    259    );
    260 
    261    for (const [index, column] of Object.entries(columns)) {
    262      const columnMarkerIndex = Number(index);
    263      // The first column breakpoint is shifted
    264      if (columnMarkerIndex == 0) {
    265        continue;
    266      }
    267      ok(
    268        !findColumnBreakpoint(dbg, file, line, column),
    269        `Before clicking on the marker, the column ${column} was not having a breakpoint`
    270      );
    271 
    272      const onSetBreakpoint = waitForDispatch(dbg.store, "SET_BREAKPOINT");
    273      let marker = getColumnMarker(lineElement, columnMarkerIndex);
    274      marker.click();
    275      await onSetBreakpoint;
    276      ok(
    277        findColumnBreakpoint(dbg, file, line, column),
    278        `Was able to set column breakpoint for ${file} @ ${line}:${column}`
    279      );
    280 
    281      const onRemoveBreakpoint = waitForDispatch(
    282        dbg.store,
    283        "REMOVE_BREAKPOINT"
    284      );
    285      marker = getColumnMarker(lineElement, columnMarkerIndex);
    286      marker.click();
    287      await onRemoveBreakpoint;
    288 
    289      ok(
    290        !findColumnBreakpoint(dbg, file, line, column),
    291        `Removed the just-added column breakpoint`
    292      );
    293    }
    294 
    295    await removeBreakpoint(dbg, source.id, line);
    296  }
    297 }
    298 
    299 function getColumnMarker(lineElement, index) {
    300  return lineElement.querySelectorAll(".column-breakpoint")[index];
    301 }