+ if (!head)
+ head = node;
+ else if (!tail) {
+ head = context.createCommaExpr(location, head);
+ tail = context.appendToCommaExpr(location, head, head, node);
+ } else
+ tail = context.appendToCommaExpr(location, head, tail, node);
+ } while (match(COMMA));
+ if (lastIdent)
+ lastPattern = createBindingPattern(context, DestructureToVariables, *lastIdent, 0, lastIdentToken);
+ return head;
+}
+
+template <typename LexerType>
+template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::createBindingPattern(TreeBuilder& context, DestructuringKind kind, const Identifier& name, int depth, JSToken token)
+{
+ ASSERT(!name.isNull());
+
+ ASSERT(name.impl()->isAtomic() || name.impl()->isSymbol());
+ if (depth) {
+ if (kind == DestructureToVariables)
+ failIfFalseIfStrict(declareVariable(&name), "Cannot destructure to a variable named '", name.impl(), "' in strict mode");
+ if (kind == DestructureToParameters) {
+ auto bindingResult = declareBoundParameter(&name);
+ if (bindingResult == Scope::StrictBindingFailed && strictMode()) {
+ semanticFailIfTrue(m_vm->propertyNames->arguments == name || m_vm->propertyNames->eval == name, "Cannot destructure to a parameter name '", name.impl(), "' in strict mode");
+ if (m_lastFunctionName && name == *m_lastFunctionName)
+ semanticFail("Cannot destructure to '", name.impl(), "' as it shadows the name of a strict mode function");
+ semanticFailureDueToKeyword("bound parameter name");
+ if (hasDeclaredParameter(name))
+ semanticFail("Cannot destructure to '", name.impl(), "' as it has already been declared");
+ semanticFail("Cannot bind to a parameter named '", name.impl(), "' in strict mode");
+ }
+ if (bindingResult == Scope::BindingFailed) {
+ semanticFailureDueToKeyword("bound parameter name");
+ if (hasDeclaredParameter(name))
+ semanticFail("Cannot destructure to '", name.impl(), "' as it has already been declared");
+ semanticFail("Cannot destructure to a parameter named '", name.impl(), "'");
+ }
+ }
+ if (kind != DestructureToExpressions)
+ context.addVar(&name, DeclarationStacks::HasInitializer);
+
+ } else {
+ if (kind == DestructureToVariables) {
+ failIfFalseIfStrict(declareVariable(&name), "Cannot declare a variable named '", name.impl(), "' in strict mode");
+ context.addVar(&name, DeclarationStacks::HasInitializer);
+ }
+
+ if (kind == DestructureToParameters) {
+ bool declarationResult = declareParameter(&name);
+ if (!declarationResult && strictMode()) {
+ semanticFailIfTrue(m_vm->propertyNames->arguments == name || m_vm->propertyNames->eval == name, "Cannot destructure to a parameter name '", name.impl(), "' in strict mode");
+ if (m_lastFunctionName && name == *m_lastFunctionName)
+ semanticFail("Cannot declare a parameter named '", name.impl(), "' as it shadows the name of a strict mode function");
+ semanticFailureDueToKeyword("parameter name");
+ if (hasDeclaredParameter(name))
+ semanticFail("Cannot declare a parameter named '", name.impl(), "' in strict mode as it has already been declared");
+ semanticFail("Cannot declare a parameter named '", name.impl(), "' in strict mode");
+ }
+ }
+ }
+ return context.createBindingLocation(token.m_location, name, token.m_startPosition, token.m_endPosition);
+}
+
+#if ENABLE(ES6_ARROWFUNCTION_SYNTAX)
+template <typename LexerType>
+template <class TreeBuilder> TreeStatement Parser<LexerType>::parseArrowFunctionSingleExpressionBody(TreeBuilder& context, FunctionParseType parseType)
+{
+ ASSERT(match(ARROWFUNCTION));
+
+ // When reparsing phase, parseType becomes StandardFunctionParseType even if the function is arrow function.
+ // This condition considers the following situations.
+ // (1): If we are in the reparsing phase, this arrow function is already parsed once, so there is no syntax error.
+ // (2): But if we are not in the reparsing phase, we should check this function is called in the context of the arrow function.
+ if (!m_lexer->isReparsing() && parseType != ArrowFunctionParseType)
+ failDueToUnexpectedToken();
+
+ JSTokenLocation location(tokenLocation());
+ JSTextPosition start = tokenStartPosition();
+ JSTextPosition end = tokenEndPosition();
+
+ next();
+
+ failIfStackOverflow();
+ TreeExpression expr = parseAssignmentExpression(context);
+ failIfFalse(expr, "Cannot parse the arrow function expression");
+
+ context.setEndOffset(expr, m_lastTokenEndPosition.offset);
+
+ failIfFalse(isEndOfArrowFunction(), "Expected a ';', ']', '}', ')', ',', line terminator or EOF following a arrow function statement");
+
+ end = tokenEndPosition();
+
+ if (!m_lexer->prevTerminator())
+ setEndOfStatement();
+
+ return context.createReturnStatement(location, expr, start, end);
+}
+#endif
+
+template <typename LexerType>
+template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::tryParseDestructuringPatternExpression(TreeBuilder& context)
+{
+ return parseDestructuringPattern(context, DestructureToExpressions);
+}
+
+template <typename LexerType>
+template <class TreeBuilder> TreeDestructuringPattern Parser<LexerType>::parseDestructuringPattern(TreeBuilder& context, DestructuringKind kind, int depth)
+{
+ failIfStackOverflow();
+ int nonLHSCount = m_nonLHSCount;
+ TreeDestructuringPattern pattern;
+ switch (m_token.m_type) {
+ case OPENBRACKET: {
+ JSTextPosition divotStart = tokenStartPosition();
+ auto arrayPattern = context.createArrayPattern(m_token.m_location);