Title: [194449] trunk
Revision
194449
Author
[email protected]
Date
2015-12-30 13:08:16 -0800 (Wed, 30 Dec 2015)

Log Message

[ES6] Arrow function syntax. Arrow function specific features. Lexical bind "super"
https://bugs.webkit.org/show_bug.cgi?id=149615

Source/_javascript_Core:

Patch by Aleksandr Skachkov <[email protected]> on 2015-12-30
Reviewed by Saam Barati.

Implemented lexical bind "super" property for arrow function. 'super' property can be accessed
inside of the arrow function in case if arrow function is nested in constructor, method,
getter or setter of class. In current patch using 'super' in arrow function, that declared out of the
class, lead to wrong type of error, should be SyntaxError(https://bugs.webkit.org/show_bug.cgi?id=150893)
and this will be fixed in separete patch.

* builtins/BuiltinExecutables.cpp:
(JSC::createExecutableInternal):
* bytecode/EvalCodeCache.h:
(JSC::EvalCodeCache::getSlow):
* bytecode/ExecutableInfo.h:
(JSC::ExecutableInfo::ExecutableInfo):
(JSC::ExecutableInfo::derivedContextType):
(JSC::ExecutableInfo::isClassContext):
* bytecode/UnlinkedCodeBlock.cpp:
(JSC::UnlinkedCodeBlock::UnlinkedCodeBlock):
* bytecode/UnlinkedCodeBlock.h:
(JSC::UnlinkedCodeBlock::derivedContextType):
(JSC::UnlinkedCodeBlock::isClassContext):
* bytecode/UnlinkedFunctionExecutable.cpp:
(JSC::generateUnlinkedFunctionCodeBlock):
(JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):
* bytecode/UnlinkedFunctionExecutable.h:
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::BytecodeGenerator):
(JSC::BytecodeGenerator::emitPutDerivedConstructorToArrowFunctionContextScope):
* bytecompiler/BytecodeGenerator.h:
(JSC::BytecodeGenerator::derivedContextType):
(JSC::BytecodeGenerator::isDerivedConstructorContext):
(JSC::BytecodeGenerator::isDerivedClassContext):
(JSC::BytecodeGenerator::isArrowFunction):
(JSC::BytecodeGenerator::makeFunction):
* bytecompiler/NodesCodegen.cpp:
(JSC::emitHomeObjectForCallee):
(JSC::FunctionCallValueNode::emitBytecode):
* debugger/DebuggerCallFrame.cpp:
(JSC::DebuggerCallFrame::evaluate):
* interpreter/Interpreter.cpp:
(JSC::eval):
* runtime/CodeCache.cpp:
(JSC::CodeCache::getFunctionExecutableFromGlobalCode):
* runtime/Executable.cpp:
(JSC::ScriptExecutable::ScriptExecutable):
(JSC::EvalExecutable::create):
(JSC::EvalExecutable::EvalExecutable):
(JSC::ProgramExecutable::ProgramExecutable):
(JSC::ModuleProgramExecutable::ModuleProgramExecutable):
(JSC::FunctionExecutable::FunctionExecutable):
* runtime/Executable.h:
(JSC::ScriptExecutable::derivedContextType):
* runtime/JSGlobalObjectFunctions.cpp:
(JSC::globalFuncEval):
* tests/es6.yaml:
* tests/stress/arrowfunction-lexical-bind-superproperty.js: Added.

LayoutTests:

Patch by Skachkov Oleksandr <[email protected]> on 2015-12-30
Reviewed by Saam Barati.

* js/arrowfunction-superproperty-expected.txt: Added.
* js/arrowfunction-superproperty.html: Added.
* js/script-tests/arrowfunction-superproperty.js: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (194448 => 194449)


--- trunk/LayoutTests/ChangeLog	2015-12-30 20:15:27 UTC (rev 194448)
+++ trunk/LayoutTests/ChangeLog	2015-12-30 21:08:16 UTC (rev 194449)
@@ -1,3 +1,14 @@
+2015-12-30  Skachkov Oleksandr  <[email protected]>
+
+        [ES6] Arrow function syntax. Arrow function specific features. Lexical bind "super"
+        https://bugs.webkit.org/show_bug.cgi?id=149615
+
+        Reviewed by Saam Barati.
+
+        * js/arrowfunction-superproperty-expected.txt: Added.
+        * js/arrowfunction-superproperty.html: Added.
+        * js/script-tests/arrowfunction-superproperty.js: Added.
+
 2015-12-29  Andy VanWagoner  <[email protected]>
 
         Remove tests for sometimes unsupported calendars, numbering systems, and time zone backward links

Added: trunk/LayoutTests/js/arrowfunction-superproperty-expected.txt (0 => 194449)


--- trunk/LayoutTests/js/arrowfunction-superproperty-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/js/arrowfunction-superproperty-expected.txt	2015-12-30 21:08:16 UTC (rev 194449)
@@ -0,0 +1,16 @@
+Tests for ES6 arrow function, access to the super property in arrow function
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS (new B()).getValueParentFunction() is expectedValue
+PASS (new C(false)).value is expectedValue
+PASS E.getParentStaticValue() is expectedValue
+PASS f.prop is expectedValue + "-" + expectedValue
+PASS f.prop is expectedValue + "-" + "new-value"
+PASS (new F()).getParentValue() is expectedValue
+PASS (new F()).getParentValueWithError()() threw exception TypeError: undefined is not an object (evaluating 'super.getValue').
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/js/arrowfunction-superproperty.html (0 => 194449)


--- trunk/LayoutTests/js/arrowfunction-superproperty.html	                        (rev 0)
+++ trunk/LayoutTests/js/arrowfunction-superproperty.html	2015-12-30 21:08:16 UTC (rev 194449)
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>

Added: trunk/LayoutTests/js/script-tests/arrowfunction-superproperty.js (0 => 194449)


--- trunk/LayoutTests/js/script-tests/arrowfunction-superproperty.js	                        (rev 0)
+++ trunk/LayoutTests/js/script-tests/arrowfunction-superproperty.js	2015-12-30 21:08:16 UTC (rev 194449)
@@ -0,0 +1,95 @@
+description('Tests for ES6 arrow function, access to the super property in arrow function');
+
+var expectedValue = 'test-value';
+
+class A {
+    getValue () {
+        return expectedValue;
+    }
+};
+
+class B extends A {
+    getValueParentFunction() {
+        var arrow  = () => super.getValue();
+        return arrow();
+    }
+};
+
+class C extends B {
+    constructor(beforeSuper) {
+        let _value;
+        let arrow = () => super.getValue();
+        if (beforeSuper) {
+            _value = arrow();
+            super();
+        } else {
+            super();
+            _value = arrow();
+        }
+        this.value = _value;
+    }
+};
+
+class D {
+    constructor() {
+        this.value = expectedValue;
+    }
+    static getStaticValue() {
+        return expectedValue;
+    }
+};
+
+class E extends D {
+    static getParentStaticValue() {
+        var arrow  = () => super.getStaticValue();
+        return arrow();
+    }
+};
+
+class F extends A {
+    constructor() {
+        super();
+        this.value = expectedValue;
+    }
+    get prop() {
+        var arrow = () => super.getValue()+ '-' + this.value;
+        return arrow();
+    }
+    set prop(value) {
+        var arrow = (newVal) => this.value = newVal;
+        arrow(value);
+    }
+    getParentValue() {
+        let arrow = () => () => super.getValue();
+        return arrow()();
+    }
+    getParentValueWithError() {
+        var f =  function () {
+            return () => super.getValue();
+        };
+        return f();
+    }
+ };
+
+shouldBe('(new B()).getValueParentFunction()', 'expectedValue');
+
+shouldBe('(new C(false)).value', 'expectedValue');
+
+// FIXME: Problem with access to the super before super() in constructor
+// https://bugs.webkit.org/show_bug.cgi?id=152108
+//shouldThrow('(new C(true))', 'ReferenceError');
+
+shouldBe('E.getParentStaticValue()', 'expectedValue');
+
+var f = new F();
+
+shouldBe('f.prop', 'expectedValue + "-" + expectedValue');
+
+f.prop = 'new-value';
+shouldBe('f.prop', 'expectedValue + "-" + "new-value"');
+
+shouldBe('(new F()).getParentValue()', 'expectedValue');
+
+shouldThrow('(new F()).getParentValueWithError()()');
+
+var successfullyParsed = true;

