Changeset 192661 in webkit


Ignore:
Timestamp:
Nov 19, 2015 2:54:46 PM (8 years ago)
Author:
commit-queue@webkit.org
Message:

[JSC] Fix AssignmentElement parsing
https://bugs.webkit.org/show_bug.cgi?id=151026

Patch by Caitlin Potter <caitp@igalia.com> on 2015-11-19
Reviewed by Geoffrey Garen.

When parsing an AssignmentPattern, any LeftHandSideExpression which
is a valid assignment target is acceptable.

Additionally, this change minimizes the amount of time spent
re-parsing ObjectLiteral and ArrayLiterals, by parsing as an
Expression first (the common case), and re-parsing only if the
result is a valid ObjectLiteral or ArrayLiteral followed by an =,
or if an error specifically indicates that the expression could
have been parsed as an AssignmentPattern.

  • bytecompiler/NodesCodegen.cpp:

(JSC::AssignmentElementNode::collectBoundIdentifiers):
(JSC::AssignmentElementNode::bindValue):
(JSC::AssignmentElementNode::toString):

  • parser/ASTBuilder.h:

(JSC::ASTBuilder::isAssignmentLocation):
(JSC::ASTBuilder::isObjectLiteral):
(JSC::ASTBuilder::isArrayLiteral):
(JSC::ASTBuilder::isObjectOrArrayLiteral):
(JSC::ASTBuilder::createAssignmentElement):

  • parser/NodeConstructors.h:

(JSC::AssignmentElementNode::AssignmentElementNode):

  • parser/Nodes.h:

(JSC::ExpressionNode::isObjectLiteral):
(JSC::ExpressionNode::isArrayLiteral):
(JSC::AssignmentElementNode::assignmentTarget):
(JSC::AssignmentElementNode::divotStart):
(JSC::AssignmentElementNode::divotEnd):

  • parser/Parser.cpp:

(JSC::Parser<LexerType>::Parser):
(JSC::Parser<LexerType>::createAssignmentElement):
(JSC::Parser<LexerType>::parseBindingOrAssignmentElement):
(JSC::Parser<LexerType>::parseAssignmentElement):
(JSC::Parser<LexerType>::parseDestructuringPattern):
(JSC::Parser<LexerType>::parseAssignmentExpression):
(JSC::Parser<LexerType>::parseProperty):

  • parser/Parser.h:

(JSC::Parser::ExpressionErrorClassifier::ExpressionErrorClassifier):
(JSC::Parser::ExpressionErrorClassifier::~ExpressionErrorClassifier):
(JSC::Parser::ExpressionErrorClassifier::classifyExpressionError):
(JSC::Parser::ExpressionErrorClassifier::indicatesPossiblePattern):
(JSC::Parser::classifyExpressionError):

  • parser/SyntaxChecker.h:

(JSC::SyntaxChecker::operatorStackPop):

  • tests/es6.yaml:
  • tests/es6/destructuring_assignment_non_simple_target.js: Added.

(test.):
(test):

  • tests/es6/destructuring_initializer_scoping.js: Added.

(test.tester):

  • tests/stress/destructuring-assignment-syntax.js: Added.

(testSyntax):
(testSyntaxError):

  • tests/stress/rest-elements.js:

(shouldThrow): Deleted.

