mirror of
				https://github.com/tc39/test262.git
				synced 2025-11-04 05:33:50 +01:00 
			
		
		
		
	sourceRevisionAtLastExport: 33f2fb0e53d135f0ee17cfccd9d993eb2a6f47de targetRevisionAtLastExport: 31340cbd9add103f586d501b0c3354b7b182abc0
		
			
				
	
	
		
			380 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			380 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
// 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();
 | 
						|
})();
 |