Ignore:
Timestamp:
Jan 29, 2015, 2:59:19 PM (10 years ago)
Author:
[email protected]
Message:

Implement ES6 class syntax without inheritance support
https://bugs.webkit.org/show_bug.cgi?id=140918

Reviewed by Geoffrey Garen.

Source/JavaScriptCore:

Added the most basic support for ES6 class syntax. After this patch, we support basic class definition like:
class A {

constructor() { }
someMethod() { }

}

We'll add the support for "extends" keyword and automatically generating a constructor in follow up patches.
We also don't support block scoping of a class declaration.

We support both class declaration and class expression. A class expression is implemented by the newly added
ClassExprNode AST node. A class declaration is implemented by ClassDeclNode, which is a thin wrapper around
AssignResolveNode.

Tests: js/class-syntax-declaration.html

js/class-syntax-expression.html

  • bytecompiler/NodesCodegen.cpp:

(JSC::ObjectLiteralNode::emitBytecode): Create a new object instead of delegating the work to PropertyListNode.
Also fixed the 5-space indentation.
(JSC::PropertyListNode::emitBytecode): Don't create a new object now that ObjectLiteralNode does this.
(JSC::ClassDeclNode::emitBytecode): Added. Just let the AssignResolveNode node emit the byte code.
(JSC::ClassExprNode::emitBytecode): Create the class constructor and add static methods to the constructor by
emitting the byte code for PropertyListNode. Add instance methods to the class's prototype object the same way.

  • parser/ASTBuilder.h:

(JSC::ASTBuilder::createClassExpr): Added. Creates a ClassExprNode.
(JSC::ASTBuilder::createClassDeclStatement): Added. Creates a AssignResolveNode and wraps it by a ClassDeclNode.

  • parser/NodeConstructors.h:

(JSC::ClassDeclNode::ClassDeclNode): Added.
(JSC::ClassExprNode::ClassExprNode): Added.

  • parser/Nodes.h:

(JSC::ClassExprNode): Added.
(JSC::ClassDeclNode): Added.

  • parser/Parser.cpp:

(JSC::Parser<LexerType>::parseStatement): Added the support for class declaration.
(JSC::stringForFunctionMode): Return "method" for MethodMode.
(JSC::Parser<LexerType>::parseClassDeclaration): Added. Uses parseClass to create a class expression and wraps
it with ClassDeclNode as described above.
(JSC::Parser<LexerType>::parseClass): Parses a class expression.
(JSC::Parser<LexerType>::parseProperty):
(JSC::Parser<LexerType>::parseGetterSetter): Extracted from parseProperty to share the code between parseProperty
and parseClass.
(JSC::Parser<LexerType>::parsePrimaryExpression): Added the support for class expression.

  • parser/Parser.h:

(FunctionParseMode): Added MethodMode.

  • parser/SyntaxChecker.h:

(JSC::SyntaxChecker::createClassExpr): Added.
(JSC::SyntaxChecker::createClassDeclStatement): Added.

LayoutTests:

Added two tests for class declarations and class expressions.

  • TestExpectations:
  • js/class-syntax-declaration-expected.txt: Added.
  • js/class-syntax-declaration.html: Added.
  • js/class-syntax-expression-expected.txt: Added.
  • js/class-syntax-expression.html: Added.
  • js/script-tests/class-syntax-declaration.js: Added.
  • js/script-tests/class-syntax-expression.js: Added.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r178918 r179371  
    274274RegisterID* ObjectLiteralNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    275275{
    276      if (!m_list) {
    277          if (dst == generator.ignoredResult())
    278              return 0;
    279          return generator.emitNewObject(generator.finalDestination(dst));
    280      }
    281      return generator.emitNode(dst, m_list);
     276    if (!m_list) {
     277        if (dst == generator.ignoredResult())
     278            return 0;
     279        return generator.emitNewObject(generator.finalDestination(dst));
     280    }
     281    RefPtr<RegisterID> newObj = generator.emitNewObject(generator.tempDestination(dst));
     282    generator.emitNode(newObj.get(), m_list);
     283    return generator.moveToDestinationIfNeeded(dst, newObj.get());
    282284}
    283285
     
    286288RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    287289{
    288     RefPtr<RegisterID> newObj = generator.tempDestination(dst);
    289    
    290     generator.emitNewObject(newObj.get());
    291    
    292290    // Fast case: this loop just handles regular value properties.
    293291    PropertyListNode* p = this;
    294292    for (; p && p->m_node->m_type == PropertyNode::Constant; p = p->m_next)
    295         emitPutConstantProperty(generator, newObj.get(), *p->m_node);
     293        emitPutConstantProperty(generator, dst, *p->m_node);
    296294
    297295    // Were there any get/set properties?
     
    319317            // Handle regular values.
    320318            if (node->m_type == PropertyNode::Constant) {
    321                 emitPutConstantProperty(generator, newObj.get(), *node);
     319                emitPutConstantProperty(generator, dst, *node);
    322320                continue;
    323321            }
     
    360358            }
    361359
    362             generator.emitPutGetterSetter(newObj.get(), *node->name(), getterReg.get(), setterReg.get());
    363         }
    364     }
    365 
    366     return generator.moveToDestinationIfNeeded(dst, newObj.get());
     360            generator.emitPutGetterSetter(dst, *node->name(), getterReg.get(), setterReg.get());
     361        }
     362    }
     363
     364    return dst;
    367365}
    368366
     
    27542752    return generator.emitNewFunctionExpression(generator.finalDestination(dst), this);
    27552753}
     2754
     2755#if ENABLE(ES6_CLASS_SYNTAX)
     2756// ------------------------------ ClassDeclNode ---------------------------------
     2757
     2758void ClassDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
     2759{
     2760    generator.emitNode(dst, m_classDeclaration);
     2761}
     2762
     2763// ------------------------------ ClassExprNode ---------------------------------
     2764
     2765RegisterID* ClassExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
     2766{
     2767    ASSERT(!m_parentClassExpression);
     2768
     2769    RefPtr<RegisterID> constructor = generator.emitNode(dst, m_constructorExpression);
     2770    RefPtr<RegisterID> prototype = generator.emitGetById(generator.newTemporary(), constructor.get(), generator.propertyNames().prototype);
     2771
     2772    if (m_staticMethods)
     2773        generator.emitNode(constructor.get(), m_staticMethods);
     2774
     2775    if (m_instanceMethods)
     2776        generator.emitNode(prototype.get(), m_instanceMethods);
     2777
     2778    return generator.moveToDestinationIfNeeded(dst, constructor.get());
     2779}
     2780#endif
    27562781   
    27572782// ------------------------------ DeconstructingAssignmentNode -----------------
Note: See TracChangeset for help on using the changeset viewer.