Modified: trunk/Source/_javascript_Core/ChangeLog (194448 => 194449)


--- trunk/Source/_javascript_Core/ChangeLog	2015-12-30 20:15:27 UTC (rev 194448)
+++ trunk/Source/_javascript_Core/ChangeLog	2015-12-30 21:08:16 UTC (rev 194449)
@@ -1,3 +1,65 @@
+2015-12-30  Aleksandr Skachkov  <[email protected]>
+
+        [ES6] Arrow function syntax. Arrow function specific features. Lexical bind "super"
+        https://bugs.webkit.org/show_bug.cgi?id=149615
+
+        Reviewed by Saam Barati.
+
+        Implemented lexical bind "super" property for arrow function. 'super' property can be accessed 
+        inside of the arrow function in case if arrow function is nested in constructor, method, 
+        getter or setter of class. In current patch using 'super' in arrow function, that declared out of the 
+        class, lead to wrong type of error, should be SyntaxError(https://bugs.webkit.org/show_bug.cgi?id=150893) 
+        and this will be fixed in separete patch.
+
+        * builtins/BuiltinExecutables.cpp:
+        (JSC::createExecutableInternal):
+        * bytecode/EvalCodeCache.h:
+        (JSC::EvalCodeCache::getSlow):
+        * bytecode/ExecutableInfo.h:
+        (JSC::ExecutableInfo::ExecutableInfo):
+        (JSC::ExecutableInfo::derivedContextType):
+        (JSC::ExecutableInfo::isClassContext):
+        * bytecode/UnlinkedCodeBlock.cpp:
+        (JSC::UnlinkedCodeBlock::UnlinkedCodeBlock):
+        * bytecode/UnlinkedCodeBlock.h:
+        (JSC::UnlinkedCodeBlock::derivedContextType):
+        (JSC::UnlinkedCodeBlock::isClassContext):
+        * bytecode/UnlinkedFunctionExecutable.cpp:
+        (JSC::generateUnlinkedFunctionCodeBlock):
+        (JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):
+        * bytecode/UnlinkedFunctionExecutable.h:
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::BytecodeGenerator):
+        (JSC::BytecodeGenerator::emitPutDerivedConstructorToArrowFunctionContextScope):
+        * bytecompiler/BytecodeGenerator.h:
+        (JSC::BytecodeGenerator::derivedContextType):
+        (JSC::BytecodeGenerator::isDerivedConstructorContext):
+        (JSC::BytecodeGenerator::isDerivedClassContext):
+        (JSC::BytecodeGenerator::isArrowFunction):
+        (JSC::BytecodeGenerator::makeFunction):
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::emitHomeObjectForCallee):
+        (JSC::FunctionCallValueNode::emitBytecode):
+        * debugger/DebuggerCallFrame.cpp:
+        (JSC::DebuggerCallFrame::evaluate):
+        * interpreter/Interpreter.cpp:
+        (JSC::eval):
+        * runtime/CodeCache.cpp:
+        (JSC::CodeCache::getFunctionExecutableFromGlobalCode):
+        * runtime/Executable.cpp:
+        (JSC::ScriptExecutable::ScriptExecutable):
+        (JSC::EvalExecutable::create):
+        (JSC::EvalExecutable::EvalExecutable):
+        (JSC::ProgramExecutable::ProgramExecutable):
+        (JSC::ModuleProgramExecutable::ModuleProgramExecutable):
+        (JSC::FunctionExecutable::FunctionExecutable):
+        * runtime/Executable.h:
+        (JSC::ScriptExecutable::derivedContextType):
+        * runtime/JSGlobalObjectFunctions.cpp:
+        (JSC::globalFuncEval):
+        * tests/es6.yaml:
+        * tests/stress/arrowfunction-lexical-bind-superproperty.js: Added.
+
 2015-12-29  Yusuke Suzuki  <[email protected]>
 
         Unreviewed, relax limitation in operationCreateThis

Modified: trunk/Source/_javascript_Core/builtins/BuiltinExecutables.cpp (194448 => 194449)


--- trunk/Source/_javascript_Core/builtins/BuiltinExecutables.cpp	2015-12-30 20:15:27 UTC (rev 194448)
+++ trunk/Source/_javascript_Core/builtins/BuiltinExecutables.cpp	2015-12-30 21:08:16 UTC (rev 194449)
@@ -115,7 +115,7 @@
     }
     metadata->overrideName(name);
     VariableEnvironment dummyTDZVariables;
-    UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(&vm, source, metadata, kind, constructAbility, dummyTDZVariables, false, WTF::move(sourceOverride));
+    UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(&vm, source, metadata, kind, constructAbility, dummyTDZVariables, DerivedContextType::None, WTF::move(sourceOverride));
     functionExecutable->setNameValue(vm, jsString(&vm, name.string()));
     return functionExecutable;
 }

Modified: trunk/Source/_javascript_Core/bytecode/EvalCodeCache.h (194448 => 194449)


--- trunk/Source/_javascript_Core/bytecode/EvalCodeCache.h	2015-12-30 20:15:27 UTC (rev 194448)
+++ trunk/Source/_javascript_Core/bytecode/EvalCodeCache.h	2015-12-30 21:08:16 UTC (rev 194449)
@@ -55,11 +55,11 @@
             return nullptr;
         }
         
