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);