destructuring.js 54 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. WScript.LoadScriptFile("..\\UnitTestFramework\\UnitTestFramework.js");
  6. var tests = [
  7. {
  8. name: "Basic parsing and early errors",
  9. body: function () {
  10. // No initializer
  11. assert.throws(function () { eval("var [];"); }, SyntaxError, "Destructured var array declaration must have at least one identifier reference", "Destructuring declarations must have an initializer");
  12. assert.throws(function () { eval("let [];"); }, SyntaxError, "Destructured let array declaration must have at least one identifier reference", "Destructuring declarations must have an initializer");
  13. assert.throws(function () { eval("const [];"); }, SyntaxError, "Destructured const array declaration must have at least one identifier reference", "Destructuring declarations must have an initializer");
  14. assert.throws(function () { eval("var [a];"); }, SyntaxError, "Destructured var array declaration must have an initializer", "Destructuring declarations must have an initializer");
  15. assert.throws(function () { eval("let [a];"); }, SyntaxError, "Destructured let array declaration must have an initializer", "Destructuring declarations must have an initializer");
  16. assert.throws(function () { eval("const [a];"); }, SyntaxError, "Destructured const array declaration must have an initializer", "Destructuring declarations must have an initializer");
  17. // No identifiers
  18. assert.doesNotThrow(function () { eval("var [] = [];"); }, "Destructured var array declaration with no identifiers does not throw");
  19. assert.doesNotThrow(function () { eval("let [] = [];"); }, "Destructured let array declaration with no identifiers does not throw");
  20. assert.doesNotThrow(function () { eval("const [] = [];"); }, "Destructured const array declaration with no identifiers does not throw");
  21. assert.doesNotThrow(function () { eval("[] = [];"); }, "Destructured array assignment with no identifiers does not throw");
  22. // Mismatched expression and initializer length
  23. assert.doesNotThrow(function () { eval("var [a] = [];"); }, "Destructured var array declaration with an empty initializer array does not throw");
  24. assert.doesNotThrow(function () { eval("let [a] = [];"); }, "Destructured let array declaration with an empty initializer array does not throw");
  25. assert.doesNotThrow(function () { eval("const [a] = [];"); }, "Destructured const array declaration with an empty initializer array does not throw");
  26. assert.doesNotThrow(function () { eval("var a; [a] = [];"); }, "Destructured var array assignment with an empty initializer array does not throw");
  27. assert.doesNotThrow(function () { eval("let a; [a] = [];"); }, "Destructured let array assignment with an empty initializer array does not throw");
  28. assert.doesNotThrow(function () { eval("var [a] = [1];"); }, "Destructured var array declaration with matching initializer array size does not throw");
  29. assert.doesNotThrow(function () { eval("let [a] = [2];"); }, "Destructured let array declaration with matching initializer array size does not throw");
  30. assert.doesNotThrow(function () { eval("const [a] = [1];"); }, "Destructured const array declaration with matching initializer array size does not throw");
  31. assert.doesNotThrow(function () { eval("var a; [a] = [1];"); }, "Destructured var array assignment with matching initializer array size does not throw");
  32. assert.doesNotThrow(function () { eval("let a; [a] = [2];"); }, "Destructured let array assignment with matching initializer array size does not throw");
  33. assert.doesNotThrow(function () { eval("var [a, b] = [1];"); }, "Destructured var array declaration with smaller initializer array size does not throw");
  34. assert.doesNotThrow(function () { eval("let [a, b] = [1];"); }, "Destructured let array declaration with smaller initializer array size does not throw");
  35. assert.doesNotThrow(function () { eval("const [a, b] = [1];"); }, "Destructured const array declaration with smaller initializer array size does not throw");
  36. assert.doesNotThrow(function () { eval("var a, b; [a, b] = [1];"); }, "Destructured var array assignment with smaller initializer array size does not throw");
  37. assert.doesNotThrow(function () { eval("let a, b; [a, b] = [1];"); }, "Destructured let array assignment with smaller initializer array size does not throw");
  38. assert.doesNotThrow(function () { eval("var [a] = [1, 2];"); }, "Destructured var array declaration with larger initializer array size does not throw");
  39. assert.doesNotThrow(function () { eval("let [a] = [1, 2];"); }, "Destructured let array declaration with larger initializer array size does not throw");
  40. assert.doesNotThrow(function () { eval("const [a] = [1, 2];"); }, "Destructured const array declaration with larger initializer array size does not throw");
  41. assert.doesNotThrow(function () { eval("var a; [a] = [1, 2];"); }, "Destructured var array assignment with larger initializer array size does not throw");
  42. assert.doesNotThrow(function () { eval("let a; [a] = [1, 2];"); }, "Destructured let array assignment with larger initializer array size does not throw");
  43. // Disallowed operators
  44. assert.throws(function () { eval("var [a--] = [];"); }, SyntaxError, "Destructured var array declaration with an operator throws", "Unexpected operator in destructuring expression");
  45. assert.throws(function () { eval("let [a--] = [];"); }, SyntaxError, "Destructured let array declaration with an operator throws", "Unexpected operator in destructuring expression");
  46. assert.throws(function () { eval("const [a--] = [];"); }, SyntaxError, "Destructured const array declaration with an operator throws", "Unexpected operator in destructuring expression");
  47. assert.throws(function () { eval("var [a + 1] = [];"); }, SyntaxError, "Destructured var array declaration with an operator throws", "Unexpected operator in destructuring expression");
  48. assert.throws(function () { eval("let [a + 1] = [];"); }, SyntaxError, "Destructured let array declaration with an operator throws", "Unexpected operator in destructuring expression");
  49. assert.throws(function () { eval("const [a + 1] = [];"); }, SyntaxError, "Destructured const array declaration with an operator throws", "Unexpected operator in destructuring expression");
  50. assert.throws(function () { eval("var [++a] = [];"); }, SyntaxError, "Destructured var array declaration with an operator throws", "Unexpected operator in destructuring expression");
  51. assert.throws(function () { eval("let [++a] = [];"); }, SyntaxError, "Destructured let array declaration with an operator throws", "Unexpected operator in destructuring expression");
  52. assert.throws(function () { eval("const [++a] = [];"); }, SyntaxError, "Destructured const array declaration with an operator throws", "Unexpected operator in destructuring expression");
  53. assert.throws(function () { eval("var a; [a--] = [];"); }, SyntaxError, "Destructured var array assignment with an operator throws", "Unexpected operator in destructuring expression");
  54. assert.throws(function () { eval("let a; [a--] = [];"); }, SyntaxError, "Destructured let array assignment with an operator throws", "Unexpected operator in destructuring expression");
  55. assert.throws(function () { eval("var a; [a + 1] = [];"); }, SyntaxError, "Destructured var array assignment with an operator throws", "Unexpected operator in destructuring expression");
  56. assert.throws(function () { eval("let a; [a + 1] = [];"); }, SyntaxError, "Destructured let array assignment with an operator throws", "Unexpected operator in destructuring expression");
  57. assert.throws(function () { eval("var a; [++a] = [];"); }, SyntaxError, "Destructured var array assignment with an operator throws", "Unexpected operator in destructuring expression");
  58. assert.throws(function () { eval("let a; [++a] = [];"); }, SyntaxError, "Destructured let array assignment with an operator throws", "Unexpected operator in destructuring expression");
  59. assert.doesNotThrow(function () { eval("var a = [1], i = 0; [a[i++]] = [];"); }, "Destructured var array assignment operators inside an identifier reference does not throw");
  60. assert.doesNotThrow(function () { eval("let a = [1], i = 0; [a[i++]] = [];"); }, "Destructured var array assignment operators inside an identifier reference does not throw");
  61. assert.doesNotThrow(function () { eval("var a = [1], i = 0; [a[(() => 1 + i)()]] = [];"); }, "Destructured var array assignment operators inside an identifier reference does not throw");
  62. assert.doesNotThrow(function () { eval("let a = [1], i = 0; [a[(() => 1 + i)()]] = [];"); }, "Destructured var array assignment operators inside an identifier reference does not throw");
  63. // Missing values
  64. assert.doesNotThrow(function () { eval("var [,] = [];"); }, "Destructured var array declaration with no identifiers and missing values does not throw");
  65. assert.doesNotThrow(function () { eval("let [,] = [];"); }, "Destructured let array declaration with no identifiers and missing values does not throw");
  66. assert.doesNotThrow(function () { eval("const [,] = [];"); }, "Destructured const array declaration with no identifiers and missing values does not throw");
  67. assert.doesNotThrow(function () { eval("[,] = [];"); }, "Destructured array assignment with no identifiers and missing values does not throw");
  68. assert.doesNotThrow(function () { eval("var [a,] = [];"); }, "Destructured var array declaration ending with a missing value does not throw");
  69. assert.doesNotThrow(function () { eval("let [a,] = [];"); }, "Destructured let array declaration ending with a missing value does not throw");
  70. assert.doesNotThrow(function () { eval("const [a,] = [];"); }, "Destructured const array declaration ending with a missing value does not throw");
  71. assert.doesNotThrow(function () { eval("var a; [a,] = [];"); }, "Destructured var array assignment ending with a missing value does not throw");
  72. assert.doesNotThrow(function () { eval("let a; [a,] = [];"); }, "Destructured let array assignment ending with a missing value does not throw");
  73. assert.doesNotThrow(function () { eval("var [a,,b] = [];"); }, "Destructured var array declaration with some missing values does not throw");
  74. assert.doesNotThrow(function () { eval("let [a,,b] = [];"); }, "Destructured let array declaration with some missing values does not throw");
  75. assert.doesNotThrow(function () { eval("const [a,,b] = [];"); }, "Destructured const array declaration with some missing values does not throw");
  76. assert.doesNotThrow(function () { eval("var a, b; [a,,b] = [];"); }, "Destructured var array assignment with some missing values does not throw");
  77. assert.doesNotThrow(function () { eval("let a, b; [a,,b] = [];"); }, "Destructured let array assignment with some missing values does not throw");
  78. assert.doesNotThrow(function () { eval("var [,,a] = [];"); }, "Destructured var array declaration beginning with missing values does not throw");
  79. assert.doesNotThrow(function () { eval("let [,,a] = [];"); }, "Destructured let array declaration beginning with missing values does not throw");
  80. assert.doesNotThrow(function () { eval("const [,,a] = [];"); }, "Destructured const array declaration beginning with missing values does not throw");
  81. assert.doesNotThrow(function () { eval("var a; [,,a] = [];"); }, "Destructured var array assignment beginning with missing values does not throw");
  82. assert.doesNotThrow(function () { eval("let a; [,,a] = [];"); }, "Destructured let array assignment beginning with missing values does not throw");
  83. assert.doesNotThrow(function () { eval("var [a] = [,,];"); }, "Destructured var array declaration with an initializer containing missing values does not throw");
  84. assert.doesNotThrow(function () { eval("let [a] = [,,];"); }, "Destructured let array declaration with an initializer containing missing values does not throw");
  85. assert.doesNotThrow(function () { eval("const [a] = [,,];"); }, "Destructured const array declaration with an initializer containing missing values does not throw");
  86. assert.doesNotThrow(function () { eval("var a; [a] = [,,];"); }, "Destructured var array assignment with an initializer containing missing values does not throw");
  87. assert.doesNotThrow(function () { eval("let a; [a] = [,,];"); }, "Destructured let array assignment with an initializer containing missing values does not throw");
  88. // Non-identifiers
  89. assert.throws(function () { eval("var [1] = [];"); }, SyntaxError, "Destructured var array declaration with no identifier references throws", "Destructuring expressions can only have identifier references");
  90. assert.throws(function () { eval("let [1] = [];"); }, SyntaxError, "Destructured let array declaration with no identifier references throws", "Destructuring expressions can only have identifier references");
  91. assert.throws(function () { eval("const [1] = [];"); }, SyntaxError, "Destructured const array declaration with no identifier references throws", "Destructuring expressions can only have identifier references");
  92. assert.throws(function () { eval("[1] = [];"); }, SyntaxError, "Destructured array assignment with no identifier references throws", "Destructuring expressions can only have identifier references");
  93. assert.throws(function () { eval("var [1, a] = [];"); }, SyntaxError, "Destructured var array declaration with valid and invalid identifier references throws", "Destructuring expressions can only have identifier references");
  94. assert.throws(function () { eval("let [1, a] = [];"); }, SyntaxError, "Destructured let array declaration with valid and invalid identifier references throws", "Destructuring expressions can only have identifier references");
  95. assert.throws(function () { eval("const [1, a] = [];"); }, SyntaxError, "Destructured const array declaration with valid and invalid identifier references throws", "Destructuring expressions can only have identifier references");
  96. assert.throws(function () { eval("var a; [1, a] = [];"); }, SyntaxError, "Destructured var array assignment with valid and invalid identifier references throws", "Destructuring expressions can only have identifier references");
  97. assert.throws(function () { eval("let a; [1, a] = [];"); }, SyntaxError, "Destructured let array assignment with valid and invalid identifier references throws", "Destructuring expressions can only have identifier references");
  98. // Rest parameter
  99. assert.doesNotThrow(function () { eval("var [...a] = [];"); }, "Destructured var array declaration with a single rest parameter does not throw");
  100. assert.doesNotThrow(function () { eval("let [...a] = [];"); }, "Destructured let array declaration with a single rest parameter does not throw");
  101. assert.doesNotThrow(function () { eval("const [...a] = [];"); }, "Destructured const array declaration with a single rest parameter does not throw");
  102. assert.doesNotThrow(function () { eval("var a; [...a] = [];"); }, "Destructured var array assignment with a single rest parameter does not throw");
  103. assert.doesNotThrow(function () { eval("let a; [...a] = [];"); }, "Destructured let array assignment with a single rest parameter does not throw");
  104. assert.throws(function () { eval("var [...a, ...b] = [];"); }, SyntaxError, "Destructured var array declaration with multiple rest parameters throws", "Destructuring rest variables must be in the last position of the expression");
  105. assert.throws(function () { eval("let [...a, ...b] = [];"); }, SyntaxError, "Destructured let array declaration with multiple rest parameters throws", "Destructuring rest variables must be in the last position of the expression");
  106. assert.throws(function () { eval("const [...a, ...b] = [];"); }, SyntaxError, "Destructured const array declaration with multiple rest parameters throws", "Destructuring rest variables must be in the last position of the expression");
  107. assert.throws(function () { eval("var a, b; [...a, ...b] = [];"); }, SyntaxError, "Destructured var array assignment with multiple rest parameters throws", "Destructuring rest variables must be in the last position of the expression");
  108. assert.throws(function () { eval("let a, b; [...a, ...b] = [];"); }, SyntaxError, "Destructured let array assignment with multiple rest parameters throws", "Destructuring rest variables must be in the last position of the expression");
  109. assert.throws(function () { eval("var [...a, b] = [];"); }, SyntaxError, "Destructured var array declaration with rest parameter in non-last position throws", "Destructuring rest variables must be in the last position of the expression");
  110. assert.throws(function () { eval("let [...a, b] = [];"); }, SyntaxError, "Destructured let array declaration with rest parameter in non-last position throws", "Destructuring rest variables must be in the last position of the expression");
  111. assert.throws(function () { eval("const [...a, b] = [];"); }, SyntaxError, "Destructured const array declaration with rest parameter in non-last position throws", "Destructuring rest variables must be in the last position of the expression");
  112. assert.throws(function () { eval("var a, b; [...a, b] = [];"); }, SyntaxError, "Destructured var array assignment with rest parameter in non-last position throws", "Destructuring rest variables must be in the last position of the expression");
  113. assert.throws(function () { eval("let a, b; [...a, b] = [];"); }, SyntaxError, "Destructured let array assignment with rest parameter in non-last position throws", "Destructuring rest variables must be in the last position of the expression");
  114. assert.throws(function () { eval("let [...a,] = [];"); }, SyntaxError, "Destructured array declaration has comma after rest parameter throws", "Destructuring rest variables must be in the last position of the expression");
  115. assert.throws(function () { eval("let a; [...a,] = [];"); }, SyntaxError, "Destructured array assignment has comma after rest parameter throws", "Destructuring rest variables must be in the last position of the expression");
  116. // Default values
  117. assert.doesNotThrow(function () { eval("var [a = 1] = [];"); }, "Destructured var array declaration with all default values does not throw");
  118. assert.doesNotThrow(function () { eval("let [a = 1] = [];"); }, "Destructured let array declaration with all default values does not throw");
  119. assert.doesNotThrow(function () { eval("const [a = 1] = [];"); }, "Destructured const array declaration with all default values does not throw");
  120. assert.doesNotThrow(function () { eval("var a; [a = 1] = [];"); }, "Destructured var array assignment with all default values does not throw");
  121. assert.doesNotThrow(function () { eval("let a; [a = 1] = [];"); }, "Destructured let array assignment with all default values does not throw");
  122. assert.doesNotThrow(function () { eval("var [a, b = 1] = [];"); }, "Destructured var array declaration with trailing default values does not throw");
  123. assert.doesNotThrow(function () { eval("let [a, b = 1] = [];"); }, "Destructured let array declaration with trailing default values does not throw");
  124. assert.doesNotThrow(function () { eval("const [a, b = 1] = [];"); }, "Destructured const array declaration with trailing default values does not throw");
  125. assert.doesNotThrow(function () { eval("var a, b; [a, b = 1] = [];"); }, "Destructured var array assignment with trailing default values does not throw");
  126. assert.doesNotThrow(function () { eval("let a, b; [a, b = 1] = [];"); }, "Destructured let array assignment with trailing default values does not throw");
  127. assert.doesNotThrow(function () { eval("var [a = 1, b] = [];"); }, "Destructured var array declaration with mixed default values does not throw");
  128. assert.doesNotThrow(function () { eval("let [a = 1, b] = [];"); }, "Destructured let array declaration with mixed default values does not throw");
  129. assert.doesNotThrow(function () { eval("const [a = 1, b] = [];"); }, "Destructured const array declaration with mixed default values does not throw");
  130. assert.doesNotThrow(function () { eval("var a, b; [a = 1, b] = [];"); }, "Destructured var array assignment with mixed default values does not throw");
  131. assert.doesNotThrow(function () { eval("let a, b; [a = 1, b] = [];"); }, "Destructured let array assignment with mixed default values does not throw");
  132. // Rest with default
  133. assert.throws(function () { eval("var [...a = 1] = [];"); }, SyntaxError, "Destructured var array declaration with a rest parameter with a default value throws", "Unexpected default initializer");
  134. assert.throws(function () { eval("let [...a = 1] = [];"); }, SyntaxError, "Destructured let array declaration with a rest parameter with a default value throws", "Unexpected default initializer");
  135. assert.throws(function () { eval("const [...a = 1] = [];"); }, SyntaxError, "Destructured const array declaration with a rest parameter with a default value throws", "Unexpected default initializer");
  136. assert.throws(function () { eval("var a; [...a = 1] = [];"); }, SyntaxError, "Destructured var array assignment with a rest parameter with a default value throws", "The rest parameter cannot have a default initializer.");
  137. assert.throws(function () { eval("let a; [...a = 1] = [];"); }, SyntaxError, "Destructured let array assignment with a rest parameter with a default value throws", "The rest parameter cannot have a default initializer.");
  138. // Nesting
  139. assert.doesNotThrow(function () { eval("var [[a]] = [[]];"); }, "Destructured var array declaration with nesting does not throw");
  140. assert.doesNotThrow(function () { eval("let [[a]] = [[]];"); }, "Destructured let array declaration with nesting does not throw");
  141. assert.doesNotThrow(function () { eval("const [[a]] = [[]];"); }, "Destructured const array declaration with nesting does not throw");
  142. assert.doesNotThrow(function () { eval("var a; [[a]] = [[]];"); }, "Destructured var array assignment with nesting does not throw");
  143. assert.doesNotThrow(function () { eval("let a; [[a]] = [[]];"); }, "Destructured let array assignment with nesting does not throw");
  144. assert.doesNotThrow(function () { eval("var [a, [b]] = [1, []];"); }, "Destructured var array declaration with some nesting does not throw");
  145. assert.doesNotThrow(function () { eval("let [a, [b]] = [1, []];"); }, "Destructured let array declaration with some nesting does not throw");
  146. assert.doesNotThrow(function () { eval("const [a, [b]] = [1, []];"); }, "Destructured const array declaration with some nesting does not throw");
  147. assert.doesNotThrow(function () { eval("var a, b; [a, [b]] = [1, []];"); }, "Destructured var array assignment with some nesting does not throw");
  148. assert.doesNotThrow(function () { eval("let a, b; [a, [b]] = [1, []];"); }, "Destructured let array assignment with some nesting does not throw");
  149. assert.throws(function () { eval("var [((a)] = [];"); }, SyntaxError, "Destructured var array declaration with a mismatched paren count throws");
  150. assert.throws(function () { eval("let [((a)] = [];"); }, SyntaxError, "Destructured let array declaration with a mismatched paren count throws", "Destructuring expressions can only have identifier references");
  151. assert.throws(function () { eval("const [((a)] = [];"); }, SyntaxError, "Destructured const array declaration with a mismatched paren count throws", "Destructuring expressions can only have identifier references");
  152. assert.throws(function () { eval("var a; [((a)] = [];"); }, SyntaxError, "Destructured var array assignment with a mismatched paren count throws", "Expected ')'");
  153. assert.throws(function () { eval("let a; [((a)] = [];"); }, SyntaxError, "Destructured let array assignment with a mismatched paren count throws");
  154. assert.throws(function () { eval("var [a)] = [];"); }, SyntaxError, "Destructured var array declaration with a mismatched paren count throws");
  155. assert.throws(function () { eval("let [a)] = [];"); }, SyntaxError, "Destructured let array declaration with a mismatched paren count throws");
  156. assert.throws(function () { eval("const [a)] = [];"); }, SyntaxError, "Destructured const array declaration with a mismatched paren count throws");
  157. assert.throws(function () { eval("var a; [a)] = [];"); }, SyntaxError, "Destructured var array assignment with a mismatched paren count throws", "Expected ']'");
  158. assert.throws(function () { eval("let a; [a)] = [];"); }, SyntaxError, "Destructured let array assignment with a mismatched paren count throws");
  159. assert.throws(function () { eval("var [((((a)))), b] = [];"); }, SyntaxError, "Destructured var array declaration with some nested parens throws");
  160. assert.throws(function () { eval("let [((((a)))), b] = [];"); }, SyntaxError, "Destructured let array declaration with some nested parens throws");
  161. assert.throws(function () { eval("const [((((a)))), b] = [];"); }, SyntaxError, "Destructured const array declaration with some nested parens throws");
  162. assert.doesNotThrow(function () { eval("var a, b; [((((a)))), b] = [];"); }, "Destructured var array assignment with some nested parens does not throw");
  163. assert.doesNotThrow(function () { eval("let a, b; [((((a)))), b] = [];"); }, "Destructured let array assignment with some nested parens does not throw");
  164. assert.doesNotThrow(function () { eval("var [[[...a]]] = [[[]]];"); }, "Destructured var array declaration with nested rest parameter does not throw");
  165. assert.doesNotThrow(function () { eval("let [[[...a]]] = [[[]]];"); }, "Destructured let array declaration with nested rest parameter does not throw");
  166. assert.doesNotThrow(function () { eval("const [[[...a]]] = [[[]]];"); }, "Destructured const array declaration with nested rest parameter does not throw");
  167. assert.doesNotThrow(function () { eval("var a; [[[...a]]] = [[[]]];"); }, "Destructured var array assignment with nested rest parameter does not throw");
  168. assert.doesNotThrow(function () { eval("let a; [[[...a]]] = [[[]]];"); }, "Destructured let array assignment with nested rest parameter does not throw");
  169. assert.doesNotThrow(function () { eval("var [[...a], ...b] = [[],];"); }, "Destructured var array declaration with valid nested rest parameters does not throw");
  170. assert.doesNotThrow(function () { eval("let [[...a], ...b] = [[],];"); }, "Destructured let array declaration with valid nested rest parameters does not throw");
  171. assert.doesNotThrow(function () { eval("const [[...a], ...b] = [[],];"); }, "Destructured const array declaration with valid nested rest parameters does not throw");
  172. assert.doesNotThrow(function () { eval("var a, b; [[...a], ...b] = [[],];"); }, "Destructured var array assignment with valid nested rest parameters does not throw");
  173. assert.doesNotThrow(function () { eval("let a, b; [[...a], ...b] = [[],];"); }, "Destructured let array assignment with valid nested rest parameters does not throw");
  174. assert.throws(function () { eval("var [[(a)], ((((((([b])))))))] = [[],[]];"); }, SyntaxError, "Destructured var array declaration with valid mixed paren and array nesting throws");
  175. assert.throws(function () { eval("let [[(a)], ((((((([b])))))))] = [[],[]];"); }, SyntaxError, "Destructured let array declaration with valid mixed paren and array nesting throws");
  176. assert.throws(function () { eval("const [[(a)], ((((((([b])))))))] = [[],[]];"); }, SyntaxError, "Destructured const array declaration with valid mixed paren and array nesting does not throw");
  177. assert.throws(function () { eval("const [[(a)], ((((((([b])))))))] = [[],[]];"); }, SyntaxError, "Destructured const array declaration with valid mixed paren and array nesting does not throw");
  178. assert.throws(function () { eval("var a; [([a])] = [[]];"); }, SyntaxError, "Destructured var array assignment with nested patterns surrounded by paren is not valid syntax");
  179. assert.throws(function () { eval("var a, b; [([a]), (((([b]))))] = [[], []];"); }, SyntaxError, "Destructured var array assignment with nested patterns surrounded by paren is not valid syntax");
  180. assert.throws(function () { eval("var a, b; [({a}), (((({b}))))] = [{}, {}];"); }, SyntaxError, "Destructured var array assignment with nested patterns surrounded by paren is not valid syntax");
  181. assert.throws(function () { eval("var a, b; ({a:({a}), b:((({b})))} = {a:{}, b:{}} );"); }, SyntaxError, "Destructured var array assignment with nested patterns surrounded by paren is not valid syntax");
  182. // Redeclarations
  183. assert.doesNotThrow(function () { eval("var [a, a] = [];"); }, "Destructured var array declaration with a repeated identifier reference does not throw");
  184. assert.throws(function () { eval("let [a, a] = [];"); }, SyntaxError, "Destructured let array declaration with a repeated identifier reference throws", "Let/Const redeclaration");
  185. assert.throws(function () { eval("const [a, a] = [];"); }, SyntaxError, "Destructured const array declaration with a repeated identifier reference throws", "Let/Const redeclaration");
  186. assert.doesNotThrow(function () { eval("var a; [a, a] = [];"); }, "Destructured var array assignment with a repeated identifier reference does not throw");
  187. assert.doesNotThrow(function () { eval("let a; [a, a] = [];"); }, "Destructured let array assignment with a repeated identifier reference does not throw");
  188. // Identifier property references
  189. assert.doesNotThrow(function () { eval("var a = {}; [a.x] = [];"); }, "Destructured var array assignment with an identifier property reference does not throw");
  190. assert.doesNotThrow(function () { eval("let a = {}; [a.x] = [];"); }, "Destructured let array assignment with an identifier property reference does not throw");
  191. assert.doesNotThrow(function () { eval("var a = {}; [a[\"x\"]] = [];"); }, "Destructured var array assignment with an identifier property reference does not throw");
  192. assert.doesNotThrow(function () { eval("let a = {}; [a[\"x\"]] = [];"); }, "Destructured let array assignment with an identifier property reference does not throw");
  193. // Call expression property references
  194. assert.throws(function () { eval("function foo() { return {}; }; var [foo()] = [];"); }, SyntaxError, "Destructured var array declaration with a call expression throws", "Syntax error");
  195. assert.throws(function () { eval("function foo() { return {}; }; let [foo()] = [];"); }, SyntaxError, "Destructured let array declaration with a call expression throws", "Let/Const redeclaration");
  196. assert.throws(function () { eval("function foo() { return {}; }; const [foo()] = [];"); }, SyntaxError, "Destructured const array declaration with a call expression throws", "Let/Const redeclaration");
  197. assert.throws(function () { eval("function foo() { return {}; }; [foo()] = [];"); }, SyntaxError, "Destructured array assignment with a call expression throws", "Invalid destructuring assignment target");
  198. assert.throws(function () { eval("function foo() { return {}; }; var [foo().x] = [];"); }, SyntaxError, "Destructured var array declaration with a call expression property reference throws", "Syntax error");
  199. assert.throws(function () { eval("function foo() { return {}; }; let [foo().x] = [];"); }, SyntaxError, "Destructured let array declaration with a call expression property reference throws", "Let/Const redeclaration");
  200. assert.throws(function () { eval("function foo() { return {}; }; const [foo().x] = [];"); }, SyntaxError, "Destructured const array declaration with a call expression property reference throws", "Let/Const redeclaration");
  201. assert.doesNotThrow(function () { eval("function foo() { return {}; }; [foo().x] = [];"); }, "Destructured array assignment with super a property reference does not throw");
  202. assert.doesNotThrow(function () { eval("function foo() { return {}; }; [foo()[\"x\"]] = [];"); }, "Destructured array assignment with a call expression property reference does not throw");
  203. // Super property references
  204. assert.throws(function () { eval("class foo { method() { var [super()] = []; } }"); }, SyntaxError, "Destructured var array declaration with a super call throws", "The use of a keyword for an identifier is invalid");
  205. assert.throws(function () { eval("class foo { method() { let [super()] = []; } }"); }, SyntaxError, "Destructured let array declaration with a super call throws", "The use of a keyword for an identifier is invalid");
  206. assert.throws(function () { eval("class foo { method() { const [super()] = []; } }"); }, SyntaxError, "Destructured const array declaration with a super call throws", "The use of a keyword for an identifier is invalid");
  207. assert.throws(function () { eval("class foo { method() { [super()] = []; } }"); }, SyntaxError, "Destructured array assignment with a super call throws", "Invalid use of the 'super' keyword");
  208. assert.throws(function () { eval("class foo { method() { var [super.x] = []; } }"); }, SyntaxError, "Destructured var array declaration with a super property reference throws", "The use of a keyword for an identifier is invalid");
  209. assert.throws(function () { eval("class foo { method() { let [super.x] = []; } }"); }, SyntaxError, "Destructured let array declaration with a super property reference does not throw", "The use of a keyword for an identifier is invalid");
  210. assert.throws(function () { eval("class foo { method() { const [super.x] = []; } }"); }, SyntaxError, "Destructured const array declaration with a super property reference does not throw", "The use of a keyword for an identifier is invalid");
  211. assert.doesNotThrow(function () { eval("class foo { method() { [super.x] = []; } }"); }, "Destructured var array assignment with super a property reference does not throw");
  212. assert.doesNotThrow(function () { eval("class foo { method() { [super[\"x\"]] = []; } }"); }, "Destructured array assignment with a super property reference does not throw");
  213. // Destructured array expressions used in other constructs
  214. assert.doesNotThrow(function () { eval("var a; `${[a] = [1]}`"); }, "Destructured assignment does not throw inside a string template");
  215. // OS 597319: Parens before a default value should not throw
  216. assert.doesNotThrow(function () { eval("[((((vrh190 )))) = 5184] = []"); }, "Destructured array assignment with parens before a default expression should not throw");
  217. }
  218. },
  219. {
  220. name: "Array destructuring basic functionality",
  221. body : function () {
  222. // Single assignments & undefined
  223. {
  224. let a1; [a1] = [1];
  225. let [a2] = [1];
  226. assert.areEqual(a1, a2, "Destructured array declaration and assignment assigning single values match");
  227. assert.areEqual(a1, 1, "Destructured array assignment assigns single value correctly");
  228. assert.areEqual(a2, 1, "Destructured array declaration assigns single value correctly");
  229. }
  230. {
  231. let a1; [a1] = [];
  232. let [a2] = [];
  233. assert.areEqual(a1, a2, "Destructured array declaration and assignment assigning an empty array match");
  234. assert.areEqual(a1, undefined, "Destructured array assignment assigning an empty array results in undefined");
  235. assert.areEqual(a2, undefined, "Destructured array declaration assigning an empty array results in undefined");
  236. let a3; [a3] = [,1];
  237. let [a4] = [,1];
  238. assert.areEqual(a3, a4, "Destructured array declaration and assignment assigning an array with missing values match");
  239. assert.areEqual(a3, undefined, "Destructured array assignment assigning an array with missing values results in undefined");
  240. assert.areEqual(a4, undefined, "Destructured array declaration assigning an array with missing values in undefined");
  241. }
  242. // Multiple assignments
  243. {
  244. let a1, b1, c1, d1, e1;
  245. [a1, b1, c1, d1, e1] = [1, 2, 3, 4, 5];
  246. let [a2, b2, c2, d2, e2] = [1, 2, 3, 4, 5];
  247. assert.areEqual([a1, b1, c1, d1, e1], [a2, b2, c2, d2, e2], "Destructured array assignment and declaration assigning multiple values match");
  248. assert.areEqual([1, 2, 3, 4, 5], [a1, b1, c1, d1, e1], "Destructured array assignment assigns multiple values correctly");
  249. assert.areEqual([1, 2, 3, 4, 5], [a2, b2, c2, d2, e2], "Destructured array declaration assigns multiple values correctly");
  250. }
  251. {
  252. let a1, b1, c1, d1, e1;
  253. [a1, b1, c1, d1, e1] = [1, 2, 3];
  254. let [a2, b2, c2, d2, e2] = [1, 2, 3];
  255. assert.areEqual([a1, b1, c1, d1, e1], [a2, b2, c2, d2, e2], "Destructured array assignment and declaration assigning a smaller array match");
  256. assert.areEqual([1, 2, 3, undefined, undefined], [a1, b1, c1, d1, e1], "Destructured array assignment assigns a smaller array correctly");
  257. assert.areEqual([1, 2, 3, undefined, undefined], [a2, b2, c2, d2, e2], "Destructured array declaration assigns a smaller array correctly");
  258. }
  259. {
  260. let a1, b1, c1, d1, e1;
  261. [a1, b1, c1, d1, e1] = [1, , 3, , 5];
  262. let [a2, b2, c2, d2, e2] = [1, , 3, , 5];
  263. assert.areEqual([a1, b1, c1, d1, e1], [a2, b2, c2, d2, e2], "Destructured array assignment and declaration assigning an array with some missing values match");
  264. assert.areEqual([1, undefined, 3, undefined, 5], [a1, b1, c1, d1, e1], "Destructured array assignment assigns an array with some missing values correctly");
  265. assert.areEqual([1, undefined, 3, undefined, 5], [a2, b2, c2, d2, e2], "Destructured array declaration assigns an array with some missing values correctly");
  266. }
  267. // Rest
  268. {
  269. let rest1;
  270. [...rest1] = [1, 2, 3, 4, 5];
  271. let [...rest2] = [1, 2, 3, 4, 5];
  272. assert.areEqual(rest1, rest2, "Destructured array assignment and declaration using only a rest parameter match");
  273. assert.areEqual([1, 2, 3, 4, 5], rest1, "Destructured array assignment uses only a rest parameter correctly");
  274. assert.areEqual([1, 2, 3, 4, 5], rest2, "Destructured array declaration uses only a rest parameter correctly");
  275. }
  276. {
  277. let a1, b1, c1, d1, e1;
  278. [a1, b1, c1, ...rest1] = [1, 2, 3, 4, 5];
  279. let [a2, b2, c2, ...rest2] = [1, 2, 3, 4, 5];
  280. assert.areEqual([a1, b1, c1, rest1], [a2, b2, c2, rest2], "Destructured array assignment and declaration using a rest parameter match");
  281. assert.areEqual([1, 2, 3, [4, 5]], [a1, b1, c1, rest1], "Destructured array assignment uses a rest parameter correctly");
  282. assert.areEqual([1, 2, 3, [4, 5]], [a2, b2, c2, rest2], "Destructured array declaration uses a rest parameter correctly");
  283. let a3, b3, c3, d3, e3;
  284. [a3, b3, c3, ...rest3] = [1, 2, 3];
  285. let [a4, b4, c4, ...rest4] = [1, 2, 3];
  286. assert.areEqual([a3, b3, c3, rest3], [a4, b4, c4, rest4], "Destructured array assignment and declaration using a rest parameter and a smaller array match");
  287. assert.areEqual([1, 2, 3, []], [a3, b3, c3, rest3], "Destructured array assignment uses a rest parameter and a smaller array correctly");
  288. assert.areEqual([1, 2, 3, []], [a4, b4, c4, rest4], "Destructured array declaration uses a rest parameter and a smaller array correctly");
  289. }
  290. {
  291. let a1, b1;
  292. [[...a1], ...b1] = [[1, 2, 3, 4], 5, 6, 7, 8];
  293. let [[...a2], ...b2] = [[1, 2, 3, 4], 5, 6, 7, 8];
  294. assert.areEqual([a1, b1], [a2, b2], "Destructured array assignment and declaration with nested rest parameters match");
  295. assert.areEqual([a1, b1], [[1, 2, 3, 4], [5, 6, 7, 8]], "Destructured array assignment uses nested rest parameters correctly");
  296. assert.areEqual([a2, b2], [[1, 2, 3, 4], [5, 6, 7, 8]], "Destructured array declaration uses nested rest parameters correctly");
  297. }
  298. // Default values
  299. {
  300. let a1, b1, c1, d1, e1;
  301. [a1 = 1, b1 = 2, c1 = 3, d1 = 4, e1 = 5] = [];
  302. let [a2 = 1, b2 = 2, c2 = 3, d2 = 4, e2 = 5] = [];
  303. assert.areEqual([a1, b1, c1, d1, e1], [a2, b2, c2, d2, e2], "Destructured array assignment and declaration with default values assigning an empty array match");
  304. assert.areEqual([1, 2, 3, 4, 5], [a1, b1, c1, d1, e1], "Destructured array assignment assigns an array with default values assigning an empty array correctly");
  305. assert.areEqual([1, 2, 3, 4, 5], [a2, b2, c2, d2, e2], "Destructured array declaration assigns an array with default values assigning an empty array correctly");
  306. }
  307. {
  308. let a1, b1, c1, d1, e1;
  309. [a1 = 1, b1 = 2, c1 = 3, d1 = 4, e1 = 5] = [5, , 3, 2, ];
  310. let [a2 = 1, b2 = 2, c2 = 3, d2 = 4, e2 = 5] = [5, , 3, 2, ];
  311. assert.areEqual([a1, b1, c1, d1, e1], [a2, b2, c2, d2, e2], "Destructured array assignment and declaration assigning an array with some missing values match");
  312. assert.areEqual([5, 2, 3, 2, 5], [a1, b1, c1, d1, e1], "Destructured array assignment assigns an array with some missing values correctly");
  313. assert.areEqual([5, 2, 3, 2, 5], [a2, b2, c2, d2, e2], "Destructured array declaration assigns an array with some missing values correctly");
  314. }
  315. // Identifier references
  316. {
  317. let a = {};
  318. [a.x] = [10];
  319. assert.areEqual(10, a.x, "Destructured array with an object property assignment works correctly");
  320. [a["x"]] = [20];
  321. assert.areEqual(20, a["x"], "Destructured array with an object index assignment works correctly");
  322. var obj = { x: 10 };
  323. function foo() { return obj };
  324. [foo().x] = [20];
  325. assert.areEqual(20, foo().x, "Destructured array with a call result property assignment works correctly");
  326. [foo()["x"]] = [30];
  327. assert.areEqual(30, foo()["x"], "Destructured array with a call result index assignment works correctly");
  328. [...foo().x] = [20];
  329. assert.areEqual([20], foo().x, "Destructured array with a call result rest element works correctly");
  330. [...foo()["x"]] = [30];
  331. assert.areEqual([30], foo()["x"], "Destructured array with a call result rest element works correctly");
  332. class base {
  333. methodProp() { return {}; }
  334. methodIndex() { return {}; }
  335. methodRestProp() { return {}; }
  336. methodRestIndex() { return {}; }
  337. get x() { return this._x; }
  338. set x(v) { this._x = v; }
  339. };
  340. class extended extends base {
  341. methodProp() { return [super.x] = [10, 20, 30]; }
  342. methodIndex() { return [super["x"]] = [40, 50, 60]; }
  343. methodRestProp() { return [...super.x] = [10, 20, 30]; }
  344. methodRestIndex() { return [...super.x] = [40, 50, 60]; }
  345. getValue() { return super.x;}
  346. };
  347. let c = new extended();
  348. assert.areEqual(undefined, c.getValue(), "Super property before destructured assignment is undefined");
  349. c.methodProp();
  350. assert.areEqual(10, c.getValue(), "Super property after destructured super property assignment");
  351. c.methodIndex();
  352. assert.areEqual(40, c.getValue(), "Super property after destructured super index assignment");
  353. c.methodRestProp();
  354. assert.areEqual([10, 20, 30], c.getValue(), "Super property after destructured super property assignment");
  355. c.methodRestIndex();
  356. assert.areEqual([40, 50, 60], c.getValue(), "Super property after destructured super index assignment");
  357. }
  358. // Nesting
  359. {
  360. let a1; [[a1]] = [[1]];
  361. let [[a2]] = [[1]];
  362. assert.areEqual(a1, a2, "Destructured array declaration and assignment assigning single values match");
  363. assert.areEqual(a1, 1, "Destructured array assignment assigns single value correctly");
  364. assert.areEqual(a2, 1, "Destructured array declaration assigns single value correctly");
  365. }
  366. {
  367. let a1, b1, c1, d1, e1;
  368. [[a1, b1], c1, [d1, [e1]]] = [[1, 2], 3, [4, [5]]];
  369. let [[a2, b2], c2, [d2, [e2]]] = [[1, 2], 3, [4, [5]]];
  370. assert.areEqual([a1, b1, c1, d1, e1], [a2, b2, c2, d2, e2], "Destructured array assignment and declaration assigning multiple values match");
  371. assert.areEqual([1, 2, 3, 4, 5], [a1, b1, c1, d1, e1], "Destructured array assignment assigns multiple values correctly");
  372. assert.areEqual([1, 2, 3, 4, 5], [a2, b2, c2, d2, e2], "Destructured array declaration assigns multiple values correctly");
  373. }
  374. {
  375. let a1; [[a1, b1] = [1, 2]] = [];
  376. let [[a2, b2] = [1, 2]] = [];
  377. assert.areEqual([a1, b1], [a2, b2], "Destructured array declaration and assignment using nested values match");
  378. assert.areEqual([1, 2], [a1, b1], "Destructured array assignment assigns nested values correctly");
  379. assert.areEqual([1, 2], [a2, b2], "Destructured array declaration assigns nested values correctly");
  380. }
  381. {
  382. let a1; [[[a1] = [1], [[b1]] = [[2]]] = [, undefined]] = [undefined, ];
  383. let [[[a2] = [1], [[b2]] = [[2]]] = [, undefined]] = [undefined, ];
  384. assert.areEqual([a1, b1], [a2, b2], "Destructured array declaration and assignment using nested default values match");
  385. assert.areEqual([1, 2], [a1, b1], "Destructured array assignment assigns nested default values correctly");
  386. assert.areEqual([1, 2], [a2, b2], "Destructured array declaration assigns nested default values correctly");
  387. }
  388. // Other iterators
  389. {
  390. let a1; [a1, b1, c1, d1, ...rest1] = "testing";
  391. let [a2, b2, c2, d2, ...rest2] = "testing";
  392. assert.areEqual([a1, b1, c1, d1, rest1], [a2, b2, c2, d2, rest2], "Destructured array declaration and assignment using nested values match");
  393. assert.areEqual(["t", "e", "s", "t", ["i", "n", "g"]], [a1, b1, c1, d1, rest1], "Destructured array assignment assigns nested values correctly");
  394. assert.areEqual(["t", "e", "s", "t", ["i", "n", "g"]], [a2, b2, c2, d2, rest2], "Destructured array declaration assigns nested values correctly");
  395. }
  396. {
  397. let map = new Map();
  398. map.set(1, 6);
  399. map.set(2, 7);
  400. map.set(3, 8);
  401. map.set(4, 9);
  402. map.set(5, 10);
  403. let a1; [a1, b1, c1, d1, ...rest1] = map.entries();
  404. let [a2, b2, c2, d2, ...rest2] = map.entries();
  405. assert.areEqual([a1, b1, c1, d1, rest1], [a2, b2, c2, d2, rest2], "Destructured array declaration and assignment using nested values match");
  406. assert.areEqual([[1, 6], [2, 7], [3, 8], [4, 9], [[5, 10]]], [a1, b1, c1, d1, rest1], "Destructured array assignment assigns nested values correctly");
  407. assert.areEqual([[1, 6], [2, 7], [3, 8], [4, 9], [[5, 10]]], [a2, b2, c2, d2, rest2], "Destructured array declaration assigns nested values correctly");
  408. }
  409. {
  410. let getIteratorCalledCount = 0;
  411. let nextCalledCount = 0;
  412. let doneCalledCount = 0;
  413. let valueCalledCount = 0;
  414. let simpleIterator = {
  415. [Symbol.iterator]: function () {
  416. ++getIteratorCalledCount;
  417. return {
  418. i: 0,
  419. next: function () {
  420. ++nextCalledCount;
  421. var that = this;
  422. return {
  423. get done() {
  424. ++doneCalledCount;
  425. return that.i == 1;
  426. },
  427. get value() {
  428. ++valueCalledCount;
  429. return that.i++;
  430. }
  431. };
  432. }
  433. };
  434. }
  435. };
  436. let [a, b, c] = simpleIterator;
  437. assert.areEqual(1, getIteratorCalledCount, "GetIterator is called once per iterator");
  438. assert.areEqual(3, nextCalledCount, "'.next()' is called once per destructuring reference");
  439. assert.areEqual(3, doneCalledCount, "'done' is read once per destructuring reference");
  440. assert.areEqual(1, valueCalledCount, "'value' is read once per .next() call until done is true");
  441. [getIteratorCalledCount, nextCalledCount, doneCalledCount, valueCalledCount] = [0, 0, 0, 0];
  442. let [...rest] = simpleIterator;
  443. assert.areEqual(1, getIteratorCalledCount, "GetIterator is called once per iterator");
  444. assert.areEqual(2, nextCalledCount, "'.next()' is called until done is true when filling a rest element");
  445. assert.areEqual(2, doneCalledCount, "'done' is read until it is true");
  446. assert.areEqual(1, valueCalledCount, "'value' is read once for each .next() call until done is true");
  447. [getIteratorCalledCount, nextCalledCount, doneCalledCount, valueCalledCount] = [0, 0, 0, 0];
  448. [a, b, c, ...rest] = simpleIterator;
  449. assert.areEqual(1, getIteratorCalledCount, "GetIterator is called once per iterator");
  450. assert.areEqual(4, nextCalledCount, "'.next()' is called once per destructuring reference");
  451. assert.areEqual(4, doneCalledCount, "'done' is read once per destructuring reference");
  452. assert.areEqual(1, valueCalledCount, "'value' is read once per .next() call until done is true");
  453. }
  454. // Runtime type errors
  455. assert.throws(function () { eval("let [a] = 1;") }, TypeError, "Non-object used as an iterator in a declaration throws", "Object doesn't support property or method 'Symbol.iterator'");
  456. assert.throws(function () { eval("let a; [a] = 1;") }, TypeError, "Non-object used as an iterator an assignment throws" , "Object doesn't support property or method 'Symbol.iterator'");
  457. assert.throws(function () { eval("let [[a]] = [];") }, TypeError, "Nested non-object used as an iterator in a declaration throws", "Unable to get property 'Symbol.iterator' of undefined or null reference");
  458. assert.throws(function () { eval("let a; [[a]] = [];") }, TypeError, "Nested non-object used as an iterator an assignment throws", "Unable to get property 'Symbol.iterator' of undefined or null reference");
  459. // Array destructuring in various contexts
  460. {
  461. let a, b, c;
  462. function foo(x = [a, b = 2, ...c] = [1,,3,4,5,6,7]) {
  463. assert.areEqual([1, 2, [3,4,5,6,7]], [a, b, c], "Destructuring array assignment works correctly inside a default parameter expression");
  464. assert.areEqual([1,,3,4,5,6,7], x, "Destructuring array assignment evaluates to RHS in a default parameter expression");
  465. }
  466. foo();
  467. `${[a = 5, b, ...c] = [, 1, 3, 5, 7, 9]}`;
  468. assert.areEqual([5, 1, [3, 5, 7, 9]], [a, b, c], "Destructuring array assignment inside a string template works correctly");
  469. (() => [a,, b, c] = [1, 2, 3])();
  470. assert.areEqual([1, 3, undefined], [a, b, c], "Destructuring array assignment inside a lambda expression works correctly");
  471. }
  472. // nested destructuring
  473. {
  474. let [[a]=[1]] = [[2]];
  475. assert.areEqual(a, 2, "Nested destructuring - value is present");
  476. [[a]=[1]] = [[]];
  477. assert.areEqual(a, undefined, "Nested destructuring - value is present but undefined");
  478. [[a]=[1]] = [];
  479. assert.areEqual(a, 1, "Nested destructuring - value is not present - use default");
  480. [[a]=1] = [[]];
  481. assert.areEqual(a, undefined, "Nested destructuring - value is present - default is incorrect - does not have @@iterator");
  482. }
  483. // Bug OSG : 4533495
  484. {
  485. function foo() {
  486. for(var [i, j, k] in { qux: 1 }) {
  487. return i === "q" && j === "u" && k === "x";
  488. }
  489. }
  490. assert.isTrue(foo(), "Array destructuring pattern on for..in is initialized correctly");
  491. }
  492. {
  493. let obj1 = {};
  494. obj1[Symbol.iterator] = function () {
  495. return {
  496. next: function() {
  497. assert.fail("next function should not be called");
  498. }
  499. };
  500. };
  501. // Empty slot should not call next on the iterator.
  502. var [] = obj1;
  503. }
  504. {
  505. let obj1 = {};
  506. obj1[Symbol.iterator] = function () {
  507. return {
  508. next: function() {
  509. this.counter++;
  510. if (this.counter > 1)
  511. {
  512. assert.fail("next function should not be called for the second time");
  513. }
  514. return {value : undefined, done: false};
  515. },
  516. counter : 0
  517. };
  518. };
  519. // Second empty slot should not call next on the iterator.
  520. var [,] = obj1;
  521. }
  522. }
  523. }
  524. ];
  525. testRunner.runTests(tests, { verbose: WScript.Arguments[0] != "summary" });