1 // Copyright 2014 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 'use strict'; 6 7 8 function ID(x) { 9 return x; 10 } 11 12 13 (function TestClassMethodString() { 14 class C { 15 a() { return 'A'} 16 ['b']() { return 'B'; } 17 c() { return 'C'; } 18 [ID('d')]() { return 'D'; } 19 } 20 assertEquals('A', new C().a()); 21 assertEquals('B', new C().b()); 22 assertEquals('C', new C().c()); 23 assertEquals('D', new C().d()); 24 assertArrayEquals([], Object.keys(C.prototype)); 25 assertArrayEquals(['constructor', 'a', 'b', 'c', 'd'], 26 Object.getOwnPropertyNames(C.prototype)); 27 })(); 28 29 30 (function TestClassMethodNumber() { 31 class C { 32 a() { return 'A'; } 33 [1]() { return 'B'; } 34 c() { return 'C'; } 35 [ID(2)]() { return 'D'; } 36 } 37 assertEquals('A', new C().a()); 38 assertEquals('B', new C()[1]()); 39 assertEquals('C', new C().c()); 40 assertEquals('D', new C()[2]()); 41 // Array indexes first. 42 assertArrayEquals([], Object.keys(C.prototype)); 43 assertArrayEquals(['1', '2', 'constructor', 'a', 'c'], 44 Object.getOwnPropertyNames(C.prototype)); 45 })(); 46 47 48 (function TestClassMethodSymbol() { 49 var sym1 = Symbol(); 50 var sym2 = Symbol(); 51 class C { 52 a() { return 'A'; } 53 [sym1]() { return 'B'; } 54 c() { return 'C'; } 55 [ID(sym2)]() { return 'D'; } 56 } 57 assertEquals('A', new C().a()); 58 assertEquals('B', new C()[sym1]()); 59 assertEquals('C', new C().c()); 60 assertEquals('D', new C()[sym2]()); 61 assertArrayEquals([], Object.keys(C.prototype)); 62 assertArrayEquals(['constructor', 'a', 'c'], 63 Object.getOwnPropertyNames(C.prototype)); 64 assertArrayEquals([sym1, sym2], Object.getOwnPropertySymbols(C.prototype)); 65 })(); 66 67 68 69 (function TestStaticClassMethodString() { 70 class C { 71 static a() { return 'A'} 72 static ['b']() { return 'B'; } 73 static c() { return 'C'; } 74 static ['d']() { return 'D'; } 75 } 76 assertEquals('A', C.a()); 77 assertEquals('B', C.b()); 78 assertEquals('C', C.c()); 79 assertEquals('D', C.d()); 80 assertArrayEquals([], Object.keys(C)); 81 // TODO(arv): It is not clear that we are adding the "standard" properties 82 // in the right order. As far as I can tell the spec adds them in alphabetical 83 // order. 84 assertArrayEquals(['length', 'name', 'prototype', 'a', 'b', 'c', 'd'], 85 Object.getOwnPropertyNames(C)); 86 })(); 87 88 89 (function TestStaticClassMethodNumber() { 90 class C { 91 static a() { return 'A'; } 92 static [1]() { return 'B'; } 93 static c() { return 'C'; } 94 static [2]() { return 'D'; } 95 } 96 assertEquals('A', C.a()); 97 assertEquals('B', C[1]()); 98 assertEquals('C', C.c()); 99 assertEquals('D', C[2]()); 100 // Array indexes first. 101 assertArrayEquals([], Object.keys(C)); 102 assertArrayEquals(['1', '2', 'length', 'name', 'prototype', 'a', 'c'], 103 Object.getOwnPropertyNames(C)); 104 })(); 105 106 107 (function TestStaticClassMethodSymbol() { 108 var sym1 = Symbol(); 109 var sym2 = Symbol(); 110 class C { 111 static a() { return 'A'; } 112 static [sym1]() { return 'B'; } 113 static c() { return 'C'; } 114 static [sym2]() { return 'D'; } 115 } 116 assertEquals('A', C.a()); 117 assertEquals('B', C[sym1]()); 118 assertEquals('C', C.c()); 119 assertEquals('D', C[sym2]()); 120 assertArrayEquals([], Object.keys(C)); 121 assertArrayEquals(['length', 'name', 'prototype', 'a', 'c'], 122 Object.getOwnPropertyNames(C)); 123 assertArrayEquals([sym1, sym2], Object.getOwnPropertySymbols(C)); 124 })(); 125 126 127 128 function assertIteratorResult(value, done, result) { 129 assertEquals({ value: value, done: done}, result); 130 } 131 132 133 (function TestGeneratorComputedName() { 134 class C { 135 *['a']() { 136 yield 1; 137 yield 2; 138 } 139 } 140 var iter = new C().a(); 141 assertIteratorResult(1, false, iter.next()); 142 assertIteratorResult(2, false, iter.next()); 143 assertIteratorResult(undefined, true, iter.next()); 144 assertArrayEquals([], Object.keys(C.prototype)); 145 assertArrayEquals(['constructor', 'a'], 146 Object.getOwnPropertyNames(C.prototype)); 147 })(); 148 149 150 (function TestToNameSideEffects() { 151 var counter = 0; 152 var key1 = { 153 toString: function() { 154 assertEquals(0, counter++); 155 return 'b'; 156 } 157 }; 158 var key2 = { 159 toString: function() { 160 assertEquals(1, counter++); 161 return 'd'; 162 } 163 }; 164 class C { 165 a() { return 'A'; } 166 [key1]() { return 'B'; } 167 c() { return 'C'; } 168 [key2]() { return 'D'; } 169 } 170 assertEquals(2, counter); 171 assertEquals('A', new C().a()); 172 assertEquals('B', new C().b()); 173 assertEquals('C', new C().c()); 174 assertEquals('D', new C().d()); 175 assertArrayEquals([], Object.keys(C.prototype)); 176 assertArrayEquals(['constructor', 'a', 'b', 'c', 'd'], 177 Object.getOwnPropertyNames(C.prototype)); 178 })(); 179 180 181 (function TestToNameSideEffectsNumbers() { 182 var counter = 0; 183 var key1 = { 184 valueOf: function() { 185 assertEquals(0, counter++); 186 return 1; 187 }, 188 toString: null 189 }; 190 var key2 = { 191 valueOf: function() { 192 assertEquals(1, counter++); 193 return 2; 194 }, 195 toString: null 196 }; 197 198 class C { 199 a() { return 'A'; } 200 [key1]() { return 'B'; } 201 c() { return 'C'; } 202 [key2]() { return 'D'; } 203 } 204 assertEquals(2, counter); 205 assertEquals('A', new C().a()); 206 assertEquals('B', new C()[1]()); 207 assertEquals('C', new C().c()); 208 assertEquals('D', new C()[2]()); 209 // Array indexes first. 210 assertArrayEquals([], Object.keys(C.prototype)); 211 assertArrayEquals(['1', '2', 'constructor', 'a', 'c'], 212 Object.getOwnPropertyNames(C.prototype)); 213 })(); 214 215 216 (function TestGetter() { 217 class C { 218 get ['a']() { 219 return 'A'; 220 } 221 } 222 assertEquals('A', new C().a); 223 224 class C2 { 225 get b() { 226 assertUnreachable(); 227 } 228 get ['b']() { 229 return 'B'; 230 } 231 } 232 assertEquals('B', new C2().b); 233 234 class C3 { 235 get c() { 236 assertUnreachable(); 237 } 238 get ['c']() { 239 assertUnreachable(); 240 } 241 get ['c']() { 242 return 'C'; 243 } 244 } 245 assertEquals('C', new C3().c); 246 247 class C4 { 248 get ['d']() { 249 assertUnreachable(); 250 } 251 get d() { 252 return 'D'; 253 } 254 } 255 assertEquals('D', new C4().d); 256 })(); 257 258 259 (function TestSetter() { 260 var calls = 0; 261 class C { 262 set ['a'](_) { 263 calls++; 264 } 265 } 266 new C().a = 'A'; 267 assertEquals(1, calls); 268 269 calls = 0; 270 class C2 { 271 set b(_) { 272 assertUnreachable(); 273 } 274 set ['b'](_) { 275 calls++; 276 } 277 } 278 new C2().b = 'B'; 279 assertEquals(1, calls); 280 281 calls = 0; 282 class C3 { 283 set c(_) { 284 assertUnreachable() 285 } 286 set ['c'](_) { 287 assertUnreachable() 288 } 289 set ['c'](_) { 290 calls++ 291 } 292 } 293 new C3().c = 'C'; 294 assertEquals(1, calls); 295 296 calls = 0; 297 class C4 { 298 set ['d'](_) { 299 assertUnreachable() 300 } 301 set d(_) { 302 calls++ 303 } 304 } 305 new C4().d = 'D'; 306 assertEquals(1, calls); 307 })(); 308 309 310 (function TestPrototype() { 311 assertThrows(function() { 312 class C { 313 static ['prototype']() { 314 return 1; 315 } 316 } 317 }, TypeError); 318 319 assertThrows(function() { 320 class C2 { 321 static get ['prototype']() { 322 return 2; 323 } 324 } 325 }, TypeError); 326 327 assertThrows(function() { 328 class C3 { 329 static set ['prototype'](x) { 330 assertEquals(3, x); 331 } 332 } 333 }, TypeError); 334 335 assertThrows(function() { 336 class C4 { 337 static *['prototype']() { 338 yield 1; 339 yield 2; 340 } 341 } 342 }, TypeError); 343 })(); 344 345 346 (function TestPrototypeConcat() { 347 assertThrows(function() { 348 class C { 349 static ['pro' + 'tot' + 'ype']() { 350 return 1; 351 } 352 } 353 }, TypeError); 354 355 assertThrows(function() { 356 class C2 { 357 static get ['pro' + 'tot' + 'ype']() { 358 return 2; 359 } 360 } 361 }, TypeError); 362 363 assertThrows(function() { 364 class C3 { 365 static set ['pro' + 'tot' + 'ype'](x) { 366 assertEquals(3, x); 367 } 368 } 369 }, TypeError); 370 371 assertThrows(function() { 372 class C4 { 373 static *['pro' + 'tot' + 'ype']() { 374 yield 1; 375 yield 2; 376 } 377 } 378 }, TypeError); 379 })(); 380 381 382 (function TestConstructor() { 383 // Normally a constructor property is not allowed. 384 class C { 385 ['constructor']() { 386 return 1; 387 } 388 } 389 assertTrue(C !== C.prototype.constructor); 390 assertEquals(1, new C().constructor()); 391 392 class C2 { 393 get ['constructor']() { 394 return 2; 395 } 396 } 397 assertEquals(2, new C2().constructor); 398 399 var calls = 0; 400 class C3 { 401 set ['constructor'](x) { 402 assertEquals(3, x); 403 calls++; 404 } 405 } 406 new C3().constructor = 3; 407 assertEquals(1, calls); 408 409 class C4 { 410 *['constructor']() { 411 yield 1; 412 yield 2; 413 } 414 } 415 var iter = new C4().constructor(); 416 assertIteratorResult(1, false, iter.next()); 417 assertIteratorResult(2, false, iter.next()); 418 assertIteratorResult(undefined, true, iter.next()); 419 })(); 420 421 422 (function TestExceptionInName() { 423 function MyError() {}; 424 function throwMyError() { 425 throw new MyError(); 426 } 427 assertThrows(function() { 428 class C { 429 [throwMyError()]() {} 430 } 431 }, MyError); 432 assertThrows(function() { 433 class C { 434 get [throwMyError()]() { return 42; } 435 } 436 }, MyError); 437 assertThrows(function() { 438 class C { 439 set [throwMyError()](_) { } 440 } 441 }, MyError); 442 })(); 443 444 445 (function TestTdzName() { 446 assertThrows(function() { 447 class C { 448 [C]() {} 449 } 450 }, ReferenceError); 451 assertThrows(function() { 452 class C { 453 get [C]() { return 42; } 454 } 455 }, ReferenceError); 456 assertThrows(function() { 457 class C { 458 set [C](_) { } 459 } 460 }, ReferenceError); 461 })(); 462