output of toString() of Generator is wrong
authoryusukesuzuki@slowstart.org <yusukesuzuki@slowstart.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 30 Aug 2018 19:05:34 +0000 (19:05 +0000)
committeryusukesuzuki@slowstart.org <yusukesuzuki@slowstart.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 30 Aug 2018 19:05:34 +0000 (19:05 +0000)
https://bugs.webkit.org/show_bug.cgi?id=188952

Reviewed by Saam Barati.

JSTests:

* stress/function-to-string.js: Added.
(shouldBe):
(shouldBe.test):
(test):
(shouldBe.async.test):
(async.test):
(shouldBe.async):
(async):
* test262/expectations.yaml:

Source/JavaScriptCore:

Function#toString does not respect generator and async generator.
This patch fixes them and supports all the function types.

* runtime/FunctionPrototype.cpp:
(JSC::functionProtoFuncToString):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@235514 268f45cc-cd09-0410-ab3c-d52691b4dbfc

JSTests/ChangeLog
JSTests/stress/function-to-string.js [new file with mode: 0644]
JSTests/test262/expectations.yaml
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/runtime/FunctionPrototype.cpp

index e040c19..686d90a 100644 (file)
@@ -1,3 +1,20 @@
+2018-08-30  Yusuke Suzuki  <yusukesuzuki@slowstart.org>
+
+        output of toString() of Generator is wrong
+        https://bugs.webkit.org/show_bug.cgi?id=188952
+
+        Reviewed by Saam Barati.
+
+        * stress/function-to-string.js: Added.
+        (shouldBe):
+        (shouldBe.test):
+        (test):
+        (shouldBe.async.test):
+        (async.test):
+        (shouldBe.async):
+        (async):
+        * test262/expectations.yaml:
+
 2018-08-29  Mark Lam  <mark.lam@apple.com>
 
         Add some missing exception checks in JSRopeString::resolveRopeToAtomicString().
diff --git a/JSTests/stress/function-to-string.js b/JSTests/stress/function-to-string.js
new file mode 100644 (file)
index 0000000..2f96a11
--- /dev/null
@@ -0,0 +1,11 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+shouldBe((function test() { }).toString(), `function test() { }`);
+shouldBe((() => { }).toString(), `() => { }`);
+shouldBe((function* test() { }).toString(), `function* test() { }`);
+shouldBe((async function* test() { }).toString(), `async function* test() { }`);
+shouldBe((async function test() { }).toString(), `async function test() { }`);
+shouldBe((async () => { }).toString(), `async () => { }`);
index 2d4a0a3..875f52d 100644 (file)
@@ -909,8 +909,8 @@ test/built-ins/Function/prototype/toString/GeneratorFunction.js:
   default: "SyntaxError: Unexpected token '}'. Expected a ')' or a ',' after a parameter declaration."
   strict mode: "SyntaxError: Unexpected token '}'. Expected a ')' or a ',' after a parameter declaration."
 test/built-ins/Function/prototype/toString/async-arrow-function.js:
-  default: "Test262Error: Conforms to NativeFunction Syntax: 'async function ( /* b */ a /* c */ , /* d */ b /* e */ ) /* f */ => /* g */ { /* h */ ; /* i */ }'.(async /* a */ ( /* b */ a /* c */ , /* d */ b /* e */ ) /* f */ => /* g */ { /* h */ ; /* i */ })"
-  strict mode: "Test262Error: Conforms to NativeFunction Syntax: 'async function ( /* b */ a /* c */ , /* d */ b /* e */ ) /* f */ => /* g */ { /* h */ ; /* i */ }'.(async /* a */ ( /* b */ a /* c */ , /* d */ b /* e */ ) /* f */ => /* g */ { /* h */ ; /* i */ })"
+  default: "Test262Error: Conforms to NativeFunction Syntax: 'async ( /* b */ a /* c */ , /* d */ b /* e */ ) /* f */ => /* g */ { /* h */ ; /* i */ }'.(async /* a */ ( /* b */ a /* c */ , /* d */ b /* e */ ) /* f */ => /* g */ { /* h */ ; /* i */ })"
+  strict mode: "Test262Error: Conforms to NativeFunction Syntax: 'async ( /* b */ a /* c */ , /* d */ b /* e */ ) /* f */ => /* g */ { /* h */ ; /* i */ }'.(async /* a */ ( /* b */ a /* c */ , /* d */ b /* e */ ) /* f */ => /* g */ { /* h */ ; /* i */ })"
 test/built-ins/Function/prototype/toString/async-function-declaration.js:
   default: "Test262Error: Conforms to NativeFunction Syntax: 'async function f( /* c */ x /* d */ , /* e */ y /* f */ ) /* g */ { /* h */ ; /* i */ ; /* j */ }'.(async function /* a */ f /* b */ ( /* c */ x /* d */ , /* e */ y /* f */ ) /* g */ { /* h */ ; /* i */ ; /* j */ })"
   strict mode: "Test262Error: Conforms to NativeFunction Syntax: 'async function f( /* c */ x /* d */ , /* e */ y /* f */ ) /* g */ { /* h */ ; /* i */ ; /* j */ }'.(async function /* a */ f /* b */ ( /* c */ x /* d */ , /* e */ y /* f */ ) /* g */ { /* h */ ; /* i */ ; /* j */ })"
