tor-browser

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

reviver-forward-modifies-object.js (4512B)


      1 // Copyright (C) 2023 the V8 project authors. All rights reserved.
      2 // This code is governed by the BSD license found in the LICENSE file.
      3 
      4 /*---
      5 esid: sec-json.parse
      6 description: Codepaths involving InternaliseJSONProperty behave as expected
      7 
      8 includes: [compareArray.js]
      9 features: [json-parse-with-source]
     10 ---*/
     11 
     12 function assertOnlyOwnProperties(object, props, message) {
     13  assert.compareArray(Object.getOwnPropertyNames(object), props, `${message}: object should have no other properties than expected`);
     14  assert.compareArray(Object.getOwnPropertySymbols(object), [], `${message}: object should have no own symbol properties`);
     15 }
     16 
     17 const replacements = [
     18  42,
     19  ["foo"],
     20  { foo: "bar" },
     21  "foo"
     22 ];
     23 
     24 // Test Array forward modify
     25 for (const replacement of replacements) {
     26  let alreadyReplaced = false;
     27  let expectedKeys = ["0", "1", ""];
     28  // if the replacement is an object, add its keys to the expected keys
     29  if (typeof replacement === "object") {
     30    expectedKeys.splice(1, 0, ...Object.keys(replacement));
     31  }
     32  const o = JSON.parse("[1, 2]", function (k, v, { source }) {
     33    assert.sameValue(k, expectedKeys.shift());
     34    if (k === "0") {
     35      if (!alreadyReplaced) {
     36        this[1] = replacement;
     37        alreadyReplaced = true;
     38      }
     39    } else if (k !== "") {
     40      assert.sameValue(source, undefined);
     41    }
     42    return this[k];
     43  });
     44  assert.sameValue(expectedKeys.length, 0);
     45  assert.compareArray(o, [1, replacement], `array forward-modified with ${replacement}`);
     46 }
     47 
     48 function assertOnlyOwnProperties(object, props, message) {
     49  assert.compareArray(Object.getOwnPropertyNames(object), props, `${message}: object should have no other properties than expected`);
     50  assert.compareArray(Object.getOwnPropertySymbols(object), [], `${message}: object should have no own symbol properties`);
     51 }
     52 
     53 // Test Object forward modify
     54 for (const replacement of replacements) {
     55  let alreadyReplaced = false;
     56  let expectedKeys = ["p", "q", ""];
     57  if (typeof replacement === "object") {
     58    expectedKeys.splice(1, 0, ...Object.keys(replacement));
     59  }
     60  const o = JSON.parse('{"p":1, "q":2}', function (k, v, { source }) {
     61    assert.sameValue(k, expectedKeys.shift());
     62    if (k === 'p') {
     63      if (!alreadyReplaced) {
     64        this.q = replacement;
     65        alreadyReplaced = true;
     66      }
     67    } else if (k !== "") {
     68      assert.sameValue(source, undefined);
     69    }
     70    return this[k];
     71  });
     72  assert.sameValue(expectedKeys.length, 0);
     73  assertOnlyOwnProperties(o, ["p", "q"], `object forward-modified with ${replacement}`);
     74  assert.sameValue(o.p, 1, "property p should not be replaced");
     75  assert.sameValue(o.q, replacement, `property q should be replaced with ${replacement}`);
     76 }
     77 
     78 // Test combinations of possible JSON input with multiple forward modifications
     79 
     80 {
     81  let reviverCallIndex = 0;
     82  const expectedKeys = ["a", "b", "c", ""];
     83  const reviver = function(key, value, {source}) {
     84    assert.sameValue(key, expectedKeys[reviverCallIndex++]);
     85    if (key === "a") {
     86      this.b = 2;
     87      assert.sameValue(source, "0");
     88    } else if (key === "b") {
     89      this.c = 3;
     90      assert.sameValue(value, 2);
     91      assert.sameValue(source, undefined);
     92    } else if (key === "c") {
     93      assert.sameValue(value, 3);
     94      assert.sameValue(source, undefined);
     95    }
     96    return value;
     97  }
     98  const parsed = JSON.parse('{"a": 0, "b": 1, "c": [1, 2]}', reviver);
     99  assertOnlyOwnProperties(parsed, ["a", "b", "c"], "object with forward-modified properties");
    100  assert.sameValue(parsed.a, 0, "'a' property should be unmodified");
    101  assert.sameValue(parsed.b, 2, "'b' property should be modified to 2");
    102  assert.sameValue(parsed.c, 3, "'c' property should be modified to 3");
    103 }
    104 
    105 {
    106  let reviverCallIndex = 0;
    107  const expectedKeys = ["0", "1", "2", "3", ""];
    108  const reviver = function(key, value, {source}) {
    109    assert.sameValue(key, expectedKeys[reviverCallIndex++]);
    110    if (key === "0") {
    111      this[1] = 3;
    112      assert.sameValue(value, 1);
    113      assert.sameValue(source, "1");
    114    } else if (key === "1") {
    115      this[2] = 4;
    116      assert.sameValue(value, 3);
    117      assert.sameValue(source, undefined);
    118    } else if(key === "2") {
    119      this[3] = 5;
    120      assert.sameValue(value, 4);
    121      assert.sameValue(source, undefined);
    122    } else if(key === "5") {
    123      assert.sameValue(value, 5);
    124      assert.sameValue(source, undefined);
    125    }
    126    return value;
    127  }
    128  assert.compareArray(JSON.parse('[1, 2, 3, {"a": 1}]', reviver), [1, 3, 4, 5], "array with forward-modified elements");
    129 }
    130 
    131 reportCompare(0, 0);