function testName(C, name, hasValue, hasGetter, hasSetter, isFunction=false) {
    if (isFunction) {
        assertEq(typeof C.name, "function");
    } else {
        assertEq(C.name, name);
    }

    var desc = Object.getOwnPropertyDescriptor(C, "name");
    if (!hasValue && !hasGetter && !hasSetter) {
        assertEq(desc, undefined);
        return;
    }

    if (hasValue) {
        assertEq("value" in desc, true);
        if (isFunction) {
            assertEq(typeof desc.value, "function");
        } else {
            assertEq(desc.value, name);
        }
        // FIXME: Methods defined in classes should not be enumerable
        // (bug 1144630).
        // assertEq(desc.enumerable, false);
        assertEq(desc.configurable, true);

        assertEq("get" in desc, false);
        assertEq("set" in desc, false);

        return;
    }

    assertEq("value" in desc, false);

    if (hasGetter) {
        assertEq("get" in desc, true);
        assertEq(desc.get(), name);
        // assertEq(desc.enumerable, false);
        assertEq(desc.configurable, true);
    } else {
        assertEq("get" in desc, true);
        assertEq(desc.get, undefined);
        // assertEq(desc.enumerable, false);
        assertEq(desc.configurable, true);
    }

    if (hasSetter) {
        assertEq("set" in desc, true);
        assertEq(typeof desc.set, "function");
        // assertEq(desc.enumerable, false);
        assertEq(desc.configurable, true);
    } else {
        assertEq("set" in desc, true);
        assertEq(desc.set, undefined);
        // assertEq(desc.enumerable, false);
        assertEq(desc.configurable, true);
    }
}

// ---- declaration ---

class Decl {
    constructor() {}
}
testName(Decl, "Decl", true, false, false);

class DeclWithFunc {
    constructor() {}
    static name() {}
}
testName(DeclWithFunc, "DeclWithFunc", true, false, false, true);

class DeclWithGetter {
    constructor() {}
    static get name() { return "base"; }
}
testName(DeclWithGetter, "base", false, true, false);

class DeclWithSetter {
    constructor() {}
    static set name(v) {}
}
testName(DeclWithSetter, undefined, false, false, true);

class DeclWithGetterSetter {
    constructor() {}
    static get name() { return "base"; }
    static set name(v) {}
}
testName(DeclWithGetterSetter, "base", false, true, true);

function prop() {
  return "name";
}
class DeclWithComputed {
    constructor() {}
    static get [prop()]() { return "base"; }
}
testName(DeclWithGetterSetter, "base", false, true, true);

class ExtendedDecl1 extends Decl {
    constructor() {}
}
testName(ExtendedDecl1, "ExtendedDecl1", true, false, false);
delete ExtendedDecl1.name;
testName(ExtendedDecl1, "Decl", false, false, false);

class ExtendedDecl2 extends DeclWithGetterSetter {
    constructor() {}
    static get name() { return "extend"; }
}
testName(ExtendedDecl2, "extend", false, true, false);
delete ExtendedDecl2.name;
testName(ExtendedDecl2, "base", false, false, false);

class ExtendedDecl3 extends DeclWithGetterSetter {
    constructor() {}
    static set name(v) {}
}
testName(ExtendedDecl3, undefined, false, false, true);
delete ExtendedDecl3.name;
testName(ExtendedDecl3, "base", false, false, false);

// ---- expression ---

let Expr = class Expr {
    constructor() {}
};
testName(Expr, "Expr", true, false, false);

let ExprWithGetter = class ExprWithGetter {
    constructor() {}
    static get name() { return "base"; }
};
testName(ExprWithGetter, "base", false, true, false);

let ExprWithSetter = class ExprWithSetter {
    constructor() {}
    static set name(v) {}
};
testName(ExprWithSetter, undefined, false, false, true);

let ExprWithGetterSetter = class ExprWithGetterSetter {
    constructor() {}
    static get name() { return "base"; }
    static set name(v) {}
};
testName(ExprWithGetterSetter, "base", false, true, true);


let ExtendedExpr1 = class ExtendedExpr1 extends Expr {
    constructor() {}
};
testName(ExtendedExpr1, "ExtendedExpr1", true, false, false);
delete ExtendedExpr1.name;
testName(ExtendedExpr1, "Expr", false, false, false);

let ExtendedExpr2 = class ExtendedExpr2 extends ExprWithGetterSetter {
    constructor() {}
    static get name() { return "extend"; }
};
testName(ExtendedExpr2, "extend", false, true, false);
delete ExtendedExpr2.name;
testName(ExtendedExpr2, "base", false, false, false);

let ExtendedExpr3 = class ExtendedExpr3 extends ExprWithGetterSetter {
    constructor() {}
    static set name(v) {}
};
testName(ExtendedExpr3, undefined, false, false, true);
delete ExtendedExpr3.name;
testName(ExtendedExpr3, "base", false, false, false);

// ---- anonymous ----

// Anonymous class expressions don't get name properties unless specified in a
// static manner.
// Use property assignment to avoid setting name property.
let tmp = {};
let Anon = tmp.value = class {
    constructor() {}
};
testName(Anon, "", false, false, false);

let AnonDefault = tmp.value = class { };
testName(AnonDefault, "", false, false, false);

let AnonWithGetter = tmp.value = class {
    constructor() {}
    static get name() { return "base"; }
};
testName(AnonWithGetter, "base", false, true, false);

let AnonWithSetter = tmp.value = class {
    constructor() {}
    static set name(v) {}
};
testName(AnonWithSetter, undefined, false, false, true);

let AnonWithGetterSetter = tmp.value = class {
    constructor() {}
    static get name() { return "base"; }
    static set name(v) {}
};
testName(AnonWithGetterSetter, "base", false, true, true);


let ExtendedAnon1 = tmp.value = class extends Anon {
    constructor() {}
};
testName(ExtendedAnon1, "", false, false, false);

let ExtendedAnonDefault = tmp.value = class extends Anon { };
testName(ExtendedAnonDefault, "", false, false, false);

let ExtendedAnon2 = tmp.value = class extends AnonWithGetterSetter {
    constructor() {}
    static get name() { return "extend"; }
};
testName(ExtendedAnon2, "extend", false, true, false);
delete ExtendedAnon2.name;
testName(ExtendedAnon2, "base", false, false, false);

let ExtendedAnon3 = tmp.value = class extends AnonWithGetterSetter {
    constructor() {}
    static set name(v) {}
};
testName(ExtendedAnon3, undefined, false, false, true);
delete ExtendedAnon3.name;
testName(ExtendedAnon3, "base", false, false, false);

// ---- mixed ----

let ExtendedExpr4 = class ExtendedExpr4 extends Anon {
    constructor() {}
}
testName(ExtendedExpr4, "ExtendedExpr4", true, false, false);
delete ExtendedExpr4.name;
testName(ExtendedExpr4, "", false, false, false);

let ExtendedExpr5 = class ExtendedExpr5 extends AnonWithGetterSetter {
    constructor() {}
    static get name() { return "extend"; }
}
testName(ExtendedExpr5, "extend", false, true, false);
delete ExtendedExpr5.name;
testName(ExtendedExpr5, "base", false, false, false);

if (typeof reportCompare === "function")
    reportCompare(0, 0, "OK");
