[ES6][ES7] Drop Constructability of generator function
authorutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 29 Dec 2015 11:49:35 +0000 (11:49 +0000)
committerutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 29 Dec 2015 11:49:35 +0000 (11:49 +0000)
https://bugs.webkit.org/show_bug.cgi?id=152383

Reviewed by Saam Barati.

We drop the constructability of generator functions.
This functionality is already landed in ES 2016 draft[1].
And this simplifies the existing JSC's generator implementation;
dropping GeneratorThisMode flag.

[1]: https://github.com/tc39/ecma262/releases/tag/es2016-draft-20151201

* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
* JavaScriptCore.xcodeproj/project.pbxproj:
* builtins/BuiltinExecutables.cpp:
(JSC::createExecutableInternal):
* bytecode/ExecutableInfo.h:
(JSC::ExecutableInfo::ExecutableInfo):
(JSC::ExecutableInfo::generatorThisMode): Deleted.
* bytecode/UnlinkedCodeBlock.cpp:
(JSC::UnlinkedCodeBlock::UnlinkedCodeBlock): Deleted.
* bytecode/UnlinkedCodeBlock.h:
(JSC::UnlinkedCodeBlock::generatorThisMode): Deleted.
* bytecode/UnlinkedFunctionExecutable.cpp:
(JSC::generateUnlinkedFunctionCodeBlock):
(JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):
* bytecode/UnlinkedFunctionExecutable.h:
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::BytecodeGenerator): Deleted.
* bytecompiler/BytecodeGenerator.h:
(JSC::BytecodeGenerator::makeFunction):
(JSC::BytecodeGenerator::generatorThisMode): Deleted.
* bytecompiler/NodesCodegen.cpp:
(JSC::ThisNode::emitBytecode):
* interpreter/Interpreter.cpp:
(JSC::eval): Deleted.
* runtime/CodeCache.cpp:
(JSC::CodeCache::getFunctionExecutableFromGlobalCode):
* runtime/Executable.h:
* runtime/GeneratorThisMode.h: Removed.
* tests/stress/generator-eval-this.js:
(shouldThrow):
* tests/stress/generator-is-not-constructible.js: Added.
(shouldThrow):
(A.staticGen):
(A.prototype.gen):
(A):
(TypeError):
* tests/stress/generator-this.js:
(shouldBe.g.next):
* tests/stress/generator-with-new-target.js:
(shouldThrow):

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

21 files changed:
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj
Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/builtins/BuiltinExecutables.cpp
Source/JavaScriptCore/bytecode/ExecutableInfo.h
Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp
Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h
Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.cpp
Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.h
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
Source/JavaScriptCore/interpreter/Interpreter.cpp
Source/JavaScriptCore/runtime/CodeCache.cpp
Source/JavaScriptCore/runtime/Executable.h
Source/JavaScriptCore/runtime/GeneratorThisMode.h [deleted file]
Source/JavaScriptCore/tests/stress/generator-eval-this.js
Source/JavaScriptCore/tests/stress/generator-is-not-constructible.js [new file with mode: 0644]
Source/JavaScriptCore/tests/stress/generator-this.js
Source/JavaScriptCore/tests/stress/generator-with-new-target.js

