154 lines
8.3 KiB
JavaScript
154 lines
8.3 KiB
JavaScript
|
|
description('Tests for ES6 class syntax "super"');
|
|
|
|
function shouldThrow(s, message) {
|
|
var threw = false;
|
|
try {
|
|
eval(s);
|
|
} catch(e) {
|
|
threw = true;
|
|
if (!message || e.toString() === eval(message))
|
|
testPassed(s + ":::" + e.toString());
|
|
else
|
|
testFailed(s);
|
|
}
|
|
if (!threw)
|
|
testFailed(s);
|
|
}
|
|
|
|
function shouldNotThrow(s, message) {
|
|
var threw = false;
|
|
try {
|
|
eval(s);
|
|
} catch(e) {
|
|
threw = true;
|
|
}
|
|
if (threw)
|
|
testFailed(s);
|
|
else
|
|
testPassed(s);
|
|
}
|
|
|
|
function shouldBe(a, b) {
|
|
if (eval(a) === eval(b))
|
|
testPassed(a + ":::" + b);
|
|
else
|
|
testFailed(a + ":::" + b);
|
|
}
|
|
|
|
function shouldBeTrue(s) {
|
|
if (eval(s) === true)
|
|
testPassed(s);
|
|
else
|
|
testFailed(s);
|
|
}
|
|
|
|
function shouldBeFalse(s) {
|
|
if (eval(s) === false)
|
|
testPassed(s);
|
|
else
|
|
testFailed(s);
|
|
}
|
|
|
|
var baseMethodValue = {};
|
|
var valueInSetter = null;
|
|
|
|
class Base {
|
|
constructor() { }
|
|
baseMethod() { return baseMethodValue; }
|
|
chainMethod() { return 'base'; }
|
|
static staticMethod() { return 'base3'; }
|
|
}
|
|
|
|
class Derived extends Base {
|
|
constructor() { super(); }
|
|
chainMethod() { return [super.chainMethod(), 'derived']; }
|
|
callBaseMethod() { return super.baseMethod(); }
|
|
get callBaseMethodInGetter() { return super['baseMethod'](); }
|
|
set callBaseMethodInSetter(x) { valueInSetter = super.baseMethod(); }
|
|
get baseMethodInGetterSetter() { return super.baseMethod; }
|
|
set baseMethodInGetterSetter(x) { valueInSetter = super['baseMethod']; }
|
|
static staticMethod() { return super.staticMethod(); }
|
|
}
|
|
|
|
class SecondDerived extends Derived {
|
|
constructor() { super(); }
|
|
chainMethod() { return super.chainMethod().concat(['secondDerived']); }
|
|
}
|
|
|
|
class DerivedWithEval extends Base {
|
|
constructor(throwTDZ) {
|
|
if (throwTDZ)
|
|
this.id = '';
|
|
|
|
eval("super()");
|
|
}
|
|
}
|
|
|
|
shouldBeTrue('(new Base) instanceof Base');
|
|
shouldBeTrue('(new Derived) instanceof Derived');
|
|
shouldBeTrue('(new DerivedWithEval) instanceof DerivedWithEval');
|
|
shouldThrow('(new DerivedWithEval(true))', `"ReferenceError: 'super()' must be called in derived constructor before accessing |this| or returning non-object."`);
|
|
shouldBe('(new Derived).callBaseMethod()', 'baseMethodValue');
|
|
shouldBe('x = (new Derived).callBaseMethod; x()', 'baseMethodValue');
|
|
shouldBe('(new Derived).callBaseMethodInGetter', 'baseMethodValue');
|
|
shouldBe('(new Derived).callBaseMethodInSetter = 1; valueInSetter', 'baseMethodValue');
|
|
shouldBe('(new Derived).baseMethodInGetterSetter', '(new Base).baseMethod');
|
|
shouldBe('(new Derived).baseMethodInGetterSetter = 1; valueInSetter', '(new Base).baseMethod');
|
|
shouldBe('Derived.staticMethod()', '"base3"');
|
|
shouldBe('(new SecondDerived).chainMethod().toString()', '["base", "derived", "secondDerived"].toString()');
|
|
shouldNotThrow('x = class extends Base { constructor() { super(); } super() {} }');
|
|
shouldThrow('x = class extends Base { constructor() { super(); } method() { super() } }',
|
|
'"SyntaxError: super is not valid in this context."');
|
|
shouldThrow('x = class extends Base { constructor() { super(); } method() { super } }', '"SyntaxError: super is not valid in this context."');
|
|
shouldThrow('x = class extends Base { constructor() { super(); } method() { return new super } }', '"SyntaxError: Cannot use new with super call."');
|
|
shouldNotThrow('x = class extends Base { constructor() { super(); } method1() { delete (super.foo) } method2() { delete super["foo"] } }');
|
|
shouldThrow('(new x).method1()', '"ReferenceError: Cannot delete a super property"');
|
|
shouldThrow('(new x).method2()', '"ReferenceError: Cannot delete a super property"');
|
|
shouldBeTrue('(new (class { constructor() { super.property = "ABC"; } })).property === "ABC"');
|
|
shouldBeTrue('(new (class extends Base { constructor() { super(); super.property = "ABC"; } })).property === "ABC"');
|
|
shouldBeTrue('(new (class { constructor() { var arr = () => super.property = "ABC"; arr(); } })).property === "ABC"');
|
|
shouldBeTrue('(new (class { constructor() { var async_arr = async () => super.property = "ABC"; async_arr(); } })).property === "ABC"');
|
|
shouldBeTrue('(new (class { constructor() { eval(\'super.property = "ABC"\'); } })).property === "ABC"');
|
|
shouldBeTrue('(new (class { constructor() { var arr = () => eval(\'super.property = "ABC"\'); arr(); } })).property === "ABC"');
|
|
shouldBeTrue('new (class { constructor() { return undefined; } }) instanceof Object');
|
|
shouldBeTrue('new (class { constructor() { return 1; } }) instanceof Object');
|
|
shouldThrow('new (class extends Base { constructor() { return undefined } })');
|
|
shouldBeTrue('new (class extends Base { constructor() { super(); return undefined } }) instanceof Object');
|
|
shouldBe('x = { }; new (class extends Base { constructor() { return x } });', 'x');
|
|
shouldBeFalse('x instanceof Base');
|
|
shouldThrow('new (class extends Base { constructor() { } })', `"ReferenceError: 'super()' must be called in derived constructor before accessing |this| or returning non-object."`);
|
|
shouldThrow('new (class extends Base { constructor() { return 1; } })', '"TypeError: Cannot return a non-object type in the constructor of a derived class."');
|
|
shouldThrow('new (class extends null { constructor() { return undefined } })');
|
|
shouldThrow('new (class extends null { constructor() { super(); return undefined } })', '"TypeError: function is not a constructor (evaluating \'super()\')"');
|
|
shouldBe('x = { }; new (class extends null { constructor() { return x } });', 'x');
|
|
shouldBeTrue('x instanceof Object');
|
|
shouldThrow('new (class extends null { constructor() { } })');
|
|
shouldThrow('new (class extends null { constructor() { return 1; } })');
|
|
shouldThrow('new (class extends null { constructor() { super() } })', '"TypeError: function is not a constructor (evaluating \'super()\')"');
|
|
shouldThrow('new (class { constructor() { super() } })', '"SyntaxError: super is not valid in this context."');
|
|
shouldThrow('function x() { super(); }', '"SyntaxError: super is not valid in this context."');
|
|
shouldThrow('new (class extends Object { constructor() { function x() { super() } } })', '"SyntaxError: super is not valid in this context."');
|
|
shouldThrow('new (class extends Object { constructor() { function x() { super.method } } })', '"SyntaxError: super is not valid in this context."');
|
|
shouldThrow('function x() { super.method(); }', '"SyntaxError: super is not valid in this context."');
|
|
shouldThrow('function x() { super(); }', '"SyntaxError: super is not valid in this context."');
|
|
shouldThrow('eval("super.method()")', '"SyntaxError: super is not valid in this context."');
|
|
shouldThrow('eval("super()")', '"SyntaxError: super is not valid in this context."');
|
|
|
|
shouldThrow('(function () { eval("super.method()");})()', '"SyntaxError: super is not valid in this context."');
|
|
shouldThrow('(function () { eval("super()");})()', '"SyntaxError: super is not valid in this context."');
|
|
|
|
shouldThrow('new (class { constructor() { (function () { eval("super()");})(); } })', '"SyntaxError: super is not valid in this context."');
|
|
shouldThrow('(new (class { method() { (function () { eval("super.method()");})(); }})).method()', '"SyntaxError: super is not valid in this context."');
|
|
|
|
shouldThrow('new (class extends Base { constructor() { super(); super();}})', '"ReferenceError: \'super()\' can\'t be called more than once in a constructor."');
|
|
shouldThrow('(new class D extends class { m() {}} { constructor() { eval(\'super["m"]()\') } })', `"ReferenceError: 'super()' must be called in derived constructor before accessing |this| or returning non-object."`);
|
|
shouldThrow('new class extends class { m() {}} { constructor() { super["m"](super()) } }', `"ReferenceError: 'super()' must be called in derived constructor before accessing |this| or returning non-object."`);
|
|
shouldThrow('(new class D extends class { m() {}} { constructor(f) { super[f()]() } }(()=>"m"))', `"ReferenceError: 'super()' must be called in derived constructor before accessing |this| or returning non-object."`);
|
|
|
|
shouldNotThrow('(new class D extends class { m() {}} { constructor() { super(); eval(\'super["m"]()\') } })');
|
|
shouldThrow('new class extends class { m() {}} { constructor() { super(); super["m"](super()) } }', '"ReferenceError: \'super()\' can\'t be called more than once in a constructor."');
|
|
shouldNotThrow('(new class D extends class { m() {}} { constructor(f) { super(); super[f()]() } }(()=>"m"))');
|
|
|
|
var successfullyParsed = true;
|