PageRenderTime 47ms CodeModel.GetById 19ms app.highlight 21ms RepoModel.GetById 2ms app.codeStats 0ms

/test/soaks.coffee

http://github.com/jashkenas/coffee-script
CoffeeScript | 133 lines | 99 code | 24 blank | 10 comment | 3 complexity | c5169e90ef27c92f95101a041bc0b777 MD5 | raw file
  1# Soaks
  2# -----
  3
  4# * Soaked Property Access
  5# * Soaked Method Invocation
  6# * Soaked Function Invocation
  7
  8
  9# Soaked Property Access
 10
 11test "soaked property access", ->
 12  nonce = {}
 13  obj = a: b: nonce
 14  eq nonce    , obj?.a.b
 15  eq nonce    , obj?['a'].b
 16  eq nonce    , obj.a?.b
 17  eq nonce    , obj?.a?['b']
 18  eq undefined, obj?.a?.non?.existent?.property
 19
 20test "soaked property access caches method calls", ->
 21  nonce ={}
 22  obj = fn: -> a: nonce
 23  eq nonce    , obj.fn()?.a
 24  eq undefined, obj.fn()?.b
 25
 26test "soaked property access caching", ->
 27  nonce = {}
 28  counter = 0
 29  fn = ->
 30    counter++
 31    'self'
 32  obj =
 33    self: -> @
 34    prop: nonce
 35  eq nonce, obj[fn()]()[fn()]()[fn()]()?.prop
 36  eq 3, counter
 37
 38test "method calls on soaked methods", ->
 39  nonce = {}
 40  obj = null
 41  eq undefined, obj?.a().b()
 42  obj = a: -> b: -> nonce
 43  eq nonce    , obj?.a().b()
 44
 45test "postfix existential operator mixes well with soaked property accesses", ->
 46  eq false, nonexistent?.property?
 47
 48test "function invocation with soaked property access", ->
 49  id = (_) -> _
 50  eq undefined, id nonexistent?.method()
 51
 52test "if-to-ternary should safely parenthesize soaked property accesses", ->
 53  ok (if nonexistent?.property then false else true)
 54
 55test "#726: don't check for a property on a conditionally-referenced nonexistent thing", ->
 56  eq undefined, nonexistent?[Date()]
 57
 58test "#756: conditional assignment edge cases", ->
 59  # TODO: improve this test
 60  a = null
 61  ok isNaN      a?.b.c +  1
 62  eq undefined, a?.b.c += 1
 63  eq undefined, ++a?.b.c
 64  eq undefined, delete a?.b.c
 65
 66test "operations on soaked properties", ->
 67  # TODO: improve this test
 68  a = b: {c: 0}
 69  eq 1,   a?.b.c +  1
 70  eq 1,   a?.b.c += 1
 71  eq 2,   ++a?.b.c
 72  eq yes, delete a?.b.c
 73
 74
 75# Soaked Method Invocation
 76
 77test "soaked method invocation", ->
 78  nonce = {}
 79  counter = 0
 80  obj =
 81    self: -> @
 82    increment: -> counter++; @
 83  eq obj      , obj.self?()
 84  eq undefined, obj.method?()
 85  eq nonce    , obj.self?().property = nonce
 86  eq undefined, obj.method?().property = nonce
 87  eq obj      , obj.increment().increment().self?()
 88  eq 2        , counter
 89
 90test "#733: conditional assignments", ->
 91  a = b: {c: null}
 92  eq a.b?.c?(), undefined
 93  a.b?.c or= (it) -> it
 94  eq a.b?.c?(1), 1
 95  eq a.b?.c?([2, 3]...), 2
 96
 97
 98# Soaked Function Invocation
 99
100test "soaked function invocation", ->
101  nonce = {}
102  id = (_) -> _
103  eq nonce    , id?(nonce)
104  eq nonce    , (id? nonce)
105  eq undefined, nonexistent?(nonce)
106  eq undefined, (nonexistent? nonce)
107
108test "soaked function invocation with generated functions", ->
109  nonce = {}
110  id = (_) -> _
111  maybe = (fn, arg) -> if typeof fn is 'function' then () -> fn(arg)
112  eq maybe(id, nonce)?(), nonce
113  eq (maybe id, nonce)?(), nonce
114  eq (maybe false, nonce)?(), undefined
115
116test "soaked constructor invocation", ->
117  eq 42       , +new Number? 42
118  eq undefined,  new Other?  42
119
120test "soaked constructor invocations with caching and property access", ->
121  semaphore = 0
122  nonce = {}
123  class C
124    constructor: ->
125      ok false if semaphore
126      semaphore++
127    prop: nonce
128  eq nonce, (new C())?.prop
129  eq 1, semaphore
130
131test "soaked function invocation safe on non-functions", ->
132  eq undefined, (0)?(1)
133  eq undefined, (0)? 1, 2