| Index: src/parser.cc
|
| diff --git a/src/parser.cc b/src/parser.cc
|
| index 149de4dcf0c5effc3b607a1ec3e53dd279b9a0cd..68823e6c1f708a84cbba432187eac0972c397b43 100644
|
| --- a/src/parser.cc
|
| +++ b/src/parser.cc
|
| @@ -46,49 +46,6 @@
|
| namespace v8 {
|
| namespace internal {
|
|
|
| -// PositionStack is used for on-stack allocation of token positions for
|
| -// new expressions. Please look at ParseNewExpression.
|
| -
|
| -class PositionStack {
|
| - public:
|
| - explicit PositionStack(bool* ok) : top_(NULL), ok_(ok) {}
|
| - ~PositionStack() {
|
| - ASSERT(!*ok_ || is_empty());
|
| - USE(ok_);
|
| - }
|
| -
|
| - class Element {
|
| - public:
|
| - Element(PositionStack* stack, int value) {
|
| - previous_ = stack->top();
|
| - value_ = value;
|
| - stack->set_top(this);
|
| - }
|
| -
|
| - private:
|
| - Element* previous() { return previous_; }
|
| - int value() { return value_; }
|
| - friend class PositionStack;
|
| - Element* previous_;
|
| - int value_;
|
| - };
|
| -
|
| - bool is_empty() { return top_ == NULL; }
|
| - int pop() {
|
| - ASSERT(!is_empty());
|
| - int result = top_->value();
|
| - top_ = top_->previous();
|
| - return result;
|
| - }
|
| -
|
| - private:
|
| - Element* top() { return top_; }
|
| - void set_top(Element* value) { top_ = value; }
|
| - Element* top_;
|
| - bool* ok_;
|
| -};
|
| -
|
| -
|
| RegExpBuilder::RegExpBuilder(Zone* zone)
|
| : zone_(zone),
|
| pending_empty_(false),
|
| @@ -250,13 +207,19 @@ void RegExpBuilder::AddQuantifierToAtom(
|
|
|
|
|
| Handle<String> Parser::LookupSymbol(int symbol_id) {
|
| - // Length of symbol cache is the number of identified symbols.
|
| - // If we are larger than that, or negative, it's not a cached symbol.
|
| - // This might also happen if there is no preparser symbol data, even
|
| - // if there is some preparser data.
|
| - if (static_cast<unsigned>(symbol_id)
|
| - >= static_cast<unsigned>(symbol_cache_.length())) {
|
| - return scanner().GetLiteralSymbol();
|
| + // If there is no preparser symbol data, a negative number will be passed. In
|
| + // that case, we'll just read the literal from Scanner. This also guards
|
| + // against corrupt preparse data where the symbol id is larger than the symbol
|
| + // count.
|
| + if (symbol_id < 0 ||
|
| + (pre_parse_data_ && symbol_id >= pre_parse_data_->symbol_count())) {
|
| + if (scanner()->is_literal_ascii()) {
|
| + return isolate()->factory()->InternalizeOneByteString(
|
| + Vector<const uint8_t>::cast(scanner()->literal_ascii_string()));
|
| + } else {
|
| + return isolate()->factory()->InternalizeTwoByteString(
|
| + scanner()->literal_utf16_string());
|
| + }
|
| }
|
| return LookupCachedSymbol(symbol_id);
|
| }
|
| @@ -271,7 +234,13 @@ Handle<String> Parser::LookupCachedSymbol(int symbol_id) {
|
| }
|
| Handle<String> result = symbol_cache_.at(symbol_id);
|
| if (result.is_null()) {
|
| - result = scanner().GetLiteralSymbol();
|
| + if (scanner()->is_literal_ascii()) {
|
| + result = isolate()->factory()->InternalizeOneByteString(
|
| + Vector<const uint8_t>::cast(scanner()->literal_ascii_string()));
|
| + } else {
|
| + result = isolate()->factory()->InternalizeTwoByteString(
|
| + scanner()->literal_utf16_string());
|
| + }
|
| symbol_cache_.at(symbol_id) = result;
|
| return result;
|
| }
|
| @@ -360,10 +329,10 @@ const char* ScriptDataImpl::ReadString(unsigned* start, int* chars) {
|
| }
|
|
|
|
|
| -ScannerBase::Location ScriptDataImpl::MessageLocation() {
|
| +Scanner::Location ScriptDataImpl::MessageLocation() {
|
| int beg_pos = Read(PreparseDataConstants::kMessageStartPos);
|
| int end_pos = Read(PreparseDataConstants::kMessageEndPos);
|
| - return ScannerBase::Location(beg_pos, end_pos);
|
| + return Scanner::Location(beg_pos, end_pos);
|
| }
|
|
|
|
|
| @@ -451,56 +420,6 @@ class TargetScope BASE_EMBEDDED {
|
|
|
|
|
| // ----------------------------------------------------------------------------
|
| -// FunctionState and BlockState together implement the parser's scope stack.
|
| -// The parser's current scope is in top_scope_. The BlockState and
|
| -// FunctionState constructors push on the scope stack and the destructors
|
| -// pop. They are also used to hold the parser's per-function and per-block
|
| -// state.
|
| -
|
| -class Parser::BlockState BASE_EMBEDDED {
|
| - public:
|
| - BlockState(Parser* parser, Scope* scope)
|
| - : parser_(parser),
|
| - outer_scope_(parser->top_scope_) {
|
| - parser->top_scope_ = scope;
|
| - }
|
| -
|
| - ~BlockState() { parser_->top_scope_ = outer_scope_; }
|
| -
|
| - private:
|
| - Parser* parser_;
|
| - Scope* outer_scope_;
|
| -};
|
| -
|
| -
|
| -Parser::FunctionState::FunctionState(Parser* parser,
|
| - Scope* scope,
|
| - Isolate* isolate)
|
| - : next_materialized_literal_index_(JSFunction::kLiteralsPrefixSize),
|
| - next_handler_index_(0),
|
| - expected_property_count_(0),
|
| - generator_object_variable_(NULL),
|
| - parser_(parser),
|
| - outer_function_state_(parser->current_function_state_),
|
| - outer_scope_(parser->top_scope_),
|
| - saved_ast_node_id_(isolate->ast_node_id()),
|
| - factory_(isolate, parser->zone()) {
|
| - parser->top_scope_ = scope;
|
| - parser->current_function_state_ = this;
|
| - isolate->set_ast_node_id(BailoutId::FirstUsable().ToInt());
|
| -}
|
| -
|
| -
|
| -Parser::FunctionState::~FunctionState() {
|
| - parser_->top_scope_ = outer_scope_;
|
| - parser_->current_function_state_ = outer_function_state_;
|
| - if (outer_function_state_ != NULL) {
|
| - parser_->isolate()->set_ast_node_id(saved_ast_node_id_);
|
| - }
|
| -}
|
| -
|
| -
|
| -// ----------------------------------------------------------------------------
|
| // The CHECK_OK macro is a convenient macro to enforce error
|
| // handling for functions that may fail (by returning !*ok).
|
| //
|
| @@ -523,26 +442,176 @@ Parser::FunctionState::~FunctionState() {
|
| // ----------------------------------------------------------------------------
|
| // Implementation of Parser
|
|
|
| +bool ParserTraits::IsEvalOrArguments(Handle<String> identifier) const {
|
| + return identifier.is_identical_to(
|
| + parser_->isolate()->factory()->eval_string()) ||
|
| + identifier.is_identical_to(
|
| + parser_->isolate()->factory()->arguments_string());
|
| +}
|
| +
|
| +
|
| +void ParserTraits::ReportMessageAt(Scanner::Location source_location,
|
| + const char* message,
|
| + Vector<const char*> args) {
|
| + MessageLocation location(parser_->script_,
|
| + source_location.beg_pos,
|
| + source_location.end_pos);
|
| + Factory* factory = parser_->isolate()->factory();
|
| + Handle<FixedArray> elements = factory->NewFixedArray(args.length());
|
| + for (int i = 0; i < args.length(); i++) {
|
| + Handle<String> arg_string = factory->NewStringFromUtf8(CStrVector(args[i]));
|
| + elements->set(i, *arg_string);
|
| + }
|
| + Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
|
| + Handle<Object> result = factory->NewSyntaxError(message, array);
|
| + parser_->isolate()->Throw(*result, &location);
|
| +}
|
| +
|
| +
|
| +void ParserTraits::ReportMessage(const char* message,
|
| + Vector<Handle<String> > args) {
|
| + Scanner::Location source_location = parser_->scanner()->location();
|
| + ReportMessageAt(source_location, message, args);
|
| +}
|
| +
|
| +
|
| +void ParserTraits::ReportMessageAt(Scanner::Location source_location,
|
| + const char* message,
|
| + Vector<Handle<String> > args) {
|
| + MessageLocation location(parser_->script_,
|
| + source_location.beg_pos,
|
| + source_location.end_pos);
|
| + Factory* factory = parser_->isolate()->factory();
|
| + Handle<FixedArray> elements = factory->NewFixedArray(args.length());
|
| + for (int i = 0; i < args.length(); i++) {
|
| + elements->set(i, *args[i]);
|
| + }
|
| + Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
|
| + Handle<Object> result = factory->NewSyntaxError(message, array);
|
| + parser_->isolate()->Throw(*result, &location);
|
| +}
|
| +
|
| +
|
| +Handle<String> ParserTraits::GetSymbol(Scanner* scanner) {
|
| + int symbol_id = -1;
|
| + if (parser_->pre_parse_data() != NULL) {
|
| + symbol_id = parser_->pre_parse_data()->GetSymbolIdentifier();
|
| + }
|
| + return parser_->LookupSymbol(symbol_id);
|
| +}
|
| +
|
| +
|
| +Handle<String> ParserTraits::NextLiteralString(Scanner* scanner,
|
| + PretenureFlag tenured) {
|
| + if (scanner->is_next_literal_ascii()) {
|
| + return parser_->isolate_->factory()->NewStringFromAscii(
|
| + scanner->next_literal_ascii_string(), tenured);
|
| + } else {
|
| + return parser_->isolate_->factory()->NewStringFromTwoByte(
|
| + scanner->next_literal_utf16_string(), tenured);
|
| + }
|
| +}
|
| +
|
| +
|
| +Expression* ParserTraits::ThisExpression(
|
| + Scope* scope,
|
| + AstNodeFactory<AstConstructionVisitor>* factory) {
|
| + return factory->NewVariableProxy(scope->receiver());
|
| +}
|
| +
|
| +
|
| +Expression* ParserTraits::ExpressionFromLiteral(
|
| + Token::Value token, int pos,
|
| + Scanner* scanner,
|
| + AstNodeFactory<AstConstructionVisitor>* factory) {
|
| + Factory* isolate_factory = parser_->isolate()->factory();
|
| + switch (token) {
|
| + case Token::NULL_LITERAL:
|
| + return factory->NewLiteral(isolate_factory->null_value(), pos);
|
| + case Token::TRUE_LITERAL:
|
| + return factory->NewLiteral(isolate_factory->true_value(), pos);
|
| + case Token::FALSE_LITERAL:
|
| + return factory->NewLiteral(isolate_factory->false_value(), pos);
|
| + case Token::NUMBER: {
|
| + ASSERT(scanner->is_literal_ascii());
|
| + double value = StringToDouble(parser_->isolate()->unicode_cache(),
|
| + scanner->literal_ascii_string(),
|
| + ALLOW_HEX | ALLOW_OCTAL |
|
| + ALLOW_IMPLICIT_OCTAL | ALLOW_BINARY);
|
| + return factory->NewNumberLiteral(value, pos);
|
| + }
|
| + default:
|
| + ASSERT(false);
|
| + }
|
| + return NULL;
|
| +}
|
| +
|
| +
|
| +Expression* ParserTraits::ExpressionFromIdentifier(
|
| + Handle<String> name, int pos, Scope* scope,
|
| + AstNodeFactory<AstConstructionVisitor>* factory) {
|
| + if (parser_->fni_ != NULL) parser_->fni_->PushVariableName(name);
|
| + // The name may refer to a module instance object, so its type is unknown.
|
| +#ifdef DEBUG
|
| + if (FLAG_print_interface_details)
|
| + PrintF("# Variable %s ", name->ToAsciiArray());
|
| +#endif
|
| + Interface* interface = Interface::NewUnknown(parser_->zone());
|
| + return scope->NewUnresolved(factory, name, interface, pos);
|
| +}
|
| +
|
| +
|
| +Expression* ParserTraits::ExpressionFromString(
|
| + int pos, Scanner* scanner,
|
| + AstNodeFactory<AstConstructionVisitor>* factory) {
|
| + Handle<String> symbol = GetSymbol(scanner);
|
| + if (parser_->fni_ != NULL) parser_->fni_->PushLiteralName(symbol);
|
| + return factory->NewLiteral(symbol, pos);
|
| +}
|
| +
|
| +
|
| +Literal* ParserTraits::GetLiteralTheHole(
|
| + int position, AstNodeFactory<AstConstructionVisitor>* factory) {
|
| + return factory->NewLiteral(parser_->isolate()->factory()->the_hole_value(),
|
| + RelocInfo::kNoPosition);
|
| +}
|
| +
|
| +
|
| +Expression* ParserTraits::ParseObjectLiteral(bool* ok) {
|
| + return parser_->ParseObjectLiteral(ok);
|
| +}
|
| +
|
| +
|
| +Expression* ParserTraits::ParseAssignmentExpression(bool accept_IN, bool* ok) {
|
| + return parser_->ParseAssignmentExpression(accept_IN, ok);
|
| +}
|
| +
|
| +
|
| +Expression* ParserTraits::ParseV8Intrinsic(bool* ok) {
|
| + return parser_->ParseV8Intrinsic(ok);
|
| +}
|
| +
|
| +
|
| Parser::Parser(CompilationInfo* info)
|
| - : ParserBase(NULL, info->isolate()->stack_guard()->real_climit()),
|
| + : ParserBase<ParserTraits>(&scanner_,
|
| + info->isolate()->stack_guard()->real_climit(),
|
| + info->extension(),
|
| + info->zone(),
|
| + this),
|
| isolate_(info->isolate()),
|
| symbol_cache_(0, info->zone()),
|
| script_(info->script()),
|
| + scanner_(isolate_->unicode_cache()),
|
| reusable_preparser_(NULL),
|
| - top_scope_(NULL),
|
| original_scope_(NULL),
|
| - current_function_state_(NULL),
|
| target_stack_(NULL),
|
| - extension_(info->extension()),
|
| pre_parse_data_(NULL),
|
| fni_(NULL),
|
| - parenthesized_function_(false),
|
| - zone_(info->zone()),
|
| info_(info) {
|
| ASSERT(!script_.is_null());
|
| isolate_->set_ast_node_id(0);
|
| - set_allow_harmony_scoping(!info_->is_native() && FLAG_harmony_scoping);
|
| - set_allow_modules(!info_->is_native() && FLAG_harmony_modules);
|
| + set_allow_harmony_scoping(!info->is_native() && FLAG_harmony_scoping);
|
| + set_allow_modules(!info->is_native() && FLAG_harmony_modules);
|
| set_allow_natives_syntax(FLAG_allow_natives_syntax || info->is_native());
|
| set_allow_lazy(false); // Must be explicitly enabled.
|
| set_allow_generators(FLAG_harmony_generators);
|
| @@ -564,18 +633,21 @@ FunctionLiteral* Parser::ParseProgram() {
|
| fni_ = new(zone()) FuncNameInferrer(isolate(), zone());
|
|
|
| // Initialize parser state.
|
| - source = FlattenGetString(source);
|
| + source->TryFlatten();
|
| FunctionLiteral* result;
|
| - delete reusable_preparser_;
|
| - delete scanner_;
|
| - if (source->IsTwoByteRepresentation()) {
|
| - scanner_ = new ExperimentalScanner<uint16_t>(source, isolate());
|
| + if (source->IsExternalTwoByteString()) {
|
| + // Notice that the stream is destroyed at the end of the branch block.
|
| + // The last line of the blocks can't be moved outside, even though they're
|
| + // identical calls.
|
| + ExternalTwoByteStringUtf16CharacterStream stream(
|
| + Handle<ExternalTwoByteString>::cast(source), 0, source->length());
|
| + scanner_.Initialize(&stream);
|
| + result = DoParseProgram(info(), source);
|
| } else {
|
| - scanner_ = new ExperimentalScanner<uint8_t>(source, isolate());
|
| + GenericStringUtf16CharacterStream stream(source, 0, source->length());
|
| + scanner_.Initialize(&stream);
|
| + result = DoParseProgram(info(), source);
|
| }
|
| - SetScannerFlags();
|
| - scanner_->Init();
|
| - result = DoParseProgram(info(), source);
|
|
|
| if (FLAG_trace_parse && result != NULL) {
|
| double ms = timer.Elapsed().InMillisecondsF();
|
| @@ -596,14 +668,14 @@ FunctionLiteral* Parser::ParseProgram() {
|
|
|
| FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info,
|
| Handle<String> source) {
|
| - ASSERT(top_scope_ == NULL);
|
| + ASSERT(scope_ == NULL);
|
| ASSERT(target_stack_ == NULL);
|
| if (pre_parse_data_ != NULL) pre_parse_data_->Initialize();
|
|
|
| Handle<String> no_name = isolate()->factory()->empty_string();
|
|
|
| FunctionLiteral* result = NULL;
|
| - { Scope* scope = NewScope(top_scope_, GLOBAL_SCOPE);
|
| + { Scope* scope = NewScope(scope_, GLOBAL_SCOPE);
|
| info->SetGlobalScope(scope);
|
| if (!info->context().is_null()) {
|
| scope = Scope::DeserializeScopeChain(*info->context(), scope, zone());
|
| @@ -629,19 +701,19 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info,
|
| ParsingModeScope parsing_mode(this, mode);
|
|
|
| // Enters 'scope'.
|
| - FunctionState function_state(this, scope, isolate());
|
| + FunctionState function_state(&function_state_, &scope_, scope, zone());
|
|
|
| - top_scope_->SetLanguageMode(info->language_mode());
|
| + scope_->SetLanguageMode(info->language_mode());
|
| ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone());
|
| bool ok = true;
|
| - int beg_pos = scanner().location().beg_pos;
|
| + int beg_pos = scanner()->location().beg_pos;
|
| ParseSourceElements(body, Token::EOS, info->is_eval(), true, &ok);
|
| - if (ok && !top_scope_->is_classic_mode()) {
|
| - CheckOctalLiteral(beg_pos, scanner().location().end_pos, &ok);
|
| + if (ok && !scope_->is_classic_mode()) {
|
| + CheckOctalLiteral(beg_pos, scanner()->location().end_pos, &ok);
|
| }
|
|
|
| if (ok && is_extended_mode()) {
|
| - CheckConflictingVarDeclarations(top_scope_, &ok);
|
| + CheckConflictingVarDeclarations(scope_, &ok);
|
| }
|
|
|
| if (ok && info->parse_restriction() == ONLY_SINGLE_FUNCTION_LITERAL) {
|
| @@ -657,7 +729,7 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info,
|
| if (ok) {
|
| result = factory()->NewFunctionLiteral(
|
| no_name,
|
| - top_scope_,
|
| + scope_,
|
| body,
|
| function_state.materialized_literal_count(),
|
| function_state.expected_property_count(),
|
| @@ -670,6 +742,7 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info,
|
| FunctionLiteral::kNotGenerator,
|
| 0);
|
| result->set_ast_properties(factory()->visitor()->ast_properties());
|
| + result->set_slot_processor(factory()->visitor()->slot_processor());
|
| result->set_dont_optimize_reason(
|
| factory()->visitor()->dont_optimize_reason());
|
| } else if (stack_overflow()) {
|
| @@ -692,10 +765,24 @@ FunctionLiteral* Parser::ParseLazy() {
|
| if (FLAG_trace_parse) {
|
| timer.Start();
|
| }
|
| - // Initialize parser state.
|
| Handle<SharedFunctionInfo> shared_info = info()->shared_info();
|
| - FunctionLiteral* result = ParseLazy(
|
| - source, shared_info->start_position(), shared_info->end_position());
|
| +
|
| + // Initialize parser state.
|
| + source->TryFlatten();
|
| + FunctionLiteral* result;
|
| + if (source->IsExternalTwoByteString()) {
|
| + ExternalTwoByteStringUtf16CharacterStream stream(
|
| + Handle<ExternalTwoByteString>::cast(source),
|
| + shared_info->start_position(),
|
| + shared_info->end_position());
|
| + result = ParseLazy(&stream);
|
| + } else {
|
| + GenericStringUtf16CharacterStream stream(source,
|
| + shared_info->start_position(),
|
| + shared_info->end_position());
|
| + result = ParseLazy(&stream);
|
| + }
|
| +
|
| if (FLAG_trace_parse && result != NULL) {
|
| double ms = timer.Elapsed().InMillisecondsF();
|
| SmartArrayPointer<char> name_chars = result->debug_name()->ToCString();
|
| @@ -705,22 +792,10 @@ FunctionLiteral* Parser::ParseLazy() {
|
| }
|
|
|
|
|
| -FunctionLiteral* Parser::ParseLazy(Handle<String> source, int start, int end) {
|
| - source = FlattenGetString(source);
|
| - delete reusable_preparser_;
|
| - delete scanner_;
|
| - if (source->IsTwoByteRepresentation()) {
|
| - scanner_ = new ExperimentalScanner<uint16_t>(source, isolate());
|
| - } else {
|
| - scanner_ = new ExperimentalScanner<uint8_t>(source, isolate());
|
| - }
|
| - SetScannerFlags();
|
| - // We don't need to Init() if we immediately SeekForward.
|
| - scanner_->SeekForward(start);
|
| - scanner_->SetEnd(end);
|
| -
|
| +FunctionLiteral* Parser::ParseLazy(Utf16CharacterStream* source) {
|
| Handle<SharedFunctionInfo> shared_info = info()->shared_info();
|
| - ASSERT(top_scope_ == NULL);
|
| + scanner_.Initialize(source);
|
| + ASSERT(scope_ == NULL);
|
| ASSERT(target_stack_ == NULL);
|
|
|
| Handle<String> name(String::cast(shared_info->name()));
|
| @@ -734,14 +809,14 @@ FunctionLiteral* Parser::ParseLazy(Handle<String> source, int start, int end) {
|
|
|
| {
|
| // Parse the function literal.
|
| - Scope* scope = NewScope(top_scope_, GLOBAL_SCOPE);
|
| + Scope* scope = NewScope(scope_, GLOBAL_SCOPE);
|
| info()->SetGlobalScope(scope);
|
| if (!info()->closure().is_null()) {
|
| scope = Scope::DeserializeScopeChain(info()->closure()->context(), scope,
|
| zone());
|
| }
|
| original_scope_ = scope;
|
| - FunctionState function_state(this, scope, isolate());
|
| + FunctionState function_state(&function_state_, &scope_, scope, zone());
|
| ASSERT(scope->language_mode() != STRICT_MODE || !info()->is_classic_mode());
|
| ASSERT(scope->language_mode() != EXTENDED_MODE ||
|
| info()->is_extended_mode());
|
| @@ -754,6 +829,7 @@ FunctionLiteral* Parser::ParseLazy(Handle<String> source, int start, int end) {
|
| : FunctionLiteral::DECLARATION;
|
| bool ok = true;
|
| result = ParseFunctionLiteral(name,
|
| + Scanner::Location::invalid(),
|
| false, // Strict mode name already checked.
|
| shared_info->is_generator(),
|
| RelocInfo::kNoPosition,
|
| @@ -776,62 +852,6 @@ FunctionLiteral* Parser::ParseLazy(Handle<String> source, int start, int end) {
|
| }
|
|
|
|
|
| -Handle<String> Parser::GetSymbol() {
|
| - int symbol_id = -1;
|
| - if (pre_parse_data() != NULL) {
|
| - symbol_id = pre_parse_data()->GetSymbolIdentifier();
|
| - }
|
| - return LookupSymbol(symbol_id);
|
| -}
|
| -
|
| -
|
| -void Parser::ReportMessage(const char* message, Vector<const char*> args) {
|
| - ScannerBase::Location source_location = scanner().location();
|
| - ReportMessageAt(source_location, message, args);
|
| -}
|
| -
|
| -
|
| -void Parser::ReportMessage(const char* message, Vector<Handle<String> > args) {
|
| - ScannerBase::Location source_location = scanner().location();
|
| - ReportMessageAt(source_location, message, args);
|
| -}
|
| -
|
| -
|
| -void Parser::ReportMessageAt(ScannerBase::Location source_location,
|
| - const char* message,
|
| - Vector<const char*> args) {
|
| - MessageLocation location(script_,
|
| - source_location.beg_pos,
|
| - source_location.end_pos);
|
| - Factory* factory = isolate()->factory();
|
| - Handle<FixedArray> elements = factory->NewFixedArray(args.length());
|
| - for (int i = 0; i < args.length(); i++) {
|
| - Handle<String> arg_string = factory->NewStringFromUtf8(CStrVector(args[i]));
|
| - elements->set(i, *arg_string);
|
| - }
|
| - Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
|
| - Handle<Object> result = factory->NewSyntaxError(message, array);
|
| - isolate()->Throw(*result, &location);
|
| -}
|
| -
|
| -
|
| -void Parser::ReportMessageAt(ScannerBase::Location source_location,
|
| - const char* message,
|
| - Vector<Handle<String> > args) {
|
| - MessageLocation location(script_,
|
| - source_location.beg_pos,
|
| - source_location.end_pos);
|
| - Factory* factory = isolate()->factory();
|
| - Handle<FixedArray> elements = factory->NewFixedArray(args.length());
|
| - for (int i = 0; i < args.length(); i++) {
|
| - elements->set(i, *args[i]);
|
| - }
|
| - Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
|
| - Handle<Object> result = factory->NewSyntaxError(message, array);
|
| - isolate()->Throw(*result, &location);
|
| -}
|
| -
|
| -
|
| void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
|
| int end_token,
|
| bool is_eval,
|
| @@ -854,7 +874,7 @@ void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
|
| directive_prologue = false;
|
| }
|
|
|
| - ScannerBase::Location token_loc = scanner().peek_location();
|
| + Scanner::Location token_loc = scanner()->peek_location();
|
| Statement* stat;
|
| if (is_global && !is_eval) {
|
| stat = ParseModuleElement(NULL, CHECK_OK);
|
| @@ -877,7 +897,7 @@ void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
|
| Handle<String> directive = Handle<String>::cast(literal->value());
|
|
|
| // Check "use strict" directive (ES5 14.1).
|
| - if (top_scope_->is_classic_mode() &&
|
| + if (scope_->is_classic_mode() &&
|
| directive->Equals(isolate()->heap()->use_strict_string()) &&
|
| token_loc.end_pos - token_loc.beg_pos ==
|
| isolate()->heap()->use_strict_string()->length() + 2) {
|
| @@ -886,16 +906,16 @@ void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
|
| // add this scope in DoParseProgram(), but that requires adaptations
|
| // all over the code base, so we go with a quick-fix for now.
|
| // In the same manner, we have to patch the parsing mode.
|
| - if (is_eval && !top_scope_->is_eval_scope()) {
|
| - ASSERT(top_scope_->is_global_scope());
|
| - Scope* scope = NewScope(top_scope_, EVAL_SCOPE);
|
| - scope->set_start_position(top_scope_->start_position());
|
| - scope->set_end_position(top_scope_->end_position());
|
| - top_scope_ = scope;
|
| + if (is_eval && !scope_->is_eval_scope()) {
|
| + ASSERT(scope_->is_global_scope());
|
| + Scope* scope = NewScope(scope_, EVAL_SCOPE);
|
| + scope->set_start_position(scope_->start_position());
|
| + scope->set_end_position(scope_->end_position());
|
| + scope_ = scope;
|
| mode_ = PARSE_EAGERLY;
|
| }
|
| // TODO(ES6): Fix entering extended mode, once it is specified.
|
| - top_scope_->SetLanguageMode(allow_harmony_scoping()
|
| + scope_->SetLanguageMode(allow_harmony_scoping()
|
| ? EXTENDED_MODE : STRICT_MODE);
|
| // "use strict" is the only directive for now.
|
| directive_prologue = false;
|
| @@ -944,14 +964,14 @@ Statement* Parser::ParseModuleElement(ZoneStringList* labels,
|
| // Handle 'module' as a context-sensitive keyword.
|
| if (FLAG_harmony_modules &&
|
| peek() == Token::IDENTIFIER &&
|
| - !scanner().HasAnyLineTerminatorBeforeNext() &&
|
| + !scanner()->HasAnyLineTerminatorBeforeNext() &&
|
| stmt != NULL) {
|
| ExpressionStatement* estmt = stmt->AsExpressionStatement();
|
| if (estmt != NULL &&
|
| estmt->expression()->AsVariableProxy() != NULL &&
|
| estmt->expression()->AsVariableProxy()->name()->Equals(
|
| isolate()->heap()->module_string()) &&
|
| - !scanner().literal_contains_escapes()) {
|
| + !scanner()->literal_contains_escapes()) {
|
| return ParseModuleDeclaration(NULL, ok);
|
| }
|
| }
|
| @@ -966,7 +986,7 @@ Statement* Parser::ParseModuleDeclaration(ZoneStringList* names, bool* ok) {
|
| // 'module' Identifier Module
|
|
|
| int pos = peek_position();
|
| - Handle<String> name = ParseIdentifier(CHECK_OK);
|
| + Handle<String> name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
|
|
|
| #ifdef DEBUG
|
| if (FLAG_print_interface_details)
|
| @@ -976,7 +996,7 @@ Statement* Parser::ParseModuleDeclaration(ZoneStringList* names, bool* ok) {
|
| Module* module = ParseModule(CHECK_OK);
|
| VariableProxy* proxy = NewUnresolved(name, MODULE, module->interface());
|
| Declaration* declaration =
|
| - factory()->NewModuleDeclaration(proxy, module, top_scope_, pos);
|
| + factory()->NewModuleDeclaration(proxy, module, scope_, pos);
|
| Declare(declaration, true, CHECK_OK);
|
|
|
| #ifdef DEBUG
|
| @@ -1034,14 +1054,14 @@ Module* Parser::ParseModuleLiteral(bool* ok) {
|
| #ifdef DEBUG
|
| if (FLAG_print_interface_details) PrintF("# Literal ");
|
| #endif
|
| - Scope* scope = NewScope(top_scope_, MODULE_SCOPE);
|
| + Scope* scope = NewScope(scope_, MODULE_SCOPE);
|
|
|
| Expect(Token::LBRACE, CHECK_OK);
|
| - scope->set_start_position(scanner().location().beg_pos);
|
| + scope->set_start_position(scanner()->location().beg_pos);
|
| scope->SetLanguageMode(EXTENDED_MODE);
|
|
|
| {
|
| - BlockState block_state(this, scope);
|
| + BlockState block_state(&scope_, scope);
|
| TargetCollector collector(zone());
|
| Target target(&this->target_stack_, &collector);
|
| Target target_body(&this->target_stack_, body);
|
| @@ -1055,7 +1075,7 @@ Module* Parser::ParseModuleLiteral(bool* ok) {
|
| }
|
|
|
| Expect(Token::RBRACE, CHECK_OK);
|
| - scope->set_end_position(scanner().location().end_pos);
|
| + scope->set_end_position(scanner()->location().end_pos);
|
| body->set_scope(scope);
|
|
|
| // Check that all exports are bound.
|
| @@ -1064,8 +1084,8 @@ Module* Parser::ParseModuleLiteral(bool* ok) {
|
| !it.done(); it.Advance()) {
|
| if (scope->LocalLookup(it.name()) == NULL) {
|
| Handle<String> name(it.name());
|
| - ReportMessage("module_export_undefined",
|
| - Vector<Handle<String> >(&name, 1));
|
| + ParserTraits::ReportMessage("module_export_undefined",
|
| + Vector<Handle<String> >(&name, 1));
|
| *ok = false;
|
| return NULL;
|
| }
|
| @@ -1104,7 +1124,8 @@ Module* Parser::ParseModulePath(bool* ok) {
|
| member->interface()->Print();
|
| }
|
| #endif
|
| - ReportMessage("invalid_module_path", Vector<Handle<String> >(&name, 1));
|
| + ParserTraits::ReportMessage("invalid_module_path",
|
| + Vector<Handle<String> >(&name, 1));
|
| return NULL;
|
| }
|
| result = member;
|
| @@ -1119,14 +1140,14 @@ Module* Parser::ParseModuleVariable(bool* ok) {
|
| // Identifier
|
|
|
| int pos = peek_position();
|
| - Handle<String> name = ParseIdentifier(CHECK_OK);
|
| + Handle<String> name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
|
| #ifdef DEBUG
|
| if (FLAG_print_interface_details)
|
| PrintF("# Module variable %s ", name->ToAsciiArray());
|
| #endif
|
| - VariableProxy* proxy = top_scope_->NewUnresolved(
|
| + VariableProxy* proxy = scope_->NewUnresolved(
|
| factory(), name, Interface::NewModule(zone()),
|
| - scanner().location().beg_pos);
|
| + scanner()->location().beg_pos);
|
|
|
| return factory()->NewModuleVariable(proxy, pos);
|
| }
|
| @@ -1148,7 +1169,7 @@ Module* Parser::ParseModuleUrl(bool* ok) {
|
|
|
| // Create an empty literal as long as the feature isn't finished.
|
| USE(symbol);
|
| - Scope* scope = NewScope(top_scope_, MODULE_SCOPE);
|
| + Scope* scope = NewScope(scope_, MODULE_SCOPE);
|
| Block* body = factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition);
|
| body->set_scope(scope);
|
| Interface* interface = scope->interface();
|
| @@ -1214,12 +1235,13 @@ Block* Parser::ParseImportDeclaration(bool* ok) {
|
| module->interface()->Print();
|
| }
|
| #endif
|
| - ReportMessage("invalid_module_path", Vector<Handle<String> >(&name, 1));
|
| + ParserTraits::ReportMessage("invalid_module_path",
|
| + Vector<Handle<String> >(&name, 1));
|
| return NULL;
|
| }
|
| VariableProxy* proxy = NewUnresolved(names[i], LET, interface);
|
| Declaration* declaration =
|
| - factory()->NewImportDeclaration(proxy, module, top_scope_, pos);
|
| + factory()->NewImportDeclaration(proxy, module, scope_, pos);
|
| Declare(declaration, true, CHECK_OK);
|
| }
|
|
|
| @@ -1244,13 +1266,14 @@ Statement* Parser::ParseExportDeclaration(bool* ok) {
|
| switch (peek()) {
|
| case Token::IDENTIFIER: {
|
| int pos = position();
|
| - Handle<String> name = ParseIdentifier(CHECK_OK);
|
| + Handle<String> name =
|
| + ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
|
| // Handle 'module' as a context-sensitive keyword.
|
| if (!name->IsOneByteEqualTo(STATIC_ASCII_VECTOR("module"))) {
|
| names.Add(name, zone());
|
| while (peek() == Token::COMMA) {
|
| Consume(Token::COMMA);
|
| - name = ParseIdentifier(CHECK_OK);
|
| + name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
|
| names.Add(name, zone());
|
| }
|
| ExpectSemicolon(CHECK_OK);
|
| @@ -1273,12 +1296,12 @@ Statement* Parser::ParseExportDeclaration(bool* ok) {
|
|
|
| default:
|
| *ok = false;
|
| - ReportUnexpectedToken(scanner().current_token());
|
| + ReportUnexpectedToken(scanner()->current_token());
|
| return NULL;
|
| }
|
|
|
| // Extract declared names into export declarations and interface.
|
| - Interface* interface = top_scope_->interface();
|
| + Interface* interface = scope_->interface();
|
| for (int i = 0; i < names.length(); ++i) {
|
| #ifdef DEBUG
|
| if (FLAG_print_interface_details)
|
| @@ -1293,8 +1316,8 @@ Statement* Parser::ParseExportDeclaration(bool* ok) {
|
| // TODO(rossberg): Rethink whether we actually need to store export
|
| // declarations (for compilation?).
|
| // ExportDeclaration* declaration =
|
| - // factory()->NewExportDeclaration(proxy, top_scope_, position);
|
| - // top_scope_->AddDeclaration(declaration);
|
| + // factory()->NewExportDeclaration(proxy, scope_, position);
|
| + // scope_->AddDeclaration(declaration);
|
| }
|
|
|
| ASSERT(result != NULL);
|
| @@ -1420,9 +1443,8 @@ Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) {
|
| // In Harmony mode, this case also handles the extension:
|
| // Statement:
|
| // GeneratorDeclaration
|
| - if (!top_scope_->is_classic_mode()) {
|
| - ReportMessageAt(scanner().peek_location(), "strict_function",
|
| - Vector<const char*>::empty());
|
| + if (!scope_->is_classic_mode()) {
|
| + ReportMessageAt(scanner()->peek_location(), "strict_function");
|
| *ok = false;
|
| return NULL;
|
| }
|
| @@ -1601,7 +1623,8 @@ void Parser::Declare(Declaration* declaration, bool resolve, bool* ok) {
|
| var->interface()->Print();
|
| }
|
| #endif
|
| - ReportMessage("module_type_error", Vector<Handle<String> >(&name, 1));
|
| + ParserTraits::ReportMessage("module_type_error",
|
| + Vector<Handle<String> >(&name, 1));
|
| }
|
| }
|
| }
|
| @@ -1615,11 +1638,12 @@ void Parser::Declare(Declaration* declaration, bool resolve, bool* ok) {
|
| Statement* Parser::ParseNativeDeclaration(bool* ok) {
|
| int pos = peek_position();
|
| Expect(Token::FUNCTION, CHECK_OK);
|
| - Handle<String> name = ParseIdentifier(CHECK_OK);
|
| + // Allow "eval" or "arguments" for backward compatibility.
|
| + Handle<String> name = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
|
| Expect(Token::LPAREN, CHECK_OK);
|
| bool done = (peek() == Token::RPAREN);
|
| while (!done) {
|
| - ParseIdentifier(CHECK_OK);
|
| + ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
|
| done = (peek() == Token::RPAREN);
|
| if (!done) {
|
| Expect(Token::COMMA, CHECK_OK);
|
| @@ -1639,7 +1663,7 @@ Statement* Parser::ParseNativeDeclaration(bool* ok) {
|
| // other functions are set up when entering the surrounding scope.
|
| VariableProxy* proxy = NewUnresolved(name, VAR, Interface::NewValue());
|
| Declaration* declaration =
|
| - factory()->NewVariableDeclaration(proxy, VAR, top_scope_, pos);
|
| + factory()->NewVariableDeclaration(proxy, VAR, scope_, pos);
|
| Declare(declaration, true, CHECK_OK);
|
| NativeFunctionLiteral* lit = factory()->NewNativeFunctionLiteral(
|
| name, extension_, RelocInfo::kNoPosition);
|
| @@ -1663,6 +1687,7 @@ Statement* Parser::ParseFunctionDeclaration(ZoneStringList* names, bool* ok) {
|
| Handle<String> name = ParseIdentifierOrStrictReservedWord(
|
| &is_strict_reserved, CHECK_OK);
|
| FunctionLiteral* fun = ParseFunctionLiteral(name,
|
| + scanner()->location(),
|
| is_strict_reserved,
|
| is_generator,
|
| pos,
|
| @@ -1674,10 +1699,10 @@ Statement* Parser::ParseFunctionDeclaration(ZoneStringList* names, bool* ok) {
|
| // In extended mode, a function behaves as a lexical binding, except in the
|
| // global scope.
|
| VariableMode mode =
|
| - is_extended_mode() && !top_scope_->is_global_scope() ? LET : VAR;
|
| + is_extended_mode() && !scope_->is_global_scope() ? LET : VAR;
|
| VariableProxy* proxy = NewUnresolved(name, mode, Interface::NewValue());
|
| Declaration* declaration =
|
| - factory()->NewFunctionDeclaration(proxy, mode, fun, top_scope_, pos);
|
| + factory()->NewFunctionDeclaration(proxy, mode, fun, scope_, pos);
|
| Declare(declaration, true, CHECK_OK);
|
| if (names) names->Add(name, zone());
|
| return factory()->NewEmptyStatement(RelocInfo::kNoPosition);
|
| @@ -1685,7 +1710,7 @@ Statement* Parser::ParseFunctionDeclaration(ZoneStringList* names, bool* ok) {
|
|
|
|
|
| Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) {
|
| - if (top_scope_->is_extended_mode()) return ParseScopedBlock(labels, ok);
|
| + if (scope_->is_extended_mode()) return ParseScopedBlock(labels, ok);
|
|
|
| // Block ::
|
| // '{' Statement* '}'
|
| @@ -1718,12 +1743,12 @@ Block* Parser::ParseScopedBlock(ZoneStringList* labels, bool* ok) {
|
| // Construct block expecting 16 statements.
|
| Block* body =
|
| factory()->NewBlock(labels, 16, false, RelocInfo::kNoPosition);
|
| - Scope* block_scope = NewScope(top_scope_, BLOCK_SCOPE);
|
| + Scope* block_scope = NewScope(scope_, BLOCK_SCOPE);
|
|
|
| // Parse the statements and collect escaping labels.
|
| Expect(Token::LBRACE, CHECK_OK);
|
| - block_scope->set_start_position(scanner().location().beg_pos);
|
| - { BlockState block_state(this, block_scope);
|
| + block_scope->set_start_position(scanner()->location().beg_pos);
|
| + { BlockState block_state(&scope_, block_scope);
|
| TargetCollector collector(zone());
|
| Target target(&this->target_stack_, &collector);
|
| Target target_body(&this->target_stack_, body);
|
| @@ -1736,7 +1761,7 @@ Block* Parser::ParseScopedBlock(ZoneStringList* labels, bool* ok) {
|
| }
|
| }
|
| Expect(Token::RBRACE, CHECK_OK);
|
| - block_scope->set_end_position(scanner().location().end_pos);
|
| + block_scope->set_end_position(scanner()->location().end_pos);
|
| block_scope = block_scope->FinalizeBlockScope();
|
| body->set_scope(block_scope);
|
| return body;
|
| @@ -1757,12 +1782,6 @@ Block* Parser::ParseVariableStatement(VariableDeclarationContext var_context,
|
| }
|
|
|
|
|
| -bool Parser::IsEvalOrArguments(Handle<String> string) {
|
| - return string.is_identical_to(isolate()->factory()->eval_string()) ||
|
| - string.is_identical_to(isolate()->factory()->arguments_string());
|
| -}
|
| -
|
| -
|
| // If the variable declaration declares exactly one non-const
|
| // variable, then *out is set to that variable. In all other cases,
|
| // *out is untouched; in particular, it is the caller's responsibility
|
| @@ -1811,7 +1830,7 @@ Block* Parser::ParseVariableDeclarations(
|
| // existing pages. Therefore we keep allowing const with the old
|
| // non-harmony semantics in classic mode.
|
| Consume(Token::CONST);
|
| - switch (top_scope_->language_mode()) {
|
| + switch (scope_->language_mode()) {
|
| case CLASSIC_MODE:
|
| mode = CONST;
|
| init_op = Token::INIT_CONST;
|
| @@ -1882,16 +1901,9 @@ Block* Parser::ParseVariableDeclarations(
|
|
|
| // Parse variable name.
|
| if (nvars > 0) Consume(Token::COMMA);
|
| - name = ParseIdentifier(CHECK_OK);
|
| + name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
|
| if (fni_ != NULL) fni_->PushVariableName(name);
|
|
|
| - // Strict mode variables may not be named eval or arguments
|
| - if (!declaration_scope->is_classic_mode() && IsEvalOrArguments(name)) {
|
| - ReportMessage("strict_var_name", Vector<const char*>::empty());
|
| - *ok = false;
|
| - return NULL;
|
| - }
|
| -
|
| // Declare variable.
|
| // Note that we *always* must treat the initial value via a separate init
|
| // assignment for variables and constants because the value must be assigned
|
| @@ -1911,12 +1923,11 @@ Block* Parser::ParseVariableDeclarations(
|
| is_const ? Interface::NewConst() : Interface::NewValue();
|
| VariableProxy* proxy = NewUnresolved(name, mode, interface);
|
| Declaration* declaration =
|
| - factory()->NewVariableDeclaration(proxy, mode, top_scope_, pos);
|
| + factory()->NewVariableDeclaration(proxy, mode, scope_, pos);
|
| Declare(declaration, mode != VAR, CHECK_OK);
|
| nvars++;
|
| if (declaration_scope->num_var_or_const() > kMaxNumFunctionLocals) {
|
| - ReportMessageAt(scanner().location(), "too_many_variables",
|
| - Vector<const char*>::empty());
|
| + ReportMessageAt(scanner()->location(), "too_many_variables");
|
| *ok = false;
|
| return NULL;
|
| }
|
| @@ -1931,7 +1942,7 @@ Block* Parser::ParseVariableDeclarations(
|
| //
|
| // var v; v = x;
|
| //
|
| - // In particular, we need to re-lookup 'v' (in top_scope_, not
|
| + // In particular, we need to re-lookup 'v' (in scope_, not
|
| // declaration_scope) as it may be a different 'v' than the 'v' in the
|
| // declaration (e.g., if we are inside a 'with' statement or 'catch'
|
| // block).
|
| @@ -1949,7 +1960,7 @@ Block* Parser::ParseVariableDeclarations(
|
| // one - there is no re-lookup (see the last parameter of the
|
| // Declare() call above).
|
|
|
| - Scope* initialization_scope = is_const ? declaration_scope : top_scope_;
|
| + Scope* initialization_scope = is_const ? declaration_scope : scope_;
|
| Expression* value = NULL;
|
| int pos = -1;
|
| // Harmony consts have non-optional initializers.
|
| @@ -2140,7 +2151,7 @@ Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels,
|
| // Remove the "ghost" variable that turned out to be a label
|
| // from the top scope. This way, we don't try to resolve it
|
| // during the scope processing.
|
| - top_scope_->RemoveUnresolved(var);
|
| + scope_->RemoveUnresolved(var);
|
| Expect(Token::COLON, CHECK_OK);
|
| return ParseStatement(labels, ok);
|
| }
|
| @@ -2150,12 +2161,12 @@ Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels,
|
| // no line-terminator between the two words.
|
| if (extension_ != NULL &&
|
| peek() == Token::FUNCTION &&
|
| - !scanner().HasAnyLineTerminatorBeforeNext() &&
|
| + !scanner()->HasAnyLineTerminatorBeforeNext() &&
|
| expr != NULL &&
|
| expr->AsVariableProxy() != NULL &&
|
| expr->AsVariableProxy()->name()->Equals(
|
| isolate()->heap()->native_string()) &&
|
| - !scanner().literal_contains_escapes()) {
|
| + !scanner()->literal_contains_escapes()) {
|
| return ParseNativeDeclaration(ok);
|
| }
|
|
|
| @@ -2163,11 +2174,11 @@ Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels,
|
| // Only expect semicolon in the former case.
|
| if (!FLAG_harmony_modules ||
|
| peek() != Token::IDENTIFIER ||
|
| - scanner().HasAnyLineTerminatorBeforeNext() ||
|
| + scanner()->HasAnyLineTerminatorBeforeNext() ||
|
| expr->AsVariableProxy() == NULL ||
|
| !expr->AsVariableProxy()->name()->Equals(
|
| isolate()->heap()->module_string()) ||
|
| - scanner().literal_contains_escapes()) {
|
| + scanner()->literal_contains_escapes()) {
|
| ExpectSemicolon(CHECK_OK);
|
| }
|
| return factory()->NewExpressionStatement(expr, pos);
|
| @@ -2204,9 +2215,10 @@ Statement* Parser::ParseContinueStatement(bool* ok) {
|
| Expect(Token::CONTINUE, CHECK_OK);
|
| Handle<String> label = Handle<String>::null();
|
| Token::Value tok = peek();
|
| - if (!scanner().HasAnyLineTerminatorBeforeNext() &&
|
| + if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
|
| tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
|
| - label = ParseIdentifier(CHECK_OK);
|
| + // ECMA allows "eval" or "arguments" as labels even in strict mode.
|
| + label = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
|
| }
|
| IterationStatement* target = NULL;
|
| target = LookupContinueTarget(label, CHECK_OK);
|
| @@ -2218,7 +2230,7 @@ Statement* Parser::ParseContinueStatement(bool* ok) {
|
| message = "unknown_label";
|
| args = Vector<Handle<String> >(&label, 1);
|
| }
|
| - ReportMessageAt(scanner().location(), message, args);
|
| + ParserTraits::ReportMessageAt(scanner()->location(), message, args);
|
| *ok = false;
|
| return NULL;
|
| }
|
| @@ -2235,9 +2247,10 @@ Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) {
|
| Expect(Token::BREAK, CHECK_OK);
|
| Handle<String> label;
|
| Token::Value tok = peek();
|
| - if (!scanner().HasAnyLineTerminatorBeforeNext() &&
|
| + if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
|
| tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
|
| - label = ParseIdentifier(CHECK_OK);
|
| + // ECMA allows "eval" or "arguments" as labels even in strict mode.
|
| + label = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
|
| }
|
| // Parse labeled break statements that target themselves into
|
| // empty statements, e.g. 'l1: l2: l3: break l2;'
|
| @@ -2255,7 +2268,7 @@ Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) {
|
| message = "unknown_label";
|
| args = Vector<Handle<String> >(&label, 1);
|
| }
|
| - ReportMessageAt(scanner().location(), message, args);
|
| + ParserTraits::ReportMessageAt(scanner()->location(), message, args);
|
| *ok = false;
|
| return NULL;
|
| }
|
| @@ -2277,7 +2290,7 @@ Statement* Parser::ParseReturnStatement(bool* ok) {
|
| Token::Value tok = peek();
|
| Statement* result;
|
| Expression* return_value;
|
| - if (scanner().HasAnyLineTerminatorBeforeNext() ||
|
| + if (scanner()->HasAnyLineTerminatorBeforeNext() ||
|
| tok == Token::SEMICOLON ||
|
| tok == Token::RBRACE ||
|
| tok == Token::EOS) {
|
| @@ -2288,7 +2301,7 @@ Statement* Parser::ParseReturnStatement(bool* ok) {
|
| ExpectSemicolon(CHECK_OK);
|
| if (is_generator()) {
|
| Expression* generator = factory()->NewVariableProxy(
|
| - current_function_state_->generator_object_variable());
|
| + function_state_->generator_object_variable());
|
| Expression* yield = factory()->NewYield(
|
| generator, return_value, Yield::FINAL, pos);
|
| result = factory()->NewExpressionStatement(yield, pos);
|
| @@ -2301,7 +2314,7 @@ Statement* Parser::ParseReturnStatement(bool* ok) {
|
| // function. See ECMA-262, section 12.9, page 67.
|
| //
|
| // To be consistent with KJS we report the syntax error at runtime.
|
| - Scope* declaration_scope = top_scope_->DeclarationScope();
|
| + Scope* declaration_scope = scope_->DeclarationScope();
|
| if (declaration_scope->is_global_scope() ||
|
| declaration_scope->is_eval_scope()) {
|
| Handle<String> message = isolate()->factory()->illegal_return_string();
|
| @@ -2320,7 +2333,7 @@ Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) {
|
| Expect(Token::WITH, CHECK_OK);
|
| int pos = position();
|
|
|
| - if (!top_scope_->is_classic_mode()) {
|
| + if (!scope_->is_classic_mode()) {
|
| ReportMessage("strict_mode_with", Vector<const char*>::empty());
|
| *ok = false;
|
| return NULL;
|
| @@ -2330,13 +2343,13 @@ Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) {
|
| Expression* expr = ParseExpression(true, CHECK_OK);
|
| Expect(Token::RPAREN, CHECK_OK);
|
|
|
| - top_scope_->DeclarationScope()->RecordWithStatement();
|
| - Scope* with_scope = NewScope(top_scope_, WITH_SCOPE);
|
| + scope_->DeclarationScope()->RecordWithStatement();
|
| + Scope* with_scope = NewScope(scope_, WITH_SCOPE);
|
| Statement* stmt;
|
| - { BlockState block_state(this, with_scope);
|
| - with_scope->set_start_position(scanner().peek_location().beg_pos);
|
| + { BlockState block_state(&scope_, with_scope);
|
| + with_scope->set_start_position(scanner()->peek_location().beg_pos);
|
| stmt = ParseStatement(labels, CHECK_OK);
|
| - with_scope->set_end_position(scanner().location().end_pos);
|
| + with_scope->set_end_position(scanner()->location().end_pos);
|
| }
|
| return factory()->NewWithStatement(with_scope, expr, stmt, pos);
|
| }
|
| @@ -2410,7 +2423,7 @@ Statement* Parser::ParseThrowStatement(bool* ok) {
|
|
|
| Expect(Token::THROW, CHECK_OK);
|
| int pos = position();
|
| - if (scanner().HasAnyLineTerminatorBeforeNext()) {
|
| + if (scanner()->HasAnyLineTerminatorBeforeNext()) {
|
| ReportMessage("newline_after_throw", Vector<const char*>::empty());
|
| *ok = false;
|
| return NULL;
|
| @@ -2465,35 +2478,27 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
|
| Consume(Token::CATCH);
|
|
|
| Expect(Token::LPAREN, CHECK_OK);
|
| - catch_scope = NewScope(top_scope_, CATCH_SCOPE);
|
| - catch_scope->set_start_position(scanner().location().beg_pos);
|
| - name = ParseIdentifier(CHECK_OK);
|
| -
|
| - if (!top_scope_->is_classic_mode() && IsEvalOrArguments(name)) {
|
| - ReportMessage("strict_catch_variable", Vector<const char*>::empty());
|
| - *ok = false;
|
| - return NULL;
|
| - }
|
| + catch_scope = NewScope(scope_, CATCH_SCOPE);
|
| + catch_scope->set_start_position(scanner()->location().beg_pos);
|
| + name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
|
|
|
| Expect(Token::RPAREN, CHECK_OK);
|
|
|
| - if (peek() == Token::LBRACE) {
|
| - Target target(&this->target_stack_, &catch_collector);
|
| - VariableMode mode = is_extended_mode() ? LET : VAR;
|
| - catch_variable =
|
| - catch_scope->DeclareLocal(name, mode, kCreatedInitialized);
|
| + Target target(&this->target_stack_, &catch_collector);
|
| + VariableMode mode = is_extended_mode() ? LET : VAR;
|
| + catch_variable =
|
| + catch_scope->DeclareLocal(name, mode, kCreatedInitialized);
|
|
|
| - BlockState block_state(this, catch_scope);
|
| - catch_block = ParseBlock(NULL, CHECK_OK);
|
| - } else {
|
| - Expect(Token::LBRACE, CHECK_OK);
|
| - }
|
| - catch_scope->set_end_position(scanner().location().end_pos);
|
| + BlockState block_state(&scope_, catch_scope);
|
| + catch_block = ParseBlock(NULL, CHECK_OK);
|
| +
|
| + catch_scope->set_end_position(scanner()->location().end_pos);
|
| tok = peek();
|
| }
|
|
|
| Block* finally_block = NULL;
|
| - if (tok == Token::FINALLY || catch_block == NULL) {
|
| + ASSERT(tok == Token::FINALLY || catch_block != NULL);
|
| + if (tok == Token::FINALLY) {
|
| Consume(Token::FINALLY);
|
| finally_block = ParseBlock(NULL, CHECK_OK);
|
| }
|
| @@ -2506,7 +2511,7 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
|
| if (catch_block != NULL && finally_block != NULL) {
|
| // If we have both, create an inner try/catch.
|
| ASSERT(catch_scope != NULL && catch_variable != NULL);
|
| - int index = current_function_state_->NextHandlerIndex();
|
| + int index = function_state_->NextHandlerIndex();
|
| TryCatchStatement* statement = factory()->NewTryCatchStatement(
|
| index, try_block, catch_scope, catch_variable, catch_block,
|
| RelocInfo::kNoPosition);
|
| @@ -2520,12 +2525,12 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
|
| if (catch_block != NULL) {
|
| ASSERT(finally_block == NULL);
|
| ASSERT(catch_scope != NULL && catch_variable != NULL);
|
| - int index = current_function_state_->NextHandlerIndex();
|
| + int index = function_state_->NextHandlerIndex();
|
| result = factory()->NewTryCatchStatement(
|
| index, try_block, catch_scope, catch_variable, catch_block, pos);
|
| } else {
|
| ASSERT(finally_block != NULL);
|
| - int index = current_function_state_->NextHandlerIndex();
|
| + int index = function_state_->NextHandlerIndex();
|
| result = factory()->NewTryFinallyStatement(
|
| index, try_block, finally_block, pos);
|
| // Combine the jump targets of the try block and the possible catch block.
|
| @@ -2605,9 +2610,9 @@ void Parser::InitializeForEachStatement(ForEachStatement* stmt,
|
|
|
| if (for_of != NULL) {
|
| Factory* heap_factory = isolate()->factory();
|
| - Variable* iterator = top_scope_->DeclarationScope()->NewTemporary(
|
| + Variable* iterator = scope_->DeclarationScope()->NewTemporary(
|
| heap_factory->dot_iterator_string());
|
| - Variable* result = top_scope_->DeclarationScope()->NewTemporary(
|
| + Variable* result = scope_->DeclarationScope()->NewTemporary(
|
| heap_factory->dot_result_string());
|
|
|
| Expression* assign_iterator;
|
| @@ -2674,13 +2679,13 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
|
| Statement* init = NULL;
|
|
|
| // Create an in-between scope for let-bound iteration variables.
|
| - Scope* saved_scope = top_scope_;
|
| - Scope* for_scope = NewScope(top_scope_, BLOCK_SCOPE);
|
| - top_scope_ = for_scope;
|
| + Scope* saved_scope = scope_;
|
| + Scope* for_scope = NewScope(scope_, BLOCK_SCOPE);
|
| + scope_ = for_scope;
|
|
|
| Expect(Token::FOR, CHECK_OK);
|
| Expect(Token::LPAREN, CHECK_OK);
|
| - for_scope->set_start_position(scanner().location().beg_pos);
|
| + for_scope->set_start_position(scanner()->location().beg_pos);
|
| if (peek() != Token::SEMICOLON) {
|
| if (peek() == Token::VAR || peek() == Token::CONST) {
|
| bool is_const = peek() == Token::CONST;
|
| @@ -2703,15 +2708,15 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
|
| Expect(Token::RPAREN, CHECK_OK);
|
|
|
| VariableProxy* each =
|
| - top_scope_->NewUnresolved(factory(), name, interface);
|
| + scope_->NewUnresolved(factory(), name, interface);
|
| Statement* body = ParseStatement(NULL, CHECK_OK);
|
| InitializeForEachStatement(loop, each, enumerable, body);
|
| Block* result =
|
| factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition);
|
| result->AddStatement(variable_statement, zone());
|
| result->AddStatement(loop, zone());
|
| - top_scope_ = saved_scope;
|
| - for_scope->set_end_position(scanner().location().end_pos);
|
| + scope_ = saved_scope;
|
| + for_scope->set_end_position(scanner()->location().end_pos);
|
| for_scope = for_scope->FinalizeBlockScope();
|
| ASSERT(for_scope == NULL);
|
| // Parsed for-in loop w/ variable/const declaration.
|
| @@ -2749,20 +2754,20 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
|
| Handle<String> tempstr =
|
| heap_factory->NewConsString(heap_factory->dot_for_string(), name);
|
| Handle<String> tempname = heap_factory->InternalizeString(tempstr);
|
| - Variable* temp = top_scope_->DeclarationScope()->NewTemporary(tempname);
|
| + Variable* temp = scope_->DeclarationScope()->NewTemporary(tempname);
|
| VariableProxy* temp_proxy = factory()->NewVariableProxy(temp);
|
| ForEachStatement* loop =
|
| factory()->NewForEachStatement(mode, labels, pos);
|
| Target target(&this->target_stack_, loop);
|
|
|
| // The expression does not see the loop variable.
|
| - top_scope_ = saved_scope;
|
| + scope_ = saved_scope;
|
| Expression* enumerable = ParseExpression(true, CHECK_OK);
|
| - top_scope_ = for_scope;
|
| + scope_ = for_scope;
|
| Expect(Token::RPAREN, CHECK_OK);
|
|
|
| VariableProxy* each =
|
| - top_scope_->NewUnresolved(factory(), name, Interface::NewValue());
|
| + scope_->NewUnresolved(factory(), name, Interface::NewValue());
|
| Statement* body = ParseStatement(NULL, CHECK_OK);
|
| Block* body_block =
|
| factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition);
|
| @@ -2774,8 +2779,8 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
|
| body_block->AddStatement(assignment_statement, zone());
|
| body_block->AddStatement(body, zone());
|
| InitializeForEachStatement(loop, temp_proxy, enumerable, body_block);
|
| - top_scope_ = saved_scope;
|
| - for_scope->set_end_position(scanner().location().end_pos);
|
| + scope_ = saved_scope;
|
| + for_scope->set_end_position(scanner()->location().end_pos);
|
| for_scope = for_scope->FinalizeBlockScope();
|
| body_block->set_scope(for_scope);
|
| // Parsed for-in loop w/ let declaration.
|
| @@ -2808,8 +2813,8 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
|
|
|
| Statement* body = ParseStatement(NULL, CHECK_OK);
|
| InitializeForEachStatement(loop, expression, enumerable, body);
|
| - top_scope_ = saved_scope;
|
| - for_scope->set_end_position(scanner().location().end_pos);
|
| + scope_ = saved_scope;
|
| + for_scope->set_end_position(scanner()->location().end_pos);
|
| for_scope = for_scope->FinalizeBlockScope();
|
| ASSERT(for_scope == NULL);
|
| // Parsed for-in loop.
|
| @@ -2843,8 +2848,8 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
|
| Expect(Token::RPAREN, CHECK_OK);
|
|
|
| Statement* body = ParseStatement(NULL, CHECK_OK);
|
| - top_scope_ = saved_scope;
|
| - for_scope->set_end_position(scanner().location().end_pos);
|
| + scope_ = saved_scope;
|
| + for_scope->set_end_position(scanner()->location().end_pos);
|
| for_scope = for_scope->FinalizeBlockScope();
|
| if (for_scope != NULL) {
|
| // Rewrite a for statement of the form
|
| @@ -2871,23 +2876,6 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
|
| }
|
|
|
|
|
| -// Precedence = 1
|
| -Expression* Parser::ParseExpression(bool accept_IN, bool* ok) {
|
| - // Expression ::
|
| - // AssignmentExpression
|
| - // Expression ',' AssignmentExpression
|
| -
|
| - Expression* result = ParseAssignmentExpression(accept_IN, CHECK_OK);
|
| - while (peek() == Token::COMMA) {
|
| - Expect(Token::COMMA, CHECK_OK);
|
| - int pos = position();
|
| - Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
|
| - result = factory()->NewBinaryOperation(Token::COMMA, result, right, pos);
|
| - }
|
| - return result;
|
| -}
|
| -
|
| -
|
| // Precedence = 2
|
| Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) {
|
| // AssignmentExpression ::
|
| @@ -2919,9 +2907,9 @@ Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) {
|
| expression = NewThrowReferenceError(message);
|
| }
|
|
|
| - if (!top_scope_->is_classic_mode()) {
|
| + if (!scope_->is_classic_mode()) {
|
| // Assignment to eval or arguments is disallowed in strict mode.
|
| - CheckStrictModeLValue(expression, "strict_lhs_assignment", CHECK_OK);
|
| + CheckStrictModeLValue(expression, CHECK_OK);
|
| }
|
| MarkAsLValue(expression);
|
|
|
| @@ -2939,7 +2927,7 @@ Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) {
|
| property != NULL &&
|
| property->obj()->AsVariableProxy() != NULL &&
|
| property->obj()->AsVariableProxy()->is_this()) {
|
| - current_function_state_->AddProperty();
|
| + function_state_->AddProperty();
|
| }
|
|
|
| // If we assign a function literal to a property we pretenure the
|
| @@ -2975,11 +2963,11 @@ Expression* Parser::ParseYieldExpression(bool* ok) {
|
| Yield::Kind kind =
|
| Check(Token::MUL) ? Yield::DELEGATING : Yield::SUSPEND;
|
| Expression* generator_object = factory()->NewVariableProxy(
|
| - current_function_state_->generator_object_variable());
|
| + function_state_->generator_object_variable());
|
| Expression* expression = ParseAssignmentExpression(false, CHECK_OK);
|
| Yield* yield = factory()->NewYield(generator_object, expression, kind, pos);
|
| if (kind == Yield::DELEGATING) {
|
| - yield->set_index(current_function_state_->NextHandlerIndex());
|
| + yield->set_index(function_state_->NextHandlerIndex());
|
| }
|
| return yield;
|
| }
|
| @@ -3006,14 +2994,6 @@ Expression* Parser::ParseConditionalExpression(bool accept_IN, bool* ok) {
|
| }
|
|
|
|
|
| -int ParserBase::Precedence(Token::Value tok, bool accept_IN) {
|
| - if (tok == Token::IN && !accept_IN)
|
| - return 0; // 0 precedence will terminate binary expression parsing
|
| -
|
| - return Token::Precedence(tok);
|
| -}
|
| -
|
| -
|
| // Precedence >= 4
|
| Expression* Parser::ParseBinaryExpression(int prec, bool accept_IN, bool* ok) {
|
| ASSERT(prec >= 4);
|
| @@ -3151,7 +3131,7 @@ Expression* Parser::ParseUnaryExpression(bool* ok) {
|
| }
|
|
|
| // "delete identifier" is a syntax error in strict mode.
|
| - if (op == Token::DELETE && !top_scope_->is_classic_mode()) {
|
| + if (op == Token::DELETE && !scope_->is_classic_mode()) {
|
| VariableProxy* operand = expression->AsVariableProxy();
|
| if (operand != NULL && !operand->is_this()) {
|
| ReportMessage("strict_delete", Vector<const char*>::empty());
|
| @@ -3199,9 +3179,9 @@ Expression* Parser::ParseUnaryExpression(bool* ok) {
|
| expression = NewThrowReferenceError(message);
|
| }
|
|
|
| - if (!top_scope_->is_classic_mode()) {
|
| + if (!scope_->is_classic_mode()) {
|
| // Prefix expression operand in strict mode may not be eval or arguments.
|
| - CheckStrictModeLValue(expression, "strict_lhs_prefix", CHECK_OK);
|
| + CheckStrictModeLValue(expression, CHECK_OK);
|
| }
|
| MarkAsLValue(expression);
|
|
|
| @@ -3221,7 +3201,7 @@ Expression* Parser::ParsePostfixExpression(bool* ok) {
|
| // LeftHandSideExpression ('++' | '--')?
|
|
|
| Expression* expression = ParseLeftHandSideExpression(CHECK_OK);
|
| - if (!scanner().HasAnyLineTerminatorBeforeNext() &&
|
| + if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
|
| Token::IsCountOp(peek())) {
|
| // Signal a reference error if the expression is an invalid
|
| // left-hand side expression. We could report this as a syntax
|
| @@ -3233,9 +3213,9 @@ Expression* Parser::ParsePostfixExpression(bool* ok) {
|
| expression = NewThrowReferenceError(message);
|
| }
|
|
|
| - if (!top_scope_->is_classic_mode()) {
|
| + if (!scope_->is_classic_mode()) {
|
| // Postfix expression operand in strict mode may not be eval or arguments.
|
| - CheckStrictModeLValue(expression, "strict_lhs_prefix", CHECK_OK);
|
| + CheckStrictModeLValue(expression, CHECK_OK);
|
| }
|
| MarkAsLValue(expression);
|
|
|
| @@ -3254,12 +3234,7 @@ Expression* Parser::ParseLeftHandSideExpression(bool* ok) {
|
| // LeftHandSideExpression ::
|
| // (NewExpression | MemberExpression) ...
|
|
|
| - Expression* result;
|
| - if (peek() == Token::NEW) {
|
| - result = ParseNewExpression(CHECK_OK);
|
| - } else {
|
| - result = ParseMemberExpression(CHECK_OK);
|
| - }
|
| + Expression* result = ParseMemberWithNewPrefixesExpression(CHECK_OK);
|
|
|
| while (true) {
|
| switch (peek()) {
|
| @@ -3274,7 +3249,7 @@ Expression* Parser::ParseLeftHandSideExpression(bool* ok) {
|
|
|
| case Token::LPAREN: {
|
| int pos;
|
| - if (scanner().current_token() == Token::IDENTIFIER) {
|
| + if (scanner()->current_token() == Token::IDENTIFIER) {
|
| // For call of an identifier we want to report position of
|
| // the identifier as position of the call in the stack trace.
|
| pos = position();
|
| @@ -3304,7 +3279,7 @@ Expression* Parser::ParseLeftHandSideExpression(bool* ok) {
|
| VariableProxy* callee = result->AsVariableProxy();
|
| if (callee != NULL &&
|
| callee->IsVariable(isolate()->factory()->eval_string())) {
|
| - top_scope_->DeclarationScope()->RecordEvalCall();
|
| + scope_->DeclarationScope()->RecordEvalCall();
|
| }
|
| result = factory()->NewCall(result, args, pos);
|
| if (fni_ != NULL) fni_->RemoveLastFunction();
|
| @@ -3328,70 +3303,73 @@ Expression* Parser::ParseLeftHandSideExpression(bool* ok) {
|
| }
|
|
|
|
|
| -Expression* Parser::ParseNewPrefix(PositionStack* stack, bool* ok) {
|
| +Expression* Parser::ParseMemberWithNewPrefixesExpression(bool* ok) {
|
| // NewExpression ::
|
| // ('new')+ MemberExpression
|
|
|
| - // The grammar for new expressions is pretty warped. The keyword
|
| - // 'new' can either be a part of the new expression (where it isn't
|
| - // followed by an argument list) or a part of the member expression,
|
| - // where it must be followed by an argument list. To accommodate
|
| - // this, we parse the 'new' keywords greedily and keep track of how
|
| - // many we have parsed. This information is then passed on to the
|
| - // member expression parser, which is only allowed to match argument
|
| - // lists as long as it has 'new' prefixes left
|
| - Expect(Token::NEW, CHECK_OK);
|
| - PositionStack::Element pos(stack, position());
|
| -
|
| - Expression* result;
|
| - if (peek() == Token::NEW) {
|
| - result = ParseNewPrefix(stack, CHECK_OK);
|
| - } else {
|
| - result = ParseMemberWithNewPrefixesExpression(stack, CHECK_OK);
|
| - }
|
| -
|
| - if (!stack->is_empty()) {
|
| - int last = stack->pop();
|
| - result = factory()->NewCallNew(
|
| - result, new(zone()) ZoneList<Expression*>(0, zone()), last);
|
| - }
|
| - return result;
|
| -}
|
| + // The grammar for new expressions is pretty warped. We can have several 'new'
|
| + // keywords following each other, and then a MemberExpression. When we see '('
|
| + // after the MemberExpression, it's associated with the rightmost unassociated
|
| + // 'new' to create a NewExpression with arguments. However, a NewExpression
|
| + // can also occur without arguments.
|
|
|
| + // Examples of new expression:
|
| + // new foo.bar().baz means (new (foo.bar)()).baz
|
| + // new foo()() means (new foo())()
|
| + // new new foo()() means (new (new foo())())
|
| + // new new foo means new (new foo)
|
| + // new new foo() means new (new foo())
|
| + // new new foo().bar().baz means (new (new foo()).bar()).baz
|
|
|
| -Expression* Parser::ParseNewExpression(bool* ok) {
|
| - PositionStack stack(ok);
|
| - return ParseNewPrefix(&stack, ok);
|
| + if (peek() == Token::NEW) {
|
| + Consume(Token::NEW);
|
| + int new_pos = position();
|
| + Expression* result = ParseMemberWithNewPrefixesExpression(CHECK_OK);
|
| + if (peek() == Token::LPAREN) {
|
| + // NewExpression with arguments.
|
| + ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
|
| + result = factory()->NewCallNew(result, args, new_pos);
|
| + // The expression can still continue with . or [ after the arguments.
|
| + result = ParseMemberExpressionContinuation(result, CHECK_OK);
|
| + return result;
|
| + }
|
| + // NewExpression without arguments.
|
| + return factory()->NewCallNew(
|
| + result, new(zone()) ZoneList<Expression*>(0, zone()), new_pos);
|
| + }
|
| + // No 'new' keyword.
|
| + return ParseMemberExpression(ok);
|
| }
|
|
|
|
|
| Expression* Parser::ParseMemberExpression(bool* ok) {
|
| - return ParseMemberWithNewPrefixesExpression(NULL, ok);
|
| -}
|
| -
|
| -
|
| -Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack,
|
| - bool* ok) {
|
| // MemberExpression ::
|
| // (PrimaryExpression | FunctionLiteral)
|
| // ('[' Expression ']' | '.' Identifier | Arguments)*
|
|
|
| + // The '[' Expression ']' and '.' Identifier parts are parsed by
|
| + // ParseMemberExpressionContinuation, and the Arguments part is parsed by the
|
| + // caller.
|
| +
|
| // Parse the initial primary or function expression.
|
| Expression* result = NULL;
|
| if (peek() == Token::FUNCTION) {
|
| - Expect(Token::FUNCTION, CHECK_OK);
|
| + Consume(Token::FUNCTION);
|
| int function_token_position = position();
|
| bool is_generator = allow_generators() && Check(Token::MUL);
|
| Handle<String> name;
|
| bool is_strict_reserved_name = false;
|
| + Scanner::Location function_name_location = Scanner::Location::invalid();
|
| if (peek_any_identifier()) {
|
| name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name,
|
| CHECK_OK);
|
| + function_name_location = scanner()->location();
|
| }
|
| FunctionLiteral::FunctionType function_type = name.is_null()
|
| ? FunctionLiteral::ANONYMOUS_EXPRESSION
|
| : FunctionLiteral::NAMED_EXPRESSION;
|
| result = ParseFunctionLiteral(name,
|
| + function_name_location,
|
| is_strict_reserved_name,
|
| is_generator,
|
| function_token_position,
|
| @@ -3401,13 +3379,22 @@ Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack,
|
| result = ParsePrimaryExpression(CHECK_OK);
|
| }
|
|
|
| + result = ParseMemberExpressionContinuation(result, CHECK_OK);
|
| + return result;
|
| +}
|
| +
|
| +
|
| +Expression* Parser::ParseMemberExpressionContinuation(Expression* expression,
|
| + bool* ok) {
|
| + // Parses this part of MemberExpression:
|
| + // ('[' Expression ']' | '.' Identifier)*
|
| while (true) {
|
| switch (peek()) {
|
| case Token::LBRACK: {
|
| Consume(Token::LBRACK);
|
| int pos = position();
|
| Expression* index = ParseExpression(true, CHECK_OK);
|
| - result = factory()->NewProperty(result, index, pos);
|
| + expression = factory()->NewProperty(expression, index, pos);
|
| if (fni_ != NULL) {
|
| if (index->IsPropertyName()) {
|
| fni_->PushLiteralName(index->AsLiteral()->AsPropertyName());
|
| @@ -3423,23 +3410,17 @@ Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack,
|
| Consume(Token::PERIOD);
|
| int pos = position();
|
| Handle<String> name = ParseIdentifierName(CHECK_OK);
|
| - result = factory()->NewProperty(
|
| - result, factory()->NewLiteral(name, pos), pos);
|
| + expression = factory()->NewProperty(
|
| + expression, factory()->NewLiteral(name, pos), pos);
|
| if (fni_ != NULL) fni_->PushLiteralName(name);
|
| break;
|
| }
|
| - case Token::LPAREN: {
|
| - if ((stack == NULL) || stack->is_empty()) return result;
|
| - // Consume one of the new prefixes (already parsed).
|
| - ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
|
| - int pos = stack->pop();
|
| - result = factory()->NewCallNew(result, args, pos);
|
| - break;
|
| - }
|
| default:
|
| - return result;
|
| + return expression;
|
| }
|
| }
|
| + ASSERT(false);
|
| + return NULL;
|
| }
|
|
|
|
|
| @@ -3457,41 +3438,6 @@ DebuggerStatement* Parser::ParseDebuggerStatement(bool* ok) {
|
| }
|
|
|
|
|
| -void Parser::ReportUnexpectedToken(Token::Value token) {
|
| - // We don't report stack overflows here, to avoid increasing the
|
| - // stack depth even further. Instead we report it after parsing is
|
| - // over, in ParseProgram/ParseJson.
|
| - if (token == Token::ILLEGAL && stack_overflow()) return;
|
| - // Four of the tokens are treated specially
|
| - switch (token) {
|
| - case Token::EOS:
|
| - return ReportMessage("unexpected_eos", Vector<const char*>::empty());
|
| - case Token::NUMBER:
|
| - return ReportMessage("unexpected_token_number",
|
| - Vector<const char*>::empty());
|
| - case Token::STRING:
|
| - return ReportMessage("unexpected_token_string",
|
| - Vector<const char*>::empty());
|
| - case Token::IDENTIFIER:
|
| - return ReportMessage("unexpected_token_identifier",
|
| - Vector<const char*>::empty());
|
| - case Token::FUTURE_RESERVED_WORD:
|
| - return ReportMessage("unexpected_reserved",
|
| - Vector<const char*>::empty());
|
| - case Token::YIELD:
|
| - case Token::FUTURE_STRICT_RESERVED_WORD:
|
| - return ReportMessage(top_scope_->is_classic_mode() ?
|
| - "unexpected_token_identifier" :
|
| - "unexpected_strict_reserved",
|
| - Vector<const char*>::empty());
|
| - default:
|
| - const char* name = Token::String(token);
|
| - ASSERT(name != NULL);
|
| - ReportMessage("unexpected_token", Vector<const char*>(&name, 1));
|
| - }
|
| -}
|
| -
|
| -
|
| void Parser::ReportInvalidPreparseData(Handle<String> name, bool* ok) {
|
| SmartArrayPointer<char> name_string = name->ToCString(DISALLOW_NULLS);
|
| const char* element[1] = { name_string.get() };
|
| @@ -3501,151 +3447,6 @@ void Parser::ReportInvalidPreparseData(Handle<String> name, bool* ok) {
|
| }
|
|
|
|
|
| -Expression* Parser::ParsePrimaryExpression(bool* ok) {
|
| - // PrimaryExpression ::
|
| - // 'this'
|
| - // 'null'
|
| - // 'true'
|
| - // 'false'
|
| - // Identifier
|
| - // Number
|
| - // String
|
| - // ArrayLiteral
|
| - // ObjectLiteral
|
| - // RegExpLiteral
|
| - // '(' Expression ')'
|
| -
|
| - int pos = peek_position();
|
| - Expression* result = NULL;
|
| - switch (peek()) {
|
| - case Token::THIS: {
|
| - Consume(Token::THIS);
|
| - result = factory()->NewVariableProxy(top_scope_->receiver());
|
| - break;
|
| - }
|
| -
|
| - case Token::NULL_LITERAL:
|
| - Consume(Token::NULL_LITERAL);
|
| - result = factory()->NewLiteral(isolate()->factory()->null_value(), pos);
|
| - break;
|
| -
|
| - case Token::TRUE_LITERAL:
|
| - Consume(Token::TRUE_LITERAL);
|
| - result = factory()->NewLiteral(isolate()->factory()->true_value(), pos);
|
| - break;
|
| -
|
| - case Token::FALSE_LITERAL:
|
| - Consume(Token::FALSE_LITERAL);
|
| - result = factory()->NewLiteral(isolate()->factory()->false_value(), pos);
|
| - break;
|
| -
|
| - case Token::IDENTIFIER:
|
| - case Token::YIELD:
|
| - case Token::FUTURE_STRICT_RESERVED_WORD: {
|
| - Handle<String> name = ParseIdentifier(CHECK_OK);
|
| - if (fni_ != NULL) fni_->PushVariableName(name);
|
| - // The name may refer to a module instance object, so its type is unknown.
|
| -#ifdef DEBUG
|
| - if (FLAG_print_interface_details)
|
| - PrintF("# Variable %s ", name->ToAsciiArray());
|
| -#endif
|
| - Interface* interface = Interface::NewUnknown(zone());
|
| - result = top_scope_->NewUnresolved(factory(), name, interface, pos);
|
| - break;
|
| - }
|
| -
|
| - case Token::NUMBER: {
|
| - Consume(Token::NUMBER);
|
| - ASSERT(scanner().is_literal_ascii());
|
| - double value = StringToDouble(isolate()->unicode_cache(),
|
| - scanner().literal_ascii_string(),
|
| - ALLOW_HEX | ALLOW_OCTAL |
|
| - ALLOW_IMPLICIT_OCTAL | ALLOW_BINARY);
|
| - result = factory()->NewNumberLiteral(value, pos);
|
| - break;
|
| - }
|
| -
|
| - case Token::STRING: {
|
| - Consume(Token::STRING);
|
| - Handle<String> symbol = GetSymbol();
|
| - result = factory()->NewLiteral(symbol, pos);
|
| - if (fni_ != NULL) fni_->PushLiteralName(symbol);
|
| - break;
|
| - }
|
| -
|
| - case Token::ASSIGN_DIV:
|
| - result = ParseRegExpLiteral(true, CHECK_OK);
|
| - break;
|
| -
|
| - case Token::DIV:
|
| - result = ParseRegExpLiteral(false, CHECK_OK);
|
| - break;
|
| -
|
| - case Token::LBRACK:
|
| - result = ParseArrayLiteral(CHECK_OK);
|
| - break;
|
| -
|
| - case Token::LBRACE:
|
| - result = ParseObjectLiteral(CHECK_OK);
|
| - break;
|
| -
|
| - case Token::LPAREN:
|
| - Consume(Token::LPAREN);
|
| - // Heuristically try to detect immediately called functions before
|
| - // seeing the call parentheses.
|
| - parenthesized_function_ = (peek() == Token::FUNCTION);
|
| - result = ParseExpression(true, CHECK_OK);
|
| - Expect(Token::RPAREN, CHECK_OK);
|
| - break;
|
| -
|
| - case Token::MOD:
|
| - if (allow_natives_syntax() || extension_ != NULL) {
|
| - result = ParseV8Intrinsic(CHECK_OK);
|
| - break;
|
| - }
|
| - // If we're not allowing special syntax we fall-through to the
|
| - // default case.
|
| -
|
| - default: {
|
| - Token::Value tok = Next();
|
| - ReportUnexpectedToken(tok);
|
| - *ok = false;
|
| - return NULL;
|
| - }
|
| - }
|
| -
|
| - return result;
|
| -}
|
| -
|
| -
|
| -Expression* Parser::ParseArrayLiteral(bool* ok) {
|
| - // ArrayLiteral ::
|
| - // '[' Expression? (',' Expression?)* ']'
|
| -
|
| - int pos = peek_position();
|
| - ZoneList<Expression*>* values = new(zone()) ZoneList<Expression*>(4, zone());
|
| - Expect(Token::LBRACK, CHECK_OK);
|
| - while (peek() != Token::RBRACK) {
|
| - Expression* elem;
|
| - if (peek() == Token::COMMA) {
|
| - elem = GetLiteralTheHole(peek_position());
|
| - } else {
|
| - elem = ParseAssignmentExpression(true, CHECK_OK);
|
| - }
|
| - values->Add(elem, zone());
|
| - if (peek() != Token::RBRACK) {
|
| - Expect(Token::COMMA, CHECK_OK);
|
| - }
|
| - }
|
| - Expect(Token::RBRACK, CHECK_OK);
|
| -
|
| - // Update the scope information before the pre-parsing bailout.
|
| - int literal_index = current_function_state_->NextMaterializedLiteralIndex();
|
| -
|
| - return factory()->NewArrayLiteral(values, literal_index, pos);
|
| -}
|
| -
|
| -
|
| bool CompileTimeValue::IsCompileTimeValue(Expression* expression) {
|
| if (expression->AsLiteral() != NULL) return true;
|
| MaterializedLiteral* lit = expression->AsMaterializedLiteral();
|
| @@ -3702,7 +3503,7 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
|
| int number_of_boilerplate_properties = 0;
|
| bool has_function = false;
|
|
|
| - ObjectLiteralChecker checker(this, top_scope_->language_mode());
|
| + ObjectLiteralChecker checker(this, scope_->language_mode());
|
|
|
| Expect(Token::LBRACE, CHECK_OK);
|
|
|
| @@ -3748,6 +3549,7 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
|
| : GetSymbol();
|
| FunctionLiteral* value =
|
| ParseFunctionLiteral(name,
|
| + scanner()->location(),
|
| false, // reserved words are allowed here
|
| false, // not a generator
|
| RelocInfo::kNoPosition,
|
| @@ -3788,9 +3590,9 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
|
| }
|
| case Token::NUMBER: {
|
| Consume(Token::NUMBER);
|
| - ASSERT(scanner().is_literal_ascii());
|
| + ASSERT(scanner()->is_literal_ascii());
|
| double value = StringToDouble(isolate()->unicode_cache(),
|
| - scanner().literal_ascii_string(),
|
| + scanner()->literal_ascii_string(),
|
| ALLOW_HEX | ALLOW_OCTAL |
|
| ALLOW_IMPLICIT_OCTAL | ALLOW_BINARY);
|
| key = factory()->NewNumberLiteral(value, next_pos);
|
| @@ -3817,12 +3619,12 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
|
| Expression* value = ParseAssignmentExpression(true, CHECK_OK);
|
|
|
| ObjectLiteral::Property* property =
|
| - new(zone()) ObjectLiteral::Property(key, value, isolate());
|
| + factory()->NewObjectLiteralProperty(key, value);
|
|
|
| // Mark top-level object literals that contain function literals and
|
| // pretenure the literal so it can be added as a constant function
|
| // property.
|
| - if (top_scope_->DeclarationScope()->is_global_scope() &&
|
| + if (scope_->DeclarationScope()->is_global_scope() &&
|
| value->AsFunctionLiteral() != NULL) {
|
| has_function = true;
|
| value->AsFunctionLiteral()->set_pretenure();
|
| @@ -3845,7 +3647,7 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
|
| Expect(Token::RBRACE, CHECK_OK);
|
|
|
| // Computation of literal_index must happen before pre parse bailout.
|
| - int literal_index = current_function_state_->NextMaterializedLiteralIndex();
|
| + int literal_index = function_state_->NextMaterializedLiteralIndex();
|
|
|
| return factory()->NewObjectLiteral(properties,
|
| literal_index,
|
| @@ -3855,26 +3657,6 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
|
| }
|
|
|
|
|
| -Expression* Parser::ParseRegExpLiteral(bool seen_equal, bool* ok) {
|
| - int pos = peek_position();
|
| - if (!scanner().ScanRegExpPattern(seen_equal)) {
|
| - Next();
|
| - ReportMessage("unterminated_regexp", Vector<const char*>::empty());
|
| - *ok = false;
|
| - return NULL;
|
| - }
|
| -
|
| - int literal_index = current_function_state_->NextMaterializedLiteralIndex();
|
| -
|
| - Handle<String> js_pattern = NextLiteralString(TENURED);
|
| - scanner().ScanRegExpFlags();
|
| - Handle<String> js_flags = NextLiteralString(TENURED);
|
| - Next();
|
| -
|
| - return factory()->NewRegExpLiteral(js_pattern, js_flags, literal_index, pos);
|
| -}
|
| -
|
| -
|
| ZoneList<Expression*>* Parser::ParseArguments(bool* ok) {
|
| // Arguments ::
|
| // '(' (AssignmentExpression)*[','] ')'
|
| @@ -3886,8 +3668,7 @@ ZoneList<Expression*>* Parser::ParseArguments(bool* ok) {
|
| Expression* argument = ParseAssignmentExpression(true, CHECK_OK);
|
| result->Add(argument, zone());
|
| if (result->length() > Code::kMaxArguments) {
|
| - ReportMessageAt(scanner().location(), "too_many_arguments",
|
| - Vector<const char*>::empty());
|
| + ReportMessageAt(scanner()->location(), "too_many_arguments");
|
| *ok = false;
|
| return NULL;
|
| }
|
| @@ -3994,6 +3775,7 @@ class SingletonLogger : public ParserRecorder {
|
|
|
| FunctionLiteral* Parser::ParseFunctionLiteral(
|
| Handle<String> function_name,
|
| + Scanner::Location function_name_location,
|
| bool name_is_strict_reserved,
|
| bool is_generator,
|
| int function_token_pos,
|
| @@ -4043,14 +3825,14 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
| // one relative to the deserialized scope chain. Otherwise we must be
|
| // compiling a function in an inner declaration scope in the eval, e.g. a
|
| // nested function, and hoisting works normally relative to that.
|
| - Scope* declaration_scope = top_scope_->DeclarationScope();
|
| + Scope* declaration_scope = scope_->DeclarationScope();
|
| Scope* original_declaration_scope = original_scope_->DeclarationScope();
|
| Scope* scope =
|
| function_type == FunctionLiteral::DECLARATION && !is_extended_mode() &&
|
| (original_scope_ == original_declaration_scope ||
|
| declaration_scope != original_declaration_scope)
|
| ? NewScope(declaration_scope, FUNCTION_SCOPE)
|
| - : NewScope(top_scope_, FUNCTION_SCOPE);
|
| + : NewScope(scope_, FUNCTION_SCOPE);
|
| ZoneList<Statement*>* body = NULL;
|
| int materialized_literal_count = -1;
|
| int expected_property_count = -1;
|
| @@ -4063,23 +3845,23 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
| FunctionLiteral::IsGeneratorFlag generator = is_generator
|
| ? FunctionLiteral::kIsGenerator
|
| : FunctionLiteral::kNotGenerator;
|
| + DeferredFeedbackSlotProcessor* slot_processor;
|
| AstProperties ast_properties;
|
| BailoutReason dont_optimize_reason = kNoReason;
|
| // Parse function body.
|
| - { FunctionState function_state(this, scope, isolate());
|
| - top_scope_->SetScopeName(function_name);
|
| + { FunctionState function_state(&function_state_, &scope_, scope, zone());
|
| + scope_->SetScopeName(function_name);
|
|
|
| if (is_generator) {
|
| // For generators, allocating variables in contexts is currently a win
|
| // because it minimizes the work needed to suspend and resume an
|
| // activation.
|
| - top_scope_->ForceContextAllocation();
|
| + scope_->ForceContextAllocation();
|
|
|
| // Calling a generator returns a generator object. That object is stored
|
| // in a temporary variable, a definition that is used by "yield"
|
| - // expressions. Presence of a variable for the generator object in the
|
| - // FunctionState indicates that this function is a generator.
|
| - Variable* temp = top_scope_->DeclarationScope()->NewTemporary(
|
| + // expressions. This also marks the FunctionState as a generator.
|
| + Variable* temp = scope_->DeclarationScope()->NewTemporary(
|
| isolate()->factory()->dot_generator_object_string());
|
| function_state.set_generator_object_variable(temp);
|
| }
|
| @@ -4087,10 +3869,14 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
| // FormalParameterList ::
|
| // '(' (Identifier)*[','] ')'
|
| Expect(Token::LPAREN, CHECK_OK);
|
| - scope->set_start_position(scanner().location().beg_pos);
|
| - ScannerBase::Location name_loc = ScannerBase::Location::invalid();
|
| - ScannerBase::Location dupe_loc = ScannerBase::Location::invalid();
|
| - ScannerBase::Location reserved_loc = ScannerBase::Location::invalid();
|
| + scope->set_start_position(scanner()->location().beg_pos);
|
| +
|
| + // We don't yet know if the function will be strict, so we cannot yet
|
| + // produce errors for parameter names or duplicates. However, we remember
|
| + // the locations of these errors if they occur and produce the errors later.
|
| + Scanner::Location eval_args_error_log = Scanner::Location::invalid();
|
| + Scanner::Location dupe_error_loc = Scanner::Location::invalid();
|
| + Scanner::Location reserved_loc = Scanner::Location::invalid();
|
|
|
| bool done = (peek() == Token::RPAREN);
|
| while (!done) {
|
| @@ -4099,22 +3885,21 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
| ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK);
|
|
|
| // Store locations for possible future error reports.
|
| - if (!name_loc.IsValid() && IsEvalOrArguments(param_name)) {
|
| - name_loc = scanner().location();
|
| - }
|
| - if (!dupe_loc.IsValid() && top_scope_->IsDeclared(param_name)) {
|
| - duplicate_parameters = FunctionLiteral::kHasDuplicateParameters;
|
| - dupe_loc = scanner().location();
|
| + if (!eval_args_error_log.IsValid() && IsEvalOrArguments(param_name)) {
|
| + eval_args_error_log = scanner()->location();
|
| }
|
| if (!reserved_loc.IsValid() && is_strict_reserved) {
|
| - reserved_loc = scanner().location();
|
| + reserved_loc = scanner()->location();
|
| + }
|
| + if (!dupe_error_loc.IsValid() && scope_->IsDeclared(param_name)) {
|
| + duplicate_parameters = FunctionLiteral::kHasDuplicateParameters;
|
| + dupe_error_loc = scanner()->location();
|
| }
|
|
|
| - top_scope_->DeclareParameter(param_name, VAR);
|
| + scope_->DeclareParameter(param_name, VAR);
|
| num_parameters++;
|
| if (num_parameters > Code::kMaxArguments) {
|
| - ReportMessageAt(scanner().location(), "too_many_parameters",
|
| - Vector<const char*>::empty());
|
| + ReportMessageAt(scanner()->location(), "too_many_parameters");
|
| *ok = false;
|
| return NULL;
|
| }
|
| @@ -4136,17 +3921,20 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
| if (function_type == FunctionLiteral::NAMED_EXPRESSION) {
|
| if (is_extended_mode()) fvar_init_op = Token::INIT_CONST_HARMONY;
|
| VariableMode fvar_mode = is_extended_mode() ? CONST_HARMONY : CONST;
|
| - fvar = new(zone()) Variable(top_scope_,
|
| + fvar = new(zone()) Variable(scope_,
|
| function_name, fvar_mode, true /* is valid LHS */,
|
| Variable::NORMAL, kCreatedInitialized, Interface::NewConst());
|
| VariableProxy* proxy = factory()->NewVariableProxy(fvar);
|
| VariableDeclaration* fvar_declaration = factory()->NewVariableDeclaration(
|
| - proxy, fvar_mode, top_scope_, RelocInfo::kNoPosition);
|
| - top_scope_->DeclareFunctionVar(fvar_declaration);
|
| + proxy, fvar_mode, scope_, RelocInfo::kNoPosition);
|
| + scope_->DeclareFunctionVar(fvar_declaration);
|
| }
|
|
|
| - // Determine whether the function will be lazily compiled.
|
| - // The heuristics are:
|
| + // Determine if the function can be parsed lazily. Lazy parsing is different
|
| + // from lazy compilation; we need to parse more eagerly than we compile.
|
| +
|
| + // We can only parse lazily if we also compile lazily. The heuristics for
|
| + // lazy compilation are:
|
| // - It must not have been prohibited by the caller to Parse (some callers
|
| // need a full AST).
|
| // - The outer scope must allow lazy compilation of inner functions.
|
| @@ -4156,12 +3944,31 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
| // compiled.
|
| // These are all things we can know at this point, without looking at the
|
| // function itself.
|
| - bool is_lazily_compiled = (mode() == PARSE_LAZILY &&
|
| - top_scope_->AllowsLazyCompilation() &&
|
| - !parenthesized_function_);
|
| +
|
| + // In addition, we need to distinguish between these cases:
|
| + // (function foo() {
|
| + // bar = function() { return 1; }
|
| + // })();
|
| + // and
|
| + // (function foo() {
|
| + // var a = 1;
|
| + // bar = function() { return a; }
|
| + // })();
|
| +
|
| + // Now foo will be parsed eagerly and compiled eagerly (optimization: assume
|
| + // parenthesis before the function means that it will be called
|
| + // immediately). The inner function *must* be parsed eagerly to resolve the
|
| + // possible reference to the variable in foo's scope. However, it's possible
|
| + // that it will be compiled lazily.
|
| +
|
| + // To make this additional case work, both Parser and PreParser implement a
|
| + // logic where only top-level functions will be parsed lazily.
|
| + bool is_lazily_parsed = (mode() == PARSE_LAZILY &&
|
| + scope_->AllowsLazyCompilation() &&
|
| + !parenthesized_function_);
|
| parenthesized_function_ = false; // The bit was set for this function only.
|
|
|
| - if (is_lazily_compiled) {
|
| + if (is_lazily_parsed) {
|
| int function_block_pos = position();
|
| FunctionEntry entry;
|
| if (pre_parse_data_ != NULL) {
|
| @@ -4175,7 +3982,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
| // to check.
|
| ReportInvalidPreparseData(function_name, CHECK_OK);
|
| }
|
| - scanner().SeekForward(entry.end_pos() - 1);
|
| + scanner()->SeekForward(entry.end_pos() - 1);
|
|
|
| scope->set_end_position(entry.end_pos());
|
| Expect(Token::RBRACE, CHECK_OK);
|
| @@ -4183,9 +3990,22 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
| scope->end_position() - function_block_pos);
|
| materialized_literal_count = entry.literal_count();
|
| expected_property_count = entry.property_count();
|
| - top_scope_->SetLanguageMode(entry.language_mode());
|
| + scope_->SetLanguageMode(entry.language_mode());
|
| } else {
|
| - is_lazily_compiled = false;
|
| + // This case happens when we have preparse data but it doesn't contain
|
| + // an entry for the function. As a safety net, fall back to eager
|
| + // parsing. It is unclear whether PreParser's laziness analysis can
|
| + // produce different results than the Parser's laziness analysis (see
|
| + // https://codereview.chromium.org/7565003 ). This safety net is
|
| + // guarding against the case where Parser thinks a function should be
|
| + // lazily parsed, but PreParser thinks it should be eagerly parsed --
|
| + // in that case we fall back to eager parsing in Parser, too. Note
|
| + // that the opposite case is worse: if PreParser thinks a function
|
| + // should be lazily parsed, but Parser thinks it should be eagerly
|
| + // parsed, it will never advance the preparse data beyond that
|
| + // function and all further laziness will fail (all functions will be
|
| + // parsed eagerly).
|
| + is_lazily_parsed = false;
|
| }
|
| } else {
|
| // With no preparser data, we partially parse the function, without
|
| @@ -4205,8 +4025,10 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
| if (arg != NULL) {
|
| args = Vector<const char*>(&arg, 1);
|
| }
|
| - ReportMessageAt(ScannerBase::Location(logger.start(), logger.end()),
|
| - logger.message(), args);
|
| + ParserTraits::ReportMessageAt(
|
| + Scanner::Location(logger.start(), logger.end()),
|
| + logger.message(),
|
| + args);
|
| *ok = false;
|
| return NULL;
|
| }
|
| @@ -4216,15 +4038,17 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
| scope->end_position() - function_block_pos);
|
| materialized_literal_count = logger.literals();
|
| expected_property_count = logger.properties();
|
| - top_scope_->SetLanguageMode(logger.language_mode());
|
| + scope_->SetLanguageMode(logger.language_mode());
|
| }
|
| }
|
|
|
| - if (!is_lazily_compiled) {
|
| + if (!is_lazily_parsed) {
|
| + // Everything inside an eagerly parsed function will be parsed eagerly
|
| + // (see comment above).
|
| ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
|
| body = new(zone()) ZoneList<Statement*>(8, zone());
|
| if (fvar != NULL) {
|
| - VariableProxy* fproxy = top_scope_->NewUnresolved(
|
| + VariableProxy* fproxy = scope_->NewUnresolved(
|
| factory(), function_name, Interface::NewConst());
|
| fproxy->BindTo(fvar);
|
| body->Add(factory()->NewExpressionStatement(
|
| @@ -4244,11 +4068,11 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
| Runtime::FunctionForId(Runtime::kCreateJSGeneratorObject),
|
| arguments, pos);
|
| VariableProxy* init_proxy = factory()->NewVariableProxy(
|
| - current_function_state_->generator_object_variable());
|
| + function_state_->generator_object_variable());
|
| Assignment* assignment = factory()->NewAssignment(
|
| Token::INIT_VAR, init_proxy, allocation, RelocInfo::kNoPosition);
|
| VariableProxy* get_proxy = factory()->NewVariableProxy(
|
| - current_function_state_->generator_object_variable());
|
| + function_state_->generator_object_variable());
|
| Yield* yield = factory()->NewYield(
|
| get_proxy, assignment, Yield::INITIAL, RelocInfo::kNoPosition);
|
| body->Add(factory()->NewExpressionStatement(
|
| @@ -4259,7 +4083,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
|
|
| if (is_generator) {
|
| VariableProxy* get_proxy = factory()->NewVariableProxy(
|
| - current_function_state_->generator_object_variable());
|
| + function_state_->generator_object_variable());
|
| Expression *undefined = factory()->NewLiteral(
|
| isolate()->factory()->undefined_value(), RelocInfo::kNoPosition);
|
| Yield* yield = factory()->NewYield(
|
| @@ -4273,48 +4097,34 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
| handler_count = function_state.handler_count();
|
|
|
| Expect(Token::RBRACE, CHECK_OK);
|
| - scope->set_end_position(scanner().location().end_pos);
|
| + scope->set_end_position(scanner()->location().end_pos);
|
| }
|
|
|
| - // Validate strict mode.
|
| - if (!top_scope_->is_classic_mode()) {
|
| + // Validate strict mode. We can do this only after parsing the function,
|
| + // since the function can declare itself strict.
|
| + if (!scope_->is_classic_mode()) {
|
| if (IsEvalOrArguments(function_name)) {
|
| - int start_pos = scope->start_position();
|
| - int position = function_token_pos != RelocInfo::kNoPosition
|
| - ? function_token_pos : (start_pos > 0 ? start_pos - 1 : start_pos);
|
| - ScannerBase::Location location =
|
| - ScannerBase::Location(position, start_pos);
|
| - ReportMessageAt(location,
|
| - "strict_function_name", Vector<const char*>::empty());
|
| + ReportMessageAt(function_name_location, "strict_eval_arguments");
|
| *ok = false;
|
| return NULL;
|
| }
|
| - if (name_loc.IsValid()) {
|
| - ReportMessageAt(name_loc, "strict_param_name",
|
| - Vector<const char*>::empty());
|
| + if (name_is_strict_reserved) {
|
| + ReportMessageAt(function_name_location, "unexpected_strict_reserved");
|
| *ok = false;
|
| return NULL;
|
| }
|
| - if (dupe_loc.IsValid()) {
|
| - ReportMessageAt(dupe_loc, "strict_param_dupe",
|
| - Vector<const char*>::empty());
|
| + if (eval_args_error_log.IsValid()) {
|
| + ReportMessageAt(eval_args_error_log, "strict_eval_arguments");
|
| *ok = false;
|
| return NULL;
|
| }
|
| - if (name_is_strict_reserved) {
|
| - int start_pos = scope->start_position();
|
| - int position = function_token_pos != RelocInfo::kNoPosition
|
| - ? function_token_pos : (start_pos > 0 ? start_pos - 1 : start_pos);
|
| - ScannerBase::Location location =
|
| - ScannerBase::Location(position, start_pos);
|
| - ReportMessageAt(location, "strict_reserved_word",
|
| - Vector<const char*>::empty());
|
| + if (dupe_error_loc.IsValid()) {
|
| + ReportMessageAt(dupe_error_loc, "strict_param_dupe");
|
| *ok = false;
|
| return NULL;
|
| }
|
| if (reserved_loc.IsValid()) {
|
| - ReportMessageAt(reserved_loc, "strict_reserved_word",
|
| - Vector<const char*>::empty());
|
| + ReportMessageAt(reserved_loc, "unexpected_strict_reserved");
|
| *ok = false;
|
| return NULL;
|
| }
|
| @@ -4323,6 +4133,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
| CHECK_OK);
|
| }
|
| ast_properties = *factory()->visitor()->ast_properties();
|
| + slot_processor = factory()->visitor()->slot_processor();
|
| dont_optimize_reason = factory()->visitor()->dont_optimize_reason();
|
| }
|
|
|
| @@ -4346,6 +4157,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
| pos);
|
| function_literal->set_function_token_position(function_token_pos);
|
| function_literal->set_ast_properties(&ast_properties);
|
| + function_literal->set_slot_processor(slot_processor);
|
| function_literal->set_dont_optimize_reason(dont_optimize_reason);
|
|
|
| if (fni_ != NULL && should_infer_name) fni_->AddFunction(function_literal);
|
| @@ -4356,11 +4168,11 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
| PreParser::PreParseResult Parser::LazyParseFunctionLiteral(
|
| SingletonLogger* logger) {
|
| HistogramTimerScope preparse_scope(isolate()->counters()->pre_parse());
|
| - ASSERT_EQ(Token::LBRACE, scanner().current_token());
|
| + ASSERT_EQ(Token::LBRACE, scanner()->current_token());
|
|
|
| if (reusable_preparser_ == NULL) {
|
| intptr_t stack_limit = isolate()->stack_guard()->real_climit();
|
| - reusable_preparser_ = new PreParser(scanner_, NULL, stack_limit);
|
| + reusable_preparser_ = new PreParser(&scanner_, NULL, stack_limit);
|
| reusable_preparser_->set_allow_harmony_scoping(allow_harmony_scoping());
|
| reusable_preparser_->set_allow_modules(allow_modules());
|
| reusable_preparser_->set_allow_natives_syntax(allow_natives_syntax());
|
| @@ -4371,7 +4183,7 @@ PreParser::PreParseResult Parser::LazyParseFunctionLiteral(
|
| allow_harmony_numeric_literals());
|
| }
|
| PreParser::PreParseResult result =
|
| - reusable_preparser_->PreParseLazyFunction(top_scope_->language_mode(),
|
| + reusable_preparser_->PreParseLazyFunction(scope_->language_mode(),
|
| is_generator(),
|
| logger);
|
| return result;
|
| @@ -4384,13 +4196,14 @@ Expression* Parser::ParseV8Intrinsic(bool* ok) {
|
|
|
| int pos = peek_position();
|
| Expect(Token::MOD, CHECK_OK);
|
| - Handle<String> name = ParseIdentifier(CHECK_OK);
|
| + // Allow "eval" or "arguments" for backward compatibility.
|
| + Handle<String> name = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
|
| ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
|
|
|
| if (extension_ != NULL) {
|
| // The extension structures are only accessible while parsing the
|
| // very first time not when reparsing because of lazy compilation.
|
| - top_scope_->DeclarationScope()->ForceEagerCompilation();
|
| + scope_->DeclarationScope()->ForceEagerCompilation();
|
| }
|
|
|
| const Runtime::Function* function = Runtime::FunctionForName(name);
|
| @@ -4422,7 +4235,8 @@ Expression* Parser::ParseV8Intrinsic(bool* ok) {
|
|
|
| // Check that the function is defined if it's an inline runtime call.
|
| if (function == NULL && name->Get(0) == '_') {
|
| - ReportMessage("not_defined", Vector<Handle<String> >(&name, 1));
|
| + ParserTraits::ReportMessage("not_defined",
|
| + Vector<Handle<String> >(&name, 1));
|
| *ok = false;
|
| return NULL;
|
| }
|
| @@ -4432,114 +4246,12 @@ Expression* Parser::ParseV8Intrinsic(bool* ok) {
|
| }
|
|
|
|
|
| -bool ParserBase::peek_any_identifier() {
|
| - Token::Value next = peek();
|
| - return next == Token::IDENTIFIER ||
|
| - next == Token::FUTURE_RESERVED_WORD ||
|
| - next == Token::FUTURE_STRICT_RESERVED_WORD ||
|
| - next == Token::YIELD;
|
| -}
|
| -
|
| -
|
| -bool ParserBase::CheckContextualKeyword(Vector<const char> keyword) {
|
| - if (peek() == Token::IDENTIFIER &&
|
| - scanner()->is_next_contextual_keyword(keyword)) {
|
| - Consume(Token::IDENTIFIER);
|
| - return true;
|
| - }
|
| - return false;
|
| -}
|
| -
|
| -
|
| -void ParserBase::ExpectSemicolon(bool* ok) {
|
| - // Check for automatic semicolon insertion according to
|
| - // the rules given in ECMA-262, section 7.9, page 21.
|
| - Token::Value tok = peek();
|
| - if (tok == Token::SEMICOLON) {
|
| - Next();
|
| - return;
|
| - }
|
| - if (scanner()->HasAnyLineTerminatorBeforeNext() ||
|
| - tok == Token::RBRACE ||
|
| - tok == Token::EOS) {
|
| - return;
|
| - }
|
| - Expect(Token::SEMICOLON, ok);
|
| -}
|
| -
|
| -
|
| -void ParserBase::ExpectContextualKeyword(Vector<const char> keyword, bool* ok) {
|
| - Expect(Token::IDENTIFIER, ok);
|
| - if (!*ok) return;
|
| - if (!scanner()->is_literal_contextual_keyword(keyword)) {
|
| - ReportUnexpectedToken(scanner()->current_token());
|
| - *ok = false;
|
| - }
|
| -}
|
| -
|
| -
|
| Literal* Parser::GetLiteralUndefined(int position) {
|
| return factory()->NewLiteral(
|
| isolate()->factory()->undefined_value(), position);
|
| }
|
|
|
|
|
| -Literal* Parser::GetLiteralTheHole(int position) {
|
| - return factory()->NewLiteral(
|
| - isolate()->factory()->the_hole_value(), RelocInfo::kNoPosition);
|
| -}
|
| -
|
| -
|
| -// Parses an identifier that is valid for the current scope, in particular it
|
| -// fails on strict mode future reserved keywords in a strict scope.
|
| -Handle<String> Parser::ParseIdentifier(bool* ok) {
|
| - Token::Value next = Next();
|
| - if (next == Token::IDENTIFIER ||
|
| - (top_scope_->is_classic_mode() &&
|
| - (next == Token::FUTURE_STRICT_RESERVED_WORD ||
|
| - (next == Token::YIELD && !is_generator())))) {
|
| - return GetSymbol();
|
| - } else {
|
| - ReportUnexpectedToken(next);
|
| - *ok = false;
|
| - return Handle<String>();
|
| - }
|
| -}
|
| -
|
| -
|
| -// Parses and identifier or a strict mode future reserved word, and indicate
|
| -// whether it is strict mode future reserved.
|
| -Handle<String> Parser::ParseIdentifierOrStrictReservedWord(
|
| - bool* is_strict_reserved, bool* ok) {
|
| - Token::Value next = Next();
|
| - if (next == Token::IDENTIFIER) {
|
| - *is_strict_reserved = false;
|
| - } else if (next == Token::FUTURE_STRICT_RESERVED_WORD ||
|
| - (next == Token::YIELD && !is_generator())) {
|
| - *is_strict_reserved = true;
|
| - } else {
|
| - ReportUnexpectedToken(next);
|
| - *ok = false;
|
| - return Handle<String>();
|
| - }
|
| - return GetSymbol();
|
| -}
|
| -
|
| -
|
| -Handle<String> Parser::ParseIdentifierName(bool* ok) {
|
| - Token::Value next = Next();
|
| - if (next != Token::IDENTIFIER &&
|
| - next != Token::FUTURE_RESERVED_WORD &&
|
| - next != Token::FUTURE_STRICT_RESERVED_WORD &&
|
| - !Token::IsKeyword(next)) {
|
| - ReportUnexpectedToken(next);
|
| - *ok = false;
|
| - return Handle<String>();
|
| - }
|
| - return GetSymbol();
|
| -}
|
| -
|
| -
|
| void Parser::MarkAsLValue(Expression* expression) {
|
| VariableProxy* proxy = expression != NULL
|
| ? expression->AsVariableProxy()
|
| @@ -4552,27 +4264,14 @@ void Parser::MarkAsLValue(Expression* expression) {
|
| // Checks LHS expression for assignment and prefix/postfix increment/decrement
|
| // in strict mode.
|
| void Parser::CheckStrictModeLValue(Expression* expression,
|
| - const char* error,
|
| bool* ok) {
|
| - ASSERT(!top_scope_->is_classic_mode());
|
| + ASSERT(!scope_->is_classic_mode());
|
| VariableProxy* lhs = expression != NULL
|
| ? expression->AsVariableProxy()
|
| : NULL;
|
|
|
| if (lhs != NULL && !lhs->is_this() && IsEvalOrArguments(lhs->name())) {
|
| - ReportMessage(error, Vector<const char*>::empty());
|
| - *ok = false;
|
| - }
|
| -}
|
| -
|
| -
|
| -// Checks whether an octal literal was last seen between beg_pos and end_pos.
|
| -// If so, reports an error. Only called for strict mode.
|
| -void ParserBase::CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) {
|
| - ScannerBase::Location octal = scanner()->octal_position();
|
| - if (octal.IsValid() && beg_pos <= octal.beg_pos && octal.end_pos <= end_pos) {
|
| - ReportMessageAt(octal, "strict_octal_literal");
|
| - scanner()->clear_octal_position();
|
| + ReportMessage("strict_eval_arguments", Vector<const char*>::empty());
|
| *ok = false;
|
| }
|
| }
|
| @@ -4588,31 +4287,15 @@ void Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) {
|
| const char* elms[2] = { "Variable", c_string.get() };
|
| Vector<const char*> args(elms, 2);
|
| int position = decl->proxy()->position();
|
| - ScannerBase::Location location = position == RelocInfo::kNoPosition
|
| - ? ScannerBase::Location::invalid()
|
| - : ScannerBase::Location(position, position + 1);
|
| - ReportMessageAt(location, "redeclaration", args);
|
| + Scanner::Location location = position == RelocInfo::kNoPosition
|
| + ? Scanner::Location::invalid()
|
| + : Scanner::Location(position, position + 1);
|
| + ParserTraits::ReportMessageAt(location, "redeclaration", args);
|
| *ok = false;
|
| }
|
| }
|
|
|
|
|
| -// This function reads an identifier name and determines whether or not it
|
| -// is 'get' or 'set'.
|
| -Handle<String> Parser::ParseIdentifierNameOrGetOrSet(bool* is_get,
|
| - bool* is_set,
|
| - bool* ok) {
|
| - Handle<String> result = ParseIdentifierName(ok);
|
| - if (!*ok) return Handle<String>();
|
| - if (scanner().is_literal_ascii() && scanner().literal_length() == 3) {
|
| - const char* token = scanner().literal_ascii_string().start();
|
| - *is_get = strncmp(token, "get", 3) == 0;
|
| - *is_set = !*is_get && strncmp(token, "set", 3) == 0;
|
| - }
|
| - return result;
|
| -}
|
| -
|
| -
|
| // ----------------------------------------------------------------------------
|
| // Parser support
|
|
|
| @@ -5594,38 +5277,29 @@ int ScriptDataImpl::ReadNumber(byte** source) {
|
| }
|
|
|
|
|
| -// Create a ScannerBase for the preparser to use as input, and preparse the
|
| -// source.
|
| +// Create a Scanner for the preparser to use as input, and preparse the source.
|
| ScriptDataImpl* PreParserApi::PreParse(Isolate* isolate,
|
| - Handle<String> source) {
|
| + Utf16CharacterStream* source) {
|
| CompleteParserRecorder recorder;
|
| HistogramTimerScope timer(isolate->counters()->pre_parse());
|
| - source = FlattenGetString(source);
|
| - ScannerBase* scanner = NULL;
|
| - if (source->IsTwoByteRepresentation()) {
|
| - scanner = new ExperimentalScanner<uint16_t>(source, isolate);
|
| - } else {
|
| - scanner = new ExperimentalScanner<uint8_t>(source, isolate);
|
| - }
|
| + Scanner scanner(isolate->unicode_cache());
|
| intptr_t stack_limit = isolate->stack_guard()->real_climit();
|
| - PreParser preparser(scanner, &recorder, stack_limit);
|
| + PreParser preparser(&scanner, &recorder, stack_limit);
|
| preparser.set_allow_lazy(true);
|
| preparser.set_allow_generators(FLAG_harmony_generators);
|
| preparser.set_allow_for_of(FLAG_harmony_iteration);
|
| preparser.set_allow_harmony_scoping(FLAG_harmony_scoping);
|
| preparser.set_allow_harmony_numeric_literals(FLAG_harmony_numeric_literals);
|
| - scanner->Init();
|
| + scanner.Initialize(source);
|
| PreParser::PreParseResult result = preparser.PreParseProgram();
|
| if (result == PreParser::kPreParseStackOverflow) {
|
| isolate->StackOverflow();
|
| - delete scanner;
|
| return NULL;
|
| }
|
|
|
| // Extract the accumulated data from the recorder as a single
|
| // contiguous vector that we are responsible for disposing.
|
| Vector<unsigned> store = recorder.ExtractData();
|
| - delete scanner;
|
| return new ScriptDataImpl(store);
|
| }
|
|
|
| @@ -5667,10 +5341,10 @@ bool Parser::Parse() {
|
| ScriptDataImpl* pre_parse_data = info()->pre_parse_data();
|
| set_pre_parse_data(pre_parse_data);
|
| if (pre_parse_data != NULL && pre_parse_data->has_error()) {
|
| - ScannerBase::Location loc = pre_parse_data->MessageLocation();
|
| + Scanner::Location loc = pre_parse_data->MessageLocation();
|
| const char* message = pre_parse_data->BuildMessage();
|
| Vector<const char*> args = pre_parse_data->BuildArgs();
|
| - ReportMessageAt(loc, message, args);
|
| + ParserTraits::ReportMessageAt(loc, message, args);
|
| DeleteArray(message);
|
| for (int i = 0; i < args.length(); i++) {
|
| DeleteArray(args[i]);
|
| @@ -5685,11 +5359,4 @@ bool Parser::Parse() {
|
| return (result != NULL);
|
| }
|
|
|
| -
|
| -void Parser::SetScannerFlags() {
|
| - scanner_->SetHarmonyScoping(allow_harmony_scoping_);
|
| - scanner_->SetHarmonyModules(allow_harmony_modules_);
|
| - scanner_->SetHarmonyNumericLiterals(allow_harmony_numeric_literals_);
|
| -}
|
| -
|
| } } // namespace v8::internal
|
|
|