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