Title: [233855] trunk
Revision
233855
Author
[email protected]
Date
2018-07-16 11:49:22 -0700 (Mon, 16 Jul 2018)

Log Message

[JSC] Generator and AsyncGeneratorMethod's prototype is incorrect
https://bugs.webkit.org/show_bug.cgi?id=187585

Reviewed by Darin Adler.

JSTests:

* stress/default-proto-for-async-generator.js: Added.
(shouldBe):
(async.asyncGenerator):
* stress/default-proto-for-generator.js: Added.
(shouldBe):
(generator):
* stress/prototype-for-async-generator.js: Added.
(shouldBe):
(async.asyncGenerator):
(A.prototype.async.asyncGenerator):
(A):
* test262/expectations.yaml:

Source/_javascript_Core:

This patch fixes Generator and AsyncGenerator's prototype issues.

1. Generator's default prototype is incorrect when `generator.prototype = null` is performed.
We fix this by changing JSFunction::prototypeForConstruction.

2. AsyncGeneratorMethod is not handled. We change the name isAsyncGeneratorFunctionParseMode
to isAsyncGeneratorWrapperParseMode since it is aligned to Generator's code. And use it well
to fix `prototype` issues for AsyncGeneratorMethod.

* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::emitPutAsyncGeneratorFields):
(JSC::BytecodeGenerator::emitNewFunction):
* bytecompiler/NodesCodegen.cpp:
(JSC::FunctionNode::emitBytecode):
* parser/ASTBuilder.h:
(JSC::ASTBuilder::createFunctionMetadata):
* parser/Parser.cpp:
(JSC::getAsynFunctionBodyParseMode):
(JSC::Parser<LexerType>::parseInner):
(JSC::Parser<LexerType>::parseAsyncGeneratorFunctionSourceElements):
* parser/ParserModes.h:
(JSC::isAsyncGeneratorParseMode):
(JSC::isAsyncGeneratorWrapperParseMode):
(JSC::isAsyncGeneratorFunctionParseMode): Deleted.
* runtime/FunctionExecutable.h:
* runtime/JSFunction.cpp:
(JSC::JSFunction::prototypeForConstruction):
(JSC::JSFunction::getOwnPropertySlot):

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (233854 => 233855)


--- trunk/JSTests/ChangeLog	2018-07-16 18:42:07 UTC (rev 233854)
+++ trunk/JSTests/ChangeLog	2018-07-16 18:49:22 UTC (rev 233855)
@@ -1,3 +1,23 @@
+2018-07-12  Yusuke Suzuki  <[email protected]>
+
+        [JSC] Generator and AsyncGeneratorMethod's prototype is incorrect
+        https://bugs.webkit.org/show_bug.cgi?id=187585
+
+        Reviewed by Darin Adler.
+
+        * stress/default-proto-for-async-generator.js: Added.
+        (shouldBe):
+        (async.asyncGenerator):
+        * stress/default-proto-for-generator.js: Added.
+        (shouldBe):
+        (generator):
+        * stress/prototype-for-async-generator.js: Added.
+        (shouldBe):
+        (async.asyncGenerator):
+        (A.prototype.async.asyncGenerator):
+        (A):
+        * test262/expectations.yaml:
+
 2018-07-11  Ryan Haddad  <[email protected]>
 
         Skip JSC test stress/keep-checks-when-converting-to-lazy-js-constant-in-strength-reduction.js

Added: trunk/JSTests/stress/default-proto-for-async-generator.js (0 => 233855)


--- trunk/JSTests/stress/default-proto-for-async-generator.js	                        (rev 0)
+++ trunk/JSTests/stress/default-proto-for-async-generator.js	2018-07-16 18:49:22 UTC (rev 233855)
@@ -0,0 +1,11 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+async function* asyncGenerator() { }
+
+var AsyncGeneratorPrototype = Object.getPrototypeOf(asyncGenerator).prototype;
+asyncGenerator.prototype = null;
+
+shouldBe(Object.getPrototypeOf(asyncGenerator()), AsyncGeneratorPrototype);

