| function assert(b) { |
| if (!b) |
| throw new Error("Bad!") |
| } |
| |
| function assertThrow(cb, errorMessage) { |
| let error; |
| try { |
| cb(); |
| } catch (e) { |
| error = e; |
| } |
| if (!error || !(error instanceof Error)) |
| throw new Error("Error is expected!"); |
| |
| if (error.toString() !== errorMessage) |
| throw new Error("Error: `" + errorMessage + "` is expected, but was `" + error.toString() + "`"); |
| } |
| |
| function test(f, count = 1000) { |
| for (let i = 0; i < count; i++) |
| f(); |
| } |
| |
| function test1() { |
| class C extends null { } |
| assertThrow(() => (new C), 'TypeError: function is not a constructor (evaluating \'super(...args)\')'); |
| assert(Reflect.getPrototypeOf(C.prototype) === null); |
| |
| let o = {} |
| class D extends null { |
| constructor() { |
| return o; |
| } |
| } |
| assert(new D === o); |
| assert(Reflect.getPrototypeOf(D.prototype) === null); |
| |
| class E extends null { |
| constructor() { |
| return this; |
| } |
| } |
| assertThrow(()=>(new E), 'ReferenceError: Cannot access uninitialized variable.'); |
| assert(Reflect.getPrototypeOf(E.prototype) === null); |
| } |
| test(test1); |
| |
| function jsNull() { return null; } |
| function test2() { |
| class C extends jsNull() { } |
| assertThrow(() => (new C), 'TypeError: function is not a constructor (evaluating \'super(...args)\')'); |
| assert(Reflect.getPrototypeOf(C.prototype) === null); |
| |
| let o = {} |
| class D extends jsNull() { |
| constructor() { |
| return o; |
| } |
| } |
| assert(new D === o); |
| assert(Reflect.getPrototypeOf(D.prototype) === null); |
| |
| class E extends jsNull() { |
| constructor() { |
| return this; |
| } |
| } |
| assert(() => (new E), 'ReferenceError: Cannot access uninitialized variable.'); |
| assert(Reflect.getPrototypeOf(E.prototype) === null); |
| } |
| test(test2); |
| |
| function test3() { |
| class C extends jsNull() { constructor() { super(); } } |
| let threw = false; |
| try { |
| new C; |
| } catch(e) { |
| threw = e.toString() === "TypeError: function is not a constructor (evaluating 'super()')"; |
| } |
| assert(threw); |
| |
| class D extends jsNull() { constructor() { let arr = ()=>super(); arr(); } } |
| threw = false; |
| try { |
| new D; |
| } catch(e) { |
| threw = e.toString() === "TypeError: function is not a constructor (evaluating 'super()')"; |
| } |
| assert(threw); |
| |
| class E extends jsNull() { constructor() { let arr = ()=>super(); return this; } } |
| assert(()=>(new E), 'ReferenceError: Cannot access uninitialized variable.'); |
| assert(Reflect.getPrototypeOf(E.prototype) === null); |
| } |
| test(test3); |
| |
| function test4() { |
| class E extends jsNull() { constructor() { return 25; } } |
| assert(() => (new E), 'ReferenceError: Cannot access uninitialized variable.'); |
| assert(Reflect.getPrototypeOf(E.prototype) === null); |
| } |
| test(test4); |
| |
| function test5() { |
| class E extends jsNull() { constructor() { let arr = ()=>this; return arr(); } } |
| assert(()=>(new E), 'ReferenceError: Cannot access uninitialized variable.'); |
| assert(Reflect.getPrototypeOf(E.prototype) === null); |
| } |
| test(test5); |
| |
| function test6() { |
| class Base { } |
| class D extends Base { } |
| class E extends jsNull() { constructor() { let ret = this; return ret; } } |
| class F extends jsNull() { constructor() { return 25; } } |
| class G extends jsNull() { constructor() { super(); } } |
| assertThrow(() => Reflect.construct(E, [], D), 'ReferenceError: Cannot access uninitialized variable.'); |
| assertThrow(() => Reflect.construct(F, [], D), 'TypeError: Cannot return a non-object type in the constructor of a derived class.'); |
| |
| let threw = false; |
| try { |
| Reflect.construct(G, [], D); |
| } catch(e) { |
| threw = e.toString() === "TypeError: function is not a constructor (evaluating 'super()')"; |
| } |
| assert(threw); |
| } |
| test(test6); |