index 7046e7a..00e3e7f 100644 (file)
@@ -1,3 +1,59 @@
+2015-12-29  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        [ES6][ES7] Drop Constructability of generator function
+        https://bugs.webkit.org/show_bug.cgi?id=152383
+
+        Reviewed by Saam Barati.
+
+        We drop the constructability of generator functions.
+        This functionality is already landed in ES 2016 draft[1].
+        And this simplifies the existing JSC's generator implementation;
+        dropping GeneratorThisMode flag.
+
+        [1]: https://github.com/tc39/ecma262/releases/tag/es2016-draft-20151201
+
+        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
+        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * builtins/BuiltinExecutables.cpp:
+        (JSC::createExecutableInternal):
+        * bytecode/ExecutableInfo.h:
+        (JSC::ExecutableInfo::ExecutableInfo):
+        (JSC::ExecutableInfo::generatorThisMode): Deleted.
+        * bytecode/UnlinkedCodeBlock.cpp:
+        (JSC::UnlinkedCodeBlock::UnlinkedCodeBlock): Deleted.
+        * bytecode/UnlinkedCodeBlock.h:
+        (JSC::UnlinkedCodeBlock::generatorThisMode): Deleted.
+        * bytecode/UnlinkedFunctionExecutable.cpp:
+        (JSC::generateUnlinkedFunctionCodeBlock):
+        (JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):
+        * bytecode/UnlinkedFunctionExecutable.h:
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::BytecodeGenerator): Deleted.
+        * bytecompiler/BytecodeGenerator.h:
+        (JSC::BytecodeGenerator::makeFunction):
+        (JSC::BytecodeGenerator::generatorThisMode): Deleted.
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::ThisNode::emitBytecode):
+        * interpreter/Interpreter.cpp:
+        (JSC::eval): Deleted.
+        * runtime/CodeCache.cpp:
+        (JSC::CodeCache::getFunctionExecutableFromGlobalCode):
+        * runtime/Executable.h:
+        * runtime/GeneratorThisMode.h: Removed.
+        * tests/stress/generator-eval-this.js:
+        (shouldThrow):
+        * tests/stress/generator-is-not-constructible.js: Added.
+        (shouldThrow):
+        (A.staticGen):
+        (A.prototype.gen):
+        (A):
+        (TypeError):
+        * tests/stress/generator-this.js:
+        (shouldBe.g.next):
+        * tests/stress/generator-with-new-target.js:
+        (shouldThrow):
+
 2015-12-27  Filip Pizlo  <fpizlo@apple.com>
 
         FTL B3 should know that used registers are not the same thing as used registers. Rename the
index cc5ce44..6d9729f 100644 (file)
     <ClInclude Include="..\runtime\GeneratorFunctionConstructor.h" />
     <ClInclude Include="..\runtime\GeneratorFunctionPrototype.h" />
     <ClInclude Include="..\runtime\GeneratorPrototype.h" />
-    <ClInclude Include="..\runtime\GeneratorThisMode.h" />
     <ClInclude Include="..\runtime\GenericArguments.h" />
     <ClInclude Include="..\runtime\GenericArgumentsInlines.h" />
     <ClInclude Include="..\runtime\GenericOffset.h" />
index 14a8a8c..e3093f9 100644 (file)
     <ClInclude Include="..\runtime\GeneratorPrototype.h">
       <Filter>runtime</Filter>
     </ClInclude>
-    <ClInclude Include="..\runtime\GeneratorThisMode.h">
-      <Filter>runtime</Filter>
-    </ClInclude>
     <ClInclude Include="..\runtime\GetPutInfo.h">
       <Filter>runtime</Filter>
     </ClInclude>
index 6439cc1..b367e8b 100644 (file)
                70B791971C024A29002481E2 /* GeneratorFunctionPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = 70B791881C024432002481E2 /* GeneratorFunctionPrototype.h */; settings = {ATTRIBUTES = (Private, ); }; };
                70B791981C024A29002481E2 /* GeneratorPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 70B791891C024432002481E2 /* GeneratorPrototype.cpp */; };
                70B791991C024A29002481E2 /* GeneratorPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = 70B7918A1C024432002481E2 /* GeneratorPrototype.h */; settings = {ATTRIBUTES = (Private, ); }; };
-               70B7919A1C024A29002481E2 /* GeneratorThisMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 70B7918B1C024432002481E2 /* GeneratorThisMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
                70B7919B1C024A46002481E2 /* JSGeneratorFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 70B7918C1C024462002481E2 /* JSGeneratorFunction.cpp */; };
                70B7919C1C024A49002481E2 /* JSGeneratorFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 70B7918D1C024462002481E2 /* JSGeneratorFunction.h */; settings = {ATTRIBUTES = (Private, ); }; };
                70B7919D1C024A56002481E2 /* GeneratorPrototype.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = 70B791901C0246CE002481E2 /* GeneratorPrototype.lut.h */; settings = {ATTRIBUTES = (Private, ); }; };
                70B791881C024432002481E2 /* GeneratorFunctionPrototype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GeneratorFunctionPrototype.h; sourceTree = "<group>"; };
                70B791891C024432002481E2 /* GeneratorPrototype.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GeneratorPrototype.cpp; sourceTree = "<group>"; };
                70B7918A1C024432002481E2 /* GeneratorPrototype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GeneratorPrototype.h; sourceTree = "<group>"; };
-               70B7918B1C024432002481E2 /* GeneratorThisMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GeneratorThisMode.h; sourceTree = "<group>"; };
                70B7918C1C024462002481E2 /* JSGeneratorFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSGeneratorFunction.cpp; sourceTree = "<group>"; };
                70B7918D1C024462002481E2 /* JSGeneratorFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSGeneratorFunction.h; sourceTree = "<group>"; };
                70B7918E1C0244C9002481E2 /* SourceCodeKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SourceCodeKey.h; sourceTree = "<group>"; };
                                70B791881C024432002481E2 /* GeneratorFunctionPrototype.h */,
                                70B791891C024432002481E2 /* GeneratorPrototype.cpp */,
                                70B7918A1C024432002481E2 /* GeneratorPrototype.h */,
