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