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-bind
6// Flags: --harmony-default-parameters
7
8(function TestObjectLiteralPattern() {
9  var { x : x, y : y, get, set } = { x : 1, y : 2, get: 3, set: 4 };
10  assertEquals(1, x);
11  assertEquals(2, y);
12  assertEquals(3, get);
13  assertEquals(4, set);
14
15  var {z} = { z : 3 };
16  assertEquals(3, z);
17
18
19  var sum = 0;
20  for (var {z} = { z : 3 }; z != 0; z--) {
21    sum += z;
22  }
23  assertEquals(6, sum);
24
25
26  var log = [];
27  var o = {
28    get x() {
29      log.push("x");
30      return 0;
31    },
32    get y() {
33      log.push("y");
34      return {
35        get z() { log.push("z"); return 1; }
36      }
37    }
38  };
39  var { x : x0, y : { z : z1 }, x : x1 } = o;
40  assertSame(0, x0);
41  assertSame(1, z1);
42  assertSame(0, x1);
43  assertArrayEquals(["x", "y", "z", "x"], log);
44}());
45
46
47(function TestObjectLiteralPatternInitializers() {
48  var { x : x, y : y = 2 } = { x : 1 };
49  assertEquals(1, x);
50  assertEquals(2, y);
51
52  var {z = 3} = {};
53  assertEquals(3, z);
54
55  var sum = 0;
56  for (var {z = 3} = {}; z != 0; z--) {
57    sum += z;
58  }
59  assertEquals(6, sum);
60
61  var log = [];
62  var o = {
63    get x() {
64      log.push("x");
65      return undefined;
66    },
67    get y() {
68      log.push("y");
69      return {
70        get z() { log.push("z"); return undefined; }
71      }
72    }
73  };
74  var { x : x0 = 0, y : { z : z1 = 1}, x : x1 = 0} = o;
75  assertSame(0, x0);
76  assertSame(1, z1);
77  assertSame(0, x1);
78  assertArrayEquals(["x", "y", "z", "x"], log);
79}());
80
81
82(function TestObjectLiteralPatternLexicalInitializers() {
83  'use strict';
84  let { x : x, y : y = 2 } = { x : 1 };
85  assertEquals(1, x);
86  assertEquals(2, y);
87
88  let {z = 3} = {};
89  assertEquals(3, z);
90
91  let log = [];
92  let o = {
93    get x() {
94      log.push("x");
95      return undefined;
96    },
97    get y() {
98      log.push("y");
99      return {
100        get z() { log.push("z"); return undefined; }
101      }
102    }
103  };
104
105  let { x : x0 = 0, y : { z : z1 = 1 }, x : x1 = 5} = o;
106  assertSame(0, x0);
107  assertSame(1, z1);
108  assertSame(5, x1);
109  assertArrayEquals(["x", "y", "z", "x"], log);
110
111  let sum = 0;
112  for (let {x = 0, z = 3} = {}; z != 0; z--) {
113    assertEquals(0, x);
114    sum += z;
115  }
116  assertEquals(6, sum);
117}());
118
119
120(function TestObjectLiteralPatternLexical() {
121  'use strict';
122  let { x : x, y : y } = { x : 1, y : 2 };
123  assertEquals(1, x);
124  assertEquals(2, y);
125
126  let {z} = { z : 3 };
127  assertEquals(3, z);
128
129  let log = [];
130  let o = {
131    get x() {
132      log.push("x");
133      return 0;
134    },
135    get y() {
136      log.push("y");
137      return {
138        get z() { log.push("z"); return 1; }
139      }
140    }
141  };
142  let { x : x0, y : { z : z1 }, x : x1 } = o;
143  assertSame(0, x0);
144  assertSame(1, z1);
145  assertSame(0, x1);
146  assertArrayEquals(["x", "y", "z", "x"], log);
147
148  let sum = 0;
149  for (let {x, z} = { x : 0, z : 3 }; z != 0; z--) {
150    assertEquals(0, x);
151    sum += z;
152  }
153  assertEquals(6, sum);
154}());
155
156
157(function TestObjectLiteralPatternLexicalConst() {
158  'use strict';
159  const { x : x, y : y } = { x : 1, y : 2 };
160  assertEquals(1, x);
161  assertEquals(2, y);
162
163  assertThrows(function() { x++; }, TypeError);
164  assertThrows(function() { y++; }, TypeError);
165
166  const {z} = { z : 3 };
167  assertEquals(3, z);
168
169  for (const {x, z} = { x : 0, z : 3 }; z != 3 || x != 0;) {
170    assertTrue(false);
171  }
172}());
173
174
175(function TestFailingMatchesSloppy() {
176  var {x, y} = {};
177  assertSame(undefined, x);
178  assertSame(undefined, y);
179
180  var { x : { z1 }, y2} = { x : {}, y2 : 42 }
181  assertSame(undefined, z1);
182  assertSame(42, y2);
183}());
184
185
186(function TestFailingMatchesStrict() {
187  'use strict';
188  var {x, y} = {};
189  assertSame(undefined, x);
190  assertSame(undefined, y);
191
192  var { x : { z1 }, y2} = { x : {}, y2 : 42 }
193  assertSame(undefined, z1);
194  assertSame(42, y2);
195
196  {
197    let {x1,y1} = {};
198    assertSame(undefined, x1);
199    assertSame(undefined, y1);
200
201    let { x : { z1 }, y2} = { x : {}, y2 : 42 }
202    assertSame(undefined, z1);
203    assertSame(42, y2);
204  }
205}());
206
207
208(function TestTDZInIntializers() {
209  'use strict';
210  {
211    let {x, y = x} = {x : 42, y : 27};
212    assertSame(42, x);
213    assertSame(27, y);
214  }
215
216  {
217    let {x, y = x + 1} = { x : 42 };
218    assertSame(42, x);
219    assertSame(43, y);
220  }
221  assertThrows(function() {
222    let {x = y, y} = { y : 42 };
223  }, ReferenceError);
224
225  {
226    let {x, y = eval("x+1")} = {x:42};
227    assertEquals(42, x);
228    assertEquals(43, y);
229  }
230
231  {
232    let {x, y = () => eval("x+1")} = {x:42};
233    assertEquals(42, x);
234    assertEquals(43, y());
235  }
236
237  {
238    let {x = function() {return y+1;}, y} = {y:42};
239    assertEquals(43, x());
240    assertEquals(42, y);
241  }
242  {
243    let {x = function() {return eval("y+1");}, y} = {y:42};
244    assertEquals(43, x());
245    assertEquals(42, y);
246  }
247}());
248
249
250(function TestSideEffectsInInitializers() {
251  var callCount = 0;
252  function f(v) { callCount++; return v; }
253
254  callCount = 0;
255  var { x = f(42) } = { x : 27 };
256  assertSame(27, x);
257  assertEquals(0, callCount);
258
259  callCount = 0;
260  var { x = f(42) } = {};
261  assertSame(42, x);
262  assertEquals(1, callCount);
263}());
264
265
266(function TestMultipleAccesses() {
267  assertThrows(
268    "'use strict';"+
269    "const {x,x} = {x:1};",
270    SyntaxError);
271
272  assertThrows(
273    "'use strict';"+
274    "let {x,x} = {x:1};",
275     SyntaxError);
276
277  (function() {
278    var {x,x = 2} = {x : 1};
279    assertSame(1, x);
280  }());
281
282  assertThrows(function () {
283    'use strict';
284    let {x = (function() { x = 2; }())} = {};
285  }, ReferenceError);
286
287  (function() {
288    'use strict';
289    let {x = (function() { x = 2; }())} = {x:1};
290    assertSame(1, x);
291  }());
292}());
293
294
295(function TestComputedNames() {
296  var x = 1;
297  var {[x]:y} = {1:2};
298  assertSame(2, y);
299
300  (function(){
301    'use strict';
302    let {[x]:y} = {1:2};
303    assertSame(2, y);
304  }());
305
306  var callCount = 0;
307  function foo(v) { callCount++; return v; }
308
309  (function() {
310    callCount = 0;
311    var {[foo("abc")]:x} = {abc:42};
312    assertSame(42, x);
313    assertEquals(1, callCount);
314  }());
315
316  (function() {
317    'use strict';
318    callCount = 0;
319    let {[foo("abc")]:x} = {abc:42};
320    assertSame(42, x);
321    assertEquals(1, callCount);
322  }());
323
324  (function() {
325    callCount = 0;
326    var {[foo("abc")]:x} = {};
327    assertSame(undefined, x);
328    assertEquals(1, callCount);
329  }());
330
331  (function() {
332    'use strict';
333    callCount = 0;
334    let {[foo("abc")]:x} = {};
335    assertSame(undefined, x);
336    assertEquals(1, callCount);
337  }());
338
339  for (val of [null, undefined]) {
340    callCount = 0;
341    assertThrows(function() {
342      var {[foo()]:x} = val;
343    }, TypeError);
344    assertEquals(0, callCount);
345
346    callCount = 0;
347    assertThrows(function() {
348      'use strict';
349      let {[foo()]:x} = val;
350    }, TypeError);
351    assertEquals(0, callCount);
352  }
353
354  var log = [];
355  var o = {
356    get x() { log.push("get x"); return 1; },
357    get y() { log.push("get y"); return 2; }
358  }
359  function f(v) { log.push("f " + v); return v; }
360
361  (function() {
362    log = [];
363    var { [f('x')]:x, [f('y')]:y } = o;
364    assertSame(1, x);
365    assertSame(2, y);
366    assertArrayEquals(["f x", "get x", "f y", "get y"], log);
367  }());
368
369  (function() {
370    'use strict';
371    log = [];
372    let { [f('x')]:x, [f('y')]:y } = o;
373    assertSame(1, x);
374    assertSame(2, y);
375    assertArrayEquals(["f x", "get x", "f y", "get y"], log);
376  }());
377
378  (function() {
379    'use strict';
380    log = [];
381    const { [f('x')]:x, [f('y')]:y } = o;
382    assertSame(1, x);
383    assertSame(2, y);
384    assertArrayEquals(["f x", "get x", "f y", "get y"], log);
385  }());
386}());
387
388
389(function TestExceptions() {
390  for (var val of [null, undefined]) {
391    assertThrows(function() { var {} = val; }, TypeError);
392    assertThrows(function() { var {x} = val; }, TypeError);
393    assertThrows(function() { var { x : {} } = { x : val }; }, TypeError);
394    assertThrows(function() { 'use strict'; let {} = val; }, TypeError);
395    assertThrows(function() { 'use strict'; let {x} = val; }, TypeError);
396    assertThrows(function() { 'use strict'; let { x : {} } = { x : val }; },
397                 TypeError);
398  }
399}());
400
401
402(function TestArrayLiteral() {
403  var [a, b, c] = [1, 2, 3];
404  assertSame(1, a);
405  assertSame(2, b);
406  assertSame(3, c);
407}());
408
409(function TestIterators() {
410  var log = [];
411  function* f() {
412    log.push("1");
413    yield 1;
414    log.push("2");
415    yield 2;
416    log.push("3");
417    yield 3;
418    log.push("done");
419  };
420
421  (function() {
422    log = [];
423    var [a, b, c] = f();
424    assertSame(1, a);
425    assertSame(2, b);
426    assertSame(3, c);
427    assertArrayEquals(["1", "2", "3"], log);
428  }());
429
430  (function() {
431    log = [];
432    var [a, b, c, d] = f();
433    assertSame(1, a);
434    assertSame(2, b);
435    assertSame(3, c);
436    assertSame(undefined, d);
437    assertArrayEquals(["1", "2", "3", "done"], log);
438  }());
439
440  (function() {
441    log = [];
442    var [a, , c] = f();
443    assertSame(1, a);
444    assertSame(3, c);
445    assertArrayEquals(["1", "2", "3"], log);
446  }());
447
448  (function() {
449    log = [];
450    var [a, , c, d] = f();
451    assertSame(1, a);
452    assertSame(3, c);
453    assertSame(undefined, d);
454    assertArrayEquals(["1", "2", "3", "done"], log);
455  }());
456
457  (function() {
458    log = [];
459    // last comma is not an elision.
460    var [a, b,] = f();
461    assertSame(1, a);
462    assertSame(2, b);
463    assertArrayEquals(["1", "2"], log);
464  }());
465
466  (function() {
467    log = [];
468    // last comma is not an elision, but the comma before the last is.
469    var [a, b, ,] = f();
470    assertSame(1, a);
471    assertSame(2, b);
472    assertArrayEquals(["1", "2", "3"], log);
473  }());
474
475  (function() {
476    log = [];
477    var [a, ...rest] = f();
478    assertSame(1, a);
479    assertArrayEquals([2,3], rest);
480    assertArrayEquals(["1", "2", "3", "done"], log);
481  }());
482
483  (function() {
484    log = [];
485    var [a, b, c, ...rest] = f();
486    assertSame(1, a);
487    assertSame(2, b);
488    assertSame(3, c);
489    assertArrayEquals([], rest);
490    assertArrayEquals(["1", "2", "3", "done"], log);
491  }());
492
493  (function() {
494    log = [];
495    var [a, b, c, d, ...rest] = f();
496    assertSame(1, a);
497    assertSame(2, b);
498    assertSame(3, c);
499    assertSame(undefined, d);
500    assertArrayEquals([], rest);
501    assertArrayEquals(["1", "2", "3", "done"], log);
502  }());
503}());
504
505
506(function TestIteratorsLexical() {
507  'use strict';
508  var log = [];
509  function* f() {
510    log.push("1");
511    yield 1;
512    log.push("2");
513    yield 2;
514    log.push("3");
515    yield 3;
516    log.push("done");
517  };
518
519  (function() {
520    log = [];
521    let [a, b, c] = f();
522    assertSame(1, a);
523    assertSame(2, b);
524    assertSame(3, c);
525    assertArrayEquals(["1", "2", "3"], log);
526  }());
527
528  (function() {
529    log = [];
530    let [a, b, c, d] = f();
531    assertSame(1, a);
532    assertSame(2, b);
533    assertSame(3, c);
534    assertSame(undefined, d);
535    assertArrayEquals(["1", "2", "3", "done"], log);
536  }());
537
538  (function() {
539    log = [];
540    let [a, , c] = f();
541    assertSame(1, a);
542    assertSame(3, c);
543    assertArrayEquals(["1", "2", "3"], log);
544  }());
545
546  (function() {
547    log = [];
548    let [a, , c, d] = f();
549    assertSame(1, a);
550    assertSame(3, c);
551    assertSame(undefined, d);
552    assertArrayEquals(["1", "2", "3", "done"], log);
553  }());
554
555  (function() {
556    log = [];
557    // last comma is not an elision.
558    let [a, b,] = f();
559    assertSame(1, a);
560    assertSame(2, b);
561    assertArrayEquals(["1", "2"], log);
562  }());
563
564  (function() {
565    log = [];
566    // last comma is not an elision, but the comma before the last is.
567    let [a, b, ,] = f();
568    assertSame(1, a);
569    assertSame(2, b);
570    assertArrayEquals(["1", "2", "3"], log);
571  }());
572
573  (function() {
574    log = [];
575    let [a, ...rest] = f();
576    assertSame(1, a);
577    assertArrayEquals([2,3], rest);
578    assertArrayEquals(["1", "2", "3", "done"], log);
579  }());
580
581  (function() {
582    log = [];
583    let [a, b, c, ...rest] = f();
584    assertSame(1, a);
585    assertSame(2, b);
586    assertSame(3, c);
587    assertArrayEquals([], rest);
588    assertArrayEquals(["1", "2", "3", "done"], log);
589  }());
590
591  (function() {
592    log = [];
593    let [a, b, c, d, ...rest] = f();
594    assertSame(1, a);
595    assertSame(2, b);
596    assertSame(3, c);
597    assertSame(undefined, d);
598    assertArrayEquals([], rest);
599    assertArrayEquals(["1", "2", "3", "done"], log);
600  }());
601}());
602
603(function TestIteratorsRecursive() {
604  var log = [];
605  function* f() {
606    log.push("1");
607    yield {x : 1, y : 2};
608    log.push("2");
609    yield [42, 27, 30];
610    log.push("3");
611    yield "abc";
612    log.push("done");
613  };
614
615  (function() {
616    var [{x, y}, [a, b]] = f();
617    assertSame(1, x);
618    assertSame(2, y);
619    assertSame(42, a);
620    assertSame(27, b);
621    assertArrayEquals(["1", "2"], log);
622  }());
623
624  (function() {
625    'use strict';
626    log = [];
627    let [{x, y}, [a, b]] = f();
628    assertSame(1, x);
629    assertSame(2, y);
630    assertSame(42, a);
631    assertSame(27, b);
632    assertArrayEquals(["1", "2"], log);
633  }());
634}());
635
636
637(function TestForEachLexical() {
638  'use strict';
639  let a = [{x:1, y:-1}, {x:2,y:-2}, {x:3,y:-3}];
640  let sumX = 0;
641  let sumY = 0;
642  let fs = [];
643  for (let {x,y} of a) {
644    sumX += x;
645    sumY += y;
646    fs.push({fx : function() { return x; }, fy : function() { return y }});
647  }
648  assertSame(6, sumX);
649  assertSame(-6, sumY);
650  assertSame(3, fs.length);
651  for (let i = 0; i < fs.length; i++) {
652    let {fx,fy} = fs[i];
653    assertSame(i+1, fx());
654    assertSame(-(i+1), fy());
655  }
656
657  var o = { __proto__:null, 'a1':1, 'b2':2 };
658  let sx = '';
659  let sy = '';
660  for (let [x,y] in o) {
661    sx += x;
662    sy += y;
663  }
664  assertEquals('ab', sx);
665  assertEquals('12', sy);
666}());
667
668
669(function TestForEachVars() {
670  var a = [{x:1, y:-1}, {x:2,y:-2}, {x:3,y:-3}];
671  var sumX = 0;
672  var sumY = 0;
673  var fs = [];
674  for (var {x,y} of a) {
675    sumX += x;
676    sumY += y;
677    fs.push({fx : function() { return x; }, fy : function() { return y }});
678  }
679  assertSame(6, sumX);
680  assertSame(-6, sumY);
681  assertSame(3, fs.length);
682  for (var i = 0; i < fs.length; i++) {
683    var {fx,fy} = fs[i];
684    assertSame(3, fx());
685    assertSame(-3, fy());
686  }
687
688  var o = { __proto__:null, 'a1':1, 'b2':2 };
689  var sx = '';
690  var sy = '';
691  for (var [x,y] in o) {
692    sx += x;
693    sy += y;
694  }
695  assertEquals('ab', sx);
696  assertEquals('12', sy);
697}());
698
699
700(function TestParameters() {
701  function f({a, b}) { return a - b; }
702  assertEquals(1, f({a : 6, b : 5}));
703
704  function f1(c, {a, b}) { return c + a - b; }
705  assertEquals(8, f1(7, {a : 6, b : 5}));
706
707  function f2({c, d}, {a, b}) { return c - d + a - b; }
708  assertEquals(7, f2({c : 7, d : 1}, {a : 6, b : 5}));
709
710  function f3([{a, b}]) { return a - b; }
711  assertEquals(1, f3([{a : 6, b : 5}]));
712
713  var g = ({a, b}) => { return a - b; };
714  assertEquals(1, g({a : 6, b : 5}));
715
716  var g1 = (c, {a, b}) => { return c + a - b; };
717  assertEquals(8, g1(7, {a : 6, b : 5}));
718
719  var g2 = ({c, d}, {a, b}) => { return c - d + a - b; };
720  assertEquals(7, g2({c : 7, d : 1}, {a : 6, b : 5}));
721
722  var g3 = ([{a, b}]) => { return a - b; };
723  assertEquals(1, g3([{a : 6, b : 5}]));
724}());
725
726
727(function TestExpressionsInParameters() {
728  function f0(x = eval(0)) { return x }
729  assertEquals(0, f0());
730  function f1({a = eval(1)}) { return a }
731  assertEquals(1, f1({}));
732  function f2([x = eval(2)]) { return x }
733  assertEquals(2, f2([]));
734  function f3({[eval(7)]: x}) { return x }
735  assertEquals(3, f3({7: 3}));
736})();
737
738
739(function TestParameterScoping() {
740  var x = 1;
741
742  function f1({a = x}) { var x = 2; return a; }
743  assertEquals(1, f1({}));
744  function f2({a = x}) { function x() {}; return a; }
745  assertEquals(1, f2({}));
746  (function() {
747    'use strict';
748    function f3({a = x}) { let x = 2; return a; }
749    assertEquals(1, f3({}));
750    function f4({a = x}) { const x = 2; return a; }
751    assertEquals(1, f4({}));
752    function f5({a = x}) { function x() {}; return a; }
753    assertEquals(1, f5({}));
754  })();
755  function f6({a = eval("x")}) { var x; return a; }
756  assertEquals(1, f6({}));
757  (function() {
758    'use strict';
759    function f61({a = eval("x")}) { var x; return a; }
760    assertEquals(1, f61({}));
761  })();
762  function f62({a = eval("'use strict'; x")}) { var x; return a; }
763  assertEquals(1, f62({}));
764  function f7({a = function() { return x }}) { var x; return a(); }
765  assertEquals(1, f7({}));
766  function f8({a = () => x}) { var x; return a(); }
767  assertEquals(1, f8({}));
768  function f9({a = () => eval("x")}) { var x; return a(); }
769  assertEquals(1, f9({}));
770  (function TestInitializedWithEvalArrowStrict() {
771    'use strict';
772    function f91({a = () => eval("x")}) { var x; return a(); }
773    assertEquals(1, f91({}));
774  })();
775  function f92({a = () => { 'use strict'; return eval("x") }}) { var x; return a(); }
776  assertEquals(1, f92({}));
777  function f93({a = () => eval("'use strict'; x")}) { var x; return a(); }
778  assertEquals(1, f93({}));
779
780  var g1 = ({a = x}) => { var x = 2; return a; };
781  assertEquals(1, g1({}));
782  var g2 = ({a = x}) => { function x() {}; return a; };
783  assertEquals(1, g2({}));
784  (function() {
785    'use strict';
786    var g3 = ({a = x}) => { let x = 2; return a; };
787    assertEquals(1, g3({}));
788    var g4 = ({a = x}) => { const x = 2; return a; };
789    assertEquals(1, g4({}));
790    var g5 = ({a = x}) => { function x() {}; return a; };
791    assertEquals(1, g5({}));
792  })();
793  var g6 = ({a = eval("x")}) => { var x; return a; };
794  assertEquals(1, g6({}));
795  (function() {
796    'use strict';
797    var g61 = ({a = eval("x")}) => { var x; return a; };
798    assertEquals(1, g61({}));
799  })();
800  var g62 = ({a = eval("'use strict'; x")}) => { var x; return a; };
801  assertEquals(1, g62({}));
802  var g7 = ({a = function() { return x }}) => { var x; return a(); };
803  assertEquals(1, g7({}));
804  var g8 = ({a = () => x}) => { var x; return a(); };
805  assertEquals(1, g8({}));
806  var g9 = ({a = () => eval("x")}) => { var x; return a(); };
807  assertEquals(1, g9({}));
808  (function() {
809    'use strict';
810    var g91 = ({a = () => eval("x")}) => { var x; return a(); };
811    assertEquals(1, g91({}));
812    var g92 = ({a = () => { return eval("x") }}) => { var x; return a(); };
813    assertEquals(1, g92({}));
814  })();
815  var g93 = ({a = () => eval("'use strict'; x")}) => { var x; return a(); };
816  assertEquals(1, g93({}));
817
818  var f11 = function f({x = f}) { var f; return x; }
819  assertSame(f11, f11({}));
820  var f12 = function f({x = f}) { function f() {}; return x; }
821  assertSame(f12, f12({}));
822  (function() {
823    'use strict';
824    var f13 = function f({x = f}) { let f; return x; }
825    assertSame(f13, f13({}));
826    var f14 = function f({x = f}) { const f = 0; return x; }
827    assertSame(f14, f14({}));
828    var f15 = function f({x = f}) { function f() {}; return x; }
829    assertSame(f15, f15({}));
830  })();
831  var f16 = function f({f = 7, x = f}) { return x; }
832  assertSame(7, f16({}));
833
834  var y = 'a';
835  function f20({[y]: x}) { var y = 'b'; return x; }
836  assertEquals(1, f20({a: 1, b: 2}));
837  function f21({[eval('y')]: x}) { var y = 'b'; return x; }
838  assertEquals(1, f21({a: 1, b: 2}));
839  var g20 = ({[y]: x}) => { var y = 'b'; return x; };
840  assertEquals(1, g20({a: 1, b: 2}));
841  var g21 = ({[eval('y')]: x}) => { var y = 'b'; return x; };
842  assertEquals(1, g21({a: 1, b: 2}));
843})();
844
845
846(function TestParameterDestructuringTDZ() {
847  function f1({a = x}, x) { return a }
848  assertThrows(() => f1({}, 4), ReferenceError);
849  assertEquals(4, f1({a: 4}, 5));
850  function f2({a = eval("x")}, x) { return a }
851  assertThrows(() => f2({}, 4), ReferenceError);
852  assertEquals(4, f2({a: 4}, 5));
853  (function() {
854    'use strict';
855    function f3({a = eval("x")}, x) { return a }
856    assertThrows(() => f3({}, 4), ReferenceError);
857    assertEquals(4, f3({a: 4}, 5));
858  })();
859  function f4({a = eval("'use strict'; x")}, x) { return a }
860  assertThrows(() => f4({}, 4), ReferenceError);
861  assertEquals(4, f4({a: 4}, 5));
862
863  function f5({a = () => x}, x) { return a() }
864  assertEquals(4, f5({a: () => 4}, 5));
865  function f6({a = () => eval("x")}, x) { return a() }
866  assertEquals(4, f6({a: () => 4}, 5));
867  (function() {
868    'use strict';
869    function f7({a = () => eval("x")}, x) { return a() }
870    assertEquals(4, f7({a: () => 4}, 5));
871  })();
872  function f8({a = () => eval("'use strict'; x")}, x) { return a() }
873  assertEquals(4, f8({a: () => 4}, 5));
874
875  function f11({a = b}, {b}) { return a }
876  assertThrows(() => f11({}, {b: 4}), ReferenceError);
877  assertEquals(4, f11({a: 4}, {b: 5}));
878  function f12({a = eval("b")}, {b}) { return a }
879  assertThrows(() => f12({}, {b: 4}), ReferenceError);
880  assertEquals(4, f12({a: 4}, {b: 5}));
881  (function() {
882    'use strict';
883    function f13({a = eval("b")}, {b}) { return a }
884    assertThrows(() => f13({}, {b: 4}), ReferenceError);
885    assertEquals(4, f13({a: 4}, {b: 5}));
886  })();
887  function f14({a = eval("'use strict'; b")}, {b}) { return a }
888  assertThrows(() => f14({}, {b: 4}), ReferenceError);
889  assertEquals(4, f14({a: 4}, {b: 5}));
890
891  function f15({a = () => b}, {b}) { return a() }
892  assertEquals(4, f15({a: () => 4}, {b: 5}));
893  function f16({a = () => eval("b")}, {b}) { return a() }
894  assertEquals(4, f16({a: () => 4}, {b: 5}));
895  (function() {
896    'use strict';
897    function f17({a = () => eval("b")}, {b}) { return a() }
898    assertEquals(4, f17({a: () => 4}, {b: 5}));
899  })();
900  function f18({a = () => eval("'use strict'; b")}, {b}) { return a() }
901  assertEquals(4, f18({a: () => 4}, {b: 5}));
902
903  // TODO(caitp): TDZ for rest parameters is not working yet.
904  // function f30({x = a}, ...a) { return x[0] }
905  // assertThrows(() => f30({}), ReferenceError);
906  // assertEquals(4, f30({a: [4]}, 5));
907  // function f31({x = eval("a")}, ...a) { return x[0] }
908  // assertThrows(() => f31({}), ReferenceError);
909  // assertEquals(4, f31({a: [4]}, 5));
910  // function f32({x = eval("a")}, ...a) { 'use strict'; return x[0] }
911  // assertThrows(() => f32({}), ReferenceError);
912  // assertEquals(4, f32({a: [4]}, 5));
913  // function f33({x = eval("'use strict'; a")}, ...a) { return x[0] }
914  // assertThrows(() => f33({}), ReferenceError);
915  // assertEquals(4, f33({a: [4]}, 5));
916
917  function f34({x = function() { return a }}, ...a) { return x()[0] }
918  assertEquals(4, f34({}, 4));
919  function f35({x = () => a}, ...a) { return x()[0] }
920  assertEquals(4, f35({}, 4));
921  function f36({x = () => eval("a")}, ...a) { return x()[0] }
922  assertEquals(4, f36({}, 4));
923  (function() {
924    'use strict';
925    function f37({x = () => eval("a")}, ...a) { return x()[0] }
926    assertEquals(4, f37({}, 4));
927  })();
928  function f38({x = () => { 'use strict'; return eval("a") }}, ...a) { return x()[0] }
929  assertEquals(4, f38({}, 4));
930  function f39({x = () => eval("'use strict'; a")}, ...a) { return x()[0] }
931  assertEquals(4, f39({}, 4));
932
933  // var g30 = ({x = a}, ...a) => {};
934  // assertThrows(() => g30({}), ReferenceError);
935  // var g31 = ({x = eval("a")}, ...a) => {};
936  // assertThrows(() => g31({}), ReferenceError);
937  // var g32 = ({x = eval("a")}, ...a) => { 'use strict'; };
938  // assertThrows(() => g32({}), ReferenceError);
939  // var g33 = ({x = eval("'use strict'; a")}, ...a) => {};
940  // assertThrows(() => g33({}), ReferenceError);
941  var g34 = ({x = function() { return a }}, ...a) => { return x()[0] };
942  assertEquals(4, g34({}, 4));
943  var g35 = ({x = () => a}, ...a) => { return x()[0] };
944  assertEquals(4, g35({}, 4));
945})();
946
947
948(function TestDuplicatesInParameters() {
949  assertThrows("'use strict';function f(x,x){}", SyntaxError);
950  assertThrows("'use strict';function f({x,x}){}", SyntaxError);
951  assertThrows("'use strict';function f(x, {x}){}", SyntaxError);
952  assertThrows("'use strict';var f = (x,x) => {};", SyntaxError);
953  assertThrows("'use strict';var f = ({x,x}) => {};", SyntaxError);
954  assertThrows("'use strict';var f = (x, {x}) => {};", SyntaxError);
955
956  function ok1(x) { var x; return x; };
957  assertEquals(1, ok1(1));
958  function ok2(x) { 'use strict'; { let x = 2; return x; } };
959  assertEquals(2, ok2(1));
960}());
961
962
963(function TestShadowingOfParameters() {
964  function f1({x}) { var x = 2; return x }
965  assertEquals(2, f1({x: 1}));
966  function f2({x}) { { var x = 2; } return x; }
967  assertEquals(2, f2({x: 1}));
968  function f3({x}) { var y = x; var x = 2; return y; }
969  assertEquals(1, f3({x: 1}));
970  function f4({x}) { { var y = x; var x = 2; } return y; }
971  assertEquals(1, f4({x: 1}));
972  function f5({x}, g = () => x) { var x = 2; return g(); }
973  assertEquals(1, f5({x: 1}));
974  function f6({x}, g = () => x) { { var x = 2; } return g(); }
975  assertEquals(1, f6({x: 1}));
976  function f7({x}) { var g = () => x; var x = 2; return g(); }
977  assertEquals(2, f7({x: 1}));
978  function f8({x}) { { var g = () => x; var x = 2; } return g(); }
979  assertEquals(2, f8({x: 1}));
980  function f9({x}, g = () => eval("x")) { var x = 2; return g(); }
981  assertEquals(1, f9({x: 1}));
982
983  function f10({x}, y) { var y; return y }
984  assertEquals(2, f10({x: 6}, 2));
985  function f11({x}, y) { var z = y; var y = 2; return z; }
986  assertEquals(1, f11({x: 6}, 1));
987  function f12(y, g = () => y) { var y = 2; return g(); }
988  assertEquals(1, f12(1));
989  function f13({x}, y, [z], v) { var x, y, z; return x*y*z*v }
990  assertEquals(210, f13({x: 2}, 3, [5], 7));
991
992  function f20({x}) { function x() { return 2 }; return x(); }
993  assertEquals(2, f20({x: 1}));
994  // Function hoisting is blocked by the conflicting x declaration
995  function f21({x}) { { function x() { return 2 } } return x(); }
996  assertThrows(() => f21({x: 1}), TypeError);
997
998  var g1 = ({x}) => { var x = 2; return x };
999  assertEquals(2, g1({x: 1}));
1000  var g2 = ({x}) => { { var x = 2; } return x; };
1001  assertEquals(2, g2({x: 1}));
1002  var g3 = ({x}) => { var y = x; var x = 2; return y; };
1003  assertEquals(1, g3({x: 1}));
1004  var g4 = ({x}) => { { var y = x; var x = 2; } return y; };
1005  assertEquals(1, g4({x: 1}));
1006  var g5 = ({x}, g = () => x) => { var x = 2; return g(); };
1007  assertEquals(1, g5({x: 1}));
1008  var g6 = ({x}, g = () => x) => { { var x = 2; } return g(); };
1009  assertEquals(1, g6({x: 1}));
1010  var g7 = ({x}) => { var g = () => x; var x = 2; return g(); };
1011  assertEquals(2, g7({x: 1}));
1012  var g8 = ({x}) => { { var g = () => x; var x = 2; } return g(); };
1013  assertEquals(2, g8({x: 1}));
1014  var g9 = ({x}, g = () => eval("x")) => { var x = 2; return g(); };
1015  assertEquals(1, g9({x: 1}));
1016
1017  var g10 = ({x}, y) => { var y; return y };
1018  assertEquals(2, g10({x: 6}, 2));
1019  var g11 = ({x}, y) => { var z = y; var y = 2; return z; };
1020  assertEquals(1, g11({x: 6}, 1));
1021  var g12 = (y, g = () => y) => { var y = 2; return g(); };
1022  assertEquals(1, g12(1));
1023  var g13 = ({x}, y, [z], v) => { var x, y, z; return x*y*z*v };
1024  assertEquals(210, g13({x: 2}, 3, [5], 7));
1025
1026  var g20 = ({x}) => { function x() { return 2 }; return x(); }
1027  assertEquals(2, g20({x: 1}));
1028  var g21 = ({x}) => { { function x() { return 2 } } return x(); }
1029  assertThrows(() => g21({x: 1}), TypeError);
1030
1031  assertThrows("'use strict'; function f(x) { let x = 0; }; f({});", SyntaxError);
1032  assertThrows("'use strict'; function f({x}) { let x = 0; }; f({});", SyntaxError);
1033  assertThrows("'use strict'; function f(x) { const x = 0; }; f({});", SyntaxError);
1034  assertThrows("'use strict'; function f({x}) { const x = 0; }; f({});", SyntaxError);
1035
1036  assertThrows("'use strict'; let g = (x) => { let x = 0; }; f({});", SyntaxError);
1037  assertThrows("'use strict'; let g = ({x}) => { let x = 0; }; f({});", SyntaxError);
1038  assertThrows("'use strict'; let g = (x) => { const x = 0; }; f({});", SyntaxError);
1039  assertThrows("'use strict'; let g = ({x}) => { const x = 0; }; f({});", SyntaxError);
1040}());
1041
1042
1043(function TestArgumentsForNonSimpleParameters() {
1044  function f1({}, x) { arguments[1] = 0; return x }
1045  assertEquals(6, f1({}, 6));
1046  function f2({}, x) { x = 2; return arguments[1] }
1047  assertEquals(7, f2({}, 7));
1048  function f3(x, {}) { arguments[0] = 0; return x }
1049  assertEquals(6, f3(6, {}));
1050  function f4(x, {}) { x = 2; return arguments[0] }
1051  assertEquals(7, f4(7, {}));
1052  function f5(x, ...a) { arguments[0] = 0; return x }
1053  assertEquals(6, f5(6, {}));
1054  function f6(x, ...a) { x = 2; return arguments[0] }
1055  assertEquals(6, f6(6, {}));
1056  function f7({a: x}) { x = 2; return arguments[0].a }
1057  assertEquals(5, f7({a: 5}));
1058  function f8(x, ...a) { a = []; return arguments[1] }
1059  assertEquals(6, f8(5, 6));
1060}());
1061
1062
1063(function TestForInOfTDZ() {
1064  assertThrows("'use strict'; let x = {}; for (let [x, y] of {x});", ReferenceError);
1065  assertThrows("'use strict'; let x = {}; for (let [y, x] of {x});", ReferenceError);
1066  assertThrows("'use strict'; let x = {}; for (let [x, y] in {x});", ReferenceError);
1067  assertThrows("'use strict'; let x = {}; for (let [y, x] in {x});", ReferenceError);
1068}());
1069
1070
1071(function TestFunctionLength() {
1072   assertEquals(1, (function({}) {}).length);
1073   assertEquals(1, (function([]) {}).length);
1074   assertEquals(1, (function({x}) {}).length);
1075   assertEquals(1, (function({}, ...a) {}).length);
1076   assertEquals(1, (function({x}, {y} = {}) {}).length);
1077   assertEquals(1, (function({x}, {y} = {}, ...a) {}).length);
1078   assertEquals(2, (function(x, {y}, {z} = {}) {}).length);
1079   assertEquals(2, (function({x}, {}, {z} = {}, ...a) {}).length);
1080   assertEquals(1, (function(x, {y} = {}, {z}) {}).length);
1081   assertEquals(1, (function({x}, {y} = {}, {z}, ...a) {}).length);
1082   assertEquals(1, (function(x, {y} = {}, {z}, {v} = {}) {}).length);
1083   assertEquals(1, (function({x}, {y} = {}, {z}, {v} = {}, ...a) {}).length);
1084})();
1085
1086
1087(function TestDirectiveThrows() {
1088  "use strict";
1089
1090  assertThrows(function(){ eval("function({}){'use strict';}") }, SyntaxError);
1091  assertThrows(function(){ eval("({}) => {'use strict';}") }, SyntaxError);
1092  assertThrows(
1093    function(){ eval("(class{foo({}) {'use strict';}});") }, SyntaxError);
1094
1095  assertThrows(
1096    function(){ eval("function(a, {}){'use strict';}") }, SyntaxError);
1097  assertThrows(function(){ eval("(a, {}) => {'use strict';}") }, SyntaxError);
1098  assertThrows(
1099    function(){ eval("(class{foo(a, {}) {'use strict';}});") }, SyntaxError);
1100})();
1101
1102
1103(function TestLegacyConstDestructuringInForLoop() {
1104  var result;
1105  for (const {foo} of [{foo: 1}]) { result = foo; }
1106  assertEquals(1, result);
1107})();
1108
1109
1110(function TestCatch() {
1111  "use strict";
1112
1113  // For testing proper scoping.
1114  var foo = "hello", bar = "world", baz = 42;
1115
1116  try {
1117    throw {foo: 1, bar: 2};
1118  } catch ({foo, bar, baz = 3}) {
1119    assertEquals(1, foo);
1120    assertEquals(2, bar);
1121    assertEquals(3, baz);
1122  }
1123
1124  try {
1125    throw [1, 2, 3];
1126  } catch ([foo, ...bar]) {
1127    assertEquals(1, foo);
1128    assertEquals([2, 3], bar);
1129  }
1130
1131  assertEquals("hello", foo);
1132  assertEquals("world", bar);
1133  assertEquals(42, baz);
1134})();
1135