/test/operators.coffee

http://github.com/jashkenas/coffee-script · CoffeeScript · 453 lines · 339 code · 85 blank · 29 comment · 23 complexity · 4fa7985a93f13778c1890fadae2eaf4f MD5 · raw file

  1. # Operators
  2. # ---------
  3. # * Operators
  4. # * Existential Operator (Binary)
  5. # * Existential Operator (Unary)
  6. # * Aliased Operators
  7. # * [not] in/of
  8. # * Chained Comparison
  9. test "binary (2-ary) math operators do not require spaces", ->
  10. a = 1
  11. b = -1
  12. eq +1, a*-b
  13. eq -1, a*+b
  14. eq +1, a/-b
  15. eq -1, a/+b
  16. test "operators should respect new lines as spaced", ->
  17. a = 123 +
  18. 456
  19. eq 579, a
  20. b = "1#{2}3" +
  21. "456"
  22. eq '123456', b
  23. test "multiple operators should space themselves", ->
  24. eq (+ +1), (- -1)
  25. test "compound operators on successive lines", ->
  26. a = 1
  27. a +=
  28. 1
  29. eq a, 2
  30. test "bitwise operators", ->
  31. eq 2, (10 & 3)
  32. eq 11, (10 | 3)
  33. eq 9, (10 ^ 3)
  34. eq 80, (10 << 3)
  35. eq 1, (10 >> 3)
  36. eq 1, (10 >>> 3)
  37. num = 10; eq 2, (num &= 3)
  38. num = 10; eq 11, (num |= 3)
  39. num = 10; eq 9, (num ^= 3)
  40. num = 10; eq 80, (num <<= 3)
  41. num = 10; eq 1, (num >>= 3)
  42. num = 10; eq 1, (num >>>= 3)
  43. test "`instanceof`", ->
  44. ok new String instanceof String
  45. ok new Boolean instanceof Boolean
  46. # `instanceof` supports negation by prefixing the operator with `not`
  47. ok new Number not instanceof String
  48. ok new Array not instanceof Boolean
  49. test "use `::` operator on keywords `this` and `@`", ->
  50. nonce = {}
  51. obj =
  52. withAt: -> @::prop
  53. withThis: -> this::prop
  54. obj.prototype = prop: nonce
  55. eq nonce, obj.withAt()
  56. eq nonce, obj.withThis()
  57. # Existential Operator (Binary)
  58. test "binary existential operator", ->
  59. nonce = {}
  60. b = a ? nonce
  61. eq nonce, b
  62. a = null
  63. b = undefined
  64. b = a ? nonce
  65. eq nonce, b
  66. a = false
  67. b = a ? nonce
  68. eq false, b
  69. a = 0
  70. b = a ? nonce
  71. eq 0, b
  72. test "binary existential operator conditionally evaluates second operand", ->
  73. i = 1
  74. func = -> i -= 1
  75. result = func() ? func()
  76. eq result, 0
  77. test "binary existential operator with negative number", ->
  78. a = null ? - 1
  79. eq -1, a
  80. # Existential Operator (Unary)
  81. test "postfix existential operator", ->
  82. ok (if nonexistent? then false else true)
  83. defined = true
  84. ok defined?
  85. defined = false
  86. ok defined?
  87. test "postfix existential operator only evaluates its operand once", ->
  88. semaphore = 0
  89. fn = ->
  90. ok false if semaphore
  91. ++semaphore
  92. ok(if fn()? then true else false)
  93. test "negated postfix existential operator", ->
  94. ok !nothing?.value
  95. test "postfix existential operator on expressions", ->
  96. eq true, (1 or 0)?, true
  97. # `is`,`isnt`,`==`,`!=`
  98. test "`==` and `is` should be interchangeable", ->
  99. a = b = 1
  100. ok a is 1 and b == 1
  101. ok a == b
  102. ok a is b
  103. test "`!=` and `isnt` should be interchangeable", ->
  104. a = 0
  105. b = 1
  106. ok a isnt 1 and b != 0
  107. ok a != b
  108. ok a isnt b
  109. # [not] in/of
  110. # - `in` should check if an array contains a value using `indexOf`
  111. # - `of` should check if a property is defined on an object using `in`
  112. test "in, of", ->
  113. arr = [1]
  114. ok 0 of arr
  115. ok 1 in arr
  116. # prefixing `not` to `in and `of` should negate them
  117. ok 1 not of arr
  118. ok 0 not in arr
  119. test "`in` should be able to operate on an array literal", ->
  120. ok 2 in [0, 1, 2, 3]
  121. ok 4 not in [0, 1, 2, 3]
  122. arr = [0, 1, 2, 3]
  123. ok 2 in arr
  124. ok 4 not in arr
  125. # should cache the value used to test the array
  126. arr = [0]
  127. val = 0
  128. ok val++ in arr
  129. ok val++ not in arr
  130. val = 0
  131. ok val++ of arr
  132. ok val++ not of arr
  133. test "`of` and `in` should be able to operate on instance variables", ->
  134. obj = {
  135. list: [2,3]
  136. in_list: (value) -> value in @list
  137. not_in_list: (value) -> value not in @list
  138. of_list: (value) -> value of @list
  139. not_of_list: (value) -> value not of @list
  140. }
  141. ok obj.in_list 3
  142. ok obj.not_in_list 1
  143. ok obj.of_list 0
  144. ok obj.not_of_list 2
  145. test "#???: `in` with cache and `__indexOf` should work in argument lists", ->
  146. eq 1, [Object() in Array()].length
  147. test "#737: `in` should have higher precedence than logical operators", ->
  148. eq 1, 1 in [1] and 1
  149. test "#768: `in` should preserve evaluation order", ->
  150. share = 0
  151. a = -> share++ if share is 0
  152. b = -> share++ if share is 1
  153. c = -> share++ if share is 2
  154. ok a() not in [b(),c()]
  155. eq 3, share
  156. test "#1099: empty array after `in` should compile to `false`", ->
  157. eq 1, [5 in []].length
  158. eq false, do -> return 0 in []
  159. test "#1354: optimized `in` checks should not happen when splats are present", ->
  160. a = [6, 9]
  161. eq 9 in [3, a...], true
  162. test "#1100: precedence in or-test compilation of `in`", ->
  163. ok 0 in [1 and 0]
  164. ok 0 in [1, 1 and 0]
  165. ok not (0 in [1, 0 or 1])
  166. test "#1630: `in` should check `hasOwnProperty`", ->
  167. ok undefined not in length: 1
  168. test "#1714: lexer bug with raw range `for` followed by `in`", ->
  169. 0 for [1..2]
  170. ok not ('a' in ['b'])
  171. 0 for [1..2]; ok not ('a' in ['b'])
  172. 0 for [1..10] # comment ending
  173. ok not ('a' in ['b'])
  174. # lexer state (specifically @seenFor) should be reset before each compilation
  175. CoffeeScript.compile "0 for [1..2]"
  176. CoffeeScript.compile "'a' in ['b']"
  177. test "#1099: statically determined `not in []` reporting incorrect result", ->
  178. ok 0 not in []
  179. test "#1099: make sure expression tested gets evaluted when array is empty", ->
  180. a = 0
  181. (do -> a = 1) in []
  182. eq a, 1
  183. # Chained Comparison
  184. test "chainable operators", ->
  185. ok 100 > 10 > 1 > 0 > -1
  186. ok -1 < 0 < 1 < 10 < 100
  187. test "`is` and `isnt` may be chained", ->
  188. ok true is not false is true is not false
  189. ok 0 is 0 isnt 1 is 1
  190. test "different comparison operators (`>`,`<`,`is`,etc.) may be combined", ->
  191. ok 1 < 2 > 1
  192. ok 10 < 20 > 2+3 is 5
  193. test "some chainable operators can be negated by `unless`", ->
  194. ok (true unless 0==10!=100)
  195. test "operator precedence: `|` lower than `<`", ->
  196. eq 1, 1 | 2 < 3 < 4
  197. test "preserve references", ->
  198. a = b = c = 1
  199. # `a == b <= c` should become `a === b && b <= c`
  200. # (this test does not seem to test for this)
  201. ok a == b <= c
  202. test "chained operations should evaluate each value only once", ->
  203. a = 0
  204. ok 1 > a++ < 1
  205. test "#891: incorrect inversion of chained comparisons", ->
  206. ok (true unless 0 > 1 > 2)
  207. ok (true unless (this.NaN = 0/0) < 0/0 < this.NaN)
  208. test "#1234: Applying a splat to :: applies the splat to the wrong object", ->
  209. nonce = {}
  210. class C
  211. method: -> @nonce
  212. nonce: nonce
  213. arr = []
  214. eq nonce, C::method arr... # should be applied to `C::`
  215. test "#1102: String literal prevents line continuation", ->
  216. eq "': '", '' +
  217. "': '"
  218. test "#1703, ---x is invalid JS", ->
  219. x = 2
  220. eq (- --x), -1
  221. test "Regression with implicit calls against an indented assignment", ->
  222. eq 1, a =
  223. 1
  224. eq a, 1
  225. test "#2155 ... conditional assignment to a closure", ->
  226. x = null
  227. func = -> x ?= (-> if true then 'hi')
  228. func()
  229. eq x(), 'hi'
  230. test "#2197: Existential existential double trouble", ->
  231. counter = 0
  232. func = -> counter++
  233. func()? ? 100
  234. eq counter, 1
  235. test "#2567: Optimization of negated existential produces correct result", ->
  236. a = 1
  237. ok !(!a?)
  238. ok !b?
  239. test "#2508: Existential access of the prototype", ->
  240. eq NonExistent?::nothing, undefined
  241. eq(
  242. NonExistent
  243. ?::nothing
  244. undefined
  245. )
  246. ok Object?::toString
  247. ok(
  248. Object
  249. ?::toString
  250. )
  251. test "floor division operator", ->
  252. eq 2, 7 // 3
  253. eq -3, -7 // 3
  254. eq NaN, 0 // 0
  255. test "floor division operator compound assignment", ->
  256. a = 7
  257. a //= 1 + 1
  258. eq 3, a
  259. test "modulo operator", ->
  260. check = (a, b, expected) ->
  261. eq expected, a %% b, "expected #{a} %%%% #{b} to be #{expected}"
  262. check 0, 1, 0
  263. check 0, -1, -0
  264. check 1, 0, NaN
  265. check 1, 2, 1
  266. check 1, -2, -1
  267. check 1, 3, 1
  268. check 2, 3, 2
  269. check 3, 3, 0
  270. check 4, 3, 1
  271. check -1, 3, 2
  272. check -2, 3, 1
  273. check -3, 3, 0
  274. check -4, 3, 2
  275. check 5.5, 2.5, 0.5
  276. check -5.5, 2.5, 2.0
  277. test "modulo operator compound assignment", ->
  278. a = -2
  279. a %%= 5
  280. eq 3, a
  281. test "modulo operator converts arguments to numbers", ->
  282. eq 1, 1 %% '42'
  283. eq 1, '1' %% 42
  284. eq 1, '1' %% '42'
  285. test "#3361: Modulo operator coerces right operand once", ->
  286. count = 0
  287. res = 42 %% valueOf: -> count += 1
  288. eq 1, count
  289. eq 0, res
  290. test "#3363: Modulo operator coercing order", ->
  291. count = 2
  292. a = valueOf: -> count *= 2
  293. b = valueOf: -> count += 1
  294. eq 4, a %% b
  295. eq 5, count
  296. test "#3598: Unary + and - coerce the operand once when it is an identifier", ->
  297. # Unary + and - do not generate `_ref`s when the operand is a number, for
  298. # readability. To make sure that they do when the operand is an identifier,
  299. # test that they are consistent with another unary operator as well as another
  300. # complex expression.
  301. # Tip: Making one of the tests temporarily fail lets you easily inspect the
  302. # compiled JavaScript.
  303. assertOneCoercion = (fn) ->
  304. count = 0
  305. value = valueOf: -> count++; 1
  306. fn value
  307. eq 1, count
  308. eq 1, 1 ? 0
  309. eq 1, +1 ? 0
  310. eq -1, -1 ? 0
  311. assertOneCoercion (a) ->
  312. eq 1, +a ? 0
  313. assertOneCoercion (a) ->
  314. eq -1, -a ? 0
  315. assertOneCoercion (a) ->
  316. eq -2, ~a ? 0
  317. assertOneCoercion (a) ->
  318. eq 0.5, a / 2 ? 0
  319. ok -2 <= 1 < 2
  320. ok -2 <= +1 < 2
  321. ok -2 <= -1 < 2
  322. assertOneCoercion (a) ->
  323. ok -2 <= +a < 2
  324. assertOneCoercion (a) ->
  325. ok -2 <= -a < 2
  326. assertOneCoercion (a) ->
  327. ok -2 <= ~a < 2
  328. assertOneCoercion (a) ->
  329. ok -2 <= a / 2 < 2
  330. arrayEq [0], (n for n in [0] by 1)
  331. arrayEq [0], (n for n in [0] by +1)
  332. arrayEq [0], (n for n in [0] by -1)
  333. assertOneCoercion (a) ->
  334. arrayEq [0], (n for n in [0] by +a)
  335. assertOneCoercion (a) ->
  336. arrayEq [0], (n for n in [0] by -a)
  337. assertOneCoercion (a) ->
  338. arrayEq [0], (n for n in [0] by ~a)
  339. assertOneCoercion (a) ->
  340. arrayEq [0], (n for n in [0] by a * 2 / 2)
  341. ok 1 in [0, 1]
  342. ok +1 in [0, 1]
  343. ok -1 in [0, -1]
  344. assertOneCoercion (a) ->
  345. ok +a in [0, 1]
  346. assertOneCoercion (a) ->
  347. ok -a in [0, -1]
  348. assertOneCoercion (a) ->
  349. ok ~a in [0, -2]
  350. assertOneCoercion (a) ->
  351. ok a / 2 in [0, 0.5]
  352. test "'new' target", ->
  353. nonce = {}
  354. ctor = -> nonce
  355. eq (new ctor), nonce
  356. eq (new ctor()), nonce
  357. ok new class
  358. ctor = class
  359. ok (new ctor) instanceof ctor
  360. ok (new ctor()) instanceof ctor
  361. # Force an executable class body
  362. ctor = class then a = 1
  363. ok (new ctor) instanceof ctor
  364. get = -> ctor
  365. ok (new get()) not instanceof ctor
  366. ok (new (get())()) instanceof ctor
  367. # classes must be called with `new`. In this case `new` applies to `get` only
  368. throws -> new get()()