tor-browser

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

browser_dump_scope.js (7357B)


      1 /* Any copyright is dedicated to the Public Domain.
      2 * http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 "use strict";
      5 const { dumpScope } = ChromeUtils.importESModule(
      6  "resource://devtools/shared/test-helpers/dump-scope.sys.mjs",
      7  { global: "devtools" }
      8 );
      9 
     10 function nestedSync1() {
     11  /* eslint-disable no-unused-vars */
     12  const a = { prop: 1 };
     13  const b = [1, 2, 3];
     14  const c = function () {};
     15  /* eslint-enable no-unused-vars */
     16 
     17  return nestedSync2();
     18 }
     19 
     20 function nestedSync2() {
     21  /* eslint-disable no-unused-vars */
     22  const d = { prop: -1 };
     23  const e = ["4", "5", "6"];
     24  const f = new Uint8Array([7, 8, 9]);
     25  /* eslint-enable no-unused-vars */
     26 
     27  return dumpScope({ saveAsFile: false });
     28 }
     29 
     30 add_task(async function testSyncStack() {
     31  const scopes = await nestedSync1();
     32  is(scopes.length, 3, "dumpScope returned 3 frames");
     33 
     34  // Test frame for nestedSync1
     35  const testScope1 = scopes[1];
     36  assertScopeInformation(testScope1);
     37 
     38  let scope = testScope1.blocks[0];
     39  is(typeof scope.a, "object", "Object type is correct");
     40  is(scope.a.prop, "1", "Object property value is correct");
     41 
     42  is(typeof scope.b, "object");
     43  ok(Array.isArray(scope.b));
     44  is(scope.b[0], "1", "Array of number value is correct");
     45  is(scope.b[1], "2", "Array of number value is correct");
     46  is(scope.b[2], "3", "Array of number value is correct");
     47 
     48  is(typeof scope.c, "string", "Function type is correct");
     49  is(scope.c, "Function c", "Function value is correct");
     50 
     51  // Test frame for nestedSync2
     52  const testScope2 = scopes[0];
     53  assertScopeInformation(testScope2);
     54 
     55  scope = testScope2.blocks[0];
     56  is(typeof scope.d, "object", "Object type is correct");
     57  is(scope.d.prop, "-1", "Object property value is correct");
     58 
     59  // Check regular array of strings
     60  is(typeof scope.e, "object");
     61  ok(Array.isArray(scope.e), "Array of string type is correct");
     62  is(scope.e[0], "4", "Array of string value is correct");
     63  is(scope.e[1], "5", "Array of string value is correct");
     64  is(scope.e[2], "6", "Array of string value is correct");
     65 
     66  // Check typed array
     67  is(typeof scope.e, "object");
     68  ok(Array.isArray(scope.f), "Typed array type is correct");
     69  is(scope.f[0], "7", "Typed array value is correct");
     70  is(scope.f[1], "8", "Typed array value is correct");
     71  is(scope.f[2], "9", "Typed array value is correct");
     72 });
     73 
     74 async function nestedAsync1() {
     75  // eslint-disable-next-line no-unused-vars
     76  const asyncA = 1;
     77  const scopes = await nestedAsync2();
     78  return scopes;
     79 }
     80 
     81 async function nestedAsync2() {
     82  // eslint-disable-next-line no-unused-vars
     83  const asyncB = 2;
     84  const scopes = await nestedAsync3();
     85  return scopes;
     86 }
     87 
     88 async function nestedAsync3() {
     89  // eslint-disable-next-line no-unused-vars
     90  const asyncC = 3;
     91  return dumpScope({ saveAsFile: false });
     92 }
     93 
     94 add_task(async function testAsyncStack() {
     95  const scopes = await nestedAsync1();
     96  is(scopes.length, 4, "dumpScope returned 4 frames");
     97 
     98  const testScope1 = scopes[2];
     99  assertScopeInformation(testScope1);
    100  is(testScope1.blocks[0].asyncA, "1", "Async frame value is correct");
    101  const testScope2 = scopes[1];
    102  assertScopeInformation(testScope2);
    103  is(testScope2.blocks[0].asyncB, "2", "Async frame value is correct");
    104  const testScope3 = scopes[0];
    105  assertScopeInformation(testScope3);
    106  is(testScope3.blocks[0].asyncC, "3", "Async frame value is correct");
    107 });
    108 
    109 function cyclicReference() {
    110  const a = {};
    111  const b = { a };
    112  a.b = b;
    113 
    114  return dumpScope({ saveAsFile: false });
    115 }
    116 
    117 add_task(async function testCyclicReference() {
    118  const scopes = await cyclicReference();
    119  is(scopes.length, 2, "dumpScope returned 2 frames");
    120 
    121  const testScope = scopes[0];
    122  assertScopeInformation(testScope);
    123  is(typeof testScope.blocks[0].a, "object", "Cyclic object type is correct");
    124 
    125  // Note that the actual way cyclic references are handled could change in the
    126  // future. If we decide to start handling them as references, this test should
    127  // simply be updated!
    128  is(typeof testScope.blocks[0].a.b, "object", "Cyclic object type is correct");
    129  is(
    130    typeof testScope.blocks[0].a.b.a,
    131    "object",
    132    "Cyclic object type is correct"
    133  );
    134  is(
    135    typeof testScope.blocks[0].a.b.a.b,
    136    "object",
    137    "Cyclic object type is correct"
    138  );
    139  is(
    140    testScope.blocks[0].a.b.a.b.a,
    141    "Object (max depth)",
    142    "Cyclic object value is correct"
    143  );
    144 });
    145 
    146 function maxDepth() {
    147  const obj = {};
    148 
    149  let o = obj;
    150  for (let i = 0; i < 100; i++) {
    151    o = o[`a${i}`] = {};
    152  }
    153 
    154  return dumpScope({ saveAsFile: false });
    155 }
    156 
    157 add_task(async function testMaxDepth() {
    158  const scopes = await maxDepth();
    159  is(scopes.length, 2, "dumpScope returned 2 frames");
    160 
    161  const testScope = scopes[0];
    162  assertScopeInformation(testScope);
    163  is(
    164    typeof testScope.blocks[0].obj,
    165    "object",
    166    "Max depth object type is correct"
    167  );
    168  is(
    169    typeof testScope.blocks[0].obj.a0,
    170    "object",
    171    "Max depth object type is correct"
    172  );
    173  is(
    174    typeof testScope.blocks[0].obj.a0.a1,
    175    "object",
    176    "Max depth object type is correct"
    177  );
    178  is(
    179    typeof testScope.blocks[0].obj.a0.a1.a2,
    180    "object",
    181    "Max depth object type is correct"
    182  );
    183  is(
    184    typeof testScope.blocks[0].obj.a0.a1.a2.a3,
    185    "string",
    186    "Max depth object type is correct"
    187  );
    188  is(
    189    testScope.blocks[0].obj.a0.a1.a2.a3,
    190    "Object (max depth)",
    191    "Max depth object value is correct"
    192  );
    193 });
    194 
    195 function nestedInABlock() {
    196  /* eslint-disable no-unused-vars */
    197  const outerBlock = "outerBlock";
    198 
    199  {
    200    const innerBlock = "innerBlock";
    201    return dumpScope({ saveAsFile: false });
    202  }
    203  /* eslint-enable no-unused-vars */
    204 }
    205 
    206 add_task(async function testBlockNesting() {
    207  const scopes = await nestedInABlock();
    208  is(scopes.length, 2, "dumpScope returned 2 frames");
    209 
    210  // Test frame for nestedInABlock
    211  const testScope1 = scopes[0];
    212  assertScopeInformation(testScope1);
    213 
    214  const block1 = testScope1.blocks[0];
    215  is(typeof block1.innerBlock, "string", "innerBlock type is correct");
    216  is(block1.innerBlock, "innerBlock", "innerBlock value is correct");
    217  const block2 = testScope1.blocks[1];
    218  is(typeof block2.outerBlock, "string", "outerBlock type is correct");
    219  is(block2.outerBlock, "outerBlock", "outerBlock value is correct");
    220 });
    221 
    222 function uninitialized() {
    223  /* eslint-disable no-unused-vars */
    224  const scopes = dumpScope({ saveAsFile: false });
    225  const afterCallToDumpScope = "afterCallToDumpScope";
    226  return scopes;
    227  /* eslint-enable no-unused-vars */
    228 }
    229 
    230 add_task(async function testUninitialized() {
    231  const scopes = await uninitialized();
    232  is(scopes.length, 2, "dumpScope returned 2 frames");
    233 
    234  // Test frame for uninitialized
    235  const testScope1 = scopes[0];
    236  assertScopeInformation(testScope1);
    237 
    238  const block1 = testScope1.blocks[0];
    239  is(
    240    block1.afterCallToDumpScope,
    241    "(uninitialized)",
    242    "variable initialized after the call to dumpScope is marked as (uninitialized)"
    243  );
    244 });
    245 
    246 /**
    247 * Basic test helper to assert the shape of the frame object
    248 */
    249 function assertScopeInformation(scopeInfo) {
    250  is(
    251    scopeInfo.details.frameScriptUrl,
    252    "chrome://mochitests/content/browser/devtools/shared/test-helpers/browser_dump_scope.js"
    253  );
    254  is(typeof scopeInfo.details.columnNumber, "number");
    255  is(typeof scopeInfo.details.lineNumber, "number");
    256  ok(Array.isArray(scopeInfo.blocks));
    257  for (const block of scopeInfo.blocks) {
    258    is(typeof block, "object");
    259  }
    260 }