| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481 |
- //-------------------------------------------------------------------------------------------------------
- // Copyright (C) Microsoft. All rights reserved.
- // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
- //-------------------------------------------------------------------------------------------------------
- WScript.LoadScriptFile("..\\UnitTestFramework\\UnitTestFramework.js");
- var tests = [
- {
- name: "Basic object destructuring syntax",
- body: function () {
- assert.doesNotThrow(function () { eval("var {} = {};"); }, "var object declaration pattern with no identifier is valid syntax");
- assert.doesNotThrow(function () { eval("let {} = {};"); }, "let object declaration pattern with no identifier is valid syntax");
- assert.doesNotThrow(function () { eval("const {} = {};"); }, "const object declaration pattern with no identifier is valid syntax");
- assert.doesNotThrow(function () { eval("({} = {});"); }, "Object pattern as an expression with no identifier is valid syntax");
- assert.doesNotThrow(function () { eval("var {x:y} = {};"); }, "var object declaration pattern with a single member is valid syntax");
- assert.doesNotThrow(function () { eval("let {x:y} = {};"); }, "let object declaration pattern with a single member is valid syntax");
- assert.doesNotThrow(function () { eval("const {x:y} = {};"); }, "const object declaration pattern with a single member is valid syntax");
- assert.doesNotThrow(function () { eval("({x:y} = {});"); }, "Object pattern as an expression with a single member is valid syntax");
- assert.doesNotThrow(function () { eval("var {x} = {};"); }, "var object declaration pattern with a single member as shorthand is valid syntax");
- assert.doesNotThrow(function () { eval("({x:y} = {});"); }, "Object pattern as an expression with a single member as shorthand is valid syntax");
- assert.doesNotThrow(function () { eval("var {x} = {}, {y} = {};"); }, "Multiple object pattern in a single var declaration is valid syntax");
- }
- },
- {
- name: "Basic object destructuring invalid syntax",
- body: function () {
- assert.throws(function () { eval("var {};"); }, SyntaxError, "var empty object declaration pattern without an initializer is not valid syntax", "Destructuring declarations must have an initializer");
- assert.throws(function () { eval("let {};"); }, SyntaxError, "let empty object declaration pattern without an initializer is not valid syntax", "Destructuring declarations must have an initializer");
- assert.throws(function () { eval("const {};"); }, SyntaxError, "const empty object declaration pattern without an initializer is not valid syntax", "Destructuring declarations must have an initializer");
- assert.throws(function () { eval("var {a};"); }, SyntaxError, "var object declaration pattern without an initializer is not valid syntax", "Destructuring declarations must have an initializer");
- assert.throws(function () { eval("let {a};"); }, SyntaxError, "let object declaration pattern without an initializer is not valid syntax", "Destructuring declarations must have an initializer");
- assert.throws(function () { eval("const {a};"); }, SyntaxError, "const object declaration pattern without an initializer is not valid syntax", "Destructuring declarations must have an initializer");
- assert.throws(function () { eval("var {,} = {}"); }, SyntaxError, "Object declaration pattern without an identifier is not valid syntax", "Expected identifier, string or number");
- assert.throws(function () { eval("({,} = {});"); }, SyntaxError, "Object expression pattern without an identifier is not valid syntax", "Expected identifier, string or number");
- assert.throws(function () { eval("var {x:y--} = {};"); }, SyntaxError, "Object declaration pattern with an operator -- is not valid syntax", "Unexpected operator in destructuring expression");
- assert.throws(function () { eval("var {x:y+1} = {};"); }, SyntaxError, "Object declaration pattern with an operator + is not valid syntax", "Unexpected operator in destructuring expression");
- assert.throws(function () { eval("var y; ({x:y--} = {});"); }, SyntaxError, "Object expression pattern with an operator -- is not valid syntax", "Unexpected operator in destructuring expression");
- assert.throws(function () { eval("var y; ({x:y+1} = {});"); }, SyntaxError, "Object expression pattern with an operator + is not valid syntax", "Unexpected operator in destructuring expression");
- }
- },
- {
- name: "Object destructuring syntax with initializer",
- body: function () {
- assert.doesNotThrow(function () { eval("var {x:x = 20} = {};"); }, "var object declaration pattern with default is valid syntax");
- assert.doesNotThrow(function () { eval("let {x:x = 20} = {};"); }, "let object declaration pattern with default is valid syntax");
- assert.doesNotThrow(function () { eval("const {x:x = 20} = {};"); }, "const object declaration pattern with default is valid syntax");
- assert.doesNotThrow(function () { eval("var x; ({x:x = 20} = {});"); }, "Object declaration pattern with default is valid syntax");
- assert.doesNotThrow(function () { eval("var {x, x1:y = 20} = {};"); }, "Object declaration pattern with default other than first is valid syntax");
- assert.doesNotThrow(function () { eval("var {x:z = 1, x1:y = 20} = {};"); }, "Object declaration pattern with defaults on more than one is valid syntax");
- assert.doesNotThrow(function () { eval("var x, y; ({x, x1:y = 20} = {});"); }, "Object expression pattern with default other than first is valid syntax");
- assert.doesNotThrow(function () { eval("var z, y; ({x:z = 1, x1:y = 20} = {});"); }, "Object expression pattern with defaults on more than one is valid syntax");
- }
- },
- {
- name: "Object destructuring syntax with identifier reference",
- body: function () {
- assert.throws(function () { eval("function foo() { return {}; }; let {x:foo()} = {};"); }, SyntaxError, "Object declaration pattern with a call expression is not valid syntax", "Let/Const redeclaration");
- assert.throws(function () { eval("function foo() { return {}; }; ({x:foo()} = {});"); }, SyntaxError, "Object expression pattern with a call expression is not valid syntax", "Invalid destructuring assignment target");
- assert.throws(function () { eval("function foo() { return {}; }; var {x:foo().x} = {};"); }, SyntaxError, "Object declaration pattern with property reference on call is not valid syntax", "Syntax error");
- assert.doesNotThrow(function () { eval("var a = {}; ({x:a.x} = {});"); }, "Object expresion pattern with a property reference is valid syntax");
- assert.doesNotThrow(function () { eval("let a = {}; ({x:a['x']} = {});"); }, "Object expression pattern with a property reference as index is valid syntax");
- assert.doesNotThrow(function () { eval("function foo() { return {}; }; ({x:foo().x} = {});"); }, "Object declaration pattern with property reference on call is valid syntax");
- assert.doesNotThrow(function () { eval("function foo() { return {}; }; ({x:foo()['x']} = {});"); }, "Object declaration pattern with property reference as index on call is valid syntax");
- assert.throws(function () { eval("class foo { method() { let {x:super()} = {}; } }"); },SyntaxError, "Object declaration pattern with a super call is not valid syntax", "The use of a keyword for an identifier is invalid");
- assert.throws(function () { eval("class foo { method() { ({x:super()} = {}); } }"); }, SyntaxError, "Object expression pattern with a super call is not valid syntax", "Invalid use of the 'super' keyword");
- assert.throws(function () { eval("class foo { method() { var {x:super.x} = {}; } }"); }, SyntaxError, "Object declaration pattern with a property reference on super is not valid syntax", "The use of a keyword for an identifier is invalid");
- assert.doesNotThrow(function () { eval("class foo { method() { ({x:super.x} = {}); } }"); }, "Object expression pattern with a property reference on super is valid syntax");
- assert.doesNotThrow(function () { eval("class foo { method() { ({x:super['x']} = {}); } }"); }, "Object expression pattern with a property reference as an index on super is valid syntax");
- assert.doesNotThrow(function () { eval("var a = [1], i = 0; ({x:a[i++]} = {});"); }, "Object Destructuring pattern assignment operators inside an identifier reference is valid syntax");
- }
- },
- {
- name: "Object destructuring syntax with computed property name",
- body: function () {
- assert.doesNotThrow(function () { eval("var zee = 'x'; var {[zee]:x1} = {}"); }, "Object declaration pattern with computed property name is valid syntax");
- assert.doesNotThrow(function () { eval("var zee = 'x'; var x1; ({[zee]:x1} = {})"); }, "Object expression pattern with computed property name is valid syntax");
- assert.doesNotThrow(function () { eval("var zee = 'x'; var {[zee + 'foo']:x1} = {}"); }, "Object declaration pattern with computed property name with add operator is valid syntax");
- assert.doesNotThrow(function () { eval("var zee = 'x'; var x1; ({[zee +'foo']:x1} = {})"); }, "Object expression pattern with computed property name with add operator is valid syntax");
- }
- },
- {
- name: "Destructing syntax - having rest element as pattern",
- body: function () {
- assert.doesNotThrow(function () { eval("let [...[a]] = [[]];"); }, "Under declaration, having rest element as array pattern is valid syntax");
- assert.doesNotThrow(function () { eval("let a; [...[a]] = [[]];"); }, "Under expression, having rest element as array pattern is valid syntax");
- assert.doesNotThrow(function () { eval("let [...{a}] = [{}];"); }, "Under declaration, having rest element as object pattern is valid syntax");
- assert.doesNotThrow(function () { eval("let a; [...{a}] = [{}];"); }, "Under expression, having rest element as object pattern is valid syntax");
- assert.doesNotThrow(function () { eval("let a; [...[a = 1]] = [[]];"); }, "Under expression, having rest element as array pattern has initializer is valid syntax");
- assert.doesNotThrow(function () { eval("let a; [...{a:a = 1}] = [{}];"); }, "Under expression, having rest element as object pattern has initializer is valid syntax");
- assert.doesNotThrow(function () { eval("let obj = {x:1}; [...obj.x] = [10];"); }, "Rest element being property reference is valid syntax");
- assert.doesNotThrow(function () { eval("let obj = {x:1}; [...obj['x']] = [10];"); }, "Rest element being property reference as index is valid syntax");
- assert.doesNotThrow(function () { eval("function foo() { return {x:1}; }; [...foo().x] = [10];"); }, "Rest element being property reference on call expression is valid syntax");
- assert.doesNotThrow(function () { eval("function foo() { return {x:1}; }; [...foo()['x']] = [10];"); }, "Rest element being property reference as index on call expression is valid syntax");
- assert.doesNotThrow(function () { eval("let [...[...[...a]]] = [[[]]];"); }, "Nesting rest element inside another rest element is valid syntax");
- assert.throws(function () { eval("let [...[a+1] = [{}];"); }, SyntaxError, "Under declaration, having rest element as pattern which has operator is not valid syntax", "Unexpected operator in destructuring expression");
- assert.throws(function () { eval("let a; [...1+a] = [{}];"); }, SyntaxError, "Under declaration, rest element has operator is not valid syntax", "Invalid destructuring assignment target");
- assert.throws(function () { eval("let a; [...[a+1] = [{}];"); }, SyntaxError, "Under expression, having rest element as pattern which has operator is not valid syntax", "Unexpected operator in destructuring expression");
- assert.throws(function () { eval("function foo() { return {x:1}; }; [...foo()] = [10];"); }, SyntaxError, "Under expression, having rest element as call expression is not valid syntax", "Invalid destructuring assignment target");
- assert.throws(function () { eval("let [...[a] = []] = [[]];"); }, SyntaxError, "Under declaration - rest as array pattern cannot have initializer", "The rest parameter cannot have a default initializer.");
- assert.throws(function () { eval("let [...{x} = {}] = [{}];"); }, SyntaxError, "Under declaration - rest as object pattern cannot have initializer", "The rest parameter cannot have a default initializer.");
- assert.throws(function () { eval("let a; ([...[a] = []] = [[]]);"); }, SyntaxError, "Under assignment - rest as array pattern cannot have initializer", "The rest parameter cannot have a default initializer.");
- assert.throws(function () { eval("let x; ([...{x} = {}] = [{}]);"); }, SyntaxError, "Under assignment - rest as object pattern cannot have initializer", "The rest parameter cannot have a default initializer.");
- }
- },
- {
- name: "Object destructuring syntax with repeated identifier",
- body: function () {
- assert.doesNotThrow(function () { eval("var {a:a, a:a} = {};"); }, "var declaration pattern with a repeated identifier is valid syntax");
- assert.throws(function () { eval("let {a:a, a:a} = {};"); }, SyntaxError, "let declaration pattern with a repeated identifier is not valid syntax", "Let/Const redeclaration");
- assert.throws(function () { eval("const {a:a, a:a} = {};"); }, SyntaxError, "const declaration pattern with a repeated identifier is not valid syntax", "Let/Const redeclaration");
- assert.throws(function () { eval("let {b, b} = {};"); }, SyntaxError, "let declaration pattern with a repeated identifier as shorthand is not valid syntax", "Let/Const redeclaration");
- assert.throws(function () { eval("const {b, b} = {};"); }, SyntaxError, "const declaration pattern with a repeated identifier as shorthand is not valid syntax", "Let/Const redeclaration");
- assert.throws(function () { eval("let {x:c, y:c} = {};"); }, SyntaxError, "let declaration pattern with a repeated identifier but different matching pattern is not valid syntax", "Let/Const redeclaration");
- assert.throws(function () { eval("const {x:c, y:c} = {};"); }, SyntaxError, "const declaration pattern with a repeated identifier but different matching pattern is not valid syntax", "Let/Const redeclaration");
- assert.doesNotThrow(function () { eval("let a; ({a:a, a:a} = {});"); }, "Object expression pattern with a repeated identifier is valid syntax");
- }
- },
- {
- name: "Object destructuring syntax on misc expressions",
- body: function () {
- assert.doesNotThrow(function () { eval("let a; ({a:((((a1))))} = {a:20})"); }, "Object expression pattern with parens is valid syntax");
- assert.doesNotThrow(function () { eval("let a; ({a:((((a1 = 31))))} = {})"); }, "Object expression pattern with parens and defaults is valid syntax");
- assert.doesNotThrow(function () { eval("let a, r1; ({a:a1 = r1} = {})"); }, "Object expression pattern with defaults as reference is valid syntax");
- assert.doesNotThrow(function () { eval("let a, r1; ({a:((((a1 = r1))))} = {})"); }, "Object expression pattern with defaults as reference under parens is valid syntax");
- assert.doesNotThrow(function () { eval("let a, r1; ({a:a1 = r1 = 44} = {})"); }, "Object expression pattern with chained assignments as defaults is valid syntax");
- assert.doesNotThrow(function () { eval("let a, r1; ({a:(a1 = r1 = 44)} = {})"); }, "Object expression pattern with chained assignments as defaults under paren is valid syntax");
- assert.throws(function () { eval("let a, r1; ({a:(a1 = r1) = 44} = {})"); }, SyntaxError, "Object expression pattern with chained assignments but paren in between is not valid syntax", "Unexpected operator in destructuring expression");
- assert.doesNotThrow(function () { eval("var a; `${({a} = {})}`"); }, "Object expression pattern inside a string template is valid syntax");
- assert.throws(function () { eval("for (let {x} = {} of []) {}"); }, SyntaxError, "for.of has declaration pattern with initializer is not valid syntax", "for-of loop head declarations cannot have an initializer");
- assert.throws(function () { eval("for (let {x} = {} in []) {}"); }, SyntaxError, "for.in has declaration pattern with initializer is not valid syntax", "for-in loop head declarations cannot have an initializer");
- assert.throws(function () { eval("for (var [x] = [] of []) {}"); }, SyntaxError, "for.of has var declaration pattern with initializer is not valid syntax", "for-of loop head declarations cannot have an initializer");
- assert.throws(function () { eval("function foo() {for (let {x} = {} of []) {}; }; foo();"); }, SyntaxError, "Inside function - for.of has declaration pattern with initializer is not valid syntax", "for-of loop head declarations cannot have an initializer");
- assert.doesNotThrow(function () { eval("var a; [a = class aClass {}] = []"); }, "Expression pattern has class as initializer is valid syntax");
- assert.doesNotThrow(function () { eval("var a; for ({x:x = class aClass {}} of []) {}"); }, "for.of's expression pattern has class as initializer is valid syntax");
- assert.doesNotThrow(function () { eval("var {x:[...y]} = {x:[1]}"); }, "rest element nesting under object pattern is valid syntax");
- assert.throws(function () { eval("let {foo() {}} = {};"); }, SyntaxError, "Invalid object pattern as it has the function short-hand instead of binding identifier", "Invalid destructuring assignment target");
- assert.throws(function () { eval("let {get foo() {}} = {};"); }, SyntaxError, "Invalid object pattern as it has the get function short-hand instead of binding identifier", "Invalid destructuring assignment target");
- assert.throws(function () { eval("let {set foo() {}} = {};"); }, SyntaxError, "Invalid object pattern as it has the set function short-hand instead of binding identifier", "Invalid destructuring assignment target");
- assert.throws(function () { eval("let {get ['foo']() {}} = {};"); }, SyntaxError, "Invalid object pattern as it has the get function name as computed property instead of binding identifier", "Invalid destructuring assignment target");
- assert.throws(function () { eval("let {set ['foo'](a) {}} = {};"); }, SyntaxError, "Invalid object pattern as it has the set function name as computed property instead of binding identifier", "Invalid destructuring assignment target");
- assert.throws(function () { eval("({foo() {}} = {});"); }, SyntaxError, "Invalid object expression pattern as it has the function short-hand instead of binding identifier", "Invalid destructuring assignment target");
- assert.throws(function () { eval("({get foo() {}} = {});"); }, SyntaxError, "Invalid object expression pattern as it has the get function short-hand instead of binding identifier", "Invalid destructuring assignment target");
- assert.throws(function () { eval("({set foo(a) {}} = {});"); }, SyntaxError, "Invalid object expression pattern as it has the set function short-hand instead of binding identifier", "Invalid destructuring assignment target");
- assert.throws(function () { eval("({get ['foo']() {}} = {});"); }, SyntaxError, "Invalid object expression pattern as it has the get function name as computed property instead of binding identifier", "Invalid destructuring assignment target");
- assert.throws(function () { eval("({set ['foo'](a) {}} = {});"); }, SyntaxError, "Invalid object expression pattern as it has the set function name as computed property instead of binding identifier", "Invalid destructuring assignment target");
- assert.throws(function () { eval("for(var [z] = function ([a]) { } in []) {}"); }, SyntaxError, "Initializer as function expression is not valid syntax", "for-in loop head declarations cannot have an initializer");
- }
- },
- {
- name: "Object destructuring with `get` and `set` identifiers",
- body: function () {
- var { get } = { get: 1 };
- let { set } = { set: 2 };
- assert.areEqual(1, get, "`get` is a valid object destructuring name");
- assert.areEqual(2, set, "`set` is a valid object destructuring name");
- assert.throws(function () { eval("var { get foo() { } } = { get: 1 };"); }, SyntaxError, "getter accessor is not a valid object destructuring name", "Invalid destructuring assignment target");
- assert.throws(function () { eval("var { set bar(x) { } } = { set: 2 };"); }, SyntaxError, "setter accessor is not a valid object destructuring name", "Invalid destructuring assignment target");
- const { get: x } = { get: 3 };
- var { set: y } = { set: 4 };
- assert.areEqual(3, x, "`get` is a valid object destructuring name mapping");
- assert.areEqual(4, y, "`set` is a valid object destructuring name mapping");
- }
- },
- {
- name: "Object destructuring with shorthand initializer",
- body: function () {
- assert.doesNotThrow(function () { eval("({x = 1} = {});"); }, "Object pattern has shorthand with initializer is a valid syntax");
- assert.doesNotThrow(function () { eval("({x, y = 1, z = 2} = {});"); }, "Object pattern has multiple shorthands with initializer is a valid syntax");
- assert.throws(function () { eval("var a = 1; ({x, y = 1, z = 2} = {a = 2});"); }, SyntaxError,"Initializer is allowed on shorthand of object pattern but not on object literal", "Expected ':'");
- assert.throws(function () { eval("var a = 1; ({x, y = {a = 1}} = {});"); }, SyntaxError,"Object literal is within object pattern but has shorthand initializer is not valid syntax", "Expected ':'");
- assert.doesNotThrow(function () { eval("var a = 1; ({x = {a = 1} = {}} = {});"); }, "Chained object patterns have shorthand initializers is a valid syntax");
- assert.doesNotThrow(function () { eval("var a = 1; var {x = {a = 1} = {}} = {};"); }, "Chained object declaration pattern have shorthand initializers is a valid syntax");
- assert.doesNotThrow(function () { eval("[{x : [{y:{z = 1}}] }] = [{x:[{y:{}}]}];"); }, "Mixed nesting pattern has shorthand initializer is a valid syntax");
- assert.doesNotThrow(function () { eval("[{x : [{y:{z = 1}, z1 = 2}] }, {x2 = 3}, {x3 : {y3:[{z3 = 4}]}} ] = [{x:[{y:{}}]}, {}, {x3:{y3:[{}]}}];"); },
- "Mixed object patterns both on nested and on same level have initializers on shorthand and is a valid syntax");
- assert.doesNotThrow(function () { eval("var [{x : [{y:{z = 1}, z1 = 2}] }, {x2 = 3}, {x3 : {y3:[{z3 = 4}]}} ] = [{x:[{y:{}}]}, {}, {x3:{y3:[{}]}}];"); },
- "Declaration - mixed object patterns both on nested and on same level have initializers on shorthand and is a valid syntax");
- assert.doesNotThrow(function () { eval("[...{x = 1}] = [{}]"); }, "Object pattern following rest has shorthand initializer is a valid syntax");
- {
- let a1 = 1;
- ({x:{a1 = 2}} = {x:{}});
- assert.areEqual(a1, 2);
- }
-
- assert.throws(function () { eval("var a = 1; switch(true) { case {a = 1} : break; };"); }, SyntaxError, "Object literal on case has initializer is not valid syntax", "Expected ':'");
-
- }
- },
- {
- name: "Object destructuring basic functionality",
- body: function () {
- {
- var x3, x4;
- let {x:x1} = {x:20};
- assert.areEqual(x1, 20, "Object declaration pattern should match the pattern and initializes that variable correctly");
- let {x2} = {x2:20};
- assert.areEqual(x2, 20, "Object declaration pattern (shorthand) should match the pattern and initializes that variable correctly");
- ({x:x3} = {x:20});
- assert.areEqual(x3, 20, "Object expression pattern should match the pattern and initializes that variable correctly");
- ({x4} = {x4:20});
- assert.areEqual(x4, 20, "Object expression pattern (shorthand) should match the pattern and initializes that variable correctly even under a paren");
- }
- {
- let {x:x1} = {};
- assert.areEqual(x1, undefined, "Object declaration pattern find no match pattern on rhs and initialize to undefined");
- let {x2} = {zee:20};
- assert.areEqual(x2, undefined, "Object declaration pattern does not match pattern on rhs and initialize to undefined");
- let x3, x4;
- ({x:x3} = {});
- assert.areEqual(x3, undefined, "Object expression pattern find no match pattern on rhs and initialize to undefined");
- ({x4} = {foobar:20});
- assert.areEqual(x4, undefined, "Object expression pattern does not match pattern on rhs and initialize to undefined");
- }
- {
- let {x:x1, y: y1, z: z1} = {x:11, y:22, z:33, foo:44};
- assert.areEqual(x1, 11, "Object declaration pattern with multiple members should match the first member correctly");
- assert.areEqual(y1, 22, "Object declaration pattern with multiple members should match the second member correctly");
- assert.areEqual(z1, 33, "Object declaration pattern with multiple members should match the third member correctly");
- let x2, y2, z2;
- ({x:x2, y: y2, z: z2} = {x:11, bar:44, y:22, z:33});
- assert.areEqual(x2, 11, "Object expression pattern with multiple members should match the first member correctly");
- assert.areEqual(y2, 22, "Object expression pattern with multiple members should match the second member correctly");
- assert.areEqual(z2, 33, "Object expression pattern with multiple members should match the third member correctly");
- }
- {
- var y1, x1;
- var z = {x:x1} = {y:y1} = {x:10, y:20};
- assert.areEqual(x1, 10, "Object declaration pattern with chained assignments should match first member to rhs correctly");
- assert.areEqual(y1, 20, "Object expression pattern with chained assignments should match second member to rhs correctly");
- }
- }
- },
- {
- name: "Object destructuring functionality with initializer",
- body : function () {
- let {x:a = 1} = {x:undefined};
- assert.areEqual(a, 1, "Object declaration pattern should match the pattern but it is evaluated to undefined so assign default correctly");
- let {x:a1 = 1} = {x:null};
- assert.areEqual(a1, null, "Object declaration pattern should match the pattern and assigned null correctly");
- let {x:x1 = 1, y:y1 = 2, z: z1 = 3} = {};
- assert.areEqual(x1, 1, "Object declaration pattern - first member initialized with default when no match found on rhs");
- assert.areEqual(y1, 2, "Object declaration pattern - second member initialized with default when no match found on rhs");
- assert.areEqual(z1, 3, "Object declaration pattern - third member initialized with default when no match found on rhs");
- let x2, y2, z2;
- ({x:x2 = 1, y:y2 = 2, z:z2 = 3} = {z:11});
- assert.areEqual(x2, 1, "Object expression pattern - first member initialized with default when no match found on rhs");
- assert.areEqual(y2, 2, "Object expression pattern - second member initialized with default when no match found on rhs");
- assert.areEqual(z2, 11, "Object expression pattern - third member has pattern match on rhs and should have assigned correctly");
- let { x: { y:z } = { y:21 } } = {};
- assert.areEqual(z, 21, "Object declaration pattern has default on nested");
- let {
- x:{
- y:{
- z:{
- k:k2 = 31
- } = { k:21 }
- } = { z:{ k:20 } }
- } = { y: { z:{} } }
- } = { x:{ y:{ z:{} } } };
- assert.areEqual(k2, 31, "Object declaration pattern has defaults on different level and got the inner most default");
- ({
- x:{
- y:{
- z:{
- k:k2 = 31
- } = {k:21}
- } = {z:{k:20}}
- } = {y:{z:{}}}
- } = {x:{y:{z:undefined}}});
- assert.areEqual(k2, 21,"Object expression pattern has default on different level but got the rhs");
- }
- },
- {
- name: "Object destructuring functionality with non-name pattern",
- body : function () {
- let {1:x1, 0:y1} = [11, 22];
- let {0:x2} = {"0":33};
- let {function:x3} = {function:44};
- assert.areEqual(x1, 22, "Object declaration pattern should match the second index on rhs array");
- assert.areEqual(y1, 11, "Object declaration pattern should match the first index on rhs array");
- assert.areEqual(x2, 33, "Object declaration pattern should match '0' on rhs");
- assert.areEqual(x3, 44, "Object declaration pattern should match the name even though it is a keyword");
- }
- },
- {
- name: "Object destructuring functionality with computed property",
- body : function () {
- {
- let key = 'x', x2;
- let {[key]:x1} = {x:20};
- assert.areEqual(x1, 20, "Object declaration pattern should match the computed property name as a pattern");
- ({[key]:x2} = {x:20});
- assert.areEqual(x2, 20, "Object expression pattern should match the computed property name as a pattern");
- ({[`abc${"def"}`]:x2} = {abcdef:30});
- assert.areEqual(x2, 30, "Object expression pattern should match the the complex computed property name as a pattern");
- }
- {
- let [i,j] = [0,0];
- function getName() {
- if (i++ == 0) return 'x';
- else return 'y'
- }
- function getData() {
- assert.areEqual(i, 0, "RHS object should be initialized before");
- if (j++ == 0) return 'this is x';
- else return 'this is y';
- }
- let {[getName()]:x1, [getName()]:y1} = {x:getData(), y:getData()};
- assert.areEqual(x1, 'this is x', "Object declaration pattern depicting initializing order should match first pattern evaluated on runtime");
- assert.areEqual(y1, 'this is y', "Object declaration pattern depicting initializing order should match second pattern evaluated on runtime");
- }
- }
- },
- {
- name: "Object destructuring functionality with property reference",
- body : function () {
- let a = {};
- ({x:a.x} = {x:10});
- assert.areEqual(10, a.x, "Object expression pattern should assign value on property reference on object correctly");
- ({x:a['x']} = {x:20});
- assert.areEqual(20, a["x"], "Object expression pattern should assign value on property reference as index on object correctly");
- var obj = { x: 10, y: 20 };
- function foo() { return obj };
- ({x:foo().x, y:foo().y} = {x:20, y:30});
- assert.areEqual(20, obj.x, "Object expression pattern should assign value on first property reference on a call expression correctly");
- assert.areEqual(30, obj.y, "Object expression pattern should assign value on second property reference on a call expression correctly");
- (((((({x:foo().x, y:foo().y} = {x:201, y:301}))))));
- assert.areEqual(201, obj.x, "Object expression pattern (under deep parens) should assign value on first property reference on a call expression correctly");
- assert.areEqual(301, obj.y, "Object expression pattern (under deep parens) should assign value on second property reference on a call expression correctly");
- }
- },
- {
- name: "Destructing functionality - rest element as pattern",
- body : function () {
- let [...[a]] = [1, 2, 3];
- assert.areEqual(a, 1, "Having rest element as array pattern and the identifier is initialized with first value");
- let [...{1:x1}] = [1, 2, 3];
- assert.areEqual(x1, 2, "Having rest element as object pattern and the identifier is initialized with second value");
- let [...[,...[[x2]]]] = [[1, 2], [3, 4], 5];
- assert.areEqual(x2, 3, "Rest element nesting another rest element and initialized with correct value");
- }
- },
- {
- name: "Object destructuring functionality with mixed array and object pattern",
- body : function () {
- let {first:f1, second : [,{y}]} = {first:'first', second:[{y:20, z:30}, {y:21, z:31}, {y:22, z:32}]};
- assert.areEqual(f1, 'first', "Destructing declaration pattern should match first pattern on rhs");
- assert.areEqual(y, 21, "Destructing declaration pattern should match second but nested array pattern on rhs");
- let metadata = {
- title: "Foobar",
- copies: [
- {
- locale: "en",
- title: "first"
- },
- {
- locale: "de",
- title: "second"
- },
- {
- locale: "ps",
- title: "third"
- },
- ],
- url: "http://foobar.com"
- };
- let { title: englishTitle, copies: [{locale : myLocale}] } = metadata;
- assert.areEqual(englishTitle, 'Foobar', "Destructing declaration pattern should match first pattern on rhs");
- assert.areEqual(myLocale, 'en', "Destructing declaration pattern should match second pattern on rhs");
- ({ copies: [,{locale : myLocale}] } = metadata);
- assert.areEqual(myLocale, 'de', "Destructing expression pattern should skip first array item and match second item on rhs");
- let [{x}, {z}] = [{x:1, z:20}, {x:2, z:30}, {x:3,z:40}];
- assert.areEqual(x, 1, "Object under array declaration pattern should match the first pattern");
- assert.areEqual(z, 30, "Object under array declaration pattern should match the second pattern");
- [{x:x}, , {z:z}] = [{x:11, z:201}, {x:21, z:301}, {x:31,z:401}];
- assert.areEqual(x, 11, "Object under array expression pattern should match the first pattern");
- assert.areEqual(z, 401, "Object under array expression pattern should match the third pattern");
- }
- },
- {
- name: "Object destructuring functionality with for/while",
- body : function () {
- let i = 0, data = [20, 30];
- for ( let {x:item} of [{x:20}, {x:30}]) {
- assert.areEqual(item, data[i++], "Object declaration pattern under for..of should match pattern correctly");
- }
- function data2() {
- return {x:[{y:[20]}, {y:[30]}]};
- }
- i = 0;
- for ({y:[item]} of data2().x) {
- assert.areEqual(item, data[i++], "Object expression pattern under for..of should match pattern correctly");
- }
- i = 0; data = [10, 12, 14, 16, 18];
- for (let {x, y} = {x:10, y:20}; x<y; {x:x} = {x:x+2}) {
- assert.areEqual(x, data[i++], "Object declaration pattern under native..for should match pattern correctly");
- }
- let y2 = 20;
- i = 0; data = [18, 16, 14, 12, 10];
- while ({y:y2} = {y:y2-2}) {
- assert.areEqual(y2, data[i++], "Object expression pattern under while should match pattern correctly");
- if (y2 == 10) {
- break;
- }
- }
- }
- }
- ];
- testRunner.runTests(tests, { verbose: WScript.Arguments[0] != "summary" });
|