Added: trunk/JSTests/stress/default-proto-for-generator.js (0 => 233855)


--- trunk/JSTests/stress/default-proto-for-generator.js	                        (rev 0)
+++ trunk/JSTests/stress/default-proto-for-generator.js	2018-07-16 18:49:22 UTC (rev 233855)
@@ -0,0 +1,11 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function* generator() { }
+
+var GeneratorPrototype = Object.getPrototypeOf(generator).prototype;
+generator.prototype = null;
+
+shouldBe(Object.getPrototypeOf(generator()), GeneratorPrototype);

Added: trunk/JSTests/stress/prototype-for-async-generator.js (0 => 233855)


--- trunk/JSTests/stress/prototype-for-async-generator.js	                        (rev 0)
+++ trunk/JSTests/stress/prototype-for-async-generator.js	2018-07-16 18:49:22 UTC (rev 233855)
@@ -0,0 +1,19 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+async function* asyncGenerator() { }
+
+var AsyncGeneratorPrototype = Object.getPrototypeOf(asyncGenerator).prototype;
+
+shouldBe(Object.getPrototypeOf(asyncGenerator.prototype), AsyncGeneratorPrototype);
+
+class A {
+    async *asyncGenerator()
+    {
+    }
+}
+
+var a = new A;
+shouldBe(Object.getPrototypeOf(a.asyncGenerator.prototype), AsyncGeneratorPrototype);

Modified: trunk/JSTests/test262/expectations.yaml (233854 => 233855)


--- trunk/JSTests/test262/expectations.yaml	2018-07-16 18:42:07 UTC (rev 233854)
+++ trunk/JSTests/test262/expectations.yaml	2018-07-16 18:49:22 UTC (rev 233855)
@@ -2686,12 +2686,6 @@
   default: 'Test262Error: Expected SameValue(«inside», «outside») to be true'
 test/language/expressions/function/scope-param-rest-elem-var-close.js:
   default: 'Test262Error: Expected SameValue(«inside», «outside») to be true'
-test/language/expressions/generators/default-proto.js:
-  default: 'Test262Error: Expected SameValue(«[object Object]», «[object Generator]») to be true'
-  strict mode: 'Test262Error: Expected SameValue(«[object Object]», «[object Generator]») to be true'
-test/language/expressions/generators/eval-body-proto-realm.js:
-  default: 'Test262Error: Expected SameValue(«[object Object]», «[object Generator]») to be true'
-  strict mode: 'Test262Error: Expected SameValue(«[object Object]», «[object Generator]») to be true'
 test/language/expressions/generators/generator-created-after-decl-inst.js:
   default: 'Test262Error: Expected SameValue(«[object Generator]», «[object Generator]») to be false'
   strict mode: 'Test262Error: Expected SameValue(«[object Generator]», «[object Generator]») to be false'
@@ -3742,9 +3736,6 @@
   default: 'Test262Error: Expected SameValue(«inside», «outside») to be true'
 test/language/statements/function/scope-param-rest-elem-var-close.js:
   default: 'Test262Error: Expected SameValue(«inside», «outside») to be true'
-test/language/statements/generators/default-proto.js:
-  default: 'Test262Error: Expected SameValue(«[object Object]», «[object Generator]») to be true'
-  strict mode: 'Test262Error: Expected SameValue(«[object Object]», «[object Generator]») to be true'
 test/language/statements/generators/generator-created-after-decl-inst.js:
   default: 'Test262Error: Expected SameValue(«[object Generator]», «[object Generator]») to be false'
   strict mode: 'Test262Error: Expected SameValue(«[object Generator]», «[object Generator]») to be false'

Modified: trunk/Source/_javascript_Core/ChangeLog (233854 => 233855)


