1425bb815Sopenharmony_ci// Copyright JS Foundation and other contributors, http://js.foundation
2425bb815Sopenharmony_ci//
3425bb815Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License");
4425bb815Sopenharmony_ci// you may not use this file except in compliance with the License.
5425bb815Sopenharmony_ci// You may obtain a copy of the License at
6425bb815Sopenharmony_ci//
7425bb815Sopenharmony_ci//     http://www.apache.org/licenses/LICENSE-2.0
8425bb815Sopenharmony_ci//
9425bb815Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software
10425bb815Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS
11425bb815Sopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12425bb815Sopenharmony_ci// See the License for the specific language governing permissions and
13425bb815Sopenharmony_ci// limitations under the License.
14425bb815Sopenharmony_ci
15425bb815Sopenharmony_cifunction checkSyntax (str) {
16425bb815Sopenharmony_ci  try {
17425bb815Sopenharmony_ci    eval (str);
18425bb815Sopenharmony_ci    assert (false);
19425bb815Sopenharmony_ci  } catch (e) {
20425bb815Sopenharmony_ci    assert (e instanceof SyntaxError);
21425bb815Sopenharmony_ci  }
22425bb815Sopenharmony_ci}
23425bb815Sopenharmony_ci
24425bb815Sopenharmony_cifunction assertArrayEqual (actual, expected) {
25425bb815Sopenharmony_ci  assert (actual.length === expected.length);
26425bb815Sopenharmony_ci
27425bb815Sopenharmony_ci  for (var i = 0; i < actual.length; i++) {
28425bb815Sopenharmony_ci    assert (actual[i] === expected[i]);
29425bb815Sopenharmony_ci  }
30425bb815Sopenharmony_ci}
31425bb815Sopenharmony_ci
32425bb815Sopenharmony_cifunction mustThrow (str) {
33425bb815Sopenharmony_ci  try {
34425bb815Sopenharmony_ci    eval (str);
35425bb815Sopenharmony_ci    assert (false);
36425bb815Sopenharmony_ci  } catch (e) {
37425bb815Sopenharmony_ci    assert (e instanceof TypeError);
38425bb815Sopenharmony_ci  }
39425bb815Sopenharmony_ci}
40425bb815Sopenharmony_ci
41425bb815Sopenharmony_cicheckSyntax ("var [a]");
42425bb815Sopenharmony_cicheckSyntax ("var [a, o.a]");
43425bb815Sopenharmony_cicheckSyntax ("var [a, ...b,]");
44425bb815Sopenharmony_cicheckSyntax ("var [a, ...b = 4]");
45425bb815Sopenharmony_cicheckSyntax ("var [a, ...[b] = 4]");
46425bb815Sopenharmony_cicheckSyntax ("var [let]");
47425bb815Sopenharmony_cicheckSyntax ("var [get = []");
48425bb815Sopenharmony_cicheckSyntax ("var [get : 5]");
49425bb815Sopenharmony_cicheckSyntax ("var [[a = {},]");
50425bb815Sopenharmony_cicheckSyntax ("let [a,a] = []");
51425bb815Sopenharmony_cicheckSyntax ("let [a, ...a] = []");
52425bb815Sopenharmony_cicheckSyntax ("const [a,a] = []");
53425bb815Sopenharmony_cicheckSyntax ("const [a, ...a] = []");
54425bb815Sopenharmony_cicheckSyntax ("[new Object()] = []");
55425bb815Sopenharmony_cicheckSyntax ("[Object()] = []");
56425bb815Sopenharmony_cicheckSyntax ("[(a, b, d, c)] = []");
57425bb815Sopenharmony_cicheckSyntax ("[super] = []");
58425bb815Sopenharmony_cicheckSyntax ("[this] = []");
59425bb815Sopenharmony_cicheckSyntax ("[()] = []");
60425bb815Sopenharmony_cicheckSyntax ("try { let [$] = $;");
61425bb815Sopenharmony_cicheckSyntax ("let a, [ b.c ] = [6];");
62425bb815Sopenharmony_cicheckSyntax ("let [(a)] = [1]");
63425bb815Sopenharmony_ci
64425bb815Sopenharmony_cimustThrow ("var [a] = 4");
65425bb815Sopenharmony_cimustThrow ("var [a] = 5");
66425bb815Sopenharmony_cimustThrow ("var [a] = {}");
67425bb815Sopenharmony_cimustThrow ("var [a] = { get [Symbol.iterator] () { throw new TypeError } }");
68425bb815Sopenharmony_cimustThrow ("var [a] = { [Symbol.iterator] () {} }");
69425bb815Sopenharmony_cimustThrow ("var [a] = { [Symbol.iterator] () { return {} } }");
70425bb815Sopenharmony_cimustThrow ("var [a] = { [Symbol.iterator] () { return { next: 5 } } }");
71425bb815Sopenharmony_cimustThrow ("var [a] = { [Symbol.iterator] () { return { next: 5 } } }");
72425bb815Sopenharmony_cimustThrow ("var [a] = { [Symbol.iterator] () { return { get next() { throw new TypeError } } } }");
73425bb815Sopenharmony_cimustThrow ("var [a] = { [Symbol.iterator] () { return { next () { } } } }");
74425bb815Sopenharmony_cimustThrow ("var [a] = { [Symbol.iterator] () { return { next () { } } } }");
75425bb815Sopenharmony_cimustThrow ("var [a] = { [Symbol.iterator] () { return { next () { return { get value () { throw new TypeError }}}}}}");
76425bb815Sopenharmony_cimustThrow ("var [a] = { [Symbol.iterator] () { return { next () { return { get done () { throw new TypeError }}}}}}");
77425bb815Sopenharmony_ci
78425bb815Sopenharmony_ci// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
79425bb815Sopenharmony_ci
80425bb815Sopenharmony_ci// Basic variable assignment
81425bb815Sopenharmony_ci(function () {
82425bb815Sopenharmony_ci  var foo = ["one", "two", "three"];
83425bb815Sopenharmony_ci
84425bb815Sopenharmony_ci  var [red, yellow, green] = foo;
85425bb815Sopenharmony_ci  assert (red === "one");
86425bb815Sopenharmony_ci  assert (yellow === "two");
87425bb815Sopenharmony_ci  assert (green === "three");
88425bb815Sopenharmony_ci}) ();
89425bb815Sopenharmony_ci
90425bb815Sopenharmony_ci// Assignment separate from declaration
91425bb815Sopenharmony_ci(function () {
92425bb815Sopenharmony_ci  var a, b;
93425bb815Sopenharmony_ci
94425bb815Sopenharmony_ci  [a, b] = [1, 2];
95425bb815Sopenharmony_ci  assert (a === 1);
96425bb815Sopenharmony_ci  assert (b === 2);
97425bb815Sopenharmony_ci}) ();
98425bb815Sopenharmony_ci
99425bb815Sopenharmony_ci// Default values
100425bb815Sopenharmony_ci(function () {
101425bb815Sopenharmony_ci  var a, b;
102425bb815Sopenharmony_ci  [a = 5, b = 7] = [1];
103425bb815Sopenharmony_ci
104425bb815Sopenharmony_ci  assert (a === 1);
105425bb815Sopenharmony_ci  assert (b === 7);
106425bb815Sopenharmony_ci}) ();
107425bb815Sopenharmony_ci
108425bb815Sopenharmony_ci// Swapping variables
109425bb815Sopenharmony_ci(function () {
110425bb815Sopenharmony_ci  var a = 1;
111425bb815Sopenharmony_ci  var b = 3;
112425bb815Sopenharmony_ci
113425bb815Sopenharmony_ci  [a, b] = [b, a];
114425bb815Sopenharmony_ci  assert (a === 3);
115425bb815Sopenharmony_ci  assert (b === 1);
116425bb815Sopenharmony_ci
117425bb815Sopenharmony_ci  var arr = [1,2,3];
118425bb815Sopenharmony_ci  [arr[2], arr[1]] = [arr[1], arr[2]];
119425bb815Sopenharmony_ci  assertArrayEqual (arr, [1, 3, 2]);
120425bb815Sopenharmony_ci}) ();
121425bb815Sopenharmony_ci
122425bb815Sopenharmony_ci// Parsing an array returned from a function
123425bb815Sopenharmony_ci(function () {
124425bb815Sopenharmony_ci  function f() {
125425bb815Sopenharmony_ci    return [1, 2];
126425bb815Sopenharmony_ci  }
127425bb815Sopenharmony_ci
128425bb815Sopenharmony_ci  var a, b;
129425bb815Sopenharmony_ci  [a, b] = f();
130425bb815Sopenharmony_ci  assert (a === 1);
131425bb815Sopenharmony_ci  assert (b === 2);
132425bb815Sopenharmony_ci}) ();
133425bb815Sopenharmony_ci
134425bb815Sopenharmony_ci// Ignoring some returned values
135425bb815Sopenharmony_ci(function () {
136425bb815Sopenharmony_ci  function f() {
137425bb815Sopenharmony_ci    return [1, 2, 3];
138425bb815Sopenharmony_ci  }
139425bb815Sopenharmony_ci
140425bb815Sopenharmony_ci  var a, b;
141425bb815Sopenharmony_ci  [a, ,b] = f();
142425bb815Sopenharmony_ci  assert (a === 1);
143425bb815Sopenharmony_ci  assert (b === 3);
144425bb815Sopenharmony_ci}) ();
145425bb815Sopenharmony_ci
146425bb815Sopenharmony_ci// Ignoring some returned values
147425bb815Sopenharmony_ci(function () {
148425bb815Sopenharmony_ci  var [a, ...b] = [1, 2, 3];
149425bb815Sopenharmony_ci  assert (a === 1);
150425bb815Sopenharmony_ci  assertArrayEqual (b, [2, 3]);
151425bb815Sopenharmony_ci}) ();
152425bb815Sopenharmony_ci
153425bb815Sopenharmony_ci// Unpacking values from a regular expression match
154425bb815Sopenharmony_ci(function () {
155425bb815Sopenharmony_ci  function parseProtocol(url) {
156425bb815Sopenharmony_ci    var parsedURL = /^(\w+)\:\/\/([^\/]+)\/(.*)$/.exec(url);
157425bb815Sopenharmony_ci    if (!parsedURL) {
158425bb815Sopenharmony_ci      return false;
159425bb815Sopenharmony_ci    }
160425bb815Sopenharmony_ci
161425bb815Sopenharmony_ci    var [, protocol, fullhost, fullpath] = parsedURL;
162425bb815Sopenharmony_ci    return protocol;
163425bb815Sopenharmony_ci  }
164425bb815Sopenharmony_ci
165425bb815Sopenharmony_ci  assert (parseProtocol("https://developer.mozilla.org/en-US/Web/JavaScript") === "https");
166425bb815Sopenharmony_ci}) ();
167425bb815Sopenharmony_ci
168425bb815Sopenharmony_ci// Test inner patterns I.
169425bb815Sopenharmony_ci(function () {
170425bb815Sopenharmony_ci  let [a, [b, [c = 4, d = 5]], [e] = [6]] = [1, [2, [3,undefined]]];
171425bb815Sopenharmony_ci
172425bb815Sopenharmony_ci  assert (a === 1);
173425bb815Sopenharmony_ci  assert (b === 2);
174425bb815Sopenharmony_ci  assert (c === 3);
175425bb815Sopenharmony_ci  assert (d === 5);
176425bb815Sopenharmony_ci  assert (e === 6);
177425bb815Sopenharmony_ci}) ();
178425bb815Sopenharmony_ci
179425bb815Sopenharmony_ci// Test inner patterns II.
180425bb815Sopenharmony_ci(function () {
181425bb815Sopenharmony_ci  var o = {};
182425bb815Sopenharmony_ci  [a, b, c, o.a = 4, o.b, o.c = 3] = ["1", "2", "3", undefined, "8", "6"];
183425bb815Sopenharmony_ci
184425bb815Sopenharmony_ci  assert (a === "1");
185425bb815Sopenharmony_ci  assert (b === "2");
186425bb815Sopenharmony_ci  assert (c === "3");
187425bb815Sopenharmony_ci  assert (o.a === 4);
188425bb815Sopenharmony_ci  assert (o.b === "8");
189425bb815Sopenharmony_ci  assert (o.c === "6");
190425bb815Sopenharmony_ci}) ();
191425bb815Sopenharmony_ci
192425bb815Sopenharmony_ci// Test rest element I.
193425bb815Sopenharmony_ci(function () {
194425bb815Sopenharmony_ci  var o = {};
195425bb815Sopenharmony_ci  [...o.a] = ["1", "2", "3"];
196425bb815Sopenharmony_ci
197425bb815Sopenharmony_ci  assertArrayEqual (o.a, ["1", "2", "3"]);
198425bb815Sopenharmony_ci}) ();
199425bb815Sopenharmony_ci
200425bb815Sopenharmony_ci// Test rest element II.
201425bb815Sopenharmony_ci(function () {
202425bb815Sopenharmony_ci  [...[a,b,c]] = ["1", "2", "3"];
203425bb815Sopenharmony_ci
204425bb815Sopenharmony_ci  assert (a === "1");
205425bb815Sopenharmony_ci  assert (b === "2");
206425bb815Sopenharmony_ci  assert (c === "3");
207425bb815Sopenharmony_ci}) ();
208425bb815Sopenharmony_ci
209425bb815Sopenharmony_ci// Test inner object pattern I.
210425bb815Sopenharmony_ci(function () {
211425bb815Sopenharmony_ci  [{f : a, g : b}, , , ...[c, d, e]] = [{ f : "1", g : "2"}, 3, 4, 5, 6, 7];
212425bb815Sopenharmony_ci
213425bb815Sopenharmony_ci  assert (a === "1");
214425bb815Sopenharmony_ci  assert (b === "2");
215425bb815Sopenharmony_ci  assert (c === 5);
216425bb815Sopenharmony_ci  assert (d === 6);
217425bb815Sopenharmony_ci  assert (e === 7);
218425bb815Sopenharmony_ci}) ();
219425bb815Sopenharmony_ci
220425bb815Sopenharmony_ci// Multiple declaration
221425bb815Sopenharmony_ci(function () {
222425bb815Sopenharmony_ci  var [a] = [1], [b] = [2];
223425bb815Sopenharmony_ci
224425bb815Sopenharmony_ci  assert (a === 1);
225425bb815Sopenharmony_ci  assert (b === 2);
226425bb815Sopenharmony_ci}) ();
227425bb815Sopenharmony_ci
228425bb815Sopenharmony_ci// Force the creation of lexical environment I.
229425bb815Sopenharmony_ci(function () {
230425bb815Sopenharmony_ci  const [a] = [1];
231425bb815Sopenharmony_ci  eval();
232425bb815Sopenharmony_ci
233425bb815Sopenharmony_ci  assert (a === 1);
234425bb815Sopenharmony_ci}) ();
235425bb815Sopenharmony_ci
236425bb815Sopenharmony_ci// Force the creation of lexical environment II.
237425bb815Sopenharmony_ci(function () {
238425bb815Sopenharmony_ci  let [a] = [1];
239425bb815Sopenharmony_ci  eval();
240425bb815Sopenharmony_ci
241425bb815Sopenharmony_ci  assert (a === 1);
242425bb815Sopenharmony_ci}) ();
243425bb815Sopenharmony_ci
244425bb815Sopenharmony_ci// Check the parsing of AssignmentElement
245425bb815Sopenharmony_ci(function () {
246425bb815Sopenharmony_ci  var a = 6;
247425bb815Sopenharmony_ci  [((a))] = [7];
248425bb815Sopenharmony_ci  assert (a === 7);
249425bb815Sopenharmony_ci}) ();
250425bb815Sopenharmony_ci
251425bb815Sopenharmony_ci// Test iterator closing
252425bb815Sopenharmony_cifunction __createIterableObject (arr, methods) {
253425bb815Sopenharmony_ci  methods = methods || {};
254425bb815Sopenharmony_ci  if (typeof Symbol !== 'function' || !Symbol.iterator) {
255425bb815Sopenharmony_ci    return {};
256425bb815Sopenharmony_ci  }
257425bb815Sopenharmony_ci  arr.length++;
258425bb815Sopenharmony_ci  var iterator = {
259425bb815Sopenharmony_ci    next: function() {
260425bb815Sopenharmony_ci      return { value: arr.shift(), done: arr.length <= 0 };
261425bb815Sopenharmony_ci    },
262425bb815Sopenharmony_ci    'return': methods['return'],
263425bb815Sopenharmony_ci    'throw': methods['throw']
264425bb815Sopenharmony_ci  };
265425bb815Sopenharmony_ci  var iterable = {};
266425bb815Sopenharmony_ci  iterable[Symbol.iterator] = function () { return iterator; };
267425bb815Sopenharmony_ci  return iterable;
268425bb815Sopenharmony_ci};
269425bb815Sopenharmony_ci
270425bb815Sopenharmony_ci(function () {
271425bb815Sopenharmony_ci  var closed = false;
272425bb815Sopenharmony_ci  var iter = __createIterableObject([1, 2, 3], {
273425bb815Sopenharmony_ci    'return': function() { closed = true; return {}; }
274425bb815Sopenharmony_ci  });
275425bb815Sopenharmony_ci  var [a, b] = iter;
276425bb815Sopenharmony_ci  assert (closed === true);
277425bb815Sopenharmony_ci  assert (a === 1);
278425bb815Sopenharmony_ci  assert (b === 2);
279425bb815Sopenharmony_ci}) ();
280425bb815Sopenharmony_ci
281425bb815Sopenharmony_cimustThrow ("var iter = __createIterableObject([], "
282425bb815Sopenharmony_ci           + "{ get 'return'() { throw new TypeError() }});"
283425bb815Sopenharmony_ci           + "var [a] = iter");
284425bb815Sopenharmony_ci
285425bb815Sopenharmony_cimustThrow ("var iter = __createIterableObject([], "
286425bb815Sopenharmony_ci           + "{ 'return': 5 });"
287425bb815Sopenharmony_ci           + "var [a] = iter");
288425bb815Sopenharmony_ci
289425bb815Sopenharmony_cimustThrow ("var iter = __createIterableObject([], "
290425bb815Sopenharmony_ci           + "{ 'return': function() { return 5; }});"
291425bb815Sopenharmony_ci           + "var [a] = iter");
292425bb815Sopenharmony_ci
293425bb815Sopenharmony_cimustThrow ("try { throw 5 } catch (e) {"
294425bb815Sopenharmony_ci           + "var iter = __createIterableObject([], "
295425bb815Sopenharmony_ci           + "{ get 'return'() { throw new TypeError() }});"
296425bb815Sopenharmony_ci           + "var [a] = iter }");
297425bb815Sopenharmony_ci
298425bb815Sopenharmony_cimustThrow ("try { throw 5 } catch (e) {"
299425bb815Sopenharmony_ci           + "var iter = __createIterableObject([], "
300425bb815Sopenharmony_ci           + "{ 'return': 5 });"
301425bb815Sopenharmony_ci           + "var [a] = iter }");
302425bb815Sopenharmony_ci
303425bb815Sopenharmony_cimustThrow ("try { throw 5 } catch (e) {"
304425bb815Sopenharmony_ci           + "var iter = __createIterableObject([], "
305425bb815Sopenharmony_ci           + "{ 'return': function() { return 5; }});"
306425bb815Sopenharmony_ci           + "var [a] = iter }");
307425bb815Sopenharmony_ci
308425bb815Sopenharmony_citry {
309425bb815Sopenharmony_ci  eval ("var a = 0; 1 + [a] = [1]");
310425bb815Sopenharmony_ci  assert (false);
311425bb815Sopenharmony_ci} catch (e) {
312425bb815Sopenharmony_ci  assert (e instanceof ReferenceError);
313425bb815Sopenharmony_ci}
314