Changeset 181293 in webkit


Ignore:
Timestamp:
Mar 9, 2015 4:47:06 PM (9 years ago)
Author:
rniwa@webkit.org
Message:

Support extends and super keywords
https://bugs.webkit.org/show_bug.cgi?id=142200

Reviewed by Filip Pizlo.

Source/JavaScriptCore:

Added the support for ES6 class syntax inheritance.

Added ConstructorKind as well as boolean flags indicating the constructor kind to
various classes in UnlinkedCodeBlock as well as AST nodes.

Each method stores the associated class as its homeObjectPrivateName. This value is used to
make super calls.

  • bytecode/UnlinkedCodeBlock.cpp:

(JSC::generateFunctionCodeBlock):
(JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):
(JSC::UnlinkedCodeBlock::UnlinkedCodeBlock):

  • bytecode/UnlinkedCodeBlock.h:

(JSC::ExecutableInfo::ExecutableInfo):
(JSC::UnlinkedFunctionExecutable::constructorKindIsDerived): Added.
(JSC::UnlinkedCodeBlock::constructorKindIsDerived): Added.

  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::BytecodeGenerator): Don't emit op_create_this in a derived class
as the object is allocated by the highest base class's constructor. Also set "this" to null
and store the original value in m_newTargetRegister. "this" is supposed to be in TDZ but
that will be implemented in a separate patch.
(JSC::BytecodeGenerator::emitReturn): Allow "undefined" to be returned from a derived class.
In a derived class's constructor, not returning "undefined" or an object results in a type
error instead of "this" being returned.
(JSC::BytecodeGenerator::emitThrowTypeError): Added.

  • bytecompiler/BytecodeGenerator.h:

(JSC::BytecodeGenerator::constructorKindIsDerived): Added.
(JSC::BytecodeGenerator::newTarget): Added.

  • bytecompiler/NodesCodegen.cpp:

(JSC::SuperNode::emitBytecode): Added. Emits the code to obtain the callee's parent class.
(JSC::emitSuperBaseForCallee): Added. Emits the code to obtain the parent class's prototype.
(JSC::emitPutHomeObject): Added.
(JSC::PropertyListNode::emitBytecode): Stores the home object when adding methods.
(JSC::PropertyListNode::emitPutConstantProperty): Ditto.
(JSC::BracketAccessorNode::emitBytecode): Added the support for superfoo?.
(JSC::DotAccessorNode::emitBytecode): Added the support for super.foo.
(JSC::FunctionCallValueNode::emitBytecode): Added the support for super().
(JSC::FunctionCallBracketNode::emitBytecode): Added the support for superfoo?().
(JSC::FunctionCallDotNode::emitBytecode): Added the support for super.foo().
(JSC::DeleteBracketNode::emitBytecode): Forbid "delete super.foo".
(JSC::DeleteDotNode::emitBytecode): Forbid "delete superfoo?".
(JSC::ClassExprNode::emitBytecode): Added the support for "classHeritage". This is the main
logic for inheritance. When a class B inherits from a class A, set B.proto to A and set
B.prototype.proto to A.prototype. Throw exceptions when either A or A.proto is not
an object.

  • parser/ASTBuilder.h:

(JSC::ASTBuilder::superExpr): Added.

  • parser/NodeConstructors.h:

(JSC::SuperNode::SuperNode): Added.

  • parser/Nodes.cpp:

(JSC::FunctionBodyNode::FunctionBodyNode):

  • parser/Nodes.h:

(JSC::ExpressionNode::isSuperNode):
(JSC::PropertyNode::type):
(JSC::PropertyNode::needsSuperBinding):

  • parser/Parser.cpp:

(JSC::Parser<LexerType>::parseFunctionBody):
(JSC::Parser<LexerType>::parseFunctionInfo): Throw a parser error if super() is used outside
of class constructors.
(JSC::Parser<LexerType>::parseFunctionDeclaration):
(JSC::Parser<LexerType>::parseClass): ConstructorKind is "derived" if and only if the parent
class is specified in the declaration / expression.
(JSC::Parser<LexerType>::parseGetterSetter):
(JSC::Parser<LexerType>::parsePrimaryExpression):
(JSC::Parser<LexerType>::parseMemberExpression): Added the support for "super()", "super.foo",
and "superfoo?". Throw a semantic error if "super" appears by itself.

  • parser/Parser.h:

(JSC::Scope::Scope): Added m_hasDirectSuper. This variable keeps track of the use of "super()"
so that parseFunctionInfo can spit an error if it's used outside of class constructors.
(JSC::Scope::hasDirectSuper): Added.
(JSC::Scope::setHasDirectSuper): Added.

  • parser/ParserModes.h:

(JSC::ConstructorKind): Added.

  • parser/SyntaxChecker.h:

(JSC::SyntaxChecker::superExpr): Added.

  • runtime/CommonIdentifiers.h: Added homeObjectPrivateName.
  • runtime/Executable.h:

(JSC::EvalExecutable::executableInfo):
(JSC::ProgramExecutable::executableInfo):

LayoutTests:

Added tests for "extends" and "super" keywords.

  • TestExpectations:
  • js/class-syntax-extends-expected.txt: Added.
  • js/class-syntax-extends.html: Added.
  • js/class-syntax-super-expected.txt: Added.
  • js/class-syntax-super.html: Added.
  • js/script-tests/class-syntax-extends.js: Added.
  • js/script-tests/class-syntax-super.js: Added.
