Set-constructor-add.js (3512B)
1 load(libdir + "asserts.js"); 2 load(libdir + "iteration.js"); 3 4 var k1 = {}; 5 var k2 = {}; 6 var k3 = {}; 7 var k4 = {}; 8 9 function test_patched() { 10 let orig = Set.prototype.add; 11 12 // If adder is modified, constructor should call it. 13 var called = false; 14 15 Set.prototype.add = function(k, v) { 16 assertEq(k, k1); 17 orig.call(this, k2); 18 called = true; 19 }; 20 21 var arr = [k1]; 22 23 var m = new Set(arr); 24 25 assertEq(called, true); 26 assertEq(m.size, 1); 27 assertEq(m.has(k1), false); 28 assertEq(m.has(k2), true); 29 30 Set.prototype.add = orig; 31 } 32 33 function test_proxy1() { 34 let orig = Set.prototype.add; 35 36 // If adder is modified, constructor should call it. 37 var called = false; 38 39 Set.prototype.add = new Proxy(function(k, v) { 40 assertEq(k, k1); 41 orig.call(this, k2); 42 called = true; 43 }, {}); 44 45 var arr = [k1]; 46 47 var m = new Set(arr); 48 49 assertEq(called, true); 50 assertEq(m.size, 1); 51 assertEq(m.has(k1), false); 52 assertEq(m.has(k2), true); 53 54 Set.prototype.add = orig; 55 } 56 57 function test_proxy2() { 58 let orig = Set.prototype.add; 59 60 // If adder is modified, constructor should call it. 61 var called = false; 62 63 Set.prototype.add = new Proxy(function() { 64 }, { 65 apply: function(target, that, args) { 66 var [k, v] = args; 67 assertEq(k, k1); 68 orig.call(that, k2); 69 called = true; 70 } 71 }); 72 73 var arr = [k1]; 74 75 var m = new Set(arr); 76 77 assertEq(called, true); 78 assertEq(m.size, 1); 79 assertEq(m.has(k1), false); 80 assertEq(m.has(k2), true); 81 82 Set.prototype.add = orig; 83 } 84 85 function test_change1() { 86 let orig = Set.prototype.add; 87 88 // Change to adder in GetIterator(..) call should be ignored. 89 var called = false; 90 var modified = false; 91 92 var arr = [k1]; 93 94 var proxy_arr = new Proxy(arr, { 95 get: function(target, name) { 96 if (name == Symbol.iterator) { 97 modified = true; 98 Set.prototype.add = function() { 99 called = true; 100 }; 101 } 102 return target[name]; 103 } 104 }); 105 106 var m = new Set(proxy_arr); 107 108 assertEq(modified, true); 109 assertEq(called, false); 110 assertEq(m.size, 1); 111 assertEq(m.has(k1), true); 112 assertEq(m.has(k2), false); 113 114 Set.prototype.add = orig; 115 } 116 117 function test_change2() { 118 let orig = Set.prototype.add; 119 120 // Change to adder in adder(...) call should be ignored. 121 var called = false; 122 var count = 0; 123 124 Set.prototype.add = function(k, v) { 125 if (count == 0) { 126 assertEq(k, k1); 127 orig.call(this, k3); 128 Set.prototype.add = function() { 129 called = true; 130 }; 131 count = 1; 132 } else { 133 assertEq(k, k2); 134 orig.call(this, k4); 135 count = 2; 136 } 137 }; 138 139 var arr = [k1, k2]; 140 141 var m = new Set(arr); 142 143 assertEq(called, false); 144 assertEq(count, 2); 145 assertEq(m.size, 2); 146 assertEq(m.has(k1), false); 147 assertEq(m.has(k2), false); 148 assertEq(m.has(k3), true); 149 assertEq(m.has(k4), true); 150 151 Set.prototype.add = orig; 152 } 153 154 function test_error() { 155 let orig = Set.prototype.add; 156 157 var arr = [k1]; 158 159 // Set should throw TypeError if adder is not callable. 160 Set.prototype.add = null; 161 assertThrowsInstanceOf(() => new Set(arr), TypeError); 162 Set.prototype.add = {}; 163 assertThrowsInstanceOf(() => new Set(arr), TypeError); 164 165 // Set should propagate error thrown by adder. 166 Set.prototype.add = function() { 167 throw SyntaxError(); 168 }; 169 assertThrowsInstanceOf(() => new Set(arr), SyntaxError); 170 171 Set.prototype.add = orig; 172 } 173 174 function test() { 175 test_patched(); 176 test_proxy1(); 177 test_proxy2(); 178 test_change1(); 179 test_change2(); 180 test_error(); 181 } 182 183 test();