1// Copyright 2015 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// Flags: --harmony-destructuring-assignment --harmony-destructuring-bind 6 7// script-level tests 8var ox, oy = {}, oz; 9({ 10 x: ox, 11 y: oy.value, 12 y2: oy["value2"], 13 z: ({ set v(val) { oz = val; } }).v 14} = { 15 x: "value of x", 16 y: "value of y1", 17 y2: "value of y2", 18 z: "value of z" 19}); 20assertEquals("value of x", ox); 21assertEquals("value of y1", oy.value); 22assertEquals("value of y2", oy.value2); 23assertEquals("value of z", oz); 24 25[ox, oy.value, oy["value2"], ...{ set v(val) { oz = val; } }.v] = [ 26 1007, 27 798432, 28 555, 29 1, 2, 3, 4, 5 30]; 31assertEquals(ox, 1007); 32assertEquals(oy.value, 798432); 33assertEquals(oy.value2, 555); 34assertEquals(oz, [1, 2, 3, 4, 5]); 35 36 37(function testInFunction() { 38 var x, y = {}, z; 39 ({ 40 x: x, 41 y: y.value, 42 y2: y["value2"], 43 z: ({ set v(val) { z = val; } }).v 44 } = { 45 x: "value of x", 46 y: "value of y1", 47 y2: "value of y2", 48 z: "value of z" 49 }); 50 assertEquals("value of x", x); 51 assertEquals("value of y1", y.value); 52 assertEquals("value of y2", y.value2); 53 assertEquals("value of z", z); 54 55 [x, y.value, y["value2"], ...{ set v(val) { z = val; } }.v] = [ 56 1007, 57 798432, 58 555, 59 1, 2, 3, 4, 5 60 ]; 61 assertEquals(x, 1007); 62 assertEquals(y.value, 798432); 63 assertEquals(y.value2, 555); 64 assertEquals(z, [1, 2, 3, 4, 5]); 65})(); 66 67 68(function testArrowFunctionInitializers() { 69 var fn = (config = { 70 value: defaults.value, 71 nada: { nada: defaults.nada } = { nada: "nothing" } 72 } = { value: "BLAH" }) => config; 73 var defaults = {}; 74 assertEquals({ value: "BLAH" }, fn()); 75 assertEquals("BLAH", defaults.value); 76 assertEquals("nothing", defaults.nada); 77})(); 78 79 80(function testArrowFunctionInitializers2() { 81 var fn = (config = [ 82 defaults.value, 83 { nada: defaults.nada } = { nada: "nothing" } 84 ] = ["BLAH"]) => config; 85 var defaults = {}; 86 assertEquals(["BLAH"], fn()); 87 assertEquals("BLAH", defaults.value); 88 assertEquals("nothing", defaults.nada); 89})(); 90 91 92(function testFunctionInitializers() { 93 function fn(config = { 94 value: defaults.value, 95 nada: { nada: defaults.nada } = { nada: "nothing" } 96 } = { value: "BLAH" }) { 97 return config; 98 } 99 var defaults = {}; 100 assertEquals({ value: "BLAH" }, fn()); 101 assertEquals("BLAH", defaults.value); 102 assertEquals("nothing", defaults.nada); 103})(); 104 105 106(function testFunctionInitializers2() { 107 function fn(config = [ 108 defaults.value, 109 { nada: defaults.nada } = { nada: "nothing" } 110 ] = ["BLAH"]) { return config; } 111 var defaults = {}; 112 assertEquals(["BLAH"], fn()); 113 assertEquals("BLAH", defaults.value); 114 assertEquals("nothing", defaults.nada); 115})(); 116 117 118(function testDeclarationInitializers() { 119 var defaults = {}; 120 var { value } = { value: defaults.value } = { value: "BLAH" }; 121 assertEquals("BLAH", value); 122 assertEquals("BLAH", defaults.value); 123})(); 124 125 126(function testDeclarationInitializers2() { 127 var defaults = {}; 128 var [value] = [defaults.value] = ["BLAH"]; 129 assertEquals("BLAH", value); 130 assertEquals("BLAH", defaults.value); 131})(); 132 133 134(function testObjectLiteralProperty() { 135 var ext = {}; 136 var obj = { 137 a: { b: ext.b, c: ext["c"], d: { set v(val) { ext.d = val; } }.v } = { 138 b: "b", c: "c", d: "d" } 139 }; 140 assertEquals({ b: "b", c: "c", d: "d" }, ext); 141 assertEquals({ a: { b: "b", c: "c", d: "d" } }, obj); 142})(); 143 144 145(function testArrayLiteralProperty() { 146 var ext = {}; 147 var obj = [ 148 ...[ ext.b, ext["c"], { set v(val) { ext.d = val; } }.v ] = [ 149 "b", "c", "d" ] 150 ]; 151 assertEquals({ b: "b", c: "c", d: "d" }, ext); 152 assertEquals([ "b", "c", "d" ], obj); 153})(); 154 155 156// TODO(caitp): add similar test for ArrayPatterns, once Proxies support 157// delegating symbol-keyed get/set. 158(function testObjectPatternOperationOrder() { 159 var steps = []; 160 var store = {}; 161 function computePropertyName(name) { 162 steps.push("compute name: " + name); 163 return name; 164 } 165 function loadValue(descr, value) { 166 steps.push("load: " + descr + " > " + value); 167 return value; 168 } 169 function storeValue(descr, name, value) { 170 steps.push("store: " + descr + " = " + value); 171 store[name] = value; 172 } 173 var result = { 174 get a() { assertUnreachable(); }, 175 set a(value) { storeValue("result.a", "a", value); }, 176 get b() { assertUnreachable(); }, 177 set b(value) { storeValue("result.b", "b", value); } 178 }; 179 180 ({ 181 obj: { 182 x: result.a = 10, 183 [computePropertyName("y")]: result.b = false, 184 } = {} 185 } = { obj: { 186 get x() { return loadValue(".temp.obj.x", undefined); }, 187 set x(value) { assertUnreachable(); }, 188 get y() { return loadValue(".temp.obj.y", undefined); }, 189 set y(value) { assertUnreachable(); } 190 }}); 191 192 assertPropertiesEqual({ 193 a: 10, 194 b: false 195 }, store); 196 197 assertArrayEquals([ 198 "load: .temp.obj.x > undefined", 199 "store: result.a = 10", 200 201 "compute name: y", 202 "load: .temp.obj.y > undefined", 203 "store: result.b = false" 204 ], steps); 205 206 steps = []; 207 208 ({ 209 obj: { 210 x: result.a = 50, 211 [computePropertyName("y")]: result.b = "hello", 212 } = {} 213 } = { obj: { 214 get x() { return loadValue(".temp.obj.x", 20); }, 215 set x(value) { assertUnreachable(); }, 216 get y() { return loadValue(".temp.obj.y", true); }, 217 set y(value) { assertUnreachable(); } 218 }}); 219 220 assertPropertiesEqual({ 221 a: 20, 222 b: true 223 }, store); 224 225 assertArrayEquals([ 226 "load: .temp.obj.x > 20", 227 "store: result.a = 20", 228 "compute name: y", 229 "load: .temp.obj.y > true", 230 "store: result.b = true", 231 ], steps); 232})(); 233 234// Credit to Mike Pennisi and other Test262 contributors for originally writing 235// the testse the following are based on. 236(function testArrayElision() { 237 var value = [1, 2, 3, 4, 5, 6, 7, 8, 9]; 238 var a, obj = {}; 239 var result = [, a, , obj.b, , ...obj["rest"]] = value; 240 241 assertEquals(result, value); 242 assertEquals(2, a); 243 assertEquals(4, obj.b); 244 assertArrayEquals([6, 7, 8, 9], obj.rest); 245})(); 246 247(function testArrayElementInitializer() { 248 function test(value, initializer, expected) { 249 var a, obj = {}; 250 var initialized = false; 251 var shouldBeInitialized = value[0] === undefined; 252 assertEquals(value, [ a = (initialized = true, initializer) ] = value); 253 assertEquals(expected, a); 254 assertEquals(shouldBeInitialized, initialized); 255 256 var initialized2 = false; 257 assertEquals(value, [ obj.a = (initialized2 = true, initializer) ] = value); 258 assertEquals(expected, obj.a); 259 assertEquals(shouldBeInitialized, initialized2); 260 } 261 262 test([], "BAM!", "BAM!"); 263 test([], "BOOP!", "BOOP!"); 264 test([null], 123, null); 265 test([undefined], 456, 456); 266 test([,], "PUPPIES", "PUPPIES"); 267 268 (function accept_IN() { 269 var value = [], x; 270 assertEquals(value, [ x = 'x' in {} ] = value); 271 assertEquals(false, x); 272 })(); 273 274 (function ordering() { 275 var x = 0, a, b, value = []; 276 assertEquals(value, [ a = x += 1, b = x *= 2 ] = value); 277 assertEquals(1, a); 278 assertEquals(2, b); 279 assertEquals(2, x); 280 })(); 281 282 (function yieldExpression() { 283 var value = [], it, result, x; 284 it = (function*() { 285 result = [ x = yield ] = value; 286 })(); 287 var next = it.next(); 288 289 assertEquals(undefined, result); 290 assertEquals(undefined, next.value); 291 assertEquals(false, next.done); 292 assertEquals(undefined, x); 293 294 next = it.next(86); 295 296 assertEquals(value, result); 297 assertEquals(undefined, next.value); 298 assertEquals(true, next.done); 299 assertEquals(86, x); 300 })(); 301 302 (function yieldIdentifier() { 303 var value = [], yield = "BOOP!", x; 304 assertEquals(value, [ x = yield ] = value); 305 assertEquals("BOOP!", x); 306 })(); 307 308 assertThrows(function let_TDZ() { 309 "use strict"; 310 var x; 311 [ x = y ] = []; 312 let y; 313 }, ReferenceError); 314})(); 315 316 317(function testArrayElementNestedPattern() { 318 assertThrows(function nestedArrayRequireObjectCoercibleNull() { 319 var x; [ [ x ] ] = [ null ]; 320 }, TypeError); 321 322 assertThrows(function nestedArrayRequireObjectCoercibleUndefined() { 323 var x; [ [ x ] ] = [ undefined ]; 324 }, TypeError); 325 326 assertThrows(function nestedArrayRequireObjectCoercibleUndefined2() { 327 var x; [ [ x ] ] = [ ]; 328 }, TypeError); 329 330 assertThrows(function nestedArrayRequireObjectCoercibleUndefined3() { 331 var x; [ [ x ] ] = [ , ]; 332 }, TypeError); 333 334 assertThrows(function nestedObjectRequireObjectCoercibleNull() { 335 var x; [ { x } ] = [ null ]; 336 }, TypeError); 337 338 assertThrows(function nestedObjectRequireObjectCoercibleUndefined() { 339 var x; [ { x } ] = [ undefined ]; 340 }, TypeError); 341 342 assertThrows(function nestedObjectRequireObjectCoercibleUndefined2() { 343 var x; [ { x } ] = [ ]; 344 }, TypeError); 345 346 assertThrows(function nestedObjectRequireObjectCoercibleUndefined3() { 347 var x; [ { x } ] = [ , ]; 348 }, TypeError); 349 350 (function nestedArray() { 351 var x, value = [ [ "zap", "blonk" ] ]; 352 assertEquals(value, [ [ , x ] ] = value); 353 assertEquals("blonk", x); 354 })(); 355 356 (function nestedObject() { 357 var x, value = [ { a: "zap", b: "blonk" } ]; 358 assertEquals(value, [ { b: x } ] = value); 359 assertEquals("blonk", x); 360 })(); 361})(); 362 363(function testArrayRestElement() { 364 (function testBasic() { 365 var x, rest, array = [1, 2, 3]; 366 assertEquals(array, [x, ...rest] = array); 367 assertEquals(1, x); 368 assertEquals([2, 3], rest); 369 370 array = [4, 5, 6]; 371 assertEquals(array, [, ...rest] = array); 372 assertEquals([5, 6], rest); 373 374 })(); 375 376 (function testNestedRestObject() { 377 var value = [1, 2, 3], x; 378 assertEquals(value, [...{ 1: x }] = value); 379 assertEquals(2, x); 380 })(); 381 382 (function iterable() { 383 var count = 0; 384 var x, y, z; 385 function* g() { 386 count++; 387 yield; 388 count++; 389 yield; 390 count++; 391 yield; 392 } 393 var it = g(); 394 assertEquals(it, [...x] = it); 395 assertEquals([undefined, undefined, undefined], x); 396 assertEquals(3, count); 397 398 it = [g()]; 399 assertEquals(it, [ [...y] ] = it); 400 assertEquals([undefined, undefined, undefined], y); 401 assertEquals(6, count); 402 403 it = { a: g() }; 404 assertEquals(it, { a: [...z] } = it); 405 assertEquals([undefined, undefined, undefined], z); 406 assertEquals(9, count); 407 })(); 408})(); 409 410(function testRequireObjectCoercible() { 411 assertThrows(() => ({} = undefined), TypeError); 412 assertThrows(() => ({} = null), TypeError); 413 assertThrows(() => [] = undefined, TypeError); 414 assertThrows(() => [] = null, TypeError); 415 assertEquals("test", ({} = "test")); 416 assertEquals("test", [] = "test"); 417 assertEquals(123, ({} = 123)); 418})(); 419 420(function testConstReassignment() { 421 "use strict"; 422 const c = "untouchable"; 423 assertThrows(() => { [ c ] = [ "nope!" ]; }, TypeError); 424 assertThrows(() => { [ [ c ] ] = [ [ "nope!" ] ]; }, TypeError); 425 assertThrows(() => { [ { c } ] = [ { c: "nope!" } ]; }, TypeError); 426 assertThrows(() => { ({ c } = { c: "nope!" }); }, TypeError); 427 assertThrows(() => { ({ a: { c } } = { a: { c: "nope!" } }); }, TypeError); 428 assertThrows(() => { ({ a: [ c ] } = { a: [ "nope!" ] }); }, TypeError); 429 assertEquals("untouchable", c); 430})(); 431 432(function testForIn() { 433 var log = []; 434 var x = {}; 435 var object = { 436 "Apenguin": 1, 437 "\u{1F382}cake": 2, 438 "Bpuppy": 3, 439 "Cspork": 4 440 }; 441 for ([x.firstLetter, ...x.rest] in object) { 442 if (x.firstLetter === "A") { 443 assertEquals(["p", "e", "n", "g", "u", "i", "n"], x.rest); 444 continue; 445 } 446 if (x.firstLetter === "C") { 447 assertEquals(["s", "p", "o", "r", "k"], x.rest); 448 break; 449 } 450 log.push({ firstLetter: x.firstLetter, rest: x.rest }); 451 } 452 assertEquals([ 453 { firstLetter: "\u{1F382}", rest: ["c", "a", "k", "e"] }, 454 { firstLetter: "B", rest: ["p", "u", "p", "p", "y"] }, 455 ], log); 456})(); 457 458(function testForOf() { 459 var log = []; 460 var x = {}; 461 var names = [ 462 "Apenguin", 463 "\u{1F382}cake", 464 "Bpuppy", 465 "Cspork" 466 ]; 467 for ([x.firstLetter, ...x.rest] of names) { 468 if (x.firstLetter === "A") { 469 assertEquals(["p", "e", "n", "g", "u", "i", "n"], x.rest); 470 continue; 471 } 472 if (x.firstLetter === "C") { 473 assertEquals(["s", "p", "o", "r", "k"], x.rest); 474 break; 475 } 476 log.push({ firstLetter: x.firstLetter, rest: x.rest }); 477 } 478 assertEquals([ 479 { firstLetter: "\u{1F382}", rest: ["c", "a", "k", "e"] }, 480 { firstLetter: "B", rest: ["p", "u", "p", "p", "y"] }, 481 ], log); 482})(); 483