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:
commit
c4f50b52d7
6 changed files with 95 additions and 39 deletions
|
@ -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('.');
|
||||||
|
|
|
@ -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; }";
|
||||||
},
|
},
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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; }
|
||||||
|
|
|
@ -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!'
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue