1 | suite 'Operators', ->
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 | test 'binary maths operators do not require spaces', ->
|
14 | a = 1
|
15 | b = -1
|
16 | eq 1, a*-b
|
17 | eq -1, a*b
|
18 | eq 1, a/-b
|
19 | eq -1, a/b
|
20 |
|
21 | test 'operators should respect new lines as spaced', ->
|
22 | a = 123 +
|
23 | 456
|
24 | eq 579, a
|
25 |
|
26 | b = "1#{2}3" +
|
27 | '456'
|
28 | eq '123456', b
|
29 |
|
30 | test 'multiple operators should space themselves', ->
|
31 | eq (+ +1), (- -1)
|
32 |
|
33 | test 'bitwise operators', ->
|
34 | eq 2, (10 & 3)
|
35 | eq 11, (10 | 3)
|
36 | eq 9, (10 ^ 3)
|
37 | eq 80, (10 << 3)
|
38 | eq 1, (10 >> 3)
|
39 | eq 1, (10 >>> 3)
|
40 | num = 10; eq 2, (num &= 3)
|
41 | num = 10; eq 11, (num |= 3)
|
42 | num = 10; eq 9, (num ^= 3)
|
43 | num = 10; eq 80, (num <<= 3)
|
44 | num = 10; eq 1, (num >>= 3)
|
45 | num = 10; eq 1, (num >>>= 3)
|
46 |
|
47 | test 'instanceof', ->
|
48 | ok new String instanceof String
|
49 | ok new Boolean instanceof Boolean
|
50 |
|
51 | test 'not instanceof', ->
|
52 | ok new Number not instanceof String
|
53 | ok new Array not instanceof Boolean
|
54 |
|
55 | test "use `::` operator on keywords `this` and `@`", ->
|
56 | obj = prototype: prop: nonce = {}
|
57 | eq nonce, (-> @::prop).call obj
|
58 | eq nonce, (-> this::prop).call obj
|
59 |
|
60 |
|
61 | suite 'Existential Operator (Binary)', ->
|
62 |
|
63 | test "binary existential operator", ->
|
64 | nonce = {}
|
65 |
|
66 | b = a ? nonce
|
67 | eq nonce, b
|
68 |
|
69 | a = null
|
70 | b = undefined
|
71 | b = a ? nonce
|
72 | eq nonce, b
|
73 |
|
74 | a = false
|
75 | b = a ? nonce
|
76 | eq false, b
|
77 |
|
78 | a = 0
|
79 | b = a ? nonce
|
80 | eq 0, b
|
81 |
|
82 | test "binary existential operator conditionally evaluates second operand", ->
|
83 | i = 1
|
84 | func = -> i -= 1
|
85 | result = func() ? func()
|
86 | eq result, 0
|
87 |
|
88 | test "binary existential operator with negative number", ->
|
89 | a = null ? - 1
|
90 | eq -1, a
|
91 |
|
92 | test 'jashkenas/coffee-script#2026: exponentiation operator via `**`', ->
|
93 | eq 27, 3 ** 3
|
94 |
|
95 | eq 55, 1 + 3 ** 3 * 2
|
96 |
|
97 | eq 2, 2 ** 1 ** 3
|
98 | eq 2 ** 8, 2 ** 2 ** 3
|
99 |
|
100 | a = 2
|
101 | a **= 2
|
102 | eq 4, a
|
103 |
|
104 |
|
105 | suite 'Existential Operator (Unary)', ->
|
106 |
|
107 | test "postfix existential operator", ->
|
108 | ok (if nonexistent? then false else true)
|
109 | defined = true
|
110 | ok defined?
|
111 | defined = false
|
112 | ok defined?
|
113 |
|
114 | test "postfix existential operator only evaluates its operand once", ->
|
115 | semaphore = 0
|
116 | fn = ->
|
117 | ok false if semaphore
|
118 | ++semaphore
|
119 | ok(if fn()? then true else false)
|
120 |
|
121 | test "negated postfix existential operator", ->
|
122 | ok !nothing?.value
|
123 |
|
124 | test "postfix existential operator on expressions", ->
|
125 | eq true, (1 or 0)?, true
|
126 |
|
127 |
|
128 | suite '`is`,`isnt`,`==`,`!=`', ->
|
129 |
|
130 | test "`==` and `is` should be interchangeable", ->
|
131 | a = b = 1
|
132 | ok a is 1 and b == 1
|
133 | ok a == b
|
134 | ok a is b
|
135 |
|
136 | test "`!=` and `isnt` should be interchangeable", ->
|
137 | a = 0
|
138 | b = 1
|
139 | ok a isnt 1 and b != 0
|
140 | ok a != b
|
141 | ok a isnt b
|
142 |
|
143 |
|
144 | suite '[not] in/of', ->
|
145 |
|
146 |
|
147 |
|
148 | test "in, of", ->
|
149 | arr = [1]
|
150 | ok 0 of arr
|
151 | ok 1 in arr
|
152 |
|
153 | test 'not in, not of', ->
|
154 | arr = [1]
|
155 | ok 1 not of arr
|
156 | ok 0 not in arr
|
157 |
|
158 | test "`in` should be able to operate on an array literal", ->
|
159 | ok 2 in [0, 1, 2, 3]
|
160 | ok 4 not in [0, 1, 2, 3]
|
161 | arr = [0, 1, 2, 3]
|
162 | ok 2 in arr
|
163 | ok 4 not in arr
|
164 |
|
165 | arr = [0]
|
166 | val = 0
|
167 | ok val++ in arr
|
168 | ok val++ not in arr
|
169 | val = 0
|
170 | ok val++ of arr
|
171 | ok val++ not of arr
|
172 |
|
173 | test "`in` with cache and `__indexOf` should work in argument lists", ->
|
174 | eq 1, [Object() in Array()].length
|
175 |
|
176 | test "jashkenas/coffee-script#737: `in` should have higher precedence than logical operators", ->
|
177 | eq 1, 1 in [1] and 1
|
178 |
|
179 | test "jashkenas/coffee-script#768: `in` should preserve evaluation order", ->
|
180 | share = 0
|
181 | a = -> share++ if share is 0
|
182 | b = -> share++ if share is 1
|
183 | c = -> share++ if share is 2
|
184 | ok a() not in [b(),c()]
|
185 | eq 3, share
|
186 |
|
187 | test "jashkenas/coffee-script#1099: empty array after `in` should compile to `false`", ->
|
188 | eq 1, [5 in []].length
|
189 | eq false, do -> return 0 in []
|
190 |
|
191 | test "jashkenas/coffee-script#1354: optimized `in` checks should not happen when splats are present", ->
|
192 | a = [6, 9]
|
193 | eq 9 in [3, a...], true
|
194 |
|
195 | test "jashkenas/coffee-script#1100: precedence in or-test compilation of `in`", ->
|
196 | ok 0 in [1 and 0]
|
197 | ok 0 in [1, 1 and 0]
|
198 | ok not (0 in [1, 0 or 1])
|
199 |
|
200 | test "jashkenas/coffee-script#1630: `in` should check `hasOwnProperty`", ->
|
201 | ok undefined not in {length: 1}
|
202 |
|
203 |
|
204 |
|
205 |
|
206 |
|
207 |
|
208 |
|
209 |
|
210 |
|
211 |
|
212 | test "jashkenas/coffee-script#1099: statically determined `not in []` reporting incorrect result", ->
|
213 | ok 0 not in []
|
214 |
|
215 |
|
216 |
|
217 |
|
218 | test "chainable operators", ->
|
219 | ok 100 > 10 > 1 > 0 > -1
|
220 | ok -1 < 0 < 1 < 10 < 100
|
221 |
|
222 | test "`is` and `isnt` may be chained", ->
|
223 | ok true is not false is true is not false
|
224 | ok 0 is 0 isnt 1 is 1
|
225 |
|
226 | test "different comparison operators (`>`,`<`,`is`,etc.) may be combined", ->
|
227 | ok 1 < 2 > 1
|
228 | ok 10 < 20 > 2+3 is 5
|
229 |
|
230 | test "some chainable operators can be negated by `unless`", ->
|
231 | ok (true unless 0==10!=100)
|
232 |
|
233 | test "operator precedence: `|` lower than `<`", ->
|
234 | eq 1, 1 | 2 < 3 < 4
|
235 |
|
236 | test "preserve references", ->
|
237 | a = b = c = 1
|
238 |
|
239 |
|
240 | ok a == b <= c
|
241 |
|
242 | test "chained operations should evaluate each value only once", ->
|
243 | a = 0
|
244 | ok 1 > a++ < 1
|
245 |
|
246 |
|
247 |
|
248 |
|
249 |
|
250 | test "jashkenas/coffee-script#1234: Applying a splat to :: applies the splat to the wrong object", ->
|
251 | nonce = {}
|
252 | class C
|
253 | method: -> @nonce
|
254 | nonce: nonce
|
255 |
|
256 | arr = []
|
257 | eq nonce, C::method arr...
|
258 |
|
259 | test "jashkenas/coffee-script#1102: String literal prevents line continuation", ->
|
260 | eq "': '", '' +
|
261 | "': '"
|
262 |
|
263 | test "jashkenas/coffee-script#1703, ---x is invalid JS", ->
|
264 | x = 2
|
265 | eq (- --x), -1
|
266 |
|
267 |
|
268 |
|
269 |
|
270 |
|
271 |
|
272 | test "jashkenas/coffee-script#2155: conditional assignment to a closure", ->
|
273 | x = null
|
274 | func = -> x ?= (-> if true then 'hi')
|
275 | func()
|
276 | eq x(), 'hi'
|
277 |
|
278 | test "jashkenas/coffee-script#2197: Existential existential double trouble", ->
|
279 | counter = 0
|
280 | func = -> counter++
|
281 | func()? ? 100
|
282 | eq counter, 1
|
283 |
|
284 | test "#85: operands of ExistsOp must be coerced to expressions", ->
|
285 | f = ->
|
286 | f (a ? a?.b())
|
287 | f (a ? while 0 then)
|
288 |
|
289 | test "#89: extends operator has side effects and should not be optimised away", ->
|
290 | class A
|
291 | class B
|
292 | B extends A
|
293 | ok new B instanceof A
|