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}
This commit is contained in:
parent
5cd84502bf
commit
9acfd4fe08
@ -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,
|
||||
|
@ -954,74 +954,73 @@ TEST(ScopeUsesArgumentsSuperThis) {
|
||||
const char* suffix;
|
||||
} surroundings[] = {
|
||||
{ "function f() {", "}" },
|
||||
{ "var f = () => {", "}" },
|
||||
{ "var f = () => {", "};" },
|
||||
{ "class C { constructor() {", "} }" },
|
||||
};
|
||||
|
||||
enum Expected {
|
||||
NONE = 0,
|
||||
ARGUMENTS = 1,
|
||||
SUPER_PROPERTY = 2,
|
||||
SUPER_CONSTRUCTOR_CALL = 4,
|
||||
THIS = 8,
|
||||
INNER_ARGUMENTS = 16,
|
||||
INNER_SUPER_PROPERTY = 32,
|
||||
INNER_SUPER_CONSTRUCTOR_CALL = 64,
|
||||
INNER_THIS = 128
|
||||
SUPER_PROPERTY = 1 << 1,
|
||||
SUPER_CONSTRUCTOR_CALL = 1 << 2,
|
||||
THIS = 1 << 3,
|
||||
INNER_ARGUMENTS = 1 << 4,
|
||||
INNER_SUPER_PROPERTY = 1 << 5,
|
||||
INNER_SUPER_CONSTRUCTOR_CALL = 1 << 6,
|
||||
INNER_THIS = 1 << 7
|
||||
};
|
||||
|
||||
static const struct {
|
||||
const char* body;
|
||||
int expected;
|
||||
} source_data[] = {
|
||||
{"", NONE},
|
||||
{"return this", THIS},
|
||||
{"return arguments", ARGUMENTS},
|
||||
{"return super()", SUPER_CONSTRUCTOR_CALL},
|
||||
{"return super.x", SUPER_PROPERTY},
|
||||
{"return arguments[0]", ARGUMENTS},
|
||||
{"return this + arguments[0]", ARGUMENTS | THIS},
|
||||
{"return this + arguments[0] + super.x",
|
||||
ARGUMENTS | SUPER_PROPERTY | THIS},
|
||||
{"return x => this + x", INNER_THIS},
|
||||
{"return x => super() + x", INNER_SUPER_CONSTRUCTOR_CALL},
|
||||
{"this.foo = 42;", THIS},
|
||||
{"this.foo();", THIS},
|
||||
{"if (foo()) { this.f() }", THIS},
|
||||
{"if (foo()) { super.f() }", SUPER_PROPERTY},
|
||||
{"if (arguments.length) { this.f() }", ARGUMENTS | THIS},
|
||||
{"while (true) { this.f() }", THIS},
|
||||
{"while (true) { super.f() }", SUPER_PROPERTY},
|
||||
{"if (true) { while (true) this.foo(arguments) }", ARGUMENTS | THIS},
|
||||
// Multiple nesting levels must work as well.
|
||||
{"while (true) { while (true) { while (true) return this } }", THIS},
|
||||
{"while (true) { while (true) { while (true) return super() } }",
|
||||
SUPER_CONSTRUCTOR_CALL},
|
||||
{"if (1) { return () => { while (true) new this() } }", INNER_THIS},
|
||||
{"if (1) { return () => { while (true) new super() } }", NONE},
|
||||
{"if (1) { return () => { while (true) new new super() } }", NONE},
|
||||
// Note that propagation of the inner_uses_this() value does not
|
||||
// cross boundaries of normal functions onto parent scopes.
|
||||
{"return function (x) { return this + x }", NONE},
|
||||
{"return function (x) { return super() + x }", NONE},
|
||||
{"var x = function () { this.foo = 42 };", NONE},
|
||||
{"var x = function () { super.foo = 42 };", NONE},
|
||||
{"if (1) { return function () { while (true) new this() } }", NONE},
|
||||
{"if (1) { return function () { while (true) new super() } }", NONE},
|
||||
{"return function (x) { return () => this }", NONE},
|
||||
{"return function (x) { return () => super() }", NONE},
|
||||
// Flags must be correctly set when using block scoping.
|
||||
{"\"use strict\"; while (true) { let x; this, arguments; }",
|
||||
INNER_ARGUMENTS | INNER_THIS},
|
||||
{"\"use strict\"; while (true) { let x; this, super(), arguments; }",
|
||||
INNER_ARGUMENTS | INNER_SUPER_CONSTRUCTOR_CALL | INNER_THIS},
|
||||
{"\"use strict\"; if (foo()) { let x; this.f() }", INNER_THIS},
|
||||
{"\"use strict\"; if (foo()) { let x; super.f() }",
|
||||
INNER_SUPER_PROPERTY},
|
||||
{"\"use strict\"; if (1) {"
|
||||
" let x; return function () { return this + super() + arguments }"
|
||||
"}",
|
||||
NONE},
|
||||
};
|
||||
{"", NONE},
|
||||
{"return this", THIS},
|
||||
{"return arguments", ARGUMENTS},
|
||||
{"return super()", SUPER_CONSTRUCTOR_CALL},
|
||||
{"return super.x", SUPER_PROPERTY},
|
||||
{"return arguments[0]", ARGUMENTS},
|
||||
{"return this + arguments[0]", ARGUMENTS | THIS},
|
||||
{"return this + arguments[0] + super.x",
|
||||
ARGUMENTS | SUPER_PROPERTY | THIS},
|
||||
{"return x => this + x", INNER_THIS},
|
||||
{"return x => super() + x", INNER_SUPER_CONSTRUCTOR_CALL},
|
||||
{"this.foo = 42;", THIS},
|
||||
{"this.foo();", THIS},
|
||||
{"if (foo()) { this.f() }", THIS},
|
||||
{"if (foo()) { super.f() }", SUPER_PROPERTY},
|
||||
{"if (arguments.length) { this.f() }", ARGUMENTS | THIS},
|
||||
{"while (true) { this.f() }", THIS},
|
||||
{"while (true) { super.f() }", SUPER_PROPERTY},
|
||||
{"if (true) { while (true) this.foo(arguments) }", ARGUMENTS | THIS},
|
||||
// Multiple nesting levels must work as well.
|
||||
{"while (true) { while (true) { while (true) return this } }", THIS},
|
||||
{"while (true) { while (true) { while (true) return super() } }",
|
||||
SUPER_CONSTRUCTOR_CALL},
|
||||
{"if (1) { return () => { while (true) new this() } }", INNER_THIS},
|
||||
// Note that propagation of the inner_uses_this() value does not
|
||||
// cross boundaries of normal functions onto parent scopes.
|
||||
{"return function (x) { return this + x }", NONE},
|
||||
{"return { m(x) { return super.m() + x } }", NONE},
|
||||
{"var x = function () { this.foo = 42 };", NONE},
|
||||
{"var x = { m() { super.foo = 42 } };", NONE},
|
||||
{"if (1) { return function () { while (true) new this() } }", NONE},
|
||||
{"if (1) { return { m() { while (true) super.m() } } }", NONE},
|
||||
{"return function (x) { return () => this }", NONE},
|
||||
{"return { m(x) { return () => super.m() } }", NONE},
|
||||
// Flags must be correctly set when using block scoping.
|
||||
{"\"use strict\"; while (true) { let x; this, arguments; }",
|
||||
INNER_ARGUMENTS | INNER_THIS},
|
||||
{"\"use strict\"; while (true) { let x; this, super(), arguments; }",
|
||||
INNER_ARGUMENTS | INNER_SUPER_CONSTRUCTOR_CALL | INNER_THIS},
|
||||
{"\"use strict\"; if (foo()) { let x; this.f() }", INNER_THIS},
|
||||
{"\"use strict\"; if (foo()) { let x; super.f() }",
|
||||
INNER_SUPER_PROPERTY},
|
||||
{"\"use strict\"; if (1) {"
|
||||
" let x; return { m() { return this + super.m() + arguments } }"
|
||||
"}",
|
||||
NONE},
|
||||
};
|
||||
|
||||
i::Isolate* isolate = CcTest::i_isolate();
|
||||
i::Factory* factory = isolate->factory();
|
||||
@ -1035,6 +1034,15 @@ TEST(ScopeUsesArgumentsSuperThis) {
|
||||
|
||||
for (unsigned j = 0; j < arraysize(surroundings); ++j) {
|
||||
for (unsigned i = 0; i < arraysize(source_data); ++i) {
|
||||
// Super constructor call is only allowed in constructor.
|
||||
// Super property is only allowed in constructor and method.
|
||||
if (((source_data[i].expected & SUPER_CONSTRUCTOR_CALL) ||
|
||||
(source_data[i].expected & SUPER_PROPERTY) ||
|
||||
(source_data[i].expected & INNER_SUPER_CONSTRUCTOR_CALL) ||
|
||||
(source_data[i].expected & INNER_SUPER_PROPERTY) ||
|
||||
(source_data[i].expected == NONE)) && j != 2) {
|
||||
continue;
|
||||
}
|
||||
int kProgramByteSize = i::StrLength(surroundings[j].prefix) +
|
||||
i::StrLength(surroundings[j].suffix) +
|
||||
i::StrLength(source_data[i].body);
|
||||
@ -1052,9 +1060,11 @@ TEST(ScopeUsesArgumentsSuperThis) {
|
||||
i::Parser parser(&info, &parse_info);
|
||||
parser.set_allow_harmony_arrow_functions(true);
|
||||
parser.set_allow_harmony_classes(true);
|
||||
parser.set_allow_harmony_object_literals(true);
|
||||
parser.set_allow_harmony_scoping(true);
|
||||
parser.set_allow_harmony_sloppy(true);
|
||||
info.MarkAsGlobal();
|
||||
parser.Parse();
|
||||
CHECK(parser.Parse());
|
||||
CHECK(i::Rewriter::Rewrite(&info));
|
||||
CHECK(i::Scope::Analyze(&info));
|
||||
CHECK(info.function() != NULL);
|
||||
@ -1064,6 +1074,11 @@ TEST(ScopeUsesArgumentsSuperThis) {
|
||||
CHECK_EQ(1, script_scope->inner_scopes()->length());
|
||||
|
||||
i::Scope* scope = script_scope->inner_scopes()->at(0);
|
||||
// Adjust for constructor scope.
|
||||
if (j == 2) {
|
||||
CHECK_EQ(1, scope->inner_scopes()->length());
|
||||
scope = scope->inner_scopes()->at(0);
|
||||
}
|
||||
CHECK_EQ((source_data[i].expected & ARGUMENTS) != 0,
|
||||
scope->uses_arguments());
|
||||
CHECK_EQ((source_data[i].expected & SUPER_PROPERTY) != 0,
|
||||
@ -3637,45 +3652,224 @@ TEST(NoErrorsArrowFunctions) {
|
||||
}
|
||||
|
||||
|
||||
TEST(NoErrorsSuper) {
|
||||
TEST(SuperNoErrors) {
|
||||
// Tests that parser and preparser accept 'super' keyword in right places.
|
||||
const char* context_data[][2] = {{"", ";"},
|
||||
{"k = ", ";"},
|
||||
{"foo(", ");"},
|
||||
{NULL, NULL}};
|
||||
const char* context_data[][2] = {
|
||||
{"class C { m() { ", "; } }"},
|
||||
{"class C { m() { k = ", "; } }"},
|
||||
{"class C { m() { foo(", "); } }"},
|
||||
{"class C { m() { () => ", "; } }"},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
const char* statement_data[] = {
|
||||
"super.x",
|
||||
"super[27]",
|
||||
"new super.x",
|
||||
"new super.x()",
|
||||
"new super[27]",
|
||||
"new super[27]()",
|
||||
"z.super", // Ok, property lookup.
|
||||
NULL
|
||||
};
|
||||
|
||||
static const ParserFlag always_flags[] = {
|
||||
kAllowHarmonyArrowFunctions,
|
||||
kAllowHarmonyClasses,
|
||||
kAllowHarmonyObjectLiterals,
|
||||
kAllowHarmonySloppy
|
||||
};
|
||||
RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
|
||||
always_flags, arraysize(always_flags));
|
||||
}
|
||||
|
||||
|
||||
TEST(SuperErrors) {
|
||||
const char* context_data[][2] = {
|
||||
{"class C { m() { ", "; } }"},
|
||||
{"class C { m() { k = ", "; } }"},
|
||||
{"class C { m() { foo(", "); } }"},
|
||||
{"class C { m() { () => ", "; } }"},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
const char* expression_data[] = {
|
||||
"super",
|
||||
"super = x",
|
||||
"y = super",
|
||||
"f(super)",
|
||||
"new super",
|
||||
"new super()",
|
||||
"new super(12, 45)",
|
||||
"new new super",
|
||||
"new new super()",
|
||||
"new new super()()",
|
||||
"z.super", // Ok, property lookup.
|
||||
NULL};
|
||||
NULL
|
||||
};
|
||||
|
||||
static const ParserFlag always_flags[] = {kAllowHarmonyClasses};
|
||||
RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
|
||||
static const ParserFlag always_flags[] = {
|
||||
kAllowHarmonyClasses,
|
||||
kAllowHarmonyObjectLiterals,
|
||||
kAllowHarmonySloppy
|
||||
};
|
||||
RunParserSyncTest(context_data, expression_data, kError, NULL, 0,
|
||||
always_flags, arraysize(always_flags));
|
||||
}
|
||||
|
||||
|
||||
TEST(ErrorsSuper) {
|
||||
// Tests that parser and preparser generate same errors for 'super'.
|
||||
const char* context_data[][2] = {{"", ";"},
|
||||
{"k = ", ";"},
|
||||
{"foo(", ");"},
|
||||
TEST(SuperCall) {
|
||||
const char* context_data[][2] = {{"", ""},
|
||||
{NULL, NULL}};
|
||||
|
||||
const char* success_data[] = {
|
||||
"class C { constructor() { super(); } }",
|
||||
"class C extends B { constructor() { super(); } }",
|
||||
"class C extends B { constructor() { () => super(); } }",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const ParserFlag always_flags[] = {
|
||||
kAllowHarmonyArrowFunctions,
|
||||
kAllowHarmonyClasses,
|
||||
kAllowHarmonyObjectLiterals,
|
||||
kAllowHarmonySloppy
|
||||
};
|
||||
RunParserSyncTest(context_data, success_data, kSuccess, NULL, 0,
|
||||
always_flags, arraysize(always_flags));
|
||||
|
||||
const char* error_data[] = {
|
||||
"class C { method() { super(); } }",
|
||||
"class C { method() { () => super(); } }",
|
||||
"class C { *method() { super(); } }",
|
||||
"class C { get x() { super(); } }",
|
||||
"class C { set x(_) { super(); } }",
|
||||
"({ method() { super(); } })",
|
||||
"({ *method() { super(); } })",
|
||||
"({ get x() { super(); } })",
|
||||
"({ set x(_) { super(); } })",
|
||||
"({ f: function() { super(); } })",
|
||||
"(function() { super(); })",
|
||||
"var f = function() { super(); }",
|
||||
"({ f: function*() { super(); } })",
|
||||
"(function*() { super(); })",
|
||||
"var f = function*() { super(); }",
|
||||
NULL
|
||||
};
|
||||
|
||||
RunParserSyncTest(context_data, error_data, kError, NULL, 0,
|
||||
always_flags, arraysize(always_flags));
|
||||
}
|
||||
|
||||
|
||||
TEST(SuperNewNoErrors) {
|
||||
const char* context_data[][2] = {
|
||||
{"class C { constructor() { ", " } }"},
|
||||
{"class C { *method() { ", " } }"},
|
||||
{"class C { get x() { ", " } }"},
|
||||
{"class C { set x(_) { ", " } }"},
|
||||
{"({ method() { ", " } })"},
|
||||
{"({ *method() { ", " } })"},
|
||||
{"({ get x() { ", " } })"},
|
||||
{"({ set x(_) { ", " } })"},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
const char* expression_data[] = {
|
||||
"new super.x;",
|
||||
"new super.x();",
|
||||
"() => new super.x;",
|
||||
"() => new super.x();",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const ParserFlag always_flags[] = {
|
||||
kAllowHarmonyArrowFunctions,
|
||||
kAllowHarmonyClasses,
|
||||
kAllowHarmonyObjectLiterals,
|
||||
kAllowHarmonySloppy
|
||||
};
|
||||
RunParserSyncTest(context_data, expression_data, kSuccess, NULL, 0,
|
||||
always_flags, arraysize(always_flags));
|
||||
}
|
||||
|
||||
|
||||
TEST(SuperNewErrors) {
|
||||
const char* context_data[][2] = {
|
||||
{"class C { method() { ", " } }"},
|
||||
{"class C { *method() { ", " } }"},
|
||||
{"class C { get x() { ", " } }"},
|
||||
{"class C { set x(_) { ", " } }"},
|
||||
{"({ method() { ", " } })"},
|
||||
{"({ *method() { ", " } })"},
|
||||
{"({ get x() { ", " } })"},
|
||||
{"({ set x(_) { ", " } })"},
|
||||
{"({ f: function() { ", " } })"},
|
||||
{"(function() { ", " })"},
|
||||
{"var f = function() { ", " }"},
|
||||
{"({ f: function*() { ", " } })"},
|
||||
{"(function*() { ", " })"},
|
||||
{"var f = function*() { ", " }"},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
const char* statement_data[] = {
|
||||
"new super;",
|
||||
"new super();",
|
||||
"() => new super;",
|
||||
"() => new super();",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const ParserFlag always_flags[] = {
|
||||
kAllowHarmonyArrowFunctions,
|
||||
kAllowHarmonyClasses,
|
||||
kAllowHarmonyObjectLiterals,
|
||||
kAllowHarmonySloppy
|
||||
};
|
||||
RunParserSyncTest(context_data, statement_data, kError, NULL, 0,
|
||||
always_flags, arraysize(always_flags));
|
||||
}
|
||||
|
||||
|
||||
TEST(SuperErrorsNonMethods) {
|
||||
// super is only allowed in methods, accessors and constructors.
|
||||
const char* context_data[][2] = {
|
||||
{"", ";"},
|
||||
{"k = ", ";"},
|
||||
{"foo(", ");"},
|
||||
{"if (", ") {}"},
|
||||
{"if (true) {", "}"},
|
||||
{"if (false) {} else {", "}"},
|
||||
{"while (true) {", "}"},
|
||||
{"function f() {", "}"},
|
||||
{"class C extends (", ") {}"},
|
||||
{"class C { m() { function f() {", "} } }"},
|
||||
{"({ m() { function f() {", "} } })"},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
const char* statement_data[] = {
|
||||
"super",
|
||||
"super = x",
|
||||
"y = super",
|
||||
"f(super)",
|
||||
NULL};
|
||||
"super.x",
|
||||
"super[27]",
|
||||
"super.x()",
|
||||
"super[27]()",
|
||||
"super()",
|
||||
"new super.x",
|
||||
"new super.x()",
|
||||
"new super[27]",
|
||||
"new super[27]()",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const ParserFlag always_flags[] = {kAllowHarmonyClasses};
|
||||
static const ParserFlag always_flags[] = {
|
||||
kAllowHarmonyClasses,
|
||||
kAllowHarmonyObjectLiterals,
|
||||
kAllowHarmonySloppy
|
||||
};
|
||||
RunParserSyncTest(context_data, statement_data, kError, NULL, 0,
|
||||
always_flags, arraysize(always_flags));
|
||||
}
|
||||
|
@ -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);
|
||||
})();
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user