blob: af53b8dc87c8ecde0a746505907bdddfe337d21f [file] [log] [blame]
// Copyright 2012 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_PARSING_PREPARSER_H_
#define V8_PARSING_PREPARSER_H_
#include "src/ast/ast-value-factory.h"
#include "src/ast/ast.h"
#include "src/ast/scopes.h"
#include "src/parsing/parse-info.h"
#include "src/parsing/parser-base.h"
#include "src/parsing/pending-compilation-error-handler.h"
#include "src/parsing/preparser-logger.h"
namespace v8 {
namespace internal {
// Whereas the Parser generates AST during the recursive descent,
// the PreParser doesn't create a tree. Instead, it passes around minimal
// data objects (PreParserExpression, PreParserIdentifier etc.) which contain
// just enough data for the upper layer functions. PreParserFactory is
// responsible for creating these dummy objects. It provides a similar kind of
// interface as AstNodeFactory, so ParserBase doesn't need to care which one is
// used.
class PreparseDataBuilder;
class PreParserIdentifier {
public:
PreParserIdentifier() : type_(kUnknownIdentifier) {}
static PreParserIdentifier Default() {
return PreParserIdentifier(kUnknownIdentifier);
}
static PreParserIdentifier Null() {
return PreParserIdentifier(kNullIdentifier);
}
static PreParserIdentifier Eval() {
return PreParserIdentifier(kEvalIdentifier);
}
static PreParserIdentifier Arguments() {
return PreParserIdentifier(kArgumentsIdentifier);
}
static PreParserIdentifier Constructor() {
return PreParserIdentifier(kConstructorIdentifier);
}
static PreParserIdentifier Await() {
return PreParserIdentifier(kAwaitIdentifier);
}
static PreParserIdentifier Async() {
return PreParserIdentifier(kAsyncIdentifier);
}
static PreParserIdentifier Name() {
return PreParserIdentifier(kNameIdentifier);
}
static PreParserIdentifier PrivateName() {
return PreParserIdentifier(kPrivateNameIdentifier);
}
bool IsNull() const { return type_ == kNullIdentifier; }
bool IsEval() const { return type_ == kEvalIdentifier; }
bool IsAsync() const { return type_ == kAsyncIdentifier; }
bool IsArguments() const { return type_ == kArgumentsIdentifier; }
bool IsEvalOrArguments() const {
STATIC_ASSERT(kEvalIdentifier + 1 == kArgumentsIdentifier);
return base::IsInRange(type_, kEvalIdentifier, kArgumentsIdentifier);
}
bool IsConstructor() const { return type_ == kConstructorIdentifier; }
bool IsAwait() const { return type_ == kAwaitIdentifier; }
bool IsName() const { return type_ == kNameIdentifier; }
bool IsPrivateName() const { return type_ == kPrivateNameIdentifier; }
private:
enum Type : uint8_t {
kNullIdentifier,
kUnknownIdentifier,
kEvalIdentifier,
kArgumentsIdentifier,
kConstructorIdentifier,
kAwaitIdentifier,
kAsyncIdentifier,
kNameIdentifier,
kPrivateNameIdentifier
};
explicit PreParserIdentifier(Type type) : string_(nullptr), type_(type) {}
const AstRawString* string_;
Type type_;
friend class PreParserExpression;
friend class PreParser;
friend class PreParserFactory;
};
class PreParserExpression {
public:
PreParserExpression() : code_(TypeField::encode(kNull)) {}
static PreParserExpression Null() { return PreParserExpression(); }
static PreParserExpression Failure() {
return PreParserExpression(TypeField::encode(kFailure));
}
static PreParserExpression Default() {
return PreParserExpression(TypeField::encode(kExpression));
}
static PreParserExpression Spread(const PreParserExpression& expression) {
return PreParserExpression(TypeField::encode(kSpreadExpression));
}
static PreParserExpression FromIdentifier(const PreParserIdentifier& id) {
return PreParserExpression(TypeField::encode(kIdentifierExpression) |
IdentifierTypeField::encode(id.type_));
}
static PreParserExpression BinaryOperation(const PreParserExpression& left,
Token::Value op,
const PreParserExpression& right,
Zone* zone) {
return PreParserExpression(TypeField::encode(kExpression));
}
static PreParserExpression Assignment() {
return PreParserExpression(TypeField::encode(kExpression) |
ExpressionTypeField::encode(kAssignment));
}
static PreParserExpression NewTargetExpression() {
return PreParserExpression::Default();
}
static PreParserExpression ObjectLiteral() {
return PreParserExpression(TypeField::encode(kObjectLiteralExpression));
}
static PreParserExpression ArrayLiteral() {
return PreParserExpression(TypeField::encode(kArrayLiteralExpression));
}
static PreParserExpression StringLiteral() {
return PreParserExpression(TypeField::encode(kStringLiteralExpression));
}
static PreParserExpression This() {
return PreParserExpression(TypeField::encode(kExpression) |
ExpressionTypeField::encode(kThisExpression));
}
static PreParserExpression ThisPrivateReference() {
return PreParserExpression(
TypeField::encode(kExpression) |
ExpressionTypeField::encode(kThisPrivateReferenceExpression));
}
static PreParserExpression ThisProperty() {
return PreParserExpression(
TypeField::encode(kExpression) |
ExpressionTypeField::encode(kThisPropertyExpression));
}
static PreParserExpression Property() {
return PreParserExpression(
TypeField::encode(kExpression) |
ExpressionTypeField::encode(kPropertyExpression));
}
static PreParserExpression PrivateReference() {
return PreParserExpression(
TypeField::encode(kExpression) |
ExpressionTypeField::encode(kPrivateReferenceExpression));
}
static PreParserExpression Call() {
return PreParserExpression(TypeField::encode(kExpression) |
ExpressionTypeField::encode(kCallExpression));
}
static PreParserExpression CallEval() {
return PreParserExpression(
TypeField::encode(kExpression) |
ExpressionTypeField::encode(kCallEvalExpression));
}
static PreParserExpression CallTaggedTemplate() {
return PreParserExpression(
TypeField::encode(kExpression) |
ExpressionTypeField::encode(kCallTaggedTemplateExpression));
}
bool is_tagged_template() const {
DCHECK(IsCall());
return ExpressionTypeField::decode(code_) == kCallTaggedTemplateExpression;
}
static PreParserExpression SuperCallReference() {
return PreParserExpression(
TypeField::encode(kExpression) |
ExpressionTypeField::encode(kSuperCallReference));
}
bool IsNull() const { return TypeField::decode(code_) == kNull; }
bool IsFailureExpression() const {
return TypeField::decode(code_) == kFailure;
}
bool IsIdentifier() const {
return TypeField::decode(code_) == kIdentifierExpression;
}
PreParserIdentifier AsIdentifier() const {
DCHECK(IsIdentifier());
return PreParserIdentifier(IdentifierTypeField::decode(code_));
}
bool IsAssignment() const {
return TypeField::decode(code_) == kExpression &&
ExpressionTypeField::decode(code_) == kAssignment;
}
bool IsObjectLiteral() const {
return TypeField::decode(code_) == kObjectLiteralExpression;
}
bool IsArrayLiteral() const {
return TypeField::decode(code_) == kArrayLiteralExpression;
}
bool IsPattern() const {
STATIC_ASSERT(kObjectLiteralExpression + 1 == kArrayLiteralExpression);
return base::IsInRange(TypeField::decode(code_), kObjectLiteralExpression,
kArrayLiteralExpression);
}
bool IsStringLiteral() const {
return TypeField::decode(code_) == kStringLiteralExpression;
}
bool IsThis() const {
return TypeField::decode(code_) == kExpression &&
ExpressionTypeField::decode(code_) == kThisExpression;
}
bool IsThisProperty() const {
return TypeField::decode(code_) == kExpression &&
(ExpressionTypeField::decode(code_) == kThisPropertyExpression ||
ExpressionTypeField::decode(code_) ==
kThisPrivateReferenceExpression);
}
bool IsProperty() const {
return TypeField::decode(code_) == kExpression &&
(ExpressionTypeField::decode(code_) == kPropertyExpression ||
ExpressionTypeField::decode(code_) == kThisPropertyExpression ||
ExpressionTypeField::decode(code_) == kPrivateReferenceExpression ||
ExpressionTypeField::decode(code_) ==
kThisPrivateReferenceExpression);
}
bool IsPrivateReference() const {
return TypeField::decode(code_) == kExpression &&
(ExpressionTypeField::decode(code_) == kPrivateReferenceExpression ||
ExpressionTypeField::decode(code_) ==
kThisPrivateReferenceExpression);
}
bool IsCall() const {
return TypeField::decode(code_) == kExpression &&
(ExpressionTypeField::decode(code_) == kCallExpression ||
ExpressionTypeField::decode(code_) == kCallEvalExpression ||
ExpressionTypeField::decode(code_) ==
kCallTaggedTemplateExpression);
}
PreParserExpression* AsCall() {
if (IsCall()) return this;
return nullptr;
}
bool IsSuperCallReference() const {
return TypeField::decode(code_) == kExpression &&
ExpressionTypeField::decode(code_) == kSuperCallReference;
}
bool IsValidReferenceExpression() const {
return IsIdentifier() || IsProperty();
}
// At the moment PreParser doesn't track these expression types.
bool IsFunctionLiteral() const { return false; }
bool IsCallNew() const { return false; }
bool IsSpread() const {
return TypeField::decode(code_) == kSpreadExpression;
}
bool is_parenthesized() const { return IsParenthesizedField::decode(code_); }
void mark_parenthesized() {
code_ = IsParenthesizedField::update(code_, true);
}
void clear_parenthesized() {
code_ = IsParenthesizedField::update(code_, false);
}
PreParserExpression AsFunctionLiteral() { return *this; }
// Dummy implementation for making expression->somefunc() work in both Parser
// and PreParser.
PreParserExpression* operator->() { return this; }
// More dummy implementations of things PreParser doesn't need to track:
void SetShouldEagerCompile() {}
void mark_as_oneshot_iife() {}
int position() const { return kNoSourcePosition; }
void set_function_token_position(int position) {}
void set_scope(Scope* scope) {}
void set_suspend_count(int suspend_count) {}
private:
enum Type {
kNull,
kFailure,
kExpression,
kIdentifierExpression,
kStringLiteralExpression,
kSpreadExpression,
kObjectLiteralExpression,
kArrayLiteralExpression
};
enum ExpressionType {
kThisExpression,
kThisPropertyExpression,
kThisPrivateReferenceExpression,
kPropertyExpression,
kPrivateReferenceExpression,
kCallExpression,
kCallEvalExpression,
kCallTaggedTemplateExpression,
kSuperCallReference,
kAssignment
};
explicit PreParserExpression(uint32_t expression_code)
: code_(expression_code) {}
// The first three bits are for the Type.
using TypeField = base::BitField<Type, 0, 3>;
// The high order bit applies only to nodes which would inherit from the
// Expression ASTNode --- This is by necessity, due to the fact that
// Expression nodes may be represented as multiple Types, not exclusively
// through kExpression.
// TODO(caitp, adamk): clean up PreParserExpression bitfields.
using IsParenthesizedField = TypeField::Next<bool, 1>;
// The rest of the bits are interpreted depending on the value
// of the Type field, so they can share the storage.
using ExpressionTypeField = IsParenthesizedField::Next<ExpressionType, 4>;
using IdentifierTypeField =
IsParenthesizedField::Next<PreParserIdentifier::Type, 8>;
using HasCoverInitializedNameField = IsParenthesizedField::Next<bool, 1>;
uint32_t code_;
friend class PreParser;
friend class PreParserFactory;
friend class PreParserExpressionList;
};
class PreParserStatement;
class PreParserStatementList {
public:
PreParserStatementList() : PreParserStatementList(false) {}
PreParserStatementList* operator->() { return this; }
void Add(const PreParserStatement& element, Zone* zone) {}
static PreParserStatementList Null() { return PreParserStatementList(true); }
bool IsNull() const { return is_null_; }
private:
explicit PreParserStatementList(bool is_null) : is_null_(is_null) {}
bool is_null_;
};
class PreParserScopedStatementList {
public:
explicit PreParserScopedStatementList(std::vector<void*>* buffer) {}
void Rewind() {}
void MergeInto(const PreParserScopedStatementList* other) {}
void Add(const PreParserStatement& element) {}
int length() { return 0; }
};
// The pre-parser doesn't need to build lists of expressions, identifiers, or
// the like. If the PreParser is used in variable tracking mode, it needs to
// build lists of variables though.
class PreParserExpressionList {
public:
explicit PreParserExpressionList(std::vector<void*>* buffer) : length_(0) {}
int length() const { return length_; }
void Add(const PreParserExpression& expression) {
++length_;
}
private:
int length_;
friend class PreParser;
friend class PreParserFactory;
};
class PreParserStatement {
public:
static PreParserStatement Default() {
return PreParserStatement(kUnknownStatement);
}
static PreParserStatement Iteration() {
return PreParserStatement(kIterationStatement);
}
static PreParserStatement Null() {
return PreParserStatement(kNullStatement);
}
static PreParserStatement Empty() {
return PreParserStatement(kEmptyStatement);
}
static PreParserStatement Jump() {
return PreParserStatement(kJumpStatement);
}
void InitializeStatements(const PreParserScopedStatementList& statements,
Zone* zone) {}
// Creates expression statement from expression.
// Preserves being an unparenthesized string literal, possibly
// "use strict".
static PreParserStatement ExpressionStatement(
const PreParserExpression& expression) {
if (expression.IsStringLiteral()) {
return PreParserStatement(kStringLiteralExpressionStatement);
}
return Default();
}
bool IsStringLiteral() { return code_ == kStringLiteralExpressionStatement; }
bool IsJumpStatement() {
return code_ == kJumpStatement;
}
bool IsNull() { return code_ == kNullStatement; }
bool IsIterationStatement() { return code_ == kIterationStatement; }
bool IsEmptyStatement() {
DCHECK(!IsNull());
return code_ == kEmptyStatement;
}
// Dummy implementation for making statement->somefunc() work in both Parser
// and PreParser.
PreParserStatement* operator->() { return this; }
PreParserStatementList statements() { return PreParserStatementList(); }
PreParserStatementList cases() { return PreParserStatementList(); }
void set_scope(Scope* scope) {}
void Initialize(const PreParserExpression& cond, PreParserStatement body,
const SourceRange& body_range = {}) {}
void Initialize(PreParserStatement init, const PreParserExpression& cond,
PreParserStatement next, PreParserStatement body,
const SourceRange& body_range = {}) {}
void Initialize(PreParserExpression each, const PreParserExpression& subject,
PreParserStatement body, const SourceRange& body_range = {}) {
}
protected:
enum Type {
kNullStatement,
kEmptyStatement,
kUnknownStatement,
kJumpStatement,
kIterationStatement,
kStringLiteralExpressionStatement,
};
explicit PreParserStatement(Type code) : code_(code) {}
private:
Type code_;
};
// A PreParserBlock extends statement with a place to store the scope.
// The scope is dropped as the block is returned as a statement.
class PreParserBlock : public PreParserStatement {
public:
void set_scope(Scope* scope) { scope_ = scope; }
Scope* scope() const { return scope_; }
static PreParserBlock Default() {
return PreParserBlock(PreParserStatement::kUnknownStatement);
}
static PreParserBlock Null() {
return PreParserBlock(PreParserStatement::kNullStatement);
}
// Dummy implementation for making block->somefunc() work in both Parser and
// PreParser.
PreParserBlock* operator->() { return this; }
private:
explicit PreParserBlock(PreParserStatement::Type type)
: PreParserStatement(type), scope_(nullptr) {}
Scope* scope_;
};
class PreParserFactory {
public:
explicit PreParserFactory(AstValueFactory* ast_value_factory, Zone* zone)
: ast_node_factory_(ast_value_factory, zone), zone_(zone) {}
AstNodeFactory* ast_node_factory() { return &ast_node_factory_; }
PreParserExpression NewStringLiteral(const PreParserIdentifier& identifier,
int pos) {
return PreParserExpression::Default();
}
PreParserExpression NewNumberLiteral(double number,
int pos) {
return PreParserExpression::Default();
}
PreParserExpression NewUndefinedLiteral(int pos) {
return PreParserExpression::Default();
}
PreParserExpression NewTheHoleLiteral() {
return PreParserExpression::Default();
}
PreParserExpression NewRegExpLiteral(const PreParserIdentifier& js_pattern,
int js_flags, int pos) {
return PreParserExpression::Default();
}
PreParserExpression NewArrayLiteral(const PreParserExpressionList& values,
int first_spread_index, int pos) {
return PreParserExpression::ArrayLiteral();
}
PreParserExpression NewClassLiteralProperty(const PreParserExpression& key,
const PreParserExpression& value,
ClassLiteralProperty::Kind kind,
bool is_static,
bool is_computed_name,
bool is_private) {
return PreParserExpression::Default();
}
PreParserExpression NewObjectLiteralProperty(const PreParserExpression& key,
const PreParserExpression& value,
ObjectLiteralProperty::Kind kind,
bool is_computed_name) {
return PreParserExpression::Default();
}
PreParserExpression NewObjectLiteralProperty(const PreParserExpression& key,
const PreParserExpression& value,
bool is_computed_name) {
return PreParserExpression::Default();
}
PreParserExpression NewObjectLiteral(
const PreParserExpressionList& properties, int boilerplate_properties,
int pos, bool has_rest_property) {
return PreParserExpression::ObjectLiteral();
}
PreParserExpression NewVariableProxy(void* variable) {
return PreParserExpression::Default();
}
PreParserExpression NewOptionalChain(const PreParserExpression& expr) {
// Needed to track `delete a?.#b` early errors
if (expr.IsPrivateReference()) {
return PreParserExpression::PrivateReference();
}
return PreParserExpression::Default();
}
PreParserExpression NewProperty(const PreParserExpression& obj,
const PreParserExpression& key, int pos,
bool optional_chain = false) {
if (key.IsIdentifier() && key.AsIdentifier().IsPrivateName()) {
if (obj.IsThis()) {
return PreParserExpression::ThisPrivateReference();
}
return PreParserExpression::PrivateReference();
}
if (obj.IsThis()) {
return PreParserExpression::ThisProperty();
}
return PreParserExpression::Property();
}
PreParserExpression NewUnaryOperation(Token::Value op,
const PreParserExpression& expression,
int pos) {
return PreParserExpression::Default();
}
PreParserExpression NewBinaryOperation(Token::Value op,
const PreParserExpression& left,
const PreParserExpression& right,
int pos) {
return PreParserExpression::BinaryOperation(left, op, right, zone_);
}
PreParserExpression NewCompareOperation(Token::Value op,
const PreParserExpression& left,
const PreParserExpression& right,
int pos) {
return PreParserExpression::Default();
}
PreParserExpression NewAssignment(Token::Value op,
const PreParserExpression& left,
const PreParserExpression& right, int pos) {
// Identifiers need to be tracked since this might be a parameter with a
// default value inside an arrow function parameter list.
return PreParserExpression::Assignment();
}
PreParserExpression NewYield(const PreParserExpression& expression, int pos,
Suspend::OnAbruptResume on_abrupt_resume) {
return PreParserExpression::Default();
}
PreParserExpression NewAwait(const PreParserExpression& expression, int pos) {
return PreParserExpression::Default();
}
PreParserExpression NewYieldStar(const PreParserExpression& iterable,
int pos) {
return PreParserExpression::Default();
}
PreParserExpression NewConditional(const PreParserExpression& condition,
const PreParserExpression& then_expression,
const PreParserExpression& else_expression,
int pos) {
return PreParserExpression::Default();
}
PreParserExpression NewCountOperation(Token::Value op, bool is_prefix,
const PreParserExpression& expression,
int pos) {
return PreParserExpression::Default();
}
PreParserExpression NewCall(PreParserExpression expression,
const PreParserExpressionList& arguments, int pos,
Call::PossiblyEval possibly_eval = Call::NOT_EVAL,
bool optional_chain = false) {
if (possibly_eval == Call::IS_POSSIBLY_EVAL) {
DCHECK(expression.IsIdentifier() && expression.AsIdentifier().IsEval());
DCHECK(!optional_chain);
return PreParserExpression::CallEval();
}
return PreParserExpression::Call();
}
PreParserExpression NewTaggedTemplate(
PreParserExpression expression, const PreParserExpressionList& arguments,
int pos) {
return PreParserExpression::CallTaggedTemplate();
}
PreParserExpression NewCallNew(const PreParserExpression& expression,
const PreParserExpressionList& arguments,
int pos) {
return PreParserExpression::Default();
}
PreParserStatement NewReturnStatement(
const PreParserExpression& expression, int pos,
int continuation_pos = kNoSourcePosition) {
return PreParserStatement::Jump();
}
PreParserStatement NewAsyncReturnStatement(
const PreParserExpression& expression, int pos,
int continuation_pos = kNoSourcePosition) {
return PreParserStatement::Jump();
}
PreParserExpression NewFunctionLiteral(
const PreParserIdentifier& name, Scope* scope,
const PreParserScopedStatementList& body, int expected_property_count,
int parameter_count, int function_length,
FunctionLiteral::ParameterFlag has_duplicate_parameters,
FunctionSyntaxKind function_syntax_kind,
FunctionLiteral::EagerCompileHint eager_compile_hint, int position,
bool has_braces, int function_literal_id,
ProducedPreparseData* produced_preparse_data = nullptr) {
DCHECK_NULL(produced_preparse_data);
return PreParserExpression::Default();
}
PreParserExpression NewSpread(const PreParserExpression& expression, int pos,
int expr_pos) {
return PreParserExpression::Spread(expression);
}
PreParserExpression NewEmptyParentheses(int pos) {
PreParserExpression result = PreParserExpression::Default();
result.mark_parenthesized();
return result;
}
PreParserStatement EmptyStatement() { return PreParserStatement::Default(); }
PreParserBlock NewBlock(int capacity, bool ignore_completion_value) {
return PreParserBlock::Default();
}
PreParserBlock NewBlock(bool ignore_completion_value, bool is_breakable) {
return PreParserBlock::Default();
}
PreParserBlock NewBlock(bool ignore_completion_value,
const PreParserScopedStatementList& list) {
return PreParserBlock::Default();
}
PreParserStatement NewDebuggerStatement(int pos) {
return PreParserStatement::Default();
}
PreParserStatement NewExpressionStatement(const PreParserExpression& expr,
int pos) {
return PreParserStatement::ExpressionStatement(expr);
}
PreParserStatement NewIfStatement(const PreParserExpression& condition,
PreParserStatement then_statement,
PreParserStatement else_statement, int pos,
SourceRange then_range = {},
SourceRange else_range = {}) {
// This must return a jump statement iff both clauses are jump statements.
return else_statement.IsJumpStatement() ? then_statement : else_statement;
}
PreParserStatement NewBreakStatement(
PreParserStatement target, int pos,
int continuation_pos = kNoSourcePosition) {
return PreParserStatement::Jump();
}
PreParserStatement NewContinueStatement(
PreParserStatement target, int pos,
int continuation_pos = kNoSourcePosition) {
return PreParserStatement::Jump();
}
PreParserStatement NewWithStatement(Scope* scope,
const PreParserExpression& expression,
PreParserStatement statement, int pos) {
return PreParserStatement::Default();
}
PreParserStatement NewDoWhileStatement(int pos) {
return PreParserStatement::Iteration();
}
PreParserStatement NewWhileStatement(int pos) {
return PreParserStatement::Iteration();
}
PreParserStatement NewSwitchStatement(const PreParserExpression& tag,
int pos) {
return PreParserStatement::Default();
}
PreParserStatement NewCaseClause(
const PreParserExpression& label,
const PreParserScopedStatementList& statements) {
return PreParserStatement::Default();
}
PreParserStatement NewForStatement(int pos) {
return PreParserStatement::Iteration();
}
PreParserStatement NewForEachStatement(ForEachStatement::VisitMode visit_mode,
int pos) {
return PreParserStatement::Iteration();
}
PreParserStatement NewForOfStatement(int pos, IteratorType type) {
return PreParserStatement::Iteration();
}
PreParserExpression NewCallRuntime(
Runtime::FunctionId id, ZoneChunkList<PreParserExpression>* arguments,
int pos) {
return PreParserExpression::Default();
}
PreParserExpression NewImportCallExpression(const PreParserExpression& args,
int pos) {
return PreParserExpression::Default();
}
private:
// For creating VariableProxy objects to track unresolved variables.
AstNodeFactory ast_node_factory_;
Zone* zone_;
};
class PreParser;
class PreParserFormalParameters : public FormalParametersBase {
public:
explicit PreParserFormalParameters(DeclarationScope* scope)
: FormalParametersBase(scope) {}
void set_has_duplicate() { has_duplicate_ = true; }
bool has_duplicate() { return has_duplicate_; }
void ValidateDuplicate(PreParser* preparser) const;
void set_strict_parameter_error(const Scanner::Location& loc,
MessageTemplate message) {
strict_parameter_error_ = loc.IsValid();
}
void ValidateStrictMode(PreParser* preparser) const;
private:
bool has_duplicate_ = false;
bool strict_parameter_error_ = false;
};
class PreParserFuncNameInferrer {
public:
explicit PreParserFuncNameInferrer(AstValueFactory* avf) {}
void RemoveAsyncKeywordFromEnd() const {}
void Infer() const {}
void RemoveLastFunction() const {}
class State {
public:
explicit State(PreParserFuncNameInferrer* fni) {}
private:
DISALLOW_COPY_AND_ASSIGN(State);
};
private:
DISALLOW_COPY_AND_ASSIGN(PreParserFuncNameInferrer);
};
class PreParserSourceRange {
public:
PreParserSourceRange() = default;
PreParserSourceRange(int start, int end) {}
static PreParserSourceRange Empty() { return PreParserSourceRange(); }
static PreParserSourceRange OpenEnded(int32_t start) { return Empty(); }
static const PreParserSourceRange& ContinuationOf(
const PreParserSourceRange& that, int end) {
return that;
}
};
class PreParserSourceRangeScope {
public:
PreParserSourceRangeScope(Scanner* scanner, PreParserSourceRange* range) {}
const PreParserSourceRange& Finalize() const { return range_; }
private:
PreParserSourceRange range_;
DISALLOW_IMPLICIT_CONSTRUCTORS(PreParserSourceRangeScope);
};
class PreParserPropertyList {};
template <>
struct ParserTypes<PreParser> {
using Base = ParserBase<PreParser>;
using Impl = PreParser;
// Return types for traversing functions.
using ClassLiteralProperty = PreParserExpression;
using Expression = PreParserExpression;
using FunctionLiteral = PreParserExpression;
using ObjectLiteralProperty = PreParserExpression;
using Suspend = PreParserExpression;
using ExpressionList = PreParserExpressionList;
using ObjectPropertyList = PreParserExpressionList;
using FormalParameters = PreParserFormalParameters;
using Identifier = PreParserIdentifier;
using ClassPropertyList = PreParserPropertyList;
using StatementList = PreParserScopedStatementList;
using Block = PreParserBlock;
using BreakableStatement = PreParserStatement;
using ForStatement = PreParserStatement;
using IterationStatement = PreParserStatement;
using Statement = PreParserStatement;
// For constructing objects returned by the traversing functions.
using Factory = PreParserFactory;
// Other implementation-specific tasks.
using FuncNameInferrer = PreParserFuncNameInferrer;
using SourceRange = PreParserSourceRange;
using SourceRangeScope = PreParserSourceRangeScope;
};
// Preparsing checks a JavaScript program and emits preparse-data that helps
// a later parsing to be faster.
// See preparse-data-format.h for the data format.
// 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.
class PreParser : public ParserBase<PreParser> {
friend class ParserBase<PreParser>;
public:
using Identifier = PreParserIdentifier;
using Expression = PreParserExpression;
using Statement = PreParserStatement;
enum PreParseResult {
kPreParseStackOverflow,
kPreParseNotIdentifiableError,
kPreParseSuccess
};
PreParser(Zone* zone, Scanner* scanner, uintptr_t stack_limit,
AstValueFactory* ast_value_factory,
PendingCompilationErrorHandler* pending_error_handler,
RuntimeCallStats* runtime_call_stats, Logger* logger,
UnoptimizedCompileFlags flags, bool parsing_on_main_thread = true)
: ParserBase<PreParser>(zone, scanner, stack_limit, nullptr,
ast_value_factory, pending_error_handler,
runtime_call_stats, logger, flags,
parsing_on_main_thread),
use_counts_(nullptr),
preparse_data_builder_(nullptr),
preparse_data_builder_buffer_() {
preparse_data_builder_buffer_.reserve(16);
}
static bool IsPreParser() { return true; }
PreParserLogger* logger() { return &log_; }
// Pre-parse the program from the character stream; returns true on
// success (even if parsing failed, the pre-parse data successfully
// captured the syntax error), and false if a stack-overflow happened
// during parsing.
V8_EXPORT_PRIVATE PreParseResult PreParseProgram();
// Parses a single function literal, from the opening parentheses before
// parameters to the closing brace after the body.
// Returns a FunctionEntry describing the body of the function in enough
// detail that it can be lazily compiled.
// The scanner is expected to have matched the "function" or "function*"
// keyword and parameters, and have consumed the initial '{'.
// At return, unless an error occurred, the scanner is positioned before the
// the final '}'.
PreParseResult PreParseFunction(
const AstRawString* function_name, FunctionKind kind,
FunctionSyntaxKind function_syntax_kind, DeclarationScope* function_scope,
int* use_counts, ProducedPreparseData** produced_preparser_scope_data);
PreparseDataBuilder* preparse_data_builder() const {
return preparse_data_builder_;
}
void set_preparse_data_builder(PreparseDataBuilder* preparse_data_builder) {
preparse_data_builder_ = preparse_data_builder;
}
std::vector<void*>* preparse_data_builder_buffer() {
return &preparse_data_builder_buffer_;
}
private:
friend class i::ExpressionScope<ParserTypes<PreParser>>;
friend class i::VariableDeclarationParsingScope<ParserTypes<PreParser>>;
friend class i::ParameterDeclarationParsingScope<ParserTypes<PreParser>>;
friend class i::ArrowHeadParsingScope<ParserTypes<PreParser>>;
friend class PreParserFormalParameters;
// These types form an algebra over syntactic categories that is just
// rich enough to let us recognize and propagate the constructs that
// are either being counted in the preparser data, or is important
// to throw the correct syntax error exceptions.
// All ParseXXX functions take as the last argument an *ok parameter
// which is set to false if parsing failed; it is unchanged otherwise.
// By making the 'exception handling' explicit, we are forced to check
// for failure at the call sites.
// Indicates that we won't switch from the preparser to the preparser; we'll
// just stay where we are.
bool AllowsLazyParsingWithoutUnresolvedVariables() const { return false; }
bool parse_lazily() const { return false; }
PendingCompilationErrorHandler* pending_error_handler() {
return pending_error_handler_;
}
V8_INLINE bool SkipFunction(const AstRawString* name, FunctionKind kind,
FunctionSyntaxKind function_syntax_kind,
DeclarationScope* function_scope,
int* num_parameters, int* function_length,
ProducedPreparseData** produced_preparse_data) {
UNREACHABLE();
}
Expression ParseFunctionLiteral(
Identifier name, Scanner::Location function_name_location,
FunctionNameValidity function_name_validity, FunctionKind kind,
int function_token_pos, FunctionSyntaxKind function_syntax_kind,
LanguageMode language_mode,
ZonePtrList<const AstRawString>* arguments_for_wrapped_function);
PreParserExpression InitializeObjectLiteral(PreParserExpression literal) {
return literal;
}
bool HasCheckedSyntax() { return false; }
void ParseStatementListAndLogFunction(PreParserFormalParameters* formals);
struct TemplateLiteralState {};
V8_INLINE TemplateLiteralState OpenTemplateLiteral(int pos) {
return TemplateLiteralState();
}
V8_INLINE void AddTemplateExpression(TemplateLiteralState* state,
const PreParserExpression& expression) {}
V8_INLINE void AddTemplateSpan(TemplateLiteralState* state, bool should_cook,
bool tail) {}
V8_INLINE PreParserExpression CloseTemplateLiteral(
TemplateLiteralState* state, int start, const PreParserExpression& tag) {
return PreParserExpression::Default();
}
V8_INLINE bool IsPrivateReference(const PreParserExpression& expression) {
return expression.IsPrivateReference();
}
V8_INLINE void SetLanguageMode(Scope* scope, LanguageMode mode) {
scope->SetLanguageMode(mode);
}
V8_INLINE void SetAsmModule() {}
V8_INLINE PreParserExpression SpreadCall(const PreParserExpression& function,
const PreParserExpressionList& args,
int pos,
Call::PossiblyEval possibly_eval,
bool optional_chain);
V8_INLINE PreParserExpression
SpreadCallNew(const PreParserExpression& function,
const PreParserExpressionList& args, int pos);
V8_INLINE void PrepareGeneratorVariables() {}
V8_INLINE void RewriteAsyncFunctionBody(
const PreParserScopedStatementList* body, PreParserStatement block,
const PreParserExpression& return_value) {}
V8_INLINE PreParserExpression
RewriteReturn(const PreParserExpression& return_value, int pos) {
return return_value;
}
V8_INLINE PreParserStatement
RewriteSwitchStatement(PreParserStatement switch_statement, Scope* scope) {
return PreParserStatement::Default();
}
Variable* DeclareVariable(const AstRawString* name, VariableKind kind,
VariableMode mode, InitializationFlag init,
Scope* scope, bool* was_added, int position) {
return DeclareVariableName(name, mode, scope, was_added, position, kind);
}
void DeclareAndBindVariable(const VariableProxy* proxy, VariableKind kind,
VariableMode mode, Scope* scope, bool* was_added,
int initializer_position) {
Variable* var = DeclareVariableName(proxy->raw_name(), mode, scope,
was_added, proxy->position(), kind);
var->set_initializer_position(initializer_position);
// Don't bother actually binding the proxy.
}
Variable* DeclarePrivateVariableName(const AstRawString* name,
ClassScope* scope, VariableMode mode,
IsStaticFlag is_static_flag,
bool* was_added) {
DCHECK(IsConstVariableMode(mode));
return scope->DeclarePrivateName(name, mode, is_static_flag, was_added);
}
Variable* DeclareVariableName(const AstRawString* name, VariableMode mode,
Scope* scope, bool* was_added,
int position = kNoSourcePosition,
VariableKind kind = NORMAL_VARIABLE) {
DCHECK(!IsPrivateMethodOrAccessorVariableMode(mode));
Variable* var = scope->DeclareVariableName(name, mode, was_added, kind);
if (var == nullptr) {
ReportUnidentifiableError();
if (!IsLexicalVariableMode(mode)) scope = scope->GetDeclarationScope();
var = scope->LookupLocal(name);
} else if (var->scope() != scope) {
DCHECK_NE(kNoSourcePosition, position);
DCHECK_EQ(VariableMode::kVar, mode);
Declaration* nested_declaration =
factory()->ast_node_factory()->NewNestedVariableDeclaration(scope,
position);
nested_declaration->set_var(var);
var->scope()->declarations()->Add(nested_declaration);
}
return var;
}
V8_INLINE PreParserBlock RewriteCatchPattern(CatchInfo* catch_info) {
return PreParserBlock::Default();
}
V8_INLINE void ReportVarRedeclarationIn(const AstRawString* name,
Scope* scope) {
ReportUnidentifiableError();
}
V8_INLINE PreParserStatement RewriteTryStatement(
PreParserStatement try_block, PreParserStatement catch_block,
const SourceRange& catch_range, PreParserStatement finally_block,
const SourceRange& finally_range, const CatchInfo& catch_info, int pos) {
return PreParserStatement::Default();
}
V8_INLINE void ReportUnexpectedTokenAt(
Scanner::Location location, Token::Value token,
MessageTemplate message = MessageTemplate::kUnexpectedToken) {
ReportUnidentifiableError();
}
V8_INLINE void ParseAndRewriteGeneratorFunctionBody(
int pos, FunctionKind kind, PreParserScopedStatementList* body) {
ParseStatementList(body, Token::RBRACE);
}
V8_INLINE void ParseAndRewriteAsyncGeneratorFunctionBody(
int pos, FunctionKind kind, PreParserScopedStatementList* body) {
ParseStatementList(body, Token::RBRACE);
}
V8_INLINE void DeclareFunctionNameVar(const AstRawString* function_name,
FunctionSyntaxKind function_syntax_kind,
DeclarationScope* function_scope) {
if (function_syntax_kind == FunctionSyntaxKind::kNamedExpression &&
function_scope->LookupLocal(function_name) == nullptr) {
DCHECK_EQ(function_scope, scope());
function_scope->DeclareFunctionVar(function_name);
}
}
V8_INLINE void DeclareFunctionNameVar(
const PreParserIdentifier& function_name,
FunctionSyntaxKind function_syntax_kind,
DeclarationScope* function_scope) {
DeclareFunctionNameVar(function_name.string_, function_syntax_kind,
function_scope);
}
bool IdentifierEquals(const PreParserIdentifier& identifier,
const AstRawString* other);
V8_INLINE PreParserStatement DeclareFunction(
const PreParserIdentifier& variable_name,
const PreParserExpression& function, VariableMode mode, VariableKind kind,
int beg_pos, int end_pos, ZonePtrList<const AstRawString>* names) {
DCHECK_NULL(names);
bool was_added;
Variable* var = DeclareVariableName(variable_name.string_, mode, scope(),
&was_added, beg_pos, kind);
if (kind == SLOPPY_BLOCK_FUNCTION_VARIABLE) {
Token::Value init =
loop_nesting_depth() > 0 ? Token::ASSIGN : Token::INIT;
SloppyBlockFunctionStatement* statement =
factory()->ast_node_factory()->NewSloppyBlockFunctionStatement(
end_pos, var, init);
GetDeclarationScope()->DeclareSloppyBlockFunction(statement);
}
return Statement::Default();
}
V8_INLINE PreParserStatement DeclareClass(
const PreParserIdentifier& variable_name,
const PreParserExpression& value, ZonePtrList<const AstRawString>* names,
int class_token_pos, int end_pos) {
// Preparser shouldn't be used in contexts where we need to track the names.
DCHECK_NULL(names);
bool was_added;
DeclareVariableName(variable_name.string_, VariableMode::kLet, scope(),
&was_added);
return PreParserStatement::Default();
}
V8_INLINE void DeclareClassVariable(ClassScope* scope,
const PreParserIdentifier& name,
ClassInfo* class_info,
int class_token_pos) {
DCHECK_IMPLIES(IsNull(name), class_info->is_anonymous);
// Declare a special class variable for anonymous classes with the dot
// if we need to save it for static private method access.
scope->DeclareClassVariable(ast_value_factory(), name.string_,
class_token_pos);
}
V8_INLINE void DeclarePublicClassMethod(const PreParserIdentifier& class_name,
const PreParserExpression& property,
bool is_constructor,
ClassInfo* class_info) {}
V8_INLINE void DeclarePublicClassField(ClassScope* scope,
const PreParserExpression& property,
bool is_static, bool is_computed_name,
ClassInfo* class_info) {
if (is_computed_name) {
bool was_added;
DeclareVariableName(
ClassFieldVariableName(ast_value_factory(),
class_info->computed_field_count),
VariableMode::kConst, scope, &was_added);
}
}
V8_INLINE void DeclarePrivateClassMember(
ClassScope* scope, const PreParserIdentifier& property_name,
const PreParserExpression& property, ClassLiteralProperty::Kind kind,
bool is_static, ClassInfo* class_info) {
bool was_added;
DeclarePrivateVariableName(
property_name.string_, scope, GetVariableMode(kind),
is_static ? IsStaticFlag::kStatic : IsStaticFlag::kNotStatic,
&was_added);
if (!was_added) {
Scanner::Location loc(property.position(), property.position() + 1);
ReportMessageAt(loc, MessageTemplate::kVarRedeclaration,
property_name.string_);
}
}
V8_INLINE PreParserExpression
RewriteClassLiteral(ClassScope* scope, const PreParserIdentifier& name,
ClassInfo* class_info, int pos, int end_pos) {
bool has_default_constructor = !class_info->has_seen_constructor;
// Account for the default constructor.
if (has_default_constructor) {
// Creating and disposing of a FunctionState makes tracking of
// next_function_is_likely_called match what Parser does. TODO(marja):
// Make the lazy function + next_function_is_likely_called + default ctor
// logic less surprising. Default ctors shouldn't affect the laziness of
// functions.
bool has_extends = class_info->extends.IsNull();
FunctionKind kind = has_extends ? FunctionKind::kDefaultDerivedConstructor
: FunctionKind::kDefaultBaseConstructor;
DeclarationScope* function_scope = NewFunctionScope(kind);
SetLanguageMode(function_scope, LanguageMode::kStrict);
function_scope->set_start_position(pos);
function_scope->set_end_position(pos);
FunctionState function_state(&function_state_, &scope_, function_scope);
GetNextFunctionLiteralId();
}
if (class_info->has_static_class_fields) {
GetNextFunctionLiteralId();
}
if (class_info->has_instance_members) {
GetNextFunctionLiteralId();
}
return PreParserExpression::Default();
}
V8_INLINE PreParserStatement DeclareNative(const PreParserIdentifier& name,
int pos) {
return PreParserStatement::Default();
}
V8_INLINE void QueueDestructuringAssignmentForRewriting(
PreParserExpression assignment) {}
// Helper functions for recursive descent.
V8_INLINE bool IsEval(const PreParserIdentifier& identifier) const {
return identifier.IsEval();
}
V8_INLINE bool IsAsync(const PreParserIdentifier& identifier) const {
return identifier.IsAsync();
}
V8_INLINE bool IsArguments(const PreParserIdentifier& identifier) const {
return identifier.IsArguments();
}
V8_INLINE bool IsEvalOrArguments(
const PreParserIdentifier& identifier) const {
return identifier.IsEvalOrArguments();
}
// Returns true if the expression is of type "this.foo".
V8_INLINE static bool IsThisProperty(const PreParserExpression& expression) {
return expression.IsThisProperty();
}
V8_INLINE static bool IsIdentifier(const PreParserExpression& expression) {
return expression.IsIdentifier();
}
V8_INLINE static PreParserIdentifier AsIdentifier(
const PreParserExpression& expression) {
return expression.AsIdentifier();
}
V8_INLINE static PreParserExpression AsIdentifierExpression(
const PreParserExpression& expression) {
return expression;
}
V8_INLINE bool IsConstructor(const PreParserIdentifier& identifier) const {
return identifier.IsConstructor();
}
V8_INLINE bool IsName(const PreParserIdentifier& identifier) const {
return identifier.IsName();
}
V8_INLINE static bool IsBoilerplateProperty(
const PreParserExpression& property) {
// PreParser doesn't count boilerplate properties.
return false;
}
V8_INLINE bool IsNative(const PreParserExpression& expr) const {
// Preparsing is disabled for extensions (because the extension
// details aren't passed to lazily compiled functions), so we
// don't accept "native function" in the preparser and there is
// no need to keep track of "native".
return false;
}
V8_INLINE static bool IsArrayIndex(const PreParserIdentifier& string,
uint32_t* index) {
return false;
}
V8_INLINE bool IsStringLiteral(PreParserStatement statement) const {
return statement.IsStringLiteral();
}
V8_INLINE static void GetDefaultStrings(
PreParserIdentifier* default_string,
PreParserIdentifier* dot_default_string) {}
// Functions for encapsulating the differences between parsing and preparsing;
// operations interleaved with the recursive descent.
V8_INLINE static void PushLiteralName(const PreParserIdentifier& id) {}
V8_INLINE static void PushVariableName(const PreParserIdentifier& id) {}
V8_INLINE void PushPropertyName(const PreParserExpression& expression) {}
V8_INLINE void PushEnclosingName(const PreParserIdentifier& name) {}
V8_INLINE static void AddFunctionForNameInference(
const PreParserExpression& expression) {}
V8_INLINE static void InferFunctionName() {}
V8_INLINE static void CheckAssigningFunctionLiteralToProperty(
const PreParserExpression& left, const PreParserExpression& right) {}
V8_INLINE bool ShortcutNumericLiteralBinaryExpression(
PreParserExpression* x, const PreParserExpression& y, Token::Value op,
int pos) {
return false;
}
V8_INLINE NaryOperation* CollapseNaryExpression(PreParserExpression* x,
PreParserExpression y,
Token::Value op, int pos,
const SourceRange& range) {
x->clear_parenthesized();
return nullptr;
}
V8_INLINE PreParserExpression BuildUnaryExpression(
const PreParserExpression& expression, Token::Value op, int pos) {
return PreParserExpression::Default();
}
V8_INLINE PreParserStatement
BuildInitializationBlock(DeclarationParsingResult* parsing_result) {
return PreParserStatement::Default();
}
V8_INLINE PreParserBlock RewriteForVarInLegacy(const ForInfo& for_info) {
return PreParserBlock::Null();
}
V8_INLINE void DesugarBindingInForEachStatement(
ForInfo* for_info, PreParserStatement* body_block,
PreParserExpression* each_variable) {
}
V8_INLINE PreParserBlock CreateForEachStatementTDZ(PreParserBlock init_block,
const ForInfo& for_info) {
if (IsLexicalVariableMode(for_info.parsing_result.descriptor.mode)) {
for (auto name : for_info.bound_names) {
bool was_added;
DeclareVariableName(name, VariableMode::kLet, scope(), &was_added);
}
return PreParserBlock::Default();
}
return init_block;
}
V8_INLINE StatementT DesugarLexicalBindingsInForStatement(
PreParserStatement loop, PreParserStatement init,
const PreParserExpression& cond, PreParserStatement next,
PreParserStatement body, Scope* inner_scope, const ForInfo& for_info) {
// See Parser::DesugarLexicalBindingsInForStatement.
for (auto name : for_info.bound_names) {
bool was_added;
DeclareVariableName(name, for_info.parsing_result.descriptor.mode,
inner_scope, &was_added);
}
return loop;
}
PreParserBlock BuildParameterInitializationBlock(
const PreParserFormalParameters& parameters);
V8_INLINE PreParserBlock
BuildRejectPromiseOnException(PreParserStatement init_block) {
return PreParserBlock::Default();
}
V8_INLINE void InsertSloppyBlockFunctionVarBindings(DeclarationScope* scope) {
scope->HoistSloppyBlockFunctions(nullptr);
}
V8_INLINE void InsertShadowingVarBindingInitializers(
PreParserStatement block) {}
V8_INLINE PreParserExpression NewThrowReferenceError(MessageTemplate message,
int pos) {
return PreParserExpression::Default();
}
V8_INLINE PreParserExpression NewThrowSyntaxError(
MessageTemplate message, const PreParserIdentifier& arg, int pos) {
return PreParserExpression::Default();
}
V8_INLINE PreParserExpression NewThrowTypeError(
MessageTemplate message, const PreParserIdentifier& arg, int pos) {
return PreParserExpression::Default();
}
// Reporting errors.
void ReportMessageAt(Scanner::Location source_location,
MessageTemplate message, const char* arg = nullptr) {
pending_error_handler()->ReportMessageAt(
source_location.beg_pos, source_location.end_pos, message, arg);
scanner()->set_parser_error();
}
V8_INLINE void ReportUnidentifiableError() {
pending_error_handler()->set_unidentifiable_error();
scanner()->set_parser_error();
}
V8_INLINE void ReportMessageAt(Scanner::Location source_location,
MessageTemplate message,
const PreParserIdentifier& arg) {
ReportMessageAt(source_location, message, arg.string_);
}
void ReportMessageAt(Scanner::Location source_location,
MessageTemplate message, const AstRawString* arg) {
pending_error_handler()->ReportMessageAt(
source_location.beg_pos, source_location.end_pos, message, arg);
scanner()->set_parser_error();
}
const AstRawString* GetRawNameFromIdentifier(const PreParserIdentifier& arg) {
return arg.string_;
}
PreParserStatement AsIterationStatement(PreParserStatement s) { return s; }
// "null" return type creators.
V8_INLINE static PreParserIdentifier NullIdentifier() {
return PreParserIdentifier::Null();
}
V8_INLINE static PreParserExpression NullExpression() {
return PreParserExpression::Null();
}
V8_INLINE static PreParserExpression FailureExpression() {
return PreParserExpression::Failure();
}
V8_INLINE static PreParserExpression NullLiteralProperty() {
return PreParserExpression::Null();
}
V8_INLINE static PreParserStatementList NullStatementList() {
return PreParserStatementList::Null();
}
V8_INLINE static PreParserStatement NullStatement() {
return PreParserStatement::Null();
}
V8_INLINE static PreParserBlock NullBlock() { return PreParserBlock::Null(); }
template <typename T>
V8_INLINE static bool IsNull(T subject) {
return subject.IsNull();
}
V8_INLINE static bool IsIterationStatement(PreParserStatement subject) {
return subject.IsIterationStatement();
}
V8_INLINE PreParserIdentifier EmptyIdentifierString() const {
PreParserIdentifier result = PreParserIdentifier::Default();
result.string_ = ast_value_factory()->empty_string();
return result;
}
// Producing data during the recursive descent.
PreParserIdentifier GetSymbol() const {
return PreParserIdentifier::Default();
}
PreParserIdentifier GetIdentifier() const;
V8_INLINE PreParserIdentifier GetNextSymbol() const {
return PreParserIdentifier::Default();
}
V8_INLINE PreParserIdentifier GetNumberAsSymbol() const {
return PreParserIdentifier::Default();
}
V8_INLINE PreParserExpression ThisExpression() {
UseThis();
return PreParserExpression::This();
}
V8_INLINE PreParserExpression NewThisExpression(int pos) {
UseThis();
return PreParserExpression::This();
}
V8_INLINE PreParserExpression NewSuperPropertyReference(int pos) {
scope()->NewUnresolved(factory()->ast_node_factory(),
ast_value_factory()->this_function_string(), pos,
NORMAL_VARIABLE);
return PreParserExpression::Default();
}
V8_INLINE PreParserExpression NewSuperCallReference(int pos) {
scope()->NewUnresolved(factory()->ast_node_factory(),
ast_value_factory()->this_function_string(), pos,
NORMAL_VARIABLE);
scope()->NewUnresolved(factory()->ast_node_factory(),
ast_value_factory()->new_target_string(), pos,
NORMAL_VARIABLE);
return PreParserExpression::SuperCallReference();
}
V8_INLINE PreParserExpression NewTargetExpression(int pos) {
return PreParserExpression::NewTargetExpression();
}
V8_INLINE PreParserExpression ImportMetaExpression(int pos) {
return PreParserExpression::Default();
}
V8_INLINE PreParserExpression ExpressionFromLiteral(Token::Value token,
int pos) {
if (token != Token::STRING) return PreParserExpression::Default();
return PreParserExpression::StringLiteral();
}
PreParserExpression ExpressionFromPrivateName(
PrivateNameScopeIterator* private_name_scope,
const PreParserIdentifier& name, int start_position) {
VariableProxy* proxy = factory()->ast_node_factory()->NewVariableProxy(
name.string_, NORMAL_VARIABLE, start_position);
private_name_scope->AddUnresolvedPrivateName(proxy);
return PreParserExpression::FromIdentifier(name);
}
PreParserExpression ExpressionFromIdentifier(
const PreParserIdentifier& name, int start_position,
InferName infer = InferName::kYes) {
expression_scope()->NewVariable(name.string_, start_position);
return PreParserExpression::FromIdentifier(name);
}
V8_INLINE void DeclareIdentifier(const PreParserIdentifier& name,
int start_position) {
expression_scope()->Declare(name.string_, start_position);
}
V8_INLINE Variable* DeclareCatchVariableName(
Scope* scope, const PreParserIdentifier& identifier) {
return scope->DeclareCatchVariableName(identifier.string_);
}
V8_INLINE PreParserPropertyList NewClassPropertyList(int size) const {
return PreParserPropertyList();
}
V8_INLINE PreParserStatementList NewStatementList(int size) const {
return PreParserStatementList();
}
V8_INLINE PreParserExpression
NewV8Intrinsic(const PreParserIdentifier& name,
const PreParserExpressionList& arguments, int pos) {
return PreParserExpression::Default();
}
V8_INLINE PreParserStatement
NewThrowStatement(const PreParserExpression& exception, int pos) {
return PreParserStatement::Jump();
}
V8_INLINE void AddFormalParameter(PreParserFormalParameters* parameters,
const PreParserExpression& pattern,
const PreParserExpression& initializer,
int initializer_end_position,
bool is_rest) {
DeclarationScope* scope = parameters->scope;
scope->RecordParameter(is_rest);
parameters->UpdateArityAndFunctionLength(!initializer.IsNull(), is_rest);
}
V8_INLINE void DeclareFormalParameters(
const PreParserFormalParameters* parameters) {
if (!parameters->is_simple) parameters->scope->SetHasNonSimpleParameters();
}
V8_INLINE void DeclareArrowFunctionFormalParameters(
PreParserFormalParameters* parameters, const PreParserExpression& params,
const Scanner::Location& params_loc) {
}
V8_INLINE PreParserExpression
ExpressionListToExpression(const PreParserExpressionList& args) {
return PreParserExpression::Default();
}
V8_INLINE void SetFunctionNameFromPropertyName(
const PreParserExpression& property, const PreParserIdentifier& name,
const AstRawString* prefix = nullptr) {}
V8_INLINE void SetFunctionNameFromIdentifierRef(
const PreParserExpression& value, const PreParserExpression& identifier) {
}
V8_INLINE void CountUsage(v8::Isolate::UseCounterFeature feature) {
if (use_counts_ != nullptr) ++use_counts_[feature];
}
V8_INLINE bool ParsingDynamicFunctionDeclaration() const { return false; }
// Generate empty functions here as the preparser does not collect source
// ranges for block coverage.
#define DEFINE_RECORD_SOURCE_RANGE(Name) \
template <typename... Ts> \
V8_INLINE void Record##Name##SourceRange(Ts... args) {}
AST_SOURCE_RANGE_LIST(DEFINE_RECORD_SOURCE_RANGE)
#undef DEFINE_RECORD_SOURCE_RANGE
// Preparser's private field members.
int* use_counts_;
PreParserLogger log_;
PreparseDataBuilder* preparse_data_builder_;
std::vector<void*> preparse_data_builder_buffer_;
};
PreParserExpression PreParser::SpreadCall(const PreParserExpression& function,
const PreParserExpressionList& args,
int pos,
Call::PossiblyEval possibly_eval,
bool optional_chain) {
return factory()->NewCall(function, args, pos, possibly_eval, optional_chain);
}
PreParserExpression PreParser::SpreadCallNew(
const PreParserExpression& function, const PreParserExpressionList& args,
int pos) {
return factory()->NewCallNew(function, args, pos);
}
} // namespace internal
} // namespace v8
#endif // V8_PARSING_PREPARSER_H_