Bug 1141863 - Tests. (r=jorendorff)

This commit is contained in:
Eric Faust 2015-10-08 17:01:49 -07:00
parent de67ecc818
commit ec937cfeb7
10 changed files with 296 additions and 9 deletions

View File

@ -0,0 +1,17 @@
var test = `
class base { constructor() { } }
class inst extends base { constructor() { super(); } }
Object.setPrototypeOf(inst, Math.sin);
assertThrowsInstanceOf(() => new inst(), TypeError);
`;
if (classesEnabled())
eval(test);
if (typeof reportCompare === 'function')
reportCompare(0,0,"OK");

View File

@ -0,0 +1,30 @@
var test = `
class base { constructor() { } }
// lies and the lying liars who tell them
function lies() { }
lies.prototype = 4;
assertThrowsInstanceOf(()=>Reflect.consruct(base, [], lies), TypeError);
// lie a slightly different way
function get(target, property, receiver) {
if (property === "prototype")
return 42;
return Reflect.get(target, property, receiver);
}
class inst extends base {
constructor() { super(); }
}
assertThrowsInstanceOf(()=>new new Proxy(inst, {get})(), TypeError);
`;
if (classesEnabled())
eval(test);
if (typeof reportCompare === 'function')
reportCompare(0,0,"OK");

View File

@ -0,0 +1,53 @@
var test = `
function testBase(base) {
class instance extends base {
constructor(inst, one) {
super(inst, one);
}
}
let inst = new instance(instance, 1);
assertEq(Object.getPrototypeOf(inst), instance.prototype);
assertEq(inst.calledBase, true);
}
class base {
// Base class must be [[Construct]]ed, as you cannot [[Call]] a class
// constructor
constructor(nt, one) {
assertEq(new.target, nt);
// Check argument ordering
assertEq(one, 1);
this.calledBase = true;
}
}
testBase(base);
testBase(class extends base {
constructor(nt, one) {
// Every step of the way, new.target and args should be right
assertEq(new.target, nt);
assertEq(one, 1);
super(nt, one);
}
});
function baseFunc(nt, one) {
assertEq(new.target, nt);
assertEq(one, 1);
this.calledBase = true;
}
testBase(baseFunc);
testBase(new Proxy(baseFunc, {}));
// Object will have to wait for fixed builtins.
`;
if (classesEnabled())
eval(test);
if (typeof reportCompare === 'function')
reportCompare(0,0,"OK");

View File

@ -0,0 +1,7 @@
// super() invalid outside derived class constructors, including in dynamic
// functions and eval
assertThrowsInstanceOf(() => new Function("super();"), SyntaxError);
assertThrowsInstanceOf(() => eval("super()"), SyntaxError);
if (typeof reportCompare === 'function')
reportCompare(0,0,"OK");

View File

@ -0,0 +1,15 @@
var test = `
class instance extends null {
constructor() { super(); }
}
assertThrowsInstanceOf(() => new instance(), TypeError);
`;
if (classesEnabled())
eval(test);
if (typeof reportCompare === 'function')
reportCompare(0,0,"OK");

View File

@ -0,0 +1,33 @@
var test = `
function base() { }
class beforeSwizzle extends base {
constructor() {
super(Object.setPrototypeOf(beforeSwizzle, null));
}
}
new beforeSwizzle();
// Again, testing both dynamic prototype dispatch, and that we get the function
// before evaluating args
class beforeThrow extends base {
constructor() {
function thrower() { throw new Error(); }
super(thrower());
}
}
Object.setPrototypeOf(beforeThrow, Math.sin);
// Will throw that Math.sin is not a constructor before evaluating the args
assertThrowsInstanceOf(() => new beforeThrow(), TypeError);
`;
if (classesEnabled())
eval(test);
if (typeof reportCompare === 'function')
reportCompare(0,0,"OK");

View File

@ -0,0 +1,33 @@
var test = `
class base1 {
constructor() {
this.base = 1;
}
}
class base2 {
constructor() {
this.base = 2;
}
}
class inst extends base1 {
constructor() {
super();
}
}
assertEq(new inst().base, 1);
Object.setPrototypeOf(inst, base2);
assertEq(new inst().base, 2);
`;
if (classesEnabled())
eval(test);
if (typeof reportCompare === 'function')
reportCompare(0,0,"OK");

View File

