1// Copyright 2011 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include <cmath> 6 7#include "src/allocation.h" 8#include "src/base/logging.h" 9#include "src/conversions-inl.h" 10#include "src/conversions.h" 11#include "src/globals.h" 12#include "src/list.h" 13#include "src/parsing/duplicate-finder.h" 14#include "src/parsing/parser-base.h" 15#include "src/parsing/preparse-data-format.h" 16#include "src/parsing/preparse-data.h" 17#include "src/parsing/preparser.h" 18#include "src/unicode.h" 19#include "src/utils.h" 20 21namespace v8 { 22namespace internal { 23 24// ---------------------------------------------------------------------------- 25// The CHECK_OK macro is a convenient macro to enforce error 26// handling for functions that may fail (by returning !*ok). 27// 28// CAUTION: This macro appends extra statements after a call, 29// thus it must never be used where only a single statement 30// is correct (e.g. an if statement branch w/o braces)! 31 32#define CHECK_OK_VALUE(x) ok); \ 33 if (!*ok) return x; \ 34 ((void)0 35#define DUMMY ) // to make indentation work 36#undef DUMMY 37 38#define CHECK_OK CHECK_OK_VALUE(Expression::Default()) 39#define CHECK_OK_VOID CHECK_OK_VALUE(this->Void()) 40 41namespace { 42 43PreParserIdentifier GetSymbolHelper(Scanner* scanner) { 44 switch (scanner->current_token()) { 45 case Token::ENUM: 46 return PreParserIdentifier::Enum(); 47 case Token::AWAIT: 48 return PreParserIdentifier::Await(); 49 case Token::FUTURE_STRICT_RESERVED_WORD: 50 return PreParserIdentifier::FutureStrictReserved(); 51 case Token::LET: 52 return PreParserIdentifier::Let(); 53 case Token::STATIC: 54 return PreParserIdentifier::Static(); 55 case Token::YIELD: 56 return PreParserIdentifier::Yield(); 57 case Token::ASYNC: 58 return PreParserIdentifier::Async(); 59 default: 60 if (scanner->UnescapedLiteralMatches("eval", 4)) 61 return PreParserIdentifier::Eval(); 62 if (scanner->UnescapedLiteralMatches("arguments", 9)) 63 return PreParserIdentifier::Arguments(); 64 if (scanner->UnescapedLiteralMatches("undefined", 9)) 65 return PreParserIdentifier::Undefined(); 66 if (scanner->LiteralMatches("prototype", 9)) 67 return PreParserIdentifier::Prototype(); 68 if (scanner->LiteralMatches("constructor", 11)) 69 return PreParserIdentifier::Constructor(); 70 return PreParserIdentifier::Default(); 71 } 72} 73 74} // unnamed namespace 75 76PreParserIdentifier PreParser::GetSymbol() const { 77 PreParserIdentifier symbol = GetSymbolHelper(scanner()); 78 if (track_unresolved_variables_) { 79 const AstRawString* result = scanner()->CurrentSymbol(ast_value_factory()); 80 DCHECK_NOT_NULL(result); 81 symbol.string_ = result; 82 } 83 return symbol; 84} 85 86PreParser::PreParseResult PreParser::PreParseFunction( 87 FunctionKind kind, DeclarationScope* function_scope, bool parsing_module, 88 bool is_inner_function, bool may_abort, int* use_counts) { 89 RuntimeCallTimerScope runtime_timer( 90 runtime_call_stats_, 91 track_unresolved_variables_ 92 ? &RuntimeCallStats::PreParseWithVariableResolution 93 : &RuntimeCallStats::PreParseNoVariableResolution); 94 DCHECK_EQ(FUNCTION_SCOPE, function_scope->scope_type()); 95 parsing_module_ = parsing_module; 96 use_counts_ = use_counts; 97 DCHECK(!track_unresolved_variables_); 98 track_unresolved_variables_ = is_inner_function; 99 100 // The caller passes the function_scope which is not yet inserted into the 101 // scope_state_. All scopes above the function_scope are ignored by the 102 // PreParser. 103 DCHECK_NULL(scope_state_); 104 FunctionState function_state(&function_state_, &scope_state_, function_scope); 105 // This indirection is needed so that we can use the CHECK_OK macros. 106 bool ok_holder = true; 107 bool* ok = &ok_holder; 108 109 PreParserFormalParameters formals(function_scope); 110 bool has_duplicate_parameters = false; 111 DuplicateFinder duplicate_finder(scanner()->unicode_cache()); 112 std::unique_ptr<ExpressionClassifier> formals_classifier; 113 114 // Parse non-arrow function parameters. For arrow functions, the parameters 115 // have already been parsed. 116 if (!IsArrowFunction(kind)) { 117 formals_classifier.reset(new ExpressionClassifier(this, &duplicate_finder)); 118 // We return kPreParseSuccess in failure cases too - errors are retrieved 119 // separately by Parser::SkipLazyFunctionBody. 120 ParseFormalParameterList(&formals, CHECK_OK_VALUE(kPreParseSuccess)); 121 Expect(Token::RPAREN, CHECK_OK_VALUE(kPreParseSuccess)); 122 int formals_end_position = scanner()->location().end_pos; 123 124 CheckArityRestrictions( 125 formals.arity, kind, formals.has_rest, function_scope->start_position(), 126 formals_end_position, CHECK_OK_VALUE(kPreParseSuccess)); 127 has_duplicate_parameters = 128 !classifier()->is_valid_formal_parameter_list_without_duplicates(); 129 } 130 131 Expect(Token::LBRACE, CHECK_OK_VALUE(kPreParseSuccess)); 132 LazyParsingResult result = ParseStatementListAndLogFunction( 133 &formals, has_duplicate_parameters, may_abort, ok); 134 use_counts_ = nullptr; 135 track_unresolved_variables_ = false; 136 if (result == kLazyParsingAborted) { 137 return kPreParseAbort; 138 } else if (stack_overflow()) { 139 return kPreParseStackOverflow; 140 } else if (!*ok) { 141 DCHECK(pending_error_handler_->has_pending_error()); 142 } else { 143 DCHECK_EQ(Token::RBRACE, scanner()->peek()); 144 145 if (!IsArrowFunction(kind)) { 146 // Validate parameter names. We can do this only after parsing the 147 // function, since the function can declare itself strict. 148 const bool allow_duplicate_parameters = 149 is_sloppy(function_scope->language_mode()) && formals.is_simple && 150 !IsConciseMethod(kind); 151 ValidateFormalParameters(function_scope->language_mode(), 152 allow_duplicate_parameters, 153 CHECK_OK_VALUE(kPreParseSuccess)); 154 } 155 156 if (is_strict(function_scope->language_mode())) { 157 int end_pos = scanner()->location().end_pos; 158 CheckStrictOctalLiteral(function_scope->start_position(), end_pos, ok); 159 CheckDecimalLiteralWithLeadingZero(function_scope->start_position(), 160 end_pos); 161 } 162 } 163 return kPreParseSuccess; 164} 165 166 167// Preparsing checks a JavaScript program and emits preparse-data that helps 168// a later parsing to be faster. 169// See preparser-data.h for the data. 170 171// The PreParser checks that the syntax follows the grammar for JavaScript, 172// and collects some information about the program along the way. 173// The grammar check is only performed in order to understand the program 174// sufficiently to deduce some information about it, that can be used 175// to speed up later parsing. Finding errors is not the goal of pre-parsing, 176// rather it is to speed up properly written and correct programs. 177// That means that contextual checks (like a label being declared where 178// it is used) are generally omitted. 179 180PreParser::Expression PreParser::ParseFunctionLiteral( 181 Identifier function_name, Scanner::Location function_name_location, 182 FunctionNameValidity function_name_validity, FunctionKind kind, 183 int function_token_pos, FunctionLiteral::FunctionType function_type, 184 LanguageMode language_mode, bool* ok) { 185 // Function :: 186 // '(' FormalParameterList? ')' '{' FunctionBody '}' 187 RuntimeCallTimerScope runtime_timer( 188 runtime_call_stats_, 189 track_unresolved_variables_ 190 ? &RuntimeCallStats::PreParseWithVariableResolution 191 : &RuntimeCallStats::PreParseNoVariableResolution); 192 193 // Parse function body. 194 PreParserStatementList body; 195 DeclarationScope* function_scope = NewFunctionScope(kind); 196 function_scope->SetLanguageMode(language_mode); 197 FunctionState function_state(&function_state_, &scope_state_, function_scope); 198 DuplicateFinder duplicate_finder(scanner()->unicode_cache()); 199 ExpressionClassifier formals_classifier(this, &duplicate_finder); 200 201 Expect(Token::LPAREN, CHECK_OK); 202 int start_position = scanner()->location().beg_pos; 203 function_scope->set_start_position(start_position); 204 PreParserFormalParameters formals(function_scope); 205 ParseFormalParameterList(&formals, CHECK_OK); 206 Expect(Token::RPAREN, CHECK_OK); 207 int formals_end_position = scanner()->location().end_pos; 208 209 CheckArityRestrictions(formals.arity, kind, formals.has_rest, start_position, 210 formals_end_position, CHECK_OK); 211 212 Expect(Token::LBRACE, CHECK_OK); 213 ParseStatementList(body, Token::RBRACE, CHECK_OK); 214 Expect(Token::RBRACE, CHECK_OK); 215 216 // Parsing the body may change the language mode in our scope. 217 language_mode = function_scope->language_mode(); 218 219 // Validate name and parameter names. We can do this only after parsing the 220 // function, since the function can declare itself strict. 221 CheckFunctionName(language_mode, function_name, function_name_validity, 222 function_name_location, CHECK_OK); 223 const bool allow_duplicate_parameters = 224 is_sloppy(language_mode) && formals.is_simple && !IsConciseMethod(kind); 225 ValidateFormalParameters(language_mode, allow_duplicate_parameters, CHECK_OK); 226 227 int end_position = scanner()->location().end_pos; 228 if (is_strict(language_mode)) { 229 CheckStrictOctalLiteral(start_position, end_position, CHECK_OK); 230 CheckDecimalLiteralWithLeadingZero(start_position, end_position); 231 } 232 function_scope->set_end_position(end_position); 233 234 if (FLAG_trace_preparse) { 235 PrintF(" [%s]: %i-%i\n", 236 track_unresolved_variables_ ? "Preparse resolution" 237 : "Preparse no-resolution", 238 function_scope->start_position(), function_scope->end_position()); 239 } 240 241 return Expression::Default(); 242} 243 244PreParser::LazyParsingResult PreParser::ParseStatementListAndLogFunction( 245 PreParserFormalParameters* formals, bool has_duplicate_parameters, 246 bool may_abort, bool* ok) { 247 PreParserStatementList body; 248 LazyParsingResult result = ParseStatementList( 249 body, Token::RBRACE, may_abort, CHECK_OK_VALUE(kLazyParsingComplete)); 250 if (result == kLazyParsingAborted) return result; 251 252 // Position right after terminal '}'. 253 DCHECK_EQ(Token::RBRACE, scanner()->peek()); 254 int body_end = scanner()->peek_location().end_pos; 255 DCHECK(this->scope()->is_function_scope()); 256 log_.LogFunction(body_end, formals->num_parameters(), 257 formals->function_length, has_duplicate_parameters, 258 function_state_->materialized_literal_count(), 259 function_state_->expected_property_count()); 260 return kLazyParsingComplete; 261} 262 263PreParserExpression PreParser::ExpressionFromIdentifier( 264 PreParserIdentifier name, int start_position, InferName infer) { 265 if (track_unresolved_variables_) { 266 AstNodeFactory factory(ast_value_factory()); 267 // Setting the Zone is necessary because zone_ might be the temp Zone, and 268 // AstValueFactory doesn't know about it. 269 factory.set_zone(zone()); 270 DCHECK_NOT_NULL(name.string_); 271 scope()->NewUnresolved(&factory, name.string_, start_position, 272 NORMAL_VARIABLE); 273 } 274 return PreParserExpression::FromIdentifier(name, zone()); 275} 276 277void PreParser::DeclareAndInitializeVariables( 278 PreParserStatement block, 279 const DeclarationDescriptor* declaration_descriptor, 280 const DeclarationParsingResult::Declaration* declaration, 281 ZoneList<const AstRawString*>* names, bool* ok) { 282 if (declaration->pattern.identifiers_ != nullptr) { 283 DCHECK(FLAG_lazy_inner_functions); 284 /* Mimic what Parser does when declaring variables (see 285 Parser::PatternRewriter::VisitVariableProxy). 286 287 var + no initializer -> RemoveUnresolved 288 let / const + no initializer -> RemoveUnresolved 289 var + initializer -> RemoveUnresolved followed by NewUnresolved 290 let / const + initializer -> RemoveUnresolved 291 */ 292 293 if (declaration->initializer.IsEmpty() || 294 (declaration_descriptor->mode == VariableMode::LET || 295 declaration_descriptor->mode == VariableMode::CONST)) { 296 for (auto identifier : *(declaration->pattern.identifiers_)) { 297 declaration_descriptor->scope->RemoveUnresolved(identifier); 298 } 299 } 300 } 301} 302 303#undef CHECK_OK 304#undef CHECK_OK_CUSTOM 305 306 307} // namespace internal 308} // namespace v8 309