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