Index: test/mjsunit/harmony/function-tostring.js |
diff --git a/test/mjsunit/harmony/function-tostring.js b/test/mjsunit/harmony/function-tostring.js |
new file mode 100644 |
index 0000000000000000000000000000000000000000..949ac2282f8314eaa3bf1fa0abb27e18d189529b |
--- /dev/null |
+++ b/test/mjsunit/harmony/function-tostring.js |
@@ -0,0 +1,124 @@ |
+// 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*/"); |