Commit 9acfd4fe authored by arv's avatar arv Committed by Commit bot

super is only allowed in methods, accessors and constructor

super() is only allowed in a class constructor.
super.p is allowed in methods, accessors and constructors.

The parser now checks the FunctionState to see what kind of function
we are currently inside.

BUG=v8:3330
LOG=N
R=dslomov@chromium.org, marja@chromium.org

Review URL: https://codereview.chromium.org/915563003

Cr-Commit-Position: refs/heads/master@{#26557}
parent 5cd84502
......@@ -217,6 +217,7 @@ class ParserBase : public Traits {
bool is_generator() const { return IsGeneratorFunction(kind_); }
FunctionKind kind() const { return kind_; }
FunctionState* outer() const { return outer_function_state_; }
void set_generator_object_variable(
typename Traits::Type::GeneratorVariable* variable) {
......@@ -249,7 +250,6 @@ class ParserBase : public Traits {
// for generator functions to have this variable set.
Variable* generator_object_variable_;
FunctionState** function_state_stack_;
FunctionState* outer_function_state_;
Scope** scope_stack_;
......@@ -569,6 +569,7 @@ class ParserBase : public Traits {
bool* ok);
ExpressionT ParseTemplateLiteral(ExpressionT tag, int start, bool* ok);
void AddTemplateExpression(ExpressionT);
ExpressionT ParseSuperExpression(bool is_new, 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,
......@@ -2666,8 +2667,9 @@ ParserBase<Traits>::ParseMemberWithNewPrefixesExpression(bool* ok) {
Consume(Token::NEW);
int new_pos = position();
ExpressionT result = this->EmptyExpression();
if (Check(Token::SUPER)) {
result = this->SuperReference(scope_, factory());
if (peek() == Token::SUPER) {
const bool is_new = true;
result = ParseSuperExpression(is_new, CHECK_OK);
} else {
result = this->ParseMemberWithNewPrefixesExpression(CHECK_OK);
}
......@@ -2724,21 +2726,8 @@ ParserBase<Traits>::ParseMemberExpression(bool* ok) {
function_token_position, function_type, FunctionLiteral::NORMAL_ARITY,
CHECK_OK);
} else if (peek() == Token::SUPER) {
int beg_pos = position();
Consume(Token::SUPER);
Token::Value next = peek();
if (next == Token::PERIOD || next == Token::LBRACK) {
scope_->RecordSuperPropertyUsage();
result = this->SuperReference(scope_, factory());
} else if (next == Token::LPAREN) {
scope_->RecordSuperConstructorCallUsage();
result = this->SuperReference(scope_, factory());
} else {
ReportMessageAt(Scanner::Location(beg_pos, position()),
"unexpected_super");
*ok = false;
return this->EmptyExpression();
}
const bool is_new = false;
result = ParseSuperExpression(is_new, CHECK_OK);
} else {
result = ParsePrimaryExpression(CHECK_OK);
}
......@@ -2748,6 +2737,39 @@ ParserBase<Traits>::ParseMemberExpression(bool* ok) {
}
template <class Traits>
typename ParserBase<Traits>::ExpressionT
ParserBase<Traits>::ParseSuperExpression(bool is_new, bool* ok) {
int beg_pos = position();
Expect(Token::SUPER, CHECK_OK);
FunctionState* function_state = function_state_;
while (IsArrowFunction(function_state->kind())) {
function_state = function_state->outer();
}
// TODO(arv): Handle eval scopes similarly.
FunctionKind kind = function_state->kind();
if (IsConciseMethod(kind) || IsAccessorFunction(kind) ||
i::IsConstructor(kind)) {
if (peek() == Token::PERIOD || peek() == Token::LBRACK) {
scope_->RecordSuperPropertyUsage();
return this->SuperReference(scope_, factory());
}
// new super() is never allowed.
// super() is only allowed in constructor
if (!is_new && peek() == Token::LPAREN && i::IsConstructor(kind)) {
scope_->RecordSuperConstructorCallUsage();
return this->SuperReference(scope_, factory());
}
}
ReportMessageAt(Scanner::Location(beg_pos, position()), "unexpected_super");
*ok = false;
return this->EmptyExpression();
}
template <class Traits>
typename ParserBase<Traits>::ExpressionT
ParserBase<Traits>::ParseMemberExpressionContinuation(ExpressionT expression,
......
This diff is collapsed.
......@@ -874,10 +874,4 @@ function assertAccessorDescriptor(object, name) {
}
};
new C3();
class C4 extends Object {
constructor() {
super(new super());
}
}; new C4();
}());
......@@ -22,15 +22,6 @@
set accessor(v) {
super.accessor = v;
},
property: function() {
super.property();
},
propertyWithParen: (function() {
super.property();
}),
propertyWithParens: ((function() {
super.property();
})),
methodNoSuper() {},
get getterNoSuper() {},
......@@ -50,9 +41,6 @@
desc = Object.getOwnPropertyDescriptor(object, 'accessor');
assertEquals(object, desc.get[%HomeObjectSymbol()]);
assertEquals(object, desc.set[%HomeObjectSymbol()]);
assertEquals(object, object.property[%HomeObjectSymbol()]);
assertEquals(object, object.propertyWithParen[%HomeObjectSymbol()]);
assertEquals(object, object.propertyWithParens[%HomeObjectSymbol()]);
assertEquals(undefined, object.methodNoSuper[%HomeObjectSymbol()]);
desc = Object.getOwnPropertyDescriptor(object, 'getterNoSuper');
......@@ -118,21 +106,6 @@
})();
(function TestMethodAsProperty() {
var object = {
__proto__: {
method: function(x) {
return 'proto' + x;
}
},
method: function(x) {
return super.method(x);
}
};
assertEquals('proto42', object.method(42));
})();
(function TestOptimized() {
// Object literals without any accessors get optimized.
var object = {
......@@ -154,15 +127,7 @@
*g() {
yield super.m();
},
g2: function*() {
yield super.m() + 1;
},
g3: (function*() {
yield super.m() + 2;
})
};
assertEquals(42, o.g().next().value);
assertEquals(43, o.g2().next().value);
assertEquals(44, o.g3().next().value);
})();
This diff is collapsed.
......@@ -117,6 +117,7 @@
# TODO(arv): TurboFan does not yet add [[HomeObject]] as needed.
'harmony/object-literals-super': [PASS, NO_VARIANTS],
'harmony/super': [PASS, NO_VARIANTS],
##############################################################################
# Too slow in debug mode with --stress-opt mode.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment