mirror of
				https://github.com/tc39/test262.git
				synced 2025-10-31 03:34:08 +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);
 |