1 | suite 'Function Invocation', ->
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 | id = (_) -> if arguments.length is 1 then _ else [].slice.call arguments
|
8 |
|
9 | test "basic argument passing", ->
|
10 | a = {}
|
11 | b = {}
|
12 | c = {}
|
13 | eq 1, (id 1)
|
14 | eq 2, (id 1, 2)[1]
|
15 | eq a, (id a)
|
16 | eq c, (id a, b, c)[2]
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 |
|
35 |
|
36 |
|
37 | test "optional parens can be used in a nested fashion", ->
|
38 | call = (func) -> func()
|
39 | add = (a,b) -> a + b
|
40 | result = call ->
|
41 | inner = call ->
|
42 | add 5, 5
|
43 | ok result is 10
|
44 |
|
45 | test "hanging commas and semicolons in argument list", ->
|
46 | fn = -> arguments.length
|
47 | eq 2, fn(0,1,)
|
48 | eq 3, fn 0, 1,
|
49 | 2
|
50 | eq 2, fn(0, 1; 2)
|
51 |
|
52 | test "function invocation", ->
|
53 | func = ->
|
54 | return if true
|
55 | eq undefined, func()
|
56 | result = ("hello".slice) 3
|
57 | ok result is 'lo'
|
58 |
|
59 | test "And even with strange things like this:", ->
|
60 | funcs = [((x) -> x), ((x) -> x * x)]
|
61 | result = funcs[1] 5
|
62 | eq 25, result
|
63 |
|
64 | test "More fun with optional parens.", ->
|
65 | fn = (arg) -> arg
|
66 | eq 101, fn(fn {prop: 101}).prop
|
67 | okFunc = (f) -> ok(f())
|
68 | okFunc -> true
|
69 |
|
70 | test "chained function calls", ->
|
71 | nonce = {}
|
72 | identityWrap = (x) ->
|
73 | -> x
|
74 | eq nonce, identityWrap(identityWrap(nonce))()()
|
75 | eq nonce, (identityWrap identityWrap nonce)()()
|
76 |
|
77 |
|
78 |
|
79 |
|
80 |
|
81 |
|
82 |
|
83 |
|
84 |
|
85 | test "method calls", ->
|
86 | fnId = (fn) -> -> fn.apply this, arguments
|
87 | obj = {}
|
88 | obj.add = (a, b) -> a + b
|
89 | obj.anonymousAdd = (a, b) -> a + b
|
90 | obj.fastAdd = fnId (a, b) -> a + b
|
91 | eq 10, obj.add(5, 5)
|
92 | eq 20, obj.anonymousAdd 10, 10
|
93 | eq 40, obj.fastAdd (20), 20
|
94 |
|
95 |
|
96 |
|
97 |
|
98 |
|
99 |
|
100 |
|
101 |
|
102 |
|
103 | test "`@` and `this` should both be able to invoke a function", ->
|
104 | nonce = {}
|
105 | fn = (arg) -> eq nonce, arg
|
106 | fn.withAt = -> @ nonce
|
107 | fn.withThis = -> this nonce
|
108 | fn.withAt()
|
109 | fn.withThis()
|
110 |
|
111 | test "Trying an implicit object call with a trailing function.", ->
|
112 | a = null
|
113 | meth = (arg, obj, func) -> a = [obj.a, arg, func()].join ' '
|
114 | meth 'apple', b: 1, a: 13, ->
|
115 | 'orange'
|
116 | ok a is '13 apple orange'
|
117 |
|
118 |
|
119 |
|
120 |
|
121 |
|
122 |
|
123 |
|
124 |
|
125 |
|
126 |
|
127 |
|
128 |
|
129 |
|
130 |
|
131 |
|
132 |
|
133 |
|
134 |
|
135 |
|
136 |
|
137 | test "Implicit call with a trailing if statement as a param.", ->
|
138 | func = -> arguments[1]
|
139 | result = func 'one', if false then 100 else 13
|
140 | ok result is 13
|
141 |
|
142 |
|
143 |
|
144 |
|
145 |
|
146 |
|
147 |
|
148 |
|
149 |
|
150 |
|
151 |
|
152 |
|
153 |
|
154 |
|
155 |
|
156 |
|
157 |
|
158 |
|
159 |
|
160 |
|
161 |
|
162 |
|
163 |
|
164 |
|
165 |
|
166 |
|
167 |
|
168 |
|
169 |
|
170 |
|
171 |
|
172 | test "TODO: find out what this test case is testing and rename it", ->
|
173 | x = (obj, func) -> func obj
|
174 | ident = (x) -> x
|
175 | result = x {one: ident 1}, (obj) ->
|
176 | inner = ident(obj)
|
177 | ident inner
|
178 | ok result.one is 1
|
179 |
|
180 | test "More paren compilation tests:", ->
|
181 | reverse = (obj) -> obj.reverse()
|
182 | ok reverse([1, 2].concat 3).join(' ') is '3 2 1'
|
183 |
|
184 | test "Test for inline functions with parentheses and implicit calls.", ->
|
185 | combine = (func, num) -> func() * num
|
186 | result = combine (-> 1 + 2), 3
|
187 | ok result is 9
|
188 |
|
189 |
|
190 |
|
191 |
|
192 |
|
193 |
|
194 |
|
195 | test "Test implicit calls in functions in parens:", ->
|
196 | result = ((val) ->
|
197 | [].push val
|
198 | val
|
199 | )(10)
|
200 | ok result is 10
|
201 |
|
202 |
|
203 |
|
204 |
|
205 |
|
206 |
|
207 |
|
208 |
|
209 |
|
210 |
|
211 |
|
212 |
|
213 |
|
214 |
|
215 |
|
216 |
|
217 |
|
218 |
|
219 |
|
220 |
|
221 |
|
222 |
|
223 |
|
224 |
|
225 |
|
226 |
|
227 |
|
228 |
|
229 |
|
230 |
|
231 |
|
232 |
|
233 |
|
234 |
|
235 | test "Non-spaced unary and binary operators should cause a function call.", ->
|
236 | func = (val) -> val + 1
|
237 | ok (func +5) is 6
|
238 | ok (func -5) is -4
|
239 |
|
240 | test "Prefix unary assignment operators are allowed in parenless calls.", ->
|
241 | func = (val) -> val + 1
|
242 | val = 5
|
243 | ok (func --val) is 5
|
244 |
|
245 | test "jashkenas/coffee-script#855: execution context for `func arr...` should be `null`", ->
|
246 | contextTest = -> eq @, if window? then window else global
|
247 | array = []
|
248 | contextTest array
|
249 | contextTest.apply null, array
|
250 | contextTest array...
|
251 |
|
252 |
|
253 |
|
254 |
|
255 |
|
256 |
|
257 |
|
258 |
|
259 |
|
260 |
|
261 |
|
262 |
|
263 |
|
264 |
|
265 |
|
266 |
|
267 | test "caching base value", ->
|
268 | obj = {index: 0, 0: {method: -> this is obj[0]}}
|
269 | ok obj[obj.index++].method([]...)
|
270 |
|
271 | test "passing splats to functions", ->
|
272 | arrayEq [0..4], id id [0..4]...
|
273 | fn = (a, b, c..., d) -> [a, b, c, d]
|
274 | range = [0..3]
|
275 | [first, second, others, last] = fn range..., 4, [5...8]...
|
276 | eq 0, first
|
277 | eq 1, second
|
278 | arrayEq [2..6], others
|
279 | eq 7, last
|
280 |
|
281 | test "splat variables are local to the function", ->
|
282 | outer = "x"
|
283 | clobber = (avar, outer...) -> outer
|
284 | clobber "foo", "bar"
|
285 | eq "x", outer
|
286 |
|
287 | test "Issue 894: Splatting against constructor-chained functions.", ->
|
288 | x = null
|
289 | class Foo
|
290 | bar: (y) -> x = y
|
291 | new Foo().bar([101]...)
|
292 | eq x, 101
|
293 |
|
294 | test "Functions with splats being called with too few arguments.", ->
|
295 | method = (first, variable..., penultimate, ultimate) ->
|
296 | penultimate
|
297 | eq 8, method 1, 2, 3, 4, 5, 6, 7, 8, 9
|
298 | eq 2, method 1, 2, 3
|
299 | eq 2, method 1, 2
|
300 |
|
301 |
|
302 |
|
303 |
|
304 |
|
305 |
|
306 |
|
307 |
|
308 |
|
309 |
|
310 |
|
311 | test "jashkenas/coffee-script#1011: passing a splat to a method of a number", ->
|
312 | eq '1011', 11.toString [2]...
|
313 | eq '1011', (31).toString [3]...
|
314 | eq '1011', 69.0.toString [4]...
|
315 | eq '1011', (131.0).toString [5]...
|
316 |
|
317 | test "splats and the `new` operator: functions that return `null` should construct their instance", ->
|
318 | args = []
|
319 | child = new (constructor = -> null) args...
|
320 | ok child instanceof constructor
|
321 |
|
322 | test "splats and the `new` operator: functions that return functions should construct their return value", ->
|
323 | args = []
|
324 | fn = ->
|
325 | child = new (constructor = -> fn) args...
|
326 | ok child not instanceof constructor
|
327 | eq fn, child
|
328 |
|
329 | test "implicit return", ->
|
330 | eq ok, new ->
|
331 | ok
|
332 |
|
333 |
|
334 | eq ok, new ->
|
335 | ok
|
336 |
|
337 |
|
338 |
|
339 | test "implicit returns with multiple branches", ->
|
340 | nonce = {}
|
341 | fn = ->
|
342 | if not nonce
|
343 | null
|
344 | else
|
345 | nonce
|
346 | eq nonce, fn()
|
347 |
|
348 | test "implicit returns with switches", ->
|
349 | nonce = {}
|
350 | fn = ->
|
351 | switch nonce
|
352 | when nonce then nonce
|
353 | else return undefined
|
354 | eq nonce, fn()
|
355 |
|
356 | test "preserve context when generating closure wrappers for expression conversions", ->
|
357 | nonce = {}
|
358 | obj = {property: nonce, method: ->
|
359 | this.result = if false
|
360 | 10
|
361 | else
|
362 | "a"
|
363 | "b"
|
364 | this.property
|
365 | }
|
366 | eq nonce, obj.method()
|
367 | eq nonce, obj.property
|
368 |
|
369 |
|
370 |
|
371 |
|
372 |
|
373 |
|
374 |
|
375 |
|
376 |
|
377 | test "usage of `new` is careful about where the invocation parens end up", ->
|
378 |
|
379 | eq 'object', typeof new do -> ->
|
380 |
|
381 | test "implicit call against control structures", ->
|
382 | result = null
|
383 | save = (obj) -> result = obj
|
384 |
|
385 | save switch id false
|
386 | when true
|
387 | 'true'
|
388 | when false
|
389 | 'false'
|
390 | eq result, 'false'
|
391 |
|
392 | save if id false
|
393 | 'false'
|
394 | else
|
395 | 'true'
|
396 | eq result, 'true'
|
397 |
|
398 | save unless id false
|
399 | 'true'
|
400 | else
|
401 | 'false'
|
402 | eq result, 'true'
|
403 |
|
404 | save try
|
405 | doesnt exist
|
406 | catch error
|
407 | 'caught'
|
408 | eq result, 'caught'
|
409 |
|
410 | save try doesnt(exist) catch error then 'caught2'
|
411 | eq result, 'caught2'
|
412 |
|
413 | test "jashkenas/coffee-script#1420: things like `(fn() ->)`; there are no words for this one", ->
|
414 | fn = -> (f) -> f()
|
415 | nonce = {}
|
416 | eq nonce, (fn() -> nonce)
|
417 |
|
418 | test "jashkenas/coffee-script#1416: don't omit one 'new' when compiling 'new new'", ->
|
419 | nonce = {}
|
420 | obj = new new -> -> {prop: nonce}
|
421 | eq obj.prop, nonce
|
422 |
|
423 | test "jashkenas/coffee-script#1416: don't omit one 'new' when compiling 'new new fn()()'", ->
|
424 | nonce = {}
|
425 | argNonceA = {}
|
426 | argNonceB = {}
|
427 | fn = (a) -> (b) -> {a, b, prop: nonce}
|
428 | obj = new new fn(argNonceA)(argNonceB)
|
429 | eq obj.prop, nonce
|
430 | eq obj.a, argNonceA
|
431 | eq obj.b, argNonceB
|
432 |
|
433 | test "jashkenas/coffee-script#1840: accessing the `prototype` after function invocation should compile", ->
|
434 | nonce = {}
|
435 | obj = {prototype: {id: nonce}}
|
436 | dotAccess = -> obj.prototype
|
437 | protoAccess = -> obj
|
438 | eq dotAccess().id, nonce
|
439 | eq protoAccess()::id, nonce
|
440 |
|
441 | test "jashkenas/coffee-script#960: improved 'do'", ->
|
442 |
|
443 | do (nonExistent = 'one') ->
|
444 | eq nonExistent, 'one'
|
445 |
|
446 | overridden = 1
|
447 | do (overridden = 2) ->
|
448 | eq overridden, 2
|
449 |
|
450 | two = 2
|
451 | do (one = 1, two, three = 3) ->
|
452 | eq one, 1
|
453 | eq two, 2
|
454 | eq three, 3
|
455 |
|
456 | ret = do func = (two) ->
|
457 | eq two, 2
|
458 | func
|
459 | eq ret, func
|
460 |
|
461 | test "soaked function application", ->
|
462 | nonce = {}
|
463 | eq undefined, f?(0, 1)
|
464 | eq undefined, f? 0, 1
|
465 | eq undefined, f?
|
466 | a: 0
|
467 | eq undefined, f? 0,
|
468 | a: 1
|
469 | f = -> nonce
|
470 | eq nonce, f?(0, 1)
|
471 | eq nonce, f? 0, 1
|
472 | eq nonce, f?
|
473 | a: 0
|
474 | eq nonce, f? 0,
|
475 | a: 1
|