UNPKG

11.1 kBtext/coffeescriptView Raw
1suite 'Assignment', ->
2# ----------
3
4# * Assignment
5# * Compound Assignment
6# * Destructuring Assignment
7# * Context Property (@) Assignment
8# * Existential Assignment (?=)
9
10 suite 'Regular Assignment', ->
11
12 test "context property assignment (using @)", ->
13 nonce = {}
14 addMethod = ->
15 @method = -> nonce
16 this
17 eq nonce, addMethod.call({}).method()
18
19 #test "unassignable values", ->
20 # nonce = {}
21 # for nonref in ['', '""', '0', 'f()'].concat CoffeeScript.RESERVED
22 # eq nonce, (try CoffeeScript.compile "#{nonref} = v" catch e then nonce)
23
24 suite 'Compound Assignment', ->
25
26 test "boolean operators", ->
27 nonce = {}
28
29 a = 0
30 a or= nonce
31 eq nonce, a
32
33 b = 1
34 b or= nonce
35 eq 1, b
36
37 c = 0
38 c and= nonce
39 eq 0, c
40
41 d = 1
42 d and= nonce
43 eq nonce, d
44
45 # ensure that RHS is treated as a group
46 e = f = false
47 e and= f or true
48 eq false, e
49
50 test "compound assignment as a sub expression", ->
51 [a, b, c] = [1, 2, 3]
52 eq 6, a + (b += c)
53 eq 1, a
54 eq 5, b
55 eq 3, c
56
57 # *note: this test could still use refactoring*
58 #test "compound assignment should be careful about caching variables", ->
59 # count = 0
60 # list = []
61
62 # list[++count] or= 1
63 # eq 1, list[1]
64 # eq 1, count
65
66 # list[++count] ?= 2
67 # eq 2, list[2]
68 # eq 2, count
69
70 # list[count++] and= 6
71 # eq 6, list[2]
72 # eq 3, count
73
74 # base = ->
75 # ++count
76 # base
77
78 # base().four or= 4
79 # eq 4, base.four
80 # eq 4, count
81
82 # base().five ?= 5
83 # eq 5, base.five
84 # eq 5, count
85
86 test "compound assignment with implicit objects", ->
87 obj = undefined
88 obj ?=
89 one: 1
90
91 eq 1, obj.one
92
93 obj and=
94 two: 2
95
96 eq undefined, obj.one
97 eq 2, obj.two
98
99 test "compound assignment (math operators)", ->
100 num = 10
101 num -= 5
102 eq 5, num
103
104 num *= 10
105 eq 50, num
106
107 num /= 10
108 eq 5, num
109
110 num %= 3
111 eq 2, num
112
113 test "more compound assignment", ->
114 a = {}
115 val = undefined
116 val ||= a
117 val ||= true
118 eq a, val
119
120 b = {}
121 val &&= true
122 eq val, true
123 val &&= b
124 eq b, val
125
126 c = {}
127 val = null
128 val ?= c
129 val ?= true
130 eq c, val
131
132
133 suite 'Destructuring Assignment', ->
134
135 test "empty destructuring assignment", ->
136 {} = [] = undefined
137
138 test "chained destructuring assignments", ->
139 [a] = {0: b} = {'0': c} = [nonce={}]
140 eq nonce, a
141 eq nonce, b
142 eq nonce, c
143
144 test "variable swapping to verify caching of RHS values when appropriate", ->
145 a = nonceA = {}
146 b = nonceB = {}
147 c = nonceC = {}
148 [a, b, c] = [b, c, a]
149 eq nonceB, a
150 eq nonceC, b
151 eq nonceA, c
152 [a, b, c] = [b, c, a]
153 eq nonceC, a
154 eq nonceA, b
155 eq nonceB, c
156 fn = ->
157 [a, b, c] = [b, c, a]
158 arrayEq [nonceA,nonceB,nonceC], fn()
159 eq nonceA, a
160 eq nonceB, b
161 eq nonceC, c
162
163 test "#713", ->
164 nonces = [nonceA={},nonceB={}]
165 eq nonces, [a, b] = [c, d] = nonces
166 eq nonceA, a
167 eq nonceA, c
168 eq nonceB, b
169 eq nonceB, d
170
171 test "destructuring assignment with splats", ->
172 a = {}; b = {}; c = {}; d = {}; e = {}
173 [x,y...,z] = [a,b,c,d,e]
174 eq a, x
175 arrayEq [b,c,d], y
176 eq e, z
177
178 test "deep destructuring assignment with splats", ->
179 a={}; b={}; c={}; d={}; e={}; f={}; g={}; h={}; i={}
180 [u, [v, w..., x], y..., z] = [a, [b, c, d, e], f, g, h, i]
181 eq a, u
182 eq b, v
183 arrayEq [c,d], w
184 eq e, x
185 arrayEq [f,g,h], y
186 eq i, z
187
188 test "destructuring assignment with objects", ->
189 a={}; b={}; c={}
190 obj = {a,b,c}
191 {a:x, b:y, c:z} = obj
192 eq a, x
193 eq b, y
194 eq c, z
195
196 test "deep destructuring assignment with objects", ->
197 a={}; b={}; c={}; d={}
198 obj = {a, b: {'c': {d: [b, {e: c, f: d}]}}}
199 {a: w, 'b': {c: {d: [x, {'f': z, e: y}]}}} = obj
200 eq a, w
201 eq b, x
202 eq c, y
203 eq d, z
204
205 test "destructuring assignment with objects and splats", ->
206 a={}; b={}; c={}; d={}
207 obj = a: b: [a, b, c, d]
208 {a: {b: [y, z...]}} = obj
209 eq a, y
210 arrayEq [b,c,d], z
211
212 test "destructuring assignment against an expression", ->
213 a={}; b={}
214 [y, z] = if true then [a, b] else [b, a]
215 eq a, y
216 eq b, z
217
218 test "bracket insertion when necessary", ->
219 [a] = [0] ? [1]
220 eq a, 0
221
222 # for implicit destructuring assignment in comprehensions, see the comprehension tests
223
224 test "destructuring assignment with context (@) properties", ->
225 a={}; b={}; c={}; d={}; e={}
226 obj =
227 fn: ->
228 local = [a, {b, c}, d, e]
229 [@a, {b: @b, c: @c}, @d, @e] = local
230 eq undefined, obj[key] for key in ['a','b','c','d','e']
231 obj.fn()
232 eq a, obj.a
233 eq b, obj.b
234 eq c, obj.c
235 eq d, obj.d
236 eq e, obj.e
237
238 #test "#1024", ->
239 # eq 2 * ([] = 3 + 5), 16
240
241 #test "#1005: invalid identifiers allowed on LHS of destructuring assignment", ->
242 # disallowed = ['eval', 'arguments'].concat CoffeeScript.RESERVED
243 # throws (-> CoffeeScript.compile "[#{disallowed.join ', '}] = x"), null, 'all disallowed'
244 # throws (-> CoffeeScript.compile "[#{disallowed.join '..., '}...] = x"), null, 'all disallowed as splats'
245 # t = tSplat = null
246 # for v in disallowed when v isnt 'class' # `class` by itself is an expression
247 # throws (-> CoffeeScript.compile t), null, t = "[#{v}] = x"
248 # throws (-> CoffeeScript.compile tSplat), null, tSplat = "[#{v}...] = x"
249 # doesNotThrow ->
250 # for v in disallowed
251 # CoffeeScript.compile "[a.#{v}] = x"
252 # CoffeeScript.compile "[a.#{v}...] = x"
253 # CoffeeScript.compile "[@#{v}] = x"
254 # CoffeeScript.compile "[@#{v}...] = x"
255
256 test "#2055: destructuring assignment with `new`", ->
257 {length} = new Array
258 eq 0, length
259
260
261 suite 'Existential Assignment', ->
262
263 test "existential assignment", ->
264 nonce = {}
265 a = false
266 a ?= nonce
267 eq false, a
268 b = undefined
269 b ?= nonce
270 eq nonce, b
271 c = null
272 c ?= nonce
273 eq nonce, c
274
275 #test "#1627: prohibit conditional assignment of undefined variables", ->
276 # throws (-> CoffeeScript.compile "x ?= 10"), null, "prohibit (x ?= 10)"
277 # throws (-> CoffeeScript.compile "x ||= 10"), null, "prohibit (x ||= 10)"
278 # throws (-> CoffeeScript.compile "x or= 10"), null, "prohibit (x or= 10)"
279 # throws (-> CoffeeScript.compile "do -> x ?= 10"), null, "prohibit (do -> x ?= 10)"
280 # throws (-> CoffeeScript.compile "do -> x ||= 10"), null, "prohibit (do -> x ||= 10)"
281 # throws (-> CoffeeScript.compile "do -> x or= 10"), null, "prohibit (do -> x or= 10)"
282 # doesNotThrow (-> CoffeeScript.compile "x = null; x ?= 10"), "allow (x = null; x ?= 10)"
283 # doesNotThrow (-> CoffeeScript.compile "x = null; x ||= 10"), "allow (x = null; x ||= 10)"
284 # doesNotThrow (-> CoffeeScript.compile "x = null; x or= 10"), "allow (x = null; x or= 10)"
285 # doesNotThrow (-> CoffeeScript.compile "x = null; do -> x ?= 10"), "allow (x = null; do -> x ?= 10)"
286 # doesNotThrow (-> CoffeeScript.compile "x = null; do -> x ||= 10"), "allow (x = null; do -> x ||= 10)"
287 # doesNotThrow (-> CoffeeScript.compile "x = null; do -> x or= 10"), "allow (x = null; do -> x or= 10)"
288
289 # throws (-> CoffeeScript.compile "-> -> -> x ?= 10"), null, "prohibit (-> -> -> x ?= 10)"
290 # doesNotThrow (-> CoffeeScript.compile "x = null; -> -> -> x ?= 10"), "allow (x = null; -> -> -> x ?= 10)"
291
292 test "more existential assignment", ->
293 obj = {}
294 obj.temp ?= 0
295 eq obj.temp, 0
296 obj.temp or= 100
297 eq obj.temp, 100
298
299 test "#1348, #1216: existential assignment compilation", ->
300 nonce = {}
301 a = nonce
302 b = (a ?= 0)
303 eq nonce, b
304 #the first ?= compiles into a statement; the second ?= compiles to a ternary expression
305 eq a ?= b ?= 1, nonce
306
307 if a then a ?= 2 else a = 3
308 eq a, nonce
309
310 #test "#1591, #1101: splatted expressions in destructuring assignment must be assignable", ->
311 # nonce = {}
312 # for nonref in ['', '""', '0', 'f()', '(->)'].concat CoffeeScript.RESERVED
313 # eq nonce, (try CoffeeScript.compile "[#{nonref}...] = v" catch e then nonce)
314
315 #test "#1643: splatted accesses in destructuring assignments should not be declared as variables", ->
316 # nonce = {}
317 # accesses = ['o.a', 'o["a"]', '(o.a)', '(o.a).a', '@o.a', 'C::a', 'C::', 'f().a', 'o?.a', 'o?.a.b', 'f?().a']
318 # for access in accesses
319 # for i,j in [1,2,3] #position can matter
320 # code =
321 # """
322 # nonce = {}; nonce2 = {}; nonce3 = {};
323 # @o = o = new (class C then a:{}); f = -> o
324 # [#{new Array(i).join('x,')}#{access}...] = [#{new Array(i).join('0,')}nonce, nonce2, nonce3]
325 # unless #{access}[0] is nonce and #{access}[1] is nonce2 and #{access}[2] is nonce3 then throw new Error('[...]')
326 # """
327 # eq nonce, unless (try CoffeeScript.run code, bare: true catch e then true) then nonce
328 # # subpatterns like `[[a]...]` and `[{a}...]`
329 # subpatterns = ['[sub, sub2, sub3]', '{0: sub, 1: sub2, 2: sub3}']
330 # for subpattern in subpatterns
331 # for i,j in [1,2,3]
332 # code =
333 # """
334 # nonce = {}; nonce2 = {}; nonce3 = {};
335 # [#{new Array(i).join('x,')}#{subpattern}...] = [#{new Array(i).join('0,')}nonce, nonce2, nonce3]
336 # unless sub is nonce and sub2 is nonce2 and sub3 is nonce3 then throw new Error('[sub...]')
337 # """
338 # eq nonce, unless (try CoffeeScript.run code, bare: true catch e then true) then nonce
339
340 test "#1838: Regression with variable assignment", ->
341 name =
342 'dave'
343
344 eq name, 'dave'
345
346 #test 'jashkenas/coffee-script#2211: splats in destructured parameters', ->
347 # doesNotThrow -> CoffeeScript.compile '([a...]) ->'
348 # doesNotThrow -> CoffeeScript.compile '([a...],b) ->'
349 # doesNotThrow -> CoffeeScript.compile '([a...],[b...]) ->'
350 # throws -> CoffeeScript.compile '([a...,[a...]]) ->'
351 # doesNotThrow -> CoffeeScript.compile '([a...,[b...]]) ->'
352
353 #test 'jashkenas/coffee-script#2213: invocations within destructured parameters', ->
354 # throws -> CoffeeScript.compile '([a()])->'
355 # throws -> CoffeeScript.compile '([a:b()])->'
356 # throws -> CoffeeScript.compile '([a:b.c()])->'
357 # throws -> CoffeeScript.compile '({a()})->'
358 # throws -> CoffeeScript.compile '({a:b()})->'
359 # throws -> CoffeeScript.compile '({a:b.c()})->'
360
361 test '#72: parsing assignment fails when the assignee is member access of a result of a call', ->
362 f = (o) -> o
363 g = -> this
364 nonce = {}
365
366 obj = {}
367 f(obj).a = nonce
368 eq nonce, obj.a
369
370 obj = {g: g}
371 obj.g().a = nonce
372 eq nonce, obj.a