Location:
trunk
Files:
6 added
18 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r181292 r181293  
     12015-03-09  Ryosuke Niwa  <rniwa@webkit.org>
     2
     3        Support extends and super keywords
     4        https://bugs.webkit.org/show_bug.cgi?id=142200
     5
     6        Reviewed by Filip Pizlo.
     7
     8        Added tests for "extends" and "super" keywords.
     9
     10        * TestExpectations:
     11        * js/class-syntax-extends-expected.txt: Added.
     12        * js/class-syntax-extends.html: Added.
     13        * js/class-syntax-super-expected.txt: Added.
     14        * js/class-syntax-super.html: Added.
     15        * js/script-tests/class-syntax-extends.js: Added.
     16        * js/script-tests/class-syntax-super.js: Added.
     17
    1182015-03-09  Myles C. Maxfield  <mmaxfield@apple.com>
    219
  • trunk/LayoutTests/TestExpectations

    r181132 r181293  
    7070webkit.org/b/140491 js/class-syntax-declaration.html [ Failure ]
    7171webkit.org/b/140491 js/class-syntax-expression.html [ Failure ]
     72webkit.org/b/140491 js/class-syntax-extends.html [ Failure ]
     73webkit.org/b/140491 js/class-syntax-super.html [ Failure ]
    7274
    7375# This test verifies dynamic manipulation of the mroot and msqrt elements.
  • trunk/Source/JavaScriptCore/ChangeLog

    r181250 r181293  
     12015-03-09  Ryosuke Niwa  <rniwa@webkit.org>
     2
     3        Support extends and super keywords
     4        https://bugs.webkit.org/show_bug.cgi?id=142200
     5
     6        Reviewed by Filip Pizlo.
     7
     8        Added the support for ES6 class syntax inheritance.
     9
     10        Added ConstructorKind as well as boolean flags indicating the constructor kind to
     11        various classes in UnlinkedCodeBlock as well as AST nodes.
     12
     13        Each method stores the associated class as its homeObjectPrivateName. This value is used to
     14        make super calls.
     15
     16        * bytecode/UnlinkedCodeBlock.cpp:
     17        (JSC::generateFunctionCodeBlock):
     18        (JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):
     19        (JSC::UnlinkedCodeBlock::UnlinkedCodeBlock):
     20
     21        * bytecode/UnlinkedCodeBlock.h:
     22        (JSC::ExecutableInfo::ExecutableInfo):
     23        (JSC::UnlinkedFunctionExecutable::constructorKindIsDerived): Added.
     24        (JSC::UnlinkedCodeBlock::constructorKindIsDerived): Added.
     25
     26        * bytecompiler/BytecodeGenerator.cpp:
     27        (JSC::BytecodeGenerator::BytecodeGenerator): Don't emit op_create_this in a derived class
     28        as the object is allocated by the highest base class's constructor. Also set "this" to null
     29        and store the original value in m_newTargetRegister. "this" is supposed to be in TDZ but
     30        that will be implemented in a separate patch.
     31        (JSC::BytecodeGenerator::emitReturn): Allow "undefined" to be returned from a derived class.
     32        In a derived class's constructor, not returning "undefined" or an object results in a type
     33        error instead of "this" being returned.
     34        (JSC::BytecodeGenerator::emitThrowTypeError): Added.
     35
     36        * bytecompiler/BytecodeGenerator.h:
     37        (JSC::BytecodeGenerator::constructorKindIsDerived): Added.
     38        (JSC::BytecodeGenerator::newTarget): Added.
     39
     40        * bytecompiler/NodesCodegen.cpp:
     41        (JSC::SuperNode::emitBytecode): Added. Emits the code to obtain the callee's parent class.
     42        (JSC::emitSuperBaseForCallee): Added. Emits the code to obtain the parent class's prototype.
     43        (JSC::emitPutHomeObject): Added.
     44        (JSC::PropertyListNode::emitBytecode): Stores the home object when adding methods.
     45        (JSC::PropertyListNode::emitPutConstantProperty): Ditto.
     46        (JSC::BracketAccessorNode::emitBytecode): Added the support for super['foo'].
     47        (JSC::DotAccessorNode::emitBytecode): Added the support for super.foo.
     48        (JSC::FunctionCallValueNode::emitBytecode): Added the support for super().
     49        (JSC::FunctionCallBracketNode::emitBytecode): Added the support for super['foo']().
     50        (JSC::FunctionCallDotNode::emitBytecode): Added the support for super.foo().
     51        (JSC::DeleteBracketNode::emitBytecode): Forbid "delete super.foo".
     52        (JSC::DeleteDotNode::emitBytecode): Forbid "delete super['foo']".
     53        (JSC::ClassExprNode::emitBytecode): Added the support for "classHeritage". This is the main
     54        logic for inheritance. When a class B inherits from a class A, set B.__proto__ to A and set
     55        B.prototype.__proto__ to A.prototype. Throw exceptions when either A or A.__proto__ is not
     56        an object.
     57
     58        * parser/ASTBuilder.h:
     59        (JSC::ASTBuilder::superExpr): Added.
     60
     61        * parser/NodeConstructors.h:
     62        (JSC::SuperNode::SuperNode): Added.
     63
     64        * parser/Nodes.cpp:
     65        (JSC::FunctionBodyNode::FunctionBodyNode):
     66
     67        * parser/Nodes.h:
     68        (JSC::ExpressionNode::isSuperNode):
     69        (JSC::PropertyNode::type):
     70        (JSC::PropertyNode::needsSuperBinding):
     71
     72        * parser/Parser.cpp:
     73        (JSC::Parser<LexerType>::parseFunctionBody):
     74        (JSC::Parser<LexerType>::parseFunctionInfo): Throw a parser error if super() is used outside
     75        of class constructors.
     76        (JSC::Parser<LexerType>::parseFunctionDeclaration):
     77        (JSC::Parser<LexerType>::parseClass): ConstructorKind is "derived" if and only if the parent
     78        class is specified in the declaration / expression.
     79        (JSC::Parser<LexerType>::parseGetterSetter):
     80        (JSC::Parser<LexerType>::parsePrimaryExpression):
     81        (JSC::Parser<LexerType>::parseMemberExpression): Added the support for "super()", "super.foo",
     82        and "super['foo']". Throw a semantic error if "super" appears by itself.
     83
     84        * parser/Parser.h:
     85        (JSC::Scope::Scope): Added m_hasDirectSuper. This variable keeps track of the use of "super()"
     86        so that parseFunctionInfo can spit an error if it's used outside of class constructors.
     87        (JSC::Scope::hasDirectSuper): Added.
     88        (JSC::Scope::setHasDirectSuper): Added.
     89
     90        * parser/ParserModes.h:
     91        (JSC::ConstructorKind): Added.
     92
     93        * parser/SyntaxChecker.h:
     94        (JSC::SyntaxChecker::superExpr): Added.
     95
     96        * runtime/CommonIdentifiers.h: Added homeObjectPrivateName.
     97
     98        * runtime/Executable.h:
     99        (JSC::EvalExecutable::executableInfo):
     100        (JSC::ProgramExecutable::executableInfo):
     101
    11022015-03-08  Andreas Kling  <akling@apple.com>
    2103
  • trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp

    r181213 r181293  
    6262    executable->recordParse(function->features(), function->hasCapturedVariables());
    6363   
    64     UnlinkedFunctionCodeBlock* result = UnlinkedFunctionCodeBlock::create(&vm, FunctionCode, ExecutableInfo(function->needsActivation(), function->usesEval(), function->isStrictMode(), kind == CodeForConstruct, functionKind == UnlinkedBuiltinFunction));
     64    UnlinkedFunctionCodeBlock* result = UnlinkedFunctionCodeBlock::create(&vm, FunctionCode,
     65        ExecutableInfo(function->needsActivation(), function->usesEval(), function->isStrictMode(), kind == CodeForConstruct, functionKind == UnlinkedBuiltinFunction, executable->constructorKindIsDerived()));
    6566    auto generator(std::make_unique<BytecodeGenerator>(vm, function.get(), result, debuggerMode, profilerMode));
    6667    error = generator->generate();
     
    8586    , m_hasCapturedVariables(false)
    8687    , m_isBuiltinFunction(kind == UnlinkedBuiltinFunction)
     88    , m_constructorKindIsDerived(node->constructorKindIsDerived())
    8789    , m_name(node->ident())
    8890    , m_inferredName(node->inferredName())
     
    230232    , m_hasCapturedVariables(false)
    231233    , m_isBuiltinFunction(info.m_isBuiltinFunction)
     234    , m_constructorKindIsDerived(info.m_constructorKindIsDerived)
    232235    , m_firstLine(0)
    233236    , m_lineCount(0)
  • trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h

    r181213 r181293  
    6666
    6767struct ExecutableInfo {
    68     ExecutableInfo(bool needsActivation, bool usesEval, bool isStrictMode, bool isConstructor, bool isBuiltinFunction)
     68    ExecutableInfo(bool needsActivation, bool usesEval, bool isStrictMode, bool isConstructor, bool isBuiltinFunction, bool constructorKindIsDerived)
    6969        : m_needsActivation(needsActivation)
    7070        , m_usesEval(usesEval)
     
    7272        , m_isConstructor(isConstructor)
    7373        , m_isBuiltinFunction(isBuiltinFunction)
     74        , m_constructorKindIsDerived(constructorKindIsDerived)
    7475    {
    7576    }
     
    7980    bool m_isConstructor : 1;
    8081    bool m_isBuiltinFunction : 1;
     82    bool m_constructorKindIsDerived : 1;
    8183};
    8284
     
    117119        return JSParseNormal;
    118120    }
     121    bool constructorKindIsDerived() const { return m_constructorKindIsDerived; }
    119122
    120123    unsigned unlinkedFunctionNameStart() const { return m_unlinkedFunctionNameStart; }
     
    168171    bool m_hasCapturedVariables : 1;
    169172    bool m_isBuiltinFunction : 1;
     173    bool m_constructorKindIsDerived : 1;
    170174
    171175    Identifier m_name;
     
    342346
    343347    bool isBuiltinFunction() const { return m_isBuiltinFunction; }
    344    
     348
     349    bool constructorKindIsDerived() const { return m_constructorKindIsDerived; }
     350
    345351    void shrinkToFit()
    346352    {
     
    534540    bool m_hasCapturedVariables : 1;
    535541    bool m_isBuiltinFunction : 1;
     542    bool m_constructorKindIsDerived : 1;
    536543    unsigned m_firstLine;
    537544    unsigned m_lineCount;
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp

    r181179 r181293  
    402402
    403403    if (isConstructor()) {
    404         emitCreateThis(&m_thisRegister);
     404        if (constructorKindIsDerived()) {
     405            m_newTargetRegister = addVar();
     406            emitMove(m_newTargetRegister, &m_thisRegister);
     407            emitLoad(&m_thisRegister, jsNull());
     408        } else
     409            emitCreateThis(&m_thisRegister);
    405410    } else if (functionNode->usesThis() || codeBlock->usesEval()) {
    406411        m_codeBlock->addPropertyAccessInstruction(instructions().size());
     
    19021907    }
    19031908
    1904     if (isConstructor() && src->index() != m_thisRegister.index()) {
    1905         RefPtr<Label> isObjectLabel = newLabel();
    1906 
    1907         emitJumpIfTrue(emitIsObject(newTemporary(), src), isObjectLabel.get());
    1908 
    1909         emitUnaryNoDstOp(op_ret, &m_thisRegister);
    1910 
    1911         emitLabel(isObjectLabel.get());
     1909    bool thisMightBeUninitialized = constructorKindIsDerived();
     1910    if (isConstructor() && (src->index() != m_thisRegister.index() || thisMightBeUninitialized)) {
     1911        RefPtr<Label> isObjectOrUndefinedLabel = newLabel();
     1912
     1913        emitJumpIfTrue(emitIsObject(newTemporary(), src), isObjectOrUndefinedLabel.get());
     1914
     1915        if (constructorKindIsDerived()) {
     1916            emitJumpIfTrue(emitIsUndefined(newTemporary(), src), isObjectOrUndefinedLabel.get());
     1917            emitThrowTypeError("Cannot return a non-object type in the constructor of a derived class.");
     1918        } else
     1919            emitUnaryNoDstOp(op_ret, &m_thisRegister);
     1920
     1921        emitLabel(isObjectOrUndefinedLabel.get());
    19121922    }
    19131923    return emitUnaryNoDstOp(op_ret, src);
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h

    r181179 r181293  
    270270        const CommonIdentifiers& propertyNames() const { return *m_vm->propertyNames; }
    271271
    272         bool isConstructor() { return m_codeBlock->isConstructor(); }
     272        bool isConstructor() const { return m_codeBlock->isConstructor(); }
     273#if ENABLE(ES6_CLASS_SYNTAX)
     274        bool constructorKindIsDerived() const { return m_codeBlock->constructorKindIsDerived(); }
     275#else
     276        bool constructorKindIsDerived() const { return false; }
     277#endif
    273278
    274279        ParserError generate();
     
    291296        // Returns the register storing "this"
    292297        RegisterID* thisRegister() { return &m_thisRegister; }
    293        
     298        RegisterID* newTarget() { return m_newTargetRegister; }
     299
    294300        RegisterID* scopeRegister() { return m_scopeRegister; }
    295301
     
    764770        RegisterID* m_globalObjectRegister { nullptr };
    765771        RegisterID* m_localArgumentsRegister { nullptr };
     772        RegisterID* m_newTargetRegister { nullptr };
    766773
    767774        Vector<Identifier, 16> m_watchableVariables;
  • trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r181179 r181293  
    157157}
    158158
     159// ------------------------------ SuperNode -------------------------------------
     160
     161RegisterID* SuperNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
     162{
     163    if (dst == generator.ignoredResult())
     164        return 0;
     165
     166    RegisterID callee;
     167    callee.setIndex(JSStack::Callee);
     168
     169    RefPtr<RegisterID> homeObject = generator.emitGetById(generator.newTemporary(), &callee, generator.propertyNames().homeObjectPrivateName);
     170    RefPtr<RegisterID> protoParent = generator.emitGetById(generator.newTemporary(), homeObject.get(), generator.propertyNames().underscoreProto);
     171    return generator.emitGetById(generator.finalDestination(dst), protoParent.get(), generator.propertyNames().constructor);
     172}
     173
     174static RegisterID* emitSuperBaseForCallee(BytecodeGenerator& generator)
     175{
     176    RegisterID callee;
     177    callee.setIndex(JSStack::Callee);
     178
     179    RefPtr<RegisterID> homeObject = generator.emitGetById(generator.newTemporary(), &callee, generator.propertyNames().homeObjectPrivateName);
     180    return generator.emitGetById(generator.newTemporary(), homeObject.get(), generator.propertyNames().underscoreProto);
     181}
     182
    159183// ------------------------------ ResolveNode ----------------------------------
    160184
     
    295319// ------------------------------ PropertyListNode -----------------------------
    296320
     321static inline void emitPutHomeObject(BytecodeGenerator& generator, RegisterID* function, RegisterID* homeObject)
     322{
     323    generator.emitPutById(function, generator.propertyNames().homeObjectPrivateName, homeObject);
     324}
     325
    297326RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    298327{
     
    331360
    332361            RegisterID* value = generator.emitNode(node->m_assign);
     362            if (node->needsSuperBinding())
     363                emitPutHomeObject(generator, value, dst);
    333364
    334365            // This is a get/set property, find its entry in the map.
     
    345376            RefPtr<RegisterID> getterReg;
    346377            RefPtr<RegisterID> setterReg;
     378            RegisterID* secondReg = nullptr;
    347379
    348380            if (node->m_type == PropertyNode::Getter) {
     
    351383                    ASSERT(pair.second->m_type == PropertyNode::Setter);
    352384                    setterReg = generator.emitNode(pair.second->m_assign);
     385                    secondReg = setterReg.get();
    353386                } else {
    354387                    setterReg = generator.newTemporary();
     
    361394                    ASSERT(pair.second->m_type == PropertyNode::Getter);
    362395                    getterReg = generator.emitNode(pair.second->m_assign);
     396                    secondReg = getterReg.get();
    363397                } else {
    364398                    getterReg = generator.newTemporary();
     
    367401            }
    368402
     403            if (pair.second && pair.second->needsSuperBinding())
     404                emitPutHomeObject(generator, secondReg, dst);
     405
    369406            generator.emitPutGetterSetter(dst, *node->name(), getterReg.get(), setterReg.get());
    370407        }
     
    376413void PropertyListNode::emitPutConstantProperty(BytecodeGenerator& generator, RegisterID* newObj, PropertyNode& node)
    377414{
     415    RefPtr<RegisterID> value = generator.emitNode(node.m_assign);
     416    if (node.needsSuperBinding())
     417        emitPutHomeObject(generator, value.get(), newObj);
    378418    if (node.name()) {
    379         generator.emitDirectPutById(newObj, *node.name(), generator.emitNode(node.m_assign), node.putType());
     419        generator.emitDirectPutById(newObj, *node.name(), value.get(), node.putType());
    380420        return;
    381421    }
    382422    RefPtr<RegisterID> propertyName = generator.emitNode(node.m_expression);
    383     generator.emitDirectPutByVal(newObj, propertyName.get(), generator.emitNode(node.m_assign));
     423    generator.emitDirectPutByVal(newObj, propertyName.get(), value.get());
    384424}
    385425
     
    388428RegisterID* BracketAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    389429{
     430    if (m_base->isSuperNode()) {
     431        // FIXME: Should we generate the profiler info?
     432        if (m_subscript->isString()) {
     433            const Identifier& id = static_cast<StringNode*>(m_subscript)->value();
     434            return generator.emitGetById(generator.finalDestination(dst), emitSuperBaseForCallee(generator), id);
     435        }
     436        return generator.emitGetByVal(generator.finalDestination(dst), emitSuperBaseForCallee(generator), generator.emitNode(m_subscript));
     437    }
     438
    390439    if (m_base->isResolveNode()
    391440        && generator.willResolveToArgumentsRegister(static_cast<ResolveNode*>(m_base)->identifier())
     
    432481
    433482nonArgumentsPath:
    434     RefPtr<RegisterID> base = generator.emitNode(m_base);
     483    RefPtr<RegisterID> base = m_base->isSuperNode() ? emitSuperBaseForCallee(generator) : generator.emitNode(m_base);
    435484    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
    436485    RegisterID* finalDest = generator.finalDestination(dst);
     
    522571    RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());
    523572    CallArguments callArguments(generator, m_args);
     573    if (m_expr->isSuperNode()) {
     574        ASSERT(generator.constructorKindIsDerived());
     575        generator.emitMove(callArguments.thisRegister(), generator.newTarget());
     576        RegisterID* ret = generator.emitConstruct(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
     577        generator.emitMove(generator.thisRegister(), ret);
     578        return ret;
     579    }
    524580    generator.emitLoad(callArguments.thisRegister(), jsUndefined());
    525581    RegisterID* ret = generator.emitCall(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
     
    575631RegisterID* FunctionCallBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    576632{
    577     RefPtr<RegisterID> base = generator.emitNode(m_base);
     633    bool baseIsSuper = m_base->isSuperNode();
     634    RefPtr<RegisterID> base = baseIsSuper ? emitSuperBaseForCallee(generator) : generator.emitNode(m_base);
    578635    RefPtr<RegisterID> property = generator.emitNode(m_subscript);
    579636    generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
     
    581638    RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get());
    582639    CallArguments callArguments(generator, m_args);
    583     generator.emitMove(callArguments.thisRegister(), base.get());
     640    if (baseIsSuper)
     641        generator.emitMove(callArguments.thisRegister(), generator.thisRegister());
     642    else
     643        generator.emitMove(callArguments.thisRegister(), base.get());
    584644    RegisterID* ret = generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
    585645    if (generator.vm()->typeProfiler()) {
     
    597657    RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get());
    598658    CallArguments callArguments(generator, m_args);
    599     generator.emitNode(callArguments.thisRegister(), m_base);
     659    bool baseIsSuper = m_base->isSuperNode();
     660    if (baseIsSuper)
     661        generator.emitMove(callArguments.thisRegister(), generator.thisRegister());
     662    else
     663        generator.emitNode(callArguments.thisRegister(), m_base);
    600664    generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
    601     generator.emitGetById(function.get(), callArguments.thisRegister(), m_ident);
     665    generator.emitGetById(function.get(), baseIsSuper ? emitSuperBaseForCallee(generator) : callArguments.thisRegister(), m_ident);
    602666    RegisterID* ret = generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
    603667    if (generator.vm()->typeProfiler()) {
     
    9411005
    9421006    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
     1007    if (m_base->isSuperNode())
     1008        return emitThrowReferenceError(generator, "Cannot delete a super property");
    9431009    return generator.emitDeleteByVal(generator.finalDestination(dst), r0.get(), r1.get());
    9441010}
     
    9511017
    9521018    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
     1019    if (m_base->isSuperNode())
     1020        return emitThrowReferenceError(generator, "Cannot delete a super property");
    9531021    return generator.emitDeleteById(generator.finalDestination(dst), r0.get(), m_ident);
    9541022}
     
    28082876RegisterID* ClassExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    28092877{
    2810     ASSERT(!m_parentClassExpression);
     2878    RefPtr<RegisterID> superclass;
     2879    if (m_classHeritage) {
     2880        superclass = generator.newTemporary();
     2881        generator.emitNode(superclass.get(), m_classHeritage);
     2882    }
    28112883
    28122884    RefPtr<RegisterID> constructor = generator.emitNode(dst, m_constructorExpression);
     2885    // FIXME: Make the prototype non-configurable & non-writable.
    28132886    RefPtr<RegisterID> prototype = generator.emitGetById(generator.newTemporary(), constructor.get(), generator.propertyNames().prototype);
     2887
     2888    if (superclass) {
     2889        RefPtr<RegisterID> tempRegister = generator.newTemporary();
     2890        RefPtr<Label> superclassIsNullLabel = generator.newLabel();
     2891        generator.emitJumpIfTrue(generator.emitUnaryOp(op_eq_null, tempRegister.get(), superclass.get()), superclassIsNullLabel.get());
     2892
     2893        // FIXME: Throw TypeError if it's a generator function.
     2894        RefPtr<Label> superclassIsObjectLabel = generator.newLabel();
     2895        generator.emitJumpIfTrue(generator.emitIsObject(tempRegister.get(), superclass.get()), superclassIsObjectLabel.get());
     2896        generator.emitThrowTypeError(ASCIILiteral("The superclass is not an object."));
     2897        generator.emitLabel(superclassIsObjectLabel.get());
     2898
     2899        RefPtr<RegisterID> protoParent = generator.newTemporary();
     2900        generator.emitGetById(protoParent.get(), superclass.get(), generator.propertyNames().prototype);
     2901
     2902        RefPtr<Label> protoParentIsObjectOrNullLabel = generator.newLabel();
     2903        generator.emitJumpIfTrue(generator.emitUnaryOp(op_is_object_or_null, tempRegister.get(), protoParent.get()), protoParentIsObjectOrNullLabel.get());
     2904        generator.emitThrowTypeError(ASCIILiteral("The superclass's prototype is not an object."));
     2905        generator.emitLabel(protoParentIsObjectOrNullLabel.get());
     2906
     2907        generator.emitDirectPutById(constructor.get(), generator.propertyNames().underscoreProto, superclass.get(), PropertyNode::Unknown);
     2908        generator.emitDirectPutById(prototype.get(), generator.propertyNames().underscoreProto, protoParent.get(), PropertyNode::Unknown);
     2909
     2910        generator.emitLabel(superclassIsNullLabel.get());
     2911        emitPutHomeObject(generator, constructor.get(), prototype.get());
     2912    }
    28142913
    28152914    if (m_staticMethods)
  • trunk/Source/JavaScriptCore/parser/ASTBuilder.h

    r181179 r181293  
    170170        return new (m_parserArena) ThisNode(location);
    171171    }
     172    ExpressionNode* superExpr(const JSTokenLocation& location)
     173    {
     174        return new (m_parserArena) SuperNode(location);
     175    }
    172176    ExpressionNode* createResolve(const JSTokenLocation& location, const Identifier* ident, const JSTextPosition& start)
    173177    {
     
    299303    }
    300304
    301     FunctionBodyNode* createFunctionBody(const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, bool inStrictContext)
    302     {
    303         return new (m_parserArena) FunctionBodyNode(m_parserArena, startLocation, endLocation, startColumn, endColumn, inStrictContext);
     305    FunctionBodyNode* createFunctionBody(const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, bool inStrictContext, ConstructorKind constructorKind)
     306    {
     307        return new (m_parserArena) FunctionBodyNode(m_parserArena, startLocation, endLocation, startColumn, endColumn, inStrictContext, constructorKind);
    304308    }
    305309
     
    310314   
    311315    NEVER_INLINE PropertyNode* createGetterOrSetterProperty(const JSTokenLocation& location, PropertyNode::Type type, bool,
    312         const Identifier* name, const ParserFunctionInfo<ASTBuilder>& info, unsigned getOrSetStartOffset)
     316        const Identifier* name, const ParserFunctionInfo<ASTBuilder>& info, unsigned getOrSetStartOffset, SuperBinding superBinding)
    313317    {
    314318        ASSERT(name);
     
    316320        info.body->setInferredName(*name);
    317321        info.body->setFunctionKeywordStart(getOrSetStartOffset);
    318         return new (m_parserArena) PropertyNode(*name, new (m_parserArena) FuncExprNode(location, m_vm->propertyNames->nullIdentifier,
    319             info.body, m_sourceCode->subExpression(info.openBraceOffset, info.closeBraceOffset, info.bodyStartLine, info.bodyStartColumn), info.parameters), type, PropertyNode::Unknown);
    320     }
    321    
    322     NEVER_INLINE PropertyNode* createGetterOrSetterProperty(VM* vm, ParserArena& parserArena, const JSTokenLocation& location, PropertyNode::Type type, bool, double name, const ParserFunctionInfo<ASTBuilder>& info, unsigned getOrSetStartOffset)
     322        SourceCode source = m_sourceCode->subExpression(info.openBraceOffset, info.closeBraceOffset, info.bodyStartLine, info.bodyStartColumn);
     323        FuncExprNode* funcExpr = new (m_parserArena) FuncExprNode(location, m_vm->propertyNames->nullIdentifier, info.body, source, info.parameters);
     324        return new (m_parserArena) PropertyNode(*name, funcExpr, type, PropertyNode::Unknown, superBinding);
     325    }
     326   
     327    NEVER_INLINE PropertyNode* createGetterOrSetterProperty(VM* vm, ParserArena& parserArena, const JSTokenLocation& location, PropertyNode::Type type, bool,
     328        double name, const ParserFunctionInfo<ASTBuilder>& info, unsigned getOrSetStartOffset, SuperBinding superBinding)
    323329    {
    324330        info.body->setLoc(info.bodyStartLine, info.bodyEndLine, location.startOffset, location.lineStartOffset);
    325331        info.body->setFunctionKeywordStart(getOrSetStartOffset);
    326332        const Identifier& ident = parserArena.identifierArena().makeNumericIdentifier(vm, name);
    327         return new (m_parserArena) PropertyNode(ident, new (m_parserArena) FuncExprNode(location, vm->propertyNames->nullIdentifier,
    328             info.body, m_sourceCode->subExpression(info.openBraceOffset, info.closeBraceOffset, info.bodyStartLine, info.bodyStartColumn), info.parameters), type, PropertyNode::Unknown);
     333        SourceCode source = m_sourceCode->subExpression(info.openBraceOffset, info.closeBraceOffset, info.bodyStartLine, info.bodyStartColumn);
     334        FuncExprNode* funcExpr = new (m_parserArena) FuncExprNode(location, vm->propertyNames->nullIdentifier, info.body, source, info.parameters);
     335        return new (m_parserArena) PropertyNode(ident, funcExpr, type, PropertyNode::Unknown, superBinding);
    329336    }
    330337
     
    334341    ArgumentListNode* createArgumentsList(const JSTokenLocation& location, ArgumentListNode* args, ExpressionNode* arg) { return new (m_parserArena) ArgumentListNode(location, args, arg); }
    335342
    336     PropertyNode* createProperty(const Identifier* propertyName, ExpressionNode* node, PropertyNode::Type type, PropertyNode::PutType putType, bool)
     343    PropertyNode* createProperty(const Identifier* propertyName, ExpressionNode* node, PropertyNode::Type type, PropertyNode::PutType putType, bool, SuperBinding superBinding = SuperBinding::NotNeeded)
    337344    {
    338345        if (node->isFuncExprNode())
    339346            static_cast<FuncExprNode*>(node)->body()->setInferredName(*propertyName);
    340         return new (m_parserArena) PropertyNode(*propertyName, node, type, putType);
     347        return new (m_parserArena) PropertyNode(*propertyName, node, type, putType, superBinding);
    341348    }
    342349    PropertyNode* createProperty(VM* vm, ParserArena& parserArena, double propertyName, ExpressionNode* node, PropertyNode::Type type, PropertyNode::PutType putType, bool)
  • trunk/Source/JavaScriptCore/parser/NodeConstructors.h

    r181179 r181293  
    113113    }
    114114
    115 inline ResolveNode::ResolveNode(const JSTokenLocation& location, const Identifier& ident, const JSTextPosition& start)
     115    inline SuperNode::SuperNode(const JSTokenLocation& location)
     116        : ExpressionNode(location)
     117    {
     118    }
     119
     120    inline ResolveNode::ResolveNode(const JSTokenLocation& location, const Identifier& ident, const JSTextPosition& start)
    116121        : ExpressionNode(location)
    117122        , m_ident(ident)
     
    160165    }
    161166
    162     inline PropertyNode::PropertyNode(const Identifier& name, ExpressionNode* assign, Type type, PutType putType)
     167    inline PropertyNode::PropertyNode(const Identifier& name, ExpressionNode* assign, Type type, PutType putType, SuperBinding superBinding = SuperBinding::NotNeeded)
    163168        : m_name(&name)
    164169        , m_assign(assign)
    165170        , m_type(type)
     171        , m_needsSuperBinding(superBinding == SuperBinding::Needed)
    166172        , m_putType(putType)
    167173    {
     
    173179        , m_assign(assign)
    174180        , m_type(type)
     181        , m_needsSuperBinding(false)
    175182        , m_putType(putType)
    176183    {
     
    788795    }
    789796
    790     inline ClassExprNode::ClassExprNode(const JSTokenLocation& location, const Identifier& name, ExpressionNode* constructorExpression, ExpressionNode* parentClassExpression, PropertyListNode* instanceMethods, PropertyListNode* staticMethods)
     797    inline ClassExprNode::ClassExprNode(const JSTokenLocation& location, const Identifier& name, ExpressionNode* constructorExpression, ExpressionNode* classHeritage, PropertyListNode* instanceMethods, PropertyListNode* staticMethods)
    791798        : ExpressionNode(location)
    792799        , m_name(name)
    793800        , m_constructorExpression(constructorExpression)
    794         , m_parentClassExpression(parentClassExpression)
     801        , m_classHeritage(classHeritage)
    795802        , m_instanceMethods(instanceMethods)
    796803        , m_staticMethods(staticMethods)
  • trunk/Source/JavaScriptCore/parser/Nodes.cpp

    r180012 r181293  
    168168}
    169169
    170 FunctionBodyNode::FunctionBodyNode(ParserArena&, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, bool isInStrictContext)
     170FunctionBodyNode::FunctionBodyNode(ParserArena&, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned startColumn, unsigned endColumn, bool isInStrictContext, ConstructorKind constructorKind)
    171171    : StatementNode(endLocation)
    172172    , m_startColumn(startColumn)
     
    174174    , m_startStartOffset(startLocation.startOffset)
    175175    , m_isInStrictContext(isInStrictContext)
     176    , m_constructorKindIsDerived(constructorKind == ConstructorKind::Derived)
    176177{
    177178}
  • trunk/Source/JavaScriptCore/parser/Nodes.h

    r181179 r181293  
    165165        virtual bool isBoolean() const { return false; }
    166166        virtual bool isSpreadExpression() const { return false; }
     167        virtual bool isSuperNode() const { return false; }
    167168
    168169        virtual void emitBytecodeInConditionContext(BytecodeGenerator&, Label*, Label*, FallThroughMode);
     
    446447    };
    447448
     449    class SuperNode final : public ExpressionNode {
     450    public:
     451        SuperNode(const JSTokenLocation&);
     452
     453    private:
     454        virtual bool isSuperNode() const override { return true; }
     455        virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
     456    };
     457
    448458    class ResolveNode : public ExpressionNode {
    449459    public:
     
    502512        enum PutType { Unknown, KnownDirect };
    503513
    504         PropertyNode(const Identifier&, ExpressionNode*, Type, PutType);
     514        PropertyNode(const Identifier&, ExpressionNode*, Type, PutType, SuperBinding);
    505515        PropertyNode(ExpressionNode* propertyName, ExpressionNode*, Type, PutType);
    506        
     516
    507517        ExpressionNode* expressionName() const { return m_expression; }
    508518        const Identifier* name() const { return m_name; }
    509519
    510         Type type() const { return m_type; }
    511         PutType putType() const { return m_putType; }
     520        Type type() const { return static_cast<Type>(m_type); }
     521        bool needsSuperBinding() const { return m_needsSuperBinding; }
     522        PutType putType() const { return static_cast<PutType>(m_putType); }
    512523
    513524    private:
     
    516527        ExpressionNode* m_expression;
    517528        ExpressionNode* m_assign;
    518         Type m_type;
    519         PutType m_putType;
     529        unsigned m_type : 3;
     530        unsigned m_needsSuperBinding : 1;
     531        unsigned m_putType : 1;
    520532    };
    521533
     
    15481560        using ParserArenaDeletable::operator new;
    15491561
    1550         FunctionBodyNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, bool isInStrictContext);
     1562        FunctionBodyNode(ParserArena&, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, bool isInStrictContext, ConstructorKind);
    15511563
    15521564        FunctionParameters* parameters() const { return m_parameters.get(); }
     
    15761588        int startStartOffset() const { return m_startStartOffset; }
    15771589        bool isInStrictContext() const { return m_isInStrictContext; }
     1590        bool constructorKindIsDerived() { return m_constructorKindIsDerived; }
    15781591
    15791592    protected:
     
    15881601        SourceCode m_source;
    15891602        int m_startStartOffset;
    1590         bool m_isInStrictContext;
     1603        bool m_isInStrictContext : 1;
     1604        bool m_constructorKindIsDerived : 1;
    15911605    };
    15921606
     
    16451659        const Identifier& m_name;
    16461660        ExpressionNode* m_constructorExpression;
    1647         ExpressionNode* m_parentClassExpression;
     1661        ExpressionNode* m_classHeritage;
    16481662        PropertyListNode* m_instanceMethods;
    16491663        PropertyListNode* m_staticMethods;
  • trunk/Source/JavaScriptCore/parser/Parser.cpp

    r181183 r181293  
    12561256
    12571257template <typename LexerType>
    1258 template <class TreeBuilder> TreeFunctionBody Parser<LexerType>::parseFunctionBody(TreeBuilder& context)
     1258template <class TreeBuilder> TreeFunctionBody Parser<LexerType>::parseFunctionBody(TreeBuilder& context, ConstructorKind constructorKind)
    12591259{
    12601260    JSTokenLocation startLocation(tokenLocation());
     
    12641264    if (match(CLOSEBRACE)) {
    12651265        unsigned endColumn = tokenColumn();
    1266         return context.createFunctionBody(startLocation, tokenLocation(), startColumn, endColumn, strictMode());
     1266        return context.createFunctionBody(startLocation, tokenLocation(), startColumn, endColumn, strictMode(), constructorKind);
    12671267    }
    12681268    DepthManager statementDepth(&m_statementDepth);
     
    12711271    failIfFalse(parseSourceElements(bodyBuilder, CheckForStrictMode), "Cannot parse body of this function");
    12721272    unsigned endColumn = tokenColumn();
    1273     return context.createFunctionBody(startLocation, tokenLocation(), startColumn, endColumn, strictMode());
     1273    return context.createFunctionBody(startLocation, tokenLocation(), startColumn, endColumn, strictMode(), constructorKind);
    12741274}
    12751275
     
    12911291
    12921292template <typename LexerType>
    1293 template <class TreeBuilder> bool Parser<LexerType>::parseFunctionInfo(TreeBuilder& context, FunctionRequirements requirements, FunctionParseMode mode, bool nameIsInContainingScope, ParserFunctionInfo<TreeBuilder>& info)
     1293template <class TreeBuilder> bool Parser<LexerType>::parseFunctionInfo(TreeBuilder& context, FunctionRequirements requirements, FunctionParseMode mode,
     1294    bool nameIsInContainingScope, ConstructorKind constructorKind, ParserFunctionInfo<TreeBuilder>& info)
    12941295{
    12951296    AutoPopScopeRef functionScope(this, pushScope());
     
    13441345        unsigned currentLineStartOffset = m_token.m_location.lineStartOffset;
    13451346
    1346         info.body = context.createFunctionBody(startLocation, endLocation, info.bodyStartColumn, bodyEndColumn, cachedInfo->strictMode);
     1347        info.body = context.createFunctionBody(startLocation, endLocation, info.bodyStartColumn, bodyEndColumn, cachedInfo->strictMode, constructorKind);
    13471348       
    13481349        functionScope->restoreFromSourceProviderCache(cachedInfo);
     
    13671368    m_lastFunctionName = lastFunctionName;
    13681369    ParserState oldState = saveState();
    1369     info.body = parseFunctionBody(context);
     1370    info.body = parseFunctionBody(context, constructorKind);
    13701371    restoreState(oldState);
    13711372    failIfFalse(info.body, "Cannot parse the body of this ", stringForFunctionMode(mode));
    13721373    context.setEndOffset(info.body, m_lexer->currentOffset());
    13731374    if (functionScope->strictMode() && info.name) {
    1374         RELEASE_ASSERT(mode == FunctionMode);
     1375        RELEASE_ASSERT(mode == FunctionMode || mode == MethodMode);
    13751376        semanticFailIfTrue(m_vm->propertyNames->arguments == *info.name, "'", info.name->impl(), "' is not a valid function name in strict mode");
    13761377        semanticFailIfTrue(m_vm->propertyNames->eval == *info.name, "'", info.name->impl(), "' is not a valid function name in strict mode");
     1378    }
     1379    if (functionScope->hasDirectSuper()) {
     1380        bool nameIsConstructor = info.name && *info.name == m_vm->propertyNames->constructor;
     1381        semanticFailIfTrue(mode != MethodMode || !nameIsConstructor, "Cannot call super() outside of a class constructor");
    13771382    }
    13781383    info.closeBraceOffset = m_token.m_data.offset;
     
    14161421    next();
    14171422    ParserFunctionInfo<TreeBuilder> info;
    1418     failIfFalse((parseFunctionInfo(context, FunctionNeedsName, FunctionMode, true, info)), "Cannot parse this function");
     1423    failIfFalse((parseFunctionInfo(context, FunctionNeedsName, FunctionMode, true, ConstructorKind::Base, info)), "Cannot parse this function");
    14191424    failIfFalse(info.name, "Function statements must have a name");
    14201425    failIfFalseIfStrict(declareVariable(info.name), "Cannot declare a function named '", info.name->impl(), "' in strict mode");
     
    14661471        parentClass = parsePrimaryExpression(context);
    14671472        failIfFalse(parentClass, "Cannot parse the parent class name");
    1468         failWithMessage("Inheritance is not supported yet");
    1469     }
     1473    }
     1474    const ConstructorKind constructorKind = parentClass ? ConstructorKind::Derived : ConstructorKind::Base;
    14701475
    14711476    consumeOrFailWithFlags(OPENBRACE, TreeBuilder::DontBuildStrings, "Expected opening '{' at the start of a class body");
     
    14991504            semanticFailIfTrue(isStaticMethod, "Cannot declare a static", stringForFunctionMode(isGetter ? GetterMode : SetterMode));
    15001505            nextExpectIdentifier(LexerFlagsIgnoreReservedWords);
    1501             property = parseGetterSetter(context, alwaysStrictInsideClass, isGetter ? PropertyNode::Getter : PropertyNode::Setter, methodStart);
     1506            property = parseGetterSetter(context, alwaysStrictInsideClass, isGetter ? PropertyNode::Getter : PropertyNode::Setter, methodStart, SuperBinding::Needed);
    15021507            failIfFalse(property, "Cannot parse this method");
    15031508        } else {
    15041509            ParserFunctionInfo<TreeBuilder> methodInfo;
    1505             failIfFalse((parseFunctionInfo(context, FunctionNeedsName, FunctionMode, false, methodInfo)), "Cannot parse this method");
     1510            failIfFalse((parseFunctionInfo(context, FunctionNeedsName, MethodMode, false, constructorKind, methodInfo)), "Cannot parse this method");
    15061511            failIfFalse(methodInfo.name, "method must have a name");
    15071512            failIfFalse(declareVariable(methodInfo.name), "Cannot declare a method named '", methodInfo.name->impl(), "'");
     
    15211526            semanticFailIfTrue(isStaticMethod && *methodInfo.name == propertyNames.prototype,
    15221527                "Cannot declare a static method named 'prototype'");
    1523             property = context.createProperty(methodInfo.name, method, PropertyNode::Constant, PropertyNode::Unknown, alwaysStrictInsideClass);
     1528            property = context.createProperty(methodInfo.name, method, PropertyNode::Constant, PropertyNode::Unknown, alwaysStrictInsideClass, SuperBinding::Needed);
    15241529        }
    15251530
     
    20082013    unsigned methodStart = tokenStart();
    20092014    ParserFunctionInfo<TreeBuilder> methodInfo;
    2010     failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, MethodMode, false, methodInfo)), "Cannot parse this method");
     2015    failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, MethodMode, false, ConstructorKind::Base, methodInfo)), "Cannot parse this method");
    20112016    methodInfo.name = methodName;
    20122017    return context.createFunctionExpr(methodLocation, methodInfo, methodStart);
     
    20142019
    20152020template <typename LexerType>
    2016 template <class TreeBuilder> TreeProperty Parser<LexerType>::parseGetterSetter(TreeBuilder& context, bool strict, PropertyNode::Type type, unsigned getterOrSetterStartOffset)
     2021template <class TreeBuilder> TreeProperty Parser<LexerType>::parseGetterSetter(TreeBuilder& context, bool strict, PropertyNode::Type type, unsigned getterOrSetterStartOffset, SuperBinding superBinding)
    20172022{
    20182023    const Identifier* stringPropertyName = 0;
     
    20292034    if (type == PropertyNode::Getter) {
    20302035        failIfFalse(match(OPENPAREN), "Expected a parameter list for getter definition");
    2031         failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, GetterMode, false, info)), "Cannot parse getter definition");
     2036        failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, GetterMode, false, ConstructorKind::Base, info)), "Cannot parse getter definition");
    20322037    } else {
    20332038        failIfFalse(match(OPENPAREN), "Expected a parameter list for setter definition");
    2034         failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, SetterMode, false, info)), "Cannot parse setter definition");
     2039        failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, SetterMode, false, ConstructorKind::Base, info)), "Cannot parse setter definition");
    20352040    }
    20362041    if (stringPropertyName)
    2037         return context.createGetterOrSetterProperty(location, type, strict, stringPropertyName, info, getterOrSetterStartOffset);
    2038     return context.createGetterOrSetterProperty(const_cast<VM*>(m_vm), m_parserArena, location, type, strict, numericPropertyName, info, getterOrSetterStartOffset);
     2042        return context.createGetterOrSetterProperty(location, type, strict, stringPropertyName, info, getterOrSetterStartOffset, superBinding);
     2043    return context.createGetterOrSetterProperty(const_cast<VM*>(m_vm), m_parserArena, location, type, strict, numericPropertyName, info, getterOrSetterStartOffset, superBinding);
    20392044}
    20402045
     
    22212226        ParserFunctionInfo<TreeBuilder> info;
    22222227        info.name = &m_vm->propertyNames->nullIdentifier;
    2223         failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, FunctionMode, false, info)), "Cannot parse function expression");
     2228        failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, FunctionMode, false, ConstructorKind::Base, info)), "Cannot parse function expression");
    22242229        return context.createFunctionExpr(location, info, functionKeywordStart);
    22252230    }
     
    23712376    }
    23722377
    2373     base = parsePrimaryExpression(context);
    2374    
     2378#if ENABLE(ES6_CLASS_SYNTAX)
     2379    bool baseIsSuper = match(SUPER);
     2380#else
     2381    bool baseIsSuper = false;
     2382#endif
     2383
     2384    if (baseIsSuper) {
     2385        base = context.superExpr(location);
     2386        next();
     2387    } else
     2388        base = parsePrimaryExpression(context);
     2389
    23752390    failIfFalse(base, "Cannot parse base expression");
    23762391    while (true) {
     
    24032418                TreeArguments arguments = parseArguments(context, AllowSpread);
    24042419                failIfFalse(arguments, "Cannot parse call arguments");
     2420                if (baseIsSuper)
     2421                    currentScope()->setHasDirectSuper();
    24052422                base = context.makeFunctionCallNode(startLocation, base, arguments, expressionStart, expressionEnd, lastTokenEndPosition());
    24062423            }
     
    24202437            goto endMemberExpression;
    24212438        }
     2439        baseIsSuper = false;
    24222440    }
    24232441endMemberExpression:
     2442    semanticFailIfTrue(baseIsSuper && !newCount, "Cannot reference super");
    24242443    while (newCount--)
    24252444        base = context.createNewExpr(location, base, expressionStart, lastTokenEndPosition());
  • trunk/Source/JavaScriptCore/parser/Parser.h

    r181183 r181293  
    114114        , m_usesEval(false)
    115115        , m_needsFullActivation(false)
     116        , m_hasDirectSuper(false)
    116117        , m_allowsNewDecls(true)
    117118        , m_strictMode(strictMode)
     
    129130        , m_usesEval(rhs.m_usesEval)
    130131        , m_needsFullActivation(rhs.m_needsFullActivation)
     132        , m_hasDirectSuper(rhs.m_hasDirectSuper)
    131133        , m_allowsNewDecls(rhs.m_allowsNewDecls)
    132134        , m_strictMode(rhs.m_strictMode)
     
    263265
    264266    void setNeedsFullActivation() { m_needsFullActivation = true; }
     267
     268#if ENABLE(ES6_CLASS_SYNTAX)
     269    bool hasDirectSuper() { return m_hasDirectSuper; }
     270#else
     271    bool hasDirectSuper() { return false; }
     272#endif
     273    void setHasDirectSuper() { m_hasDirectSuper = true; }
    265274
    266275    bool collectFreeVariables(Scope* nestedScope, bool shouldTrackClosedVariables)
     
    357366    bool m_usesEval : 1;
    358367    bool m_needsFullActivation : 1;
     368    bool m_hasDirectSuper : 1;
    359369    bool m_allowsNewDecls : 1;
    360370    bool m_strictMode : 1;
     
    739749    template <class TreeBuilder> TreeProperty parseProperty(TreeBuilder&, bool strict);
    740750    template <class TreeBuilder> TreeExpression parsePropertyMethod(TreeBuilder& context, const Identifier* methodName);
    741     template <class TreeBuilder> TreeProperty parseGetterSetter(TreeBuilder&, bool strict, PropertyNode::Type, unsigned getterOrSetterStartOffset);
    742     template <class TreeBuilder> ALWAYS_INLINE TreeFunctionBody parseFunctionBody(TreeBuilder&);
     751    template <class TreeBuilder> TreeProperty parseGetterSetter(TreeBuilder&, bool strict, PropertyNode::Type, unsigned getterOrSetterStartOffset, SuperBinding = SuperBinding::NotNeeded);
     752    template <class TreeBuilder> ALWAYS_INLINE TreeFunctionBody parseFunctionBody(TreeBuilder&, ConstructorKind);
    743753    template <class TreeBuilder> ALWAYS_INLINE TreeFormalParameterList parseFormalParameters(TreeBuilder&);
    744754    enum VarDeclarationListContext { ForLoopContext, VarDeclarationContext };
     
    750760    template <class TreeBuilder> NEVER_INLINE TreeDeconstructionPattern tryParseDeconstructionPatternExpression(TreeBuilder&);
    751761
    752     template <class TreeBuilder> NEVER_INLINE bool parseFunctionInfo(TreeBuilder&, FunctionRequirements, FunctionParseMode, bool nameIsInContainingScope, ParserFunctionInfo<TreeBuilder>&);
     762    template <class TreeBuilder> NEVER_INLINE bool parseFunctionInfo(TreeBuilder&, FunctionRequirements, FunctionParseMode, bool nameIsInContainingScope, ConstructorKind, ParserFunctionInfo<TreeBuilder>&);
    753763#if ENABLE(ES6_CLASS_SYNTAX)
    754764    template <class TreeBuilder> NEVER_INLINE TreeClassExpression parseClass(TreeBuilder&, FunctionRequirements);
  • trunk/Source/JavaScriptCore/parser/ParserModes.h

    r174821 r181293  
    3434enum JSParserStrictness { JSParseNormal, JSParseBuiltin, JSParseStrict };
    3535enum JSParserMode { JSParseProgramCode, JSParseFunctionCode };
     36
     37enum class ConstructorKind { Base, Derived };
     38enum class SuperBinding { Needed, NotNeeded };
    3639
    3740enum ProfilerMode { ProfilerOff, ProfilerOn };
  • trunk/Source/JavaScriptCore/parser/SyntaxChecker.h

    r181179 r181293  
    7474        ResolveEvalExpr, ResolveExpr, IntegerExpr, DoubleExpr, StringExpr,
    7575        ThisExpr, NullExpr, BoolExpr, RegExpExpr, ObjectLiteralExpr,
    76         FunctionExpr, ClassExpr, BracketExpr, DotExpr, CallExpr,
     76        FunctionExpr, ClassExpr, SuperExpr, BracketExpr, DotExpr, CallExpr,
    7777        NewExpr, PreExpr, PostExpr, UnaryExpr, BinaryExpr,
    7878        ConditionalExpr, AssignmentExpr, TypeofExpr,
     
    147147    ExpressionType createVoid(const JSTokenLocation&, ExpressionType) { return UnaryExpr; }
    148148    ExpressionType thisExpr(const JSTokenLocation&) { return ThisExpr; }
     149    ExpressionType superExpr(const JSTokenLocation&) { return SuperExpr; }
    149150    ExpressionType createResolve(const JSTokenLocation&, const Identifier*, int) { return ResolveExpr; }
    150151    ExpressionType createObjectLiteral(const JSTokenLocation&) { return ObjectLiteralExpr; }
     
    169170#endif
    170171    ExpressionType createFunctionExpr(const JSTokenLocation&, const ParserFunctionInfo<SyntaxChecker>&, int) { return FunctionExpr; }
    171     int createFunctionBody(const JSTokenLocation&, const JSTokenLocation&, int, int, bool) { return FunctionBodyResult; }
     172    int createFunctionBody(const JSTokenLocation&, const JSTokenLocation&, int, int, bool, ConstructorKind) { return FunctionBodyResult; }
    172173    void setFunctionNameStart(int, int) { }
    173174    int createArguments() { return ArgumentsResult; }
     
    176177    int createArgumentsList(const JSTokenLocation&, int) { return ArgumentsListResult; }
    177178    int createArgumentsList(const JSTokenLocation&, int, int) { return ArgumentsListResult; }
    178     Property createProperty(const Identifier* name, int, PropertyNode::Type type, PropertyNode::PutType, bool complete)
     179    Property createProperty(const Identifier* name, int, PropertyNode::Type type, PropertyNode::PutType, bool complete, SuperBinding = SuperBinding::NotNeeded)
    179180    {
    180181        if (!complete)
     
    231232    int createConstStatement(const JSTokenLocation&, int, int, int) { return StatementResult; }
    232233    int appendConstDecl(const JSTokenLocation&, int, const Identifier*, int) { return StatementResult; }
    233     Property createGetterOrSetterProperty(const JSTokenLocation&, PropertyNode::Type type, bool strict, const Identifier* name, const ParserFunctionInfo<SyntaxChecker>&, unsigned)
     234    Property createGetterOrSetterProperty(const JSTokenLocation&, PropertyNode::Type type, bool strict, const Identifier* name, const ParserFunctionInfo<SyntaxChecker>&, unsigned, SuperBinding)
    234235    {
    235236        ASSERT(name);
     
    238239        return Property(name, type);
    239240    }
    240     Property createGetterOrSetterProperty(VM* vm, ParserArena& parserArena, const JSTokenLocation&, PropertyNode::Type type, bool strict, double name, const ParserFunctionInfo<SyntaxChecker>&, unsigned)
     241    Property createGetterOrSetterProperty(VM* vm, ParserArena& parserArena, const JSTokenLocation&, PropertyNode::Type type, bool strict, double name, const ParserFunctionInfo<SyntaxChecker>&, unsigned, SuperBinding)
    241242    {
    242243        if (!strict)
  • trunk/Source/JavaScriptCore/runtime/CommonIdentifiers.h

    r181084 r181293  
    262262    macro(TypeError) \
    263263    macro(undefined) \
    264     macro(BuiltinLog)
     264    macro(BuiltinLog) \
     265    macro(homeObject)
    265266
    266267namespace JSC {
  • trunk/Source/JavaScriptCore/runtime/Executable.h

    r181208 r181293  
    468468    void clearCode();
    469469
    470     ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false, false); }
     470    ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false, false, false); }
    471471
    472472    unsigned numVariables() { return m_unlinkedEvalCodeBlock->numVariables(); }
     
    523523    void clearCode();
    524524
    525     ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false, false); }
     525    ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false, false, false); }
    526526
    527527private:
Note: See TracChangeset for help on using the changeset viewer.