1// Copyright JS Foundation and other contributors, http://js.foundation 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15function checkSyntax (str) { 16 try { 17 eval (str); 18 assert (false); 19 } catch (e) { 20 assert (e instanceof SyntaxError); 21 } 22} 23 24function assertArrayEqual (actual, expected) { 25 assert (actual.length === expected.length); 26 27 for (var i = 0; i < actual.length; i++) { 28 assert (actual[i] === expected[i]); 29 } 30} 31 32function mustThrow (str) { 33 try { 34 eval (str); 35 assert (false); 36 } catch (e) { 37 assert (e instanceof TypeError); 38 } 39} 40 41checkSyntax ("var [a]"); 42checkSyntax ("var [a, o.a]"); 43checkSyntax ("var [a, ...b,]"); 44checkSyntax ("var [a, ...b = 4]"); 45checkSyntax ("var [a, ...[b] = 4]"); 46checkSyntax ("var [let]"); 47checkSyntax ("var [get = []"); 48checkSyntax ("var [get : 5]"); 49checkSyntax ("var [[a = {},]"); 50checkSyntax ("let [a,a] = []"); 51checkSyntax ("let [a, ...a] = []"); 52checkSyntax ("const [a,a] = []"); 53checkSyntax ("const [a, ...a] = []"); 54checkSyntax ("[new Object()] = []"); 55checkSyntax ("[Object()] = []"); 56checkSyntax ("[(a, b, d, c)] = []"); 57checkSyntax ("[super] = []"); 58checkSyntax ("[this] = []"); 59checkSyntax ("[()] = []"); 60checkSyntax ("try { let [$] = $;"); 61checkSyntax ("let a, [ b.c ] = [6];"); 62checkSyntax ("let [(a)] = [1]"); 63 64mustThrow ("var [a] = 4"); 65mustThrow ("var [a] = 5"); 66mustThrow ("var [a] = {}"); 67mustThrow ("var [a] = { get [Symbol.iterator] () { throw new TypeError } }"); 68mustThrow ("var [a] = { [Symbol.iterator] () {} }"); 69mustThrow ("var [a] = { [Symbol.iterator] () { return {} } }"); 70mustThrow ("var [a] = { [Symbol.iterator] () { return { next: 5 } } }"); 71mustThrow ("var [a] = { [Symbol.iterator] () { return { next: 5 } } }"); 72mustThrow ("var [a] = { [Symbol.iterator] () { return { get next() { throw new TypeError } } } }"); 73mustThrow ("var [a] = { [Symbol.iterator] () { return { next () { } } } }"); 74mustThrow ("var [a] = { [Symbol.iterator] () { return { next () { } } } }"); 75mustThrow ("var [a] = { [Symbol.iterator] () { return { next () { return { get value () { throw new TypeError }}}}}}"); 76mustThrow ("var [a] = { [Symbol.iterator] () { return { next () { return { get done () { throw new TypeError }}}}}}"); 77 78// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment 79 80// Basic variable assignment 81(function () { 82 var foo = ["one", "two", "three"]; 83 84 var [red, yellow, green] = foo; 85 assert (red === "one"); 86 assert (yellow === "two"); 87 assert (green === "three"); 88}) (); 89 90// Assignment separate from declaration 91(function () { 92 var a, b; 93 94 [a, b] = [1, 2]; 95 assert (a === 1); 96 assert (b === 2); 97}) (); 98 99// Default values 100(function () { 101 var a, b; 102 [a = 5, b = 7] = [1]; 103 104 assert (a === 1); 105 assert (b === 7); 106}) (); 107 108// Swapping variables 109(function () { 110 var a = 1; 111 var b = 3; 112 113 [a, b] = [b, a]; 114 assert (a === 3); 115 assert (b === 1); 116 117 var arr = [1,2,3]; 118 [arr[2], arr[1]] = [arr[1], arr[2]]; 119 assertArrayEqual (arr, [1, 3, 2]); 120}) (); 121 122// Parsing an array returned from a function 123(function () { 124 function f() { 125 return [1, 2]; 126 } 127 128 var a, b; 129 [a, b] = f(); 130 assert (a === 1); 131 assert (b === 2); 132}) (); 133 134// Ignoring some returned values 135(function () { 136 function f() { 137 return [1, 2, 3]; 138 } 139 140 var a, b; 141 [a, ,b] = f(); 142 assert (a === 1); 143 assert (b === 3); 144}) (); 145 146// Ignoring some returned values 147(function () { 148 var [a, ...b] = [1, 2, 3]; 149 assert (a === 1); 150 assertArrayEqual (b, [2, 3]); 151}) (); 152 153// Unpacking values from a regular expression match 154(function () { 155 function parseProtocol(url) { 156 var parsedURL = /^(\w+)\:\/\/([^\/]+)\/(.*)$/.exec(url); 157 if (!parsedURL) { 158 return false; 159 } 160 161 var [, protocol, fullhost, fullpath] = parsedURL; 162 return protocol; 163 } 164 165 assert (parseProtocol("https://developer.mozilla.org/en-US/Web/JavaScript") === "https"); 166}) (); 167 168// Test inner patterns I. 169(function () { 170 let [a, [b, [c = 4, d = 5]], [e] = [6]] = [1, [2, [3,undefined]]]; 171 172 assert (a === 1); 173 assert (b === 2); 174 assert (c === 3); 175 assert (d === 5); 176 assert (e === 6); 177}) (); 178 179// Test inner patterns II. 180(function () { 181 var o = {}; 182 [a, b, c, o.a = 4, o.b, o.c = 3] = ["1", "2", "3", undefined, "8", "6"]; 183 184 assert (a === "1"); 185 assert (b === "2"); 186 assert (c === "3"); 187 assert (o.a === 4); 188 assert (o.b === "8"); 189 assert (o.c === "6"); 190}) (); 191 192// Test rest element I. 193(function () { 194 var o = {}; 195 [...o.a] = ["1", "2", "3"]; 196 197 assertArrayEqual (o.a, ["1", "2", "3"]); 198}) (); 199 200// Test rest element II. 201(function () { 202 [...[a,b,c]] = ["1", "2", "3"]; 203 204 assert (a === "1"); 205 assert (b === "2"); 206 assert (c === "3"); 207}) (); 208 209// Test inner object pattern I. 210(function () { 211 [{f : a, g : b}, , , ...[c, d, e]] = [{ f : "1", g : "2"}, 3, 4, 5, 6, 7]; 212 213 assert (a === "1"); 214 assert (b === "2"); 215 assert (c === 5); 216 assert (d === 6); 217 assert (e === 7); 218}) (); 219 220// Multiple declaration 221(function () { 222 var [a] = [1], [b] = [2]; 223 224 assert (a === 1); 225 assert (b === 2); 226}) (); 227 228// Force the creation of lexical environment I. 229(function () { 230 const [a] = [1]; 231 eval(); 232 233 assert (a === 1); 234}) (); 235 236// Force the creation of lexical environment II. 237(function () { 238 let [a] = [1]; 239 eval(); 240 241 assert (a === 1); 242}) (); 243 244// Check the parsing of AssignmentElement 245(function () { 246 var a = 6; 247 [((a))] = [7]; 248 assert (a === 7); 249}) (); 250 251// Test iterator closing 252function __createIterableObject (arr, methods) { 253 methods = methods || {}; 254 if (typeof Symbol !== 'function' || !Symbol.iterator) { 255 return {}; 256 } 257 arr.length++; 258 var iterator = { 259 next: function() { 260 return { value: arr.shift(), done: arr.length <= 0 }; 261 }, 262 'return': methods['return'], 263 'throw': methods['throw'] 264 }; 265 var iterable = {}; 266 iterable[Symbol.iterator] = function () { return iterator; }; 267 return iterable; 268}; 269 270(function () { 271 var closed = false; 272 var iter = __createIterableObject([1, 2, 3], { 273 'return': function() { closed = true; return {}; } 274 }); 275 var [a, b] = iter; 276 assert (closed === true); 277 assert (a === 1); 278 assert (b === 2); 279}) (); 280 281mustThrow ("var iter = __createIterableObject([], " 282 + "{ get 'return'() { throw new TypeError() }});" 283 + "var [a] = iter"); 284 285mustThrow ("var iter = __createIterableObject([], " 286 + "{ 'return': 5 });" 287 + "var [a] = iter"); 288 289mustThrow ("var iter = __createIterableObject([], " 290 + "{ 'return': function() { return 5; }});" 291 + "var [a] = iter"); 292 293mustThrow ("try { throw 5 } catch (e) {" 294 + "var iter = __createIterableObject([], " 295 + "{ get 'return'() { throw new TypeError() }});" 296 + "var [a] = iter }"); 297 298mustThrow ("try { throw 5 } catch (e) {" 299 + "var iter = __createIterableObject([], " 300 + "{ 'return': 5 });" 301 + "var [a] = iter }"); 302 303mustThrow ("try { throw 5 } catch (e) {" 304 + "var iter = __createIterableObject([], " 305 + "{ 'return': function() { return 5; }});" 306 + "var [a] = iter }"); 307 308try { 309 eval ("var a = 0; 1 + [a] = [1]"); 310 assert (false); 311} catch (e) { 312 assert (e instanceof ReferenceError); 313} 314