Prohibiting conditional assignment of undefined variables for #1627.

This commit is contained in:
Jeremy Banks 2011-09-21 23:01:05 -04:00
parent 52dd348289
commit 036197fac3
3 changed files with 16 additions and 15 deletions

View File

@ -1388,6 +1388,9 @@
Assign.prototype.compileConditional = function(o) {
var left, rite, _ref2;
_ref2 = this.variable.cacheReference(o), left = _ref2[0], rite = _ref2[1];
if (left.base instanceof Literal && IDENTIFIER.test(left.base.value) && left.base.value !== "this" && !o.scope.check(left.base.value)) {
throw new Error("" + left.base.value + " can't be re-assigned with " + this.context + " because it's not defined in lexical scope.");
}
if (__indexOf.call(this.context, "?") >= 0) o.isExistentialEquals = true;
return new Op(this.context.slice(0, -1), left, new Assign(rite, this.value, '=')).compile(o);
};

View File

@ -1048,6 +1048,9 @@ exports.Assign = class Assign extends Base
# more than once.
compileConditional: (o) ->
[left, rite] = @variable.cacheReference o
# Disallow conditional assignment of undefined variables.
if left.base instanceof Literal and IDENTIFIER.test(left.base.value) and left.base.value != "this" and not o.scope.check left.base.value
throw new Error "#{left.base.value} can't be re-assigned with #{@context} because it's not defined in lexical scope."
if "?" in @context then o.isExistentialEquals = true
new Op(@context[0...-1], left, new Assign(rite, @value, '=') ).compile o

View File

@ -19,12 +19,6 @@ test "unassignable values", ->
for nonref in ['', '""', '0', 'f()'].concat CoffeeScript.RESERVED
eq nonce, (try CoffeeScript.compile "#{nonref} = v" catch e then nonce)
test "compound assignments should not declare", ->
# TODO: make description more clear
# TODO: remove reference to Math
eq Math, (-> Math or= 0)()
# Compound Assignment
test "boolean operators", ->
@ -281,8 +275,16 @@ test "existential assignment", ->
c = null
c ?= nonce
eq nonce, c
d ?= nonce
eq nonce, d
test "#1627: prohibit conditional assignment of undefined variables", ->
nonce = {}
eq nonce, (try CoffeeScript.compile "x ?= 10"; false catch e then nonce), "prohibit (x ?= 10)"
eq nonce, (try CoffeeScript.compile("x = null; x ?= 10"); nonce), "allow (x = null; x ?= 10)"
eq nonce, (try CoffeeScript.compile "x ||= 10"; false catch e then nonce), "prohibit (x ||= 10)"
eq nonce, (try CoffeeScript.compile("x = null; x ||= 10"); nonce), "allow (x = null; x ||= 10)"
eq nonce, (try CoffeeScript.compile "x or= 10"; false catch e then nonce), "prohibit (x or= 10)"
eq nonce, (try CoffeeScript.compile("x = null; x or= 10"); nonce), "allow (x = null; x or= 10)"
test "#1348, #1216: existential assignment compilation", ->
nonce = {}
@ -292,13 +294,6 @@ test "#1348, #1216: existential assignment compilation", ->
#the first ?= compiles into a statement; the second ?= compiles to a ternary expression
eq a ?= b ?= 1, nonce
e ?= f ?= g ?= 1
eq e + g, 2
#need to ensure the two vars are not defined, hence the strange names;
# broke earlier when using c ?= d ?= 1 because `d` is declared elsewhere
eq und1_1348 ?= und2_1348 ?= 1, 1
if a then a ?= 2 else a = 3
eq a, nonce