-                               70B7918B1C024432002481E2 /* GeneratorThisMode.h */,
                                0FE050111AA9091100D33B33 /* GenericArguments.h */,
                                0FE050121AA9091100D33B33 /* GenericArgumentsInlines.h */,
                                0FE050131AA9091100D33B33 /* GenericOffset.h */,
                                BC18C46A0E16F5CD00B34460 /* StringPrototype.h in Headers */,
                                0FB3878E1BFBC44D00E3AB1E /* AirBlockWorklist.h in Headers */,
                                142E313B134FF0A600AFADB5 /* Strong.h in Headers */,
-                               70B7919A1C024A29002481E2 /* GeneratorThisMode.h in Headers */,
                                145722861437E140005FDE26 /* StrongInlines.h in Headers */,
                                BCDE3AB80E6C82F5001453A7 /* Structure.h in Headers */,
                                7E4EE7090EBB7963005934AA /* StructureChain.h in Headers */,
index b800f51..da75287 100644 (file)
@@ -115,7 +115,7 @@ UnlinkedFunctionExecutable* createExecutableInternal(VM& vm, const SourceCode& s
     }
     metadata->overrideName(name);
     VariableEnvironment dummyTDZVariables;
-    UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(&vm, source, metadata, kind, constructAbility, GeneratorThisMode::NonEmpty, dummyTDZVariables, false, WTF::move(sourceOverride));
+    UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(&vm, source, metadata, kind, constructAbility, dummyTDZVariables, false, WTF::move(sourceOverride));
     functionExecutable->setNameValue(vm, jsString(&vm, name.string()));
     return functionExecutable;
 }
index aac3904..a923441 100644 (file)
@@ -26,7 +26,6 @@
 #ifndef ExecutableInfo_h
 #define ExecutableInfo_h
 
