// 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_PARSER_H_ #define V8_PARSING_PARSER_H_ #include "src/ast/ast.h" #include "src/ast/scopes.h" #include "src/base/compiler-specific.h" #include "src/globals.h" #include "src/parsing/parser-base.h" #include "src/parsing/parsing.h" #include "src/parsing/preparse-data-format.h" #include "src/parsing/preparse-data.h" #include "src/parsing/preparser.h" #include "src/pending-compilation-error-handler.h" #include "src/utils.h" namespace v8 { class ScriptCompiler; namespace internal { class ParseInfo; class ScriptData; class ParserTarget; class ParserTargetScope; class PreParsedScopeData; class FunctionEntry BASE_EMBEDDED { public: enum { kStartPositionIndex, kEndPositionIndex, kNumParametersIndex, kFunctionLengthIndex, kPropertyCountIndex, kFlagsIndex, kNumInnerFunctionsIndex, kSize }; explicit FunctionEntry(Vector backing) : backing_(backing) { } FunctionEntry() : backing_() { } class LanguageModeField : public BitField {}; class UsesSuperPropertyField : public BitField {}; class CallsEvalField : public BitField {}; class HasDuplicateParametersField : public BitField {}; static uint32_t EncodeFlags(LanguageMode language_mode, bool uses_super_property, bool calls_eval, bool has_duplicate_parameters) { return LanguageModeField::encode(language_mode) | UsesSuperPropertyField::encode(uses_super_property) | CallsEvalField::encode(calls_eval) | HasDuplicateParametersField::encode(has_duplicate_parameters); } int start_pos() const { return backing_[kStartPositionIndex]; } int end_pos() const { return backing_[kEndPositionIndex]; } int num_parameters() const { return backing_[kNumParametersIndex]; } int function_length() const { return backing_[kFunctionLengthIndex]; } int property_count() const { return backing_[kPropertyCountIndex]; } LanguageMode language_mode() const { return LanguageModeField::decode(backing_[kFlagsIndex]); } bool uses_super_property() const { return UsesSuperPropertyField::decode(backing_[kFlagsIndex]); } bool calls_eval() const { return CallsEvalField::decode(backing_[kFlagsIndex]); } bool has_duplicate_parameters() const { return HasDuplicateParametersField::decode(backing_[kFlagsIndex]); } int num_inner_functions() const { return backing_[kNumInnerFunctionsIndex]; } bool is_valid() const { return !backing_.is_empty(); } private: Vector backing_; }; // Wrapper around ScriptData to provide parser-specific functionality. class ParseData { public: static ParseData* FromCachedData(ScriptData* cached_data) { ParseData* pd = new ParseData(cached_data); if (pd->IsSane()) return pd; cached_data->Reject(); delete pd; return NULL; } void Initialize(); FunctionEntry GetFunctionEntry(int start); int FunctionCount(); unsigned* Data() { // Writable data as unsigned int array. return reinterpret_cast(const_cast(script_data_->data())); } void Reject() { script_data_->Reject(); } bool rejected() const { return script_data_->rejected(); } private: explicit ParseData(ScriptData* script_data) : script_data_(script_data) {} bool IsSane(); unsigned Magic(); unsigned Version(); int FunctionsSize(); int Length() const { // Script data length is already checked to be a multiple of unsigned size. return script_data_->length() / sizeof(unsigned); } ScriptData* script_data_; int function_index_; DISALLOW_COPY_AND_ASSIGN(ParseData); }; // ---------------------------------------------------------------------------- // JAVASCRIPT PARSING class Parser; struct ParserFormalParameters : FormalParametersBase { struct Parameter : public ZoneObject { Parameter(const AstRawString* name, Expression* pattern, Expression* initializer, int initializer_end_position, bool is_rest) : name(name), pattern(pattern), initializer(initializer), initializer_end_position(initializer_end_position), is_rest(is_rest) {} const AstRawString* name; Expression* pattern; Expression* initializer; int initializer_end_position; bool is_rest; Parameter* next_parameter = nullptr; bool is_simple() const { return pattern->IsVariableProxy() && initializer == nullptr && !is_rest; } bool is_nondestructuring_rest() const { DCHECK_IMPLIES(is_rest, initializer == nullptr); return is_rest && pattern->IsVariableProxy(); } Parameter** next() { return &next_parameter; } Parameter* const* next() const { return &next_parameter; } }; explicit ParserFormalParameters(DeclarationScope* scope) : FormalParametersBase(scope) {} ThreadedList params; }; template <> struct ParserTypes { typedef ParserBase Base; typedef Parser Impl; typedef v8::internal::Variable Variable; // Return types for traversing functions. typedef const AstRawString* Identifier; typedef v8::internal::Expression* Expression; typedef v8::internal::FunctionLiteral* FunctionLiteral; typedef ObjectLiteral::Property* ObjectLiteralProperty; typedef ClassLiteral::Property* ClassLiteralProperty; typedef ZoneList* ExpressionList; typedef ZoneList* ObjectPropertyList; typedef ZoneList* ClassPropertyList; typedef ParserFormalParameters FormalParameters; typedef v8::internal::Statement* Statement; typedef ZoneList* StatementList; typedef v8::internal::Block* Block; typedef v8::internal::BreakableStatement* BreakableStatement; typedef v8::internal::IterationStatement* IterationStatement; // For constructing objects returned by the traversing functions. typedef AstNodeFactory Factory; typedef ParserTarget Target; typedef ParserTargetScope TargetScope; }; class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase) { public: explicit Parser(ParseInfo* info); ~Parser() { delete reusable_preparser_; reusable_preparser_ = NULL; delete cached_parse_data_; cached_parse_data_ = NULL; } static bool const IsPreParser() { return false; } void ParseOnBackground(ParseInfo* info); // Deserialize the scope chain prior to parsing in which the script is going // to be executed. If the script is a top-level script, or the scope chain // consists of only a native context, maybe_outer_scope_info should be an // empty handle. // // This only deserializes the scope chain, but doesn't connect the scopes to // their corresponding scope infos. Therefore, looking up variables in the // deserialized scopes is not possible. void DeserializeScopeChain(ParseInfo* info, MaybeHandle maybe_outer_scope_info); // Handle errors detected during parsing void ReportErrors(Isolate* isolate, Handle