mirror of
https://github.com/jashkenas/coffeescript.git
synced 2022-11-09 12:23:24 -05:00
fixes #1630: in
should check indices of the right operand when it can
pass a `hasOwnProperty` check for them
This commit is contained in:
parent
8686e31271
commit
2ff6c4c3fc
5 changed files with 35 additions and 24 deletions
|
@ -1,8 +1,8 @@
|
||||||
(function() {
|
(function() {
|
||||||
var ASSIGNED, BOOL, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_ALIAS_MAP, COFFEE_KEYWORDS, COMMENT, COMPARE, COMPOUND_ASSIGN, HEREDOC, HEREDOC_ILLEGAL, HEREDOC_INDENT, HEREGEX, HEREGEX_OMIT, IDENTIFIER, INDEXABLE, JSTOKEN, JS_FORBIDDEN, JS_KEYWORDS, LINE_BREAK, LINE_CONTINUER, LOGIC, Lexer, MATH, MULTILINER, MULTI_DENT, NOT_REGEX, NOT_SPACED_REGEX, NO_NEWLINE, NUMBER, OPERATOR, REGEX, RELATION, RESERVED, Rewriter, SHIFT, SIMPLESTR, TRAILING_SPACES, UNARY, WHITESPACE, compact, count, key, last, starts, _ref;
|
var ASSIGNED, BOOL, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_ALIAS_MAP, COFFEE_KEYWORDS, COMMENT, COMPARE, COMPOUND_ASSIGN, HEREDOC, HEREDOC_ILLEGAL, HEREDOC_INDENT, HEREGEX, HEREGEX_OMIT, IDENTIFIER, INDEXABLE, JSTOKEN, JS_FORBIDDEN, JS_KEYWORDS, LINE_BREAK, LINE_CONTINUER, LOGIC, Lexer, MATH, MULTILINER, MULTI_DENT, NOT_REGEX, NOT_SPACED_REGEX, NO_NEWLINE, NUMBER, OPERATOR, REGEX, RELATION, RESERVED, Rewriter, SHIFT, SIMPLESTR, TRAILING_SPACES, UNARY, WHITESPACE, compact, count, key, last, starts, _ref;
|
||||||
var __indexOf = Array.prototype.indexOf || function(item) {
|
var __hasProp = Object.prototype.hasOwnProperty, __indexOf = Array.prototype.indexOf || function(item) {
|
||||||
for (var i = 0, l = this.length; i < l; i++) {
|
for (var i = 0, l = this.length; i < l; i++) {
|
||||||
if (this[i] === item) return i;
|
if (__hasProp.call(this, i) && this[i] === item) return i;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
return child;
|
return child;
|
||||||
}, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __indexOf = Array.prototype.indexOf || function(item) {
|
}, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __indexOf = Array.prototype.indexOf || function(item) {
|
||||||
for (var i = 0, l = this.length; i < l; i++) {
|
for (var i = 0, l = this.length; i < l; i++) {
|
||||||
if (this[i] === item) return i;
|
if (__hasProp.call(this, i) && this[i] === item) return i;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
};
|
};
|
||||||
|
@ -680,7 +680,6 @@
|
||||||
}
|
}
|
||||||
Extends.prototype.children = ['child', 'parent'];
|
Extends.prototype.children = ['child', 'parent'];
|
||||||
Extends.prototype.compile = function(o) {
|
Extends.prototype.compile = function(o) {
|
||||||
utility('hasProp');
|
|
||||||
return new Call(new Value(new Literal(utility('extends'))), [this.child, this.parent]).compile(o);
|
return new Call(new Value(new Literal(utility('extends'))), [this.child, this.parent]).compile(o);
|
||||||
};
|
};
|
||||||
return Extends;
|
return Extends;
|
||||||
|
@ -2083,11 +2082,21 @@
|
||||||
return ifn;
|
return ifn;
|
||||||
};
|
};
|
||||||
UTILITIES = {
|
UTILITIES = {
|
||||||
"extends": 'function(child, parent) {\n for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }\n function ctor() { this.constructor = child; }\n ctor.prototype = parent.prototype;\n child.prototype = new ctor;\n child.__super__ = parent.prototype;\n return child;\n}',
|
"extends": function() {
|
||||||
bind: 'function(fn, me){ return function(){ return fn.apply(me, arguments); }; }',
|
return "function(child, parent) {\n for (var key in parent) { if (" + (utility('hasProp')) + ".call(parent, key)) child[key] = parent[key]; }\n function ctor() { this.constructor = child; }\n ctor.prototype = parent.prototype;\n child.prototype = new ctor;\n child.__super__ = parent.prototype;\n return child;\n}";
|
||||||
indexOf: 'Array.prototype.indexOf || function(item) {\n for (var i = 0, l = this.length; i < l; i++) {\n if (this[i] === item) return i;\n }\n return -1;\n}',
|
},
|
||||||
hasProp: 'Object.prototype.hasOwnProperty',
|
bind: function() {
|
||||||
slice: 'Array.prototype.slice'
|
return 'function(fn, me){ return function(){ return fn.apply(me, arguments); }; }';
|
||||||
|
},
|
||||||
|
indexOf: function() {
|
||||||
|
return "Array.prototype.indexOf || function(item) {\n for (var i = 0, l = this.length; i < l; i++) {\n if (" + (utility('hasProp')) + ".call(this, i) && this[i] === item) return i;\n }\n return -1;\n}";
|
||||||
|
},
|
||||||
|
hasProp: function() {
|
||||||
|
return 'Object.prototype.hasOwnProperty';
|
||||||
|
},
|
||||||
|
slice: function() {
|
||||||
|
return 'Array.prototype.slice';
|
||||||
|
}
|
||||||
};
|
};
|
||||||
LEVEL_TOP = 1;
|
LEVEL_TOP = 1;
|
||||||
LEVEL_PAREN = 2;
|
LEVEL_PAREN = 2;
|
||||||
|
@ -2104,7 +2113,7 @@
|
||||||
utility = function(name) {
|
utility = function(name) {
|
||||||
var ref;
|
var ref;
|
||||||
ref = "__" + name;
|
ref = "__" + name;
|
||||||
Scope.root.assign(ref, UTILITIES[name]);
|
Scope.root.assign(ref, UTILITIES[name]());
|
||||||
return ref;
|
return ref;
|
||||||
};
|
};
|
||||||
multident = function(code, tab) {
|
multident = function(code, tab) {
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
(function() {
|
(function() {
|
||||||
var BALANCED_PAIRS, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_BLOCK, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, IMPLICIT_UNSPACED_CALL, INVERSES, LINEBREAKS, SINGLE_CLOSERS, SINGLE_LINERS, left, rite, _i, _len, _ref;
|
var BALANCED_PAIRS, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_BLOCK, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, IMPLICIT_UNSPACED_CALL, INVERSES, LINEBREAKS, SINGLE_CLOSERS, SINGLE_LINERS, left, rite, _i, _len, _ref;
|
||||||
var __indexOf = Array.prototype.indexOf || function(item) {
|
var __hasProp = Object.prototype.hasOwnProperty, __indexOf = Array.prototype.indexOf || function(item) {
|
||||||
for (var i = 0, l = this.length; i < l; i++) {
|
for (var i = 0, l = this.length; i < l; i++) {
|
||||||
if (this[i] === item) return i;
|
if (__hasProp.call(this, i) && this[i] === item) return i;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}, __slice = Array.prototype.slice;
|
}, __slice = Array.prototype.slice;
|
||||||
|
|
|
@ -590,7 +590,6 @@ exports.Extends = class Extends extends Base
|
||||||
|
|
||||||
# Hooks one constructor into another's prototype chain.
|
# Hooks one constructor into another's prototype chain.
|
||||||
compile: (o) ->
|
compile: (o) ->
|
||||||
utility 'hasProp'
|
|
||||||
new Call(new Value(new Literal utility 'extends'), [@child, @parent]).compile o
|
new Call(new Value(new Literal utility 'extends'), [@child, @parent]).compile o
|
||||||
|
|
||||||
#### Access
|
#### Access
|
||||||
|
@ -1593,7 +1592,7 @@ exports.For = class For extends Base
|
||||||
varPart = "\n#{idt1}#{namePart};" if namePart
|
varPart = "\n#{idt1}#{namePart};" if namePart
|
||||||
if @object
|
if @object
|
||||||
forPart = "#{ivar} in #{svar}"
|
forPart = "#{ivar} in #{svar}"
|
||||||
guardPart = "\n#{idt1}if (!#{utility('hasProp')}.call(#{svar}, #{ivar})) continue;" if @own
|
guardPart = "\n#{idt1}if (!#{utility 'hasProp'}.call(#{svar}, #{ivar})) continue;" if @own
|
||||||
body = body.compile merge(o, indent: idt1), LEVEL_TOP
|
body = body.compile merge(o, indent: idt1), LEVEL_TOP
|
||||||
body = '\n' + body + '\n' if body
|
body = '\n' + body + '\n' if body
|
||||||
"""
|
"""
|
||||||
|
@ -1801,35 +1800,35 @@ UTILITIES =
|
||||||
|
|
||||||
# Correctly set up a prototype chain for inheritance, including a reference
|
# Correctly set up a prototype chain for inheritance, including a reference
|
||||||
# to the superclass for `super()` calls, and copies of any static properties.
|
# to the superclass for `super()` calls, and copies of any static properties.
|
||||||
extends: '''
|
extends: -> """
|
||||||
function(child, parent) {
|
function(child, parent) {
|
||||||
for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
|
for (var key in parent) { if (#{utility 'hasProp'}.call(parent, key)) child[key] = parent[key]; }
|
||||||
function ctor() { this.constructor = child; }
|
function ctor() { this.constructor = child; }
|
||||||
ctor.prototype = parent.prototype;
|
ctor.prototype = parent.prototype;
|
||||||
child.prototype = new ctor;
|
child.prototype = new ctor;
|
||||||
child.__super__ = parent.prototype;
|
child.__super__ = parent.prototype;
|
||||||
return child;
|
return child;
|
||||||
}
|
}
|
||||||
'''
|
"""
|
||||||
|
|
||||||
# Create a function bound to the current value of "this".
|
# Create a function bound to the current value of "this".
|
||||||
bind: '''
|
bind: -> '''
|
||||||
function(fn, me){ return function(){ return fn.apply(me, arguments); }; }
|
function(fn, me){ return function(){ return fn.apply(me, arguments); }; }
|
||||||
'''
|
'''
|
||||||
|
|
||||||
# Discover if an item is in an array.
|
# Discover if an item is in an array.
|
||||||
indexOf: '''
|
indexOf: -> """
|
||||||
Array.prototype.indexOf || function(item) {
|
Array.prototype.indexOf || function(item) {
|
||||||
for (var i = 0, l = this.length; i < l; i++) {
|
for (var i = 0, l = this.length; i < l; i++) {
|
||||||
if (this[i] === item) return i;
|
if (#{utility 'hasProp'}.call(this, i) && this[i] === item) return i;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
'''
|
"""
|
||||||
|
|
||||||
# Shortcuts to speed up the lookup time for native functions.
|
# Shortcuts to speed up the lookup time for native functions.
|
||||||
hasProp: 'Object.prototype.hasOwnProperty'
|
hasProp: -> 'Object.prototype.hasOwnProperty'
|
||||||
slice : 'Array.prototype.slice'
|
slice : -> 'Array.prototype.slice'
|
||||||
|
|
||||||
# Levels indicate a node's position in the AST. Useful for knowing if
|
# Levels indicate a node's position in the AST. Useful for knowing if
|
||||||
# parens are necessary or superfluous.
|
# parens are necessary or superfluous.
|
||||||
|
@ -1871,7 +1870,7 @@ IS_STRING = /^['"]/
|
||||||
# Helper for ensuring that utility functions are assigned at the top level.
|
# Helper for ensuring that utility functions are assigned at the top level.
|
||||||
utility = (name) ->
|
utility = (name) ->
|
||||||
ref = "__#{name}"
|
ref = "__#{name}"
|
||||||
Scope.root.assign ref, UTILITIES[name]
|
Scope.root.assign ref, UTILITIES[name]()
|
||||||
ref
|
ref
|
||||||
|
|
||||||
multident = (code, tab) ->
|
multident = (code, tab) ->
|
||||||
|
|
|
@ -197,6 +197,9 @@ test "#1100: precedence in or-test compilation of `in`", ->
|
||||||
ok 0 in [1, 1 and 0]
|
ok 0 in [1, 1 and 0]
|
||||||
ok not (0 in [1, 0 or 1])
|
ok not (0 in [1, 0 or 1])
|
||||||
|
|
||||||
|
test "#1630: `in` should check `hasOwnProperty`", ->
|
||||||
|
ok undefined not in length: 1
|
||||||
|
|
||||||
|
|
||||||
# Chained Comparison
|
# Chained Comparison
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue