tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

classes.js (26079B)


      1 // |reftest| slow skip-if(!xulRuntime.shell)
      2 // Classes
      3 function testClasses() {
      4    function methodFun(id, kind, generator, args, body = []) {
      5        assertEq(generator && kind === "method", generator);
      6        assertEq(typeof id === 'string' || id === null, true);
      7        let methodName;
      8        switch (kind) {
      9            case "method":
     10                methodName = typeof id === 'string' ? ident(id) : null;
     11                break;
     12            case "get":
     13            case "set":
     14                methodName = ident(`${kind} ${typeof id === 'string' ? id : ""}`);
     15                break;
     16            default:
     17                methodName = null;
     18                break;
     19        }
     20        return generator
     21            ? genFunExpr("es6", methodName, args.map(ident), blockStmt(body))
     22            : funExpr(methodName, args.map(ident), blockStmt(body));
     23    }
     24 
     25    function simpleMethod(id, kind, generator, args = [], isStatic = false) {
     26        return classMethod(ident(id),
     27            methodFun(id, kind, generator, args),
     28            kind, isStatic);
     29    }
     30    function ctorWithName(id, body = []) {
     31        return classMethod(ident("constructor"),
     32            methodFun(id, "method", false, [], body),
     33            "method", false);
     34    }
     35    function emptyCPNMethod(id, isStatic) {
     36        return classMethod(computedName(lit(id)),
     37            funExpr(null, [], blockStmt([])),
     38            "method", isStatic);
     39    }
     40 
     41    function assertClassExpr(str, methods, heritage = null, name = null) {
     42        let template = classExpr(name, heritage, methods);
     43        assertExpr("(" + str + ")", template);
     44    }
     45 
     46    // FunctionExpression of constructor has class name as its id.
     47    // FIXME: Implement ES6 function "name" property semantics (bug 883377).
     48    let ctorPlaceholder = {};
     49    function assertClass(str, methods, heritage = null, constructorBody = []) {
     50        let namelessStr = str.replace("NAME", "");
     51        let namedStr = str.replace("NAME", "Foo");
     52        let namedCtor = ctorWithName("Foo", constructorBody);
     53        let namelessCtor = ctorWithName(null, constructorBody);
     54        let namelessMethods = methods.map(x => x == ctorPlaceholder ? namelessCtor : x);
     55        let namedMethods = methods.map(x => x == ctorPlaceholder ? namedCtor : x);
     56        assertClassExpr(namelessStr, namelessMethods, heritage);
     57        assertClassExpr(namedStr, namedMethods, heritage, ident("Foo"));
     58 
     59        let template = classStmt(ident("Foo"), heritage, namedMethods);
     60        assertStmt(namedStr, template);
     61    }
     62    function assertNamedClassError(str, error) {
     63        assertError(str, error);
     64        assertError("(" + str + ")", error);
     65    }
     66    function assertClassError(str, error) {
     67        assertNamedClassError(str, error);
     68        assertError("(" + str.replace("NAME", "") + ")", error);
     69    }
     70 
     71    /* Trivial classes */
     72    // Unnamed class statements are forbidden, but unnamed class expressions are
     73    // just fine.
     74    assertError("class { constructor() { } }", SyntaxError);
     75    assertClass("class NAME { constructor() { } }", [ctorPlaceholder]);
     76 
     77    // A class name must actually be a name
     78    assertNamedClassError("class x.y { constructor() {} }", SyntaxError);
     79    assertNamedClassError("class []  { constructor() {} }", SyntaxError);
     80    assertNamedClassError("class {x} { constructor() {} }", SyntaxError);
     81    assertNamedClassError("class for { constructor() {} }", SyntaxError);
     82 
     83    // Allow methods and accessors
     84    assertClass("class NAME { constructor() { } method() { } }",
     85        [ctorPlaceholder, simpleMethod("method", "method", false)]);
     86 
     87    assertClass("class NAME { constructor() { } get method() { } }",
     88        [ctorPlaceholder, simpleMethod("method", "get", false)]);
     89 
     90    assertClass("class NAME { constructor() { } set method(x) { } }",
     91        [ctorPlaceholder, simpleMethod("method", "set", false, ["x"])]);
     92 
     93    /* Static */
     94    assertClass(`class NAME {
     95                   constructor() { };
     96                   static method() { };
     97                   static *methodGen() { };
     98                   static get getter() { };
     99                   static set setter(x) { }
    100                 }`,
    101        [ctorPlaceholder,
    102            simpleMethod("method", "method", false, [], true),
    103            simpleMethod("methodGen", "method", true, [], true),
    104            simpleMethod("getter", "get", false, [], true),
    105            simpleMethod("setter", "set", false, ["x"], true)]);
    106 
    107    // It's not an error to have a method named static, static, or not.
    108    assertClass("class NAME { constructor() { } static() { } }",
    109        [ctorPlaceholder, simpleMethod("static", "method", false)]);
    110    assertClass("class NAME { static static() { }; constructor() { } }",
    111        [simpleMethod("static", "method", false, [], true), ctorPlaceholder]);
    112    assertClass("class NAME { static get static() { }; constructor() { } }",
    113        [simpleMethod("static", "get", false, [], true), ctorPlaceholder]);
    114    assertClass("class NAME { constructor() { }; static set static(x) { } }",
    115        [ctorPlaceholder, simpleMethod("static", "set", false, ["x"], true)]);
    116 
    117    // You do, however, have to put static in the right spot
    118    assertClassError("class NAME { constructor() { }; get static foo() { } }", SyntaxError);
    119 
    120    // Spec disallows "prototype" as a static member in a class, since that
    121    // one's important to make the desugaring work
    122    assertClassError("class NAME { constructor() { } static prototype() { } }", SyntaxError);
    123    assertClassError("class NAME { constructor() { } static *prototype() { } }", SyntaxError);
    124    assertClassError("class NAME { static get prototype() { }; constructor() { } }", SyntaxError);
    125    assertClassError("class NAME { static set prototype(x) { }; constructor() { } }", SyntaxError);
    126 
    127    // You are, however, allowed to have a CPN called prototype as a static
    128    assertClass("class NAME { constructor() { }; static [\"prototype\"]() { } }",
    129        [ctorPlaceholder, emptyCPNMethod("prototype", true)]);
    130 
    131    /* Constructor */
    132    // Allow default constructors
    133    assertClass("class NAME { }", []);
    134    assertClass("class NAME extends null { }", [], lit(null));
    135 
    136    // Derived class constructor must have curly brackets
    137    assertClassError("class NAME extends null {  constructor() 1 }", SyntaxError);
    138 
    139    // It is an error to have two methods named constructor, but not other
    140    // names, regardless if one is an accessor or a generator or static.
    141    assertClassError("class NAME { constructor() { } constructor(a) { } }", SyntaxError);
    142    let methods = [["method() { }", simpleMethod("method", "method", false)],
    143    ["*method() { }", simpleMethod("method", "method", true)],
    144    ["get method() { }", simpleMethod("method", "get", false)],
    145    ["set method(x) { }", simpleMethod("method", "set", false, ["x"])],
    146    ["static method() { }", simpleMethod("method", "method", false, [], true)],
    147    ["static *method() { }", simpleMethod("method", "method", true, [], true)],
    148    ["static get method() { }", simpleMethod("method", "get", false, [], true)],
    149    ["static set method(x) { }", simpleMethod("method", "set", false, ["x"], true)]];
    150    let i, j;
    151    for (i = 0; i < methods.length; i++) {
    152        for (j = 0; j < methods.length; j++) {
    153            let str = "class NAME { constructor() { } " +
    154                methods[i][0] + " " + methods[j][0] +
    155                " }";
    156            assertClass(str, [ctorPlaceholder, methods[i][1], methods[j][1]]);
    157        }
    158    }
    159 
    160    // It is, however, not an error to have a constructor, and a method with a
    161    // computed property name 'constructor'
    162    assertClass("class NAME { constructor () { } [\"constructor\"] () { } }",
    163        [ctorPlaceholder, emptyCPNMethod("constructor", false)]);
    164 
    165    // It is an error to have a generator or accessor named constructor
    166    assertClassError("class NAME { *constructor() { } }", SyntaxError);
    167    assertClassError("class NAME { get constructor() { } }", SyntaxError);
    168    assertClassError("class NAME { set constructor() { } }", SyntaxError);
    169 
    170    /* Semicolons */
    171    // Allow Semicolons in Class Definitions
    172    assertClass("class NAME { constructor() { }; }", [ctorPlaceholder]);
    173 
    174    // Allow more than one semicolon, even in otherwise trivial classses
    175    assertClass("class NAME { ;;; constructor() { } }", [ctorPlaceholder]);
    176 
    177    // Semicolons are optional, even if the methods share a line
    178    assertClass("class NAME { method() { } constructor() { } }",
    179        [simpleMethod("method", "method", false), ctorPlaceholder]);
    180 
    181    /* Generators */
    182    // No yield as a class name inside a generator
    183    assertError(`function *foo() {
    184                    class yield {
    185                        constructor() { }
    186                    }
    187                 }`, SyntaxError);
    188    assertError(`function *foo() {
    189                    (class yield {
    190                        constructor() { }
    191                    })
    192                 }`, SyntaxError);
    193 
    194    // No legacy generators for methods.
    195    assertClassError(`class NAME {
    196                          constructor() { yield 2; }
    197                      }`, SyntaxError);
    198    assertClassError(`class NAME {
    199                          method() { yield 2; }
    200                      }`, SyntaxError);
    201    assertClassError(`class NAME {
    202                          get method() { yield 2; }
    203                      }`, SyntaxError);
    204    assertClassError(`class NAME {
    205                          set method() { yield 2; }
    206                      }`, SyntaxError);
    207 
    208    // Methods may be generators, but not accessors
    209    assertClassError("class NAME { constructor() { } *get foo() { } }", SyntaxError);
    210    assertClassError("class NAME { constructor() { } *set foo() { } }", SyntaxError);
    211 
    212    assertClass("class NAME { *method() { } constructor() { } }",
    213        [simpleMethod("method", "method", true), ctorPlaceholder]);
    214 
    215    /* Strictness */
    216    // yield is a strict-mode keyword, and class definitions are always strict.
    217    assertClassError("class NAME { constructor() { var yield; } }", SyntaxError);
    218 
    219    // Beware of the strictness of computed property names. Here use bareword
    220    // deletion (a deprecated action) to check.
    221    assertClassError("class NAME { constructor() { } [delete bar]() { }}", SyntaxError);
    222 
    223    /* Bindings */
    224    // Class statements bind lexically, so they should collide with other
    225    // in-block lexical bindings, but class expressions don't.
    226    let FooCtor = ctorWithName("Foo");
    227    assertError("{ let Foo; class Foo { constructor() { } } }", SyntaxError);
    228    assertStmt("{ let Foo; (class Foo { constructor() { } }) }",
    229        blockStmt([letDecl([{ id: ident("Foo"), init: null }]),
    230        exprStmt(classExpr(ident("Foo"), null, [FooCtor]))]));
    231    assertError("{ const Foo = 0; class Foo { constructor() { } } }", SyntaxError);
    232    assertStmt("{ const Foo = 0; (class Foo { constructor() { } }) }",
    233        blockStmt([constDecl([{ id: ident("Foo"), init: lit(0) }]),
    234        exprStmt(classExpr(ident("Foo"), null, [FooCtor]))]));
    235    assertError("{ class Foo { constructor() { } } class Foo { constructor() { } } }", SyntaxError);
    236    assertStmt(`{
    237                    (class Foo {
    238                        constructor() { }
    239                     },
    240                     class Foo {
    241                        constructor() { }
    242                     });
    243                }`,
    244        blockStmt([exprStmt(seqExpr([classExpr(ident("Foo"), null, [FooCtor]),
    245        classExpr(ident("Foo"), null, [FooCtor])]))]));
    246    assertStmt(`{
    247                    var x = class Foo { constructor() { } };
    248                    class Foo { constructor() { } }
    249                }`,
    250        blockStmt([varDecl([{
    251            id: ident("x"),
    252            init: classExpr(ident("Foo"), null, [FooCtor])
    253        }]),
    254        classStmt(ident("Foo"), null, [FooCtor])]));
    255 
    256 
    257    // Can't make a lexical binding without a block.
    258    assertError("if (1) class Foo { constructor() { } }", SyntaxError);
    259 
    260    /* Heritage Expressions */
    261    // It's illegal to have things that look like "multiple inheritance":
    262    // non-parenthesized comma expressions.
    263    assertClassError("class NAME extends null, undefined { constructor() { } }", SyntaxError);
    264 
    265    // Again check for strict-mode in heritage expressions
    266    assertClassError("class NAME extends (delete x) { constructor() { } }", SyntaxError);
    267 
    268    // You must specify an inheritance if you say "extends"
    269    assertClassError("class NAME extends { constructor() { } }", SyntaxError);
    270 
    271    // "extends" is still a valid name for a method
    272    assertClass("class NAME { constructor() { }; extends() { } }",
    273        [ctorPlaceholder, simpleMethod("extends", "method", false)]);
    274 
    275    // Immediate expression
    276    assertClass("class NAME extends null { constructor() { } }",
    277        [ctorPlaceholder], lit(null));
    278 
    279    // Sequence expresson
    280    assertClass("class NAME extends (undefined, undefined) { constructor() { } }",
    281        [ctorPlaceholder], seqExpr([ident("undefined"), ident("undefined")]));
    282 
    283    // Function expression
    284    let emptyFunction = funExpr(null, [], blockStmt([]));
    285    assertClass("class NAME extends function(){ } { constructor() { } }",
    286        [ctorPlaceholder], emptyFunction);
    287 
    288    // New expression
    289    assertClass("class NAME extends new function(){ }() { constructor() { } }",
    290        [ctorPlaceholder], newExpr(emptyFunction, []));
    291 
    292    // Call expression
    293    assertClass("class NAME extends function(){ }() { constructor() { } }",
    294        [ctorPlaceholder], callExpr(emptyFunction, []));
    295 
    296    // Dot expression
    297    assertClass("class NAME extends {}.foo { constructor() { } }",
    298        [ctorPlaceholder], dotExpr(objExpr([]), ident("foo")));
    299 
    300    // Member expression
    301    assertClass("class NAME extends {}[foo] { constructor() { } }",
    302        [ctorPlaceholder], memExpr(objExpr([]), ident("foo")));
    303 
    304    // #constructor is an invalid private method name.
    305    assertClassError("class NAME { #constructor() { } }", SyntaxError);
    306 
    307    const method = ["#method() { }", simpleMethod("#method", "method", false)];
    308    const generator = ["*#method() { }", simpleMethod("#method", "method", true)];
    309    const getter = ["get #method() { }", simpleMethod("#method", "get", false)];
    310    const setter = ["set #method(x) { }", simpleMethod("#method", "set", false, ["x"])];
    311    for (const [source, parsed] of [method, generator, getter, setter]) {
    312        assertClass(`class NAME { constructor() { } ${source} }`, [ctorPlaceholder, parsed]);
    313    }
    314 
    315    // Private getters and setters of the same name are allowed.
    316    assertClass(`class NAME { constructor() { } ${getter[0]} ${setter[0]} }`,
    317        [ctorPlaceholder, getter[1], setter[1]]);
    318    assertClass(`class NAME { constructor() { } ${setter[0]} ${getter[0]} }`,
    319        [ctorPlaceholder, setter[1], getter[1]]);
    320 
    321    // Private method names can't be used multiple times, other than for a getter/setter pair.
    322    for (const [source1, _] of [method, generator, getter, setter]) {
    323        for (const [source2, _] of [method, generator]) {
    324            assertClassError(`class NAME { constructor() { } ${source1} ${source2} }`, SyntaxError);
    325        }
    326    }
    327 
    328    assertClassError(`class NAME { constructor() { } ${setter[0]} ${setter[0]} }`, SyntaxError);
    329    assertClassError(`class NAME { constructor() { } ${getter[0]} ${getter[0]} }`, SyntaxError);
    330 
    331 
    332    /* SuperProperty */
    333    // NOTE: Some of these tests involve object literals, as SuperProperty is a
    334    // valid production in any method definition, including in objectl
    335    // litterals. These tests still fall here, as |super| is not implemented in
    336    // any form without classes.
    337 
    338    function assertValidSuperProps(assertion, makeStr, makeExpr, type, generator, args, static,
    339        extending) {
    340        let superProperty = superProp(ident("prop"));
    341        let superMember = superElem(lit("prop"));
    342 
    343        let situations = [
    344            ["super.prop", superProperty],
    345            ["super['prop']", superMember],
    346            ["super.prop()", callExpr(superProperty, [])],
    347            ["super['prop']()", callExpr(superMember, [])],
    348            ["new super.prop()", newExpr(superProperty, [])],
    349            ["new super['prop']()", newExpr(superMember, [])],
    350            ["delete super.prop", unExpr("delete", superProperty)],
    351            ["delete super['prop']", unExpr("delete", superMember)],
    352            ["++super.prop", updExpr("++", superProperty, true)],
    353            ["super['prop']--", updExpr("--", superMember, false)],
    354            ["super.prop = 4", aExpr("=", superProperty, lit(4))],
    355            ["super['prop'] = 4", aExpr("=", superMember, lit(4))],
    356            ["super.prop += 4", aExpr("+=", superProperty, lit(4))],
    357            ["super['prop'] += 4", aExpr("+=", superMember, lit(4))],
    358            ["super.prop -= 4", aExpr("-=", superProperty, lit(4))],
    359            ["super['prop'] -= 4", aExpr("-=", superMember, lit(4))],
    360            ["super.prop *= 4", aExpr("*=", superProperty, lit(4))],
    361            ["super['prop'] *= 4", aExpr("*=", superMember, lit(4))],
    362            ["super.prop /= 4", aExpr("/=", superProperty, lit(4))],
    363            ["super['prop'] /= 4", aExpr("/=", superMember, lit(4))],
    364            ["super.prop %= 4", aExpr("%=", superProperty, lit(4))],
    365            ["super['prop'] %= 4", aExpr("%=", superMember, lit(4))],
    366            ["super.prop <<= 4", aExpr("<<=", superProperty, lit(4))],
    367            ["super['prop'] <<= 4", aExpr("<<=", superMember, lit(4))],
    368            ["super.prop >>= 4", aExpr(">>=", superProperty, lit(4))],
    369            ["super['prop'] >>= 4", aExpr(">>=", superMember, lit(4))],
    370            ["super.prop >>>= 4", aExpr(">>>=", superProperty, lit(4))],
    371            ["super['prop'] >>>= 4", aExpr(">>>=", superMember, lit(4))],
    372            ["super.prop |= 4", aExpr("|=", superProperty, lit(4))],
    373            ["super['prop'] |= 4", aExpr("|=", superMember, lit(4))],
    374            ["super.prop ^= 4", aExpr("^=", superProperty, lit(4))],
    375            ["super['prop'] ^= 4", aExpr("^=", superMember, lit(4))],
    376            ["super.prop &= 4", aExpr("&=", superProperty, lit(4))],
    377            ["super['prop'] &= 4", aExpr("&=", superMember, lit(4))],
    378 
    379            // We can also use super from inside arrow functions in method
    380            // definitions
    381            ["()=>super.prop", arrowExpr([], superProperty)],
    382            ["()=>super['prop']", arrowExpr([], superMember)]];
    383 
    384        for (let situation of situations) {
    385            let sitStr = situation[0];
    386            let sitExpr = situation[1];
    387 
    388            let fun = methodFun("method", type, generator, args, [exprStmt(sitExpr)]);
    389            let str = makeStr(sitStr, type, generator, args, static, extending);
    390            assertion(str, makeExpr(fun, type, static), extending);
    391        }
    392    }
    393 
    394    function assertValidSuperPropTypes(assertion, makeStr, makeExpr, static, extending) {
    395        for (let type of ["method", "get", "set"]) {
    396            if (type === "method") {
    397                // methods can also be generators
    398                assertValidSuperProps(assertion, makeStr, makeExpr, type, true, [], static, extending);
    399                assertValidSuperProps(assertion, makeStr, makeExpr, type, false, [], static, extending);
    400                continue;
    401            }
    402 
    403            // Setters require 1 argument, and getters require 0
    404            assertValidSuperProps(assertion, makeStr, makeExpr, type, false,
    405                type === "set" ? ["x"] : [], static, extending);
    406        }
    407    }
    408 
    409    function makeSuperPropMethodStr(propStr, type, generator, args) {
    410        return `${type === "method" ? "" : type} ${generator ? "*" : ""} method(${args.join(",")})
    411                {
    412                    ${propStr};
    413                }`;
    414    }
    415 
    416    function makeClassSuperPropStr(propStr, type, generator, args, static, extending) {
    417        return `class NAME ${extending ? "extends null" : ""} {
    418                    constructor() { };
    419                    ${static ? "static" : ""} ${makeSuperPropMethodStr(propStr, type, generator, args)}
    420                }`;
    421    }
    422    function makeClassSuperPropExpr(fun, type, static) {
    423        // We are going right into assertClass, so we don't have to build the
    424        // entire statement.
    425        return [ctorPlaceholder,
    426            classMethod(ident("method"), fun, type, static)];
    427    }
    428    function doClassSuperPropAssert(str, expr, extending) {
    429        assertClass(str, expr, extending ? lit(null) : null);
    430    }
    431    function assertValidClassSuperPropExtends(extending) {
    432        // super.prop and super[prop] are valid, regardless of whether the
    433        // method is static or not
    434        assertValidSuperPropTypes(doClassSuperPropAssert, makeClassSuperPropStr, makeClassSuperPropExpr,
    435            false, extending);
    436        assertValidSuperPropTypes(doClassSuperPropAssert, makeClassSuperPropStr, makeClassSuperPropExpr,
    437            true, extending);
    438    }
    439    function assertValidClassSuperProps() {
    440        // super.prop and super[prop] are valid, regardless of class heritage
    441        assertValidClassSuperPropExtends(false);
    442        assertValidClassSuperPropExtends(true);
    443    }
    444 
    445    function makeOLSuperPropStr(propStr, type, generator, args) {
    446        let str = `({ ${makeSuperPropMethodStr(propStr, type, generator, args)} })`;
    447        return str;
    448    }
    449    function makeOLSuperPropExpr(fun) {
    450        return objExpr([{ type: "Property", key: ident("method"), value: fun }]);
    451    }
    452    function assertValidOLSuperProps() {
    453        assertValidSuperPropTypes(assertExpr, makeOLSuperPropStr, makeOLSuperPropExpr);
    454    }
    455 
    456 
    457    // Check all valid uses of SuperProperty
    458    assertValidClassSuperProps();
    459    assertValidOLSuperProps();
    460 
    461    // SuperProperty is forbidden outside of method definitions.
    462    assertError("function foo () { super.prop; }", SyntaxError);
    463    assertError("(function () { super.prop; }", SyntaxError);
    464    assertError("(()=>super.prop)", SyntaxError);
    465    assertError("function *foo() { super.prop; }", SyntaxError);
    466    assertError("super.prop", SyntaxError);
    467    assertError("function foo () { super['prop']; }", SyntaxError);
    468    assertError("(function () { super['prop']; }", SyntaxError);
    469    assertError("(()=>super['prop'])", SyntaxError);
    470    assertError("function *foo() { super['prop']; }", SyntaxError);
    471    assertError("super['prop']", SyntaxError);
    472 
    473    // Or inside functions inside method definitions...
    474    assertClassError("class NAME { constructor() { function nested() { super.prop; }}}", SyntaxError);
    475 
    476    // Bare super is forbidden
    477    assertError("super", SyntaxError);
    478 
    479    // Even where super is otherwise allowed
    480    assertError("{ foo() { super } }", SyntaxError);
    481    assertClassError("class NAME { constructor() { super; } }", SyntaxError);
    482 
    483    /* SuperCall */
    484 
    485    // SuperCall is invalid outside derived class constructors.
    486    assertError("super()", SyntaxError);
    487    assertError("(function() { super(); })", SyntaxError);
    488 
    489 
    490    // Even in class constructors
    491    assertClassError("class NAME { constructor() { super(); } }", SyntaxError);
    492 
    493    function superConstructor(args) {
    494        return classMethod(ident("constructor"),
    495            methodFun("NAME", "method", false,
    496                [], [exprStmt(superCallExpr(args))]),
    497            "method", false);
    498    }
    499 
    500    function superCallBody(args) {
    501        return [exprStmt(superCallExpr(args))];
    502    }
    503 
    504    // SuperCall works with various argument configurations.
    505    assertClass("class NAME extends null { constructor() { super() } }",
    506        [ctorPlaceholder], lit(null), superCallBody([]));
    507    assertClass("class NAME extends null { constructor() { super(1) } }",
    508        [ctorPlaceholder], lit(null), superCallBody([lit(1)]));
    509    assertClass("class NAME extends null { constructor() { super(1, a) } }",
    510        [ctorPlaceholder], lit(null), superCallBody([lit(1), ident("a")]));
    511    assertClass("class NAME extends null { constructor() { super(...[]) } }",
    512        [ctorPlaceholder], lit(null), superCallBody([spread(arrExpr([]))]));
    513 
    514    /* EOF */
    515    // Clipped classes should throw a syntax error
    516    assertClassError("class NAME {", SyntaxError);
    517    assertClassError("class NAME {;", SyntaxError);
    518    assertClassError("class NAME { constructor", SyntaxError);
    519    assertClassError("class NAME { constructor(", SyntaxError);
    520    assertClassError("class NAME { constructor()", SyntaxError);
    521    assertClassError("class NAME { constructor()", SyntaxError);
    522    assertClassError("class NAME { constructor() {", SyntaxError);
    523    assertClassError("class NAME { constructor() { }", SyntaxError);
    524    assertClassError("class NAME { static", SyntaxError);
    525    assertClassError("class NAME { static y", SyntaxError);
    526    assertClassError("class NAME { static *", SyntaxError);
    527    assertClassError("class NAME { static *y", SyntaxError);
    528    assertClassError("class NAME { static get", SyntaxError);
    529    assertClassError("class NAME { static get y", SyntaxError);
    530    assertClassError("class NAME { static ;", SyntaxError);
    531    assertClassError("class NAME extends", SyntaxError);
    532    assertClassError("class NAME { constructor() { super", SyntaxError);
    533    assertClassError("class NAME { constructor() { super.", SyntaxError);
    534    assertClassError("class NAME { constructor() { super.x", SyntaxError);
    535    assertClassError("class NAME { constructor() { super.m(", SyntaxError);
    536    assertClassError("class NAME { constructor() { super[", SyntaxError);
    537    assertClassError("class NAME { constructor() { super(", SyntaxError);
    538 
    539    // Can not omit curly brackets
    540    assertClassError("class NAME { constructor() ({}) }", SyntaxError);
    541    assertClassError("class NAME { constructor() void 0 }", SyntaxError);
    542    assertClassError("class NAME { constructor() 1 }", SyntaxError);
    543    assertClassError("class NAME { constructor() false }", SyntaxError);
    544    assertClassError("class NAME { constructor() {} a() ({}) }", SyntaxError);
    545    assertClassError("class NAME { constructor() {} a() void 0 }", SyntaxError);
    546    assertClassError("class NAME { constructor() {} a() 1 }", SyntaxError);
    547    assertClassError("class NAME { constructor() {} a() false }", SyntaxError);
    548 
    549 }
    550 
    551 runtest(testClasses);