diff --git a/lib/nodes.js b/lib/nodes.js index 8318d644..111b68dd 100644 --- a/lib/nodes.js +++ b/lib/nodes.js @@ -631,37 +631,41 @@ } return ifn; }; + Call.prototype.filterImplicitObjects = function(list) { + var node, nodes, obj, prop, properties, _i, _j, _len, _len2, _ref; + nodes = []; + for (_i = 0, _len = list.length; _i < _len; _i++) { + node = list[_i]; + if (!((typeof node.isObject == "function" ? node.isObject() : void 0) && node.base.generated)) { + nodes.push(node); + continue; + } + obj = null; + _ref = node.base.properties; + for (_j = 0, _len2 = _ref.length; _j < _len2; _j++) { + prop = _ref[_j]; + if (prop instanceof Assign) { + if (!obj) { + nodes.push(obj = new Obj(properties = [], true)); + } + properties.push(prop); + } else { + nodes.push(prop); + obj = null; + } + } + } + return nodes; + }; Call.prototype.compileNode = function(o) { - var arg, args, code, obj, prop, properties, _i, _j, _len, _len2, _ref, _ref2, _ref3; + var arg, args, code, _ref; if ((_ref = this.variable) != null) { _ref.front = this.front; } if (code = Splat.compileSplattedArray(o, this.args, true)) { return this.compileSplat(o, code); } - args = []; - _ref2 = this.args; - for (_i = 0, _len = _ref2.length; _i < _len; _i++) { - arg = _ref2[_i]; - if (!((typeof arg.isObject == "function" ? arg.isObject() : void 0) && arg.base.generated)) { - args.push(arg); - continue; - } - obj = null; - _ref3 = arg.base.properties; - for (_j = 0, _len2 = _ref3.length; _j < _len2; _j++) { - prop = _ref3[_j]; - if (prop instanceof Assign) { - if (!obj) { - args.push(obj = new Obj(properties = [], true)); - } - properties.push(prop); - } else { - args.push(prop); - obj = null; - } - } - } + args = this.filterImplicitObjects(this.args); args = ((function() { var _i, _len, _results; _results = []; @@ -931,25 +935,26 @@ this.objects = objs || []; } Arr.prototype.children = ['objects']; + Arr.prototype.filterImplicitObjects = Call.prototype.filterImplicitObjects; Arr.prototype.compileNode = function(o) { - var code, obj; + var code, obj, objs; if (!this.objects.length) { return '[]'; } o.indent += TAB; - if (code = Splat.compileSplattedArray(o, this.objects)) { + objs = this.filterImplicitObjects(this.objects); + if (code = Splat.compileSplattedArray(o, objs)) { return code; } code = ((function() { - var _i, _len, _ref, _results; - _ref = this.objects; + var _i, _len, _results; _results = []; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - obj = _ref[_i]; + for (_i = 0, _len = objs.length; _i < _len; _i++) { + obj = objs[_i]; _results.push(obj.compile(o, LEVEL_LIST)); } return _results; - }).call(this)).join(', '); + })()).join(', '); if (code.indexOf('\n') >= 0) { return "[\n" + o.indent + code + "\n" + this.tab + "]"; } else { diff --git a/src/nodes.coffee b/src/nodes.coffee index ddf01c9a..088da48d 100644 --- a/src/nodes.coffee +++ b/src/nodes.coffee @@ -499,28 +499,30 @@ exports.Call = class Call extends Base ifn = unfoldSoak o, call, 'variable' ifn + # Walk through the objects in the arguments, moving over simple values. + # This allows syntax like `call a: b, c` into `call({a: b}, c);` + filterImplicitObjects: (list) -> + nodes = [] + for node in list + unless node.isObject?() and node.base.generated + nodes.push node + continue + obj = null + for prop in node.base.properties + if prop instanceof Assign + nodes.push obj = new Obj properties = [], true if not obj + properties.push prop + else + nodes.push prop + obj = null + nodes + # Compile a vanilla function call. compileNode: (o) -> @variable?.front = @front if code = Splat.compileSplattedArray o, @args, true return @compileSplat o, code - - # Walk through the objects in the arguments, moving over simple values. - # This allows syntax like `call a: b, c` into `call({a: b}, c);` - args = [] - for arg in @args - unless arg.isObject?() and arg.base.generated - args.push arg - continue - obj = null - for prop in arg.base.properties - if prop instanceof Assign - args.push obj = new Obj properties = [], true if not obj - properties.push prop - else - args.push prop - obj = null - + args = @filterImplicitObjects @args args = (arg.compile o, LEVEL_LIST for arg in args).join ', ' if @isSuper @superReference(o) + ".call(this#{ args and ', ' + args })" @@ -755,11 +757,14 @@ exports.Arr = class Arr extends Base children: ['objects'] + filterImplicitObjects: Call::filterImplicitObjects + compileNode: (o) -> return '[]' unless @objects.length o.indent += TAB - return code if code = Splat.compileSplattedArray o, @objects - code = (obj.compile o, LEVEL_LIST for obj in @objects).join ', ' + objs = @filterImplicitObjects @objects + return code if code = Splat.compileSplattedArray o, objs + code = (obj.compile o, LEVEL_LIST for obj in objs).join ', ' if code.indexOf('\n') >= 0 "[\n#{o.indent}#{code}\n#{@tab}]" else diff --git a/test/array_literals.coffee b/test/array_literals.coffee index a8e6f4b4..c40b9cdb 100644 --- a/test/array_literals.coffee +++ b/test/array_literals.coffee @@ -35,3 +35,24 @@ test "array splat expansions with assignments", -> eq 0, a eq 4, b arrayEq [0,1,2,3,4], list + +test "mixed shorthand objects in array lists", -> + + arr = [ + a:1 + 'b' + c:1 + ] + ok arr.length is 3 + ok arr[2].c is 1 + + arr = [b: 1, a: 2, 100] + eq arr[1], 100 + + arr = [a:0, b:1, (1 + 1)] + eq arr[1], 2 + + arr = [a:1, 'a', b:1, 'b'] + eq arr.length, 4 + eq arr[2].b, 1 + eq arr[3], 'b'