| Index: src/preparser.h
|
| diff --git a/src/preparser.h b/src/preparser.h
|
| index 08963c942540f05f97a1893a5166b243522a56d7..1999272d3daefcbe917b2a45b04a9aeeae446f1a 100644
|
| --- a/src/preparser.h
|
| +++ b/src/preparser.h
|
| @@ -90,6 +90,7 @@ class ParserBase : public Traits {
|
| allow_harmony_sloppy_(false),
|
| allow_harmony_computed_property_names_(false),
|
| allow_harmony_rest_params_(false),
|
| + allow_harmony_spreadcalls_(false),
|
| allow_strong_mode_(false) {}
|
|
|
| // Getters that indicate whether certain syntactical constructs are
|
| @@ -115,6 +116,7 @@ class ParserBase : public Traits {
|
| bool allow_harmony_rest_params() const {
|
| return allow_harmony_rest_params_;
|
| }
|
| + bool allow_harmony_spreadcalls() const { return allow_harmony_spreadcalls_; }
|
|
|
| bool allow_strong_mode() const { return allow_strong_mode_; }
|
|
|
| @@ -149,6 +151,9 @@ class ParserBase : public Traits {
|
| void set_allow_harmony_rest_params(bool allow) {
|
| allow_harmony_rest_params_ = allow;
|
| }
|
| + void set_allow_harmony_spreadcalls(bool allow) {
|
| + allow_harmony_spreadcalls_ = allow;
|
| + }
|
| void set_allow_strong_mode(bool allow) { allow_strong_mode_ = allow; }
|
|
|
| protected:
|
| @@ -583,7 +588,8 @@ class ParserBase : public Traits {
|
| ObjectLiteralCheckerBase* checker, bool in_class, bool has_extends,
|
| bool is_static, bool* is_computed_name, bool* has_seen_constructor,
|
| bool* ok);
|
| - typename Traits::Type::ExpressionList ParseArguments(bool* ok);
|
| + typename Traits::Type::ExpressionList ParseArguments(
|
| + Scanner::Location* first_spread_pos, bool* ok);
|
| ExpressionT ParseAssignmentExpression(bool accept_IN, bool* ok);
|
| ExpressionT ParseYieldExpression(bool* ok);
|
| ExpressionT ParseConditionalExpression(bool accept_IN, bool* ok);
|
| @@ -695,6 +701,7 @@ class ParserBase : public Traits {
|
| bool allow_harmony_sloppy_;
|
| bool allow_harmony_computed_property_names_;
|
| bool allow_harmony_rest_params_;
|
| + bool allow_harmony_spreadcalls_;
|
| bool allow_strong_mode_;
|
| };
|
|
|
| @@ -787,6 +794,10 @@ class PreParserExpression {
|
| return PreParserExpression(TypeField::encode(kExpression));
|
| }
|
|
|
| + static PreParserExpression Spread(PreParserExpression expression) {
|
| + return PreParserExpression(TypeField::encode(kSpreadExpression));
|
| + }
|
| +
|
| static PreParserExpression FromIdentifier(PreParserIdentifier id) {
|
| return PreParserExpression(TypeField::encode(kIdentifierExpression) |
|
| IdentifierTypeField::encode(id.type_));
|
| @@ -915,6 +926,10 @@ class PreParserExpression {
|
| ExpressionTypeField::decode(code_) == kNoTemplateTagExpression;
|
| }
|
|
|
| + bool IsSpreadExpression() const {
|
| + return TypeField::decode(code_) == kSpreadExpression;
|
| + }
|
| +
|
| PreParserExpression AsFunctionLiteral() { return *this; }
|
|
|
| bool IsBinaryOperation() const {
|
| @@ -947,7 +962,8 @@ class PreParserExpression {
|
| kExpression,
|
| kIdentifierExpression,
|
| kStringLiteralExpression,
|
| - kBinaryOperationExpression
|
| + kBinaryOperationExpression,
|
| + kSpreadExpression
|
| };
|
|
|
| enum Parenthesization {
|
| @@ -973,8 +989,8 @@ class PreParserExpression {
|
| : (IsIdentifier() && AsIdentifier().IsValidArrowParam());
|
| }
|
|
|
| - // The first four bits are for the Type and Parenthesization.
|
| - typedef BitField<Type, 0, 2> TypeField;
|
| + // The first five bits are for the Type and Parenthesization.
|
| + typedef BitField<Type, 0, 3> TypeField;
|
| typedef BitField<Parenthesization, TypeField::kNext, 2> ParenthesizationField;
|
|
|
| // The rest of the bits are interpreted depending on the value
|
| @@ -1175,6 +1191,12 @@ class PreParserFactory {
|
| int pos) {
|
| return PreParserExpression::Default();
|
| }
|
| + PreParserExpression NewCallRuntime(const AstRawString* name,
|
| + const Runtime::Function* function,
|
| + PreParserExpressionList arguments,
|
| + int pos) {
|
| + return PreParserExpression::Default();
|
| + }
|
| PreParserStatement NewReturnStatement(PreParserExpression expression,
|
| int pos) {
|
| return PreParserStatement::Default();
|
| @@ -1191,6 +1213,11 @@ class PreParserFactory {
|
| return PreParserExpression::Default();
|
| }
|
|
|
| + PreParserExpression NewSpreadOperation(PreParserExpression expression,
|
| + int pos) {
|
| + return PreParserExpression::Spread(expression);
|
| + }
|
| +
|
| // Return the object itself as AstVisitor and implement the needed
|
| // dummy method right in this class.
|
| PreParserFactory* visitor() { return this; }
|
| @@ -1503,6 +1530,19 @@ class PreParserTraits {
|
| bool name_is_strict_reserved, int pos,
|
| bool* ok);
|
|
|
| + PreParserExpressionList PrepareSpreadArguments(PreParserExpressionList list) {
|
| + return list;
|
| + }
|
| +
|
| + inline void MaterializeUnspreadArgumentsLiterals(int count);
|
| +
|
| + inline PreParserExpression SpreadCall(PreParserExpression function,
|
| + PreParserExpressionList args, int pos);
|
| +
|
| + inline PreParserExpression SpreadCallNew(PreParserExpression function,
|
| + PreParserExpressionList args,
|
| + int pos);
|
| +
|
| private:
|
| PreParser* pre_parser_;
|
| };
|
| @@ -1642,6 +1682,26 @@ void PreParserTraits::MaterializeTemplateCallsiteLiterals() {
|
| }
|
|
|
|
|
| +void PreParserTraits::MaterializeUnspreadArgumentsLiterals(int count) {
|
| + for (int i = 0; i < count; ++i) {
|
| + pre_parser_->function_state_->NextMaterializedLiteralIndex();
|
| + }
|
| +}
|
| +
|
| +
|
| +PreParserExpression PreParserTraits::SpreadCall(PreParserExpression function,
|
| + PreParserExpressionList args,
|
| + int pos) {
|
| + return pre_parser_->factory()->NewCall(function, args, pos);
|
| +}
|
| +
|
| +PreParserExpression PreParserTraits::SpreadCallNew(PreParserExpression function,
|
| + PreParserExpressionList args,
|
| + int pos) {
|
| + return pre_parser_->factory()->NewCallNew(function, args, pos);
|
| +}
|
| +
|
| +
|
| PreParserStatementList PreParser::ParseEagerFunctionBody(
|
| PreParserIdentifier function_name, int pos, Variable* fvar,
|
| Token::Value fvar_init_op, FunctionKind kind, bool* ok) {
|
| @@ -2311,18 +2371,42 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseObjectLiteral(
|
|
|
| template <class Traits>
|
| typename Traits::Type::ExpressionList ParserBase<Traits>::ParseArguments(
|
| - bool* ok) {
|
| + Scanner::Location* first_spread_arg_loc, bool* ok) {
|
| // Arguments ::
|
| // '(' (AssignmentExpression)*[','] ')'
|
|
|
| + Scanner::Location spread_arg = Scanner::Location::invalid();
|
| typename Traits::Type::ExpressionList result =
|
| this->NewExpressionList(4, zone_);
|
| Expect(Token::LPAREN, CHECK_OK_CUSTOM(NullExpressionList));
|
| bool done = (peek() == Token::RPAREN);
|
| + bool was_unspread = false;
|
| + int unspread_sequences_count = 0;
|
| while (!done) {
|
| + bool is_spread = allow_harmony_spreadcalls() && (peek() == Token::ELLIPSIS);
|
| + int start_pos = peek_position();
|
| + if (is_spread) Consume(Token::ELLIPSIS);
|
| +
|
| ExpressionT argument = this->ParseAssignmentExpression(
|
| true, CHECK_OK_CUSTOM(NullExpressionList));
|
| + if (is_spread) {
|
| + if (!spread_arg.IsValid()) {
|
| + spread_arg.beg_pos = start_pos;
|
| + spread_arg.end_pos = peek_position();
|
| + }
|
| + argument = factory()->NewSpreadOperation(argument, start_pos);
|
| + }
|
| result->Add(argument, zone_);
|
| +
|
| + // unspread_sequences_count is the number of sequences of parameters which
|
| + // are not prefixed with a spread '...' operator.
|
| + if (is_spread) {
|
| + was_unspread = false;
|
| + } else if (!was_unspread) {
|
| + was_unspread = true;
|
| + unspread_sequences_count++;
|
| + }
|
| +
|
| if (result->length() > Code::kMaxArguments) {
|
| ReportMessage("too_many_arguments");
|
| *ok = false;
|
| @@ -2339,6 +2423,15 @@ typename Traits::Type::ExpressionList ParserBase<Traits>::ParseArguments(
|
| *ok = false;
|
| return this->NullExpressionList();
|
| }
|
| + *first_spread_arg_loc = spread_arg;
|
| +
|
| + if (spread_arg.IsValid()) {
|
| + // Unspread parameter sequences are translated into array literals in the
|
| + // parser. Ensure that the number of materialized literals matches between
|
| + // the parser and preparser
|
| + Traits::MaterializeUnspreadArgumentsLiterals(unspread_sequences_count);
|
| + }
|
| +
|
| return result;
|
| }
|
|
|
| @@ -2653,7 +2746,9 @@ ParserBase<Traits>::ParseLeftHandSideExpression(bool* ok) {
|
| result->AsFunctionLiteral()->set_parenthesized();
|
| }
|
| }
|
| - typename Traits::Type::ExpressionList args = ParseArguments(CHECK_OK);
|
| + Scanner::Location spread_pos;
|
| + typename Traits::Type::ExpressionList args =
|
| + ParseArguments(&spread_pos, CHECK_OK);
|
|
|
| // Keep track of eval() calls since they disable all local variable
|
| // optimizations.
|
| @@ -2663,7 +2758,13 @@ ParserBase<Traits>::ParseLeftHandSideExpression(bool* ok) {
|
| // These calls are marked as potentially direct eval calls. Whether
|
| // they are actually direct calls to eval is determined at run time.
|
| this->CheckPossibleEvalCall(result, scope_);
|
| - result = factory()->NewCall(result, args, pos);
|
| +
|
| + if (spread_pos.IsValid()) {
|
| + args = Traits::PrepareSpreadArguments(args);
|
| + result = Traits::SpreadCall(result, args, pos);
|
| + } else {
|
| + result = factory()->NewCall(result, args, pos);
|
| + }
|
| if (fni_ != NULL) fni_->RemoveLastFunction();
|
| break;
|
| }
|
| @@ -2717,9 +2818,16 @@ ParserBase<Traits>::ParseMemberWithNewPrefixesExpression(bool* ok) {
|
| }
|
| if (peek() == Token::LPAREN) {
|
| // NewExpression with arguments.
|
| + Scanner::Location spread_pos;
|
| typename Traits::Type::ExpressionList args =
|
| - this->ParseArguments(CHECK_OK);
|
| - result = factory()->NewCallNew(result, args, new_pos);
|
| + this->ParseArguments(&spread_pos, CHECK_OK);
|
| +
|
| + if (spread_pos.IsValid()) {
|
| + args = Traits::PrepareSpreadArguments(args);
|
| + result = Traits::SpreadCallNew(result, args, new_pos);
|
| + } else {
|
| + result = factory()->NewCallNew(result, args, new_pos);
|
| + }
|
| // The expression can still continue with . or [ after the arguments.
|
| result = this->ParseMemberExpressionContinuation(result, CHECK_OK);
|
| return result;
|
|
|