| Index: src/parser.cc
|
| diff --git a/src/parser.cc b/src/parser.cc
|
| index 4412b8a98cdca5618ec0b7caf1a77caf246718b3..0dc013202f857d8398a72fb599c2b6daadc94ce1 100644
|
| --- a/src/parser.cc
|
| +++ b/src/parser.cc
|
| @@ -877,6 +877,7 @@ Parser::Parser(ParseInfo* info)
|
| set_allow_harmony_computed_property_names(
|
| FLAG_harmony_computed_property_names);
|
| set_allow_harmony_rest_params(FLAG_harmony_rest_parameters);
|
| + set_allow_harmony_spreadcalls(FLAG_harmony_spreadcalls);
|
| set_allow_strong_mode(FLAG_strong_mode);
|
| for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
|
| ++feature) {
|
| @@ -4231,6 +4232,8 @@ PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser(
|
| allow_harmony_computed_property_names());
|
| reusable_preparser_->set_allow_harmony_rest_params(
|
| allow_harmony_rest_params());
|
| + reusable_preparser_->set_allow_harmony_spreadcalls(
|
| + allow_harmony_spreadcalls());
|
| reusable_preparser_->set_allow_strong_mode(allow_strong_mode());
|
| }
|
| PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction(
|
| @@ -4349,7 +4352,10 @@ Expression* Parser::ParseV8Intrinsic(bool* ok) {
|
| Expect(Token::MOD, CHECK_OK);
|
| // Allow "eval" or "arguments" for backward compatibility.
|
| const AstRawString* name = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
|
| - ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
|
| + Scanner::Location spread_pos;
|
| + ZoneList<Expression*>* args = ParseArguments(&spread_pos, CHECK_OK);
|
| +
|
| + DCHECK(!spread_pos.IsValid());
|
|
|
| if (extension_ != NULL) {
|
| // The extension structures are only accessible while parsing the
|
| @@ -5614,4 +5620,121 @@ uint32_t Parser::ComputeTemplateLiteralHash(const TemplateLiteral* lit) {
|
|
|
| return running_hash;
|
| }
|
| +
|
| +
|
| +ZoneList<v8::internal::Expression*>* Parser::PrepareSpreadArguments(
|
| + ZoneList<v8::internal::Expression*>* list) {
|
| + ZoneList<v8::internal::Expression*>* args =
|
| + new (zone()) ZoneList<v8::internal::Expression*>(1, zone());
|
| + if (list->length() == 1) {
|
| + // Spread-call with single spread argument produces an InternalArray
|
| + // containing the values from the array.
|
| + //
|
| + // Function is called or constructed with the produced array of arguments
|
| + //
|
| + // EG: Apply(Func, Spread(spread0))
|
| + ZoneList<Expression*>* spread_list =
|
| + new (zone()) ZoneList<Expression*>(0, zone());
|
| + spread_list->Add(list->at(0)->AsSpread()->expression(), zone());
|
| + args->Add(
|
| + factory()->NewCallRuntime(ast_value_factory()->spread_iterable_string(),
|
| + NULL, spread_list, RelocInfo::kNoPosition),
|
| + zone());
|
| + return args;
|
| + } else {
|
| + // Spread-call with multiple arguments produces array literals for each
|
| + // sequences of unspread arguments, and converts each spread iterable to
|
| + // an Internal array. Finally, all of these produced arrays are flattened
|
| + // into a single InternalArray, containing the arguments for the call.
|
| + //
|
| + // EG: Apply(Func, Flatten([unspread0, unspread1], Spread(spread0),
|
| + // Spread(spread1), [unspread2, unspread3]))
|
| + int i = 0;
|
| + int n = list->length();
|
| + while (i < n) {
|
| + if (!list->at(i)->IsSpread()) {
|
| + ZoneList<v8::internal::Expression*>* unspread =
|
| + new (zone()) ZoneList<v8::internal::Expression*>(1, zone());
|
| +
|
| + // Push array of unspread parameters
|
| + while (i < n && !list->at(i)->IsSpread()) {
|
| + unspread->Add(list->at(i++), zone());
|
| + }
|
| + int literal_index = function_state_->NextMaterializedLiteralIndex();
|
| + args->Add(factory()->NewArrayLiteral(unspread, literal_index,
|
| + RelocInfo::kNoPosition),
|
| + zone());
|
| +
|
| + if (i == n) break;
|
| + }
|
| +
|
| + // Push eagerly spread argument
|
| + ZoneList<v8::internal::Expression*>* spread_list =
|
| + new (zone()) ZoneList<v8::internal::Expression*>(1, zone());
|
| + spread_list->Add(list->at(i++)->AsSpread()->expression(), zone());
|
| + args->Add(factory()->NewCallRuntime(
|
| + ast_value_factory()->spread_iterable_string(), NULL,
|
| + spread_list, RelocInfo::kNoPosition),
|
| + zone());
|
| + }
|
| +
|
| + list = new (zone()) ZoneList<v8::internal::Expression*>(1, zone());
|
| + list->Add(factory()->NewCallRuntime(
|
| + ast_value_factory()->spread_arguments_string(), NULL, args,
|
| + RelocInfo::kNoPosition),
|
| + zone());
|
| + return list;
|
| + }
|
| + UNREACHABLE();
|
| +}
|
| +
|
| +
|
| +Expression* Parser::SpreadCall(Expression* function,
|
| + ZoneList<v8::internal::Expression*>* args,
|
| + int pos) {
|
| + if (function->IsSuperReference()) {
|
| + // Super calls
|
| + args->InsertAt(0, function, zone());
|
| + args->Add(factory()->NewVariableProxy(scope_->new_target_var()), zone());
|
| + Expression* result = factory()->NewCallRuntime(
|
| + ast_value_factory()->reflect_construct_string(), NULL, args, pos);
|
| + args = new (zone()) ZoneList<Expression*>(0, zone());
|
| + args->Add(result, zone());
|
| + return factory()->NewCallRuntime(
|
| + ast_value_factory()->empty_string(),
|
| + Runtime::FunctionForId(Runtime::kInlineCallSuperWithSpread), args, pos);
|
| + } else {
|
| + if (function->IsProperty()) {
|
| + // Method calls
|
| + Variable* temp =
|
| + scope_->NewTemporary(ast_value_factory()->empty_string());
|
| + VariableProxy* obj = factory()->NewVariableProxy(temp);
|
| + Assignment* assign_obj = factory()->NewAssignment(
|
| + Token::ASSIGN, obj, function->AsProperty()->obj(),
|
| + RelocInfo::kNoPosition);
|
| + function = factory()->NewProperty(
|
| + assign_obj, function->AsProperty()->key(), RelocInfo::kNoPosition);
|
| + args->InsertAt(0, function, zone());
|
| + obj = factory()->NewVariableProxy(temp);
|
| + args->InsertAt(1, obj, zone());
|
| + } else {
|
| + // Non-method calls
|
| + args->InsertAt(0, function, zone());
|
| + args->InsertAt(1, factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
|
| + zone());
|
| + }
|
| + return factory()->NewCallRuntime(
|
| + ast_value_factory()->reflect_apply_string(), NULL, args, pos);
|
| + }
|
| +}
|
| +
|
| +
|
| +Expression* Parser::SpreadCallNew(Expression* function,
|
| + ZoneList<v8::internal::Expression*>* args,
|
| + int pos) {
|
| + args->InsertAt(0, function, zone());
|
| +
|
| + return factory()->NewCallRuntime(
|
| + ast_value_factory()->reflect_construct_string(), NULL, args, pos);
|
| +}
|
| } } // namespace v8::internal
|
|
|