merged in stricter noncallables

This commit is contained in:
Jeremy Ashkenas 2013-10-20 18:49:30 -03:00
commit 351c875576
5 changed files with 79 additions and 12 deletions

View File

@ -1,6 +1,6 @@
// Generated by CoffeeScript 1.6.3
(function() {
var Access, Arr, Assign, Base, Block, Call, Class, Closure, Code, CodeFragment, Comment, Existence, Extends, For, HEXNUM, 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, NUMBER, Obj, Op, Param, Parens, RESERVED, Range, Return, SIMPLENUM, STRICT_PROSCRIBED, Scope, Slice, Splat, Switch, TAB, THIS, Throw, Try, UTILITIES, Value, While, YES, addLocationDataFn, compact, del, ends, extend, flatten, fragmentsToText, last, locationDataToString, merge, multident, parseNum, some, starts, throwSyntaxError, unfoldSoak, utility, _ref, _ref1, _ref2, _ref3,
var Access, Arr, Assign, Base, Block, Call, Class, Closure, Code, CodeFragment, Comment, Existence, Extends, For, HEXNUM, IDENTIFIER, IDENTIFIER_STR, IS_REGEX, IS_STRING, If, In, Index, LEVEL_ACCESS, LEVEL_COND, LEVEL_LIST, LEVEL_OP, LEVEL_PAREN, LEVEL_TOP, Literal, METHOD_DEF, NEGATE, NO, NUMBER, Obj, Op, Param, Parens, RESERVED, Range, Return, SIMPLENUM, STRICT_PROSCRIBED, Scope, Slice, Splat, Switch, TAB, THIS, Throw, Try, UTILITIES, Value, While, YES, addLocationDataFn, compact, del, ends, extend, flatten, fragmentsToText, last, locationDataToString, merge, multident, parseNum, some, starts, throwSyntaxError, unfoldSoak, utility, _ref, _ref1, _ref2, _ref3,
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
@ -678,8 +678,16 @@
return !!this.properties.length;
};
Value.prototype.bareLiteral = function(type) {
return !this.properties.length && this.base instanceof type;
};
Value.prototype.isArray = function() {
return !this.properties.length && this.base instanceof Arr;
return this.bareLiteral(Arr);
};
Value.prototype.isRange = function() {
return this.bareLiteral(Range);
};
Value.prototype.isComplex = function() {
@ -691,11 +699,15 @@
};
Value.prototype.isSimpleNumber = function() {
return this.base instanceof Literal && SIMPLENUM.test(this.base.value);
return this.bareLiteral(Literal) && SIMPLENUM.test(this.base.value);
};
Value.prototype.isString = function() {
return this.base instanceof Literal && IS_STRING.test(this.base.value);
return this.bareLiteral(Literal) && IS_STRING.test(this.base.value);
};
Value.prototype.isRegex = function() {
return this.bareLiteral(Literal) && IS_REGEX.test(this.base.value);
};
Value.prototype.isAtomic = function() {
@ -710,6 +722,10 @@
return true;
};
Value.prototype.isNotCallable = function() {
return this.isSimpleNumber() || this.isString() || this.isRegex() || this.isArray() || this.isRange() || this.isSplice() || this.isObject();
};
Value.prototype.isStatement = function(o) {
return !this.properties.length && this.base.isStatement(o);
};
@ -847,6 +863,9 @@
this.isNew = false;
this.isSuper = variable === 'super';
this.variable = this.isSuper ? null : variable;
if (variable instanceof Value && variable.isNotCallable()) {
variable.error("literal is not a function");
}
}
Call.prototype.children = ['variable', 'args'];
@ -1742,7 +1761,7 @@
fromDecl = fromRef = '0';
}
if (to) {
if ((from != null ? from.isSimpleNumber() : void 0) && to.isSimpleNumber()) {
if (from && from instanceof Value && (from != null ? from.isSimpleNumber() : void 0) && to instanceof Value && to.isSimpleNumber()) {
to = +to.compile(o) - +fromRef;
if (!exclusive) {
to += 1;
@ -3057,6 +3076,8 @@
IS_STRING = /^['"]/;
IS_REGEX = /^\//;
utility = function(name) {
var ref;
ref = "__" + name;

View File

@ -469,17 +469,25 @@ exports.Value = class Value extends Base
hasProperties: ->
!!@properties.length
bareLiteral: (type) ->
not @properties.length and @base instanceof type
# Some boolean checks for the benefit of other nodes.
isArray : -> not @properties.length and @base instanceof Arr
isArray : -> @bareLiteral(Arr)
isRange : -> @bareLiteral(Range)
isComplex : -> @hasProperties() or @base.isComplex()
isAssignable : -> @hasProperties() or @base.isAssignable()
isSimpleNumber : -> @base instanceof Literal and SIMPLENUM.test @base.value
isString : -> @base instanceof Literal and IS_STRING.test @base.value
isSimpleNumber : -> @bareLiteral(Literal) and SIMPLENUM.test @base.value
isString : -> @bareLiteral(Literal) and IS_STRING.test @base.value
isRegex : -> @bareLiteral(Literal) and IS_REGEX.test @base.value
isAtomic : ->
for node in @properties.concat @base
return no if node.soak or node instanceof Call
yes
isNotCallable : -> @isSimpleNumber() or @isString() or @isRegex() or
@isArray() or @isRange() or @isSplice() or @isObject()
isStatement : (o) -> not @properties.length and @base.isStatement o
assigns : (name) -> not @properties.length and @base.assigns name
jumps : (o) -> not @properties.length and @base.jumps o
@ -570,6 +578,8 @@ exports.Call = class Call extends Base
@isNew = false
@isSuper = variable is 'super'
@variable = if @isSuper then null else variable
if variable instanceof Value and variable.isNotCallable()
variable.error "literal is not a function"
children: ['variable', 'args']
@ -1257,7 +1267,8 @@ exports.Assign = class Assign extends Base
else
fromDecl = fromRef = '0'
if to
if from?.isSimpleNumber() and to.isSimpleNumber()
if from and from instanceof Value and from?.isSimpleNumber() and
to instanceof Value and to.isSimpleNumber()
to = +to.compile(o) - +fromRef
to += 1 unless exclusive
else
@ -2182,8 +2193,9 @@ METHOD_DEF = ///
$
///
# Is a literal value a string?
# Is a literal value a string/regex?
IS_STRING = /^['"]/
IS_REGEX = /^\//
# Utility Functions
# -----------------

View File

@ -9,6 +9,9 @@
# shared identity function
id = (_) -> if arguments.length is 1 then _ else [arguments...]
# helper to assert that a string should fail compilation
cantCompile = (code) ->
throws -> CoffeeScript.compile code
test "basic argument passing", ->
@ -649,3 +652,25 @@ test "Loose tokens inside of explicit call lists", ->
bar = first( first
one: 1)
eq bar.one, 1
test "Non-callable literals shouldn't compile", ->
cantCompile '1(2)'
cantCompile '1 2'
cantCompile '/t/(2)'
cantCompile '/t/ 2'
cantCompile '///t///(2)'
cantCompile '///t/// 2'
cantCompile "''(2)"
cantCompile "'' 2"
cantCompile '""(2)'
cantCompile '"" 2'
cantCompile '""""""(2)'
cantCompile '"""""" 2'
cantCompile '{}(2)'
cantCompile '{} 2'
cantCompile '[](2)'
cantCompile '[] 2'
cantCompile '[2..9] 2'
cantCompile '[2..9](2)'
cantCompile '[1..10][2..9] 2'
cantCompile '[1..10][2..9](2)'

View File

@ -144,3 +144,12 @@ test "#1723: operator precedence in unbounded splice compilation", ->
list = [0..9]
list[..if n then n else 0] = n
arrayEq [n..9], list
test "#2953: methods on endpoints in assignment from array splice literal", ->
list = [0..9]
Number.prototype.same = -> this
list[1.same()...9.same()] = 5
delete Number.prototype.same
arrayEq [0, 5, 9], list

View File

@ -130,5 +130,5 @@ test "soaked constructor invocations with caching and property access", ->
eq 1, semaphore
test "soaked function invocation safe on non-functions", ->
eq undefined, 0?(1)
eq undefined, 0? 1, 2
eq undefined, (0)?(1)
eq undefined, (0)? 1, 2