| // Copyright 2017 the V8 project authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | // Flags: --preparser-scope-analysis --enable-slow-asserts | 
 |  | 
 | (function TestBasicSkipping() { | 
 |   var result = 0; | 
 |  | 
 |   function lazy(ctxt_alloc_param) { | 
 |     var ctxt_alloc_var = 10; | 
 |     function skip_me() { | 
 |       result = ctxt_alloc_param + ctxt_alloc_var; | 
 |     } | 
 |     return skip_me; | 
 |   } | 
 |   // Test that parameters and variables of the outer function get context | 
 |   // allocated even if we skip the inner function. | 
 |   lazy(9)(); | 
 |   assertEquals(19, result); | 
 | })(); | 
 |  | 
 | (function TestSkippingFunctionWithEval() { | 
 |   var result = 0; | 
 |  | 
 |   function lazy(ctxt_alloc_param) { | 
 |     var ctxt_alloc_var = 10; | 
 |     function skip_me() { | 
 |       eval('result = ctxt_alloc_param + ctxt_alloc_var'); | 
 |     } | 
 |     return skip_me; | 
 |   } | 
 |   // Test that parameters and variables of the outer function get context | 
 |   // allocated even if we skip the inner function. | 
 |   lazy(9)(); | 
 |   assertEquals(19, result); | 
 | })(); | 
 |  | 
 | (function TestCtxtAllocatingNonSimpleParams1() { | 
 |   var result = 0; | 
 |  | 
 |   function lazy([other_param1, ctxt_alloc_param, other_param2]) { | 
 |     function skip_me() { | 
 |       result = ctxt_alloc_param; | 
 |     } | 
 |     return skip_me; | 
 |   } | 
 |   // Test that parameters and variables of the outer function get context | 
 |   // allocated even if we skip the inner function. | 
 |   lazy([30, 29, 28])(); | 
 |   assertEquals(29, result); | 
 | })(); | 
 |  | 
 | (function TestCtxtAllocatingNonSimpleParams2() { | 
 |   var result = 0; | 
 |  | 
 |   function lazy({a: other_param1, b: ctxt_alloc_param, c: other_param2}) { | 
 |     function skip_me() { | 
 |       result = ctxt_alloc_param; | 
 |     } | 
 |     return skip_me; | 
 |   } | 
 |   // Test that parameters and variables of the outer function get context | 
 |   // allocated even if we skip the inner function. | 
 |   lazy({a: 31, b: 32, c: 33})(); | 
 |   assertEquals(32, result); | 
 | })(); | 
 |  | 
 | (function TestCtxtAllocatingNonSimpleParams3() { | 
 |   var result = 0; | 
 |  | 
 |   function lazy(...ctxt_alloc_param) { | 
 |     function skip_me() { | 
 |       result = ctxt_alloc_param; | 
 |     } | 
 |     return skip_me; | 
 |   } | 
 |   // Test that parameters and variables of the outer function get context | 
 |   // allocated even if we skip the inner function. | 
 |   lazy(34, 35)(); | 
 |   assertEquals([34, 35], result); | 
 | })(); | 
 |  | 
 | // Skippable top level functions. | 
 | var result = 0; | 
 | function lazy_top_level(ctxt_alloc_param) { | 
 |   let ctxt_alloc_var = 24; | 
 |   function skip_me() { | 
 |     result = ctxt_alloc_param + ctxt_alloc_var; | 
 |   } | 
 |   skip_me(); | 
 | } | 
 |  | 
 | lazy_top_level(10); | 
 | assertEquals(34, result); | 
 |  | 
 | // Tests for using a function name in an inner function. | 
 | var TestUsingNamedExpressionName1 = function this_is_the_name() { | 
 |   function inner() { | 
 |     this_is_the_name; | 
 |   } | 
 |   inner(); | 
 | } | 
 | TestUsingNamedExpressionName1(); | 
 |  | 
 | function TestUsingNamedExpressionName2() { | 
 |   let f = function this_is_the_name() { | 
 |     function inner() { | 
 |       this_is_the_name; | 
 |     } | 
 |     inner(); | 
 |   } | 
 |   f(); | 
 | } | 
 | TestUsingNamedExpressionName2(); | 
 |  | 
 | function TestSkippedFunctionInsideLoopInitializer() { | 
 |   let saved_func; | 
 |   for (let i = 0, f = function() { return i }; i < 1; ++i) { | 
 |     saved_func = f; | 
 |   } | 
 |   assertEquals(0, saved_func()); | 
 | } | 
 | TestSkippedFunctionInsideLoopInitializer(); | 
 |  | 
 | (function TestSkippedFunctionWithParameters() { | 
 |   var result = 0; | 
 |  | 
 |   function lazy(ctxt_alloc_param) { | 
 |     var ctxt_alloc_var = 10; | 
 |     function skip_me(param1, param2) { | 
 |       result = ctxt_alloc_param + ctxt_alloc_var + param1 + param2; | 
 |     } | 
 |     return skip_me; | 
 |   } | 
 |   lazy(9)(8, 7); | 
 |   assertEquals(34, result); | 
 | })(); | 
 |  | 
 | function TestSkippingDeeperLazyFunctions() { | 
 |   let result = 0; | 
 |   function inner_lazy(ctxt_alloc_param) { | 
 |     let ctxt_alloc_var = 13; | 
 |     function skip_me() { | 
 |       result = ctxt_alloc_param + ctxt_alloc_var; | 
 |     } | 
 |     return skip_me; | 
 |   } | 
 |   let f = inner_lazy(12); | 
 |   f(); | 
 |   assertEquals(25, result); | 
 | } | 
 |  | 
 | TestSkippingDeeperLazyFunctions(); | 
 |  | 
 | function TestEagerFunctionsBetweenLazyFunctions() { | 
 |   let result = 0; | 
 |   // We produce one data set for TestEagerFunctionsBetweenLazyFunctions and | 
 |   // another one for inner. The variable data for eager belongs to the former | 
 |   // data set. | 
 |   let ctxt_allocated1 = 3; | 
 |   (function eager() { | 
 |     let ctxt_allocated2 = 4; | 
 |     function inner() { | 
 |       result = ctxt_allocated1 + ctxt_allocated2; | 
 |     } | 
 |     return inner; | 
 |   })()(); | 
 |   assertEquals(7, result); | 
 | } | 
 |  | 
 | TestEagerFunctionsBetweenLazyFunctions(); | 
 |  | 
 | function TestEagerNotIifeFunctionsBetweenLazyFunctions() { | 
 |   let result = 0; | 
 |   // We produce one data set for TestEagerFunctionsBetweenLazyFunctions and | 
 |   // another one for inner. The variable data for eager belongs to the former | 
 |   // data set. | 
 |   let ctxt_allocated1 = 3; | 
 |   (function eager_not_iife() { | 
 |     let ctxt_allocated2 = 4; | 
 |     function inner() { | 
 |       result = ctxt_allocated1 + ctxt_allocated2; | 
 |     } | 
 |     return inner; | 
 |   }); // Function not called; not an iife. | 
 |   // This is just a regression test. We cannot test that the context allocation | 
 |   // was done correctly (since there's no way to call eager_not_iife), but code | 
 |   // like this used to trigger some DCHECKs. | 
 | } | 
 |  | 
 | TestEagerNotIifeFunctionsBetweenLazyFunctions(); | 
 |  | 
 | // Regression test for functions inside a lazy arrow function. (Only top-level | 
 | // arrow functions are lazy, so this cannot be wrapped in a function.) | 
 | result = 0; | 
 | let f1 = (ctxt_alloc_param) => { | 
 |   let ctxt_alloc_var = 10; | 
 |   function inner() { | 
 |     result = ctxt_alloc_param + ctxt_alloc_var; | 
 |   } | 
 |   return inner; | 
 | } | 
 | f1(9)(); | 
 | assertEquals(19, result); | 
 |  | 
 | function TestStrictEvalInParams() { | 
 |   "use strict"; | 
 |   var result = 0; | 
 |  | 
 |   function lazy(a = function() { return 2; }, b = eval('3')) { | 
 |     function skip_me() { | 
 |       result = a() + b; | 
 |     } | 
 |     return skip_me; | 
 |   } | 
 |   lazy()(); | 
 |   assertEquals(5, result); | 
 |  | 
 |   function not_skippable_either() {} | 
 | } | 
 |  | 
 | TestStrictEvalInParams(); | 
 |  | 
 | function TestSloppyEvalInFunctionWithComplexParams() { | 
 |   var result = 0; | 
 |  | 
 |   function lazy1(ctxt_alloc_param = 2) { | 
 |     var ctxt_alloc_var = 3; | 
 |     function skip_me() { | 
 |       result = ctxt_alloc_param + ctxt_alloc_var; | 
 |     } | 
 |     eval(''); | 
 |     return skip_me; | 
 |   } | 
 |   lazy1()(); | 
 |   assertEquals(5, result); | 
 |  | 
 |   function lazy2(ctxt_alloc_param = 4) { | 
 |     var ctxt_alloc_var = 5; | 
 |     function skip_me() { | 
 |       eval('result = ctxt_alloc_param + ctxt_alloc_var;'); | 
 |     } | 
 |     return skip_me; | 
 |   } | 
 |   lazy2()(); | 
 |   assertEquals(9, result); | 
 | } | 
 |  | 
 | TestSloppyEvalInFunctionWithComplexParams(); | 
 |  | 
 | function TestSkippableFunctionInForOfHeader() { | 
 |   var c; | 
 |   function inner() { | 
 |     for (let [a, b = c = function() { return a; }] of [[10]]) { | 
 |     } | 
 |   } | 
 |   inner(); | 
 |   var result = c(); | 
 |   assertEquals(10, result); | 
 | } | 
 |  | 
 | TestSkippableFunctionInForOfHeader(); | 
 |  | 
 | function TestSkippableFunctionInForOfBody() { | 
 |   var c; | 
 |   function inner() { | 
 |     for (let [a, b] of [[10, 11]]) { | 
 |       c = function f() { | 
 |         return a + b; | 
 |       } | 
 |     } | 
 |   } | 
 |   inner(); | 
 |   var result = c(); | 
 |   assertEquals(21, result); | 
 | } | 
 |  | 
 | TestSkippableFunctionInForOfBody(); | 
 |  | 
 |  | 
 | function TestSkippableFunctionInForOfHeaderAndBody() { | 
 |   var c1; | 
 |   var c2; | 
 |   function inner() { | 
 |     for (let [a, b = c1 = function() { return a; }] of [[10]]) { | 
 |       c2 = function f() { | 
 |         return a + 1; | 
 |       } | 
 |     } | 
 |   } | 
 |   inner(); | 
 |   var result = c1() + c2(); | 
 |   assertEquals(21, result); | 
 | } | 
 |  | 
 | TestSkippableFunctionInForOfHeaderAndBody(); | 
 |  | 
 | (function TestSkippableGeneratorInSloppyBlock() { | 
 |   var result = 0; | 
 |  | 
 |   function lazy(ctxt_alloc_param) { | 
 |     var ctxt_alloc_var = 10; | 
 |     { | 
 |       function *skip_me() { | 
 |         result = ctxt_alloc_param + ctxt_alloc_var; | 
 |         yield 3; | 
 |       } | 
 |       return skip_me; | 
 |     } | 
 |   } | 
 |   // Test that parameters and variables of the outer function get context | 
 |   // allocated even if we skip the inner function. | 
 |   assertEquals(3, lazy(9)().next().value); | 
 |   assertEquals(19, result); | 
 | })(); | 
 |  | 
 | (function TestRestoringDataToAsyncArrowFunctionWithNonSimpleParams_1() { | 
 |   // Regression test for | 
 |   // https://bugs.chromium.org/p/chromium/issues/detail?id=765532 | 
 |   function lazy() { | 
 |     // The arrow function is not skippable, but we need to traverse its scopes | 
 |     // and restore data to them. | 
 |     async(a=0) => { const d = 0; } | 
 |     function skippable() {} | 
 |   } | 
 |   lazy(); | 
 | })(); | 
 |  | 
 | (function TestRestoringDataToAsyncArrowFunctionWithNonSimpleParams_2() { | 
 |   // Regression test for | 
 |   // https://bugs.chromium.org/p/chromium/issues/detail?id=765532 | 
 |   function lazy() { | 
 |     // The arrow function is not skippable, but we need to traverse its scopes | 
 |     // and restore data to them. | 
 |     async(...a) => { const d = 0; } | 
 |     function skippable() {} | 
 |   } | 
 |   lazy(); | 
 | })(); | 
 |  | 
 | (function TestSloppyBlockFunctionShadowingCatchVariable() { | 
 |   // Regression test for | 
 |   // https://bugs.chromium.org/p/chromium/issues/detail?id=771474 | 
 |   function lazy() { | 
 |     try { | 
 |     } catch (my_var) { | 
 |       if (false) { | 
 |         function my_var() { } | 
 |       } | 
 |     } | 
 |   } | 
 |   lazy(); | 
 | })(); | 
 |  | 
 |  | 
 | (function TestLazinessDecisionWithDefaultConstructors() { | 
 |   // Regression test for | 
 |   // https://bugs.chromium.org/p/chromium/issues/detail?id=773576 | 
 |  | 
 |   // The problem was that Parser and PreParser treated default constructors | 
 |   // differently, and that threw off the "next / previous function is likely | 
 |   // called" logic. | 
 |  | 
 |   function lazy(p = (function() {}, class {}, function() {}, class { method1() { } })) { } | 
 |   lazy(); | 
 | })(); | 
 |  | 
 | (function TestOneByteTwoByteMismatch() { | 
 |   // Regression test for | 
 |   // https://bugs.chromium.org/p/v8/issues/detail?id=7428 | 
 |  | 
 |   let name = 'weird_string\u2653'.slice(0, 12); | 
 |   let o = {}; | 
 |   o[name] = null; | 
 |   var x; | 
 |   eval('x = function weird_string() { function skip() {} };'); | 
 |   x(); | 
 | })(); |