@@ -942,14 +942,14 @@ test/built-ins/Function/prototype/toString/function-expression.js:
   default: "Test262Error: Conforms to NativeFunction Syntax: 'function F( /* c */ x /* d */ , /* e */ y /* f */ ) /* g */ { /* h */ ; /* i */ ; /* j */ }'.(function /* a */ F /* b */ ( /* c */ x /* d */ , /* e */ y /* f */ ) /* g */ { /* h */ ; /* i */ ; /* j */ })"
   strict mode: "Test262Error: Conforms to NativeFunction Syntax: 'function F( /* c */ x /* d */ , /* e */ y /* f */ ) /* g */ { /* h */ ; /* i */ ; /* j */ }'.(function /* a */ F /* b */ ( /* c */ x /* d */ , /* e */ y /* f */ ) /* g */ { /* h */ ; /* i */ ; /* j */ })"
 test/built-ins/Function/prototype/toString/generator-function-declaration.js:
-  default: "Test262Error: Conforms to NativeFunction Syntax: 'function g( /* d */ x /* e */ , /* f */ y /* g */ ) /* h */ { /* i */ ; /* j */ ; /* k */ }'.(function /* a */ * /* b */ g /* c */ ( /* d */ x /* e */ , /* f */ y /* g */ ) /* h */ { /* i */ ; /* j */ ; /* k */ })"
-  strict mode: "Test262Error: Conforms to NativeFunction Syntax: 'function g( /* d */ x /* e */ , /* f */ y /* g */ ) /* h */ { /* i */ ; /* j */ ; /* k */ }'.(function /* a */ * /* b */ g /* c */ ( /* d */ x /* e */ , /* f */ y /* g */ ) /* h */ { /* i */ ; /* j */ ; /* k */ })"
+  default: "Test262Error: Conforms to NativeFunction Syntax: 'function* g( /* d */ x /* e */ , /* f */ y /* g */ ) /* h */ { /* i */ ; /* j */ ; /* k */ }'.(function /* a */ * /* b */ g /* c */ ( /* d */ x /* e */ , /* f */ y /* g */ ) /* h */ { /* i */ ; /* j */ ; /* k */ })"
+  strict mode: "Test262Error: Conforms to NativeFunction Syntax: 'function* g( /* d */ x /* e */ , /* f */ y /* g */ ) /* h */ { /* i */ ; /* j */ ; /* k */ }'.(function /* a */ * /* b */ g /* c */ ( /* d */ x /* e */ , /* f */ y /* g */ ) /* h */ { /* i */ ; /* j */ ; /* k */ })"
 test/built-ins/Function/prototype/toString/generator-function-expression.js:
-  default: "Test262Error: Conforms to NativeFunction Syntax: 'function F( /* d */ x /* e */ , /* f */ y /* g */ ) /* h */ { /* i */ ; /* j */ ; /* k */ }'.(function /* a */ * /* b */ F /* c */ ( /* d */ x /* e */ , /* f */ y /* g */ ) /* h */ { /* i */ ; /* j */ ; /* k */ })"
-  strict mode: "Test262Error: Conforms to NativeFunction Syntax: 'function F( /* d */ x /* e */ , /* f */ y /* g */ ) /* h */ { /* i */ ; /* j */ ; /* k */ }'.(function /* a */ * /* b */ F /* c */ ( /* d */ x /* e */ , /* f */ y /* g */ ) /* h */ { /* i */ ; /* j */ ; /* k */ })"
+  default: "Test262Error: Conforms to NativeFunction Syntax: 'function* F( /* d */ x /* e */ , /* f */ y /* g */ ) /* h */ { /* i */ ; /* j */ ; /* k */ }'.(function /* a */ * /* b */ F /* c */ ( /* d */ x /* e */ , /* f */ y /* g */ ) /* h */ { /* i */ ; /* j */ ; /* k */ })"
+  strict mode: "Test262Error: Conforms to NativeFunction Syntax: 'function* F( /* d */ x /* e */ , /* f */ y /* g */ ) /* h */ { /* i */ ; /* j */ ; /* k */ }'.(function /* a */ * /* b */ F /* c */ ( /* d */ x /* e */ , /* f */ y /* g */ ) /* h */ { /* i */ ; /* j */ ; /* k */ })"
 test/built-ins/Function/prototype/toString/generator-method.js:
