| let assert = (e) => { |
| if (!e) |
| throw Error("Bad assertion!"); |
| } |
| |
| let assertPropDescriptor = (restObj, prop) => { |
| let desc = Object.getOwnPropertyDescriptor(restObj, prop); |
| assert(desc.enumerable); |
| assert(desc.writable); |
| assert(desc.configurable); |
| } |
| |
| // Base Case |
| (() => { |
| let obj = {x: 1, y: 2, a: 5, b: 3} |
| |
| let {a, b, ...rest} = obj; |
| |
| assert(a === 5); |
| assert(b === 3); |
| |
| assert(rest.x === 1); |
| assert(rest.y === 2); |
| |
| assertPropDescriptor(rest, 'x'); |
| assertPropDescriptor(rest, 'y'); |
| })(); |
| |
| // Empty Object |
| (() => { |
| let obj = {} |
| |
| let {a, b, ...rest} = obj; |
| |
| assert(a === undefined); |
| assert(b === undefined); |
| |
| assert(typeof rest === "object"); |
| })(); |
| |
| // Number case |
| (() => { |
| let obj = 3; |
| |
| let {...rest} = obj; |
| |
| assert(typeof rest === "object"); |
| })(); |
| |
| // String case |
| (() => { |
| let obj = "foo"; |
| |
| let {...rest} = obj; |
| |
| assert(typeof rest === "object"); |
| })(); |
| |
| // Symbol case |
| (() => { |
| let obj = Symbol("foo"); |
| |
| let {...rest} = obj; |
| |
| assert(typeof rest === "object"); |
| })(); |
| |
| // null case |
| (() => { |
| let obj = null; |
| |
| try { |
| let {...rest} = obj; |
| assert(false); |
| } catch (e) { |
| assert(e.message == "Right side of assignment cannot be destructured"); |
| } |
| |
| })(); |
| |
| // undefined case |
| (() => { |
| let obj = undefined; |
| |
| try { |
| let {...rest} = obj; |
| assert(false); |
| } catch (e) { |
| assert(e.message == "Right side of assignment cannot be destructured"); |
| } |
| |
| })(); |
| |
| // getter case |
| (() => { |
| let obj = {a: 3, b: 4}; |
| Object.defineProperty(obj, "x", { get: () => 3, enumerable: true }); |
| |
| let {a, b, ...rest} = obj; |
| |
| assert(a === 3); |
| assert(b === 4); |
| |
| assert(rest.x === 3); |
| assertPropDescriptor(rest, 'x'); |
| })(); |
| |
| // Skip non-enumerable case |
| (() => { |
| let obj = {a: 3, b: 4}; |
| Object.defineProperty(obj, "x", { value: 4, enumerable: false }); |
| |
| let {...rest} = obj; |
| |
| assert(rest.a === 3); |
| assert(rest.b === 4); |
| assert(rest.x === undefined); |
| })(); |
| |
| // Don't copy descriptor case |
| (() => { |
| let obj = {}; |
| Object.defineProperty(obj, "a", { value: 3, configurable: false, enumerable: true }); |
| Object.defineProperty(obj, "b", { value: 4, writable: false, enumerable: true }); |
| |
| let {...rest} = obj; |
| |
| assert(rest.a === 3); |
| assert(rest.b === 4); |
| |
| assertPropDescriptor(rest, 'a'); |
| assertPropDescriptor(rest, 'b'); |
| })(); |
| |
| // Destructuring function parameter |
| |
| (() => { |
| |
| var o = { x: 1, y: 2, w: 3, z: 4 }; |
| |
| function foo({ x, y, ...rest }) { |
| assert(x === 1); |
| assert(y === 2); |
| assert(rest.w === 3); |
| assert(rest.z === 4); |
| } |
| foo(o); |
| })(); |
| |
| // Destructuring arrow function parameter |
| |
| (() => { |
| |
| var o = { x: 1, y: 2, w: 3, z: 4 }; |
| |
| (({ x, y, ...rest }) => { |
| assert(x === 1); |
| assert(y === 2); |
| assert(rest.w === 3); |
| assert(rest.z === 4); |
| })(o); |
| })(); |
| |
| // Destructuring to a property |
| (() => { |
| |
| var o = { x: 1, y: 2}; |
| |
| let settedValue; |
| let src = {}; |
| ({...src.y} = o); |
| assert(src.y.x === 1); |
| assert(src.y.y === 2); |
| })(); |
| |
| // Destructuring with setter |
| (() => { |
| |
| var o = { x: 1, y: 2}; |
| |
| let settedValue; |
| let src = { |
| get y() { throw Error("The property should not be accessed"); }, |
| set y(v) { |
| settedValue = v; |
| } |
| } |
| src.y = undefined; |
| ({...src.y} = o); |
| assert(settedValue.x === 1); |
| assert(settedValue.y === 2); |
| })(); |
| |
| // Destructuring computed property |
| (() => { |
| |
| var a = "foo"; |
| |
| var {[a]: b, ...r} = {foo: 1, bar: 2, baz: 3}; |
| assert(b === 1); |
| assert(r.bar === 2); |
| assert(r.baz === 3); |
| })(); |
| |
| // Catch case |
| |
| (() => { |
| try { |
| throw {foo: 1, bar: 2, baz: 3}; |
| } catch({foo, ...rest}) { |
| assert(foo === 1); |
| assert(rest.bar === 2); |
| assert(rest.baz === 3); |
| } |
| })(); |
| |