Location:
trunk/Source/JavaScriptCore
Files:
4 added
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r192659 r192661  
     12015-11-19  Caitlin Potter  <caitp@igalia.com>
     2
     3        [JSC] Fix AssignmentElement parsing
     4        https://bugs.webkit.org/show_bug.cgi?id=151026
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        When parsing an AssignmentPattern, any LeftHandSideExpression which
     9        is a valid assignment target is acceptable.
     10
     11        Additionally, this change minimizes the amount of time spent
     12        re-parsing ObjectLiteral and ArrayLiterals, by parsing as an
     13        Expression first (the common case), and re-parsing only if the
     14        result is a valid ObjectLiteral or ArrayLiteral followed by an `=`,
     15        or if an error specifically indicates that the expression could
     16        have been parsed as an AssignmentPattern.
     17
     18        * bytecompiler/NodesCodegen.cpp:
     19        (JSC::AssignmentElementNode::collectBoundIdentifiers):
     20        (JSC::AssignmentElementNode::bindValue):
     21        (JSC::AssignmentElementNode::toString):
     22        * parser/ASTBuilder.h:
     23        (JSC::ASTBuilder::isAssignmentLocation):
     24        (JSC::ASTBuilder::isObjectLiteral):
     25        (JSC::ASTBuilder::isArrayLiteral):
     26        (JSC::ASTBuilder::isObjectOrArrayLiteral):
     27        (JSC::ASTBuilder::createAssignmentElement):
     28        * parser/NodeConstructors.h:
     29        (JSC::AssignmentElementNode::AssignmentElementNode):
     30        * parser/Nodes.h:
     31        (JSC::ExpressionNode::isObjectLiteral):
     32        (JSC::ExpressionNode::isArrayLiteral):
     33        (JSC::AssignmentElementNode::assignmentTarget):
     34        (JSC::AssignmentElementNode::divotStart):
     35        (JSC::AssignmentElementNode::divotEnd):
     36        * parser/Parser.cpp:
     37        (JSC::Parser<LexerType>::Parser):
     38        (JSC::Parser<LexerType>::createAssignmentElement):
     39        (JSC::Parser<LexerType>::parseBindingOrAssignmentElement):
     40        (JSC::Parser<LexerType>::parseAssignmentElement):
     41        (JSC::Parser<LexerType>::parseDestructuringPattern):
     42        (JSC::Parser<LexerType>::parseAssignmentExpression):
     43        (JSC::Parser<LexerType>::parseProperty):
     44        * parser/Parser.h:
     45        (JSC::Parser::ExpressionErrorClassifier::ExpressionErrorClassifier):
     46        (JSC::Parser::ExpressionErrorClassifier::~ExpressionErrorClassifier):
     47        (JSC::Parser::ExpressionErrorClassifier::classifyExpressionError):
     48        (JSC::Parser::ExpressionErrorClassifier::indicatesPossiblePattern):
     49        (JSC::Parser::classifyExpressionError):
     50        * parser/SyntaxChecker.h:
     51        (JSC::SyntaxChecker::operatorStackPop):
     52        * tests/es6.yaml:
     53        * tests/es6/destructuring_assignment_non_simple_target.js: Added.
     54        (test.):
     55        (test):
     56        * tests/es6/destructuring_initializer_scoping.js: Added.
     57        (test.tester):
     58        * tests/stress/destructuring-assignment-syntax.js: Added.
     59        (testSyntax):
     60        (testSyntaxError):
     61        * tests/stress/rest-elements.js:
     62        (shouldThrow): Deleted.
     63
    1642015-11-19  Filip Pizlo  <fpizlo@apple.com>
    265
  • trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r192597 r192661  
    33983398    identifiers.append(m_boundProperty);
    33993399}
    3400    
     3400
     3401void AssignmentElementNode::collectBoundIdentifiers(Vector<Identifier>&) const
     3402{
     3403}
     3404
     3405void AssignmentElementNode::bindValue(BytecodeGenerator& generator, RegisterID* value) const
     3406{
     3407    if (m_assignmentTarget->isResolveNode()) {
     3408        ResolveNode* lhs = static_cast<ResolveNode*>(m_assignmentTarget);
     3409        Variable var = generator.variable(lhs->identifier());
     3410        bool isReadOnly = var.isReadOnly();
     3411        if (RegisterID* local = var.local()) {
     3412            generator.emitTDZCheckIfNecessary(var, local, nullptr);
     3413
     3414            if (isReadOnly)
     3415                generator.emitReadOnlyExceptionIfNeeded(var);
     3416            else {
     3417                generator.invalidateForInContextForLocal(local);
     3418                generator.moveToDestinationIfNeeded(local, value);
     3419                generator.emitProfileType(local, divotStart(), divotEnd());
     3420            }
     3421            return;
     3422        }
     3423        if (generator.isStrictMode())
     3424            generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
     3425        RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
     3426        generator.emitTDZCheckIfNecessary(var, nullptr, scope.get());
     3427        if (isReadOnly) {
     3428            bool threwException = generator.emitReadOnlyExceptionIfNeeded(var);
     3429            if (threwException)
     3430                return;
     3431        }
     3432        generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
     3433        if (!isReadOnly) {
     3434            generator.emitPutToScope(scope.get(), var, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, NotInitialization);
     3435            generator.emitProfileType(value, var, divotStart(), divotEnd());
     3436        }
     3437    } else if (m_assignmentTarget->isDotAccessorNode()) {
     3438        DotAccessorNode* lhs = static_cast<DotAccessorNode*>(m_assignmentTarget);
     3439        RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(lhs->base(), true, false);
     3440        generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
     3441        generator.emitPutById(base.get(), lhs->identifier(), value);
     3442        generator.emitProfileType(value, divotStart(), divotEnd());
     3443    } else if (m_assignmentTarget->isBracketAccessorNode()) {
     3444        BracketAccessorNode* lhs = static_cast<BracketAccessorNode*>(m_assignmentTarget);
     3445        RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(lhs->base(), true, false);
     3446        RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(lhs->subscript(), true, false);
     3447        generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
     3448        generator.emitPutByVal(base.get(), property.get(), value);
     3449        generator.emitProfileType(value, divotStart(), divotEnd());
     3450    }
     3451}
     3452
     3453void AssignmentElementNode::toString(StringBuilder& builder) const
     3454{
     3455    if (m_assignmentTarget->isResolveNode())
     3456        builder.append(static_cast<ResolveNode*>(m_assignmentTarget)->identifier().string());
     3457}
     3458
    34013459RegisterID* SpreadExpressionNode::emitBytecode(BytecodeGenerator&, RegisterID*)
    34023460{
  • trunk/Source/JavaScriptCore/parser/ASTBuilder.h

    r192597 r192661  
    122122    typedef ObjectPatternNode* ObjectPattern;
    123123    typedef BindingNode* BindingPattern;
     124    typedef AssignmentElementNode* AssignmentElement;
    124125    static const bool CreatesAST = true;
    125126    static const bool NeedsFreeVariableInfo = true;
     
    525526    }
    526527
     528    bool isAssignmentLocation(const Expression& pattern)
     529    {
     530        return pattern->isAssignmentLocation();
     531    }
     532
     533    bool isObjectLiteral(const Expression& node)
     534    {
     535        return node->isObjectLiteral();
     536    }
     537
     538    bool isArrayLiteral(const Expression& node)
     539    {
     540        return node->isArrayLiteral();
     541    }
     542
     543    bool isObjectOrArrayLiteral(const Expression& node)
     544    {
     545        return isObjectLiteral(node) || isArrayLiteral(node);
     546    }
     547
    527548    StatementNode* createEmptyStatement(const JSTokenLocation& location) { return new (m_parserArena) EmptyStatementNode(location); }
    528549
     
    835856    {
    836857        return new (m_parserArena) BindingNode(boundProperty, start, end, context);
     858    }
     859
     860    AssignmentElement createAssignmentElement(const Expression& assignmentTarget, const JSTextPosition& start, const JSTextPosition& end)
     861    {
     862        return new (m_parserArena) AssignmentElementNode(assignmentTarget, start, end);
    837863    }
    838864
  • trunk/Source/JavaScriptCore/parser/NodeConstructors.h

    r192597 r192661  
    10211021    {
    10221022    }
    1023    
     1023
     1024    inline AssignmentElementNode::AssignmentElementNode(ExpressionNode* assignmentTarget, const JSTextPosition& start, const JSTextPosition& end)
     1025        : DestructuringPatternNode()
     1026        , m_divotStart(start)
     1027        , m_divotEnd(end)
     1028        , m_assignmentTarget(assignmentTarget)
     1029    {
     1030    }
     1031
    10241032    inline DestructuringAssignmentNode::DestructuringAssignmentNode(const JSTokenLocation& location, DestructuringPatternNode* bindings, ExpressionNode* initializer)
    10251033        : ExpressionNode(location)
  • trunk/Source/JavaScriptCore/parser/Nodes.h

    r192597 r192661  
    154154        virtual bool isNumber() const { return false; }
    155155        virtual bool isString() const { return false; }
     156        virtual bool isObjectLiteral() const { return false; }
     157        virtual bool isArrayLiteral() const { return false; }
    156158        virtual bool isNull() const { return false; }
    157159        virtual bool isPure(BytecodeGenerator&) const { return false; }       
     
    593595        ArrayNode(const JSTokenLocation&, int elision, ElementNode*);
    594596
     597        virtual bool isArrayLiteral() const override { return true; }
     598
    595599        ArgumentListNode* toArgumentList(ParserArena&, int, int) const;
    596600
     
    648652        ObjectLiteralNode(const JSTokenLocation&);
    649653        ObjectLiteralNode(const JSTokenLocation&, PropertyListNode*);
     654        virtual bool isObjectLiteral() const override { return true; }
    650655
    651656    private:
     
    20492054    };
    20502055
     2056    class AssignmentElementNode : public DestructuringPatternNode {
     2057    public:
     2058        AssignmentElementNode(ExpressionNode* assignmentTarget, const JSTextPosition& start, const JSTextPosition& end);
     2059        const ExpressionNode* assignmentTarget() { return m_assignmentTarget; }
     2060
     2061        const JSTextPosition& divotStart() const { return m_divotStart; }
     2062        const JSTextPosition& divotEnd() const { return m_divotEnd; }
     2063
     2064    private:
     2065        virtual void collectBoundIdentifiers(Vector<Identifier>&) const override;
     2066        virtual void bindValue(BytecodeGenerator&, RegisterID*) const override;
     2067        virtual void toString(StringBuilder&) const override;
     2068
     2069        JSTextPosition m_divotStart;
     2070        JSTextPosition m_divotEnd;
     2071        ExpressionNode* m_assignmentTarget;
     2072    };
     2073
    20512074    class DestructuringAssignmentNode : public ExpressionNode {
    20522075    public:
  • trunk/Source/JavaScriptCore/parser/Parser.cpp

    r192603 r192661  
    6161#define semanticFailIfFalse(cond, ...) do { if (!(cond)) internalFailWithMessage(false, __VA_ARGS__); } while (0)
    6262#define regexFail(failure) do { setErrorMessage(failure); return 0; } while (0)
     63#define restoreSavePointAndFail(savePoint, message) do { restoreSavePointWithError(savePoint, message); return 0; } while (0)
    6364#define failDueToUnexpectedToken() do {\
    6465        logError(true);\
     
    220221    m_token.m_location.lineStartOffset = source.startOffset();
    221222    m_functionCache = vm->addSourceProviderCache(source.provider());
     223    m_expressionErrorClassifier = nullptr;
    222224
    223225    ScopeRef scope = pushScope();
     
    713715
    714716template <typename LexerType>
     717template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern Parser<LexerType>::createAssignmentElement(TreeBuilder& context, TreeExpression& assignmentTarget, const JSTextPosition& startPosition, const JSTextPosition& endPosition)
     718{
     719    return context.createAssignmentElement(assignmentTarget, startPosition, endPosition);
     720}
     721
     722template <typename LexerType>
    715723template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseArrowFunctionSingleExpressionBodySourceElements(TreeBuilder& context)
    716724{
     
    745753{
    746754    return parseDestructuringPattern(context, DestructureToExpressions, ExportType::NotExported, nullptr, nullptr, bindingContext);
     755}
     756
     757template <typename LexerType>
     758template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::parseBindingOrAssignmentElement(TreeBuilder& context, DestructuringKind kind, ExportType exportType, const Identifier** duplicateIdentifier, bool* hasDestructuringPattern, AssignmentContext bindingContext, int depth)
     759{
     760    if (kind == DestructureToExpressions)
     761        return parseAssignmentElement(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth);
     762    return parseDestructuringPattern(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth);
     763}
     764
     765template <typename LexerType>
     766template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::parseAssignmentElement(TreeBuilder& context, DestructuringKind kind, ExportType exportType, const Identifier** duplicateIdentifier, bool* hasDestructuringPattern, AssignmentContext bindingContext, int depth)
     767{
     768    SavePoint savePoint = createSavePoint();
     769    TreeDestructuringPattern assignmentTarget = 0;
     770
     771    if (match(OPENBRACE) || match(OPENBRACKET))
     772        assignmentTarget = parseDestructuringPattern(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth);
     773    if (!assignmentTarget || match(DOT) || match(OPENBRACKET) || match(OPENPAREN) || match(TEMPLATE)) {
     774        restoreSavePoint(savePoint);
     775        JSTextPosition startPosition = tokenStartPosition();
     776        auto element = parseMemberExpression(context);
     777
     778        semanticFailIfFalse(element && context.isAssignmentLocation(element), "Invalid destructuring assignment target");
     779
     780        return createAssignmentElement(context, element, startPosition, lastTokenEndPosition());
     781    }
     782    return assignmentTarget;
    747783}
    748784
     
    777813                JSTokenLocation location = m_token.m_location;
    778814                next();
    779                 auto innerPattern = parseDestructuringPattern(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
     815                auto innerPattern = parseBindingOrAssignmentElement(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
    780816                if (kind == DestructureToExpressions && !innerPattern)
    781817                    return 0;
     
    790826
    791827            JSTokenLocation location = m_token.m_location;
    792             auto innerPattern = parseDestructuringPattern(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
     828            auto innerPattern = parseBindingOrAssignmentElement(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
    793829            if (kind == DestructureToExpressions && !innerPattern)
    794830                return 0;
     
    798834        } while (consume(COMMA));
    799835
    800         if (kind == DestructureToExpressions && !match(CLOSEBRACKET))
    801             return 0;
    802836        consumeOrFail(CLOSEBRACKET, restElementWasFound ? "Expected a closing ']' following a rest element destructuring pattern" : "Expected either a closing ']' or a ',' following an element destructuring pattern");
    803837        context.finishArrayPattern(arrayPattern, divotStart, divotStart, lastTokenEndPosition());
     
    827861                next();
    828862                if (consume(COLON))
    829                     innerPattern = parseDestructuringPattern(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
     863                    innerPattern = parseBindingOrAssignmentElement(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
    830864                else
    831865                    innerPattern = createBindingPattern(context, kind, exportType, *propertyName, identifierToken, bindingContext, duplicateIdentifier);
     
    860894                    failWithMessage("Expected a ':' prior to a named destructuring property");
    861895                }
    862                 innerPattern = parseDestructuringPattern(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
     896                innerPattern = parseBindingOrAssignmentElement(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
    863897            }
    864898            if (kind == DestructureToExpressions && !innerPattern)
     
    26712705    int initialAssignmentCount = m_assignmentCount;
    26722706    int initialNonLHSCount = m_nonLHSCount;
    2673     if (match(OPENBRACE) || match(OPENBRACKET)) {
    2674         SavePoint savePoint = createSavePoint();
    2675         auto pattern = tryParseDestructuringPatternExpression(context, AssignmentContext::AssignmentExpression);
    2676         if (pattern && consume(EQUAL)) {
    2677             auto rhs = parseAssignmentExpression(context);
    2678             if (rhs)
    2679                 return context.createDestructuringAssignment(location, pattern, rhs);
    2680         }
    2681         restoreSavePoint(savePoint);
    2682     }
     2707    bool maybeAssignmentPattern = match(OPENBRACE) || match(OPENBRACKET);
     2708    SavePoint savePoint = createSavePoint();
     2709    ExpressionErrorClassifier classifier(this);
    26832710
    26842711#if ENABLE(ES6_GENERATORS)
     
    26932720   
    26942721    TreeExpression lhs = parseConditionalExpression(context);
     2722
     2723    if (!lhs && (!maybeAssignmentPattern || !classifier.indicatesPossiblePattern()))
     2724        propagateError();
     2725
     2726    if (maybeAssignmentPattern && (!lhs || (context.isObjectOrArrayLiteral(lhs) && match(EQUAL)))) {
     2727        String expressionError = m_errorMessage;
     2728        SavePoint expressionErrorLocation = createSavePointForError();
     2729        restoreSavePoint(savePoint);
     2730        auto pattern = tryParseDestructuringPatternExpression(context, AssignmentContext::AssignmentExpression);
     2731        if (classifier.indicatesPossiblePattern() && (!pattern || !match(EQUAL)))
     2732            restoreSavePointAndFail(expressionErrorLocation, expressionError);
     2733        failIfFalse(pattern, "Cannot parse assignment pattern");
     2734        consumeOrFail(EQUAL, "Expected '=' following assignment pattern");
     2735        auto rhs = parseAssignmentExpression(context);
     2736        if (!rhs)
     2737            propagateError();
     2738        return context.createDestructuringAssignment(location, pattern, rhs);
     2739    }
     2740
    26952741    failIfFalse(lhs, "Cannot parse expression");
    26962742    if (initialNonLHSCount != m_nonLHSCount) {
     
    29112957            return context.createProperty(ident, node, static_cast<PropertyNode::Type>(PropertyNode::Constant | PropertyNode::Shorthand), PropertyNode::KnownDirect, complete);
    29122958        }
     2959
     2960        if (match(EQUAL)) // CoverInitializedName is exclusive to BindingPattern and AssignmentPattern
     2961            classifyExpressionError(ErrorIndicatesPattern);
    29132962
    29142963        PropertyNode::Type type;
  • trunk/Source/JavaScriptCore/parser/Parser.h

    r192603 r192661  
    717717        Parser* m_parser;
    718718    };
     719
     720    enum ExpressionErrorClass {
     721        ErrorIndicatesNothing,
     722        ErrorIndicatesPattern
     723    };
     724
     725    struct ExpressionErrorClassifier {
     726        ExpressionErrorClassifier(Parser* parser)
     727            : m_class(ErrorIndicatesNothing)
     728            , m_previous(parser->m_expressionErrorClassifier)
     729            , m_parser(parser)
     730        {
     731            m_parser->m_expressionErrorClassifier = this;
     732        }
     733
     734        ~ExpressionErrorClassifier()
     735        {
     736            m_parser->m_expressionErrorClassifier = m_previous;
     737        }
     738
     739        void classifyExpressionError(ExpressionErrorClass classification)
     740        {
     741            if (m_class != ErrorIndicatesNothing)
     742                return;
     743            m_class = classification;
     744        }
     745        bool indicatesPossiblePattern() const { return m_class == ErrorIndicatesPattern; }
     746
     747    private:
     748        ExpressionErrorClass m_class;
     749        ExpressionErrorClassifier* m_previous;
     750        Parser* m_parser;
     751    };
     752
     753    ALWAYS_INLINE void classifyExpressionError(ExpressionErrorClass classification)
     754    {
     755        if (m_expressionErrorClassifier)
     756            m_expressionErrorClassifier->classifyExpressionError(classification);
     757    }
    719758
    720759    ALWAYS_INLINE DestructuringKind destructuringKindFromDeclarationType(DeclarationType type)
     
    11401179    template <class TreeBuilder> TreeExpression parseArrowFunctionExpression(TreeBuilder&);
    11411180    template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern createBindingPattern(TreeBuilder&, DestructuringKind, ExportType, const Identifier&, JSToken, AssignmentContext, const Identifier** duplicateIdentifier);
     1181    template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern createAssignmentElement(TreeBuilder&, TreeExpression&, const JSTextPosition&, const JSTextPosition&);
     1182    template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern parseBindingOrAssignmentElement(TreeBuilder& context, DestructuringKind, ExportType, const Identifier** duplicateIdentifier, bool* hasDestructuringPattern, AssignmentContext bindingContext, int depth);
     1183    template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern parseAssignmentElement(TreeBuilder& context, DestructuringKind, ExportType, const Identifier** duplicateIdentifier, bool* hasDestructuringPattern, AssignmentContext bindingContext, int depth);
    11421184    template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern parseDestructuringPattern(TreeBuilder&, DestructuringKind, ExportType, const Identifier** duplicateIdentifier = nullptr, bool* hasDestructuringPattern = nullptr, AssignmentContext = AssignmentContext::DeclarationStatement, int depth = 0);
    11431185    template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern tryParseDestructuringPatternExpression(TreeBuilder&, AssignmentContext);
     
    12021244    };
    12031245   
    1204     ALWAYS_INLINE SavePoint createSavePoint()
    1205     {
    1206         ASSERT(!hasError());
     1246    ALWAYS_INLINE SavePoint createSavePointForError()
     1247    {
    12071248        SavePoint result;
    12081249        result.startOffset = m_token.m_location.startOffset;
     
    12131254    }
    12141255   
    1215     ALWAYS_INLINE void restoreSavePoint(const SavePoint& savePoint)
    1216     {
    1217         m_errorMessage = String();
     1256    ALWAYS_INLINE SavePoint createSavePoint()
     1257    {
     1258        ASSERT(!hasError());
     1259        return createSavePointForError();
     1260    }
     1261
     1262    ALWAYS_INLINE void restoreSavePointWithError(const SavePoint& savePoint, const String& message)
     1263    {
     1264        m_errorMessage = message;
    12181265        m_lexer->setOffset(savePoint.startOffset, savePoint.oldLineStartOffset);
    12191266        next();
    12201267        m_lexer->setLastLineNumber(savePoint.oldLastLineNumber);
    12211268        m_lexer->setLineNumber(savePoint.oldLineNumber);
     1269    }
     1270
     1271    ALWAYS_INLINE void restoreSavePoint(const SavePoint& savePoint)
     1272    {
     1273        restoreSavePointWithError(savePoint, String());
    12221274    }
    12231275
     
    12771329    CodeFeatures m_features;
    12781330    int m_numConstants;
     1331    ExpressionErrorClassifier* m_expressionErrorClassifier;
    12791332   
    12801333    struct DepthManager {
  • trunk/Source/JavaScriptCore/parser/SyntaxChecker.h

    r192597 r192661  
    347347        return BindingDestructuring;
    348348    }
     349    DestructuringPattern createAssignmentElement(const Expression&, const JSTextPosition&, const JSTextPosition&)
     350    {
     351        return BindingDestructuring;
     352    }
    349353
    350354    bool isBindingNode(DestructuringPattern pattern)
    351355    {
    352356        return pattern == BindingDestructuring;
     357    }
     358
     359    bool isAssignmentLocation(ExpressionType type)
     360    {
     361        return type == ResolveExpr || type == DotExpr || type == BracketExpr;
     362    }
     363
     364    bool isObjectLiteral(ExpressionType type)
     365    {
     366        return type == ObjectLiteralExpr;
     367    }
     368
     369    bool isArrayLiteral(ExpressionType type)
     370    {
     371        return type == ArrayLiteralExpr;
     372    }
     373
     374    bool isObjectOrArrayLiteral(ExpressionType type)
     375    {
     376        return isObjectLiteral(type) || isArrayLiteral(type);
    353377    }
    354378
  • trunk/Source/JavaScriptCore/tests/es6.yaml

    r192597 r192661  
    215215- path: es6/destructuring_with_strings.js
    216216  cmd: runES6 :normal
     217- path: es6/destructuring_assignment_non_simple_target.js
     218  cmd: runES6 :normal
     219- path: es6/destructuring_initializer_scoping.js
     220  cmd: runES6 :normal
    217221- path: es6/for..of_loops_with_arrays.js
    218222  cmd: runES6 :normal
     
    748752  cmd: runES6 :fail
    749753- path: es6/destructuring_nested_rest.js
    750   cmd: runES6 :fail
     754  cmd: runES6 :normal
    751755- path: es6/destructuring_with_generator_instances.js
    752756  cmd: runES6 :fail
  • trunk/Source/JavaScriptCore/tests/stress/rest-elements.js

    r192597 r192661  
    110110testSyntaxError(String.raw`(function ([a, ...{ b, c }]) { })`, String.raw`SyntaxError: Unexpected token ']'. Expected identifier for a rest element destructuring pattern.`);
    111111
    112 shouldThrow(function () {
    113     [a, ...b, c] = 20;
    114 }, "ReferenceError: Left side of assignment is not a reference.");
    115 
    116 shouldThrow(function () {
    117     [a, ...b,] = 20
    118 }, "ReferenceError: Left side of assignment is not a reference.");
    119 
    120 shouldThrow(function () {
    121     [a, ...b,,] = 20
    122 }, "ReferenceError: Left side of assignment is not a reference.");
    123 
    124 shouldThrow(function () {
    125     [a, ...b = 20] = 20
    126 }, "ReferenceError: Left side of assignment is not a reference.");
     112
     113testSyntaxError(String.raw`[a, ...b, c] = 20`, String.raw`SyntaxError: Unexpected token ','. Expected a closing ']' following a rest element destructuring pattern.`);
     114testSyntaxError(String.raw`[a, ...b,] = 20`, String.raw`SyntaxError: Unexpected token ','. Expected a closing ']' following a rest element destructuring pattern.`);
     115testSyntaxError(String.raw`[a, ...b,,] = 20`, String.raw`SyntaxError: Unexpected token ','. Expected a closing ']' following a rest element destructuring pattern.`);
     116testSyntaxError(String.raw`[a, ...b = 20] = 20`, String.raw`SyntaxError: Unexpected token '='. Expected a closing ']' following a rest element destructuring pattern.`);
    127117
    128118(function () {
Note: See TracChangeset for help on using the changeset viewer.