mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-27 12:15:33 +00:00
Bug 1066233 - Tests. (r=jorendorff)
This commit is contained in:
parent
3ba28c5305
commit
ad9c2fb296
@ -4,6 +4,9 @@ var test = `
|
||||
assertThrowsInstanceOf(() => eval(\`class a extends Math.sin {
|
||||
constructor() { }
|
||||
}\`), TypeError);
|
||||
assertThrowsInstanceOf(() => eval(\`(class a extends Math.sin {
|
||||
constructor() { }
|
||||
})\`), TypeError);
|
||||
|
||||
// Unless it's null, in which case it works like a normal class, except that
|
||||
// the prototype object does not inherit from Object.prototype.
|
||||
@ -13,14 +16,19 @@ class basic {
|
||||
class nullExtends extends null {
|
||||
constructor() { }
|
||||
}
|
||||
assertEq(Object.getPrototypeOf(basic), Function.prototype);
|
||||
assertEq(Object.getPrototypeOf(nullExtends), Function.prototype);
|
||||
assertEq(Object.getPrototypeOf(basic.prototype), Object.prototype);
|
||||
assertEq(Object.getPrototypeOf(nullExtends.prototype), null);
|
||||
var nullExtendsExpr = class extends null { constructor() { } };
|
||||
|
||||
var baseMethodCalled = false;
|
||||
var staticMethodCalled = false;
|
||||
var overrideCalled = "";
|
||||
assertEq(Object.getPrototypeOf(basic), Function.prototype);
|
||||
assertEq(Object.getPrototypeOf(basic.prototype), Object.prototype);
|
||||
|
||||
for (let extension of [nullExtends, nullExtendsExpr]) {
|
||||
assertEq(Object.getPrototypeOf(extension), Function.prototype);
|
||||
assertEq(Object.getPrototypeOf(extension.prototype), null);
|
||||
}
|
||||
|
||||
var baseMethodCalled;
|
||||
var staticMethodCalled;
|
||||
var overrideCalled;
|
||||
class base {
|
||||
constructor() { };
|
||||
method() { baseMethodCalled = true; }
|
||||
@ -31,22 +39,32 @@ class derived extends base {
|
||||
constructor() { };
|
||||
override() { overrideCalled = "derived"; }
|
||||
}
|
||||
var derivedExpr = class extends base {
|
||||
constructor() { };
|
||||
override() { overrideCalled = "derived"; }
|
||||
};
|
||||
|
||||
// Make sure we get the right object layouts.
|
||||
assertEq(Object.getPrototypeOf(derived), base);
|
||||
assertEq(Object.getPrototypeOf(derived.prototype), base.prototype);
|
||||
for (let extension of [derived, derivedExpr]) {
|
||||
baseMethodCalled = false;
|
||||
staticMethodCalled = false;
|
||||
overrideCalled = "";
|
||||
// Make sure we get the right object layouts.
|
||||
assertEq(Object.getPrototypeOf(extension), base);
|
||||
assertEq(Object.getPrototypeOf(extension.prototype), base.prototype);
|
||||
|
||||
// We do inherit the methods, right?
|
||||
(new derived()).method();
|
||||
assertEq(baseMethodCalled, true);
|
||||
// We do inherit the methods, right?
|
||||
(new extension()).method();
|
||||
assertEq(baseMethodCalled, true);
|
||||
|
||||
// But we can still override them?
|
||||
(new derived()).override();
|
||||
assertEq(overrideCalled, "derived");
|
||||
// But we can still override them?
|
||||
(new extension()).override();
|
||||
assertEq(overrideCalled, "derived");
|
||||
|
||||
// What about the statics?
|
||||
derived.staticMethod();
|
||||
assertEq(staticMethodCalled, true);
|
||||
// What about the statics?
|
||||
extension.staticMethod();
|
||||
assertEq(staticMethodCalled, true);
|
||||
}
|
||||
|
||||
// Gotta extend an object, or null.
|
||||
function nope() {
|
||||
@ -54,7 +72,13 @@ function nope() {
|
||||
constructor() { }
|
||||
}
|
||||
}
|
||||
function nopeExpr() {
|
||||
(class extends "Bar" {
|
||||
constructor() { }
|
||||
});
|
||||
}
|
||||
assertThrowsInstanceOf(nope, TypeError);
|
||||
assertThrowsInstanceOf(nopeExpr, TypeError);
|
||||
|
||||
// The .prototype of the extension must be an object, or null.
|
||||
nope.prototype = "not really, no";
|
||||
@ -63,7 +87,13 @@ function stillNo() {
|
||||
constructor() { }
|
||||
}
|
||||
}
|
||||
function stillNoExpr() {
|
||||
(class extends nope {
|
||||
constructor() { }
|
||||
});
|
||||
}
|
||||
assertThrowsInstanceOf(stillNo, TypeError);
|
||||
assertThrowsInstanceOf(stillNoExpr, TypeError);
|
||||
|
||||
`;
|
||||
|
||||
|
@ -2,22 +2,25 @@ var test = `
|
||||
|
||||
// The prototype of a class is a non-writable, non-configurable, non-enumerable data property.
|
||||
class a { constructor() { } }
|
||||
var protoDesc = Object.getOwnPropertyDescriptor(a, "prototype");
|
||||
assertEq(protoDesc.writable, false);
|
||||
assertEq(protoDesc.configurable, false);
|
||||
assertEq(protoDesc.enumerable, false);
|
||||
let b = class { constructor() { } };
|
||||
for (let test of [a,b]) {
|
||||
var protoDesc = Object.getOwnPropertyDescriptor(test, "prototype");
|
||||
assertEq(protoDesc.writable, false);
|
||||
assertEq(protoDesc.configurable, false);
|
||||
assertEq(protoDesc.enumerable, false);
|
||||
|
||||
var prototype = protoDesc.value;
|
||||
assertEq(typeof prototype, "object");
|
||||
assertEq(Object.getPrototypeOf(prototype), Object.prototype);
|
||||
assertEq(Object.isExtensible(prototype), true);
|
||||
var prototype = protoDesc.value;
|
||||
assertEq(typeof prototype, "object");
|
||||
assertEq(Object.getPrototypeOf(prototype), Object.prototype);
|
||||
assertEq(Object.isExtensible(prototype), true);
|
||||
|
||||
var desiredPrototype = {};
|
||||
Object.defineProperty(desiredPrototype, "constructor", { writable: true,
|
||||
configurable: true,
|
||||
enumerable: false,
|
||||
value: a });
|
||||
assertDeepEq(prototype, desiredPrototype);
|
||||
var desiredPrototype = {};
|
||||
Object.defineProperty(desiredPrototype, "constructor", { writable: true,
|
||||
configurable: true,
|
||||
enumerable: false,
|
||||
value: test });
|
||||
assertDeepEq(prototype, desiredPrototype);
|
||||
}
|
||||
|
||||
try {
|
||||
eval(\`class a {
|
||||
@ -50,6 +53,25 @@ assertThrowsInstanceOf(() => eval(\`
|
||||
static set ["prototype"](x) { }
|
||||
}
|
||||
\`), TypeError);
|
||||
|
||||
assertThrowsInstanceOf(() => eval(\`(
|
||||
class a {
|
||||
constructor() { };
|
||||
static ["prototype"]() { }
|
||||
}
|
||||
)\`), TypeError);
|
||||
assertThrowsInstanceOf(() => eval(\`(
|
||||
class a {
|
||||
constructor() { };
|
||||
static get ["prototype"]() { }
|
||||
}
|
||||
)\`), TypeError);
|
||||
assertThrowsInstanceOf(() => eval(\`(
|
||||
class a {
|
||||
constructor() { };
|
||||
static set ["prototype"](x) { }
|
||||
}
|
||||
)\`), TypeError);
|
||||
*/
|
||||
}
|
||||
`;
|
||||
|
@ -8,20 +8,40 @@ class a { constructor(x) { assertEq(x, 4); called = true } }
|
||||
new a(4);
|
||||
assertEq(called, true);
|
||||
|
||||
called = false;
|
||||
var aExpr = class { constructor(x) { assertEq(x, 4); called = true } };
|
||||
new aExpr(4);
|
||||
assertEq(called, true);
|
||||
|
||||
called = false;
|
||||
class b { constructor() { called = true } method() { } }
|
||||
new b();
|
||||
assertEq(called, true);
|
||||
|
||||
called = false;
|
||||
var bExpr = class { constructor() { called = true } method() { } };
|
||||
new bExpr();
|
||||
assertEq(called, true);
|
||||
|
||||
called = false;
|
||||
class c { method() { } constructor() { called = true; } }
|
||||
new c();
|
||||
assertEq(called, true);
|
||||
|
||||
called = false;
|
||||
var cExpr = class { method() { } constructor() { called = true; } }
|
||||
new cExpr();
|
||||
assertEq(called, true);
|
||||
|
||||
called = false;
|
||||
class d { [\"constructor\"]() { throw new Error(\"NO\"); } constructor() { called = true; } }
|
||||
new d();
|
||||
assertEq(called, true);
|
||||
|
||||
called = false;
|
||||
var dExpr = class { [\"constructor\"]() { throw new Error(\"NO\"); } constructor() { called = true; } }
|
||||
new dExpr();
|
||||
assertEq(called, true);
|
||||
`;
|
||||
|
||||
if (classesEnabled())
|
||||
|
@ -1,23 +1,36 @@
|
||||
// Class statements should create an immutable inner binding. Since all code in
|
||||
// classes is in strict mode, attempts to mutate it should throw.
|
||||
// Named class definitions should create an immutable inner binding.
|
||||
// Since all code in classes is in strict mode, attempts to mutate it
|
||||
// should throw.
|
||||
|
||||
if (classesEnabled()) {
|
||||
|
||||
// XXXefaust Because we currently try to do assignment to const as an early error,
|
||||
// this is a syntax error. It is specced to be a TypeError
|
||||
// XXXefaust Because we currently try to do assignment to const as an early
|
||||
// error, sometimes, maybe, this is almost sometimes a syntax error.
|
||||
// It is specced to be a TypeError
|
||||
|
||||
function syntaxWrapper() {
|
||||
function statementWrapper() {
|
||||
eval("class Foo { constructor() { } tryBreak() { Foo = 4; } }");
|
||||
}
|
||||
assertThrowsInstanceOf(syntaxWrapper, SyntaxError);
|
||||
|
||||
function expressionWrapper() {
|
||||
// Mmmmm. Lazy parseing means we don't see this as an error until later.
|
||||
eval(`var x = class Foo { constructor() { }; tryBreak() { Foo = 4; } };
|
||||
new x().tryBreak();`);
|
||||
}
|
||||
|
||||
assertThrowsInstanceOf(statementWrapper, SyntaxError);
|
||||
assertThrowsInstanceOf(expressionWrapper, TypeError);
|
||||
|
||||
/*
|
||||
var test = `
|
||||
class Foo { constructor() { }; tryBreak() { Foo = 4; } }
|
||||
assertThrowsInstanceOf(() => new Foo().tryBreak(), TypeError);
|
||||
for (let result of [Foo, class Bar { constructor() { }; tryBreak() { Bar = 4; } }])
|
||||
assertThrowsInstanceOf(() => new result().tryBreak(), TypeError);
|
||||
|
||||
{
|
||||
class foo { constructor() { }; tryBreak() { foo = 4; } }
|
||||
assertThrowsInstanceOf(() => new foo().tryBreak(), TypeError);
|
||||
for (let result of [foo, class Bar { constructor() { }; tryBreak() { Bar = 4 }])
|
||||
assertThrowsInstanceOf(() => new result().tryBreak(), TypeError);
|
||||
}
|
||||
`;
|
||||
*/
|
||||
@ -30,6 +43,11 @@ assertThrowsInstanceOf(()=>eval(\`class Bar {
|
||||
[Bar] () { };
|
||||
}\`), ReferenceError);
|
||||
|
||||
assertThrowsInstanceOf(()=>eval(\`(class Bar {
|
||||
constructor() { };
|
||||
[Bar] () { };
|
||||
})\`), ReferenceError);
|
||||
|
||||
// There's no magic "inner binding" global
|
||||
{
|
||||
class Foo {
|
||||
@ -43,6 +61,15 @@ assertThrowsInstanceOf(()=>eval(\`class Bar {
|
||||
}
|
||||
}
|
||||
assertEq(new Foo().test(), false);
|
||||
assertEq(new class foo {
|
||||
constructor() { };
|
||||
test() {
|
||||
return new class bar {
|
||||
constructor() { }
|
||||
test() { return foo === bar }
|
||||
}().test();
|
||||
}
|
||||
}().test(), false);
|
||||
}
|
||||
|
||||
// Inner bindings are shadowable
|
||||
@ -52,8 +79,20 @@ assertThrowsInstanceOf(()=>eval(\`class Bar {
|
||||
test(Foo) { return Foo; }
|
||||
}
|
||||
assertEq(new Foo().test(4), 4);
|
||||
assertEq(new class foo {
|
||||
constructor() { };
|
||||
test(foo) { return foo }
|
||||
}().test(4), 4);
|
||||
}
|
||||
|
||||
// Inner bindings in expressions should shadow even existing names.
|
||||
class Foo { constructor() { } static method() { throw new Error("NO!"); } }
|
||||
assertEq(new class Foo {
|
||||
constructor() { };
|
||||
static method() { return 4; };
|
||||
test() { return Foo.method(); }
|
||||
}().test(), 4);
|
||||
|
||||
// The outer binding is distinct from the inner one
|
||||
{
|
||||
let orig_X;
|
||||
@ -68,6 +107,8 @@ assertThrowsInstanceOf(()=>eval(\`class Bar {
|
||||
assertEq(X, 13);
|
||||
new orig_X().f();
|
||||
}
|
||||
|
||||
|
||||
`;
|
||||
|
||||
eval(test);
|
||||
|
@ -2,14 +2,14 @@
|
||||
|
||||
var test= `
|
||||
|
||||
var methodCalled = false;
|
||||
var getterCalled = false;
|
||||
var setterCalled = false;
|
||||
var constructorCalled = false;
|
||||
var staticMethodCalled = false;
|
||||
var staticGetterCalled = false;
|
||||
var staticSetterCalled = false;
|
||||
class a {
|
||||
var methodCalled;
|
||||
var getterCalled;
|
||||
var setterCalled;
|
||||
var constructorCalled;
|
||||
var staticMethodCalled;
|
||||
var staticGetterCalled;
|
||||
var staticSetterCalled;
|
||||
class testClass {
|
||||
constructor() { constructorCalled = true; }
|
||||
__proto__() { methodCalled = true }
|
||||
get getter() { getterCalled = true; }
|
||||
@ -19,58 +19,80 @@ class a {
|
||||
static set staticSetter(x) { staticSetterCalled = true; }
|
||||
*[Symbol.iterator]() { yield "cow"; yield "pig"; }
|
||||
}
|
||||
var aConstDesc = Object.getOwnPropertyDescriptor(a.prototype, \"constructor\");
|
||||
assertEq(aConstDesc.writable, true);
|
||||
assertEq(aConstDesc.configurable, true);
|
||||
assertEq(aConstDesc.enumerable, false);
|
||||
aConstDesc.value();
|
||||
assertEq(constructorCalled, true);
|
||||
|
||||
// __proto__ is just an identifier for classes. No prototype changes are made.
|
||||
assertEq(Object.getPrototypeOf(a.prototype), Object.prototype);
|
||||
var aMethDesc = Object.getOwnPropertyDescriptor(a.prototype, \"__proto__\");
|
||||
assertEq(aMethDesc.writable, true);
|
||||
assertEq(aMethDesc.configurable, true);
|
||||
assertEq(aMethDesc.enumerable, true);
|
||||
aMethDesc.value();
|
||||
assertEq(methodCalled, true);
|
||||
for (let a of [testClass,
|
||||
class {
|
||||
constructor() { constructorCalled = true; }
|
||||
__proto__() { methodCalled = true }
|
||||
get getter() { getterCalled = true; }
|
||||
set setter(x) { setterCalled = true; }
|
||||
static staticMethod() { staticMethodCalled = true; }
|
||||
static get staticGetter() { staticGetterCalled = true; }
|
||||
static set staticSetter(x) { staticSetterCalled = true; }
|
||||
*[Symbol.iterator]() { yield "cow"; yield "pig"; }
|
||||
}]) {
|
||||
|
||||
var aGetDesc = Object.getOwnPropertyDescriptor(a.prototype, \"getter\");
|
||||
assertEq(aGetDesc.configurable, true);
|
||||
assertEq(aGetDesc.enumerable, true);
|
||||
aGetDesc.get();
|
||||
assertEq(getterCalled, true);
|
||||
methodCalled = false;
|
||||
getterCalled = false;
|
||||
setterCalled = false;
|
||||
constructorCalled = false;
|
||||
staticMethodCalled = false;
|
||||
staticGetterCalled = false;
|
||||
staticSetterCalled = false;
|
||||
|
||||
var aSetDesc = Object.getOwnPropertyDescriptor(a.prototype, \"setter\");
|
||||
assertEq(aSetDesc.configurable, true);
|
||||
assertEq(aSetDesc.enumerable, true);
|
||||
aSetDesc.set();
|
||||
assertEq(setterCalled, true);
|
||||
assertDeepEq(aSetDesc, Object.getOwnPropertyDescriptor(a.prototype, \"setter\"));
|
||||
var aConstDesc = Object.getOwnPropertyDescriptor(a.prototype, \"constructor\");
|
||||
assertEq(aConstDesc.writable, true);
|
||||
assertEq(aConstDesc.configurable, true);
|
||||
assertEq(aConstDesc.enumerable, false);
|
||||
aConstDesc.value();
|
||||
assertEq(constructorCalled, true);
|
||||
|
||||
assertEq(Object.getOwnPropertyDescriptor(new a(), \"staticMethod\"), undefined);
|
||||
var aStaticMethDesc = Object.getOwnPropertyDescriptor(a, \"staticMethod\");
|
||||
assertEq(aStaticMethDesc.configurable, true);
|
||||
assertEq(aStaticMethDesc.enumerable, true);
|
||||
assertEq(aStaticMethDesc.writable, true);
|
||||
aStaticMethDesc.value();
|
||||
assertEq(staticMethodCalled, true);
|
||||
// __proto__ is just an identifier for classes. No prototype changes are made.
|
||||
assertEq(Object.getPrototypeOf(a.prototype), Object.prototype);
|
||||
var aMethDesc = Object.getOwnPropertyDescriptor(a.prototype, \"__proto__\");
|
||||
assertEq(aMethDesc.writable, true);
|
||||
assertEq(aMethDesc.configurable, true);
|
||||
assertEq(aMethDesc.enumerable, true);
|
||||
aMethDesc.value();
|
||||
assertEq(methodCalled, true);
|
||||
|
||||
assertEq(Object.getOwnPropertyDescriptor(new a(), \"staticGetter\"), undefined);
|
||||
var aStaticGetDesc = Object.getOwnPropertyDescriptor(a, \"staticGetter\");
|
||||
assertEq(aStaticGetDesc.configurable, true);
|
||||
assertEq(aStaticGetDesc.enumerable, true);
|
||||
aStaticGetDesc.get();
|
||||
assertEq(staticGetterCalled, true);
|
||||
var aGetDesc = Object.getOwnPropertyDescriptor(a.prototype, \"getter\");
|
||||
assertEq(aGetDesc.configurable, true);
|
||||
assertEq(aGetDesc.enumerable, true);
|
||||
aGetDesc.get();
|
||||
assertEq(getterCalled, true);
|
||||
|
||||
assertEq(Object.getOwnPropertyDescriptor(new a(), \"staticSetter\"), undefined);
|
||||
var aStaticSetDesc = Object.getOwnPropertyDescriptor(a, \"staticSetter\");
|
||||
assertEq(aStaticSetDesc.configurable, true);
|
||||
assertEq(aStaticSetDesc.enumerable, true);
|
||||
aStaticSetDesc.set();
|
||||
assertEq(staticSetterCalled, true);
|
||||
var aSetDesc = Object.getOwnPropertyDescriptor(a.prototype, \"setter\");
|
||||
assertEq(aSetDesc.configurable, true);
|
||||
assertEq(aSetDesc.enumerable, true);
|
||||
aSetDesc.set();
|
||||
assertEq(setterCalled, true);
|
||||
assertDeepEq(aSetDesc, Object.getOwnPropertyDescriptor(a.prototype, \"setter\"));
|
||||
|
||||
assertEq([...new a()].join(), "cow,pig");
|
||||
assertEq(Object.getOwnPropertyDescriptor(new a(), \"staticMethod\"), undefined);
|
||||
var aStaticMethDesc = Object.getOwnPropertyDescriptor(a, \"staticMethod\");
|
||||
assertEq(aStaticMethDesc.configurable, true);
|
||||
assertEq(aStaticMethDesc.enumerable, true);
|
||||
assertEq(aStaticMethDesc.writable, true);
|
||||
aStaticMethDesc.value();
|
||||
assertEq(staticMethodCalled, true);
|
||||
|
||||
assertEq(Object.getOwnPropertyDescriptor(new a(), \"staticGetter\"), undefined);
|
||||
var aStaticGetDesc = Object.getOwnPropertyDescriptor(a, \"staticGetter\");
|
||||
assertEq(aStaticGetDesc.configurable, true);
|
||||
assertEq(aStaticGetDesc.enumerable, true);
|
||||
aStaticGetDesc.get();
|
||||
assertEq(staticGetterCalled, true);
|
||||
|
||||
assertEq(Object.getOwnPropertyDescriptor(new a(), \"staticSetter\"), undefined);
|
||||
var aStaticSetDesc = Object.getOwnPropertyDescriptor(a, \"staticSetter\");
|
||||
assertEq(aStaticSetDesc.configurable, true);
|
||||
assertEq(aStaticSetDesc.enumerable, true);
|
||||
aStaticSetDesc.set();
|
||||
assertEq(staticSetterCalled, true);
|
||||
|
||||
assertEq([...new a()].join(), "cow,pig");
|
||||
}
|
||||
`;
|
||||
|
||||
if (classesEnabled())
|
||||
|
@ -1,41 +1,83 @@
|
||||
// Ensure that we can overwrite methods when more tha one is present.
|
||||
|
||||
var test = `
|
||||
var result = 0;
|
||||
// Regardless of order, the constructor is overridden by any CPN, because it's
|
||||
// processed seperately.
|
||||
class a { [\"constructor\"]() { result += 1; }; constructor() { result += 2; } }
|
||||
var aInst = new a();
|
||||
assertEq(result, 2);
|
||||
aInst.constructor();
|
||||
assertEq(result, 3);
|
||||
|
||||
class b { constructor() { result += 2; } [\"constructor\"]() { result += 1; }; }
|
||||
var bInst = new b();
|
||||
assertEq(result, 5);
|
||||
bInst.constructor();
|
||||
assertEq(result, 6);
|
||||
{
|
||||
var result = 0;
|
||||
// Regardless of order, the constructor is overridden by any CPN, because it's
|
||||
// processed seperately.
|
||||
class a { [\"constructor\"]() { result += 1; }; constructor() { result += 2; } }
|
||||
var aInst = new a();
|
||||
assertEq(result, 2);
|
||||
aInst.constructor();
|
||||
assertEq(result, 3);
|
||||
|
||||
class c { constructor() { } method() { result += 1 } get method() { result += 2 } }
|
||||
new c().method;
|
||||
assertEq(result, 8);
|
||||
class b { constructor() { result += 2; } [\"constructor\"]() { result += 1; }; }
|
||||
var bInst = new b();
|
||||
assertEq(result, 5);
|
||||
bInst.constructor();
|
||||
assertEq(result, 6);
|
||||
|
||||
class d { constructor() { } get method() { result += 1 } method() { result += 2 } }
|
||||
new d().method();
|
||||
assertEq(result, 10);
|
||||
class c { constructor() { } method() { result += 1 } get method() { result += 2 } }
|
||||
new c().method;
|
||||
assertEq(result, 8);
|
||||
|
||||
// getters and setter should not overwrite each other, but merge cleanly.
|
||||
class e { constructor() { } get method() { result += 1 } set method(x) { } }
|
||||
new e().method;
|
||||
assertEq(result, 11);
|
||||
class d { constructor() { } get method() { result += 1 } method() { result += 2 } }
|
||||
new d().method();
|
||||
assertEq(result, 10);
|
||||
|
||||
class f { constructor() { }
|
||||
set method(x) { throw "NO"; }
|
||||
method() { throw "NO" }
|
||||
get method() { return new Function("result += 1"); }
|
||||
}
|
||||
new f().method();
|
||||
assertEq(result, 12);
|
||||
// getters and setter should not overwrite each other, but merge cleanly.
|
||||
class e { constructor() { } get method() { result += 1 } set method(x) { } }
|
||||
new e().method;
|
||||
assertEq(result, 11);
|
||||
|
||||
class f { constructor() { }
|
||||
set method(x) { throw "NO"; }
|
||||
method() { throw "NO" }
|
||||
get method() { return new Function("result += 1"); }
|
||||
}
|
||||
new f().method();
|
||||
assertEq(result, 12);
|
||||
}
|
||||
|
||||
// Try again with expressions.
|
||||
{
|
||||
var result = 0;
|
||||
// Regardless of order, the constructor is overridden by any CPN, because it's
|
||||
// processed seperately.
|
||||
let a = class { [\"constructor\"]() { result += 1; }; constructor() { result += 2; } };
|
||||
var aInst = new a();
|
||||
assertEq(result, 2);
|
||||
aInst.constructor();
|
||||
assertEq(result, 3);
|
||||
|
||||
let b = class { constructor() { result += 2; } [\"constructor\"]() { result += 1; }; };
|
||||
var bInst = new b();
|
||||
assertEq(result, 5);
|
||||
bInst.constructor();
|
||||
assertEq(result, 6);
|
||||
|
||||
let c = class { constructor() { } method() { result += 1 } get method() { result += 2 } };
|
||||
new c().method;
|
||||
assertEq(result, 8);
|
||||
|
||||
let d = class { constructor() { } get method() { result += 1 } method() { result += 2 } };
|
||||
new d().method();
|
||||
assertEq(result, 10);
|
||||
|
||||
// getters and setter should not overwrite each other, but merge cleanly.
|
||||
let e = class { constructor() { } get method() { result += 1 } set method(x) { } };
|
||||
new e().method;
|
||||
assertEq(result, 11);
|
||||
|
||||
let f = class { constructor() { }
|
||||
set method(x) { throw "NO"; }
|
||||
method() { throw "NO" }
|
||||
get method() { return new Function("result += 1"); }
|
||||
};
|
||||
new f().method();
|
||||
assertEq(result, 12);
|
||||
}
|
||||
`;
|
||||
|
||||
if (classesEnabled())
|
||||
|
@ -1,4 +1,4 @@
|
||||
// A class creates a mutable lexical outer binding.
|
||||
// A class statement creates a mutable lexical outer binding.
|
||||
|
||||
var test = `
|
||||
class Foo { constructor() { } }
|
||||
|
@ -4,21 +4,36 @@
|
||||
var test = `
|
||||
class a { constructor() { Object.preventExtensions({}).prop = 0; } }
|
||||
assertThrowsInstanceOf(() => new a(), TypeError);
|
||||
var aExpr = class { constructor() { Object.preventExtensions().prop = 0; } };
|
||||
assertThrowsInstanceOf(() => new aExpr(), TypeError);
|
||||
|
||||
function shouldThrow() {
|
||||
function shouldThrowCPN() {
|
||||
class b {
|
||||
[Object.preventExtensions({}).prop = 4]() { }
|
||||
constructor() { }
|
||||
}
|
||||
}
|
||||
assertThrowsInstanceOf(shouldThrow, TypeError);
|
||||
function shouldThrowCPNExpr() {
|
||||
var b = class {
|
||||
[Object.preventExtensions({}).prop = 4]() { }
|
||||
constructor() { }
|
||||
};
|
||||
}
|
||||
assertThrowsInstanceOf(shouldThrowCPN, TypeError);
|
||||
assertThrowsInstanceOf(shouldThrowCPNExpr, TypeError);
|
||||
|
||||
function shouldThrow2() {
|
||||
function shouldThrowHeritage() {
|
||||
class b extends (Object.preventExtensions({}).prop = 4) {
|
||||
constructor() { }
|
||||
}
|
||||
}
|
||||
assertThrowsInstanceOf(shouldThrow2, TypeError);
|
||||
function shouldThrowHeritageExpr() {
|
||||
var b = class extends (Object.preventExtensions({}).prop = 4) {
|
||||
constructor() { }
|
||||
};
|
||||
}
|
||||
assertThrowsInstanceOf(shouldThrowHeritage, TypeError);
|
||||
assertThrowsInstanceOf(shouldThrowHeritageExpr, TypeError);
|
||||
`;
|
||||
|
||||
if (classesEnabled())
|
||||
|
@ -72,6 +72,10 @@ function classStmt(id, heritage, body) Pattern({ type: "ClassStatement",
|
||||
name: id,
|
||||
heritage: heritage,
|
||||
body: body})
|
||||
function classExpr(id, heritage, body) Pattern({ type: "ClassExpression",
|
||||
name: id,
|
||||
heritage: heritage,
|
||||
body: body})
|
||||
function classMethod(id, body, kind, static) Pattern({ type: "ClassMethod",
|
||||
name: id,
|
||||
body: body,
|
||||
@ -1158,9 +1162,6 @@ function classesEnabled() {
|
||||
}
|
||||
|
||||
function testClasses() {
|
||||
// No unnamed class statements.
|
||||
assertError("class { constructor() { } }", SyntaxError);
|
||||
|
||||
function simpleMethod(id, kind, generator, args=[], isStatic=false) {
|
||||
assertEq(generator && kind === "method", generator);
|
||||
let idN = ident(id);
|
||||
@ -1175,76 +1176,98 @@ function testClasses() {
|
||||
funExpr(null, [], blockStmt([])),
|
||||
"method", isStatic);
|
||||
}
|
||||
function setClassMethods(class_, methods) {
|
||||
class_.template.body = methods;
|
||||
|
||||
function assertClassExpr(str, methods, heritage=null, name=null) {
|
||||
let template = classExpr(name, heritage, methods);
|
||||
assertExpr("(" + str + ")", template);
|
||||
}
|
||||
function setClassHeritage(class_, heritage) {
|
||||
class_.template.heritage = heritage;
|
||||
function assertClass(str, methods, heritage=null) {
|
||||
let namelessStr = str.replace("NAME", "");
|
||||
let namedStr = str.replace("NAME", "Foo");
|
||||
assertClassExpr(namelessStr, methods, heritage);
|
||||
assertClassExpr(namedStr, methods, heritage, ident("Foo"));
|
||||
|
||||
let template = classStmt(ident("Foo"), heritage, methods);
|
||||
assertStmt(namedStr, template);
|
||||
}
|
||||
function assertNamedClassError(str, error) {
|
||||
assertError(str, error);
|
||||
assertError("(" + str + ")", error);
|
||||
}
|
||||
function assertClassError(str, error) {
|
||||
assertNamedClassError(str, error);
|
||||
assertError("(" + str.replace("NAME", "") + ")", error);
|
||||
}
|
||||
|
||||
let simpleConstructor = simpleMethod("constructor", "method", false);
|
||||
let emptyFooClass = classStmt(ident("Foo"), null, [simpleConstructor]);
|
||||
|
||||
/* Trivial classes */
|
||||
assertStmt("class Foo { constructor() { } }", emptyFooClass);
|
||||
// Unnamed class statements are forbidden, but unnamed class expressions are
|
||||
// just fine.
|
||||
assertError("class { constructor() { } }", SyntaxError);
|
||||
assertClass("class NAME { constructor() { } }", [simpleConstructor]);
|
||||
|
||||
// A class name must actually be a name
|
||||
assertNamedClassError("class x.y { constructor() {} }", SyntaxError);
|
||||
assertNamedClassError("class [] { constructor() {} }", SyntaxError);
|
||||
assertNamedClassError("class {x} { constructor() {} }", SyntaxError);
|
||||
assertNamedClassError("class for { constructor() {} }", SyntaxError);
|
||||
|
||||
// Allow methods and accessors
|
||||
let stmt = classStmt(ident("Foo"), null,
|
||||
[simpleConstructor, simpleMethod("method", "method", false)]);
|
||||
assertStmt("class Foo { constructor() { } method() { } }", stmt);
|
||||
assertClass("class NAME { constructor() { } method() { } }",
|
||||
[simpleConstructor, simpleMethod("method", "method", false)]);
|
||||
|
||||
setClassMethods(stmt, [simpleConstructor, simpleMethod("method", "get", false)]);
|
||||
assertStmt("class Foo { constructor() { } get method() { } }", stmt);
|
||||
assertClass("class NAME { constructor() { } get method() { } }",
|
||||
[simpleConstructor, simpleMethod("method", "get", false)]);
|
||||
|
||||
setClassMethods(stmt, [simpleConstructor, simpleMethod("method", "set", false, ["x"])]);
|
||||
assertStmt("class Foo { constructor() { } set method(x) { } }", stmt);
|
||||
assertClass("class NAME { constructor() { } set method(x) { } }",
|
||||
[simpleConstructor, simpleMethod("method", "set", false, ["x"])]);
|
||||
|
||||
/* Static */
|
||||
setClassMethods(stmt, [simpleConstructor,
|
||||
simpleMethod("method", "method", false, [], true),
|
||||
simpleMethod("methodGen", "method", true, [], true),
|
||||
simpleMethod("getter", "get", false, [], true),
|
||||
simpleMethod("setter", "set", false, ["x"], true)]);
|
||||
assertStmt(`class Foo {
|
||||
constructor() { };
|
||||
static method() { };
|
||||
static *methodGen() { };
|
||||
static get getter() { };
|
||||
static set setter(x) { }
|
||||
}`, stmt);
|
||||
|
||||
assertClass(`class NAME {
|
||||
constructor() { };
|
||||
static method() { };
|
||||
static *methodGen() { };
|
||||
static get getter() { };
|
||||
static set setter(x) { }
|
||||
}`,
|
||||
[simpleConstructor,
|
||||
simpleMethod("method", "method", false, [], true),
|
||||
simpleMethod("methodGen", "method", true, [], true),
|
||||
simpleMethod("getter", "get", false, [], true),
|
||||
simpleMethod("setter", "set", false, ["x"], true)]);
|
||||
|
||||
// It's not an error to have a method named static, static, or not.
|
||||
setClassMethods(stmt, [simpleConstructor, simpleMethod("static", "method", false, [], false)]);
|
||||
assertStmt("class Foo{ constructor() { } static() { } }", stmt);
|
||||
setClassMethods(stmt, [simpleMethod("static", "method", false, [], true), simpleConstructor]);
|
||||
assertStmt("class Foo{ static static() { }; constructor() { } }", stmt);
|
||||
setClassMethods(stmt, [simpleMethod("static", "get", false, [], true), simpleConstructor]);
|
||||
assertStmt("class Foo { static get static() { }; constructor() { } }", stmt);
|
||||
setClassMethods(stmt, [simpleConstructor, simpleMethod("static", "set", false, ["x"], true)]);
|
||||
assertStmt("class Foo { constructor() { }; static set static(x) { } }", stmt);
|
||||
assertClass("class NAME { constructor() { } static() { } }",
|
||||
[simpleConstructor, simpleMethod("static", "method", false)]);
|
||||
assertClass("class NAME { static static() { }; constructor() { } }",
|
||||
[simpleMethod("static", "method", false, [], true), simpleConstructor]);
|
||||
assertClass("class NAME { static get static() { }; constructor() { } }",
|
||||
[simpleMethod("static", "get", false, [], true), simpleConstructor]);
|
||||
assertClass("class NAME { constructor() { }; static set static(x) { } }",
|
||||
[simpleConstructor, simpleMethod("static", "set", false, ["x"], true)]);
|
||||
|
||||
// You do, however, have to put static in the right spot
|
||||
assertError("class Foo { constructor() { }; get static foo() { } }", SyntaxError);
|
||||
assertClassError("class NAME { constructor() { }; get static foo() { } }", SyntaxError);
|
||||
|
||||
// Spec disallows "prototype" as a static member in a class, since that
|
||||
// one's important to make the desugaring work
|
||||
assertError("class Foo { constructor() { } static prototype() { } }", SyntaxError);
|
||||
assertError("class Foo { constructor() { } static *prototype() { } }", SyntaxError);
|
||||
assertError("class Foo { static get prototype() { }; constructor() { } }", SyntaxError);
|
||||
assertError("class Foo { static set prototype(x) { }; constructor() { } }", SyntaxError);
|
||||
assertClassError("class NAME { constructor() { } static prototype() { } }", SyntaxError);
|
||||
assertClassError("class NAME { constructor() { } static *prototype() { } }", SyntaxError);
|
||||
assertClassError("class NAME { static get prototype() { }; constructor() { } }", SyntaxError);
|
||||
assertClassError("class NAME { static set prototype(x) { }; constructor() { } }", SyntaxError);
|
||||
|
||||
// You are, however, allowed to have a CPN called prototype as a static
|
||||
setClassMethods(stmt, [simpleConstructor, emptyCPNMethod("prototype", true)]);
|
||||
assertStmt("class Foo { constructor() { }; static [\"prototype\"]() { } }", stmt);
|
||||
assertClass("class NAME { constructor() { }; static [\"prototype\"]() { } }",
|
||||
[simpleConstructor, emptyCPNMethod("prototype", true)]);
|
||||
|
||||
/* Constructor */
|
||||
// Currently, we do not allow default constructors
|
||||
assertError("class Foo { }", TypeError);
|
||||
assertClassError("class NAME { }", TypeError);
|
||||
|
||||
// It is an error to have two methods named constructor, but not other
|
||||
// names, regardless if one is an accessor or a generator or static.
|
||||
assertError("class Foo { constructor() { } constructor(a) { } }", SyntaxError);
|
||||
assertClassError("class NAME { constructor() { } constructor(a) { } }", SyntaxError);
|
||||
let methods = [["method() { }", simpleMethod("method", "method", false)],
|
||||
["*method() { }", simpleMethod("method", "method", true)],
|
||||
["get method() { }", simpleMethod("method", "get", false)],
|
||||
@ -1256,66 +1279,93 @@ function testClasses() {
|
||||
let i,j;
|
||||
for (i=0; i < methods.length; i++) {
|
||||
for (j=0; j < methods.length; j++) {
|
||||
setClassMethods(stmt,
|
||||
[simpleConstructor,
|
||||
methods[i][1],
|
||||
methods[j][1]]);
|
||||
let str = "class Foo { constructor() { } " +
|
||||
let str = "class NAME { constructor() { } " +
|
||||
methods[i][0] + " " + methods[j][0] +
|
||||
" }";
|
||||
assertStmt(str, stmt);
|
||||
assertClass(str, [simpleConstructor, methods[i][1], methods[j][1]]);
|
||||
}
|
||||
}
|
||||
|
||||
// It is, however, not an error to have a constructor, and a method with a
|
||||
// computed property name 'constructor'
|
||||
setClassMethods(stmt, [simpleConstructor, emptyCPNMethod("constructor", false)]);
|
||||
assertStmt("class Foo { constructor () { } [\"constructor\"] () { } }", stmt);
|
||||
assertClass("class NAME { constructor () { } [\"constructor\"] () { } }",
|
||||
[simpleConstructor, emptyCPNMethod("constructor", false)]);
|
||||
|
||||
// It is an error to have a generator or accessor named constructor
|
||||
assertError("class Foo { *constructor() { } }", SyntaxError);
|
||||
assertError("class Foo { get constructor() { } }", SyntaxError);
|
||||
assertError("class Foo { set constructor() { } }", SyntaxError);
|
||||
assertClassError("class NAME { *constructor() { } }", SyntaxError);
|
||||
assertClassError("class NAME { get constructor() { } }", SyntaxError);
|
||||
assertClassError("class NAME { set constructor() { } }", SyntaxError);
|
||||
|
||||
/* Semicolons */
|
||||
// Allow Semicolons in Class Definitions
|
||||
assertStmt("class Foo { constructor() { }; }", emptyFooClass);
|
||||
assertClass("class NAME { constructor() { }; }", [simpleConstructor]);
|
||||
|
||||
// Allow more than one semicolon, even in otherwise trivial classses
|
||||
assertStmt("class Foo { ;;; constructor() { } }", emptyFooClass);
|
||||
assertClass("class NAME { ;;; constructor() { } }", [simpleConstructor]);
|
||||
|
||||
// Semicolons are optional, even if the methods share a line
|
||||
setClassMethods(stmt, [simpleMethod("method", "method", false), simpleConstructor]);
|
||||
assertStmt("class Foo { method() { } constructor() { } }", stmt);
|
||||
assertClass("class NAME { method() { } constructor() { } }",
|
||||
[simpleMethod("method", "method", false), simpleConstructor]);
|
||||
|
||||
/* Generators */
|
||||
// No yield as a class name inside a generator
|
||||
assertError("function *foo() {\
|
||||
class yield {\
|
||||
constructor() { } \
|
||||
}\
|
||||
}", SyntaxError);
|
||||
assertError(`function *foo() {
|
||||
class yield {
|
||||
constructor() { }
|
||||
}
|
||||
}`, SyntaxError);
|
||||
assertError(`function *foo() {
|
||||
(class yield {
|
||||
constructor() { }
|
||||
})
|
||||
}`, SyntaxError);
|
||||
|
||||
// Methods may be generators, but not accessors
|
||||
assertError("class Foo { constructor() { } *get foo() { } }", SyntaxError);
|
||||
assertError("class Foo { constructor() { } *set foo() { } }", SyntaxError);
|
||||
assertClassError("class NAME { constructor() { } *get foo() { } }", SyntaxError);
|
||||
assertClassError("class NAME { constructor() { } *set foo() { } }", SyntaxError);
|
||||
|
||||
setClassMethods(stmt, [simpleMethod("method", "method", true), simpleConstructor]);
|
||||
assertStmt("class Foo { *method() { } constructor() { } }", stmt);
|
||||
assertClass("class NAME { *method() { } constructor() { } }",
|
||||
[simpleMethod("method", "method", true), simpleConstructor]);
|
||||
|
||||
/* Strictness */
|
||||
// yield is a strict-mode keyword, and class definitions are always strict.
|
||||
assertError("class Foo { constructor() { var yield; } }", SyntaxError);
|
||||
assertClassError("class NAME { constructor() { var yield; } }", SyntaxError);
|
||||
|
||||
// Beware of the strictness of computed property names. Here use bareword
|
||||
// deletion (a deprecated action) to check.
|
||||
assertError("class Foo { constructor() { } [delete bar]() { }}", SyntaxError);
|
||||
assertClassError("class NAME { constructor() { } [delete bar]() { }}", SyntaxError);
|
||||
|
||||
/* Bindings */
|
||||
// Classes should bind lexically, so they should collide with other in-block
|
||||
// lexical bindings
|
||||
// Class statements bind lexically, so they should collide with other
|
||||
// in-block lexical bindings, but class expressions don't.
|
||||
assertError("{ let Foo; class Foo { constructor() { } } }", TypeError);
|
||||
assertStmt("{ let Foo; (class Foo { constructor() { } }) }",
|
||||
blockStmt([letDecl([{id: ident("Foo"), init: null}]),
|
||||
exprStmt(classExpr(ident("Foo"), null, [simpleConstructor]))]));
|
||||
assertError("{ const Foo = 0; class Foo { constructor() { } } }", TypeError);
|
||||
assertStmt("{ const Foo = 0; (class Foo { constructor() { } }) }",
|
||||
blockStmt([constDecl([{id: ident("Foo"), init: lit(0)}]),
|
||||
exprStmt(classExpr(ident("Foo"), null, [simpleConstructor]))]));
|
||||
assertError("{ class Foo { constructor() { } } class Foo { constructor() { } } }", TypeError);
|
||||
assertStmt(`{
|
||||
(class Foo {
|
||||
constructor() { }
|
||||
},
|
||||
class Foo {
|
||||
constructor() { }
|
||||
});
|
||||
}`,
|
||||
blockStmt([exprStmt(seqExpr([classExpr(ident("Foo"), null, [simpleConstructor]),
|
||||
classExpr(ident("Foo"), null, [simpleConstructor])]))]));
|
||||
assertStmt(`{
|
||||
var x = class Foo { constructor() { } };
|
||||
class Foo { constructor() { } }
|
||||
}`,
|
||||
blockStmt([varDecl([{ id: ident("x"),
|
||||
init: classExpr(ident("Foo"), null, [simpleConstructor])
|
||||
}]),
|
||||
classStmt(ident("Foo"), null, [simpleConstructor])]));
|
||||
|
||||
|
||||
// Can't make a lexical binding inside a block.
|
||||
assertError("if (1) class Foo { constructor() { } }", SyntaxError);
|
||||
@ -1323,65 +1373,64 @@ function testClasses() {
|
||||
/* Heritage Expressions */
|
||||
// It's illegal to have things that look like "multiple inheritance":
|
||||
// non-parenthesized comma expressions.
|
||||
assertError("class Foo extends null, undefined { constructor() { } }", SyntaxError);
|
||||
assertClassError("class NAME extends null, undefined { constructor() { } }", SyntaxError);
|
||||
|
||||
// Again check for strict-mode in heritage expressions
|
||||
assertError("class Foo extends (delete x) { constructor() { } }", SyntaxError);
|
||||
assertClassError("class NAME extends (delete x) { constructor() { } }", SyntaxError);
|
||||
|
||||
// You must specify an inheritance if you say "extends"
|
||||
assertError("class Foo extends { constructor() { } }", SyntaxError);
|
||||
assertClassError("class NAME extends { constructor() { } }", SyntaxError);
|
||||
|
||||
// "extends" is still a valid name for a method
|
||||
setClassMethods(stmt, [simpleConstructor, simpleMethod("extends", "method", false)]);
|
||||
assertStmt("class Foo { constructor() { }; extends() { } }", stmt);
|
||||
assertClass("class NAME { constructor() { }; extends() { } }",
|
||||
[simpleConstructor, simpleMethod("extends", "method", false)]);
|
||||
|
||||
// Immediate expression
|
||||
setClassMethods(stmt, [simpleConstructor]);
|
||||
setClassHeritage(stmt, lit(null));
|
||||
assertStmt("class Foo extends null { constructor() { } }", stmt);
|
||||
assertClass("class NAME extends null { constructor() { } }",
|
||||
[simpleConstructor], lit(null));
|
||||
|
||||
// Sequence expresson
|
||||
setClassHeritage(stmt, seqExpr([ident("undefined"), ident("undefined")]));
|
||||
assertStmt("class Foo extends (undefined, undefined) { constructor() { } }", stmt);
|
||||
assertClass("class NAME extends (undefined, undefined) { constructor() { } }",
|
||||
[simpleConstructor], seqExpr([ident("undefined"), ident("undefined")]));
|
||||
|
||||
// Function expression
|
||||
let emptyFunction = funExpr(null, [], blockStmt([]));
|
||||
setClassHeritage(stmt, emptyFunction);
|
||||
assertStmt("class Foo extends function(){ } { constructor() { } }", stmt);
|
||||
assertClass("class NAME extends function(){ } { constructor() { } }",
|
||||
[simpleConstructor], emptyFunction);
|
||||
|
||||
// New expression
|
||||
setClassHeritage(stmt, newExpr(emptyFunction, []));
|
||||
assertStmt("class Foo extends new function(){ }() { constructor() { } }", stmt);
|
||||
assertClass("class NAME extends new function(){ }() { constructor() { } }",
|
||||
[simpleConstructor], newExpr(emptyFunction, []));
|
||||
|
||||
// Call expression
|
||||
setClassHeritage(stmt, callExpr(emptyFunction, []));
|
||||
assertStmt("class Foo extends function(){ }() { constructor() { } }", stmt);
|
||||
assertClass("class NAME extends function(){ }() { constructor() { } }",
|
||||
[simpleConstructor], callExpr(emptyFunction, []));
|
||||
|
||||
// Dot expression
|
||||
setClassHeritage(stmt, dotExpr(objExpr([]), ident("foo")));
|
||||
assertStmt("class Foo extends {}.foo { constructor() { } }", stmt);
|
||||
assertClass("class NAME extends {}.foo { constructor() { } }",
|
||||
[simpleConstructor], dotExpr(objExpr([]), ident("foo")));
|
||||
|
||||
// Member expression
|
||||
setClassHeritage(stmt, memExpr(objExpr([]), ident("foo")));
|
||||
assertStmt("class Foo extends {}[foo] { constructor() { } }", stmt);
|
||||
assertClass("class NAME extends {}[foo] { constructor() { } }",
|
||||
[simpleConstructor], memExpr(objExpr([]), ident("foo")));
|
||||
|
||||
/* EOF */
|
||||
// Clipped classes should throw a syntax error
|
||||
assertError("class Foo {", SyntaxError);
|
||||
assertError("class Foo {;", SyntaxError);
|
||||
assertError("class Foo { constructor", SyntaxError);
|
||||
assertError("class Foo { constructor(", SyntaxError);
|
||||
assertError("class Foo { constructor()", SyntaxError);
|
||||
assertError("class Foo { constructor()", SyntaxError);
|
||||
assertError("class Foo { constructor() {", SyntaxError);
|
||||
assertError("class Foo { constructor() { }", SyntaxError);
|
||||
assertError("class Foo { static", SyntaxError);
|
||||
assertError("class Foo { static y", SyntaxError);
|
||||
assertError("class Foo { static *", SyntaxError);
|
||||
assertError("class Foo { static *y", SyntaxError);
|
||||
assertError("class Foo { static get", SyntaxError);
|
||||
assertError("class Foo { static get y", SyntaxError);
|
||||
assertError("class Foo extends", SyntaxError);
|
||||
assertClassError("class NAME {", SyntaxError);
|
||||
assertClassError("class NAME {;", SyntaxError);
|
||||
assertClassError("class NAME { constructor", SyntaxError);
|
||||
assertClassError("class NAME { constructor(", SyntaxError);
|
||||
assertClassError("class NAME { constructor()", SyntaxError);
|
||||
assertClassError("class NAME { constructor()", SyntaxError);
|
||||
assertClassError("class NAME { constructor() {", SyntaxError);
|
||||
assertClassError("class NAME { constructor() { }", SyntaxError);
|
||||
assertClassError("class NAME { static", SyntaxError);
|
||||
assertClassError("class NAME { static y", SyntaxError);
|
||||
assertClassError("class NAME { static *", SyntaxError);
|
||||
assertClassError("class NAME { static *y", SyntaxError);
|
||||
assertClassError("class NAME { static get", SyntaxError);
|
||||
assertClassError("class NAME { static get y", SyntaxError);
|
||||
assertClassError("class NAME extends", SyntaxError);
|
||||
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user