@ -0,0 +1,34 @@
var test = `
class base {
constructor(a, b, c) {
assertEq(a, 1);
assertEq(b, 2);
assertEq(c, 3);
this.calledBase = true;
}
}
class test extends base {
constructor(arr) {
super(...arr);
}
}
assertEq(new test([1,2,3]).calledBase, true);
class testRest extends base {
constructor(...args) {
super(...args);
}
}
assertEq(new testRest(1,2,3).calledBase, true);
`;
if (classesEnabled())
eval(test);
if (typeof reportCompare === 'function')
reportCompare(0,0,"OK");

View File

@ -0,0 +1,52 @@
var test = `
function base() { this.prop = 42; }
class testInitialize extends base {
constructor() {
// A poor man's assertThrowsInstanceOf, as arrow functions are currently
// disabled in this context
try {
this;
throw new Error();
} catch (e if e instanceof ReferenceError) { }
super();
assertEq(this.prop, 42);
}
}
assertEq(new testInitialize().prop, 42);
// super() twice is a no-go.
class willThrow extends base {
constructor() {
super();
super();
}
}
assertThrowsInstanceOf(()=>new willThrow(), ReferenceError);
// This is determined at runtime, not the syntax level.
class willStillThrow extends base {
constructor() {
for (let i = 0; i < 3; i++) {
super();
}
}
}
assertThrowsInstanceOf(()=>new willStillThrow(), ReferenceError);
class canCatchThrow extends base {
constructor() {
super();
try { super(); } catch(e) { }
}
}
assertEq(new canCatchThrow().prop, 42);
`;
if (classesEnabled())
eval(test);
if (typeof reportCompare === 'function')
reportCompare(0,0,"OK");

View File

@ -25,9 +25,9 @@ function testClasses() {
methodFun(id, kind, generator, args),
kind, isStatic);
}
function ctorWithName(id) {
function ctorWithName(id, body = []) {
return classMethod(ident("constructor"),
methodFun(id, "method", false, []),
methodFun(id, "method", false, [], body),
"method", false);
}
function emptyCPNMethod(id, isStatic) {
@ -40,14 +40,15 @@ function testClasses() {
let template = classExpr(name, heritage, methods);
assertExpr("(" + str + ")", template);
}
// FunctionExpression of constructor has class name as its id.
// FIXME: Implement ES6 function "name" property semantics (bug 883377).
let ctorPlaceholder = {};
function assertClass(str, methods, heritage=null) {
function assertClass(str, methods, heritage=null, constructorBody=[]) {
let namelessStr = str.replace("NAME", "");
let namedStr = str.replace("NAME", "Foo");
let namedCtor = ctorWithName("Foo");
let namelessCtor = ctorWithName(null);
let namedCtor = ctorWithName("Foo", constructorBody);
let namelessCtor = ctorWithName(null, constructorBody);
let namelessMethods = methods.map(x => x == ctorPlaceholder ? namelessCtor : x);
let namedMethods = methods.map(x => x == ctorPlaceholder ? namedCtor : x);
assertClassExpr(namelessStr, namelessMethods, heritage);
@ -443,23 +444,35 @@ function testClasses() {
assertError("super()", SyntaxError);
assertError("(function() { super(); })", SyntaxError);
// SuperCall is invalid in generator comprehensions, even inside derived
// class constructors
assertError("(super() for (x in y))", SyntaxError);
assertClassError("class NAME { constructor() { (super() for (x in y))", SyntaxError);
// Even in class constructors
assertClassError("class NAME { constructor() { super(); } }", SyntaxError);
function superConstructor(args) {
return classMethod(ident("constructor"),
methodFun("constructor", "method", false,
methodFun("NAME", "method", false,
[], [exprStmt(superCallExpr(args))]),
"method", false);
}
function superCallBody(args) {
return [exprStmt(superCallExpr(args))];
}
// SuperCall works with various argument configurations.
assertClass("class NAME extends null { constructor() { super() } }",
[superConstructor([])], lit(null));
[ctorPlaceholder], lit(null), superCallBody([]));
assertClass("class NAME extends null { constructor() { super(1) } }",
[superConstructor([lit(1)])], lit(null));
[ctorPlaceholder], lit(null), superCallBody([lit(1)]));
assertClass("class NAME extends null { constructor() { super(1, a) } }",
[ctorPlaceholder], lit(null), superCallBody([lit(1), ident("a")]));
assertClass("class NAME extends null { constructor() { super(...[]) } }",
[superConstructor([spread(arrExpr([]))])], lit(null));
[ctorPlaceholder], lit(null), superCallBody([spread(arrExpr([]))]));
/* EOF */
// Clipped classes should throw a syntax error