1# Function Invocation
2# -------------------
3
4# * Function Invocation
5# * Splats in Function Invocations
6# * Implicit Returns
7# * Explicit Returns
8
9# shared identity function
10id = (_) -> if arguments.length is 1 then _ else [arguments...]
11
12test "basic argument passing", ->
13
14  a = {}
15  b = {}
16  c = {}
17  eq 1, (id 1)
18  eq 2, (id 1, 2)[1]
19  eq a, (id a)
20  eq c, (id a, b, c)[2]
21
22
23test "passing arguments on separate lines", ->
24
25  a = {}
26  b = {}
27  c = {}
28  ok(id(
29    a
30    b
31    c
32  )[1] is b)
33  eq(0, id(
34    0
35    10
36  )[0])
37  eq(a,id(
38    a
39  ))
40  eq b,
41  (id b)
42
43
44test "optional parens can be used in a nested fashion", ->
45
46  call = (func) -> func()
47  add = (a,b) -> a + b
48  result = call ->
49    inner = call ->
50      add 5, 5
51  ok result is 10
52
53
54test "hanging commas and semicolons in argument list", ->
55
56  fn = () -> arguments.length
57  eq 2, fn(0,1,)
58  eq 3, fn 0, 1,
59  2
60  eq 2, fn(0, 1;)
61  # TODO: this test fails (the string compiles), but should it?
62  #throwsCompileError "fn(0,1,;)"
63  throwsCompileError "fn(0,1,;;)"
64  throwsCompileError "fn(0, 1;,)"
65  throwsCompileError "fn(,0)"
66  throwsCompileError "fn(;0)"
67
68
69test "function invocation", ->
70
71  func = ->
72    return if true
73  eq undefined, func()
74
75  result = ("hello".slice) 3
76  ok result is 'lo'
77
78
79test "And even with strange things like this:", ->
80
81  funcs  = [((x) -> x), ((x) -> x * x)]
82  result = funcs[1] 5
83  ok result is 25
84
85
86test "More fun with optional parens.", ->
87
88  fn = (arg) -> arg
89  ok fn(fn {prop: 101}).prop is 101
90
91  okFunc = (f) -> ok(f())
92  okFunc -> true
93
94
95test "chained function calls", ->
96  nonce = {}
97  identityWrap = (x) ->
98    -> x
99  eq nonce, identityWrap(identityWrap(nonce))()()
100  eq nonce, (identityWrap identityWrap nonce)()()
101
102
103test "Multi-blocks with optional parens.", ->
104
105  fn = (arg) -> arg
106  result = fn( ->
107    fn ->
108      "Wrapped"
109  )
110  ok result()() is 'Wrapped'
111
112
113test "method calls", ->
114
115  fnId = (fn) -> -> fn.apply this, arguments
116  math = {
117    add: (a, b) -> a + b
118    anonymousAdd: (a, b) -> a + b
119    fastAdd: fnId (a, b) -> a + b
120  }
121  ok math.add(5, 5) is 10
122  ok math.anonymousAdd(10, 10) is 20
123  ok math.fastAdd(20, 20) is 40
124
125
126test "Ensure that functions can have a trailing comma in their argument list", ->
127
128  mult = (x, mids..., y) ->
129    x *= n for n in mids
130    x *= y
131  #ok mult(1, 2,) is 2
132  #ok mult(1, 2, 3,) is 6
133  ok mult(10, (i for i in [1..6])...) is 7200
134
135
136test "`@` and `this` should both be able to invoke a method", ->
137  nonce = {}
138  fn          = (arg) -> eq nonce, arg
139  fn.withAt   = -> @ nonce
140  fn.withThis = -> this nonce
141  fn.withAt()
142  fn.withThis()
143
144
145test "Trying an implicit object call with a trailing function.", ->
146
147  a = null
148  meth = (arg, obj, func) -> a = [obj.a, arg, func()].join ' '
149  meth 'apple', b: 1, a: 13, ->
150    'orange'
151  ok a is '13 apple orange'
152
153
154test "Ensure that empty functions don't return mistaken values.", ->
155
156  obj =
157    func: (@param, @rest...) ->
158  ok obj.func(101, 102, 103, 104) is undefined
159  ok obj.param is 101
160  ok obj.rest.join(' ') is '102 103 104'
161
162
163test "Passing multiple functions without paren-wrapping is legal, and should compile.", ->
164
165  sum = (one, two) -> one() + two()
166  result = sum ->
167    7 + 9
168  , ->
169    1 + 3
170  ok result is 20
171
172
173test "Implicit call with a trailing if statement as a param.", ->
174
175  func = -> arguments[1]
176  result = func 'one', if false then 100 else 13
177  ok result is 13
178
179
180test "Test more function passing:", ->
181
182  sum = (one, two) -> one() + two()
183
184  result = sum( ->
185    1 + 2
186  , ->
187    2 + 1
188  )
189  ok result is 6
190
191  sum = (a, b) -> a + b
192  result = sum(1
193  , 2)
194  ok result is 3
195
196
197test "Chained blocks, with proper indentation levels:", ->
198
199  counter =
200    results: []
201    tick: (func) ->
202      @results.push func()
203      this
204  counter
205    .tick ->
206      3
207    .tick ->
208      2
209    .tick ->
210      1
211  arrayEq [3,2,1], counter.results
212
213
214test "This is a crazy one.", ->
215
216  x = (obj, func) -> func obj
217  ident = (x) -> x
218  result = x {one: ident 1}, (obj) ->
219    inner = ident(obj)
220    ident inner
221  ok result.one is 1
222
223
224test "More paren compilation tests:", ->
225
226  reverse = (obj) -> obj.reverse()
227  ok reverse([1, 2].concat 3).join(' ') is '3 2 1'
228
229
230test "Test for inline functions with parentheses and implicit calls.", ->
231
232  combine = (func, num) -> func() * num
233  result  = combine (-> 1 + 2), 3
234  ok result is 9
235
236
237test "Test for calls/parens/multiline-chains.", ->
238
239  f = (x) -> x
240  result = (f 1).toString()
241    .length
242  ok result is 1
243
244
245test "Test implicit calls in functions in parens:", ->
246
247  result = ((val) ->
248    [].push val
249    val
250  )(10)
251  ok result is 10
252
253
254test "Ensure that chained calls with indented implicit object literals below are alright.", ->
255
256  result = null
257  obj =
258    method: (val)  -> this
259    second: (hash) -> result = hash.three
260  obj
261    .method(
262      101
263    ).second(
264      one:
265        two: 2
266      three: 3
267    )
268  eq result, 3
269
270
271test "Test newline-supressed call chains with nested functions.", ->
272
273  obj  =
274    call: -> this
275  func = ->
276    obj
277      .call ->
278        one two
279      .call ->
280        three four
281    101
282  eq func(), 101
283
284
285test "Implicit objects with number arguments.", ->
286
287  func = (x, y) -> y
288  obj =
289    prop: func "a", 1
290  ok obj.prop is 1
291
292
293test "Non-spaced unary and binary operators should cause a function call.", ->
294
295  func = (val) -> val + 1
296  ok (func +5) is 6
297  ok (func -5) is -4
298
299
300test "Prefix unary assignment operators are allowed in parenless calls.", ->
301
302  func = (val) -> val + 1
303  val = 5
304  ok (func --val) is 5
305
306test "#855: execution context for `func arr...` should be `null`", ->
307  contextTest = -> eq @, if window? then window else global
308  array = []
309  contextTest array
310  contextTest.apply null, array
311  contextTest array...
312
313test "#904: Destructuring function arguments with same-named variables in scope", ->
314  a = b = nonce = {}
315  fn = ([a,b]) -> {a:a,b:b}
316  result = fn([c={},d={}])
317  eq c, result.a
318  eq d, result.b
319  eq nonce, a
320  eq nonce, b
321
322test "Simple Destructuring function arguments with same-named variables in scope", ->
323  x = 1
324  f = ([x]) -> x
325  eq f([2]), 2
326  eq x, 1
327
328test "#4843: Bad output when assigning to @prop in destructuring assignment with defaults", ->
329  works = "maybe"
330  drinks = "beer"
331  class A
332    constructor: ({@works = 'no', @drinks = 'wine'}) ->
333  a = new A {works: 'yes', drinks: 'coffee'}
334  eq a.works, 'yes'
335  eq a.drinks, 'coffee'
336
337test "caching base value", ->
338
339  obj =
340    index: 0
341    0: {method: -> this is obj[0]}
342  ok obj[obj.index++].method([]...)
343
344
345test "passing splats to functions", ->
346  arrayEq [0..4], id id [0..4]...
347  fn = (a, b, c..., d) -> [a, b, c, d]
348  range = [0..3]
349  [first, second, others, last] = fn range..., 4, [5...8]...
350  eq 0, first
351  eq 1, second
352  arrayEq [2..6], others
353  eq 7, last
354
355  # Should not trigger implicit call, e.g. rest ... => rest(...)
356  arrayEq [0..4], id id [0..4] ...
357  fn = (a, b, c ..., d) -> [a, b, c, d]
358  range = [0..3]
359  [first, second, others, last] = fn range ..., 4, [5 ... 8] ...
360  eq 0, first
361  eq 1, second
362  arrayEq [2..6], others
363  eq 7, last
364
365test "splat variables are local to the function", ->
366  outer = "x"
367  clobber = (avar, outer...) -> outer
368  clobber "foo", "bar"
369  eq "x", outer
370
371test "Issue 4631: left and right spread dots with preceding space", ->
372  a = []
373  f = (a) -> a
374  eq yes, (f ...a) is (f ... a) is (f a...) is (f a ...) is f(a...) is f(...a) is f(a ...) is f(... a)
375
376test "Issue 894: Splatting against constructor-chained functions.", ->
377
378  x = null
379  class Foo
380    bar: (y) -> x = y
381  new Foo().bar([101]...)
382  eq x, 101
383
384
385test "Functions with splats being called with too few arguments.", ->
386
387  pen = null
388  method = (first, variable..., penultimate, ultimate) ->
389    pen = penultimate
390  method 1, 2, 3, 4, 5, 6, 7, 8, 9
391  ok pen is 8
392  method 1, 2, 3
393  ok pen is 2
394  method 1, 2
395  ok pen is 2
396
397
398test "splats with super() within classes.", ->
399
400  class Parent
401    meth: (args...) ->
402      args
403  class Child extends Parent
404    meth: ->
405      nums = [3, 2, 1]
406      super nums...
407  ok (new Child).meth().join(' ') is '3 2 1'
408
409  # Should not trigger implicit call, e.g. rest ... => rest(...)
410  class Parent
411    meth: (args ...) ->
412      args
413  class Child extends Parent
414    meth: ->
415      nums = [3, 2, 1]
416      super nums ...
417  ok (new Child).meth().join(' ') is '3 2 1'
418
419
420test "#1011: passing a splat to a method of a number", ->
421  eq '1011', 11.toString [2]...
422  eq '1011', (31).toString [3]...
423  eq '1011', 69.0.toString [4]...
424  eq '1011', (131.0).toString [5]...
425
426  # Should not trigger implicit call, e.g. rest ... => rest(...)
427  eq '1011', 11.toString [2] ...
428  eq '1011', (31).toString [3] ...
429  eq '1011', 69.0.toString [4] ...
430  eq '1011', (131.0).toString [5] ...
431
432test "splats and the `new` operator: functions that return `null` should construct their instance", ->
433  args = []
434  child = new (constructor = -> null) args...
435  ok child instanceof constructor
436
437  # Should not trigger implicit call, e.g. rest ... => rest(...)
438  child = new (constructor = -> null) args ...
439  ok child instanceof constructor
440
441test "splats and the `new` operator: functions that return functions should construct their return value", ->
442  args = []
443  fn = ->
444  child = new (constructor = -> fn) args...
445  ok child not instanceof constructor
446  eq fn, child
447
448test "implicit return", ->
449
450  eq ok, new ->
451    ok
452    ### Should `return` implicitly   ###
453    ### even with trailing comments. ###
454
455
456test "implicit returns with multiple branches", ->
457  nonce = {}
458  fn = ->
459    if false
460      for a in b
461        return c if d
462    else
463      nonce
464  eq nonce, fn()
465
466
467test "implicit returns with switches", ->
468  nonce = {}
469  fn = ->
470    switch nonce
471      when nonce then nonce
472      else return undefined
473  eq nonce, fn()
474
475
476test "preserve context when generating closure wrappers for expression conversions", ->
477  nonce = {}
478  obj =
479    property: nonce
480    method: ->
481      this.result = if false
482        10
483      else
484        "a"
485        "b"
486        this.property
487  eq nonce, obj.method()
488  eq nonce, obj.property
489
490
491test "don't wrap 'pure' statements in a closure", ->
492  nonce = {}
493  items = [0, 1, 2, 3, nonce, 4, 5]
494  fn = (items) ->
495    for item in items
496      return item if item is nonce
497  eq nonce, fn items
498
499
500test "usage of `new` is careful about where the invocation parens end up", ->
501  eq 'object', typeof new try Array
502  eq 'object', typeof new do -> ->
503  a = b: ->
504  eq 'object', typeof new (do -> a).b
505
506
507test "implicit call against control structures", ->
508  result = null
509  save   = (obj) -> result = obj
510
511  save switch id false
512    when true
513      'true'
514    when false
515      'false'
516
517  eq result, 'false'
518
519  save if id false
520    'false'
521  else
522    'true'
523
524  eq result, 'true'
525
526  save unless id false
527    'true'
528  else
529    'false'
530
531  eq result, 'true'
532
533  save try
534    doesnt exist
535  catch error
536    'caught'
537
538  eq result, 'caught'
539
540  save try doesnt(exist) catch error then 'caught2'
541
542  eq result, 'caught2'
543
544
545test "#1420: things like `(fn() ->)`; there are no words for this one", ->
546  fn = -> (f) -> f()
547  nonce = {}
548  eq nonce, (fn() -> nonce)
549
550test "#1416: don't omit one 'new' when compiling 'new new'", ->
551  nonce = {}
552  obj = new new -> -> {prop: nonce}
553  eq obj.prop, nonce
554
555test "#1416: don't omit one 'new' when compiling 'new new fn()()'", ->
556  nonce = {}
557  argNonceA = {}
558  argNonceB = {}
559  fn = (a) -> (b) -> {a, b, prop: nonce}
560  obj = new new fn(argNonceA)(argNonceB)
561  eq obj.prop, nonce
562  eq obj.a, argNonceA
563  eq obj.b, argNonceB
564
565test "#1840: accessing the `prototype` after function invocation should compile", ->
566  doesNotThrowCompileError 'fn()::prop'
567
568  nonce = {}
569  class Test then id: nonce
570
571  dotAccess = -> Test::
572  protoAccess = -> Test
573
574  eq dotAccess().id, nonce
575  eq protoAccess()::id, nonce
576
577test "#960: improved 'do'", ->
578
579  do (nonExistent = 'one') ->
580    eq nonExistent, 'one'
581
582  overridden = 1
583  do (overridden = 2) ->
584    eq overridden, 2
585
586  two = 2
587  do (one = 1, two, three = 3) ->
588    eq one, 1
589    eq two, 2
590    eq three, 3
591
592  ret = do func = (two) ->
593    eq two, 2
594    func
595  eq ret, func
596
597test "#2617: implicit call before unrelated implicit object", ->
598  pass = ->
599    true
600
601  result = if pass 1
602    one: 1
603  eq result.one, 1
604
605test "#2292, b: f (z),(x)", ->
606  f = (x, y) -> y
607  one = 1
608  two = 2
609  o = b: f (one),(two)
610  eq o.b, 2
611
612test "#2297, Different behaviors on interpreting literal", ->
613  foo = (x, y) -> y
614  bar =
615    baz: foo 100, on
616
617  eq bar.baz, on
618
619  qux = (x) -> x
620  quux = qux
621    corge: foo 100, true
622
623  eq quux.corge, on
624
625  xyzzy =
626    e: 1
627    f: foo
628      a: 1
629      b: 2
630    ,
631      one: 1
632      two: 2
633      three: 3
634    g:
635      a: 1
636      b: 2
637      c: foo 2,
638        one: 1
639        two: 2
640        three: 3
641      d: 3
642    four: 4
643    h: foo one: 1, two: 2, three: three: three: 3,
644      2
645
646  eq xyzzy.f.two, 2
647  eq xyzzy.g.c.three, 3
648  eq xyzzy.four, 4
649  eq xyzzy.h, 2
650
651test "#2715, Chained implicit calls", ->
652  first  = (x)    -> x
653  second = (x, y) -> y
654
655  foo = first first
656    one: 1
657  eq foo.one, 1
658
659  bar = first second
660    one: 1, 2
661  eq bar, 2
662
663  baz = first second
664    one: 1,
665    2
666  eq baz, 2
667
668test "Implicit calls and new", ->
669  first = (x) -> x
670  foo = (@x) ->
671  bar = first new foo first 1
672  eq bar.x, 1
673
674  third = (x, y, z) -> z
675  baz = first new foo new foo third
676        one: 1
677        two: 2
678        1
679        three: 3
680        2
681  eq baz.x.x.three, 3
682
683test "Loose tokens inside of explicit call lists", ->
684  first = (x) -> x
685  second = (x, y) -> y
686  one = 1
687
688  foo = second( one
689                2)
690  eq foo, 2
691
692  bar = first( first
693               one: 1)
694  eq bar.one, 1
695
696test "Non-callable literals shouldn't compile", ->
697  throwsCompileError '1(2)'
698  throwsCompileError '1 2'
699  throwsCompileError '/t/(2)'
700  throwsCompileError '/t/ 2'
701  throwsCompileError '///t///(2)'
702  throwsCompileError '///t/// 2'
703  throwsCompileError "''(2)"
704  throwsCompileError "'' 2"
705  throwsCompileError '""(2)'
706  throwsCompileError '"" 2'
707  throwsCompileError '""""""(2)'
708  throwsCompileError '"""""" 2'
709  throwsCompileError '{}(2)'
710  throwsCompileError '{} 2'
711  throwsCompileError '[](2)'
712  throwsCompileError '[] 2'
713  throwsCompileError '[2..9] 2'
714  throwsCompileError '[2..9](2)'
715  throwsCompileError '[1..10][2..9] 2'
716  throwsCompileError '[1..10][2..9](2)'
717
718test "implicit invocation with implicit object literal", ->
719  f = (obj) -> eq 1, obj.a
720
721  f
722    a: 1
723  obj =
724    if f
725      a: 2
726    else
727      a: 1
728  eq 2, obj.a
729
730  f
731    "a": 1
732  obj =
733    if f
734      "a": 2
735    else
736      "a": 1
737  eq 2, obj.a
738
739  # #3935: Implicit call when the first key of an implicit object has interpolation.
740  a = 'a'
741  f
742    "#{a}": 1
743  obj =
744    if f
745      "#{a}": 2
746    else
747      "#{a}": 1
748  eq 2, obj.a
749
750test "get and set can be used as function names when not ambiguous with `get`/`set` keywords", ->
751  get = (val) -> val
752  set = (val) -> val
753  eq 2, get(2)
754  eq 3, set(3)
755  eq 'a', get('a')
756  eq 'b', set('b')
757  eq 4, get 4
758  eq 5, set 5
759  eq 'c', get 'c'
760  eq 'd', set 'd'
761
762  @get = get
763  @set = set
764  eq 6, @get 6
765  eq 7, @set 7
766
767  get = ({val}) -> val
768  set = ({val}) -> val
769  eq 8, get({val: 8})
770  eq 9, set({val: 9})
771  eq 'e', get({val: 'e'})
772  eq 'f', set({val: 'f'})
773  eq 10, get {val: 10}
774  eq 11, set {val: 11}
775  eq 'g', get {val: 'g'}
776  eq 'h', set {val: 'h'}
777
778test "get and set can be used as variable and property names", ->
779  get = 2
780  set = 3
781  eq 2, get
782  eq 3, set
783
784  {get} = {get: 4}
785  {set} = {set: 5}
786  eq 4, get
787  eq 5, set
788
789test "get and set can be used as class method names", ->
790  class A
791    get: -> 2
792    set: -> 3
793
794  a = new A()
795  eq 2, a.get()
796  eq 3, a.set()
797
798  class B
799    @get = -> 4
800    @set = -> 5
801
802  eq 4, B.get()
803  eq 5, B.set()
804
805test "#4524: functions named get or set can be used without parentheses when attached to an object", ->
806  obj =
807    get: (x) -> x + 2
808    set: (x) -> x + 3
809
810  class A
811    get: (x) -> x + 4
812    set: (x) -> x + 5
813
814  a = new A()
815
816  class B
817    get: (x) -> x.value + 6
818    set: (x) -> x.value + 7
819
820  b = new B()
821
822  eq 12, obj.get 10
823  eq 13, obj.set 10
824  eq 12, obj?.get 10
825  eq 13, obj?.set 10
826
827  eq 14, a.get 10
828  eq 15, a.set 10
829
830  @ten = 10
831
832  eq 12, obj.get @ten
833  eq 13, obj.set @ten
834
835  eq 14, a.get @ten
836  eq 15, a.set @ten
837
838  obj.obj = obj
839
840  eq 12, obj.obj.get @ten
841  eq 13, obj.obj.set @ten
842
843  eq 16, b.get value: 10
844  eq 17, b.set value: 10
845
846  eq 16, b.get value: @ten
847  eq 17, b.set value: @ten
848
849test "#4836: functions named get or set can be used without parentheses when attached to this or @", ->
850  @get = (x) -> x + 2
851  @set = (x) -> x + 3
852  @a = 4
853
854  eq 12, this.get 10
855  eq 13, this.set 10
856  eq 12, this?.get 10
857  eq 13, this?.set 10
858  eq 6, this.get @a
859  eq 7, this.set @a
860  eq 6, this?.get @a
861  eq 7, this?.set @a
862
863  eq 12, @get 10
864  eq 13, @set 10
865  eq 12, @?.get 10
866  eq 13, @?.set 10
867  eq 6, @get @a
868  eq 7, @set @a
869  eq 6, @?.get @a
870  eq 7, @?.set @a
871
872test "#4852: functions named get or set can be used without parentheses when attached to this or @, with an argument of an implicit object", ->
873  @get = ({ x }) -> x + 2
874  @set = ({ x }) -> x + 3
875
876  eq 12, @get x: 10
877  eq 13, @set x: 10
878  eq 12, @?.get x: 10
879  eq 13, @?.set x: 10
880  eq 12, this?.get x: 10
881  eq 13, this?.set x: 10
882
883test "#4473: variable scope in chained calls", ->
884  obj =
885    foo: -> this
886    bar: (a) ->
887      a()
888      this
889
890  obj.foo(a = 1).bar(-> a = 2)
891  eq a, 2
892
893  obj.bar(-> b = 2).foo(b = 1)
894  eq b, 1
895
896  obj.foo(c = 1).bar(-> c = 2).foo(c = 3)
897  eq c, 3
898
899  obj.foo([d, e] = [1, 2]).bar(-> d = 4)
900  eq d, 4
901
902  obj.foo({f} = {f: 1}).bar(-> f = 5)
903  eq f, 5
904
905test "#5052: implicit call of class with no body", ->
906  doesNotThrowCompileError 'f class'
907  doesNotThrowCompileError 'f class A'
908  doesNotThrowCompileError 'f class A extends B'
909
910  f = (args...) -> args
911  a = 1
912
913  [klass, shouldBeA] = f class A, a
914  eq shouldBeA, a
915
916  [shouldBeA] = f a, class A
917  eq shouldBeA, a
918
919  [obj, klass, shouldBeA] =
920    f
921      b: 1
922      class A
923      a
924  eq shouldBeA, a
925