From 7af6692c0aa0eb5f30aaa9793641d194442f5acc Mon Sep 17 00:00:00 2001 From: Marcus Stade Date: Tue, 22 Apr 2014 14:25:16 +0200 Subject: [PATCH 01/22] Placeholder commit for channel branch, to start discussions --- lib/chan.js | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 lib/chan.js diff --git a/lib/chan.js b/lib/chan.js new file mode 100644 index 0000000..836da07 --- /dev/null +++ b/lib/chan.js @@ -0,0 +1,4 @@ +module.exports = chan + +function chan() { +} \ No newline at end of file From 50f5f223c00fd2a4e20c13a4865b1afa0e70096a Mon Sep 17 00:00:00 2001 From: Marcus Stade Date: Sun, 12 Oct 2014 17:05:25 +0100 Subject: [PATCH 02/22] Added `defprop` and `when` `defprop` is used to define properties on objects, and is the king of mutability. It's useful though for low level mechanics in implementing abstractions, and provides a cleaner API than `Object.defineProperties`. --- lib/defprop.js | 52 ++++++++++++++++++ lib/when.js | 9 +++ test/defprop.js | 142 ++++++++++++++++++++++++++++++++++++++++++++++++ test/when.js | 51 +++++++++++++++++ 4 files changed, 254 insertions(+) create mode 100644 lib/defprop.js create mode 100644 lib/when.js create mode 100644 test/defprop.js create mode 100644 test/when.js diff --git a/lib/defprop.js b/lib/defprop.js new file mode 100644 index 0000000..0042cb7 --- /dev/null +++ b/lib/defprop.js @@ -0,0 +1,52 @@ +module.exports = defprop + +function defprop(target, fields, opts) { + if (isnt(target)) throw TypeError("Target must exist.") + if (isnt(fields)) throw TypeError("Fields must exist.") + + opts || (opts = {}) + + var names = Object.getOwnPropertyNames(fields) + + var isMutable = get(opts, "^writable", false) + , isEnum = get(opts, "^enumerable", false) + , isConf = get(opts, "^configurable", false) + , scope = get(opts, "^bind", false) + + return Object.defineProperties(target, + names.reduce(function(p, k) { + var prop = describe(fields, k) + , opt = $(get, opts[k]) + + if (isnt(prop.get) && isnt(prop.set)) { + prop.writable = opt("writable", isMutable) + + when(is(Function, prop.value) && opt("bind", scope), function(scope) { + prop.value = prop.value.bind(scope) + }) + } else { + when(prop.get && opt("writable") && !prop.set, function() { + throw TypeError("The accessor `"+k+"` can't be writable without a setter.") + }) + + when(opt("bind", scope), function(scope) { + prop.get && (prop.get = prop.get.bind(scope)) + prop.set && (prop.set = prop.set.bind(scope)) + }) + } + + prop.enumerable = opt("enumerable", isEnum) + prop.configurable = opt("configurable", isConf) + + return (p[k] = prop), p + }, {}) + ) +} + +var describe = Object.getOwnPropertyDescriptor + , isEmpty = require("./isEmpty") + , isnt = require("./isnt") + , when = require("./when") + , get = require("./get") + , is = require("./is") + , $ = require("./partial") \ No newline at end of file diff --git a/lib/when.js b/lib/when.js new file mode 100644 index 0000000..1ca798c --- /dev/null +++ b/lib/when.js @@ -0,0 +1,9 @@ +module.exports = when + +function when(cond, body) { + const it = val(cond) + return is(it)? val(body, it) : null +} + +const val = require('./val') + , is = require('./is') \ No newline at end of file diff --git a/test/defprop.js b/test/defprop.js new file mode 100644 index 0000000..71c414b --- /dev/null +++ b/test/defprop.js @@ -0,0 +1,142 @@ +var defprop = require("../lib/defprop") + , expect = require("chai").expect + , desc = Object.getOwnPropertyDescriptor + , each = require("../lib/each") + , $ = require("../lib/partial") + +describe("`defprop`", function() { + describe("given a target object", function() { + describe("which doesn't exist", function() { + it("should throw a TypeError", function() { + expect($(defprop, null)).to.throw(TypeError) + }) + }) + + describe("and an invalid set of fields", function() { + it("should throw a TypeError", function() { + each([null, undefined, false], function(fields) { + expect($(defprop, {}, fields)).to.throw(TypeError) + }) + }) + }) + + describe("and a valid set of fields", function() { + it("should mutate the target object", function() { + var target = {} + + expect(target).to.not.have.property('foo') + defprop(target, { foo: 'wobble' }) + expect(target).to.have.property('foo', 'wobble') + }) + + it("should return the mutated target object", function() { + var target = {} + + expect(target).to.not.have.property('foo') + expect(defprop(target, { foo: 'wobble' })).to.equal(target) + expect(target).to.have.property('foo', 'wobble') + }) + + it("should not make the fields configurable", function() { + var target = defprop({}, { foo: 'wobble' }) + expect(desc(target, 'foo')).to.have.property('configurable', false) + }) + + describe("when a field is a getter and/or setter, or the field is a function", function() { + describe("and the `^bind` option is set to an object", function() { + it("should bind the field to the object", function() { + var scope = {} + var target = defprop({}, + { get prop() { return this.wibble } + , set prop(x) { this.wibble = x } + , get scope() { return this } + , fun: function() { return this } + } + , { "^bind" : scope } + ) + + expect(target).to.not.equal(scope) + expect(target.scope).to.equal(scope) + + expect(target.prop).to.equal(undefined) + expect(scope).to.not.have.property('wibble') + expect(target).to.not.have.property('wibble') + + target.prop = 'wobble' + expect(target.prop).to.equal('wobble') + expect(scope).to.have.property('wibble', 'wobble') + expect(target).to.not.have.property('wibble') + + expect(target.fun()).to.equal(scope) + }) + }) + }) + + describe("when a field has no options", function() { + it("should make the field immutable", function() { + var target = defprop({}, { foo: 1 }) + expect(desc(target, 'foo')).to.have.property('writable', false) + }) + + it("should not make the field enumerable", function() { + var target = defprop({}, { foo: 1 }) + expect(desc(target, 'foo')).to.have.property('enumerable', false) + }) + }) + + describe("when a field is set to be writable", function() { + describe("and is just a getter", function() { + it("should throw a TypeError", function() { + var field = { get field() {} } + , opt = { field: { writable : true } } + + expect($(defprop, {}, field, opt)).to.throw(TypeError) + }) + }) + + describe("but when it is any other value", function() { + it("should make the field mutable", function() { + each( + [ { get field() {}, set field() {} } + , { set field() {} } + , { field: 1 } + , { field: 'wibble' } + , { field: function() {} } + ] + , function(field) { + var target = {} + defprop(target, field, { field: { writable: true } }) + + var prop = desc(target, 'field') + + if (prop.value) { + expect(prop).to.have.property('writable', true) + } else { + expect(prop.set).to.be.ok + } + } + ) + }) + }) + }) + + describe("when a field is set to be enumerable", function() { + it("should make the field enumerable", function() { + each( + [ { get field() {}, set field() {} } + , { set field() {} } + , { field: 1 } + , { field: 'wibble' } + , { field: function() {} } + ] + , function(field) { + var target = {} + defprop(target, field, { field: { enumerable: true } }) + expect(target).to.have.key('field') + } + ) + }) + }) + }) + }) +}) \ No newline at end of file diff --git a/test/when.js b/test/when.js new file mode 100644 index 0000000..742de62 --- /dev/null +++ b/test/when.js @@ -0,0 +1,51 @@ +const constantly = require('../lib/constantly') + , expect = require('chai').expect + , when = require('../lib/when') + +describe('`when`', function() { + describe('given a `test` and a `body`', function() { + describe('when `test` is a function', function() { + describe('and when calling `test` returns logically true', function () { + describe('when `body` is a function', function() { + it('then return the value of calling `body`', function() { + const tru = constantly(true) + , wbl = constantly('wibble') + + expect(when(tru, wbl)).to.equal('wibble') + }) + }) + + describe('when `body` is not a function', function() { + it('then return `body`', function() { + const tru = constantly(true) + expect(when(tru, 'wibble')).to.equal('wibble') + }) + }) + }) + + describe('but when calling `test` returns logically false', function() { + it('then return `undefined`', function() { + const no = constantly(null) + expect(when(no, 'wibble')).to.equal.undefined + }) + }) + }) + + describe('when `test` is not a function', function() { + describe('but when the value is logically true', function() { + describe('when `body` is a function', function() { + it('then return the value of calling `body`', function() { + const wbl = constantly('wibble') + expect(when(0, wbl)).to.equal('wibble') + }) + }) + + describe('when `body` is not a function', function() { + it('then return `body`', function() { + expect(when(1, 'wibble')).to.equal('wibble') + }) + }) + }) + }) + }) +}) \ No newline at end of file From c37655ecfd533e33942ae21ad2684f9a408cedb4 Mon Sep 17 00:00:00 2001 From: Marcus Stade Date: Sun, 12 Oct 2014 17:13:11 +0100 Subject: [PATCH 03/22] Clean up `nth` --- lib/nth.js | 19 +++++++++++++++---- test/nth.js | 13 ++++++++----- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/lib/nth.js b/lib/nth.js index 45eec16..d94c0ff 100644 --- a/lib/nth.js +++ b/lib/nth.js @@ -1,6 +1,11 @@ module.exports = nth function nth(coll, i) { + if (is(Array, coll)) { + assert(0 <= i && i < coll.length, $(bounds, i)) + return coll[i] + } + coll = seq(coll) var n = i @@ -9,11 +14,17 @@ function nth(coll, i) { coll = coll.rest } - if (n > 0 || isnt(coll)) throw new RangeError('Index '+i+' is out of bounds.') + assert(n < 0 && coll, $(bounds, i)) return coll.first } -var isnt = require('./isnt') - , seq = require('./seq') - , is = require('./is') \ No newline at end of file +var assert = require("./assert") + , isnt = require("./isnt") + , seq = require("./seq") + , is = require("./is") + , $ = require("./partial") + +function bounds(i) { + return RangeError("Index "+i+" is out of bounds.") +} \ No newline at end of file diff --git a/test/nth.js b/test/nth.js index a628f34..f40e18c 100644 --- a/test/nth.js +++ b/test/nth.js @@ -1,15 +1,18 @@ var partial = require('../lib/partial') , expect = require('must') , nth = require('../lib/nth') + , $ = require('../lib/partial') -describe('nth', function() { - describe('when given a seqable object and an index', function() { - it('should return the item at the given index', function() { +describe("`nth`", function() { + describe("when given a seqable object and an index", function() { + it("should return the item at the given index", function() { expect(nth([1, 2, 3], 1)).to.equal(2) + expect(nth(range(), 1)).to.equal(1) }) - it('should throw an error if the index is out of bounds', function() { - expect(partial(nth, [1, 2, 3], 3)).to.throw(RangeError) + it("should throw an error if the index is out of bounds", function() { + expect($(nth, [1, 2, 3], 3)).to.throw("RangeError") + expect($(nth, range(3), 5)).to.throw("RangeError") }) }) }) \ No newline at end of file From 242a11c653b371ab18896678c070e1829c68dbc8 Mon Sep 17 00:00:00 2001 From: Marcus Stade Date: Sun, 12 Oct 2014 17:14:41 +0100 Subject: [PATCH 04/22] Fix up `src` --- lib/src.js | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/lib/src.js b/lib/src.js index f4166a6..1a21417 100644 --- a/lib/src.js +++ b/lib/src.js @@ -10,11 +10,12 @@ function src(x) { return s(x) } -var type = require('./type') +var keys = Object.getOwnPropertyNames + , type = require("./type") , from = - { 'array' : fromArray - , 'string' : fromString - , 'object' : fromObject + { "array" : fromArray + , "string" : fromString + , "object" : fromObject } function toString(x) { @@ -26,11 +27,15 @@ function fromString(x) { } function fromArray(x) { - return '[' + x.map(src).join(',') + ']' + return "[" + x.map(src).join(",") + "]" } function fromObject(x) { - return '{' + Object.keys(x).map(prop).join(',') + '}' + return "{" + keys(x).filter(ignored).map(prop).join(",") + "}" + + function ignored(k) { + return !(k === "constructor" || k === "prototype") + } function prop(k) { return '"' + k + '":' + src(x[k]) From 4e8daa6b27cafda109923b6fc00f55f93f86813c Mon Sep 17 00:00:00 2001 From: Marcus Stade Date: Fri, 25 Apr 2014 23:22:17 +0200 Subject: [PATCH 05/22] Fixed `is` when checking for booleans, and improved tests. --- lib/is.js | 2 +- test/is.js | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/lib/is.js b/lib/is.js index 0836262..731d1f3 100644 --- a/lib/is.js +++ b/lib/is.js @@ -18,7 +18,7 @@ function is(c, x) { } else if (type(c) === 'string') { return cs === type(x) } else { - return is(x) && x.constructor === c || c.isPrototypeOf(x) + return (x != null && x.constructor === c) || c.isPrototypeOf(x) } } diff --git a/test/is.js b/test/is.js index 8147df1..c8d23a6 100644 --- a/test/is.js +++ b/test/is.js @@ -29,6 +29,38 @@ describe('is', function() { }) }) + describe('when testing for booleans', function() { + each([ true, false ], function(x) { + describe('and when `x = '+x+'`', function() { + it('should return true', function() { + expect(is(Boolean, x)).to.be.true + expect(is('boolean', x)).to.be.true + }) + }) + } + ) + + each( + [ NaN + , '', 'wobble', 'true', 'false' + , {} + , [] + , -1, 0, 1, 3.14 + , function() {} + , undefined, null + ] + , + function(x) { + describe('and when `x = '+src(x)+'`', function() { + it('should return false', function() { + expect(is(Boolean, x)).to.be.false + expect(is('boolean', x)).to.be.false + }) + }) + } + ) + }) + describe('when testing for numbers', function() { each( [ 0 From 71dadb7403ebaaea71e9aa5df2a14096305417e6 Mon Sep 17 00:00:00 2001 From: Marcus Stade Date: Sat, 26 Apr 2014 19:29:52 +0200 Subject: [PATCH 06/22] Fixed a bug when calling `is` with identical args `is(x, x)` could return false if `x` is an object --- lib/is.js | 2 ++ test/is.js | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/lib/is.js b/lib/is.js index 731d1f3..277effb 100644 --- a/lib/is.js +++ b/lib/is.js @@ -5,6 +5,8 @@ function is(c, x) { return !not(c) } + if (c === x) return true + var cs = lowerCase(c) if (cs === 'null') { diff --git a/test/is.js b/test/is.js index c8d23a6..8491718 100644 --- a/test/is.js +++ b/test/is.js @@ -29,6 +29,24 @@ describe('is', function() { }) }) + describe('when given two arguments that are identical', function() { + it('should return `true`', function() { + each( + [ true, false, + , -1, 0, 1, 3.14 + , '', 'wibble' + , [], [1, 2, 3] + , {}, { foo: 1 } + , Function + , null, undefined + ] + , function(x) { + expect(is(x, x)).to.be.true + } + ) + }) + }) + describe('when testing for booleans', function() { each([ true, false ], function(x) { describe('and when `x = '+x+'`', function() { From 581c289c6e20128c9722aff1aaa8d1214b16cb26 Mon Sep 17 00:00:00 2001 From: Marcus Stade Date: Tue, 14 Oct 2014 01:08:45 +0100 Subject: [PATCH 07/22] Fixed `type` to return constructor name if it exists. N.b.: If you do `Object.create(function() {}, {})`, the resulting object will have a constructor set, but not to the prototype function and I have no idea what indeed it gets set to. Might be worth investigating. --- lib/type.js | 19 ++++++++++++++----- test/type.js | 4 +++- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/lib/type.js b/lib/type.js index 5fcd069..393056a 100644 --- a/lib/type.js +++ b/lib/type.js @@ -3,15 +3,24 @@ module.exports = type function type(x) { if (x !== x) return 'nan' - var t = str.call(x).slice(8, -1).toLowerCase() + var t = lower(str.call(x).slice(8, -1)) if (t === 'object') { - // Check if prototype is a function and has a name - var proto = Object.getPrototypeOf(x) - if (type(proto) === 'function' && proto.name) return proto.name + if (x.constructor === Object) { + return t + } else { + var proto = Object.getPrototypeOf(x) + + if (type(proto) === 'function' && proto.name) { + return proto.name + } else if (x.constructor && x.constructor.name) { + return x.constructor.name + } + } } return t } -var str = ({}).toString \ No newline at end of file +var lower = require('./lowerCase') + str = ({}).toString \ No newline at end of file diff --git a/test/type.js b/test/type.js index 8dead7a..a46c67e 100644 --- a/test/type.js +++ b/test/type.js @@ -2,6 +2,7 @@ var expect = require('must') , range = require('../lib/range') , type = require('../lib/type') , seq = require('../lib/seq') + , src = require('../lib/src') describe('type', function() { [ ['string', 'hello'] @@ -14,8 +15,9 @@ describe('type', function() { , ['undefined', void 0] , ['seq', seq([1, 2, 3])] , ['nan', NaN] + , ['Foo', new (function Foo() {})] ].forEach(function(test) { - describe('when called with ' + test[1], function() { + describe('when called with ' + src(test[1]), function() { it('should return \'' + test[0] + '\'', function() { expect(type(test[1])).to.equal(test[0]) }) From eb55446eea026ae8cedeb780885aa7efc7c7c01d Mon Sep 17 00:00:00 2001 From: Marcus Stade Date: Tue, 14 Oct 2014 01:46:09 +0100 Subject: [PATCH 08/22] Tab fix in test/each.js --- test/each.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/each.js b/test/each.js index e739982..86eea03 100644 --- a/test/each.js +++ b/test/each.js @@ -7,7 +7,7 @@ describe('each', function() { describe('when given a seq', function() { it('should call `fn` once for each item', function() { var l = [1, 2, 3] - , s = seq(l) + , s = seq(l) var i = 0 From 96e8990e6b9b45943d13a30a62ca9d62ca9a235c Mon Sep 17 00:00:00 2001 From: Marcus Stade Date: Tue, 14 Oct 2014 01:52:41 +0100 Subject: [PATCH 09/22] Added `every` for easy testing of sequence values --- lib/every.js | 16 ++++++++++++++++ test/every.js | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 lib/every.js create mode 100644 test/every.js diff --git a/lib/every.js b/lib/every.js new file mode 100644 index 0000000..19ed952 --- /dev/null +++ b/lib/every.js @@ -0,0 +1,16 @@ +module.exports = every + +function every(coll, it) { + coll = seq(coll) + + while (is(coll)) { + if (!it(coll.first)) return false + coll = coll.rest + } + + return true +} + +var type = require('./type') + , seq = require('./seq') + , is = require('./is') \ No newline at end of file diff --git a/test/every.js b/test/every.js new file mode 100644 index 0000000..dbdf7d7 --- /dev/null +++ b/test/every.js @@ -0,0 +1,48 @@ +var expect = require('chai').expect + , every = require('../lib/every') + , each = require('../lib/each') + , src = require('../lib/src') + , seq = require('../lib/seq') + +describe('every', function() { + describe('when given a seq', function() { + it('should call `fn` so long as it keeps returning `true`', function() { + var l = [1, 2, 3] + , s = seq(l) + + var i = 0 + + var fn = function(x) { + expect(x).to.equal(l[i++]) + return true + } + + every(s, fn) + expect(i).to.equal(l.length) + }) + + it('should stop calling `fn` when it returns `false`', function() { + var l = [1, 2, 3] + , s = seq(l) + + var i = 0 + + var fn = function(x) { + if (x < 3) { + expect(x).to.equal(l[i++]) + return true + } + } + + every(s, fn) + expect(i).to.equal(2) + }) + }) + + describe('when given an empty sequence', function() { + it('should do nothing', function() { + var fn = function(x) { throw new Error("shouldn't get here!") } + each(null, fn) + }) + }) +}) \ No newline at end of file From 57f61995459b9bb936b5ad04e7a8b6193ad19071 Mon Sep 17 00:00:00 2001 From: Marcus Stade Date: Tue, 14 Oct 2014 03:00:20 +0100 Subject: [PATCH 10/22] A stab at protocols --- lib/defprotocol.js | 89 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 lib/defprotocol.js diff --git a/lib/defprotocol.js b/lib/defprotocol.js new file mode 100644 index 0000000..6321e6e --- /dev/null +++ b/lib/defprotocol.js @@ -0,0 +1,89 @@ +module.exports = defprotocol + +function defprotocol(name, sigs) { + assert(is(String, name), 'Name must be a string.') + + var map = new WeakMap() + + defprop(Protocol, { + toString: function() { + return '[protocol ' + name + ']' + } + ) + + return Protocol + + function Protocol(target, impl) { + return arguments.length > 1 + ? reify(target, impl) + : fetch(target) + } + + function fetch(target) { + var T = typeOf(target) + , impl = map.get(T) + + assert(impl, 'Protocol not implemented for type ' + type(target)) + + var exec = {} + + each(impl, function(sig) { + var name = sig[0] + , fun = sig[1] + + exec[name] = fun.bind(target) + }) + + return exec + } + + function reify(target, impl) { + var T = is(Function, target)? target : typeOf(target) + + assert(not(map.has(T)), 'Protocol already implemented for type ' + type(target)) + + var exec = {} + + map.set(T, exec) + + each(sigs, function(sig) { + var name = sig[0] + , args = sig[1] + , fun = impl[name] + + assert(fun, 'Missing implementation for ' + name) + assert(every(args, $(is, Function)), 'Argument signature must be a function') + + exec[name] = function() { + var vals = new Array(args.length) + , raw = [].slice.call(arguments) + + for (var i = 1; i < args.length; i++) { + vals[i] = args[i](raw) + } + + return fun.apply(this, vals) + } + }) + } +} + +function typeOf(x) { + if (isnt(x)) { + return nil + } else { + return x.constructor || Object.getPrototypeOf(x) + } +} + +function nil() {} + +var variadic = require('./variadic') + , defprop = require('./defprop') + , assert = require('./assert') + , every = require('./every') + , type = require('./type') + , src = require('./src') + , not = require('./not') + , is = require('./is') + , $ = require('./partial') \ No newline at end of file From 4491110972d69ebcc83ea2f0556a362e3585d308 Mon Sep 17 00:00:00 2001 From: Marcus Stade Date: Fri, 10 Oct 2014 20:45:34 +0100 Subject: [PATCH 11/22] Fix failing tests; expose crappy coverage of `defprotocol` Hint: there is no coverage of `defprotocol`. Write some tests, man. --- index.js | 82 ++++++++++++++++++++------------------- lib/async/buffer/fixed.js | 5 +++ lib/async/buffer/index.js | 35 +++++++++++++++++ lib/async/chan.js | 46 ++++++++++++++++++++++ lib/async/go.js | 32 +++++++++++++++ lib/async/index.js | 1 + lib/chan.js | 4 -- lib/defprotocol.js | 2 +- lib/deftype.js | 5 +++ repl.js => repl | 14 +++++-- test/funkis.js | 8 ++-- 11 files changed, 182 insertions(+), 52 deletions(-) create mode 100644 lib/async/buffer/fixed.js create mode 100644 lib/async/buffer/index.js create mode 100644 lib/async/chan.js create mode 100644 lib/async/go.js create mode 100644 lib/async/index.js delete mode 100644 lib/chan.js create mode 100644 lib/deftype.js rename repl.js => repl (57%) mode change 100644 => 100755 diff --git a/index.js b/index.js index 285cddf..458f65c 100644 --- a/index.js +++ b/index.js @@ -1,41 +1,45 @@ module.exports = - { and : require('./lib/and') - , apply : require('./lib/apply') - , assert : require('./lib/assert') - , call : require('./lib/call') - , compose : require('./lib/compose') - , constantly : require('./lib/constantly') - , count : require('./lib/count') - , dec : require('./lib/dec') - , each : require('./lib/each') - , eq : require('./lib/eq') - , gt : require('./lib/gt') - , get : require('./lib/get') - , identity : require('./lib/identity') - , inc : require('./lib/inc') - , is : require('./lib/is') - , isEmpty : require('./lib/isEmpty') - , isnt : require('./lib/isnt') - , log : require('./lib/log') - , lowerCase : require('./lib/lowerCase') - , lt : require('./lib/lt') - , merge : require('./lib/merge') - , min : require('./lib/min') - , not : require('./lib/not') - , nth : require('./lib/nth') - , once : require('./lib/once') - , partial : require('./lib/partial') - , pipe : require('./lib/pipe') - , range : require('./lib/range') - , repeatedly : require('./lib/repeatedly') - , seq : require('./lib/seq') - , slice : require('./lib/slice') - , src : require('./lib/src') - , take : require('./lib/take') - , thunk : require('./lib/thunk') - , trampoline : require('./lib/trampoline') - , type : require('./lib/type') - , val : require('./lib/val') - , variadic : require('./lib/variadic') - , vec : require('./lib/vec') + { and : require('./lib/and') + , apply : require('./lib/apply') + , assert : require('./lib/assert') + , call : require('./lib/call') + , compose : require('./lib/compose') + , constantly : require('./lib/constantly') + , count : require('./lib/count') + , dec : require('./lib/dec') + , defprop : require('./lib/defprop') + , deftype : require('./lib/deftype') + , defprotocol : require('./lib/defprotocol') + , each : require('./lib/each') + , every : require('./lib/every') + , eq : require('./lib/eq') + , gt : require('./lib/gt') + , get : require('./lib/get') + , identity : require('./lib/identity') + , inc : require('./lib/inc') + , is : require('./lib/is') + , isEmpty : require('./lib/isEmpty') + , isnt : require('./lib/isnt') + , log : require('./lib/log') + , lowerCase : require('./lib/lowerCase') + , lt : require('./lib/lt') + , merge : require('./lib/merge') + , min : require('./lib/min') + , not : require('./lib/not') + , nth : require('./lib/nth') + , once : require('./lib/once') + , partial : require('./lib/partial') + , pipe : require('./lib/pipe') + , range : require('./lib/range') + , repeatedly : require('./lib/repeatedly') + , seq : require('./lib/seq') + , slice : require('./lib/slice') + , src : require('./lib/src') + , take : require('./lib/take') + , thunk : require('./lib/thunk') + , trampoline : require('./lib/trampoline') + , type : require('./lib/type') + , val : require('./lib/val') + , variadic : require('./lib/variadic') + , vec : require('./lib/vec') } \ No newline at end of file diff --git a/lib/async/buffer/fixed.js b/lib/async/buffer/fixed.js new file mode 100644 index 0000000..1ec339e --- /dev/null +++ b/lib/async/buffer/fixed.js @@ -0,0 +1,5 @@ +module.exports = fixed + +function fixed() { + +} \ No newline at end of file diff --git a/lib/async/buffer/index.js b/lib/async/buffer/index.js new file mode 100644 index 0000000..b80d575 --- /dev/null +++ b/lib/async/buffer/index.js @@ -0,0 +1,35 @@ +var defprotocol = require('../../defprotocol') + +module.exports = defprotocol('Buffer', + { add : [Object] + , isFull : [] + , remove : [] + } +) + +module.exports = deftype(FixedBuffer, [LinkedList, Number], Buffer) + +function FixedBuffer(size) { + var list = [] + + return Buffer(FixedBuffer, + { add : add + , remove : remove + , isFull : isFull + } + ) + + function add(item) { + !isFull() && list.unshift(item) + } + + function remove() { + return list.pop() + } + + function isFull() { + return list.length >= size + } +} + +Buffer(obj).add() \ No newline at end of file diff --git a/lib/async/chan.js b/lib/async/chan.js new file mode 100644 index 0000000..263a195 --- /dev/null +++ b/lib/async/chan.js @@ -0,0 +1,46 @@ +module.exports = chan + +function chan() { + return create( + { put : { value: put } + , take : { value: take } + } + ) + + function put(value) { + } + + function take() { + } +} + +var create = Object.create + +// var ReadPort = protocol({ +// 'take' : [protocol, { returns: Promise }] +// }) + +// var WritePort = protocol({ +// 'put' : [protocol, Object, { returns: Promise }] +// }) + +// var Channel = protocol({ +// 'isClosed' : [protocol, { returns: Boolean }] +// 'close' : [protocol] +// }) + +// var Channel = protocol({ +// 'take' : { returns: Promise } +// 'put' : { sig: [Object], returns: Promise } +// }) + +// var Channel = protocol({ +// 'take' : { returns: Promise } +// 'put' : { sig: [Object], returns: Promise } +// }) + +// Channel(thing).take() + +// go(function *() { +// var search = yield get('www.google.com').take() +// }) \ No newline at end of file diff --git a/lib/async/go.js b/lib/async/go.js new file mode 100644 index 0000000..3b71093 --- /dev/null +++ b/lib/async/go.js @@ -0,0 +1,32 @@ +module.exports = require('./variadic')(go) + +function go(process, rest) { + if (isnt(Generator, process)) throw new TypeError('Co-routine must be a generator function') + + var routine = process.apply(undefined, rest) + + tick(function() { + step(routine.next()) + }) + + function step(state) { + if (isnt(Object, state)) { + routine.throw(state) + } else if (state.done) return + + state = routine.next(state.value) + + if (is(Promise, state.value)) { + state.value.then(step) + } else { + setImmediate(step.bind(null, state)) + } + } +} + +var tick = setImmediate + , comp = require('./compose') + , isnt = require('./isnt') + , is = require('./is') + +var Generator = (function *(){}).constructor \ No newline at end of file diff --git a/lib/async/index.js b/lib/async/index.js new file mode 100644 index 0000000..7c6d6c7 --- /dev/null +++ b/lib/async/index.js @@ -0,0 +1 @@ +module.exports = {} \ No newline at end of file diff --git a/lib/chan.js b/lib/chan.js deleted file mode 100644 index 836da07..0000000 --- a/lib/chan.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = chan - -function chan() { -} \ No newline at end of file diff --git a/lib/defprotocol.js b/lib/defprotocol.js index 6321e6e..e74be4f 100644 --- a/lib/defprotocol.js +++ b/lib/defprotocol.js @@ -9,7 +9,7 @@ function defprotocol(name, sigs) { toString: function() { return '[protocol ' + name + ']' } - ) + }) return Protocol diff --git a/lib/deftype.js b/lib/deftype.js new file mode 100644 index 0000000..f752a11 --- /dev/null +++ b/lib/deftype.js @@ -0,0 +1,5 @@ +module.exports = deftype + +function deftype() { + +} \ No newline at end of file diff --git a/repl.js b/repl old mode 100644 new mode 100755 similarity index 57% rename from repl.js rename to repl index 9540ad2..2421a3f --- a/repl.js +++ b/repl @@ -1,3 +1,5 @@ +#!/usr/bin/env node --harmony + ;(function() { var global = this , libdir = __dirname + '/lib' @@ -6,15 +8,19 @@ global['reload'] = function() { Object.keys(require.cache) .forEach(function(k) { - delete require.cache[k] + delete require.cache[k] }) fs.readdirSync(libdir) .forEach(function(lib) { - lib = lib.replace(/\.js$/, '') - global[lib] = require(libdir + '/' + lib) + lib = lib.replace(/\.js$/, '') + global[lib] = require(libdir + '/' + lib) }) } reload() -}()) \ No newline at end of file +}()) + +var repl = require('repl') + +repl.start({ prompt: 'fun > ', useGlobal: true }) \ No newline at end of file diff --git a/test/funkis.js b/test/funkis.js index d3021fc..a5c199c 100644 --- a/test/funkis.js +++ b/test/funkis.js @@ -1,8 +1,8 @@ -var fs = require('fs') - , path = require('path') - , each = require('../lib/each') - , funkis = require('../') +var funkis = require('../') , expect = require('must') + , each = require('../lib/each') + , path = require('path') + , fs = require('fs') describe('funkis', function() { it('should export every function in lib/', function() { From 8fee34e47e6d8f8d38b41782ebde70f60978221a Mon Sep 17 00:00:00 2001 From: Marcus Stade Date: Wed, 15 Oct 2014 02:12:09 +0100 Subject: [PATCH 12/22] Some first tests for `defprotocol` Damn gamification makes me want to achieve 100% coverage. I'm so easy.. --- lib/defprotocol.js | 2 ++ test/defprotocol.js | 50 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 test/defprotocol.js diff --git a/lib/defprotocol.js b/lib/defprotocol.js index e74be4f..3dbf819 100644 --- a/lib/defprotocol.js +++ b/lib/defprotocol.js @@ -82,7 +82,9 @@ var variadic = require('./variadic') , defprop = require('./defprop') , assert = require('./assert') , every = require('./every') + , each = require('./each') , type = require('./type') + , isnt = require('./isnt') , src = require('./src') , not = require('./not') , is = require('./is') diff --git a/test/defprotocol.js b/test/defprotocol.js new file mode 100644 index 0000000..996ba61 --- /dev/null +++ b/test/defprotocol.js @@ -0,0 +1,50 @@ +var expect = require('chai').expect + , defprotocol = require('../lib/defprotocol') + +describe('defprotocol', function() { + describe('when given an object', function() { + it('should verify the signature of each key') + + describe('and all signatures are ok', function() { + var Seq + + it('should return a protocol', function() { + Seq = defprotocol('Seq', + { first : [] + , rest : [] + }) + + expect(Seq).to.be.a('function') + expect(Seq.name).to.equal('Protocol') + }) + + describe('and when implemented', function() { + it('should do what it says on the tin', function() { + var Node = function(data, left, right){ + this.data = data + this.left = left + this.right = right + } + + Seq(Node, + { first : function() { return this.data } + , rest : function() { return [this.left, this.right] } + }) + + var one = new Node(1) + , two = new Node(2) + , tre = new Node(3) + + one.left = tre + one.right = two + two.left = one + two.right = tre + tre.left = two + tre.right = one + + expect(Seq(one).first()).to.equal(1) + }) + }) + }) + }) +}) \ No newline at end of file From 2b7c258fec386caf9ba15956086fd3b7b4546089 Mon Sep 17 00:00:00 2001 From: Marcus Stade Date: Sat, 31 Jan 2015 14:52:24 +0000 Subject: [PATCH 13/22] Rebased branch, fix all the things --- lib/async/go.js | 30 +++---- lib/defprotocol.js | 104 ++++++++++++----------- lib/type.js | 4 +- test/defprop.js | 196 ++++++++++++++++++++++---------------------- test/defprotocol.js | 64 +++++++-------- test/every.js | 18 ++-- test/is.js | 65 +++++++++++++-- test/when.js | 58 ++++++------- 8 files changed, 296 insertions(+), 243 deletions(-) diff --git a/lib/async/go.js b/lib/async/go.js index 3b71093..cc874a7 100644 --- a/lib/async/go.js +++ b/lib/async/go.js @@ -1,32 +1,34 @@ -module.exports = require('./variadic')(go) +module.exports = require('../variadic')(go) function go(process, rest) { if (isnt(Generator, process)) throw new TypeError('Co-routine must be a generator function') var routine = process.apply(undefined, rest) + , error = routine.throw.bind(routine) + , next = routine.next.bind(routine) tick(function() { - step(routine.next()) + step(next()) }) function step(state) { - if (isnt(Object, state)) { - routine.throw(state) - } else if (state.done) return - - state = routine.next(state.value) - - if (is(Promise, state.value)) { - state.value.then(step) + if (is(Promise, state.value) || is(Function, state.value.then)) { + console.log('step:promise', state) + Promise.resolve(state.value).then(next).then(step).catch(error) + } else if (state.done) { + return /* Put state.value on return channel */ } else { - setImmediate(step.bind(null, state)) + console.log('step:value', state) + tick(function() { + step(next(state.value)) + }) } } } var tick = setImmediate - , comp = require('./compose') - , isnt = require('./isnt') - , is = require('./is') + , comp = require('../compose') + , isnt = require('../isnt') + , is = require('../is') var Generator = (function *(){}).constructor \ No newline at end of file diff --git a/lib/defprotocol.js b/lib/defprotocol.js index 3dbf819..efc74a0 100644 --- a/lib/defprotocol.js +++ b/lib/defprotocol.js @@ -2,70 +2,67 @@ module.exports = defprotocol function defprotocol(name, sigs) { assert(is(String, name), 'Name must be a string.') + assert(is(Object, sigs), 'Signatures must be an object.') var map = new WeakMap() - defprop(Protocol, { - toString: function() { - return '[protocol ' + name + ']' - } - }) + defprop(Protocol, { toString : constantly('[protocol ' + name + ']') }) return Protocol function Protocol(target, impl) { return arguments.length > 1 - ? reify(target, impl) - : fetch(target) + ? reify(map, target, sigs, impl) + : fetch(map, target, Protocol) } +} - function fetch(target) { - var T = typeOf(target) - , impl = map.get(T) - - assert(impl, 'Protocol not implemented for type ' + type(target)) +function fetch(map, target, Protocol) { + var T = typeOf(target) + , impl = map.get(T) - var exec = {} + if (!impl) return - each(impl, function(sig) { - var name = sig[0] - , fun = sig[1] + var exec = Object.create(Protocol, {}) - exec[name] = fun.bind(target) - }) + each(impl, function(sig) { + var name = sig[0] + , fun = sig[1] - return exec - } + exec[name] = fun.bind(target) + }) - function reify(target, impl) { - var T = is(Function, target)? target : typeOf(target) + return exec +} - assert(not(map.has(T)), 'Protocol already implemented for type ' + type(target)) +function reify(map, target, sigs, impl) { + var T = is(Function, target)? target : typeOf(target) - var exec = {} + assert(not(map.has(T)), 'Protocol already implemented for type ' + type(target)) - map.set(T, exec) + var exec = {} - each(sigs, function(sig) { - var name = sig[0] - , args = sig[1] - , fun = impl[name] + map.set(T, exec) - assert(fun, 'Missing implementation for ' + name) - assert(every(args, $(is, Function)), 'Argument signature must be a function') + each(sigs, function(sig) { + var name = sig[0] + , args = sig[1] + , fun = impl[name] - exec[name] = function() { - var vals = new Array(args.length) - , raw = [].slice.call(arguments) + assert(fun, 'Missing implementation for ' + name) + assert(every(args, $(is, Function)), 'Argument signature must be a function') - for (var i = 1; i < args.length; i++) { - vals[i] = args[i](raw) - } + exec[name] = function() { + var vals = new Array(args.length) + , raw = [].slice.call(arguments) - return fun.apply(this, vals) + for (var i = 1; i < args.length; i++) { + vals[i] = args[i](raw) } - }) - } + + return fun.apply(this, vals) + } + }) } function typeOf(x) { @@ -76,16 +73,17 @@ function typeOf(x) { } } -function nil() {} - -var variadic = require('./variadic') - , defprop = require('./defprop') - , assert = require('./assert') - , every = require('./every') - , each = require('./each') - , type = require('./type') - , isnt = require('./isnt') - , src = require('./src') - , not = require('./not') - , is = require('./is') - , $ = require('./partial') \ No newline at end of file +var constantly = require('./constantly') + , variadic = require('./variadic') + , defprop = require('./defprop') + , assert = require('./assert') + , lower = require('./lowerCase') + , every = require('./every') + , each = require('./each') + , type = require('./type') + , isnt = require('./isnt') + , src = require('./src') + , not = require('./not') + , nil = {} + , is = require('./is') + , $ = require('./partial') \ No newline at end of file diff --git a/lib/type.js b/lib/type.js index 393056a..4f2f910 100644 --- a/lib/type.js +++ b/lib/type.js @@ -22,5 +22,5 @@ function type(x) { return t } -var lower = require('./lowerCase') - str = ({}).toString \ No newline at end of file +var lower = require('./lowerCase') + , str = ({}).toString \ No newline at end of file diff --git a/test/defprop.js b/test/defprop.js index 71c414b..d01d999 100644 --- a/test/defprop.js +++ b/test/defprop.js @@ -1,5 +1,5 @@ var defprop = require("../lib/defprop") - , expect = require("chai").expect + , expect = require("must") , desc = Object.getOwnPropertyDescriptor , each = require("../lib/each") , $ = require("../lib/partial") @@ -8,134 +8,134 @@ describe("`defprop`", function() { describe("given a target object", function() { describe("which doesn't exist", function() { it("should throw a TypeError", function() { - expect($(defprop, null)).to.throw(TypeError) + expect($(defprop, null)).to.throw(TypeError) }) }) describe("and an invalid set of fields", function() { it("should throw a TypeError", function() { each([null, undefined, false], function(fields) { - expect($(defprop, {}, fields)).to.throw(TypeError) - }) + expect($(defprop, {}, fields)).to.throw(TypeError) + }) }) }) describe("and a valid set of fields", function() { it("should mutate the target object", function() { - var target = {} + var target = {} - expect(target).to.not.have.property('foo') - defprop(target, { foo: 'wobble' }) - expect(target).to.have.property('foo', 'wobble') + expect(target).to.not.have.property('foo') + defprop(target, { foo: 'wobble' }) + expect(target).to.have.property('foo', 'wobble') }) it("should return the mutated target object", function() { - var target = {} + var target = {} - expect(target).to.not.have.property('foo') - expect(defprop(target, { foo: 'wobble' })).to.equal(target) - expect(target).to.have.property('foo', 'wobble') + expect(target).to.not.have.property('foo') + expect(defprop(target, { foo: 'wobble' })).to.equal(target) + expect(target).to.have.property('foo', 'wobble') }) it("should not make the fields configurable", function() { - var target = defprop({}, { foo: 'wobble' }) - expect(desc(target, 'foo')).to.have.property('configurable', false) + var target = defprop({}, { foo: 'wobble' }) + expect(desc(target, 'foo')).to.have.property('configurable', false) }) describe("when a field is a getter and/or setter, or the field is a function", function() { - describe("and the `^bind` option is set to an object", function() { - it("should bind the field to the object", function() { - var scope = {} - var target = defprop({}, - { get prop() { return this.wibble } - , set prop(x) { this.wibble = x } - , get scope() { return this } - , fun: function() { return this } - } - , { "^bind" : scope } - ) - - expect(target).to.not.equal(scope) - expect(target.scope).to.equal(scope) - - expect(target.prop).to.equal(undefined) - expect(scope).to.not.have.property('wibble') - expect(target).to.not.have.property('wibble') - - target.prop = 'wobble' - expect(target.prop).to.equal('wobble') - expect(scope).to.have.property('wibble', 'wobble') - expect(target).to.not.have.property('wibble') - - expect(target.fun()).to.equal(scope) - }) - }) + describe("and the `^bind` option is set to an object", function() { + it("should bind the field to the object", function() { + var scope = {} + var target = defprop({}, + { get prop() { return this.wibble } + , set prop(x) { this.wibble = x } + , get scope() { return this } + , fun: function() { return this } + } + , { "^bind" : scope } + ) + + expect(target).to.not.equal(scope) + expect(target.scope).to.equal(scope) + + expect(target.prop).to.equal(undefined) + expect(scope).to.not.have.property('wibble') + expect(target).to.not.have.property('wibble') + + target.prop = 'wobble' + expect(target.prop).to.equal('wobble') + expect(scope).to.have.property('wibble', 'wobble') + expect(target).to.not.have.property('wibble') + + expect(target.fun()).to.equal(scope) + }) + }) }) describe("when a field has no options", function() { - it("should make the field immutable", function() { - var target = defprop({}, { foo: 1 }) - expect(desc(target, 'foo')).to.have.property('writable', false) - }) - - it("should not make the field enumerable", function() { - var target = defprop({}, { foo: 1 }) - expect(desc(target, 'foo')).to.have.property('enumerable', false) - }) + it("should make the field immutable", function() { + var target = defprop({}, { foo: 1 }) + expect(desc(target, 'foo')).to.have.property('writable', false) + }) + + it("should not make the field enumerable", function() { + var target = defprop({}, { foo: 1 }) + expect(desc(target, 'foo')).to.have.property('enumerable', false) + }) }) describe("when a field is set to be writable", function() { - describe("and is just a getter", function() { - it("should throw a TypeError", function() { - var field = { get field() {} } - , opt = { field: { writable : true } } - - expect($(defprop, {}, field, opt)).to.throw(TypeError) - }) - }) - - describe("but when it is any other value", function() { - it("should make the field mutable", function() { - each( - [ { get field() {}, set field() {} } - , { set field() {} } - , { field: 1 } - , { field: 'wibble' } - , { field: function() {} } - ] - , function(field) { - var target = {} - defprop(target, field, { field: { writable: true } }) - - var prop = desc(target, 'field') - - if (prop.value) { - expect(prop).to.have.property('writable', true) - } else { - expect(prop.set).to.be.ok - } - } - ) - }) - }) + describe("and is just a getter", function() { + it("should throw a TypeError", function() { + var field = { get field() {} } + , opt = { field: { writable : true } } + + expect($(defprop, {}, field, opt)).to.throw(TypeError) + }) + }) + + describe("but when it is any other value", function() { + it("should make the field mutable", function() { + each( + [ { get field() {}, set field(val) {} } + , { set field(val) {} } + , { field: 1 } + , { field: 'wibble' } + , { field: function() {} } + ] + , function(field) { + var target = {} + defprop(target, field, { field: { writable: true } }) + + var prop = desc(target, 'field') + + if (prop.value) { + expect(prop).to.have.property('writable', true) + } else { + expect(prop.set).to.be.ok + } + } + ) + }) + }) }) describe("when a field is set to be enumerable", function() { - it("should make the field enumerable", function() { - each( - [ { get field() {}, set field() {} } - , { set field() {} } - , { field: 1 } - , { field: 'wibble' } - , { field: function() {} } - ] - , function(field) { - var target = {} - defprop(target, field, { field: { enumerable: true } }) - expect(target).to.have.key('field') - } - ) - }) + it("should make the field enumerable", function() { + each( + [ { get field() {}, set field(val) {} } + , { set field(val) {} } + , { field: 1 } + , { field: 'wibble' } + , { field: function() {} } + ] + , function(field) { + var target = {} + defprop(target, field, { field: { enumerable: true } }) + expect(target).to.have.key('field') + } + ) + }) }) }) }) diff --git a/test/defprotocol.js b/test/defprotocol.js index 996ba61..8e6e418 100644 --- a/test/defprotocol.js +++ b/test/defprotocol.js @@ -1,4 +1,4 @@ -var expect = require('chai').expect +var expect = require('must') , defprotocol = require('../lib/defprotocol') describe('defprotocol', function() { @@ -9,41 +9,41 @@ describe('defprotocol', function() { var Seq it('should return a protocol', function() { - Seq = defprotocol('Seq', - { first : [] - , rest : [] - }) + Seq = defprotocol('Seq', + { first : [] + , rest : [] + }) - expect(Seq).to.be.a('function') - expect(Seq.name).to.equal('Protocol') + expect(Seq).to.be.a('function') + expect(Seq.name).to.equal('Protocol') }) describe('and when implemented', function() { - it('should do what it says on the tin', function() { - var Node = function(data, left, right){ - this.data = data - this.left = left - this.right = right - } - - Seq(Node, - { first : function() { return this.data } - , rest : function() { return [this.left, this.right] } - }) - - var one = new Node(1) - , two = new Node(2) - , tre = new Node(3) - - one.left = tre - one.right = two - two.left = one - two.right = tre - tre.left = two - tre.right = one - - expect(Seq(one).first()).to.equal(1) - }) + it('should do what it says on the tin', function() { + var Node = function(data, left, right){ + this.data = data + this.left = left + this.right = right + } + + Seq(Node, + { first : function() { return this.data } + , rest : function() { return [this.left, this.right] } + }) + + var one = new Node(1) + , two = new Node(2) + , tre = new Node(3) + + one.left = tre + one.right = two + two.left = one + two.right = tre + tre.left = two + tre.right = one + + expect(Seq(one).first()).to.equal(1) + }) }) }) }) diff --git a/test/every.js b/test/every.js index dbdf7d7..5edd408 100644 --- a/test/every.js +++ b/test/every.js @@ -1,4 +1,4 @@ -var expect = require('chai').expect +var expect = require('must') , every = require('../lib/every') , each = require('../lib/each') , src = require('../lib/src') @@ -8,13 +8,13 @@ describe('every', function() { describe('when given a seq', function() { it('should call `fn` so long as it keeps returning `true`', function() { var l = [1, 2, 3] - , s = seq(l) + , s = seq(l) var i = 0 var fn = function(x) { - expect(x).to.equal(l[i++]) - return true + expect(x).to.equal(l[i++]) + return true } every(s, fn) @@ -23,15 +23,15 @@ describe('every', function() { it('should stop calling `fn` when it returns `false`', function() { var l = [1, 2, 3] - , s = seq(l) + , s = seq(l) var i = 0 var fn = function(x) { - if (x < 3) { - expect(x).to.equal(l[i++]) - return true - } + if (x < 3) { + expect(x).to.equal(l[i++]) + return true + } } every(s, fn) diff --git a/test/is.js b/test/is.js index 8491718..7ccb739 100644 --- a/test/is.js +++ b/test/is.js @@ -1,9 +1,13 @@ -var expect = require('must') - , range = require('../lib/range') - , each = require('../lib/each') - , seq = require('../lib/seq') - , src = require('../lib/src') - , is = require('../lib/is') +var defprotocol = require('../lib/defprotocol') + , assert = require('../lib/assert') + , expect = require('must') + , range = require('../lib/range') + , each = require('../lib/each') + , type = require('../lib/type') + , isnt = require('../lib/isnt') + , seq = require('../lib/seq') + , src = require('../lib/src') + , is = require('../lib/is') describe('is', function() { describe('when given a single argument `x`', function() { @@ -413,4 +417,53 @@ describe('is', function() { } ) }) + + describe('when testing for protocols', function() { + describe('and when `x` implements the protocol', function() { + it('should return true', function() { + var Test = defprotocol('Test', {}) + + each( + [ [Number, 3] + , [Array, []] + , [Function, function() {}] + , [Boolean, true] + , [String, 'hello'] + , [Object, {}] + , [Foo, new Foo] + ] + , function (data) { + var T = data[0] + , i = data[1] + + Test(T, {}) + + assert(is(Test, Test(i)), 'Expected type `' + T.name + '` to implement protocol') + } + ) + }) + + function Foo() {} + }) + + describe('but when `x` does not implement the protocol', function() { + it('should return false', function() { + var Test = defprotocol('Test', {}) + + each( + [ 3 + , [] + , function() {} + , true + , 'hello' + , {} + , new (function Foo() {}) + ] + , function (i) { + assert(isnt(Test, Test(i)), 'Expected type `' + type(i) + '` to not implement protocol') + } + ) + }) + }) + }) }) \ No newline at end of file diff --git a/test/when.js b/test/when.js index 742de62..7ab0f46 100644 --- a/test/when.js +++ b/test/when.js @@ -1,50 +1,50 @@ const constantly = require('../lib/constantly') - , expect = require('chai').expect + , expect = require('must') , when = require('../lib/when') describe('`when`', function() { describe('given a `test` and a `body`', function() { describe('when `test` is a function', function() { describe('and when calling `test` returns logically true', function () { - describe('when `body` is a function', function() { - it('then return the value of calling `body`', function() { - const tru = constantly(true) - , wbl = constantly('wibble') + describe('when `body` is a function', function() { + it('then return the value of calling `body`', function() { + const tru = constantly(true) + , wbl = constantly('wibble') - expect(when(tru, wbl)).to.equal('wibble') - }) - }) + expect(when(tru, wbl)).to.equal('wibble') + }) + }) - describe('when `body` is not a function', function() { - it('then return `body`', function() { - const tru = constantly(true) - expect(when(tru, 'wibble')).to.equal('wibble') - }) - }) + describe('when `body` is not a function', function() { + it('then return `body`', function() { + const tru = constantly(true) + expect(when(tru, 'wibble')).to.equal('wibble') + }) + }) }) describe('but when calling `test` returns logically false', function() { - it('then return `undefined`', function() { - const no = constantly(null) - expect(when(no, 'wibble')).to.equal.undefined - }) + it('then return `undefined`', function() { + const no = constantly(null) + expect(when(no, 'wibble')).to.equal.undefined + }) }) }) describe('when `test` is not a function', function() { describe('but when the value is logically true', function() { - describe('when `body` is a function', function() { - it('then return the value of calling `body`', function() { - const wbl = constantly('wibble') - expect(when(0, wbl)).to.equal('wibble') - }) - }) + describe('when `body` is a function', function() { + it('then return the value of calling `body`', function() { + const wbl = constantly('wibble') + expect(when(0, wbl)).to.equal('wibble') + }) + }) - describe('when `body` is not a function', function() { - it('then return `body`', function() { - expect(when(1, 'wibble')).to.equal('wibble') - }) - }) + describe('when `body` is not a function', function() { + it('then return `body`', function() { + expect(when(1, 'wibble')).to.equal('wibble') + }) + }) }) }) }) From 83edd9708d519440c9825c0fd1a1ad247176bb33 Mon Sep 17 00:00:00 2001 From: Marcus Stade Date: Sat, 31 Jan 2015 16:36:33 +0000 Subject: [PATCH 14/22] Change funkis test to only pick up js files This should probably change to something better, such as a **/*.api.js or something such that it's possible to have files explicitly marked public and others that would be considered private. --- test/funkis.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/funkis.js b/test/funkis.js index a5c199c..ab512b6 100644 --- a/test/funkis.js +++ b/test/funkis.js @@ -7,8 +7,10 @@ var funkis = require('../') describe('funkis', function() { it('should export every function in lib/', function() { var names = fs.readdirSync(path.join(__dirname, '../lib')).map(function(file) { - return path.basename(file, '.js') - }) + if (path.extname(file) === '.js') { + return path.basename(file, '.js') + } + }).filter(function(x) { return !!x }) each(names, function(name) { expect(funkis).to.have.property(name) From 61a6536000e4b502b63b467851d31564100d387e Mon Sep 17 00:00:00 2001 From: Marcus Stade Date: Sat, 31 Jan 2015 16:37:31 +0000 Subject: [PATCH 15/22] Add `when` to index --- index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/index.js b/index.js index 458f65c..0e7250a 100644 --- a/index.js +++ b/index.js @@ -42,4 +42,5 @@ module.exports = , val : require('./lib/val') , variadic : require('./lib/variadic') , vec : require('./lib/vec') + , when : require('./lib/when') } \ No newline at end of file From 6d26bb1c496428e8ca50651b4b3a1f81010af5d0 Mon Sep 17 00:00:00 2001 From: Marcus Stade Date: Sat, 31 Jan 2015 16:37:51 +0000 Subject: [PATCH 16/22] Remove unused argument from `assert` --- lib/assert.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/assert.js b/lib/assert.js index d9f4ac1..308e5ac 100644 --- a/lib/assert.js +++ b/lib/assert.js @@ -1,6 +1,6 @@ module.exports = assert -function assert(x, message, type) { +function assert(x, message) { if (isnt(x)) { message = val(message) isnt(message) && (message = "Assertion failed.") From 2758968c1ca02e8fb318834b7e484b8d5b81b584 Mon Sep 17 00:00:00 2001 From: Marcus Stade Date: Sat, 31 Jan 2015 16:38:17 +0000 Subject: [PATCH 17/22] Make sure `is` also tests constructor inheritance when type checking This probably needs tests. --- lib/is.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/is.js b/lib/is.js index 277effb..457c3ce 100644 --- a/lib/is.js +++ b/lib/is.js @@ -20,7 +20,9 @@ function is(c, x) { } else if (type(c) === 'string') { return cs === type(x) } else { - return (x != null && x.constructor === c) || c.isPrototypeOf(x) + return (x != null && x.constructor === c) + || (type(c) === 'function' && x instanceof c) + || c.isPrototypeOf(x) } } From f6c6a9a19b0be104720e672bbe6aab5328c7e928 Mon Sep 17 00:00:00 2001 From: Marcus Stade Date: Sat, 31 Jan 2015 16:39:26 +0000 Subject: [PATCH 18/22] Fix `nth` tests and remove unnecessary partial application --- lib/nth.js | 4 ++-- test/nth.js | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/nth.js b/lib/nth.js index d94c0ff..534d548 100644 --- a/lib/nth.js +++ b/lib/nth.js @@ -2,7 +2,7 @@ module.exports = nth function nth(coll, i) { if (is(Array, coll)) { - assert(0 <= i && i < coll.length, $(bounds, i)) + assert(0 <= i && i < coll.length, bounds(i)) return coll[i] } @@ -14,7 +14,7 @@ function nth(coll, i) { coll = coll.rest } - assert(n < 0 && coll, $(bounds, i)) + assert(n < 0 && coll, bounds(i)) return coll.first } diff --git a/test/nth.js b/test/nth.js index f40e18c..7f0d6fa 100644 --- a/test/nth.js +++ b/test/nth.js @@ -1,5 +1,6 @@ var partial = require('../lib/partial') , expect = require('must') + , range = require('../lib/range') , nth = require('../lib/nth') , $ = require('../lib/partial') @@ -11,8 +12,8 @@ describe("`nth`", function() { }) it("should throw an error if the index is out of bounds", function() { - expect($(nth, [1, 2, 3], 3)).to.throw("RangeError") - expect($(nth, range(3), 5)).to.throw("RangeError") + expect($(nth, [1, 2, 3], 3)).to.throw(RangeError) + expect($(nth, range(3), 5)).to.throw(RangeError) }) }) }) \ No newline at end of file From 48b97b1ed4ec68c1290fcfaa4890cd09fbbc78a7 Mon Sep 17 00:00:00 2001 From: Marcus Stade Date: Sat, 31 Jan 2015 16:40:45 +0000 Subject: [PATCH 19/22] Fix indentation issues. (I hate Windows so much it hurts sometimes.) --- lib/type.js | 4 ++-- test/defprop.js | 2 +- test/defprotocol.js | 2 +- test/is.js | 54 ++++++++++++++++++++++----------------------- 4 files changed, 31 insertions(+), 31 deletions(-) diff --git a/lib/type.js b/lib/type.js index 4f2f910..ce474ea 100644 --- a/lib/type.js +++ b/lib/type.js @@ -12,9 +12,9 @@ function type(x) { var proto = Object.getPrototypeOf(x) if (type(proto) === 'function' && proto.name) { - return proto.name + return proto.name } else if (x.constructor && x.constructor.name) { - return x.constructor.name + return x.constructor.name } } } diff --git a/test/defprop.js b/test/defprop.js index d01d999..b709db5 100644 --- a/test/defprop.js +++ b/test/defprop.js @@ -132,7 +132,7 @@ describe("`defprop`", function() { , function(field) { var target = {} defprop(target, field, { field: { enumerable: true } }) - expect(target).to.have.key('field') + expect(target).to.have.property('field') } ) }) diff --git a/test/defprotocol.js b/test/defprotocol.js index 8e6e418..66fac02 100644 --- a/test/defprotocol.js +++ b/test/defprotocol.js @@ -14,7 +14,7 @@ describe('defprotocol', function() { , rest : [] }) - expect(Seq).to.be.a('function') + expect(Seq).to.be.a(Function) expect(Seq.name).to.equal('Protocol') }) diff --git a/test/is.js b/test/is.js index 7ccb739..2562f95 100644 --- a/test/is.js +++ b/test/is.js @@ -36,29 +36,29 @@ describe('is', function() { describe('when given two arguments that are identical', function() { it('should return `true`', function() { each( - [ true, false, - , -1, 0, 1, 3.14 - , '', 'wibble' - , [], [1, 2, 3] - , {}, { foo: 1 } - , Function - , null, undefined - ] - , function(x) { - expect(is(x, x)).to.be.true - } + [ true, false, + , -1, 0, 1, 3.14 + , '', 'wibble' + , [], [1, 2, 3] + , {}, { foo: 1 } + , Function + , null, undefined + ] + , function(x) { + expect(is(x, x)).to.be.true + } ) }) }) describe('when testing for booleans', function() { each([ true, false ], function(x) { - describe('and when `x = '+x+'`', function() { - it('should return true', function() { - expect(is(Boolean, x)).to.be.true - expect(is('boolean', x)).to.be.true - }) - }) + describe('and when `x = '+x+'`', function() { + it('should return true', function() { + expect(is(Boolean, x)).to.be.true + expect(is('boolean', x)).to.be.true + }) + }) } ) @@ -73,12 +73,12 @@ describe('is', function() { ] , function(x) { - describe('and when `x = '+src(x)+'`', function() { - it('should return false', function() { - expect(is(Boolean, x)).to.be.false - expect(is('boolean', x)).to.be.false - }) - }) + describe('and when `x = '+src(x)+'`', function() { + it('should return false', function() { + expect(is(Boolean, x)).to.be.false + expect(is('boolean', x)).to.be.false + }) + }) } ) }) @@ -99,7 +99,7 @@ describe('is', function() { ] , function(x) { - var n = is(Array, x)? x[1] : src(x) + var n = is(Array, x)? x[1] : src(x) is(Array, x) && (x = x[0]) @@ -256,7 +256,7 @@ describe('is', function() { ] , function(x) { - var n = is(Array, x)? x[1] : src(x) + var n = is(Array, x)? x[1] : src(x) is(Array, x) && (x = x[0]) @@ -288,7 +288,7 @@ describe('is', function() { ] , function(x) { - var n = is(Array, x)? x[1] : src(x) + var n = is(Array, x)? x[1] : src(x) is(Array, x) && (x = x[0]) @@ -317,7 +317,7 @@ describe('is', function() { ] , function(x) { - var n = is(Array, x)? x[1] : src(x) + var n = is(Array, x)? x[1] : src(x) is(Array, x) && (x = x[0]) From 216a60c3f43d255af98b02a460417d8329cb1d99 Mon Sep 17 00:00:00 2001 From: Marcus Stade Date: Sat, 31 Jan 2015 19:23:23 +0000 Subject: [PATCH 20/22] Add feature detection for generators --- package.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/package.json b/package.json index 8323107..0c91d9a 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,9 @@ }, "author": "Marcus Stade", "license": "MIT", + "dependencies": { + "feature-detect-generators": "^1.0.1" + }, "devDependencies": { "coveralls": "~2.8.0", "expect.js": "^0.3.1", From 58e1203d72c86a1a65eb9c16b6d971fe81d7e1b5 Mon Sep 17 00:00:00 2001 From: Marcus Stade Date: Sat, 31 Jan 2015 19:46:07 +0000 Subject: [PATCH 21/22] Fix all indentation issues. Seriously. --- lib/defprop.js | 26 ++++++++++++------------- repl | 8 ++++---- test/and.js | 16 ++++++++-------- test/call.js | 12 ++++++------ test/constantly.js | 2 +- test/count.js | 4 ++-- test/each.js | 2 +- test/identity.js | 2 +- test/seq.js | 2 +- test/slice.js | 2 +- test/take.js | 2 +- test/thunk.js | 48 +++++++++++++++++++++++----------------------- test/vec.js | 2 +- 13 files changed, 64 insertions(+), 64 deletions(-) diff --git a/lib/defprop.js b/lib/defprop.js index 0042cb7..55fa0c6 100644 --- a/lib/defprop.js +++ b/lib/defprop.js @@ -16,23 +16,23 @@ function defprop(target, fields, opts) { return Object.defineProperties(target, names.reduce(function(p, k) { var prop = describe(fields, k) - , opt = $(get, opts[k]) + , opt = $(get, opts[k]) if (isnt(prop.get) && isnt(prop.set)) { - prop.writable = opt("writable", isMutable) + prop.writable = opt("writable", isMutable) - when(is(Function, prop.value) && opt("bind", scope), function(scope) { - prop.value = prop.value.bind(scope) - }) + when(is(Function, prop.value) && opt("bind", scope), function(scope) { + prop.value = prop.value.bind(scope) + }) } else { - when(prop.get && opt("writable") && !prop.set, function() { - throw TypeError("The accessor `"+k+"` can't be writable without a setter.") - }) - - when(opt("bind", scope), function(scope) { - prop.get && (prop.get = prop.get.bind(scope)) - prop.set && (prop.set = prop.set.bind(scope)) - }) + when(prop.get && opt("writable") && !prop.set, function() { + throw TypeError("The accessor `"+k+"` can't be writable without a setter.") + }) + + when(opt("bind", scope), function(scope) { + prop.get && (prop.get = prop.get.bind(scope)) + prop.set && (prop.set = prop.set.bind(scope)) + }) } prop.enumerable = opt("enumerable", isEnum) diff --git a/repl b/repl index 2421a3f..51d5af8 100755 --- a/repl +++ b/repl @@ -1,4 +1,4 @@ -#!/usr/bin/env node --harmony +#!/usr/bin/env node ;(function() { var global = this @@ -8,13 +8,13 @@ global['reload'] = function() { Object.keys(require.cache) .forEach(function(k) { - delete require.cache[k] + delete require.cache[k] }) fs.readdirSync(libdir) .forEach(function(lib) { - lib = lib.replace(/\.js$/, '') - global[lib] = require(libdir + '/' + lib) + lib = lib.replace(/\.js$/, '') + global[lib] = require(libdir + '/' + lib) }) } diff --git a/test/and.js b/test/and.js index 95fa90f..e88b9a1 100644 --- a/test/and.js +++ b/test/and.js @@ -18,7 +18,7 @@ describe('`and`', function() { describe('and when that argument is a function', function() { it('should return the value of calling that function', function() { - expect(and(constantly('wibble'))).to.equal('wibble') + expect(and(constantly('wibble'))).to.equal('wibble') }) }) }) @@ -26,24 +26,24 @@ describe('`and`', function() { describe('given two or more arguments', function() { describe('when the values of all arguments are logically true', function() { it('should return the last supplied value', function() { - expect(and(0, 1, 2, 3)).to.equal(3) + expect(and(0, 1, 2, 3)).to.equal(3) }) }) describe('when any one argument is logically false', function() { it('should return the value that was logically false', function() { - expect(and(0, null, 1)).to.equal(null) - expect(and(false, true, 1)).to.equal(false) - expect(and(0, true, undefined)).to.equal(undefined) + expect(and(0, null, 1)).to.equal(null) + expect(and(false, true, 1)).to.equal(false) + expect(and(0, true, undefined)).to.equal(undefined) }) }) describe('when an argument is a function', function() { it('should call the function and evaluate its return value', function() { - var called = false + var called = false - expect(and(0, function() { return (called = true) }, 1, 'yup')).to.equal('yup') - expect(called).to.be.true + expect(and(0, function() { return (called = true) }, 1, 'yup')).to.equal('yup') + expect(called).to.be.true }) }) }) diff --git a/test/call.js b/test/call.js index 796f267..6a8be5c 100644 --- a/test/call.js +++ b/test/call.js @@ -23,7 +23,7 @@ describe('call', function() { describe('when given a function `fn`', function() { describe('and no arguments', function(done) { it('should call the function without arguments', function(done) { - var fn = function() { + var fn = function() { expect(arguments.length).to.equal(0) done() } @@ -33,9 +33,9 @@ describe('call', function() { describe('and `fn` is bound', function() { it('should not affect the binding', function(done) { - var owner = {} + var owner = {} - var fn = function() { + var fn = function() { expect(arguments.length).to.equal(0) expect(this).to.equal(owner) done() @@ -48,7 +48,7 @@ describe('call', function() { describe('and when given arguments', function(done) { it('should call the function with arguments', function(done) { - var fn = function() { + var fn = function() { expect(slice(arguments)).to.eql([1, true, 'wibble']) done() } @@ -58,9 +58,9 @@ describe('call', function() { describe('and `fn` is bound', function() { it('should not affect the binding', function(done) { - var owner = {} + var owner = {} - var fn = function() { + var fn = function() { expect(slice(arguments)).to.eql([1, true, 'wibble']) expect(this).to.equal(owner) done() diff --git a/test/constantly.js b/test/constantly.js index 9887b99..c2fcb88 100644 --- a/test/constantly.js +++ b/test/constantly.js @@ -14,7 +14,7 @@ describe('constantly', function() { ] , function(val) { describe('when called with the value `' + src(val) + '`', function() { - var v = constantly(val) + var v = constantly(val) it('should return a function called `constant`', function() { expect(v.name).to.equal('constant') diff --git a/test/count.js b/test/count.js index 5eb81fc..5ead9ff 100644 --- a/test/count.js +++ b/test/count.js @@ -42,14 +42,14 @@ describe('count', function() { describe('when given a seq', function () { describe('and when the length is defined', function() { it('should return it', function() { - var s = seq([1, 2, 3]) + var s = seq([1, 2, 3]) expect(count(s)).to.equal(3) }) }) describe('but when the length is undefined', function() { it('should return undefined', function() { - var s = seq(Math.random) + var s = seq(Math.random) expect(count(s)).to.equal(undefined) }) }) diff --git a/test/each.js b/test/each.js index 86eea03..4965907 100644 --- a/test/each.js +++ b/test/each.js @@ -7,7 +7,7 @@ describe('each', function() { describe('when given a seq', function() { it('should call `fn` once for each item', function() { var l = [1, 2, 3] - , s = seq(l) + , s = seq(l) var i = 0 diff --git a/test/identity.js b/test/identity.js index a76fcaa..6a7e1ac 100644 --- a/test/identity.js +++ b/test/identity.js @@ -21,7 +21,7 @@ describe('identity', function() { describe('when given `' + str + '`', function() { it('should return `' + str + '`', function() { - var id = identity(x) + var id = identity(x) if (x !== x) { // NaN *sigh* expect(id).to.not.equal(id) diff --git a/test/seq.js b/test/seq.js index 25d1191..b25aa4c 100644 --- a/test/seq.js +++ b/test/seq.js @@ -32,7 +32,7 @@ describe('seq', function() { , [undefined] ] , function(arr) { - var s = seq(arr) + var s = seq(arr) var i = 0 diff --git a/test/slice.js b/test/slice.js index 8a7b9e8..e846ecb 100644 --- a/test/slice.js +++ b/test/slice.js @@ -16,7 +16,7 @@ describe('slice', function() { describe('and no other arguments', function() { it('should return an exact copy', function() { - var copy = slice(arr) + var copy = slice(arr) expect(copy).to.not.equal(arr) expect(copy).to.eql([1, 2, 3, 4, 5]) diff --git a/test/take.js b/test/take.js index c137d48..4506317 100644 --- a/test/take.js +++ b/test/take.js @@ -16,7 +16,7 @@ describe('take', function() { , function(coll) { describe('and when given the collection `' + src(coll) + '`', function() { it('should return a lazy sequence of the first `n` items', function() { - var s = take(3, coll) + var s = take(3, coll) expect(vec(s)).to.eql(slice(coll, 0, 3)) }) diff --git a/test/thunk.js b/test/thunk.js index 92deea5..805bf51 100644 --- a/test/thunk.js +++ b/test/thunk.js @@ -8,7 +8,7 @@ describe('thunk', function() { describe('when given a function `fn`', function() { describe('and no parameters', function() { it('should return a zero arity thunk', function() { - var th = thunk(function() {}) + var th = thunk(function() {}) expect(th).to.be.a(Function) expect(th.length).to.equal(0) @@ -17,7 +17,7 @@ describe('thunk', function() { describe('when called', function() { it('should call `fn` with no parameters', function(done) { - var th = thunk(function() { + var th = thunk(function() { expect(arguments.length).to.equal(0) done() }) @@ -26,7 +26,7 @@ describe('thunk', function() { }) it('should ignore any parameters given to it', function (done) { - var th = thunk(function() { + var th = thunk(function() { expect(arguments.length).to.equal(0) done() }) @@ -35,7 +35,7 @@ describe('thunk', function() { }) it('should return whatever `fn` returns', function() { - var th = thunk(function() { return 'hello' }) + var th = thunk(function() { return 'hello' }) expect(th()).to.equal('hello') }) }) @@ -45,7 +45,7 @@ describe('thunk', function() { , function(param) { describe('and a single parameter `' + src(param) + '`', function() { it('should return a zero arity thunk', function() { - var th = thunk(function() {}) + var th = thunk(function() {}) expect(th).to.be.a(Function) expect(th.length).to.equal(0) @@ -53,7 +53,7 @@ describe('thunk', function() { describe('when called', function() { it('should call `fn` with `' + src(param) + '` as the sole parameter', function(done) { - var th = thunk(function(a) { + var th = thunk(function(a) { expect(arguments.length).to.equal(1) expect(a).to.equal(param) done() @@ -63,7 +63,7 @@ describe('thunk', function() { }) it('should ignore any parameters given to it', function (done) { - var th = thunk(function(a) { + var th = thunk(function(a) { expect(arguments.length).to.equal(1) expect(a).to.equal(param) done() @@ -73,7 +73,7 @@ describe('thunk', function() { }) it('should return whatever `fn` returns', function() { - var th = thunk(function(a) { return a }, 'hello') + var th = thunk(function(a) { return a }, 'hello') expect(th()).to.equal('hello') }) }) @@ -83,7 +83,7 @@ describe('thunk', function() { describe('and more than one parameter', function() { it('should return a zero arity function', function() { - var th = thunk(function() {}, 1, 2, 3) + var th = thunk(function() {}, 1, 2, 3) expect(th).to.be.a(Function) expect(th.length).to.equal(0) expect(th.name).to.equal('thunk') @@ -91,7 +91,7 @@ describe('thunk', function() { describe('and when called', function() { it('should call the given function, with the given parameters', function(done) { - var th = thunk(function(a, b, c) { + var th = thunk(function(a, b, c) { expect(arguments.length).to.equal(3) expect(a).to.equal(1) expect(b).to.equal(false) @@ -103,7 +103,7 @@ describe('thunk', function() { }) it('should ignore any parameters given to it', function (done) { - var th = thunk(function(a, b, c) { + var th = thunk(function(a, b, c) { expect(arguments.length).to.equal(3) expect(a).to.equal(1) expect(b).to.equal(false) @@ -115,7 +115,7 @@ describe('thunk', function() { }) it('should return whatever `fn` returns', function() { - var th = thunk(function(a, b) { return a + ' ' + b }, 'hello', 'world') + var th = thunk(function(a, b) { return a + ' ' + b }, 'hello', 'world') expect(th()).to.equal('hello world') }) }) @@ -126,12 +126,12 @@ describe('thunk', function() { describe('when given an unbound function `fn`', function() { describe('and when called', function() { it('should bind `this` of `fn` to the global object', function(done) { - var noargs = thunk(function() { + var noargs = thunk(function() { expect(this).to.equal(global) args() }) - var args = thunk(function(a, b, c) { + var args = thunk(function(a, b, c) { expect(this).to.equal(global) expect(a).to.equal(1) expect(b).to.equal(2) @@ -147,14 +147,14 @@ describe('thunk', function() { describe('when given a bound function `fn`', function() { describe('and when called', function() { it('should not affect the `this` of `fn`', function(done) { - var that = {} + var that = {} - var noargs = thunk(function() { + var noargs = thunk(function() { expect(this).to.equal(that) args() }.bind(that)) - var args = thunk(function(a, b, c) { + var args = thunk(function(a, b, c) { expect(this).to.equal(that) expect(a).to.equal(1) expect(b).to.equal(2) @@ -171,14 +171,14 @@ describe('thunk', function() { describe('and given an unbound function `fn`', function() { describe('and when called', function() { it('should bind `this` of `fn` to the thunk\'s `this`', function(done) { - var that = {} + var that = {} - var noargs = thunk(function() { + var noargs = thunk(function() { expect(this).to.equal(that) args() }).bind(that) - var args = thunk(function(a, b, c) { + var args = thunk(function(a, b, c) { expect(this).to.equal(that) expect(a).to.equal(1) expect(b).to.equal(2) @@ -193,14 +193,14 @@ describe('thunk', function() { describe('and given a bound function `fn`', function() { it('should not affect the `this` of `fn`', function(done) { - var that = {} + var that = {} - var noargs = thunk(function() { + var noargs = thunk(function() { expect(this).to.not.equal(that) args() }.bind({})).bind(that) - var args = thunk(function(a, b, c) { + var args = thunk(function(a, b, c) { expect(this).to.not.equal(that) expect(a).to.equal(1) expect(b).to.equal(2) @@ -238,7 +238,7 @@ describe('thunk', function() { ] , function(val) { - var th = thunk(val) + var th = thunk(val) expect(th()).to.equal(val) } ) diff --git a/test/vec.js b/test/vec.js index 00b96bd..f1be7b9 100644 --- a/test/vec.js +++ b/test/vec.js @@ -26,7 +26,7 @@ describe('vec', function() { ], function(t) { describe('when given the ' + type(t[0]) + ' `' + src(t[0]) + '`', function() { it('should turn it into `' + src(t[1]) + '`', function() { - var v = vec(t[0]) + var v = vec(t[0]) expect(v).to.eql(t[1]) }) }) From 71016355322b28df39543af74c6e2ec8c13a5fa6 Mon Sep 17 00:00:00 2001 From: Marcus Stade Date: Sat, 7 Feb 2015 15:24:04 +0000 Subject: [PATCH 22/22] Change Travis config to use iojs instead of node --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2104b26..5ef363a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,5 @@ language: node_js node_js: - - "0.11" - - "0.10" + - "iojs" after_script: NODE_ENV=test istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R spec && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage \ No newline at end of file