Skip to content

Commit 383efd4

Browse files
committed
handle non-final object-destructured splat
1 parent c95ae2d commit 383efd4

File tree

4 files changed

+81
-17
lines changed

4 files changed

+81
-17
lines changed

lib/coffeescript/nodes.js

+23-12
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/nodes.coffee

+13-5
Original file line numberDiff line numberDiff line change
@@ -2318,12 +2318,19 @@ exports.Assign = class Assign extends Base
23182318

23192319
isSplat = splats?.length > 0
23202320
isExpans = expans?.length > 0
2321-
isObject = @variable.isObject()
2322-
isArray = @variable.isArray()
23232321

23242322
vvar = value.compileToFragments o, LEVEL_LIST
23252323
vvarText = fragmentsToText vvar
23262324
assigns = []
2325+
pushAssign = (variable, val) =>
2326+
assigns.push new Assign(variable, val, null, param: @param, subpattern: yes).compileToFragments o, LEVEL_LIST
2327+
2328+
if isSplat
2329+
splatVar = objects[splats[0]].name.unwrap()
2330+
if splatVar instanceof Arr or splatVar instanceof Obj
2331+
splatVarRef = new IdentifierLiteral o.scope.freeVariable 'ref'
2332+
objects[splats[0]].name = splatVarRef
2333+
splatVarAssign = -> pushAssign new Value(splatVar), splatVarRef
23272334

23282335
# At this point, there are several things to destructure. So the `fn()` in
23292336
# `{a, b} = fn()` must be cached, for example. Make vvar into a simple
@@ -2388,13 +2395,13 @@ exports.Assign = class Assign extends Base
23882395
else new Value new Literal(vvarTxt), [new Index new NumberLiteral i]
23892396
message = isUnassignable vvar.unwrap().value
23902397
vvar.error message if message
2391-
assigns.push new Assign(vvar, vval, null, param: @param, subpattern: yes).compileToFragments o, LEVEL_LIST
2398+
pushAssign vvar, vval
23922399

23932400
# "Simple" `objects` can be split and compiled to arrays, [a, b, c] = arr, [a, b, c...] = arr
23942401
assignObjects = (objs, vvar, vvarTxt) =>
23952402
vvar = new Value new Arr(objs, yes)
23962403
vval = if vvarTxt instanceof Value then vvarTxt else new Value new Literal(vvarTxt)
2397-
assigns.push new Assign(vvar, vval, null, param: @param, subpattern: yes).compileToFragments o, LEVEL_LIST
2404+
pushAssign vvar, vval
23982405

23992406
processObjects = (objs, vvar, vvarTxt) ->
24002407
if complexObjects objs
@@ -2431,6 +2438,7 @@ exports.Assign = class Assign extends Base
24312438
else
24322439
# There is no `Splat` or `Expansion` in `objects`.
24332440
processObjects objects, vvar, vvarText
2441+
splatVarAssign?()
24342442
assigns.push vvar unless top or @subpattern
24352443
fragments = @joinFragmentArrays assigns, ', '
24362444
if o.level < LEVEL_LIST then fragments else @wrapInParentheses fragments
@@ -2592,7 +2600,7 @@ exports.Code = class Code extends Base
25922600
param.error 'an expansion parameter cannot be the only parameter in a function definition'
25932601
haveSplatParam = yes
25942602
if param.splat
2595-
if param.name instanceof Arr
2603+
if param.name instanceof Arr or param.name instanceof Obj
25962604
# Splat arrays are treated oddly by ES; deal with them the legacy
25972605
# way in the function body. TODO: Should this be handled in the
25982606
# function parameter list, and if so, how?

test/assignment.coffee

+35
Original file line numberDiff line numberDiff line change
@@ -686,3 +686,38 @@ test "#5004: array destructuring with accessors", ->
686686
[obj.list.middle..., d] = obj.arr
687687
eq d, 'd'
688688
arrayEq obj.list.middle, ['a', 'b', 'c']
689+
690+
test "destructured object splat", ->
691+
[{length}...] = [1, 2, 3]
692+
eq length, 3
693+
[{length: len}...] = [1, 2, 3]
694+
eq len, 3
695+
[{length}..., three] = [1, 2, 3]
696+
eq length, 2
697+
eq three, 3
698+
[{length: len}..., three] = [1, 2, 3]
699+
eq len, 2
700+
eq three, 3
701+
x = [{length}..., three] = [1, 2, 3]
702+
eq length, 2
703+
eq three, 3
704+
eq x[2], 3
705+
x = [{length: len}..., three] = [1, 2, 3]
706+
eq len, 2
707+
eq three, 3
708+
eq x[2], 3
709+
710+
test "destructured array splat", ->
711+
[[one, two, three]...] = [1, 2, 3]
712+
eq one, 1
713+
eq two, 2
714+
eq three, 3
715+
[[one, two]..., three] = [1, 2, 3]
716+
eq one, 1
717+
eq two, 2
718+
eq three, 3
719+
x = [[one, two]..., three] = [1, 2, 3]
720+
eq one, 1
721+
eq two, 2
722+
eq three, 3
723+
eq x[2], 3

test/functions.coffee

+10
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,16 @@ test "destructured splatted parameters", ->
127127
splatArray = ([a ...]) -> a
128128
splatArrayRest = ([a ...],b ...) -> arrayEq(a,b); b
129129

130+
test "object-destructured splatted parameters", ->
131+
f = ({length}...) -> length
132+
eq f(4, 5, 6), 3
133+
f = ({length: len}...) -> len
134+
eq f(4, 5, 6), 3
135+
f = ({length}..., last) -> [length, last]
136+
arrayEq f(4, 5, 6), [2, 6]
137+
f = ({length: len}..., last) -> [len, last]
138+
arrayEq f(4, 5, 6), [2, 6]
139+
130140
test "@-parameters: automatically assign an argument's value to a property of the context", ->
131141
nonce = {}
132142

0 commit comments

Comments
 (0)