-        EvalExecutable* getSlow(ExecState* exec, JSCell* owner, bool inStrictContext, ThisTDZMode thisTDZMode, bool isDerivedConstructorContext, bool isArrowFunctionContext, const SourceCode& evalSource, JSScope* scope)
+        EvalExecutable* getSlow(ExecState* exec, JSCell* owner, bool inStrictContext, ThisTDZMode thisTDZMode, DerivedContextType derivedContextType, bool isArrowFunctionContext, const SourceCode& evalSource, JSScope* scope)
         {
             VariableEnvironment variablesUnderTDZ;
             JSScope::collectVariablesUnderTDZ(scope, variablesUnderTDZ);
-            EvalExecutable* evalExecutable = EvalExecutable::create(exec, evalSource, inStrictContext, thisTDZMode, isDerivedConstructorContext, isArrowFunctionContext, &variablesUnderTDZ);
+            EvalExecutable* evalExecutable = EvalExecutable::create(exec, evalSource, inStrictContext, thisTDZMode, derivedContextType, isArrowFunctionContext, &variablesUnderTDZ);
 
             if (!evalExecutable)
                 return nullptr;

Modified: trunk/Source/_javascript_Core/bytecode/ExecutableInfo.h (194448 => 194449)


--- trunk/Source/_javascript_Core/bytecode/ExecutableInfo.h	2015-12-30 20:15:27 UTC (rev 194448)
+++ trunk/Source/_javascript_Core/bytecode/ExecutableInfo.h	2015-12-30 21:08:16 UTC (rev 194449)
@@ -29,11 +29,13 @@
 #include "ParserModes.h"
 
 namespace JSC {
+    
+enum class DerivedContextType { None, DerivedConstructorContext, DerivedMethodContext };
 
 // 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, 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, DerivedContextType derivedContextType, bool isArrowFunctionContext, bool isClassContext)
         : m_needsActivation(needsActivation)
         , m_usesEval(usesEval)
         , m_isStrictMode(isStrictMode)
@@ -42,8 +44,9 @@
         , m_constructorKind(static_cast<unsigned>(constructorKind))
         , m_superBinding(static_cast<unsigned>(superBinding))
         , m_parseMode(parseMode)
-        , m_isDerivedConstructorContext(isDerivedConstructorContext)
+        , m_derivedContextType(static_cast<unsigned>(derivedContextType))
         , m_isArrowFunctionContext(isArrowFunctionContext)
+        , m_isClassContext(isClassContext)
     {
         ASSERT(m_constructorKind == static_cast<unsigned>(constructorKind));
         ASSERT(m_superBinding == static_cast<unsigned>(superBinding));
@@ -57,8 +60,9 @@
     ConstructorKind constructorKind() const { return static_cast<ConstructorKind>(m_constructorKind); }
     SuperBinding superBinding() const { return static_cast<SuperBinding>(m_superBinding); }
     SourceParseMode parseMode() const { return m_parseMode; }
-    bool isDerivedConstructorContext() const { return m_isDerivedConstructorContext; }
+    DerivedContextType derivedContextType() const { return static_cast<DerivedContextType>(m_derivedContextType); }
     bool isArrowFunctionContext() const { return m_isArrowFunctionContext; }
+    bool isClassContext() const { return m_isClassContext; }
 
 private:
     unsigned m_needsActivation : 1;
@@ -69,8 +73,9 @@
     unsigned m_constructorKind : 2;
     unsigned m_superBinding : 1;
     SourceParseMode m_parseMode;
-    unsigned m_isDerivedConstructorContext : 1;
+    unsigned m_derivedContextType : 2;
     unsigned m_isArrowFunctionContext : 1;
+    unsigned m_isClassContext : 1;
 };
 
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.cpp (194448 => 194449)


--- trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.cpp	2015-12-30 20:15:27 UTC (rev 194448)
+++ trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.cpp	2015-12-30 21:08:16 UTC (rev 194449)
@@ -66,8 +66,9 @@
     , m_isBuiltinFunction(info.isBuiltinFunction())
     , m_constructorKind(static_cast<unsigned>(info.constructorKind()))
     , m_superBinding(static_cast<unsigned>(info.superBinding()))
-    , m_isDerivedConstructorContext(info.isDerivedConstructorContext())
+    , m_derivedContextType(static_cast<unsigned>(info.derivedContextType()))
     , m_isArrowFunctionContext(info.isArrowFunctionContext())
+    , m_isClassContext(info.isClassContext())
     , m_firstLine(0)
     , m_lineCount(0)
     , m_endColumn(UINT_MAX)

Modified: trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.h (194448 => 194449)


--- trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.h	2015-12-30 20:15:27 UTC (rev 194448)
+++ trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.h	2015-12-30 21:08:16 UTC (rev 194449)
@@ -119,8 +119,9 @@
     bool usesEval() const { return m_usesEval; }
     SourceParseMode parseMode() const { return m_parseMode; }
     bool isArrowFunction() const { return m_parseMode == SourceParseMode::ArrowFunctionMode; }
-    bool isDerivedConstructorContext() const { return m_isDerivedConstructorContext; }
+    DerivedContextType derivedContextType() const { return static_cast<DerivedContextType>(m_derivedContextType); }
     bool isArrowFunctionContext() const { return m_isArrowFunctionContext; }
+    bool isClassContext() const { return m_isClassContext; }
 
     bool needsFullScopeChain() const { return m_needsFullScopeChain; }
 
@@ -393,9 +394,9 @@
     unsigned m_isBuiltinFunction : 1;
     unsigned m_constructorKind : 2;
     unsigned m_superBinding : 1;
-    unsigned m_isDerivedConstructorContext : 1;
+    unsigned m_derivedContextType : 2;
     unsigned m_isArrowFunctionContext : 1;
-
+    unsigned m_isClassContext : 1;
     unsigned m_firstLine;
     unsigned m_lineCount;
     unsigned m_endColumn;

Modified: trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.cpp (194448 => 194449)


--- trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.cpp	2015-12-30 20:15:27 UTC (rev 194448)
+++ trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.cpp	2015-12-30 21:08:16 UTC (rev 194449)
@@ -65,9 +65,11 @@
 
     function->finishParsing(executable->name(), executable->functionMode());
     executable->recordParse(function->features(), function->hasCapturedVariables());
-    
+
+    bool isClassContext = executable->superBinding() == SuperBinding::Needed;
+
     UnlinkedFunctionCodeBlock* result = UnlinkedFunctionCodeBlock::create(&vm, FunctionCode,
-        ExecutableInfo(function->needsActivation(), function->usesEval(), function->isStrictMode(), kind == CodeForConstruct, functionKind == UnlinkedBuiltinFunction, executable->constructorKind(), executable->superBinding(), parseMode,  executable->isDerivedConstructorContext(), false));
+        ExecutableInfo(function->needsActivation(), function->usesEval(), function->isStrictMode(), kind == CodeForConstruct, functionKind == UnlinkedBuiltinFunction, executable->constructorKind(), executable->superBinding(), parseMode, executable->derivedContextType(), false, isClassContext));
 
     auto generator(std::make_unique<BytecodeGenerator>(vm, function.get(), result, debuggerMode, profilerMode, executable->parentScopeTDZVariables()));
     error = generator->generate();
@@ -76,7 +78,7 @@
     return result;
 }
 
-UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(VM* vm, Structure* structure, const SourceCode& source, RefPtr<SourceProvider>&& sourceOverride, FunctionMetadataNode* node, UnlinkedFunctionKind kind, ConstructAbility constructAbility, VariableEnvironment& parentScopeTDZVariables, bool isDerivedConstructorContext)
+UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(VM* vm, Structure* structure, const SourceCode& source, RefPtr<SourceProvider>&& sourceOverride, FunctionMetadataNode* node, UnlinkedFunctionKind kind, ConstructAbility constructAbility, VariableEnvironment& parentScopeTDZVariables, DerivedContextType derivedContextType)
     : Base(*vm, structure)
     , m_name(node->ident())
     , m_inferredName(node->inferredName())
@@ -101,7 +103,7 @@
     , m_constructorKind(static_cast<unsigned>(node->constructorKind()))
     , m_functionMode(node->functionMode())
     , m_superBinding(static_cast<unsigned>(node->superBinding()))
