2011-05-19 09:22:32 +00:00
|
|
|
// Copyright 2011 the V8 project authors. All rights reserved.
|
2014-04-29 06:42:26 +00:00
|
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
|
|
// found in the LICENSE file.
|
2010-11-23 11:46:36 +00:00
|
|
|
|
2013-04-19 13:26:47 +00:00
|
|
|
#include <cmath>
|
2011-09-07 12:39:53 +00:00
|
|
|
|
2014-06-03 08:12:43 +00:00
|
|
|
#include "src/allocation.h"
|
2014-06-30 13:25:46 +00:00
|
|
|
#include "src/base/logging.h"
|
2014-06-03 08:12:43 +00:00
|
|
|
#include "src/conversions-inl.h"
|
2014-06-20 08:40:11 +00:00
|
|
|
#include "src/conversions.h"
|
2014-06-03 08:12:43 +00:00
|
|
|
#include "src/globals.h"
|
|
|
|
#include "src/list.h"
|
2016-08-25 11:58:07 +00:00
|
|
|
#include "src/parsing/duplicate-finder.h"
|
2015-12-07 14:26:25 +00:00
|
|
|
#include "src/parsing/parser-base.h"
|
2015-11-26 16:22:34 +00:00
|
|
|
#include "src/parsing/preparse-data-format.h"
|
2016-04-26 17:30:21 +00:00
|
|
|
#include "src/parsing/preparse-data.h"
|
2015-11-26 16:22:34 +00:00
|
|
|
#include "src/parsing/preparser.h"
|
2014-06-03 08:12:43 +00:00
|
|
|
#include "src/unicode.h"
|
|
|
|
#include "src/utils.h"
|
2011-07-05 11:54:11 +00:00
|
|
|
|
2013-04-19 13:26:47 +00:00
|
|
|
namespace v8 {
|
2013-10-14 13:07:20 +00:00
|
|
|
namespace internal {
|
2010-11-23 11:46:36 +00:00
|
|
|
|
2016-07-19 08:03:43 +00:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// The CHECK_OK macro is a convenient macro to enforce error
|
|
|
|
// handling for functions that may fail (by returning !*ok).
|
|
|
|
//
|
|
|
|
// CAUTION: This macro appends extra statements after a call,
|
|
|
|
// thus it must never be used where only a single statement
|
|
|
|
// is correct (e.g. an if statement branch w/o braces)!
|
|
|
|
|
2016-09-01 10:22:54 +00:00
|
|
|
#define CHECK_OK_VALUE(x) ok); \
|
|
|
|
if (!*ok) return x; \
|
2016-07-19 08:03:43 +00:00
|
|
|
((void)0
|
|
|
|
#define DUMMY ) // to make indentation work
|
|
|
|
#undef DUMMY
|
|
|
|
|
2016-09-30 08:03:18 +00:00
|
|
|
#define CHECK_OK CHECK_OK_VALUE(Expression::Default())
|
2016-09-01 10:22:54 +00:00
|
|
|
#define CHECK_OK_VOID CHECK_OK_VALUE(this->Void())
|
2016-07-19 08:03:43 +00:00
|
|
|
|
2016-09-27 09:48:17 +00:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
PreParserIdentifier GetSymbolHelper(Scanner* scanner) {
|
|
|
|
switch (scanner->current_token()) {
|
2016-08-19 08:14:16 +00:00
|
|
|
case Token::ENUM:
|
|
|
|
return PreParserIdentifier::Enum();
|
|
|
|
case Token::AWAIT:
|
|
|
|
return PreParserIdentifier::Await();
|
|
|
|
case Token::FUTURE_STRICT_RESERVED_WORD:
|
|
|
|
return PreParserIdentifier::FutureStrictReserved();
|
|
|
|
case Token::LET:
|
|
|
|
return PreParserIdentifier::Let();
|
|
|
|
case Token::STATIC:
|
|
|
|
return PreParserIdentifier::Static();
|
|
|
|
case Token::YIELD:
|
|
|
|
return PreParserIdentifier::Yield();
|
|
|
|
case Token::ASYNC:
|
|
|
|
return PreParserIdentifier::Async();
|
|
|
|
default:
|
2016-09-27 09:48:17 +00:00
|
|
|
if (scanner->UnescapedLiteralMatches("eval", 4))
|
2016-08-19 08:14:16 +00:00
|
|
|
return PreParserIdentifier::Eval();
|
2016-09-27 09:48:17 +00:00
|
|
|
if (scanner->UnescapedLiteralMatches("arguments", 9))
|
2016-08-19 08:14:16 +00:00
|
|
|
return PreParserIdentifier::Arguments();
|
2016-09-27 09:48:17 +00:00
|
|
|
if (scanner->UnescapedLiteralMatches("undefined", 9))
|
2016-08-19 08:14:16 +00:00
|
|
|
return PreParserIdentifier::Undefined();
|
2016-09-27 09:48:17 +00:00
|
|
|
if (scanner->LiteralMatches("prototype", 9))
|
2016-08-19 08:14:16 +00:00
|
|
|
return PreParserIdentifier::Prototype();
|
2016-09-27 09:48:17 +00:00
|
|
|
if (scanner->LiteralMatches("constructor", 11))
|
2016-08-19 08:14:16 +00:00
|
|
|
return PreParserIdentifier::Constructor();
|
2016-12-07 10:34:15 +00:00
|
|
|
if (scanner->LiteralMatches("name", 4))
|
|
|
|
return PreParserIdentifier::Name();
|
2016-08-19 08:14:16 +00:00
|
|
|
return PreParserIdentifier::Default();
|
2014-02-11 09:35:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-27 09:48:17 +00:00
|
|
|
} // unnamed namespace
|
|
|
|
|
|
|
|
PreParserIdentifier PreParser::GetSymbol() const {
|
|
|
|
PreParserIdentifier symbol = GetSymbolHelper(scanner());
|
|
|
|
if (track_unresolved_variables_) {
|
|
|
|
const AstRawString* result = scanner()->CurrentSymbol(ast_value_factory());
|
|
|
|
DCHECK_NOT_NULL(result);
|
|
|
|
symbol.string_ = result;
|
|
|
|
}
|
|
|
|
return symbol;
|
|
|
|
}
|
|
|
|
|
2016-10-14 14:08:53 +00:00
|
|
|
PreParser::PreParseResult PreParser::PreParseFunction(
|
2016-11-04 15:04:03 +00:00
|
|
|
FunctionKind kind, DeclarationScope* function_scope, bool parsing_module,
|
2016-11-07 13:23:01 +00:00
|
|
|
bool is_inner_function, bool may_abort, int* use_counts) {
|
2016-09-27 09:49:26 +00:00
|
|
|
DCHECK_EQ(FUNCTION_SCOPE, function_scope->scope_type());
|
2016-04-29 18:12:57 +00:00
|
|
|
parsing_module_ = parsing_module;
|
2016-04-26 00:29:37 +00:00
|
|
|
use_counts_ = use_counts;
|
2016-09-27 09:48:17 +00:00
|
|
|
DCHECK(!track_unresolved_variables_);
|
|
|
|
track_unresolved_variables_ = is_inner_function;
|
2016-12-06 13:23:29 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
function_scope->set_is_being_lazily_parsed(true);
|
|
|
|
#endif
|
2016-09-27 09:48:17 +00:00
|
|
|
|
2016-11-28 11:40:22 +00:00
|
|
|
// In the preparser, we use the function literal ids to count how many
|
|
|
|
// FunctionLiterals were encountered. The PreParser doesn't actually persist
|
|
|
|
// FunctionLiterals, so there IDs don't matter.
|
|
|
|
ResetFunctionLiteralId();
|
|
|
|
|
2016-09-27 09:48:17 +00:00
|
|
|
// The caller passes the function_scope which is not yet inserted into the
|
2017-02-20 10:41:29 +00:00
|
|
|
// scope stack. All scopes above the function_scope are ignored by the
|
2016-09-27 09:48:17 +00:00
|
|
|
// PreParser.
|
2017-02-20 10:41:29 +00:00
|
|
|
DCHECK_NULL(function_state_);
|
|
|
|
DCHECK_NULL(scope_);
|
|
|
|
FunctionState function_state(&function_state_, &scope_, function_scope);
|
2016-11-04 15:04:03 +00:00
|
|
|
// This indirection is needed so that we can use the CHECK_OK macros.
|
|
|
|
bool ok_holder = true;
|
|
|
|
bool* ok = &ok_holder;
|
|
|
|
|
|
|
|
PreParserFormalParameters formals(function_scope);
|
|
|
|
bool has_duplicate_parameters = false;
|
2016-12-02 12:34:58 +00:00
|
|
|
DuplicateFinder duplicate_finder;
|
2016-11-04 15:04:03 +00:00
|
|
|
std::unique_ptr<ExpressionClassifier> formals_classifier;
|
|
|
|
|
|
|
|
// Parse non-arrow function parameters. For arrow functions, the parameters
|
|
|
|
// have already been parsed.
|
|
|
|
if (!IsArrowFunction(kind)) {
|
|
|
|
formals_classifier.reset(new ExpressionClassifier(this, &duplicate_finder));
|
|
|
|
// We return kPreParseSuccess in failure cases too - errors are retrieved
|
|
|
|
// separately by Parser::SkipLazyFunctionBody.
|
|
|
|
ParseFormalParameterList(&formals, CHECK_OK_VALUE(kPreParseSuccess));
|
|
|
|
Expect(Token::RPAREN, CHECK_OK_VALUE(kPreParseSuccess));
|
|
|
|
int formals_end_position = scanner()->location().end_pos;
|
|
|
|
|
|
|
|
CheckArityRestrictions(
|
|
|
|
formals.arity, kind, formals.has_rest, function_scope->start_position(),
|
|
|
|
formals_end_position, CHECK_OK_VALUE(kPreParseSuccess));
|
|
|
|
has_duplicate_parameters =
|
|
|
|
!classifier()->is_valid_formal_parameter_list_without_duplicates();
|
|
|
|
}
|
|
|
|
|
2017-02-10 13:37:03 +00:00
|
|
|
Expect(Token::LBRACE, CHECK_OK_VALUE(kPreParseSuccess));
|
2017-02-08 16:45:24 +00:00
|
|
|
DeclarationScope* inner_scope = function_scope;
|
|
|
|
LazyParsingResult result;
|
|
|
|
|
|
|
|
if (!formals.is_simple) {
|
|
|
|
inner_scope = NewVarblockScope();
|
|
|
|
inner_scope->set_start_position(scanner()->location().beg_pos);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
2017-02-20 10:41:29 +00:00
|
|
|
BlockState block_state(&scope_, inner_scope);
|
2017-02-08 16:45:24 +00:00
|
|
|
result = ParseStatementListAndLogFunction(
|
|
|
|
&formals, has_duplicate_parameters, may_abort, ok);
|
|
|
|
}
|
|
|
|
|
2017-02-10 13:37:03 +00:00
|
|
|
if (!formals.is_simple) {
|
2017-02-16 09:16:32 +00:00
|
|
|
BuildParameterInitializationBlock(formals, ok);
|
|
|
|
|
|
|
|
if (is_sloppy(inner_scope->language_mode())) {
|
|
|
|
inner_scope->HoistSloppyBlockFunctions(nullptr);
|
|
|
|
}
|
|
|
|
|
2017-02-10 13:37:03 +00:00
|
|
|
SetLanguageMode(function_scope, inner_scope->language_mode());
|
|
|
|
inner_scope->set_end_position(scanner()->peek_location().end_pos);
|
|
|
|
inner_scope->FinalizeBlockScope();
|
2017-02-16 09:16:32 +00:00
|
|
|
} else {
|
|
|
|
if (is_sloppy(function_scope->language_mode())) {
|
|
|
|
function_scope->HoistSloppyBlockFunctions(nullptr);
|
|
|
|
}
|
2017-02-03 08:16:07 +00:00
|
|
|
}
|
|
|
|
|
2017-01-26 10:14:40 +00:00
|
|
|
if (!IsArrowFunction(kind) && track_unresolved_variables_) {
|
|
|
|
// Declare arguments after parsing the function since lexical 'arguments'
|
|
|
|
// masks the arguments object. Declare arguments before declaring the
|
|
|
|
// function var since the arguments object masks 'function arguments'.
|
|
|
|
function_scope->DeclareArguments(ast_value_factory());
|
|
|
|
}
|
|
|
|
|
2016-04-26 00:29:37 +00:00
|
|
|
use_counts_ = nullptr;
|
2016-09-27 09:48:17 +00:00
|
|
|
track_unresolved_variables_ = false;
|
2016-12-06 13:23:29 +00:00
|
|
|
|
2016-09-01 10:22:54 +00:00
|
|
|
if (result == kLazyParsingAborted) {
|
|
|
|
return kPreParseAbort;
|
2015-05-06 10:21:20 +00:00
|
|
|
} else if (stack_overflow()) {
|
|
|
|
return kPreParseStackOverflow;
|
2016-11-04 15:04:03 +00:00
|
|
|
} else if (!*ok) {
|
2016-11-15 10:15:43 +00:00
|
|
|
DCHECK(pending_error_handler_->has_pending_error());
|
2011-11-25 09:36:31 +00:00
|
|
|
} else {
|
2014-08-04 11:34:54 +00:00
|
|
|
DCHECK_EQ(Token::RBRACE, scanner()->peek());
|
2016-11-04 15:04:03 +00:00
|
|
|
|
|
|
|
if (!IsArrowFunction(kind)) {
|
|
|
|
// Validate parameter names. We can do this only after parsing the
|
|
|
|
// function, since the function can declare itself strict.
|
|
|
|
const bool allow_duplicate_parameters =
|
|
|
|
is_sloppy(function_scope->language_mode()) && formals.is_simple &&
|
|
|
|
!IsConciseMethod(kind);
|
|
|
|
ValidateFormalParameters(function_scope->language_mode(),
|
|
|
|
allow_duplicate_parameters,
|
|
|
|
CHECK_OK_VALUE(kPreParseSuccess));
|
|
|
|
}
|
|
|
|
|
2016-09-27 09:49:26 +00:00
|
|
|
if (is_strict(function_scope->language_mode())) {
|
2013-10-14 16:46:51 +00:00
|
|
|
int end_pos = scanner()->location().end_pos;
|
2016-11-04 15:04:03 +00:00
|
|
|
CheckStrictOctalLiteral(function_scope->start_position(), end_pos, ok);
|
2011-11-25 09:36:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return kPreParseSuccess;
|
|
|
|
}
|
|
|
|
|
2014-11-14 15:05:05 +00:00
|
|
|
|
2010-11-23 11:46:36 +00:00
|
|
|
// Preparsing checks a JavaScript program and emits preparse-data that helps
|
|
|
|
// a later parsing to be faster.
|
|
|
|
// See preparser-data.h for the data.
|
|
|
|
|
|
|
|
// The PreParser checks that the syntax follows the grammar for JavaScript,
|
|
|
|
// and collects some information about the program along the way.
|
|
|
|
// The grammar check is only performed in order to understand the program
|
|
|
|
// sufficiently to deduce some information about it, that can be used
|
|
|
|
// to speed up later parsing. Finding errors is not the goal of pre-parsing,
|
|
|
|
// rather it is to speed up properly written and correct programs.
|
|
|
|
// That means that contextual checks (like a label being declared where
|
|
|
|
// it is used) are generally omitted.
|
|
|
|
|
2014-02-07 10:47:01 +00:00
|
|
|
PreParser::Expression PreParser::ParseFunctionLiteral(
|
2014-09-10 16:39:42 +00:00
|
|
|
Identifier function_name, Scanner::Location function_name_location,
|
2015-07-09 21:31:11 +00:00
|
|
|
FunctionNameValidity function_name_validity, FunctionKind kind,
|
|
|
|
int function_token_pos, FunctionLiteral::FunctionType function_type,
|
2015-07-15 09:14:49 +00:00
|
|
|
LanguageMode language_mode, bool* ok) {
|
2010-11-23 11:46:36 +00:00
|
|
|
// Function ::
|
|
|
|
// '(' FormalParameterList? ')' '{' FunctionBody '}'
|
2016-11-16 18:51:32 +00:00
|
|
|
const RuntimeCallStats::CounterId counters[2][2] = {
|
2016-11-17 16:51:51 +00:00
|
|
|
{&RuntimeCallStats::PreParseBackgroundNoVariableResolution,
|
2016-12-01 17:09:04 +00:00
|
|
|
&RuntimeCallStats::PreParseNoVariableResolution},
|
|
|
|
{&RuntimeCallStats::PreParseBackgroundWithVariableResolution,
|
|
|
|
&RuntimeCallStats::PreParseWithVariableResolution}};
|
2016-11-15 16:08:16 +00:00
|
|
|
RuntimeCallTimerScope runtime_timer(
|
|
|
|
runtime_call_stats_,
|
2016-11-16 18:51:32 +00:00
|
|
|
counters[track_unresolved_variables_][parsing_on_main_thread_]);
|
2010-11-23 11:46:36 +00:00
|
|
|
|
2016-08-05 14:30:54 +00:00
|
|
|
DeclarationScope* function_scope = NewFunctionScope(kind);
|
2015-07-15 09:14:49 +00:00
|
|
|
function_scope->SetLanguageMode(language_mode);
|
2017-02-20 10:41:29 +00:00
|
|
|
FunctionState function_state(&function_state_, &scope_, function_scope);
|
2016-12-02 12:34:58 +00:00
|
|
|
DuplicateFinder duplicate_finder;
|
2016-02-19 15:58:57 +00:00
|
|
|
ExpressionClassifier formals_classifier(this, &duplicate_finder);
|
2016-11-28 11:40:22 +00:00
|
|
|
GetNextFunctionLiteralId();
|
2015-04-10 12:04:51 +00:00
|
|
|
|
2015-04-21 11:09:53 +00:00
|
|
|
Expect(Token::LPAREN, CHECK_OK);
|
|
|
|
int start_position = scanner()->location().beg_pos;
|
|
|
|
function_scope->set_start_position(start_position);
|
2015-08-26 14:59:05 +00:00
|
|
|
PreParserFormalParameters formals(function_scope);
|
2016-09-01 08:58:15 +00:00
|
|
|
ParseFormalParameterList(&formals, CHECK_OK);
|
2015-04-17 09:51:22 +00:00
|
|
|
Expect(Token::RPAREN, CHECK_OK);
|
2015-04-21 11:09:53 +00:00
|
|
|
int formals_end_position = scanner()->location().end_pos;
|
|
|
|
|
2016-02-19 02:50:58 +00:00
|
|
|
CheckArityRestrictions(formals.arity, kind, formals.has_rest, start_position,
|
2015-06-22 14:15:53 +00:00
|
|
|
formals_end_position, CHECK_OK);
|
2010-11-23 11:46:36 +00:00
|
|
|
|
2013-10-15 08:57:36 +00:00
|
|
|
Expect(Token::LBRACE, CHECK_OK);
|
2017-01-26 10:14:40 +00:00
|
|
|
|
|
|
|
// Parse function body.
|
|
|
|
PreParserStatementList body;
|
|
|
|
int pos = function_token_pos == kNoSourcePosition ? peek_position()
|
|
|
|
: function_token_pos;
|
|
|
|
ParseFunctionBody(body, function_name, pos, formals, kind, function_type,
|
|
|
|
CHECK_OK);
|
2011-05-06 11:41:15 +00:00
|
|
|
|
2015-07-15 09:14:49 +00:00
|
|
|
// Parsing the body may change the language mode in our scope.
|
|
|
|
language_mode = function_scope->language_mode();
|
|
|
|
|
2017-01-16 12:07:57 +00:00
|
|
|
if (is_sloppy(language_mode)) {
|
|
|
|
function_scope->HoistSloppyBlockFunctions(nullptr);
|
|
|
|
}
|
|
|
|
|
2015-02-06 18:04:11 +00:00
|
|
|
// Validate name and parameter names. We can do this only after parsing the
|
|
|
|
// function, since the function can declare itself strict.
|
2015-07-15 09:14:49 +00:00
|
|
|
CheckFunctionName(language_mode, function_name, function_name_validity,
|
2015-07-09 21:31:11 +00:00
|
|
|
function_name_location, CHECK_OK);
|
2015-05-13 11:45:04 +00:00
|
|
|
const bool allow_duplicate_parameters =
|
2015-07-23 11:53:31 +00:00
|
|
|
is_sloppy(language_mode) && formals.is_simple && !IsConciseMethod(kind);
|
2016-09-01 08:58:15 +00:00
|
|
|
ValidateFormalParameters(language_mode, allow_duplicate_parameters, CHECK_OK);
|
2014-02-07 10:47:01 +00:00
|
|
|
|
2016-10-18 08:00:03 +00:00
|
|
|
int end_position = scanner()->location().end_pos;
|
2015-07-15 09:14:49 +00:00
|
|
|
if (is_strict(language_mode)) {
|
2014-12-18 22:01:25 +00:00
|
|
|
CheckStrictOctalLiteral(start_position, end_position, CHECK_OK);
|
2011-05-06 11:41:15 +00:00
|
|
|
}
|
2016-10-18 08:00:03 +00:00
|
|
|
|
|
|
|
if (FLAG_trace_preparse) {
|
|
|
|
PrintF(" [%s]: %i-%i\n",
|
|
|
|
track_unresolved_variables_ ? "Preparse resolution"
|
|
|
|
: "Preparse no-resolution",
|
|
|
|
function_scope->start_position(), function_scope->end_position());
|
|
|
|
}
|
2011-05-06 11:41:15 +00:00
|
|
|
|
2011-05-19 09:01:46 +00:00
|
|
|
return Expression::Default();
|
2010-11-23 11:46:36 +00:00
|
|
|
}
|
|
|
|
|
2016-10-14 13:20:46 +00:00
|
|
|
PreParser::LazyParsingResult PreParser::ParseStatementListAndLogFunction(
|
2016-11-07 13:23:01 +00:00
|
|
|
PreParserFormalParameters* formals, bool has_duplicate_parameters,
|
|
|
|
bool may_abort, bool* ok) {
|
2016-09-05 13:42:01 +00:00
|
|
|
PreParserStatementList body;
|
2016-09-01 10:22:54 +00:00
|
|
|
LazyParsingResult result = ParseStatementList(
|
2016-09-05 13:42:01 +00:00
|
|
|
body, Token::RBRACE, may_abort, CHECK_OK_VALUE(kLazyParsingComplete));
|
2016-09-01 10:22:54 +00:00
|
|
|
if (result == kLazyParsingAborted) return result;
|
2011-11-25 09:36:31 +00:00
|
|
|
|
|
|
|
// Position right after terminal '}'.
|
2014-08-04 11:34:54 +00:00
|
|
|
DCHECK_EQ(Token::RBRACE, scanner()->peek());
|
2013-10-14 16:46:51 +00:00
|
|
|
int body_end = scanner()->peek_location().end_pos;
|
2017-02-08 16:45:24 +00:00
|
|
|
DCHECK_EQ(this->scope()->is_function_scope(), formals->is_simple);
|
2017-02-15 15:12:13 +00:00
|
|
|
log_.LogFunction(body_end, formals->num_parameters(),
|
|
|
|
formals->function_length, has_duplicate_parameters,
|
|
|
|
function_state_->expected_property_count(),
|
|
|
|
GetLastFunctionLiteralId());
|
2016-09-01 10:22:54 +00:00
|
|
|
return kLazyParsingComplete;
|
2011-11-25 09:36:31 +00:00
|
|
|
}
|
|
|
|
|
2016-09-27 09:48:17 +00:00
|
|
|
PreParserExpression PreParser::ExpressionFromIdentifier(
|
2016-10-25 07:59:05 +00:00
|
|
|
PreParserIdentifier name, int start_position, InferName infer) {
|
2016-12-12 14:44:29 +00:00
|
|
|
VariableProxy* proxy = nullptr;
|
2016-09-27 09:48:17 +00:00
|
|
|
if (track_unresolved_variables_) {
|
|
|
|
AstNodeFactory factory(ast_value_factory());
|
|
|
|
// Setting the Zone is necessary because zone_ might be the temp Zone, and
|
|
|
|
// AstValueFactory doesn't know about it.
|
|
|
|
factory.set_zone(zone());
|
|
|
|
DCHECK_NOT_NULL(name.string_);
|
2016-12-12 14:44:29 +00:00
|
|
|
proxy = scope()->NewUnresolved(&factory, name.string_, start_position,
|
|
|
|
NORMAL_VARIABLE);
|
2016-09-27 09:48:17 +00:00
|
|
|
}
|
2016-12-12 14:44:29 +00:00
|
|
|
return PreParserExpression::FromIdentifier(name, proxy, zone());
|
2016-09-27 09:48:17 +00:00
|
|
|
}
|
|
|
|
|
2016-10-04 09:38:23 +00:00
|
|
|
void PreParser::DeclareAndInitializeVariables(
|
|
|
|
PreParserStatement block,
|
|
|
|
const DeclarationDescriptor* declaration_descriptor,
|
|
|
|
const DeclarationParsingResult::Declaration* declaration,
|
|
|
|
ZoneList<const AstRawString*>* names, bool* ok) {
|
2016-12-12 14:44:29 +00:00
|
|
|
if (declaration->pattern.variables_ != nullptr) {
|
2016-10-10 09:22:22 +00:00
|
|
|
DCHECK(FLAG_lazy_inner_functions);
|
2017-02-06 10:40:00 +00:00
|
|
|
DCHECK(track_unresolved_variables_);
|
2016-12-12 14:44:29 +00:00
|
|
|
for (auto variable : *(declaration->pattern.variables_)) {
|
2017-01-10 12:33:01 +00:00
|
|
|
declaration_descriptor->scope->RemoveUnresolved(variable);
|
2017-02-07 20:43:17 +00:00
|
|
|
Variable* var = scope()->DeclareVariableName(
|
|
|
|
variable->raw_name(), declaration_descriptor->mode);
|
|
|
|
if (FLAG_preparser_scope_analysis) {
|
|
|
|
MarkLoopVariableAsAssigned(declaration_descriptor->scope, var);
|
|
|
|
// This is only necessary if there is an initializer, but we don't have
|
|
|
|
// that information here. Consequently, the preparser sometimes says
|
|
|
|
// maybe-assigned where the parser (correctly) says never-assigned.
|
|
|
|
}
|
2017-02-03 07:14:48 +00:00
|
|
|
if (names) {
|
|
|
|
names->Add(variable->raw_name(), zone());
|
|
|
|
}
|
2016-12-06 13:23:29 +00:00
|
|
|
}
|
2016-10-04 09:38:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-19 09:01:46 +00:00
|
|
|
#undef CHECK_OK
|
2016-07-19 08:03:43 +00:00
|
|
|
#undef CHECK_OK_CUSTOM
|
2011-05-19 09:01:46 +00:00
|
|
|
|
2010-11-23 11:46:36 +00:00
|
|
|
|
2015-09-30 13:46:56 +00:00
|
|
|
} // namespace internal
|
|
|
|
} // namespace v8
|