-#include "GeneratorThisMode.h"
 #include "ParserModes.h"
 
 namespace JSC {
@@ -34,13 +33,12 @@ namespace JSC {
 // FIXME: These flags, ParserModes and propagation to XXXCodeBlocks should be reorganized.
 // https://bugs.webkit.org/show_bug.cgi?id=151547
 struct ExecutableInfo {
-    ExecutableInfo(bool needsActivation, bool usesEval, bool isStrictMode, bool isConstructor, bool isBuiltinFunction, ConstructorKind constructorKind, GeneratorThisMode generatorThisMode, SuperBinding superBinding, SourceParseMode parseMode, bool isDerivedConstructorContext, bool isArrowFunctionContext)
+    ExecutableInfo(bool needsActivation, bool usesEval, bool isStrictMode, bool isConstructor, bool isBuiltinFunction, ConstructorKind constructorKind, SuperBinding superBinding, SourceParseMode parseMode, bool isDerivedConstructorContext, bool isArrowFunctionContext)
         : m_needsActivation(needsActivation)
         , m_usesEval(usesEval)
         , m_isStrictMode(isStrictMode)
         , m_isConstructor(isConstructor)
         , m_isBuiltinFunction(isBuiltinFunction)
-        , m_generatorThisMode(static_cast<unsigned>(generatorThisMode))
         , m_constructorKind(static_cast<unsigned>(constructorKind))
         , m_superBinding(static_cast<unsigned>(superBinding))
         , m_parseMode(parseMode)
@@ -49,7 +47,6 @@ struct ExecutableInfo {
     {
         ASSERT(m_constructorKind == static_cast<unsigned>(constructorKind));
         ASSERT(m_superBinding == static_cast<unsigned>(superBinding));
-        ASSERT(m_generatorThisMode == static_cast<unsigned>(generatorThisMode));
     }
 
     bool needsActivation() const { return m_needsActivation; }
@@ -57,7 +54,6 @@ struct ExecutableInfo {
     bool isStrictMode() const { return m_isStrictMode; }
     bool isConstructor() const { return m_isConstructor; }
     bool isBuiltinFunction() const { return m_isBuiltinFunction; }
-    GeneratorThisMode generatorThisMode() const { return static_cast<GeneratorThisMode>(m_generatorThisMode); }
     ConstructorKind constructorKind() const { return static_cast<ConstructorKind>(m_constructorKind); }
     SuperBinding superBinding() const { return static_cast<SuperBinding>(m_superBinding); }
     SourceParseMode parseMode() const { return m_parseMode; }
@@ -70,7 +66,6 @@ private:
     unsigned m_isStrictMode : 1;
     unsigned m_isConstructor : 1;
     unsigned m_isBuiltinFunction : 1;
-    unsigned m_generatorThisMode : 1;
     unsigned m_constructorKind : 2;
     unsigned m_superBinding : 1;
     SourceParseMode m_parseMode;
index 8a7d026..22dbf96 100644 (file)
@@ -65,7 +65,6 @@ UnlinkedCodeBlock::UnlinkedCodeBlock(VM* vm, Structure* structure, CodeType code
     , m_hasCapturedVariables(false)
     , m_isBuiltinFunction(info.isBuiltinFunction())
     , m_constructorKind(static_cast<unsigned>(info.constructorKind()))
-    , m_generatorThisMode(static_cast<unsigned>(info.generatorThisMode()))
     , m_superBinding(static_cast<unsigned>(info.superBinding()))
     , m_isDerivedConstructorContext(info.isDerivedConstructorContext())
     , m_isArrowFunctionContext(info.isArrowFunctionContext())
index bec6e08..a8e40ed 100644 (file)
@@ -31,7 +31,6 @@
 #include "CodeType.h"
 #include "ConstructAbility.h"
 #include "ExpressionRangeInfo.h"
-#include "GeneratorThisMode.h"
 #include "HandlerInfo.h"
 #include "Identifier.h"
 #include "JSCell.h"
@@ -207,7 +206,6 @@ public:
     bool isBuiltinFunction() const { return m_isBuiltinFunction; }
 
     ConstructorKind constructorKind() const { return static_cast<ConstructorKind>(m_constructorKind); }
-    GeneratorThisMode generatorThisMode() const { return static_cast<GeneratorThisMode>(m_generatorThisMode); }
     SuperBinding superBinding() const { return static_cast<SuperBinding>(m_superBinding); }
 
     void shrinkToFit()
@@ -394,7 +392,6 @@ private:
     unsigned m_hasCapturedVariables : 1;
     unsigned m_isBuiltinFunction : 1;
     unsigned m_constructorKind : 2;
-    unsigned m_generatorThisMode : 1;
     unsigned m_superBinding : 1;
     unsigned m_isDerivedConstructorContext : 1;
     unsigned m_isArrowFunctionContext : 1;
index 0c7f452..d914ca1 100644 (file)
@@ -67,7 +67,7 @@ static UnlinkedFunctionCodeBlock* generateUnlinkedFunctionCodeBlock(
     executable->recordParse(function->features(), function->hasCapturedVariables());
     
     UnlinkedFunctionCodeBlock* result = UnlinkedFunctionCodeBlock::create(&vm, FunctionCode,
-        ExecutableInfo(function->needsActivation(), function->usesEval(), function->isStrictMode(), kind == CodeForConstruct, functionKind == UnlinkedBuiltinFunction, executable->constructorKind(), executable->generatorThisMode(), executable->superBinding(), parseMode,  executable->isDerivedConstructorContext(), false));
+        ExecutableInfo(function->needsActivation(), function->usesEval(), function->isStrictMode(), kind == CodeForConstruct, functionKind == UnlinkedBuiltinFunction, executable->constructorKind(), executable->superBinding(), parseMode,  executable->isDerivedConstructorContext(), false));
 
     auto generator(std::make_unique<BytecodeGenerator>(vm, function.get(), result, debuggerMode, profilerMode, executable->parentScopeTDZVariables()));
     error = generator->generate();
@@ -76,7 +76,7 @@ static UnlinkedFunctionCodeBlock* generateUnlinkedFunctionCodeBlock(
     return result;
 }
 
-UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(VM* vm, Structure* structure, const SourceCode& source, RefPtr<SourceProvider>&& sourceOverride, FunctionMetadataNode* node, UnlinkedFunctionKind kind, ConstructAbility constructAbility, GeneratorThisMode generatorThisMode, VariableEnvironment& parentScopeTDZVariables, bool isDerivedConstructorContext)
+UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(VM* vm, Structure* structure, const SourceCode& source, RefPtr<SourceProvider>&& sourceOverride, FunctionMetadataNode* node, UnlinkedFunctionKind kind, ConstructAbility constructAbility, VariableEnvironment& parentScopeTDZVariables, bool isDerivedConstructorContext)
     : Base(*vm, structure)
     , m_name(node->ident())
     , m_inferredName(node->inferredName())
@@ -100,7 +100,6 @@ UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(VM* vm, Structure* struct
     , m_constructAbility(static_cast<unsigned>(constructAbility))
     , m_constructorKind(static_cast<unsigned>(node->constructorKind()))
     , m_functionMode(node->functionMode())
-    , m_generatorThisMode(static_cast<unsigned>(generatorThisMode))
     , m_superBinding(static_cast<unsigned>(node->superBinding()))
     , m_isDerivedConstructorContext(isDerivedConstructorContext)
 {
index fa21e38..be81aca 100644 (file)
@@ -31,7 +31,6 @@
 #include "CodeType.h"
 #include "ConstructAbility.h"
 #include "ExpressionRangeInfo.h"
-#include "GeneratorThisMode.h"
 #include "HandlerInfo.h"
 #include "Identifier.h"
 #include "JSCell.h"
@@ -66,10 +65,10 @@ public:
     typedef JSCell Base;
     static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
 
-    static UnlinkedFunctionExecutable* create(VM* vm, const SourceCode& source, FunctionMetadataNode* node, UnlinkedFunctionKind unlinkedFunctionKind, ConstructAbility constructAbility, GeneratorThisMode generatorThisMode, VariableEnvironment& parentScopeTDZVariables, bool isDerivedConstructorContext, RefPtr<SourceProvider>&& sourceOverride = nullptr)
+    static UnlinkedFunctionExecutable* create(VM* vm, const SourceCode& source, FunctionMetadataNode* node, UnlinkedFunctionKind unlinkedFunctionKind, ConstructAbility constructAbility, VariableEnvironment& parentScopeTDZVariables, bool isDerivedConstructorContext, RefPtr<SourceProvider>&& sourceOverride = nullptr)
     {
         UnlinkedFunctionExecutable* instance = new (NotNull, allocateCell<UnlinkedFunctionExecutable>(vm->heap))
-            UnlinkedFunctionExecutable(vm, vm->unlinkedFunctionExecutableStructure.get(), source, WTF::move(sourceOverride), node, unlinkedFunctionKind, constructAbility, generatorThisMode, parentScopeTDZVariables, isDerivedConstructorContext);
+            UnlinkedFunctionExecutable(vm, vm->unlinkedFunctionExecutableStructure.get(), source, WTF::move(sourceOverride), node, unlinkedFunctionKind, constructAbility, parentScopeTDZVariables, isDerivedConstructorContext);
         instance->finishCreation(*vm);
         return instance;
     }
@@ -83,7 +82,6 @@ public:
     bool isInStrictContext() const { return m_isInStrictContext; }
     FunctionMode functionMode() const { return static_cast<FunctionMode>(m_functionMode); }
     ConstructorKind constructorKind() const { return static_cast<ConstructorKind>(m_constructorKind); }
-    GeneratorThisMode generatorThisMode() const { return static_cast<GeneratorThisMode>(m_generatorThisMode); }
     SuperBinding superBinding() const { return static_cast<SuperBinding>(m_superBinding); }
 
     unsigned unlinkedFunctionNameStart() const { return m_unlinkedFunctionNameStart; }
@@ -133,7 +131,7 @@ public:
     bool isDerivedConstructorContext() const {return m_isDerivedConstructorContext; }
 
 private:
-    UnlinkedFunctionExecutable(VM*, Structure*, const SourceCode&, RefPtr<SourceProvider>&& sourceOverride, FunctionMetadataNode*, UnlinkedFunctionKind, ConstructAbility, GeneratorThisMode, VariableEnvironment&, bool isDerivedConstructorContext);
+    UnlinkedFunctionExecutable(VM*, Structure*, const SourceCode&, RefPtr<SourceProvider>&& sourceOverride, FunctionMetadataNode*, UnlinkedFunctionKind, ConstructAbility, VariableEnvironment&, bool isDerivedConstructorContext);
     
     WriteBarrier<UnlinkedFunctionCodeBlock> m_unlinkedCodeBlockForCall;
     WriteBarrier<UnlinkedFunctionCodeBlock> m_unlinkedCodeBlockForConstruct;
@@ -164,7 +162,6 @@ private:
     unsigned m_constructAbility: 1;
     unsigned m_constructorKind : 2;
     unsigned m_functionMode : 1; // FunctionMode
-    unsigned m_generatorThisMode : 1;
     unsigned m_superBinding : 1;
     unsigned m_isDerivedConstructorContext : 1;
 
index bf601b5..1cfa18d 100644 (file)
@@ -298,8 +298,6 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, FunctionNode* functionNode, Unlinke
     // Before emitting a scope creation, emit a generator prologue that contains jump based on a generator's state.
     if (parseMode == SourceParseMode::GeneratorBodyMode) {
         m_generatorRegister = &m_parameters[1];
-        if (generatorThisMode() == GeneratorThisMode::Empty)
-            emitMoveEmptyValue(&m_thisRegister);
 
         // Jump with switch_imm based on @generatorState. We don't take the coroutine styled generator implementation.
         // When calling `next()`, we would like to enter the same prologue instead of jumping based on the saved instruction pointer.
index 100bcb3..1d88a12 100644 (file)
@@ -32,7 +32,6 @@
 #define BytecodeGenerator_h
 
 #include "CodeBlock.h"
-#include "GeneratorThisMode.h"
 #include <wtf/HashTraits.h>
 #include "Instruction.h"
 #include "Label.h"
@@ -288,7 +287,6 @@ namespace JSC {
         bool usesEval() const { return m_scopeNode->usesEval(); }
         bool usesThis() const { return m_scopeNode->usesThis(); }
         ConstructorKind constructorKind() const { return m_codeBlock->constructorKind(); }
-        GeneratorThisMode generatorThisMode() const { return m_codeBlock->generatorThisMode(); }
         SuperBinding superBinding() const { return m_codeBlock->superBinding(); }
 
         ParserError generate();
@@ -805,18 +803,12 @@ namespace JSC {
             // https://bugs.webkit.org/show_bug.cgi?id=151547
             SourceParseMode parseMode = metadata->parseMode();
             ConstructAbility constructAbility = ConstructAbility::CanConstruct;
-            if (parseMode == SourceParseMode::GetterMode || parseMode == SourceParseMode::SetterMode || parseMode == SourceParseMode::ArrowFunctionMode)
+            if (parseMode == SourceParseMode::GetterMode || parseMode == SourceParseMode::SetterMode || parseMode == SourceParseMode::ArrowFunctionMode || parseMode == SourceParseMode::GeneratorWrapperFunctionMode)
                 constructAbility = ConstructAbility::CannotConstruct;
             else if (parseMode == SourceParseMode::MethodMode && metadata->constructorKind() == ConstructorKind::None)
                 constructAbility = ConstructAbility::CannotConstruct;
-            else if (parseMode == SourceParseMode::GeneratorWrapperFunctionMode && metadata->superBinding() == SuperBinding::Needed)
-                constructAbility = ConstructAbility::CannotConstruct;
-
-            GeneratorThisMode generatorThisMode = GeneratorThisMode::NonEmpty;
-            if (parseMode == SourceParseMode::GeneratorBodyMode && isConstructor())
-                generatorThisMode = GeneratorThisMode::Empty;
 
-            return UnlinkedFunctionExecutable::create(m_vm, m_scopeNode->source(), metadata, isBuiltinFunction() ? UnlinkedBuiltinFunction : UnlinkedNormalFunction, constructAbility, generatorThisMode, variablesUnderTDZ, newisDerivedConstructorContext);
+            return UnlinkedFunctionExecutable::create(m_vm, m_scopeNode->source(), metadata, isBuiltinFunction() ? UnlinkedBuiltinFunction : UnlinkedNormalFunction, constructAbility, variablesUnderTDZ, newisDerivedConstructorContext);
         }
 
         void getVariablesUnderTDZ(VariableEnvironment&);
index 4ad0795..ba98ed5 100644 (file)
@@ -149,7 +149,7 @@ RegisterID* ThisNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst
     if (generator.constructorKind() == ConstructorKind::Derived && generator.needsToUpdateArrowFunctionContext())
         generator.emitLoadThisFromArrowFunctionLexicalEnvironment();
 
-    if (m_shouldAlwaysEmitTDZCheck || generator.constructorKind() == ConstructorKind::Derived || generator.generatorThisMode() == GeneratorThisMode::Empty || generator.isDerivedConstructorContext())
+    if (m_shouldAlwaysEmitTDZCheck || generator.constructorKind() == ConstructorKind::Derived || generator.isDerivedConstructorContext())
         generator.emitTDZCheck(generator.thisRegister());
 
     if (dst == generator.ignoredResult())
index fe02c41..6d14087 100644 (file)
@@ -163,8 +163,6 @@ JSValue eval(CallFrame* callFrame)
     ThisTDZMode thisTDZMode = ThisTDZMode::CheckIfNeeded;
     if (callerUnlinkedCodeBlock->constructorKind() == ConstructorKind::Derived)
         thisTDZMode = ThisTDZMode::AlwaysCheck;
-    if (callerUnlinkedCodeBlock->parseMode() == SourceParseMode::GeneratorBodyMode && callerUnlinkedCodeBlock->generatorThisMode() == GeneratorThisMode::Empty)
-        thisTDZMode = ThisTDZMode::AlwaysCheck;
 
     SourceCode sourceCode(makeSource(programSource));
     EvalExecutable* eval = callerCodeBlock->evalCodeCache().tryGet(callerCodeBlock->isStrictMode(), sourceCode, thisTDZMode, callerScopeChain);
index b10b114..0c13463 100644 (file)
@@ -188,7 +188,7 @@ UnlinkedFunctionExecutable* CodeCache::getFunctionExecutableFromGlobalCode(VM& v
     metadata->setEndPosition(positionBeforeLastNewline);
     // The Function constructor only has access to global variables, so no variables will be under TDZ.
     VariableEnvironment emptyTDZVariables;
-    UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(&vm, source, metadata, UnlinkedNormalFunction, ConstructAbility::CanConstruct, GeneratorThisMode::NonEmpty, emptyTDZVariables, false);
+    UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(&vm, source, metadata, UnlinkedNormalFunction, ConstructAbility::CanConstruct, emptyTDZVariables, false);
     functionExecutable->m_nameValue.set(vm, functionExecutable, jsString(&vm, name.string()));
 
     m_sourceCode.addCache(key, SourceCodeValue(vm, functionExecutable, m_sourceCode.age()));
index 86a5777..1248cae 100644 (file)
@@ -453,7 +453,7 @@ public:
     DECLARE_INFO;
 
 
-    ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false, false, ConstructorKind::None, GeneratorThisMode::NonEmpty, SuperBinding::NotNeeded, SourceParseMode::ProgramMode, isDerivedConstructorContext(), isArrowFunctionContext()); }
+    ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false, false, ConstructorKind::None, SuperBinding::NotNeeded, SourceParseMode::ProgramMode, isDerivedConstructorContext(), isArrowFunctionContext()); }
 
     unsigned numVariables() { return m_unlinkedEvalCodeBlock->numVariables(); }
     unsigned numberOfFunctionDecls() { return m_unlinkedEvalCodeBlock->numberOfFunctionDecls(); }
@@ -506,7 +506,7 @@ public:
         
     DECLARE_INFO;
 
-    ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false, false, ConstructorKind::None, GeneratorThisMode::NonEmpty, SuperBinding::NotNeeded, SourceParseMode::ProgramMode, isDerivedConstructorContext(), false); }
+    ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false, false, ConstructorKind::None, SuperBinding::NotNeeded, SourceParseMode::ProgramMode, isDerivedConstructorContext(), false); }
 
 private:
     friend class ExecutableBase;
@@ -547,7 +547,7 @@ public:
 
     DECLARE_INFO;
 
-    ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false, false, ConstructorKind::None, GeneratorThisMode::NonEmpty, SuperBinding::NotNeeded, SourceParseMode::ModuleEvaluateMode, isDerivedConstructorContext(), false); }
+    ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false, false, ConstructorKind::None, SuperBinding::NotNeeded, SourceParseMode::ModuleEvaluateMode, isDerivedConstructorContext(), false); }
 
     UnlinkedModuleProgramCodeBlock* unlinkedModuleProgramCodeBlock() { return m_unlinkedModuleProgramCodeBlock.get(); }
 
