Fix #4798: Incorrect output for object rest destructuring inside array destructuring (#4799)

* fix #4798

* additional tests
This commit is contained in:
zdenko 2017-12-04 17:00:45 +01:00 committed by Geoffrey Booth
parent 81d1b511f0
commit 5bc85b8f6d
3 changed files with 22 additions and 8 deletions

View File

@ -3212,7 +3212,7 @@
// we've been assigned to, for correct internal references. If the variable
// has not been seen yet within the current scope, declare it.
compileNode(o) {
var answer, compiledName, isValue, j, name, objDestructAnswer, properties, prototype, ref1, ref2, ref3, ref4, ref5, val, varBase;
var answer, compiledName, hasSplat, isValue, j, name, objDestructAnswer, properties, prototype, ref1, ref2, ref3, ref4, ref5, val, varBase;
isValue = this.variable instanceof Value;
if (isValue) {
// When compiling `@variable`, remember if it is part of a function parameter.
@ -3226,12 +3226,14 @@
// know that, so that those nodes know that theyre assignable as
// destructured variables.
this.variable.base.lhs = true;
if (!this.variable.isAssignable()) {
// Check if @variable contains Obj with splats.
hasSplat = this.variable.contains(function(node) {
return node instanceof Obj && node.hasSplat();
});
if (!this.variable.isAssignable() || this.variable.isArray() && hasSplat) {
return this.compileDestructuring(o);
}
if (this.variable.isObject() && this.variable.contains(function(node) {
return node instanceof Obj && node.hasSplat();
})) {
if (this.variable.isObject() && hasSplat) {
// Object destructuring. Can be removed once ES proposal hits Stage 4.
objDestructAnswer = this.compileObjectDestruct(o);
}

View File

@ -2156,10 +2156,11 @@ exports.Assign = class Assign extends Base
# know that, so that those nodes know that theyre assignable as
# destructured variables.
@variable.base.lhs = yes
return @compileDestructuring o unless @variable.isAssignable()
# Check if @variable contains Obj with splats.
hasSplat = @variable.contains (node) -> node instanceof Obj and node.hasSplat()
return @compileDestructuring o if not @variable.isAssignable() or @variable.isArray() and hasSplat
# Object destructuring. Can be removed once ES proposal hits Stage 4.
objDestructAnswer = @compileObjectDestruct(o) if @variable.isObject() and @variable.contains (node) ->
node instanceof Obj and node.hasSplat()
objDestructAnswer = @compileObjectDestruct(o) if @variable.isObject() and hasSplat
return objDestructAnswer if objDestructAnswer
return @compileSplice o if @variable.isSplice()

View File

@ -185,6 +185,17 @@ test "#4787 destructuring of objects within arrays", ->
eq b, arr[1].b
deepEqual {a, b}, arr[1]
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
test "destructuring assignment with splats", ->
a = {}; b = {}; c = {}; d = {}; e = {}
[x,y...,z] = [a,b,c,d,e]