jashkenas--coffeescript/test/objects.coffee

279 lines
5.0 KiB
CoffeeScript

# Object Literals
# ---------------
# TODO: refactor object literal tests
# TODO: add indexing and method invocation tests: {a}['a'] is a, {a}.a()
trailingComma = {k1: "v1", k2: 4, k3: (-> true),}
ok trailingComma.k3() and (trailingComma.k2 is 4) and (trailingComma.k1 is "v1")
ok {a: (num) -> num is 10 }.a 10
moe = {
name: 'Moe'
greet: (salutation) ->
salutation + " " + @name
hello: ->
@['greet'] "Hello"
10: 'number'
}
ok moe.hello() is "Hello Moe"
ok moe[10] is 'number'
moe.hello = ->
this['greet'] "Hello"
ok moe.hello() is 'Hello Moe'
obj = {
is: -> yes,
'not': -> no,
}
ok obj.is()
ok not obj.not()
### Top-level object literal... ###
obj: 1
### ...doesn't break things. ###
# Object literals should be able to include keywords.
obj = {class: 'höt'}
obj.function = 'dog'
ok obj.class + obj.function is 'hötdog'
# Implicit objects as part of chained calls.
pluck = (x) -> x.a
eq 100, pluck pluck pluck a: a: a: 100
test "YAML-style object literals", ->
obj =
a: 1
b: 2
eq 1, obj.a
eq 2, obj.b
config =
development:
server: 'localhost'
timeout: 10
production:
server: 'dreamboat'
timeout: 1000
ok config.development.server is 'localhost'
ok config.production.server is 'dreamboat'
ok config.development.timeout is 10
ok config.production.timeout is 1000
obj =
a: 1,
b: 2,
ok obj.a is 1
ok obj.b is 2
# Implicit objects nesting.
obj =
options:
value: yes
fn: ->
{}
null
ok obj.options.value is yes
ok obj.fn() is null
# Implicit objects with wacky indentation:
obj =
'reverse': (obj) ->
Array.prototype.reverse.call obj
abc: ->
@reverse(
@reverse @reverse ['a', 'b', 'c'].reverse()
)
one: [1, 2,
a: 'b'
3, 4]
red:
orange:
yellow:
green: 'blue'
indigo: 'violet'
misdent: [[],
[],
[],
[]]
ok obj.abc().join(' ') is 'a b c'
ok obj.one.length is 5
ok obj.one[4] is 4
ok obj.one[2].a is 'b'
ok (key for key of obj.red).length is 2
ok obj.red.orange.yellow.green is 'blue'
ok obj.red.indigo is 'violet'
ok obj.misdent.toString() is ',,,'
#542: Objects leading expression statement should be parenthesized.
{f: -> ok yes }.f() + 1
# String-keyed objects shouldn't suppress newlines.
one =
'>!': 3
six: -> 10
ok not one.six
# Shorthand objects with property references.
obj =
### comment one ###
### comment two ###
one: 1
two: 2
object: -> {@one, @two}
list: -> [@one, @two]
result = obj.object()
eq result.one, 1
eq result.two, 2
eq result.two, obj.list()[1]
third = (a, b, c) -> c
obj =
one: 'one'
two: third 'one', 'two', 'three'
ok obj.one is 'one'
ok obj.two is 'three'
test "invoking functions with implicit object literals", ->
generateGetter = (prop) -> (obj) -> obj[prop]
getA = generateGetter 'a'
getArgs = -> arguments
a = b = 30
result = getA
a: 10
eq 10, result
result = getA
"a": 20
eq 20, result
result = getA a,
b:1
eq undefined, result
result = getA b:1,
a:43
eq 43, result
result = getA b:1,
a:62
eq undefined, result
result = getA
b:1
a
eq undefined, result
result = getA
a:
b:2
b:1
eq 2, result.b
result = getArgs
a:1
b
c:1
ok result.length is 3
ok result[2].c is 1
result = getA b: 13, a: 42, 2
eq 42, result
result = getArgs a:1, (1 + 1)
ok result[1] is 2
result = getArgs a:1, b
ok result.length is 2
ok result[1] is 30
result = getArgs a:1, b, b:1, a
ok result.length is 4
ok result[2].b is 1
throws -> CoffeeScript.compile "a = b:1, c"
test "some weird indentation in YAML-style object literals", ->
two = (a, b) -> b
obj = then two 1,
1: 1
a:
b: ->
fn c,
d: e
f: 1
eq 1, obj[1]
test "#1274: `{} = a()` compiles to `false` instead of `a()`", ->
a = false
fn = -> a = true
{} = fn()
ok a
test "#1436: `for` etc. work as normal property names", ->
obj = {}
eq no, obj.hasOwnProperty 'for'
obj.for = 'foo' of obj
eq yes, obj.hasOwnProperty 'for'
test "#1322: implicit call against implicit object with block comments", ->
((obj, arg) ->
eq obj.x * obj.y, 6
ok not arg
)
###
x
###
x: 2
### y ###
y: 3
test "#1513: Top level bare objs need to be wrapped in parens for unary and existence ops", ->
doesNotThrow -> CoffeeScript.run "{}?", bare: true
doesNotThrow -> CoffeeScript.run "{}.a++", bare: true
test "#1871: Special case for IMPLICIT_END in the middle of an implicit object", ->
result = 'result'
ident = (x) -> x
result = ident one: 1 if false
eq result, 'result'
result = ident
one: 1
two: 2 for i in [1..3]
eq result.two.join(' '), '2 2 2'
test "#1961, #1974, regression with compound assigning to an implicit object", ->
obj = null
obj ?=
one: 1
two: 2
eq obj.two, 2
obj = null
obj or=
three: 3
four: 4
eq obj.four, 4
test "#2207: Immediate implicit closes don't close implicit objects", ->
func = ->
key: for i in [1, 2, 3] then i
eq func().key.join(' '), '1 2 3'