diff --git a/Source/JavaScriptCore/runtime/GeneratorThisMode.h b/Source/JavaScriptCore/runtime/GeneratorThisMode.h
deleted file mode 100644 (file)
index 4c03e7b..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef GeneratorThisMode_h
-#define GeneratorThisMode_h
-
-namespace JSC {
-
-// http://ecma-international.org/ecma-262/6.0/#sec-functionallocate
-// http://ecma-international.org/ecma-262/6.0/#sec-ecmascript-function-objects-construct-argumentslist-newtarget
-// When the function is a GeneratorFunction, its [[ConstructorKind]] is always "derived".
-// This means that OrdinaryCallBindThis in section 9.2.2 is never executed for GeneratorFunction.
-// So, when we execute the following,
-//
-//     function *gen()
-//     {
-//        yield this
-//     }
-//
-//     {
-//         let g = gen();
-//         // |this| should be global.
-//         g.next();
-//     }
-//
-//     {
-//         let g = new gen();
-//         // |this| in gen should be TDZ (and it won't be filled).
-//         g.next();
-//     }
-//
-// The following flag manages this state. When GeneratorFunction is called as a constructor, it returns a Generator that function has GeneratorThisMode::Empty flag.
-// In this case, when accessing |this|, a TDZ reference error occurs.
-enum class GeneratorThisMode : unsigned {
-    Empty,
-    NonEmpty
-};
-
-}
-
-#endif // GeneratorThisMode_h
index c9bd78d..f5766de 100644 (file)
@@ -22,10 +22,10 @@ function *gen() {
     yield eval("this");
 }
 
