Merge remote-tracking branch 'upstream/master'
Conflicts: lib/coffee-script/helpers.js test/helpers.coffee
This commit is contained in:
commit
c4f50b52d7
|
@ -165,7 +165,7 @@
|
|||
}
|
||||
parts = file.split('.');
|
||||
parts.pop();
|
||||
if (parts[parts.length - 1] === 'coffee') {
|
||||
if (parts[parts.length - 1] === 'coffee' && parts.length > 1) {
|
||||
parts.pop();
|
||||
}
|
||||
return parts.join('.');
|
||||
|
|
|
@ -1394,18 +1394,12 @@
|
|||
};
|
||||
|
||||
Class.prototype.addBoundFunctions = function(o) {
|
||||
var body, bound, func, lhs, name, rhs, _i, _len, _ref4, _ref5;
|
||||
if (this.boundFuncs.length) {
|
||||
o.scope.assign('_this', 'this');
|
||||
_ref4 = this.boundFuncs;
|
||||
for (_i = 0, _len = _ref4.length; _i < _len; _i++) {
|
||||
_ref5 = _ref4[_i], name = _ref5[0], func = _ref5[1];
|
||||
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);
|
||||
}
|
||||
var bvar, lhs, _i, _len, _ref4;
|
||||
_ref4 = this.boundFuncs;
|
||||
for (_i = 0, _len = _ref4.length; _i < _len; _i++) {
|
||||
bvar = _ref4[_i];
|
||||
lhs = (new Value(new Literal("this"), [new Access(bvar)])).compile(o);
|
||||
this.ctor.body.unshift(new Literal("" + lhs + " = " + (utility('bind')) + "(" + lhs + ", this)"));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1442,7 +1436,7 @@
|
|||
} else {
|
||||
assign.variable = new Value(new Literal(name), [new Access(new Literal('prototype')), new Access(base)]);
|
||||
if (func instanceof Code && func.bound) {
|
||||
this.boundFuncs.push([base, func]);
|
||||
this.boundFuncs.push(base);
|
||||
func.bound = false;
|
||||
}
|
||||
}
|
||||
|
@ -3048,6 +3042,9 @@
|
|||
"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; }";
|
||||
},
|
||||
bind: function() {
|
||||
return 'function(fn, me){ return function(){ return fn.apply(me, arguments); }; }';
|
||||
},
|
||||
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; }";
|
||||
},
|
||||
|
|
|
@ -120,7 +120,7 @@ exports.baseFileName = (file, stripExt = no) ->
|
|||
return file unless stripExt
|
||||
parts = file.split('.')
|
||||
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('.')
|
||||
|
||||
# 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
|
||||
# constructor.
|
||||
addBoundFunctions: (o) ->
|
||||
if @boundFuncs.length
|
||||
o.scope.assign '_this', 'this'
|
||||
for [name, func] in @boundFuncs
|
||||
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
|
||||
for bvar in @boundFuncs
|
||||
lhs = (new Value (new Literal "this"), [new Access bvar]).compile o
|
||||
@ctor.body.unshift new Literal "#{lhs} = #{utility 'bind'}(#{lhs}, this)"
|
||||
return
|
||||
|
||||
# Merge the properties from a top-level object as prototypal properties
|
||||
|
@ -1020,7 +1015,7 @@ exports.Class = class Class extends Base
|
|||
else
|
||||
assign.variable = new Value(new Literal(name), [(new Access new Literal 'prototype'), new Access base ])
|
||||
if func instanceof Code and func.bound
|
||||
@boundFuncs.push [base, func]
|
||||
@boundFuncs.push base
|
||||
func.bound = no
|
||||
assign
|
||||
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; }
|
||||
"""
|
||||
|
||||
# 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.
|
||||
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; }
|
||||
|
|
|
@ -730,23 +730,52 @@ test "#2359: extending native objects that use other typed constructors requires
|
|||
eq 'yes!', workingArray.method()
|
||||
|
||||
|
||||
test "#2489: removing __bind", ->
|
||||
test "#2782: non-alphanumeric-named bound functions", ->
|
||||
class A
|
||||
'b:c': =>
|
||||
'd'
|
||||
|
||||
class Thing
|
||||
foo: (a, b, c) ->
|
||||
bar: (a, b, c) =>
|
||||
|
||||
thing = new Thing
|
||||
|
||||
eq thing.foo.length, 3
|
||||
eq thing.bar.length, 3
|
||||
eq (new A)['b:c'](), 'd'
|
||||
|
||||
|
||||
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
|
||||
method: => 'Foo'
|
||||
method: ({a}) => 'Bar'
|
||||
|
||||
class Bar extends Foo
|
||||
method: => 'Bar'
|
||||
eq (new Foo).method({a: 'Bar'}), '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
|
||||
{starts, ends, compact, count, merge, extend, flatten, del, last} = CoffeeScript.helpers
|
||||
{starts, ends, compact, count, merge, extend, flatten, del, last, baseFileName} = CoffeeScript.helpers
|
||||
|
||||
|
||||
# `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", ->
|
||||
ary = [0, 1, 2, 3, 4]
|
||||
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 New Issue