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

Merge remote-tracking branch 'upstream/master'

Conflicts:
	lib/coffee-script/helpers.js
	test/helpers.coffee
This commit is contained in:
Jason Walton 2013-03-08 10:17:47 -05:00
commit c4f50b52d7
6 changed files with 95 additions and 39 deletions

View file

@ -165,7 +165,7 @@
} }
parts = file.split('.'); parts = file.split('.');
parts.pop(); parts.pop();
if (parts[parts.length - 1] === 'coffee') { if (parts[parts.length - 1] === 'coffee' && parts.length > 1) {
parts.pop(); parts.pop();
} }
return parts.join('.'); return parts.join('.');

View file

@ -1394,18 +1394,12 @@
}; };
Class.prototype.addBoundFunctions = function(o) { Class.prototype.addBoundFunctions = function(o) {
var body, bound, func, lhs, name, rhs, _i, _len, _ref4, _ref5; var bvar, lhs, _i, _len, _ref4;
if (this.boundFuncs.length) { _ref4 = this.boundFuncs;
o.scope.assign('_this', 'this'); for (_i = 0, _len = _ref4.length; _i < _len; _i++) {
_ref4 = this.boundFuncs; bvar = _ref4[_i];
for (_i = 0, _len = _ref4.length; _i < _len; _i++) { lhs = (new Value(new Literal("this"), [new Access(bvar)])).compile(o);
_ref5 = _ref4[_i], name = _ref5[0], func = _ref5[1]; this.ctor.body.unshift(new Literal("" + lhs + " = " + (utility('bind')) + "(" + lhs + ", this)"));
lhs = new Value(new Literal("this"), [new Access(name)]);
body = new Block([new Return(new Literal("" + this.ctor.name + ".prototype." + name.value + ".apply(_this, arguments)"))]);
rhs = new Code(func.params, body, 'boundfunc');
bound = new Assign(lhs, rhs);
this.ctor.body.push(bound);
}
} }
}; };
@ -1442,7 +1436,7 @@
} else { } else {
assign.variable = new Value(new Literal(name), [new Access(new Literal('prototype')), new Access(base)]); assign.variable = new Value(new Literal(name), [new Access(new Literal('prototype')), new Access(base)]);
if (func instanceof Code && func.bound) { if (func instanceof Code && func.bound) {
this.boundFuncs.push([base, func]); this.boundFuncs.push(base);
func.bound = false; func.bound = false;
} }
} }
@ -3048,6 +3042,9 @@
"extends": function() { "extends": function() {
return "function(child, parent) { for (var key in parent) { if (" + (utility('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; }"; return "function(child, parent) { for (var key in parent) { if (" + (utility('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; }";
}, },
bind: function() {
return 'function(fn, me){ return function(){ return fn.apply(me, arguments); }; }';
},
indexOf: function() { indexOf: function() {
return "[].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }"; return "[].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }";
}, },

View file

@ -120,7 +120,7 @@ exports.baseFileName = (file, stripExt = no) ->
return file unless stripExt return file unless stripExt
parts = file.split('.') parts = file.split('.')
parts.pop() parts.pop()
parts.pop() if parts[parts.length - 1] is 'coffee' parts.pop() if parts[parts.length - 1] is 'coffee' and parts.length > 1
parts.join('.') parts.join('.')
# Determine if a filename represents a CoffeeScript file. # Determine if a filename represents a CoffeeScript file.

View file

@ -983,14 +983,9 @@ exports.Class = class Class extends Base
# Ensure that all functions bound to the instance are proxied in the # Ensure that all functions bound to the instance are proxied in the
# constructor. # constructor.
addBoundFunctions: (o) -> addBoundFunctions: (o) ->
if @boundFuncs.length for bvar in @boundFuncs
o.scope.assign '_this', 'this' lhs = (new Value (new Literal "this"), [new Access bvar]).compile o
for [name, func] in @boundFuncs @ctor.body.unshift new Literal "#{lhs} = #{utility 'bind'}(#{lhs}, this)"
lhs = new Value (new Literal "this"), [new Access name]
body = new Block [new Return new Literal "#{@ctor.name}.prototype.#{name.value}.apply(_this, arguments)"]
rhs = new Code func.params, body, 'boundfunc'
bound = new Assign lhs, rhs
@ctor.body.push bound
return return
# Merge the properties from a top-level object as prototypal properties # Merge the properties from a top-level object as prototypal properties
@ -1020,7 +1015,7 @@ exports.Class = class Class extends Base
else else
assign.variable = new Value(new Literal(name), [(new Access new Literal 'prototype'), new Access base ]) assign.variable = new Value(new Literal(name), [(new Access new Literal 'prototype'), new Access base ])
if func instanceof Code and func.bound if func instanceof Code and func.bound
@boundFuncs.push [base, func] @boundFuncs.push base
func.bound = no func.bound = no
assign assign
compact exprs compact exprs
@ -2122,6 +2117,11 @@ UTILITIES =
function(child, parent) { for (var key in parent) { if (#{utility '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; } function(child, parent) { for (var key in parent) { if (#{utility '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; }
""" """
# Create a function bound to the current value of "this".
bind: -> '''
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: -> """
[].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; } [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }

View file

@ -730,23 +730,52 @@ test "#2359: extending native objects that use other typed constructors requires
eq 'yes!', workingArray.method() eq 'yes!', workingArray.method()
test "#2489: removing __bind", -> test "#2782: non-alphanumeric-named bound functions", ->
class A
'b:c': =>
'd'
class Thing eq (new A)['b:c'](), 'd'
foo: (a, b, c) ->
bar: (a, b, c) =>
thing = new Thing
eq thing.foo.length, 3
eq thing.bar.length, 3
test "#2773: overriding bound functions", -> test "#2781: overriding bound functions", ->
class A
a: ->
@b()
b: =>
1
class B extends A
b: =>
2
b = (new A).b
eq b(), 1
b = (new B).b
eq b(), 2
test "#2791: bound function with destructured argument", ->
class Foo class Foo
method: => 'Foo' method: ({a}) => 'Bar'
class Bar extends Foo eq (new Foo).method({a: 'Bar'}), 'Bar'
method: => 'Bar'
eq (new Bar).method(), 'Bar'
test "#2796: ditto, ditto, ditto", ->
answer = null
outsideMethod = (func) ->
func.call message: 'wrong!'
class Base
constructor: ->
@message = 'right!'
outsideMethod @echo
echo: =>
answer = @message
new Base
eq answer, 'right!'

View file

@ -2,7 +2,7 @@
# ------- # -------
# pull the helpers from `CoffeeScript.helpers` into local variables # pull the helpers from `CoffeeScript.helpers` into local variables
{starts, ends, compact, count, merge, extend, flatten, del, last} = CoffeeScript.helpers {starts, ends, compact, count, merge, extend, flatten, del, last, baseFileName} = CoffeeScript.helpers
# `starts` # `starts`
@ -94,3 +94,33 @@ test "the `last` helper returns the last item of an array-like object", ->
test "the `last` helper allows one to specify an optional offset", -> test "the `last` helper allows one to specify an optional offset", ->
ary = [0, 1, 2, 3, 4] ary = [0, 1, 2, 3, 4]
eq 2, last(ary, 2) eq 2, last(ary, 2)
# `baseFileName`
test "the `baseFileName` helper returns the file name to write to", ->
ext = '.js'
sourceToCompiled =
'.coffee': ext
'a.coffee': 'a' + ext
'b.coffee': 'b' + ext
'coffee.coffee': 'coffee' + ext
'.litcoffee': ext
'a.litcoffee': 'a' + ext
'b.litcoffee': 'b' + ext
'coffee.litcoffee': 'coffee' + ext
'.lit': ext
'a.lit': 'a' + ext
'b.lit': 'b' + ext
'coffee.lit': 'coffee' + ext
'.coffee.md': ext
'a.coffee.md': 'a' + ext
'b.coffee.md': 'b' + ext
'coffee.coffee.md': 'coffee' + ext
for sourceFileName, expectedFileName of sourceToCompiled
name = baseFileName sourceFileName, yes
filename = name + ext
eq filename, expectedFileName