mirror of
				https://github.com/tc39/test262.git
				synced 2025-11-04 13:44:29 +01:00 
			
		
		
		
	sourceRevisionAtLastExport: 33f2fb0e53d135f0ee17cfccd9d993eb2a6f47de targetRevisionAtLastExport: 31340cbd9add103f586d501b0c3354b7b182abc0
		
			
				
	
	
		
			180 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			180 lines
		
	
	
		
			7.1 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.
 | 
						|
 | 
						|
/*
 | 
						|
- Duplicate parameters are allowed for
 | 
						|
  - non-arrow functions which are not conscise methods *and*
 | 
						|
  - when the parameter list is simple *and*
 | 
						|
  - we're in sloppy mode (incl. the function doesn't declare itself strict).
 | 
						|
*/
 | 
						|
 | 
						|
function assertDuplicateParametersError(code) {
 | 
						|
  caught = false;
 | 
						|
  try {
 | 
						|
    eval(code);
 | 
						|
  } catch(e) {
 | 
						|
    // Assert that it's the duplicate parameters error, and e.g,. not a syntax
 | 
						|
    // error because of a typo in the test.
 | 
						|
    assertTrue(e.message.startsWith("Duplicate parameter name not allowed"));
 | 
						|
    caught = true;
 | 
						|
  } finally {
 | 
						|
    assertTrue(caught);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
FunctionType = {
 | 
						|
  NORMAL : 0,
 | 
						|
  ARROW : 1,
 | 
						|
  METHOD : 2,
 | 
						|
  CONCISE_METHOD : 3,
 | 
						|
};
 | 
						|
 | 
						|
Laziness = {
 | 
						|
  EAGER : 0,
 | 
						|
  LAZY_BOUNDARY : 1,
 | 
						|
  LAZY : 2
 | 
						|
};
 | 
						|
 | 
						|
Strictness = {
 | 
						|
  SLOPPY : 0,
 | 
						|
  STRICT : 1,
 | 
						|
  STRICT_FUNCTION : 2
 | 
						|
};
 | 
						|
 | 
						|
function testHelper(type, strict, lazy, duplicate_params_string, ok) {
 | 
						|
  code = ""
 | 
						|
  strict_inside = "";
 | 
						|
  if (strict == Strictness.STRICT) {
 | 
						|
    code = "'use strict'; ";
 | 
						|
  } else if (strict == Strictness.STRICT_FUNCTION) {
 | 
						|
    strict_inside = "'use strict'; ";
 | 
						|
  } else {
 | 
						|
    assertEquals(strict, Strictness.SLOPPY);
 | 
						|
  }
 | 
						|
 | 
						|
  if (type == FunctionType.NORMAL) {
 | 
						|
    if (lazy == Laziness.EAGER) {
 | 
						|
      code += "(function foo(" + duplicate_params_string + ") { " + strict_inside + "})";
 | 
						|
    } else if (lazy == Laziness.LAZY_BOUNDARY) {
 | 
						|
      code += "function foo(" + duplicate_params_string + ") { " + strict_inside + "}";
 | 
						|
    } else if (lazy == Laziness.LAZY) {
 | 
						|
      code += 'function lazy() { function foo(' + duplicate_params_string +
 | 
						|
          ') { ' + strict_inside + '} }';
 | 
						|
    } else {
 | 
						|
      assertUnreachable();
 | 
						|
    }
 | 
						|
  } else if (type == FunctionType.ARROW) {
 | 
						|
    if (lazy == Laziness.EAGER) {
 | 
						|
      // Force an arrow function to be eager by making its body trivial.
 | 
						|
      assertEquals(strict, Strictness.SLOPPY);
 | 
						|
      code += "(" + duplicate_params_string + ") => 1";
 | 
						|
    } else if (lazy == Laziness.LAZY_BOUNDARY) {
 | 
						|
      // Duplicate parameters in non-simple parameter lists are not recognized
 | 
						|
      // at the laziness boundary, when the lazy function is an arrow
 | 
						|
      // function. Hack around this by calling the function. See
 | 
						|
      // https://bugs.chromium.org/p/v8/issues/detail?id=6108.
 | 
						|
      let simple = /^[a-z, ]*$/.test(duplicate_params_string);
 | 
						|
      if (simple) {
 | 
						|
        code += "(" + duplicate_params_string + ") => { " + strict_inside + "};";
 | 
						|
      } else {
 | 
						|
        code += "let foo = (" + duplicate_params_string + ") => { " + strict_inside + "}; foo();";
 | 
						|
      }
 | 
						|
    } else if (lazy == Laziness.LAZY) {
 | 
						|
      // PreParser cannot detect duplicates in arrow function parameters. When
 | 
						|
      // parsing the parameter list, it doesn't know it's an arrow function
 | 
						|
      // parameter list, so it just discards the identifiers, and cannot do the
 | 
						|
      // check any more when it sees the arrow. Work around this by calling the
 | 
						|
      // function which forces parsing it.
 | 
						|
      code += 'function lazy() { (' + duplicate_params_string + ') => { ' +
 | 
						|
          strict_inside + '} } lazy();';
 | 
						|
    } else {
 | 
						|
      assertUnreachable();
 | 
						|
    }
 | 
						|
  } else if (type == FunctionType.METHOD) {
 | 
						|
    code += "var o = {";
 | 
						|
    if (lazy == Laziness.EAGER) {
 | 
						|
      code += "foo : (function(" + duplicate_params_string + ") { " + strict_inside + "})";
 | 
						|
    } else if (lazy == Laziness.LAZY_BOUNDARY) {
 | 
						|
      code += "foo : function(" + duplicate_params_string + ") { " + strict_inside + "}";
 | 
						|
    } else if (lazy == Laziness.LAZY) {
 | 
						|
      code += 'lazy: function() { function foo(' + duplicate_params_string +
 | 
						|
          ') { ' + strict_inside + '} }';
 | 
						|
    } else {
 | 
						|
      assertUnreachable();
 | 
						|
    }
 | 
						|
    code += "};";
 | 
						|
  } else if (type == FunctionType.CONCISE_METHOD) {
 | 
						|
    if (lazy == Laziness.LAZY_BOUNDARY) {
 | 
						|
      code += "var o = { foo(" + duplicate_params_string + ") { " + strict_inside + "} };";
 | 
						|
    } else if (lazy == Laziness.LAZY) {
 | 
						|
      code += 'function lazy() { var o = { foo(' + duplicate_params_string +
 | 
						|
          ') { ' + strict_inside + '} }; }';
 | 
						|
    } else {
 | 
						|
      assertUnreachable();
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    assertUnreachable();
 | 
						|
  }
 | 
						|
 | 
						|
  if (ok) {
 | 
						|
    assertDoesNotThrow(code);
 | 
						|
  } else {
 | 
						|
    assertDuplicateParametersError(code);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
function test(type, strict, lazy, ok_if_param_list_simple) {
 | 
						|
  // Simple duplicate params.
 | 
						|
  testHelper(type, strict, lazy, "a, dup, dup, b", ok_if_param_list_simple)
 | 
						|
 | 
						|
  if (strict != Strictness.STRICT_FUNCTION) {
 | 
						|
    // Generate test cases where the duplicate parameter occurs because of
 | 
						|
    // destructuring or the rest parameter. That is always an error: duplicate
 | 
						|
    // parameters are only allowed in simple parameter lists. These tests are
 | 
						|
    // not possible if a function declares itself strict, since non-simple
 | 
						|
    // parameters are not allowed then.
 | 
						|
    testHelper(type, strict, lazy, "a, [dup], dup, b", false);
 | 
						|
    testHelper(type, strict, lazy, "a, dup, {b: dup}, c", false);
 | 
						|
    testHelper(type, strict, lazy, "a, {dup}, [dup], b", false);
 | 
						|
    testHelper(type, strict, lazy, "a, dup, ...dup", false);
 | 
						|
    testHelper(type, strict, lazy, "a, dup, dup, ...rest", false);
 | 
						|
    testHelper(type, strict, lazy, "a, dup, dup, b = 1", false);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
// No duplicate parameters allowed for arrow functions even in sloppy mode.
 | 
						|
test(FunctionType.ARROW, Strictness.SLOPPY, Laziness.EAGER, false);
 | 
						|
test(FunctionType.ARROW, Strictness.SLOPPY, Laziness.LAZY_BOUNDARY, false);
 | 
						|
test(FunctionType.ARROW, Strictness.SLOPPY, Laziness.LAZY, false);
 | 
						|
 | 
						|
// Duplicate parameters allowed for normal functions in sloppy mode.
 | 
						|
test(FunctionType.NORMAL, Strictness.SLOPPY, Laziness.EAGER, true);
 | 
						|
test(FunctionType.NORMAL, Strictness.SLOPPY, Laziness.LAZY_BOUNDARY, true);
 | 
						|
test(FunctionType.NORMAL, Strictness.SLOPPY, Laziness.LAZY, true);
 | 
						|
 | 
						|
test(FunctionType.NORMAL, Strictness.STRICT, Laziness.EAGER, false);
 | 
						|
test(FunctionType.NORMAL, Strictness.STRICT, Laziness.LAZY_BOUNDARY, false);
 | 
						|
test(FunctionType.NORMAL, Strictness.STRICT, Laziness.LAZY, false);
 | 
						|
 | 
						|
test(FunctionType.NORMAL, Strictness.STRICT_FUNCTION, Laziness.EAGER, false);
 | 
						|
test(FunctionType.NORMAL, Strictness.STRICT_FUNCTION, Laziness.LAZY_BOUNDARY, false);
 | 
						|
test(FunctionType.NORMAL, Strictness.STRICT_FUNCTION, Laziness.LAZY, false);
 | 
						|
 | 
						|
// No duplicate parameters allowed for conscise methods even in sloppy mode.
 | 
						|
test(FunctionType.CONCISE_METHOD, Strictness.SLOPPY, Laziness.LAZY_BOUNDARY, false);
 | 
						|
test(FunctionType.CONCISE_METHOD, Strictness.SLOPPY, Laziness.LAZY, false);
 | 
						|
 | 
						|
// But non-concise methods follow the rules for normal funcs.
 | 
						|
test(FunctionType.METHOD, Strictness.SLOPPY, Laziness.EAGER, true);
 | 
						|
test(FunctionType.METHOD, Strictness.SLOPPY, Laziness.LAZY_BOUNDARY, true);
 | 
						|
test(FunctionType.METHOD, Strictness.SLOPPY, Laziness.LAZY, true);
 | 
						|
 | 
						|
test(FunctionType.METHOD, Strictness.STRICT, Laziness.EAGER, false);
 | 
						|
test(FunctionType.METHOD, Strictness.STRICT, Laziness.LAZY_BOUNDARY, false);
 | 
						|
test(FunctionType.METHOD, Strictness.STRICT, Laziness.LAZY, false);
 | 
						|
 | 
						|
test(FunctionType.METHOD, Strictness.STRICT_FUNCTION, Laziness.EAGER, false);
 | 
						|
test(FunctionType.METHOD, Strictness.STRICT_FUNCTION, Laziness.LAZY_BOUNDARY, false);
 | 
						|
test(FunctionType.METHOD, Strictness.STRICT_FUNCTION, Laziness.LAZY, false);
 |