-  default: "Test262Error: Conforms to NativeFunction Syntax: 'function f( /* c */ ) /* d */ { /* e */ }'.(* /* a */ f /* b */ ( /* c */ ) /* d */ { /* e */ })"
-  strict mode: "Test262Error: Conforms to NativeFunction Syntax: 'function f( /* c */ ) /* d */ { /* e */ }'.(* /* a */ f /* b */ ( /* c */ ) /* d */ { /* e */ })"
+  default: "Test262Error: Conforms to NativeFunction Syntax: 'function* f( /* c */ ) /* d */ { /* e */ }'.(* /* a */ f /* b */ ( /* c */ ) /* d */ { /* e */ })"
+  strict mode: "Test262Error: Conforms to NativeFunction Syntax: 'function* f( /* c */ ) /* d */ { /* e */ }'.(* /* a */ f /* b */ ( /* c */ ) /* d */ { /* e */ })"
 test/built-ins/Function/prototype/toString/getter-class-expression-static.js:
   default: "Test262Error: Conforms to NativeFunction Syntax: 'function ( /* c */ ) /* d */ { /* e */ }'.(get /* a */ f /* b */ ( /* c */ ) /* d */ { /* e */ })"
   strict mode: "Test262Error: Conforms to NativeFunction Syntax: 'function ( /* c */ ) /* d */ { /* e */ }'.(get /* a */ f /* b */ ( /* c */ ) /* d */ { /* e */ })"
index 724ed19..bc52e6f 100644 (file)
@@ -1,3 +1,16 @@
+2018-08-30  Yusuke Suzuki  <yusukesuzuki@slowstart.org>
+
+        output of toString() of Generator is wrong
+        https://bugs.webkit.org/show_bug.cgi?id=188952
+
+        Reviewed by Saam Barati.
+
+        Function#toString does not respect generator and async generator.
+        This patch fixes them and supports all the function types.
+
+        * runtime/FunctionPrototype.cpp:
+        (JSC::functionProtoFuncToString):
+
 2018-08-29  Mark Lam  <mark.lam@apple.com>
 
         Add some missing exception checks in JSRopeString::resolveRopeToAtomicString().
index 3e0407a..8fc3013 100644 (file)
@@ -98,18 +98,46 @@ EncodedJSValue JSC_HOST_CALL functionProtoFuncToString(ExecState* exec)
             return JSValue::encode(jsString(exec, classSource.toStringWithoutCopying()));
         }
 
-        if (thisValue.inherits<JSAsyncFunction>(vm)) {
-            String functionHeader = executable->isArrowFunction() ? "async " : "async function ";
-
-            StringView source = executable->source().provider()->getRange(
-                executable->parametersStartOffset(),
-                executable->parametersStartOffset() + executable->source().length());
-            scope.release();
-            return JSValue::encode(jsMakeNontrivialString(exec, functionHeader, function->name(vm), source));
+        String functionHeader;
+        switch (executable->parseMode()) {
+        case SourceParseMode::GeneratorWrapperFunctionMode:
+        case SourceParseMode::GeneratorWrapperMethodMode:
+            functionHeader = "function* ";
+            break;
+
+        case SourceParseMode::NormalFunctionMode:
+        case SourceParseMode::GetterMode:
+        case SourceParseMode::SetterMode:
+        case SourceParseMode::MethodMode:
+        case SourceParseMode::ProgramMode:
+        case SourceParseMode::ModuleAnalyzeMode:
+        case SourceParseMode::ModuleEvaluateMode:
+        case SourceParseMode::GeneratorBodyMode:
+        case SourceParseMode::AsyncGeneratorBodyMode:
+        case SourceParseMode::AsyncFunctionBodyMode:
+        case SourceParseMode::AsyncArrowFunctionBodyMode:
+            functionHeader = "function ";
+            break;
+
+        case SourceParseMode::ArrowFunctionMode:
+            functionHeader = "";
+            break;
+
+        case SourceParseMode::AsyncFunctionMode:
+        case SourceParseMode::AsyncMethodMode:
+            functionHeader = "async function ";
+            break;
+
+        case SourceParseMode::AsyncArrowFunctionMode:
+            functionHeader = "async ";
+            break;
+
+        case SourceParseMode::AsyncGeneratorWrapperFunctionMode:
+        case SourceParseMode::AsyncGeneratorWrapperMethodMode:
+            functionHeader = "async function* ";
+            break;
         }
 
-        String functionHeader = executable->isArrowFunction() ? "" : "function ";
-        
         StringView source = executable->source().provider()->getRange(
             executable->parametersStartOffset(),
             executable->parametersStartOffset() + executable->source().length());