1
0
Fork 0
mirror of https://github.com/jashkenas/coffeescript.git synced 2022-11-09 12:23:24 -05:00

fixes #1005: invalid identifiers allowed on LHS of destructuring

assignment
This commit is contained in:
Michael Ficarra 2011-08-11 01:11:33 -04:00
parent e5b77b180a
commit df5aca9348
3 changed files with 37 additions and 7 deletions

View file

@ -1,5 +1,5 @@
(function() {
var Access, Arr, Assign, Base, Block, Call, Class, Closure, Code, Comment, Existence, Extends, For, IDENTIFIER, IDENTIFIER_STR, IS_STRING, If, In, Index, LEVEL_ACCESS, LEVEL_COND, LEVEL_LIST, LEVEL_OP, LEVEL_PAREN, LEVEL_TOP, Literal, METHOD_DEF, NEGATE, NO, Obj, Op, Param, Parens, Push, Range, Return, SIMPLENUM, Scope, Slice, Splat, Switch, TAB, THIS, Throw, Try, UTILITIES, Value, While, YES, compact, del, ends, extend, flatten, last, merge, multident, starts, unfoldSoak, utility, _ref;
var Access, Arr, Assign, Base, Block, Call, Class, Closure, Code, Comment, Existence, Extends, For, IDENTIFIER, IDENTIFIER_STR, IS_STRING, If, In, Index, LEVEL_ACCESS, LEVEL_COND, LEVEL_LIST, LEVEL_OP, LEVEL_PAREN, LEVEL_TOP, Literal, METHOD_DEF, NEGATE, NO, Obj, Op, Param, Parens, Push, RESERVED, Range, Return, SIMPLENUM, Scope, Slice, Splat, Switch, TAB, THIS, Throw, Try, UTILITIES, Value, While, YES, compact, del, ends, extend, flatten, last, merge, multident, starts, unfoldSoak, utility, _ref;
var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
function ctor() { this.constructor = child; }
@ -14,6 +14,7 @@
return -1;
};
Scope = require('./scope').Scope;
RESERVED = require('./lexer').RESERVED;
_ref = require('./helpers'), compact = _ref.compact, flatten = _ref.flatten, extend = _ref.extend, merge = _ref.merge, del = _ref.del, starts = _ref.starts, ends = _ref.ends, last = _ref.last;
exports.extend = extend;
YES = function() {
@ -1090,7 +1091,7 @@
}
};
Assign.prototype.compilePatternMatch = function(o) {
var acc, assigns, code, i, idx, isObject, ivar, obj, objects, olen, ref, rest, splat, top, val, value, vvar, _len, _ref2, _ref3, _ref4, _ref5;
var acc, assigns, code, i, idx, isObject, ivar, name, obj, objects, olen, ref, rest, splat, top, val, value, vvar, _len, _ref2, _ref3, _ref4, _ref5, _ref6;
top = o.level === LEVEL_TOP;
value = this.value;
objects = this.variable.base.objects;
@ -1116,6 +1117,9 @@
acc = IDENTIFIER.test(idx.unwrap().value || 0);
value = new Value(value);
value.properties.push(new (acc ? Access : Index)(idx));
if (_ref4 = obj.unwrap().value, __indexOf.call(['arguments', 'eval'].concat(RESERVED), _ref4) >= 0) {
throw new SyntaxError("assignment to a reserved word: " + (obj.compile(o)) + " = " + (value.compile(o)));
}
return new Assign(obj, value, null, {
param: this.param
}).compile(o, LEVEL_TOP);
@ -1132,16 +1136,17 @@
idx = i;
if (isObject) {
if (obj instanceof Assign) {
_ref4 = obj, idx = _ref4.variable.base, obj = _ref4.value;
_ref5 = obj, idx = _ref5.variable.base, obj = _ref5.value;
} else {
if (obj.base instanceof Parens) {
_ref5 = new Value(obj.unwrapAll()).cacheReference(o), obj = _ref5[0], idx = _ref5[1];
_ref6 = new Value(obj.unwrapAll()).cacheReference(o), obj = _ref6[0], idx = _ref6[1];
} else {
idx = obj["this"] ? obj.properties[0].name : obj;
}
}
}
if (!splat && obj instanceof Splat) {
name = obj.name.unwrap().value;
val = "" + olen + " <= " + vvar + ".length ? " + (utility('slice')) + ".call(" + vvar + ", " + i;
if (rest = olen - i - 1) {
ivar = o.scope.freeVariable('i');
@ -1152,9 +1157,10 @@
val = new Literal(val);
splat = "" + ivar + "++";
} else {
name = obj.unwrap().value;
if (obj instanceof Splat) {
obj = obj.name.compile(o);
throw SyntaxError("multiple splats are disallowed in an assignment: " + obj + " ...");
throw new SyntaxError("multiple splats are disallowed in an assignment: " + obj + "...");
}
if (typeof idx === 'number') {
idx = new Literal(splat || idx);
@ -1164,6 +1170,9 @@
}
val = new Value(new Literal(vvar), [new (acc ? Access : Index)(idx)]);
}
if ((name != null) && __indexOf.call(['arguments', 'eval'].concat(RESERVED), name) >= 0) {
throw new SyntaxError("assignment to a reserved word: " + (obj.compile(o)) + " = " + (val.compile(o)));
}
assigns.push(new Assign(obj, val, null, {
param: this.param
}).compile(o, LEVEL_TOP));

View file

@ -4,6 +4,7 @@
# the syntax tree into a string of JavaScript code, call `compile()` on the root.
{Scope} = require './scope'
{RESERVED} = require './lexer'
# Import the helpers we plan to use.
{compact, flatten, extend, merge, del, starts, ends, last} = require './helpers'
@ -978,6 +979,8 @@ exports.Assign = class Assign extends Base
acc = IDENTIFIER.test idx.unwrap().value or 0
value = new Value value
value.properties.push new (if acc then Access else Index) idx
if obj.unwrap().value in ['arguments','eval'].concat RESERVED
throw new SyntaxError "assignment to a reserved word: #{obj.compile o} = #{value.compile o}"
return new Assign(obj, value, null, param: @param).compile o, LEVEL_TOP
vvar = value.compile o, LEVEL_LIST
assigns = []
@ -999,6 +1002,7 @@ exports.Assign = class Assign extends Base
else
idx = if obj.this then obj.properties[0].name else obj
if not splat and obj instanceof Splat
name = obj.name.unwrap().value
val = "#{olen} <= #{vvar}.length ? #{ utility 'slice' }.call(#{vvar}, #{i}"
if rest = olen - i - 1
ivar = o.scope.freeVariable 'i'
@ -1008,16 +1012,19 @@ exports.Assign = class Assign extends Base
val = new Literal val
splat = "#{ivar}++"
else
name = obj.unwrap().value
if obj instanceof Splat
obj = obj.name.compile o
throw SyntaxError \
"multiple splats are disallowed in an assignment: #{obj} ..."
throw new SyntaxError \
"multiple splats are disallowed in an assignment: #{obj}..."
if typeof idx is 'number'
idx = new Literal splat or idx
acc = no
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]
if name? and name in ['arguments','eval'].concat RESERVED
throw new SyntaxError "assignment to a reserved word: #{obj.compile o} = #{val.compile o}"
assigns.push new Assign(obj, val, null, param: @param).compile o, LEVEL_TOP
assigns.push vvar unless top
code = assigns.join ', '

View file

@ -252,6 +252,20 @@ test "destructuring assignment with context (@) properties", ->
test "#1024", ->
eq 2 * [] = 3 + 5, 16
test "#1005: invalid identifiers allowed on LHS of destructuring assignment", ->
disallowed = ['eval', 'arguments'].concat CoffeeScript.RESERVED
throws -> CoffeeScript.compile "[#{disallowed.join ', '}] = x"
throws -> CoffeeScript.compile "[#{disallowed.join '..., '}...] = x"
for v in disallowed when v isnt 'class' # `class` by itself is an expression
throws -> CoffeeScript.compile "[#{v}] = x"
throws -> CoffeeScript.compile "[#{v}...] = x"
doesNotThrow ->
for v in disallowed
CoffeeScript.compile "[a.#{v}] = x"
CoffeeScript.compile "[a.#{v}...] = x"
CoffeeScript.compile "[@#{v}] = x"
CoffeeScript.compile "[@#{v}...] = x"
# Existential Assignment