--- trunk/Source/_javascript_Core/ChangeLog	2018-07-16 18:42:07 UTC (rev 233854)
+++ trunk/Source/_javascript_Core/ChangeLog	2018-07-16 18:49:22 UTC (rev 233855)
@@ -1,3 +1,39 @@
+2018-07-12  Yusuke Suzuki  <[email protected]>
+
+        [JSC] Generator and AsyncGeneratorMethod's prototype is incorrect
+        https://bugs.webkit.org/show_bug.cgi?id=187585
+
+        Reviewed by Darin Adler.
+
+        This patch fixes Generator and AsyncGenerator's prototype issues.
+
+        1. Generator's default prototype is incorrect when `generator.prototype = null` is performed.
+        We fix this by changing JSFunction::prototypeForConstruction.
+
+        2. AsyncGeneratorMethod is not handled. We change the name isAsyncGeneratorFunctionParseMode
+        to isAsyncGeneratorWrapperParseMode since it is aligned to Generator's code. And use it well
+        to fix `prototype` issues for AsyncGeneratorMethod.
+
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::emitPutAsyncGeneratorFields):
+        (JSC::BytecodeGenerator::emitNewFunction):
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::FunctionNode::emitBytecode):
+        * parser/ASTBuilder.h:
+        (JSC::ASTBuilder::createFunctionMetadata):
+        * parser/Parser.cpp:
+        (JSC::getAsynFunctionBodyParseMode):
+        (JSC::Parser<LexerType>::parseInner):
+        (JSC::Parser<LexerType>::parseAsyncGeneratorFunctionSourceElements):
+        * parser/ParserModes.h:
+        (JSC::isAsyncGeneratorParseMode):
+        (JSC::isAsyncGeneratorWrapperParseMode):
+        (JSC::isAsyncGeneratorFunctionParseMode): Deleted.
+        * runtime/FunctionExecutable.h:
+        * runtime/JSFunction.cpp:
+        (JSC::JSFunction::prototypeForConstruction):
+        (JSC::JSFunction::getOwnPropertySlot):
+
 2018-07-16  Mark Lam  <[email protected]>
 
         jsc shell's noFTL utility test function should be more robust.

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (233854 => 233855)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2018-07-16 18:42:07 UTC (rev 233854)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2018-07-16 18:49:22 UTC (rev 233855)
@@ -2878,7 +2878,7 @@
 
 void BytecodeGenerator::emitPutAsyncGeneratorFields(RegisterID* nextFunction)
 {
-    ASSERT(isAsyncGeneratorFunctionParseMode(parseMode()));
+    ASSERT(isAsyncGeneratorWrapperParseMode(parseMode()));
 
     emitDirectPutById(m_generatorRegister, propertyNames().builtinNames().generatorNextPrivateName(), nextFunction, PropertyNode::KnownDirect);
         
@@ -3359,7 +3359,7 @@
         emitOpcode(op_new_generator_func);
     else if (function->parseMode() == SourceParseMode::AsyncFunctionMode)
         emitOpcode(op_new_async_func);
-    else if (function->parseMode() == SourceParseMode::AsyncGeneratorWrapperFunctionMode) {
+    else if (isAsyncGeneratorWrapperParseMode(function->parseMode())) {
         ASSERT(Options::useAsyncIterator());
         emitOpcode(op_new_async_generator_func);
     } else

Modified: trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp (233854 => 233855)


--- trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2018-07-16 18:42:07 UTC (rev 233854)
+++ trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2018-07-16 18:49:22 UTC (rev 233855)
@@ -3790,7 +3790,7 @@
         if (isGeneratorWrapperParseMode(generator.parseMode()))
             generator.emitPutGeneratorFields(next.get());
         else {
-            ASSERT(isAsyncGeneratorFunctionParseMode(generator.parseMode()));
+            ASSERT(isAsyncGeneratorWrapperParseMode(generator.parseMode()));
             generator.emitPutAsyncGeneratorFields(next.get());
         }
         

Modified: trunk/Source/_javascript_Core/parser/ASTBuilder.h (233854 => 233855)


--- trunk/Source/_javascript_Core/parser/ASTBuilder.h	2018-07-16 18:42:07 UTC (rev 233854)
+++ trunk/Source/_javascript_Core/parser/ASTBuilder.h	2018-07-16 18:49:22 UTC (rev 233855)
@@ -446,7 +446,7 @@
         unsigned parameterCount,
         SourceParseMode mode, bool isArrowFunctionBodyExpression)
     {
-        ASSERT(Options::useAsyncIterator() || (mode != SourceParseMode::AsyncGeneratorBodyMode && mode != SourceParseMode::AsyncGeneratorWrapperFunctionMode && mode != SourceParseMode::AsyncGeneratorWrapperMethodMode));
+        ASSERT(Options::useAsyncIterator() || !isAsyncGeneratorParseMode(mode));
 
         return new (m_parserArena) FunctionMetadataNode(
             m_parserArena, startLocation, endLocation, startColumn, endColumn, 

Modified: trunk/Source/_javascript_Core/parser/Parser.cpp (233854 => 233855)


--- trunk/Source/_javascript_Core/parser/Parser.cpp	2018-07-16 18:42:07 UTC (rev 233854)
+++ trunk/Source/_javascript_Core/parser/Parser.cpp	2018-07-16 18:49:22 UTC (rev 233855)
@@ -90,7 +90,7 @@
 
 ALWAYS_INLINE static SourceParseMode getAsynFunctionBodyParseMode(SourceParseMode parseMode)
 {
-    if (isAsyncGeneratorFunctionParseMode(parseMode))
+    if (isAsyncGeneratorWrapperParseMode(parseMode))
         return SourceParseMode::AsyncGeneratorBodyMode;
 
     if (parseMode == SourceParseMode::AsyncArrowFunctionMode)
@@ -237,7 +237,7 @@
             sourceElements = parseModuleSourceElements(context, parseMode);
         else if (isGeneratorWrapperParseMode(parseMode))
             sourceElements = parseGeneratorFunctionSourceElements(context, calleeName, CheckForStrictMode);
-        else if (isAsyncGeneratorFunctionParseMode(parseMode))
+        else if (isAsyncGeneratorWrapperParseMode(parseMode))
             sourceElements = parseAsyncGeneratorFunctionSourceElements(context, parseMode, isArrowFunctionBodyExpression, CheckForStrictMode);
         else
             sourceElements = parseSourceElements(context, CheckForStrictMode);
@@ -566,7 +566,7 @@
 template <typename LexerType>
 template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseAsyncGeneratorFunctionSourceElements(TreeBuilder& context, SourceParseMode parseMode, bool isArrowFunctionBodyExpression, SourceElementsMode mode)
 {
-    ASSERT_UNUSED(parseMode, isAsyncGeneratorFunctionParseMode(parseMode));
+    ASSERT_UNUSED(parseMode, isAsyncGeneratorWrapperParseMode(parseMode));
     auto sourceElements = context.createSourceElements();
         
     unsigned functionKeywordStart = tokenStart();

Modified: trunk/Source/_javascript_Core/parser/ParserModes.h (233854 => 233855)


--- trunk/Source/_javascript_Core/parser/ParserModes.h	2018-07-16 18:42:07 UTC (rev 233854)
+++ trunk/Source/_javascript_Core/parser/ParserModes.h	2018-07-16 18:49:22 UTC (rev 233855)
@@ -133,10 +133,18 @@
         SourceParseMode::AsyncArrowFunctionBodyMode).contains(parseMode); 
 } 
 
-ALWAYS_INLINE bool isAsyncGeneratorFunctionParseMode(SourceParseMode parseMode)
+ALWAYS_INLINE bool isAsyncGeneratorParseMode(SourceParseMode parseMode)
 {
     return SourceParseModeSet(
         SourceParseMode::AsyncGeneratorWrapperFunctionMode,
+        SourceParseMode::AsyncGeneratorWrapperMethodMode,
+        SourceParseMode::AsyncGeneratorBodyMode).contains(parseMode);
+}
+
+ALWAYS_INLINE bool isAsyncGeneratorWrapperParseMode(SourceParseMode parseMode)
+{
+    return SourceParseModeSet(
+        SourceParseMode::AsyncGeneratorWrapperFunctionMode,
         SourceParseMode::AsyncGeneratorWrapperMethodMode).contains(parseMode);
 }
 

Modified: trunk/Source/_javascript_Core/runtime/FunctionExecutable.h (233854 => 233855)


--- trunk/Source/_javascript_Core/runtime/FunctionExecutable.h	2018-07-16 18:42:07 UTC (rev 233854)
+++ trunk/Source/_javascript_Core/runtime/FunctionExecutable.h	2018-07-16 18:49:22 UTC (rev 233855)
@@ -136,7 +136,7 @@
     bool isGetter() const { return parseMode() == SourceParseMode::GetterMode; }
     bool isSetter() const { return parseMode() == SourceParseMode::SetterMode; }
     bool isGenerator() const { return isGeneratorParseMode(parseMode()); }
-    bool isAsyncGenerator() const { return SourceParseModeSet(SourceParseMode::AsyncGeneratorWrapperFunctionMode, SourceParseMode::AsyncGeneratorBodyMode).contains(parseMode()); }
+    bool isAsyncGenerator() const { return isAsyncGeneratorParseMode(parseMode()); }
     bool isMethod() const { return parseMode() == SourceParseMode::MethodMode; }
     bool hasCallerAndArgumentsProperties() const
     {
@@ -152,6 +152,7 @@
             SourceParseMode::GeneratorWrapperFunctionMode,
             SourceParseMode::GeneratorWrapperMethodMode,
             SourceParseMode::AsyncGeneratorWrapperFunctionMode,
+            SourceParseMode::AsyncGeneratorWrapperMethodMode,
             SourceParseMode::AsyncGeneratorBodyMode
         ).contains(parseMode()) || isClass();
     }

Modified: trunk/Source/_javascript_Core/runtime/JSFunction.cpp (233854 => 233855)


--- trunk/Source/_javascript_Core/runtime/JSFunction.cpp	2018-07-16 18:42:07 UTC (rev 233854)
+++ trunk/Source/_javascript_Core/runtime/JSFunction.cpp	2018-07-16 18:49:22 UTC (rev 233855)
@@ -150,10 +150,20 @@
     auto scope = DECLARE_CATCH_SCOPE(vm);
     JSValue prototype = get(exec, vm.propertyNames->prototype);
     scope.releaseAssertNoException();
-    if (prototype.isObject())
+    if (LIKELY(prototype.isObject()))
         return asObject(prototype);
 
-    return globalObject(vm)->objectPrototype();
+    JSGlobalObject* globalObject = this->globalObject(vm);
+    if (!isHostOrBuiltinFunction()) {
+        // https://tc39.github.io/ecma262/#sec-generator-function-definitions-runtime-semantics-evaluatebody
+        if (isGeneratorWrapperParseMode(jsExecutable()->parseMode()))
+            return globalObject->generatorPrototype();
+
+        // https://tc39.github.io/ecma262/#sec-asyncgenerator-definitions-evaluatebody
+        if (isAsyncGeneratorWrapperParseMode(jsExecutable()->parseMode()))
+            return globalObject->asyncGeneratorPrototype();
+    }
+    return globalObject->objectPrototype();
 }
 
 FunctionRareData* JSFunction::allocateAndInitializeRareData(ExecState* exec, size_t inlineCapacity)
@@ -418,7 +428,7 @@
                 // property does not have a constructor property whose value is the GeneratorFunction instance.
                 // https://tc39.github.io/ecma262/#sec-generatorfunction-instances-prototype
                 prototype = constructEmptyObject(exec, thisObject->globalObject(vm)->generatorPrototype());
-            } else if (thisObject->jsExecutable()->parseMode() == SourceParseMode::AsyncGeneratorWrapperFunctionMode)
+            } else if (isAsyncGeneratorWrapperParseMode(thisObject->jsExecutable()->parseMode()))
                 prototype = constructEmptyObject(exec, thisObject->globalObject(vm)->asyncGeneratorPrototype());
             else {
                 prototype = constructEmptyObject(exec);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to