arguments-iterator-unmapped.js (3449B)
1 // Test iteration with an unmapped arguments object. 2 3 function simple() { 4 function f() { 5 "use strict"; 6 7 var sum = 0; 8 for (var v of arguments) { 9 sum += v; 10 } 11 return sum; 12 } 13 14 for (var i = 0; i < 100; ++i) { 15 assertEq(f(1, 2, 3), 6); 16 } 17 } 18 simple(); 19 20 function spreadCall() { 21 function f() { 22 var sum = 0; 23 for (var v of arguments) { 24 sum += v; 25 } 26 return sum; 27 } 28 29 function g() { 30 "use strict"; 31 return f(...arguments); 32 } 33 34 for (var i = 0; i < 100; ++i) { 35 assertEq(g(1, 2, 3), 6); 36 } 37 } 38 spreadCall(); 39 40 function spreadArray() { 41 function f() { 42 "use strict"; 43 44 var arr = [...arguments]; 45 var sum = 0; 46 for (var v of arr) { 47 sum += v; 48 } 49 return sum; 50 } 51 52 for (var i = 0; i < 100; ++i) { 53 assertEq(f(1, 2, 3), 6); 54 } 55 } 56 spreadArray(); 57 58 function reifyIterator() { 59 var reify = false; 60 function f() { 61 "use strict"; 62 63 if (reify) { 64 // Redefining any property attributes will reify the iterator property. 65 Object.defineProperty(arguments, Symbol.iterator, { 66 writable: false 67 }); 68 } 69 70 var sum = 0; 71 for (var v of arguments) { 72 sum += v; 73 } 74 return sum; 75 } 76 77 for (var i = 0; i <= 100; ++i) { 78 reify = i >= 50; 79 assertEq(f(1, 2, 3), 6); 80 } 81 } 82 reifyIterator(); 83 84 function overwriteIterator() { 85 var callCount = 0; 86 function Iterator() { 87 callCount += 1; 88 return Array.prototype[Symbol.iterator].call(this); 89 } 90 91 var overwrite = false; 92 function f() { 93 "use strict"; 94 95 if (overwrite) { 96 arguments[Symbol.iterator] = Iterator; 97 } 98 99 var sum = 0; 100 for (var v of arguments) { 101 sum += v; 102 } 103 return sum; 104 } 105 106 for (var i = 0; i <= 100; ++i) { 107 overwrite = i > 50; 108 assertEq(f(1, 2, 3), 6); 109 } 110 assertEq(callCount, 50); 111 } 112 overwriteIterator(); 113 114 function deleteIterator() { 115 var remove = false; 116 function f() { 117 "use strict"; 118 119 // Deleting Symbol.iterator won't change the shape of the arguments object. 120 // That's why we need to use a separate guard instruction to check if the 121 // iterator property was modified. 122 if (remove) { 123 delete arguments[Symbol.iterator]; 124 } 125 126 var sum = 0; 127 for (var v of arguments) { 128 sum += v; 129 } 130 return sum; 131 } 132 133 var error; 134 try { 135 for (var i = 0; i <= 100; ++i) { 136 remove = i === 100; 137 assertEq(f(1, 2, 3), 6); 138 } 139 } catch (e) { 140 error = e; 141 } 142 assertEq(error instanceof TypeError, true); 143 } 144 deleteIterator(); 145 146 function deleteIteratorInherit() { 147 var callCount = 0; 148 function Iterator() { 149 callCount += 1; 150 return Array.prototype[Symbol.iterator].call(this); 151 } 152 153 Object.prototype[Symbol.iterator] = Iterator; 154 155 var remove = false; 156 function f() { 157 "use strict"; 158 159 // Deleting Symbol.iterator won't change the shape of the arguments object. 160 // That's why we need to use a separate guard instruction to check if the 161 // iterator property was modified. 162 if (remove) { 163 delete arguments[Symbol.iterator]; 164 } 165 166 var sum = 0; 167 for (var v of arguments) { 168 sum += v; 169 } 170 return sum; 171 } 172 173 for (var i = 0; i <= 100; ++i) { 174 remove = i === 100; 175 assertEq(f(1, 2, 3), 6); 176 } 177 assertEq(callCount, 1); 178 179 delete Object.prototype[Symbol.iterator]; 180 } 181 deleteIteratorInherit(); 182 183 // Don't add tests below this point because |Object.prototype[Symbol.iterator]| 184 // was modified, which may lead to engine-wide deoptimisations.