jashkenas--coffeescript/test/object_rest_spread.coffee

467 lines
8.7 KiB
CoffeeScript

test "#4798 destructuring of objects with splat within arrays", ->
arr = [1, {a:1, b:2}]
[...,{a, r...}] = arr
eq a, 1
deepEqual r, {b:2}
[b, {q...}] = arr
eq b, 1
deepEqual q, arr[1]
eq q.b, r.b
eq q.a, a
arr2 = [arr[1]]
[{a2...}] = arr2
eq a2.a, arr2[0].a
test "destructuring assignment with objects and splats: ES2015", ->
obj = {a: 1, b: 2, c: 3, d: 4, e: 5}
throwsCompileError "{a, r..., s...} = x", null, null, "multiple rest elements are disallowed"
throwsCompileError "{a, r..., s..., b} = x", null, null, "multiple rest elements are disallowed"
prop = "b"
{a, b, r...} = obj
eq a, 1
eq b, 2
eq r.e, obj.e
eq r.a, undefined
{d, c: x, r...} = obj
eq x, 3
eq d, 4
eq r.c, undefined
eq r.b, 2
{a, 'b': z, g = 9, r...} = obj
eq g, 9
eq z, 2
eq r.b, undefined
test "destructuring assignment with splats and default values", ->
obj = {}
c = {b: 1}
{ a: {b} = c, d...} = obj
eq b, 1
deepEqual d, {}
# Should not trigger implicit call, e.g. rest ... => rest(...)
{
a: {b} = c
d ...
} = obj
eq b, 1
deepEqual d, {}
test "destructuring assignment with splat with default value", ->
obj = {}
c = {val: 1}
{ a: {b...} = c } = obj
deepEqual b, val: 1
test "destructuring assignment with multiple splats in different objects", ->
obj = { a: {val: 1}, b: {val: 2} }
{ a: {a...}, b: {b...} } = obj
deepEqual a, val: 1
deepEqual b, val: 2
o = {
props: {
p: {
n: 1
m: 5
}
s: 6
}
}
{p: {m, q..., t = {obj...}}, r...} = o.props
eq m, o.props.p.m
deepEqual r, s: 6
deepEqual q, n: 1
deepEqual t, obj
@props = o.props
{p: {m}, r...} = @props
eq m, @props.p.m
deepEqual r, s: 6
{p: {m}, r...} = {o.props..., p:{m:9}}
eq m, 9
# Should not trigger implicit call, e.g. rest ... => rest(...)
{
a: {
a ...
}
b: {
b ...
}
} = obj
deepEqual a, val: 1
deepEqual b, val: 2
test "destructuring assignment with dynamic keys and splats", ->
i = 0
foo = -> ++i
obj = {1: 'a', 2: 'b'}
{ "#{foo()}": a, b... } = obj
eq a, 'a'
eq i, 1
deepEqual b, 2: 'b'
# Tests from https://babeljs.io/docs/plugins/transform-object-rest-spread/.
test "destructuring assignment with objects and splats: Babel tests", ->
# What Babel calls “rest properties:”
{ x, y, z... } = { x: 1, y: 2, a: 3, b: 4 }
eq x, 1
eq y, 2
deepEqual z, { a: 3, b: 4 }
# What Babel calls “spread properties:”
n = { x, y, z... }
deepEqual n, { x: 1, y: 2, a: 3, b: 4 }
# Should not trigger implicit call, e.g. rest ... => rest(...)
{ x, y, z ... } = { x: 1, y: 2, a: 3, b: 4 }
eq x, 1
eq y, 2
deepEqual z, { a: 3, b: 4 }
n = { x, y, z ... }
deepEqual n, { x: 1, y: 2, a: 3, b: 4 }
test "deep destructuring assignment with objects: ES2015", ->
a1={}; b1={}; c1={}; d1={}
obj = {
a: a1
b: {
'c': {
d: {
b1
e: c1
f: d1
}
}
}
b2: {b1, c1}
}
{a: w, b: {c: {d: {b1: bb, r1...}}}, r2...} = obj
eq r1.e, c1
eq r2.b, undefined
eq bb, b1
eq r2.b2, obj.b2
# Should not trigger implicit call, e.g. rest ... => rest(...)
{a: w, b: {c: {d: {b1: bb, r1 ...}}}, r2 ...} = obj
eq r1.e, c1
eq r2.b, undefined
eq bb, b1
eq r2.b2, obj.b2
test "deep destructuring assignment with defaults: ES2015", ->
obj =
b: { c: 1, baz: 'qux' }
foo: 'bar'
j =
f: 'world'
i =
some: 'prop'
{
a...
b: { c, d... }
e: {
f: hello
g: { h... } = i
} = j
} = obj
deepEqual a, foo: 'bar'
eq c, 1
deepEqual d, baz: 'qux'
eq hello, 'world'
deepEqual h, some: 'prop'
# Should not trigger implicit call, e.g. rest ... => rest(...)
{
a ...
b: {
c,
d ...
}
e: {
f: hello
g: {
h ...
} = i
} = j
} = obj
deepEqual a, foo: 'bar'
eq c, 1
deepEqual d, baz: 'qux'
eq hello, 'world'
deepEqual h, some: 'prop'
test "object spread properties: ES2015", ->
obj = {a: 1, b: 2, c: 3, d: 4, e: 5}
obj2 = {obj..., c:9}
eq obj2.c, 9
eq obj.a, obj2.a
# Should not trigger implicit call, e.g. rest ... => rest(...)
obj2 = {
obj ...
c:9
}
eq obj2.c, 9
eq obj.a, obj2.a
obj2 = {obj..., a: 8, c: 9, obj...}
eq obj2.c, 3
eq obj.a, obj2.a
# Should not trigger implicit call, e.g. rest ... => rest(...)
obj2 = {
obj ...
a: 8
c: 9
obj ...
}
eq obj2.c, 3
eq obj.a, obj2.a
obj3 = {obj..., b: 7, g: {obj2..., c: 1}}
eq obj3.g.c, 1
eq obj3.b, 7
deepEqual obj3.g, {obj..., c: 1}
(({a, b, r...}) ->
eq 1, a
deepEqual r, {c: 3, d: 44, e: 55}
) {obj2..., d: 44, e: 55}
obj = {a: 1, b: 2, c: {d: 3, e: 4, f: {g: 5}}}
obj4 = {a: 10, obj.c...}
eq obj4.a, 10
eq obj4.d, 3
eq obj4.f.g, 5
deepEqual obj4.f, obj.c.f
# Should not trigger implicit call, e.g. rest ... => rest(...)
(({
a
b
r ...
}) ->
eq 1, a
deepEqual r, {c: 3, d: 44, e: 55}
) {
obj2 ...
d: 44
e: 55
}
# Should not trigger implicit call, e.g. rest ... => rest(...)
obj4 = {
a: 10
obj.c ...
}
eq obj4.a, 10
eq obj4.d, 3
eq obj4.f.g, 5
deepEqual obj4.f, obj.c.f
obj5 = {obj..., ((k) -> {b: k})(99)...}
eq obj5.b, 99
deepEqual obj5.c, obj.c
# Should not trigger implicit call, e.g. rest ... => rest(...)
obj5 = {
obj ...
((k) -> {b: k})(99) ...
}
eq obj5.b, 99
deepEqual obj5.c, obj.c
fn = -> {c: {d: 33, e: 44, f: {g: 55}}}
obj6 = {obj..., fn()...}
eq obj6.c.d, 33
deepEqual obj6.c, {d: 33, e: 44, f: {g: 55}}
obj7 = {obj..., fn()..., {c: {d: 55, e: 66, f: {77}}}...}
eq obj7.c.d, 55
deepEqual obj6.c, {d: 33, e: 44, f: {g: 55}}
# Should not trigger implicit call, e.g. rest ... => rest(...)
obj7 = {
obj ...
fn() ...
{c: {d: 55, e: 66, f: {77}}} ...
}
eq obj7.c.d, 55
deepEqual obj6.c, {d: 33, e: 44, f: {g: 55}}
obj =
a:
b:
c:
d:
e: {}
obj9 = {a:1, obj.a.b.c..., g:3}
deepEqual obj9.d, {e: {}}
a = "a"
c = "c"
obj9 = {a:1, obj[a].b[c]..., g:3}
deepEqual obj9.d, {e: {}}
obj9 = {a:1, obj.a["b"].c["d"]..., g:3}
deepEqual obj9["e"], {}
test "#4673: complex destructured object spread variables", ->
b = c: 1
{{a...}...} = b
eq a.c, 1
d = {}
{d.e...} = f: 1
eq d.e.f, 1
{{g}...} = g: 1
eq g, 1
test "rest element destructuring in function definition", ->
obj = {a: 1, b: 2, c: 3, d: 4, e: 5}
(({a, b, r...}) ->
eq 1, a
eq 2, b,
deepEqual r, {c: 3, d: 4, e: 5}
) obj
(({a: p, b, r...}, q) ->
eq p, 1
eq q, 9
deepEqual r, {c: 3, d: 4, e: 5}
) {a:1, b:2, c:3, d:4, e:5}, 9
# Should not trigger implicit call, e.g. rest ... => rest(...)
(({
a: p
b
r ...
}, q) ->
eq p, 1
eq q, 9
deepEqual r, {c: 3, d: 4, e: 5}
) {a:1, b:2, c:3, d:4, e:5}, 9
a1={}; b1={}; c1={}; d1={}
obj1 = {
a: a1
b: {
'c': {
d: {
b1
e: c1
f: d1
}
}
}
b2: {b1, c1}
}
(({a: w, b: {c: {d: {b1: bb, r1...}}}, r2...}) ->
eq a1, w
eq bb, b1
eq r2.b, undefined
deepEqual r1, {e: c1, f: d1}
deepEqual r2.b2, {b1, c1}
) obj1
b = 3
f = ({a, b...}) ->
f {}
eq 3, b
(({a, r...} = {}) ->
eq a, undefined
deepEqual r, {}
)()
(({a, r...} = {}) ->
eq a, 1
deepEqual r, {b: 2, c: 3}
) {a: 1, b: 2, c: 3}
f = ({a, r...} = {}) -> [a, r]
deepEqual [undefined, {}], f()
deepEqual [1, {b: 2}], f {a: 1, b: 2}
deepEqual [1, {}], f {a: 1}
f = ({a, r...} = {a: 1, b: 2}) -> [a, r]
deepEqual [1, {b:2}], f()
deepEqual [2, {}], f {a:2}
deepEqual [3, {c:5}], f {a:3, c:5}
f = ({ a: aa = 0, b: bb = 0 }) -> [aa, bb]
deepEqual [0, 0], f {}
deepEqual [0, 42], f {b:42}
deepEqual [42, 0], f {a:42}
deepEqual [42, 43], f {a:42, b:43}
test "#4673: complex destructured object spread variables", ->
f = ({{a...}...}) ->
a
eq f(c: 1).c, 1
g = ({@y...}) ->
eq @y.b, 1
g b: 1
test "#4834: dynamic import can technically be object spread", ->
eqJS """
x = {...import('module')}
""",
"""
var x;
x = {...import('module')};
"""
test "#5168: allow indented property index", ->
a = b: c: 3
eq 3, {
...a[
if yes
'b'
else
'c'
]
}.c
test "#5291: soaks/prototype shorthands in object spread variables", ->
withPrototype =
prototype:
b: {c: 1}
eq {withPrototype::b...}.c, 1
eq {...withPrototype::b}.c, 1
withSoak =
b:
c: 2
eq {withSoak?.b...}.c, 2
eq {...withSoak?.b}.c, 2
soakedCall = ->
b:
c: 3
eq {soakedCall?().b...}.c, 3
eq {...soakedCall?().b}.c, 3
assignToPrototype =
prototype: {}
{...assignToPrototype::b} = c: 4
eq assignToPrototype::b.c, 4