Fixing Issue #904. Destructuring parameters need to reserve their variable names as if they were true parameters.

This commit is contained in:
Jeremy Ashkenas
2010-12-09 21:34:52 -05:00
parent 7c3ef56332
commit ba27b4be69
3 changed files with 33 additions and 10 deletions

View File

@@ -1034,10 +1034,11 @@
}();
exports.Assign = Assign = function() {
__extends(Assign, Base);
function Assign(variable, value, context) {
function Assign(variable, value, context, options) {
this.variable = variable;
this.value = value;
this.context = context;
this.param = options && options.param;
}
Assign.prototype.METHOD_DEF = /^(?:(\S+)\.prototype\.|\S+?)?\b([$A-Za-z_][$\w]*)$/;
Assign.prototype.children = ['variable', 'value'];
@@ -1075,7 +1076,11 @@
throw SyntaxError("\"" + (this.variable.compile(o)) + "\" cannot be assigned.");
}
if (!(this.context || isValue && (this.variable.namespaced || this.variable.hasProperties()))) {
o.scope.find(name);
if (this.param) {
o.scope.add(name, 'var');
} else {
o.scope.find(name);
}
}
val = name + (" " + (this.context || '=') + " ") + val;
if (o.level <= LEVEL_LIST) {
@@ -1152,7 +1157,9 @@
}
val = new Value(new Literal(vvar), [new (acc ? Access : Index)(idx)]);
}
assigns.push(new Assign(obj, val).compile(o, LEVEL_TOP));
assigns.push(new Assign(obj, val, null, {
param: this.param
}).compile(o, LEVEL_TOP));
}
if (!top) {
assigns.push(vvar);
@@ -1246,7 +1253,9 @@
if (param.value) {
val = new Op('?', ref, param.value);
}
exprs.push(new Assign(new Value(param.name), val, '='));
exprs.push(new Assign(new Value(param.name), val, '=', {
param: true
}));
} else {
ref = param;
if (param.value) {

View File

@@ -832,7 +832,8 @@ exports.Class = class Class extends Base
# The **Assign** is used to assign a local variable to value, or to set the
# property of an object -- including within object literals.
exports.Assign = class Assign extends Base
constructor: (@variable, @value, @context) ->
constructor: (@variable, @value, @context, options) ->
@param = options and options.param
# Matchers for detecting class/method names
METHOD_DEF: /^(?:(\S+)\.prototype\.|\S+?)?\b([$A-Za-z_][$\w]*)$/
@@ -862,8 +863,11 @@ exports.Assign = class Assign extends Base
return "#{name}: #{val}" if @context is 'object'
unless @variable.isAssignable()
throw SyntaxError "\"#{ @variable.compile o }\" cannot be assigned."
o.scope.find name unless @context or
isValue and (@variable.namespaced or @variable.hasProperties())
unless @context or isValue and (@variable.namespaced or @variable.hasProperties())
if @param
o.scope.add name, 'var'
else
o.scope.find name
val = name + " #{ @context or '=' } " + val
if o.level <= LEVEL_LIST then val else "(#{val})"
@@ -932,7 +936,7 @@ exports.Assign = class Assign extends Base
else
acc = isObject and IDENTIFIER.test idx.unwrap().value or 0
val = new Value new Literal(vvar), [new (if acc then Access else Index) idx]
assigns.push new Assign(obj, val).compile o, LEVEL_TOP
assigns.push new Assign(obj, val, null, param: @param).compile o, LEVEL_TOP
assigns.push vvar unless top
code = assigns.join ', '
if o.level < LEVEL_LIST then code else "(#{code})"
@@ -1000,7 +1004,7 @@ exports.Code = class Code extends Base
if param.isComplex()
val = ref = param.asReference o
val = new Op '?', ref, param.value if param.value
exprs.push new Assign new Value(param.name), val, '='
exprs.push new Assign new Value(param.name), val, '=', param: yes
else
ref = param
if param.value

View File

@@ -366,4 +366,14 @@ class Foo
new Foo().bar([101]...)
eq x, 101
eq x, 101
# Issue #904: Destructuring function arguments with same-named variables in scope.
key for key, value of a: 1
f = ([key, value]) ->
key + value
eq f([10, 11]), 21
eq key, 'a'
eq value, 1