| OLD | NEW | 
|---|
| (Empty) |  | 
|  | 1 // Copyright 2015 the V8 project authors. All rights reserved. | 
|  | 2 // Use of this source code is governed by a BSD-style license that can be | 
|  | 3 // found in the LICENSE file. | 
|  | 4 | 
|  | 5 // Flags: --harmony-do-expressions --harmony-sloppy-let --allow-natives-syntax | 
|  | 6 // Flags: --harmony-default-parameters --harmony-destructuring | 
|  | 7 | 
|  | 8 function returnValue(v) { return v; } | 
|  | 9 function MyError() {} | 
|  | 10 var global = this; | 
|  | 11 | 
|  | 12 function TestBasic() { | 
|  | 13   // Looping and lexical declarations | 
|  | 14   assertEquals(512, returnValue(do { | 
|  | 15     let n = 2; | 
|  | 16     for (let i = 0; i < 4; i++) n <<= 2; | 
|  | 17   })); | 
|  | 18 | 
|  | 19   // Strings do the right thing | 
|  | 20   assertEquals("spooky halloween", returnValue(do { | 
|  | 21     "happy halloween".replace('happy', 'spooky'); | 
|  | 22   })); | 
|  | 23 | 
|  | 24   // Do expressions with no completion produce an undefined value | 
|  | 25   assertEquals(undefined, returnValue(do {})); | 
|  | 26   assertEquals(undefined, returnValue(do { var x = 99; })); | 
|  | 27   assertEquals(undefined, returnValue(do { function f() {}; })); | 
|  | 28   assertEquals(undefined, returnValue(do { let z = 33; })); | 
|  | 29 | 
|  | 30   // Propagation of exception | 
|  | 31   assertThrows(function() { | 
|  | 32     (do { | 
|  | 33       throw new MyError(); | 
|  | 34       "potatoes"; | 
|  | 35     }); | 
|  | 36   }, MyError); | 
|  | 37 | 
|  | 38   assertThrows(function() { | 
|  | 39     return do { | 
|  | 40       throw new MyError(); | 
|  | 41       "potatoes"; | 
|  | 42     }; | 
|  | 43   }, MyError); | 
|  | 44 | 
|  | 45   // Return value within do-block overrides `return |do-expression|` | 
|  | 46   assertEquals("inner-return", (function() { | 
|  | 47     return "outer-return" + do { | 
|  | 48       return "inner-return"; | 
|  | 49       ""; | 
|  | 50     }; | 
|  | 51   })()); | 
|  | 52 | 
|  | 53   var count = 0, n = 1; | 
|  | 54   // Breaking out |do-expression| | 
|  | 55   assertEquals(3, (function() { | 
|  | 56     for (var i = 0; i < 10; ++i) (count += 2 * do { if (i === 3) break; ++n }); | 
|  | 57     return i; | 
|  | 58   })()); | 
|  | 59   // (2 * 2) + (2 * 3) + (2 * 4) | 
|  | 60   assertEquals(18, count); | 
|  | 61 | 
|  | 62   // Continue in |do-expression| | 
|  | 63   count = 0, n = 1; | 
|  | 64   assertEquals([1, 3, 5, 7, 9], (function() { | 
|  | 65     var values = []; | 
|  | 66     for (var i = 0; i < 10; ++i) { | 
|  | 67       count += 2 * (do { | 
|  | 68         if ((i & 1) === 0) continue; | 
|  | 69         values.push(i); | 
|  | 70         ++n; | 
|  | 71       }) + 1; | 
|  | 72     } | 
|  | 73     // (2*2) + 1 + (2*3) + 1 + (2*4) + 1 + (2*5) + 1 + (2*6) + 1 | 
|  | 74     return values; | 
|  | 75   })()); | 
|  | 76   assertEquals(count, 45); | 
|  | 77 | 
|  | 78   assertThrows("(do { break; });", SyntaxError); | 
|  | 79   assertThrows("(do { continue; });", SyntaxError); | 
|  | 80 | 
|  | 81   // Real-world use case for desugaring | 
|  | 82   var array = [1, 2, 3, 4, 5], iterable = [6, 7, 8,9]; | 
|  | 83   assertEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], do { | 
|  | 84     for (var element of iterable) array.push(element); | 
|  | 85     array; | 
|  | 86   }); | 
|  | 87 | 
|  | 88   // Nested do-expressions | 
|  | 89   assertEquals(125, do { (do { (do { 5 * 5 * 5 }) }) }); | 
|  | 90 | 
|  | 91   // Directives are not honoured | 
|  | 92   (do { | 
|  | 93     "use strict"; | 
|  | 94     foo = 80; | 
|  | 95     assertEquals(foo, 80); | 
|  | 96   }); | 
|  | 97 | 
|  | 98   // Non-empty operand stack testing | 
|  | 99   var O = { | 
|  | 100     method1() { | 
|  | 101       let x = 256; | 
|  | 102       return x + do { | 
|  | 103         for (var i = 0; i < 4; ++i) x += i; | 
|  | 104       } + 17; | 
|  | 105     }, | 
|  | 106     method2() { | 
|  | 107       let x = 256; | 
|  | 108       this.reset(); | 
|  | 109       return x + do { | 
|  | 110         for (var i = 0; i < this.length(); ++i) x += this.index() * 2; | 
|  | 111       }; | 
|  | 112     }, | 
|  | 113     _index: 0, | 
|  | 114     index() { | 
|  | 115       return ++this._index; | 
|  | 116     }, | 
|  | 117     _length: 4, | 
|  | 118     length() { return this._length; }, | 
|  | 119     reset() { this._index = 0; } | 
|  | 120   }; | 
|  | 121   assertEquals(535, O["method" + do { 1 } + ""]()); | 
|  | 122   assertEquals(532, O["method" + do { ({ valueOf() { return "2"; } }); }]()); | 
|  | 123   assertEquals(532, O[ | 
|  | 124       do { let s = ""; for (let c of "method") s += c; } + "2"]()); | 
|  | 125 } | 
|  | 126 TestBasic(); | 
|  | 127 | 
|  | 128 | 
|  | 129 function TestDeoptimization1() { | 
|  | 130   function f(v) { | 
|  | 131     return 88 + do { | 
|  | 132       v.a * v.b + v.c; | 
|  | 133     }; | 
|  | 134   } | 
|  | 135 | 
|  | 136   var o1 = {}; | 
|  | 137   o1.a = 10; | 
|  | 138   o1.b = 5; | 
|  | 139   o1.c = 50; | 
|  | 140 | 
|  | 141   var o2 = {}; | 
|  | 142   o2.c = 100; | 
|  | 143   o2.a = 10; | 
|  | 144   o2.b = 10; | 
|  | 145 | 
|  | 146   assertEquals(188, f(o1)); | 
|  | 147   assertEquals(188, f(o1)); | 
|  | 148   %OptimizeFunctionOnNextCall(f); | 
|  | 149   assertEquals(188, f(o1)); | 
|  | 150   assertOptimized(f); | 
|  | 151   assertEquals(288, f(o2)); | 
|  | 152   assertUnoptimized(f); | 
|  | 153   assertEquals(288, f(o2)); | 
|  | 154 } | 
|  | 155 TestDeoptimization1(); | 
|  | 156 | 
|  | 157 | 
|  | 158 function TestInParameterInitializers() { | 
|  | 159   var first_name = "George"; | 
|  | 160   var last_name = "Jetson"; | 
|  | 161   function fn1(name = do { first_name + " " + last_name }) { | 
|  | 162     return name; | 
|  | 163   } | 
|  | 164   assertEquals("George Jetson", fn1()); | 
|  | 165 | 
|  | 166   var _items = [1, 2, 3, NaN, 4, 5]; | 
|  | 167   function fn2(items = do { | 
|  | 168     let items = []; | 
|  | 169     for (var el of _items) { | 
|  | 170       if (el !== el) break; | 
|  | 171       items.push(el), items; | 
|  | 172     } | 
|  | 173   }) { | 
|  | 174     return items; | 
|  | 175   } | 
|  | 176   assertEquals([1, 2, 3], fn2()); | 
|  | 177 | 
|  | 178   function thrower() { throw new MyError(); } | 
|  | 179   function fn3(exception = do {  try { thrower(); } catch (e) { e } }) { | 
|  | 180     return exception; | 
|  | 181   } | 
|  | 182   assertDoesNotThrow(fn3); | 
|  | 183   assertInstanceof(fn3(), MyError); | 
|  | 184 | 
|  | 185   function fn4(exception = do { throw new MyError() }) {} | 
|  | 186   function catcher(fn) { | 
|  | 187     try { | 
|  | 188       fn(); | 
|  | 189       assertUnreachable("fn() initializer should throw"); | 
|  | 190     } catch (e) { | 
|  | 191       assertInstanceof(e, MyError); | 
|  | 192     } | 
|  | 193   } | 
|  | 194   catcher(fn4); | 
|  | 195 } | 
|  | 196 TestInParameterInitializers(); | 
|  | 197 | 
|  | 198 | 
|  | 199 function TestWithEval() { | 
|  | 200   (function sloppy1() { | 
|  | 201     assertEquals(do { eval("var x = 5"), x }, 5); | 
|  | 202     assertEquals(x, 5); | 
|  | 203   })(); | 
|  | 204 | 
|  | 205   assertThrows(function strict1() { | 
|  | 206     "use strict"; | 
|  | 207     (do { eval("var x = 5"), x }, 5); | 
|  | 208   }, ReferenceError); | 
|  | 209 | 
|  | 210   assertThrows(function strict2() { | 
|  | 211     (do { eval("'use strict'; var x = 5"), x }, 5); | 
|  | 212   }, ReferenceError); | 
|  | 213 } | 
|  | 214 TestWithEval(); | 
|  | 215 | 
|  | 216 | 
|  | 217 function TestHoisting() { | 
|  | 218   (do { var a = 1; }); | 
|  | 219   assertEquals(a, 1); | 
|  | 220   assertEquals(global.a, undefined); | 
|  | 221 | 
|  | 222   (do { | 
|  | 223     for (let it of [1, 2, 3, 4, 5]) { | 
|  | 224       var b = it; | 
|  | 225     } | 
|  | 226   }); | 
|  | 227   assertEquals(b, 5); | 
|  | 228   assertEquals(global.b, undefined); | 
|  | 229 | 
|  | 230   { | 
|  | 231     let x = 1 | 
|  | 232 | 
|  | 233     // TODO(caitp): ensure VariableStatements in |do-expressions| in parameter | 
|  | 234     // initializers, are evaluated in the same VariableEnvironment as they would | 
|  | 235     // be for eval(). | 
|  | 236     // function f1(a = do { var x = 2 }, b = x) { return b } | 
|  | 237     // assertEquals(1, f1()) | 
|  | 238 | 
|  | 239     // function f2(a = x, b = do { var x = 2 }) { return a } | 
|  | 240     // assertEquals(1, f2()) | 
|  | 241 | 
|  | 242     function f3({a = do { var x = 2 }, b = x}) { return b } | 
|  | 243     assertEquals(2, f3({})) | 
|  | 244 | 
|  | 245     function f4({a = x, b = do { var x = 2 }}) { return b } | 
|  | 246     assertEquals(undefined, f4({})) | 
|  | 247 | 
|  | 248     function f5(a = do { var y = 0 }) {} | 
|  | 249     assertThrows(() => y, ReferenceError) | 
|  | 250   } | 
|  | 251 | 
|  | 252   // TODO(caitp): Always block-scope function declarations in |do| expressions | 
|  | 253   //(do { | 
|  | 254   //  assertEquals(true, inner_func()); | 
|  | 255   //  function inner_func() { return true; } | 
|  | 256   //}); | 
|  | 257   //assertThrows(function() { return innerFunc(); }, ReferenceError); | 
|  | 258 } | 
|  | 259 TestHoisting(); | 
|  | 260 | 
|  | 261 | 
|  | 262 function TestOSR() { | 
|  | 263   var numbers = do { | 
|  | 264     let nums = []; | 
|  | 265     for (let i = 0; i < 1000; ++i) { | 
|  | 266       let value = (Math.random() * 100) | 0; | 
|  | 267       nums.push(value === 0 ? 1 : value), nums; | 
|  | 268     } | 
|  | 269   }; | 
|  | 270   assertEquals(numbers.length, 1000); | 
|  | 271 } | 
|  | 272 | 
|  | 273 for (var i = 0; i < 64; ++i) TestOSR(); | 
| OLD | NEW | 
|---|