Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(103)

Unified Diff: src/preparser.h

Issue 561913002: Class syntax parsing (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: git rebase Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/parser.cc ('k') | src/preparser.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/preparser.h
diff --git a/src/preparser.h b/src/preparser.h
index b24c0728477a9a9bff8cabfb7c0d6a2d1188605d..0147caf5d134e312bc5fd49754d7c57c8d19f866 100644
--- a/src/preparser.h
+++ b/src/preparser.h
@@ -46,6 +46,7 @@ namespace internal {
// typedef Identifier;
// typedef Expression;
// typedef FunctionLiteral;
+// typedef ClassLiteral;
// typedef ObjectLiteralProperty;
// typedef Literal;
// typedef ExpressionList;
@@ -63,6 +64,7 @@ class ParserBase : public Traits {
typedef typename Traits::Type::Expression ExpressionT;
typedef typename Traits::Type::Identifier IdentifierT;
typedef typename Traits::Type::FunctionLiteral FunctionLiteralT;
+ typedef typename Traits::Type::ClassLiteral ClassLiteralT;
typedef typename Traits::Type::Literal LiteralT;
typedef typename Traits::Type::ObjectLiteralProperty ObjectLiteralPropertyT;
@@ -480,10 +482,12 @@ class ParserBase : public Traits {
ExpressionT ParsePrimaryExpression(bool* ok);
ExpressionT ParseExpression(bool accept_IN, bool* ok);
ExpressionT ParseArrayLiteral(bool* ok);
+ IdentifierT ParsePropertyName(bool* is_get, bool* is_set, bool* is_static,
+ bool* ok);
ExpressionT ParseObjectLiteral(bool* ok);
ObjectLiteralPropertyT ParsePropertyDefinition(ObjectLiteralChecker* checker,
+ bool in_class, bool is_static,
bool* ok);
- IdentifierT ParsePropertyName(bool* is_getter, bool* is_setter, bool* ok);
typename Traits::Type::ExpressionList ParseArguments(bool* ok);
ExpressionT ParseAssignmentExpression(bool accept_IN, bool* ok);
ExpressionT ParseYieldExpression(bool* ok);
@@ -498,6 +502,10 @@ class ParserBase : public Traits {
bool* ok);
ExpressionT ParseArrowFunctionLiteral(int start_pos, ExpressionT params_ast,
bool* ok);
+ ClassLiteralT ParseClassLiteral(IdentifierT name,
+ Scanner::Location function_name_location,
+ bool name_is_strict_reserved, int pos,
+ bool* ok);
// Checks if the expression is a valid reference expression (e.g., on the
// left-hand side of assignments). Although ruled out by ECMA as early errors,
@@ -612,10 +620,20 @@ class PreParserIdentifier {
static PreParserIdentifier Yield() {
return PreParserIdentifier(kYieldIdentifier);
}
+ static PreParserIdentifier Prototype() {
+ return PreParserIdentifier(kPrototypeIdentifier);
+ }
+ static PreParserIdentifier Constructor() {
+ return PreParserIdentifier(kConstructorIdentifier);
+ }
bool IsEval() const { return type_ == kEvalIdentifier; }
bool IsArguments() const { return type_ == kArgumentsIdentifier; }
- bool IsEvalOrArguments() const { return type_ >= kEvalIdentifier; }
bool IsYield() const { return type_ == kYieldIdentifier; }
+ bool IsPrototype() const { return type_ == kPrototypeIdentifier; }
+ bool IsConstructor() const { return type_ == kConstructorIdentifier; }
+ bool IsEvalOrArguments() const {
+ return type_ == kEvalIdentifier || type_ == kArgumentsIdentifier;
+ }
bool IsFutureReserved() const { return type_ == kFutureReservedIdentifier; }
bool IsFutureStrictReserved() const {
return type_ == kFutureStrictReservedIdentifier;
@@ -638,7 +656,9 @@ class PreParserIdentifier {
kLetIdentifier,
kYieldIdentifier,
kEvalIdentifier,
- kArgumentsIdentifier
+ kArgumentsIdentifier,
+ kPrototypeIdentifier,
+ kConstructorIdentifier
};
explicit PreParserIdentifier(Type type) : type_(type) {}
Type type_;
@@ -927,6 +947,7 @@ class PreParserScope {
ScopeType type() { return scope_type_; }
StrictMode strict_mode() const { return strict_mode_; }
void SetStrictMode(StrictMode strict_mode) { strict_mode_ = strict_mode; }
+ void SetScopeName(PreParserIdentifier name) {}
// When PreParser is in use, lazy compilation is already being done,
// things cannot get lazier than that.
@@ -971,11 +992,12 @@ class PreParserFactory {
}
PreParserExpression NewObjectLiteralProperty(bool is_getter,
PreParserExpression value,
- int pos) {
+ int pos, bool is_static) {
return PreParserExpression::Default();
}
PreParserExpression NewObjectLiteralProperty(PreParserExpression key,
- PreParserExpression value) {
+ PreParserExpression value,
+ bool is_static) {
return PreParserExpression::Default();
}
PreParserExpression NewObjectLiteral(PreParserExpressionList properties,
@@ -985,7 +1007,7 @@ class PreParserFactory {
int pos) {
return PreParserExpression::Default();
}
- PreParserExpression NewVariableProxy(void* generator_variable) {
+ PreParserExpression NewVariableProxy(void* variable) {
return PreParserExpression::Default();
}
PreParserExpression NewProperty(PreParserExpression obj,
@@ -1061,6 +1083,14 @@ class PreParserFactory {
int position) {
return PreParserExpression::Default();
}
+ PreParserExpression NewClassLiteral(PreParserIdentifier name,
+ PreParserExpression extends,
+ PreParserExpression constructor,
+ PreParserExpressionList properties,
+ AstValueFactory* ast_value_factory,
+ int position) {
+ return PreParserExpression::Default();
+ }
// Return the object itself as AstVisitor and implement the needed
// dummy method right in this class.
@@ -1099,6 +1129,7 @@ class PreParserTraits {
typedef PreParserExpression Expression;
typedef PreParserExpression YieldExpression;
typedef PreParserExpression FunctionLiteral;
+ typedef PreParserExpression ClassLiteral;
typedef PreParserExpression ObjectLiteralProperty;
typedef PreParserExpression Literal;
typedef PreParserExpressionList ExpressionList;
@@ -1125,6 +1156,14 @@ class PreParserTraits {
return identifier.IsEvalOrArguments();
}
+ static bool IsPrototype(PreParserIdentifier identifier) {
+ return identifier.IsPrototype();
+ }
+
+ static bool IsConstructor(PreParserIdentifier identifier) {
+ return identifier.IsConstructor();
+ }
+
// Returns true if the expression is of type "this.foo".
static bool IsThisProperty(PreParserExpression expression) {
return expression.IsThisProperty();
@@ -1245,6 +1284,12 @@ class PreParserTraits {
static PreParserExpression EmptyObjectLiteralProperty() {
return PreParserExpression::Default();
}
+ static PreParserExpression EmptyFunctionLiteral() {
+ return PreParserExpression::Default();
+ }
+ static PreParserExpression EmptyClassLiteral() {
+ return PreParserExpression::Default();
+ }
static PreParserExpressionList NullExpressionList() {
return PreParserExpressionList();
}
@@ -1435,6 +1480,7 @@ class PreParser : public ParserBase<PreParserTraits> {
SourceElements ParseSourceElements(int end_token, bool* ok);
Statement ParseStatement(bool* ok);
Statement ParseFunctionDeclaration(bool* ok);
+ Statement ParseClassDeclaration(bool* ok);
Statement ParseBlock(bool* ok);
Statement ParseVariableStatement(VariableDeclarationContext var_context,
bool* ok);
@@ -1708,6 +1754,7 @@ ParserBase<Traits>::ParsePrimaryExpression(bool* ok) {
// ArrayLiteral
// ObjectLiteral
// RegExpLiteral
+ // ClassLiteral
// '(' Expression ')'
int pos = peek_position();
@@ -1778,6 +1825,23 @@ ParserBase<Traits>::ParsePrimaryExpression(bool* ok) {
}
break;
+ case Token::CLASS: {
+ Consume(Token::CLASS);
+ int class_token_position = position();
+ IdentifierT name = this->EmptyIdentifier();
+ bool is_strict_reserved_name = false;
+ Scanner::Location class_name_location = Scanner::Location::invalid();
+ if (peek_any_identifier()) {
+ name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name,
+ CHECK_OK);
+ class_name_location = scanner()->location();
+ }
+ result = this->ParseClassLiteral(name, class_name_location,
+ is_strict_reserved_name,
+ class_token_position, CHECK_OK);
+ break;
+ }
+
case Token::MOD:
if (allow_natives_syntax() || extension_ != NULL) {
result = this->ParseV8Intrinsic(CHECK_OK);
@@ -1848,7 +1912,7 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseArrayLiteral(
template <class Traits>
typename ParserBase<Traits>::IdentifierT ParserBase<Traits>::ParsePropertyName(
- bool* is_getter, bool* is_setter, bool* ok) {
+ bool* is_get, bool* is_set, bool* is_static, bool* ok) {
Token::Value next = peek();
switch (next) {
case Token::STRING:
@@ -1857,27 +1921,35 @@ typename ParserBase<Traits>::IdentifierT ParserBase<Traits>::ParsePropertyName(
case Token::NUMBER:
Consume(Token::NUMBER);
return this->GetNumberAsSymbol(scanner_);
+ case Token::STATIC:
+ *is_static = true;
+ // Fall through.
default:
- return ParseIdentifierNameOrGetOrSet(is_getter, is_setter,
- CHECK_OK_CUSTOM(EmptyIdentifier));
+ return ParseIdentifierNameOrGetOrSet(is_get, is_set, ok);
}
+ UNREACHABLE();
+ return this->EmptyIdentifier();
}
template <class Traits>
typename ParserBase<Traits>::ObjectLiteralPropertyT ParserBase<
- Traits>::ParsePropertyDefinition(ObjectLiteralChecker* checker, bool* ok) {
+ Traits>::ParsePropertyDefinition(ObjectLiteralChecker* checker,
+ bool in_class, bool is_static, bool* ok) {
// TODO(arv): Add support for concise generator methods.
ExpressionT value = this->EmptyExpression();
- bool is_getter = false;
- bool is_setter = false;
+ bool is_get = false;
+ bool is_set = false;
+ bool name_is_static = false;
Token::Value name_token = peek();
int next_pos = peek_position();
- IdentifierT name = ParsePropertyName(
- &is_getter, &is_setter, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
+ IdentifierT name =
+ ParsePropertyName(&is_get, &is_set, &name_is_static,
+ CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
+
if (fni_ != NULL) this->PushLiteralName(fni_, name);
- if (peek() == Token::COLON) {
+ if (!in_class && peek() == Token::COLON) {
// PropertyDefinition : PropertyName ':' AssignmentExpression
checker->CheckProperty(name_token, kValueProperty,
CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
@@ -1887,6 +1959,13 @@ typename ParserBase<Traits>::ObjectLiteralPropertyT ParserBase<
} else if (allow_harmony_object_literals_ && peek() == Token::LPAREN) {
// Concise Method
+
+ if (is_static && this->IsPrototype(name)) {
+ ReportMessageAt(scanner()->location(), "static_prototype");
+ *ok = false;
+ return this->EmptyObjectLiteralProperty();
+ }
+
checker->CheckProperty(name_token, kValueProperty,
CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
value = this->ParseFunctionLiteral(
@@ -1896,25 +1975,43 @@ typename ParserBase<Traits>::ObjectLiteralPropertyT ParserBase<
FunctionLiteral::ANONYMOUS_EXPRESSION, FunctionLiteral::NORMAL_ARITY,
CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
- } else if (is_getter || is_setter) {
+ } else if (in_class && name_is_static && !is_static) {
+ // static MethodDefinition
+ return ParsePropertyDefinition(checker, true, true, ok);
+
+ } else if (is_get || is_set) {
// Accessor
bool dont_care = false;
name_token = peek();
- name = ParsePropertyName(&dont_care, &dont_care,
+ name = ParsePropertyName(&dont_care, &dont_care, &dont_care,
CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
+
// Validate the property.
+ if (is_static && this->IsPrototype(name)) {
+ ReportMessageAt(scanner()->location(), "static_prototype");
+ *ok = false;
+ return this->EmptyObjectLiteralProperty();
+ } else if (in_class && !is_static && this->IsConstructor(name)) {
+ // ES6, spec draft rev 27, treats static get constructor as an error too.
+ // https://bugs.ecmascript.org/show_bug.cgi?id=3223
+ // TODO(arv): Update when bug is resolved.
+ ReportMessageAt(scanner()->location(), "constructor_special_method");
+ *ok = false;
+ return this->EmptyObjectLiteralProperty();
+ }
checker->CheckProperty(name_token,
- is_getter ? kGetterProperty : kSetterProperty,
+ is_get ? kGetterProperty : kSetterProperty,
CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
+
typename Traits::Type::FunctionLiteral value = this->ParseFunctionLiteral(
name, scanner()->location(),
false, // reserved words are allowed here
FunctionKind::kNormalFunction, RelocInfo::kNoPosition,
FunctionLiteral::ANONYMOUS_EXPRESSION,
- is_getter ? FunctionLiteral::GETTER_ARITY
- : FunctionLiteral::SETTER_ARITY,
+ is_get ? FunctionLiteral::GETTER_ARITY : FunctionLiteral::SETTER_ARITY,
CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
- return factory()->NewObjectLiteralProperty(is_getter, value, next_pos);
+ return factory()->NewObjectLiteralProperty(is_get, value, next_pos,
+ is_static);
} else {
Token::Value next = Next();
ReportUnexpectedToken(next);
@@ -1927,7 +2024,7 @@ typename ParserBase<Traits>::ObjectLiteralPropertyT ParserBase<
? factory()->NewNumberLiteral(index, next_pos)
: factory()->NewStringLiteral(name, next_pos);
- return factory()->NewObjectLiteralProperty(key, value);
+ return factory()->NewObjectLiteralProperty(key, value, is_static);
}
@@ -1950,8 +2047,10 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseObjectLiteral(
while (peek() != Token::RBRACE) {
if (fni_ != NULL) fni_->Enter();
+ const bool in_class = false;
+ const bool is_static = false;
ObjectLiteralPropertyT property =
- this->ParsePropertyDefinition(&checker, CHECK_OK);
+ this->ParsePropertyDefinition(&checker, in_class, is_static, CHECK_OK);
// Mark top-level object literals that contain function literals and
// pretenure the literal so it can be added as a constant function
@@ -2400,7 +2499,7 @@ template <class Traits>
typename ParserBase<Traits>::ExpressionT
ParserBase<Traits>::ParseMemberExpression(bool* ok) {
// MemberExpression ::
- // (PrimaryExpression | FunctionLiteral)
+ // (PrimaryExpression | FunctionLiteral | ClassLiteral)
// ('[' Expression ']' | '.' Identifier | Arguments)*
// The '[' Expression ']' and '.' Identifier parts are parsed by
@@ -2603,6 +2702,69 @@ typename ParserBase<Traits>::ExpressionT ParserBase<
}
+template <class Traits>
+typename ParserBase<Traits>::ClassLiteralT
+ParserBase<Traits>::ParseClassLiteral(IdentifierT name,
+ Scanner::Location class_name_location,
+ bool name_is_strict_reserved, int pos,
+ bool* ok) {
+ // All parts of a ClassDeclaration or a ClassExpression are strict code.
+ if (name_is_strict_reserved) {
+ ReportMessageAt(class_name_location, "unexpected_strict_reserved");
+ *ok = false;
+ return this->EmptyClassLiteral();
+ }
+ if (this->IsEvalOrArguments(name)) {
+ ReportMessageAt(class_name_location, "strict_eval_arguments");
+ *ok = false;
+ return this->EmptyClassLiteral();
+ }
+
+ // TODO(arv): Implement scopes and name binding in class body only.
+ // TODO(arv): Maybe add CLASS_SCOPE?
+ typename Traits::Type::ScopePtr extends_scope =
+ this->NewScope(scope_, BLOCK_SCOPE);
+ FunctionState extends_function_state(
+ &function_state_, &scope_, &extends_scope, zone(),
+ this->ast_value_factory(), ast_node_id_gen_);
+ scope_->SetStrictMode(STRICT);
+ scope_->SetScopeName(name);
+
+ ExpressionT extends = this->EmptyExpression();
+ if (Check(Token::EXTENDS)) {
+ extends =
+ this->ParseLeftHandSideExpression(CHECK_OK_CUSTOM(EmptyClassLiteral));
+ }
+
+ ObjectLiteralChecker checker(this, STRICT);
+ typename Traits::Type::PropertyList properties =
+ this->NewPropertyList(4, zone_);
+ FunctionLiteralT constructor = this->EmptyFunctionLiteral();
+
+ Expect(Token::LBRACE, CHECK_OK_CUSTOM(EmptyClassLiteral));
+ while (peek() != Token::RBRACE) {
+ if (Check(Token::SEMICOLON)) continue;
+ if (fni_ != NULL) fni_->Enter();
+
+ const bool in_class = true;
+ const bool is_static = false;
+ ObjectLiteralPropertyT property = this->ParsePropertyDefinition(
+ &checker, in_class, is_static, CHECK_OK_CUSTOM(EmptyClassLiteral));
+
+ properties->Add(property, zone());
+
+ if (fni_ != NULL) {
+ fni_->Infer();
+ fni_->Leave();
+ }
+ }
+ Expect(Token::RBRACE, CHECK_OK_CUSTOM(EmptyClassLiteral));
+
+ return factory()->NewClassLiteral(name, extends, constructor, properties,
+ this->ast_value_factory(), pos);
+}
+
+
template <typename Traits>
typename ParserBase<Traits>::ExpressionT
ParserBase<Traits>::CheckAndRewriteReferenceExpression(
« no previous file with comments | « src/parser.cc ('k') | src/preparser.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698