tor-browser

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

test_objectgrips-20.js (10751B)


      1 /* Any copyright is dedicated to the Public Domain.
      2   http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 "use strict";
      5 
      6 // Test that onEnumProperties returns the expected data
      7 // when passing `ignoreNonIndexedProperties` and `ignoreIndexedProperties` options
      8 // with various objects. (See Bug 1403065)
      9 
     10 const DO_NOT_CHECK_VALUE = Symbol();
     11 
     12 Services.prefs.setBoolPref("security.allow_eval_with_system_principal", true);
     13 registerCleanupFunction(() => {
     14  Services.prefs.clearUserPref("security.allow_eval_with_system_principal");
     15 });
     16 
     17 add_task(
     18  threadFrontTest(async ({ threadFront, debuggee }) => {
     19    debuggee.eval(
     20      // These arguments are tested.
     21      // eslint-disable-next-line no-unused-vars
     22      function stopMe(arg1) {
     23        debugger;
     24      }.toString()
     25    );
     26 
     27    const testCases = [
     28      {
     29        evaledObject: { a: 10 },
     30        expectedIndexedProperties: [],
     31        expectedNonIndexedProperties: [["a", 10]],
     32      },
     33      {
     34        evaledObject: { length: 10 },
     35        expectedIndexedProperties: [],
     36        expectedNonIndexedProperties: [["length", 10]],
     37      },
     38      {
     39        evaledObject: { a: 10, 0: "indexed" },
     40        expectedIndexedProperties: [["0", "indexed"]],
     41        expectedNonIndexedProperties: [["a", 10]],
     42      },
     43      {
     44        evaledObject: { 1: 1, length: 42, a: 10 },
     45        expectedIndexedProperties: [["1", 1]],
     46        expectedNonIndexedProperties: [
     47          ["length", 42],
     48          ["a", 10],
     49        ],
     50      },
     51      {
     52        evaledObject: { 1: 1, length: 2.34, a: 10 },
     53        expectedIndexedProperties: [["1", 1]],
     54        expectedNonIndexedProperties: [
     55          ["length", 2.34],
     56          ["a", 10],
     57        ],
     58      },
     59      {
     60        evaledObject: { 1: 1, length: -0, a: 10 },
     61        expectedIndexedProperties: [["1", 1]],
     62        expectedNonIndexedProperties: [
     63          ["length", -0],
     64          ["a", 10],
     65        ],
     66      },
     67      {
     68        evaledObject: { 1: 1, length: -10, a: 10 },
     69        expectedIndexedProperties: [["1", 1]],
     70        expectedNonIndexedProperties: [
     71          ["length", -10],
     72          ["a", 10],
     73        ],
     74      },
     75      {
     76        evaledObject: { 1: 1, length: true, a: 10 },
     77        expectedIndexedProperties: [["1", 1]],
     78        expectedNonIndexedProperties: [
     79          ["length", true],
     80          ["a", 10],
     81        ],
     82      },
     83      {
     84        evaledObject: { 1: 1, length: null, a: 10 },
     85        expectedIndexedProperties: [["1", 1]],
     86        expectedNonIndexedProperties: [
     87          ["length", DO_NOT_CHECK_VALUE],
     88          ["a", 10],
     89        ],
     90      },
     91      {
     92        evaledObject: { 1: 1, length: Math.pow(2, 53), a: 10 },
     93        expectedIndexedProperties: [["1", 1]],
     94        expectedNonIndexedProperties: [
     95          ["length", 9007199254740992],
     96          ["a", 10],
     97        ],
     98      },
     99      {
    100        evaledObject: { 1: 1, length: "fake", a: 10 },
    101        expectedIndexedProperties: [["1", 1]],
    102        expectedNonIndexedProperties: [
    103          ["length", "fake"],
    104          ["a", 10],
    105        ],
    106      },
    107      {
    108        evaledObject: { 1: 1, length: Infinity, a: 10 },
    109        expectedIndexedProperties: [["1", 1]],
    110        expectedNonIndexedProperties: [
    111          ["length", DO_NOT_CHECK_VALUE],
    112          ["a", 10],
    113        ],
    114      },
    115      {
    116        evaledObject: { 0: 0, length: 0 },
    117        expectedIndexedProperties: [["0", 0]],
    118        expectedNonIndexedProperties: [["length", 0]],
    119      },
    120      {
    121        evaledObject: { 0: 0, 1: 1, length: 1 },
    122        expectedIndexedProperties: [
    123          ["0", 0],
    124          ["1", 1],
    125        ],
    126        expectedNonIndexedProperties: [["length", 1]],
    127      },
    128      {
    129        evaledObject: { length: 0 },
    130        expectedIndexedProperties: [],
    131        expectedNonIndexedProperties: [["length", 0]],
    132      },
    133      {
    134        evaledObject: { 1: 1 },
    135        expectedIndexedProperties: [["1", 1]],
    136        expectedNonIndexedProperties: [],
    137      },
    138      {
    139        evaledObject: { a: 1, [2 ** 32 - 2]: 2, [2 ** 32 - 1]: 3 },
    140        expectedIndexedProperties: [["4294967294", 2]],
    141        expectedNonIndexedProperties: [
    142          ["a", 1],
    143          ["4294967295", 3],
    144        ],
    145      },
    146      {
    147        evaledObject: `(() => {
    148          x = [12, 42];
    149          x.foo = 90;
    150          return x;
    151        })()`,
    152        expectedIndexedProperties: [
    153          ["0", 12],
    154          ["1", 42],
    155        ],
    156        expectedNonIndexedProperties: [
    157          ["length", 2],
    158          ["foo", 90],
    159        ],
    160      },
    161      {
    162        evaledObject: `(() => {
    163          x = [12, 42];
    164          x.length = 3;
    165          return x;
    166        })()`,
    167        expectedIndexedProperties: [
    168          ["0", 12],
    169          ["1", 42],
    170          ["2", undefined],
    171        ],
    172        expectedNonIndexedProperties: [["length", 3]],
    173      },
    174      {
    175        evaledObject: `(() => {
    176          x = [12, 42];
    177          x.length = 1;
    178          return x;
    179        })()`,
    180        expectedIndexedProperties: [["0", 12]],
    181        expectedNonIndexedProperties: [["length", 1]],
    182      },
    183      {
    184        evaledObject: `(() => {
    185          x = [, 42,,];
    186          x.foo = 90;
    187          return x;
    188        })()`,
    189        expectedIndexedProperties: [
    190          ["0", undefined],
    191          ["1", 42],
    192          ["2", undefined],
    193        ],
    194        expectedNonIndexedProperties: [
    195          ["length", 3],
    196          ["foo", 90],
    197        ],
    198      },
    199      {
    200        evaledObject: `(() => {
    201          x = Array(2);
    202          x.foo = "bar";
    203          x.bar = "foo";
    204          return x;
    205        })()`,
    206        expectedIndexedProperties: [
    207          ["0", undefined],
    208          ["1", undefined],
    209        ],
    210        expectedNonIndexedProperties: [
    211          ["length", 2],
    212          ["foo", "bar"],
    213          ["bar", "foo"],
    214        ],
    215      },
    216      {
    217        evaledObject: `(() => {
    218          x = new Int8Array(new ArrayBuffer(2));
    219          x.foo = "bar";
    220          x.bar = "foo";
    221          return x;
    222        })()`,
    223        expectedIndexedProperties: [
    224          ["0", 0],
    225          ["1", 0],
    226        ],
    227        expectedNonIndexedProperties: [
    228          ["foo", "bar"],
    229          ["bar", "foo"],
    230          ["length", 2],
    231          ["buffer", DO_NOT_CHECK_VALUE],
    232          ["byteLength", 2],
    233          ["byteOffset", 0],
    234        ],
    235      },
    236      {
    237        evaledObject: `(() => {
    238          x = new Int8Array([1, 2]);
    239          Object.defineProperty(x, 'length', {value: 0});
    240          return x;
    241        })()`,
    242        expectedIndexedProperties: [
    243          ["0", 1],
    244          ["1", 2],
    245        ],
    246        expectedNonIndexedProperties: [
    247          ["length", 0],
    248          ["buffer", DO_NOT_CHECK_VALUE],
    249          ["byteLength", 2],
    250          ["byteOffset", 0],
    251        ],
    252      },
    253      {
    254        evaledObject: `(() => {
    255          x = new Int32Array([1, 2]);
    256          Object.setPrototypeOf(x, null);
    257          return x;
    258        })()`,
    259        expectedIndexedProperties: [
    260          ["0", 1],
    261          ["1", 2],
    262        ],
    263        expectedNonIndexedProperties: [],
    264      },
    265      {
    266        evaledObject: `(() => {
    267          return new (class extends Int8Array {})([1, 2]);
    268        })()`,
    269        expectedIndexedProperties: [
    270          ["0", 1],
    271          ["1", 2],
    272        ],
    273        expectedNonIndexedProperties: [
    274          ["length", 2],
    275          ["buffer", DO_NOT_CHECK_VALUE],
    276          ["byteLength", 2],
    277          ["byteOffset", 0],
    278        ],
    279      },
    280      {
    281        evaledObject: `(() => {
    282          x = new BigInt64Array(2);
    283          x[0] = 42n;
    284          x[1] = 5886014448488689n;
    285          return x;
    286        })()`,
    287        expectedIndexedProperties: [
    288          ["0", { type: "BigInt", text: "42" }],
    289          ["1", { type: "BigInt", text: "5886014448488689" }],
    290        ],
    291        expectedNonIndexedProperties: [
    292          ["length", 2],
    293          ["buffer", DO_NOT_CHECK_VALUE],
    294          ["byteLength", 2],
    295          ["byteOffset", 0],
    296        ],
    297      },
    298    ];
    299 
    300    for (const test of testCases) {
    301      await test_object_grip(debuggee, threadFront, test);
    302    }
    303  })
    304 );
    305 
    306 async function test_object_grip(debuggee, threadFront, testData = {}) {
    307  const {
    308    evaledObject,
    309    expectedIndexedProperties,
    310    expectedNonIndexedProperties,
    311  } = testData;
    312 
    313  const packet = await executeOnNextTickAndWaitForPause(eval_code, threadFront);
    314 
    315  const [grip] = packet.frame.arguments;
    316 
    317  const objClient = threadFront.pauseGrip(grip);
    318 
    319  info(`
    320        Check enumProperties response for
    321        ${
    322          typeof evaledObject === "string"
    323            ? evaledObject
    324            : JSON.stringify(evaledObject)
    325        }
    326      `);
    327 
    328  // Checks the result of enumProperties.
    329  let response = await objClient.enumProperties({
    330    ignoreNonIndexedProperties: true,
    331  });
    332  await check_enum_properties(response, expectedIndexedProperties);
    333 
    334  response = await objClient.enumProperties({
    335    ignoreIndexedProperties: true,
    336  });
    337  await check_enum_properties(response, expectedNonIndexedProperties);
    338 
    339  await threadFront.resume();
    340 
    341  function eval_code() {
    342    // Be sure to run debuggee code in its own HTML 'task', so that when we call
    343    // the onDebuggerStatement hook, the test's own microtasks don't get suspended
    344    // along with the debuggee's.
    345    do_timeout(0, () => {
    346      debuggee.eval(`
    347        stopMe(${
    348          typeof evaledObject === "string"
    349            ? evaledObject
    350            : JSON.stringify(evaledObject)
    351        });
    352      `);
    353    });
    354  }
    355 }
    356 
    357 async function check_enum_properties(iterator, expected = []) {
    358  equal(
    359    iterator.count,
    360    expected.length,
    361    "iterator.count has the expected value"
    362  );
    363 
    364  info("Check iterator.slice response for all properties");
    365  const sliceResponse = await iterator.slice(0, iterator.count);
    366  ok(
    367    sliceResponse &&
    368      Object.getOwnPropertyNames(sliceResponse).includes("ownProperties"),
    369    "The response object has an ownProperties property"
    370  );
    371 
    372  const { ownProperties } = sliceResponse;
    373  const names = Object.getOwnPropertyNames(ownProperties);
    374  equal(
    375    names.length,
    376    expected.length,
    377    "The response has the expected number of properties"
    378  );
    379  for (let i = 0; i < names.length; i++) {
    380    const name = names[i];
    381    const [key, value] = expected[i];
    382    equal(name, key, "Property has the expected name");
    383    const property = ownProperties[name];
    384 
    385    if (value === DO_NOT_CHECK_VALUE) {
    386      return;
    387    }
    388 
    389    if (value === undefined) {
    390      equal(
    391        property,
    392        undefined,
    393        `Response has no value for the "${key}" property`
    394      );
    395    } else {
    396      const propValue = property.hasOwnProperty("value")
    397        ? property.value
    398        : property.getterValue;
    399      Assert.deepEqual(
    400        propValue,
    401        value,
    402        `Property "${key}" has the expected value`
    403      );
    404    }
    405  }
    406 }