2010-07-25 05:23:37 +00:00
|
|
|
x = 1
|
|
|
|
y = {}
|
|
|
|
y.x = -> 3
|
2010-01-14 01:59:57 +00:00
|
|
|
|
2010-02-17 00:45:25 +00:00
|
|
|
ok x is 1
|
|
|
|
ok typeof(y.x) is 'function'
|
|
|
|
ok y.x instanceof Function
|
|
|
|
ok y.x() is 3
|
2010-01-14 01:59:57 +00:00
|
|
|
|
|
|
|
|
2010-01-16 20:02:04 +00:00
|
|
|
# The empty function should not cause a syntax error.
|
2010-01-26 15:52:05 +00:00
|
|
|
->
|
2010-02-15 23:03:00 +00:00
|
|
|
() ->
|
2010-01-16 20:02:04 +00:00
|
|
|
|
|
|
|
|
2010-03-02 05:43:01 +00:00
|
|
|
# Multiple nested function declarations mixed with implicit calls should not
|
|
|
|
# cause a syntax error.
|
|
|
|
(one) -> (two) -> three four, (five) -> six seven, eight, (nine) ->
|
|
|
|
|
|
|
|
|
2010-07-25 05:23:37 +00:00
|
|
|
obj = {
|
2010-07-25 07:15:12 +00:00
|
|
|
name: 'Fred'
|
2010-01-14 01:59:57 +00:00
|
|
|
|
2010-01-26 15:52:05 +00:00
|
|
|
bound: ->
|
2010-10-11 17:04:51 +00:00
|
|
|
(=> eq this, obj)()
|
2010-01-14 01:59:57 +00:00
|
|
|
|
2010-01-26 15:52:05 +00:00
|
|
|
unbound: ->
|
2010-10-11 17:04:51 +00:00
|
|
|
(-> ok this isnt obj)()
|
2010-07-25 07:15:12 +00:00
|
|
|
|
|
|
|
nested: ->
|
|
|
|
(=>
|
|
|
|
(=>
|
|
|
|
(=>
|
2010-10-11 17:04:51 +00:00
|
|
|
eq this, obj
|
2010-07-25 07:15:12 +00:00
|
|
|
)()
|
|
|
|
)()
|
|
|
|
)()
|
2010-01-14 01:59:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
obj.unbound()
|
2010-01-16 16:24:10 +00:00
|
|
|
obj.bound()
|
2010-07-25 07:15:12 +00:00
|
|
|
obj.nested()
|
2010-01-16 20:44:07 +00:00
|
|
|
|
|
|
|
|
|
|
|
# Python decorator style wrapper that memoizes any function
|
2010-07-25 05:23:37 +00:00
|
|
|
memoize = (fn) ->
|
|
|
|
cache = {}
|
|
|
|
self = this
|
2010-01-26 15:52:05 +00:00
|
|
|
(args...) ->
|
2010-07-25 05:23:37 +00:00
|
|
|
key = args.toString()
|
2010-01-16 20:44:07 +00:00
|
|
|
return cache[key] if cache[key]
|
|
|
|
cache[key] = fn.apply(self, args)
|
|
|
|
|
2010-07-25 05:23:37 +00:00
|
|
|
Math = {
|
2010-01-26 15:52:05 +00:00
|
|
|
Add: (a, b) -> a + b
|
2010-10-22 17:59:25 +00:00
|
|
|
AnonymousAdd: (a, b) -> a + b
|
2010-01-26 15:52:05 +00:00
|
|
|
FastAdd: memoize (a, b) -> a + b
|
2010-01-16 20:44:07 +00:00
|
|
|
}
|
|
|
|
|
2010-02-17 00:45:25 +00:00
|
|
|
ok Math.Add(5, 5) is 10
|
|
|
|
ok Math.AnonymousAdd(10, 10) is 20
|
|
|
|
ok Math.FastAdd(20, 20) is 40
|
2010-01-25 04:56:27 +00:00
|
|
|
|
|
|
|
|
2010-07-25 05:23:37 +00:00
|
|
|
okFunc = (f) -> ok(f())
|
2010-06-12 23:05:13 +00:00
|
|
|
okFunc -> true
|
2010-01-26 19:49:33 +00:00
|
|
|
|
|
|
|
# Optional parens can be used in a nested fashion.
|
2010-07-25 05:23:37 +00:00
|
|
|
call = (func) -> func()
|
2010-01-26 19:49:33 +00:00
|
|
|
|
2010-07-25 05:23:37 +00:00
|
|
|
result = call ->
|
|
|
|
inner = call ->
|
2010-01-26 19:49:33 +00:00
|
|
|
Math.Add(5, 5)
|
|
|
|
|
2010-02-17 00:45:25 +00:00
|
|
|
ok result is 10
|
2010-01-27 02:15:56 +00:00
|
|
|
|
|
|
|
|
2010-03-10 02:54:44 +00:00
|
|
|
# More fun with optional parens.
|
2010-07-25 05:23:37 +00:00
|
|
|
fn = (arg) -> arg
|
2010-03-10 02:54:44 +00:00
|
|
|
|
|
|
|
ok fn(fn {prop: 101}).prop is 101
|
|
|
|
|
|
|
|
|
2010-03-10 14:28:00 +00:00
|
|
|
# Multi-blocks with optional parens.
|
2010-07-25 05:23:37 +00:00
|
|
|
result = fn( ->
|
2010-03-10 14:28:00 +00:00
|
|
|
fn ->
|
|
|
|
"Wrapped"
|
|
|
|
)
|
|
|
|
|
|
|
|
ok result()() is 'Wrapped'
|
|
|
|
|
|
|
|
|
2010-01-27 02:15:56 +00:00
|
|
|
# And even with strange things like this:
|
2010-07-25 05:23:37 +00:00
|
|
|
funcs = [((x) -> x), ((x) -> x * x)]
|
|
|
|
result = funcs[1] 5
|
2010-01-27 02:15:56 +00:00
|
|
|
|
2010-02-17 00:45:25 +00:00
|
|
|
ok result is 25
|
2010-01-27 02:15:56 +00:00
|
|
|
|
2010-07-25 05:23:37 +00:00
|
|
|
result = ("hello".slice) 3
|
2010-01-27 02:15:56 +00:00
|
|
|
|
2010-02-27 16:03:43 +00:00
|
|
|
ok result is 'lo'
|
|
|
|
|
|
|
|
|
|
|
|
# And with multiple single-line functions on the same line.
|
2010-07-25 05:23:37 +00:00
|
|
|
func = (x) -> (x) -> (x) -> x
|
2010-02-27 16:03:43 +00:00
|
|
|
ok func(1)(2)(3) is 3
|
2010-03-14 21:48:43 +00:00
|
|
|
|
|
|
|
|
|
|
|
# Ensure that functions with the same name don't clash with helper functions.
|
2010-07-25 05:23:37 +00:00
|
|
|
del = -> 5
|
2010-03-14 21:48:43 +00:00
|
|
|
ok del() is 5
|
2010-03-26 15:44:25 +00:00
|
|
|
|
|
|
|
# Ensure that functions can have a trailing comma in their argument list
|
2010-07-25 05:23:37 +00:00
|
|
|
mult = (x, mids..., y) ->
|
2010-10-24 18:11:09 +00:00
|
|
|
x *= n for n in mids
|
2010-07-25 05:23:37 +00:00
|
|
|
x *= y
|
2010-03-26 15:44:25 +00:00
|
|
|
|
|
|
|
ok mult(1, 2,) is 2
|
|
|
|
ok mult(1, 2, 3,) is 6
|
2010-11-20 22:46:44 +00:00
|
|
|
ok mult(10, (i for i in [1..6])...) is 7200
|
2010-03-28 20:44:41 +00:00
|
|
|
|
|
|
|
|
|
|
|
# Test for inline functions with parentheses and implicit calls.
|
2010-07-25 05:23:37 +00:00
|
|
|
combine = (func, num) -> func() * num
|
|
|
|
result = combine (-> 1 + 2), 3
|
2010-03-28 20:44:41 +00:00
|
|
|
|
|
|
|
ok result is 9
|
2010-04-02 03:38:20 +00:00
|
|
|
|
2010-04-03 13:58:45 +00:00
|
|
|
|
2010-04-02 03:38:20 +00:00
|
|
|
# Test for calls/parens/multiline-chains.
|
2010-07-25 05:23:37 +00:00
|
|
|
f = (x) -> x
|
|
|
|
result = (f 1).toString()
|
2010-04-02 03:38:20 +00:00
|
|
|
.length
|
|
|
|
|
|
|
|
ok result is 1
|
2010-04-10 22:56:46 +00:00
|
|
|
|
|
|
|
|
|
|
|
# Test implicit calls in functions in parens:
|
2010-07-25 05:23:37 +00:00
|
|
|
result = ((val) ->
|
2010-04-10 22:56:46 +00:00
|
|
|
[].push val
|
|
|
|
val
|
|
|
|
)(10)
|
|
|
|
|
|
|
|
ok result is 10
|
2010-04-20 05:32:12 +00:00
|
|
|
|
|
|
|
|
|
|
|
# More paren compilation tests:
|
2010-07-25 05:23:37 +00:00
|
|
|
reverse = (obj) -> obj.reverse()
|
2010-04-20 05:32:12 +00:00
|
|
|
ok reverse([1, 2].concat 3).join(' ') is '3 2 1'
|
2010-05-01 03:20:22 +00:00
|
|
|
|
|
|
|
# Passing multiple functions without paren-wrapping is legal, and should compile.
|
2010-07-25 05:23:37 +00:00
|
|
|
sum = (one, two) -> one() + two()
|
|
|
|
result = sum ->
|
2010-05-01 03:20:22 +00:00
|
|
|
7 + 9
|
|
|
|
, ->
|
|
|
|
1 + 3
|
2010-06-16 11:24:17 +00:00
|
|
|
|
2010-05-01 03:20:22 +00:00
|
|
|
ok result is 20
|
2010-06-11 12:29:16 +00:00
|
|
|
|
2010-07-10 18:52:54 +00:00
|
|
|
|
|
|
|
# Implicit call with a trailing if statement as a param.
|
2010-07-25 05:23:37 +00:00
|
|
|
func = -> arguments[1]
|
|
|
|
result = func 'one', if false then 100 else 13
|
2010-07-10 18:52:54 +00:00
|
|
|
ok result is 13
|
|
|
|
|
|
|
|
|
2010-06-11 12:29:16 +00:00
|
|
|
# Test more function passing:
|
2010-07-25 05:23:37 +00:00
|
|
|
result = sum( ->
|
2010-06-11 12:29:16 +00:00
|
|
|
1 + 2
|
|
|
|
, ->
|
|
|
|
2 + 1
|
|
|
|
)
|
|
|
|
ok result is 6
|
|
|
|
|
2010-07-25 05:23:37 +00:00
|
|
|
sum = (a, b) -> a + b
|
|
|
|
result = sum(1
|
2010-06-11 12:29:16 +00:00
|
|
|
, 2)
|
2010-06-16 11:24:17 +00:00
|
|
|
|
2010-06-11 12:29:16 +00:00
|
|
|
ok result is 3
|
2010-06-16 11:24:17 +00:00
|
|
|
|
|
|
|
|
2010-07-14 13:40:07 +00:00
|
|
|
# This is a crazy one.
|
2010-07-25 05:23:37 +00:00
|
|
|
x = (obj, func) -> func obj
|
|
|
|
ident = (x) -> x
|
2010-07-14 13:40:07 +00:00
|
|
|
|
2010-07-25 05:23:37 +00:00
|
|
|
result = x {one: ident 1}, (obj) ->
|
|
|
|
inner = ident(obj)
|
2010-07-14 13:40:07 +00:00
|
|
|
ident inner
|
|
|
|
|
|
|
|
ok result.one is 1
|
|
|
|
|
|
|
|
|
2010-06-16 11:24:17 +00:00
|
|
|
# Assignment to a Object.prototype-named variable should not leak to outer scope.
|
2010-10-11 23:54:36 +00:00
|
|
|
# FIXME: fails on IE
|
2010-06-16 11:24:17 +00:00
|
|
|
(->
|
2010-07-25 05:23:37 +00:00
|
|
|
constructor = 'word'
|
2010-06-16 11:24:17 +00:00
|
|
|
)()
|
|
|
|
|
|
|
|
ok constructor isnt 'word'
|
2010-07-27 01:39:43 +00:00
|
|
|
|
|
|
|
|
|
|
|
# Trying an implicit object call with a trailing function.
|
|
|
|
a = null
|
|
|
|
meth = (arg, obj, func) -> a = [obj.a, arg, func()].join ' '
|
|
|
|
|
|
|
|
meth 'apple', b: 1, a: 13, ->
|
|
|
|
'orange'
|
|
|
|
|
|
|
|
ok a is '13 apple orange'
|
2010-07-29 00:43:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
# Ensure that empty functions don't return mistaken values.
|
|
|
|
obj =
|
|
|
|
func: (@param, @rest...) ->
|
|
|
|
|
|
|
|
ok obj.func(101, 102, 103, 104) is undefined
|
|
|
|
ok obj.param is 101
|
|
|
|
ok obj.rest.join(' ') is '102 103 104'
|
2010-09-09 00:15:16 +00:00
|
|
|
|
|
|
|
|
|
|
|
# `@` and `this` should both be able to invoke a method.
|
|
|
|
func = (arg) -> ok arg is true
|
|
|
|
func.withAt = -> @ true
|
|
|
|
func.withThis = -> this true
|
|
|
|
|
|
|
|
func.withAt()
|
|
|
|
func.withThis()
|
2010-09-11 13:28:22 +00:00
|
|
|
|
|
|
|
|
|
|
|
# Ensure that constructors invoked with splats return a new object.
|
|
|
|
args = [1, 2, 3]
|
|
|
|
Type = (@args) ->
|
2010-09-20 10:02:16 +00:00
|
|
|
type = new Type args
|
2010-09-11 13:28:22 +00:00
|
|
|
|
|
|
|
ok type and type instanceof Type
|
2010-09-20 10:02:16 +00:00
|
|
|
ok type.args and type.args instanceof Array
|
2010-09-11 13:28:22 +00:00
|
|
|
ok v is args[i] for v, i in type.args
|
2010-09-11 13:49:25 +00:00
|
|
|
|
2010-09-20 10:02:16 +00:00
|
|
|
Type1 = (@a, @b, @c) ->
|
|
|
|
type1 = new Type1 args...
|
|
|
|
|
2010-10-12 12:48:25 +00:00
|
|
|
ok type1 instanceof Type1
|
|
|
|
eq type1.constructor, Type1
|
2010-10-10 15:29:14 +00:00
|
|
|
ok type1.a is args[0] and type1.b is args[1] and type1.c is args[2]
|
2010-09-20 10:02:16 +00:00
|
|
|
|
2010-09-11 13:49:25 +00:00
|
|
|
|
|
|
|
# Ensure that constructors invoked with splats cache the function.
|
|
|
|
called = 0
|
|
|
|
get = -> if called++ then false else class Type
|
|
|
|
new get() args...
|
2010-09-25 09:13:37 +00:00
|
|
|
|
|
|
|
|
2010-10-11 23:54:36 +00:00
|
|
|
# Chained blocks, with proper indentation levels:
|
|
|
|
counter =
|
|
|
|
results: []
|
|
|
|
tick: (func) ->
|
|
|
|
@results.push func()
|
|
|
|
this
|
|
|
|
|
|
|
|
counter
|
|
|
|
.tick ->
|
|
|
|
3
|
|
|
|
.tick ->
|
|
|
|
2
|
|
|
|
.tick ->
|
|
|
|
1
|
|
|
|
|
|
|
|
eq counter.results.join(' '), '3 2 1'
|
|
|
|
|
|
|
|
|
|
|
|
# Make incorrect indentation safe.
|
|
|
|
func = ->
|
|
|
|
obj = {
|
|
|
|
key: 10
|
|
|
|
}
|
|
|
|
obj.key - 5
|
|
|
|
|
|
|
|
eq func(), 5
|
|
|
|
|
|
|
|
|
|
|
|
# Ensure that chained calls with indented implicit object literals below are
|
|
|
|
# alright.
|
|
|
|
result = null
|
|
|
|
obj =
|
|
|
|
method: (val) -> this
|
|
|
|
second: (hash) -> result = hash.three
|
|
|
|
|
|
|
|
|
|
|
|
obj
|
|
|
|
.method(
|
|
|
|
101
|
|
|
|
).second(
|
|
|
|
one:
|
|
|
|
two: 2
|
|
|
|
three: 3
|
|
|
|
)
|
|
|
|
|
|
|
|
eq result, 3
|
|
|
|
|
|
|
|
|
|
|
|
# Test newline-supressed call chains with nested functions.
|
|
|
|
obj =
|
|
|
|
call: -> this
|
|
|
|
func = ->
|
|
|
|
obj
|
|
|
|
.call ->
|
|
|
|
one two
|
|
|
|
.call ->
|
|
|
|
three four
|
|
|
|
101
|
|
|
|
|
|
|
|
eq func(), 101
|
|
|
|
|
|
|
|
|
2010-10-19 15:52:07 +00:00
|
|
|
# `new` shouldn't add extra parens
|
2010-09-25 09:13:37 +00:00
|
|
|
ok new Date().constructor is Date
|
|
|
|
|
2010-10-10 15:29:14 +00:00
|
|
|
|
2010-10-19 15:52:07 +00:00
|
|
|
# `new` works against bare function
|
2010-10-11 19:00:57 +00:00
|
|
|
eq Date, new ->
|
|
|
|
eq this, new => this
|
|
|
|
Date
|
2010-10-10 15:29:14 +00:00
|
|
|
|
|
|
|
|
2010-10-19 15:52:07 +00:00
|
|
|
# Implicit objects with number arguments.
|
2010-10-10 15:29:14 +00:00
|
|
|
func = (x, y) -> y
|
|
|
|
obj =
|
|
|
|
prop: func "a", 1
|
|
|
|
|
|
|
|
ok obj.prop is 1
|
2010-10-19 15:52:07 +00:00
|
|
|
|
|
|
|
|
|
|
|
# Non-spaced unary and binary operators should cause a function call.
|
|
|
|
func = (val) -> val + 1
|
|
|
|
ok (func +5) is 6
|
|
|
|
ok (func -5) is -4
|
|
|
|
|
|
|
|
|
|
|
|
# Prefix unary assignment operators are allowed in parenless calls.
|
|
|
|
val = 5
|
|
|
|
ok (func --val) is 5
|
2010-10-22 17:59:25 +00:00
|
|
|
|
|
|
|
|
|
|
|
eq ok, new ->
|
|
|
|
ok
|
|
|
|
### Should `return` implicitly ###
|
|
|
|
### even with trailing comments. ###
|
2010-11-26 07:06:10 +00:00
|
|
|
|
2010-12-05 20:08:41 +00:00
|
|
|
|
2010-11-26 07:06:10 +00:00
|
|
|
#855: execution context for `func arr...` should be `null`
|
|
|
|
(->
|
|
|
|
global = @
|
|
|
|
contextTest = -> ok global is @
|
|
|
|
array = []
|
|
|
|
contextTest array
|
|
|
|
contextTest.apply null, array
|
|
|
|
contextTest array...
|
|
|
|
)()
|
2010-12-05 20:08:41 +00:00
|
|
|
|
|
|
|
|
|
|
|
# #894: Splatting against constructor-chained functions.
|
|
|
|
x = null
|
|
|
|
|
|
|
|
class Foo
|
|
|
|
bar: (y) -> x = y
|
|
|
|
|
|
|
|
new Foo().bar([101]...)
|
|
|
|
|
2010-12-10 02:34:52 +00:00
|
|
|
eq x, 101
|
|
|
|
|
|
|
|
|
2010-12-12 23:35:41 +00:00
|
|
|
test "#904: Destructuring function arguments with same-named variables in scope", ->
|
|
|
|
a = b = nonce = {}
|
|
|
|
fn = ([a,b]) -> {a:a,b:b}
|
|
|
|
result = fn([c={},d={}])
|
|
|
|
eq c, result.a
|
|
|
|
eq d, result.b
|
|
|
|
eq nonce, a
|
|
|
|
eq nonce, b
|