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

Unified Diff: test/cctest/test-parsing.cc

Issue 915563003: super is only allowed in methods, accessors and constructor (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Use i:: to qualify function name Created 5 years, 10 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/preparser.h ('k') | test/mjsunit/harmony/classes.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: test/cctest/test-parsing.cc
diff --git a/test/cctest/test-parsing.cc b/test/cctest/test-parsing.cc
index ba2fa975fd7ad7728098686d2941e03fe279959f..a59566bd8003ac5175acbff69fccf0d867395204 100644
--- a/test/cctest/test-parsing.cc
+++ b/test/cctest/test-parsing.cc
@@ -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));
}
« no previous file with comments | « src/preparser.h ('k') | test/mjsunit/harmony/classes.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698