Changeset 192436 in webkit
- Timestamp:
- Nov 13, 2015, 11:13:39 AM (10 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 3 added
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r192434 r192436 1 2015-11-13 Caitlin Potter <[email protected]> 2 3 Allow any LeftHandSideExpression as a valid AssignmentElement 4 https://bugs.webkit.org/show_bug.cgi?id=151026 5 6 Reviewed by Geoffrey Garen. 7 8 * bytecompiler/NodesCodegen.cpp: 9 (JSC::AssignmentElementNode::collectBoundIdentifiers): 10 (JSC::AssignmentElementNode::bindValue): 11 (JSC::AssignmentElementNode::toString): 12 * parser/ASTBuilder.h: 13 (JSC::ASTBuilder::isAssignmentLocation): 14 (JSC::ASTBuilder::createAssignmentElement): 15 * parser/NodeConstructors.h: 16 (JSC::AssignmentElementNode::AssignmentElementNode): 17 * parser/Nodes.h: 18 (JSC::AssignmentElementNode::assignmentTarget): 19 (JSC::AssignmentElementNode::divotStart): 20 (JSC::AssignmentElementNode::divotEnd): 21 * parser/Parser.cpp: 22 (JSC::Parser<LexerType>::createAssignmentElement): 23 (JSC::Parser<LexerType>::parseDestructuringPattern): 24 * parser/Parser.h: 25 * parser/SyntaxChecker.h: 26 (JSC::SyntaxChecker::operatorStackPop): 27 1 28 2015-11-13 Yusuke Suzuki <[email protected]> 2 29 -
trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
r192155 r192436 3398 3398 identifiers.append(m_boundProperty); 3399 3399 } 3400 3400 3401 void AssignmentElementNode::collectBoundIdentifiers(Vector<Identifier>&) const 3402 { 3403 } 3404 3405 void 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 3453 void AssignmentElementNode::toString(StringBuilder& builder) const 3454 { 3455 if (m_assignmentTarget->isResolveNode()) 3456 builder.append(static_cast<ResolveNode*>(m_assignmentTarget)->identifier().string()); 3457 } 3458 3401 3459 RegisterID* SpreadExpressionNode::emitBytecode(BytecodeGenerator&, RegisterID*) 3402 3460 { -
trunk/Source/JavaScriptCore/parser/ASTBuilder.h
r192147 r192436 122 122 typedef ObjectPatternNode* ObjectPattern; 123 123 typedef BindingNode* BindingPattern; 124 typedef AssignmentElementNode* AssignmentElement; 124 125 static const bool CreatesAST = true; 125 126 static const bool NeedsFreeVariableInfo = true; … … 525 526 } 526 527 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 527 548 StatementNode* createEmptyStatement(const JSTokenLocation& location) { return new (m_parserArena) EmptyStatementNode(location); } 528 549 … … 835 856 { 836 857 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); 837 863 } 838 864 -
trunk/Source/JavaScriptCore/parser/NodeConstructors.h
r192147 r192436 1021 1021 { 1022 1022 } 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 1024 1032 inline DestructuringAssignmentNode::DestructuringAssignmentNode(const JSTokenLocation& location, DestructuringPatternNode* bindings, ExpressionNode* initializer) 1025 1033 : ExpressionNode(location) -
trunk/Source/JavaScriptCore/parser/Nodes.h
r192147 r192436 154 154 virtual bool isNumber() const { return false; } 155 155 virtual bool isString() const { return false; } 156 virtual bool isObjectLiteral() const { return false; } 157 virtual bool isArrayLiteral() const { return false; } 156 158 virtual bool isNull() const { return false; } 157 159 virtual bool isPure(BytecodeGenerator&) const { return false; } … … 593 595 ArrayNode(const JSTokenLocation&, int elision, ElementNode*); 594 596 597 virtual bool isArrayLiteral() const override { return true; } 598 595 599 ArgumentListNode* toArgumentList(ParserArena&, int, int) const; 596 600 … … 648 652 ObjectLiteralNode(const JSTokenLocation&); 649 653 ObjectLiteralNode(const JSTokenLocation&, PropertyListNode*); 654 virtual bool isObjectLiteral() const override { return true; } 650 655 651 656 private: … … 2049 2054 }; 2050 2055 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 2051 2074 class DestructuringAssignmentNode : public ExpressionNode { 2052 2075 public: -
trunk/Source/JavaScriptCore/parser/Parser.cpp
r192147 r192436 732 732 733 733 template <typename LexerType> 734 template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern Parser<LexerType>::createAssignmentElement(TreeBuilder& context, TreeExpression& assignmentTarget, const JSTextPosition& startPosition, const JSTextPosition& endPosition) 735 { 736 return context.createAssignmentElement(assignmentTarget, startPosition, endPosition); 737 } 738 739 template <typename LexerType> 734 740 template <class TreeBuilder> TreeSourceElements Parser<LexerType>::parseArrowFunctionSingleExpressionBodySourceElements(TreeBuilder& context) 735 741 { … … 764 770 { 765 771 return parseDestructuringPattern(context, DestructureToExpressions, ExportType::NotExported, nullptr, nullptr, bindingContext); 772 } 773 774 template <typename LexerType> 775 template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::parseBindingOrAssignmentElement(TreeBuilder& context, DestructuringKind kind, ExportType exportType, const Identifier** duplicateIdentifier, bool* hasDestructuringPattern, AssignmentContext bindingContext, int depth) 776 { 777 if (kind == DestructureToExpressions) 778 return parseAssignmentElement(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth); 779 return parseDestructuringPattern(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth); 780 } 781 782 template <typename LexerType> 783 template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::parseAssignmentElement(TreeBuilder& context, DestructuringKind kind, ExportType exportType, const Identifier** duplicateIdentifier, bool* hasDestructuringPattern, AssignmentContext bindingContext, int depth) 784 { 785 SavePoint savePoint = createSavePoint(); 786 TreeDestructuringPattern assignmentTarget = 0; 787 788 if (match(OPENBRACE) || match(OPENBRACKET)) 789 assignmentTarget = parseDestructuringPattern(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth); 790 if (!assignmentTarget || match(DOT) || match(OPENBRACKET) || match(OPENPAREN) || match(TEMPLATE)) { 791 restoreSavePoint(savePoint); 792 JSTextPosition startPosition = tokenStartPosition(); 793 auto element = parseMemberExpression(context); 794 795 semanticFailIfFalse(element && context.isAssignmentLocation(element), "Invalid destructuring assignment target"); 796 797 return createAssignmentElement(context, element, startPosition, lastTokenEndPosition()); 798 } 799 return assignmentTarget; 766 800 } 767 801 … … 796 830 JSTokenLocation location = m_token.m_location; 797 831 next(); 798 auto innerPattern = parse DestructuringPattern(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);832 auto innerPattern = parseBindingOrAssignmentElement(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1); 799 833 if (kind == DestructureToExpressions && !innerPattern) 800 834 return 0; … … 809 843 810 844 JSTokenLocation location = m_token.m_location; 811 auto innerPattern = parse DestructuringPattern(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);845 auto innerPattern = parseBindingOrAssignmentElement(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1); 812 846 if (kind == DestructureToExpressions && !innerPattern) 813 847 return 0; … … 817 851 } while (consume(COMMA)); 818 852 819 if (kind == DestructureToExpressions && !match(CLOSEBRACKET))820 return 0;821 853 consumeOrFail(CLOSEBRACKET, restElementWasFound ? "Expected a closing ']' following a rest element destructuring pattern" : "Expected either a closing ']' or a ',' following an element destructuring pattern"); 822 854 context.finishArrayPattern(arrayPattern, divotStart, divotStart, lastTokenEndPosition()); … … 846 878 next(); 847 879 if (consume(COLON)) 848 innerPattern = parse DestructuringPattern(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);880 innerPattern = parseBindingOrAssignmentElement(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1); 849 881 else 850 882 innerPattern = createBindingPattern(context, kind, exportType, *propertyName, depth + 1, identifierToken, bindingContext, duplicateIdentifier); … … 879 911 failWithMessage("Expected a ':' prior to a named destructuring property"); 880 912 } 881 innerPattern = parse DestructuringPattern(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);913 innerPattern = parseBindingOrAssignmentElement(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1); 882 914 } 883 915 if (kind == DestructureToExpressions && !innerPattern) … … 2690 2722 int initialAssignmentCount = m_assignmentCount; 2691 2723 int initialNonLHSCount = m_nonLHSCount; 2724 String assignmentPatternError = String(); 2692 2725 if (match(OPENBRACE) || match(OPENBRACKET)) { 2693 2726 SavePoint savePoint = createSavePoint(); … … 2698 2731 return context.createDestructuringAssignment(location, pattern, rhs); 2699 2732 } 2733 assignmentPatternError = m_errorMessage; 2700 2734 restoreSavePoint(savePoint); 2701 2735 } … … 2712 2746 2713 2747 TreeExpression lhs = parseConditionalExpression(context); 2748 if (!assignmentPatternError.isNull() && (lhs && (context.isObjectOrArrayLiteral(lhs) && match(EQUAL)))) { 2749 setErrorMessage(assignmentPatternError); 2750 return 0; 2751 } 2714 2752 failIfFalse(lhs, "Cannot parse expression"); 2715 2753 if (initialNonLHSCount != m_nonLHSCount) { -
trunk/Source/JavaScriptCore/parser/Parser.h
r192147 r192436 1161 1161 template <class TreeBuilder> TreeExpression parseArrowFunctionExpression(TreeBuilder&); 1162 1162 template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern createBindingPattern(TreeBuilder&, DestructuringKind, ExportType, const Identifier&, int depth, JSToken, AssignmentContext, const Identifier** duplicateIdentifier); 1163 template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern createAssignmentElement(TreeBuilder&, TreeExpression&, const JSTextPosition&, const JSTextPosition&); 1164 template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern parseBindingOrAssignmentElement(TreeBuilder& context, DestructuringKind, ExportType, const Identifier** duplicateIdentifier, bool* hasDestructuringPattern, AssignmentContext bindingContext, int depth); 1165 template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern parseAssignmentElement(TreeBuilder& context, DestructuringKind, ExportType, const Identifier** duplicateIdentifier, bool* hasDestructuringPattern, AssignmentContext bindingContext, int depth); 1163 1166 template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern parseDestructuringPattern(TreeBuilder&, DestructuringKind, ExportType, const Identifier** duplicateIdentifier = nullptr, bool* hasDestructuringPattern = nullptr, AssignmentContext = AssignmentContext::DeclarationStatement, int depth = 0); 1164 1167 template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern tryParseDestructuringPatternExpression(TreeBuilder&, AssignmentContext); -
trunk/Source/JavaScriptCore/parser/SyntaxChecker.h
r192147 r192436 347 347 return BindingDestructuring; 348 348 } 349 DestructuringPattern createAssignmentElement(const Expression&, const JSTextPosition&, const JSTextPosition&) 350 { 351 return BindingDestructuring; 352 } 349 353 350 354 bool isBindingNode(DestructuringPattern pattern) 351 355 { 352 356 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); 353 377 } 354 378 -
trunk/Source/JavaScriptCore/tests/es6.yaml
r191864 r192436 215 215 - path: es6/destructuring_with_strings.js 216 216 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 217 221 - path: es6/for..of_loops_with_arrays.js 218 222 cmd: runES6 :normal … … 748 752 cmd: runES6 :fail 749 753 - path: es6/destructuring_nested_rest.js 750 cmd: runES6 : fail754 cmd: runES6 :normal 751 755 - path: es6/destructuring_with_generator_instances.js 752 756 cmd: runES6 :fail -
trunk/Source/JavaScriptCore/tests/stress/rest-elements.js
r186246 r192436 110 110 testSyntaxError(String.raw`(function ([a, ...{ b, c }]) { })`, String.raw`SyntaxError: Unexpected token ']'. Expected identifier for a rest element destructuring pattern.`); 111 111 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 113 testSyntaxError(String.raw`[a, ...b, c] = 20`, String.raw`SyntaxError: Unexpected token ','. Expected a closing ']' following a rest element destructuring pattern.`); 114 testSyntaxError(String.raw`[a, ...b,] = 20`, String.raw`SyntaxError: Unexpected token ','. Expected a closing ']' following a rest element destructuring pattern.`); 115 testSyntaxError(String.raw`[a, ...b,,] = 20`, String.raw`SyntaxError: Unexpected token ','. Expected a closing ']' following a rest element destructuring pattern.`); 116 testSyntaxError(String.raw`[a, ...b = 20] = 20`, String.raw`SyntaxError: Unexpected token '='. Expected a closing ']' following a rest element destructuring pattern.`); 127 117 128 118 (function () {
Note:
See TracChangeset
for help on using the changeset viewer.