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 21 namespace v8 { 22 namespace 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 41 namespace { 42 43 PreParserIdentifier 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 if (scanner->LiteralMatches("name", 4)) 71 return PreParserIdentifier::Name(); 72 return PreParserIdentifier::Default(); 73 } 74 } 75 76 } // unnamed namespace 77 78 PreParserIdentifier PreParser::GetSymbol() const { 79 PreParserIdentifier symbol = GetSymbolHelper(scanner()); 80 if (track_unresolved_variables_) { 81 const AstRawString* result = scanner()->CurrentSymbol(ast_value_factory()); 82 DCHECK_NOT_NULL(result); 83 symbol.string_ = result; 84 } 85 return symbol; 86 } 87 88 PreParser::PreParseResult PreParser::PreParseFunction( 89 FunctionKind kind, DeclarationScope* function_scope, bool parsing_module, 90 bool is_inner_function, bool may_abort, int* use_counts) { 91 DCHECK_EQ(FUNCTION_SCOPE, function_scope->scope_type()); 92 parsing_module_ = parsing_module; 93 use_counts_ = use_counts; 94 DCHECK(!track_unresolved_variables_); 95 track_unresolved_variables_ = is_inner_function; 96 #ifdef DEBUG 97 function_scope->set_is_being_lazily_parsed(true); 98 #endif 99 100 // In the preparser, we use the function literal ids to count how many 101 // FunctionLiterals were encountered. The PreParser doesn't actually persist 102 // FunctionLiterals, so there IDs don't matter. 103 ResetFunctionLiteralId(); 104 105 // The caller passes the function_scope which is not yet inserted into the 106 // scope stack. All scopes above the function_scope are ignored by the 107 // PreParser. 108 DCHECK_NULL(function_state_); 109 DCHECK_NULL(scope_); 110 FunctionState function_state(&function_state_, &scope_, function_scope); 111 // This indirection is needed so that we can use the CHECK_OK macros. 112 bool ok_holder = true; 113 bool* ok = &ok_holder; 114 115 PreParserFormalParameters formals(function_scope); 116 bool has_duplicate_parameters = false; 117 DuplicateFinder duplicate_finder; 118 std::unique_ptr<ExpressionClassifier> formals_classifier; 119 120 // Parse non-arrow function parameters. For arrow functions, the parameters 121 // have already been parsed. 122 if (!IsArrowFunction(kind)) { 123 formals_classifier.reset(new ExpressionClassifier(this, &duplicate_finder)); 124 // We return kPreParseSuccess in failure cases too - errors are retrieved 125 // separately by Parser::SkipLazyFunctionBody. 126 ParseFormalParameterList(&formals, CHECK_OK_VALUE(kPreParseSuccess)); 127 Expect(Token::RPAREN, CHECK_OK_VALUE(kPreParseSuccess)); 128 int formals_end_position = scanner()->location().end_pos; 129 130 CheckArityRestrictions( 131 formals.arity, kind, formals.has_rest, function_scope->start_position(), 132 formals_end_position, CHECK_OK_VALUE(kPreParseSuccess)); 133 has_duplicate_parameters = 134 !classifier()->is_valid_formal_parameter_list_without_duplicates(); 135 } 136 137 Expect(Token::LBRACE, CHECK_OK_VALUE(kPreParseSuccess)); 138 DeclarationScope* inner_scope = function_scope; 139 LazyParsingResult result; 140 141 if (!formals.is_simple) { 142 inner_scope = NewVarblockScope(); 143 inner_scope->set_start_position(scanner()->location().beg_pos); 144 } 145 146 { 147 BlockState block_state(&scope_, inner_scope); 148 result = ParseStatementListAndLogFunction( 149 &formals, has_duplicate_parameters, may_abort, ok); 150 } 151 152 if (!formals.is_simple) { 153 BuildParameterInitializationBlock(formals, ok); 154 155 if (is_sloppy(inner_scope->language_mode())) { 156 inner_scope->HoistSloppyBlockFunctions(nullptr); 157 } 158 159 SetLanguageMode(function_scope, inner_scope->language_mode()); 160 inner_scope->set_end_position(scanner()->peek_location().end_pos); 161 inner_scope->FinalizeBlockScope(); 162 } else { 163 if (is_sloppy(function_scope->language_mode())) { 164 function_scope->HoistSloppyBlockFunctions(nullptr); 165 } 166 } 167 168 if (!IsArrowFunction(kind) && track_unresolved_variables_) { 169 // Declare arguments after parsing the function since lexical 'arguments' 170 // masks the arguments object. Declare arguments before declaring the 171 // function var since the arguments object masks 'function arguments'. 172 function_scope->DeclareArguments(ast_value_factory()); 173 } 174 175 use_counts_ = nullptr; 176 track_unresolved_variables_ = false; 177 178 if (result == kLazyParsingAborted) { 179 return kPreParseAbort; 180 } else if (stack_overflow()) { 181 return kPreParseStackOverflow; 182 } else if (!*ok) { 183 DCHECK(pending_error_handler_->has_pending_error()); 184 } else { 185 DCHECK_EQ(Token::RBRACE, scanner()->peek()); 186 187 if (!IsArrowFunction(kind)) { 188 // Validate parameter names. We can do this only after parsing the 189 // function, since the function can declare itself strict. 190 const bool allow_duplicate_parameters = 191 is_sloppy(function_scope->language_mode()) && formals.is_simple && 192 !IsConciseMethod(kind); 193 ValidateFormalParameters(function_scope->language_mode(), 194 allow_duplicate_parameters, 195 CHECK_OK_VALUE(kPreParseSuccess)); 196 } 197 198 if (is_strict(function_scope->language_mode())) { 199 int end_pos = scanner()->location().end_pos; 200 CheckStrictOctalLiteral(function_scope->start_position(), end_pos, ok); 201 } 202 } 203 return kPreParseSuccess; 204 } 205 206 207 // Preparsing checks a JavaScript program and emits preparse-data that helps 208 // a later parsing to be faster. 209 // See preparser-data.h for the data. 210 211 // The PreParser checks that the syntax follows the grammar for JavaScript, 212 // and collects some information about the program along the way. 213 // The grammar check is only performed in order to understand the program 214 // sufficiently to deduce some information about it, that can be used 215 // to speed up later parsing. Finding errors is not the goal of pre-parsing, 216 // rather it is to speed up properly written and correct programs. 217 // That means that contextual checks (like a label being declared where 218 // it is used) are generally omitted. 219 220 PreParser::Expression PreParser::ParseFunctionLiteral( 221 Identifier function_name, Scanner::Location function_name_location, 222 FunctionNameValidity function_name_validity, FunctionKind kind, 223 int function_token_pos, FunctionLiteral::FunctionType function_type, 224 LanguageMode language_mode, bool* ok) { 225 // Function :: 226 // '(' FormalParameterList? ')' '{' FunctionBody '}' 227 const RuntimeCallStats::CounterId counters[2][2] = { 228 {&RuntimeCallStats::PreParseBackgroundNoVariableResolution, 229 &RuntimeCallStats::PreParseNoVariableResolution}, 230 {&RuntimeCallStats::PreParseBackgroundWithVariableResolution, 231 &RuntimeCallStats::PreParseWithVariableResolution}}; 232 RuntimeCallTimerScope runtime_timer( 233 runtime_call_stats_, 234 counters[track_unresolved_variables_][parsing_on_main_thread_]); 235 236 DeclarationScope* function_scope = NewFunctionScope(kind); 237 function_scope->SetLanguageMode(language_mode); 238 FunctionState function_state(&function_state_, &scope_, function_scope); 239 DuplicateFinder duplicate_finder; 240 ExpressionClassifier formals_classifier(this, &duplicate_finder); 241 GetNextFunctionLiteralId(); 242 243 Expect(Token::LPAREN, CHECK_OK); 244 int start_position = scanner()->location().beg_pos; 245 function_scope->set_start_position(start_position); 246 PreParserFormalParameters formals(function_scope); 247 ParseFormalParameterList(&formals, CHECK_OK); 248 Expect(Token::RPAREN, CHECK_OK); 249 int formals_end_position = scanner()->location().end_pos; 250 251 CheckArityRestrictions(formals.arity, kind, formals.has_rest, start_position, 252 formals_end_position, CHECK_OK); 253 254 Expect(Token::LBRACE, CHECK_OK); 255 256 // Parse function body. 257 PreParserStatementList body; 258 int pos = function_token_pos == kNoSourcePosition ? peek_position() 259 : function_token_pos; 260 ParseFunctionBody(body, function_name, pos, formals, kind, function_type, 261 CHECK_OK); 262 263 // Parsing the body may change the language mode in our scope. 264 language_mode = function_scope->language_mode(); 265 266 if (is_sloppy(language_mode)) { 267 function_scope->HoistSloppyBlockFunctions(nullptr); 268 } 269 270 // Validate name and parameter names. We can do this only after parsing the 271 // function, since the function can declare itself strict. 272 CheckFunctionName(language_mode, function_name, function_name_validity, 273 function_name_location, CHECK_OK); 274 const bool allow_duplicate_parameters = 275 is_sloppy(language_mode) && formals.is_simple && !IsConciseMethod(kind); 276 ValidateFormalParameters(language_mode, allow_duplicate_parameters, CHECK_OK); 277 278 int end_position = scanner()->location().end_pos; 279 if (is_strict(language_mode)) { 280 CheckStrictOctalLiteral(start_position, end_position, CHECK_OK); 281 } 282 283 if (FLAG_trace_preparse) { 284 PrintF(" [%s]: %i-%i\n", 285 track_unresolved_variables_ ? "Preparse resolution" 286 : "Preparse no-resolution", 287 function_scope->start_position(), function_scope->end_position()); 288 } 289 290 return Expression::Default(); 291 } 292 293 PreParser::LazyParsingResult PreParser::ParseStatementListAndLogFunction( 294 PreParserFormalParameters* formals, bool has_duplicate_parameters, 295 bool may_abort, bool* ok) { 296 PreParserStatementList body; 297 LazyParsingResult result = ParseStatementList( 298 body, Token::RBRACE, may_abort, CHECK_OK_VALUE(kLazyParsingComplete)); 299 if (result == kLazyParsingAborted) return result; 300 301 // Position right after terminal '}'. 302 DCHECK_EQ(Token::RBRACE, scanner()->peek()); 303 int body_end = scanner()->peek_location().end_pos; 304 DCHECK_EQ(this->scope()->is_function_scope(), formals->is_simple); 305 log_.LogFunction(body_end, formals->num_parameters(), 306 formals->function_length, has_duplicate_parameters, 307 function_state_->expected_property_count(), 308 GetLastFunctionLiteralId()); 309 return kLazyParsingComplete; 310 } 311 312 PreParserExpression PreParser::ExpressionFromIdentifier( 313 PreParserIdentifier name, int start_position, InferName infer) { 314 VariableProxy* proxy = nullptr; 315 if (track_unresolved_variables_) { 316 AstNodeFactory factory(ast_value_factory()); 317 // Setting the Zone is necessary because zone_ might be the temp Zone, and 318 // AstValueFactory doesn't know about it. 319 factory.set_zone(zone()); 320 DCHECK_NOT_NULL(name.string_); 321 proxy = scope()->NewUnresolved(&factory, name.string_, start_position, 322 NORMAL_VARIABLE); 323 } 324 return PreParserExpression::FromIdentifier(name, proxy, zone()); 325 } 326 327 void PreParser::DeclareAndInitializeVariables( 328 PreParserStatement block, 329 const DeclarationDescriptor* declaration_descriptor, 330 const DeclarationParsingResult::Declaration* declaration, 331 ZoneList<const AstRawString*>* names, bool* ok) { 332 if (declaration->pattern.variables_ != nullptr) { 333 DCHECK(FLAG_lazy_inner_functions); 334 DCHECK(track_unresolved_variables_); 335 for (auto variable : *(declaration->pattern.variables_)) { 336 declaration_descriptor->scope->RemoveUnresolved(variable); 337 Variable* var = scope()->DeclareVariableName( 338 variable->raw_name(), declaration_descriptor->mode); 339 if (FLAG_preparser_scope_analysis) { 340 MarkLoopVariableAsAssigned(declaration_descriptor->scope, var); 341 // This is only necessary if there is an initializer, but we don't have 342 // that information here. Consequently, the preparser sometimes says 343 // maybe-assigned where the parser (correctly) says never-assigned. 344 } 345 if (names) { 346 names->Add(variable->raw_name(), zone()); 347 } 348 } 349 } 350 } 351 352 #undef CHECK_OK 353 #undef CHECK_OK_CUSTOM 354 355 356 } // namespace internal 357 } // namespace v8 358