-    , m_isDerivedConstructorContext(isDerivedConstructorContext)
+    , m_derivedContextType(static_cast<unsigned>(derivedContextType))
 {
     ASSERT(m_constructorKind == static_cast<unsigned>(node->constructorKind()));
     m_parentScopeTDZVariables.swap(parentScopeTDZVariables);

Modified: trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.h (194448 => 194449)


--- trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.h	2015-12-30 20:15:27 UTC (rev 194448)
+++ trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.h	2015-12-30 21:08:16 UTC (rev 194449)
@@ -30,6 +30,7 @@
 #include "CodeSpecializationKind.h"
 #include "CodeType.h"
 #include "ConstructAbility.h"
+#include "ExecutableInfo.h"
 #include "ExpressionRangeInfo.h"
 #include "HandlerInfo.h"
 #include "Identifier.h"
@@ -65,10 +66,10 @@
     typedef JSCell Base;
     static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
 
-    static UnlinkedFunctionExecutable* create(VM* vm, const SourceCode& source, FunctionMetadataNode* node, UnlinkedFunctionKind unlinkedFunctionKind, ConstructAbility constructAbility, VariableEnvironment& parentScopeTDZVariables, bool isDerivedConstructorContext, RefPtr<SourceProvider>&& sourceOverride = nullptr)
+    static UnlinkedFunctionExecutable* create(VM* vm, const SourceCode& source, FunctionMetadataNode* node, UnlinkedFunctionKind unlinkedFunctionKind, ConstructAbility constructAbility, VariableEnvironment& parentScopeTDZVariables, DerivedContextType derivedContextType, RefPtr<SourceProvider>&& sourceOverride = nullptr)
     {
         UnlinkedFunctionExecutable* instance = new (NotNull, allocateCell<UnlinkedFunctionExecutable>(vm->heap))
-            UnlinkedFunctionExecutable(vm, vm->unlinkedFunctionExecutableStructure.get(), source, WTF::move(sourceOverride), node, unlinkedFunctionKind, constructAbility, parentScopeTDZVariables, isDerivedConstructorContext);
+            UnlinkedFunctionExecutable(vm, vm->unlinkedFunctionExecutableStructure.get(), source, WTF::move(sourceOverride), node, unlinkedFunctionKind, constructAbility, parentScopeTDZVariables, derivedContextType);
         instance->finishCreation(*vm);
         return instance;
     }
@@ -128,11 +129,12 @@
     const VariableEnvironment* parentScopeTDZVariables() const { return &m_parentScopeTDZVariables; }
     
     bool isArrowFunction() const { return m_parseMode == SourceParseMode::ArrowFunctionMode; }
-    bool isDerivedConstructorContext() const {return m_isDerivedConstructorContext; }
 
+    JSC::DerivedContextType derivedContextType() const {return static_cast<JSC::DerivedContextType>(m_derivedContextType); }
+    
 private:
-    UnlinkedFunctionExecutable(VM*, Structure*, const SourceCode&, RefPtr<SourceProvider>&& sourceOverride, FunctionMetadataNode*, UnlinkedFunctionKind, ConstructAbility, VariableEnvironment&, bool isDerivedConstructorContext);
-    
+    UnlinkedFunctionExecutable(VM*, Structure*, const SourceCode&, RefPtr<SourceProvider>&& sourceOverride, FunctionMetadataNode*, UnlinkedFunctionKind, ConstructAbility, VariableEnvironment&,  JSC::DerivedContextType);
+
     WriteBarrier<UnlinkedFunctionCodeBlock> m_unlinkedCodeBlockForCall;
     WriteBarrier<UnlinkedFunctionCodeBlock> m_unlinkedCodeBlockForConstruct;
 
@@ -163,7 +165,7 @@
     unsigned m_constructorKind : 2;
     unsigned m_functionMode : 1; // FunctionMode
     unsigned m_superBinding : 1;
-    unsigned m_isDerivedConstructorContext : 1;
+    unsigned m_derivedContextType: 2;
 
 protected:
     void finishCreation(VM& vm)

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (194448 => 194449)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2015-12-30 20:15:27 UTC (rev 194448)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2015-12-30 21:08:16 UTC (rev 194449)
@@ -157,7 +157,6 @@
     , m_thisRegister(CallFrame::thisArgumentOffset())
     , m_codeType(GlobalCode)
     , m_vm(&vm)
-    , m_isDerivedConstructorContext(false)
     , m_needsToUpdateArrowFunctionContext(programNode->usesArrowFunction() || programNode->usesEval())
 {
     ASSERT_UNUSED(parentScopeTDZVariables, !parentScopeTDZVariables->size());
@@ -211,8 +210,8 @@
     // compatible with tail calls (we have no way of emitting op_did_call).
     // https://bugs.webkit.org/show_bug.cgi?id=148819
     , m_inTailPosition(Options::useTailCalls() && !isConstructor() && constructorKind() == ConstructorKind::None && isStrictMode() && !m_shouldEmitProfileHooks)
-    , m_isDerivedConstructorContext(codeBlock->isDerivedConstructorContext())
     , m_needsToUpdateArrowFunctionContext(functionNode->usesArrowFunction() || functionNode->usesEval())
+    , m_derivedContextType(codeBlock->derivedContextType())
 {
     for (auto& constantRegister : m_linkTimeConstantRegisters)
         constantRegister = nullptr;
@@ -571,9 +570,9 @@
     // Loading |this| inside an arrow function must be done after initializeDefaultParameterValuesAndSetupFunctionScopeStack()
     // because that function sets up the SymbolTable stack and emitLoadThisFromArrowFunctionLexicalEnvironment()
     // consults the SymbolTable stack
-    if (parseMode == SourceParseMode::ArrowFunctionMode && functionNode->usesThis())
+    if (SourceParseMode::ArrowFunctionMode == parseMode && (functionNode->usesThis() || isDerivedClassContext() || isDerivedConstructorContext()))
         emitLoadThisFromArrowFunctionLexicalEnvironment();
-
+    
     if (needsToUpdateArrowFunctionContext() && !codeBlock->isArrowFunction()) {
         initializeArrowFunctionContextScopeIfNeeded(functionSymbolTable);
         emitPutThisToArrowFunctionContextScope();
@@ -593,8 +592,8 @@
     , m_codeType(EvalCode)
     , m_vm(&vm)
     , m_usesNonStrictEval(codeBlock->usesEval() && !codeBlock->isStrictMode())
-    , m_isDerivedConstructorContext(codeBlock->isDerivedConstructorContext())
     , m_needsToUpdateArrowFunctionContext(evalNode->usesArrowFunction() || evalNode->usesEval())
+    , m_derivedContextType(codeBlock->derivedContextType())
 {
     for (auto& constantRegister : m_linkTimeConstantRegisters)
         constantRegister = nullptr;
@@ -644,7 +643,6 @@
     , m_codeType(ModuleCode)
     , m_vm(&vm)
     , m_usesNonStrictEval(false)
-    , m_isDerivedConstructorContext(false)
     , m_needsToUpdateArrowFunctionContext(moduleProgramNode->usesArrowFunction() || moduleProgramNode->usesEval())
 {
     ASSERT_UNUSED(parentScopeTDZVariables, !parentScopeTDZVariables->size());
@@ -4047,14 +4045,14 @@
     
 void BytecodeGenerator::emitPutDerivedConstructorToArrowFunctionContextScope()
 {
-    if (isConstructor() && constructorKind() == ConstructorKind::Derived) {
+    if ((isConstructor() && constructorKind() == ConstructorKind::Derived) || m_codeBlock->isClassContext()) {
         ASSERT(m_arrowFunctionContextLexicalEnvironmentRegister);
             
         Variable protoScope = variable(propertyNames().derivedConstructorPrivateName);
         emitPutToScope(m_arrowFunctionContextLexicalEnvironmentRegister, protoScope, &m_calleeRegister, DoNotThrowIfNotFound, Initialization);
     }
 }
-    
+
 void BytecodeGenerator::emitPutThisToArrowFunctionContextScope()
 {
     ASSERT(isDerivedConstructorContext() || m_arrowFunctionContextLexicalEnvironmentRegister != nullptr);

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h (194448 => 194449)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2015-12-30 20:15:27 UTC (rev 194448)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2015-12-30 21:08:16 UTC (rev 194449)
@@ -281,7 +281,7 @@
         const CommonIdentifiers& propertyNames() const { return *m_vm->propertyNames; }
 
         bool isConstructor() const { return m_codeBlock->isConstructor(); }
-        bool isDerivedConstructorContext() const { return m_codeBlock->isDerivedConstructorContext(); }
+        DerivedContextType derivedContextType() const { return m_derivedContextType; }
         bool usesArrowFunction() const { return m_scopeNode->usesArrowFunction(); }
         bool needsToUpdateArrowFunctionContext() const { return m_needsToUpdateArrowFunctionContext; }
         bool usesEval() const { return m_scopeNode->usesEval(); }
@@ -697,6 +697,10 @@
         bool isBuiltinFunction() const { return m_isBuiltinFunction; }
 
         OpcodeID lastOpcodeID() const { return m_lastOpcodeID; }
+        
+        bool isDerivedConstructorContext() { return m_derivedContextType == DerivedContextType::DerivedConstructorContext; }
+        bool isDerivedClassContext() { return m_derivedContextType == DerivedContextType::DerivedMethodContext; }
+        bool isArrowFunction() { return m_codeBlock->isArrowFunction(); }
 
         enum class TDZCheckOptimization { Optimize, DoNotOptimize };
         enum class NestedScopeType { IsNested, IsNotNested };
@@ -794,8 +798,15 @@
         
         UnlinkedFunctionExecutable* makeFunction(FunctionMetadataNode* metadata)
         {
-            bool newisDerivedConstructorContext = constructorKind() == ConstructorKind::Derived || (m_isDerivedConstructorContext && metadata->parseMode() == SourceParseMode::ArrowFunctionMode);
+            DerivedContextType newDerivedContextType = DerivedContextType::None;
 
+            if (metadata->parseMode() == SourceParseMode::ArrowFunctionMode) {
+                if (constructorKind() == ConstructorKind::Derived || isDerivedConstructorContext())
+                    newDerivedContextType = DerivedContextType::DerivedConstructorContext;
+                else if (m_codeBlock->isClassContext() || isDerivedClassContext())
+                    newDerivedContextType = DerivedContextType::DerivedMethodContext;
+            }
+
             VariableEnvironment variablesUnderTDZ;
             getVariablesUnderTDZ(variablesUnderTDZ);
 
@@ -808,7 +819,7 @@
             else if (parseMode == SourceParseMode::MethodMode && metadata->constructorKind() == ConstructorKind::None)
                 constructAbility = ConstructAbility::CannotConstruct;
 
-            return UnlinkedFunctionExecutable::create(m_vm, m_scopeNode->source(), metadata, isBuiltinFunction() ? UnlinkedBuiltinFunction : UnlinkedNormalFunction, constructAbility, variablesUnderTDZ, newisDerivedConstructorContext);
+            return UnlinkedFunctionExecutable::create(m_vm, m_scopeNode->source(), metadata, isBuiltinFunction() ? UnlinkedBuiltinFunction : UnlinkedNormalFunction, constructAbility, variablesUnderTDZ, newDerivedContextType);
         }
 
         void getVariablesUnderTDZ(VariableEnvironment&);
@@ -918,9 +929,9 @@
         bool m_isBuiltinFunction { false };
         bool m_usesNonStrictEval { false };
         bool m_inTailPosition { false };
-        bool m_isDerivedConstructorContext { false };
         bool m_needsToUpdateArrowFunctionContext;
         bool m_isNewTargetLoadedInArrowFunction { false };
+        DerivedContextType m_derivedContextType { DerivedContextType::None };
     };
 
 }

Modified: trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp (194448 => 194449)


--- trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2015-12-30 20:15:27 UTC (rev 194448)
+++ trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2015-12-30 21:08:16 UTC (rev 194449)
@@ -173,12 +173,16 @@
 
     RegisterID callee;
     callee.setIndex(JSStack::Callee);
-
     return generator.emitGetById(generator.finalDestination(dst), &callee, generator.propertyNames().underscoreProto);
 }
 
 static RegisterID* emitHomeObjectForCallee(BytecodeGenerator& generator)
 {
+    if (generator.isDerivedClassContext() || generator.isDerivedConstructorContext()) {
+        RegisterID* derivedConstructor = generator.emitLoadDerivedConstructorFromArrowFunctionLexicalEnvironment();
+        return generator.emitGetById(generator.newTemporary(), derivedConstructor, generator.propertyNames().homeObjectPrivateName);
+    }
+
     RegisterID callee;
     callee.setIndex(JSStack::Callee);
     return generator.emitGetById(generator.newTemporary(), &callee, generator.propertyNames().homeObjectPrivateName);
@@ -749,8 +753,8 @@
     RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
     CallArguments callArguments(generator, m_args);
     if (m_expr->isSuperNode()) {
-        ASSERT(generator.isConstructor() || generator.isDerivedConstructorContext());
-        ASSERT(generator.constructorKind() == ConstructorKind::Derived || generator.isDerivedConstructorContext());
+        ASSERT(generator.isConstructor() || generator.derivedContextType() == DerivedContextType::DerivedConstructorContext);
+        ASSERT(generator.constructorKind() == ConstructorKind::Derived || generator.derivedContextType() == DerivedContextType::DerivedConstructorContext);
         generator.emitMove(callArguments.thisRegister(), generator.newTarget());
         RegisterID* ret = generator.emitConstruct(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
         generator.emitMove(generator.thisRegister(), ret);

Modified: trunk/Source/_javascript_Core/debugger/DebuggerCallFrame.cpp (194448 => 194449)


--- trunk/Source/_javascript_Core/debugger/DebuggerCallFrame.cpp	2015-12-30 20:15:27 UTC (rev 194448)
+++ trunk/Source/_javascript_Core/debugger/DebuggerCallFrame.cpp	2015-12-30 21:08:16 UTC (rev 194449)
@@ -192,7 +192,7 @@
     VariableEnvironment variablesUnderTDZ;
     JSScope::collectVariablesUnderTDZ(scope()->jsScope(), variablesUnderTDZ);
 
-    EvalExecutable* eval = EvalExecutable::create(callFrame, makeSource(script), codeBlock.isStrictMode(), thisTDZMode, codeBlock.unlinkedCodeBlock()->isDerivedConstructorContext(), codeBlock.unlinkedCodeBlock()->isArrowFunction(), &variablesUnderTDZ);
+    EvalExecutable* eval = EvalExecutable::create(callFrame, makeSource(script), codeBlock.isStrictMode(), thisTDZMode, codeBlock.unlinkedCodeBlock()->derivedContextType(), codeBlock.unlinkedCodeBlock()->isArrowFunction(), &variablesUnderTDZ);
     if (vm.exception()) {
         exception = vm.exception();
         vm.clearException();

Modified: trunk/Source/_javascript_Core/interpreter/Interpreter.cpp (194448 => 194449)


--- trunk/Source/_javascript_Core/interpreter/Interpreter.cpp	2015-12-30 20:15:27 UTC (rev 194448)
+++ trunk/Source/_javascript_Core/interpreter/Interpreter.cpp	2015-12-30 21:08:16 UTC (rev 194449)
@@ -183,7 +183,7 @@
         // If the literal parser bailed, it should not have thrown exceptions.
         ASSERT(!callFrame->vm().exception());
 
-        eval = callerCodeBlock->evalCodeCache().getSlow(callFrame, callerCodeBlock, callerCodeBlock->isStrictMode(), thisTDZMode, callerCodeBlock->unlinkedCodeBlock()->isDerivedConstructorContext(), callerCodeBlock->unlinkedCodeBlock()->isArrowFunction(), sourceCode, callerScopeChain);
+        eval = callerCodeBlock->evalCodeCache().getSlow(callFrame, callerCodeBlock, callerCodeBlock->isStrictMode(), thisTDZMode, callerCodeBlock->unlinkedCodeBlock()->derivedContextType(), callerCodeBlock->unlinkedCodeBlock()->isArrowFunction(), sourceCode, callerScopeChain);
 
         if (!eval)
             return jsUndefined();

Modified: trunk/Source/_javascript_Core/runtime/CodeCache.cpp (194448 => 194449)


--- trunk/Source/_javascript_Core/runtime/CodeCache.cpp	2015-12-30 20:15:27 UTC (rev 194448)
+++ trunk/Source/_javascript_Core/runtime/CodeCache.cpp	2015-12-30 21:08:16 UTC (rev 194449)
@@ -188,7 +188,8 @@
     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, emptyTDZVariables, false);
+    UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(&vm, source, metadata, UnlinkedNormalFunction, ConstructAbility::CanConstruct, emptyTDZVariables, DerivedContextType::None);
+
     functionExecutable->m_nameValue.set(vm, functionExecutable, jsString(&vm, name.string()));
 
     m_sourceCode.addCache(key, SourceCodeValue(vm, functionExecutable, m_sourceCode.age()));

Modified: trunk/Source/_javascript_Core/runtime/Executable.cpp (194448 => 194449)


--- trunk/Source/_javascript_Core/runtime/Executable.cpp	2015-12-30 20:15:27 UTC (rev 194448)
+++ trunk/Source/_javascript_Core/runtime/Executable.cpp	2015-12-30 21:08:16 UTC (rev 194449)
@@ -131,14 +131,14 @@
 
 const ClassInfo ScriptExecutable::s_info = { "ScriptExecutable", &ExecutableBase::s_info, 0, CREATE_METHOD_TABLE(ScriptExecutable) };
 
-ScriptExecutable::ScriptExecutable(Structure* structure, VM& vm, const SourceCode& source, bool isInStrictContext, bool isInDerivedConstructorContext, bool isInArrowFunctionContext)
+ScriptExecutable::ScriptExecutable(Structure* structure, VM& vm, const SourceCode& source, bool isInStrictContext, DerivedContextType derivedContextType, bool isInArrowFunctionContext)
     : ExecutableBase(vm, structure, NUM_PARAMETERS_NOT_COMPILED)
     , m_source(source)
     , m_features(isInStrictContext ? StrictModeFeature : 0)
     , m_hasCapturedVariables(false)
     , m_neverInline(false)
     , m_didTryToEnterInLoop(false)
-    , m_isDerivedConstructorContext(isInDerivedConstructorContext)
+    , m_derivedContextType(derivedContextType)
     , m_isArrowFunctionContext(isInArrowFunctionContext)
     , m_overrideLineNumber(-1)
     , m_firstLine(-1)
@@ -414,7 +414,7 @@
 
 const ClassInfo EvalExecutable::s_info = { "EvalExecutable", &ScriptExecutable::s_info, 0, CREATE_METHOD_TABLE(EvalExecutable) };
 
-EvalExecutable* EvalExecutable::create(ExecState* exec, const SourceCode& source, bool isInStrictContext, ThisTDZMode thisTDZMode, bool isDerivedConstructorContext, bool isArrowFunctionContext, const VariableEnvironment* variablesUnderTDZ)
+EvalExecutable* EvalExecutable::create(ExecState* exec, const SourceCode& source, bool isInStrictContext, ThisTDZMode thisTDZMode, DerivedContextType derivedContextType, bool isArrowFunctionContext, const VariableEnvironment* variablesUnderTDZ)
 {
     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
     if (!globalObject->evalEnabled()) {
@@ -422,7 +422,7 @@
         return 0;
     }
 
-    EvalExecutable* executable = new (NotNull, allocateCell<EvalExecutable>(*exec->heap())) EvalExecutable(exec, source, isInStrictContext, isDerivedConstructorContext, isArrowFunctionContext);
+    EvalExecutable* executable = new (NotNull, allocateCell<EvalExecutable>(*exec->heap())) EvalExecutable(exec, source, isInStrictContext, derivedContextType, isArrowFunctionContext);
     executable->finishCreation(exec->vm());
 
     UnlinkedEvalCodeBlock* unlinkedEvalCode = globalObject->createEvalCodeBlock(exec, executable, thisTDZMode, isArrowFunctionContext, variablesUnderTDZ);
@@ -434,8 +434,8 @@
     return executable;
 }
 
-EvalExecutable::EvalExecutable(ExecState* exec, const SourceCode& source, bool inStrictContext, bool isDerivedConstructorContext, bool isArrowFunctionContext)
-    : ScriptExecutable(exec->vm().evalExecutableStructure.get(), exec->vm(), source, inStrictContext, isDerivedConstructorContext, isArrowFunctionContext)
+EvalExecutable::EvalExecutable(ExecState* exec, const SourceCode& source, bool inStrictContext, DerivedContextType derivedContextType, bool isArrowFunctionContext)
+    : ScriptExecutable(exec->vm().evalExecutableStructure.get(), exec->vm(), source, inStrictContext, derivedContextType, isArrowFunctionContext)
 {
 }
 
@@ -447,7 +447,7 @@
 const ClassInfo ProgramExecutable::s_info = { "ProgramExecutable", &ScriptExecutable::s_info, 0, CREATE_METHOD_TABLE(ProgramExecutable) };
 
 ProgramExecutable::ProgramExecutable(ExecState* exec, const SourceCode& source)
-    : ScriptExecutable(exec->vm().programExecutableStructure.get(), exec->vm(), source, false, false, false)
+    : ScriptExecutable(exec->vm().programExecutableStructure.get(), exec->vm(), source, false, DerivedContextType::None, false)
 {
     m_typeProfilingStartOffset = 0;
     m_typeProfilingEndOffset = source.length() - 1;
@@ -463,7 +463,7 @@
 const ClassInfo ModuleProgramExecutable::s_info = { "ModuleProgramExecutable", &ScriptExecutable::s_info, 0, CREATE_METHOD_TABLE(ModuleProgramExecutable) };
 
 ModuleProgramExecutable::ModuleProgramExecutable(ExecState* exec, const SourceCode& source)
-    : ScriptExecutable(exec->vm().moduleProgramExecutableStructure.get(), exec->vm(), source, false, false, false)
+    : ScriptExecutable(exec->vm().moduleProgramExecutableStructure.get(), exec->vm(), source, false, DerivedContextType::None, false)
 {
     m_typeProfilingStartOffset = 0;
     m_typeProfilingEndOffset = source.length() - 1;
@@ -495,7 +495,7 @@
 const ClassInfo FunctionExecutable::s_info = { "FunctionExecutable", &ScriptExecutable::s_info, 0, CREATE_METHOD_TABLE(FunctionExecutable) };
 
 FunctionExecutable::FunctionExecutable(VM& vm, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, unsigned firstLine, unsigned lastLine, unsigned startColumn, unsigned endColumn)
-    : ScriptExecutable(vm.functionExecutableStructure.get(), vm, source, unlinkedExecutable->isInStrictContext(), unlinkedExecutable->isDerivedConstructorContext(), false)
+    : ScriptExecutable(vm.functionExecutableStructure.get(), vm, source, unlinkedExecutable->isInStrictContext(), unlinkedExecutable->derivedContextType(), false)
     , m_unlinkedExecutable(vm, this, unlinkedExecutable)
 {
     RELEASE_ASSERT(!source.isNull());

Modified: trunk/Source/_javascript_Core/runtime/Executable.h (194448 => 194449)


--- trunk/Source/_javascript_Core/runtime/Executable.h	2015-12-30 20:15:27 UTC (rev 194448)
+++ trunk/Source/_javascript_Core/runtime/Executable.h	2015-12-30 21:08:16 UTC (rev 194449)
@@ -346,7 +346,8 @@
     bool needsActivation() const { return m_hasCapturedVariables || m_features & (EvalFeature | WithFeature); }
     bool isArrowFunctionContext() const { return m_isArrowFunctionContext; }
     bool isStrictMode() const { return m_features & StrictModeFeature; }
-    bool isDerivedConstructorContext() const { return m_isDerivedConstructorContext; }
+    DerivedContextType derivedContextType() const { return m_derivedContextType; }
+
     ECMAMode ecmaMode() const { return isStrictMode() ? StrictMode : NotStrictMode; }
         
     void setNeverInline(bool value) { m_neverInline = value; }
@@ -395,7 +396,7 @@
     JSObject* prepareForExecutionImpl(ExecState*, JSFunction*, JSScope*, CodeSpecializationKind);
 
 protected:
-    ScriptExecutable(Structure*, VM&, const SourceCode&, bool isInStrictContext, bool isInDerivedConstructorContext, bool isInArrowFunctionContext);
+    ScriptExecutable(Structure*, VM&, const SourceCode&, bool isInStrictContext, DerivedContextType, bool isInArrowFunctionContext);
 
     void finishCreation(VM& vm)
     {
@@ -414,7 +415,7 @@
     bool m_neverInline;
     bool m_neverOptimize { false };
     bool m_didTryToEnterInLoop;
-    bool m_isDerivedConstructorContext;
+    DerivedContextType m_derivedContextType;
     bool m_isArrowFunctionContext;
     int m_overrideLineNumber;
     int m_firstLine;
@@ -438,7 +439,7 @@
         return m_evalCodeBlock.get();
     }
 
-    static EvalExecutable* create(ExecState*, const SourceCode&, bool isInStrictContext, ThisTDZMode, bool isDerivedConstructorContext, bool isArrowFunctionContext, const VariableEnvironment*);
+    static EvalExecutable* create(ExecState*, const SourceCode&, bool isInStrictContext, ThisTDZMode, DerivedContextType, bool isArrowFunctionContext, const VariableEnvironment*);
 
     PassRefPtr<JITCode> generatedJITCode()
     {
@@ -452,17 +453,17 @@
         
     DECLARE_INFO;
 
+    ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false, false, ConstructorKind::None, SuperBinding::NotNeeded, SourceParseMode::ProgramMode, derivedContextType(), isArrowFunctionContext() , false); }
 
-    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(); }
 
 private:
     friend class ExecutableBase;
     friend class ScriptExecutable;
-    EvalExecutable(ExecState*, const SourceCode&, bool inStrictContext, bool isDerivedConstructorContext, bool isArrowFunctionContext);
 
+    EvalExecutable(ExecState*, const SourceCode&, bool inStrictContext, DerivedContextType, bool isArrowFunctionContext);
+
     static void visitChildren(JSCell*, SlotVisitor&);
 
     WriteBarrier<EvalCodeBlock> m_evalCodeBlock;
@@ -506,7 +507,7 @@
         
     DECLARE_INFO;
 
-    ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false, false, ConstructorKind::None, SuperBinding::NotNeeded, SourceParseMode::ProgramMode, isDerivedConstructorContext(), false); }
+    ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false, false, ConstructorKind::None, SuperBinding::NotNeeded, SourceParseMode::ProgramMode, derivedContextType(), isArrowFunctionContext(), false); }
 
 private:
     friend class ExecutableBase;
@@ -547,7 +548,7 @@
 
     DECLARE_INFO;
 
-    ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false, false, ConstructorKind::None, SuperBinding::NotNeeded, SourceParseMode::ModuleEvaluateMode, isDerivedConstructorContext(), false); }
+    ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false, false, ConstructorKind::None, SuperBinding::NotNeeded, SourceParseMode::ModuleEvaluateMode, derivedContextType(), isArrowFunctionContext(), false); }
 
     UnlinkedModuleProgramCodeBlock* unlinkedModuleProgramCodeBlock() { return m_unlinkedModuleProgramCodeBlock.get(); }
 
@@ -657,7 +658,7 @@
     bool isBuiltinFunction() const { return m_unlinkedExecutable->isBuiltinFunction(); }
     ConstructAbility constructAbility() const { return m_unlinkedExecutable->constructAbility(); }
     bool isArrowFunction() const { return parseMode() == SourceParseMode::ArrowFunctionMode; }
-    bool isDerivedConstructorContext() const { return m_unlinkedExecutable->isDerivedConstructorContext(); }
+    DerivedContextType derivedContextType() const { return m_unlinkedExecutable->derivedContextType(); }
     bool isClassConstructorFunction() const { return m_unlinkedExecutable->isClassConstructorFunction(); }
     const Identifier& name() { return m_unlinkedExecutable->name(); }
     const Identifier& inferredName() { return m_unlinkedExecutable->inferredName(); }

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.cpp (194448 => 194449)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.cpp	2015-12-30 20:15:27 UTC (rev 194448)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.cpp	2015-12-30 21:08:16 UTC (rev 194449)
@@ -587,7 +587,7 @@
 
     JSGlobalObject* calleeGlobalObject = exec->callee()->globalObject();
     VariableEnvironment emptyTDZVariables; // Indirect eval does not have access to the lexical scope.
-    EvalExecutable* eval = EvalExecutable::create(exec, makeSource(s), false, ThisTDZMode::CheckIfNeeded, false, false, &emptyTDZVariables);
+    EvalExecutable* eval = EvalExecutable::create(exec, makeSource(s), false, ThisTDZMode::CheckIfNeeded, DerivedContextType::None, false, &emptyTDZVariables);
     if (!eval)
         return JSValue::encode(jsUndefined());
 

Modified: trunk/Source/_javascript_Core/tests/es6.yaml (194448 => 194449)


--- trunk/Source/_javascript_Core/tests/es6.yaml	2015-12-30 20:15:27 UTC (rev 194448)
+++ trunk/Source/_javascript_Core/tests/es6.yaml	2015-12-30 21:08:16 UTC (rev 194449)
@@ -747,7 +747,7 @@
 - path: es6/arrow_functions_lexical_new.target_binding.js
   cmd: runES6 :normal
 - path: es6/arrow_functions_lexical_super_binding.js
-  cmd: runES6 :fail
+  cmd: runES6 :normal
 - path: es6/arrow_functions_no_prototype_property.js
   cmd: runES6 :normal
 - path: es6/block-level_function_declaration.js

Added: trunk/Source/_javascript_Core/tests/stress/arrowfunction-lexical-bind-superproperty.js (0 => 194449)


--- trunk/Source/_javascript_Core/tests/stress/arrowfunction-lexical-bind-superproperty.js	                        (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/arrowfunction-lexical-bind-superproperty.js	2015-12-30 21:08:16 UTC (rev 194449)
@@ -0,0 +1,224 @@
+var testCase = function (actual, expected, message) {
+    if (actual !== expected) {
+        throw message + ". Expected '" + expected + "', but was '" + actual + "'";
+    }
+};
+
+var testValue  = 'test-value';
+
+var A = class A {
+    constructor() {
+        this.value = testValue;
+    }
+    getConstValue () {
+        return testValue;
+    }
+    getValue () {
+        return this.value;
+    }
+    setValue (value) {
+        this.value = value;
+    }
+};
+
+var B = class B extends A {
+    getParentValue() {
+        var arrow  = () => super.getValue();
+        return arrow();
+    }
+};
+
+var C = class C {
+    constructor() {
+        this.value = testValue;
+    }
+    static getStaticValue() {
+        return testValue;
+    }
+};
+
+var D = class D extends C {
+    static getParentStaticValue() {
+        var arrow  = () => super.getStaticValue();
+        return arrow();
+    }
+};
+
+var E = class E extends A {
+     constructor() {
+         super();
+     }
+     get prop() {
+         var arrow = () => super.getConstValue() + '-' + this.value;
+         return arrow();
+     }
+     set prop(value) {
+         var arrow = (newVal) => super.setValue(newVal);
+         arrow(value);
+     }
+     setInitValue() {
+       this.value = testValue;
+     }
+ };
+
+var b = new B();
+for (var i = 0; i < 10000; i++) {
+    testCase(b.getParentValue(), testValue, i);
+}
+
+for (var i = 0; i < 10000; i++) {
+    testCase(D.getParentStaticValue(), testValue, i);
+}
+
+var e = new E();
+for (var i = 0; i < 10000; i++) {
+     e.setInitValue();
+     testCase(e.prop, testValue+'-'+testValue, i);
+     e.prop = 'new-test-value';
+     testCase(e.prop, testValue+'-new-test-value', i);
+}
+
+var F  = class F extends A {
+    newMethod() {
+        var arrow  = () => eval('super.getValue()');
+        var r = arrow();
+        return r;
+    }
+};
+
+var f = new F();
+for (var i=0; i < 10000; i++) {
+    try {
+        var result = f.newMethod();
+        testCase(result, testValue, i);
+     } catch(e) {
+        if (!(e instanceof SyntaxError))
+           throw e;
+     }
+}
+
+var G = class G extends A {
+     constructor() {
+         super();
+     }
+     get prop() {
+         var arrow = () => () => super.getConstValue() + '-' + this.value;
+         return arrow()();
+     }
+     set prop(value) {
+         var arrow =  () => (newVal) => this.value = newVal;
+         arrow()(value);
+     }
+     setInitValue() {
+         this.value = testValue;
+     }
+     getValueCB() {
+         var arrow  = () => super.getValue();
+         return arrow;
+     }
+     setValueCB() {
+         var arrow =  (newVal) => this.value = newVal;
+         return arrow;
+     }
+     getParentValue() {
+         return super.getValue();
+     }
+     getParentValueWithError() {
+         var f =  function () {
+             return () => super.getValue();
+         };
+         return f();
+     }
+ };
+
+ var g = new G();
+ for (var i = 0; i < 10000; i++) {
+    g.setInitValue();
+    testCase(g.prop, testValue + '-' + testValue, 'Error: Some problem with using arrow and "super" inside of the method');
+    g.prop = 'new-test-value';
+    testCase(g.prop, testValue + '-new-test-value', 'Error: Some problem with using arrow and "super" inside of the getter and setter');
+ }
+
+var g1 = new G();
+for (var i = 0; i < 10000; i++) {
+    g1.setInitValue();
+    let getValue = g1.getValueCB();
+    testCase(getValue(), testValue,  'Error: Some problem with using arrow and "super" inside of the method that retun arrow function');
+    let setValue = g1.setValueCB();
+    setValue('new-value');
+    testCase(getValue(), 'new-value', 'Error: Some problem with using arrow and "super" inside of the method that retun arrow function');
+}
+
+var g2 = new G();
+for (var i = 0; i < 10000; i++) {
+    let error = false;
+    try {
+       g2.getParentValueWithError()();
+    } catch(e) {
+      // FIXME: should by check if e instanceof SyntaxError
+      // https://bugs.webkit.org/show_bug.cgi?id=150893
+      error = true;
+    }
+    testCase(error, true, 'Error: using "super" should lead to error');
+}
+
+
+var H = class H extends A {
+    constructor() {
+        var arrow = () => () => super.getValue();
+        super();
+        this.newValue  = arrow()();
+    }
+};
+
+for (var i = 0; i < 10000; i++) {
+    let h = new H();
+    testCase(h.newValue, testValue, 'Error: Some problem with using "super" inside of the constructor');
+}
+
+var I = class I extends A {
+    constructor (beforeSuper) {
+        var arrow = () => super.getValue();
+        if (beforeSuper)  {
+            this._value = arrow();
+            super();
+        } else {
+            super();
+            this._value = arrow();
+        }
+    }
+}
+
+var J = class J extends A {
+    constructor (beforeSuper) {
+        var _value;
+        var arrow = () => super.getConstValue();
+        if (beforeSuper)  {
+            _value = arrow();
+            super();
+         } else {
+            super();
+            _value = arrow();
+        }
+        this._value = _value;
+    }
+}
+
+for (var i = 0; i < 10000; i++) {
+    let i = new I(false);
+    testCase(i._value, testValue, 'Error: Some problem with using "super" inside of the constructor');
+    let j = new J(false);
+    testCase(j._value, testValue, 'Error: Some problem with using "super" inside of the constructor');
+
+    // FIXME: Problem with access to the super before super() in constructor
+    // https://bugs.webkit.org/show_bug.cgi?id=152108
+    //let j2 = new J(true);
+    //testCase(j2._value, testValue, 'Error: Some problem with using "super" inside of the constructor');
+    error = false;
+    try {
+        new I(true);
+    } catch (e) {
+        error = e instanceof ReferenceError;
+    }
+    testCase(error, true, 'Error: using "super" property before super() should lead to error');
+}
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to