-var g = new gen();
 shouldThrow(() => {
+    var g = new gen();
     g.next().value;
-}, `ReferenceError: Cannot access uninitialized variable.`);
+}, `TypeError: function is not a constructor (evaluating 'new gen()')`);
 
 class B { }
 
diff --git a/Source/JavaScriptCore/tests/stress/generator-is-not-constructible.js b/Source/JavaScriptCore/tests/stress/generator-is-not-constructible.js
new file mode 100644 (file)
index 0000000..35736c1
--- /dev/null
@@ -0,0 +1,41 @@
+function shouldThrow(func, errorMessage) {
+    var errorThrown = false;
+    var error = null;
+    try {
+        func();
+    } catch (e) {
+        errorThrown = true;
+        error = e;
+    }
+    if (!errorThrown)
+        throw new Error('not thrown');
+    if (String(error) !== errorMessage)
+        throw new Error(`bad error: ${String(error)}`);
+}
+
+function *gen()
+{
+}
+
+shouldThrow(() => {
+    new gen();
+}, `TypeError: function is not a constructor (evaluating 'new gen()')`);
+
+class A {
+    static *staticGen()
+    {
+    }
+
+    *gen()
+    {
+    }
+};
+
+shouldThrow(() => {
+    let a = new A();
+    new a.gen();
+}, `TypeError: function is not a constructor (evaluating 'new a.gen()')`);
+
+shouldThrow(() => {
+    new A.staticGen();
+}, `TypeError: function is not a constructor (evaluating 'new A.staticGen()')`);
index 880af6e..10450a7 100644 (file)
@@ -31,10 +31,10 @@ var global = new Function('return this')();
         shouldBe(g.next().value, global);
     }
     {
-        let g = new gen();
         shouldThrow(() => {
+            let g = new gen();
             g.next();
-        }, `ReferenceError: Cannot access uninitialized variable.`);
+        }, `TypeError: function is not a constructor (evaluating 'new gen()')`);
     }
     {
         let thisObject = {};
@@ -54,10 +54,10 @@ var global = new Function('return this')();
         shouldBe(g.next().value, undefined);
     }
     {
-        let g = new gen();
         shouldThrow(() => {
+            let g = new gen();
             g.next();
-        }, `ReferenceError: Cannot access uninitialized variable.`);
+        }, `TypeError: function is not a constructor (evaluating 'new gen()')`);
     }
     {
         let thisObject = {};
index 0d3b2df..ba5013e 100644 (file)
@@ -3,6 +3,21 @@ function shouldBe(actual, expected) {
         throw new Error('bad value: ' + actual);
 }
 
+function shouldThrow(func, errorMessage) {
+    var errorThrown = false;
+    var error = null;
+    try {
+        func();
+    } catch (e) {
+        errorThrown = true;
+        error = e;
+    }
+    if (!errorThrown)
+        throw new Error('not thrown');
+    if (String(error) !== errorMessage)
+        throw new Error(`bad error: ${String(error)}`);
+}
+
 function *gen()
 {
     yield new.target;
@@ -11,5 +26,6 @@ function *gen()
 var g = gen();
 shouldBe(g.next().value, undefined);
 
-var g2 = new gen();
-shouldBe(g.next().value, undefined);
+shouldThrow(() => {
+    var g2 = new gen();
+}, `TypeError: function is not a constructor (evaluating 'new gen()')`);