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);