2010-12-29 00:48:54 -05:00
|
|
|
# Assignment
|
|
|
|
# ----------
|
|
|
|
|
2010-12-29 14:06:57 -05:00
|
|
|
# * Assignment
|
|
|
|
# * Compound Assignment
|
|
|
|
# * Destructuring Assignment
|
|
|
|
# * Context Property (@) Assignment
|
|
|
|
# * Existential Assignment (?=)
|
Fix #1500, #1574, #3318: Name generated vars uniquely
Any variables generated by CoffeeScript are now made sure to be named to
something not present in the source code being compiled. This way you can no
longer interfere with them, either on purpose or by mistake. (#1500, #1574)
For example, `({a}, _arg) ->` now compiles correctly. (#1574)
As opposed to the somewhat complex implementations discussed in #1500, this
commit takes a very simple approach by saving all used variables names using a
single pass over the token stream. Any generated variables are then made sure
not to exist in that list.
`(@a) -> a` used to be equivalent to `(@a) -> @a`, but now throws a runtime
`ReferenceError` instead (unless `a` exists in an upper scope of course). (#3318)
`(@a) ->` used to compile to `(function(a) { this.a = a; })`. Now it compiles to
`(function(_at_a) { this.a = _at_a; })`. (But you cannot access `_at_a` either,
of course.)
Because of the above, `(@a, a) ->` is now valid; `@a` and `a` are not duplicate
parameters.
Duplicate this-parameters with a reserved word, such as `(@case, @case) ->`,
used to compile but now throws, just like regular duplicate parameters.
2015-01-10 17:04:30 -05:00
|
|
|
# * Assignment to variables similar to generated variables
|
2010-12-29 14:06:57 -05:00
|
|
|
|
2010-12-29 00:48:54 -05:00
|
|
|
test "context property assignment (using @)", ->
|
|
|
|
nonce = {}
|
|
|
|
addMethod = ->
|
|
|
|
@method = -> nonce
|
|
|
|
this
|
|
|
|
eq nonce, addMethod.call({}).method()
|
|
|
|
|
|
|
|
test "unassignable values", ->
|
|
|
|
nonce = {}
|
|
|
|
for nonref in ['', '""', '0', 'f()'].concat CoffeeScript.RESERVED
|
|
|
|
eq nonce, (try CoffeeScript.compile "#{nonref} = v" catch e then nonce)
|
|
|
|
|
2011-03-11 21:41:12 -05:00
|
|
|
# Compound Assignment
|
2010-12-29 00:48:54 -05:00
|
|
|
|
2011-01-03 04:17:00 -05:00
|
|
|
test "boolean operators", ->
|
|
|
|
nonce = {}
|
|
|
|
|
|
|
|
a = 0
|
|
|
|
a or= nonce
|
|
|
|
eq nonce, a
|
|
|
|
|
|
|
|
b = 1
|
|
|
|
b or= nonce
|
|
|
|
eq 1, b
|
|
|
|
|
|
|
|
c = 0
|
|
|
|
c and= nonce
|
|
|
|
eq 0, c
|
|
|
|
|
|
|
|
d = 1
|
|
|
|
d and= nonce
|
|
|
|
eq nonce, d
|
|
|
|
|
|
|
|
# ensure that RHS is treated as a group
|
|
|
|
e = f = false
|
|
|
|
e and= f or true
|
|
|
|
eq false, e
|
|
|
|
|
|
|
|
test "compound assignment as a sub expression", ->
|
|
|
|
[a, b, c] = [1, 2, 3]
|
|
|
|
eq 6, (a + b += c)
|
|
|
|
eq 1, a
|
|
|
|
eq 5, b
|
|
|
|
eq 3, c
|
|
|
|
|
|
|
|
# *note: this test could still use refactoring*
|
|
|
|
test "compound assignment should be careful about caching variables", ->
|
|
|
|
count = 0
|
|
|
|
list = []
|
|
|
|
|
|
|
|
list[++count] or= 1
|
|
|
|
eq 1, list[1]
|
|
|
|
eq 1, count
|
|
|
|
|
|
|
|
list[++count] ?= 2
|
|
|
|
eq 2, list[2]
|
|
|
|
eq 2, count
|
|
|
|
|
|
|
|
list[count++] and= 6
|
|
|
|
eq 6, list[2]
|
|
|
|
eq 3, count
|
|
|
|
|
|
|
|
base = ->
|
|
|
|
++count
|
|
|
|
base
|
|
|
|
|
|
|
|
base().four or= 4
|
|
|
|
eq 4, base.four
|
|
|
|
eq 4, count
|
|
|
|
|
|
|
|
base().five ?= 5
|
|
|
|
eq 5, base.five
|
|
|
|
eq 5, count
|
|
|
|
|
2013-10-20 16:59:01 -04:00
|
|
|
eq 5, base().five ?= 6
|
|
|
|
eq 6, count
|
|
|
|
|
2011-01-03 04:17:00 -05:00
|
|
|
test "compound assignment with implicit objects", ->
|
|
|
|
obj = undefined
|
|
|
|
obj ?=
|
|
|
|
one: 1
|
|
|
|
|
|
|
|
eq 1, obj.one
|
|
|
|
|
|
|
|
obj and=
|
|
|
|
two: 2
|
|
|
|
|
|
|
|
eq undefined, obj.one
|
|
|
|
eq 2, obj.two
|
|
|
|
|
2010-12-29 00:48:54 -05:00
|
|
|
test "compound assignment (math operators)", ->
|
|
|
|
num = 10
|
|
|
|
num -= 5
|
|
|
|
eq 5, num
|
|
|
|
|
|
|
|
num *= 10
|
|
|
|
eq 50, num
|
|
|
|
|
|
|
|
num /= 10
|
|
|
|
eq 5, num
|
|
|
|
|
|
|
|
num %= 3
|
|
|
|
eq 2, num
|
|
|
|
|
|
|
|
test "more compound assignment", ->
|
|
|
|
a = {}
|
|
|
|
val = undefined
|
|
|
|
val ||= a
|
|
|
|
val ||= true
|
|
|
|
eq a, val
|
|
|
|
|
|
|
|
b = {}
|
|
|
|
val &&= true
|
|
|
|
eq val, true
|
|
|
|
val &&= b
|
|
|
|
eq b, val
|
|
|
|
|
|
|
|
c = {}
|
|
|
|
val = null
|
|
|
|
val ?= c
|
|
|
|
val ?= true
|
|
|
|
eq c, val
|
|
|
|
|
|
|
|
|
2011-03-11 21:41:12 -05:00
|
|
|
# Destructuring Assignment
|
2010-12-29 00:48:54 -05:00
|
|
|
|
2011-01-03 04:17:00 -05:00
|
|
|
test "empty destructuring assignment", ->
|
|
|
|
{} = [] = undefined
|
|
|
|
|
|
|
|
test "chained destructuring assignments", ->
|
|
|
|
[a] = {0: b} = {'0': c} = [nonce={}]
|
|
|
|
eq nonce, a
|
|
|
|
eq nonce, b
|
|
|
|
eq nonce, c
|
|
|
|
|
|
|
|
test "variable swapping to verify caching of RHS values when appropriate", ->
|
|
|
|
a = nonceA = {}
|
|
|
|
b = nonceB = {}
|
|
|
|
c = nonceC = {}
|
|
|
|
[a, b, c] = [b, c, a]
|
|
|
|
eq nonceB, a
|
|
|
|
eq nonceC, b
|
|
|
|
eq nonceA, c
|
|
|
|
[a, b, c] = [b, c, a]
|
|
|
|
eq nonceC, a
|
|
|
|
eq nonceA, b
|
|
|
|
eq nonceB, c
|
|
|
|
fn = ->
|
|
|
|
[a, b, c] = [b, c, a]
|
|
|
|
arrayEq [nonceA,nonceB,nonceC], fn()
|
|
|
|
eq nonceA, a
|
|
|
|
eq nonceB, b
|
|
|
|
eq nonceC, c
|
|
|
|
|
|
|
|
test "#713", ->
|
|
|
|
nonces = [nonceA={},nonceB={}]
|
|
|
|
eq nonces, [a, b] = [c, d] = nonces
|
|
|
|
eq nonceA, a
|
|
|
|
eq nonceA, c
|
|
|
|
eq nonceB, b
|
|
|
|
eq nonceB, d
|
|
|
|
|
|
|
|
test "destructuring assignment with splats", ->
|
|
|
|
a = {}; b = {}; c = {}; d = {}; e = {}
|
|
|
|
[x,y...,z] = [a,b,c,d,e]
|
|
|
|
eq a, x
|
|
|
|
arrayEq [b,c,d], y
|
|
|
|
eq e, z
|
|
|
|
|
|
|
|
test "deep destructuring assignment with splats", ->
|
|
|
|
a={}; b={}; c={}; d={}; e={}; f={}; g={}; h={}; i={}
|
|
|
|
[u, [v, w..., x], y..., z] = [a, [b, c, d, e], f, g, h, i]
|
|
|
|
eq a, u
|
|
|
|
eq b, v
|
|
|
|
arrayEq [c,d], w
|
|
|
|
eq e, x
|
|
|
|
arrayEq [f,g,h], y
|
|
|
|
eq i, z
|
|
|
|
|
|
|
|
test "destructuring assignment with objects", ->
|
|
|
|
a={}; b={}; c={}
|
|
|
|
obj = {a,b,c}
|
|
|
|
{a:x, b:y, c:z} = obj
|
|
|
|
eq a, x
|
|
|
|
eq b, y
|
|
|
|
eq c, z
|
|
|
|
|
|
|
|
test "deep destructuring assignment with objects", ->
|
|
|
|
a={}; b={}; c={}; d={}
|
|
|
|
obj = {
|
|
|
|
a
|
|
|
|
b: {
|
|
|
|
'c': {
|
|
|
|
d: [
|
|
|
|
b
|
|
|
|
{e: c, f: d}
|
|
|
|
]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{a: w, 'b': {c: d: [x, {'f': z, e: y}]}} = obj
|
|
|
|
eq a, w
|
|
|
|
eq b, x
|
|
|
|
eq c, y
|
|
|
|
eq d, z
|
|
|
|
|
|
|
|
test "destructuring assignment with objects and splats", ->
|
|
|
|
a={}; b={}; c={}; d={}
|
|
|
|
obj = a: b: [a, b, c, d]
|
|
|
|
{a: b: [y, z...]} = obj
|
|
|
|
eq a, y
|
|
|
|
arrayEq [b,c,d], z
|
|
|
|
|
|
|
|
test "destructuring assignment against an expression", ->
|
|
|
|
a={}; b={}
|
|
|
|
[y, z] = if true then [a, b] else [b, a]
|
|
|
|
eq a, y
|
|
|
|
eq b, z
|
|
|
|
|
2011-03-27 15:22:09 -04:00
|
|
|
test "bracket insertion when necessary", ->
|
|
|
|
[a] = [0] ? [1]
|
|
|
|
eq a, 0
|
|
|
|
|
2011-01-03 04:17:00 -05:00
|
|
|
# for implicit destructuring assignment in comprehensions, see the comprehension tests
|
|
|
|
|
|
|
|
test "destructuring assignment with context (@) properties", ->
|
|
|
|
a={}; b={}; c={}; d={}; e={}
|
|
|
|
obj =
|
|
|
|
fn: () ->
|
|
|
|
local = [a, {b, c}, d, e]
|
|
|
|
[@a, {b: @b, c: @c}, @d, @e] = local
|
|
|
|
eq undefined, obj[key] for key in ['a','b','c','d','e']
|
|
|
|
obj.fn()
|
|
|
|
eq a, obj.a
|
|
|
|
eq b, obj.b
|
|
|
|
eq c, obj.c
|
|
|
|
eq d, obj.d
|
|
|
|
eq e, obj.e
|
|
|
|
|
2011-01-10 23:09:21 -05:00
|
|
|
test "#1024", ->
|
|
|
|
eq 2 * [] = 3 + 5, 16
|
|
|
|
|
2011-08-11 01:11:33 -04:00
|
|
|
test "#1005: invalid identifiers allowed on LHS of destructuring assignment", ->
|
|
|
|
disallowed = ['eval', 'arguments'].concat CoffeeScript.RESERVED
|
2011-08-11 02:17:48 -04:00
|
|
|
throws (-> CoffeeScript.compile "[#{disallowed.join ', '}] = x"), null, 'all disallowed'
|
|
|
|
throws (-> CoffeeScript.compile "[#{disallowed.join '..., '}...] = x"), null, 'all disallowed as splats'
|
|
|
|
t = tSplat = null
|
2011-08-11 01:11:33 -04:00
|
|
|
for v in disallowed when v isnt 'class' # `class` by itself is an expression
|
2011-08-11 02:17:48 -04:00
|
|
|
throws (-> CoffeeScript.compile t), null, t = "[#{v}] = x"
|
|
|
|
throws (-> CoffeeScript.compile tSplat), null, tSplat = "[#{v}...] = x"
|
2011-08-11 01:11:33 -04:00
|
|
|
doesNotThrow ->
|
|
|
|
for v in disallowed
|
|
|
|
CoffeeScript.compile "[a.#{v}] = x"
|
|
|
|
CoffeeScript.compile "[a.#{v}...] = x"
|
|
|
|
CoffeeScript.compile "[@#{v}] = x"
|
|
|
|
CoffeeScript.compile "[@#{v}...] = x"
|
|
|
|
|
2012-01-18 23:12:50 -05:00
|
|
|
test "#2055: destructuring assignment with `new`", ->
|
|
|
|
{length} = new Array
|
|
|
|
eq 0, length
|
|
|
|
|
2014-01-24 11:00:34 -05:00
|
|
|
test "#156: destructuring with expansion", ->
|
|
|
|
array = [1..5]
|
|
|
|
[first, ..., last] = array
|
|
|
|
eq 1, first
|
|
|
|
eq 5, last
|
|
|
|
[..., lastButOne, last] = array
|
|
|
|
eq 4, lastButOne
|
|
|
|
eq 5, last
|
|
|
|
[first, second, ..., last] = array
|
|
|
|
eq 2, second
|
|
|
|
[..., last] = 'strings as well -> x'
|
|
|
|
eq 'x', last
|
|
|
|
throws (-> CoffeeScript.compile "[1, ..., 3]"), null, "prohibit expansion outside of assignment"
|
|
|
|
throws (-> CoffeeScript.compile "[..., a, b...] = c"), null, "prohibit expansion and a splat"
|
|
|
|
throws (-> CoffeeScript.compile "[...] = c"), null, "prohibit lone expansion"
|
|
|
|
|
2011-01-03 04:17:00 -05:00
|
|
|
|
2011-03-11 21:41:12 -05:00
|
|
|
# Existential Assignment
|
2011-01-03 04:17:00 -05:00
|
|
|
|
|
|
|
test "existential assignment", ->
|
|
|
|
nonce = {}
|
|
|
|
a = false
|
|
|
|
a ?= nonce
|
|
|
|
eq false, a
|
|
|
|
b = undefined
|
|
|
|
b ?= nonce
|
|
|
|
eq nonce, b
|
|
|
|
c = null
|
|
|
|
c ?= nonce
|
|
|
|
eq nonce, c
|
2011-09-21 23:01:05 -04:00
|
|
|
|
|
|
|
test "#1627: prohibit conditional assignment of undefined variables", ->
|
2011-10-03 21:57:33 -04:00
|
|
|
throws (-> CoffeeScript.compile "x ?= 10"), null, "prohibit (x ?= 10)"
|
|
|
|
throws (-> CoffeeScript.compile "x ||= 10"), null, "prohibit (x ||= 10)"
|
|
|
|
throws (-> CoffeeScript.compile "x or= 10"), null, "prohibit (x or= 10)"
|
|
|
|
throws (-> CoffeeScript.compile "do -> x ?= 10"), null, "prohibit (do -> x ?= 10)"
|
|
|
|
throws (-> CoffeeScript.compile "do -> x ||= 10"), null, "prohibit (do -> x ||= 10)"
|
|
|
|
throws (-> CoffeeScript.compile "do -> x or= 10"), null, "prohibit (do -> x or= 10)"
|
|
|
|
doesNotThrow (-> CoffeeScript.compile "x = null; x ?= 10"), "allow (x = null; x ?= 10)"
|
|
|
|
doesNotThrow (-> CoffeeScript.compile "x = null; x ||= 10"), "allow (x = null; x ||= 10)"
|
|
|
|
doesNotThrow (-> CoffeeScript.compile "x = null; x or= 10"), "allow (x = null; x or= 10)"
|
|
|
|
doesNotThrow (-> CoffeeScript.compile "x = null; do -> x ?= 10"), "allow (x = null; do -> x ?= 10)"
|
|
|
|
doesNotThrow (-> CoffeeScript.compile "x = null; do -> x ||= 10"), "allow (x = null; do -> x ||= 10)"
|
|
|
|
doesNotThrow (-> CoffeeScript.compile "x = null; do -> x or= 10"), "allow (x = null; do -> x or= 10)"
|
2013-02-01 06:07:19 -05:00
|
|
|
|
2011-10-03 21:57:33 -04:00
|
|
|
throws (-> CoffeeScript.compile "-> -> -> x ?= 10"), null, "prohibit (-> -> -> x ?= 10)"
|
|
|
|
doesNotThrow (-> CoffeeScript.compile "x = null; -> -> -> x ?= 10"), "allow (x = null; -> -> -> x ?= 10)"
|
2013-02-01 06:07:19 -05:00
|
|
|
|
2012-04-10 17:07:38 -04:00
|
|
|
test "more existential assignment", ->
|
|
|
|
global.temp ?= 0
|
|
|
|
eq global.temp, 0
|
|
|
|
global.temp or= 100
|
|
|
|
eq global.temp, 100
|
|
|
|
delete global.temp
|
2011-05-11 00:08:24 -04:00
|
|
|
|
2011-05-11 09:11:41 -04:00
|
|
|
test "#1348, #1216: existential assignment compilation", ->
|
2011-05-11 00:08:24 -04:00
|
|
|
nonce = {}
|
|
|
|
a = nonce
|
|
|
|
b = (a ?= 0)
|
|
|
|
eq nonce, b
|
2011-05-11 09:11:41 -04:00
|
|
|
#the first ?= compiles into a statement; the second ?= compiles to a ternary expression
|
|
|
|
eq a ?= b ?= 1, nonce
|
2013-02-01 06:07:19 -05:00
|
|
|
|
2011-05-11 09:11:41 -04:00
|
|
|
if a then a ?= 2 else a = 3
|
|
|
|
eq a, nonce
|
2011-08-30 11:12:39 -04:00
|
|
|
|
|
|
|
test "#1591, #1101: splatted expressions in destructuring assignment must be assignable", ->
|
|
|
|
nonce = {}
|
|
|
|
for nonref in ['', '""', '0', 'f()', '(->)'].concat CoffeeScript.RESERVED
|
|
|
|
eq nonce, (try CoffeeScript.compile "[#{nonref}...] = v" catch e then nonce)
|
2011-09-01 14:47:30 -04:00
|
|
|
|
2011-12-24 07:04:34 -05:00
|
|
|
test "#1643: splatted accesses in destructuring assignments should not be declared as variables", ->
|
2011-09-01 14:47:30 -04:00
|
|
|
nonce = {}
|
2011-09-09 18:59:35 -04:00
|
|
|
accesses = ['o.a', 'o["a"]', '(o.a)', '(o.a).a', '@o.a', 'C::a', 'C::', 'f().a', 'o?.a', 'o?.a.b', 'f?().a']
|
2011-09-01 14:47:30 -04:00
|
|
|
for access in accesses
|
2011-09-09 18:59:35 -04:00
|
|
|
for i,j in [1,2,3] #position can matter
|
2011-12-24 07:04:34 -05:00
|
|
|
code =
|
2011-09-09 21:30:00 -04:00
|
|
|
"""
|
2011-12-24 07:04:34 -05:00
|
|
|
nonce = {}; nonce2 = {}; nonce3 = {};
|
2011-09-09 21:30:00 -04:00
|
|
|
@o = o = new (class C then a:{}); f = -> o
|
|
|
|
[#{new Array(i).join('x,')}#{access}...] = [#{new Array(i).join('0,')}nonce, nonce2, nonce3]
|
|
|
|
unless #{access}[0] is nonce and #{access}[1] is nonce2 and #{access}[2] is nonce3 then throw new Error('[...]')
|
|
|
|
"""
|
2011-09-09 18:59:35 -04:00
|
|
|
eq nonce, unless (try CoffeeScript.run code, bare: true catch e then true) then nonce
|
|
|
|
# subpatterns like `[[a]...]` and `[{a}...]`
|
|
|
|
subpatterns = ['[sub, sub2, sub3]', '{0: sub, 1: sub2, 2: sub3}']
|
|
|
|
for subpattern in subpatterns
|
|
|
|
for i,j in [1,2,3]
|
|
|
|
code =
|
2011-09-09 21:30:00 -04:00
|
|
|
"""
|
2011-12-24 07:04:34 -05:00
|
|
|
nonce = {}; nonce2 = {}; nonce3 = {};
|
2011-09-09 21:30:00 -04:00
|
|
|
[#{new Array(i).join('x,')}#{subpattern}...] = [#{new Array(i).join('0,')}nonce, nonce2, nonce3]
|
|
|
|
unless sub is nonce and sub2 is nonce2 and sub3 is nonce3 then throw new Error('[sub...]')
|
|
|
|
"""
|
2011-09-09 18:59:35 -04:00
|
|
|
eq nonce, unless (try CoffeeScript.run code, bare: true catch e then true) then nonce
|
2011-12-14 18:31:20 -05:00
|
|
|
|
|
|
|
test "#1838: Regression with variable assignment", ->
|
|
|
|
name =
|
|
|
|
'dave'
|
2011-12-24 07:04:34 -05:00
|
|
|
|
|
|
|
eq name, 'dave'
|
2012-03-23 13:20:15 -04:00
|
|
|
|
|
|
|
test '#2211: splats in destructured parameters', ->
|
|
|
|
doesNotThrow -> CoffeeScript.compile '([a...]) ->'
|
|
|
|
doesNotThrow -> CoffeeScript.compile '([a...],b) ->'
|
|
|
|
doesNotThrow -> CoffeeScript.compile '([a...],[b...]) ->'
|
|
|
|
throws -> CoffeeScript.compile '([a...,[a...]]) ->'
|
|
|
|
doesNotThrow -> CoffeeScript.compile '([a...,[b...]]) ->'
|
2012-05-02 18:03:32 -04:00
|
|
|
|
|
|
|
test '#2213: invocations within destructured parameters', ->
|
|
|
|
throws -> CoffeeScript.compile '([a()])->'
|
|
|
|
throws -> CoffeeScript.compile '([a:b()])->'
|
|
|
|
throws -> CoffeeScript.compile '([a:b.c()])->'
|
|
|
|
throws -> CoffeeScript.compile '({a()})->'
|
|
|
|
throws -> CoffeeScript.compile '({a:b()})->'
|
|
|
|
throws -> CoffeeScript.compile '({a:b.c()})->'
|
2012-11-27 20:11:01 -05:00
|
|
|
|
|
|
|
test '#2532: compound assignment with terminator', ->
|
|
|
|
doesNotThrow -> CoffeeScript.compile """
|
|
|
|
a = "hello"
|
|
|
|
a +=
|
|
|
|
"
|
|
|
|
world
|
|
|
|
!
|
|
|
|
"
|
|
|
|
"""
|
2013-02-01 06:07:19 -05:00
|
|
|
|
|
|
|
test "#2613: parens on LHS of destructuring", ->
|
|
|
|
a = {}
|
|
|
|
[(a).b] = [1, 2, 3]
|
|
|
|
eq a.b, 1
|
2013-10-20 16:59:01 -04:00
|
|
|
|
|
|
|
test "#2181: conditional assignment as a subexpression", ->
|
|
|
|
a = false
|
|
|
|
false && a or= true
|
|
|
|
eq false, a
|
|
|
|
eq false, not a or= true
|
Fix #1500, #1574, #3318: Name generated vars uniquely
Any variables generated by CoffeeScript are now made sure to be named to
something not present in the source code being compiled. This way you can no
longer interfere with them, either on purpose or by mistake. (#1500, #1574)
For example, `({a}, _arg) ->` now compiles correctly. (#1574)
As opposed to the somewhat complex implementations discussed in #1500, this
commit takes a very simple approach by saving all used variables names using a
single pass over the token stream. Any generated variables are then made sure
not to exist in that list.
`(@a) -> a` used to be equivalent to `(@a) -> @a`, but now throws a runtime
`ReferenceError` instead (unless `a` exists in an upper scope of course). (#3318)
`(@a) ->` used to compile to `(function(a) { this.a = a; })`. Now it compiles to
`(function(_at_a) { this.a = _at_a; })`. (But you cannot access `_at_a` either,
of course.)
Because of the above, `(@a, a) ->` is now valid; `@a` and `a` are not duplicate
parameters.
Duplicate this-parameters with a reserved word, such as `(@case, @case) ->`,
used to compile but now throws, just like regular duplicate parameters.
2015-01-10 17:04:30 -05:00
|
|
|
|
|
|
|
test "#1500: Assignment to variables similar to generated variables", ->
|
2015-01-30 14:33:03 -05:00
|
|
|
len = 0
|
|
|
|
x = ((results = null; n) for n in [1, 2, 3])
|
Fix #1500, #1574, #3318: Name generated vars uniquely
Any variables generated by CoffeeScript are now made sure to be named to
something not present in the source code being compiled. This way you can no
longer interfere with them, either on purpose or by mistake. (#1500, #1574)
For example, `({a}, _arg) ->` now compiles correctly. (#1574)
As opposed to the somewhat complex implementations discussed in #1500, this
commit takes a very simple approach by saving all used variables names using a
single pass over the token stream. Any generated variables are then made sure
not to exist in that list.
`(@a) -> a` used to be equivalent to `(@a) -> @a`, but now throws a runtime
`ReferenceError` instead (unless `a` exists in an upper scope of course). (#3318)
`(@a) ->` used to compile to `(function(a) { this.a = a; })`. Now it compiles to
`(function(_at_a) { this.a = _at_a; })`. (But you cannot access `_at_a` either,
of course.)
Because of the above, `(@a, a) ->` is now valid; `@a` and `a` are not duplicate
parameters.
Duplicate this-parameters with a reserved word, such as `(@case, @case) ->`,
used to compile but now throws, just like regular duplicate parameters.
2015-01-10 17:04:30 -05:00
|
|
|
arrayEq [1, 2, 3], x
|
2015-01-30 14:33:03 -05:00
|
|
|
eq 0, len
|
Fix #1500, #1574, #3318: Name generated vars uniquely
Any variables generated by CoffeeScript are now made sure to be named to
something not present in the source code being compiled. This way you can no
longer interfere with them, either on purpose or by mistake. (#1500, #1574)
For example, `({a}, _arg) ->` now compiles correctly. (#1574)
As opposed to the somewhat complex implementations discussed in #1500, this
commit takes a very simple approach by saving all used variables names using a
single pass over the token stream. Any generated variables are then made sure
not to exist in that list.
`(@a) -> a` used to be equivalent to `(@a) -> @a`, but now throws a runtime
`ReferenceError` instead (unless `a` exists in an upper scope of course). (#3318)
`(@a) ->` used to compile to `(function(a) { this.a = a; })`. Now it compiles to
`(function(_at_a) { this.a = _at_a; })`. (But you cannot access `_at_a` either,
of course.)
Because of the above, `(@a, a) ->` is now valid; `@a` and `a` are not duplicate
parameters.
Duplicate this-parameters with a reserved word, such as `(@case, @case) ->`,
used to compile but now throws, just like regular duplicate parameters.
2015-01-10 17:04:30 -05:00
|
|
|
|
|
|
|
for x in [1, 2, 3]
|
|
|
|
f = ->
|
2015-01-30 14:33:03 -05:00
|
|
|
i = 0
|
Fix #1500, #1574, #3318: Name generated vars uniquely
Any variables generated by CoffeeScript are now made sure to be named to
something not present in the source code being compiled. This way you can no
longer interfere with them, either on purpose or by mistake. (#1500, #1574)
For example, `({a}, _arg) ->` now compiles correctly. (#1574)
As opposed to the somewhat complex implementations discussed in #1500, this
commit takes a very simple approach by saving all used variables names using a
single pass over the token stream. Any generated variables are then made sure
not to exist in that list.
`(@a) -> a` used to be equivalent to `(@a) -> @a`, but now throws a runtime
`ReferenceError` instead (unless `a` exists in an upper scope of course). (#3318)
`(@a) ->` used to compile to `(function(a) { this.a = a; })`. Now it compiles to
`(function(_at_a) { this.a = _at_a; })`. (But you cannot access `_at_a` either,
of course.)
Because of the above, `(@a, a) ->` is now valid; `@a` and `a` are not duplicate
parameters.
Duplicate this-parameters with a reserved word, such as `(@case, @case) ->`,
used to compile but now throws, just like regular duplicate parameters.
2015-01-10 17:04:30 -05:00
|
|
|
f()
|
2015-01-30 14:33:03 -05:00
|
|
|
eq 'undefined', typeof i
|
Fix #1500, #1574, #3318: Name generated vars uniquely
Any variables generated by CoffeeScript are now made sure to be named to
something not present in the source code being compiled. This way you can no
longer interfere with them, either on purpose or by mistake. (#1500, #1574)
For example, `({a}, _arg) ->` now compiles correctly. (#1574)
As opposed to the somewhat complex implementations discussed in #1500, this
commit takes a very simple approach by saving all used variables names using a
single pass over the token stream. Any generated variables are then made sure
not to exist in that list.
`(@a) -> a` used to be equivalent to `(@a) -> @a`, but now throws a runtime
`ReferenceError` instead (unless `a` exists in an upper scope of course). (#3318)
`(@a) ->` used to compile to `(function(a) { this.a = a; })`. Now it compiles to
`(function(_at_a) { this.a = _at_a; })`. (But you cannot access `_at_a` either,
of course.)
Because of the above, `(@a, a) ->` is now valid; `@a` and `a` are not duplicate
parameters.
Duplicate this-parameters with a reserved word, such as `(@case, @case) ->`,
used to compile but now throws, just like regular duplicate parameters.
2015-01-10 17:04:30 -05:00
|
|
|
|
2015-01-30 14:33:03 -05:00
|
|
|
ref = 2
|
|
|
|
x = ref * 2 ? 1
|
Fix #1500, #1574, #3318: Name generated vars uniquely
Any variables generated by CoffeeScript are now made sure to be named to
something not present in the source code being compiled. This way you can no
longer interfere with them, either on purpose or by mistake. (#1500, #1574)
For example, `({a}, _arg) ->` now compiles correctly. (#1574)
As opposed to the somewhat complex implementations discussed in #1500, this
commit takes a very simple approach by saving all used variables names using a
single pass over the token stream. Any generated variables are then made sure
not to exist in that list.
`(@a) -> a` used to be equivalent to `(@a) -> @a`, but now throws a runtime
`ReferenceError` instead (unless `a` exists in an upper scope of course). (#3318)
`(@a) ->` used to compile to `(function(a) { this.a = a; })`. Now it compiles to
`(function(_at_a) { this.a = _at_a; })`. (But you cannot access `_at_a` either,
of course.)
Because of the above, `(@a, a) ->` is now valid; `@a` and `a` are not duplicate
parameters.
Duplicate this-parameters with a reserved word, such as `(@case, @case) ->`,
used to compile but now throws, just like regular duplicate parameters.
2015-01-10 17:04:30 -05:00
|
|
|
eq x, 4
|
2015-01-30 14:33:03 -05:00
|
|
|
eq 'undefined', typeof ref1
|
Fix #1500, #1574, #3318: Name generated vars uniquely
Any variables generated by CoffeeScript are now made sure to be named to
something not present in the source code being compiled. This way you can no
longer interfere with them, either on purpose or by mistake. (#1500, #1574)
For example, `({a}, _arg) ->` now compiles correctly. (#1574)
As opposed to the somewhat complex implementations discussed in #1500, this
commit takes a very simple approach by saving all used variables names using a
single pass over the token stream. Any generated variables are then made sure
not to exist in that list.
`(@a) -> a` used to be equivalent to `(@a) -> @a`, but now throws a runtime
`ReferenceError` instead (unless `a` exists in an upper scope of course). (#3318)
`(@a) ->` used to compile to `(function(a) { this.a = a; })`. Now it compiles to
`(function(_at_a) { this.a = _at_a; })`. (But you cannot access `_at_a` either,
of course.)
Because of the above, `(@a, a) ->` is now valid; `@a` and `a` are not duplicate
parameters.
Duplicate this-parameters with a reserved word, such as `(@case, @case) ->`,
used to compile but now throws, just like regular duplicate parameters.
2015-01-10 17:04:30 -05:00
|
|
|
|
|
|
|
x = {}
|
2015-01-30 14:33:03 -05:00
|
|
|
base = -> x
|
|
|
|
name = -1
|
|
|
|
base()[-name] ?= 2
|
Fix #1500, #1574, #3318: Name generated vars uniquely
Any variables generated by CoffeeScript are now made sure to be named to
something not present in the source code being compiled. This way you can no
longer interfere with them, either on purpose or by mistake. (#1500, #1574)
For example, `({a}, _arg) ->` now compiles correctly. (#1574)
As opposed to the somewhat complex implementations discussed in #1500, this
commit takes a very simple approach by saving all used variables names using a
single pass over the token stream. Any generated variables are then made sure
not to exist in that list.
`(@a) -> a` used to be equivalent to `(@a) -> @a`, but now throws a runtime
`ReferenceError` instead (unless `a` exists in an upper scope of course). (#3318)
`(@a) ->` used to compile to `(function(a) { this.a = a; })`. Now it compiles to
`(function(_at_a) { this.a = _at_a; })`. (But you cannot access `_at_a` either,
of course.)
Because of the above, `(@a, a) ->` is now valid; `@a` and `a` are not duplicate
parameters.
Duplicate this-parameters with a reserved word, such as `(@case, @case) ->`,
used to compile but now throws, just like regular duplicate parameters.
2015-01-10 17:04:30 -05:00
|
|
|
eq x[1], 2
|
2015-01-30 14:33:03 -05:00
|
|
|
eq base(), x
|
|
|
|
eq name, -1
|
Fix #1500, #1574, #3318: Name generated vars uniquely
Any variables generated by CoffeeScript are now made sure to be named to
something not present in the source code being compiled. This way you can no
longer interfere with them, either on purpose or by mistake. (#1500, #1574)
For example, `({a}, _arg) ->` now compiles correctly. (#1574)
As opposed to the somewhat complex implementations discussed in #1500, this
commit takes a very simple approach by saving all used variables names using a
single pass over the token stream. Any generated variables are then made sure
not to exist in that list.
`(@a) -> a` used to be equivalent to `(@a) -> @a`, but now throws a runtime
`ReferenceError` instead (unless `a` exists in an upper scope of course). (#3318)
`(@a) ->` used to compile to `(function(a) { this.a = a; })`. Now it compiles to
`(function(_at_a) { this.a = _at_a; })`. (But you cannot access `_at_a` either,
of course.)
Because of the above, `(@a, a) ->` is now valid; `@a` and `a` are not duplicate
parameters.
Duplicate this-parameters with a reserved word, such as `(@case, @case) ->`,
used to compile but now throws, just like regular duplicate parameters.
2015-01-10 17:04:30 -05:00
|
|
|
|
2015-01-30 14:33:03 -05:00
|
|
|
f = (@a, a) -> [@a, a]
|
|
|
|
arrayEq [1, 2], f.call scope = {}, 1, 2
|
Fix #1500, #1574, #3318: Name generated vars uniquely
Any variables generated by CoffeeScript are now made sure to be named to
something not present in the source code being compiled. This way you can no
longer interfere with them, either on purpose or by mistake. (#1500, #1574)
For example, `({a}, _arg) ->` now compiles correctly. (#1574)
As opposed to the somewhat complex implementations discussed in #1500, this
commit takes a very simple approach by saving all used variables names using a
single pass over the token stream. Any generated variables are then made sure
not to exist in that list.
`(@a) -> a` used to be equivalent to `(@a) -> @a`, but now throws a runtime
`ReferenceError` instead (unless `a` exists in an upper scope of course). (#3318)
`(@a) ->` used to compile to `(function(a) { this.a = a; })`. Now it compiles to
`(function(_at_a) { this.a = _at_a; })`. (But you cannot access `_at_a` either,
of course.)
Because of the above, `(@a, a) ->` is now valid; `@a` and `a` are not duplicate
parameters.
Duplicate this-parameters with a reserved word, such as `(@case, @case) ->`,
used to compile but now throws, just like regular duplicate parameters.
2015-01-10 17:04:30 -05:00
|
|
|
eq 1, scope.a
|
|
|
|
|
2015-01-30 14:33:03 -05:00
|
|
|
doesNotThrow -> CoffeeScript.compile '(@slice...) ->'
|
2015-01-11 06:12:40 -05:00
|
|
|
|
|
|
|
test "Assignment to variables similar to helper functions", ->
|
2015-01-30 14:33:03 -05:00
|
|
|
f = (slice...) -> slice
|
2015-01-11 06:12:40 -05:00
|
|
|
arrayEq [1, 2, 3], f 1, 2, 3
|
2015-01-30 14:33:03 -05:00
|
|
|
eq 'undefined', typeof slice1
|
2015-01-11 06:12:40 -05:00
|
|
|
|
|
|
|
class A
|
|
|
|
class B extends A
|
2015-01-30 14:33:03 -05:00
|
|
|
extend = 3
|
|
|
|
hasProp = 4
|
2015-01-11 06:12:40 -05:00
|
|
|
value: 5
|
2015-01-30 14:33:03 -05:00
|
|
|
method: (bind, bind1) => [bind, bind1, extend, hasProp, @value]
|
2015-01-11 06:12:40 -05:00
|
|
|
{method} = new B
|
|
|
|
arrayEq [1, 2, 3, 4, 5], method 1, 2
|
|
|
|
|
2015-01-30 14:33:03 -05:00
|
|
|
modulo = -1 %% 3
|
|
|
|
eq 2, modulo
|
2015-01-11 06:12:40 -05:00
|
|
|
|
2015-01-30 14:33:03 -05:00
|
|
|
indexOf = [1, 2, 3]
|
|
|
|
ok 2 in indexOf
|