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:
parent
e5b77b180a
commit
df5aca9348
3 changed files with 37 additions and 7 deletions
|
@ -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));
|
||||
|
|
|
@ -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 ', '
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue