Home | History | Annotate | Download | only in parsing
      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