}
+void ParserTraits::CheckPossibleEvalCall(Expression* expression,
+ Scope* scope) {
+ VariableProxy* callee = expression->AsVariableProxy();
+ if (callee != NULL &&
+ callee->IsVariable(parser_->isolate()->factory()->eval_string())) {
+ scope->DeclarationScope()->RecordEvalCall();
+ }
+}
+
+
Expression* ParserTraits::MarkExpressionAsLValue(Expression* expression) {
VariableProxy* proxy = expression != NULL
? expression->AsVariableProxy()
}
-Expression* ParserTraits::ParseLeftHandSideExpression(bool* ok) {
- return parser_->ParseLeftHandSideExpression(ok);
+Expression* ParserTraits::ParseMemberWithNewPrefixesExpression(bool* ok) {
+ return parser_->ParseMemberWithNewPrefixesExpression(ok);
}
}
-Expression* Parser::ParseLeftHandSideExpression(bool* ok) {
- // LeftHandSideExpression ::
- // (NewExpression | MemberExpression) ...
-
- Expression* result = ParseMemberWithNewPrefixesExpression(CHECK_OK);
-
- while (true) {
- switch (peek()) {
- case Token::LBRACK: {
- Consume(Token::LBRACK);
- int pos = position();
- Expression* index = ParseExpression(true, CHECK_OK);
- result = factory()->NewProperty(result, index, pos);
- Expect(Token::RBRACK, CHECK_OK);
- break;
- }
-
- case Token::LPAREN: {
- int pos;
- if (scanner()->current_token() == Token::IDENTIFIER) {
- // For call of an identifier we want to report position of
- // the identifier as position of the call in the stack trace.
- pos = position();
- } else {
- // For other kinds of calls we record position of the parenthesis as
- // position of the call. Note that this is extremely important for
- // expressions of the form function(){...}() for which call position
- // should not point to the closing brace otherwise it will intersect
- // with positions recorded for function literal and confuse debugger.
- pos = peek_position();
- // Also the trailing parenthesis are a hint that the function will
- // be called immediately. If we happen to have parsed a preceding
- // function literal eagerly, we can also compile it eagerly.
- if (result->IsFunctionLiteral() && mode() == PARSE_EAGERLY) {
- result->AsFunctionLiteral()->set_parenthesized();
- }
- }
- ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
-
- // Keep track of eval() calls since they disable all local variable
- // optimizations.
- // The calls that need special treatment are the
- // direct eval calls. These calls are all of the form eval(...), with
- // no explicit receiver.
- // These calls are marked as potentially direct eval calls. Whether
- // they are actually direct calls to eval is determined at run time.
- VariableProxy* callee = result->AsVariableProxy();
- if (callee != NULL &&
- callee->IsVariable(isolate()->factory()->eval_string())) {
- scope_->DeclarationScope()->RecordEvalCall();
- }
- result = factory()->NewCall(result, args, pos);
- if (fni_ != NULL) fni_->RemoveLastFunction();
- break;
- }
-
- case Token::PERIOD: {
- Consume(Token::PERIOD);
- int pos = position();
- Handle<String> name = ParseIdentifierName(CHECK_OK);
- result = factory()->NewProperty(
- result, factory()->NewLiteral(name, pos), pos);
- if (fni_ != NULL) fni_->PushLiteralName(name);
- break;
- }
-
- default:
- return result;
- }
- }
-}
-
-
Expression* Parser::ParseMemberWithNewPrefixesExpression(bool* ok) {
// NewExpression ::
// ('new')+ MemberExpression
static void CheckAssigningFunctionLiteralToProperty(Expression* left,
Expression* right);
+ // Keep track of eval() calls since they disable all local variable
+ // optimizations. This checks if expression is an eval call, and if yes,
+ // forwards the information to scope.
+ void CheckPossibleEvalCall(Expression* expression, Scope* scope);
+
// Determine if the expression is a variable proxy and mark it as being used
// in an assignment or with a increment/decrement operator. This is currently
// used on for the statically checking assignments to harmony const bindings.
// Checks LHS expression for assignment and prefix/postfix increment/decrement
// in strict mode.
- void CheckStrictModeLValue(Expression*expression, bool* ok);
+ void CheckStrictModeLValue(Expression* expression, bool* ok);
// Returns true if we have a binary expression between two numeric
// literals. In that case, *x will be changed to an expression which is the
int function_token_position,
FunctionLiteral::FunctionType type,
bool* ok);
- Expression* ParseLeftHandSideExpression(bool* ok);
+ Expression* ParseMemberWithNewPrefixesExpression(bool* ok);
private:
Parser* parser_;
// https://codereview.chromium.org/7003030/ ).
static const int kMaxNumFunctionLocals = 4194303; // 2^22-1
- enum Mode {
- PARSE_LAZILY,
- PARSE_EAGERLY
- };
-
enum VariableDeclarationContext {
kModuleElement,
kBlockElement,
kHasNoInitializers
};
- class ParsingModeScope BASE_EMBEDDED {
- public:
- ParsingModeScope(Parser* parser, Mode mode)
- : parser_(parser),
- old_mode_(parser->mode()) {
- parser_->mode_ = mode;
- }
- ~ParsingModeScope() {
- parser_->mode_ = old_mode_;
- }
-
- private:
- Parser* parser_;
- Mode old_mode_;
- };
-
// Returns NULL if parsing failed.
FunctionLiteral* ParseProgram();
}
bool inside_with() const { return scope_->inside_with(); }
- Mode mode() const { return mode_; }
ScriptDataImpl** cached_data() const { return cached_data_; }
CachedDataMode cached_data_mode() const { return cached_data_mode_; }
Scope* DeclarationScope(VariableMode mode) {
// Support for hamony block scoped bindings.
Block* ParseScopedBlock(ZoneStringList* labels, bool* ok);
- Expression* ParseUnaryExpression(bool* ok);
- Expression* ParseLeftHandSideExpression(bool* ok);
Expression* ParseMemberWithNewPrefixesExpression(bool* ok);
Expression* ParseMemberExpression(bool* ok);
Expression* ParseMemberExpressionContinuation(Expression* expression,
bool* ok);
- Expression* ParseObjectLiteral(bool* ok);
-
// Initialize the components of a for-in / for-of statement.
void InitializeForEachStatement(ForEachStatement* stmt,
Expression* each,
ScriptDataImpl** cached_data_;
CachedDataMode cached_data_mode_;
- Mode mode_;
-
CompilationInfo* info_;
};
extension_(extension),
fni_(NULL),
log_(log),
+ mode_(PARSE_EAGERLY), // Lazy mode must be set explicitly.
scanner_(scanner),
stack_limit_(stack_limit),
stack_overflow_(false),
kDontAllowEvalOrArguments
};
+ enum Mode {
+ PARSE_LAZILY,
+ PARSE_EAGERLY
+ };
+
// ---------------------------------------------------------------------------
// FunctionState and BlockState together implement the parser's scope stack.
// The parser's current scope is in scope_. BlockState and FunctionState
friend class ParserTraits;
};
+ class ParsingModeScope BASE_EMBEDDED {
+ public:
+ ParsingModeScope(ParserBase* parser, Mode mode)
+ : parser_(parser),
+ old_mode_(parser->mode()) {
+ parser_->mode_ = mode;
+ }
+ ~ParsingModeScope() {
+ parser_->mode_ = old_mode_;
+ }
+
+ private:
+ ParserBase* parser_;
+ Mode old_mode_;
+ };
+
Scanner* scanner() const { return scanner_; }
int position() { return scanner_->location().beg_pos; }
int peek_position() { return scanner_->peek_location().beg_pos; }
bool stack_overflow() const { return stack_overflow_; }
void set_stack_overflow() { stack_overflow_ = true; }
+ Mode mode() const { return mode_; }
typename Traits::Type::Zone* zone() const { return zone_; }
INLINE(Token::Value peek()) {
ExpressionT ParseBinaryExpression(int prec, bool accept_IN, bool* ok);
ExpressionT ParseUnaryExpression(bool* ok);
ExpressionT ParsePostfixExpression(bool* ok);
+ ExpressionT ParseLeftHandSideExpression(bool* ok);
// Used to detect duplicates in object literals. Each of the values
// kGetterProperty, kSetterProperty and kValueProperty represents
v8::Extension* extension_;
FuncNameInferrer* fni_;
ParserRecorder* log_;
+ Mode mode_;
private:
Scanner* scanner_;
return IsIdentifier() || IsProperty();
}
+ // At the moment PreParser doesn't track these expression types.
+ bool IsFunctionLiteral() const { return false; }
+ bool IsCall() const { return false; }
+ bool IsCallNew() const { return false; }
+
+ PreParserExpression AsFunctionLiteral() { return *this; }
+
// Dummy implementation for making expression->somefunc() work in both Parser
// and PreParser.
PreParserExpression* operator->() { return this; }
- // These are only used when doing function name inferring, and PreParser
- // doesn't do function name inferring.
- void* AsCall() const { return NULL; }
- void* AsCallNew() const { return NULL; }
-
// More dummy implementations of things PreParser doesn't need to track:
void set_index(int index) {} // For YieldExpressions
+ void set_parenthesized() {}
private:
// Least significant 2 bits are used as flags. Bits 0 and 1 represent
class PreParserFactory {
public:
explicit PreParserFactory(void* extra_param) {}
-
- PreParserExpression NewRegExpLiteral(PreParserIdentifier js_pattern,
- PreParserIdentifier js_flags,
- int literal_index,
- int pos) {
- return PreParserExpression::Default();
- }
- PreParserExpression NewUnaryOperation(Token::Value op,
- PreParserExpression expression,
- int pos) {
+ PreParserExpression NewLiteral(PreParserIdentifier identifier,
+ int pos) {
return PreParserExpression::Default();
}
- PreParserExpression NewBinaryOperation(Token::Value op,
- PreParserExpression left,
- PreParserExpression right, int pos) {
+ PreParserExpression NewNumberLiteral(double number,
+ int pos) {
return PreParserExpression::Default();
}
- PreParserExpression NewCompareOperation(Token::Value op,
- PreParserExpression left,
- PreParserExpression right, int pos) {
+ PreParserExpression NewRegExpLiteral(PreParserIdentifier js_pattern,
+ PreParserIdentifier js_flags,
+ int literal_index,
+ int pos) {
return PreParserExpression::Default();
}
PreParserExpression NewArrayLiteral(PreParserExpressionList values,
int pos) {
return PreParserExpression::Default();
}
-
PreParserExpression NewObjectLiteralProperty(bool is_getter,
PreParserExpression value,
int pos) {
return PreParserExpression::Default();
}
-
PreParserExpression NewObjectLiteralProperty(PreParserExpression key,
PreParserExpression value) {
return PreParserExpression::Default();
}
-
PreParserExpression NewObjectLiteral(PreParserExpressionList properties,
int literal_index,
int boilerplate_properties,
int pos) {
return PreParserExpression::Default();
}
-
- PreParserExpression NewLiteral(PreParserIdentifier identifier,
- int pos) {
+ PreParserExpression NewVariableProxy(void* generator_variable) {
return PreParserExpression::Default();
}
-
- PreParserExpression NewNumberLiteral(double number,
- int pos) {
+ PreParserExpression NewProperty(PreParserExpression obj,
+ PreParserExpression key,
+ int pos) {
+ if (obj.IsThis()) {
+ return PreParserExpression::ThisProperty();
+ }
+ return PreParserExpression::Property();
+ }
+ PreParserExpression NewUnaryOperation(Token::Value op,
+ PreParserExpression expression,
+ int pos) {
+ return PreParserExpression::Default();
+ }
+ PreParserExpression NewBinaryOperation(Token::Value op,
+ PreParserExpression left,
+ PreParserExpression right, int pos) {
+ return PreParserExpression::Default();
+ }
+ PreParserExpression NewCompareOperation(Token::Value op,
+ PreParserExpression left,
+ PreParserExpression right, int pos) {
return PreParserExpression::Default();
}
-
PreParserExpression NewAssignment(Token::Value op,
PreParserExpression left,
PreParserExpression right,
int pos) {
return PreParserExpression::Default();
}
-
- PreParserExpression NewVariableProxy(void* generator_variable) {
- return PreParserExpression::Default();
- }
-
PreParserExpression NewYield(PreParserExpression generator_object,
PreParserExpression expression,
Yield::Kind yield_kind,
int pos) {
return PreParserExpression::Default();
}
-
PreParserExpression NewConditional(PreParserExpression condition,
PreParserExpression then_expression,
PreParserExpression else_expression,
int pos) {
return PreParserExpression::Default();
}
-
PreParserExpression NewCountOperation(Token::Value op,
bool is_prefix,
PreParserExpression expression,
int pos) {
return PreParserExpression::Default();
}
+ PreParserExpression NewCall(PreParserExpression expression,
+ PreParserExpressionList arguments,
+ int pos) {
+ return PreParserExpression::Default();
+ }
};
static void CheckAssigningFunctionLiteralToProperty(
PreParserExpression left, PreParserExpression right) {}
+ // PreParser doesn't need to keep track of eval calls.
+ static void CheckPossibleEvalCall(PreParserExpression expression,
+ PreParserScope* scope) {}
+
static PreParserExpression MarkExpressionAsLValue(
PreParserExpression expression) {
// TODO(marja): To be able to produce the same errors, the preparser needs
int function_token_position,
FunctionLiteral::FunctionType type,
bool* ok);
- PreParserExpression ParseLeftHandSideExpression(bool* ok);
+ PreParserExpression ParseMemberWithNewPrefixesExpression(bool* ok);
private:
PreParser* pre_parser_;
Statement ParseTryStatement(bool* ok);
Statement ParseDebuggerStatement(bool* ok);
Expression ParseConditionalExpression(bool accept_IN, bool* ok);
- Expression ParseLeftHandSideExpression(bool* ok);
Expression ParseMemberExpression(bool* ok);
Expression ParseMemberExpressionContinuation(PreParserExpression expression,
bool* ok);
if ((op == Token::INIT_VAR
|| op == Token::INIT_CONST_LEGACY
|| op == Token::ASSIGN)
- && (right->AsCall() == NULL && right->AsCallNew() == NULL)) {
+ && (!right->IsCall() && !right->IsCallNew())) {
fni_->Infer();
} else {
fni_->RemoveLastFunction();
}
+template <class Traits>
+typename ParserBase<Traits>::ExpressionT
+ParserBase<Traits>::ParseLeftHandSideExpression(bool* ok) {
+ // LeftHandSideExpression ::
+ // (NewExpression | MemberExpression) ...
+
+ ExpressionT result = this->ParseMemberWithNewPrefixesExpression(CHECK_OK);
+
+ while (true) {
+ switch (peek()) {
+ case Token::LBRACK: {
+ Consume(Token::LBRACK);
+ int pos = position();
+ ExpressionT index = ParseExpression(true, CHECK_OK);
+ result = factory()->NewProperty(result, index, pos);
+ Expect(Token::RBRACK, CHECK_OK);
+ break;
+ }
+
+ case Token::LPAREN: {
+ int pos;
+ if (scanner()->current_token() == Token::IDENTIFIER) {
+ // For call of an identifier we want to report position of
+ // the identifier as position of the call in the stack trace.
+ pos = position();
+ } else {
+ // For other kinds of calls we record position of the parenthesis as
+ // position of the call. Note that this is extremely important for
+ // expressions of the form function(){...}() for which call position
+ // should not point to the closing brace otherwise it will intersect
+ // with positions recorded for function literal and confuse debugger.
+ pos = peek_position();
+ // Also the trailing parenthesis are a hint that the function will
+ // be called immediately. If we happen to have parsed a preceding
+ // function literal eagerly, we can also compile it eagerly.
+ if (result->IsFunctionLiteral() && mode() == PARSE_EAGERLY) {
+ result->AsFunctionLiteral()->set_parenthesized();
+ }
+ }
+ typename Traits::Type::ExpressionList args = ParseArguments(CHECK_OK);
+
+ // Keep track of eval() calls since they disable all local variable
+ // optimizations.
+ // The calls that need special treatment are the
+ // direct eval calls. These calls are all of the form eval(...), with
+ // no explicit receiver.
+ // These calls are marked as potentially direct eval calls. Whether
+ // they are actually direct calls to eval is determined at run time.
+ this->CheckPossibleEvalCall(result, scope_);
+ result = factory()->NewCall(result, args, pos);
+ if (fni_ != NULL) fni_->RemoveLastFunction();
+ break;
+ }
+
+ case Token::PERIOD: {
+ Consume(Token::PERIOD);
+ int pos = position();
+ IdentifierT name = ParseIdentifierName(CHECK_OK);
+ result = factory()->NewProperty(
+ result, factory()->NewLiteral(name, pos), pos);
+ if (fni_ != NULL) this->PushLiteralName(fni_, name);
+ break;
+ }
+
+ default:
+ return result;
+ }
+ }
+}
+
+
#undef CHECK_OK
#undef CHECK_OK_CUSTOM