// Copyright 2016 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: --harmony-function-tostring var prefix = "/*before*/"; var suffix = "/*after*/"; function checkStringRepresentation(f, source) { assertEquals(typeof f, "function"); assertEquals(source, f.toString()); } function testDeclaration(source) { // this eval should define a local variable f that is a function eval(prefix + source + suffix); checkStringRepresentation(f, source); } testDeclaration( "function f(){}"); testDeclaration( "function*f(){}"); testDeclaration("async function f(){}"); testDeclaration( "function/*A*/ f/*B*/(/*C*/a/*D*/,/*E*/b/*G*/)/*H*/{/*I*/}"); testDeclaration( "function/*A*/*f/*B*/(/*C*/a/*D*/,/*E*/b/*G*/)/*H*/{/*I*/}"); testDeclaration("async/*Z*/function/*A*/ f/*B*/(/*C*/a/*D*/,/*E*/b/*G*/)/*H*/{/*I*/}"); testDeclaration( "function \t f \n ( \r a \r\n,\n\r b ) {'\u2654'}"); testDeclaration( "function \t *f \n ( \r a \r\n,\n\r b ) { }"); testDeclaration( "function *\t f \n ( \r a \r\n,\n\r b ) { }"); testDeclaration("async \t function f \n ( \r a \r\n,\n\r b ) { }"); function testExpression(source) { // this eval should return a function var f = eval("(" + prefix + source + suffix + ")"); checkStringRepresentation(f, source); } testExpression( "function (){}"); testExpression( "function f(){}"); testExpression( "function* (){}"); testExpression( "function*f(){}"); testExpression("async function (){}"); testExpression("async function f(){}"); testExpression( "function/*A*/ /*B*/(/*C*/a/*D*/,/*E*/b/*G*/)/*H*/{/*I*/}"); testExpression( "function/*A*/ f/*B*/(/*C*/a/*D*/,/*E*/b/*G*/)/*H*/{/*I*/}"); testExpression( "function/*A*/* /*B*/(/*C*/a/*D*/,/*E*/b/*G*/)/*H*/{/*I*/}"); testExpression( "function/*A*/*f/*B*/(/*C*/a/*D*/,/*E*/b/*G*/)/*H*/{/*I*/}"); testExpression("async/*Z*/function/*A*/ f/*B*/(/*C*/a/*D*/,/*E*/b/*G*/)/*H*/{/*I*/}"); testExpression( "function \t \n ( \r a \r\n,\n\r b ) { }"); testExpression( "function \t f \n ( \r a \r\n,\n\r b ) { }"); testExpression( "function \t * \n ( \r a \r\n,\n\r b ) { }"); testExpression( "function \t *f \n ( \r a \r\n,\n\r b ) { }"); testExpression( "function *\t \n ( \r a \r\n,\n\r b ) { }"); testExpression( "function *\t f \n ( \r a \r\n,\n\r b ) { }"); testExpression("async \t function \n ( \r a \r\n,\n\r b ) { }"); testExpression( "(/*A*/ /*B*/ /*C*/ /*D*/ /*E*/ /*F*/)/*G*/=>/*H*/0"); testExpression( "a/*B*/ /*C*/ /*D*/ /*E*/ /*F*/ /*G*/=>/*H*/{}"); testExpression( "(/*A*/a/*B*/ /*C*/ /*D*/ /*E*/ /*F*/)/*G*/=>/*H*/0"); testExpression( "(/*A*/a/*B*/,/*C*/b/*D*/,/*E*/c/*F*/)/*G*/=>/*H*/{}"); testExpression("async (/*A*/ /*B*/ /*C*/ /*D*/ /*E*/ /*F*/)/*G*/=>/*H*/0"); testExpression("async a/*B*/ /*C*/ /*D*/ /*E*/ /*F*/ /*G*/=>/*H*/{}"); testExpression("async (/*A*/a/*B*/ /*C*/ /*D*/ /*E*/ /*F*/)/*G*/=>/*H*/0"); testExpression("async (/*A*/a/*B*/,/*C*/b/*D*/,/*E*/c/*F*/)/*G*/=>/*H*/{}"); function testSimpleMethod(source) { // the source should define a method f // object method var f = eval("({" + prefix + source + suffix + "}.f)"); checkStringRepresentation(f, source); // nonstatic class method var f = eval("new class{" + prefix + source + suffix + "}().f"); checkStringRepresentation(f, source); // static class method var f = eval("(class{static" + prefix + source + suffix + "}).f"); checkStringRepresentation(f, source); } testSimpleMethod("f(){}"); testSimpleMethod("*f(){}"); testSimpleMethod("async f(){}"); testSimpleMethod("f \t (){}"); testSimpleMethod("* \tf(){}"); testSimpleMethod("async \t f (){}"); function testAccessorMethod(source, getOrSet) { // the source should define a getter or setter method // object method var f = Object.getOwnPropertyDescriptor(eval("({" + prefix + source + suffix + "})"), "f")[getOrSet]; checkStringRepresentation(f, source); // nonstatic class method var f = Object.getOwnPropertyDescriptor(eval("(class{" + prefix + source + suffix + "})").prototype, "f")[getOrSet]; // static class method var f = Object.getOwnPropertyDescriptor(eval("(class{static" + prefix + source + suffix + "})"), "f")[getOrSet]; checkStringRepresentation(f, source); } testAccessorMethod("get f( ){}", "get"); testAccessorMethod("set f(a){}", "set"); testAccessorMethod("get/*A*/f/*B*/(/*C*/ /*D*/)/*E*/{/*F*/}", "get"); testAccessorMethod("set/*A*/f/*B*/(/*C*/a/*D*/)/*E*/{/*F*/}", "set"); const GeneratorFunction = function*(){}.constructor; const AsyncFunction = async function(){}.constructor; function testDynamicFunction(...args) { var P = args.slice(0, args.length - 1).join(","); var bodyText = args.length > 0 ? args[args.length - 1] : ""; var source = " anonymous(" + P + "\n) {\n" + bodyText + "\n}"; checkStringRepresentation( Function(...args), "function" + source); checkStringRepresentation(GeneratorFunction(...args), "function*" + source); checkStringRepresentation( AsyncFunction(...args), "async function" + source); } testDynamicFunction(); testDynamicFunction(";"); testDynamicFunction("return"); testDynamicFunction("a", "return a"); testDynamicFunction("a", "b", "return a"); testDynamicFunction("a, b", "return a"); testDynamicFunction("a,/*A*/b", "return a"); testDynamicFunction("/*A*/a,b", "return a"); testDynamicFunction("a,b", "return a/*A*/");